From 75d0aba49be010bb18b514171fcf2672b47cc855 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 25 Apr 2018 22:05:00 +0900 Subject: [PATCH 1/2] device: fix serialization and deserialization of DeviceFound DeviceFound is a bit flag. So, it is necessary to support the case that multiple bits are set. Follow-up for 918e6f1c0151429f5095355f4f3f74f16e79724a. --- src/core/device.c | 88 +++++++++++++++++++++++++++++++++++++---------- src/core/device.h | 3 -- 2 files changed, 70 insertions(+), 21 deletions(-) diff --git a/src/core/device.c b/src/core/device.c index 1441d08b97a..294e79f9b58 100644 --- a/src/core/device.c +++ b/src/core/device.c @@ -17,7 +17,6 @@ #include "parse-util.h" #include "path-util.h" #include "stat-util.h" -#include "string-table.h" #include "string-util.h" #include "swap.h" #include "udev-util.h" @@ -152,7 +151,71 @@ static int device_coldplug(Unit *u) { return 0; } +static const struct { + DeviceFound flag; + const char *name; +} device_found_map[] = { + { DEVICE_FOUND_UDEV, "found-udev" }, + { DEVICE_FOUND_UDEV_DB, "found-udev-db" }, + { DEVICE_FOUND_MOUNT, "found-mount" }, + { DEVICE_FOUND_SWAP, "found-swap" }, + {} +}; + +static int device_found_to_string_many(DeviceFound flags, char **ret) { + _cleanup_free_ char *s = NULL; + unsigned i; + + assert(ret); + + for (i = 0; device_found_map[i].name; i++) { + if ((flags & device_found_map[i].flag) != device_found_map[i].flag) + continue; + + if (!strextend_with_separator(&s, ",", device_found_map[i].name, NULL)) + return -ENOMEM; + } + + *ret = TAKE_PTR(s); + + return 0; +} + +static int device_found_from_string_many(const char *name, DeviceFound *ret) { + DeviceFound flags = 0; + int r; + + assert(ret); + + for (;;) { + _cleanup_free_ char *word = NULL; + DeviceFound f = 0; + unsigned i; + + r = extract_first_word(&name, &word, ",", 0); + if (r < 0) + return r; + if (r == 0) + break; + + for (i = 0; device_found_map[i].name; i++) + if (streq(word, device_found_map[i].name)) { + f = device_found_map[i].flag; + break; + } + + if (f == 0) + return -EINVAL; + + flags |= f; + } + + *ret = flags; + return 0; +} + static int device_serialize(Unit *u, FILE *f, FDSet *fds) { + _cleanup_free_ char *s = NULL; Device *d = DEVICE(u); assert(u); @@ -160,13 +223,16 @@ static int device_serialize(Unit *u, FILE *f, FDSet *fds) { assert(fds); unit_serialize_item(u, f, "state", device_state_to_string(d->state)); - unit_serialize_item(u, f, "found", device_found_to_string(d->found)); + + (void) device_found_to_string_many(d->found, &s); + unit_serialize_item(u, f, "found", s); return 0; } static int device_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) { Device *d = DEVICE(u); + int r; assert(u); assert(key); @@ -195,13 +261,9 @@ static int device_deserialize_item(Unit *u, const char *key, const char *value, d->deserialized_state = state; } else if (streq(key, "found")) { - DeviceFound found; - - found = device_found_from_string(value); - if (found < 0) + r = device_found_from_string_many(value, &d->found); + if (r < 0) log_unit_debug(u, "Failed to parse found value: %s", value); - else - d->found = found; } else log_unit_debug(u, "Unknown serialization key: %s", key); @@ -934,16 +996,6 @@ bool device_shall_be_bound_by(Unit *device, Unit *u) { return DEVICE(device)->bind_mounts; } -static const char* const device_found_table[] = { - [DEVICE_NOT_FOUND] = "not-found", - [DEVICE_FOUND_UDEV] = "found-udev", - [DEVICE_FOUND_UDEV_DB] = "found-udev-db", - [DEVICE_FOUND_MOUNT] = "found-mount", - [DEVICE_FOUND_SWAP] = "found-swap", -}; - -DEFINE_STRING_TABLE_LOOKUP(device_found, DeviceFound); - const UnitVTable device_vtable = { .object_size = sizeof(Device), .sections = diff --git a/src/core/device.h b/src/core/device.h index a96aa6d24d5..d52700b66f6 100644 --- a/src/core/device.h +++ b/src/core/device.h @@ -37,6 +37,3 @@ extern const UnitVTable device_vtable; int device_found_node(Manager *m, const char *node, bool add, DeviceFound found, bool now); bool device_shall_be_bound_by(Unit *device, Unit *u); - -const char *device_found_to_string(DeviceFound f) _const_; -DeviceFound device_found_from_string(const char *s) _pure_; From 4d86c235b84a62dde6dfe99a78cabc5cd9bb369c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 26 Apr 2018 10:05:33 +0200 Subject: [PATCH 2/2] core: include Found state in device dumps In particular, this confirms that the Found state needs to remain a bit-field: $ systemd-analyze dump |grep 'Found: '|sort |uniq -c 105 Found: found-udev 3 Found: found-udev,found-mount 1 Found: found-udev,found-swap --- src/core/device.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/core/device.c b/src/core/device.c index 294e79f9b58..565410fd361 100644 --- a/src/core/device.c +++ b/src/core/device.c @@ -273,14 +273,19 @@ static int device_deserialize_item(Unit *u, const char *key, const char *value, static void device_dump(Unit *u, FILE *f, const char *prefix) { Device *d = DEVICE(u); + _cleanup_free_ char *s = NULL; assert(d); + (void) device_found_to_string_many(d->found, &s); + fprintf(f, "%sDevice State: %s\n" - "%sSysfs Path: %s\n", + "%sSysfs Path: %s\n" + "%sFound: %s\n", prefix, device_state_to_string(d->state), - prefix, strna(d->sysfs)); + prefix, strna(d->sysfs), + prefix, strna(s)); } _pure_ static UnitActiveState device_active_state(Unit *u) {