chiark / gitweb /
cgroup: get rid of MemorySoftLimit=
[elogind.git] / src / core / load-fragment.c
index 2b10d72ab331893ed07e19de08290eafa6b54f8e..74454abe49888bce1232ce9504e0fc07a9aa589d 100644 (file)
@@ -99,9 +99,12 @@ int config_parse_unit_deps(const char* unit,
                 if (!t)
                         return log_oom();
 
                 if (!t)
                         return log_oom();
 
-                k = unit_name_printf(u, t);
-                if (!k)
-                        return log_oom();
+                r = unit_name_printf(u, t, &k);
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, -r,
+                                   "Failed to resolve specifiers, ignoring: %s", strerror(-r));
+                        continue;
+                }
 
                 r = unit_add_dependency_by_name(u, d, k, NULL, true);
                 if (r < 0)
 
                 r = unit_add_dependency_by_name(u, d, k, NULL, true);
                 if (r < 0)
@@ -124,16 +127,17 @@ int config_parse_unit_string_printf(const char *unit,
 
         Unit *u = userdata;
         _cleanup_free_ char *k = NULL;
 
         Unit *u = userdata;
         _cleanup_free_ char *k = NULL;
+        int r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
         assert(u);
 
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
         assert(u);
 
-        k = unit_full_printf(u, rvalue);
-        if (!k)
-                log_syntax(unit, LOG_ERR, filename, line, EINVAL,
-                           "Failed to resolve unit specifiers on %s. Ignoring.", rvalue);
+        r = unit_full_printf(u, rvalue, &k);
+        if (r < 0)
+                log_syntax(unit, LOG_ERR, filename, line, -r,
+                           "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
 
         return config_parse_string(unit, filename, line, section, lvalue, ltype,
                                    k ? k : rvalue, data, userdata);
 
         return config_parse_string(unit, filename, line, section, lvalue, ltype,
                                    k ? k : rvalue, data, userdata);
@@ -151,16 +155,17 @@ int config_parse_unit_strv_printf(const char *unit,
 
         Unit *u = userdata;
         _cleanup_free_ char *k = NULL;
 
         Unit *u = userdata;
         _cleanup_free_ char *k = NULL;
+        int r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
         assert(u);
 
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
         assert(u);
 
-        k = unit_full_printf(u, rvalue);
-        if (!k)
-                log_syntax(unit, LOG_ERR, filename, line, EINVAL,
-                           "Failed to resolve unit specifiers on %s. Ignoring.", rvalue);
+        r = unit_full_printf(u, rvalue, &k);
+        if (r < 0)
+                log_syntax(unit, LOG_ERR, filename, line, -r,
+                           "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
 
         return config_parse_strv(unit, filename, line, section, lvalue, ltype,
                                  k ? k : rvalue, data, userdata);
 
         return config_parse_strv(unit, filename, line, section, lvalue, ltype,
                                  k ? k : rvalue, data, userdata);
@@ -178,16 +183,17 @@ int config_parse_unit_path_printf(const char *unit,
 
         Unit *u = userdata;
         _cleanup_free_ char *k = NULL;
 
         Unit *u = userdata;
         _cleanup_free_ char *k = NULL;
+        int r;
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
         assert(u);
 
 
         assert(filename);
         assert(lvalue);
         assert(rvalue);
         assert(u);
 
-        k = unit_full_printf(u, rvalue);
-        if (!k)
-                log_syntax(unit, LOG_ERR, filename, line, EINVAL,
-                           "Failed to resolve unit specifiers on %s. Ignoring.", rvalue);
+        r = unit_full_printf(u, rvalue, &k);
+        if (r < 0)
+                log_syntax(unit, LOG_ERR, filename, line, -r,
+                           "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
 
         return config_parse_path(unit, filename, line, section, lvalue, ltype,
                                  k ? k : rvalue, data, userdata);
 
         return config_parse_path(unit, filename, line, section, lvalue, ltype,
                                  k ? k : rvalue, data, userdata);
@@ -205,6 +211,7 @@ int config_parse_socket_listen(const char *unit,
 
         SocketPort *p, *tail;
         Socket *s;
 
         SocketPort *p, *tail;
         Socket *s;
+        int r;
 
         assert(filename);
         assert(lvalue);
 
         assert(filename);
         assert(lvalue);
@@ -226,32 +233,31 @@ int config_parse_socket_listen(const char *unit,
         if (ltype != SOCKET_SOCKET) {
 
                 p->type = ltype;
         if (ltype != SOCKET_SOCKET) {
 
                 p->type = ltype;
-                p->path = unit_full_printf(UNIT(s), rvalue);
-                if (!p->path) {
+                r = unit_full_printf(UNIT(s), rvalue, &p->path);
+                if (r < 0) {
                         p->path = strdup(rvalue);
                         if (!p->path) {
                                 free(p);
                                 return log_oom();
                         } else
                         p->path = strdup(rvalue);
                         if (!p->path) {
                                 free(p);
                                 return log_oom();
                         } else
-                                log_syntax(unit, LOG_ERR, filename, line, EINVAL,
-                                           "Failed to resolve unit specifiers on %s. Ignoring.", rvalue);
+                                log_syntax(unit, LOG_ERR, filename, line, -r,
+                                           "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
                 }
 
                 path_kill_slashes(p->path);
 
         } else if (streq(lvalue, "ListenNetlink")) {
                 _cleanup_free_ char  *k = NULL;
                 }
 
                 path_kill_slashes(p->path);
 
         } else if (streq(lvalue, "ListenNetlink")) {
                 _cleanup_free_ char  *k = NULL;
-                int r;
 
                 p->type = SOCKET_SOCKET;
 
                 p->type = SOCKET_SOCKET;
-                k = unit_full_printf(UNIT(s), rvalue);
-                if (!k)
-                        log_syntax(unit, LOG_ERR, filename, line, EINVAL,
-                                   "Failed to resolve unit specifiers on %s. Ignoring.", rvalue);
+                r = unit_full_printf(UNIT(s), rvalue, &k);
+                if (r < 0)
+                        log_syntax(unit, LOG_ERR, filename, line, -r,
+                                   "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
 
                 r = socket_address_parse_netlink(&p->address, k ? k : rvalue);
                 if (r < 0) {
 
                 r = socket_address_parse_netlink(&p->address, k ? k : rvalue);
                 if (r < 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+                        log_syntax(unit, LOG_ERR, filename, line, -r,
                                    "Failed to parse address value, ignoring: %s", rvalue);
                         free(p);
                         return 0;
                                    "Failed to parse address value, ignoring: %s", rvalue);
                         free(p);
                         return 0;
@@ -259,17 +265,16 @@ int config_parse_socket_listen(const char *unit,
 
         } else {
                 _cleanup_free_ char *k = NULL;
 
         } else {
                 _cleanup_free_ char *k = NULL;
-                int r;
 
                 p->type = SOCKET_SOCKET;
 
                 p->type = SOCKET_SOCKET;
-                k = unit_full_printf(UNIT(s), rvalue);
-                if (!k)
-                        log_syntax(unit, LOG_ERR, filename, line, EINVAL,
-                                   "Failed to resolve unit specifiers on %s. Ignoring.", rvalue);
+                r = unit_full_printf(UNIT(s), rvalue, &k);
+                if (r < 0)
+                        log_syntax(unit, LOG_ERR, filename, line, -r,
+                                   "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
 
                 r = socket_address_parse(&p->address, k ? k : rvalue);
                 if (r < 0) {
 
                 r = socket_address_parse(&p->address, k ? k : rvalue);
                 if (r < 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+                        log_syntax(unit, LOG_ERR, filename, line, -r,
                                    "Failed to parse address value, ignoring: %s", rvalue);
                         free(p);
                         return 0;
                                    "Failed to parse address value, ignoring: %s", rvalue);
                         free(p);
                         return 0;
@@ -1230,11 +1235,12 @@ int config_parse_trigger_unit(
                 return 0;
         }
 
                 return 0;
         }
 
-        p = unit_name_printf(u, rvalue);
-        if (!p)
-                return log_oom();
+        r = unit_name_printf(u, rvalue, &p);
+        if (r < 0)
+                log_syntax(unit, LOG_ERR, filename, line, -r,
+                           "Failed to resolve specifiers, ignoring: %s", strerror(-r));
 
 
-        type = unit_name_to_type(p);
+        type = unit_name_to_type(p ?: rvalue);
         if (type < 0) {
                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
                            "Unit type not valid, ignoring: %s", rvalue);
         if (type < 0) {
                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
                            "Unit type not valid, ignoring: %s", rvalue);
@@ -1247,10 +1253,10 @@ int config_parse_trigger_unit(
                 return 0;
         }
 
                 return 0;
         }
 
-        r = unit_add_two_dependencies_by_name(u, UNIT_BEFORE, UNIT_TRIGGERS, p, NULL, true);
+        r = unit_add_two_dependencies_by_name(u, UNIT_BEFORE, UNIT_TRIGGERS, p ?: rvalue, NULL, true);
         if (r < 0) {
                 log_syntax(unit, LOG_ERR, filename, line, -r,
         if (r < 0) {
                 log_syntax(unit, LOG_ERR, filename, line, -r,
-                           "Failed to add trigger on %s, ignoring: %s", p, strerror(-r));
+                           "Failed to add trigger on %s, ignoring: %s", p ?: rvalue, strerror(-r));
                 return 0;
         }
 
                 return 0;
         }
 
@@ -1271,6 +1277,7 @@ int config_parse_path_spec(const char *unit,
         PathSpec *s;
         PathType b;
         _cleanup_free_ char *k = NULL;
         PathSpec *s;
         PathType b;
         _cleanup_free_ char *k = NULL;
+        int r;
 
         assert(filename);
         assert(lvalue);
 
         assert(filename);
         assert(lvalue);
@@ -1290,13 +1297,13 @@ int config_parse_path_spec(const char *unit,
                 return 0;
         }
 
                 return 0;
         }
 
-        k = unit_full_printf(UNIT(p), rvalue);
-        if (!k) {
+        r = unit_full_printf(UNIT(p), rvalue, &k);
+        if (r < 0) {
                 k = strdup(rvalue);
                 if (!k)
                         return log_oom();
                 else
                 k = strdup(rvalue);
                 if (!k)
                         return log_oom();
                 else
-                        log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+                        log_syntax(unit, LOG_ERR, filename, line, -r,
                                    "Failed to resolve unit specifiers on %s. Ignoring.",
                                    rvalue);
         }
                                    "Failed to resolve unit specifiers on %s. Ignoring.",
                                    rvalue);
         }
@@ -1344,19 +1351,20 @@ int config_parse_socket_service(const char *unit,
 
         dbus_error_init(&error);
 
 
         dbus_error_init(&error);
 
-        p = unit_name_printf(UNIT(s), rvalue);
-        if (!p)
-                return log_oom();
+        r = unit_name_printf(UNIT(s), rvalue, &p);
+        if (r < 0)
+                log_syntax(unit, LOG_ERR, filename, line, -r,
+                           "Failed to resolve specifiers, ignoring: %s", rvalue);
 
 
-        if (!endswith(p, ".service")) {
+        if (!endswith(p ?: rvalue, ".service")) {
                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
                            "Unit must be of type service, ignoring: %s", rvalue);
                 return 0;
         }
 
                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
                            "Unit must be of type service, ignoring: %s", rvalue);
                 return 0;
         }
 
-        r = manager_load_unit(UNIT(s)->manager, p, NULL, &error, &x);
+        r = manager_load_unit(UNIT(s)->manager, p ?: rvalue, NULL, &error, &x);
         if (r < 0) {
         if (r < 0) {
-                log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+                log_syntax(unit, LOG_ERR, filename, line, r,
                            "Failed to load unit %s, ignoring: %s",
                            rvalue, bus_error(&error, r));
                 dbus_error_free(&error);
                            "Failed to load unit %s, ignoring: %s",
                            rvalue, bus_error(&error, r));
                 dbus_error_free(&error);
@@ -1395,23 +1403,24 @@ int config_parse_service_sockets(const char *unit,
                 if (!t)
                         return log_oom();
 
                 if (!t)
                         return log_oom();
 
-                k = unit_name_printf(UNIT(s), t);
-                if (!k)
-                        return log_oom();
+                r = unit_name_printf(UNIT(s), t, &k);
+                if (r < 0)
+                        log_syntax(unit, LOG_ERR, filename, line, -r,
+                                   "Failed to resolve specifiers, ignoring: %s", strerror(-r));
 
 
-                if (!endswith(k, ".socket")) {
+                if (!endswith(k ?: t, ".socket")) {
                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
-                                   "Unit must be of type socket, ignoring: %s", k);
+                                   "Unit must be of type socket, ignoring: %s", k ?: t);
                         continue;
                 }
 
                         continue;
                 }
 
-                r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_WANTS, UNIT_AFTER, k, NULL, true);
+                r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_WANTS, UNIT_AFTER, k ?: t, NULL, true);
                 if (r < 0)
                         log_syntax(unit, LOG_ERR, filename, line, -r,
                                    "Failed to add dependency on %s, ignoring: %s",
                 if (r < 0)
                         log_syntax(unit, LOG_ERR, filename, line, -r,
                                    "Failed to add dependency on %s, ignoring: %s",
-                                   k, strerror(-r));
+                                   k ?: t, strerror(-r));
 
 
-                r = unit_add_dependency_by_name(UNIT(s), UNIT_TRIGGERED_BY, k, NULL, true);
+                r = unit_add_dependency_by_name(UNIT(s), UNIT_TRIGGERED_BY, k ?: t, NULL, true);
                 if (r < 0)
                         return r;
         }
                 if (r < 0)
                         return r;
         }
@@ -1463,7 +1472,8 @@ int config_parse_unit_env_file(const char *unit,
 
         char ***env = data;
         Unit *u = userdata;
 
         char ***env = data;
         Unit *u = userdata;
-        _cleanup_free_ char *s = NULL;
+        _cleanup_free_ char *n = NULL;
+        const char *s;
         int r;
 
         assert(filename);
         int r;
 
         assert(filename);
@@ -1478,10 +1488,12 @@ int config_parse_unit_env_file(const char *unit,
                 return 0;
         }
 
                 return 0;
         }
 
-        s = unit_full_printf(u, rvalue);
-        if (!s)
-                return log_oom();
+        r = unit_full_printf(u, rvalue, &n);
+        if (r < 0)
+                log_syntax(unit, LOG_ERR, filename, line, r,
+                           "Failed to resolve specifiers, ignoring: %s", rvalue);
 
 
+        s = n ?: rvalue;
         if (!path_is_absolute(s[0] == '-' ? s + 1 : s)) {
                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
                            "Path '%s' is not absolute, ignoring.", s);
         if (!path_is_absolute(s[0] == '-' ? s + 1 : s)) {
                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
                            "Path '%s' is not absolute, ignoring.", s);
@@ -1509,6 +1521,7 @@ int config_parse_environ(const char *unit,
         char*** env = data, *w, *state;
         size_t l;
         _cleanup_free_ char *k = NULL;
         char*** env = data, *w, *state;
         size_t l;
         _cleanup_free_ char *k = NULL;
+        int r;
 
         assert(filename);
         assert(lvalue);
 
         assert(filename);
         assert(lvalue);
@@ -1522,11 +1535,15 @@ int config_parse_environ(const char *unit,
                 return 0;
         }
 
                 return 0;
         }
 
-        if (u)
-                k = unit_full_printf(u, rvalue);
-        else
-                k = strdup(rvalue);
+        if (u) {
+                r = unit_full_printf(u, rvalue, &k);
+                if (r < 0)
+                        log_syntax(unit, LOG_ERR, filename, line, -r,
+                                   "Failed to resolve specifiers, ignoring: %s", rvalue);
+        }
 
 
+        if (!k)
+                k = strdup(rvalue);
         if (!k)
                 return log_oom();
 
         if (!k)
                 return log_oom();
 
@@ -1598,6 +1615,7 @@ int config_parse_unit_condition_path(const char *unit,
         bool trigger, negate;
         Condition *c;
         _cleanup_free_ char *p = NULL;
         bool trigger, negate;
         Condition *c;
         _cleanup_free_ char *p = NULL;
+        int r;
 
         assert(filename);
         assert(lvalue);
 
         assert(filename);
         assert(lvalue);
@@ -1619,9 +1637,15 @@ int config_parse_unit_condition_path(const char *unit,
         if (negate)
                 rvalue++;
 
         if (negate)
                 rvalue++;
 
-        p = unit_full_printf(u, rvalue);
-        if (!p)
-                return log_oom();
+        r = unit_full_printf(u, rvalue, &p);
+        if (r < 0)
+                log_syntax(unit, LOG_ERR, filename, line, -r,
+                           "Failed to resolve specifiers, ignoring: %s", rvalue);
+        if (!p) {
+                p = strdup(rvalue);
+                if (!p)
+                        return log_oom();
+        }
 
         if (!path_is_absolute(p)) {
                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
 
         if (!path_is_absolute(p)) {
                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
@@ -1652,6 +1676,7 @@ int config_parse_unit_condition_string(const char *unit,
         bool trigger, negate;
         Condition *c;
         _cleanup_free_ char *s = NULL;
         bool trigger, negate;
         Condition *c;
         _cleanup_free_ char *s = NULL;
+        int r;
 
         assert(filename);
         assert(lvalue);
 
         assert(filename);
         assert(lvalue);
@@ -1673,9 +1698,15 @@ int config_parse_unit_condition_string(const char *unit,
         if (negate)
                 rvalue++;
 
         if (negate)
                 rvalue++;
 
-        s = unit_full_printf(u, rvalue);
-        if (!s)
-                return log_oom();
+        r = unit_full_printf(u, rvalue, &s);
+        if (r < 0)
+                log_syntax(unit, LOG_ERR, filename, line, -r,
+                           "Failed to resolve specifiers, ignoring: %s", rvalue);
+        if (!s) {
+                s = strdup(rvalue);
+                if (!s)
+                        return log_oom();
+        }
 
         c = condition_new(cond, s, trigger, negate);
         if (!c)
 
         c = condition_new(cond, s, trigger, negate);
         if (!c)
@@ -1929,21 +1960,26 @@ int config_parse_unit_slice(
         assert(rvalue);
         assert(u);
 
         assert(rvalue);
         assert(u);
 
-        k = unit_name_printf(u, rvalue);
-        if (!k)
-                log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+        r = unit_name_printf(u, rvalue, &k);
+        if (r < 0)
+                log_syntax(unit, LOG_ERR, filename, line, -r,
                            "Failed to resolve unit specifiers on %s. Ignoring.", rvalue);
                            "Failed to resolve unit specifiers on %s. Ignoring.", rvalue);
+        if (!k) {
+                k = strdup(rvalue);
+                if (!k)
+                        return log_oom();
+        }
 
 
-        r = manager_load_unit(u->manager, k ? k : rvalue, NULL, NULL, &slice);
+        r = manager_load_unit(u->manager, k, NULL, NULL, &slice);
         if (r < 0) {
                 log_syntax(unit, LOG_ERR, filename, line, -r,
         if (r < 0) {
                 log_syntax(unit, LOG_ERR, filename, line, -r,
-                           "Failed to load slice unit %s. Ignoring.", k ? k : rvalue);
+                           "Failed to load slice unit %s. Ignoring.", k);
                 return 0;
         }
 
         if (slice->type != UNIT_SLICE) {
                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
                 return 0;
         }
 
         if (slice->type != UNIT_SLICE) {
                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
-                           "Slice unit %s is not a slice. Ignoring.", k ? k : rvalue);
+                           "Slice unit %s is not a slice. Ignoring.", k);
                 return 0;
         }
 
                 return 0;
         }
 
@@ -2000,14 +2036,11 @@ int config_parse_memory_limit(
                 void *userdata) {
 
         CGroupContext *c = data;
                 void *userdata) {
 
         CGroupContext *c = data;
-        uint64_t *limit;
         off_t bytes;
         int r;
 
         off_t bytes;
         int r;
 
-        limit = streq(lvalue, "MemoryLimit") ? &c->memory_limit : &c->memory_soft_limit;
-
         if (isempty(rvalue)) {
         if (isempty(rvalue)) {
-                *limit = (uint64_t) -1;
+                c->memory_limit = (uint64_t) -1;
                 return 0;
         }
 
                 return 0;
         }
 
@@ -2020,7 +2053,7 @@ int config_parse_memory_limit(
                 return 0;
         }
 
                 return 0;
         }
 
-        *limit = (uint64_t) bytes;
+        c->memory_limit = (uint64_t) bytes;
         return 0;
 }
 
         return 0;
 }
 
@@ -2094,7 +2127,44 @@ int config_parse_blockio_weight(
                 void *data,
                 void *userdata) {
 
                 void *data,
                 void *userdata) {
 
+        CGroupContext *c = data;
+        unsigned long lu;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+
+        if (isempty(rvalue)) {
+                c->blockio_weight = 1000;
+                return 0;
+        }
+
+        r = safe_atolu(rvalue, &lu);
+        if (r < 0 || lu < 10 || lu > 1000) {
+                log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+                           "Block IO weight '%s' invalid. Ignoring.", rvalue);
+                return 0;
+        }
+
+        c->blockio_weight = lu;
+
+        return 0;
+}
+
+int config_parse_blockio_device_weight(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
         _cleanup_free_ char *path = NULL;
         _cleanup_free_ char *path = NULL;
+        CGroupBlockIODeviceWeight *w;
         CGroupContext *c = data;
         unsigned long lu;
         const char *weight;
         CGroupContext *c = data;
         unsigned long lu;
         const char *weight;
@@ -2106,8 +2176,6 @@ int config_parse_blockio_weight(
         assert(rvalue);
 
         if (isempty(rvalue)) {
         assert(rvalue);
 
         if (isempty(rvalue)) {
-                c->blockio_weight = 1000;
-
                 while (c->blockio_device_weights)
                         cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
 
                 while (c->blockio_device_weights)
                         cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
 
@@ -2116,23 +2184,23 @@ int config_parse_blockio_weight(
 
         n = strcspn(rvalue, WHITESPACE);
         weight = rvalue + n;
 
         n = strcspn(rvalue, WHITESPACE);
         weight = rvalue + n;
-        if (*weight) {
-                /* Two params, first device name, then weight */
-                path = strndup(rvalue, n);
-                if (!path)
-                        return log_oom();
+        if (!*weight) {
+                log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+                           "Expected block device and device weight. Ignoring.");
+                return 0;
+        }
 
 
-                if (!path_startswith(path, "/dev")) {
-                        log_syntax(unit, LOG_ERR, filename, line, EINVAL,
-                                   "Invalid device node path '%s'. Ignoring.", path);
-                        return 0;
-                }
+        path = strndup(rvalue, n);
+        if (!path)
+                return log_oom();
 
 
-                weight += strspn(weight, WHITESPACE);
-        } else
-                /* One param, only weight */
-                weight = rvalue;
+        if (!path_startswith(path, "/dev")) {
+                log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+                           "Invalid device node path '%s'. Ignoring.", path);
+                return 0;
+        }
 
 
+        weight += strspn(weight, WHITESPACE);
         r = safe_atolu(weight, &lu);
         if (r < 0 || lu < 10 || lu > 1000) {
                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
         r = safe_atolu(weight, &lu);
         if (r < 0 || lu < 10 || lu > 1000) {
                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
@@ -2140,23 +2208,17 @@ int config_parse_blockio_weight(
                 return 0;
         }
 
                 return 0;
         }
 
-        if (!path)
-                c->blockio_weight = lu;
-        else {
-                CGroupBlockIODeviceWeight *w;
-
-                w = new0(CGroupBlockIODeviceWeight, 1);
-                if (!w)
-                        return log_oom();
 
 
-                w->path = path;
-                path = NULL;
+        w = new0(CGroupBlockIODeviceWeight, 1);
+        if (!w)
+                return log_oom();
 
 
-                w->weight = lu;
+        w->path = path;
+        path = NULL;
 
 
-                LIST_PREPEND(CGroupBlockIODeviceWeight, device_weights, c->blockio_device_weights, w);
-        }
+        w->weight = lu;
 
 
+        LIST_PREPEND(CGroupBlockIODeviceWeight, device_weights, c->blockio_device_weights, w);
         return 0;
 }
 
         return 0;
 }
 
@@ -2176,6 +2238,7 @@ int config_parse_blockio_bandwidth(
         CGroupContext *c = data;
         const char *bandwidth;
         off_t bytes;
         CGroupContext *c = data;
         const char *bandwidth;
         off_t bytes;
+        bool read;
         size_t n;
         int r;
 
         size_t n;
         int r;
 
@@ -2183,9 +2246,14 @@ int config_parse_blockio_bandwidth(
         assert(lvalue);
         assert(rvalue);
 
         assert(lvalue);
         assert(rvalue);
 
+        read = streq("BlockIOReadBandwidth", lvalue);
+
         if (isempty(rvalue)) {
         if (isempty(rvalue)) {
-                while (c->blockio_device_bandwidths)
-                        cgroup_context_free_blockio_device_bandwidth(c, c->blockio_device_bandwidths);
+                CGroupBlockIODeviceBandwidth *next;
+
+                LIST_FOREACH_SAFE (device_bandwidths, b, next, c->blockio_device_bandwidths)
+                        if (b->read == read)
+                                cgroup_context_free_blockio_device_bandwidth(c, b);
 
                 return 0;
         }
 
                 return 0;
         }
@@ -2224,6 +2292,7 @@ int config_parse_blockio_bandwidth(
         b->path = path;
         path = NULL;
         b->bandwidth = (uint64_t) bytes;
         b->path = path;
         path = NULL;
         b->bandwidth = (uint64_t) bytes;
+        b->read = read;
 
         LIST_PREPEND(CGroupBlockIODeviceBandwidth, device_bandwidths, c->blockio_device_bandwidths, b);
 
 
         LIST_PREPEND(CGroupBlockIODeviceBandwidth, device_bandwidths, c->blockio_device_bandwidths, b);
 
@@ -2618,6 +2687,23 @@ void unit_dump_config_items(FILE *f) {
                 { config_parse_unit_condition_string, "CONDITION" },
                 { config_parse_unit_condition_null,   "CONDITION" },
                 { config_parse_unit_slice,            "SLICE" },
                 { config_parse_unit_condition_string, "CONDITION" },
                 { config_parse_unit_condition_null,   "CONDITION" },
                 { config_parse_unit_slice,            "SLICE" },
+                { config_parse_documentation,         "URL" },
+                { config_parse_service_timeout,       "SECONDS" },
+                { config_parse_start_limit_action,    "ACTION" },
+                { config_parse_set_status,            "STATUS" },
+                { config_parse_service_sockets,       "SOCKETS" },
+                { config_parse_fsck_passno,           "PASSNO" },
+                { config_parse_environ,               "ENVIRON" },
+                { config_parse_syscall_filter,        "SYSCALL" },
+                { config_parse_cpu_shares,            "SHARES" },
+                { config_parse_memory_limit,          "LIMIT" },
+                { config_parse_device_allow,          "DEVICE" },
+                { config_parse_device_policy,         "POLICY" },
+                { config_parse_blockio_bandwidth,     "BANDWIDTH" },
+                { config_parse_blockio_weight,        "WEIGHT" },
+                { config_parse_blockio_device_weight, "DEVICEWEIGHT" },
+                { config_parse_long,                  "LONG" },
+                { config_parse_socket_service,        "SERVICE" },
         };
 
         const char *prev = NULL;
         };
 
         const char *prev = NULL;