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>
32 #include "mount-setup.h"
34 #include "path-util.h"
38 #include "udev-util.h"
40 typedef struct MountPoint {
43 LIST_FIELDS(struct MountPoint, mount_point);
46 static void mount_point_free(MountPoint **head, MountPoint *m) {
50 LIST_REMOVE(mount_point, *head, m);
56 static void mount_points_list_free(MountPoint **head) {
60 mount_point_free(head, *head);
63 static int mount_points_list_get(MountPoint **head) {
64 _cleanup_fclose_ FILE *proc_self_mountinfo = NULL;
69 proc_self_mountinfo = fopen("/proc/self/mountinfo", "re");
70 if (!proc_self_mountinfo)
74 _cleanup_free_ char *path = NULL;
79 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 */
97 log_warning("Failed to parse /proc/self/mountinfo:%u.", i);
105 /* Ignore mount points we can't unmount because they
106 * are API or because we are keeping them open (like
108 if (mount_point_is_api(p) ||
109 mount_point_ignore(p) ||
110 path_equal(p, "/dev/console")) {
115 m = new0(MountPoint, 1);
122 LIST_PREPEND(mount_point, *head, m);
128 static int swap_list_get(MountPoint **head) {
129 _cleanup_fclose_ FILE *proc_swaps = NULL;
134 if (!(proc_swaps = fopen("/proc/swaps", "re")))
135 return (errno == ENOENT) ? 0 : -errno;
137 (void) fscanf(proc_swaps, "%*s %*s %*s %*s %*s\n");
141 char *dev = NULL, *d;
144 if ((k = fscanf(proc_swaps,
145 "%ms " /* device/file */
146 "%*s " /* type of swap */
147 "%*s " /* swap size */
149 "%*s\n", /* priority */
155 log_warning("Failed to parse /proc/swaps:%u.", i);
161 if (endswith(dev, " (deleted)")) {
173 if (!(swap = new0(MountPoint, 1))) {
179 LIST_PREPEND(mount_point, *head, swap);
185 static int loopback_list_get(MountPoint **head) {
186 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
187 struct udev_list_entry *item = NULL, *first = NULL;
188 _cleanup_udev_unref_ struct udev *udev = NULL;
197 e = udev_enumerate_new(udev);
201 r = udev_enumerate_add_match_subsystem(e, "block");
205 r = udev_enumerate_add_match_sysname(e, "loop*");
209 r = udev_enumerate_add_match_sysattr(e, "loop/backing_file", NULL);
213 r = udev_enumerate_scan_devices(e);
217 first = udev_enumerate_get_list_entry(e);
218 udev_list_entry_foreach(item, first) {
220 _cleanup_udev_device_unref_ struct udev_device *d;
224 d = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
228 dn = udev_device_get_devnode(d);
236 lb = new0(MountPoint, 1);
243 LIST_PREPEND(mount_point, *head, lb);
249 static int dm_list_get(MountPoint **head) {
250 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
251 struct udev_list_entry *item = NULL, *first = NULL;
252 _cleanup_udev_unref_ struct udev *udev = NULL;
261 e = udev_enumerate_new(udev);
265 r = udev_enumerate_add_match_subsystem(e, "block");
269 r = udev_enumerate_add_match_sysname(e, "dm-*");
273 r = udev_enumerate_scan_devices(e);
277 first = udev_enumerate_get_list_entry(e);
278 udev_list_entry_foreach(item, first) {
280 _cleanup_udev_device_unref_ struct udev_device *d;
285 d = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
289 devnum = udev_device_get_devnum(d);
290 dn = udev_device_get_devnode(d);
291 if (major(devnum) == 0 || !dn)
298 m = new(MountPoint, 1);
306 LIST_PREPEND(mount_point, *head, m);
312 static int delete_loopback(const char *device) {
313 _cleanup_close_ int fd = -1;
316 fd = open(device, O_RDONLY|O_CLOEXEC);
318 return errno == ENOENT ? 0 : -errno;
320 r = ioctl(fd, LOOP_CLR_FD, 0);
324 /* ENXIO: not bound, so no error */
331 static int delete_dm(dev_t devnum) {
332 _cleanup_close_ int fd = -1;
334 struct dm_ioctl dm = {
335 .version = {DM_VERSION_MAJOR,
337 DM_VERSION_PATCHLEVEL},
338 .data_size = sizeof(dm),
342 assert(major(devnum) != 0);
344 fd = open("/dev/mapper/control", O_RDWR|O_CLOEXEC);
348 r = ioctl(fd, DM_DEV_REMOVE, &dm);
349 return r >= 0 ? 0 : -errno;
352 static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_error) {
358 LIST_FOREACH_SAFE(mount_point, m, n, *head) {
360 /* If we are in a container, don't attempt to
361 read-only mount anything as that brings no real
362 benefits, but might confuse the host, as we remount
363 the superblock here, not the bind mound. */
364 if (detect_container(NULL) <= 0) {
365 /* We always try to remount directories
366 * read-only first, before we go on and umount
369 * Mount points can be stacked. If a mount
370 * point is stacked below / or /usr, we
371 * cannot umount or remount it directly,
372 * since there is no way to refer to the
373 * underlying mount. There's nothing we can do
374 * about it for the general case, but we can
375 * do something about it if it is aliased
376 * somehwere else via a bind mount. If we
377 * explicitly remount the super block of that
378 * alias read-only we hence should be
379 * relatively safe regarding keeping the fs we
380 * can otherwise not see dirty. */
381 mount(NULL, m->path, NULL, MS_REMOUNT|MS_RDONLY, NULL);
384 /* Skip / and /usr since we cannot unmount that
385 * anyway, since we are running from it. They have
386 * already been remounted ro. */
387 if (path_equal(m->path, "/")
388 #ifndef HAVE_SPLIT_USR
389 || path_equal(m->path, "/usr")
394 /* Trying to umount. We don't force here since we rely
395 * on busy NFS and FUSE file systems to return EBUSY
396 * until we closed everything on top of them. */
397 log_info("Unmounting %s.", m->path);
398 if (umount2(m->path, 0) == 0) {
402 mount_point_free(head, m);
403 } else if (log_error) {
404 log_warning("Could not unmount %s: %m", m->path);
412 static int swap_points_list_off(MountPoint **head, bool *changed) {
418 LIST_FOREACH_SAFE(mount_point, m, n, *head) {
419 log_info("Deactivating swap %s.", m->path);
420 if (swapoff(m->path) == 0) {
424 mount_point_free(head, m);
426 log_warning("Could not deactivate swap %s: %m", m->path);
434 static int loopback_points_list_detach(MountPoint **head, bool *changed) {
441 k = lstat("/", &root_st);
443 LIST_FOREACH_SAFE(mount_point, m, n, *head) {
445 struct stat loopback_st;
448 major(root_st.st_dev) != 0 &&
449 lstat(m->path, &loopback_st) >= 0 &&
450 root_st.st_dev == loopback_st.st_rdev) {
455 log_info("Detaching loopback %s.", m->path);
456 r = delete_loopback(m->path);
458 if (r > 0 && changed)
461 mount_point_free(head, m);
463 log_warning("Could not detach loopback %s: %m", m->path);
471 static int dm_points_list_detach(MountPoint **head, bool *changed) {
478 k = lstat("/", &root_st);
480 LIST_FOREACH_SAFE(mount_point, m, n, *head) {
484 major(root_st.st_dev) != 0 &&
485 root_st.st_dev == m->devnum) {
490 log_info("Detaching DM %u:%u.", major(m->devnum), minor(m->devnum));
491 r = delete_dm(m->devnum);
496 mount_point_free(head, m);
498 log_warning("Could not detach DM %s: %m", m->path);
506 int umount_all(bool *changed) {
509 LIST_HEAD(MountPoint, mp_list_head);
511 LIST_HEAD_INIT(mp_list_head);
512 r = mount_points_list_get(&mp_list_head);
516 /* retry umount, until nothing can be umounted anymore */
518 umount_changed = false;
520 mount_points_list_umount(&mp_list_head, &umount_changed, false);
524 } while (umount_changed);
526 /* umount one more time with logging enabled */
527 r = mount_points_list_umount(&mp_list_head, &umount_changed, true);
532 mount_points_list_free(&mp_list_head);
537 int swapoff_all(bool *changed) {
539 LIST_HEAD(MountPoint, swap_list_head);
541 LIST_HEAD_INIT(swap_list_head);
543 r = swap_list_get(&swap_list_head);
547 r = swap_points_list_off(&swap_list_head, changed);
550 mount_points_list_free(&swap_list_head);
555 int loopback_detach_all(bool *changed) {
557 LIST_HEAD(MountPoint, loopback_list_head);
559 LIST_HEAD_INIT(loopback_list_head);
561 r = loopback_list_get(&loopback_list_head);
565 r = loopback_points_list_detach(&loopback_list_head, changed);
568 mount_points_list_free(&loopback_list_head);
573 int dm_detach_all(bool *changed) {
575 LIST_HEAD(MountPoint, dm_list_head);
577 LIST_HEAD_INIT(dm_list_head);
579 r = dm_list_get(&dm_list_head);
583 r = dm_points_list_detach(&dm_list_head, changed);
586 mount_points_list_free(&dm_list_head);