1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 ProFUSION embedded systems
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
25 #include <sys/mount.h>
28 #include <linux/loop.h>
29 #include <linux/dm-ioctl.h>
33 #include "mount-setup.h"
35 #include "path-util.h"
39 typedef struct MountPoint {
42 LIST_FIELDS (struct MountPoint, mount_point);
45 static void mount_point_free(MountPoint **head, MountPoint *m) {
49 LIST_REMOVE(MountPoint, mount_point, *head, m);
55 static void mount_points_list_free(MountPoint **head) {
59 mount_point_free(head, *head);
62 static int mount_points_list_get(MountPoint **head) {
63 FILE *proc_self_mountinfo;
70 if (!(proc_self_mountinfo = fopen("/proc/self/mountinfo", "re")))
79 if ((k = fscanf(proc_self_mountinfo,
80 "%*s " /* (1) mount id */
81 "%*s " /* (2) parent id */
82 "%*s " /* (3) major:minor */
84 "%ms " /* (5) mount point */
85 "%*s" /* (6) mount options */
86 "%*[^-]" /* (7) optional fields */
87 "- " /* (8) separator */
88 "%*s " /* (9) file system type */
89 "%*s" /* (10) mount source */
90 "%*s" /* (11) mount options 2 */
91 "%*[^\n]", /* some rubbish at the end */
96 log_warning("Failed to parse /proc/self/mountinfo:%u.", i);
110 /* Ignore mount points we can't unmount because they
111 * are API or because we are keeping them open (like
113 if (mount_point_is_api(p) ||
114 mount_point_ignore(p) ||
115 path_equal(p, "/dev/console")) {
120 if (!(m = new0(MountPoint, 1))) {
127 LIST_PREPEND(MountPoint, mount_point, *head, m);
133 fclose(proc_self_mountinfo);
138 static int swap_list_get(MountPoint **head) {
145 if (!(proc_swaps = fopen("/proc/swaps", "re")))
146 return (errno == ENOENT) ? 0 : -errno;
148 (void) fscanf(proc_swaps, "%*s %*s %*s %*s %*s\n");
152 char *dev = NULL, *d;
155 if ((k = fscanf(proc_swaps,
156 "%ms " /* device/file */
157 "%*s " /* type of swap */
158 "%*s " /* swap size */
160 "%*s\n", /* priority */
166 log_warning("Failed to parse /proc/swaps:%u.", i);
172 if (endswith(dev, "(deleted)")) {
185 if (!(swap = new0(MountPoint, 1))) {
192 LIST_PREPEND(MountPoint, mount_point, *head, swap);
203 static int loopback_list_get(MountPoint **head) {
206 struct udev_enumerate *e = NULL;
207 struct udev_list_entry *item = NULL, *first = NULL;
211 if (!(udev = udev_new())) {
216 if (!(e = udev_enumerate_new(udev))) {
221 if (udev_enumerate_add_match_subsystem(e, "block") < 0 ||
222 udev_enumerate_add_match_sysname(e, "loop*") < 0 ||
223 udev_enumerate_add_match_sysattr(e, "loop/backing_file", NULL) < 0) {
228 if (udev_enumerate_scan_devices(e) < 0) {
233 first = udev_enumerate_get_list_entry(e);
234 udev_list_entry_foreach(item, first) {
236 struct udev_device *d;
240 if (!(d = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item)))) {
245 if (!(dn = udev_device_get_devnode(d))) {
246 udev_device_unref(d);
251 udev_device_unref(d);
258 if (!(lb = new0(MountPoint, 1))) {
265 LIST_PREPEND(MountPoint, mount_point, *head, lb);
272 udev_enumerate_unref(e);
280 static int dm_list_get(MountPoint **head) {
283 struct udev_enumerate *e = NULL;
284 struct udev_list_entry *item = NULL, *first = NULL;
288 if (!(udev = udev_new())) {
293 if (!(e = udev_enumerate_new(udev))) {
298 if (udev_enumerate_add_match_subsystem(e, "block") < 0 ||
299 udev_enumerate_add_match_sysname(e, "dm-*") < 0) {
304 if (udev_enumerate_scan_devices(e) < 0) {
309 first = udev_enumerate_get_list_entry(e);
311 udev_list_entry_foreach(item, first) {
313 struct udev_device *d;
318 if (!(d = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item)))) {
323 devnum = udev_device_get_devnum(d);
324 dn = udev_device_get_devnode(d);
326 if (major(devnum) == 0 || !dn) {
327 udev_device_unref(d);
332 udev_device_unref(d);
339 if (!(m = new(MountPoint, 1))) {
347 LIST_PREPEND(MountPoint, mount_point, *head, m);
354 udev_enumerate_unref(e);
362 static int delete_loopback(const char *device) {
365 if ((fd = open(device, O_RDONLY|O_CLOEXEC)) < 0)
366 return errno == ENOENT ? 0 : -errno;
368 r = ioctl(fd, LOOP_CLR_FD, 0);
369 close_nointr_nofail(fd);
374 /* ENXIO: not bound, so no error */
381 static int delete_dm(dev_t devnum) {
385 assert(major(devnum) != 0);
387 if ((fd = open("/dev/mapper/control", O_RDWR|O_CLOEXEC)) < 0)
391 dm.version[0] = DM_VERSION_MAJOR;
392 dm.version[1] = DM_VERSION_MINOR;
393 dm.version[2] = DM_VERSION_PATCHLEVEL;
395 dm.data_size = sizeof(dm);
398 r = ioctl(fd, DM_DEV_REMOVE, &dm);
399 close_nointr_nofail(fd);
401 return r >= 0 ? 0 : -errno;
404 static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_error) {
410 LIST_FOREACH_SAFE(mount_point, m, n, *head) {
412 /* If we are in a container, don't attempt to
413 read-only mount anything as that brings no real
414 benefits, but might confuse the host, as we remount
415 the superblock here, not the bind mound. */
416 if (detect_container(NULL) <= 0) {
417 /* We always try to remount directories
418 * read-only first, before we go on and umount
421 * Mount points can be stacked. If a mount
422 * point is stacked below / or /usr, we
423 * cannnot umount or remount it directly,
424 * since there is no way to refer to the
425 * underlying mount. There's nothing we can do
426 * about it for the general case, but we can
427 * do something about it if it is aliased
428 * somehwere else via a bind mount. If we
429 * explicitly remount the super block of that
430 * alias read-only we hence should be
431 * relatively safe regarding keeping the fs we
432 * can otherwise not see dirty. */
433 mount(NULL, m->path, NULL, MS_REMOUNT|MS_RDONLY, NULL);
436 /* Skip / and /usr since we cannot unmount that
437 * anyway, since we are running from it. They have
438 * already been remounted ro. */
439 if (path_equal(m->path, "/")
440 #ifndef HAVE_SPLIT_USR
441 || path_equal(m->path, "/usr")
446 /* Trying to umount. We don't force here since we rely
447 * on busy NFS and FUSE file systems to return EBUSY
448 * until we closed everything on top of them. */
449 log_info("Unmounting %s.", m->path);
450 if (umount2(m->path, 0) == 0) {
454 mount_point_free(head, m);
455 } else if (log_error) {
456 log_warning("Could not unmount %s: %m", m->path);
464 static int swap_points_list_off(MountPoint **head, bool *changed) {
470 LIST_FOREACH_SAFE(mount_point, m, n, *head) {
471 log_info("Deactivating swap %s.", m->path);
472 if (swapoff(m->path) == 0) {
476 mount_point_free(head, m);
478 log_warning("Could not deactivate swap %s: %m", m->path);
486 static int loopback_points_list_detach(MountPoint **head, bool *changed) {
493 k = lstat("/", &root_st);
495 LIST_FOREACH_SAFE(mount_point, m, n, *head) {
497 struct stat loopback_st;
500 major(root_st.st_dev) != 0 &&
501 lstat(m->path, &loopback_st) >= 0 &&
502 root_st.st_dev == loopback_st.st_rdev) {
507 log_info("Detaching loopback %s.", m->path);
508 r = delete_loopback(m->path);
510 if (r > 0 && changed)
513 mount_point_free(head, m);
515 log_warning("Could not detach loopback %s: %m", m->path);
523 static int dm_points_list_detach(MountPoint **head, bool *changed) {
530 k = lstat("/", &root_st);
532 LIST_FOREACH_SAFE(mount_point, m, n, *head) {
536 major(root_st.st_dev) != 0 &&
537 root_st.st_dev == m->devnum) {
542 log_info("Detaching DM %u:%u.", major(m->devnum), minor(m->devnum));
543 r = delete_dm(m->devnum);
548 mount_point_free(head, m);
550 log_warning("Could not detach DM %s: %m", m->path);
558 int umount_all(bool *changed) {
561 LIST_HEAD(MountPoint, mp_list_head);
563 LIST_HEAD_INIT(MountPoint, mp_list_head);
564 r = mount_points_list_get(&mp_list_head);
568 /* retry umount, until nothing can be umounted anymore */
570 umount_changed = false;
572 mount_points_list_umount(&mp_list_head, &umount_changed, false);
576 } while (umount_changed);
578 /* umount one more time with logging enabled */
579 r = mount_points_list_umount(&mp_list_head, &umount_changed, true);
584 mount_points_list_free(&mp_list_head);
589 int swapoff_all(bool *changed) {
591 LIST_HEAD(MountPoint, swap_list_head);
593 LIST_HEAD_INIT(MountPoint, swap_list_head);
595 r = swap_list_get(&swap_list_head);
599 r = swap_points_list_off(&swap_list_head, changed);
602 mount_points_list_free(&swap_list_head);
607 int loopback_detach_all(bool *changed) {
609 LIST_HEAD(MountPoint, loopback_list_head);
611 LIST_HEAD_INIT(MountPoint, loopback_list_head);
613 r = loopback_list_get(&loopback_list_head);
617 r = loopback_points_list_detach(&loopback_list_head, changed);
620 mount_points_list_free(&loopback_list_head);
625 int dm_detach_all(bool *changed) {
627 LIST_HEAD(MountPoint, dm_list_head);
629 LIST_HEAD_INIT(MountPoint, dm_list_head);
631 r = dm_list_get(&dm_list_head);
635 r = dm_points_list_detach(&dm_list_head, changed);
638 mount_points_list_free(&dm_list_head);