From 4534b32c7394d9f5c9d49820f11b9f07fe41b079 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 22 Sep 2020 11:19:37 +0200 Subject: [PATCH 1/4] shutdown: fsync() before detaching loopback devices This is a follow-up for cae1e8fb88c5a6b0960a2d0be3df8755f0c78462: we also call the detach ioctls in the shutdown code, hence add the fsync()s there too, just to be safe. --- src/shutdown/umount.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/shutdown/umount.c b/src/shutdown/umount.c index 0eb694c1af..307944c657 100644 --- a/src/shutdown/umount.c +++ b/src/shutdown/umount.c @@ -387,8 +387,15 @@ static int delete_loopback(const char *device) { assert(device); fd = open(device, O_RDONLY|O_CLOEXEC); - if (fd < 0) + if (fd < 0) { + log_debug_errno(errno, "Failed to open loopback device %s: %m", device); return errno == ENOENT ? 0 : -errno; + } + + /* Loopback block devices don't sync in-flight blocks when we clear the fd, hence sync explicitly + * first */ + if (fsync(fd) < 0) + log_debug_errno(errno, "Failed to sync loop block device %s, ignoring: %m", device); if (ioctl(fd, LOOP_CLR_FD, 0) < 0) { if (errno == ENXIO) /* Nothing bound, didn't do anything */ From 1a269c4ee34a4fc98f2407996cc6bda82f3e03bf Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 22 Sep 2020 11:21:19 +0200 Subject: [PATCH 2/4] shutdown: don't compare pointers with 0 --- src/shutdown/umount.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/shutdown/umount.c b/src/shutdown/umount.c index 307944c657..4354485728 100644 --- a/src/shutdown/umount.c +++ b/src/shutdown/umount.c @@ -474,11 +474,11 @@ static int delete_dm(dev_t devnum) { } static int delete_md(MountPoint *m) { - _cleanup_close_ int fd = -1; + assert(m); assert(major(m->devnum) != 0); - assert(m->path != 0); + assert(m->path); fd = open(m->path, O_RDONLY|O_CLOEXEC|O_EXCL); if (fd < 0) From 32c4626c4c34a7deb9ddc5edfba98c3f171900c8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 22 Sep 2020 11:21:27 +0200 Subject: [PATCH 3/4] shutdown: also fsync() MD devices when going down Let's make this explicit, just in case this suffers by the same issues as the loopback devices, and drops in-flight IO when we disassemble it. --- src/shutdown/umount.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/shutdown/umount.c b/src/shutdown/umount.c index 4354485728..89b05fcc3f 100644 --- a/src/shutdown/umount.c +++ b/src/shutdown/umount.c @@ -484,6 +484,9 @@ static int delete_md(MountPoint *m) { if (fd < 0) return -errno; + if (fsync(fd) < 0) + log_debug_errno(errno, "Failed to sync MD block device %s, ignoring: %m", m->path); + if (ioctl(fd, STOP_ARRAY, NULL) < 0) return -errno; From e55299da4d75f1e33385f04fded002f23530de94 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 22 Sep 2020 11:23:35 +0200 Subject: [PATCH 4/4] shutdown: also fsync() DM devices before going down Similar reasons as the previous patch. --- src/shutdown/umount.c | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/src/shutdown/umount.c b/src/shutdown/umount.c index 89b05fcc3f..6eebaf7abc 100644 --- a/src/shutdown/umount.c +++ b/src/shutdown/umount.c @@ -23,6 +23,7 @@ #include "device-util.h" #include "escape.h" #include "fd-util.h" +#include "fs-util.h" #include "fstab-util.h" #include "libmount-util.h" #include "mount-setup.h" @@ -447,27 +448,31 @@ static int delete_loopback(const char *device) { return -EBUSY; /* Nothing changed, the device is still attached, hence it apparently is still busy */ } -static int delete_dm(dev_t devnum) { - - struct dm_ioctl dm = { - .version = { - DM_VERSION_MAJOR, - DM_VERSION_MINOR, - DM_VERSION_PATCHLEVEL - }, - .data_size = sizeof(dm), - .dev = devnum, - }; - +static int delete_dm(MountPoint *m) { _cleanup_close_ int fd = -1; + int r; - assert(major(devnum) != 0); + assert(m); + assert(major(m->devnum) != 0); + assert(m->path); fd = open("/dev/mapper/control", O_RDWR|O_CLOEXEC); if (fd < 0) return -errno; - if (ioctl(fd, DM_DEV_REMOVE, &dm) < 0) + r = fsync_path_at(AT_FDCWD, m->path); + if (r < 0) + log_debug_errno(r, "Failed to sync DM block device %s, ignoring: %m", m->path); + + if (ioctl(fd, DM_DEV_REMOVE, &(struct dm_ioctl) { + .version = { + DM_VERSION_MAJOR, + DM_VERSION_MINOR, + DM_VERSION_PATCHLEVEL + }, + .data_size = sizeof(struct dm_ioctl), + .dev = m->devnum, + }) < 0) return -errno; return 0; @@ -702,7 +707,7 @@ static int dm_points_list_detach(MountPoint **head, bool *changed, int umount_lo } log_info("Detaching DM %s (%u:%u).", m->path, major(m->devnum), minor(m->devnum)); - r = delete_dm(m->devnum); + r = delete_dm(m); if (r < 0) { log_full_errno(umount_log_level, r, "Could not detach DM %s: %m", m->path); n_failed++;