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
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-02-03 15:03:47 +03: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-02-03 15:03:47 +03:00
2012-04-12 02:20:58 +04:00
You should have received a copy of the GNU Lesser General Public License
2010-02-03 15:03:47 +03:00
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"
2012-04-10 23:54:31 +04:00
# include "mkdir.h"
2012-05-07 23:36:12 +04:00
# include "path-util.h"
2010-04-10 19:53:17 +04:00
# 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 ) ;
2012-01-15 15:04:08 +04:00
assert ( u - > load_state = = UNIT_STUB ) ;
2010-04-21 05:27:44 +04:00
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
2012-05-22 21:23:33 +04:00
if ( unit_has_name ( u , " -.mount " ) ) {
/* Don't allow start/stop for root directory */
UNIT ( m ) - > refuse_manual_start = true ;
UNIT ( m ) - > refuse_manual_stop = true ;
} else {
/* The stdio/kmsg bridge socket is on /, in order to avoid a
* dep loop , don ' t use kmsg logging for - . mount */
2012-01-15 15:04:08 +04:00
m - > exec_context . std_output = u - > manager - > default_std_output ;
m - > exec_context . std_error = u - > manager - > default_std_error ;
2011-11-19 05:47:09 +04:00
}
2010-07-08 07:22:34 +04:00
2012-07-20 01:47:10 +04:00
kill_context_init ( & m - > kill_context ) ;
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
2012-01-15 15:25:20 +04:00
UNIT ( m ) - > 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_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
}
2012-05-22 21:23:33 +04:00
static MountParameters * get_mount_parameters_fragment ( Mount * m ) {
2011-03-30 03:53:34 +04:00
assert ( m ) ;
if ( m - > from_fragment )
return & m - > parameters_fragment ;
return NULL ;
}
static MountParameters * get_mount_parameters ( Mount * m ) {
assert ( m ) ;
if ( m - > from_proc_self_mountinfo )
return & m - > parameters_proc_self_mountinfo ;
2012-05-22 21:23:33 +04:00
return get_mount_parameters_fragment ( m ) ;
2011-03-30 03:53:34 +04:00
}
2010-05-13 05:07:16 +04:00
static int mount_add_mount_links ( Mount * m ) {
2012-01-15 15:04:08 +04:00
Unit * 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
2012-05-22 21:23:33 +04:00
pm = get_mount_parameters_fragment ( 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
2012-01-15 15:25:20 +04:00
LIST_FOREACH ( units_by_type , other , UNIT ( m ) - > manager - > units_by_type [ UNIT_MOUNT ] ) {
2012-01-15 15:37: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
2012-01-15 15:25:20 +04:00
if ( UNIT ( n ) - > load_state ! = UNIT_LOADED )
2010-05-13 05:07:16 +04:00
continue ;
2010-01-29 04:07:41 +03:00
2012-05-22 21:23:33 +04:00
pn = get_mount_parameters_fragment ( 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 ;
2012-03-13 06:34:42 +04:00
} else if ( pm & & pm - > what & & path_startswith ( pm - > what , n - > where ) ) {
2010-09-28 03:03:19 +04:00
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
2012-03-13 06:34:42 +04:00
} else if ( pn & & pn - > what & & path_startswith ( pn - > what , m - > where ) ) {
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 ( ( 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 ) {
2012-01-15 15:04:08 +04:00
Unit * 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
2012-01-15 15:25:20 +04:00
LIST_FOREACH ( units_by_type , other , UNIT ( m ) - > manager - > units_by_type [ UNIT_SWAP ] )
2012-01-15 15:37:16 +04:00
if ( ( r = swap_add_one_mount_link ( SWAP ( other ) , m ) ) < 0 )
2010-05-13 05:07:16 +04:00
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 ) {
2012-01-15 15:04:08 +04:00
Unit * other ;
2010-05-24 07:25:33 +04:00
int r ;
assert ( m ) ;
2012-01-15 15:25:20 +04:00
LIST_FOREACH ( units_by_type , other , UNIT ( m ) - > manager - > units_by_type [ UNIT_PATH ] )
2012-01-15 15:37:16 +04:00
if ( ( r = path_add_one_mount_link ( PATH ( other ) , m ) ) < 0 )
2010-05-24 07:25:33 +04:00
return r ;
return 0 ;
}
2010-05-13 05:07:16 +04:00
static int mount_add_automount_links ( Mount * m ) {
2012-01-15 15:04:08 +04:00
Unit * other ;
2010-05-13 05:07:16 +04:00
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
2012-01-15 15:25:20 +04:00
LIST_FOREACH ( units_by_type , other , UNIT ( m ) - > manager - > units_by_type [ UNIT_AUTOMOUNT ] )
2012-01-15 15:37:16 +04:00
if ( ( r = automount_add_one_mount_link ( AUTOMOUNT ( other ) , m ) ) < 0 )
2010-05-13 05:07:16 +04:00
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 ) {
2012-01-15 15:04:08 +04:00
Unit * other ;
2010-05-13 05:07:16 +04:00
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
2012-01-15 15:25:20 +04:00
LIST_FOREACH ( units_by_type , other , UNIT ( m ) - > manager - > units_by_type [ UNIT_SOCKET ] )
2012-01-15 15:37:16 +04:00
if ( ( r = socket_add_one_mount_link ( SOCKET ( other ) , m ) ) < 0 )
2010-05-13 05:07:16 +04:00
return r ;
2010-01-29 04:07:41 +03:00
return 0 ;
}
2012-04-29 16:26:07 +04:00
static int mount_add_requires_mounts_links ( Mount * m ) {
Unit * other ;
int r ;
assert ( m ) ;
LIST_FOREACH ( has_requires_mounts_for , other , UNIT ( m ) - > manager - > has_requires_mounts_for ) {
r = unit_add_one_mount_link ( other , m ) ;
if ( r < 0 )
return r ;
}
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 )
2012-02-29 17:42:49 +04:00
return NULL ;
2010-04-10 19:53:17 +04:00
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
}
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 ) ;
2012-05-22 21:23:33 +04:00
p = get_mount_parameters_fragment ( m ) ;
if ( ! p )
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 ) & &
2012-05-22 21:23:33 +04:00
! path_equal ( m - > where , " / " ) ) {
r = unit_add_node_link ( UNIT ( m ) , p - > what , false ) ;
if ( r < 0 )
2010-10-13 05:57:04 +04:00
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 ) & &
2012-05-22 21:23:33 +04:00
! path_equal ( m - > where , " / " ) & &
UNIT ( m ) - > manager - > running_as = = MANAGER_SYSTEM ) {
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 */
2012-06-25 15:47:45 +04:00
name = unit_name_from_path_instance ( " systemd-fsck " , p - > what , " .service " ) ;
2012-05-22 21:23:33 +04:00
if ( ! name )
2010-10-13 05:57:04 +04:00
return - ENOMEM ;
2012-05-22 21:23:33 +04:00
r = manager_load_unit_prepare ( UNIT ( m ) - > manager , name , NULL , NULL , & fsck ) ;
if ( r < 0 ) {
2010-10-13 05:57:04 +04:00
log_warning ( " Failed to prepare unit %s: %s " , name , strerror ( - r ) ) ;
free ( name ) ;
return r ;
}
free ( name ) ;
SERVICE ( fsck ) - > fsck_passno = p - > passno ;
2012-05-22 21:23:33 +04:00
r = unit_add_two_dependencies ( UNIT ( m ) , UNIT_AFTER , UNIT_REQUIRES , fsck , true ) ;
if ( r < 0 )
2010-10-13 05:57:04 +04:00
return r ;
}
return 0 ;
2010-08-25 22:37:04 +04:00
}
2012-05-22 21:23:33 +04:00
static int mount_add_quota_links ( Mount * m ) {
int r ;
MountParameters * p ;
assert ( m ) ;
if ( UNIT ( m ) - > manager - > running_as ! = MANAGER_SYSTEM )
return 0 ;
p = get_mount_parameters_fragment ( m ) ;
if ( ! p )
return 0 ;
if ( ! needs_quota ( p ) )
return 0 ;
r = unit_add_two_dependencies_by_name ( UNIT ( m ) , UNIT_BEFORE , UNIT_WANTS , SPECIAL_QUOTACHECK_SERVICE , NULL , true ) ;
if ( r < 0 )
return r ;
r = unit_add_two_dependencies_by_name ( UNIT ( m ) , UNIT_BEFORE , UNIT_WANTS , SPECIAL_QUOTAON_SERVICE , NULL , true ) ;
if ( r < 0 )
return r ;
return 0 ;
}
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 ;
2012-05-22 21:23:33 +04:00
const char * after ;
2010-07-13 00:55:27 +04:00
assert ( m ) ;
2012-01-15 15:25:20 +04:00
if ( UNIT ( m ) - > manager - > running_as ! = MANAGER_SYSTEM )
2012-01-14 02:55:28 +04:00
return 0 ;
2011-03-30 03:53:34 +04:00
2012-05-22 21:23:33 +04:00
p = get_mount_parameters_fragment ( m ) ;
if ( ! p )
return 0 ;
2010-07-13 00:55:27 +04:00
2012-05-22 21:23:33 +04:00
if ( path_equal ( m - > where , " / " ) )
return 0 ;
if ( mount_is_network ( p ) )
after = SPECIAL_REMOTE_FS_PRE_TARGET ;
else
after = SPECIAL_LOCAL_FS_PRE_TARGET ;
r = unit_add_two_dependencies_by_name ( UNIT ( m ) , UNIT_WANTS , UNIT_AFTER , after , NULL , true ) ;
if ( r < 0 )
return r ;
r = unit_add_two_dependencies_by_name ( UNIT ( m ) , UNIT_BEFORE , UNIT_CONFLICTS , SPECIAL_UMOUNT_TARGET , NULL , true ) ;
if ( r < 0 )
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 ) ;
2012-05-22 21:23:33 +04:00
p = get_mount_parameters_fragment ( m ) ;
if ( ! p )
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 ;
2012-05-22 04:00:53 +04:00
else if ( ( timeout = mount_test_option ( p - > options , " x-systemd.device-timeout " ) ) )
2011-04-16 06:39:50 +04:00
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
}
2012-01-15 15:25:20 +04:00
SET_FOREACH ( other , UNIT ( m ) - > dependencies [ UNIT_AFTER ] , i ) {
2012-01-15 15:04:08 +04:00
if ( other - > type ! = UNIT_DEVICE )
2011-04-16 06:39:50 +04:00
continue ;
2012-01-15 15:04:08 +04:00
other - > job_timeout = u ;
2011-04-16 06:39:50 +04:00
}
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 ) ;
2012-01-15 15:25:20 +04:00
if ( UNIT ( m ) - > load_state ! = UNIT_LOADED )
2010-04-17 01:24:39 +04:00
return 0 ;
2012-05-22 21:23:33 +04:00
if ( ! m - > from_fragment & & ! m - > from_proc_self_mountinfo )
2010-05-21 05:32:21 +04:00
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 ) {
2012-01-15 15:25:20 +04:00
log_error ( " %s's Where setting doesn't match unit name. Refusing. " , UNIT ( m ) - > 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 ;
}
2012-01-15 15:25:20 +04:00
if ( UNIT ( m ) - > fragment_path & & ! m - > parameters_fragment . what ) {
log_error ( " %s's What setting is missing. Refusing. " , UNIT ( m ) - > id ) ;
2010-05-14 04:29:45 +04:00
return - EBADMSG ;
}
2012-07-20 01:47:10 +04:00
if ( m - > exec_context . pam_name & & m - > kill_context . kill_mode ! = KILL_CONTROL_GROUP ) {
2012-01-15 15:25:20 +04:00
log_error ( " %s has PAM enabled. Kill mode must be set to 'control-group'. Refusing. " , UNIT ( m ) - > id ) ;
2010-06-19 18:57:54 +04:00
return - EINVAL ;
}
2010-04-17 01:24:39 +04:00
return 0 ;
}
2012-06-29 03:47:24 +04:00
static int mount_add_extras ( Mount * m ) {
Unit * u = UNIT ( m ) ;
2010-04-10 19:53:17 +04:00
int r ;
2012-06-29 03:47:24 +04:00
r = unit_add_exec_dependencies ( u , & m - > exec_context ) ;
if ( r < 0 )
2010-04-10 19:53:17 +04:00
return r ;
2012-06-29 03:47:24 +04:00
if ( UNIT ( m ) - > fragment_path )
m - > from_fragment = true ;
2010-04-10 19:53:17 +04:00
2012-06-29 03:47:24 +04:00
if ( ! m - > where ) {
m - > where = unit_name_to_path ( u - > id ) ;
2010-04-21 05:27:44 +04:00
if ( ! m - > where )
2012-06-29 03:47:24 +04:00
return - ENOMEM ;
}
2010-04-21 05:27:44 +04:00
2012-06-29 03:47:24 +04:00
path_kill_slashes ( m - > where ) ;
2010-04-10 19:53:17 +04:00
2012-06-29 03:47:24 +04:00
if ( ! UNIT ( m ) - > description ) {
r = unit_set_description ( u , m - > where ) ;
if ( r < 0 )
2010-08-25 22:37:04 +04:00
return r ;
2012-06-29 03:47:24 +04:00
}
2010-05-13 05:07:16 +04:00
2012-06-29 03:47:24 +04:00
r = mount_add_device_links ( m ) ;
if ( r < 0 )
return r ;
2010-05-13 05:07:16 +04:00
2012-06-29 03:47:24 +04:00
r = mount_add_mount_links ( m ) ;
if ( r < 0 )
return r ;
2010-05-13 05:07:16 +04:00
2012-06-29 03:47:24 +04:00
r = mount_add_socket_links ( m ) ;
if ( r < 0 )
return r ;
2010-04-10 19:53:17 +04:00
2012-06-29 03:47:24 +04:00
r = mount_add_swap_links ( m ) ;
if ( r < 0 )
return r ;
2010-05-24 07:25:33 +04:00
2012-06-29 03:47:24 +04:00
r = mount_add_path_links ( m ) ;
if ( r < 0 )
return r ;
2012-04-29 16:26:07 +04:00
2012-06-29 03:47:24 +04:00
r = mount_add_requires_mounts_links ( m ) ;
if ( r < 0 )
return r ;
r = mount_add_automount_links ( m ) ;
if ( r < 0 )
return r ;
r = mount_add_quota_links ( m ) ;
if ( r < 0 )
return r ;
2010-04-10 19:53:17 +04:00
2012-06-29 03:47:24 +04:00
if ( UNIT ( m ) - > default_dependencies ) {
r = mount_add_default_dependencies ( m ) ;
2012-05-22 21:23:33 +04:00
if ( r < 0 )
2010-04-10 19:53:17 +04:00
return r ;
2012-06-29 03:47:24 +04:00
}
2010-07-10 04:41:06 +04:00
2012-06-29 03:47:24 +04:00
r = unit_add_default_cgroups ( u ) ;
if ( r < 0 )
return r ;
2011-04-16 06:39:50 +04:00
2012-06-29 03:47:24 +04:00
r = mount_fix_timeouts ( m ) ;
if ( r < 0 )
return r ;
return 0 ;
}
static int mount_load ( Unit * u ) {
Mount * m = MOUNT ( u ) ;
int r ;
assert ( u ) ;
assert ( u - > load_state = = UNIT_STUB ) ;
2012-06-29 03:50:31 +04:00
if ( m - > from_proc_self_mountinfo )
r = unit_load_fragment_and_dropin_optional ( u ) ;
else
r = unit_load_fragment_and_dropin ( u ) ;
2012-06-29 03:47:24 +04:00
if ( r < 0 )
return r ;
2011-04-20 02:45:22 +04:00
2012-06-29 03:47:24 +04:00
/* This is a new unit? Then let's add in some extras */
if ( u - > load_state = = UNIT_LOADED ) {
r = mount_add_extras ( m ) ;
if ( r < 0 )
return r ;
2012-07-16 14:44:42 +04:00
2012-07-20 02:09:35 +04:00
r = unit_exec_context_defaults ( u , & m - > exec_context ) ;
2012-07-16 14:44:42 +04:00
if ( r < 0 )
return r ;
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-15 15:25:20 +04:00
SET_FOREACH ( p , UNIT ( m ) - > dependencies [ UNIT_TRIGGERED_BY ] , i )
2012-01-15 15:04:08 +04:00
if ( p - > type = = UNIT_AUTOMOUNT ) {
2012-01-07 02:08:54 +04:00
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 | |
2012-06-05 23:10:28 +04:00
state = = MOUNT_FAILED ) {
if ( state ! = old_state )
mount_notify_automount ( m , - ENODEV ) ;
}
2010-04-17 01:24:39 +04:00
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 " ,
2012-01-15 15:25:20 +04:00
UNIT ( m ) - > 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
2012-02-03 06:10:56 +04:00
unit_notify ( UNIT ( m ) , state_translation_table [ old_state ] , state_translation_table [ state ] , m - > reload_result = = MOUNT_SUCCESS ) ;
m - > reload_result = MOUNT_SUCCESS ;
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 "
2012-02-03 06:27:25 +04:00
" %sResult: %s \n "
2010-04-10 19:53:17 +04:00
" %sWhere: %s \n "
" %sWhat: %s \n "
" %sFile System Type: %s \n "
" %sOptions: %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 ) ,
2012-02-03 06:27:25 +04:00
prefix , mount_result_to_string ( m - > result ) ,
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_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 ) ;
2012-07-20 01:47:10 +04:00
kill_context_dump ( & m - > kill_context , f , prefix ) ;
2010-04-10 19:53:17 +04:00
}
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 ,
2012-01-15 15:25:20 +04:00
UNIT ( m ) - > manager - > environment ,
2010-04-21 05:27:44 +04:00
true ,
true ,
2010-07-08 06:09:17 +04:00
true ,
2012-01-15 15:25:20 +04:00
UNIT ( m ) - > manager - > confirm_spawn ,
UNIT ( m ) - > cgroup_bondings ,
UNIT ( m ) - > cgroup_attributes ,
2012-04-14 01:24:47 +04:00
NULL ,
2012-06-22 00:40:47 +04:00
UNIT ( m ) - > id ,
2012-04-24 16:28:00 +04:00
NULL ,
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 ;
}
2012-02-03 06:10:56 +04:00
static void mount_enter_dead ( Mount * m , MountResult f ) {
2010-04-10 19:53:17 +04:00
assert ( m ) ;
2012-02-03 06:10:56 +04:00
if ( f ! = MOUNT_SUCCESS )
m - > result = f ;
2010-04-10 19:53:17 +04:00
2012-02-03 06:10:56 +04:00
mount_set_state ( m , m - > result ! = MOUNT_SUCCESS ? MOUNT_FAILED : MOUNT_DEAD ) ;
2010-04-10 19:53:17 +04:00
}
2012-02-03 06:10:56 +04:00
static void mount_enter_mounted ( Mount * m , MountResult f ) {
2010-04-13 04:06:27 +04:00
assert ( m ) ;
2012-02-03 06:10:56 +04:00
if ( f ! = MOUNT_SUCCESS )
m - > result = f ;
2010-04-13 04:06:27 +04:00
mount_set_state ( m , MOUNT_MOUNTED ) ;
}
2012-02-03 06:10:56 +04:00
static void mount_enter_signal ( Mount * m , MountState state , MountResult f ) {
2010-04-10 19:53:17 +04:00
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 ) ;
2012-02-03 06:10:56 +04:00
if ( f ! = MOUNT_SUCCESS )
m - > result = f ;
2010-04-10 19:53:17 +04:00
2012-07-20 01:47:10 +04:00
if ( m - > kill_context . kill_mode ! = KILL_NONE ) {
2010-04-13 04:06:27 +04:00
int sig = ( state = = MOUNT_MOUNTING_SIGTERM | |
state = = MOUNT_UNMOUNTING_SIGTERM | |
2012-07-20 01:47:10 +04:00
state = = MOUNT_REMOUNTING_SIGTERM ) ? m - > kill_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
}
2012-07-20 01:47:10 +04:00
if ( m - > kill_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 ;
2012-05-03 23:54:44 +04:00
r = cgroup_bonding_kill_list ( UNIT ( m ) - > cgroup_bondings , sig , true , false , pid_set , NULL ) ;
2012-04-14 01:24:47 +04:00
if ( r < 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 )
2012-02-03 06:10:56 +04:00
mount_enter_mounted ( m , MOUNT_SUCCESS ) ;
2010-04-13 04:06:27 +04:00
else
2012-02-03 06:10:56 +04:00
mount_enter_dead ( m , MOUNT_SUCCESS ) ;
2010-04-10 19:53:17 +04:00
return ;
fail :
2012-01-15 15:25:20 +04:00
log_warning ( " %s failed to kill processes: %s " , UNIT ( m ) - > 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 )
2012-02-03 06:10:56 +04:00
mount_enter_mounted ( m , MOUNT_FAILURE_RESOURCES ) ;
2010-04-13 04:06:27 +04:00
else
2012-02-03 06:10:56 +04:00
mount_enter_dead ( m , MOUNT_FAILURE_RESOURCES ) ;
2010-09-01 01:24:47 +04:00
if ( pid_set )
set_free ( pid_set ) ;
2010-04-10 19:53:17 +04:00
}
2012-02-03 06:10:56 +04:00
static void mount_enter_unmounting ( Mount * m ) {
2010-04-10 19:53:17 +04:00
int r ;
assert ( m ) ;
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 :
2012-01-15 15:25:20 +04:00
log_warning ( " %s failed to run 'umount' task: %s " , UNIT ( m ) - > id , strerror ( - r ) ) ;
2012-02-03 06:10:56 +04:00
mount_enter_mounted ( m , MOUNT_FAILURE_RESOURCES ) ;
2010-04-10 19:53:17 +04:00
}
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
2012-05-31 14:40:20 +04:00
mkdir_p_label ( m - > where , m - > directory_mode ) ;
2010-07-02 02:28:44 +04:00
2012-09-18 20:40:31 +04:00
if ( dir_is_empty ( m - > where ) < = 0 )
log_notice ( " %s: Directory %s to mount over is not empty, ignoring. (To see the over-mounted files, please manually mount the underlying file system to a secondary location.) " , m - > meta . id , m - > where ) ;
2011-03-30 03:53:34 +04:00
/* Create the source directory for bind-mounts if needed */
2012-05-22 21:23:33 +04:00
p = get_mount_parameters_fragment ( m ) ;
2011-03-30 03:53:34 +04:00
if ( p & & mount_is_bind ( p ) )
2012-05-31 14:40:20 +04:00
mkdir_p_label ( 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
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
2012-09-18 20:40:31 +04:00
r = mount_spawn ( m , m - > control_command , & m - > control_pid ) ;
if ( r < 0 )
2010-04-10 19:53:17 +04:00
goto fail ;
mount_set_state ( m , MOUNT_MOUNTING ) ;
return ;
fail :
2012-01-15 15:25:20 +04:00
log_warning ( " %s failed to run 'mount' task: %s " , UNIT ( m ) - > id , strerror ( - r ) ) ;
2012-02-03 06:10:56 +04:00
mount_enter_dead ( m , MOUNT_FAILURE_RESOURCES ) ;
2010-04-10 19:53:17 +04:00
}
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 ) ;
}
2012-02-03 06:10:56 +04:00
static void mount_enter_remounting ( Mount * m ) {
2010-04-10 19:53:17 +04:00
int r ;
assert ( m ) ;
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 ) ;
2012-05-22 21:23:33 +04:00
} else
2010-04-10 19:53:17 +04:00
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 :
2012-01-15 15:25:20 +04:00
log_warning ( " %s failed to run 'remount' task: %s " , UNIT ( m ) - > id , strerror ( - r ) ) ;
2012-02-03 06:10:56 +04:00
m - > reload_result = MOUNT_FAILURE_RESOURCES ;
mount_enter_mounted ( m , MOUNT_SUCCESS ) ;
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
2012-02-03 06:10:56 +04:00
m - > result = MOUNT_SUCCESS ;
m - > reload_result = MOUNT_SUCCESS ;
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
2012-02-03 06:10:56 +04:00
mount_enter_unmounting ( m ) ;
2010-04-10 19:53:17 +04:00
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 ) ;
2012-02-03 06:10:56 +04:00
mount_enter_remounting ( m ) ;
2010-04-10 19:53:17 +04:00
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 ) ) ;
2012-02-03 06:10:56 +04:00
unit_serialize_item ( u , f , " result " , mount_result_to_string ( m - > result ) ) ;
unit_serialize_item ( u , f , " reload-result " , mount_result_to_string ( m - > reload_result ) ) ;
2010-04-21 05:27:44 +04:00
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 ;
2012-02-03 06:10:56 +04:00
} else if ( streq ( key , " result " ) ) {
MountResult f ;
2010-04-21 05:27:44 +04:00
2012-02-03 06:10:56 +04:00
f = mount_result_from_string ( value ) ;
if ( f < 0 )
log_debug ( " Failed to parse result value %s " , value ) ;
else if ( f ! = MOUNT_SUCCESS )
m - > result = f ;
} else if ( streq ( key , " reload-result " ) ) {
MountResult f ;
f = mount_result_from_string ( value ) ;
if ( f < 0 )
log_debug ( " Failed to parse reload result value %s " , value ) ;
else if ( f ! = MOUNT_SUCCESS )
m - > reload_result = f ;
2010-04-21 05:27:44 +04:00
} 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 ) ;
2012-05-22 21:23:33 +04:00
return m - > from_proc_self_mountinfo ;
2010-04-21 08:01:13 +04:00
}
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 ) ;
2012-02-03 06:10:56 +04:00
MountResult f ;
2010-04-10 19:53:17 +04:00
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 ;
2012-08-13 15:58:01 +04:00
if ( is_clean_exit ( code , status , NULL ) )
2012-02-03 06:10:56 +04:00
f = MOUNT_SUCCESS ;
else if ( code = = CLD_EXITED )
f = MOUNT_FAILURE_EXIT_CODE ;
else if ( code = = CLD_KILLED )
f = MOUNT_FAILURE_SIGNAL ;
else if ( code = = CLD_DUMPED )
f = MOUNT_FAILURE_CORE_DUMP ;
else
assert_not_reached ( " Unknown code " ) ;
if ( f ! = MOUNT_SUCCESS )
m - > result = f ;
2010-06-16 07:10:31 +04:00
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 ) ;
2012-02-03 06:10:56 +04:00
2010-04-21 05:27:44 +04:00
m - > control_command = NULL ;
m - > control_command_id = _MOUNT_EXEC_COMMAND_INVALID ;
}
2012-02-03 06:10:56 +04:00
log_full ( f = = MOUNT_SUCCESS ? LOG_DEBUG : LOG_NOTICE ,
2012-01-15 15:04:08 +04:00
" %s mount process exited, code=%s status=%i " , u - > 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 :
2012-02-03 06:10:56 +04:00
if ( f = = MOUNT_SUCCESS )
mount_enter_mounted ( m , f ) ;
2010-04-10 19:53:17 +04:00
else if ( m - > from_proc_self_mountinfo )
2012-02-03 06:10:56 +04:00
mount_enter_mounted ( m , f ) ;
2010-04-10 19:53:17 +04:00
else
2012-02-03 06:10:56 +04:00
mount_enter_dead ( m , f ) ;
2010-04-10 19:53:17 +04:00
break ;
2011-01-20 15:17:22 +03:00
case MOUNT_REMOUNTING :
case MOUNT_REMOUNTING_SIGKILL :
case MOUNT_REMOUNTING_SIGTERM :
2012-02-03 06:10:56 +04:00
m - > reload_result = f ;
2011-01-20 15:17:22 +03:00
if ( m - > from_proc_self_mountinfo )
2012-02-03 06:10:56 +04:00
mount_enter_mounted ( m , MOUNT_SUCCESS ) ;
2011-01-20 15:17:22 +03:00
else
2012-02-03 06:10:56 +04:00
mount_enter_dead ( m , MOUNT_SUCCESS ) ;
2011-01-20 15:17:22 +03:00
break ;
2010-04-10 19:53:17 +04:00
case MOUNT_UNMOUNTING :
case MOUNT_UNMOUNTING_SIGKILL :
case MOUNT_UNMOUNTING_SIGTERM :
2012-02-03 06:10:56 +04:00
if ( f = = MOUNT_SUCCESS )
mount_enter_dead ( m , f ) ;
2010-04-10 19:53:17 +04:00
else if ( m - > from_proc_self_mountinfo )
2012-02-03 06:10:56 +04:00
mount_enter_mounted ( m , f ) ;
2010-04-10 19:53:17 +04:00
else
2012-02-03 06:10:56 +04:00
mount_enter_dead ( m , f ) ;
2010-04-10 19:53:17 +04:00
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 :
2012-01-15 15:04:08 +04:00
log_warning ( " %s mounting timed out. Stopping. " , u - > id ) ;
2012-02-03 06:10:56 +04:00
mount_enter_signal ( m , MOUNT_MOUNTING_SIGTERM , MOUNT_FAILURE_TIMEOUT ) ;
2010-04-10 19:53:17 +04:00
break ;
case MOUNT_REMOUNTING :
2012-01-15 15:04:08 +04:00
log_warning ( " %s remounting timed out. Stopping. " , u - > id ) ;
2012-02-03 06:10:56 +04:00
m - > reload_result = MOUNT_FAILURE_TIMEOUT ;
mount_enter_mounted ( m , MOUNT_SUCCESS ) ;
2010-04-10 19:53:17 +04:00
break ;
case MOUNT_UNMOUNTING :
2012-01-15 15:04:08 +04:00
log_warning ( " %s unmounting timed out. Stopping. " , u - > id ) ;
2012-02-03 06:10:56 +04:00
mount_enter_signal ( m , MOUNT_UNMOUNTING_SIGTERM , MOUNT_FAILURE_TIMEOUT ) ;
2010-04-10 19:53:17 +04:00
break ;
case MOUNT_MOUNTING_SIGTERM :
2012-07-20 01:47:10 +04:00
if ( m - > kill_context . send_sigkill ) {
2012-01-15 15:04:08 +04:00
log_warning ( " %s mounting timed out. Killing. " , u - > id ) ;
2012-02-03 06:10:56 +04:00
mount_enter_signal ( m , MOUNT_MOUNTING_SIGKILL , MOUNT_FAILURE_TIMEOUT ) ;
2011-01-19 00:55:54 +03:00
} else {
2012-01-15 15:04:08 +04:00
log_warning ( " %s mounting timed out. Skipping SIGKILL. Ignoring. " , u - > id ) ;
2011-01-19 00:55:54 +03:00
if ( m - > from_proc_self_mountinfo )
2012-02-03 06:10:56 +04:00
mount_enter_mounted ( m , MOUNT_FAILURE_TIMEOUT ) ;
2011-01-19 00:55:54 +03:00
else
2012-02-03 06:10:56 +04:00
mount_enter_dead ( m , MOUNT_FAILURE_TIMEOUT ) ;
2011-01-19 00:55:54 +03:00
}
2010-04-10 19:53:17 +04:00
break ;
case MOUNT_REMOUNTING_SIGTERM :
2012-07-20 01:47:10 +04:00
if ( m - > kill_context . send_sigkill ) {
2012-01-15 15:04:08 +04:00
log_warning ( " %s remounting timed out. Killing. " , u - > id ) ;
2012-02-03 06:10:56 +04:00
mount_enter_signal ( m , MOUNT_REMOUNTING_SIGKILL , MOUNT_FAILURE_TIMEOUT ) ;
2011-01-19 00:55:54 +03:00
} else {
2012-01-15 15:04:08 +04:00
log_warning ( " %s remounting timed out. Skipping SIGKILL. Ignoring. " , u - > id ) ;
2011-01-19 00:55:54 +03:00
if ( m - > from_proc_self_mountinfo )
2012-02-03 06:10:56 +04:00
mount_enter_mounted ( m , MOUNT_FAILURE_TIMEOUT ) ;
2011-01-19 00:55:54 +03:00
else
2012-02-03 06:10:56 +04:00
mount_enter_dead ( m , MOUNT_FAILURE_TIMEOUT ) ;
2011-01-19 00:55:54 +03:00
}
2010-04-10 19:53:17 +04:00
break ;
case MOUNT_UNMOUNTING_SIGTERM :
2012-07-20 01:47:10 +04:00
if ( m - > kill_context . send_sigkill ) {
2012-01-15 15:04:08 +04:00
log_warning ( " %s unmounting timed out. Killing. " , u - > id ) ;
2012-02-03 06:10:56 +04:00
mount_enter_signal ( m , MOUNT_UNMOUNTING_SIGKILL , MOUNT_FAILURE_TIMEOUT ) ;
2011-01-19 00:55:54 +03:00
} else {
2012-01-15 15:04:08 +04:00
log_warning ( " %s unmounting timed out. Skipping SIGKILL. Ignoring. " , u - > id ) ;
2011-01-19 00:55:54 +03:00
if ( m - > from_proc_self_mountinfo )
2012-02-03 06:10:56 +04:00
mount_enter_mounted ( m , MOUNT_FAILURE_TIMEOUT ) ;
2011-01-19 00:55:54 +03:00
else
2012-02-03 06:10:56 +04:00
mount_enter_dead ( m , MOUNT_FAILURE_TIMEOUT ) ;
2011-01-19 00:55:54 +03:00
}
2010-04-10 19:53:17 +04:00
break ;
case MOUNT_MOUNTING_SIGKILL :
case MOUNT_REMOUNTING_SIGKILL :
case MOUNT_UNMOUNTING_SIGKILL :
2012-01-15 15:04:08 +04:00
log_warning ( " %s mount process still around after SIGKILL. Ignoring. " , u - > id ) ;
2010-04-10 19:53:17 +04:00
if ( m - > from_proc_self_mountinfo )
2012-02-03 06:10:56 +04:00
mount_enter_mounted ( m , MOUNT_FAILURE_TIMEOUT ) ;
2010-04-10 19:53:17 +04:00
else
2012-02-03 06:10:56 +04:00
mount_enter_dead ( m , MOUNT_FAILURE_TIMEOUT ) ;
2010-04-10 19:53:17 +04:00
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 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 ) ;
/* 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 ) ;
2012-06-29 03:50:31 +04:00
if ( u - > load_state = = UNIT_ERROR ) {
u - > load_state = UNIT_LOADED ;
u - > load_error = 0 ;
r = mount_add_extras ( MOUNT ( u ) ) ;
if ( r < 0 )
goto fail ;
}
2010-01-29 04:07:41 +03:00
}
2010-04-10 19:53:17 +04:00
if ( ! ( w = strdup ( what ) ) | |
! ( o = strdup ( options ) ) | |
! ( f = strdup ( fstype ) ) ) {
r = - ENOMEM ;
goto fail ;
}
2012-05-22 21:23:33 +04:00
p = & MOUNT ( u ) - > parameters_proc_self_mountinfo ;
if ( set_flags ) {
MOUNT ( u ) - > is_mounted = true ;
MOUNT ( u ) - > just_mounted = ! MOUNT ( u ) - > from_proc_self_mountinfo ;
MOUNT ( u ) - > just_changed = ! streq_ptr ( p - > options , o ) ;
2010-01-29 08:04:08 +03:00
}
2010-01-29 05:18:09 +03:00
2012-05-22 21:23:33 +04:00
MOUNT ( u ) - > from_proc_self_mountinfo = true ;
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-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
}
2012-07-13 15:41:01 +04:00
o = strjoin ( options , " , " , options2 , NULL ) ;
2012-05-21 19:22:36 +04:00
if ( ! o ) {
2010-06-03 01:03:39 +04:00
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
}
2012-05-22 21:23:33 +04:00
if ( ( k = mount_add_one ( m , d , p , o , fstype , 0 , 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
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 ) {
2012-01-15 15:37:16 +04:00
Unit * u ;
2010-01-29 08:04:08 +03:00
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 */
2012-01-15 15:37:16 +04:00
LIST_FOREACH ( units_by_type , u , m - > units_by_type [ UNIT_MOUNT ] ) {
Mount * mount = MOUNT ( u ) ;
2010-04-10 19:53:17 +04:00
mount - > is_mounted = mount - > just_mounted = mount - > just_changed = false ;
}
2010-01-29 08:04:08 +03:00
return ;
}
manager_dispatch_load_queue ( m ) ;
2012-01-15 15:37:16 +04:00
LIST_FOREACH ( units_by_type , u , m - > units_by_type [ UNIT_MOUNT ] ) {
Mount * mount = MOUNT ( u ) ;
2010-01-29 08:04:08 +03:00
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 :
2012-02-03 06:10:56 +04:00
mount_enter_dead ( mount , MOUNT_SUCCESS ) ;
2010-04-10 19:53:17 +04:00
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 :
2012-02-03 06:10:56 +04:00
mount_enter_mounted ( mount , MOUNT_SUCCESS ) ;
2010-04-10 19:53:17 +04:00
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 ) ;
2012-02-03 06:10:56 +04:00
m - > result = MOUNT_SUCCESS ;
m - > reload_result = MOUNT_SUCCESS ;
2010-07-18 06:58:01 +04:00
}
2012-07-20 02:00:04 +04:00
static int mount_kill ( Unit * u , KillWho who , int signo , DBusError * error ) {
2010-10-22 18:11:50 +04:00
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
2012-07-20 02:00:04 +04:00
if ( who = = KILL_ALL ) {
2010-10-22 18:11:50 +04:00
int q ;
2012-07-20 02:00:04 +04:00
pid_set = set_new ( trivial_hash_func , trivial_compare_func ) ;
if ( ! pid_set )
2010-10-22 18:11:50 +04:00
return - ENOMEM ;
/* Exclude the control pid from being killed via the cgroup */
2012-07-20 02:00:04 +04:00
if ( m - > control_pid > 0 ) {
q = set_put ( pid_set , LONG_TO_PTR ( m - > control_pid ) ) ;
if ( q < 0 ) {
2010-10-22 18:11:50 +04:00
r = q ;
goto finish ;
}
2012-07-20 02:00:04 +04:00
}
2010-10-22 18:11:50 +04:00
2012-05-03 23:54:44 +04:00
q = cgroup_bonding_kill_list ( UNIT ( m ) - > cgroup_bondings , signo , false , false , pid_set , NULL ) ;
2012-07-20 02:00:04 +04:00
if ( q < 0 & & q ! = - EAGAIN & & q ! = - ESRCH & & q ! = - ENOENT )
r = q ;
2010-10-22 18:11:50 +04:00
}
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 ) ;
2012-02-03 06:10:56 +04:00
static const char * const mount_result_table [ _MOUNT_RESULT_MAX ] = {
[ MOUNT_SUCCESS ] = " success " ,
[ MOUNT_FAILURE_RESOURCES ] = " resources " ,
[ MOUNT_FAILURE_TIMEOUT ] = " timeout " ,
[ MOUNT_FAILURE_EXIT_CODE ] = " exit-code " ,
[ MOUNT_FAILURE_SIGNAL ] = " signal " ,
[ MOUNT_FAILURE_CORE_DUMP ] = " core-dump "
} ;
DEFINE_STRING_TABLE_LOOKUP ( mount_result , MountResult ) ;
2010-01-26 23:39:06 +03:00
const UnitVTable mount_vtable = {
2012-01-15 13:53:49 +04:00
. object_size = sizeof ( Mount ) ,
2012-09-18 13:40:01 +04:00
. exec_context_offset = offsetof ( Mount , exec_context ) ,
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-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 ,
2012-05-13 20:18:54 +04:00
. shutdown = mount_shutdown ,
. status_message_formats = {
. starting_stopping = {
[ 0 ] = " Mounting %s... " ,
[ 1 ] = " Unmounting %s... " ,
} ,
. finished_start_job = {
[ JOB_DONE ] = " Mounted %s. " ,
[ JOB_FAILED ] = " Failed to mount %s. " ,
[ JOB_DEPENDENCY ] = " Dependency failed for %s. " ,
[ JOB_TIMEOUT ] = " Timed out mounting %s. " ,
} ,
. finished_stop_job = {
[ JOB_DONE ] = " Unmounted %s. " ,
[ JOB_FAILED ] = " Failed unmounting %s. " ,
[ JOB_TIMEOUT ] = " Timed out unmounting %s. " ,
} ,
} ,
2010-01-23 03:52:57 +03:00
} ;