diff options
author | Lennart Poettering <lennart@poettering.net> | 2019-12-20 17:58:03 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2019-12-20 18:16:05 +0100 |
commit | b877c3b06f15a025748b9f09621ddf1bd00cacce (patch) | |
tree | 9d8201ede78b8801672e02be519043b969e73bb6 /src/shutdown | |
parent | 63135a2d8db0b89b226aad2838702a1813b761e3 (diff) | |
download | systemd-b877c3b06f15a025748b9f09621ddf1bd00cacce.tar.gz |
umount: check LO_FLAGS_AUTOCLEAR after LOOP_CLR_FD claimed success
Fixes: #14410
Replaces: #14386
Diffstat (limited to 'src/shutdown')
-rw-r--r-- | src/shutdown/umount.c | 28 |
1 files changed, 23 insertions, 5 deletions
diff --git a/src/shutdown/umount.c b/src/shutdown/umount.c index 47d1a3d676..cc86f4180e 100644 --- a/src/shutdown/umount.c +++ b/src/shutdown/umount.c @@ -328,6 +328,7 @@ static int dm_list_get(MountPoint **head) { static int delete_loopback(const char *device) { _cleanup_close_ int fd = -1; + struct loop_info64 info; assert(device); @@ -335,14 +336,31 @@ static int delete_loopback(const char *device) { if (fd < 0) return errno == ENOENT ? 0 : -errno; - if (ioctl(fd, LOOP_CLR_FD, 0) >= 0) + if (ioctl(fd, LOOP_CLR_FD, 0) < 0) { + if (errno == ENXIO) /* Nothing bound, didn't do anything */ + return 0; + + return -errno; + } + + if (ioctl(fd, LOOP_GET_STATUS64, &info) < 0) { + /* If the LOOP_CLR_FD above succeeded we'll see ENXIO here. */ + if (errno == ENXIO) + log_debug("Successfully detached loopback device %s.", device); + else + log_debug_errno(errno, "Failed to invoke LOOP_GET_STATUS64 on loopback device %s, ignoring: %m", device); /* the LOOP_CLR_FD at least worked, let's hope for the best */ + return 1; + } - /* ENXIO: not bound, so no error */ - if (errno == ENXIO) - return 0; + /* Linux makes LOOP_CLR_FD succeed whenever LO_FLAGS_AUTOCLEAR is set without actually doing + * anything. Very confusing. Let's hence not claim we did anything in this case. */ + if (FLAGS_SET(info.lo_flags, LO_FLAGS_AUTOCLEAR)) + log_debug("Successfully called LOOP_CLR_FD on a loopback device %s with autoclear set, which is a NOP.", device); + else + log_debug("Weird, LOOP_CLR_FD succeeded but the device is still attached on %s.", device); - return -errno; + return -EBUSY; /* Nothing changed, the device is still attached, hence it apparently is still busy */ } static int delete_dm(dev_t devnum) { |