Skip to content

Commit 2791b2b

Browse files
poetteringyuwata
authored andcommitted
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 systemd#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.
1 parent 7baf24c commit 2791b2b

File tree

3 files changed

+30
-11
lines changed

3 files changed

+30
-11
lines changed

src/shutdown/detach-loopback.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "blockdev-util.h"
1818
#include "detach-loopback.h"
1919
#include "device-util.h"
20+
#include "errno-util.h"
2021
#include "fd-util.h"
2122
#include "shutdown.h"
2223

@@ -106,8 +107,12 @@ static int delete_loopback(const char *device) {
106107

107108
fd = open(device, O_RDONLY|O_CLOEXEC);
108109
if (fd < 0) {
109-
log_debug_errno(errno, "Failed to open loopback device %s: %m", device);
110-
return errno == ENOENT ? 0 : -errno;
110+
if (ERRNO_IS_DEVICE_ABSENT(errno)) {
111+
log_debug_errno(errno, "Tried to open loopback device '%s', but device disappeared by now, ignoring: %m", device);
112+
return 0;
113+
}
114+
115+
return log_debug_errno(errno, "Failed to open loopback device '%s': %m", device);
111116
}
112117

113118
/* Loopback block devices don't sync in-flight blocks when we clear the fd, hence sync explicitly

src/shutdown/detach-md.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -131,12 +131,21 @@ static int delete_md(RaidDevice *m) {
131131
assert(m->path);
132132

133133
fd = open(m->path, O_RDONLY|O_CLOEXEC|O_EXCL);
134-
if (fd < 0)
135-
return -errno;
134+
if (fd < 0) {
135+
if (ERRNO_IS_DEVICE_ABSENT(errno)) {
136+
log_debug_errno(errno, "Tried to open MD device '%s', but device disappeared by now, ignoring: %m", m->path);
137+
return 0;
138+
}
139+
140+
return log_debug_errno(errno, "Failed to open MD device '%s': %m", m->path);
141+
}
136142

137143
(void) sync_with_progress(fd);
138144

139-
return RET_NERRNO(ioctl(fd, STOP_ARRAY, NULL));
145+
if (ioctl(fd, STOP_ARRAY, NULL) < 0)
146+
return log_debug_errno(errno, "Failed to issue STOP_ARRAY on MD device '%s': %m", m->path);
147+
148+
return 1;
140149
}
141150

142151
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
164173
n_failed++;
165174
continue;
166175
}
176+
if (r > 0)
177+
*changed = true;
167178

168-
*changed = true;
169179
raid_device_free(head, m);
170180
}
171181

src/shutdown/detach-swap.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include "alloc-util.h"
99
#include "detach-swap.h"
10+
#include "errno-util.h"
1011
#include "libmount-util.h"
1112

1213
static void swap_device_free(SwapDevice **head, SwapDevice *m) {
@@ -74,20 +75,23 @@ int swap_list_get(const char *swaps, SwapDevice **head) {
7475
}
7576

7677
static int swap_points_list_off(SwapDevice **head, bool *changed) {
77-
int n_failed = 0;
78+
int n_failed = 0, r;
7879

7980
assert(head);
8081
assert(changed);
8182

8283
LIST_FOREACH(swap_device, m, *head) {
8384
log_info("Deactivating swap %s.", m->path);
84-
if (swapoff(m->path) < 0) {
85-
log_warning_errno(errno, "Could not deactivate swap %s: %m", m->path);
85+
r = RET_NERRNO(swapoff(m->path));
86+
if (ERRNO_IS_NEG_DEVICE_ABSENT(r))
87+
log_debug_errno(r, "Tried to deactivate swap '%s', but swap disappeared by now, ignoring: %m", m->path);
88+
else if (r < 0) {
89+
log_warning_errno(r, "Could not deactivate swap %s: %m", m->path);
8690
n_failed++;
8791
continue;
88-
}
92+
} else
93+
*changed = true;
8994

90-
*changed = true;
9195
swap_device_free(head, m);
9296
}
9397

0 commit comments

Comments
 (0)