summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Janssen <medhefgo@web.de>2015-10-26 15:13:28 +0100
committerJan Janssen <medhefgo@web.de>2015-10-26 15:13:28 +0100
commit471b48ed2ff6539e7071ff4694c03483c5835639 (patch)
tree58d2bc5567406ed5da28631c59c5ba78cb56d518
parentad1a44b23bbc909aa3f5876dadd482a9f6c18d5c (diff)
unmount: Pass in mount options when remounting read-only
man 2 mount says that the mountflags and data parameteres should match the original values except for the desired changes. We only bother with the mount options since the only flags we can change are MS_RDONLY, MS_SYNCHRONOUS and MS_MANDLOCK; which shouldn't matter too much. Fixes: #351
-rw-r--r--src/core/umount.c26
1 files changed, 20 insertions, 6 deletions
diff --git a/src/core/umount.c b/src/core/umount.c
index 0e61bcaebb..8735bed7b1 100644
--- a/src/core/umount.c
+++ b/src/core/umount.c
@@ -31,6 +31,7 @@
#include "escape.h"
#include "fd-util.h"
+#include "fstab-util.h"
#include "list.h"
#include "mount-setup.h"
#include "path-util.h"
@@ -42,6 +43,7 @@
typedef struct MountPoint {
char *path;
+ char *options;
dev_t devnum;
LIST_FIELDS(struct MountPoint, mount_point);
} MountPoint;
@@ -75,7 +77,7 @@ static int mount_points_list_get(MountPoint **head) {
return -errno;
for (i = 1;; i++) {
- _cleanup_free_ char *path = NULL;
+ _cleanup_free_ char *path = NULL, *options = NULL;
char *p = NULL;
MountPoint *m;
int k;
@@ -86,15 +88,15 @@ static int mount_points_list_get(MountPoint **head) {
"%*s " /* (3) major:minor */
"%*s " /* (4) root */
"%ms " /* (5) mount point */
- "%*s" /* (6) mount options */
+ "%*s" /* (6) mount flags */
"%*[^-]" /* (7) optional fields */
"- " /* (8) separator */
"%*s " /* (9) file system type */
"%*s" /* (10) mount source */
- "%*s" /* (11) mount options 2 */
+ "%ms" /* (11) mount options */
"%*[^\n]", /* some rubbish at the end */
- &path);
- if (k != 1) {
+ &path, &options);
+ if (k != 2) {
if (k == EOF)
break;
@@ -129,6 +131,9 @@ static int mount_points_list_get(MountPoint **head) {
}
m->path = p;
+ m->options = options;
+ options = NULL;
+
LIST_PREPEND(mount_point, *head, m);
}
@@ -373,6 +378,14 @@ static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_e
benefits, but might confuse the host, as we remount
the superblock here, not the bind mound. */
if (detect_container() <= 0) {
+ _cleanup_free_ char *options = NULL;
+ /* MS_REMOUNT requires that the data parameter
+ * should be the same from the original mount
+ * except for the desired changes. Since we want
+ * to remount read-only, we should filter out
+ * rw (and ro too, because it confuses the kernel) */
+ (void) fstab_filter_options(m->options, "rw\0ro\0", NULL, NULL, &options);
+
/* We always try to remount directories
* read-only first, before we go on and umount
* them.
@@ -389,7 +402,8 @@ static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_e
* alias read-only we hence should be
* relatively safe regarding keeping the fs we
* can otherwise not see dirty. */
- (void) mount(NULL, m->path, NULL, MS_REMOUNT|MS_RDONLY, NULL);
+ log_info("Remounting '%s' read-only with options '%s'.", m->path, options);
+ (void) mount(NULL, m->path, NULL, MS_REMOUNT|MS_RDONLY, options);
}
/* Skip / and /usr since we cannot unmount that