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