]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Add x-systemd.makefs option for fstab
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Tue, 21 Nov 2017 22:18:05 +0000 (23:18 +0100)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 30 Nov 2017 19:46:30 +0000 (20:46 +0100)
I opted to completely generate a unit for both mount points and swaps. For
swaps, it would be possible to use fixed template unit like systemd-mkswap@.service,
because there's no information passed except the device name. For mount points,
that's not possible because both the device name and file system type need to
be passed. Nevertheless, I expect that options will need to passed to both mkfs
and mkswap, in which case it'll be necessary to create units of both types
anyway.

meson.build
src/fstab-generator/fstab-generator.c
src/shared/generator.c
src/shared/generator.h

index abb152a03389db837d1a7bdcb87d233979e73c0f..b9015c8f1ab97c48b9d39cb32b19473704cf0db9 100644 (file)
@@ -182,6 +182,7 @@ conf.set_quoted('CATALOG_DATABASE',                           join_paths(catalog
 conf.set_quoted('SYSTEMD_CGROUP_AGENT_PATH',                  join_paths(rootlibexecdir, 'systemd-cgroups-agent'))
 conf.set_quoted('SYSTEMD_BINARY_PATH',                        join_paths(rootlibexecdir, 'systemd'))
 conf.set_quoted('SYSTEMD_FSCK_PATH',                          join_paths(rootlibexecdir, 'systemd-fsck'))
+conf.set_quoted('SYSTEMD_MAKEFS_PATH',                        join_paths(rootlibexecdir, 'systemd-makefs'))
 conf.set_quoted('SYSTEMD_SHUTDOWN_BINARY_PATH',               join_paths(rootlibexecdir, 'systemd-shutdown'))
 conf.set_quoted('SYSTEMD_SLEEP_BINARY_PATH',                  join_paths(rootlibexecdir, 'systemd-sleep'))
 conf.set_quoted('SYSTEMCTL_BINARY_PATH',                      join_paths(rootbindir, 'systemctl'))
index 913992e365865dd021cf101e0483220c9f21384e..5bdeae04c34448c2c2489269562d4fd7ef30c87e 100644 (file)
@@ -51,6 +51,7 @@ typedef enum MountpointFlags {
         NOAUTO    = 1 << 0,
         NOFAIL    = 1 << 1,
         AUTOMOUNT = 1 << 2,
+        MAKEFS    = 1 << 3,
 } MountpointFlags;
 
 static const char *arg_dest = "/tmp";
@@ -155,6 +156,12 @@ static int add_swap(
         if (r < 0)
                 return r;
 
+        if (flags & MAKEFS) {
+                r = generator_hook_up_mkswap(arg_dest, what);
+                if (r < 0)
+                        return r;
+        }
+
         if (!(flags & NOAUTO)) {
                 r = generator_add_symlink(arg_dest, SPECIAL_SWAP_TARGET,
                                           (flags & NOFAIL) ? "wants" : "requires", name);
@@ -307,10 +314,11 @@ static int add_mount(
                 const char *source) {
 
         _cleanup_free_ char
-                *name = NULL, *unit = NULL,
+                *name = NULL,
                 *automount_name = NULL, *automount_unit = NULL,
                 *filtered = NULL,
                 *where_escaped = NULL;
+        const char *unit;
         _cleanup_fclose_ FILE *f = NULL;
         int r;
 
@@ -347,9 +355,7 @@ static int add_mount(
         if (r < 0)
                 return log_error_errno(r, "Failed to generate unit name: %m");
 
-        unit = strjoin(dest, "/", name);
-        if (!unit)
-                return log_oom();
+        unit = strjoina(dest, "/", name);
 
         f = fopen(unit, "wxe");
         if (!f)
@@ -447,6 +453,12 @@ static int add_mount(
         if (r < 0)
                 return log_error_errno(r, "Failed to write unit file %s: %m", unit);
 
+        if (flags & MAKEFS) {
+                r = generator_hook_up_mkfs(dest, what, where, fstype);
+                if (r < 0)
+                        return r;
+        }
+
         if (!(flags & NOAUTO) && !(flags & AUTOMOUNT)) {
                 r = generator_add_symlink(dest, post,
                                           (flags & NOFAIL) ? "wants" : "requires", name);
@@ -532,7 +544,7 @@ static int parse_fstab(bool initrd) {
 
         while ((me = getmntent(f))) {
                 _cleanup_free_ char *where = NULL, *what = NULL, *canonical_where = NULL;
-                bool noauto, nofail;
+                bool makefs, noauto, nofail;
                 int k;
 
                 if (initrd && !mount_in_initrd(me))
@@ -574,15 +586,17 @@ static int parse_fstab(bool initrd) {
                         }
                 }
 
+                makefs = fstab_test_option(me->mnt_opts, "x-systemd.makefs\0");
                 noauto = fstab_test_yes_no_option(me->mnt_opts, "noauto\0" "auto\0");
                 nofail = fstab_test_yes_no_option(me->mnt_opts, "nofail\0" "fail\0");
-                log_debug("Found entry what=%s where=%s type=%s nofail=%s noauto=%s",
+                log_debug("Found entry what=%s where=%s type=%s makefs=%s nofail=%s noauto=%s",
                           what, where, me->mnt_type,
+                          yes_no(makefs),
                           yes_no(noauto), yes_no(nofail));
 
                 if (streq(me->mnt_type, "swap"))
                         k = add_swap(what, me,
-                                     noauto*NOAUTO | nofail*NOFAIL);
+                                     makefs*MAKEFS | noauto*NOAUTO | nofail*NOFAIL);
                 else {
                         bool automount;
                         const char *post;
@@ -604,7 +618,7 @@ static int parse_fstab(bool initrd) {
                                       me->mnt_type,
                                       me->mnt_opts,
                                       me->mnt_passno,
-                                      noauto*NOAUTO | nofail*NOFAIL | automount*AUTOMOUNT,
+                                      makefs*MAKEFS | noauto*NOAUTO | nofail*NOFAIL | automount*AUTOMOUNT,
                                       post,
                                       fstab_path);
                 }
@@ -665,7 +679,7 @@ static int add_sysroot_mount(void) {
                          arg_root_fstype,
                          opts,
                          is_device_path(what) ? 1 : 0, /* passno */
-                         0,                            /* noauto off, nofail off, automount off */
+                         0,                            /* makefs off, noauto off, nofail off, automount off */
                          SPECIAL_INITRD_ROOT_FS_TARGET,
                          "/proc/cmdline");
 }
index 462457e2fe5275e389ad970ee6c7a5153b916644..7c764328d6175101f8ca25dd0202e08ab4a02711 100644 (file)
@@ -83,8 +83,8 @@ static int write_fsck_sysroot_service(const char *dir, const char *what) {
         fprintf(f,
                 "# Automatically generated by %1$s\n\n"
                 "[Unit]\n"
-                "Documentation=man:systemd-fsck-root.service(8)\n"
                 "Description=File System Check on %2$s\n"
+                "Documentation=man:systemd-fsck-root.service(8)\n"
                 "DefaultDependencies=no\n"
                 "BindsTo=%3$s\n"
                 "After=initrd-root-device.target local-fs-pre.target %3$s\n"
@@ -248,7 +248,8 @@ int generator_write_device_deps(
 
         r = unit_name_from_path(node, ".device", &unit);
         if (r < 0)
-                return log_error_errno(r, "Failed to make unit name from path: %m");
+                return log_error_errno(r, "Failed to make unit name from path \"%s\": %m",
+                                       node);
 
         /* See mount_add_default_dependencies for explanation why we create such
          * dependencies. */
@@ -266,7 +267,8 @@ int generator_write_initrd_root_device_deps(const char *dir, const char *what) {
 
         r = unit_name_from_path(what, ".device", &unit);
         if (r < 0)
-                return log_error_errno(r, "Failed to make unit name from path: %m");
+                return log_error_errno(r, "Failed to make unit name from path \"%s\": %m",
+                                       what);
 
         return write_drop_in_format(dir, SPECIAL_INITRD_ROOT_DEVICE_TARGET, 50, "root-device",
                                     "# Automatically generated by %s\n\n"
@@ -277,3 +279,151 @@ int generator_write_initrd_root_device_deps(const char *dir, const char *what) {
                                     unit,
                                     unit);
 }
+
+int generator_hook_up_mkswap(
+                const char *dir,
+                const char *what) {
+
+        _cleanup_free_ char *node = NULL, *unit = NULL, *escaped = NULL, *where_unit = NULL;
+        _cleanup_fclose_ FILE *f = NULL;
+        const char *unit_file;
+        int r;
+
+        node = fstab_node_to_udev_node(what);
+        if (!node)
+                return log_oom();
+
+        /* Nothing to work on. */
+        if (!is_device_path(node)) {
+                log_error("Cannot format something that is not a device node: %s", node);
+                return -EINVAL;
+        }
+
+        r = unit_name_from_path_instance("systemd-mkswap", node, ".service", &unit);
+        if (r < 0)
+                return log_error_errno(r, "Failed to make unit instance name from path \"%s\": %m",
+                                       node);
+
+        unit_file = strjoina(dir, "/", unit);
+        log_debug("Creating %s", unit_file);
+
+        escaped = cescape(node);
+        if (!escaped)
+                return log_oom();
+
+        r = unit_name_from_path(what, ".swap", &where_unit);
+        if (r < 0)
+                return log_error_errno(r, "Failed to make unit name from path \"%s\": %m",
+                                       what);
+
+        f = fopen(unit_file, "wxe");
+        if (!f)
+                return log_error_errno(errno, "Failed to create unit file %s: %m",
+                                       unit_file);
+
+        fprintf(f,
+                "# Automatically generated by %s\n\n"
+                "[Unit]\n"
+                "Description=Make Swap on %%f\n"
+                "Documentation=man:systemd-mkswap@.service(8)\n"
+                "DefaultDependencies=no\n"
+                "BindsTo=%%i.device\n"
+                "After=%%i.device\n"
+                "Before=%s\n"
+                "Before=shutdown.target\n"
+                "\n"
+                "[Service]\n"
+                "Type=oneshot\n"
+                "RemainAfterExit=yes\n"
+                "ExecStart="SYSTEMD_MAKEFS_PATH " swap %s\n"
+                "TimeoutSec=0\n",
+                program_invocation_short_name,
+                where_unit,
+                escaped);
+
+        r = fflush_and_check(f);
+        if (r < 0)
+                return log_error_errno(r, "Failed to write unit file %s: %m", unit_file);
+
+        return generator_add_symlink(dir, where_unit, "requires", unit);
+}
+
+int generator_hook_up_mkfs(
+                const char *dir,
+                const char *what,
+                const char *where,
+                const char *type) {
+
+        _cleanup_free_ char *node = NULL, *unit = NULL, *escaped = NULL, *where_unit = NULL;
+        _cleanup_fclose_ FILE *f = NULL;
+        const char *unit_file;
+        int r;
+
+        node = fstab_node_to_udev_node(what);
+        if (!node)
+                return log_oom();
+
+        /* Nothing to work on. */
+        if (!is_device_path(node)) {
+                log_error("Cannot format something that is not a device node: %s", node);
+                return -EINVAL;
+        }
+
+        if (!type || streq(type, "auto")) {
+                log_error("Cannot format partition %s, filesystem type is not specified", node);
+                return -EINVAL;
+        }
+
+        r = unit_name_from_path_instance("systemd-mkfs", node, ".service", &unit);
+        if (r < 0)
+                return log_error_errno(r, "Failed to make unit instance name from path \"%s\": %m",
+                                       node);
+
+        unit_file = strjoina(dir, "/", unit);
+        log_debug("Creating %s", unit_file);
+
+        escaped = cescape(node);
+        if (!escaped)
+                return log_oom();
+
+        r = unit_name_from_path(where, ".mount", &where_unit);
+        if (r < 0)
+                return log_error_errno(r, "Failed to make unit name from path \"%s\": %m",
+                                       where);
+
+        f = fopen(unit_file, "wxe");
+        if (!f)
+                return log_error_errno(errno, "Failed to create unit file %s: %m",
+                                       unit_file);
+
+        fprintf(f,
+                "# Automatically generated by %s\n\n"
+                "[Unit]\n"
+                "Description=Make File System on %%f\n"
+                "Documentation=man:systemd-mkfs@.service(8)\n"
+                "DefaultDependencies=no\n"
+                "BindsTo=%%i.device\n"
+                "After=%%i.device\n"
+                /* fsck might or might not be used, so let's be safe and order
+                 * ourselves before both systemd-fsck@.service and the mount unit. */
+                "Before=systemd-fsck@%%i.service\n"
+                "Before=%s\n"
+                "Before=shutdown.target\n"
+                "\n"
+                "[Service]\n"
+                "Type=oneshot\n"
+                "RemainAfterExit=yes\n"
+                "ExecStart="SYSTEMD_MAKEFS_PATH " %s %s\n"
+                "TimeoutSec=0\n",
+                program_invocation_short_name,
+                where_unit,
+                type,
+                escaped);
+        // XXX: what about local-fs-pre.target?
+
+        r = fflush_and_check(f);
+        if (r < 0)
+                return log_error_errno(r, "Failed to write unit file %s: %m", unit_file);
+
+        return generator_add_symlink(dir, where_unit, "requires", unit);
+}
index 39dd520f9f149a6326e9ee5771d45864def99892..f4109b95a396c3ce6bb6d1778fe25f110d05f351 100644 (file)
@@ -39,11 +39,20 @@ int generator_write_timeouts(
         char **filtered);
 
 int generator_write_device_deps(
-                const char *dir,
-                const char *what,
-                const char *where,
-                const char *opts);
+        const char *dir,
+        const char *what,
+        const char *where,
+        const char *opts);
 
 int generator_write_initrd_root_device_deps(
         const char *dir,
         const char *what);
+
+int generator_hook_up_mkswap(
+        const char *dir,
+        const char *what);
+int generator_hook_up_mkfs(
+        const char *dir,
+        const char *what,
+        const char *where,
+        const char *type);