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_unref_ struct udev *udev;
206 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
207 struct udev_list_entry *item = NULL, *first = NULL;
215 e = udev_enumerate_new(udev);
219 if (udev_enumerate_add_match_subsystem(e, "block") < 0 ||
220 udev_enumerate_add_match_sysname(e, "loop*") < 0 ||
221 udev_enumerate_add_match_sysattr(e, "loop/backing_file", NULL) < 0)
224 if (udev_enumerate_scan_devices(e) < 0)
227 first = udev_enumerate_get_list_entry(e);
228 udev_list_entry_foreach(item, first) {
230 _cleanup_udev_device_unref_ struct udev_device *d;
234 d = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
238 dn = udev_device_get_devnode(d);
246 lb = new0(MountPoint, 1);
253 LIST_PREPEND(mount_point, *head, lb);
259 static int dm_list_get(MountPoint **head) {
260 _cleanup_udev_unref_ struct udev *udev;
261 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
262 struct udev_list_entry *item = NULL, *first = NULL;
270 e = udev_enumerate_new(udev);
274 if (udev_enumerate_add_match_subsystem(e, "block") < 0 ||
275 udev_enumerate_add_match_sysname(e, "dm-*") < 0)
278 if (udev_enumerate_scan_devices(e) < 0)
281 first = udev_enumerate_get_list_entry(e);
283 udev_list_entry_foreach(item, first) {
285 _cleanup_udev_device_unref_ struct udev_device *d;
290 d = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item));
294 devnum = udev_device_get_devnum(d);
295 dn = udev_device_get_devnode(d);
296 if (major(devnum) == 0 || !dn)
303 m = new(MountPoint, 1);
311 LIST_PREPEND(mount_point, *head, m);
317 static int delete_loopback(const char *device) {
320 if ((fd = open(device, O_RDONLY|O_CLOEXEC)) < 0)
321 return errno == ENOENT ? 0 : -errno;
323 r = ioctl(fd, LOOP_CLR_FD, 0);
324 close_nointr_nofail(fd);
329 /* ENXIO: not bound, so no error */
336 static int delete_dm(dev_t devnum) {
337 _cleanup_close_ int fd = -1;
339 struct dm_ioctl dm = {
340 .version = {DM_VERSION_MAJOR,
342 DM_VERSION_PATCHLEVEL},
343 .data_size = sizeof(dm),
347 assert(major(devnum) != 0);
349 fd = open("/dev/mapper/control", O_RDWR|O_CLOEXEC);
353 r = ioctl(fd, DM_DEV_REMOVE, &dm);
354 return r >= 0 ? 0 : -errno;
357 static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_error) {
363 LIST_FOREACH_SAFE(mount_point, m, n, *head) {
365 /* If we are in a container, don't attempt to
366 read-only mount anything as that brings no real
367 benefits, but might confuse the host, as we remount
368 the superblock here, not the bind mound. */
369 if (detect_container(NULL) <= 0) {
370 /* We always try to remount directories
371 * read-only first, before we go on and umount
374 * Mount points can be stacked. If a mount
375 * point is stacked below / or /usr, we
376 * cannot umount or remount it directly,
377 * since there is no way to refer to the
378 * underlying mount. There's nothing we can do
379 * about it for the general case, but we can
380 * do something about it if it is aliased
381 * somehwere else via a bind mount. If we
382 * explicitly remount the super block of that
383 * alias read-only we hence should be
384 * relatively safe regarding keeping the fs we
385 * can otherwise not see dirty. */
386 mount(NULL, m->path, NULL, MS_REMOUNT|MS_RDONLY, NULL);
389 /* Skip / and /usr since we cannot unmount that
390 * anyway, since we are running from it. They have
391 * already been remounted ro. */
392 if (path_equal(m->path, "/")
393 #ifndef HAVE_SPLIT_USR
394 || path_equal(m->path, "/usr")
399 /* Trying to umount. We don't force here since we rely
400 * on busy NFS and FUSE file systems to return EBUSY
401 * until we closed everything on top of them. */
402 log_info("Unmounting %s.", m->path);
403 if (umount2(m->path, 0) == 0) {
407 mount_point_free(head, m);
408 } else if (log_error) {
409 log_warning("Could not unmount %s: %m", m->path);
417 static int swap_points_list_off(MountPoint **head, bool *changed) {
423 LIST_FOREACH_SAFE(mount_point, m, n, *head) {
424 log_info("Deactivating swap %s.", m->path);
425 if (swapoff(m->path) == 0) {
429 mount_point_free(head, m);
431 log_warning("Could not deactivate swap %s: %m", m->path);
439 static int loopback_points_list_detach(MountPoint **head, bool *changed) {
446 k = lstat("/", &root_st);
448 LIST_FOREACH_SAFE(mount_point, m, n, *head) {
450 struct stat loopback_st;
453 major(root_st.st_dev) != 0 &&
454 lstat(m->path, &loopback_st) >= 0 &&
455 root_st.st_dev == loopback_st.st_rdev) {
460 log_info("Detaching loopback %s.", m->path);
461 r = delete_loopback(m->path);
463 if (r > 0 && changed)
466 mount_point_free(head, m);
468 log_warning("Could not detach loopback %s: %m", m->path);
476 static int dm_points_list_detach(MountPoint **head, bool *changed) {
483 k = lstat("/", &root_st);
485 LIST_FOREACH_SAFE(mount_point, m, n, *head) {
489 major(root_st.st_dev) != 0 &&
490 root_st.st_dev == m->devnum) {
495 log_info("Detaching DM %u:%u.", major(m->devnum), minor(m->devnum));
496 r = delete_dm(m->devnum);
501 mount_point_free(head, m);
503 log_warning("Could not detach DM %s: %m", m->path);
511 int umount_all(bool *changed) {
514 LIST_HEAD(MountPoint, mp_list_head);
516 LIST_HEAD_INIT(mp_list_head);
517 r = mount_points_list_get(&mp_list_head);
521 /* retry umount, until nothing can be umounted anymore */
523 umount_changed = false;
525 mount_points_list_umount(&mp_list_head, &umount_changed, false);
529 } while (umount_changed);
531 /* umount one more time with logging enabled */
532 r = mount_points_list_umount(&mp_list_head, &umount_changed, true);
537 mount_points_list_free(&mp_list_head);
542 int swapoff_all(bool *changed) {
544 LIST_HEAD(MountPoint, swap_list_head);
546 LIST_HEAD_INIT(swap_list_head);
548 r = swap_list_get(&swap_list_head);
552 r = swap_points_list_off(&swap_list_head, changed);
555 mount_points_list_free(&swap_list_head);
560 int loopback_detach_all(bool *changed) {
562 LIST_HEAD(MountPoint, loopback_list_head);
564 LIST_HEAD_INIT(loopback_list_head);
566 r = loopback_list_get(&loopback_list_head);
570 r = loopback_points_list_detach(&loopback_list_head, changed);
573 mount_points_list_free(&loopback_list_head);
578 int dm_detach_all(bool *changed) {
580 LIST_HEAD(MountPoint, dm_list_head);
582 LIST_HEAD_INIT(dm_list_head);
584 r = dm_list_get(&dm_list_head);
588 r = dm_points_list_detach(&dm_list_head, changed);
591 mount_points_list_free(&dm_list_head);