2010-08-14 21:59:25 +04:00
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2010-01-23 03:52:57 +03:00
2010-02-03 15:03:47 +03:00
/***
This file is part of systemd .
Copyright 2010 Lennart Poettering
systemd is free software ; you can redistribute it and / or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( 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
General Public License for more details .
You should have received a copy of the GNU General Public License
along with systemd ; If not , see < http : //www.gnu.org/licenses/>.
* * */
2010-01-23 03:52:57 +03:00
# include <errno.h>
2010-01-29 04:07:41 +03:00
# include <stdio.h>
# include <mntent.h>
2010-01-29 08:04:08 +03:00
# include <sys/epoll.h>
2010-04-10 19:53:17 +04:00
# include <signal.h>
2010-01-23 03:52:57 +03:00
2010-01-26 23:39:06 +03:00
# include "unit.h"
2010-01-23 03:52:57 +03:00
# include "mount.h"
# include "load-fragment.h"
# include "load-dropin.h"
2010-01-29 04:07:41 +03:00
# include "log.h"
2010-04-10 19:53:17 +04:00
# include "strv.h"
# include "mount-setup.h"
2010-04-15 05:11:11 +04:00
# include "unit-name.h"
2010-04-18 05:08:16 +04:00
# include "dbus-mount.h"
2010-06-18 06:22:59 +04:00
# include "special.h"
2010-10-22 18:11:50 +04:00
# include "bus-errors.h"
2011-01-20 20:22:03 +03:00
# include "exit-status.h"
2011-03-17 06:02:35 +03:00
# include "def.h"
2010-01-23 03:52:57 +03:00
2010-01-29 05:18:09 +03:00
static const UnitActiveState state_translation_table [ _MOUNT_STATE_MAX ] = {
[ MOUNT_DEAD ] = UNIT_INACTIVE ,
[ MOUNT_MOUNTING ] = UNIT_ACTIVATING ,
2010-04-10 19:53:17 +04:00
[ MOUNT_MOUNTING_DONE ] = UNIT_ACTIVE ,
2010-01-29 05:18:09 +03:00
[ MOUNT_MOUNTED ] = UNIT_ACTIVE ,
2010-07-01 05:34:15 +04:00
[ MOUNT_REMOUNTING ] = UNIT_RELOADING ,
2010-01-29 05:18:09 +03:00
[ MOUNT_UNMOUNTING ] = UNIT_DEACTIVATING ,
2010-04-10 19:53:17 +04:00
[ MOUNT_MOUNTING_SIGTERM ] = UNIT_DEACTIVATING ,
[ MOUNT_MOUNTING_SIGKILL ] = UNIT_DEACTIVATING ,
2010-07-01 05:34:15 +04:00
[ MOUNT_REMOUNTING_SIGTERM ] = UNIT_RELOADING ,
[ MOUNT_REMOUNTING_SIGKILL ] = UNIT_RELOADING ,
2010-04-10 19:53:17 +04:00
[ MOUNT_UNMOUNTING_SIGTERM ] = UNIT_DEACTIVATING ,
[ MOUNT_UNMOUNTING_SIGKILL ] = UNIT_DEACTIVATING ,
2010-08-31 02:23:34 +04:00
[ MOUNT_FAILED ] = UNIT_FAILED
2010-01-29 05:18:09 +03:00
} ;
2010-01-23 03:52:57 +03:00
2010-04-21 05:27:44 +04:00
static void mount_init ( Unit * u ) {
Mount * m = MOUNT ( u ) ;
2010-01-23 03:52:57 +03:00
2010-04-21 05:27:44 +04:00
assert ( u ) ;
assert ( u - > meta . load_state = = UNIT_STUB ) ;
m - > timeout_usec = DEFAULT_TIMEOUT_USEC ;
2010-07-02 02:28:44 +04:00
m - > directory_mode = 0755 ;
2010-07-08 07:22:34 +04:00
exec_context_init ( & m - > exec_context ) ;
2011-04-13 06:34:35 +04:00
/* The stdio/kmsg bridge socket is on /, in order to avoid a
* dep loop , don ' t use kmsg logging for - . mount */
2011-11-19 05:47:09 +04:00
if ( ! unit_has_name ( u , " -.mount " ) ) {
m - > exec_context . std_output = u - > meta . manager - > default_std_output ;
m - > exec_context . std_error = u - > meta . manager - > default_std_error ;
}
2010-07-08 07:22:34 +04:00
2010-04-21 05:27:44 +04:00
/* We need to make sure that /bin/mount is always called in
* the same process group as us , so that the autofs kernel
* side doesn ' t send us another mount request while we are
* already trying to comply its last one . */
2010-07-05 03:08:13 +04:00
m - > exec_context . same_pgrp = true ;
2010-04-17 01:24:39 +04:00
2010-04-21 05:27:44 +04:00
m - > timer_watch . type = WATCH_INVALID ;
m - > control_command_id = _MOUNT_EXEC_COMMAND_INVALID ;
2011-04-14 05:55:03 +04:00
m - > meta . ignore_on_isolate = true ;
2010-04-17 01:24:39 +04:00
}
2010-04-21 05:27:44 +04:00
static void mount_unwatch_control_pid ( Mount * m ) {
2010-04-11 02:22:36 +04:00
assert ( m ) ;
if ( m - > control_pid < = 0 )
return ;
unit_unwatch_pid ( UNIT ( m ) , m - > control_pid ) ;
m - > control_pid = 0 ;
}
2010-04-10 19:53:17 +04:00
static void mount_parameters_done ( MountParameters * p ) {
assert ( p ) ;
free ( p - > what ) ;
free ( p - > options ) ;
free ( p - > fstype ) ;
p - > what = p - > options = p - > fstype = NULL ;
}
2010-01-26 23:39:06 +03:00
static void mount_done ( Unit * u ) {
2010-01-29 08:04:08 +03:00
Mount * m = MOUNT ( u ) ;
2010-01-26 06:18:44 +03:00
2010-01-29 08:04:08 +03:00
assert ( m ) ;
2010-01-26 06:18:44 +03:00
2010-04-10 19:53:17 +04:00
free ( m - > where ) ;
m - > where = NULL ;
2010-01-29 05:18:09 +03:00
2010-04-10 19:53:17 +04:00
mount_parameters_done ( & m - > parameters_etc_fstab ) ;
mount_parameters_done ( & m - > parameters_proc_self_mountinfo ) ;
mount_parameters_done ( & m - > parameters_fragment ) ;
2010-01-29 08:04:08 +03:00
2010-04-10 19:53:17 +04:00
exec_context_done ( & m - > exec_context ) ;
exec_command_done_array ( m - > exec_command , _MOUNT_EXEC_COMMAND_MAX ) ;
m - > control_command = NULL ;
2010-01-29 05:18:09 +03:00
2010-04-21 05:27:44 +04:00
mount_unwatch_control_pid ( m ) ;
2010-01-29 05:18:09 +03:00
2010-04-10 19:53:17 +04:00
unit_unwatch_timer ( u , & m - > timer_watch ) ;
2010-01-29 05:18:09 +03:00
}
2011-03-30 03:53:34 +04:00
static MountParameters * get_mount_parameters_configured ( Mount * m ) {
assert ( m ) ;
if ( m - > from_fragment )
return & m - > parameters_fragment ;
else if ( m - > from_etc_fstab )
return & m - > parameters_etc_fstab ;
return NULL ;
}
static MountParameters * get_mount_parameters ( Mount * m ) {
assert ( m ) ;
if ( m - > from_proc_self_mountinfo )
return & m - > parameters_proc_self_mountinfo ;
return get_mount_parameters_configured ( m ) ;
}
2010-05-13 05:07:16 +04:00
static int mount_add_mount_links ( Mount * m ) {
Meta * other ;
2010-01-29 04:07:41 +03:00
int r ;
2010-09-28 03:03:19 +04:00
MountParameters * pm ;
2010-01-29 04:07:41 +03:00
2010-05-13 05:07:16 +04:00
assert ( m ) ;
2010-01-29 04:07:41 +03:00
2011-03-30 03:53:34 +04:00
pm = get_mount_parameters_configured ( m ) ;
2010-09-28 03:03:19 +04:00
2010-05-13 05:07:16 +04:00
/* Adds in links to other mount points that might lie below or
* above us in the hierarchy */
2010-04-10 19:53:17 +04:00
2011-05-24 01:53:43 +04:00
LIST_FOREACH ( units_by_type , other , m - > meta . manager - > units_by_type [ UNIT_MOUNT ] ) {
2010-05-13 05:07:16 +04:00
Mount * n = ( Mount * ) other ;
2010-09-28 03:03:19 +04:00
MountParameters * pn ;
2010-05-09 20:44:11 +04:00
2010-05-13 05:07:16 +04:00
if ( n = = m )
continue ;
2010-01-29 04:07:41 +03:00
2010-05-13 05:07:16 +04:00
if ( n - > meta . load_state ! = UNIT_LOADED )
continue ;
2010-01-29 04:07:41 +03:00
2011-03-30 03:53:34 +04:00
pn = get_mount_parameters_configured ( n ) ;
2010-09-28 03:03:19 +04:00
2010-05-13 05:07:16 +04:00
if ( path_startswith ( m - > where , n - > where ) ) {
2010-01-29 04:07:41 +03:00
2010-05-13 05:07:16 +04:00
if ( ( r = unit_add_dependency ( UNIT ( m ) , UNIT_AFTER , UNIT ( n ) , true ) ) < 0 )
return r ;
2010-01-29 04:07:41 +03:00
2011-03-30 03:53:34 +04:00
if ( pn )
2010-05-13 05:07:16 +04:00
if ( ( r = unit_add_dependency ( UNIT ( m ) , UNIT_REQUIRES , UNIT ( n ) , true ) ) < 0 )
return r ;
2010-01-29 04:07:41 +03:00
2010-05-13 05:07:16 +04:00
} else if ( path_startswith ( n - > where , m - > where ) ) {
2010-01-29 04:07:41 +03:00
2010-09-28 03:03:19 +04:00
if ( ( r = unit_add_dependency ( UNIT ( n ) , UNIT_AFTER , UNIT ( m ) , true ) ) < 0 )
return r ;
2011-03-30 03:53:34 +04:00
if ( pm )
2010-09-28 03:03:19 +04:00
if ( ( r = unit_add_dependency ( UNIT ( n ) , UNIT_REQUIRES , UNIT ( m ) , true ) ) < 0 )
return r ;
} else if ( pm & & path_startswith ( pm - > what , n - > where ) ) {
if ( ( r = unit_add_dependency ( UNIT ( m ) , UNIT_AFTER , UNIT ( n ) , true ) ) < 0 )
2010-05-13 05:07:16 +04:00
return r ;
2011-03-30 03:53:34 +04:00
if ( ( r = unit_add_dependency ( UNIT ( m ) , UNIT_REQUIRES , UNIT ( n ) , true ) ) < 0 )
return r ;
2010-09-28 03:03:19 +04:00
} else if ( pn & & path_startswith ( pn - > what , m - > where ) ) {
if ( ( r = unit_add_dependency ( UNIT ( n ) , UNIT_AFTER , UNIT ( m ) , true ) ) < 0 )
return r ;
2011-03-30 03:53:34 +04:00
if ( ( r = unit_add_dependency ( UNIT ( n ) , UNIT_REQUIRES , UNIT ( m ) , true ) ) < 0 )
return r ;
2010-05-13 05:07:16 +04:00
}
}
2010-01-29 04:07:41 +03:00
return 0 ;
}
2010-05-13 05:07:16 +04:00
static int mount_add_swap_links ( Mount * m ) {
2010-01-29 08:04:08 +03:00
Meta * other ;
2010-01-29 04:07:41 +03:00
int r ;
2010-05-13 05:07:16 +04:00
assert ( m ) ;
2010-01-29 04:07:41 +03:00
2011-05-24 01:53:43 +04:00
LIST_FOREACH ( units_by_type , other , m - > meta . manager - > units_by_type [ UNIT_SWAP ] )
2010-05-13 05:07:16 +04:00
if ( ( r = swap_add_one_mount_link ( ( Swap * ) other , m ) ) < 0 )
return r ;
2010-01-29 04:07:41 +03:00
2010-05-13 05:07:16 +04:00
return 0 ;
}
2010-01-29 04:07:41 +03:00
2010-05-24 07:25:33 +04:00
static int mount_add_path_links ( Mount * m ) {
Meta * other ;
int r ;
assert ( m ) ;
2011-05-24 01:53:43 +04:00
LIST_FOREACH ( units_by_type , other , m - > meta . manager - > units_by_type [ UNIT_PATH ] )
2010-05-24 07:25:33 +04:00
if ( ( r = path_add_one_mount_link ( ( Path * ) other , m ) ) < 0 )
return r ;
return 0 ;
}
2010-05-13 05:07:16 +04:00
static int mount_add_automount_links ( Mount * m ) {
Meta * other ;
int r ;
2010-04-10 19:53:17 +04:00
2010-05-13 05:07:16 +04:00
assert ( m ) ;
2010-01-29 04:07:41 +03:00
2011-05-24 01:53:43 +04:00
LIST_FOREACH ( units_by_type , other , m - > meta . manager - > units_by_type [ UNIT_AUTOMOUNT ] )
2010-05-13 05:07:16 +04:00
if ( ( r = automount_add_one_mount_link ( ( Automount * ) other , m ) ) < 0 )
return r ;
2010-01-29 04:07:41 +03:00
2010-05-13 05:07:16 +04:00
return 0 ;
}
2010-01-29 04:07:41 +03:00
2010-05-13 05:07:16 +04:00
static int mount_add_socket_links ( Mount * m ) {
Meta * other ;
int r ;
2010-01-29 04:07:41 +03:00
2010-05-13 05:07:16 +04:00
assert ( m ) ;
2010-01-29 04:07:41 +03:00
2011-05-24 01:53:43 +04:00
LIST_FOREACH ( units_by_type , other , m - > meta . manager - > units_by_type [ UNIT_SOCKET ] )
2010-05-13 05:07:16 +04:00
if ( ( r = socket_add_one_mount_link ( ( Socket * ) other , m ) ) < 0 )
return r ;
2010-01-29 04:07:41 +03:00
return 0 ;
}
2010-05-09 20:44:11 +04:00
static char * mount_test_option ( const char * haystack , const char * needle ) {
2010-04-10 19:53:17 +04:00
struct mntent me ;
assert ( needle ) ;
/* Like glibc's hasmntopt(), but works on a string, not a
* struct mntent */
if ( ! haystack )
return false ;
zero ( me ) ;
me . mnt_opts = ( char * ) haystack ;
2010-05-09 20:44:11 +04:00
return hasmntopt ( & me , needle ) ;
2010-04-10 19:53:17 +04:00
}
2011-03-30 03:53:34 +04:00
static bool mount_is_network ( MountParameters * p ) {
assert ( p ) ;
if ( mount_test_option ( p - > options , " _netdev " ) )
return true ;
if ( p - > fstype & & fstype_is_network ( p - > fstype ) )
return true ;
return false ;
}
static bool mount_is_bind ( MountParameters * p ) {
assert ( p ) ;
if ( mount_test_option ( p - > options , " bind " ) )
return true ;
if ( p - > fstype & & streq ( p - > fstype , " bind " ) )
return true ;
return false ;
}
static bool needs_quota ( MountParameters * p ) {
assert ( p ) ;
if ( mount_is_network ( p ) )
return false ;
if ( mount_is_bind ( p ) )
return false ;
return mount_test_option ( p - > options , " usrquota " ) | |
2011-09-21 22:19:43 +04:00
mount_test_option ( p - > options , " grpquota " ) | |
mount_test_option ( p - > options , " quota " ) | |
mount_test_option ( p - > options , " usrjquota " ) | |
mount_test_option ( p - > options , " grpjquota " ) ;
2011-03-30 03:53:34 +04:00
}
2011-04-20 02:45:22 +04:00
static int mount_add_fstab_links ( Mount * m ) {
2011-11-02 01:27:48 +04:00
const char * target , * after = NULL , * after2 = NULL ;
2010-04-10 19:53:17 +04:00
MountParameters * p ;
2010-04-21 05:27:44 +04:00
Unit * tu ;
2010-04-10 19:53:17 +04:00
int r ;
2010-10-29 08:05:02 +04:00
bool noauto , nofail , handle , automount ;
2010-04-10 19:53:17 +04:00
assert ( m ) ;
2011-04-20 02:45:22 +04:00
if ( m - > meta . manager - > running_as ! = MANAGER_SYSTEM )
return 0 ;
2011-03-30 03:53:34 +04:00
if ( ! ( p = get_mount_parameters_configured ( m ) ) )
2010-04-10 19:53:17 +04:00
return 0 ;
2011-04-20 02:45:22 +04:00
if ( p ! = & m - > parameters_etc_fstab )
return 0 ;
noauto = ! ! mount_test_option ( p - > options , " noauto " ) ;
2010-10-29 08:05:02 +04:00
nofail = ! ! mount_test_option ( p - > options , " nofail " ) ;
2011-04-20 02:45:22 +04:00
automount =
mount_test_option ( p - > options , " comment=systemd.automount " ) | |
mount_test_option ( p - > options , " x-systemd-automount " ) ;
2011-03-08 05:08:15 +03:00
handle =
2011-04-20 02:45:22 +04:00
automount | |
2011-03-08 05:08:15 +03:00
mount_test_option ( p - > options , " comment=systemd.mount " ) | |
mount_test_option ( p - > options , " x-systemd-mount " ) | |
2010-08-25 05:11:26 +04:00
m - > meta . manager - > mount_auto ;
2010-04-10 19:53:17 +04:00
2011-03-30 03:53:34 +04:00
if ( mount_is_network ( p ) ) {
2010-04-10 19:53:17 +04:00
target = SPECIAL_REMOTE_FS_TARGET ;
2011-10-11 05:33:53 +04:00
after = SPECIAL_REMOTE_FS_PRE_TARGET ;
2011-11-02 01:27:48 +04:00
after2 = SPECIAL_NETWORK_TARGET ;
2011-10-11 05:33:53 +04:00
} else {
2010-04-10 19:53:17 +04:00
target = SPECIAL_LOCAL_FS_TARGET ;
2011-10-11 05:33:53 +04:00
after = SPECIAL_LOCAL_FS_PRE_TARGET ;
}
2010-04-10 19:53:17 +04:00
2010-07-08 04:43:18 +04:00
if ( ( r = manager_load_unit ( m - > meta . manager , target , NULL , NULL , & tu ) ) < 0 )
2010-04-10 19:53:17 +04:00
return r ;
2010-10-05 21:49:38 +04:00
if ( after )
2011-02-21 15:32:18 +03:00
if ( ( r = unit_add_dependency_by_name ( UNIT ( m ) , UNIT_AFTER , after , NULL , true ) ) < 0 )
2010-10-05 21:49:38 +04:00
return r ;
2011-11-02 01:27:48 +04:00
if ( after2 )
if ( ( r = unit_add_dependency_by_name ( UNIT ( m ) , UNIT_AFTER , after2 , NULL , true ) ) < 0 )
return r ;
2011-04-20 02:45:22 +04:00
if ( automount ) {
2010-04-21 05:27:44 +04:00
Unit * am ;
if ( ( r = unit_load_related_unit ( UNIT ( m ) , " .automount " , & am ) ) < 0 )
2010-04-13 23:55:34 +04:00
return r ;
2010-04-10 19:53:17 +04:00
2011-04-20 02:45:22 +04:00
/* If auto is configured as well also pull in the
* mount right - away , but don ' t rely on it . */
if ( ! noauto ) /* automount + auto */
if ( ( r = unit_add_dependency ( tu , UNIT_WANTS , UNIT ( m ) , true ) ) < 0 )
return r ;
/* Install automount unit */
if ( ! nofail ) /* automount + fail */
return unit_add_two_dependencies ( tu , UNIT_AFTER , UNIT_REQUIRES , UNIT ( am ) , true ) ;
else /* automount + nofail */
return unit_add_two_dependencies ( tu , UNIT_AFTER , UNIT_WANTS , UNIT ( am ) , true ) ;
} else if ( handle & & ! noauto ) {
2010-04-21 05:27:44 +04:00
2010-08-25 23:24:21 +04:00
/* Automatically add mount points that aren't natively
* configured to local - fs . target */
2010-04-21 05:27:44 +04:00
2011-04-20 02:45:22 +04:00
if ( ! nofail ) /* auto + fail */
return unit_add_two_dependencies ( tu , UNIT_AFTER , UNIT_REQUIRES , UNIT ( m ) , true ) ;
else /* auto + nofail */
return unit_add_dependency ( tu , UNIT_WANTS , UNIT ( m ) , true ) ;
2010-04-21 05:27:44 +04:00
}
2011-04-20 02:45:22 +04:00
return 0 ;
2010-04-10 19:53:17 +04:00
}
2010-08-25 22:37:04 +04:00
static int mount_add_device_links ( Mount * m ) {
MountParameters * p ;
2010-10-13 05:57:04 +04:00
int r ;
2010-08-25 22:37:04 +04:00
assert ( m ) ;
2011-03-30 03:53:34 +04:00
if ( ! ( p = get_mount_parameters_configured ( m ) ) )
2010-08-25 22:37:04 +04:00
return 0 ;
2010-10-13 05:57:04 +04:00
if ( ! p - > what )
2010-08-25 22:37:04 +04:00
return 0 ;
2010-09-28 03:03:19 +04:00
2011-04-20 02:45:22 +04:00
if ( ! mount_is_bind ( p ) & &
! path_equal ( m - > where , " / " ) & &
p = = & m - > parameters_etc_fstab ) {
2010-10-13 05:57:04 +04:00
bool nofail , noauto ;
2010-08-25 22:37:04 +04:00
2011-04-20 02:45:22 +04:00
noauto = ! ! mount_test_option ( p - > options , " noauto " ) ;
2010-10-13 05:57:04 +04:00
nofail = ! ! mount_test_option ( p - > options , " nofail " ) ;
if ( ( r = unit_add_node_link ( UNIT ( m ) , p - > what ,
! noauto & & nofail & &
UNIT ( m ) - > meta . manager - > running_as = = MANAGER_SYSTEM ) ) < 0 )
return r ;
}
2010-10-13 19:18:25 +04:00
if ( p - > passno > 0 & &
2011-01-21 03:28:30 +03:00
! mount_is_bind ( p ) & &
2010-10-20 16:26:46 +04:00
UNIT ( m ) - > meta . manager - > running_as = = MANAGER_SYSTEM & &
! path_equal ( m - > where , " / " ) ) {
2010-10-13 05:57:04 +04:00
char * name ;
Unit * fsck ;
/* Let's add in the fsck service */
2010-08-25 22:37:04 +04:00
2010-10-20 01:45:18 +04:00
/* aka SPECIAL_FSCK_SERVICE */
2010-10-13 05:57:04 +04:00
if ( ! ( name = unit_name_from_path_instance ( " fsck " , p - > what , " .service " ) ) )
return - ENOMEM ;
if ( ( r = manager_load_unit_prepare ( m - > meta . manager , name , NULL , NULL , & fsck ) ) < 0 ) {
log_warning ( " Failed to prepare unit %s: %s " , name , strerror ( - r ) ) ;
free ( name ) ;
return r ;
}
free ( name ) ;
SERVICE ( fsck ) - > fsck_passno = p - > passno ;
2010-10-20 17:21:05 +04:00
if ( ( r = unit_add_two_dependencies ( UNIT ( m ) , UNIT_AFTER , UNIT_REQUIRES , fsck , true ) ) < 0 )
2010-10-13 05:57:04 +04:00
return r ;
}
return 0 ;
2010-08-25 22:37:04 +04:00
}
2010-07-13 00:55:27 +04:00
static int mount_add_default_dependencies ( Mount * m ) {
int r ;
2012-01-14 02:55:28 +04:00
MountParameters * p ;
2010-07-13 00:55:27 +04:00
assert ( m ) ;
2012-01-14 02:55:28 +04:00
if ( m - > meta . manager - > running_as ! = MANAGER_SYSTEM )
return 0 ;
2011-03-30 03:53:34 +04:00
2012-01-14 02:55:28 +04:00
p = get_mount_parameters_configured ( m ) ;
if ( p & & needs_quota ( p ) ) {
if ( ( r = unit_add_two_dependencies_by_name ( UNIT ( m ) , UNIT_BEFORE , UNIT_WANTS , SPECIAL_QUOTACHECK_SERVICE , NULL , true ) ) < 0 | |
( r = unit_add_two_dependencies_by_name ( UNIT ( m ) , UNIT_BEFORE , UNIT_WANTS , SPECIAL_QUOTAON_SERVICE , NULL , true ) ) < 0 )
return r ;
}
2010-07-13 00:55:27 +04:00
2012-01-14 02:55:28 +04:00
if ( ! path_equal ( m - > where , " / " ) )
2010-10-29 03:15:18 +04:00
if ( ( r = unit_add_two_dependencies_by_name ( UNIT ( m ) , UNIT_BEFORE , UNIT_CONFLICTS , SPECIAL_UMOUNT_TARGET , NULL , true ) ) < 0 )
2010-08-06 04:23:45 +04:00
return r ;
2010-07-13 00:55:27 +04:00
return 0 ;
}
2011-04-20 00:09:34 +04:00
static int mount_fix_timeouts ( Mount * m ) {
2011-04-16 06:39:50 +04:00
MountParameters * p ;
const char * timeout = NULL ;
Unit * other ;
Iterator i ;
usec_t u ;
2011-04-20 00:09:34 +04:00
char * t ;
int r ;
2011-04-16 06:39:50 +04:00
assert ( m ) ;
if ( ! ( p = get_mount_parameters_configured ( m ) ) )
2011-04-20 00:09:34 +04:00
return 0 ;
2011-04-16 06:39:50 +04:00
/* Allow configuration how long we wait for a device that
* backs a mount point to show up . This is useful to support
* endless device timeouts for devices that show up only after
* user input , like crypto devices . */
if ( ( timeout = mount_test_option ( p - > options , " comment=systemd.device-timeout " ) ) )
timeout + = 31 ;
else if ( ( timeout = mount_test_option ( p - > options , " x-systemd-device-timeout " ) ) )
timeout + = 25 ;
else
2011-04-20 00:09:34 +04:00
return 0 ;
t = strndup ( timeout , strcspn ( timeout , " ,; " WHITESPACE ) ) ;
if ( ! t )
return - ENOMEM ;
2011-04-16 06:39:50 +04:00
2011-04-20 00:09:34 +04:00
r = parse_usec ( t , & u ) ;
free ( t ) ;
if ( r < 0 ) {
2011-04-16 06:39:50 +04:00
log_warning ( " Failed to parse timeout for %s, ignoring: %s " , m - > where , timeout ) ;
2011-04-20 00:09:34 +04:00
return r ;
2011-04-16 06:39:50 +04:00
}
SET_FOREACH ( other , m - > meta . dependencies [ UNIT_AFTER ] , i ) {
if ( other - > meta . type ! = UNIT_DEVICE )
continue ;
other - > meta . job_timeout = u ;
}
2011-04-20 00:09:34 +04:00
return 0 ;
2011-04-16 06:39:50 +04:00
}
2010-04-17 01:24:39 +04:00
static int mount_verify ( Mount * m ) {
bool b ;
char * e ;
assert ( m ) ;
2010-05-21 05:32:21 +04:00
if ( m - > meta . load_state ! = UNIT_LOADED )
2010-04-17 01:24:39 +04:00
return 0 ;
2010-05-21 05:32:21 +04:00
if ( ! m - > from_etc_fstab & & ! m - > from_fragment & & ! m - > from_proc_self_mountinfo )
return - ENOENT ;
2010-04-21 05:27:44 +04:00
if ( ! ( e = unit_name_from_path ( m - > where , " .mount " ) ) )
2010-04-17 01:24:39 +04:00
return - ENOMEM ;
b = unit_has_name ( UNIT ( m ) , e ) ;
free ( e ) ;
if ( ! b ) {
2010-06-19 18:55:49 +04:00
log_error ( " %s's Where setting doesn't match unit name. Refusing. " , m - > meta . id ) ;
2010-04-17 01:24:39 +04:00
return - EINVAL ;
}
2011-04-06 01:39:21 +04:00
if ( mount_point_is_api ( m - > where ) | | mount_point_ignore ( m - > where ) ) {
log_error ( " Cannot create mount unit for API file system %s. Refusing. " , m - > where ) ;
return - EINVAL ;
}
2010-05-14 04:29:45 +04:00
if ( m - > meta . fragment_path & & ! m - > parameters_fragment . what ) {
2010-06-19 18:55:49 +04:00
log_error ( " %s's What setting is missing. Refusing. " , m - > meta . id ) ;
2010-05-14 04:29:45 +04:00
return - EBADMSG ;
}
2010-07-10 06:49:37 +04:00
if ( m - > exec_context . pam_name & & m - > exec_context . kill_mode ! = KILL_CONTROL_GROUP ) {
2010-06-19 18:57:54 +04:00
log_error ( " %s has PAM enabled. Kill mode must be set to 'control-group'. Refusing. " , m - > meta . id ) ;
return - EINVAL ;
}
2010-04-17 01:24:39 +04:00
return 0 ;
}
2010-04-10 19:53:17 +04:00
static int mount_load ( Unit * u ) {
Mount * m = MOUNT ( u ) ;
int r ;
assert ( u ) ;
assert ( u - > meta . load_state = = UNIT_STUB ) ;
if ( ( r = unit_load_fragment_and_dropin_optional ( u ) ) < 0 )
return r ;
/* This is a new unit? Then let's add in some extras */
if ( u - > meta . load_state = = UNIT_LOADED ) {
2011-02-15 14:28:26 +03:00
if ( ( r = unit_add_exec_dependencies ( u , & m - > exec_context ) ) < 0 )
return r ;
2010-05-14 04:29:45 +04:00
if ( m - > meta . fragment_path )
m - > from_fragment = true ;
2010-04-10 19:53:17 +04:00
2010-04-21 05:27:44 +04:00
if ( ! m - > where )
if ( ! ( m - > where = unit_name_to_path ( u - > meta . id ) ) )
return - ENOMEM ;
path_kill_slashes ( m - > where ) ;
2010-05-14 04:29:45 +04:00
if ( ! m - > meta . description )
if ( ( r = unit_set_description ( u , m - > where ) ) < 0 )
return r ;
2010-04-10 19:53:17 +04:00
2010-08-25 22:37:04 +04:00
if ( ( r = mount_add_device_links ( m ) ) < 0 )
return r ;
2010-05-13 05:07:16 +04:00
if ( ( r = mount_add_mount_links ( m ) ) < 0 )
return r ;
if ( ( r = mount_add_socket_links ( m ) ) < 0 )
return r ;
if ( ( r = mount_add_swap_links ( m ) ) < 0 )
2010-04-10 19:53:17 +04:00
return r ;
2010-05-24 07:25:33 +04:00
if ( ( r = mount_add_path_links ( m ) ) < 0 )
return r ;
2010-05-13 05:07:16 +04:00
if ( ( r = mount_add_automount_links ( m ) ) < 0 )
2010-04-10 19:53:17 +04:00
return r ;
2011-04-20 02:45:22 +04:00
if ( ( r = mount_add_fstab_links ( m ) ) < 0 )
2010-04-10 19:53:17 +04:00
return r ;
2010-07-10 04:41:06 +04:00
2010-07-13 00:55:27 +04:00
if ( m - > meta . default_dependencies )
if ( ( r = mount_add_default_dependencies ( m ) ) < 0 )
2010-07-10 04:41:06 +04:00
return r ;
2011-04-16 06:39:50 +04:00
2011-04-20 02:45:22 +04:00
if ( ( r = unit_add_default_cgroups ( u ) ) < 0 )
return r ;
2011-04-16 06:39:50 +04:00
mount_fix_timeouts ( m ) ;
2010-04-10 19:53:17 +04:00
}
2010-04-17 01:24:39 +04:00
return mount_verify ( m ) ;
2010-04-10 19:53:17 +04:00
}
2010-04-21 05:27:44 +04:00
static int mount_notify_automount ( Mount * m , int status ) {
Unit * p ;
int r ;
2012-01-07 02:08:54 +04:00
Iterator i ;
2010-04-21 05:27:44 +04:00
assert ( m ) ;
2012-01-07 02:08:54 +04:00
SET_FOREACH ( p , m - > meta . dependencies [ UNIT_TRIGGERED_BY ] , i )
if ( p - > meta . type = = UNIT_AUTOMOUNT ) {
r = automount_send_ready ( AUTOMOUNT ( p ) , status ) ;
if ( r < 0 )
return r ;
}
2010-04-21 05:27:44 +04:00
2012-01-07 02:08:54 +04:00
return 0 ;
2010-04-21 05:27:44 +04:00
}
2010-04-10 19:53:17 +04:00
static void mount_set_state ( Mount * m , MountState state ) {
MountState old_state ;
assert ( m ) ;
old_state = m - > state ;
m - > state = state ;
if ( state ! = MOUNT_MOUNTING & &
state ! = MOUNT_MOUNTING_DONE & &
state ! = MOUNT_REMOUNTING & &
state ! = MOUNT_UNMOUNTING & &
state ! = MOUNT_MOUNTING_SIGTERM & &
state ! = MOUNT_MOUNTING_SIGKILL & &
state ! = MOUNT_UNMOUNTING_SIGTERM & &
state ! = MOUNT_UNMOUNTING_SIGKILL & &
state ! = MOUNT_REMOUNTING_SIGTERM & &
state ! = MOUNT_REMOUNTING_SIGKILL ) {
unit_unwatch_timer ( UNIT ( m ) , & m - > timer_watch ) ;
2010-04-21 05:27:44 +04:00
mount_unwatch_control_pid ( m ) ;
2010-04-10 19:53:17 +04:00
m - > control_command = NULL ;
2010-04-21 05:27:44 +04:00
m - > control_command_id = _MOUNT_EXEC_COMMAND_INVALID ;
2010-04-10 19:53:17 +04:00
}
2010-04-17 01:24:39 +04:00
if ( state = = MOUNT_MOUNTED | |
state = = MOUNT_REMOUNTING )
mount_notify_automount ( m , 0 ) ;
else if ( state = = MOUNT_DEAD | |
state = = MOUNT_UNMOUNTING | |
state = = MOUNT_MOUNTING_SIGTERM | |
state = = MOUNT_MOUNTING_SIGKILL | |
state = = MOUNT_REMOUNTING_SIGTERM | |
state = = MOUNT_REMOUNTING_SIGKILL | |
state = = MOUNT_UNMOUNTING_SIGTERM | |
state = = MOUNT_UNMOUNTING_SIGKILL | |
2010-08-31 02:23:34 +04:00
state = = MOUNT_FAILED )
2010-04-17 01:24:39 +04:00
mount_notify_automount ( m , - ENODEV ) ;
2010-04-10 19:53:17 +04:00
if ( state ! = old_state )
2010-04-23 22:25:55 +04:00
log_debug ( " %s changed %s -> %s " ,
2010-06-19 18:55:49 +04:00
m - > meta . id ,
2010-04-21 05:27:44 +04:00
mount_state_to_string ( old_state ) ,
mount_state_to_string ( state ) ) ;
2010-04-10 19:53:17 +04:00
2011-01-20 15:17:22 +03:00
unit_notify ( UNIT ( m ) , state_translation_table [ old_state ] , state_translation_table [ state ] , ! m - > reload_failure ) ;
m - > reload_failure = false ;
2010-04-10 19:53:17 +04:00
}
static int mount_coldplug ( Unit * u ) {
Mount * m = MOUNT ( u ) ;
2010-04-21 05:27:44 +04:00
MountState new_state = MOUNT_DEAD ;
int r ;
2010-04-10 19:53:17 +04:00
assert ( m ) ;
assert ( m - > state = = MOUNT_DEAD ) ;
2010-04-21 05:27:44 +04:00
if ( m - > deserialized_state ! = m - > state )
new_state = m - > deserialized_state ;
else if ( m - > from_proc_self_mountinfo )
new_state = MOUNT_MOUNTED ;
2010-04-10 19:53:17 +04:00
2010-04-21 05:27:44 +04:00
if ( new_state ! = m - > state ) {
2010-04-10 19:53:17 +04:00
2010-04-21 05:27:44 +04:00
if ( new_state = = MOUNT_MOUNTING | |
new_state = = MOUNT_MOUNTING_DONE | |
new_state = = MOUNT_REMOUNTING | |
new_state = = MOUNT_UNMOUNTING | |
new_state = = MOUNT_MOUNTING_SIGTERM | |
new_state = = MOUNT_MOUNTING_SIGKILL | |
new_state = = MOUNT_UNMOUNTING_SIGTERM | |
new_state = = MOUNT_UNMOUNTING_SIGKILL | |
new_state = = MOUNT_REMOUNTING_SIGTERM | |
new_state = = MOUNT_REMOUNTING_SIGKILL ) {
2010-04-10 19:53:17 +04:00
2010-04-21 05:27:44 +04:00
if ( m - > control_pid < = 0 )
return - EBADMSG ;
2010-04-10 19:53:17 +04:00
2010-04-21 05:27:44 +04:00
if ( ( r = unit_watch_pid ( UNIT ( m ) , m - > control_pid ) ) < 0 )
return r ;
2010-04-10 19:53:17 +04:00
2010-04-21 05:27:44 +04:00
if ( ( r = unit_watch_timer ( UNIT ( m ) , m - > timeout_usec , & m - > timer_watch ) ) < 0 )
return r ;
}
2010-04-10 19:53:17 +04:00
2010-04-21 05:27:44 +04:00
mount_set_state ( m , new_state ) ;
}
2010-04-10 19:53:17 +04:00
return 0 ;
}
static void mount_dump ( Unit * u , FILE * f , const char * prefix ) {
Mount * m = MOUNT ( u ) ;
MountParameters * p ;
assert ( m ) ;
assert ( f ) ;
2011-03-30 03:53:34 +04:00
p = get_mount_parameters ( m ) ;
2010-04-10 19:53:17 +04:00
fprintf ( f ,
" %sMount State: %s \n "
" %sWhere: %s \n "
" %sWhat: %s \n "
" %sFile System Type: %s \n "
" %sOptions: %s \n "
" %sFrom /etc/fstab: %s \n "
" %sFrom /proc/self/mountinfo: %s \n "
" %sFrom fragment: %s \n "
2010-07-02 02:28:44 +04:00
" %sDirectoryMode: %04o \n " ,
2010-04-21 05:27:44 +04:00
prefix , mount_state_to_string ( m - > state ) ,
2010-04-10 19:53:17 +04:00
prefix , m - > where ,
prefix , strna ( p - > what ) ,
prefix , strna ( p - > fstype ) ,
prefix , strna ( p - > options ) ,
prefix , yes_no ( m - > from_etc_fstab ) ,
prefix , yes_no ( m - > from_proc_self_mountinfo ) ,
prefix , yes_no ( m - > from_fragment ) ,
2010-07-02 02:28:44 +04:00
prefix , m - > directory_mode ) ;
2010-04-10 19:53:17 +04:00
if ( m - > control_pid > 0 )
fprintf ( f ,
2010-06-19 06:35:52 +04:00
" %sControl PID: %lu \n " ,
prefix , ( unsigned long ) m - > control_pid ) ;
2010-04-10 19:53:17 +04:00
exec_context_dump ( & m - > exec_context , f , prefix ) ;
}
2010-04-21 05:27:44 +04:00
static int mount_spawn ( Mount * m , ExecCommand * c , pid_t * _pid ) {
pid_t pid ;
int r ;
assert ( m ) ;
assert ( c ) ;
assert ( _pid ) ;
if ( ( r = unit_watch_timer ( UNIT ( m ) , m - > timeout_usec , & m - > timer_watch ) ) < 0 )
goto fail ;
if ( ( r = exec_spawn ( c ,
NULL ,
& m - > exec_context ,
NULL , 0 ,
2010-05-10 01:53:52 +04:00
m - > meta . manager - > environment ,
2010-04-21 05:27:44 +04:00
true ,
true ,
2010-07-08 06:09:17 +04:00
true ,
2010-07-08 07:22:34 +04:00
m - > meta . manager - > confirm_spawn ,
2010-06-19 18:55:49 +04:00
m - > meta . cgroup_bondings ,
2011-08-20 02:20:41 +04:00
m - > meta . cgroup_attributes ,
2010-04-21 05:27:44 +04:00
& pid ) ) < 0 )
goto fail ;
if ( ( r = unit_watch_pid ( UNIT ( m ) , pid ) ) < 0 )
/* FIXME: we need to do something here */
goto fail ;
* _pid = pid ;
return 0 ;
fail :
unit_unwatch_timer ( UNIT ( m ) , & m - > timer_watch ) ;
return r ;
}
2010-04-10 19:53:17 +04:00
static void mount_enter_dead ( Mount * m , bool success ) {
assert ( m ) ;
if ( ! success )
m - > failure = true ;
2010-08-31 02:23:34 +04:00
mount_set_state ( m , m - > failure ? MOUNT_FAILED : MOUNT_DEAD ) ;
2010-04-10 19:53:17 +04:00
}
2010-04-13 04:06:27 +04:00
static void mount_enter_mounted ( Mount * m , bool success ) {
assert ( m ) ;
if ( ! success )
m - > failure = true ;
mount_set_state ( m , MOUNT_MOUNTED ) ;
}
2010-04-10 19:53:17 +04:00
static void mount_enter_signal ( Mount * m , MountState state , bool success ) {
int r ;
2010-09-01 01:24:47 +04:00
Set * pid_set = NULL ;
bool wait_for_exit = false ;
2010-04-10 19:53:17 +04:00
assert ( m ) ;
if ( ! success )
m - > failure = true ;
2010-07-10 06:49:37 +04:00
if ( m - > exec_context . kill_mode ! = KILL_NONE ) {
2010-04-13 04:06:27 +04:00
int sig = ( state = = MOUNT_MOUNTING_SIGTERM | |
state = = MOUNT_UNMOUNTING_SIGTERM | |
2010-07-10 06:49:37 +04:00
state = = MOUNT_REMOUNTING_SIGTERM ) ? m - > exec_context . kill_signal : SIGKILL ;
2010-04-10 19:53:17 +04:00
2010-09-01 01:24:47 +04:00
if ( m - > control_pid > 0 ) {
2011-03-30 01:31:38 +04:00
if ( kill_and_sigcont ( m - > control_pid , sig ) < 0 & & errno ! = ESRCH )
2010-04-10 19:53:17 +04:00
2010-09-01 01:24:47 +04:00
log_warning ( " Failed to kill control process %li: %m " , ( long ) m - > control_pid ) ;
else
wait_for_exit = true ;
2010-04-10 19:53:17 +04:00
}
2010-09-01 01:24:47 +04:00
if ( m - > exec_context . kill_mode = = KILL_CONTROL_GROUP ) {
2010-07-10 06:49:37 +04:00
2010-09-01 01:24:47 +04:00
if ( ! ( pid_set = set_new ( trivial_hash_func , trivial_compare_func ) ) ) {
r = - ENOMEM ;
2010-04-10 19:53:17 +04:00
goto fail ;
}
2010-09-01 01:24:47 +04:00
/* Exclude the control pid from being killed via the cgroup */
if ( m - > control_pid > 0 )
if ( ( r = set_put ( pid_set , LONG_TO_PTR ( m - > control_pid ) ) ) < 0 )
goto fail ;
2011-03-04 01:55:30 +03:00
if ( ( r = cgroup_bonding_kill_list ( m - > meta . cgroup_bondings , sig , true , pid_set ) ) < 0 ) {
2010-09-01 01:24:47 +04:00
if ( r ! = - EAGAIN & & r ! = - ESRCH & & r ! = - ENOENT )
log_warning ( " Failed to kill control group: %s " , strerror ( - r ) ) ;
} else if ( r > 0 )
wait_for_exit = true ;
set_free ( pid_set ) ;
2011-03-31 17:35:40 +04:00
pid_set = NULL ;
2010-09-01 01:24:47 +04:00
}
2010-04-10 19:53:17 +04:00
}
2010-09-01 01:24:47 +04:00
if ( wait_for_exit ) {
2010-04-13 04:06:27 +04:00
if ( ( r = unit_watch_timer ( UNIT ( m ) , m - > timeout_usec , & m - > timer_watch ) ) < 0 )
goto fail ;
2010-04-10 19:53:17 +04:00
2010-04-13 04:06:27 +04:00
mount_set_state ( m , state ) ;
} else if ( state = = MOUNT_REMOUNTING_SIGTERM | | state = = MOUNT_REMOUNTING_SIGKILL )
mount_enter_mounted ( m , true ) ;
else
2010-04-10 19:53:17 +04:00
mount_enter_dead ( m , true ) ;
return ;
fail :
2010-06-19 18:55:49 +04:00
log_warning ( " %s failed to kill processes: %s " , m - > meta . id , strerror ( - r ) ) ;
2010-04-10 19:53:17 +04:00
2010-04-13 04:06:27 +04:00
if ( state = = MOUNT_REMOUNTING_SIGTERM | | state = = MOUNT_REMOUNTING_SIGKILL )
mount_enter_mounted ( m , false ) ;
else
mount_enter_dead ( m , false ) ;
2010-09-01 01:24:47 +04:00
if ( pid_set )
set_free ( pid_set ) ;
2010-04-10 19:53:17 +04:00
}
static void mount_enter_unmounting ( Mount * m , bool success ) {
int r ;
assert ( m ) ;
if ( ! success )
m - > failure = true ;
2010-04-21 05:27:44 +04:00
m - > control_command_id = MOUNT_EXEC_UNMOUNT ;
m - > control_command = m - > exec_command + MOUNT_EXEC_UNMOUNT ;
2010-04-10 19:53:17 +04:00
if ( ( r = exec_command_set (
2010-04-21 05:27:44 +04:00
m - > control_command ,
2010-04-10 19:53:17 +04:00
" /bin/umount " ,
m - > where ,
NULL ) ) < 0 )
goto fail ;
2010-04-21 05:27:44 +04:00
mount_unwatch_control_pid ( m ) ;
2010-04-11 02:22:36 +04:00
2010-04-21 05:27:44 +04:00
if ( ( r = mount_spawn ( m , m - > control_command , & m - > control_pid ) ) < 0 )
2010-04-10 19:53:17 +04:00
goto fail ;
mount_set_state ( m , MOUNT_UNMOUNTING ) ;
return ;
fail :
2010-06-19 18:55:49 +04:00
log_warning ( " %s failed to run 'umount' task: %s " , m - > meta . id , strerror ( - r ) ) ;
2010-04-10 19:53:17 +04:00
mount_enter_mounted ( m , false ) ;
}
2010-04-17 01:24:39 +04:00
static void mount_enter_mounting ( Mount * m ) {
2010-04-10 19:53:17 +04:00
int r ;
2011-03-30 03:53:34 +04:00
MountParameters * p ;
2010-04-10 19:53:17 +04:00
assert ( m ) ;
2010-04-21 05:27:44 +04:00
m - > control_command_id = MOUNT_EXEC_MOUNT ;
m - > control_command = m - > exec_command + MOUNT_EXEC_MOUNT ;
2010-04-10 19:53:17 +04:00
2010-07-02 02:28:44 +04:00
mkdir_p ( m - > where , m - > directory_mode ) ;
2011-03-30 03:53:34 +04:00
/* Create the source directory for bind-mounts if needed */
p = get_mount_parameters_configured ( m ) ;
if ( p & & mount_is_bind ( p ) )
mkdir_p ( p - > what , m - > directory_mode ) ;
2011-03-25 07:07:20 +03:00
2010-04-10 19:53:17 +04:00
if ( m - > from_fragment )
r = exec_command_set (
2010-04-21 05:27:44 +04:00
m - > control_command ,
2010-04-10 19:53:17 +04:00
" /bin/mount " ,
m - > parameters_fragment . what ,
m - > where ,
2010-10-08 04:43:05 +04:00
" -t " , m - > parameters_fragment . fstype ? m - > parameters_fragment . fstype : " auto " ,
2010-04-17 01:24:39 +04:00
m - > parameters_fragment . options ? " -o " : NULL , m - > parameters_fragment . options ,
2010-04-10 19:53:17 +04:00
NULL ) ;
else if ( m - > from_etc_fstab )
r = exec_command_set (
2010-04-21 05:27:44 +04:00
m - > control_command ,
2010-04-10 19:53:17 +04:00
" /bin/mount " ,
m - > where ,
NULL ) ;
else
r = - ENOENT ;
if ( r < 0 )
goto fail ;
2010-04-21 05:27:44 +04:00
mount_unwatch_control_pid ( m ) ;
2010-04-11 02:22:36 +04:00
2010-04-21 05:27:44 +04:00
if ( ( r = mount_spawn ( m , m - > control_command , & m - > control_pid ) ) < 0 )
2010-04-10 19:53:17 +04:00
goto fail ;
mount_set_state ( m , MOUNT_MOUNTING ) ;
return ;
fail :
2010-06-19 18:55:49 +04:00
log_warning ( " %s failed to run 'mount' task: %s " , m - > meta . id , strerror ( - r ) ) ;
2010-04-10 19:53:17 +04:00
mount_enter_dead ( m , false ) ;
}
2010-04-17 01:24:39 +04:00
static void mount_enter_mounting_done ( Mount * m ) {
2010-04-10 19:53:17 +04:00
assert ( m ) ;
mount_set_state ( m , MOUNT_MOUNTING_DONE ) ;
}
static void mount_enter_remounting ( Mount * m , bool success ) {
int r ;
assert ( m ) ;
if ( ! success )
m - > failure = true ;
2010-04-21 05:27:44 +04:00
m - > control_command_id = MOUNT_EXEC_REMOUNT ;
m - > control_command = m - > exec_command + MOUNT_EXEC_REMOUNT ;
2010-04-10 19:53:17 +04:00
if ( m - > from_fragment ) {
char * buf = NULL ;
const char * o ;
if ( m - > parameters_fragment . options ) {
if ( ! ( buf = strappend ( " remount, " , m - > parameters_fragment . options ) ) ) {
r = - ENOMEM ;
goto fail ;
}
o = buf ;
} else
o = " remount " ;
r = exec_command_set (
2010-04-21 05:27:44 +04:00
m - > control_command ,
2010-04-10 19:53:17 +04:00
" /bin/mount " ,
m - > parameters_fragment . what ,
m - > where ,
2010-10-08 04:43:05 +04:00
" -t " , m - > parameters_fragment . fstype ? m - > parameters_fragment . fstype : " auto " ,
2010-04-10 19:53:17 +04:00
" -o " , o ,
NULL ) ;
free ( buf ) ;
} else if ( m - > from_etc_fstab )
r = exec_command_set (
2010-04-21 05:27:44 +04:00
m - > control_command ,
2010-04-10 19:53:17 +04:00
" /bin/mount " ,
m - > where ,
" -o " , " remount " ,
NULL ) ;
else
r = - ENOENT ;
2010-10-12 06:06:21 +04:00
if ( r < 0 )
2010-04-10 19:53:17 +04:00
goto fail ;
2010-04-21 05:27:44 +04:00
mount_unwatch_control_pid ( m ) ;
2010-04-11 02:22:36 +04:00
2010-04-21 05:27:44 +04:00
if ( ( r = mount_spawn ( m , m - > control_command , & m - > control_pid ) ) < 0 )
2010-04-10 19:53:17 +04:00
goto fail ;
mount_set_state ( m , MOUNT_REMOUNTING ) ;
return ;
fail :
2010-08-12 00:04:22 +04:00
log_warning ( " %s failed to run 'remount' task: %s " , m - > meta . id , strerror ( - r ) ) ;
2011-01-20 15:17:22 +03:00
m - > reload_failure = true ;
mount_enter_mounted ( m , true ) ;
2010-04-10 19:53:17 +04:00
}
static int mount_start ( Unit * u ) {
Mount * m = MOUNT ( u ) ;
assert ( m ) ;
/* We cannot fulfill this request right now, try again later
* please ! */
if ( m - > state = = MOUNT_UNMOUNTING | |
m - > state = = MOUNT_UNMOUNTING_SIGTERM | |
2010-10-12 06:06:21 +04:00
m - > state = = MOUNT_UNMOUNTING_SIGKILL | |
m - > state = = MOUNT_MOUNTING_SIGTERM | |
m - > state = = MOUNT_MOUNTING_SIGKILL )
2010-04-10 19:53:17 +04:00
return - EAGAIN ;
/* Already on it! */
2010-10-12 06:06:21 +04:00
if ( m - > state = = MOUNT_MOUNTING )
2010-04-10 19:53:17 +04:00
return 0 ;
2010-08-31 02:23:34 +04:00
assert ( m - > state = = MOUNT_DEAD | | m - > state = = MOUNT_FAILED ) ;
2010-04-10 19:53:17 +04:00
m - > failure = false ;
2010-04-17 01:24:39 +04:00
mount_enter_mounting ( m ) ;
2010-04-10 19:53:17 +04:00
return 0 ;
}
static int mount_stop ( Unit * u ) {
Mount * m = MOUNT ( u ) ;
assert ( m ) ;
/* Already on it */
if ( m - > state = = MOUNT_UNMOUNTING | |
m - > state = = MOUNT_UNMOUNTING_SIGKILL | |
2010-10-12 06:06:21 +04:00
m - > state = = MOUNT_UNMOUNTING_SIGTERM | |
m - > state = = MOUNT_MOUNTING_SIGTERM | |
m - > state = = MOUNT_MOUNTING_SIGKILL )
2010-04-10 19:53:17 +04:00
return 0 ;
2010-07-10 06:52:00 +04:00
assert ( m - > state = = MOUNT_MOUNTING | |
m - > state = = MOUNT_MOUNTING_DONE | |
m - > state = = MOUNT_MOUNTED | |
m - > state = = MOUNT_REMOUNTING | |
m - > state = = MOUNT_REMOUNTING_SIGTERM | |
m - > state = = MOUNT_REMOUNTING_SIGKILL ) ;
2010-04-10 19:53:17 +04:00
mount_enter_unmounting ( m , true ) ;
return 0 ;
}
static int mount_reload ( Unit * u ) {
Mount * m = MOUNT ( u ) ;
assert ( m ) ;
if ( m - > state = = MOUNT_MOUNTING_DONE )
return - EAGAIN ;
assert ( m - > state = = MOUNT_MOUNTED ) ;
mount_enter_remounting ( m , true ) ;
return 0 ;
}
2010-04-21 05:27:44 +04:00
static int mount_serialize ( Unit * u , FILE * f , FDSet * fds ) {
Mount * m = MOUNT ( u ) ;
assert ( m ) ;
assert ( f ) ;
assert ( fds ) ;
unit_serialize_item ( u , f , " state " , mount_state_to_string ( m - > state ) ) ;
unit_serialize_item ( u , f , " failure " , yes_no ( m - > failure ) ) ;
if ( m - > control_pid > 0 )
2010-06-18 00:55:53 +04:00
unit_serialize_item_format ( u , f , " control-pid " , " %lu " , ( unsigned long ) m - > control_pid ) ;
2010-04-21 05:27:44 +04:00
if ( m - > control_command_id > = 0 )
unit_serialize_item ( u , f , " control-command " , mount_exec_command_to_string ( m - > control_command_id ) ) ;
return 0 ;
}
static int mount_deserialize_item ( Unit * u , const char * key , const char * value , FDSet * fds ) {
Mount * m = MOUNT ( u ) ;
assert ( u ) ;
assert ( key ) ;
assert ( value ) ;
assert ( fds ) ;
if ( streq ( key , " state " ) ) {
MountState state ;
if ( ( state = mount_state_from_string ( value ) ) < 0 )
log_debug ( " Failed to parse state value %s " , value ) ;
else
m - > deserialized_state = state ;
} else if ( streq ( key , " failure " ) ) {
int b ;
if ( ( b = parse_boolean ( value ) ) < 0 )
log_debug ( " Failed to parse failure value %s " , value ) ;
else
m - > failure = b | | m - > failure ;
} else if ( streq ( key , " control-pid " ) ) {
2010-06-18 00:55:53 +04:00
pid_t pid ;
2010-04-21 05:27:44 +04:00
2010-08-12 00:04:22 +04:00
if ( parse_pid ( value , & pid ) < 0 )
2010-04-21 05:27:44 +04:00
log_debug ( " Failed to parse control-pid value %s " , value ) ;
else
2010-06-18 00:55:53 +04:00
m - > control_pid = pid ;
2010-04-21 05:27:44 +04:00
} else if ( streq ( key , " control-command " ) ) {
MountExecCommand id ;
if ( ( id = mount_exec_command_from_string ( value ) ) < 0 )
log_debug ( " Failed to parse exec-command value %s " , value ) ;
else {
m - > control_command_id = id ;
m - > control_command = m - > exec_command + id ;
}
} else
log_debug ( " Unknown serialization key '%s' " , key ) ;
return 0 ;
}
2010-04-10 19:53:17 +04:00
static UnitActiveState mount_active_state ( Unit * u ) {
assert ( u ) ;
return state_translation_table [ MOUNT ( u ) - > state ] ;
}
2010-04-13 22:59:01 +04:00
static const char * mount_sub_state_to_string ( Unit * u ) {
assert ( u ) ;
2010-04-21 05:27:44 +04:00
return mount_state_to_string ( MOUNT ( u ) - > state ) ;
2010-04-13 22:59:01 +04:00
}
2010-04-21 08:01:13 +04:00
static bool mount_check_gc ( Unit * u ) {
Mount * m = MOUNT ( u ) ;
assert ( m ) ;
return m - > from_etc_fstab | | m - > from_proc_self_mountinfo ;
}
2010-04-10 19:53:17 +04:00
static void mount_sigchld_event ( Unit * u , pid_t pid , int code , int status ) {
Mount * m = MOUNT ( u ) ;
bool success ;
assert ( m ) ;
assert ( pid > = 0 ) ;
2010-06-16 07:10:31 +04:00
if ( pid ! = m - > control_pid )
return ;
2010-04-10 19:53:17 +04:00
m - > control_pid = 0 ;
2010-06-16 07:10:31 +04:00
success = is_clean_exit ( code , status ) ;
m - > failure = m - > failure | | ! success ;
2010-04-21 05:27:44 +04:00
if ( m - > control_command ) {
2011-05-18 03:07:31 +04:00
exec_status_exit ( & m - > control_command - > exec_status , & m - > exec_context , pid , code , status ) ;
2010-04-21 05:27:44 +04:00
m - > control_command = NULL ;
m - > control_command_id = _MOUNT_EXEC_COMMAND_INVALID ;
}
2010-07-17 06:17:30 +04:00
log_full ( success ? LOG_DEBUG : LOG_NOTICE ,
" %s mount process exited, code=%s status=%i " , u - > meta . id , sigchld_code_to_string ( code ) , status ) ;
2010-04-10 19:53:17 +04:00
/* Note that mount(8) returning and the kernel sending us a
* mount table change event might happen out - of - order . If an
* operation succeed we assume the kernel will follow soon too
* and already change into the resulting state . If it fails
* we check if the kernel still knows about the mount . and
* change state accordingly . */
switch ( m - > state ) {
case MOUNT_MOUNTING :
case MOUNT_MOUNTING_DONE :
case MOUNT_MOUNTING_SIGKILL :
case MOUNT_MOUNTING_SIGTERM :
2010-05-21 05:32:58 +04:00
if ( success )
2010-04-10 19:53:17 +04:00
mount_enter_mounted ( m , true ) ;
else if ( m - > from_proc_self_mountinfo )
mount_enter_mounted ( m , false ) ;
else
mount_enter_dead ( m , false ) ;
break ;
2011-01-20 15:17:22 +03:00
case MOUNT_REMOUNTING :
case MOUNT_REMOUNTING_SIGKILL :
case MOUNT_REMOUNTING_SIGTERM :
m - > reload_failure = ! success ;
if ( m - > from_proc_self_mountinfo )
mount_enter_mounted ( m , true ) ;
else
mount_enter_dead ( m , true ) ;
break ;
2010-04-10 19:53:17 +04:00
case MOUNT_UNMOUNTING :
case MOUNT_UNMOUNTING_SIGKILL :
case MOUNT_UNMOUNTING_SIGTERM :
if ( success )
mount_enter_dead ( m , true ) ;
else if ( m - > from_proc_self_mountinfo )
mount_enter_mounted ( m , false ) ;
else
mount_enter_dead ( m , false ) ;
break ;
default :
assert_not_reached ( " Uh, control process died at wrong time. " ) ;
}
2010-08-20 04:26:05 +04:00
/* Notify clients about changed exit status */
unit_add_to_dbus_queue ( u ) ;
2010-04-10 19:53:17 +04:00
}
static void mount_timer_event ( Unit * u , uint64_t elapsed , Watch * w ) {
Mount * m = MOUNT ( u ) ;
assert ( m ) ;
assert ( elapsed = = 1 ) ;
assert ( w = = & m - > timer_watch ) ;
switch ( m - > state ) {
case MOUNT_MOUNTING :
case MOUNT_MOUNTING_DONE :
2010-04-15 05:11:11 +04:00
log_warning ( " %s mounting timed out. Stopping. " , u - > meta . id ) ;
2010-04-10 19:53:17 +04:00
mount_enter_signal ( m , MOUNT_MOUNTING_SIGTERM , false ) ;
break ;
case MOUNT_REMOUNTING :
2010-04-15 05:11:11 +04:00
log_warning ( " %s remounting timed out. Stopping. " , u - > meta . id ) ;
2011-01-20 15:17:22 +03:00
m - > reload_failure = true ;
mount_enter_mounted ( m , true ) ;
2010-04-10 19:53:17 +04:00
break ;
case MOUNT_UNMOUNTING :
2010-04-15 05:11:11 +04:00
log_warning ( " %s unmounting timed out. Stopping. " , u - > meta . id ) ;
2010-04-10 19:53:17 +04:00
mount_enter_signal ( m , MOUNT_UNMOUNTING_SIGTERM , false ) ;
break ;
case MOUNT_MOUNTING_SIGTERM :
2011-01-19 00:55:54 +03:00
if ( m - > exec_context . send_sigkill ) {
log_warning ( " %s mounting timed out. Killing. " , u - > meta . id ) ;
mount_enter_signal ( m , MOUNT_MOUNTING_SIGKILL , false ) ;
} else {
log_warning ( " %s mounting timed out. Skipping SIGKILL. Ignoring. " , u - > meta . id ) ;
if ( m - > from_proc_self_mountinfo )
mount_enter_mounted ( m , false ) ;
else
mount_enter_dead ( m , false ) ;
}
2010-04-10 19:53:17 +04:00
break ;
case MOUNT_REMOUNTING_SIGTERM :
2011-01-19 00:55:54 +03:00
if ( m - > exec_context . send_sigkill ) {
log_warning ( " %s remounting timed out. Killing. " , u - > meta . id ) ;
mount_enter_signal ( m , MOUNT_REMOUNTING_SIGKILL , false ) ;
} else {
log_warning ( " %s remounting timed out. Skipping SIGKILL. Ignoring. " , u - > meta . id ) ;
if ( m - > from_proc_self_mountinfo )
mount_enter_mounted ( m , false ) ;
else
mount_enter_dead ( m , false ) ;
}
2010-04-10 19:53:17 +04:00
break ;
case MOUNT_UNMOUNTING_SIGTERM :
2011-01-19 00:55:54 +03:00
if ( m - > exec_context . send_sigkill ) {
log_warning ( " %s unmounting timed out. Killing. " , u - > meta . id ) ;
mount_enter_signal ( m , MOUNT_UNMOUNTING_SIGKILL , false ) ;
} else {
log_warning ( " %s unmounting timed out. Skipping SIGKILL. Ignoring. " , u - > meta . id ) ;
if ( m - > from_proc_self_mountinfo )
mount_enter_mounted ( m , false ) ;
else
mount_enter_dead ( m , false ) ;
}
2010-04-10 19:53:17 +04:00
break ;
case MOUNT_MOUNTING_SIGKILL :
case MOUNT_REMOUNTING_SIGKILL :
case MOUNT_UNMOUNTING_SIGKILL :
2010-04-15 05:11:11 +04:00
log_warning ( " %s mount process still around after SIGKILL. Ignoring. " , u - > meta . id ) ;
2010-04-10 19:53:17 +04:00
if ( m - > from_proc_self_mountinfo )
mount_enter_mounted ( m , false ) ;
else
mount_enter_dead ( m , false ) ;
break ;
default :
assert_not_reached ( " Timeout at wrong time. " ) ;
}
}
static int mount_add_one (
Manager * m ,
const char * what ,
const char * where ,
const char * options ,
const char * fstype ,
2010-10-13 05:57:04 +04:00
int passno ,
2010-04-10 19:53:17 +04:00
bool from_proc_self_mountinfo ,
bool set_flags ) {
2010-01-29 04:07:41 +03:00
int r ;
Unit * u ;
bool delete ;
2010-04-10 19:53:17 +04:00
char * e , * w = NULL , * o = NULL , * f = NULL ;
2010-05-14 04:29:45 +04:00
MountParameters * p ;
2010-01-29 04:07:41 +03:00
2010-01-29 05:18:09 +03:00
assert ( m ) ;
2010-01-29 04:07:41 +03:00
assert ( what ) ;
assert ( where ) ;
2010-04-10 19:53:17 +04:00
assert ( options ) ;
assert ( fstype ) ;
assert ( ! set_flags | | from_proc_self_mountinfo ) ;
/* Ignore API mount points. They should never be referenced in
* dependencies ever . */
2011-04-06 01:39:21 +04:00
if ( mount_point_is_api ( where ) | | mount_point_ignore ( where ) )
2010-11-11 13:15:16 +03:00
return 0 ;
2010-01-29 04:07:41 +03:00
2010-04-17 01:24:39 +04:00
if ( streq ( fstype , " autofs " ) )
return 0 ;
2010-05-14 04:29:45 +04:00
/* probably some kind of swap, ignore */
if ( ! is_path ( where ) )
2010-01-29 04:07:41 +03:00
return 0 ;
2012-01-15 13:53:49 +04:00
e = unit_name_from_path ( where , " .mount " ) ;
if ( ! e )
2010-01-29 04:07:41 +03:00
return - ENOMEM ;
2012-01-15 13:53:49 +04:00
u = manager_get_unit ( m , e ) ;
if ( ! u ) {
2010-01-29 04:07:41 +03:00
delete = true ;
2012-01-15 13:53:49 +04:00
u = unit_new ( m , sizeof ( Mount ) ) ;
if ( ! u ) {
2010-01-29 04:07:41 +03:00
free ( e ) ;
return - ENOMEM ;
}
r = unit_add_name ( u , e ) ;
free ( e ) ;
if ( r < 0 )
goto fail ;
2012-01-15 13:53:49 +04:00
MOUNT ( u ) - > where = strdup ( where ) ;
if ( ! MOUNT ( u ) - > where ) {
2010-05-09 20:44:11 +04:00
r = - ENOMEM ;
goto fail ;
}
2010-01-29 05:18:09 +03:00
2010-01-29 08:45:59 +03:00
unit_add_to_load_queue ( u ) ;
2010-01-29 04:07:41 +03:00
} else {
delete = false ;
free ( e ) ;
}
2010-04-10 19:53:17 +04:00
if ( ! ( w = strdup ( what ) ) | |
! ( o = strdup ( options ) ) | |
! ( f = strdup ( fstype ) ) ) {
r = - ENOMEM ;
goto fail ;
}
if ( from_proc_self_mountinfo ) {
2010-05-14 04:29:45 +04:00
p = & MOUNT ( u ) - > parameters_proc_self_mountinfo ;
2010-04-10 19:53:17 +04:00
if ( set_flags ) {
MOUNT ( u ) - > is_mounted = true ;
MOUNT ( u ) - > just_mounted = ! MOUNT ( u ) - > from_proc_self_mountinfo ;
2010-05-14 04:29:45 +04:00
MOUNT ( u ) - > just_changed = ! streq_ptr ( p - > options , o ) ;
2010-04-10 19:53:17 +04:00
}
2010-01-29 08:04:08 +03:00
2010-01-29 05:18:09 +03:00
MOUNT ( u ) - > from_proc_self_mountinfo = true ;
2010-01-29 08:04:08 +03:00
} else {
2010-05-14 04:29:45 +04:00
p = & MOUNT ( u ) - > parameters_etc_fstab ;
2010-01-29 05:18:09 +03:00
MOUNT ( u ) - > from_etc_fstab = true ;
2010-01-29 08:04:08 +03:00
}
2010-01-29 05:18:09 +03:00
2010-05-14 04:29:45 +04:00
free ( p - > what ) ;
p - > what = w ;
2010-01-29 04:07:41 +03:00
2010-05-14 04:29:45 +04:00
free ( p - > options ) ;
p - > options = o ;
2010-04-10 19:53:17 +04:00
2010-05-14 04:29:45 +04:00
free ( p - > fstype ) ;
p - > fstype = f ;
2010-01-29 04:07:41 +03:00
2010-10-13 05:57:04 +04:00
p - > passno = passno ;
2010-02-05 02:38:41 +03:00
unit_add_to_dbus_queue ( u ) ;
2010-01-29 04:07:41 +03:00
return 0 ;
fail :
2010-04-10 19:53:17 +04:00
free ( w ) ;
free ( o ) ;
free ( f ) ;
2010-01-29 04:07:41 +03:00
if ( delete & & u )
unit_free ( u ) ;
2010-05-14 04:29:45 +04:00
return r ;
2010-01-29 04:07:41 +03:00
}
2010-05-09 20:44:11 +04:00
static int mount_find_pri ( char * options ) {
char * end , * pri ;
unsigned long r ;
2011-08-31 03:46:38 +04:00
if ( ! ( pri = mount_test_option ( options , " pri " ) ) )
2010-05-09 20:44:11 +04:00
return 0 ;
pri + = 4 ;
errno = 0 ;
r = strtoul ( pri , & end , 10 ) ;
if ( errno ! = 0 )
return - errno ;
if ( end = = pri | | ( * end ! = ' , ' & & * end ! = 0 ) )
return - EINVAL ;
return ( int ) r ;
}
2010-04-10 19:53:17 +04:00
static int mount_load_etc_fstab ( Manager * m ) {
2010-01-29 04:07:41 +03:00
FILE * f ;
2010-10-12 06:06:21 +04:00
int r = 0 ;
2010-01-29 04:07:41 +03:00
struct mntent * me ;
assert ( m ) ;
errno = 0 ;
if ( ! ( f = setmntent ( " /etc/fstab " , " r " ) ) )
return - errno ;
while ( ( me = getmntent ( f ) ) ) {
char * where , * what ;
2010-10-12 06:06:21 +04:00
int k ;
2010-01-29 04:07:41 +03:00
if ( ! ( what = fstab_node_to_udev_node ( me - > mnt_fsname ) ) ) {
r = - ENOMEM ;
goto finish ;
}
if ( ! ( where = strdup ( me - > mnt_dir ) ) ) {
free ( what ) ;
r = - ENOMEM ;
goto finish ;
}
if ( what [ 0 ] = = ' / ' )
path_kill_slashes ( what ) ;
if ( where [ 0 ] = = ' / ' )
path_kill_slashes ( where ) ;
2010-05-09 20:44:11 +04:00
if ( streq ( me - > mnt_type , " swap " ) ) {
int pri ;
if ( ( pri = mount_find_pri ( me - > mnt_opts ) ) < 0 )
2010-10-12 06:06:21 +04:00
k = pri ;
2010-05-09 20:44:11 +04:00
else
2010-10-12 06:06:21 +04:00
k = swap_add_one ( m ,
2010-05-09 20:44:11 +04:00
what ,
2010-10-12 06:06:21 +04:00
NULL ,
2010-05-09 20:44:11 +04:00
pri ,
2011-04-20 02:45:22 +04:00
! ! mount_test_option ( me - > mnt_opts , " noauto " ) ,
2010-08-25 22:37:04 +04:00
! ! mount_test_option ( me - > mnt_opts , " nofail " ) ,
2010-05-14 04:29:45 +04:00
! ! mount_test_option ( me - > mnt_opts , " comment=systemd.swapon " ) ,
2010-05-09 20:44:11 +04:00
false ) ;
} else
2010-10-13 05:57:04 +04:00
k = mount_add_one ( m , what , where , me - > mnt_opts , me - > mnt_type , me - > mnt_passno , false , false ) ;
2010-05-09 20:44:11 +04:00
2010-01-29 04:07:41 +03:00
free ( what ) ;
free ( where ) ;
if ( r < 0 )
2010-10-12 06:06:21 +04:00
r = k ;
2010-01-29 04:07:41 +03:00
}
finish :
endmntent ( f ) ;
return r ;
}
2010-01-29 08:04:08 +03:00
static int mount_load_proc_self_mountinfo ( Manager * m , bool set_flags ) {
2010-10-12 06:06:21 +04:00
int r = 0 ;
2010-10-05 19:41:06 +04:00
unsigned i ;
2010-06-03 01:03:39 +04:00
char * device , * path , * options , * options2 , * fstype , * d , * p , * o ;
2010-01-29 04:07:41 +03:00
assert ( m ) ;
2010-01-29 08:04:08 +03:00
rewind ( m - > proc_self_mountinfo ) ;
2010-01-29 04:07:41 +03:00
2010-10-05 19:41:06 +04:00
for ( i = 1 ; ; i + + ) {
2010-01-29 04:07:41 +03:00
int k ;
2010-04-10 19:53:17 +04:00
2010-06-03 01:03:39 +04:00
device = path = options = options2 = fstype = d = p = o = NULL ;
2010-01-29 04:07:41 +03:00
2010-01-29 08:04:08 +03:00
if ( ( k = fscanf ( m - > proc_self_mountinfo ,
2010-01-29 04:07:41 +03:00
" %*s " /* (1) mount id */
" %*s " /* (2) parent id */
" %*s " /* (3) major:minor */
" %*s " /* (4) root */
" %ms " /* (5) mount point */
2010-04-10 19:53:17 +04:00
" %ms " /* (6) mount options */
2010-01-29 04:07:41 +03:00
" %*[^-] " /* (7) optional fields */
2010-09-29 17:13:04 +04:00
" - " /* (8) separator */
2010-04-10 19:53:17 +04:00
" %ms " /* (9) file system type */
2010-01-29 08:04:08 +03:00
" %ms " /* (10) mount source */
2010-06-03 01:03:39 +04:00
" %ms " /* (11) mount options 2 */
2010-01-29 08:04:08 +03:00
" %*[^ \n ] " , /* some rubbish at the end */
2010-01-29 04:07:41 +03:00
& path ,
2010-04-10 19:53:17 +04:00
& options ,
& fstype ,
2010-06-03 01:03:39 +04:00
& device ,
& options2 ) ) ! = 5 ) {
2010-01-29 04:07:41 +03:00
2010-01-29 08:04:08 +03:00
if ( k = = EOF )
break ;
2010-01-29 04:07:41 +03:00
2010-10-05 19:41:06 +04:00
log_warning ( " Failed to parse /proc/self/mountinfo:%u. " , i ) ;
goto clean_up ;
2010-01-29 04:07:41 +03:00
}
2010-06-03 01:03:39 +04:00
if ( asprintf ( & o , " %s,%s " , options , options2 ) < 0 ) {
r = - ENOMEM ;
goto finish ;
}
2010-04-10 19:53:17 +04:00
if ( ! ( d = cunescape ( device ) ) | |
! ( p = cunescape ( path ) ) ) {
r = - ENOMEM ;
goto finish ;
2010-01-29 04:07:41 +03:00
}
2010-10-13 05:57:04 +04:00
if ( ( k = mount_add_one ( m , d , p , o , fstype , 0 , true , set_flags ) ) < 0 )
2010-10-12 06:06:21 +04:00
r = k ;
2010-01-29 04:07:41 +03:00
2010-10-05 19:41:06 +04:00
clean_up :
2010-04-10 19:53:17 +04:00
free ( device ) ;
free ( path ) ;
free ( options ) ;
2010-06-03 01:03:39 +04:00
free ( options2 ) ;
2010-04-10 19:53:17 +04:00
free ( fstype ) ;
2010-01-29 04:07:41 +03:00
free ( d ) ;
free ( p ) ;
2010-06-03 01:03:39 +04:00
free ( o ) ;
2010-01-29 04:07:41 +03:00
}
2010-04-10 19:53:17 +04:00
finish :
free ( device ) ;
free ( path ) ;
free ( options ) ;
2010-06-03 01:03:39 +04:00
free ( options2 ) ;
2010-04-10 19:53:17 +04:00
free ( fstype ) ;
free ( d ) ;
free ( p ) ;
2010-06-03 01:03:39 +04:00
free ( o ) ;
2010-04-10 19:53:17 +04:00
return r ;
}
static void mount_shutdown ( Manager * m ) {
assert ( m ) ;
2010-04-21 05:27:44 +04:00
if ( m - > proc_self_mountinfo ) {
2010-04-10 19:53:17 +04:00
fclose ( m - > proc_self_mountinfo ) ;
2010-04-21 05:27:44 +04:00
m - > proc_self_mountinfo = NULL ;
}
2010-01-29 04:07:41 +03:00
}
static int mount_enumerate ( Manager * m ) {
int r ;
2010-01-29 08:04:08 +03:00
struct epoll_event ev ;
2010-01-29 04:07:41 +03:00
assert ( m ) ;
2010-04-21 05:27:44 +04:00
if ( ! m - > proc_self_mountinfo ) {
if ( ! ( m - > proc_self_mountinfo = fopen ( " /proc/self/mountinfo " , " re " ) ) )
return - errno ;
2010-01-29 08:04:08 +03:00
2010-04-21 05:27:44 +04:00
m - > mount_watch . type = WATCH_MOUNT ;
m - > mount_watch . fd = fileno ( m - > proc_self_mountinfo ) ;
2010-01-29 08:04:08 +03:00
2010-04-21 05:27:44 +04:00
zero ( ev ) ;
2010-10-19 01:09:09 +04:00
ev . events = EPOLLPRI ;
2010-04-21 05:27:44 +04:00
ev . data . ptr = & m - > mount_watch ;
2010-01-29 08:04:08 +03:00
2010-04-21 05:27:44 +04:00
if ( epoll_ctl ( m - > epoll_fd , EPOLL_CTL_ADD , m - > mount_watch . fd , & ev ) < 0 )
return - errno ;
}
2010-01-29 08:04:08 +03:00
2010-04-10 19:53:17 +04:00
if ( ( r = mount_load_etc_fstab ( m ) ) < 0 )
2010-01-29 04:07:41 +03:00
goto fail ;
2010-01-29 08:04:08 +03:00
if ( ( r = mount_load_proc_self_mountinfo ( m , false ) ) < 0 )
2010-01-29 04:07:41 +03:00
goto fail ;
return 0 ;
fail :
mount_shutdown ( m ) ;
return r ;
2010-01-23 03:52:57 +03:00
}
2010-01-29 08:04:08 +03:00
void mount_fd_event ( Manager * m , int events ) {
Meta * meta ;
int r ;
assert ( m ) ;
2010-10-19 01:09:09 +04:00
assert ( events & EPOLLPRI ) ;
2010-01-29 08:04:08 +03:00
/* The manager calls this for every fd event happening on the
* / proc / self / mountinfo file , which informs us about mounting
* table changes */
if ( ( r = mount_load_proc_self_mountinfo ( m , true ) ) < 0 ) {
2010-08-12 00:04:22 +04:00
log_error ( " Failed to reread /proc/self/mountinfo: %s " , strerror ( - r ) ) ;
2010-04-10 19:53:17 +04:00
/* Reset flags, just in case, for later calls */
2011-05-24 01:53:43 +04:00
LIST_FOREACH ( units_by_type , meta , m - > units_by_type [ UNIT_MOUNT ] ) {
2010-04-10 19:53:17 +04:00
Mount * mount = ( Mount * ) meta ;
mount - > is_mounted = mount - > just_mounted = mount - > just_changed = false ;
}
2010-01-29 08:04:08 +03:00
return ;
}
manager_dispatch_load_queue ( m ) ;
2011-05-24 01:53:43 +04:00
LIST_FOREACH ( units_by_type , meta , m - > units_by_type [ UNIT_MOUNT ] ) {
2010-01-29 08:04:08 +03:00
Mount * mount = ( Mount * ) meta ;
2010-04-10 19:53:17 +04:00
if ( ! mount - > is_mounted ) {
/* This has just been unmounted. */
2010-01-29 08:04:08 +03:00
mount - > from_proc_self_mountinfo = false ;
2010-04-10 19:53:17 +04:00
switch ( mount - > state ) {
case MOUNT_MOUNTED :
mount_enter_dead ( mount , true ) ;
break ;
default :
mount_set_state ( mount , mount - > state ) ;
break ;
}
} else if ( mount - > just_mounted | | mount - > just_changed ) {
2010-10-12 06:06:21 +04:00
/* New or changed mount entry */
2010-04-10 19:53:17 +04:00
switch ( mount - > state ) {
case MOUNT_DEAD :
2010-08-31 02:23:34 +04:00
case MOUNT_FAILED :
2010-04-10 19:53:17 +04:00
mount_enter_mounted ( mount , true ) ;
break ;
case MOUNT_MOUNTING :
2010-04-17 01:24:39 +04:00
mount_enter_mounting_done ( mount ) ;
2010-04-10 19:53:17 +04:00
break ;
default :
/* Nothing really changed, but let's
* issue an notification call
* nonetheless , in case somebody is
* waiting for this . ( e . g . file system
* ro / rw remounts . ) */
mount_set_state ( mount , mount - > state ) ;
break ;
}
}
/* Reset the flags for later calls */
mount - > is_mounted = mount - > just_mounted = mount - > just_changed = false ;
}
}
2010-08-31 02:23:34 +04:00
static void mount_reset_failed ( Unit * u ) {
2010-07-18 06:58:01 +04:00
Mount * m = MOUNT ( u ) ;
assert ( m ) ;
2010-08-31 02:23:34 +04:00
if ( m - > state = = MOUNT_FAILED )
2010-07-18 06:58:01 +04:00
mount_set_state ( m , MOUNT_DEAD ) ;
m - > failure = false ;
}
2010-10-22 18:11:50 +04:00
static int mount_kill ( Unit * u , KillWho who , KillMode mode , int signo , DBusError * error ) {
Mount * m = MOUNT ( u ) ;
int r = 0 ;
Set * pid_set = NULL ;
assert ( m ) ;
if ( who = = KILL_MAIN ) {
dbus_set_error ( error , BUS_ERROR_NO_SUCH_PROCESS , " Mount units have no main processes " ) ;
2011-07-13 21:57:36 +04:00
return - ESRCH ;
2010-10-22 18:11:50 +04:00
}
if ( m - > control_pid < = 0 & & who = = KILL_CONTROL ) {
dbus_set_error ( error , BUS_ERROR_NO_SUCH_PROCESS , " No control process to kill " ) ;
2011-07-13 21:57:36 +04:00
return - ESRCH ;
2010-10-22 18:11:50 +04:00
}
2011-07-12 06:05:33 +04:00
if ( who = = KILL_CONTROL | | who = = KILL_ALL )
if ( m - > control_pid > 0 )
if ( kill ( m - > control_pid , signo ) < 0 )
r = - errno ;
2010-10-22 18:11:50 +04:00
2011-07-12 06:05:33 +04:00
if ( who = = KILL_ALL & & mode = = KILL_CONTROL_GROUP ) {
2010-10-22 18:11:50 +04:00
int q ;
if ( ! ( pid_set = set_new ( trivial_hash_func , trivial_compare_func ) ) )
return - ENOMEM ;
/* Exclude the control pid from being killed via the cgroup */
if ( m - > control_pid > 0 )
if ( ( q = set_put ( pid_set , LONG_TO_PTR ( m - > control_pid ) ) ) < 0 ) {
r = q ;
goto finish ;
}
2011-03-04 01:55:30 +03:00
if ( ( q = cgroup_bonding_kill_list ( m - > meta . cgroup_bondings , signo , false , pid_set ) ) < 0 )
2011-07-12 06:05:33 +04:00
if ( q ! = - EAGAIN & & q ! = - ESRCH & & q ! = - ENOENT )
2010-10-22 18:11:50 +04:00
r = q ;
}
finish :
if ( pid_set )
set_free ( pid_set ) ;
return r ;
}
2010-04-21 05:27:44 +04:00
static const char * const mount_state_table [ _MOUNT_STATE_MAX ] = {
[ MOUNT_DEAD ] = " dead " ,
[ MOUNT_MOUNTING ] = " mounting " ,
[ MOUNT_MOUNTING_DONE ] = " mounting-done " ,
[ MOUNT_MOUNTED ] = " mounted " ,
[ MOUNT_REMOUNTING ] = " remounting " ,
[ MOUNT_UNMOUNTING ] = " unmounting " ,
[ MOUNT_MOUNTING_SIGTERM ] = " mounting-sigterm " ,
[ MOUNT_MOUNTING_SIGKILL ] = " mounting-sigkill " ,
[ MOUNT_REMOUNTING_SIGTERM ] = " remounting-sigterm " ,
[ MOUNT_REMOUNTING_SIGKILL ] = " remounting-sigkill " ,
[ MOUNT_UNMOUNTING_SIGTERM ] = " unmounting-sigterm " ,
[ MOUNT_UNMOUNTING_SIGKILL ] = " unmounting-sigkill " ,
2010-08-31 02:23:34 +04:00
[ MOUNT_FAILED ] = " failed "
2010-04-21 05:27:44 +04:00
} ;
DEFINE_STRING_TABLE_LOOKUP ( mount_state , MountState ) ;
static const char * const mount_exec_command_table [ _MOUNT_EXEC_COMMAND_MAX ] = {
[ MOUNT_EXEC_MOUNT ] = " ExecMount " ,
[ MOUNT_EXEC_UNMOUNT ] = " ExecUnmount " ,
[ MOUNT_EXEC_REMOUNT ] = " ExecRemount " ,
} ;
DEFINE_STRING_TABLE_LOOKUP ( mount_exec_command , MountExecCommand ) ;
2010-01-26 23:39:06 +03:00
const UnitVTable mount_vtable = {
2010-01-23 03:52:57 +03:00
. suffix = " .mount " ,
2012-01-15 13:53:49 +04:00
. object_size = sizeof ( Mount ) ,
2011-08-01 02:43:05 +04:00
. sections =
" Unit \0 "
" Mount \0 "
" Install \0 " ,
2010-01-23 03:52:57 +03:00
2010-04-10 19:53:17 +04:00
. no_alias = true ,
2010-04-15 05:11:11 +04:00
. no_instances = true ,
2010-07-07 02:00:59 +04:00
. show_status = true ,
2010-04-10 19:53:17 +04:00
. init = mount_init ,
. load = mount_load ,
2010-01-26 06:18:44 +03:00
. done = mount_done ,
2010-04-10 19:53:17 +04:00
2010-01-29 05:18:09 +03:00
. coldplug = mount_coldplug ,
2010-01-26 06:18:44 +03:00
. dump = mount_dump ,
2010-01-23 03:52:57 +03:00
2010-04-10 19:53:17 +04:00
. start = mount_start ,
. stop = mount_stop ,
. reload = mount_reload ,
2010-10-22 18:11:50 +04:00
. kill = mount_kill ,
2010-04-21 05:27:44 +04:00
. serialize = mount_serialize ,
. deserialize_item = mount_deserialize_item ,
2010-01-29 05:18:09 +03:00
. active_state = mount_active_state ,
2010-04-13 22:59:01 +04:00
. sub_state_to_string = mount_sub_state_to_string ,
2010-01-29 04:07:41 +03:00
2010-04-21 08:01:13 +04:00
. check_gc = mount_check_gc ,
2010-04-10 19:53:17 +04:00
. sigchld_event = mount_sigchld_event ,
. timer_event = mount_timer_event ,
2010-08-31 02:23:34 +04:00
. reset_failed = mount_reset_failed ,
2010-07-18 06:58:01 +04:00
2010-08-20 04:26:05 +04:00
. bus_interface = " org.freedesktop.systemd1.Mount " ,
2010-04-18 05:08:16 +04:00
. bus_message_handler = bus_mount_message_handler ,
2010-08-20 04:26:05 +04:00
. bus_invalidating_properties = bus_mount_invalidating_properties ,
2010-04-18 05:08:16 +04:00
2010-01-29 05:18:09 +03:00
. enumerate = mount_enumerate ,
. shutdown = mount_shutdown
2010-01-23 03:52:57 +03:00
} ;