From: Devendra Tewari Date: Wed, 24 Aug 2022 10:13:04 +0000 (-0300) Subject: systemd-growfs: remove dependency on udev symlinks X-Git-Tag: v252-rc1~350 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=aa181897cf189263e2786d8a184918442e52ee1a;p=thirdparty%2Fsystemd.git systemd-growfs: remove dependency on udev symlinks systemd-growfs currently requires that udev ran first to work (because /dev/block/ symlinks must exist) but that is not what happens when we're not using initrd and systemd is PID1. --- diff --git a/src/basic/devnum-util.c b/src/basic/devnum-util.c index 70c07315c59..fbefa2bd69c 100644 --- a/src/basic/devnum-util.c +++ b/src/basic/devnum-util.c @@ -5,6 +5,7 @@ #include "chase-symlinks.h" #include "devnum-util.h" +#include "fs-util.h" #include "parse-util.h" #include "path-util.h" #include "string-util.h" @@ -57,6 +58,53 @@ int device_path_make_major_minor(mode_t mode, dev_t devnum, char **ret) { return 0; } +int device_path_make_major_minor_sysfs(mode_t mode, dev_t devnum, char **ret) { + _cleanup_free_ char *syspath = NULL, *link = NULL, *fname = NULL; + _cleanup_free_ char *devpath = NULL; + const char *t; + int r; + + /* Generates the /dev/... path given a dev_t. What makes this different + * from device_path_make_major_minor is that it works even when udev + * hasn't yet run */ + + if (S_ISCHR(mode)) + t = "char"; + else if (S_ISBLK(mode)) + t = "block"; + else + return -ENODEV; + + if (asprintf(&syspath, "/sys/dev/%s/" DEVNUM_FORMAT_STR, t, DEVNUM_FORMAT_VAL(devnum)) < 0) + return -ENOMEM; + + r = readlink_malloc(syspath, &link); + if (r < 0) + return r; + + r = path_extract_filename(link, &fname); + if (r < 0) + return r; + + devpath = path_join("/dev", fname); + if (!devpath) + return -ENOMEM; + + struct stat st; + if (stat(devpath, &st) < 0) + return -errno; + + if (((st.st_mode ^ mode) & S_IFMT) != 0) + return S_ISBLK(mode) ? -ENOTBLK : -ENODEV; + + if (st.st_rdev != devnum) + return -ENXIO; + + *ret = TAKE_PTR(devpath); + + return 0; +} + int device_path_make_canonical(mode_t mode, dev_t devnum, char **ret) { _cleanup_free_ char *p = NULL; int r; diff --git a/src/basic/devnum-util.h b/src/basic/devnum-util.h index 3f1894b2fd7..7adb6fb249e 100644 --- a/src/basic/devnum-util.h +++ b/src/basic/devnum-util.h @@ -29,6 +29,7 @@ int parse_devnum(const char *s, dev_t *ret); }) int device_path_make_major_minor(mode_t mode, dev_t devnum, char **ret); +int device_path_make_major_minor_sysfs(mode_t mode, dev_t devnum, char **ret); int device_path_make_canonical(mode_t mode, dev_t devnum, char **ret); int device_path_parse_major_minor(const char *path, mode_t *ret_mode, dev_t *ret_devnum); diff --git a/src/partition/growfs.c b/src/partition/growfs.c index e105c0e151a..e940dccd48b 100644 --- a/src/partition/growfs.c +++ b/src/partition/growfs.c @@ -41,7 +41,7 @@ static int resize_crypt_luks_device(dev_t devno, const char *fstype, dev_t main_ if (r < 0) return log_error_errno(r, "Cannot resize LUKS device: %m"); - r = device_path_make_major_minor(S_IFBLK, main_devno, &main_devpath); + r = device_path_make_major_minor_sysfs(S_IFBLK, main_devno, &main_devpath); if (r < 0) return log_error_errno(r, "Failed to format device major/minor path: %m"); @@ -54,7 +54,7 @@ static int resize_crypt_luks_device(dev_t devno, const char *fstype, dev_t main_ main_devpath); log_debug("%s is %"PRIu64" bytes", main_devpath, size); - r = device_path_make_major_minor(S_IFBLK, devno, &devpath); + r = device_path_make_major_minor_sysfs(S_IFBLK, devno, &devpath); if (r < 0) return log_error_errno(r, "Failed to format major/minor path: %m"); @@ -115,7 +115,7 @@ static int maybe_resize_underlying_device( if (devno == main_devno) return 0; - r = device_path_make_major_minor(S_IFBLK, devno, &devpath); + r = device_path_make_major_minor_sysfs(S_IFBLK, devno, &devpath); if (r < 0) return log_error_errno(r, "Failed to format device major/minor path: %m"); @@ -237,7 +237,7 @@ static int run(int argc, char *argv[]) { if (r < 0) log_warning_errno(r, "Unable to resize underlying device of \"%s\", proceeding anyway: %m", arg_target); - r = device_path_make_major_minor(S_IFBLK, devno, &devpath); + r = device_path_make_major_minor_sysfs(S_IFBLK, devno, &devpath); if (r < 0) return log_error_errno(r, "Failed to format device major/minor path: %m");