#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"
#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"
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;
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");
return r;
}
- return 0;
+ return true;
}
static bool mount_is_network(struct mntent *me) {
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;
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) {
if (initrd)
fstab = sysroot_fstab_path();
- else
+ else {
fstab = fstab_path();
+ assert(!arg_sysroot_check);
+ }
log_debug("Parsing %s...", fstab);
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;
}
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");
(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();
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);