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 FILE *proc_self_mountinfo;
71 if (!(proc_self_mountinfo = fopen("/proc/self/mountinfo", "re")))
80 if ((k = fscanf(proc_self_mountinfo,
81 "%*s " /* (1) mount id */
82 "%*s " /* (2) parent id */
83 "%*s " /* (3) major:minor */
85 "%ms " /* (5) mount point */
86 "%*s" /* (6) mount options */
87 "%*[^-]" /* (7) optional fields */
88 "- " /* (8) separator */
89 "%*s " /* (9) file system type */
90 "%*s" /* (10) mount source */
91 "%*s" /* (11) mount options 2 */
92 "%*[^\n]", /* some rubbish at the end */
97 log_warning("Failed to parse /proc/self/mountinfo:%u.", i);
111 /* Ignore mount points we can't unmount because they
112 * are API or because we are keeping them open (like
114 if (mount_point_is_api(p) ||
115 mount_point_ignore(p) ||
116 path_equal(p, "/dev/console")) {
121 if (!(m = new0(MountPoint, 1))) {
128 LIST_PREPEND(mount_point, *head, m);
134 fclose(proc_self_mountinfo);
139 static int swap_list_get(MountPoint **head) {
146 if (!(proc_swaps = fopen("/proc/swaps", "re")))
147 return (errno == ENOENT) ? 0 : -errno;
149 (void) fscanf(proc_swaps, "%*s %*s %*s %*s %*s\n");
153 char *dev = NULL, *d;
156 if ((k = fscanf(proc_swaps,
157 "%ms " /* device/file */
158 "%*s " /* type of swap */
159 "%*s " /* swap size */
161 "%*s\n", /* priority */
167 log_warning("Failed to parse /proc/swaps:%u.", i);
173 if (endswith(dev, " (deleted)")) {
186 if (!(swap = new0(MountPoint, 1))) {
193 LIST_PREPEND(mount_point, *head, swap);
204 static int loopback_list_get(MountPoint **head) {
205 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
206 struct udev_list_entry *item = NULL, *first = NULL;
207 _cleanup_udev_unref_ struct udev *udev = NULL;
216 e = udev_enumerate_new(udev);
220 r = udev_enumerate_add_match_subsystem(e, "block");
224 r = udev_enumerate_add_match_sysname(e, "loop*");
228 r = udev_enumerate_add_match_sysattr(e, "loop/backing_file", NULL);
232 r = udev_enumerate_scan_devices(e);
236 first = udev_enumerate_get_list_entry(e);
237 udev_list_entry_foreach(item, first) {
239 _cleanup_udev_device_unref_ struct udev_device *d;
243 d = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
247 dn = udev_device_get_devnode(d);
255 lb = new0(MountPoint, 1);
262 LIST_PREPEND(mount_point, *head, lb);
268 static int dm_list_get(MountPoint **head) {
269 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
270 struct udev_list_entry *item = NULL, *first = NULL;
271 _cleanup_udev_unref_ struct udev *udev = NULL;
280 e = udev_enumerate_new(udev);
284 r = udev_enumerate_add_match_subsystem(e, "block");
288 r = udev_enumerate_add_match_sysname(e, "dm-*");
292 r = udev_enumerate_scan_devices(e);
296 first = udev_enumerate_get_list_entry(e);
297 udev_list_entry_foreach(item, first) {
299 _cleanup_udev_device_unref_ struct udev_device *d;
304 d = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
308 devnum = udev_device_get_devnum(d);
309 dn = udev_device_get_devnode(d);
310 if (major(devnum) == 0 || !dn)
317 m = new(MountPoint, 1);
325 LIST_PREPEND(mount_point, *head, m);
331 static int delete_loopback(const char *device) {
332 _cleanup_close_ int fd = -1;
335 fd = open(device, O_RDONLY|O_CLOEXEC);
337 return errno == ENOENT ? 0 : -errno;
339 r = ioctl(fd, LOOP_CLR_FD, 0);
343 /* ENXIO: not bound, so no error */
350 static int delete_dm(dev_t devnum) {
351 _cleanup_close_ int fd = -1;
353 struct dm_ioctl dm = {
354 .version = {DM_VERSION_MAJOR,
356 DM_VERSION_PATCHLEVEL},
357 .data_size = sizeof(dm),
361 assert(major(devnum) != 0);
363 fd = open("/dev/mapper/control", O_RDWR|O_CLOEXEC);
367 r = ioctl(fd, DM_DEV_REMOVE, &dm);
368 return r >= 0 ? 0 : -errno;
371 static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_error) {
377 LIST_FOREACH_SAFE(mount_point, m, n, *head) {
379 /* If we are in a container, don't attempt to
380 read-only mount anything as that brings no real
381 benefits, but might confuse the host, as we remount
382 the superblock here, not the bind mound. */
383 if (detect_container(NULL) <= 0) {
384 /* We always try to remount directories
385 * read-only first, before we go on and umount
388 * Mount points can be stacked. If a mount
389 * point is stacked below / or /usr, we
390 * cannot umount or remount it directly,
391 * since there is no way to refer to the
392 * underlying mount. There's nothing we can do
393 * about it for the general case, but we can
394 * do something about it if it is aliased
395 * somehwere else via a bind mount. If we
396 * explicitly remount the super block of that
397 * alias read-only we hence should be
398 * relatively safe regarding keeping the fs we
399 * can otherwise not see dirty. */
400 mount(NULL, m->path, NULL, MS_REMOUNT|MS_RDONLY, NULL);
403 /* Skip / and /usr since we cannot unmount that
404 * anyway, since we are running from it. They have
405 * already been remounted ro. */
406 if (path_equal(m->path, "/")
407 #ifndef HAVE_SPLIT_USR
408 || path_equal(m->path, "/usr")
413 /* Trying to umount. We don't force here since we rely
414 * on busy NFS and FUSE file systems to return EBUSY
415 * until we closed everything on top of them. */
416 log_info("Unmounting %s.", m->path);
417 if (umount2(m->path, 0) == 0) {
421 mount_point_free(head, m);
422 } else if (log_error) {
423 log_warning("Could not unmount %s: %m", m->path);
431 static int swap_points_list_off(MountPoint **head, bool *changed) {
437 LIST_FOREACH_SAFE(mount_point, m, n, *head) {
438 log_info("Deactivating swap %s.", m->path);
439 if (swapoff(m->path) == 0) {
443 mount_point_free(head, m);
445 log_warning("Could not deactivate swap %s: %m", m->path);
453 static int loopback_points_list_detach(MountPoint **head, bool *changed) {
460 k = lstat("/", &root_st);
462 LIST_FOREACH_SAFE(mount_point, m, n, *head) {
464 struct stat loopback_st;
467 major(root_st.st_dev) != 0 &&
468 lstat(m->path, &loopback_st) >= 0 &&
469 root_st.st_dev == loopback_st.st_rdev) {
474 log_info("Detaching loopback %s.", m->path);
475 r = delete_loopback(m->path);
477 if (r > 0 && changed)
480 mount_point_free(head, m);
482 log_warning("Could not detach loopback %s: %m", m->path);
490 static int dm_points_list_detach(MountPoint **head, bool *changed) {
497 k = lstat("/", &root_st);
499 LIST_FOREACH_SAFE(mount_point, m, n, *head) {
503 major(root_st.st_dev) != 0 &&
504 root_st.st_dev == m->devnum) {
509 log_info("Detaching DM %u:%u.", major(m->devnum), minor(m->devnum));
510 r = delete_dm(m->devnum);
515 mount_point_free(head, m);
517 log_warning("Could not detach DM %s: %m", m->path);
525 int umount_all(bool *changed) {
528 LIST_HEAD(MountPoint, mp_list_head);
530 LIST_HEAD_INIT(mp_list_head);
531 r = mount_points_list_get(&mp_list_head);
535 /* retry umount, until nothing can be umounted anymore */
537 umount_changed = false;
539 mount_points_list_umount(&mp_list_head, &umount_changed, false);
543 } while (umount_changed);
545 /* umount one more time with logging enabled */
546 r = mount_points_list_umount(&mp_list_head, &umount_changed, true);
551 mount_points_list_free(&mp_list_head);
556 int swapoff_all(bool *changed) {
558 LIST_HEAD(MountPoint, swap_list_head);
560 LIST_HEAD_INIT(swap_list_head);
562 r = swap_list_get(&swap_list_head);
566 r = swap_points_list_off(&swap_list_head, changed);
569 mount_points_list_free(&swap_list_head);
574 int loopback_detach_all(bool *changed) {
576 LIST_HEAD(MountPoint, loopback_list_head);
578 LIST_HEAD_INIT(loopback_list_head);
580 r = loopback_list_get(&loopback_list_head);
584 r = loopback_points_list_detach(&loopback_list_head, changed);
587 mount_points_list_free(&loopback_list_head);
592 int dm_detach_all(bool *changed) {
594 LIST_HEAD(MountPoint, dm_list_head);
596 LIST_HEAD_INIT(dm_list_head);
598 r = dm_list_get(&dm_list_head);
602 r = dm_points_list_detach(&dm_list_head, changed);
605 mount_points_list_free(&dm_list_head);