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