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