From 659b15313b9ca8c7f3f6e523e0d3fd696243ff8b Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Thu, 8 Mar 2018 16:44:17 +0100 Subject: [PATCH 1/7] umount: Fix memory leak --- src/core/umount.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/umount.c b/src/core/umount.c index ff3e63710c..8ba4179a0f 100644 --- a/src/core/umount.c +++ b/src/core/umount.c @@ -61,6 +61,8 @@ static void mount_point_free(MountPoint **head, MountPoint *m) { LIST_REMOVE(mount_point, *head, m); free(m->path); + free(m->options); + free(m->type); free(m); } From 0494cae03d762eaf2fb7217ee7d70f615dcb5183 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Thu, 8 Mar 2018 17:22:58 +0100 Subject: [PATCH 2/7] umount: Add more asserts and remove some unused arguments --- src/core/umount.c | 54 +++++++++++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/src/core/umount.c b/src/core/umount.c index 8ba4179a0f..fd478d9123 100644 --- a/src/core/umount.c +++ b/src/core/umount.c @@ -333,6 +333,8 @@ static int delete_loopback(const char *device) { _cleanup_close_ int fd = -1; int r; + assert(device); + fd = open(device, O_RDONLY|O_CLOEXEC); if (fd < 0) return errno == ENOENT ? 0 : -errno; @@ -382,12 +384,15 @@ static bool nonunmountable_path(const char *path) { || path_startswith(path, "/run/initramfs"); } -static int remount_with_timeout(MountPoint *m, char *options, int *n_failed) { +static int remount_with_timeout(MountPoint *m, char *options) { pid_t pid; int r; BLOCK_SIGNALS(SIGCHLD); + assert(m); + assert(options); + /* Due to the possiblity of a remount operation hanging, we * fork a child process and set a timeout. If the timeout * lapses, the assumption is that that particular remount @@ -418,12 +423,14 @@ static int remount_with_timeout(MountPoint *m, char *options, int *n_failed) { return r; } -static int umount_with_timeout(MountPoint *m, bool *changed) { +static int umount_with_timeout(MountPoint *m) { pid_t pid; int r; BLOCK_SIGNALS(SIGCHLD); + assert(m); + /* Due to the possiblity of a umount operation hanging, we * fork a child process and set a timeout. If the timeout * lapses, the assumption is that that particular umount @@ -468,6 +475,7 @@ static int mount_points_list_umount(MountPoint **head, bool *changed) { int n_failed = 0; assert(head); + assert(changed); LIST_FOREACH(mount_point, m, *head) { bool mount_is_readonly; @@ -514,7 +522,7 @@ static int mount_points_list_umount(MountPoint **head, bool *changed) { * Since the remount can hang in the instance of * remote filesystems, we remount asynchronously * and skip the subsequent umount if it fails */ - if (remount_with_timeout(m, options, &n_failed) < 0) { + if (remount_with_timeout(m, options) < 0) { if (nonunmountable_path(m->path)) n_failed++; continue; @@ -528,12 +536,10 @@ static int mount_points_list_umount(MountPoint **head, bool *changed) { continue; /* Trying to umount */ - if (umount_with_timeout(m, changed) < 0) + if (umount_with_timeout(m) < 0) n_failed++; - else { - if (changed) - *changed = true; - } + else + *changed = true; } return n_failed; @@ -544,13 +550,12 @@ static int swap_points_list_off(MountPoint **head, bool *changed) { int n_failed = 0; assert(head); + assert(changed); LIST_FOREACH_SAFE(mount_point, m, n, *head) { log_info("Deactivating swap %s.", m->path); if (swapoff(m->path) == 0) { - if (changed) - *changed = true; - + *changed = true; mount_point_free(head, m); } else { log_warning_errno(errno, "Could not deactivate swap %s: %m", m->path); @@ -567,6 +572,7 @@ static int loopback_points_list_detach(MountPoint **head, bool *changed) { struct stat root_st; assert(head); + assert(changed); k = lstat("/", &root_st); @@ -585,7 +591,7 @@ static int loopback_points_list_detach(MountPoint **head, bool *changed) { log_info("Detaching loopback %s.", m->path); r = delete_loopback(m->path); if (r >= 0) { - if (r > 0 && changed) + if (r > 0) *changed = true; mount_point_free(head, m); @@ -604,6 +610,7 @@ static int dm_points_list_detach(MountPoint **head, bool *changed) { dev_t rootdev; assert(head); + assert(changed); r = get_block_device("/", &rootdev); if (r <= 0) @@ -611,18 +618,15 @@ static int dm_points_list_detach(MountPoint **head, bool *changed) { LIST_FOREACH_SAFE(mount_point, m, n, *head) { - if (major(rootdev) != 0) - if (rootdev == m->devnum) { - n_failed ++; - continue; - } + if (major(rootdev) != 0 && rootdev == m->devnum) { + n_failed ++; + continue; + } log_info("Detaching DM %u:%u.", major(m->devnum), minor(m->devnum)); r = delete_dm(m->devnum); if (r >= 0) { - if (changed) - *changed = true; - + *changed = true; mount_point_free(head, m); } else { log_warning_errno(errno, "Could not detach DM %s: %m", m->path); @@ -637,6 +641,8 @@ static int umount_all_once(bool *changed) { int r; LIST_HEAD(MountPoint, mp_list_head); + assert(changed); + LIST_HEAD_INIT(mp_list_head); r = mount_points_list_get(&mp_list_head); if (r < 0) @@ -654,6 +660,8 @@ int umount_all(bool *changed) { bool umount_changed; int r; + assert(changed); + /* Retry umount, until nothing can be umounted anymore. Mounts are * processed in order, newest first. The retries are needed when * an old mount has been moved, to a path inside a newer mount. */ @@ -672,6 +680,8 @@ int swapoff_all(bool *changed) { int r; LIST_HEAD(MountPoint, swap_list_head); + assert(changed); + LIST_HEAD_INIT(swap_list_head); r = swap_list_get(&swap_list_head); @@ -690,6 +700,8 @@ int loopback_detach_all(bool *changed) { int r; LIST_HEAD(MountPoint, loopback_list_head); + assert(changed); + LIST_HEAD_INIT(loopback_list_head); r = loopback_list_get(&loopback_list_head); @@ -708,6 +720,8 @@ int dm_detach_all(bool *changed) { int r; LIST_HEAD(MountPoint, dm_list_head); + assert(changed); + LIST_HEAD_INIT(dm_list_head); r = dm_list_get(&dm_list_head); From 1d62d22d9432d5c4a637002c9a29b20d52f25d9a Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Thu, 8 Mar 2018 17:40:44 +0100 Subject: [PATCH 3/7] umount: Decide whether to remount read-only earlier --- src/core/umount.c | 52 +++++++++++++++++++---------------------------- 1 file changed, 21 insertions(+), 31 deletions(-) diff --git a/src/core/umount.c b/src/core/umount.c index fd478d9123..16e82a7925 100644 --- a/src/core/umount.c +++ b/src/core/umount.c @@ -49,7 +49,7 @@ typedef struct MountPoint { char *path; char *options; - char *type; + bool try_remount_ro; dev_t devnum; LIST_FIELDS(struct MountPoint, mount_point); } MountPoint; @@ -62,7 +62,6 @@ static void mount_point_free(MountPoint **head, MountPoint *m) { free(m->path); free(m->options); - free(m->type); free(m); } @@ -85,8 +84,7 @@ static int mount_points_list_get(MountPoint **head) { return -errno; for (i = 1;; i++) { - _cleanup_free_ char *path = NULL, *options = NULL, *type = NULL; - char *p = NULL; + _cleanup_free_ char *path = NULL, *options = NULL, *type = NULL, *p = NULL; MountPoint *m; int k; @@ -127,22 +125,29 @@ static int mount_points_list_get(MountPoint **head) { mount_point_ignore(p) || path_startswith(p, "/dev") || path_startswith(p, "/sys") || - path_startswith(p, "/proc")) { - free(p); + path_startswith(p, "/proc")) continue; - } m = new0(MountPoint, 1); - if (!m) { - free(p); + if (!m) return -ENOMEM; - } - m->path = p; - m->options = options; - options = NULL; - m->type = type; - type = NULL; + /* 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 mount. + * + * If the filesystem is a network fs, also skip the + * remount. It brings no value (we cannot leave + * a "dirty fs") and could hang if the network is down. + * Note that umount2() is more careful and will not + * hang because of the network being down. */ + m->try_remount_ro = detect_container() <= 0 && + !fstype_is_network(type) && + !fstab_test_yes_no_option(options, "ro\0rw\0"); + + free_and_replace(m->path, p); + free_and_replace(m->options, options); LIST_PREPEND(mount_point, *head, m); } @@ -478,22 +483,7 @@ static int mount_points_list_umount(MountPoint **head, bool *changed) { assert(changed); LIST_FOREACH(mount_point, m, *head) { - bool mount_is_readonly; - - mount_is_readonly = fstab_test_yes_no_option(m->options, "ro\0rw\0"); - - /* 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 mount. - If the filesystem is a network fs, also skip the - remount. It brings no value (we cannot leave - a "dirty fs") and could hang if the network is down. - Note that umount2() is more careful and will not - hang because of the network being down. */ - if (detect_container() <= 0 && - !fstype_is_network(m->type) && - !mount_is_readonly) { + if (m->try_remount_ro) { _cleanup_free_ char *options = NULL; /* MS_REMOUNT requires that the data parameter * should be the same from the original mount From 3bc341bee9fc7dfb41a131246b6fb0afd6ff4407 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Thu, 8 Mar 2018 18:37:21 +0100 Subject: [PATCH 4/7] umount: Provide the same mount flags too when remounting read-only This most likely amounts to no real benefits and is just here for completeness sake. --- src/core/umount.c | 57 +++++++++++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 22 deletions(-) diff --git a/src/core/umount.c b/src/core/umount.c index 16e82a7925..9770bdb1da 100644 --- a/src/core/umount.c +++ b/src/core/umount.c @@ -48,7 +48,8 @@ typedef struct MountPoint { char *path; - char *options; + char *remount_options; + unsigned long remount_flags; bool try_remount_ro; dev_t devnum; LIST_FIELDS(struct MountPoint, mount_point); @@ -61,7 +62,7 @@ static void mount_point_free(MountPoint **head, MountPoint *m) { LIST_REMOVE(mount_point, *head, m); free(m->path); - free(m->options); + free(m->remount_options); free(m); } @@ -84,7 +85,7 @@ static int mount_points_list_get(MountPoint **head) { return -errno; for (i = 1;; i++) { - _cleanup_free_ char *path = NULL, *options = NULL, *type = NULL, *p = NULL; + _cleanup_free_ char *path = NULL, *options = NULL, *flags = NULL, *type = NULL, *p = NULL; MountPoint *m; int k; @@ -94,15 +95,15 @@ static int mount_points_list_get(MountPoint **head) { "%*s " /* (3) major:minor */ "%*s " /* (4) root */ "%ms " /* (5) mount point */ - "%*s" /* (6) mount flags */ + "%ms" /* (6) mount flags */ "%*[^-]" /* (7) optional fields */ "- " /* (8) separator */ "%ms " /* (9) file system type */ "%*s" /* (10) mount source */ "%ms" /* (11) mount options */ "%*[^\n]", /* some rubbish at the end */ - &path, &type, &options); - if (k != 3) { + &path, &flags, &type, &options); + if (k != 4) { if (k == EOF) break; @@ -132,6 +133,8 @@ static int mount_points_list_get(MountPoint **head) { if (!m) return -ENOMEM; + free_and_replace(m->path, p); + /* 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 @@ -146,8 +149,28 @@ static int mount_points_list_get(MountPoint **head) { !fstype_is_network(type) && !fstab_test_yes_no_option(options, "ro\0rw\0"); - free_and_replace(m->path, p); - free_and_replace(m->options, options); + if (m->try_remount_ro) { + _cleanup_free_ char *unknown_flags = NULL; + + /* mount(2) states that mount flags and options need to be exactly the same + * as they were when the filesystem was mounted, except for the desired + * changes. So we reconstruct both here and adjust them for the later + * remount call too. */ + + r = mount_option_mangle(flags, 0, &m->remount_flags, &unknown_flags); + if (r < 0) + return r; + if (!isempty(unknown_flags)) + log_warning("Ignoring unknown mount flags '%s'.", unknown_flags); + + r = mount_option_mangle(options, m->remount_flags, &m->remount_flags, &m->remount_options); + if (r < 0) + return r; + + /* MS_BIND is special. If it is provided it will only make the mount-point + * read-only. If left out, the super block itself is remounted, which we want. */ + m->remount_flags = (m->remount_flags|MS_REMOUNT|MS_RDONLY) & ~MS_BIND; + } LIST_PREPEND(mount_point, *head, m); } @@ -389,14 +412,13 @@ static bool nonunmountable_path(const char *path) { || path_startswith(path, "/run/initramfs"); } -static int remount_with_timeout(MountPoint *m, char *options) { +static int remount_with_timeout(MountPoint *m) { pid_t pid; int r; BLOCK_SIGNALS(SIGCHLD); assert(m); - assert(options); /* Due to the possiblity of a remount operation hanging, we * fork a child process and set a timeout. If the timeout @@ -406,10 +428,10 @@ static int remount_with_timeout(MountPoint *m, char *options) { if (r < 0) return r; if (r == 0) { - log_info("Remounting '%s' read-only in with options '%s'.", m->path, options); + log_info("Remounting '%s' read-only in with options '%s'.", m->path, m->remount_options); /* Start the mount operation here in the child */ - r = mount(NULL, m->path, NULL, MS_REMOUNT|MS_RDONLY, options); + r = mount(NULL, m->path, NULL, m->remount_flags, m->remount_options); if (r < 0) log_error_errno(errno, "Failed to remount '%s' read-only: %m", m->path); @@ -474,7 +496,6 @@ static int umount_with_timeout(MountPoint *m) { /* This includes remounting readonly, which changes the kernel mount options. * Therefore the list passed to this function is invalidated, and should not be reused. */ - static int mount_points_list_umount(MountPoint **head, bool *changed) { MountPoint *m; int n_failed = 0; @@ -484,14 +505,6 @@ static int mount_points_list_umount(MountPoint **head, bool *changed) { LIST_FOREACH(mount_point, m, *head) { if (m->try_remount_ro) { - _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. @@ -512,7 +525,7 @@ static int mount_points_list_umount(MountPoint **head, bool *changed) { * Since the remount can hang in the instance of * remote filesystems, we remount asynchronously * and skip the subsequent umount if it fails */ - if (remount_with_timeout(m, options) < 0) { + if (remount_with_timeout(m) < 0) { if (nonunmountable_path(m->path)) n_failed++; continue; From 8645ffd12b3cc7b0292acd9e1d691c4fab4cf409 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Thu, 8 Mar 2018 18:46:58 +0100 Subject: [PATCH 5/7] umount: Try unmounting even if remounting read-only failed In the case of some api filesystems remounting read-only fails while unmounting succeeds. --- src/core/umount.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/core/umount.c b/src/core/umount.c index 9770bdb1da..40153defe5 100644 --- a/src/core/umount.c +++ b/src/core/umount.c @@ -519,16 +519,19 @@ static int mount_points_list_umount(MountPoint **head, bool *changed) { * 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 dirty an fs + * relatively safe regarding keeping a dirty fs * we cannot otherwise see. * * Since the remount can hang in the instance of * remote filesystems, we remount asynchronously - * and skip the subsequent umount if it fails */ + * and skip the subsequent umount if it fails. */ if (remount_with_timeout(m) < 0) { - if (nonunmountable_path(m->path)) + /* Remount failed, but try unmounting anyway, + * unless this is a mount point we want to skip. */ + if (nonunmountable_path(m->path)) { n_failed++; - continue; + continue; + } } } From e783b4902f387640bba12496936d01e967545c3c Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Thu, 8 Mar 2018 18:51:13 +0100 Subject: [PATCH 6/7] umount: Don't bother remounting api and ro filesystems read-only --- src/core/umount.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/umount.c b/src/core/umount.c index 40153defe5..f9b4a21cfc 100644 --- a/src/core/umount.c +++ b/src/core/umount.c @@ -147,6 +147,8 @@ static int mount_points_list_get(MountPoint **head) { * hang because of the network being down. */ m->try_remount_ro = detect_container() <= 0 && !fstype_is_network(type) && + !fstype_is_api_vfs(type) && + !fstype_is_ro(type) && !fstab_test_yes_no_option(options, "ro\0rw\0"); if (m->try_remount_ro) { From 456b2199f6ef0378da007e71347657bcf83ae465 Mon Sep 17 00:00:00 2001 From: Jan Janssen Date: Mon, 12 Mar 2018 13:33:16 +0100 Subject: [PATCH 7/7] shutdown: Reduce log level of unmounts There is little point in logging about unmounting errors if the exact mountpoint will be successfully unmounted in a later retry due unmounts below it having been removed. Additionally, don't log those errors if we are going to switch back to a initrd, because that one is also likely to finalize the remaining mountpoints. If not, it will log errors then. --- src/core/shutdown.c | 24 +++++++++++++++++------- src/core/umount.c | 42 +++++++++++++++++++++--------------------- src/core/umount.h | 6 +++--- 3 files changed, 41 insertions(+), 31 deletions(-) diff --git a/src/core/shutdown.c b/src/core/shutdown.c index 58c9a9de79..fec9c276fc 100644 --- a/src/core/shutdown.c +++ b/src/core/shutdown.c @@ -269,11 +269,11 @@ static void sync_with_progress(void) { int main(int argc, char *argv[]) { bool need_umount, need_swapoff, need_loop_detach, need_dm_detach; - bool in_container, use_watchdog = false; + bool in_container, use_watchdog = false, can_initrd; _cleanup_free_ char *cgroup = NULL; char *arguments[3]; unsigned retries; - int cmd, r; + int cmd, r, umount_log_level = LOG_INFO; static const char* const dirs[] = {SYSTEM_SHUTDOWN_PATH, NULL}; char *watchdog_device; @@ -349,6 +349,7 @@ int main(int argc, char *argv[]) { need_swapoff = !in_container; need_loop_detach = !in_container; need_dm_detach = !in_container; + can_initrd = !in_container && !in_initrd() && access("/run/initramfs/shutdown", X_OK) == 0; /* Unmount all mountpoints, swaps, and loopback devices */ for (retries = 0; retries < FINALIZE_ATTEMPTS; retries++) { @@ -366,7 +367,7 @@ int main(int argc, char *argv[]) { if (need_umount) { log_info("Unmounting file systems."); - r = umount_all(&changed); + r = umount_all(&changed, umount_log_level); if (r == 0) { need_umount = false; log_info("All filesystems unmounted."); @@ -390,7 +391,7 @@ int main(int argc, char *argv[]) { if (need_loop_detach) { log_info("Detaching loop devices."); - r = loopback_detach_all(&changed); + r = loopback_detach_all(&changed, umount_log_level); if (r == 0) { need_loop_detach = false; log_info("All loop devices detached."); @@ -402,7 +403,7 @@ int main(int argc, char *argv[]) { if (need_dm_detach) { log_info("Detaching DM devices."); - r = dm_detach_all(&changed); + r = dm_detach_all(&changed, umount_log_level); if (r == 0) { need_dm_detach = false; log_info("All DM devices detached."); @@ -419,6 +420,16 @@ int main(int argc, char *argv[]) { goto initrd_jump; } + if (!changed && umount_log_level == LOG_INFO && !can_initrd) { + /* There are things we cannot get rid of. Loop one more time + * with LOG_ERR to inform the user. Note that we don't need + * to do this if there is a initrd to switch to, because that + * one is likely to get rid of the remounting mounts. If not, + * it will log about them. */ + umount_log_level = LOG_ERR; + continue; + } + /* If in this iteration we didn't manage to * unmount/deactivate anything, we simply give up */ if (!changed) { @@ -450,8 +461,7 @@ int main(int argc, char *argv[]) { arguments[2] = NULL; execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments); - if (!in_container && !in_initrd() && - access("/run/initramfs/shutdown", X_OK) == 0) { + if (can_initrd) { r = switch_root_initramfs(); if (r >= 0) { argv[0] = (char*) "/shutdown"; diff --git a/src/core/umount.c b/src/core/umount.c index f9b4a21cfc..220b2fb6d9 100644 --- a/src/core/umount.c +++ b/src/core/umount.c @@ -414,7 +414,7 @@ static bool nonunmountable_path(const char *path) { || path_startswith(path, "/run/initramfs"); } -static int remount_with_timeout(MountPoint *m) { +static int remount_with_timeout(MountPoint *m, int umount_log_level) { pid_t pid; int r; @@ -435,7 +435,7 @@ static int remount_with_timeout(MountPoint *m) { /* Start the mount operation here in the child */ r = mount(NULL, m->path, NULL, m->remount_flags, m->remount_options); if (r < 0) - log_error_errno(errno, "Failed to remount '%s' read-only: %m", m->path); + log_full_errno(umount_log_level, errno, "Failed to remount '%s' read-only: %m", m->path); _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS); } @@ -445,14 +445,14 @@ static int remount_with_timeout(MountPoint *m) { log_error_errno(r, "Remounting '%s' timed out, issuing SIGKILL to PID " PID_FMT ".", m->path, pid); (void) kill(pid, SIGKILL); } else if (r == -EPROTO) - log_error_errno(r, "Remounting '%s' failed abnormally, child process " PID_FMT " aborted or exited non-zero.", m->path, pid); + log_debug_errno(r, "Remounting '%s' failed abnormally, child process " PID_FMT " aborted or exited non-zero.", m->path, pid); else if (r < 0) log_error_errno(r, "Remounting '%s' failed unexpectedly, couldn't wait for child process " PID_FMT ": %m", m->path, pid); return r; } -static int umount_with_timeout(MountPoint *m) { +static int umount_with_timeout(MountPoint *m, int umount_log_level) { pid_t pid; int r; @@ -479,7 +479,7 @@ static int umount_with_timeout(MountPoint *m) { * then return EBUSY).*/ r = umount2(m->path, MNT_FORCE); if (r < 0) - log_error_errno(errno, "Failed to unmount %s: %m", m->path); + log_full_errno(umount_log_level, errno, "Failed to unmount %s: %m", m->path); _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS); } @@ -489,7 +489,7 @@ static int umount_with_timeout(MountPoint *m) { log_error_errno(r, "Unmounting '%s' timed out, issuing SIGKILL to PID " PID_FMT ".", m->path, pid); (void) kill(pid, SIGKILL); } else if (r == -EPROTO) - log_error_errno(r, "Unmounting '%s' failed abnormally, child process " PID_FMT " aborted or exited non-zero.", m->path, pid); + log_debug_errno(r, "Unmounting '%s' failed abnormally, child process " PID_FMT " aborted or exited non-zero.", m->path, pid); else if (r < 0) log_error_errno(r, "Unmounting '%s' failed unexpectedly, couldn't wait for child process " PID_FMT ": %m", m->path, pid); @@ -498,7 +498,7 @@ static int umount_with_timeout(MountPoint *m) { /* This includes remounting readonly, which changes the kernel mount options. * Therefore the list passed to this function is invalidated, and should not be reused. */ -static int mount_points_list_umount(MountPoint **head, bool *changed) { +static int mount_points_list_umount(MountPoint **head, bool *changed, int umount_log_level) { MountPoint *m; int n_failed = 0; @@ -527,7 +527,7 @@ static int mount_points_list_umount(MountPoint **head, bool *changed) { * Since the remount can hang in the instance of * remote filesystems, we remount asynchronously * and skip the subsequent umount if it fails. */ - if (remount_with_timeout(m) < 0) { + if (remount_with_timeout(m, umount_log_level) < 0) { /* Remount failed, but try unmounting anyway, * unless this is a mount point we want to skip. */ if (nonunmountable_path(m->path)) { @@ -544,7 +544,7 @@ static int mount_points_list_umount(MountPoint **head, bool *changed) { continue; /* Trying to umount */ - if (umount_with_timeout(m) < 0) + if (umount_with_timeout(m, umount_log_level) < 0) n_failed++; else *changed = true; @@ -574,7 +574,7 @@ static int swap_points_list_off(MountPoint **head, bool *changed) { return n_failed; } -static int loopback_points_list_detach(MountPoint **head, bool *changed) { +static int loopback_points_list_detach(MountPoint **head, bool *changed, int umount_log_level) { MountPoint *m, *n; int n_failed = 0, k; struct stat root_st; @@ -604,7 +604,7 @@ static int loopback_points_list_detach(MountPoint **head, bool *changed) { mount_point_free(head, m); } else { - log_warning_errno(errno, "Could not detach loopback %s: %m", m->path); + log_full_errno(umount_log_level, errno, "Could not detach loopback %s: %m", m->path); n_failed++; } } @@ -612,7 +612,7 @@ static int loopback_points_list_detach(MountPoint **head, bool *changed) { return n_failed; } -static int dm_points_list_detach(MountPoint **head, bool *changed) { +static int dm_points_list_detach(MountPoint **head, bool *changed, int umount_log_level) { MountPoint *m, *n; int n_failed = 0, r; dev_t rootdev; @@ -637,7 +637,7 @@ static int dm_points_list_detach(MountPoint **head, bool *changed) { *changed = true; mount_point_free(head, m); } else { - log_warning_errno(errno, "Could not detach DM %s: %m", m->path); + log_full_errno(umount_log_level, errno, "Could not detach DM %s: %m", m->path); n_failed++; } } @@ -645,7 +645,7 @@ static int dm_points_list_detach(MountPoint **head, bool *changed) { return n_failed; } -static int umount_all_once(bool *changed) { +static int umount_all_once(bool *changed, int umount_log_level) { int r; LIST_HEAD(MountPoint, mp_list_head); @@ -656,7 +656,7 @@ static int umount_all_once(bool *changed) { if (r < 0) goto end; - r = mount_points_list_umount(&mp_list_head, changed); + r = mount_points_list_umount(&mp_list_head, changed, umount_log_level); end: mount_points_list_free(&mp_list_head); @@ -664,7 +664,7 @@ static int umount_all_once(bool *changed) { return r; } -int umount_all(bool *changed) { +int umount_all(bool *changed, int umount_log_level) { bool umount_changed; int r; @@ -676,7 +676,7 @@ int umount_all(bool *changed) { do { umount_changed = false; - r = umount_all_once(&umount_changed); + r = umount_all_once(&umount_changed, umount_log_level); if (umount_changed) *changed = true; } while (umount_changed); @@ -704,7 +704,7 @@ int swapoff_all(bool *changed) { return r; } -int loopback_detach_all(bool *changed) { +int loopback_detach_all(bool *changed, int umount_log_level) { int r; LIST_HEAD(MountPoint, loopback_list_head); @@ -716,7 +716,7 @@ int loopback_detach_all(bool *changed) { if (r < 0) goto end; - r = loopback_points_list_detach(&loopback_list_head, changed); + r = loopback_points_list_detach(&loopback_list_head, changed, umount_log_level); end: mount_points_list_free(&loopback_list_head); @@ -724,7 +724,7 @@ int loopback_detach_all(bool *changed) { return r; } -int dm_detach_all(bool *changed) { +int dm_detach_all(bool *changed, int umount_log_level) { int r; LIST_HEAD(MountPoint, dm_list_head); @@ -736,7 +736,7 @@ int dm_detach_all(bool *changed) { if (r < 0) goto end; - r = dm_points_list_detach(&dm_list_head, changed); + r = dm_points_list_detach(&dm_list_head, changed, umount_log_level); end: mount_points_list_free(&dm_list_head); diff --git a/src/core/umount.h b/src/core/umount.h index 7c029c384c..a6613e6ad6 100644 --- a/src/core/umount.h +++ b/src/core/umount.h @@ -20,10 +20,10 @@ along with systemd; If not, see . ***/ -int umount_all(bool *changed); +int umount_all(bool *changed, int umount_log_level); int swapoff_all(bool *changed); -int loopback_detach_all(bool *changed); +int loopback_detach_all(bool *changed, int umount_log_level); -int dm_detach_all(bool *changed); +int dm_detach_all(bool *changed, int umount_log_level);