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/>.
24 #include <linux/dm-ioctl.h>
25 #include <linux/loop.h>
27 #include <sys/mount.h>
32 #include "alloc-util.h"
35 #include "fstab-util.h"
37 #include "mount-setup.h"
38 #include "path-util.h"
39 #include "string-util.h"
40 #include "udev-util.h"
45 typedef struct MountPoint
{
49 LIST_FIELDS(struct MountPoint
, mount_point
);
52 static void mount_point_free(MountPoint
**head
, MountPoint
*m
) {
56 LIST_REMOVE(mount_point
, *head
, m
);
62 static void mount_points_list_free(MountPoint
**head
) {
66 mount_point_free(head
, *head
);
69 static int mount_points_list_get(MountPoint
**head
) {
70 _cleanup_fclose_
FILE *proc_self_mountinfo
= NULL
;
76 proc_self_mountinfo
= fopen("/proc/self/mountinfo", "re");
77 if (!proc_self_mountinfo
)
81 _cleanup_free_
char *path
= NULL
, *options
= NULL
;
86 k
= fscanf(proc_self_mountinfo
,
87 "%*s " /* (1) mount id */
88 "%*s " /* (2) parent id */
89 "%*s " /* (3) major:minor */
91 "%ms " /* (5) mount point */
92 "%*s" /* (6) mount flags */
93 "%*[^-]" /* (7) optional fields */
94 "- " /* (8) separator */
95 "%*s " /* (9) file system type */
96 "%*s" /* (10) mount source */
97 "%ms" /* (11) mount options */
98 "%*[^\n]", /* some rubbish at the end */
104 log_warning("Failed to parse /proc/self/mountinfo:%u.", i
);
108 r
= cunescape(path
, UNESCAPE_RELAX
, &p
);
112 /* Ignore mount points we can't unmount because they
113 * are API or because we are keeping them open (like
114 * /dev/console). Also, ignore all mounts below API
115 * file systems, since they are likely virtual too,
116 * and hence not worth spending time on. Also, in
117 * unprivileged containers we might lack the rights to
118 * unmount these things, hence don't bother. */
119 if (mount_point_is_api(p
) ||
120 mount_point_ignore(p
) ||
121 path_startswith(p
, "/dev") ||
122 path_startswith(p
, "/sys") ||
123 path_startswith(p
, "/proc")) {
128 m
= new0(MountPoint
, 1);
135 m
->options
= options
;
138 LIST_PREPEND(mount_point
, *head
, m
);
144 static int swap_list_get(MountPoint
**head
) {
145 _cleanup_fclose_
FILE *proc_swaps
= NULL
;
151 proc_swaps
= fopen("/proc/swaps", "re");
153 return (errno
== ENOENT
) ? 0 : -errno
;
155 (void) fscanf(proc_swaps
, "%*s %*s %*s %*s %*s\n");
159 char *dev
= NULL
, *d
;
162 k
= fscanf(proc_swaps
,
163 "%ms " /* device/file */
164 "%*s " /* type of swap */
165 "%*s " /* swap size */
167 "%*s\n", /* priority */
174 log_warning("Failed to parse /proc/swaps:%u.", i
);
179 if (endswith(dev
, " (deleted)")) {
184 r
= cunescape(dev
, UNESCAPE_RELAX
, &d
);
189 swap
= new0(MountPoint
, 1);
196 LIST_PREPEND(mount_point
, *head
, swap
);
202 static int loopback_list_get(MountPoint
**head
) {
203 _cleanup_udev_enumerate_unref_
struct udev_enumerate
*e
= NULL
;
204 struct udev_list_entry
*item
= NULL
, *first
= NULL
;
205 _cleanup_udev_unref_
struct udev
*udev
= NULL
;
214 e
= udev_enumerate_new(udev
);
218 r
= udev_enumerate_add_match_subsystem(e
, "block");
222 r
= udev_enumerate_add_match_sysname(e
, "loop*");
226 r
= udev_enumerate_add_match_sysattr(e
, "loop/backing_file", NULL
);
230 r
= udev_enumerate_scan_devices(e
);
234 first
= udev_enumerate_get_list_entry(e
);
235 udev_list_entry_foreach(item
, first
) {
237 _cleanup_udev_device_unref_
struct udev_device
*d
;
241 d
= udev_device_new_from_syspath(udev
, udev_list_entry_get_name(item
));
245 dn
= udev_device_get_devnode(d
);
253 lb
= new0(MountPoint
, 1);
260 LIST_PREPEND(mount_point
, *head
, lb
);
266 static int dm_list_get(MountPoint
**head
) {
267 _cleanup_udev_enumerate_unref_
struct udev_enumerate
*e
= NULL
;
268 struct udev_list_entry
*item
= NULL
, *first
= NULL
;
269 _cleanup_udev_unref_
struct udev
*udev
= NULL
;
278 e
= udev_enumerate_new(udev
);
282 r
= udev_enumerate_add_match_subsystem(e
, "block");
286 r
= udev_enumerate_add_match_sysname(e
, "dm-*");
290 r
= udev_enumerate_scan_devices(e
);
294 first
= udev_enumerate_get_list_entry(e
);
295 udev_list_entry_foreach(item
, first
) {
297 _cleanup_udev_device_unref_
struct udev_device
*d
;
302 d
= udev_device_new_from_syspath(udev
, udev_list_entry_get_name(item
));
306 devnum
= udev_device_get_devnum(d
);
307 dn
= udev_device_get_devnode(d
);
308 if (major(devnum
) == 0 || !dn
)
315 m
= new(MountPoint
, 1);
323 LIST_PREPEND(mount_point
, *head
, m
);
329 static int delete_loopback(const char *device
) {
330 _cleanup_close_
int fd
= -1;
333 fd
= open(device
, O_RDONLY
|O_CLOEXEC
);
335 return errno
== ENOENT
? 0 : -errno
;
337 r
= ioctl(fd
, LOOP_CLR_FD
, 0);
341 /* ENXIO: not bound, so no error */
348 static int delete_dm(dev_t devnum
) {
349 _cleanup_close_
int fd
= -1;
351 struct dm_ioctl dm
= {
352 .version
= {DM_VERSION_MAJOR
,
354 DM_VERSION_PATCHLEVEL
},
355 .data_size
= sizeof(dm
),
359 assert(major(devnum
) != 0);
361 fd
= open("/dev/mapper/control", O_RDWR
|O_CLOEXEC
);
365 r
= ioctl(fd
, DM_DEV_REMOVE
, &dm
);
366 return r
>= 0 ? 0 : -errno
;
369 static int mount_points_list_umount(MountPoint
**head
, bool *changed
, bool log_error
) {
375 LIST_FOREACH_SAFE(mount_point
, m
, n
, *head
) {
377 /* If we are in a container, don't attempt to
378 read-only mount anything as that brings no real
379 benefits, but might confuse the host, as we remount
380 the superblock here, not the bind mound. */
381 if (detect_container() <= 0) {
382 _cleanup_free_
char *options
= NULL
;
383 /* MS_REMOUNT requires that the data parameter
384 * should be the same from the original mount
385 * except for the desired changes. Since we want
386 * to remount read-only, we should filter out
387 * rw (and ro too, because it confuses the kernel) */
388 (void) fstab_filter_options(m
->options
, "rw\0ro\0", NULL
, NULL
, &options
);
390 /* We always try to remount directories
391 * read-only first, before we go on and umount
394 * Mount points can be stacked. If a mount
395 * point is stacked below / or /usr, we
396 * cannot umount or remount it directly,
397 * since there is no way to refer to the
398 * underlying mount. There's nothing we can do
399 * about it for the general case, but we can
400 * do something about it if it is aliased
401 * somehwere else via a bind mount. If we
402 * explicitly remount the super block of that
403 * alias read-only we hence should be
404 * relatively safe regarding keeping the fs we
405 * can otherwise not see dirty. */
406 log_info("Remounting '%s' read-only with options '%s'.", m
->path
, options
);
407 (void) mount(NULL
, m
->path
, NULL
, MS_REMOUNT
|MS_RDONLY
, options
);
410 /* Skip / and /usr since we cannot unmount that
411 * anyway, since we are running from it. They have
412 * already been remounted ro. */
413 if (path_equal(m
->path
, "/")
414 #ifndef HAVE_SPLIT_USR
415 || path_equal(m
->path
, "/usr")
420 /* Trying to umount. We don't force here since we rely
421 * on busy NFS and FUSE file systems to return EBUSY
422 * until we closed everything on top of them. */
423 log_info("Unmounting %s.", m
->path
);
424 if (umount2(m
->path
, 0) == 0) {
428 mount_point_free(head
, m
);
429 } else if (log_error
) {
430 log_warning_errno(errno
, "Could not unmount %s: %m", m
->path
);
438 static int swap_points_list_off(MountPoint
**head
, bool *changed
) {
444 LIST_FOREACH_SAFE(mount_point
, m
, n
, *head
) {
445 log_info("Deactivating swap %s.", m
->path
);
446 if (swapoff(m
->path
) == 0) {
450 mount_point_free(head
, m
);
452 log_warning_errno(errno
, "Could not deactivate swap %s: %m", m
->path
);
460 static int loopback_points_list_detach(MountPoint
**head
, bool *changed
) {
467 k
= lstat("/", &root_st
);
469 LIST_FOREACH_SAFE(mount_point
, m
, n
, *head
) {
471 struct stat loopback_st
;
474 major(root_st
.st_dev
) != 0 &&
475 lstat(m
->path
, &loopback_st
) >= 0 &&
476 root_st
.st_dev
== loopback_st
.st_rdev
) {
481 log_info("Detaching loopback %s.", m
->path
);
482 r
= delete_loopback(m
->path
);
484 if (r
> 0 && changed
)
487 mount_point_free(head
, m
);
489 log_warning_errno(errno
, "Could not detach loopback %s: %m", m
->path
);
497 static int dm_points_list_detach(MountPoint
**head
, bool *changed
) {
504 k
= lstat("/", &root_st
);
506 LIST_FOREACH_SAFE(mount_point
, m
, n
, *head
) {
510 major(root_st
.st_dev
) != 0 &&
511 root_st
.st_dev
== m
->devnum
) {
516 log_info("Detaching DM %u:%u.", major(m
->devnum
), minor(m
->devnum
));
517 r
= delete_dm(m
->devnum
);
522 mount_point_free(head
, m
);
524 log_warning_errno(errno
, "Could not detach DM %s: %m", m
->path
);
532 int umount_all(bool *changed
) {
535 LIST_HEAD(MountPoint
, mp_list_head
);
537 LIST_HEAD_INIT(mp_list_head
);
538 r
= mount_points_list_get(&mp_list_head
);
542 /* retry umount, until nothing can be umounted anymore */
544 umount_changed
= false;
546 mount_points_list_umount(&mp_list_head
, &umount_changed
, false);
550 } while (umount_changed
);
552 /* umount one more time with logging enabled */
553 r
= mount_points_list_umount(&mp_list_head
, &umount_changed
, true);
558 mount_points_list_free(&mp_list_head
);
563 int swapoff_all(bool *changed
) {
565 LIST_HEAD(MountPoint
, swap_list_head
);
567 LIST_HEAD_INIT(swap_list_head
);
569 r
= swap_list_get(&swap_list_head
);
573 r
= swap_points_list_off(&swap_list_head
, changed
);
576 mount_points_list_free(&swap_list_head
);
581 int loopback_detach_all(bool *changed
) {
583 LIST_HEAD(MountPoint
, loopback_list_head
);
585 LIST_HEAD_INIT(loopback_list_head
);
587 r
= loopback_list_get(&loopback_list_head
);
591 r
= loopback_points_list_detach(&loopback_list_head
, changed
);
594 mount_points_list_free(&loopback_list_head
);
599 int dm_detach_all(bool *changed
) {
601 LIST_HEAD(MountPoint
, dm_list_head
);
603 LIST_HEAD_INIT(dm_list_head
);
605 r
= dm_list_get(&dm_list_head
);
609 r
= dm_points_list_detach(&dm_list_head
, changed
);
612 mount_points_list_free(&dm_list_head
);