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) {
135 if (!(proc_swaps = fopen("/proc/swaps", "re")))
136 return (errno == ENOENT) ? 0 : -errno;
138 (void) fscanf(proc_swaps, "%*s %*s %*s %*s %*s\n");
142 char *dev = NULL, *d;
145 if ((k = fscanf(proc_swaps,
146 "%ms " /* device/file */
147 "%*s " /* type of swap */
148 "%*s " /* swap size */
150 "%*s\n", /* priority */
156 log_warning("Failed to parse /proc/swaps:%u.", i);
162 if (endswith(dev, " (deleted)")) {
175 if (!(swap = new0(MountPoint, 1))) {
182 LIST_PREPEND(mount_point, *head, swap);
193 static int loopback_list_get(MountPoint **head) {
194 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
195 struct udev_list_entry *item = NULL, *first = NULL;
196 _cleanup_udev_unref_ struct udev *udev = NULL;
205 e = udev_enumerate_new(udev);
209 r = udev_enumerate_add_match_subsystem(e, "block");
213 r = udev_enumerate_add_match_sysname(e, "loop*");
217 r = udev_enumerate_add_match_sysattr(e, "loop/backing_file", NULL);
221 r = udev_enumerate_scan_devices(e);
225 first = udev_enumerate_get_list_entry(e);
226 udev_list_entry_foreach(item, first) {
228 _cleanup_udev_device_unref_ struct udev_device *d;
232 d = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
236 dn = udev_device_get_devnode(d);
244 lb = new0(MountPoint, 1);
251 LIST_PREPEND(mount_point, *head, lb);
257 static int dm_list_get(MountPoint **head) {
258 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
259 struct udev_list_entry *item = NULL, *first = NULL;
260 _cleanup_udev_unref_ struct udev *udev = NULL;
269 e = udev_enumerate_new(udev);
273 r = udev_enumerate_add_match_subsystem(e, "block");
277 r = udev_enumerate_add_match_sysname(e, "dm-*");
281 r = udev_enumerate_scan_devices(e);
285 first = udev_enumerate_get_list_entry(e);
286 udev_list_entry_foreach(item, first) {
288 _cleanup_udev_device_unref_ struct udev_device *d;
293 d = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
297 devnum = udev_device_get_devnum(d);
298 dn = udev_device_get_devnode(d);
299 if (major(devnum) == 0 || !dn)
306 m = new(MountPoint, 1);
314 LIST_PREPEND(mount_point, *head, m);
320 static int delete_loopback(const char *device) {
321 _cleanup_close_ int fd = -1;
324 fd = open(device, O_RDONLY|O_CLOEXEC);
326 return errno == ENOENT ? 0 : -errno;
328 r = ioctl(fd, LOOP_CLR_FD, 0);
332 /* ENXIO: not bound, so no error */
339 static int delete_dm(dev_t devnum) {
340 _cleanup_close_ int fd = -1;
342 struct dm_ioctl dm = {
343 .version = {DM_VERSION_MAJOR,
345 DM_VERSION_PATCHLEVEL},
346 .data_size = sizeof(dm),
350 assert(major(devnum) != 0);
352 fd = open("/dev/mapper/control", O_RDWR|O_CLOEXEC);
356 r = ioctl(fd, DM_DEV_REMOVE, &dm);
357 return r >= 0 ? 0 : -errno;
360 static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_error) {
366 LIST_FOREACH_SAFE(mount_point, m, n, *head) {
368 /* If we are in a container, don't attempt to
369 read-only mount anything as that brings no real
370 benefits, but might confuse the host, as we remount
371 the superblock here, not the bind mound. */
372 if (detect_container(NULL) <= 0) {
373 /* We always try to remount directories
374 * read-only first, before we go on and umount
377 * Mount points can be stacked. If a mount
378 * point is stacked below / or /usr, we
379 * cannot umount or remount it directly,
380 * since there is no way to refer to the
381 * underlying mount. There's nothing we can do
382 * about it for the general case, but we can
383 * do something about it if it is aliased
384 * somehwere else via a bind mount. If we
385 * explicitly remount the super block of that
386 * alias read-only we hence should be
387 * relatively safe regarding keeping the fs we
388 * can otherwise not see dirty. */
389 mount(NULL, m->path, NULL, MS_REMOUNT|MS_RDONLY, NULL);
392 /* Skip / and /usr since we cannot unmount that
393 * anyway, since we are running from it. They have
394 * already been remounted ro. */
395 if (path_equal(m->path, "/")
396 #ifndef HAVE_SPLIT_USR
397 || path_equal(m->path, "/usr")
402 /* Trying to umount. We don't force here since we rely
403 * on busy NFS and FUSE file systems to return EBUSY
404 * until we closed everything on top of them. */
405 log_info("Unmounting %s.", m->path);
406 if (umount2(m->path, 0) == 0) {
410 mount_point_free(head, m);
411 } else if (log_error) {
412 log_warning("Could not unmount %s: %m", m->path);
420 static int swap_points_list_off(MountPoint **head, bool *changed) {
426 LIST_FOREACH_SAFE(mount_point, m, n, *head) {
427 log_info("Deactivating swap %s.", m->path);
428 if (swapoff(m->path) == 0) {
432 mount_point_free(head, m);
434 log_warning("Could not deactivate swap %s: %m", m->path);
442 static int loopback_points_list_detach(MountPoint **head, bool *changed) {
449 k = lstat("/", &root_st);
451 LIST_FOREACH_SAFE(mount_point, m, n, *head) {
453 struct stat loopback_st;
456 major(root_st.st_dev) != 0 &&
457 lstat(m->path, &loopback_st) >= 0 &&
458 root_st.st_dev == loopback_st.st_rdev) {
463 log_info("Detaching loopback %s.", m->path);
464 r = delete_loopback(m->path);
466 if (r > 0 && changed)
469 mount_point_free(head, m);
471 log_warning("Could not detach loopback %s: %m", m->path);
479 static int dm_points_list_detach(MountPoint **head, bool *changed) {
486 k = lstat("/", &root_st);
488 LIST_FOREACH_SAFE(mount_point, m, n, *head) {
492 major(root_st.st_dev) != 0 &&
493 root_st.st_dev == m->devnum) {
498 log_info("Detaching DM %u:%u.", major(m->devnum), minor(m->devnum));
499 r = delete_dm(m->devnum);
504 mount_point_free(head, m);
506 log_warning("Could not detach DM %s: %m", m->path);
514 int umount_all(bool *changed) {
517 LIST_HEAD(MountPoint, mp_list_head);
519 LIST_HEAD_INIT(mp_list_head);
520 r = mount_points_list_get(&mp_list_head);
524 /* retry umount, until nothing can be umounted anymore */
526 umount_changed = false;
528 mount_points_list_umount(&mp_list_head, &umount_changed, false);
532 } while (umount_changed);
534 /* umount one more time with logging enabled */
535 r = mount_points_list_umount(&mp_list_head, &umount_changed, true);
540 mount_points_list_free(&mp_list_head);
545 int swapoff_all(bool *changed) {
547 LIST_HEAD(MountPoint, swap_list_head);
549 LIST_HEAD_INIT(swap_list_head);
551 r = swap_list_get(&swap_list_head);
555 r = swap_points_list_off(&swap_list_head, changed);
558 mount_points_list_free(&swap_list_head);
563 int loopback_detach_all(bool *changed) {
565 LIST_HEAD(MountPoint, loopback_list_head);
567 LIST_HEAD_INIT(loopback_list_head);
569 r = loopback_list_get(&loopback_list_head);
573 r = loopback_points_list_detach(&loopback_list_head, changed);
576 mount_points_list_free(&loopback_list_head);
581 int dm_detach_all(bool *changed) {
583 LIST_HEAD(MountPoint, dm_list_head);
585 LIST_HEAD_INIT(dm_list_head);
587 r = dm_list_get(&dm_list_head);
591 r = dm_points_list_detach(&dm_list_head, changed);
594 mount_points_list_free(&dm_list_head);