From 93bd157722c76b47d80742f290373c1ce2865070 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 16 Nov 2012 18:36:28 +0100
Subject: [PATCH] umount: always remount read-only before unmounting in final
shutdown loop
---
src/core/umount.c | 57 ++++++++++++++++++++++++++-----------------------------
1 file changed, 27 insertions(+), 30 deletions(-)
diff --git a/src/core/umount.c b/src/core/umount.c
index 83c9de3..e794057 100644
--- a/src/core/umount.c
+++ b/src/core/umount.c
@@ -407,6 +407,33 @@ static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_e
assert(head);
LIST_FOREACH_SAFE(mount_point, m, n, *head) {
+
+ /* If we are in a container, don't attempt to
+ read-only mount anything as that brings no real
+ benefits, but might confuse the host, as we remount
+ the superblock here, not the bind mound. */
+ if (detect_container(NULL) <= 0) {
+ /* We always try to remount directories
+ * read-only first, before we go on and umount
+ * them.
+ *
+ * Mount points can be stacked. If a mount
+ * point is stacked below / or /usr, we
+ * cannnot umount or remount it directly,
+ * since there is no way to refer to the
+ * underlying mount. There's nothing we can do
+ * about it for the general case, but we can
+ * do something about it if it is aliased
+ * somehwere else via a bind mount. If we
+ * explicitly remount the super block of that
+ * alias read-only we hence should be
+ * relatively safe regarding keeping the fs we
+ * can otherwise not see dirty. */
+ mount(NULL, m->path, NULL, MS_REMOUNT|MS_RDONLY, NULL);
+ }
+
+ /* Skip / and /usr since we cannot unmount that
+ * anyway, since we are running from it */
if (path_equal(m->path, "/")
#ifndef HAVE_SPLIT_USR
|| path_equal(m->path, "/usr")
@@ -432,29 +459,6 @@ static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_e
return n_failed;
}
-static int mount_points_list_remount_read_only(MountPoint **head, bool *changed) {
- MountPoint *m, *n;
- int n_failed = 0;
-
- assert(head);
-
- LIST_FOREACH_SAFE(mount_point, m, n, *head) {
-
- /* Trying to remount read-only */
- if (mount(NULL, m->path, NULL, MS_REMOUNT|MS_RDONLY, NULL) == 0) {
- if (changed)
- *changed = true;
-
- mount_point_free(head, m);
- } else {
- log_warning("Could not remount as read-only %s: %m", m->path);
- n_failed++;
- }
- }
-
- return n_failed;
-}
-
static int swap_points_list_off(MountPoint **head, bool *changed) {
MountPoint *m, *n;
int n_failed = 0;
@@ -571,13 +575,6 @@ int umount_all(bool *changed) {
if (r <= 0)
goto end;
- /* If we are in a container, don't attempt to read-only mount
- anything as that brings no real benefits, but might confuse
- the host, as we remount the superblock here, not the bind
- mound. */
- if (detect_container(NULL) <= 0)
- r = mount_points_list_remount_read_only(&mp_list_head, changed);
-
end:
mount_points_list_free(&mp_list_head);
--
1.7.12.1