84b277
From c9e49e522d609f39ab77cbab18b8f1389692e1b8 Mon Sep 17 00:00:00 2001
84b277
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
84b277
Date: Tue, 12 Nov 2013 00:53:59 -0500
84b277
Subject: [PATCH] fsck,fstab-generator: be lenient about missing fsck.<type>
84b277
84b277
If fstab contains 1 for passno, treat this as an error, but only warn
84b277
briefly. If fstab doesn't contain this information, don't complain at
84b277
all.
84b277
84b277
Patch is complicated a bit by the fact that we might have the fstype specified
84b277
in fstab or on /proc/cmdline, in which case we can check if we have the appropriate
84b277
fsck tool, or not specified, or specified as auto, in which case we have to look
84b277
and check the type of the filesystem ourselves. It cannot be done before the
84b277
device appears, so it is too early in the generator phase, and it must be done
84b277
directly in fsck service.
84b277
84b277
(cherry picked from commit 94192cdaf652c9717f15274504ed315126c07a93)
84b277
84b277
Resolves: #1098310
84b277
---
84b277
 src/fsck/fsck.c                       | 40 ++++++++++++++----
84b277
 src/fstab-generator/fstab-generator.c | 77 +++++++++++++++++++++++------------
84b277
 2 files changed, 82 insertions(+), 35 deletions(-)
84b277
84b277
diff --git a/src/fsck/fsck.c b/src/fsck/fsck.c
84b277
index 9b4e555..1189fe7 100644
84b277
--- a/src/fsck/fsck.c
84b277
+++ b/src/fsck/fsck.c
84b277
@@ -244,10 +244,11 @@ int main(int argc, char *argv[]) {
84b277
         siginfo_t status;
84b277
         _cleanup_udev_unref_ struct udev *udev = NULL;
84b277
         _cleanup_udev_device_unref_ struct udev_device *udev_device = NULL;
84b277
-        const char *device;
84b277
+        const char *device, *type;
84b277
         bool root_directory;
84b277
         int progress_pipe[2] = { -1, -1 };
84b277
         char dash_c[2+10+1];
84b277
+        struct stat st;
84b277
 
84b277
         if (argc > 2) {
84b277
                 log_error("This program expects one or no arguments.");
84b277
@@ -266,11 +267,27 @@ int main(int argc, char *argv[]) {
84b277
         if (!arg_force && arg_skip)
84b277
                 return 0;
84b277
 
84b277
+        udev = udev_new();
84b277
+        if (!udev) {
84b277
+                log_oom();
84b277
+                return EXIT_FAILURE;
84b277
+        }
84b277
+
84b277
         if (argc > 1) {
84b277
                 device = argv[1];
84b277
                 root_directory = false;
84b277
+
84b277
+                if (stat(device, &st) < 0) {
84b277
+                        log_error("Failed to stat '%s': %m", device);
84b277
+                        return EXIT_FAILURE;
84b277
+                }
84b277
+
84b277
+                udev_device = udev_device_new_from_devnum(udev, 'b', st.st_rdev);
84b277
+                if (!udev_device) {
84b277
+                        log_error("Failed to detect device %s", device);
84b277
+                        return EXIT_FAILURE;
84b277
+                }
84b277
         } else {
84b277
-                struct stat st;
84b277
                 struct timespec times[2];
84b277
 
84b277
                 /* Find root device */
84b277
@@ -292,12 +309,6 @@ int main(int argc, char *argv[]) {
84b277
                         return EXIT_SUCCESS;
84b277
                 }
84b277
 
84b277
-                udev = udev_new();
84b277
-                if (!udev) {
84b277
-                        log_oom();
84b277
-                        return EXIT_FAILURE;
84b277
-                }
84b277
-
84b277
                 udev_device = udev_device_new_from_devnum(udev, 'b', st.st_dev);
84b277
                 if (!udev_device) {
84b277
                         log_error("Failed to detect root device.");
84b277
@@ -313,6 +324,19 @@ int main(int argc, char *argv[]) {
84b277
                 root_directory = true;
84b277
         }
84b277
 
84b277
+        type = udev_device_get_property_value(udev_device, "ID_FS_TYPE");
84b277
+        if (type) {
84b277
+                const char *checker = strappenda("/sbin/fsck.", type);
84b277
+                r = access(checker, X_OK);
84b277
+                if (r < 0) {
84b277
+                        if (errno == ENOENT) {
84b277
+                                log_info("%s doesn't exist, not checking file system.", checker);
84b277
+                                return EXIT_SUCCESS;
84b277
+                        } else
84b277
+                                log_warning("%s cannot be used: %m", checker);
84b277
+                }
84b277
+        }
84b277
+
84b277
         if (arg_show_progress)
84b277
                 if (pipe(progress_pipe) < 0) {
84b277
                         log_error("pipe(): %m");
84b277
diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c
84b277
index 78d7609..fa23ac9 100644
84b277
--- a/src/fstab-generator/fstab-generator.c
84b277
+++ b/src/fstab-generator/fstab-generator.c
84b277
@@ -147,6 +147,52 @@ static bool mount_in_initrd(struct mntent *me) {
84b277
                 streq(me->mnt_dir, "/usr");
84b277
 }
84b277
 
84b277
+static int add_fsck(FILE *f, const char *what, const char *where, const char *type, int passno) {
84b277
+        assert(f);
84b277
+
84b277
+        if (passno == 0)
84b277
+                return 0;
84b277
+
84b277
+        if (type && !streq(type, "auto")) {
84b277
+                int r;
84b277
+                const char *checker;
84b277
+
84b277
+                checker = strappenda("/sbin/fsck.", type);
84b277
+                r = access(checker, X_OK);
84b277
+                if (r < 0) {
84b277
+                        log_warning("Checking was requested for %s, but %s cannot be used: %m", what, checker);
84b277
+
84b277
+                        /* treat missing check as essentially OK */
84b277
+                        return errno == ENOENT ? 0 : -errno;
84b277
+                }
84b277
+        }
84b277
+
84b277
+        if (streq(where, "/")) {
84b277
+                char *lnk;
84b277
+
84b277
+                lnk = strappenda(arg_dest, "/" SPECIAL_LOCAL_FS_TARGET ".wants/systemd-fsck-root.service");
84b277
+                mkdir_parents_label(lnk, 0755);
84b277
+                if (symlink("systemd-fsck-root.service", lnk) < 0) {
84b277
+                        log_error("Failed to create symlink %s: %m", lnk);
84b277
+                        return -errno;
84b277
+                }
84b277
+        } else {
84b277
+                _cleanup_free_ char *fsck = NULL;
84b277
+
84b277
+                fsck = unit_name_from_path_instance("systemd-fsck", what, ".service");
84b277
+                if (!fsck)
84b277
+                        return log_oom();
84b277
+
84b277
+                fprintf(f,
84b277
+                        "Requires=%s\n"
84b277
+                        "After=%s\n",
84b277
+                        fsck,
84b277
+                        fsck);
84b277
+        }
84b277
+
84b277
+        return 0;
84b277
+}
84b277
+
84b277
 static int add_mount(
84b277
                 const char *what,
84b277
                 const char *where,
84b277
@@ -162,6 +208,7 @@ static int add_mount(
84b277
                 *name = NULL, *unit = NULL, *lnk = NULL,
84b277
                 *automount_name = NULL, *automount_unit = NULL;
84b277
         _cleanup_fclose_ FILE *f = NULL;
84b277
+        int r;
84b277
 
84b277
         assert(what);
84b277
         assert(where);
84b277
@@ -209,32 +256,9 @@ static int add_mount(
84b277
                         "Before=%s\n",
84b277
                         post);
84b277
 
84b277
-        if (passno > 0) {
84b277
-                if (streq(where, "/")) {
84b277
-                        lnk = strjoin(arg_dest, "/", SPECIAL_LOCAL_FS_TARGET, ".wants/", "systemd-fsck-root.service", NULL);
84b277
-                        if (!lnk)
84b277
-                                return log_oom();
84b277
-
84b277
-                        mkdir_parents_label(lnk, 0755);
84b277
-                        if (symlink("systemd-fsck-root.service", lnk) < 0) {
84b277
-                                log_error("Failed to create symlink %s: %m", lnk);
84b277
-                                return -errno;
84b277
-                        }
84b277
-                } else {
84b277
-                        _cleanup_free_ char *fsck = NULL;
84b277
-
84b277
-                        fsck = unit_name_from_path_instance("systemd-fsck", what, ".service");
84b277
-                        if (!fsck)
84b277
-                                return log_oom();
84b277
-
84b277
-                        fprintf(f,
84b277
-                                "Requires=%s\n"
84b277
-                                "After=%s\n",
84b277
-                                fsck,
84b277
-                                fsck);
84b277
-                }
84b277
-        }
84b277
-
84b277
+        r = add_fsck(f, what, where, type, passno);
84b277
+        if (r < 0)
84b277
+                return r;
84b277
 
84b277
         fprintf(f,
84b277
                 "\n"
84b277
@@ -260,7 +284,6 @@ static int add_mount(
84b277
 
84b277
         if (!noauto) {
84b277
                 if (post) {
84b277
-                        free(lnk);
84b277
                         lnk = strjoin(arg_dest, "/", post, nofail || automount ? ".wants/" : ".requires/", name, NULL);
84b277
                         if (!lnk)
84b277
                                 return log_oom();