]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: fix support for transient resource limit properties
authorLennart Poettering <lennart@poettering.net>
Mon, 1 Feb 2016 20:37:28 +0000 (21:37 +0100)
committerLennart Poettering <lennart@poettering.net>
Mon, 1 Feb 2016 21:18:16 +0000 (22:18 +0100)
Make sure we can properly process resource limit properties. Specifically, allow transient configuration of both the
soft and hard limit, the same way from the unit files. Previously, only the the hard rlimits could be configured but
they'd implicitly spill into the soft hard rlimits.

This also updates the client-side code to be able to parse hard/soft resource limit specifications. Since we need to
serialize two properties in bus_append_unit_property_assignment() now, the marshalling of the container around it is
now moved into the function itself. This has the benefit of shortening the calling code.

As a side effect this now beefs up the rlimit parser of "systemctl set-property" to understand time and disk sizes
where that's appropriate.

src/core/dbus-execute.c
src/nspawn/nspawn-register.c
src/run/run.c
src/shared/bus-util.c
src/systemctl/systemctl.c

index eae0808f9e3c9dd4573e7fd97077feb26c964de9..2de28f43e1339311ece4b78b387a9d3272ec2d4c 100644 (file)
@@ -835,7 +835,8 @@ int bus_exec_context_set_transient_property(
                 UnitSetPropertiesMode mode,
                 sd_bus_error *error) {
 
-        int r;
+        const char *soft = NULL;
+        int r, ri;
 
         assert(u);
         assert(c);
@@ -1492,7 +1493,23 @@ int bus_exec_context_set_transient_property(
 
                 return 1;
 
-        } else if (rlimit_from_string(name) >= 0) {
+        }
+
+        ri = rlimit_from_string(name);
+        if (ri < 0) {
+                soft = endswith(name, "Soft");
+                if (soft) {
+                        const char *n;
+
+                        n = strndupa(name, soft - name);
+                        ri = rlimit_from_string(n);
+                        if (ri >= 0)
+                                name = n;
+
+                }
+        }
+
+        if (ri >= 0) {
                 uint64_t rl;
                 rlim_t x;
 
@@ -1510,22 +1527,36 @@ int bus_exec_context_set_transient_property(
                 }
 
                 if (mode != UNIT_CHECK) {
-                        int z;
-
-                        z = rlimit_from_string(name);
+                        _cleanup_free_ char *f = NULL;
+                        struct rlimit nl;
+
+                        if (c->rlimit[ri]) {
+                                nl = *c->rlimit[ri];
+
+                                if (soft)
+                                        nl.rlim_cur = x;
+                                else
+                                        nl.rlim_max = x;
+                        } else
+                                /* When the resource limit is not initialized yet, then assign the value to both fields */
+                                nl = (struct rlimit) {
+                                        .rlim_cur = x,
+                                        .rlim_max = x,
+                                };
+
+                        r = rlimit_format(&nl, &f);
+                        if (r < 0)
+                                return r;
 
-                        if (!c->rlimit[z]) {
-                                c->rlimit[z] = new(struct rlimit, 1);
-                                if (!c->rlimit[z])
+                        if (c->rlimit[ri])
+                                *c->rlimit[ri] = nl;
+                        else {
+                                c->rlimit[ri] = newdup(struct rlimit, &nl, 1);
+                                if (!c->rlimit[ri])
                                         return -ENOMEM;
                         }
 
-                        c->rlimit[z]->rlim_cur = c->rlimit[z]->rlim_max = x;
-
-                        if (x == RLIM_INFINITY)
-                                unit_write_drop_in_private_format(u, mode, name, "%s=infinity\n", name);
-                        else
-                                unit_write_drop_in_private_format(u, mode, name, "%s=%" PRIu64 "\n", name, rl);
+                        unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, f);
                 }
 
                 return 1;
index 65ca9c762bf2f94e65601582004ab68b56b992b5..a89de4b32459d08f09e5fc4296fc32462934e299 100644 (file)
@@ -166,17 +166,9 @@ int register_machine(
                 }
 
                 STRV_FOREACH(i, properties) {
-                        r = sd_bus_message_open_container(m, 'r', "sv");
-                        if (r < 0)
-                                return bus_log_create_error(r);
-
                         r = bus_append_unit_property_assignment(m, *i);
                         if (r < 0)
                                 return r;
-
-                        r = sd_bus_message_close_container(m);
-                        if (r < 0)
-                                return bus_log_create_error(r);
                 }
 
                 r = sd_bus_message_close_container(m);
index 92a1d5373c5a275f3c0f92ff0826ebb0c4431956..080c15466cce41db68de00e184412bdaa095331f 100644 (file)
@@ -422,17 +422,9 @@ static int transient_unit_set_properties(sd_bus_message *m, char **properties) {
                 return r;
 
         STRV_FOREACH(i, properties) {
-                r = sd_bus_message_open_container(m, 'r', "sv");
-                if (r < 0)
-                        return r;
-
                 r = bus_append_unit_property_assignment(m, *i);
                 if (r < 0)
                         return r;
-
-                r = sd_bus_message_close_container(m);
-                if (r < 0)
-                        return r;
         }
 
         return 0;
index 76356a6e31be9a4581f8f1c679681e6673ba4338..9bd7db9aaa9719257ff3cb25723991a80f40bfa5 100644 (file)
@@ -1398,7 +1398,7 @@ int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) {
 
 int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignment) {
         const char *eq, *field;
-        int r;
+        int r, rl;
 
         assert(m);
         assert(assignment);
@@ -1409,6 +1409,10 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
                 return -EINVAL;
         }
 
+        r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
+        if (r < 0)
+                return bus_log_create_error(r);
+
         field = strndupa(assignment, eq - assignment);
         eq ++;
 
@@ -1430,20 +1434,14 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
                         return -EINVAL;
                 }
 
-                if (r < 0)
-                        return bus_log_create_error(r);
-
-                return 0;
+                goto finish;
 
         } else if (streq(field, "EnvironmentFile")) {
 
                 r = sd_bus_message_append(m, "sv", "EnvironmentFiles", "a(sb)", 1,
                                           eq[0] == '-' ? eq + 1 : eq,
                                           eq[0] == '-');
-                if (r < 0)
-                        return bus_log_create_error(r);
-
-                return 0;
+                goto finish;
 
         } else if (STR_IN_SET(field, "AccuracySec", "RandomizedDelaySec")) {
                 char *n;
@@ -1461,17 +1459,38 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
                 /* Change suffix Sec → USec */
                 strcpy(mempcpy(n, field, l - 3), "USec");
                 r = sd_bus_message_append(m, "sv", n, "t", t);
-                if (r < 0)
-                        return bus_log_create_error(r);
-
-                return 0;
+                goto finish;
         }
 
         r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
         if (r < 0)
                 return bus_log_create_error(r);
 
-        if (STR_IN_SET(field,
+        rl = rlimit_from_string(field);
+        if (rl >= 0) {
+                const char *sn;
+                struct rlimit l;
+
+                r = rlimit_parse(rl, eq, &l);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to parse resource limit: %s", eq);
+
+                r = sd_bus_message_append(m, "v", "t", l.rlim_max);
+                if (r < 0)
+                        return bus_log_create_error(r);
+
+                r = sd_bus_message_close_container(m);
+                if (r < 0)
+                        return bus_log_create_error(r);
+
+                r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
+                if (r < 0)
+                        return bus_log_create_error(r);
+
+                sn = strjoina(field, "Soft");
+                r = sd_bus_message_append(m, "sv", sn, "t", l.rlim_cur);
+
+        } else if (STR_IN_SET(field,
                        "CPUAccounting", "MemoryAccounting", "BlockIOAccounting", "TasksAccounting",
                        "SendSIGHUP", "SendSIGKILL", "WakeSystem", "DefaultDependencies",
                        "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "RemainAfterExit",
@@ -1652,21 +1671,6 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
                         r = sd_bus_message_append(m, "v", "a(st)", path, u);
                 }
 
-        } else if (rlimit_from_string(field) >= 0) {
-                uint64_t rl;
-
-                if (streq(eq, "infinity"))
-                        rl = (uint64_t) -1;
-                else {
-                        r = safe_atou64(eq, &rl);
-                        if (r < 0) {
-                                log_error("Invalid resource limit: %s", eq);
-                                return -EINVAL;
-                        }
-                }
-
-                r = sd_bus_message_append(m, "v", "t", rl);
-
         } else if (streq(field, "Nice")) {
                 int32_t i;
 
@@ -1849,6 +1853,11 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
                 return -EINVAL;
         }
 
+finish:
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        r = sd_bus_message_close_container(m);
         if (r < 0)
                 return bus_log_create_error(r);
 
index 078c1b5ea49684d73d0662ab12d4ee7c7044174a..536beb28cef7e8c3f31efe3516aacd293a6906d1 100644 (file)
@@ -4873,17 +4873,9 @@ static int set_property(int argc, char *argv[], void *userdata) {
                 return bus_log_create_error(r);
 
         STRV_FOREACH(i, strv_skip(argv, 2)) {
-                r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
-                if (r < 0)
-                        return bus_log_create_error(r);
-
                 r = bus_append_unit_property_assignment(m, *i);
                 if (r < 0)
                         return r;
-
-                r = sd_bus_message_close_container(m);
-                if (r < 0)
-                        return bus_log_create_error(r);
         }
 
         r = sd_bus_message_close_container(m);