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