2010-10-07 16:43:57 +04:00
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd .
Copyright 2010 ProFUSION embedded systems
systemd is free software ; you can redistribute it and / or modify it
2012-04-12 02:20:58 +04:00
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation ; either version 2.1 of the License , or
2010-10-07 16:43:57 +04:00
( at your option ) any later version .
systemd is distributed in the hope that it will be useful , but
WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
2012-04-12 02:20:58 +04:00
Lesser General Public License for more details .
2010-10-07 16:43:57 +04:00
2012-04-12 02:20:58 +04:00
You should have received a copy of the GNU Lesser General Public License
2010-10-07 16:43:57 +04:00
along with systemd ; If not , see < http : //www.gnu.org/licenses/>.
* * */
# include <errno.h>
# include <fcntl.h>
# include <string.h>
# include <sys/mount.h>
# include <sys/swap.h>
# include <unistd.h>
# include <linux/loop.h>
2010-10-14 04:33:09 +04:00
# include <linux/dm-ioctl.h>
2010-10-07 16:43:57 +04:00
# include "list.h"
# include "mount-setup.h"
# include "umount.h"
2012-05-07 23:36:12 +04:00
# include "path-util.h"
2010-10-07 16:43:57 +04:00
# include "util.h"
2012-08-25 00:50:16 +04:00
# include "virt.h"
2013-10-13 04:28:21 +04:00
# include "libudev.h"
# include "udev-util.h"
2010-10-07 16:43:57 +04:00
typedef struct MountPoint {
char * path ;
2010-10-14 20:17:23 +04:00
dev_t devnum ;
2013-10-14 08:10:14 +04:00
LIST_FIELDS ( struct MountPoint , mount_point ) ;
2010-10-07 16:43:57 +04:00
} MountPoint ;
2010-10-14 20:55:04 +04:00
static void mount_point_free ( MountPoint * * head , MountPoint * m ) {
assert ( head ) ;
assert ( m ) ;
2010-10-07 16:43:57 +04:00
2013-10-14 08:10:14 +04:00
LIST_REMOVE ( mount_point , * head , m ) ;
2010-10-14 20:55:04 +04:00
free ( m - > path ) ;
free ( m ) ;
2010-10-07 16:43:57 +04:00
}
2010-10-14 20:55:04 +04:00
static void mount_points_list_free ( MountPoint * * head ) {
assert ( head ) ;
while ( * head )
mount_point_free ( head , * head ) ;
2010-10-07 16:43:57 +04:00
}
2010-10-14 20:55:04 +04:00
static int mount_points_list_get ( MountPoint * * head ) {
2010-10-07 16:43:57 +04:00
FILE * proc_self_mountinfo ;
char * path , * p ;
unsigned int i ;
int r ;
2010-10-14 20:55:04 +04:00
assert ( head ) ;
2010-10-07 16:43:57 +04:00
if ( ! ( proc_self_mountinfo = fopen ( " /proc/self/mountinfo " , " re " ) ) )
return - errno ;
for ( i = 1 ; ; i + + ) {
int k ;
2010-10-14 20:55:04 +04:00
MountPoint * m ;
2010-10-07 16:43:57 +04:00
path = p = NULL ;
if ( ( k = fscanf ( proc_self_mountinfo ,
" %*s " /* (1) mount id */
" %*s " /* (2) parent id */
" %*s " /* (3) major:minor */
2012-04-25 19:46:46 +04:00
" %*s " /* (4) root */
2010-10-07 16:43:57 +04:00
" %ms " /* (5) mount point */
" %*s " /* (6) mount options */
" %*[^-] " /* (7) optional fields */
" - " /* (8) separator */
" %*s " /* (9) file system type */
" %*s " /* (10) mount source */
" %*s " /* (11) mount options 2 */
" %*[^ \n ] " , /* some rubbish at the end */
2012-04-25 19:46:46 +04:00
& path ) ) ! = 1 ) {
2010-10-07 16:43:57 +04:00
if ( k = = EOF )
break ;
log_warning ( " Failed to parse /proc/self/mountinfo:%u. " , i ) ;
free ( path ) ;
continue ;
}
2010-10-14 02:41:57 +04:00
p = cunescape ( path ) ;
free ( path ) ;
2010-10-07 16:43:57 +04:00
2010-10-14 02:41:57 +04:00
if ( ! p ) {
2010-10-07 16:43:57 +04:00
r = - ENOMEM ;
goto finish ;
}
2012-04-12 15:34:09 +04:00
/* Ignore mount points we can't unmount because they
* are API or because we are keeping them open ( like
* / dev / console ) */
if ( mount_point_is_api ( p ) | |
mount_point_ignore ( p ) | |
2012-04-12 15:48:20 +04:00
path_equal ( p , " /dev/console " ) ) {
2010-10-14 02:41:57 +04:00
free ( p ) ;
continue ;
}
2010-10-14 20:55:04 +04:00
if ( ! ( m = new0 ( MountPoint , 1 ) ) ) {
2010-10-14 02:41:57 +04:00
free ( p ) ;
2010-10-07 16:43:57 +04:00
r = - ENOMEM ;
goto finish ;
}
2010-10-14 20:55:04 +04:00
m - > path = p ;
2013-10-14 08:10:14 +04:00
LIST_PREPEND ( mount_point , * head , m ) ;
2010-10-07 16:43:57 +04:00
}
r = 0 ;
finish :
fclose ( proc_self_mountinfo ) ;
return r ;
}
2010-10-14 20:55:04 +04:00
static int swap_list_get ( MountPoint * * head ) {
2010-10-07 16:43:57 +04:00
FILE * proc_swaps ;
unsigned int i ;
int r ;
2010-10-14 20:55:04 +04:00
assert ( head ) ;
2010-10-07 16:43:57 +04:00
if ( ! ( proc_swaps = fopen ( " /proc/swaps " , " re " ) ) )
2011-06-28 11:30:08 +04:00
return ( errno = = ENOENT ) ? 0 : - errno ;
2010-10-07 16:43:57 +04:00
( void ) fscanf ( proc_swaps , " %*s %*s %*s %*s %*s \n " ) ;
for ( i = 2 ; ; i + + ) {
MountPoint * swap ;
char * dev = NULL , * d ;
int k ;
if ( ( k = fscanf ( proc_swaps ,
" %ms " /* device/file */
" %*s " /* type of swap */
" %*s " /* swap size */
" %*s " /* used */
" %*s \n " , /* priority */
& dev ) ) ! = 1 ) {
if ( k = = EOF )
break ;
log_warning ( " Failed to parse /proc/swaps:%u. " , i ) ;
free ( dev ) ;
continue ;
}
2014-02-16 16:58:18 +04:00
if ( endswith ( dev , " (deleted) " ) ) {
2010-10-07 16:43:57 +04:00
free ( dev ) ;
continue ;
}
d = cunescape ( dev ) ;
free ( dev ) ;
if ( ! d ) {
r = - ENOMEM ;
goto finish ;
}
2010-10-14 20:17:23 +04:00
if ( ! ( swap = new0 ( MountPoint , 1 ) ) ) {
2010-10-07 16:43:57 +04:00
free ( d ) ;
r = - ENOMEM ;
goto finish ;
}
2010-10-14 20:17:23 +04:00
swap - > path = d ;
2013-10-14 08:10:14 +04:00
LIST_PREPEND ( mount_point , * head , swap ) ;
2010-10-07 16:43:57 +04:00
}
r = 0 ;
finish :
fclose ( proc_swaps ) ;
return r ;
}
2010-10-14 20:55:04 +04:00
static int loopback_list_get ( MountPoint * * head ) {
2013-10-13 04:28:21 +04:00
_cleanup_udev_enumerate_unref_ struct udev_enumerate * e = NULL ;
2010-10-07 16:43:57 +04:00
struct udev_list_entry * item = NULL , * first = NULL ;
2013-12-18 20:13:42 +04:00
_cleanup_udev_unref_ struct udev * udev = NULL ;
int r ;
2010-10-07 16:43:57 +04:00
2010-10-14 20:55:04 +04:00
assert ( head ) ;
2013-10-13 04:28:21 +04:00
udev = udev_new ( ) ;
if ( ! udev )
return - ENOMEM ;
2010-10-07 16:43:57 +04:00
2013-10-13 04:28:21 +04:00
e = udev_enumerate_new ( udev ) ;
if ( ! e )
return - ENOMEM ;
2010-10-07 16:43:57 +04:00
2013-12-18 20:13:42 +04:00
r = udev_enumerate_add_match_subsystem ( e , " block " ) ;
if ( r < 0 )
return r ;
r = udev_enumerate_add_match_sysname ( e , " loop* " ) ;
if ( r < 0 )
return r ;
r = udev_enumerate_add_match_sysattr ( e , " loop/backing_file " , NULL ) ;
if ( r < 0 )
return r ;
2010-10-07 16:43:57 +04:00
2013-12-18 20:13:42 +04:00
r = udev_enumerate_scan_devices ( e ) ;
if ( r < 0 )
return r ;
2010-10-07 16:43:57 +04:00
first = udev_enumerate_get_list_entry ( e ) ;
udev_list_entry_foreach ( item , first ) {
MountPoint * lb ;
2013-10-13 04:28:21 +04:00
_cleanup_udev_device_unref_ struct udev_device * d ;
2010-10-07 16:43:57 +04:00
char * loop ;
2010-10-14 02:42:44 +04:00
const char * dn ;
2010-10-07 16:43:57 +04:00
2013-10-13 04:28:21 +04:00
d = udev_device_new_from_syspath ( udev , udev_list_entry_get_name ( item ) ) ;
if ( ! d )
return - ENOMEM ;
2010-10-07 16:43:57 +04:00
2013-10-13 04:28:21 +04:00
dn = udev_device_get_devnode ( d ) ;
if ( ! dn )
2010-10-14 20:17:23 +04:00
continue ;
2010-10-14 02:42:44 +04:00
2010-10-14 20:17:23 +04:00
loop = strdup ( dn ) ;
2013-10-13 04:28:21 +04:00
if ( ! loop )
return - ENOMEM ;
2010-10-14 02:42:44 +04:00
2013-10-13 04:28:21 +04:00
lb = new0 ( MountPoint , 1 ) ;
if ( ! lb ) {
2010-10-07 16:43:57 +04:00
free ( loop ) ;
2013-10-13 04:28:21 +04:00
return - ENOMEM ;
2010-10-07 16:43:57 +04:00
}
2010-10-14 20:17:23 +04:00
lb - > path = loop ;
2013-10-14 08:10:14 +04:00
LIST_PREPEND ( mount_point , * head , lb ) ;
2010-10-07 16:43:57 +04:00
}
2013-10-13 04:28:21 +04:00
return 0 ;
2010-10-07 16:43:57 +04:00
}
2010-10-14 20:55:04 +04:00
static int dm_list_get ( MountPoint * * head ) {
2013-10-13 04:28:21 +04:00
_cleanup_udev_enumerate_unref_ struct udev_enumerate * e = NULL ;
2010-10-14 04:33:09 +04:00
struct udev_list_entry * item = NULL , * first = NULL ;
2013-12-18 20:13:42 +04:00
_cleanup_udev_unref_ struct udev * udev = NULL ;
int r ;
2010-10-14 04:33:09 +04:00
2010-10-14 20:55:04 +04:00
assert ( head ) ;
2013-10-13 04:28:21 +04:00
udev = udev_new ( ) ;
if ( ! udev )
return - ENOMEM ;
2010-10-14 04:33:09 +04:00
2013-10-13 04:28:21 +04:00
e = udev_enumerate_new ( udev ) ;
if ( ! e )
return - ENOMEM ;
2010-10-14 04:33:09 +04:00
2013-12-18 20:13:42 +04:00
r = udev_enumerate_add_match_subsystem ( e , " block " ) ;
if ( r < 0 )
return r ;
2010-10-14 04:33:09 +04:00
2013-12-18 20:13:42 +04:00
r = udev_enumerate_add_match_sysname ( e , " dm-* " ) ;
if ( r < 0 )
return r ;
2010-10-14 04:33:09 +04:00
2013-12-18 20:13:42 +04:00
r = udev_enumerate_scan_devices ( e ) ;
if ( r < 0 )
return r ;
2010-10-14 04:33:09 +04:00
2013-12-18 20:13:42 +04:00
first = udev_enumerate_get_list_entry ( e ) ;
2010-10-14 04:33:09 +04:00
udev_list_entry_foreach ( item , first ) {
2010-10-14 20:17:23 +04:00
MountPoint * m ;
2013-10-13 04:28:21 +04:00
_cleanup_udev_device_unref_ struct udev_device * d ;
2010-10-14 20:17:23 +04:00
dev_t devnum ;
char * node ;
const char * dn ;
2010-10-14 04:33:09 +04:00
2013-10-13 04:28:21 +04:00
d = udev_device_new_from_syspath ( udev , udev_list_entry_get_name ( item ) ) ;
if ( ! d )
return - ENOMEM ;
2010-10-14 04:33:09 +04:00
2010-10-14 20:17:23 +04:00
devnum = udev_device_get_devnum ( d ) ;
dn = udev_device_get_devnode ( d ) ;
2013-10-13 04:28:21 +04:00
if ( major ( devnum ) = = 0 | | ! dn )
2010-10-14 20:17:23 +04:00
continue ;
2010-10-14 04:33:09 +04:00
2010-10-14 20:17:23 +04:00
node = strdup ( dn ) ;
2013-10-13 04:28:21 +04:00
if ( ! node )
return - ENOMEM ;
2010-10-14 04:33:09 +04:00
2013-10-13 04:28:21 +04:00
m = new ( MountPoint , 1 ) ;
if ( ! m ) {
2010-10-14 20:17:23 +04:00
free ( node ) ;
2013-10-13 04:28:21 +04:00
return - ENOMEM ;
2010-10-14 04:33:09 +04:00
}
2010-10-14 20:17:23 +04:00
m - > path = node ;
m - > devnum = devnum ;
2013-10-14 08:10:14 +04:00
LIST_PREPEND ( mount_point , * head , m ) ;
2010-10-14 04:33:09 +04:00
}
2013-10-13 04:28:21 +04:00
return 0 ;
2010-10-14 04:33:09 +04:00
}
2010-10-07 16:43:57 +04:00
static int delete_loopback ( const char * device ) {
int fd , r ;
2010-10-14 02:43:13 +04:00
if ( ( fd = open ( device , O_RDONLY | O_CLOEXEC ) ) < 0 )
2011-03-14 07:37:47 +03:00
return errno = = ENOENT ? 0 : - errno ;
2010-10-07 16:43:57 +04:00
2010-10-14 02:43:13 +04:00
r = ioctl ( fd , LOOP_CLR_FD , 0 ) ;
2010-10-07 22:46:35 +04:00
close_nointr_nofail ( fd ) ;
2010-10-07 16:43:57 +04:00
2010-10-14 20:55:04 +04:00
if ( r > = 0 )
return 1 ;
2010-10-14 02:43:13 +04:00
/* ENXIO: not bound, so no error */
2010-10-14 20:55:04 +04:00
if ( errno = = ENXIO )
return 0 ;
return - errno ;
2010-10-07 16:43:57 +04:00
}
2010-10-14 20:17:23 +04:00
static int delete_dm ( dev_t devnum ) {
2013-04-18 11:11:22 +04:00
_cleanup_close_ int fd = - 1 ;
2013-03-25 03:45:16 +04:00
int r ;
2013-03-25 03:59:00 +04:00
struct dm_ioctl dm = {
. version = { DM_VERSION_MAJOR ,
DM_VERSION_MINOR ,
DM_VERSION_PATCHLEVEL } ,
. data_size = sizeof ( dm ) ,
. dev = devnum ,
} ;
2010-10-14 04:33:09 +04:00
2010-10-14 20:17:23 +04:00
assert ( major ( devnum ) ! = 0 ) ;
2010-10-14 04:33:09 +04:00
2013-03-25 03:45:16 +04:00
fd = open ( " /dev/mapper/control " , O_RDWR | O_CLOEXEC ) ;
if ( fd < 0 )
2010-10-14 04:33:09 +04:00
return - errno ;
r = ioctl ( fd , DM_DEV_REMOVE , & dm ) ;
return r > = 0 ? 0 : - errno ;
}
2011-05-27 12:59:45 +04:00
static int mount_points_list_umount ( MountPoint * * head , bool * changed , bool log_error ) {
2010-10-14 20:55:04 +04:00
MountPoint * m , * n ;
int n_failed = 0 ;
2010-10-07 16:43:57 +04:00
2010-10-14 20:55:04 +04:00
assert ( head ) ;
LIST_FOREACH_SAFE ( mount_point , m , n , * head ) {
2012-11-16 21:36:28 +04:00
/* If we are in a container, don't attempt to
read - only mount anything as that brings no real
benefits , but might confuse the host , as we remount
the superblock here , not the bind mound . */
if ( detect_container ( NULL ) < = 0 ) {
/* We always try to remount directories
* read - only first , before we go on and umount
* them .
*
* Mount points can be stacked . If a mount
* point is stacked below / or / usr , we
2013-04-15 06:37:54 +04:00
* cannot umount or remount it directly ,
2012-11-16 21:36:28 +04:00
* since there is no way to refer to the
* underlying mount . There ' s nothing we can do
* about it for the general case , but we can
* do something about it if it is aliased
* somehwere else via a bind mount . If we
* explicitly remount the super block of that
* alias read - only we hence should be
* relatively safe regarding keeping the fs we
* can otherwise not see dirty . */
mount ( NULL , m - > path , NULL , MS_REMOUNT | MS_RDONLY , NULL ) ;
}
/* Skip / and /usr since we cannot unmount that
2012-11-29 00:20:37 +04:00
* anyway , since we are running from it . They have
* already been remounted ro . */
2012-03-06 04:28:32 +04:00
if ( path_equal ( m - > path , " / " )
# ifndef HAVE_SPLIT_USR
| | path_equal ( m - > path , " /usr " )
# endif
2012-11-28 21:08:54 +04:00
)
2010-10-07 16:43:57 +04:00
continue ;
2013-01-16 06:51:56 +04:00
/* Trying to umount. We don't force here since we rely
* on busy NFS and FUSE file systems to return EBUSY
* until we closed everything on top of them . */
2012-12-07 20:44:50 +04:00
log_info ( " Unmounting %s. " , m - > path ) ;
2013-01-16 06:51:56 +04:00
if ( umount2 ( m - > path , 0 ) = = 0 ) {
2010-10-14 20:55:04 +04:00
if ( changed )
* changed = true ;
mount_point_free ( head , m ) ;
2011-05-27 12:59:45 +04:00
} else if ( log_error ) {
2010-10-14 20:55:04 +04:00
log_warning ( " Could not unmount %s: %m " , m - > path ) ;
n_failed + + ;
2010-10-07 16:43:57 +04:00
}
}
2010-10-14 20:55:04 +04:00
return n_failed ;
2010-10-07 16:43:57 +04:00
}
2010-10-14 20:55:04 +04:00
static int swap_points_list_off ( MountPoint * * head , bool * changed ) {
MountPoint * m , * n ;
int n_failed = 0 ;
assert ( head ) ;
2010-10-07 16:43:57 +04:00
2010-10-14 20:55:04 +04:00
LIST_FOREACH_SAFE ( mount_point , m , n , * head ) {
2012-12-07 21:02:43 +04:00
log_info ( " Deactivating swap %s. " , m - > path ) ;
2010-10-14 20:55:04 +04:00
if ( swapoff ( m - > path ) = = 0 ) {
if ( changed )
* changed = true ;
mount_point_free ( head , m ) ;
} else {
log_warning ( " Could not deactivate swap %s: %m " , m - > path ) ;
n_failed + + ;
2010-10-07 16:43:57 +04:00
}
}
2010-10-14 20:55:04 +04:00
return n_failed ;
2010-10-07 16:43:57 +04:00
}
2010-10-14 20:55:04 +04:00
static int loopback_points_list_detach ( MountPoint * * head , bool * changed ) {
MountPoint * m , * n ;
2011-01-06 21:10:17 +03:00
int n_failed = 0 , k ;
struct stat root_st ;
2010-10-14 20:55:04 +04:00
assert ( head ) ;
2011-01-06 21:10:17 +03:00
k = lstat ( " / " , & root_st ) ;
2010-10-14 20:55:04 +04:00
LIST_FOREACH_SAFE ( mount_point , m , n , * head ) {
int r ;
2011-01-06 21:10:17 +03:00
struct stat loopback_st ;
if ( k > = 0 & &
major ( root_st . st_dev ) ! = 0 & &
lstat ( m - > path , & loopback_st ) > = 0 & &
root_st . st_dev = = loopback_st . st_rdev ) {
n_failed + + ;
continue ;
}
2010-10-07 16:43:57 +04:00
2012-12-07 21:02:43 +04:00
log_info ( " Detaching loopback %s. " , m - > path ) ;
2012-12-07 20:44:50 +04:00
r = delete_loopback ( m - > path ) ;
if ( r > = 0 ) {
2010-10-14 20:55:04 +04:00
if ( r > 0 & & changed )
* changed = true ;
mount_point_free ( head , m ) ;
} else {
2012-12-07 21:02:43 +04:00
log_warning ( " Could not detach loopback %s: %m " , m - > path ) ;
2010-10-14 20:55:04 +04:00
n_failed + + ;
2010-10-07 16:43:57 +04:00
}
}
2010-10-14 20:55:04 +04:00
return n_failed ;
2010-10-07 16:43:57 +04:00
}
2010-10-14 20:55:04 +04:00
static int dm_points_list_detach ( MountPoint * * head , bool * changed ) {
MountPoint * m , * n ;
2011-01-06 21:10:17 +03:00
int n_failed = 0 , k ;
struct stat root_st ;
2010-10-14 20:55:04 +04:00
assert ( head ) ;
2011-01-06 21:10:17 +03:00
k = lstat ( " / " , & root_st ) ;
2010-10-14 20:55:04 +04:00
LIST_FOREACH_SAFE ( mount_point , m , n , * head ) {
int r ;
2011-01-06 21:10:17 +03:00
if ( k > = 0 & &
major ( root_st . st_dev ) ! = 0 & &
root_st . st_dev = = m - > devnum ) {
n_failed + + ;
continue ;
}
2012-12-07 21:02:43 +04:00
log_info ( " Detaching DM %u:%u. " , major ( m - > devnum ) , minor ( m - > devnum ) ) ;
2012-12-07 20:44:50 +04:00
r = delete_dm ( m - > devnum ) ;
if ( r > = 0 ) {
2012-12-07 20:34:21 +04:00
if ( changed )
2010-10-14 20:55:04 +04:00
* changed = true ;
2010-10-14 04:33:09 +04:00
2010-10-14 20:55:04 +04:00
mount_point_free ( head , m ) ;
} else {
2012-12-07 21:02:43 +04:00
log_warning ( " Could not detach DM %s: %m " , m - > path ) ;
2010-10-14 20:55:04 +04:00
n_failed + + ;
2010-10-14 04:33:09 +04:00
}
}
2010-10-14 20:55:04 +04:00
return n_failed ;
2010-10-14 04:33:09 +04:00
}
2010-10-14 20:55:04 +04:00
int umount_all ( bool * changed ) {
2010-10-07 16:43:57 +04:00
int r ;
2011-05-05 14:26:31 +04:00
bool umount_changed ;
2010-10-07 16:43:57 +04:00
LIST_HEAD ( MountPoint , mp_list_head ) ;
2013-10-14 08:10:14 +04:00
LIST_HEAD_INIT ( mp_list_head ) ;
2010-10-07 16:43:57 +04:00
r = mount_points_list_get ( & mp_list_head ) ;
if ( r < 0 )
goto end ;
2011-05-05 14:26:31 +04:00
/* retry umount, until nothing can be umounted anymore */
do {
umount_changed = false ;
2011-09-23 04:39:54 +04:00
mount_points_list_umount ( & mp_list_head , & umount_changed , false ) ;
2011-05-05 14:26:31 +04:00
if ( umount_changed )
* changed = true ;
2011-09-23 04:39:54 +04:00
} while ( umount_changed ) ;
2011-05-27 12:59:45 +04:00
/* umount one more time with logging enabled */
r = mount_points_list_umount ( & mp_list_head , & umount_changed , true ) ;
2010-10-07 16:43:57 +04:00
if ( r < = 0 )
goto end ;
end :
mount_points_list_free ( & mp_list_head ) ;
return r ;
}
2010-10-14 20:55:04 +04:00
int swapoff_all ( bool * changed ) {
2010-10-07 16:43:57 +04:00
int r ;
LIST_HEAD ( MountPoint , swap_list_head ) ;
2013-10-14 08:10:14 +04:00
LIST_HEAD_INIT ( swap_list_head ) ;
2010-10-07 16:43:57 +04:00
r = swap_list_get ( & swap_list_head ) ;
if ( r < 0 )
goto end ;
2010-10-14 20:55:04 +04:00
r = swap_points_list_off ( & swap_list_head , changed ) ;
2010-10-07 16:43:57 +04:00
end :
mount_points_list_free ( & swap_list_head ) ;
return r ;
}
2010-10-14 20:55:04 +04:00
int loopback_detach_all ( bool * changed ) {
2010-10-07 16:43:57 +04:00
int r ;
LIST_HEAD ( MountPoint , loopback_list_head ) ;
2013-10-14 08:10:14 +04:00
LIST_HEAD_INIT ( loopback_list_head ) ;
2010-10-07 16:43:57 +04:00
r = loopback_list_get ( & loopback_list_head ) ;
if ( r < 0 )
goto end ;
2010-10-14 20:55:04 +04:00
r = loopback_points_list_detach ( & loopback_list_head , changed ) ;
2010-10-07 16:43:57 +04:00
end :
mount_points_list_free ( & loopback_list_head ) ;
return r ;
}
2010-10-14 04:33:09 +04:00
2010-10-14 20:55:04 +04:00
int dm_detach_all ( bool * changed ) {
2010-10-14 04:33:09 +04:00
int r ;
LIST_HEAD ( MountPoint , dm_list_head ) ;
2013-10-14 08:10:14 +04:00
LIST_HEAD_INIT ( dm_list_head ) ;
2010-10-14 04:33:09 +04:00
r = dm_list_get ( & dm_list_head ) ;
if ( r < 0 )
goto end ;
2010-10-14 20:55:04 +04:00
r = dm_points_list_detach ( & dm_list_head , changed ) ;
2010-10-14 04:33:09 +04:00
end :
mount_points_list_free ( & dm_list_head ) ;
return r ;
}