1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 /***
3 Copyright © 2010 ProFUSION embedded systems
4 ***/
5
6 #include <errno.h>
7 #include <fcntl.h>
8 #include <linux/dm-ioctl.h>
9 #include <linux/major.h>
10 #include <linux/raid/md_u.h>
11 #include <linux/loop.h>
12 #include <sys/mount.h>
13 #include <sys/swap.h>
14 #include <sys/stat.h>
15 #include <sys/types.h>
16 #include <unistd.h>
17
18 #if HAVE_VALGRIND_MEMCHECK_H
19 #include <valgrind/memcheck.h>
20 #endif
21
22 #include "sd-device.h"
23
24 #include "alloc-util.h"
25 #include "blockdev-util.h"
26 #include "def.h"
27 #include "device-util.h"
28 #include "escape.h"
29 #include "fd-util.h"
30 #include "fstab-util.h"
31 #include "libmount-util.h"
32 #include "mount-setup.h"
33 #include "mount-util.h"
34 #include "mountpoint-util.h"
35 #include "path-util.h"
36 #include "process-util.h"
37 #include "signal-util.h"
38 #include "string-util.h"
39 #include "strv.h"
40 #include "sync-util.h"
41 #include "umount.h"
42 #include "util.h"
43 #include "virt.h"
44
mount_point_free(MountPoint ** head,MountPoint * m)45 static void mount_point_free(MountPoint **head, MountPoint *m) {
46 assert(head);
47 assert(m);
48
49 LIST_REMOVE(mount_point, *head, m);
50
51 free(m->path);
52 free(m->remount_options);
53 free(m);
54 }
55
mount_points_list_free(MountPoint ** head)56 void mount_points_list_free(MountPoint **head) {
57 assert(head);
58
59 while (*head)
60 mount_point_free(head, *head);
61 }
62
mount_points_list_get(const char * mountinfo,MountPoint ** head)63 int mount_points_list_get(const char *mountinfo, MountPoint **head) {
64 _cleanup_(mnt_free_tablep) struct libmnt_table *table = NULL;
65 _cleanup_(mnt_free_iterp) struct libmnt_iter *iter = NULL;
66 int r;
67
68 assert(head);
69
70 r = libmount_parse(mountinfo, NULL, &table, &iter);
71 if (r < 0)
72 return log_error_errno(r, "Failed to parse %s: %m", mountinfo ?: "/proc/self/mountinfo");
73
74 for (;;) {
75 struct libmnt_fs *fs;
76 const char *path, *fstype;
77 _cleanup_free_ char *options = NULL;
78 unsigned long remount_flags = 0u;
79 _cleanup_free_ char *remount_options = NULL;
80 bool try_remount_ro;
81 _cleanup_free_ MountPoint *m = NULL;
82
83 r = mnt_table_next_fs(table, iter, &fs);
84 if (r == 1)
85 break;
86 if (r < 0)
87 return log_error_errno(r, "Failed to get next entry from %s: %m", mountinfo ?: "/proc/self/mountinfo");
88
89 path = mnt_fs_get_target(fs);
90 if (!path)
91 continue;
92
93 fstype = mnt_fs_get_fstype(fs);
94
95 /* Combine the generic VFS options with the FS-specific
96 * options. Duplicates are not a problem here, because the only
97 * options that should come up twice are typically ro/rw, which
98 * are turned into MS_RDONLY or the inversion of it.
99 *
100 * Even if there are duplicates later in mount_option_mangle()
101 * they shouldn't hurt anyways as they override each other.
102 */
103 if (!strextend_with_separator(&options, ",", mnt_fs_get_vfs_options(fs)))
104 return log_oom();
105 if (!strextend_with_separator(&options, ",", mnt_fs_get_fs_options(fs)))
106 return log_oom();
107
108 /* Ignore mount points we can't unmount because they
109 * are API or because we are keeping them open (like
110 * /dev/console). Also, ignore all mounts below API
111 * file systems, since they are likely virtual too,
112 * and hence not worth spending time on. Also, in
113 * unprivileged containers we might lack the rights to
114 * unmount these things, hence don't bother. */
115 if (mount_point_is_api(path) ||
116 mount_point_ignore(path) ||
117 PATH_STARTSWITH_SET(path, "/dev", "/sys", "/proc"))
118 continue;
119
120 /* If we are in a container, don't attempt to
121 * read-only mount anything as that brings no real
122 * benefits, but might confuse the host, as we remount
123 * the superblock here, not the bind mount.
124 *
125 * If the filesystem is a network fs, also skip the
126 * remount. It brings no value (we cannot leave
127 * a "dirty fs") and could hang if the network is down.
128 * Note that umount2() is more careful and will not
129 * hang because of the network being down. */
130 try_remount_ro = detect_container() <= 0 &&
131 !fstype_is_network(fstype) &&
132 !fstype_is_api_vfs(fstype) &&
133 !fstype_is_ro(fstype) &&
134 !fstab_test_yes_no_option(options, "ro\0rw\0");
135
136 if (try_remount_ro) {
137 /* mount(2) states that mount flags and options need to be exactly the same
138 * as they were when the filesystem was mounted, except for the desired
139 * changes. So we reconstruct both here and adjust them for the later
140 * remount call too. */
141
142 r = mnt_fs_get_propagation(fs, &remount_flags);
143 if (r < 0) {
144 log_warning_errno(r, "mnt_fs_get_propagation() failed for %s, ignoring: %m", path);
145 continue;
146 }
147
148 r = mount_option_mangle(options, remount_flags, &remount_flags, &remount_options);
149 if (r < 0) {
150 log_warning_errno(r, "mount_option_mangle failed for %s, ignoring: %m", path);
151 continue;
152 }
153
154 /* MS_BIND is special. If it is provided it will only make the mount-point
155 * read-only. If left out, the super block itself is remounted, which we want. */
156 remount_flags = (remount_flags|MS_REMOUNT|MS_RDONLY) & ~MS_BIND;
157 }
158
159 m = new0(MountPoint, 1);
160 if (!m)
161 return log_oom();
162
163 m->path = strdup(path);
164 if (!m->path)
165 return log_oom();
166
167 m->remount_options = TAKE_PTR(remount_options);
168 m->remount_flags = remount_flags;
169 m->try_remount_ro = try_remount_ro;
170
171 LIST_PREPEND(mount_point, *head, TAKE_PTR(m));
172 }
173
174 return 0;
175 }
176
swap_list_get(const char * swaps,MountPoint ** head)177 int swap_list_get(const char *swaps, MountPoint **head) {
178 _cleanup_(mnt_free_tablep) struct libmnt_table *t = NULL;
179 _cleanup_(mnt_free_iterp) struct libmnt_iter *i = NULL;
180 int r;
181
182 assert(head);
183
184 t = mnt_new_table();
185 i = mnt_new_iter(MNT_ITER_FORWARD);
186 if (!t || !i)
187 return log_oom();
188
189 r = mnt_table_parse_swaps(t, swaps);
190 if (r == -ENOENT) /* no /proc/swaps is fine */
191 return 0;
192 if (r < 0)
193 return log_error_errno(r, "Failed to parse %s: %m", swaps ?: "/proc/swaps");
194
195 for (;;) {
196 struct libmnt_fs *fs;
197 _cleanup_free_ MountPoint *swap = NULL;
198 const char *source;
199
200 r = mnt_table_next_fs(t, i, &fs);
201 if (r == 1)
202 break;
203 if (r < 0)
204 return log_error_errno(r, "Failed to get next entry from %s: %m", swaps ?: "/proc/swaps");
205
206 source = mnt_fs_get_source(fs);
207 if (!source)
208 continue;
209
210 swap = new0(MountPoint, 1);
211 if (!swap)
212 return log_oom();
213
214 swap->path = strdup(source);
215 if (!swap->path)
216 return log_oom();
217
218 LIST_PREPEND(mount_point, *head, TAKE_PTR(swap));
219 }
220
221 return 0;
222 }
223
loopback_list_get(MountPoint ** head)224 static int loopback_list_get(MountPoint **head) {
225 _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
226 sd_device *d;
227 int r;
228
229 assert(head);
230
231 r = sd_device_enumerator_new(&e);
232 if (r < 0)
233 return r;
234
235 r = sd_device_enumerator_allow_uninitialized(e);
236 if (r < 0)
237 return r;
238
239 r = sd_device_enumerator_add_match_subsystem(e, "block", true);
240 if (r < 0)
241 return r;
242
243 r = sd_device_enumerator_add_match_sysname(e, "loop*");
244 if (r < 0)
245 return r;
246
247 r = sd_device_enumerator_add_match_sysattr(e, "loop/backing_file", NULL, true);
248 if (r < 0)
249 return r;
250
251 FOREACH_DEVICE(e, d) {
252 _cleanup_free_ char *p = NULL;
253 const char *dn;
254 MountPoint *lb;
255 dev_t devnum;
256
257 if (sd_device_get_devnum(d, &devnum) < 0 ||
258 sd_device_get_devname(d, &dn) < 0)
259 continue;
260
261 p = strdup(dn);
262 if (!p)
263 return -ENOMEM;
264
265 lb = new(MountPoint, 1);
266 if (!lb)
267 return -ENOMEM;
268
269 *lb = (MountPoint) {
270 .path = TAKE_PTR(p),
271 .devnum = devnum,
272 };
273
274 LIST_PREPEND(mount_point, *head, lb);
275 }
276
277 return 0;
278 }
279
dm_list_get(MountPoint ** head)280 static int dm_list_get(MountPoint **head) {
281 _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
282 sd_device *d;
283 int r;
284
285 assert(head);
286
287 r = sd_device_enumerator_new(&e);
288 if (r < 0)
289 return r;
290
291 r = sd_device_enumerator_allow_uninitialized(e);
292 if (r < 0)
293 return r;
294
295 r = sd_device_enumerator_add_match_subsystem(e, "block", true);
296 if (r < 0)
297 return r;
298
299 r = sd_device_enumerator_add_match_sysname(e, "dm-*");
300 if (r < 0)
301 return r;
302
303 FOREACH_DEVICE(e, d) {
304 _cleanup_free_ char *p = NULL;
305 const char *dn;
306 MountPoint *m;
307 dev_t devnum;
308
309 if (sd_device_get_devnum(d, &devnum) < 0 ||
310 sd_device_get_devname(d, &dn) < 0)
311 continue;
312
313 p = strdup(dn);
314 if (!p)
315 return -ENOMEM;
316
317 m = new(MountPoint, 1);
318 if (!m)
319 return -ENOMEM;
320
321 *m = (MountPoint) {
322 .path = TAKE_PTR(p),
323 .devnum = devnum,
324 };
325
326 LIST_PREPEND(mount_point, *head, m);
327 }
328
329 return 0;
330 }
331
md_list_get(MountPoint ** head)332 static int md_list_get(MountPoint **head) {
333 _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
334 sd_device *d;
335 int r;
336
337 assert(head);
338
339 r = sd_device_enumerator_new(&e);
340 if (r < 0)
341 return r;
342
343 r = sd_device_enumerator_allow_uninitialized(e);
344 if (r < 0)
345 return r;
346
347 r = sd_device_enumerator_add_match_subsystem(e, "block", true);
348 if (r < 0)
349 return r;
350
351 r = sd_device_enumerator_add_match_sysname(e, "md*");
352 if (r < 0)
353 return r;
354
355 /* Filter out partitions. */
356 r = sd_device_enumerator_add_match_property(e, "DEVTYPE", "disk");
357 if (r < 0)
358 return r;
359
360 FOREACH_DEVICE(e, d) {
361 _cleanup_free_ char *p = NULL;
362 const char *dn, *md_level;
363 MountPoint *m;
364 dev_t devnum;
365
366 if (sd_device_get_devnum(d, &devnum) < 0 ||
367 sd_device_get_devname(d, &dn) < 0)
368 continue;
369
370 r = sd_device_get_property_value(d, "MD_LEVEL", &md_level);
371 if (r < 0) {
372 log_warning_errno(r, "Failed to get MD_LEVEL property for %s, ignoring: %m", dn);
373 continue;
374 }
375
376 /* MD "containers" are a special type of MD devices, used for external metadata.
377 * Since it doesn't provide RAID functionality in itself we don't need to stop it. */
378 if (streq(md_level, "container"))
379 continue;
380
381 p = strdup(dn);
382 if (!p)
383 return -ENOMEM;
384
385 m = new(MountPoint, 1);
386 if (!m)
387 return -ENOMEM;
388
389 *m = (MountPoint) {
390 .path = TAKE_PTR(p),
391 .devnum = devnum,
392 };
393
394 LIST_PREPEND(mount_point, *head, m);
395 }
396
397 return 0;
398 }
399
delete_loopback(const char * device)400 static int delete_loopback(const char *device) {
401 _cleanup_close_ int fd = -1;
402 struct loop_info64 info;
403
404 assert(device);
405
406 fd = open(device, O_RDONLY|O_CLOEXEC);
407 if (fd < 0) {
408 log_debug_errno(errno, "Failed to open loopback device %s: %m", device);
409 return errno == ENOENT ? 0 : -errno;
410 }
411
412 /* Loopback block devices don't sync in-flight blocks when we clear the fd, hence sync explicitly
413 * first */
414 if (fsync(fd) < 0)
415 log_debug_errno(errno, "Failed to sync loop block device %s, ignoring: %m", device);
416
417 if (ioctl(fd, LOOP_CLR_FD, 0) < 0) {
418 if (errno == ENXIO) /* Nothing bound, didn't do anything */
419 return 0;
420
421 if (errno != EBUSY)
422 return log_debug_errno(errno, "Failed to clear loopback device %s: %m", device);
423
424 if (ioctl(fd, LOOP_GET_STATUS64, &info) < 0) {
425 if (errno == ENXIO) /* What? Suddenly detached after all? That's fine by us then. */
426 return 1;
427
428 log_debug_errno(errno, "Failed to invoke LOOP_GET_STATUS64 on loopback device %s, ignoring: %m", device);
429 return -EBUSY; /* propagate original error */
430 }
431
432 #if HAVE_VALGRIND_MEMCHECK_H
433 VALGRIND_MAKE_MEM_DEFINED(&info, sizeof(info));
434 #endif
435
436 if (FLAGS_SET(info.lo_flags, LO_FLAGS_AUTOCLEAR)) /* someone else already set LO_FLAGS_AUTOCLEAR for us? fine by us */
437 return -EBUSY; /* propagate original error */
438
439 info.lo_flags |= LO_FLAGS_AUTOCLEAR;
440 if (ioctl(fd, LOOP_SET_STATUS64, &info) < 0) {
441 if (errno == ENXIO) /* Suddenly detached after all? Fine by us */
442 return 1;
443
444 log_debug_errno(errno, "Failed to set LO_FLAGS_AUTOCLEAR flag for loop device %s, ignoring: %m", device);
445 } else
446 log_debug("Successfully set LO_FLAGS_AUTOCLEAR flag for loop device %s.", device);
447
448 return -EBUSY;
449 }
450
451 if (ioctl(fd, LOOP_GET_STATUS64, &info) < 0) {
452 /* If the LOOP_CLR_FD above succeeded we'll see ENXIO here. */
453 if (errno == ENXIO)
454 log_debug("Successfully detached loopback device %s.", device);
455 else
456 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 */
457
458 return 1;
459 }
460
461 #if HAVE_VALGRIND_MEMCHECK_H
462 VALGRIND_MAKE_MEM_DEFINED(&info, sizeof(info));
463 #endif
464
465 /* Linux makes LOOP_CLR_FD succeed whenever LO_FLAGS_AUTOCLEAR is set without actually doing
466 * anything. Very confusing. Let's hence not claim we did anything in this case. */
467 if (FLAGS_SET(info.lo_flags, LO_FLAGS_AUTOCLEAR))
468 log_debug("Successfully called LOOP_CLR_FD on a loopback device %s with autoclear set, which is a NOP.", device);
469 else
470 log_debug("Weird, LOOP_CLR_FD succeeded but the device is still attached on %s.", device);
471
472 return -EBUSY; /* Nothing changed, the device is still attached, hence it apparently is still busy */
473 }
474
delete_dm(MountPoint * m)475 static int delete_dm(MountPoint *m) {
476 _cleanup_close_ int fd = -1;
477 int r;
478
479 assert(m);
480 assert(major(m->devnum) != 0);
481 assert(m->path);
482
483 fd = open("/dev/mapper/control", O_RDWR|O_CLOEXEC);
484 if (fd < 0)
485 return -errno;
486
487 r = fsync_path_at(AT_FDCWD, m->path);
488 if (r < 0)
489 log_debug_errno(r, "Failed to sync DM block device %s, ignoring: %m", m->path);
490
491 return RET_NERRNO(ioctl(fd, DM_DEV_REMOVE, &(struct dm_ioctl) {
492 .version = {
493 DM_VERSION_MAJOR,
494 DM_VERSION_MINOR,
495 DM_VERSION_PATCHLEVEL
496 },
497 .data_size = sizeof(struct dm_ioctl),
498 .dev = m->devnum,
499 }));
500 }
501
delete_md(MountPoint * m)502 static int delete_md(MountPoint *m) {
503 _cleanup_close_ int fd = -1;
504
505 assert(m);
506 assert(major(m->devnum) != 0);
507 assert(m->path);
508
509 fd = open(m->path, O_RDONLY|O_CLOEXEC|O_EXCL);
510 if (fd < 0)
511 return -errno;
512
513 if (fsync(fd) < 0)
514 log_debug_errno(errno, "Failed to sync MD block device %s, ignoring: %m", m->path);
515
516 return RET_NERRNO(ioctl(fd, STOP_ARRAY, NULL));
517 }
518
nonunmountable_path(const char * path)519 static bool nonunmountable_path(const char *path) {
520 return path_equal(path, "/")
521 #if ! HAVE_SPLIT_USR
522 || path_equal(path, "/usr")
523 #endif
524 || path_startswith(path, "/run/initramfs");
525 }
526
remount_with_timeout(MountPoint * m,int umount_log_level)527 static int remount_with_timeout(MountPoint *m, int umount_log_level) {
528 pid_t pid;
529 int r;
530
531 BLOCK_SIGNALS(SIGCHLD);
532
533 assert(m);
534
535 /* Due to the possibility of a remount operation hanging, we fork a child process and set a
536 * timeout. If the timeout lapses, the assumption is that the particular remount failed. */
537 r = safe_fork("(sd-remount)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_REOPEN_LOG, &pid);
538 if (r < 0)
539 return r;
540 if (r == 0) {
541 log_info("Remounting '%s' read-only with options '%s'.", m->path, strempty(m->remount_options));
542
543 /* Start the mount operation here in the child */
544 r = mount(NULL, m->path, NULL, m->remount_flags, m->remount_options);
545 if (r < 0)
546 log_full_errno(umount_log_level, errno, "Failed to remount '%s' read-only: %m", m->path);
547
548 _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
549 }
550
551 r = wait_for_terminate_with_timeout(pid, DEFAULT_TIMEOUT_USEC);
552 if (r == -ETIMEDOUT) {
553 log_error_errno(r, "Remounting '%s' timed out, issuing SIGKILL to PID " PID_FMT ".", m->path, pid);
554 (void) kill(pid, SIGKILL);
555 } else if (r == -EPROTO)
556 log_debug_errno(r, "Remounting '%s' failed abnormally, child process " PID_FMT " aborted or exited non-zero.", m->path, pid);
557 else if (r < 0)
558 log_error_errno(r, "Remounting '%s' failed unexpectedly, couldn't wait for child process " PID_FMT ": %m", m->path, pid);
559
560 return r;
561 }
562
umount_with_timeout(MountPoint * m,int umount_log_level)563 static int umount_with_timeout(MountPoint *m, int umount_log_level) {
564 pid_t pid;
565 int r;
566
567 BLOCK_SIGNALS(SIGCHLD);
568
569 assert(m);
570
571 /* Due to the possibility of a umount operation hanging, we fork a child process and set a
572 * timeout. If the timeout lapses, the assumption is that the particular umount failed. */
573 r = safe_fork("(sd-umount)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_LOG|FORK_REOPEN_LOG, &pid);
574 if (r < 0)
575 return r;
576 if (r == 0) {
577 log_info("Unmounting '%s'.", m->path);
578
579 /* Start the mount operation here in the child Using MNT_FORCE
580 * causes some filesystems (e.g. FUSE and NFS and other network
581 * filesystems) to abort any pending requests and return -EIO
582 * rather than blocking indefinitely. If the filesysten is
583 * "busy", this may allow processes to die, thus making the
584 * filesystem less busy so the unmount might succeed (rather
585 * than return EBUSY). */
586 r = umount2(m->path, MNT_FORCE);
587 if (r < 0)
588 log_full_errno(umount_log_level, errno, "Failed to unmount %s: %m", m->path);
589
590 _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
591 }
592
593 r = wait_for_terminate_with_timeout(pid, DEFAULT_TIMEOUT_USEC);
594 if (r == -ETIMEDOUT) {
595 log_error_errno(r, "Unmounting '%s' timed out, issuing SIGKILL to PID " PID_FMT ".", m->path, pid);
596 (void) kill(pid, SIGKILL);
597 } else if (r == -EPROTO)
598 log_debug_errno(r, "Unmounting '%s' failed abnormally, child process " PID_FMT " aborted or exited non-zero.", m->path, pid);
599 else if (r < 0)
600 log_error_errno(r, "Unmounting '%s' failed unexpectedly, couldn't wait for child process " PID_FMT ": %m", m->path, pid);
601
602 return r;
603 }
604
605 /* This includes remounting readonly, which changes the kernel mount options. Therefore the list passed to
606 * this function is invalidated, and should not be reused. */
mount_points_list_umount(MountPoint ** head,bool * changed,int umount_log_level)607 static int mount_points_list_umount(MountPoint **head, bool *changed, int umount_log_level) {
608 int n_failed = 0;
609
610 assert(head);
611 assert(changed);
612
613 LIST_FOREACH(mount_point, m, *head) {
614 if (m->try_remount_ro) {
615 /* We always try to remount directories read-only first, before we go on and umount
616 * them.
617 *
618 * Mount points can be stacked. If a mount point is stacked below / or /usr, we
619 * cannot umount or remount it directly, since there is no way to refer to the
620 * underlying mount. There's nothing we can do about it for the general case, but we
621 * can do something about it if it is aliased somewhere else via a bind mount. If we
622 * explicitly remount the super block of that alias read-only we hence should be
623 * relatively safe regarding keeping a dirty fs we cannot otherwise see.
624 *
625 * Since the remount can hang in the instance of remote filesystems, we remount
626 * asynchronously and skip the subsequent umount if it fails. */
627 if (remount_with_timeout(m, umount_log_level) < 0) {
628 /* Remount failed, but try unmounting anyway,
629 * unless this is a mount point we want to skip. */
630 if (nonunmountable_path(m->path)) {
631 n_failed++;
632 continue;
633 }
634 }
635 }
636
637 /* Skip / and /usr since we cannot unmount that anyway, since we are running from it. They
638 * have already been remounted ro. */
639 if (nonunmountable_path(m->path))
640 continue;
641
642 /* Trying to umount */
643 if (umount_with_timeout(m, umount_log_level) < 0)
644 n_failed++;
645 else
646 *changed = true;
647 }
648
649 return n_failed;
650 }
651
swap_points_list_off(MountPoint ** head,bool * changed)652 static int swap_points_list_off(MountPoint **head, bool *changed) {
653 int n_failed = 0;
654
655 assert(head);
656 assert(changed);
657
658 LIST_FOREACH(mount_point, m, *head) {
659 log_info("Deactivating swap %s.", m->path);
660 if (swapoff(m->path) < 0) {
661 log_warning_errno(errno, "Could not deactivate swap %s: %m", m->path);
662 n_failed++;
663 continue;
664 }
665
666 *changed = true;
667 mount_point_free(head, m);
668 }
669
670 return n_failed;
671 }
672
loopback_points_list_detach(MountPoint ** head,bool * changed,int umount_log_level)673 static int loopback_points_list_detach(MountPoint **head, bool *changed, int umount_log_level) {
674 int n_failed = 0, r;
675 dev_t rootdev = 0;
676
677 assert(head);
678 assert(changed);
679
680 (void) get_block_device("/", &rootdev);
681
682 LIST_FOREACH(mount_point, m, *head) {
683 if (major(rootdev) != 0 && rootdev == m->devnum) {
684 n_failed++;
685 continue;
686 }
687
688 log_info("Detaching loopback %s.", m->path);
689 r = delete_loopback(m->path);
690 if (r < 0) {
691 log_full_errno(umount_log_level, r, "Could not detach loopback %s: %m", m->path);
692 n_failed++;
693 continue;
694 }
695 if (r > 0)
696 *changed = true;
697
698 mount_point_free(head, m);
699 }
700
701 return n_failed;
702 }
703
dm_points_list_detach(MountPoint ** head,bool * changed,int umount_log_level)704 static int dm_points_list_detach(MountPoint **head, bool *changed, int umount_log_level) {
705 int n_failed = 0, r;
706 dev_t rootdev = 0;
707
708 assert(head);
709 assert(changed);
710
711 (void) get_block_device("/", &rootdev);
712
713 LIST_FOREACH(mount_point, m, *head) {
714 if (major(rootdev) != 0 && rootdev == m->devnum) {
715 n_failed ++;
716 continue;
717 }
718
719 log_info("Detaching DM %s (%u:%u).", m->path, major(m->devnum), minor(m->devnum));
720 r = delete_dm(m);
721 if (r < 0) {
722 log_full_errno(umount_log_level, r, "Could not detach DM %s: %m", m->path);
723 n_failed++;
724 continue;
725 }
726
727 *changed = true;
728 mount_point_free(head, m);
729 }
730
731 return n_failed;
732 }
733
md_points_list_detach(MountPoint ** head,bool * changed,int umount_log_level)734 static int md_points_list_detach(MountPoint **head, bool *changed, int umount_log_level) {
735 int n_failed = 0, r;
736 dev_t rootdev = 0;
737
738 assert(head);
739 assert(changed);
740
741 (void) get_block_device("/", &rootdev);
742
743 LIST_FOREACH(mount_point, m, *head) {
744 if (major(rootdev) != 0 && rootdev == m->devnum) {
745 n_failed ++;
746 continue;
747 }
748
749 log_info("Stopping MD %s (%u:%u).", m->path, major(m->devnum), minor(m->devnum));
750 r = delete_md(m);
751 if (r < 0) {
752 log_full_errno(umount_log_level, r, "Could not stop MD %s: %m", m->path);
753 n_failed++;
754 continue;
755 }
756
757 *changed = true;
758 mount_point_free(head, m);
759 }
760
761 return n_failed;
762 }
763
umount_all_once(bool * changed,int umount_log_level)764 static int umount_all_once(bool *changed, int umount_log_level) {
765 _cleanup_(mount_points_list_free) LIST_HEAD(MountPoint, mp_list_head);
766 int r;
767
768 assert(changed);
769
770 LIST_HEAD_INIT(mp_list_head);
771 r = mount_points_list_get(NULL, &mp_list_head);
772 if (r < 0)
773 return r;
774
775 return mount_points_list_umount(&mp_list_head, changed, umount_log_level);
776 }
777
umount_all(bool * changed,int umount_log_level)778 int umount_all(bool *changed, int umount_log_level) {
779 bool umount_changed;
780 int r;
781
782 assert(changed);
783
784 /* Retry umount, until nothing can be umounted anymore. Mounts are
785 * processed in order, newest first. The retries are needed when
786 * an old mount has been moved, to a path inside a newer mount. */
787 do {
788 umount_changed = false;
789
790 r = umount_all_once(&umount_changed, umount_log_level);
791 if (umount_changed)
792 *changed = true;
793 } while (umount_changed);
794
795 return r;
796 }
797
swapoff_all(bool * changed)798 int swapoff_all(bool *changed) {
799 _cleanup_(mount_points_list_free) LIST_HEAD(MountPoint, swap_list_head);
800 int r;
801
802 assert(changed);
803
804 LIST_HEAD_INIT(swap_list_head);
805
806 r = swap_list_get(NULL, &swap_list_head);
807 if (r < 0)
808 return r;
809
810 return swap_points_list_off(&swap_list_head, changed);
811 }
812
loopback_detach_all(bool * changed,int umount_log_level)813 int loopback_detach_all(bool *changed, int umount_log_level) {
814 _cleanup_(mount_points_list_free) LIST_HEAD(MountPoint, loopback_list_head);
815 int r;
816
817 assert(changed);
818
819 LIST_HEAD_INIT(loopback_list_head);
820
821 r = loopback_list_get(&loopback_list_head);
822 if (r < 0)
823 return r;
824
825 return loopback_points_list_detach(&loopback_list_head, changed, umount_log_level);
826 }
827
dm_detach_all(bool * changed,int umount_log_level)828 int dm_detach_all(bool *changed, int umount_log_level) {
829 _cleanup_(mount_points_list_free) LIST_HEAD(MountPoint, dm_list_head);
830 int r;
831
832 assert(changed);
833
834 LIST_HEAD_INIT(dm_list_head);
835
836 r = dm_list_get(&dm_list_head);
837 if (r < 0)
838 return r;
839
840 return dm_points_list_detach(&dm_list_head, changed, umount_log_level);
841 }
842
md_detach_all(bool * changed,int umount_log_level)843 int md_detach_all(bool *changed, int umount_log_level) {
844 _cleanup_(mount_points_list_free) LIST_HEAD(MountPoint, md_list_head);
845 int r;
846
847 assert(changed);
848
849 LIST_HEAD_INIT(md_list_head);
850
851 r = md_list_get(&md_list_head);
852 if (r < 0)
853 return r;
854
855 return md_points_list_detach(&md_list_head, changed, umount_log_level);
856 }
857