2010-08-14 21:59:25 +04:00
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2010-05-09 20:44:11 +04: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/>.
* * */
# include <errno.h>
# include <limits.h>
# include <unistd.h>
# include <fcntl.h>
# include <sys/epoll.h>
# include <sys/stat.h>
# include <sys/swap.h>
2010-10-12 06:07:43 +04:00
# include <libudev.h>
2010-05-09 20:44:11 +04:00
# include "unit.h"
# include "swap.h"
# include "load-fragment.h"
# include "load-dropin.h"
# include "unit-name.h"
# include "dbus-swap.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-05-09 20:44:11 +04:00
static const UnitActiveState state_translation_table [ _SWAP_STATE_MAX ] = {
[ SWAP_DEAD ] = UNIT_INACTIVE ,
2010-10-12 06:07:43 +04:00
[ SWAP_ACTIVATING ] = UNIT_ACTIVATING ,
2010-05-09 20:44:11 +04:00
[ SWAP_ACTIVE ] = UNIT_ACTIVE ,
2010-10-12 06:07:43 +04:00
[ SWAP_DEACTIVATING ] = UNIT_DEACTIVATING ,
[ SWAP_ACTIVATING_SIGTERM ] = UNIT_DEACTIVATING ,
[ SWAP_ACTIVATING_SIGKILL ] = UNIT_DEACTIVATING ,
[ SWAP_DEACTIVATING_SIGTERM ] = UNIT_DEACTIVATING ,
[ SWAP_DEACTIVATING_SIGKILL ] = UNIT_DEACTIVATING ,
2010-08-31 02:23:34 +04:00
[ SWAP_FAILED ] = UNIT_FAILED
2010-05-09 20:44:11 +04:00
} ;
2010-10-12 06:07:43 +04:00
static void swap_unset_proc_swaps ( Swap * s ) {
Swap * first ;
assert ( s ) ;
if ( ! s - > parameters_proc_swaps . what )
return ;
/* Remove this unit from the chain of swaps which share the
* same kernel swap device . */
2012-01-15 15:25:20 +04:00
first = hashmap_get ( UNIT ( s ) - > manager - > swaps_by_proc_swaps , s - > parameters_proc_swaps . what ) ;
2010-10-12 06:07:43 +04:00
LIST_REMOVE ( Swap , same_proc_swaps , first , s ) ;
if ( first )
2012-01-15 15:25:20 +04:00
hashmap_remove_and_replace ( UNIT ( s ) - > manager - > swaps_by_proc_swaps , s - > parameters_proc_swaps . what , first - > parameters_proc_swaps . what , first ) ;
2010-10-12 06:07:43 +04:00
else
2012-01-15 15:25:20 +04:00
hashmap_remove ( UNIT ( s ) - > manager - > swaps_by_proc_swaps , s - > parameters_proc_swaps . what ) ;
2010-10-12 06:07:43 +04:00
free ( s - > parameters_proc_swaps . what ) ;
s - > parameters_proc_swaps . what = NULL ;
}
2011-11-19 05:47:09 +04:00
static void swap_init ( Unit * u ) {
2010-05-10 01:41:03 +04:00
Swap * s = SWAP ( u ) ;
assert ( s ) ;
2012-01-15 15:25:20 +04:00
assert ( UNIT ( s ) - > load_state = = UNIT_STUB ) ;
2010-05-10 01:41:03 +04:00
2010-10-12 06:07:43 +04:00
s - > timeout_usec = DEFAULT_TIMEOUT_USEC ;
exec_context_init ( & s - > exec_context ) ;
2012-01-15 15:04:08 +04:00
s - > exec_context . std_output = u - > manager - > default_std_output ;
s - > exec_context . std_error = u - > manager - > default_std_error ;
2010-10-12 06:07:43 +04:00
2010-05-14 04:29:45 +04:00
s - > parameters_etc_fstab . priority = s - > parameters_proc_swaps . priority = s - > parameters_fragment . priority = - 1 ;
2010-10-12 06:07:43 +04:00
s - > timer_watch . type = WATCH_INVALID ;
s - > control_command_id = _MOUNT_EXEC_COMMAND_INVALID ;
2011-04-14 05:55:03 +04:00
2012-01-15 15:25:20 +04:00
UNIT ( s ) - > ignore_on_isolate = true ;
2010-10-12 06:07:43 +04:00
}
static void swap_unwatch_control_pid ( Swap * s ) {
assert ( s ) ;
if ( s - > control_pid < = 0 )
return ;
unit_unwatch_pid ( UNIT ( s ) , s - > control_pid ) ;
s - > control_pid = 0 ;
2010-05-10 01:41:03 +04:00
}
2010-05-14 04:29:45 +04:00
static void swap_done ( Unit * u ) {
Swap * s = SWAP ( u ) ;
2010-05-09 20:44:11 +04:00
2010-05-14 04:29:45 +04:00
assert ( s ) ;
2010-05-09 20:44:11 +04:00
2010-10-12 06:07:43 +04:00
swap_unset_proc_swaps ( s ) ;
2010-05-14 04:29:45 +04:00
free ( s - > what ) ;
2010-10-12 06:07:43 +04:00
s - > what = NULL ;
2010-05-14 04:29:45 +04:00
free ( s - > parameters_etc_fstab . what ) ;
free ( s - > parameters_fragment . what ) ;
2010-10-12 06:07:43 +04:00
s - > parameters_etc_fstab . what = s - > parameters_fragment . what = NULL ;
exec_context_done ( & s - > exec_context ) ;
exec_command_done_array ( s - > exec_command , _SWAP_EXEC_COMMAND_MAX ) ;
s - > control_command = NULL ;
swap_unwatch_control_pid ( s ) ;
unit_unwatch_timer ( u , & s - > timer_watch ) ;
2010-05-09 20:44:11 +04:00
}
2010-05-13 05:07:16 +04:00
int swap_add_one_mount_link ( Swap * s , Mount * m ) {
int r ;
assert ( s ) ;
assert ( m ) ;
2012-01-15 15:25:20 +04:00
if ( UNIT ( s ) - > load_state ! = UNIT_LOADED | |
UNIT ( m ) - > load_state ! = UNIT_LOADED )
2010-05-13 05:07:16 +04:00
return 0 ;
2010-05-16 20:13:58 +04:00
if ( is_device_path ( s - > what ) )
return 0 ;
2010-05-13 05:07:16 +04:00
if ( ! path_startswith ( s - > what , m - > where ) )
return 0 ;
2010-07-03 21:46:38 +04:00
if ( ( r = unit_add_two_dependencies ( UNIT ( s ) , UNIT_AFTER , UNIT_REQUIRES , UNIT ( m ) , true ) ) < 0 )
2010-05-13 05:07:16 +04:00
return r ;
return 0 ;
}
static int swap_add_mount_links ( Swap * s ) {
2012-01-15 15:04:08 +04:00
Unit * other ;
2010-05-13 05:07:16 +04:00
int r ;
assert ( s ) ;
2012-01-15 15:25:20 +04:00
LIST_FOREACH ( units_by_type , other , UNIT ( s ) - > manager - > units_by_type [ UNIT_MOUNT ] )
2012-01-15 15:37:16 +04:00
if ( ( r = swap_add_one_mount_link ( s , MOUNT ( other ) ) ) < 0 )
2010-05-13 05:07:16 +04:00
return r ;
return 0 ;
}
2010-05-09 20:44:11 +04:00
static int swap_add_target_links ( Swap * s ) {
Unit * tu ;
2010-05-14 04:29:45 +04:00
SwapParameters * p ;
2010-05-09 20:44:11 +04:00
int r ;
2010-05-14 04:29:45 +04:00
assert ( s ) ;
if ( s - > from_fragment )
p = & s - > parameters_fragment ;
else if ( s - > from_etc_fstab )
p = & s - > parameters_etc_fstab ;
else
return 0 ;
2012-01-15 15:25:20 +04:00
if ( ( r = manager_load_unit ( UNIT ( s ) - > manager , SPECIAL_SWAP_TARGET , NULL , NULL , & tu ) ) < 0 )
2010-05-09 20:44:11 +04:00
return r ;
2010-08-25 23:24:21 +04:00
if ( ! p - > noauto & &
2011-02-15 20:38:15 +03:00
! p - > nofail & &
2012-01-15 15:25:20 +04:00
( p - > handle | | UNIT ( s ) - > manager - > swap_auto ) & &
2010-10-27 00:58:54 +04:00
s - > from_etc_fstab & &
2012-01-15 15:25:20 +04:00
UNIT ( s ) - > manager - > running_as = = MANAGER_SYSTEM )
2010-05-13 05:07:16 +04:00
if ( ( r = unit_add_dependency ( tu , UNIT_WANTS , UNIT ( s ) , true ) ) < 0 )
return r ;
2010-05-09 20:44:11 +04:00
return unit_add_dependency ( UNIT ( s ) , UNIT_BEFORE , tu , true ) ;
}
2010-08-25 22:37:04 +04:00
static int swap_add_device_links ( Swap * s ) {
SwapParameters * p ;
assert ( s ) ;
if ( ! s - > what )
return 0 ;
if ( s - > from_fragment )
p = & s - > parameters_fragment ;
else if ( s - > from_etc_fstab )
p = & s - > parameters_etc_fstab ;
else
return 0 ;
2010-11-22 23:06:38 +03:00
if ( is_device_path ( s - > what ) )
return unit_add_node_link ( UNIT ( s ) , s - > what ,
! p - > noauto & & p - > nofail & &
2012-01-15 15:25:20 +04:00
UNIT ( s ) - > manager - > running_as = = MANAGER_SYSTEM ) ;
2010-11-22 23:06:38 +03:00
else
/* File based swap devices need to be ordered after
* remount - rootfs . service , since they might need a
* writable file system . */
return unit_add_dependency_by_name ( UNIT ( s ) , UNIT_AFTER , SPECIAL_REMOUNT_ROOTFS_SERVICE , NULL , true ) ;
2010-08-25 22:37:04 +04:00
}
2010-07-13 00:55:27 +04:00
static int swap_add_default_dependencies ( Swap * s ) {
int r ;
assert ( s ) ;
2012-01-15 15:25:20 +04:00
if ( UNIT ( s ) - > manager - > running_as = = MANAGER_SYSTEM ) {
2010-07-13 00:55:27 +04:00
2010-10-29 03:15:18 +04:00
if ( ( r = unit_add_two_dependencies_by_name ( UNIT ( s ) , UNIT_BEFORE , UNIT_CONFLICTS , SPECIAL_UMOUNT_TARGET , NULL , true ) ) < 0 )
2010-10-12 06:07:43 +04:00
return r ;
2010-07-13 00:55:27 +04:00
}
return 0 ;
}
2010-05-14 04:29:45 +04:00
static int swap_verify ( Swap * s ) {
bool b ;
char * e ;
2012-01-15 15:25:20 +04:00
if ( UNIT ( s ) - > load_state ! = UNIT_LOADED )
2010-05-14 04:29:45 +04:00
return 0 ;
if ( ! ( e = unit_name_from_path ( s - > what , " .swap " ) ) )
return - ENOMEM ;
b = unit_has_name ( UNIT ( s ) , e ) ;
free ( e ) ;
if ( ! b ) {
2012-01-15 15:25:20 +04:00
log_error ( " %s: Value of \" What \" and unit name do not match, not loading. \n " , UNIT ( s ) - > id ) ;
2010-05-14 04:29:45 +04:00
return - EINVAL ;
}
2010-10-12 06:07:43 +04:00
if ( s - > exec_context . pam_name & & s - > exec_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 ( s ) - > id ) ;
2010-10-12 06:07:43 +04:00
return - EINVAL ;
}
2010-05-14 04:29:45 +04:00
return 0 ;
}
2010-05-09 20:44:11 +04:00
static int swap_load ( Unit * u ) {
int r ;
Swap * s = SWAP ( u ) ;
assert ( s ) ;
2012-01-15 15:04:08 +04:00
assert ( u - > load_state = = UNIT_STUB ) ;
2010-05-09 20:44:11 +04:00
/* Load a .swap file */
if ( ( r = unit_load_fragment_and_dropin_optional ( u ) ) < 0 )
return r ;
2012-01-15 15:04:08 +04:00
if ( u - > load_state = = UNIT_LOADED ) {
2011-02-15 14:28:26 +03:00
if ( ( r = unit_add_exec_dependencies ( u , & s - > exec_context ) ) < 0 )
return r ;
2010-05-14 04:29:45 +04:00
2012-01-15 15:25:20 +04:00
if ( UNIT ( s ) - > fragment_path )
2010-05-14 04:29:45 +04:00
s - > from_fragment = true ;
if ( ! s - > what ) {
if ( s - > parameters_fragment . what )
s - > what = strdup ( s - > parameters_fragment . what ) ;
else if ( s - > parameters_etc_fstab . what )
s - > what = strdup ( s - > parameters_etc_fstab . what ) ;
else if ( s - > parameters_proc_swaps . what )
s - > what = strdup ( s - > parameters_proc_swaps . what ) ;
else
2012-01-15 15:04:08 +04:00
s - > what = unit_name_to_path ( u - > id ) ;
2010-05-14 04:29:45 +04:00
if ( ! s - > what )
2010-05-09 20:44:11 +04:00
return - ENOMEM ;
2010-05-14 04:29:45 +04:00
}
2010-05-09 20:44:11 +04:00
path_kill_slashes ( s - > what ) ;
2012-01-15 15:25:20 +04:00
if ( ! UNIT ( s ) - > description )
2010-05-14 04:29:45 +04:00
if ( ( r = unit_set_description ( u , s - > what ) ) < 0 )
return r ;
2010-08-25 22:37:04 +04:00
if ( ( r = swap_add_device_links ( s ) ) < 0 )
2010-05-09 20:44:11 +04:00
return r ;
2010-05-13 05:07:16 +04:00
if ( ( r = swap_add_mount_links ( s ) ) < 0 )
return r ;
2010-05-09 20:44:11 +04:00
if ( ( r = swap_add_target_links ( s ) ) < 0 )
return r ;
2010-07-13 00:55:27 +04:00
2010-11-17 23:27:53 +03:00
if ( ( r = unit_add_default_cgroups ( u ) ) < 0 )
2010-10-27 00:06:11 +04:00
return r ;
2012-01-15 15:25:20 +04:00
if ( UNIT ( s ) - > default_dependencies )
2010-07-13 00:55:27 +04:00
if ( ( r = swap_add_default_dependencies ( s ) ) < 0 )
return r ;
2010-05-09 20:44:11 +04:00
}
return swap_verify ( s ) ;
}
2010-05-14 04:29:45 +04:00
int swap_add_one (
Manager * m ,
const char * what ,
2010-10-12 06:07:43 +04:00
const char * what_proc_swaps ,
2010-05-14 04:29:45 +04:00
int priority ,
bool noauto ,
2010-08-25 22:37:04 +04:00
bool nofail ,
2010-05-14 04:29:45 +04:00
bool handle ,
2010-10-12 06:07:43 +04:00
bool set_flags ) {
2010-05-14 04:29:45 +04:00
Unit * u = NULL ;
2010-10-12 06:07:43 +04:00
char * e = NULL , * wp = NULL ;
2010-06-02 20:54:50 +04:00
bool delete = false ;
2010-05-09 20:44:11 +04:00
int r ;
2010-05-14 04:29:45 +04:00
SwapParameters * p ;
assert ( m ) ;
assert ( what ) ;
2010-05-09 20:44:11 +04:00
2012-01-15 13:53:49 +04:00
e = unit_name_from_path ( what , " .swap " ) ;
if ( ! e )
2010-05-09 20:44:11 +04:00
return - ENOMEM ;
2010-10-12 06:07:43 +04:00
u = manager_get_unit ( m , e ) ;
if ( what_proc_swaps & &
u & &
SWAP ( u ) - > from_proc_swaps & &
! path_equal ( SWAP ( u ) - > parameters_proc_swaps . what , what_proc_swaps ) )
return - EEXIST ;
2010-05-14 04:29:45 +04:00
if ( ! u ) {
2010-05-09 20:44:11 +04:00
delete = true ;
2012-01-15 13:53:49 +04:00
u = unit_new ( m , sizeof ( Swap ) ) ;
if ( ! u ) {
2010-05-09 20:44:11 +04:00
free ( e ) ;
return - ENOMEM ;
}
2010-10-12 06:07:43 +04:00
2012-01-15 13:53:49 +04:00
r = unit_add_name ( u , e ) ;
if ( r < 0 )
2010-10-12 06:07:43 +04:00
goto fail ;
2012-01-15 13:53:49 +04:00
SWAP ( u ) - > what = strdup ( what ) ;
if ( ! SWAP ( u ) - > what ) {
2010-10-12 06:07:43 +04:00
r = - ENOMEM ;
goto fail ;
}
unit_add_to_load_queue ( u ) ;
2010-05-14 04:29:45 +04:00
} else
delete = false ;
2010-05-09 20:44:11 +04:00
2010-10-12 06:07:43 +04:00
if ( what_proc_swaps ) {
Swap * first ;
2010-05-09 20:44:11 +04:00
2010-05-14 04:29:45 +04:00
p = & SWAP ( u ) - > parameters_proc_swaps ;
2010-10-12 06:07:43 +04:00
if ( ! p - > what ) {
if ( ! ( wp = strdup ( what_proc_swaps ) ) ) {
r = - ENOMEM ;
goto fail ;
}
if ( ! m - > swaps_by_proc_swaps )
if ( ! ( m - > swaps_by_proc_swaps = hashmap_new ( string_hash_func , string_compare_func ) ) ) {
r = - ENOMEM ;
goto fail ;
}
free ( p - > what ) ;
p - > what = wp ;
first = hashmap_get ( m - > swaps_by_proc_swaps , wp ) ;
LIST_PREPEND ( Swap , same_proc_swaps , first , SWAP ( u ) ) ;
if ( ( r = hashmap_replace ( m - > swaps_by_proc_swaps , wp , first ) ) < 0 )
goto fail ;
}
if ( set_flags ) {
SWAP ( u ) - > is_active = true ;
SWAP ( u ) - > just_activated = ! SWAP ( u ) - > from_proc_swaps ;
}
2010-05-14 04:29:45 +04:00
SWAP ( u ) - > from_proc_swaps = true ;
2010-10-12 06:07:43 +04:00
2010-05-14 04:29:45 +04:00
} else {
p = & SWAP ( u ) - > parameters_etc_fstab ;
2010-10-12 06:07:43 +04:00
if ( ! ( wp = strdup ( what ) ) ) {
r = - ENOMEM ;
goto fail ;
}
free ( p - > what ) ;
p - > what = wp ;
2010-05-14 04:29:45 +04:00
SWAP ( u ) - > from_etc_fstab = true ;
}
2010-05-09 20:44:11 +04:00
2010-05-14 04:29:45 +04:00
p - > priority = priority ;
p - > noauto = noauto ;
2010-08-25 22:37:04 +04:00
p - > nofail = nofail ;
2010-05-14 04:29:45 +04:00
p - > handle = handle ;
2010-05-09 20:44:11 +04:00
2010-05-14 04:29:45 +04:00
unit_add_to_dbus_queue ( u ) ;
2010-05-09 20:44:11 +04:00
2010-05-14 04:29:45 +04:00
free ( e ) ;
2010-05-09 20:44:11 +04:00
return 0 ;
fail :
2010-10-12 06:07:43 +04:00
log_warning ( " Failed to load swap unit: %s " , strerror ( - r ) ) ;
free ( wp ) ;
2010-05-14 04:29:45 +04:00
free ( e ) ;
if ( delete & & u )
2010-05-09 20:44:11 +04:00
unit_free ( u ) ;
2010-05-14 04:29:45 +04:00
return r ;
2010-05-09 20:44:11 +04:00
}
2010-10-12 06:07:43 +04:00
static int swap_process_new_swap ( Manager * m , const char * device , int prio , bool set_flags ) {
struct stat st ;
int r = 0 , k ;
assert ( m ) ;
if ( stat ( device , & st ) > = 0 & & S_ISBLK ( st . st_mode ) ) {
struct udev_device * d ;
const char * dn ;
struct udev_list_entry * item = NULL , * first = NULL ;
/* So this is a proper swap device. Create swap units
* for all names this swap device is known under */
if ( ! ( d = udev_device_new_from_devnum ( m - > udev , ' b ' , st . st_rdev ) ) )
return - ENOMEM ;
if ( ( dn = udev_device_get_devnode ( d ) ) )
r = swap_add_one ( m , dn , device , prio , false , false , false , set_flags ) ;
/* Add additional units for all symlinks */
first = udev_device_get_devlinks_list_entry ( d ) ;
udev_list_entry_foreach ( item , first ) {
const char * p ;
/* Don't bother with the /dev/block links */
p = udev_list_entry_get_name ( item ) ;
if ( path_startswith ( p , " /dev/block/ " ) )
continue ;
if ( stat ( p , & st ) > = 0 )
if ( ( ! S_ISBLK ( st . st_mode ) ) | | st . st_rdev ! = udev_device_get_devnum ( d ) )
continue ;
if ( ( k = swap_add_one ( m , p , device , prio , false , false , false , set_flags ) ) < 0 )
r = k ;
}
udev_device_unref ( d ) ;
}
if ( ( k = swap_add_one ( m , device , device , prio , false , false , false , set_flags ) ) < 0 )
r = k ;
return r ;
}
2010-05-09 20:44:11 +04:00
static void swap_set_state ( Swap * s , SwapState state ) {
SwapState old_state ;
2010-10-12 06:07:43 +04:00
2010-05-09 20:44:11 +04:00
assert ( s ) ;
old_state = s - > state ;
s - > state = state ;
2010-10-12 06:07:43 +04:00
if ( state ! = SWAP_ACTIVATING & &
state ! = SWAP_ACTIVATING_SIGTERM & &
state ! = SWAP_ACTIVATING_SIGKILL & &
state ! = SWAP_DEACTIVATING & &
state ! = SWAP_DEACTIVATING_SIGTERM & &
state ! = SWAP_DEACTIVATING_SIGKILL ) {
unit_unwatch_timer ( UNIT ( s ) , & s - > timer_watch ) ;
swap_unwatch_control_pid ( s ) ;
s - > control_command = NULL ;
s - > control_command_id = _SWAP_EXEC_COMMAND_INVALID ;
}
2010-05-09 20:44:11 +04:00
if ( state ! = old_state )
log_debug ( " %s changed %s -> %s " ,
2012-01-15 15:25:20 +04:00
UNIT ( s ) - > id ,
2010-05-09 20:44:11 +04:00
swap_state_to_string ( old_state ) ,
swap_state_to_string ( state ) ) ;
2011-01-20 15:17:22 +03:00
unit_notify ( UNIT ( s ) , state_translation_table [ old_state ] , state_translation_table [ state ] , true ) ;
2010-05-09 20:44:11 +04:00
}
static int swap_coldplug ( Unit * u ) {
Swap * s = SWAP ( u ) ;
SwapState new_state = SWAP_DEAD ;
2010-10-12 06:07:43 +04:00
int r ;
2010-05-09 20:44:11 +04:00
assert ( s ) ;
assert ( s - > state = = SWAP_DEAD ) ;
if ( s - > deserialized_state ! = s - > state )
new_state = s - > deserialized_state ;
2010-05-14 04:29:45 +04:00
else if ( s - > from_proc_swaps )
2010-05-09 20:44:11 +04:00
new_state = SWAP_ACTIVE ;
2010-10-12 06:07:43 +04:00
if ( new_state ! = s - > state ) {
if ( new_state = = SWAP_ACTIVATING | |
new_state = = SWAP_ACTIVATING_SIGTERM | |
new_state = = SWAP_ACTIVATING_SIGKILL | |
new_state = = SWAP_DEACTIVATING | |
new_state = = SWAP_DEACTIVATING_SIGTERM | |
new_state = = SWAP_DEACTIVATING_SIGKILL ) {
if ( s - > control_pid < = 0 )
return - EBADMSG ;
if ( ( r = unit_watch_pid ( UNIT ( s ) , s - > control_pid ) ) < 0 )
return r ;
if ( ( r = unit_watch_timer ( UNIT ( s ) , s - > timeout_usec , & s - > timer_watch ) ) < 0 )
return r ;
}
2010-05-14 04:29:45 +04:00
swap_set_state ( s , new_state ) ;
2010-10-12 06:07:43 +04:00
}
2010-05-09 20:44:11 +04:00
return 0 ;
}
static void swap_dump ( Unit * u , FILE * f , const char * prefix ) {
Swap * s = SWAP ( u ) ;
2010-05-14 04:29:45 +04:00
SwapParameters * p ;
2010-05-09 20:44:11 +04:00
assert ( s ) ;
2010-05-14 04:29:45 +04:00
assert ( f ) ;
if ( s - > from_proc_swaps )
p = & s - > parameters_proc_swaps ;
else if ( s - > from_fragment )
p = & s - > parameters_fragment ;
else
p = & s - > parameters_etc_fstab ;
2010-05-09 20:44:11 +04:00
fprintf ( f ,
2010-05-14 04:29:45 +04:00
" %sSwap State: %s \n "
2010-05-09 20:44:11 +04:00
" %sWhat: %s \n "
" %sPriority: %i \n "
2010-05-14 04:29:45 +04:00
" %sNoAuto: %s \n "
2010-08-25 22:37:04 +04:00
" %sNoFail: %s \n "
2010-05-14 04:29:45 +04:00
" %sHandle: %s \n "
" %sFrom /etc/fstab: %s \n "
" %sFrom /proc/swaps: %s \n "
" %sFrom fragment: %s \n " ,
2010-05-09 20:44:11 +04:00
prefix , swap_state_to_string ( s - > state ) ,
prefix , s - > what ,
2010-05-14 04:29:45 +04:00
prefix , p - > priority ,
prefix , yes_no ( p - > noauto ) ,
2010-08-25 22:37:04 +04:00
prefix , yes_no ( p - > nofail ) ,
2010-05-14 04:29:45 +04:00
prefix , yes_no ( p - > handle ) ,
prefix , yes_no ( s - > from_etc_fstab ) ,
prefix , yes_no ( s - > from_proc_swaps ) ,
prefix , yes_no ( s - > from_fragment ) ) ;
2010-10-12 06:07:43 +04:00
if ( s - > control_pid > 0 )
fprintf ( f ,
" %sControl PID: %lu \n " ,
prefix , ( unsigned long ) s - > control_pid ) ;
exec_context_dump ( & s - > exec_context , f , prefix ) ;
}
static int swap_spawn ( Swap * s , ExecCommand * c , pid_t * _pid ) {
pid_t pid ;
int r ;
assert ( s ) ;
assert ( c ) ;
assert ( _pid ) ;
if ( ( r = unit_watch_timer ( UNIT ( s ) , s - > timeout_usec , & s - > timer_watch ) ) < 0 )
goto fail ;
if ( ( r = exec_spawn ( c ,
NULL ,
& s - > exec_context ,
NULL , 0 ,
2012-01-15 15:25:20 +04:00
UNIT ( s ) - > manager - > environment ,
2010-10-12 06:07:43 +04:00
true ,
true ,
true ,
2012-01-15 15:25:20 +04:00
UNIT ( s ) - > manager - > confirm_spawn ,
UNIT ( s ) - > cgroup_bondings ,
UNIT ( s ) - > cgroup_attributes ,
2010-10-12 06:07:43 +04:00
& pid ) ) < 0 )
goto fail ;
if ( ( r = unit_watch_pid ( UNIT ( s ) , pid ) ) < 0 )
/* FIXME: we need to do something here */
goto fail ;
* _pid = pid ;
return 0 ;
fail :
unit_unwatch_timer ( UNIT ( s ) , & s - > timer_watch ) ;
return r ;
2010-05-09 20:44:11 +04:00
}
static void swap_enter_dead ( Swap * s , bool success ) {
assert ( s ) ;
2010-10-12 06:07:43 +04:00
if ( ! success )
s - > failure = true ;
swap_set_state ( s , s - > failure ? SWAP_FAILED : SWAP_DEAD ) ;
2010-05-09 20:44:11 +04:00
}
2010-10-12 06:07:43 +04:00
static void swap_enter_active ( Swap * s , bool success ) {
assert ( s ) ;
if ( ! success )
s - > failure = true ;
swap_set_state ( s , SWAP_ACTIVE ) ;
}
static void swap_enter_signal ( Swap * s , SwapState state , bool success ) {
2010-05-09 20:44:11 +04:00
int r ;
2010-10-12 06:07:43 +04:00
Set * pid_set = NULL ;
bool wait_for_exit = false ;
2010-05-09 20:44:11 +04:00
assert ( s ) ;
2010-10-12 06:07:43 +04:00
if ( ! success )
s - > failure = true ;
if ( s - > exec_context . kill_mode ! = KILL_NONE ) {
int sig = ( state = = SWAP_ACTIVATING_SIGTERM | |
state = = SWAP_DEACTIVATING_SIGTERM ) ? s - > exec_context . kill_signal : SIGKILL ;
if ( s - > control_pid > 0 ) {
2011-03-30 01:31:38 +04:00
if ( kill_and_sigcont ( s - > control_pid , sig ) < 0 & & errno ! = ESRCH )
2010-10-12 06:07:43 +04:00
log_warning ( " Failed to kill control process %li: %m " , ( long ) s - > control_pid ) ;
else
wait_for_exit = true ;
}
if ( s - > exec_context . kill_mode = = KILL_CONTROL_GROUP ) {
if ( ! ( pid_set = set_new ( trivial_hash_func , trivial_compare_func ) ) ) {
r = - ENOMEM ;
goto fail ;
}
/* Exclude the control pid from being killed via the cgroup */
if ( s - > control_pid > 0 )
if ( ( r = set_put ( pid_set , LONG_TO_PTR ( s - > control_pid ) ) ) < 0 )
goto fail ;
2012-01-15 15:25:20 +04:00
if ( ( r = cgroup_bonding_kill_list ( UNIT ( s ) - > cgroup_bondings , sig , true , pid_set ) ) < 0 ) {
2010-10-12 06:07:43 +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-10-12 06:07:43 +04:00
}
}
if ( wait_for_exit ) {
if ( ( r = unit_watch_timer ( UNIT ( s ) , s - > timeout_usec , & s - > timer_watch ) ) < 0 )
goto fail ;
swap_set_state ( s , state ) ;
} else
swap_enter_dead ( s , true ) ;
return ;
fail :
2012-01-15 15:25:20 +04:00
log_warning ( " %s failed to kill processes: %s " , UNIT ( s ) - > id , strerror ( - r ) ) ;
2010-10-12 06:07:43 +04:00
swap_enter_dead ( s , false ) ;
if ( pid_set )
set_free ( pid_set ) ;
}
static void swap_enter_activating ( Swap * s ) {
int r , priority ;
assert ( s ) ;
s - > control_command_id = SWAP_EXEC_ACTIVATE ;
s - > control_command = s - > exec_command + SWAP_EXEC_ACTIVATE ;
2010-05-09 20:44:11 +04:00
2010-05-14 04:29:45 +04:00
if ( s - > from_fragment )
priority = s - > parameters_fragment . priority ;
else if ( s - > from_etc_fstab )
priority = s - > parameters_etc_fstab . priority ;
2010-10-12 06:07:43 +04:00
else
priority = - 1 ;
2010-05-14 04:29:45 +04:00
2010-10-12 06:07:43 +04:00
if ( priority > = 0 ) {
char p [ LINE_MAX ] ;
2010-05-09 20:44:11 +04:00
2010-10-12 06:07:43 +04:00
snprintf ( p , sizeof ( p ) , " %i " , priority ) ;
char_array_0 ( p ) ;
2010-05-09 20:44:11 +04:00
2010-10-12 06:07:43 +04:00
r = exec_command_set (
s - > control_command ,
" /sbin/swapon " ,
" -p " ,
p ,
s - > what ,
NULL ) ;
} else
r = exec_command_set (
s - > control_command ,
" /sbin/swapon " ,
s - > what ,
NULL ) ;
if ( r < 0 )
goto fail ;
swap_unwatch_control_pid ( s ) ;
if ( ( r = swap_spawn ( s , s - > control_command , & s - > control_pid ) ) < 0 )
goto fail ;
swap_set_state ( s , SWAP_ACTIVATING ) ;
return ;
fail :
2012-01-15 15:25:20 +04:00
log_warning ( " %s failed to run 'swapon' task: %s " , UNIT ( s ) - > id , strerror ( - r ) ) ;
2010-10-12 06:07:43 +04:00
swap_enter_dead ( s , false ) ;
}
static void swap_enter_deactivating ( Swap * s , bool success ) {
int r ;
assert ( s ) ;
if ( ! success )
s - > failure = true ;
s - > control_command_id = SWAP_EXEC_DEACTIVATE ;
s - > control_command = s - > exec_command + SWAP_EXEC_DEACTIVATE ;
if ( ( r = exec_command_set (
s - > control_command ,
" /sbin/swapoff " ,
s - > what ,
NULL ) ) < 0 )
goto fail ;
swap_unwatch_control_pid ( s ) ;
if ( ( r = swap_spawn ( s , s - > control_command , & s - > control_pid ) ) < 0 )
goto fail ;
swap_set_state ( s , SWAP_DEACTIVATING ) ;
return ;
fail :
2012-01-15 15:25:20 +04:00
log_warning ( " %s failed to run 'swapoff' task: %s " , UNIT ( s ) - > id , strerror ( - r ) ) ;
2010-10-12 06:07:43 +04:00
swap_enter_active ( s , false ) ;
}
static int swap_start ( Unit * u ) {
Swap * s = SWAP ( u ) ;
assert ( s ) ;
/* We cannot fulfill this request right now, try again later
* please ! */
if ( s - > state = = SWAP_DEACTIVATING | |
s - > state = = SWAP_DEACTIVATING_SIGTERM | |
s - > state = = SWAP_DEACTIVATING_SIGKILL | |
s - > state = = SWAP_ACTIVATING_SIGTERM | |
s - > state = = SWAP_ACTIVATING_SIGKILL )
return - EAGAIN ;
if ( s - > state = = SWAP_ACTIVATING )
return 0 ;
assert ( s - > state = = SWAP_DEAD | | s - > state = = SWAP_FAILED ) ;
s - > failure = false ;
swap_enter_activating ( s ) ;
2010-05-09 20:44:11 +04:00
return 0 ;
}
static int swap_stop ( Unit * u ) {
Swap * s = SWAP ( u ) ;
assert ( s ) ;
2010-10-12 06:07:43 +04:00
if ( s - > state = = SWAP_DEACTIVATING | |
s - > state = = SWAP_DEACTIVATING_SIGTERM | |
s - > state = = SWAP_DEACTIVATING_SIGKILL | |
s - > state = = SWAP_ACTIVATING_SIGTERM | |
s - > state = = SWAP_ACTIVATING_SIGKILL )
return 0 ;
2010-05-09 20:44:11 +04:00
2010-10-12 06:07:43 +04:00
assert ( s - > state = = SWAP_ACTIVATING | |
s - > state = = SWAP_ACTIVE ) ;
2010-05-09 20:44:11 +04:00
2010-10-12 06:07:43 +04:00
swap_enter_deactivating ( s , true ) ;
2010-05-09 20:44:11 +04:00
return 0 ;
}
static int swap_serialize ( Unit * u , FILE * f , FDSet * fds ) {
Swap * s = SWAP ( u ) ;
assert ( s ) ;
assert ( f ) ;
assert ( fds ) ;
unit_serialize_item ( u , f , " state " , swap_state_to_string ( s - > state ) ) ;
2010-10-12 06:07:43 +04:00
unit_serialize_item ( u , f , " failure " , yes_no ( s - > failure ) ) ;
if ( s - > control_pid > 0 )
unit_serialize_item_format ( u , f , " control-pid " , " %lu " , ( unsigned long ) s - > control_pid ) ;
if ( s - > control_command_id > = 0 )
unit_serialize_item ( u , f , " control-command " , swap_exec_command_to_string ( s - > control_command_id ) ) ;
2010-05-09 20:44:11 +04:00
return 0 ;
}
static int swap_deserialize_item ( Unit * u , const char * key , const char * value , FDSet * fds ) {
Swap * s = SWAP ( u ) ;
assert ( s ) ;
assert ( fds ) ;
if ( streq ( key , " state " ) ) {
SwapState state ;
if ( ( state = swap_state_from_string ( value ) ) < 0 )
log_debug ( " Failed to parse state value %s " , value ) ;
else
s - > deserialized_state = state ;
2010-10-12 06:07:43 +04:00
} else if ( streq ( key , " failure " ) ) {
int b ;
if ( ( b = parse_boolean ( value ) ) < 0 )
log_debug ( " Failed to parse failure value %s " , value ) ;
else
s - > failure = b | | s - > failure ;
} else if ( streq ( key , " control-pid " ) ) {
pid_t pid ;
if ( parse_pid ( value , & pid ) < 0 )
log_debug ( " Failed to parse control-pid value %s " , value ) ;
else
s - > control_pid = pid ;
} else if ( streq ( key , " control-command " ) ) {
SwapExecCommand id ;
if ( ( id = swap_exec_command_from_string ( value ) ) < 0 )
log_debug ( " Failed to parse exec-command value %s " , value ) ;
else {
s - > control_command_id = id ;
s - > control_command = s - > exec_command + id ;
}
2010-05-09 20:44:11 +04:00
} else
log_debug ( " Unknown serialization key '%s' " , key ) ;
return 0 ;
}
static UnitActiveState swap_active_state ( Unit * u ) {
assert ( u ) ;
return state_translation_table [ SWAP ( u ) - > state ] ;
}
static const char * swap_sub_state_to_string ( Unit * u ) {
assert ( u ) ;
return swap_state_to_string ( SWAP ( u ) - > state ) ;
}
static bool swap_check_gc ( Unit * u ) {
Swap * s = SWAP ( u ) ;
assert ( s ) ;
2010-05-14 04:29:45 +04:00
return s - > from_etc_fstab | | s - > from_proc_swaps ;
2010-05-09 20:44:11 +04:00
}
2010-10-12 06:07:43 +04:00
static void swap_sigchld_event ( Unit * u , pid_t pid , int code , int status ) {
Swap * s = SWAP ( u ) ;
bool success ;
assert ( s ) ;
assert ( pid > = 0 ) ;
if ( pid ! = s - > control_pid )
return ;
s - > control_pid = 0 ;
success = is_clean_exit ( code , status ) ;
s - > failure = s - > failure | | ! success ;
if ( s - > control_command ) {
2011-05-18 03:07:31 +04:00
exec_status_exit ( & s - > control_command - > exec_status , & s - > exec_context , pid , code , status ) ;
2010-10-12 06:07:43 +04:00
s - > control_command = NULL ;
s - > control_command_id = _SWAP_EXEC_COMMAND_INVALID ;
}
log_full ( success ? LOG_DEBUG : LOG_NOTICE ,
2012-01-15 15:04:08 +04:00
" %s swap process exited, code=%s status=%i " , u - > id , sigchld_code_to_string ( code ) , status ) ;
2010-10-12 06:07:43 +04:00
switch ( s - > state ) {
case SWAP_ACTIVATING :
case SWAP_ACTIVATING_SIGTERM :
case SWAP_ACTIVATING_SIGKILL :
if ( success )
swap_enter_active ( s , true ) ;
else
swap_enter_dead ( s , false ) ;
break ;
case SWAP_DEACTIVATING :
case SWAP_DEACTIVATING_SIGKILL :
case SWAP_DEACTIVATING_SIGTERM :
if ( success )
swap_enter_dead ( s , true ) ;
else
swap_enter_dead ( s , false ) ;
break ;
default :
assert_not_reached ( " Uh, control process died at wrong time. " ) ;
}
/* Notify clients about changed exit status */
unit_add_to_dbus_queue ( u ) ;
/* Request a reload of /proc/swaps, so that following units
* can follow our state change */
2012-01-15 15:04:08 +04:00
u - > manager - > request_reload = true ;
2010-10-12 06:07:43 +04:00
}
static void swap_timer_event ( Unit * u , uint64_t elapsed , Watch * w ) {
Swap * s = SWAP ( u ) ;
assert ( s ) ;
assert ( elapsed = = 1 ) ;
assert ( w = = & s - > timer_watch ) ;
switch ( s - > state ) {
case SWAP_ACTIVATING :
2012-01-15 15:04:08 +04:00
log_warning ( " %s activation timed out. Stopping. " , u - > id ) ;
2010-10-12 06:07:43 +04:00
swap_enter_signal ( s , SWAP_ACTIVATING_SIGTERM , false ) ;
break ;
case SWAP_DEACTIVATING :
2012-01-15 15:04:08 +04:00
log_warning ( " %s deactivation timed out. Stopping. " , u - > id ) ;
2010-10-12 06:07:43 +04:00
swap_enter_signal ( s , SWAP_DEACTIVATING_SIGTERM , false ) ;
break ;
case SWAP_ACTIVATING_SIGTERM :
2011-01-19 00:55:54 +03:00
if ( s - > exec_context . send_sigkill ) {
2012-01-15 15:04:08 +04:00
log_warning ( " %s activation timed out. Killing. " , u - > id ) ;
2011-01-19 00:55:54 +03:00
swap_enter_signal ( s , SWAP_ACTIVATING_SIGKILL , false ) ;
} else {
2012-01-15 15:04:08 +04:00
log_warning ( " %s activation timed out. Skipping SIGKILL. Ignoring. " , u - > id ) ;
2011-01-19 00:55:54 +03:00
swap_enter_dead ( s , false ) ;
}
2010-10-12 06:07:43 +04:00
break ;
case SWAP_DEACTIVATING_SIGTERM :
2011-01-19 00:55:54 +03:00
if ( s - > exec_context . send_sigkill ) {
2012-01-15 15:04:08 +04:00
log_warning ( " %s deactivation timed out. Killing. " , u - > id ) ;
2011-01-19 00:55:54 +03:00
swap_enter_signal ( s , SWAP_DEACTIVATING_SIGKILL , false ) ;
} else {
2012-01-15 15:04:08 +04:00
log_warning ( " %s deactivation timed out. Skipping SIGKILL. Ignoring. " , u - > id ) ;
2011-01-19 00:55:54 +03:00
swap_enter_dead ( s , false ) ;
}
2010-10-12 06:07:43 +04:00
break ;
case SWAP_ACTIVATING_SIGKILL :
case SWAP_DEACTIVATING_SIGKILL :
2012-01-15 15:04:08 +04:00
log_warning ( " %s swap process still around after SIGKILL. Ignoring. " , u - > id ) ;
2010-10-12 06:07:43 +04:00
swap_enter_dead ( s , false ) ;
break ;
default :
assert_not_reached ( " Timeout at wrong time. " ) ;
}
}
static int swap_load_proc_swaps ( Manager * m , bool set_flags ) {
unsigned i ;
int r = 0 ;
assert ( m ) ;
2010-05-09 20:44:11 +04:00
rewind ( m - > proc_swaps ) ;
2010-05-10 05:34:31 +04:00
2010-05-14 04:29:45 +04:00
( void ) fscanf ( m - > proc_swaps , " %*s %*s %*s %*s %*s \n " ) ;
2010-05-09 20:44:11 +04:00
2010-10-12 06:07:43 +04:00
for ( i = 1 ; ; i + + ) {
2010-05-09 20:44:11 +04:00
char * dev = NULL , * d ;
int prio = 0 , k ;
2010-05-14 04:29:45 +04:00
if ( ( k = fscanf ( m - > proc_swaps ,
2010-10-12 06:07:43 +04:00
" %ms " /* device/file */
" %*s " /* type of swap */
" %*s " /* swap size */
" %*s " /* used */
2010-05-14 04:29:45 +04:00
" %i \n " , /* priority */
& dev , & prio ) ) ! = 2 ) {
2010-05-09 20:44:11 +04:00
if ( k = = EOF )
2010-05-14 04:29:45 +04:00
break ;
2010-05-09 20:44:11 +04:00
2010-10-12 06:07:43 +04:00
log_warning ( " Failed to parse /proc/swaps:%u. " , i ) ;
2010-05-09 20:44:11 +04:00
free ( dev ) ;
2010-10-12 06:07:43 +04:00
continue ;
2010-05-09 20:44:11 +04:00
}
2010-05-14 04:29:45 +04:00
d = cunescape ( dev ) ;
2010-05-09 20:44:11 +04:00
free ( dev ) ;
2010-05-14 04:29:45 +04:00
if ( ! d )
return - ENOMEM ;
2010-10-12 06:07:43 +04:00
k = swap_process_new_swap ( m , d , prio , set_flags ) ;
2010-05-09 20:44:11 +04:00
free ( d ) ;
if ( k < 0 )
2010-10-12 06:07:43 +04:00
r = k ;
2010-05-09 20:44:11 +04:00
}
2010-10-12 06:07:43 +04:00
return r ;
}
int swap_dispatch_reload ( Manager * m ) {
2010-10-19 01:09:09 +04:00
/* This function should go as soon as the kernel properly notifies us */
2010-10-12 06:07:43 +04:00
if ( _likely_ ( ! m - > request_reload ) )
return 0 ;
m - > request_reload = false ;
2010-10-19 01:09:09 +04:00
return swap_fd_event ( m , EPOLLPRI ) ;
}
int swap_fd_event ( Manager * m , int events ) {
2012-01-15 15:37:16 +04:00
Unit * u ;
2010-10-19 01:09:09 +04:00
int r ;
assert ( m ) ;
assert ( events & EPOLLPRI ) ;
2011-01-22 04:18:59 +03:00
if ( ( r = swap_load_proc_swaps ( m , true ) ) < 0 ) {
2010-10-12 06:07:43 +04:00
log_error ( " Failed to reread /proc/swaps: %s " , strerror ( - r ) ) ;
/* Reset flags, just in case, for late calls */
2012-01-15 15:37:16 +04:00
LIST_FOREACH ( units_by_type , u , m - > units_by_type [ UNIT_SWAP ] ) {
Swap * swap = SWAP ( u ) ;
2010-10-12 06:07:43 +04:00
swap - > is_active = swap - > just_activated = false ;
}
return 0 ;
}
manager_dispatch_load_queue ( m ) ;
2012-01-15 15:37:16 +04:00
LIST_FOREACH ( units_by_type , u , m - > units_by_type [ UNIT_SWAP ] ) {
Swap * swap = SWAP ( u ) ;
2010-10-12 06:07:43 +04:00
if ( ! swap - > is_active ) {
/* This has just been deactivated */
swap - > from_proc_swaps = false ;
swap_unset_proc_swaps ( swap ) ;
switch ( swap - > state ) {
case SWAP_ACTIVE :
swap_enter_dead ( swap , true ) ;
break ;
default :
swap_set_state ( swap , swap - > state ) ;
break ;
}
} else if ( swap - > just_activated ) {
/* New swap entry */
switch ( swap - > state ) {
case SWAP_DEAD :
case SWAP_FAILED :
swap_enter_active ( swap , true ) ;
break ;
default :
/* Nothing really changed, but let's
* issue an notification call
* nonetheless , in case somebody is
* waiting for this . */
swap_set_state ( swap , swap - > state ) ;
break ;
}
}
/* Reset the flags for later calls */
swap - > is_active = swap - > just_activated = false ;
}
return 1 ;
}
static Unit * swap_following ( Unit * u ) {
Swap * s = SWAP ( u ) ;
Swap * other , * first = NULL ;
assert ( s ) ;
if ( streq_ptr ( s - > what , s - > parameters_proc_swaps . what ) )
return NULL ;
/* Make everybody follow the unit that's named after the swap
* device in the kernel */
LIST_FOREACH_AFTER ( same_proc_swaps , other , s )
if ( streq_ptr ( other - > what , other - > parameters_proc_swaps . what ) )
return UNIT ( other ) ;
LIST_FOREACH_BEFORE ( same_proc_swaps , other , s ) {
if ( streq_ptr ( other - > what , other - > parameters_proc_swaps . what ) )
return UNIT ( other ) ;
first = other ;
}
return UNIT ( first ) ;
2010-05-09 20:44:11 +04:00
}
2010-11-15 01:47:53 +03:00
static int swap_following_set ( Unit * u , Set * * _set ) {
Swap * s = SWAP ( u ) ;
Swap * other ;
Set * set ;
int r ;
assert ( s ) ;
assert ( _set ) ;
if ( LIST_JUST_US ( same_proc_swaps , s ) ) {
* _set = NULL ;
return 0 ;
}
if ( ! ( set = set_new ( NULL , NULL ) ) )
return - ENOMEM ;
LIST_FOREACH_AFTER ( same_proc_swaps , other , s )
if ( ( r = set_put ( set , other ) ) < 0 )
goto fail ;
LIST_FOREACH_BEFORE ( same_proc_swaps , other , s )
if ( ( r = set_put ( set , other ) ) < 0 )
goto fail ;
* _set = set ;
return 1 ;
fail :
set_free ( set ) ;
return r ;
}
2010-05-09 20:44:11 +04:00
static void swap_shutdown ( Manager * m ) {
assert ( m ) ;
if ( m - > proc_swaps ) {
fclose ( m - > proc_swaps ) ;
m - > proc_swaps = NULL ;
}
2010-10-12 06:07:43 +04:00
hashmap_free ( m - > swaps_by_proc_swaps ) ;
m - > swaps_by_proc_swaps = NULL ;
2010-05-09 20:44:11 +04:00
}
static int swap_enumerate ( Manager * m ) {
int r ;
2010-10-19 01:09:09 +04:00
struct epoll_event ev ;
2010-05-09 20:44:11 +04:00
assert ( m ) ;
2010-10-19 01:09:09 +04:00
if ( ! m - > proc_swaps ) {
2010-05-14 04:29:45 +04:00
if ( ! ( m - > proc_swaps = fopen ( " /proc/swaps " , " re " ) ) )
2011-06-24 15:43:19 +04:00
return ( errno = = ENOENT ) ? 0 : - errno ;
2010-05-09 20:44:11 +04:00
2010-10-19 01:09:09 +04:00
m - > swap_watch . type = WATCH_SWAP ;
m - > swap_watch . fd = fileno ( m - > proc_swaps ) ;
zero ( ev ) ;
ev . events = EPOLLPRI ;
ev . data . ptr = & m - > swap_watch ;
if ( epoll_ctl ( m - > epoll_fd , EPOLL_CTL_ADD , m - > swap_watch . fd , & ev ) < 0 )
return - errno ;
}
2010-10-12 06:07:43 +04:00
/* We rely on mount.c to load /etc/fstab for us */
if ( ( r = swap_load_proc_swaps ( m , false ) ) < 0 )
2010-05-09 20:44:11 +04:00
swap_shutdown ( m ) ;
return r ;
}
2010-08-31 02:23:34 +04:00
static void swap_reset_failed ( Unit * u ) {
2010-07-18 06:58:01 +04:00
Swap * s = SWAP ( u ) ;
assert ( s ) ;
2010-08-31 02:23:34 +04:00
if ( s - > state = = SWAP_FAILED )
2010-07-18 06:58:01 +04:00
swap_set_state ( s , SWAP_DEAD ) ;
2010-10-12 06:07:43 +04:00
s - > failure = false ;
2010-07-18 06:58:01 +04:00
}
2010-10-22 18:11:50 +04:00
static int swap_kill ( Unit * u , KillWho who , KillMode mode , int signo , DBusError * error ) {
Swap * s = SWAP ( u ) ;
int r = 0 ;
Set * pid_set = NULL ;
assert ( s ) ;
if ( who = = KILL_MAIN ) {
dbus_set_error ( error , BUS_ERROR_NO_SUCH_PROCESS , " Swap units have no main processes " ) ;
2011-07-13 21:57:36 +04:00
return - ESRCH ;
2010-10-22 18:11:50 +04:00
}
if ( s - > 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 ( s - > control_pid > 0 )
if ( kill ( s - > 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 ( s - > control_pid > 0 )
if ( ( q = set_put ( pid_set , LONG_TO_PTR ( s - > control_pid ) ) ) < 0 ) {
r = q ;
goto finish ;
}
2012-01-15 15:25:20 +04:00
if ( ( q = cgroup_bonding_kill_list ( UNIT ( s ) - > 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-07-18 06:58:01 +04:00
static const char * const swap_state_table [ _SWAP_STATE_MAX ] = {
[ SWAP_DEAD ] = " dead " ,
2010-10-12 06:07:43 +04:00
[ SWAP_ACTIVATING ] = " activating " ,
2010-07-18 06:58:01 +04:00
[ SWAP_ACTIVE ] = " active " ,
2010-10-12 06:07:43 +04:00
[ SWAP_DEACTIVATING ] = " deactivating " ,
[ SWAP_ACTIVATING_SIGTERM ] = " activating-sigterm " ,
[ SWAP_ACTIVATING_SIGKILL ] = " activating-sigkill " ,
[ SWAP_DEACTIVATING_SIGTERM ] = " deactivating-sigterm " ,
[ SWAP_DEACTIVATING_SIGKILL ] = " deactivating-sigkill " ,
2010-08-31 02:23:34 +04:00
[ SWAP_FAILED ] = " failed "
2010-07-18 06:58:01 +04:00
} ;
DEFINE_STRING_TABLE_LOOKUP ( swap_state , SwapState ) ;
2010-10-12 06:07:43 +04:00
static const char * const swap_exec_command_table [ _SWAP_EXEC_COMMAND_MAX ] = {
[ SWAP_EXEC_ACTIVATE ] = " ExecActivate " ,
[ SWAP_EXEC_DEACTIVATE ] = " ExecDeactivate " ,
} ;
DEFINE_STRING_TABLE_LOOKUP ( swap_exec_command , SwapExecCommand ) ;
2010-05-09 20:44:11 +04:00
const UnitVTable swap_vtable = {
. suffix = " .swap " ,
2012-01-15 13:53:49 +04:00
. object_size = sizeof ( Swap ) ,
2011-08-01 02:43:05 +04:00
. sections =
" Unit \0 "
" Swap \0 "
" Install \0 " ,
2010-05-09 20:44:11 +04:00
2010-10-12 06:07:43 +04:00
. no_alias = true ,
2010-05-09 20:44:11 +04:00
. no_instances = true ,
2010-07-07 02:00:59 +04:00
. show_status = true ,
2010-05-09 20:44:11 +04:00
2010-05-14 04:29:45 +04:00
. init = swap_init ,
2010-05-09 20:44:11 +04:00
. load = swap_load ,
2010-05-10 01:41:03 +04:00
. done = swap_done ,
2010-05-09 20:44:11 +04:00
. coldplug = swap_coldplug ,
. dump = swap_dump ,
. start = swap_start ,
. stop = swap_stop ,
2010-10-22 18:11:50 +04:00
. kill = swap_kill ,
2010-05-09 20:44:11 +04:00
. serialize = swap_serialize ,
. deserialize_item = swap_deserialize_item ,
. active_state = swap_active_state ,
. sub_state_to_string = swap_sub_state_to_string ,
. check_gc = swap_check_gc ,
2010-10-12 06:07:43 +04:00
. sigchld_event = swap_sigchld_event ,
. timer_event = swap_timer_event ,
. reset_failed = swap_reset_failed ,
2010-08-20 04:26:05 +04:00
. bus_interface = " org.freedesktop.systemd1.Swap " ,
2010-05-09 20:44:11 +04:00
. bus_message_handler = bus_swap_message_handler ,
2010-08-20 04:26:05 +04:00
. bus_invalidating_properties = bus_swap_invalidating_properties ,
2010-05-09 20:44:11 +04:00
2010-10-12 06:07:43 +04:00
. following = swap_following ,
2010-11-15 01:47:53 +03:00
. following_set = swap_following_set ,
2010-07-18 06:58:01 +04:00
2010-05-10 01:41:03 +04:00
. enumerate = swap_enumerate ,
. shutdown = swap_shutdown
2010-05-09 20:44:11 +04:00
} ;