Let's gracefully handle cases where a device disappears in the time we
between our discovery and when we want to detach it, due to "auto-clear"
or a similar logic.
The loopback case already handled this quite OK, do the same for MD and
swap too.
Switch to ERRNO_IS_DEVICE_ABSENT() for all checks, just in case.
Also improve debug logging for all these cases, so we know exactly what
is going on.
This is inspired by #37160, but shouldn't really fix anything there, I
am pretty sure the ENODEV seen in that output stems from the STOP_ARRAY
call, not from the open().
Note that this does not change anything for the device mapper case,
because the DM subsystem does not return useful error codes to
userspace, hence everything is a complete mess there.
(cherry picked from commit
2791b2bc3d84efe674d05e45fa85333eea05ad6f)
(cherry picked from commit
4f0a4976dfe64399bc5a3c6b8f00675e2548b067)
#include "blockdev-util.h"
#include "detach-loopback.h"
#include "device-util.h"
+#include "errno-util.h"
#include "fd-util.h"
#include "shutdown.h"
fd = open(device, O_RDONLY|O_CLOEXEC);
if (fd < 0) {
- log_debug_errno(errno, "Failed to open loopback device %s: %m", device);
- return errno == ENOENT ? 0 : -errno;
+ if (ERRNO_IS_DEVICE_ABSENT(errno)) {
+ log_debug_errno(errno, "Tried to open loopback device '%s', but device disappeared by now, ignoring: %m", device);
+ return 0;
+ }
+
+ return log_debug_errno(errno, "Failed to open loopback device '%s': %m", device);
}
/* Loopback block devices don't sync in-flight blocks when we clear the fd, hence sync explicitly
assert(m->path);
fd = open(m->path, O_RDONLY|O_CLOEXEC|O_EXCL);
- if (fd < 0)
- return -errno;
+ if (fd < 0) {
+ if (ERRNO_IS_DEVICE_ABSENT(errno)) {
+ log_debug_errno(errno, "Tried to open MD device '%s', but device disappeared by now, ignoring: %m", m->path);
+ return 0;
+ }
+
+ return log_debug_errno(errno, "Failed to open MD device '%s': %m", m->path);
+ }
(void) sync_with_progress(fd);
- return RET_NERRNO(ioctl(fd, STOP_ARRAY, NULL));
+ if (ioctl(fd, STOP_ARRAY, NULL) < 0)
+ return log_debug_errno(errno, "Failed to issue STOP_ARRAY on MD device '%s': %m", m->path);
+
+ return 1;
}
static int md_points_list_detach(RaidDevice **head, bool *changed, bool last_try) {
n_failed++;
continue;
}
+ if (r > 0)
+ *changed = true;
- *changed = true;
raid_device_free(head, m);
}
#include "alloc-util.h"
#include "detach-swap.h"
+#include "errno-util.h"
#include "libmount-util.h"
static void swap_device_free(SwapDevice **head, SwapDevice *m) {
}
static int swap_points_list_off(SwapDevice **head, bool *changed) {
- int n_failed = 0;
+ int n_failed = 0, r;
assert(head);
assert(changed);
LIST_FOREACH(swap_device, m, *head) {
log_info("Deactivating swap %s.", m->path);
- if (swapoff(m->path) < 0) {
- log_warning_errno(errno, "Could not deactivate swap %s: %m", m->path);
+ r = RET_NERRNO(swapoff(m->path));
+ if (ERRNO_IS_NEG_DEVICE_ABSENT(r))
+ log_debug_errno(r, "Tried to deactivate swap '%s', but swap disappeared by now, ignoring: %m", m->path);
+ else if (r < 0) {
+ log_warning_errno(r, "Could not deactivate swap %s: %m", m->path);
n_failed++;
continue;
- }
+ } else
+ *changed = true;
- *changed = true;
swap_device_free(head, m);
}