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.
This commit is contained in:
Devendra Tewari
2022-08-24 07:13:04 -03:00
committed by Luca Boccassi
parent 782c6e5c90
commit aa181897cf
3 changed files with 53 additions and 4 deletions

View File

@@ -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;

View File

@@ -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);

View File

@@ -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");