diff options
author | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2022-07-14 14:36:52 +0200 |
---|---|---|
committer | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2022-07-23 19:02:39 +0200 |
commit | 028a981c005e90c36c269e28709bf25032c2e8ca (patch) | |
tree | f911f852b74a6601ccca297298468a6d39bed257 /src/fstab-generator | |
parent | 5df2a4a6e0b3e8574e067d0252b954a5e002e751 (diff) | |
download | systemd-028a981c005e90c36c269e28709bf25032c2e8ca.tar.gz |
fstab-generator: add mode to check /sysroot/etc/fstab and maybe do daemon-reload
The idea is that we can peek into /sysroot/etc/fstab and figure out if there's
anything interesting there. We could use a separate binary for this, but we'd
need to duplicate most of the logic that in systemd-fstab-generator. Thus I
think it's nicer to make systemd-fstab-generator work as a multi-call binary.
If called as systemd-sysroot-fstab-check, we look for units that we'd mount and
call daemon-reload and initrd-fs.target/restart, similarly to what we did
before, but in the process itself.
Diffstat (limited to 'src/fstab-generator')
-rw-r--r-- | src/fstab-generator/fstab-generator.c | 118 |
1 files changed, 110 insertions, 8 deletions
diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c index da7ea627f1..e76de45a0f 100644 --- a/src/fstab-generator/fstab-generator.c +++ b/src/fstab-generator/fstab-generator.c @@ -5,6 +5,8 @@ #include <unistd.h> #include "alloc-util.h" +#include "bus-error.h" +#include "bus-locator.h" #include "chase-symlinks.h" #include "fd-util.h" #include "fileio.h" @@ -20,6 +22,7 @@ #include "parse-util.h" #include "path-util.h" #include "proc-cmdline.h" +#include "process-util.h" #include "special.h" #include "specifier.h" #include "stat-util.h" @@ -39,6 +42,7 @@ typedef enum MountPointFlags { MOUNT_RW_ONLY = 1 << 5, } MountPointFlags; +static bool arg_sysroot_check = false; static const char *arg_dest = NULL; static const char *arg_dest_late = NULL; static bool arg_fstab_enabled = true; @@ -119,6 +123,11 @@ static int add_swap( return 0; } + if (arg_sysroot_check) { + log_info("%s should be enabled in the initrd, will request daemon-reload.", what); + return true; + } + r = unit_name_from_path(what, ".swap", &name); if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); @@ -175,7 +184,7 @@ static int add_swap( return r; } - return 0; + return true; } static bool mount_is_network(struct mntent *me) { @@ -378,6 +387,11 @@ static int add_mount( mount_point_ignore(where)) return 0; + if (arg_sysroot_check) { + log_info("%s should be mounted in the initrd, will request daemon-reload.", where); + return true; + } + r = fstab_filter_options(opts, "x-systemd.wanted-by\0", NULL, NULL, &wanted_by, NULL); if (r < 0) return r; @@ -567,7 +581,52 @@ static int add_mount( return r; } - return 0; + return true; +} + +static int do_daemon_reload(void) { + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + int r, k; + + log_debug("Calling org.freedesktop.systemd1.Manager.Reload()..."); + + r = bus_connect_system_systemd(&bus); + if (r < 0) + return log_error_errno(r, "Failed to get D-Bus connection: %m"); + + r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, "Reload"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_call(bus, m, DAEMON_RELOAD_TIMEOUT_SEC, &error, NULL); + if (r < 0) + return log_error_errno(r, "Failed to reload daemon: %s", bus_error_message(&error, r)); + + /* We need to requeue the two targets so that any new units which previously were not part of the + * targets, and which we now added, will be started. */ + + r = 0; + FOREACH_STRING(unit, SPECIAL_INITRD_FS_TARGET, SPECIAL_SWAP_TARGET) { + log_info("Requesting %s/start/replace...", unit); + + k = sd_bus_call_method(bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "StartUnit", + &error, + NULL, + "ss", unit, "replace"); + if (k < 0) { + log_error_errno(k, "Failed to (re)start %s: %s", unit, bus_error_message(&error, r)); + if (r == 0) + r = k; + } + } + + return r; } static const char* sysroot_fstab_path(void) { @@ -582,8 +641,10 @@ static int parse_fstab(bool initrd) { if (initrd) fstab = sysroot_fstab_path(); - else + else { fstab = fstab_path(); + assert(!arg_sysroot_check); + } log_debug("Parsing %s...", fstab); @@ -700,6 +761,8 @@ static int parse_fstab(bool initrd) { target_unit); } + if (arg_sysroot_check && k > 0) + return true; /* We found a mount or swap that would be started… */ if (r >= 0 && k < 0) r = k; } @@ -1126,12 +1189,14 @@ static int determine_usr(void) { return determine_device(&arg_usr_what, arg_usr_hash, "usr"); } -static int run(const char *dest, const char *dest_early, const char *dest_late) { +/* If arg_sysroot_check is false, run as generator in the usual fashion. + * If it is true, check /sysroot/etc/fstab for any units that we'd want to mount + * in the initrd, and call daemon-reload. We will get reinvoked as a generator, + * with /sysroot/etc/fstab available, and then we can write additional units based + * on that file. */ +static int run_generator(void) { int r, r2 = 0, r3 = 0; - assert_se(arg_dest = dest); - assert_se(arg_dest_late = dest_late); - r = proc_cmdline_parse(parse_proc_cmdline_item, NULL, 0); if (r < 0) log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); @@ -1139,6 +1204,15 @@ static int run(const char *dest, const char *dest_early, const char *dest_late) (void) determine_root(); (void) determine_usr(); + if (arg_sysroot_check) { + r = parse_fstab(true); + if (r == 0) + log_debug("Nothing interesting found, not doing daemon-reload."); + if (r > 0) + r = do_daemon_reload(); + return r; + } + /* Always honour root= and usr= in the kernel command line if we are in an initrd */ if (in_initrd()) { r = add_sysroot_mount(); @@ -1164,4 +1238,32 @@ static int run(const char *dest, const char *dest_early, const char *dest_late) return r < 0 ? r : r2 < 0 ? r2 : r3; } -DEFINE_MAIN_GENERATOR_FUNCTION(run); +static int run(int argc, char **argv) { + arg_sysroot_check = invoked_as(argv, "systemd-sysroot-fstab-check"); + + if (arg_sysroot_check) { + /* Run as in systemd-sysroot-fstab-check mode */ + log_setup(); + + if (strv_length(argv) > 1) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "This program takes no arguments."); + if (!in_initrd()) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "This program is only useful in the initrd."); + } else { + /* Run in generator mode */ + log_setup_generator(); + + if (!IN_SET(strv_length(argv), 2, 4)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "This program takes one or three arguments."); + + arg_dest = ASSERT_PTR(argv[1]); + arg_dest_late = ASSERT_PTR(argv[argc > 3 ? 3 : 1]); + } + + return run_generator(); +} + +DEFINE_MAIN_FUNCTION(run); |