mirror of
https://github.com/morgan9e/systemd
synced 2026-04-14 00:14:32 +09:00
shutdown: handle gracefully if a device disappears while we detach it
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.
This commit is contained in:
committed by
Yu Watanabe
parent
7baf24c949
commit
2791b2bc3d
@@ -17,6 +17,7 @@
|
||||
#include "blockdev-util.h"
|
||||
#include "detach-loopback.h"
|
||||
#include "device-util.h"
|
||||
#include "errno-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "shutdown.h"
|
||||
|
||||
@@ -106,8 +107,12 @@ static int delete_loopback(const char *device) {
|
||||
|
||||
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
|
||||
|
||||
@@ -131,12 +131,21 @@ static int delete_md(RaidDevice *m) {
|
||||
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) {
|
||||
@@ -164,8 +173,9 @@ 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);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#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) {
|
||||
@@ -74,20 +75,23 @@ int swap_list_get(const char *swaps, SwapDevice **head) {
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user