803fb7
From 02a5d91ec022be1188875e0f169277cef3b11ad6 Mon Sep 17 00:00:00 2001
803fb7
From: Jan Janssen <medhefgo@web.de>
803fb7
Date: Mon, 26 Oct 2015 15:13:28 +0100
803fb7
Subject: [PATCH] unmount: Pass in mount options when remounting read-only
803fb7
803fb7
man 2 mount says that the mountflags and data parameteres should
803fb7
match the original values except for the desired changes. We only
803fb7
bother with the mount options since the only flags we can change
803fb7
are MS_RDONLY, MS_SYNCHRONOUS and MS_MANDLOCK; which shouldn't
803fb7
matter too much.
803fb7
803fb7
Fixes: #351
803fb7
803fb7
(cherry picked from commit 471b48ed2ff6539e7071ff4694c03483c5835639)
803fb7
803fb7
Related: #1312002
803fb7
---
803fb7
 src/core/umount.c | 26 ++++++++++++++++++++------
803fb7
 1 file changed, 20 insertions(+), 6 deletions(-)
803fb7
803fb7
diff --git a/src/core/umount.c b/src/core/umount.c
803fb7
index dd7df194d..bfd8aa5f8 100644
803fb7
--- a/src/core/umount.c
803fb7
+++ b/src/core/umount.c
803fb7
@@ -28,6 +28,7 @@
803fb7
 #include <linux/loop.h>
803fb7
 #include <linux/dm-ioctl.h>
803fb7
 
803fb7
+#include "fstab-util.h"
803fb7
 #include "list.h"
803fb7
 #include "mount-setup.h"
803fb7
 #include "umount.h"
803fb7
@@ -39,6 +40,7 @@
803fb7
 
803fb7
 typedef struct MountPoint {
803fb7
         char *path;
803fb7
+        char *options;
803fb7
         dev_t devnum;
803fb7
         LIST_FIELDS(struct MountPoint, mount_point);
803fb7
 } MountPoint;
803fb7
@@ -71,7 +73,7 @@ static int mount_points_list_get(MountPoint **head) {
803fb7
                 return -errno;
803fb7
 
803fb7
         for (i = 1;; i++) {
803fb7
-                _cleanup_free_ char *path = NULL;
803fb7
+                _cleanup_free_ char *path = NULL, *options = NULL;
803fb7
                 char *p = NULL;
803fb7
                 MountPoint *m;
803fb7
                 int k;
803fb7
@@ -82,15 +84,15 @@ static int mount_points_list_get(MountPoint **head) {
803fb7
                            "%*s "       /* (3) major:minor */
803fb7
                            "%*s "       /* (4) root */
803fb7
                            "%ms "       /* (5) mount point */
803fb7
-                           "%*s"        /* (6) mount options */
803fb7
+                           "%*s"        /* (6) mount flags */
803fb7
                            "%*[^-]"     /* (7) optional fields */
803fb7
                            "- "         /* (8) separator */
803fb7
                            "%*s "       /* (9) file system type */
803fb7
                            "%*s"        /* (10) mount source */
803fb7
-                           "%*s"        /* (11) mount options 2 */
803fb7
+                           "%ms"        /* (11) mount options */
803fb7
                            "%*[^\n]",   /* some rubbish at the end */
803fb7
-                           &path);
803fb7
-                if (k != 1) {
803fb7
+                           &path, &options);
803fb7
+                if (k != 2) {
803fb7
                         if (k == EOF)
803fb7
                                 break;
803fb7
 
803fb7
@@ -125,6 +127,9 @@ static int mount_points_list_get(MountPoint **head) {
803fb7
                 }
803fb7
 
803fb7
                 m->path = p;
803fb7
+                m->options = options;
803fb7
+                options = NULL;
803fb7
+
803fb7
                 LIST_PREPEND(mount_point, *head, m);
803fb7
         }
803fb7
 
803fb7
@@ -368,6 +373,14 @@ static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_e
803fb7
                    benefits, but might confuse the host, as we remount
803fb7
                    the superblock here, not the bind mound. */
803fb7
                 if (detect_container(NULL) <= 0)  {
803fb7
+                        _cleanup_free_ char *options = NULL;
803fb7
+                        /* MS_REMOUNT requires that the data parameter
803fb7
+                         * should be the same from the original mount
803fb7
+                         * except for the desired changes. Since we want
803fb7
+                         * to remount read-only, we should filter out
803fb7
+                         * rw (and ro too, because it confuses the kernel) */
803fb7
+                        (void) fstab_filter_options(m->options, "rw\0ro\0", NULL, NULL, &options);
803fb7
+
803fb7
                         /* We always try to remount directories
803fb7
                          * read-only first, before we go on and umount
803fb7
                          * them.
803fb7
@@ -384,7 +397,8 @@ static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_e
803fb7
                          * alias read-only we hence should be
803fb7
                          * relatively safe regarding keeping the fs we
803fb7
                          * can otherwise not see dirty. */
803fb7
-                        mount(NULL, m->path, NULL, MS_REMOUNT|MS_RDONLY, NULL);
803fb7
+                        log_info("Remounting '%s' read-only with options '%s'.", m->path, options);
803fb7
+                        (void) mount(NULL, m->path, NULL, MS_REMOUNT|MS_RDONLY, options);
803fb7
                 }
803fb7
 
803fb7
                 /* Skip / and /usr since we cannot unmount that