From: Yu Watanabe Date: Sun, 18 Sep 2022 21:27:37 +0000 (+0900) Subject: blockdev-util: re-implement block_get_originating() by using sd_device X-Git-Tag: v252-rc1~49^2~3 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=612fc70fc0f5445817f3f5c033dd3d5b5fd058ea;p=thirdparty%2Fsystemd.git blockdev-util: re-implement block_get_originating() by using sd_device And split out the core logic as block_device_get_originating(). Hopefully, this changes no behavior. Just refactoring and preparation for later commits. --- diff --git a/src/shared/blockdev-util.c b/src/shared/blockdev-util.c index d9921681702..43bdcda6204 100644 --- a/src/shared/blockdev-util.c +++ b/src/shared/blockdev-util.c @@ -119,6 +119,54 @@ int block_device_get_whole_disk(sd_device *dev, sd_device **ret) { return 0; } +static int block_device_get_originating(sd_device *dev, sd_device **ret) { + _cleanup_(sd_device_unrefp) sd_device *first_found = NULL; + const char *suffix; + sd_device *child; + dev_t devnum = 0; /* avoid false maybe-uninitialized warning */ + + /* For the specified block device tries to chase it through the layers, in case LUKS-style DM + * stacking is used, trying to find the next underlying layer. */ + + assert(dev); + assert(ret); + + FOREACH_DEVICE_CHILD_WITH_SUFFIX(dev, child, suffix) { + sd_device *child_whole_disk; + dev_t n; + + if (!path_startswith(suffix, "slaves")) + continue; + + if (block_device_get_whole_disk(child, &child_whole_disk) < 0) + continue; + + if (sd_device_get_devnum(child_whole_disk, &n) < 0) + continue; + + if (!first_found) { + first_found = sd_device_ref(child); + devnum = n; + continue; + } + + /* We found a device backed by multiple other devices. We don't really support automatic + * discovery on such setups, with the exception of dm-verity partitions. In this case there + * are two backing devices: the data partition and the hash partition. We are fine with such + * setups, however, only if both partitions are on the same physical device. Hence, let's + * verify this by iterating over every node in the 'slaves/' directory and comparing them with + * the first that gets returned by readdir(), to ensure they all point to the same device. */ + if (n != devnum) + return -ENOTUNIQ; + } + + if (!first_found) + return -ENOENT; + + *ret = TAKE_PTR(first_found); + return 1; /* found */ +} + int block_get_whole_disk(dev_t d, dev_t *ret) { char p[SYS_BLOCK_PATH_MAX("/partition")]; _cleanup_free_ char *s = NULL; @@ -219,86 +267,20 @@ int get_block_device(const char *path, dev_t *ret) { } int block_get_originating(dev_t dt, dev_t *ret) { - _cleanup_closedir_ DIR *d = NULL; - _cleanup_free_ char *t = NULL; - char p[SYS_BLOCK_PATH_MAX("/slaves")]; - _cleanup_free_ char *first_found = NULL; - const char *q; - dev_t devt; + _cleanup_(sd_device_unrefp) sd_device *dev = NULL, *origin = NULL; int r; - /* For the specified block device tries to chase it through the layers, in case LUKS-style DM stacking is used, - * trying to find the next underlying layer. */ - - xsprintf_sys_block_path(p, "/slaves", dt); - d = opendir(p); - if (!d) - return -errno; - - FOREACH_DIRENT_ALL(de, d, return -errno) { - - if (dot_or_dot_dot(de->d_name)) - continue; - - if (!IN_SET(de->d_type, DT_LNK, DT_UNKNOWN)) - continue; - - if (first_found) { - _cleanup_free_ char *u = NULL, *v = NULL, *a = NULL, *b = NULL; - - /* We found a device backed by multiple other devices. We don't really support - * automatic discovery on such setups, with the exception of dm-verity partitions. In - * this case there are two backing devices: the data partition and the hash - * partition. We are fine with such setups, however, only if both partitions are on - * the same physical device. Hence, let's verify this by iterating over every node - * in the 'slaves/' directory and comparing them with the first that gets returned by - * readdir(), to ensure they all point to the same device. */ - - u = path_join(p, de->d_name, "../dev"); - if (!u) - return -ENOMEM; - - v = path_join(p, first_found, "../dev"); - if (!v) - return -ENOMEM; - - r = read_one_line_file(u, &a); - if (r < 0) - return log_debug_errno(r, "Failed to read %s: %m", u); - - r = read_one_line_file(v, &b); - if (r < 0) - return log_debug_errno(r, "Failed to read %s: %m", v); - - /* Check if the parent device is the same. If not, then the two backing devices are on - * different physical devices, and we don't support that. */ - if (!streq(a, b)) - return -ENOTUNIQ; - } else { - first_found = strdup(de->d_name); - if (!first_found) - return -ENOMEM; - } - } - - if (!first_found) - return -ENOENT; - - q = strjoina(p, "/", first_found, "/dev"); + assert(ret); - r = read_one_line_file(q, &t); + r = sd_device_new_from_devnum(&dev, 'b', dt); if (r < 0) return r; - r = parse_devnum(t, &devt); + r = block_device_get_originating(dev, &origin); if (r < 0) - return -EINVAL; - - if (major(devt) == 0) - return -ENOENT; + return r; - *ret = devt; - return 1; + return sd_device_get_devnum(origin, ret); } int get_block_device_harder_fd(int fd, dev_t *ret) {