2001-10-09 20:05:34 +04:00
/*
2008-01-30 17:00:02 +03:00
* Copyright ( C ) 2001 - 2004 Sistina Software , Inc . All rights reserved .
2009-02-24 18:48:00 +03:00
* Copyright ( C ) 2004 - 2009 Red Hat , Inc . All rights reserved .
2001-10-09 20:05:34 +04:00
*
2004-03-30 23:35:44 +04:00
* This file is part of LVM2 .
*
* This copyrighted material is made available to anyone wishing to use ,
* modify , copy , or redistribute it subject to the terms and conditions
2007-08-21 00:55:30 +04:00
* of the GNU Lesser General Public License v .2 .1 .
2004-03-30 23:35:44 +04:00
*
2007-08-21 00:55:30 +04:00
* You should have received a copy of the GNU Lesser General Public License
2004-03-30 23:35:44 +04:00
* along with this program ; if not , write to the Free Software Foundation ,
* Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
2001-10-09 20:05:34 +04:00
*/
2002-11-18 17:01:16 +03:00
# include "lib.h"
2001-10-16 20:25:28 +04:00
# include "metadata.h"
2001-10-09 20:05:34 +04:00
# include "activate.h"
2003-07-05 02:34:56 +04:00
# include "memlock.h"
2001-11-15 17:27:51 +03:00
# include "display.h"
2001-11-12 15:20:58 +03:00
# include "fs.h"
2005-10-17 22:00:02 +04:00
# include "lvm-exec.h"
2004-04-08 19:23:23 +04:00
# include "lvm-file.h"
2001-12-31 22:09:51 +03:00
# include "lvm-string.h"
2002-02-25 15:56:16 +03:00
# include "toolcontext.h"
2002-02-26 14:49:17 +03:00
# include "dev_manager.h"
2004-03-08 21:13:22 +03:00
# include "str_list.h"
2004-05-05 01:25:57 +04:00
# include "config.h"
2005-10-25 23:08:21 +04:00
# include "filter.h"
2005-12-02 23:35:07 +03:00
# include "segtype.h"
2002-01-21 14:06:32 +03:00
# include <limits.h>
2002-02-18 18:52:48 +03:00
# include <fcntl.h>
2003-07-05 02:34:56 +04:00
# include <unistd.h>
2002-01-21 14:06:32 +03:00
2002-02-11 18:48:34 +03:00
# define _skip(fmt, args...) log_very_verbose("Skipping: " fmt , ## args)
2001-10-09 20:05:34 +04:00
2004-04-08 19:23:23 +04:00
int lvm1_present ( struct cmd_context * cmd )
{
char path [ PATH_MAX ] ;
2006-08-21 16:54:53 +04:00
if ( dm_snprintf ( path , sizeof ( path ) , " %s/lvm/global " , cmd - > proc_dir )
2004-04-08 19:23:23 +04:00
< 0 ) {
log_error ( " LVM1 proc global snprintf failed " ) ;
return 0 ;
}
if ( path_exists ( path ) )
return 1 ;
else
return 0 ;
}
2006-10-03 21:55:20 +04:00
int list_segment_modules ( struct dm_pool * mem , const struct lv_segment * seg ,
2008-11-04 01:14:30 +03:00
struct dm_list * modules )
2006-10-03 21:55:20 +04:00
{
unsigned int s ;
struct lv_segment * seg2 , * snap_seg ;
2008-11-04 01:14:30 +03:00
struct dm_list * snh ;
2006-10-03 21:55:20 +04:00
if ( seg - > segtype - > ops - > modules_needed & &
! seg - > segtype - > ops - > modules_needed ( mem , seg , modules ) ) {
log_error ( " module string allocation failed " ) ;
return 0 ;
}
if ( lv_is_origin ( seg - > lv ) )
2008-11-04 01:14:30 +03:00
dm_list_iterate ( snh , & seg - > lv - > snapshot_segs )
2006-10-03 21:55:20 +04:00
if ( ! list_lv_modules ( mem ,
2008-11-04 01:14:30 +03:00
dm_list_struct_base ( snh ,
2006-10-03 21:55:20 +04:00
struct lv_segment ,
origin_list ) - > cow ,
modules ) )
return_0 ;
if ( lv_is_cow ( seg - > lv ) ) {
snap_seg = find_cow ( seg - > lv ) ;
if ( snap_seg - > segtype - > ops - > modules_needed & &
! snap_seg - > segtype - > ops - > modules_needed ( mem , snap_seg ,
modules ) ) {
log_error ( " snap_seg module string allocation failed " ) ;
return 0 ;
}
}
for ( s = 0 ; s < seg - > area_count ; s + + ) {
switch ( seg_type ( seg , s ) ) {
case AREA_LV :
seg2 = find_seg_by_le ( seg_lv ( seg , s ) , seg_le ( seg , s ) ) ;
if ( seg2 & & ! list_segment_modules ( mem , seg2 , modules ) )
return_0 ;
break ;
case AREA_PV :
case AREA_UNASSIGNED :
;
}
}
return 1 ;
}
int list_lv_modules ( struct dm_pool * mem , const struct logical_volume * lv ,
2008-11-04 01:14:30 +03:00
struct dm_list * modules )
2006-10-03 21:55:20 +04:00
{
struct lv_segment * seg ;
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( seg , & lv - > segments )
2006-10-03 21:55:20 +04:00
if ( ! list_segment_modules ( mem , seg , modules ) )
return_0 ;
return 1 ;
}
2003-01-09 01:44:07 +03:00
# ifndef DEVMAPPER_SUPPORT
void set_activation ( int act )
{
2004-03-19 19:26:46 +03:00
static int warned = 0 ;
if ( warned | | ! act )
return ;
log_error ( " Compiled without libdevmapper support. "
" Can't enable activation. " ) ;
warned = 1 ;
2003-01-09 01:44:07 +03:00
}
int activation ( void )
{
return 0 ;
}
int library_version ( char * version , size_t size )
{
return 0 ;
}
int driver_version ( char * version , size_t size )
{
return 0 ;
}
2005-12-20 00:01:39 +03:00
int target_version ( const char * target_name , uint32_t * maj ,
uint32_t * min , uint32_t * patchlevel )
{
return 0 ;
}
2009-02-28 03:54:06 +03:00
int target_present ( struct cmd_context * cmd , const char * target_name ,
int use_modprobe )
2004-03-26 22:52:09 +03:00
{
return 0 ;
}
2005-10-17 22:00:02 +04:00
int lv_info ( struct cmd_context * cmd , const struct logical_volume * lv , struct lvinfo * info ,
2007-11-12 23:51:54 +03:00
int with_open_count , int with_read_ahead )
2003-01-09 01:44:07 +03:00
{
return 0 ;
}
2004-03-26 18:35:01 +03:00
int lv_info_by_lvid ( struct cmd_context * cmd , const char * lvid_s ,
2007-11-12 23:51:54 +03:00
struct lvinfo * info , int with_open_count , int with_read_ahead )
2004-03-26 18:35:01 +03:00
{
return 0 ;
}
2009-10-01 04:35:29 +04:00
int lv_snapshot_percent ( const struct logical_volume * lv , float * percent ,
percent_range_t * percent_range )
2003-01-09 01:44:07 +03:00
{
return 0 ;
}
2006-04-06 18:06:27 +04:00
int lv_mirror_percent ( struct cmd_context * cmd , struct logical_volume * lv ,
2009-10-01 04:35:29 +04:00
int wait , float * percent , percent_range_t * percent_range ,
uint32_t * event_nr )
2003-04-30 19:26:25 +04:00
{
return 0 ;
}
2003-01-09 01:44:07 +03:00
int lvs_in_vg_activated ( struct volume_group * vg )
{
return 0 ;
}
int lvs_in_vg_opened ( struct volume_group * vg )
{
return 0 ;
}
2004-03-08 21:54:13 +03:00
int lv_suspend ( struct cmd_context * cmd , const char * lvid_s )
{
return 1 ;
}
2003-01-09 01:44:07 +03:00
int lv_suspend_if_active ( struct cmd_context * cmd , const char * lvid_s )
{
return 1 ;
}
2004-03-08 21:54:13 +03:00
int lv_resume ( struct cmd_context * cmd , const char * lvid_s )
{
return 1 ;
}
2003-01-09 01:44:07 +03:00
int lv_resume_if_active ( struct cmd_context * cmd , const char * lvid_s )
{
return 1 ;
}
int lv_deactivate ( struct cmd_context * cmd , const char * lvid_s )
{
return 1 ;
}
2004-03-08 21:54:13 +03:00
int lv_activation_filter ( struct cmd_context * cmd , const char * lvid_s ,
int * activate_lv )
{
return 1 ;
}
2005-08-15 03:18:28 +04:00
int lv_activate ( struct cmd_context * cmd , const char * lvid_s , int exclusive )
2003-01-09 01:44:07 +03:00
{
return 1 ;
}
2005-08-15 03:18:28 +04:00
int lv_activate_with_filter ( struct cmd_context * cmd , const char * lvid_s , int exclusive )
2004-03-08 21:54:13 +03:00
{
return 1 ;
}
2003-11-12 22:16:48 +03:00
int lv_mknodes ( struct cmd_context * cmd , const struct logical_volume * lv )
{
return 1 ;
}
2006-12-20 19:19:01 +03:00
int pv_uses_vg ( struct physical_volume * pv ,
2006-05-12 23:16:48 +04:00
struct volume_group * vg )
2005-10-25 23:08:21 +04:00
{
return 0 ;
}
2006-05-16 20:48:31 +04:00
void activation_release ( void )
{
return ;
}
2003-07-05 02:34:56 +04:00
void activation_exit ( void )
{
return ;
}
2003-01-09 01:44:07 +03:00
# else /* DEVMAPPER_SUPPORT */
2002-11-18 17:01:16 +03:00
static int _activation = 1 ;
2002-12-20 02:25:55 +03:00
void set_activation ( int act )
2002-11-18 17:01:16 +03:00
{
2002-12-20 02:25:55 +03:00
if ( act = = _activation )
2002-11-18 17:01:16 +03:00
return ;
2002-12-20 02:25:55 +03:00
_activation = act ;
2002-11-18 17:01:16 +03:00
if ( _activation )
log_verbose ( " Activation enabled. Device-mapper kernel "
" driver will be used. " ) ;
else
2007-06-28 21:33:44 +04:00
log_warn ( " WARNING: Activation disabled. No device-mapper "
2005-12-22 19:13:38 +03:00
" interaction will be attempted. " ) ;
2002-11-18 17:01:16 +03:00
}
2002-12-20 02:25:55 +03:00
int activation ( void )
2002-11-18 17:01:16 +03:00
{
return _activation ;
}
2004-03-08 21:13:22 +03:00
static int _passes_activation_filter ( struct cmd_context * cmd ,
struct logical_volume * lv )
{
2004-05-04 22:28:15 +04:00
const struct config_node * cn ;
2004-03-08 21:13:22 +03:00
struct config_value * cv ;
char * str ;
char path [ PATH_MAX ] ;
2006-05-16 20:48:31 +04:00
if ( ! ( cn = find_config_tree_node ( cmd , " activation/volume_list " ) ) ) {
2010-07-12 15:37:49 +04:00
log_verbose ( " activation/volume_list configuration setting "
" not defined, checking host tags only " ) ;
2004-05-04 22:28:15 +04:00
/* If no host tags defined, activate */
2008-11-04 01:14:30 +03:00
if ( dm_list_empty ( & cmd - > tags ) )
2004-03-08 21:13:22 +03:00
return 1 ;
/* If any host tag matches any LV or VG tag, activate */
if ( str_list_match_list ( & cmd - > tags , & lv - > tags ) | |
str_list_match_list ( & cmd - > tags , & lv - > vg - > tags ) )
return 1 ;
2010-07-12 15:37:49 +04:00
log_verbose ( " No host tag matches %s/%s " ,
lv - > vg - > name , lv - > name ) ;
2004-03-08 21:13:22 +03:00
/* Don't activate */
return 0 ;
}
for ( cv = cn - > v ; cv ; cv = cv - > next ) {
2010-07-12 15:37:49 +04:00
log_verbose ( " activation/volume_list configuration setting "
" defined, checking the list to match %s/%s " ,
lv - > vg - > name , lv - > name ) ;
2004-03-08 21:13:22 +03:00
if ( cv - > type ! = CFG_STRING ) {
log_error ( " Ignoring invalid string in config file "
" activation/volume_list " ) ;
continue ;
}
str = cv - > v . str ;
if ( ! * str ) {
log_error ( " Ignoring empty string in config file "
" activation/volume_list " ) ;
continue ;
}
/* Tag? */
if ( * str = = ' @ ' ) {
str + + ;
if ( ! * str ) {
log_error ( " Ignoring empty tag in config file "
" activation/volume_list " ) ;
continue ;
}
/* If any host tag matches any LV or VG tag, activate */
if ( ! strcmp ( str , " * " ) ) {
if ( str_list_match_list ( & cmd - > tags , & lv - > tags )
| | str_list_match_list ( & cmd - > tags ,
& lv - > vg - > tags ) )
return 1 ;
else
continue ;
}
/* If supplied tag matches LV or VG tag, activate */
if ( str_list_match_item ( & lv - > tags , str ) | |
str_list_match_item ( & lv - > vg - > tags , str ) )
return 1 ;
else
continue ;
}
2007-07-02 15:17:21 +04:00
if ( ! strchr ( str , ' / ' ) ) {
2004-03-08 21:13:22 +03:00
/* vgname supplied */
if ( ! strcmp ( str , lv - > vg - > name ) )
return 1 ;
else
continue ;
}
/* vgname/lvname */
2006-08-21 16:54:53 +04:00
if ( dm_snprintf ( path , sizeof ( path ) , " %s/%s " , lv - > vg - > name ,
2004-03-08 21:13:22 +03:00
lv - > name ) < 0 ) {
2006-08-21 16:54:53 +04:00
log_error ( " dm_snprintf error from %s/%s " , lv - > vg - > name ,
2004-03-08 21:13:22 +03:00
lv - > name ) ;
continue ;
}
if ( ! strcmp ( path , str ) )
return 1 ;
}
2010-07-12 15:37:49 +04:00
log_verbose ( " No item supplied in activation/volume_list configuration "
" setting matches %s/%s " , lv - > vg - > name , lv - > name ) ;
2004-03-08 21:13:22 +03:00
return 0 ;
}
2002-01-17 19:39:24 +03:00
int library_version ( char * version , size_t size )
{
2002-11-18 17:01:16 +03:00
if ( ! activation ( ) )
return 0 ;
2005-10-17 22:00:02 +04:00
return dm_get_library_version ( version , size ) ;
2002-01-17 19:39:24 +03:00
}
int driver_version ( char * version , size_t size )
{
2002-11-18 17:01:16 +03:00
if ( ! activation ( ) )
return 0 ;
2002-01-17 19:39:24 +03:00
log_very_verbose ( " Getting driver version " ) ;
2005-10-17 22:00:02 +04:00
return dm_driver_version ( version , size ) ;
2002-01-17 19:39:24 +03:00
}
2005-12-20 00:01:39 +03:00
int target_version ( const char * target_name , uint32_t * maj ,
uint32_t * min , uint32_t * patchlevel )
2004-03-26 22:52:09 +03:00
{
int r = 0 ;
struct dm_task * dmt ;
struct dm_versions * target , * last_target ;
log_very_verbose ( " Getting target version for %s " , target_name ) ;
2005-11-09 01:52:26 +03:00
if ( ! ( dmt = dm_task_create ( DM_DEVICE_LIST_VERSIONS ) ) )
return_0 ;
2004-03-26 22:52:09 +03:00
if ( ! dm_task_run ( dmt ) ) {
log_debug ( " Failed to get %s target version " , target_name ) ;
/* Assume this was because LIST_VERSIONS isn't supported */
return 1 ;
}
target = dm_task_get_versions ( dmt ) ;
do {
last_target = target ;
if ( ! strcmp ( target_name , target - > name ) ) {
r = 1 ;
2005-12-20 00:01:39 +03:00
* maj = target - > version [ 0 ] ;
* min = target - > version [ 1 ] ;
* patchlevel = target - > version [ 2 ] ;
2004-03-26 22:52:09 +03:00
goto out ;
}
target = ( void * ) target + target - > next ;
} while ( last_target ! = target ) ;
out :
dm_task_destroy ( dmt ) ;
return r ;
}
2009-02-28 03:54:06 +03:00
int module_present ( struct cmd_context * cmd , const char * target_name )
2005-10-17 22:00:02 +04:00
{
2008-04-07 14:23:47 +04:00
int ret = 0 ;
2005-10-19 17:59:18 +04:00
# ifdef MODPROBE_CMD
2005-10-17 22:00:02 +04:00
char module [ 128 ] ;
2009-02-24 18:48:00 +03:00
const char * argv [ 3 ] ;
2008-04-07 14:23:47 +04:00
if ( dm_snprintf ( module , sizeof ( module ) , " dm-%s " , target_name ) < 0 ) {
log_error ( " module_present module name too long: %s " ,
target_name ) ;
return 0 ;
}
2009-02-24 18:48:00 +03:00
argv [ 0 ] = MODPROBE_CMD ;
argv [ 1 ] = module ;
argv [ 2 ] = NULL ;
2009-02-28 03:54:06 +03:00
ret = exec_cmd ( cmd , argv ) ;
2005-10-19 17:59:18 +04:00
# endif
2008-04-07 14:23:47 +04:00
return ret ;
}
2009-02-28 03:54:06 +03:00
int target_present ( struct cmd_context * cmd , const char * target_name ,
int use_modprobe )
2008-04-07 14:23:47 +04:00
{
uint32_t maj , min , patchlevel ;
2005-10-17 22:00:02 +04:00
if ( ! activation ( ) )
return 0 ;
# ifdef MODPROBE_CMD
2005-11-09 01:52:26 +03:00
if ( use_modprobe ) {
2005-12-20 00:01:39 +03:00
if ( target_version ( target_name , & maj , & min , & patchlevel ) )
2005-11-09 01:52:26 +03:00
return 1 ;
2005-10-17 22:00:02 +04:00
2009-02-28 03:54:06 +03:00
if ( ! module_present ( cmd , target_name ) )
2005-11-09 01:52:26 +03:00
return_0 ;
2005-10-17 22:00:02 +04:00
}
# endif
2005-12-20 00:01:39 +03:00
return target_version ( target_name , & maj , & min , & patchlevel ) ;
2005-10-17 22:00:02 +04:00
}
2002-02-26 14:49:17 +03:00
/*
* Returns 1 if info structure populated , else 0 on failure .
*/
2010-02-24 23:00:56 +03:00
int lv_info ( struct cmd_context * cmd , const struct logical_volume * lv ,
struct lvinfo * info , int with_open_count , int with_read_ahead )
2001-11-07 14:51:42 +03:00
{
2003-01-09 01:44:07 +03:00
struct dm_info dminfo ;
2002-01-11 02:21:07 +03:00
2002-11-18 17:01:16 +03:00
if ( ! activation ( ) )
return 0 ;
2010-02-24 23:00:56 +03:00
if ( ! dev_manager_info ( lv - > vg - > cmd - > mem , lv , with_open_count ,
with_read_ahead , & dminfo , & info - > read_ahead ) )
2005-11-09 01:52:26 +03:00
return_0 ;
2002-01-11 02:21:07 +03:00
2003-01-09 01:44:07 +03:00
info - > exists = dminfo . exists ;
info - > suspended = dminfo . suspended ;
info - > open_count = dminfo . open_count ;
info - > major = dminfo . major ;
info - > minor = dminfo . minor ;
info - > read_only = dminfo . read_only ;
2005-11-09 01:52:26 +03:00
info - > live_table = dminfo . live_table ;
info - > inactive_table = dminfo . inactive_table ;
2003-01-09 01:44:07 +03:00
2005-10-17 22:00:02 +04:00
return 1 ;
2002-02-26 14:49:17 +03:00
}
2002-02-11 20:42:02 +03:00
2004-03-26 18:35:01 +03:00
int lv_info_by_lvid ( struct cmd_context * cmd , const char * lvid_s ,
2007-11-12 23:51:54 +03:00
struct lvinfo * info , int with_open_count , int with_read_ahead )
2004-03-26 18:35:01 +03:00
{
2009-12-01 22:10:23 +03:00
int r ;
2004-03-26 18:35:01 +03:00
struct logical_volume * lv ;
2005-10-31 23:15:28 +03:00
if ( ! ( lv = lv_from_lvid ( cmd , lvid_s , 0 ) ) )
2004-03-26 18:35:01 +03:00
return 0 ;
2010-02-24 23:00:56 +03:00
r = lv_info ( cmd , lv , info , with_open_count , with_read_ahead ) ;
2009-12-01 22:10:23 +03:00
vg_release ( lv - > vg ) ;
return r ;
2004-03-26 18:35:01 +03:00
}
2010-05-24 19:32:20 +04:00
/*
* Returns 1 if percent set , else 0 on failure .
*/
int lv_check_transient ( struct logical_volume * lv )
{
int r ;
struct dev_manager * dm ;
if ( ! activation ( ) )
return 0 ;
if ( ! ( dm = dev_manager_create ( lv - > vg - > cmd , lv - > vg - > name ) ) )
return_0 ;
if ( ! ( r = dev_manager_transient ( dm , lv ) ) )
stack ;
dev_manager_destroy ( dm ) ;
return r ;
}
2002-05-10 01:17:57 +04:00
/*
* Returns 1 if percent set , else 0 on failure .
*/
2009-10-01 04:35:29 +04:00
int lv_snapshot_percent ( const struct logical_volume * lv , float * percent ,
percent_range_t * percent_range )
2002-05-10 01:17:57 +04:00
{
int r ;
struct dev_manager * dm ;
2002-11-18 17:01:16 +03:00
if ( ! activation ( ) )
return 0 ;
2005-11-09 01:52:26 +03:00
if ( ! ( dm = dev_manager_create ( lv - > vg - > cmd , lv - > vg - > name ) ) )
return_0 ;
2002-05-10 01:17:57 +04:00
2009-10-01 04:35:29 +04:00
if ( ! ( r = dev_manager_snapshot_percent ( dm , lv , percent , percent_range ) ) )
2002-05-10 01:17:57 +04:00
stack ;
2002-05-22 18:03:45 +04:00
2002-05-10 01:17:57 +04:00
dev_manager_destroy ( dm ) ;
return r ;
}
2003-04-30 19:26:25 +04:00
/* FIXME Merge with snapshot_percent */
2006-04-06 18:06:27 +04:00
int lv_mirror_percent ( struct cmd_context * cmd , struct logical_volume * lv ,
2009-10-01 04:35:29 +04:00
int wait , float * percent , percent_range_t * percent_range ,
uint32_t * event_nr )
2003-04-30 19:26:25 +04:00
{
int r ;
struct dev_manager * dm ;
2004-03-26 22:10:48 +03:00
struct lvinfo info ;
2003-04-30 19:26:25 +04:00
2008-01-16 22:18:51 +03:00
/* If mirrored LV is temporarily shrinked to 1 area (= linear),
* it should be considered in - sync . */
2008-11-04 01:14:30 +03:00
if ( dm_list_size ( & lv - > segments ) = = 1 & & first_seg ( lv ) - > area_count = = 1 ) {
2008-01-16 22:18:51 +03:00
* percent = 100.0 ;
return 1 ;
}
2003-04-30 19:26:25 +04:00
if ( ! activation ( ) )
return 0 ;
2007-11-12 23:51:54 +03:00
if ( ! lv_info ( cmd , lv , & info , 0 , 0 ) )
2005-11-09 01:52:26 +03:00
return_0 ;
2004-03-26 22:10:48 +03:00
if ( ! info . exists )
return 0 ;
2005-11-09 01:52:26 +03:00
if ( ! ( dm = dev_manager_create ( lv - > vg - > cmd , lv - > vg - > name ) ) )
return_0 ;
2003-04-30 19:26:25 +04:00
2009-10-01 04:35:29 +04:00
if ( ! ( r = dev_manager_mirror_percent ( dm , lv , wait , percent ,
percent_range , event_nr ) ) )
2003-04-30 19:26:25 +04:00
stack ;
dev_manager_destroy ( dm ) ;
return r ;
}
2010-02-24 23:00:56 +03:00
static int _lv_active ( struct cmd_context * cmd , struct logical_volume * lv )
2001-11-07 18:02:07 +03:00
{
2003-01-09 01:44:07 +03:00
struct lvinfo info ;
2001-11-07 18:02:07 +03:00
2010-02-24 23:00:56 +03:00
if ( ! lv_info ( cmd , lv , & info , 0 , 0 ) ) {
2001-11-07 18:02:07 +03:00
stack ;
2002-02-26 14:49:17 +03:00
return - 1 ;
2001-11-07 18:02:07 +03:00
}
2002-02-26 14:49:17 +03:00
return info . exists ;
2001-11-07 18:02:07 +03:00
}
2005-10-17 22:00:02 +04:00
static int _lv_open_count ( struct cmd_context * cmd , struct logical_volume * lv )
2002-02-18 18:52:48 +03:00
{
2003-01-09 01:44:07 +03:00
struct lvinfo info ;
2002-02-18 18:52:48 +03:00
2007-11-12 23:51:54 +03:00
if ( ! lv_info ( cmd , lv , & info , 1 , 0 ) ) {
2002-02-18 18:52:48 +03:00
stack ;
2002-02-26 14:49:17 +03:00
return - 1 ;
2002-02-18 18:52:48 +03:00
}
2002-02-26 14:49:17 +03:00
return info . open_count ;
2002-02-18 18:52:48 +03:00
}
2004-03-08 21:54:13 +03:00
static int _lv_activate_lv ( struct logical_volume * lv )
2001-10-09 20:05:34 +04:00
{
2002-02-11 18:48:34 +03:00
int r ;
2002-02-26 14:49:17 +03:00
struct dev_manager * dm ;
2001-10-09 20:05:34 +04:00
2005-11-09 01:52:26 +03:00
if ( ! ( dm = dev_manager_create ( lv - > vg - > cmd , lv - > vg - > name ) ) )
return_0 ;
2001-11-02 16:45:05 +03:00
2002-03-07 19:48:46 +03:00
if ( ! ( r = dev_manager_activate ( dm , lv ) ) )
2002-02-11 18:48:34 +03:00
stack ;
2001-11-02 16:45:05 +03:00
2002-02-26 14:49:17 +03:00
dev_manager_destroy ( dm ) ;
2001-11-02 16:45:05 +03:00
return r ;
2001-10-09 20:05:34 +04:00
}
2001-10-16 20:25:28 +04:00
2009-05-20 13:52:37 +04:00
static int _lv_preload ( struct logical_volume * lv , int * flush_required )
2001-10-31 20:59:52 +03:00
{
2002-02-26 14:49:17 +03:00
int r ;
struct dev_manager * dm ;
2001-11-07 14:51:42 +03:00
2005-11-09 01:52:26 +03:00
if ( ! ( dm = dev_manager_create ( lv - > vg - > cmd , lv - > vg - > name ) ) )
return_0 ;
2009-05-20 13:52:37 +04:00
if ( ! ( r = dev_manager_preload ( dm , lv , flush_required ) ) )
2002-02-11 18:48:34 +03:00
stack ;
2005-11-09 01:52:26 +03:00
dev_manager_destroy ( dm ) ;
return r ;
}
static int _lv_deactivate ( struct logical_volume * lv )
{
int r ;
struct dev_manager * dm ;
if ( ! ( dm = dev_manager_create ( lv - > vg - > cmd , lv - > vg - > name ) ) )
return_0 ;
2001-11-07 14:51:42 +03:00
2002-02-26 14:49:17 +03:00
if ( ! ( r = dev_manager_deactivate ( dm , lv ) ) )
2001-11-07 14:51:42 +03:00
stack ;
2002-02-26 14:49:17 +03:00
dev_manager_destroy ( dm ) ;
return r ;
2001-11-07 14:51:42 +03:00
}
2009-05-20 13:52:37 +04:00
static int _lv_suspend_lv ( struct logical_volume * lv , int lockfs , int flush_required )
2002-01-11 02:21:07 +03:00
{
2002-03-14 18:36:07 +03:00
int r ;
struct dev_manager * dm ;
2001-11-28 21:03:11 +03:00
2005-11-09 01:52:26 +03:00
if ( ! ( dm = dev_manager_create ( lv - > vg - > cmd , lv - > vg - > name ) ) )
return_0 ;
2001-10-31 20:59:52 +03:00
2009-05-20 13:52:37 +04:00
if ( ! ( r = dev_manager_suspend ( dm , lv , lockfs , flush_required ) ) )
2001-11-07 14:51:42 +03:00
stack ;
2001-10-31 20:59:52 +03:00
2002-03-14 18:36:07 +03:00
dev_manager_destroy ( dm ) ;
return r ;
2002-02-11 18:48:34 +03:00
}
2002-01-11 02:21:07 +03:00
2002-03-01 22:08:11 +03:00
/*
2004-05-11 22:18:14 +04:00
* These two functions return the number of visible LVs in the state ,
2002-03-01 22:08:11 +03:00
* or - 1 on error .
*/
2010-02-24 23:01:40 +03:00
int lvs_in_vg_activated ( struct volume_group * vg )
2001-11-02 19:28:04 +03:00
{
2005-06-01 20:51:55 +04:00
struct lv_list * lvl ;
2001-11-08 19:15:58 +03:00
int count = 0 ;
2001-11-07 14:51:42 +03:00
2002-11-18 17:01:16 +03:00
if ( ! activation ( ) )
return 0 ;
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( lvl , & vg - > lvs ) {
2009-05-14 01:26:45 +04:00
if ( lv_is_visible ( lvl - > lv ) )
2010-02-24 23:00:56 +03:00
count + = ( _lv_active ( vg - > cmd , lvl - > lv ) = = 1 ) ;
2001-11-07 14:51:42 +03:00
}
return count ;
2001-11-02 19:28:04 +03:00
}
2001-11-07 18:02:07 +03:00
2007-08-07 13:06:05 +04:00
int lvs_in_vg_opened ( const struct volume_group * vg )
2001-11-07 18:02:07 +03:00
{
2007-08-07 13:06:05 +04:00
const struct lv_list * lvl ;
2001-11-08 19:15:58 +03:00
int count = 0 ;
2001-11-07 18:02:07 +03:00
2002-11-18 17:01:16 +03:00
if ( ! activation ( ) )
return 0 ;
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( lvl , & vg - > lvs ) {
2009-05-14 01:27:43 +04:00
if ( lv_is_visible ( lvl - > lv ) )
2005-10-17 22:00:02 +04:00
count + = ( _lv_open_count ( vg - > cmd , lvl - > lv ) > 0 ) ;
2001-11-07 18:02:07 +03:00
}
return count ;
}
2002-02-25 15:56:16 +03:00
2008-04-11 01:34:18 +04:00
/*
* Determine whether an LV is active locally or in a cluster .
* Assumes vg lock held .
* Returns :
* 0 - not active locally or on any node in cluster
* 1 - active either locally or some node in the cluster
*/
int lv_is_active ( struct logical_volume * lv )
{
2009-05-20 16:58:03 +04:00
int ret ;
2010-02-24 23:00:56 +03:00
if ( _lv_active ( lv - > vg - > cmd , lv ) )
2008-04-11 01:34:18 +04:00
return 1 ;
if ( ! vg_is_clustered ( lv - > vg ) )
return 0 ;
2009-05-20 16:58:03 +04:00
if ( ( ret = remote_lock_held ( lv - > lvid . s ) ) > = 0 )
return ret ;
/*
* Old compatibility code if locking doesn ' t support lock query
* FIXME : check status to not deactivate already activate device
*/
if ( activate_lv_excl ( lv - > vg - > cmd , lv ) ) {
2010-01-06 00:08:34 +03:00
if ( ! deactivate_lv ( lv - > vg - > cmd , lv ) )
stack ;
2009-05-21 07:04:52 +04:00
return 0 ;
2009-05-20 16:58:03 +04:00
}
/*
* Exclusive local activation failed so assume it is active elsewhere .
*/
return 1 ;
2008-04-11 01:34:18 +04:00
}
2006-05-12 23:16:48 +04:00
/*
2007-01-20 01:21:45 +03:00
* Returns 0 if an attempt to ( un ) monitor the device failed .
* Returns 1 otherwise .
2006-05-12 23:16:48 +04:00
*/
2007-01-20 01:21:45 +03:00
int monitor_dev_for_events ( struct cmd_context * cmd ,
struct logical_volume * lv , int monitor )
2005-12-02 23:35:07 +03:00
{
2006-01-27 21:38:14 +03:00
# ifdef DMEVENTD
2007-01-20 01:21:45 +03:00
int i , pending = 0 , monitored ;
int r = 1 ;
2008-11-04 01:14:30 +03:00
struct dm_list * tmp , * snh , * snht ;
2005-12-02 23:35:07 +03:00
struct lv_segment * seg ;
2010-03-27 01:15:43 +03:00
struct lv_segment * log_seg ;
2007-01-25 01:06:11 +03:00
int ( * monitor_fn ) ( struct lv_segment * s , int e ) ;
2008-01-31 15:19:36 +03:00
uint32_t s ;
2005-12-02 23:35:07 +03:00
2007-01-25 02:43:27 +03:00
/* skip dmeventd code altogether */
if ( dmeventd_monitor_mode ( ) = = DMEVENTD_MONITOR_IGNORE )
return 1 ;
2007-01-20 01:21:45 +03:00
/*
* Nothing to do if dmeventd configured not to be used .
*/
if ( monitor & & ! dmeventd_monitor_mode ( ) )
2006-05-12 23:16:48 +04:00
return 1 ;
2008-01-09 18:32:19 +03:00
/*
* In case of a snapshot device , we monitor lv - > snapshot - > lv ,
* not the actual LV itself .
*/
2010-01-13 04:55:43 +03:00
if ( lv_is_cow ( lv ) & & ! lv_is_merging_cow ( lv ) )
2008-01-09 18:32:19 +03:00
return monitor_dev_for_events ( cmd , lv - > snapshot - > lv , monitor ) ;
/*
* In case this LV is a snapshot origin , we instead monitor
* each of its respective snapshots ( the origin itself does
* not need to be monitored ) .
*
* TODO : This may change when snapshots of mirrors are allowed .
*/
if ( lv_is_origin ( lv ) ) {
2008-11-04 01:14:30 +03:00
dm_list_iterate_safe ( snh , snht , & lv - > snapshot_segs )
if ( ! monitor_dev_for_events ( cmd , dm_list_struct_base ( snh ,
2008-01-17 20:17:09 +03:00
struct lv_segment , origin_list ) - > cow , monitor ) )
r = 0 ;
2008-01-09 18:32:19 +03:00
return r ;
}
2010-03-27 01:15:43 +03:00
/*
* If the volume is mirrored and its log is also mirrored , monitor
* the log volume as well .
*/
if ( ( seg = first_seg ( lv ) ) ! = NULL & & seg - > log_lv ! = NULL & &
( log_seg = first_seg ( seg - > log_lv ) ) ! = NULL & &
seg_is_mirrored ( log_seg ) )
if ( ! monitor_dev_for_events ( cmd , seg - > log_lv , monitor ) )
r = 0 ;
2008-11-04 01:14:30 +03:00
dm_list_iterate ( tmp , & lv - > segments ) {
seg = dm_list_item ( tmp , struct lv_segment ) ;
2005-12-02 23:35:07 +03:00
2008-01-31 15:19:36 +03:00
/* Recurse for AREA_LV */
for ( s = 0 ; s < seg - > area_count ; s + + ) {
if ( seg_type ( seg , s ) ! = AREA_LV )
continue ;
if ( ! monitor_dev_for_events ( cmd , seg_lv ( seg , s ) ,
monitor ) ) {
log_error ( " Failed to %smonitor %s " ,
monitor ? " " : " un " ,
seg_lv ( seg , s ) - > name ) ;
r = 0 ;
}
}
2007-01-12 23:38:30 +03:00
if ( ! seg_monitored ( seg ) | | ( seg - > status & PVMOVE ) )
continue ;
2007-01-20 01:21:45 +03:00
monitor_fn = NULL ;
2006-01-27 21:38:14 +03:00
2007-01-12 23:38:30 +03:00
/* Check monitoring status */
2007-01-20 01:21:45 +03:00
if ( seg - > segtype - > ops - > target_monitored )
monitored = seg - > segtype - > ops - > target_monitored ( seg , & pending ) ;
2007-01-12 23:38:30 +03:00
else
continue ; /* segtype doesn't support registration */
/*
* FIXME : We should really try again if pending
*/
2007-01-20 01:21:45 +03:00
monitored = ( pending ) ? 0 : monitored ;
2007-01-12 23:38:30 +03:00
2007-01-20 01:21:45 +03:00
if ( monitor ) {
if ( monitored )
2007-01-12 23:38:30 +03:00
log_verbose ( " %s/%s already monitored. " , lv - > vg - > name , lv - > name ) ;
2007-01-20 01:21:45 +03:00
else if ( seg - > segtype - > ops - > target_monitor_events )
monitor_fn = seg - > segtype - > ops - > target_monitor_events ;
2007-01-12 23:38:30 +03:00
} else {
2007-01-20 01:21:45 +03:00
if ( ! monitored )
2007-01-12 23:38:30 +03:00
log_verbose ( " %s/%s already not monitored. " , lv - > vg - > name , lv - > name ) ;
2007-01-20 01:21:45 +03:00
else if ( seg - > segtype - > ops - > target_unmonitor_events )
monitor_fn = seg - > segtype - > ops - > target_unmonitor_events ;
2007-01-12 23:38:30 +03:00
}
2005-12-02 23:35:07 +03:00
2007-01-12 23:38:30 +03:00
/* Do [un]monitor */
2007-01-20 01:21:45 +03:00
if ( ! monitor_fn )
2006-05-12 23:16:48 +04:00
continue ;
2006-04-28 18:06:06 +04:00
2007-01-20 01:21:45 +03:00
log_verbose ( " %sonitoring %s/%s " , monitor ? " M " : " Not m " , lv - > vg - > name , lv - > name ) ;
2006-05-12 23:16:48 +04:00
/* FIXME specify events */
2007-01-24 19:51:24 +03:00
if ( ! monitor_fn ( seg , 0 ) ) {
2007-01-20 01:21:45 +03:00
log_error ( " %s/%s: %s segment monitoring function failed. " ,
lv - > vg - > name , lv - > name , seg - > segtype - > name ) ;
return 0 ;
2006-04-28 18:06:06 +04:00
}
2006-05-12 23:16:48 +04:00
2007-01-12 23:38:30 +03:00
/* Check [un]monitor results */
/* Try a couple times if pending, but not forever... */
for ( i = 0 ; i < 10 ; i + + ) {
pending = 0 ;
2007-01-20 01:21:45 +03:00
monitored = seg - > segtype - > ops - > target_monitored ( seg , & pending ) ;
2007-01-12 23:38:30 +03:00
if ( pending | |
2007-01-20 01:21:45 +03:00
( ! monitored & & monitor ) | |
( monitored & & ! monitor ) )
log_very_verbose ( " %s/%s %smonitoring still pending: waiting... " ,
lv - > vg - > name , lv - > name , monitor ? " " : " un " ) ;
2007-01-12 23:38:30 +03:00
else
break ;
sleep ( 1 ) ;
}
2007-01-20 01:21:45 +03:00
r = ( monitored & & monitor ) | | ( ! monitored & & ! monitor ) ;
2005-12-02 23:35:07 +03:00
}
2005-12-08 20:49:34 +03:00
2006-05-12 23:16:48 +04:00
return r ;
# else
2005-12-02 23:35:07 +03:00
return 1 ;
2006-05-12 23:16:48 +04:00
# endif
2005-12-02 23:35:07 +03:00
}
2004-03-08 21:54:13 +03:00
static int _lv_suspend ( struct cmd_context * cmd , const char * lvid_s ,
int error_if_not_suspended )
2002-02-25 15:56:16 +03:00
{
2009-04-10 14:00:04 +04:00
struct logical_volume * lv = NULL , * lv_pre = NULL ;
2003-01-09 01:44:07 +03:00
struct lvinfo info ;
2009-05-20 13:52:37 +04:00
int r = 0 , lockfs = 0 , flush_required = 0 ;
2002-02-25 15:56:16 +03:00
2002-11-18 17:01:16 +03:00
if ( ! activation ( ) )
return 1 ;
2006-01-27 23:39:37 +03:00
if ( ! ( lv = lv_from_lvid ( cmd , lvid_s , 0 ) ) )
2009-04-10 14:00:04 +04:00
goto_out ;
2006-01-27 23:39:37 +03:00
2005-10-31 23:15:28 +03:00
/* Use precommitted metadata if present */
2006-01-27 23:39:37 +03:00
if ( ! ( lv_pre = lv_from_lvid ( cmd , lvid_s , 1 ) ) )
2009-04-10 14:00:04 +04:00
goto_out ;
2002-02-25 15:56:16 +03:00
2002-03-14 18:36:07 +03:00
if ( test_mode ( ) ) {
_skip ( " Suspending '%s'. " , lv - > name ) ;
2009-04-10 14:00:04 +04:00
r = 1 ;
goto out ;
2002-03-14 18:36:07 +03:00
}
2007-11-12 23:51:54 +03:00
if ( ! lv_info ( cmd , lv , & info , 0 , 0 ) )
2009-04-10 14:00:04 +04:00
goto_out ;
2002-03-11 22:02:28 +03:00
2009-04-10 14:00:04 +04:00
if ( ! info . exists | | info . suspended ) {
2009-12-03 22:23:40 +03:00
if ( ! error_if_not_suspended ) {
r = 1 ;
if ( info . suspended )
2010-03-05 17:48:33 +03:00
memlock_inc ( cmd ) ;
2009-12-03 22:23:40 +03:00
}
2009-04-10 14:00:04 +04:00
goto out ;
}
2003-07-05 02:34:56 +04:00
2010-05-21 18:34:01 +04:00
if ( ! lv_read_replicator_vgs ( lv ) )
goto_out ;
2009-06-01 16:43:31 +04:00
lv_calculate_readahead ( lv , NULL ) ;
2005-11-09 01:52:26 +03:00
/* If VG was precommitted, preload devices for the LV */
2006-01-27 23:39:37 +03:00
if ( ( lv_pre - > vg - > status & PRECOMMITTED ) ) {
2009-05-20 13:52:37 +04:00
if ( ! _lv_preload ( lv_pre , & flush_required ) ) {
2005-11-09 01:52:26 +03:00
/* FIXME Revert preloading */
2009-04-10 14:00:04 +04:00
goto_out ;
2005-11-09 01:52:26 +03:00
}
}
2007-01-20 01:21:45 +03:00
if ( ! monitor_dev_for_events ( cmd , lv , 0 ) )
2006-04-28 18:06:06 +04:00
/* FIXME Consider aborting here */
2006-01-27 21:38:14 +03:00
stack ;
2010-03-05 17:48:33 +03:00
memlock_inc ( cmd ) ;
2006-08-09 01:20:00 +04:00
if ( lv_is_origin ( lv_pre ) | | lv_is_cow ( lv_pre ) )
lockfs = 1 ;
2009-05-20 13:52:37 +04:00
if ( ! _lv_suspend_lv ( lv , lockfs , flush_required ) ) {
2010-03-05 17:48:33 +03:00
memlock_dec ( cmd ) ;
2003-07-05 02:34:56 +04:00
fs_unlock ( ) ;
2009-04-10 14:00:04 +04:00
goto out ;
2003-07-05 02:34:56 +04:00
}
2002-03-01 22:08:11 +03:00
2009-04-10 14:00:04 +04:00
r = 1 ;
out :
if ( lv_pre )
vg_release ( lv_pre - > vg ) ;
2010-05-21 18:34:01 +04:00
if ( lv ) {
lv_release_replicator_vgs ( lv ) ;
2009-04-10 14:00:04 +04:00
vg_release ( lv - > vg ) ;
2010-05-21 18:34:01 +04:00
}
2009-04-10 14:00:04 +04:00
return r ;
2002-02-25 15:56:16 +03:00
}
2004-03-08 21:54:13 +03:00
/* Returns success if the device is not active */
int lv_suspend_if_active ( struct cmd_context * cmd , const char * lvid_s )
{
return _lv_suspend ( cmd , lvid_s , 0 ) ;
}
int lv_suspend ( struct cmd_context * cmd , const char * lvid_s )
{
return _lv_suspend ( cmd , lvid_s , 1 ) ;
}
static int _lv_resume ( struct cmd_context * cmd , const char * lvid_s ,
int error_if_not_active )
2002-02-25 15:56:16 +03:00
{
struct logical_volume * lv ;
2003-01-09 01:44:07 +03:00
struct lvinfo info ;
2009-04-10 14:00:04 +04:00
int r = 0 ;
2002-02-25 15:56:16 +03:00
2002-11-18 17:01:16 +03:00
if ( ! activation ( ) )
return 1 ;
2005-10-31 23:15:28 +03:00
if ( ! ( lv = lv_from_lvid ( cmd , lvid_s , 0 ) ) )
2009-10-30 16:07:49 +03:00
goto_out ;
2002-02-25 15:56:16 +03:00
2002-03-14 18:36:07 +03:00
if ( test_mode ( ) ) {
_skip ( " Resuming '%s'. " , lv - > name ) ;
2009-04-10 14:00:04 +04:00
r = 1 ;
goto out ;
2002-03-14 18:36:07 +03:00
}
2007-11-12 23:51:54 +03:00
if ( ! lv_info ( cmd , lv , & info , 0 , 0 ) )
2009-04-10 14:00:04 +04:00
goto_out ;
2002-03-11 22:02:28 +03:00
2009-04-10 14:00:04 +04:00
if ( ! info . exists | | ! info . suspended ) {
2010-07-08 16:24:04 +04:00
if ( error_if_not_active )
goto_out ;
r = 1 ;
goto out ;
2009-04-10 14:00:04 +04:00
}
2003-07-05 02:34:56 +04:00
2004-03-08 21:54:13 +03:00
if ( ! _lv_activate_lv ( lv ) )
2009-10-30 16:07:49 +03:00
goto_out ;
2003-07-05 02:34:56 +04:00
2010-03-05 17:48:33 +03:00
memlock_dec ( cmd ) ;
2003-07-05 02:34:56 +04:00
fs_unlock ( ) ;
2002-02-25 15:56:16 +03:00
2007-01-20 01:21:45 +03:00
if ( ! monitor_dev_for_events ( cmd , lv , 1 ) )
2006-01-27 21:38:14 +03:00
stack ;
2005-12-02 23:35:07 +03:00
2009-04-10 14:00:04 +04:00
r = 1 ;
out :
if ( lv )
vg_release ( lv - > vg ) ;
return r ;
2002-02-25 15:56:16 +03:00
}
2004-03-08 21:54:13 +03:00
/* Returns success if the device is not active */
int lv_resume_if_active ( struct cmd_context * cmd , const char * lvid_s )
{
return _lv_resume ( cmd , lvid_s , 0 ) ;
}
int lv_resume ( struct cmd_context * cmd , const char * lvid_s )
{
return _lv_resume ( cmd , lvid_s , 1 ) ;
}
2009-09-29 22:50:28 +04:00
static int _lv_has_open_snapshots ( struct logical_volume * lv )
{
struct lv_segment * snap_seg ;
struct lvinfo info ;
int r = 0 ;
dm_list_iterate_items_gen ( snap_seg , & lv - > snapshot_segs , origin_list ) {
if ( ! lv_info ( lv - > vg - > cmd , snap_seg - > cow , & info , 1 , 0 ) ) {
r = 1 ;
continue ;
}
if ( info . exists & & info . open_count ) {
log_error ( " LV %s/%s has open snapshot %s: "
" not deactivating " , lv - > vg - > name , lv - > name ,
snap_seg - > cow - > name ) ;
r = 1 ;
}
}
return r ;
}
2002-03-11 18:08:39 +03:00
int lv_deactivate ( struct cmd_context * cmd , const char * lvid_s )
2002-02-27 15:26:41 +03:00
{
struct logical_volume * lv ;
2003-01-09 01:44:07 +03:00
struct lvinfo info ;
2009-04-10 14:00:04 +04:00
int r = 0 ;
2002-02-27 15:26:41 +03:00
2002-11-18 17:01:16 +03:00
if ( ! activation ( ) )
return 1 ;
2005-10-31 23:15:28 +03:00
if ( ! ( lv = lv_from_lvid ( cmd , lvid_s , 0 ) ) )
2009-04-10 14:00:04 +04:00
goto out ;
2002-02-27 15:26:41 +03:00
2002-03-14 18:36:07 +03:00
if ( test_mode ( ) ) {
_skip ( " Deactivating '%s'. " , lv - > name ) ;
2009-04-10 14:00:04 +04:00
r = 1 ;
goto out ;
2002-03-14 18:36:07 +03:00
}
2007-11-12 23:51:54 +03:00
if ( ! lv_info ( cmd , lv , & info , 1 , 0 ) )
2009-04-10 14:00:04 +04:00
goto_out ;
2002-03-11 22:02:28 +03:00
2009-04-10 14:00:04 +04:00
if ( ! info . exists ) {
r = 1 ;
goto out ;
}
2002-02-27 15:26:41 +03:00
2009-09-29 22:50:28 +04:00
if ( lv_is_visible ( lv ) ) {
if ( info . open_count ) {
log_error ( " LV %s/%s in use: not deactivating " ,
lv - > vg - > name , lv - > name ) ;
goto out ;
}
if ( lv_is_origin ( lv ) & & _lv_has_open_snapshots ( lv ) )
goto_out ;
2003-10-22 02:00:36 +04:00
}
2010-05-21 18:34:01 +04:00
if ( ! lv_read_replicator_vgs ( lv ) )
goto_out ;
2009-06-01 16:43:31 +04:00
lv_calculate_readahead ( lv , NULL ) ;
2007-01-20 01:21:45 +03:00
if ( ! monitor_dev_for_events ( cmd , lv , 0 ) )
2006-01-27 21:38:14 +03:00
stack ;
2005-12-02 23:35:07 +03:00
2010-03-05 17:48:33 +03:00
memlock_inc ( cmd ) ;
2003-07-05 02:34:56 +04:00
r = _lv_deactivate ( lv ) ;
2010-03-05 17:48:33 +03:00
memlock_dec ( cmd ) ;
2003-07-05 02:34:56 +04:00
fs_unlock ( ) ;
2009-09-29 19:17:54 +04:00
if ( ! lv_info ( cmd , lv , & info , 1 , 0 ) | | info . exists )
r = 0 ;
2009-04-10 14:00:04 +04:00
out :
2010-05-21 18:34:01 +04:00
if ( lv ) {
lv_release_replicator_vgs ( lv ) ;
2009-04-10 14:00:04 +04:00
vg_release ( lv - > vg ) ;
2010-05-21 18:34:01 +04:00
}
2009-04-10 14:00:04 +04:00
2003-07-05 02:34:56 +04:00
return r ;
2002-02-27 15:26:41 +03:00
}
2004-03-08 21:54:13 +03:00
/* Test if LV passes filter */
int lv_activation_filter ( struct cmd_context * cmd , const char * lvid_s ,
int * activate_lv )
{
struct logical_volume * lv ;
2009-04-10 14:00:04 +04:00
int r = 0 ;
2004-03-08 21:54:13 +03:00
2009-04-10 14:00:04 +04:00
if ( ! activation ( ) ) {
* activate_lv = 1 ;
return 1 ;
}
2004-03-08 21:54:13 +03:00
2008-06-08 15:33:15 +04:00
if ( ! ( lv = lv_from_lvid ( cmd , lvid_s , 0 ) ) )
2009-04-10 14:00:04 +04:00
goto out ;
2004-03-08 21:54:13 +03:00
if ( ! _passes_activation_filter ( cmd , lv ) ) {
log_verbose ( " Not activating %s/%s due to config file settings " ,
lv - > vg - > name , lv - > name ) ;
* activate_lv = 0 ;
2009-04-10 14:00:04 +04:00
} else
* activate_lv = 1 ;
r = 1 ;
out :
if ( lv )
vg_release ( lv - > vg ) ;
2004-03-08 21:54:13 +03:00
2009-04-10 14:00:04 +04:00
return r ;
2004-03-08 21:54:13 +03:00
}
2005-08-15 03:18:28 +04:00
static int _lv_activate ( struct cmd_context * cmd , const char * lvid_s ,
int exclusive , int filter )
2002-02-27 15:26:41 +03:00
{
struct logical_volume * lv ;
2003-01-09 01:44:07 +03:00
struct lvinfo info ;
2009-04-10 14:00:04 +04:00
int r = 0 ;
2002-02-27 15:26:41 +03:00
2002-11-18 17:01:16 +03:00
if ( ! activation ( ) )
return 1 ;
2008-06-08 15:33:15 +04:00
if ( ! ( lv = lv_from_lvid ( cmd , lvid_s , 0 ) ) )
2009-04-10 14:00:04 +04:00
goto out ;
2002-02-27 15:26:41 +03:00
2004-03-08 21:54:13 +03:00
if ( filter & & ! _passes_activation_filter ( cmd , lv ) ) {
2004-03-08 21:13:22 +03:00
log_verbose ( " Not activating %s/%s due to config file settings " ,
lv - > vg - > name , lv - > name ) ;
2009-04-10 14:00:04 +04:00
goto out ;
2004-03-08 21:13:22 +03:00
}
2008-09-19 11:12:45 +04:00
if ( ( ! lv - > vg - > cmd - > partial_activation ) & & ( lv - > status & PARTIAL_LV ) ) {
2008-09-19 10:42:00 +04:00
log_error ( " Refusing activation of partial LV %s. Use --partial to override. " ,
lv - > name ) ;
2009-04-10 14:00:04 +04:00
goto_out ;
2008-09-19 10:42:00 +04:00
}
2009-10-16 21:41:49 +04:00
if ( lv_has_unknown_segments ( lv ) ) {
log_error ( " Refusing activation of LV %s containing "
" an unrecognised segment. " , lv - > name ) ;
goto_out ;
}
2002-03-14 18:36:07 +03:00
if ( test_mode ( ) ) {
_skip ( " Activating '%s'. " , lv - > name ) ;
2009-04-10 14:00:04 +04:00
r = 1 ;
goto out ;
2002-03-14 18:36:07 +03:00
}
2007-11-12 23:51:54 +03:00
if ( ! lv_info ( cmd , lv , & info , 0 , 0 ) )
2009-04-10 14:00:04 +04:00
goto_out ;
2002-03-01 22:08:11 +03:00
2009-04-10 14:00:04 +04:00
if ( info . exists & & ! info . suspended & & info . live_table ) {
r = 1 ;
goto out ;
}
2002-02-27 15:26:41 +03:00
2010-05-21 18:34:01 +04:00
if ( ! lv_read_replicator_vgs ( lv ) )
goto_out ;
2009-06-01 16:43:31 +04:00
lv_calculate_readahead ( lv , NULL ) ;
2005-08-15 03:18:28 +04:00
if ( exclusive )
lv - > status | = ACTIVATE_EXCL ;
2010-03-05 17:48:33 +03:00
memlock_inc ( cmd ) ;
2009-10-30 16:07:49 +03:00
if ( ! ( r = _lv_activate_lv ( lv ) ) )
stack ;
2010-03-05 17:48:33 +03:00
memlock_dec ( cmd ) ;
2003-07-05 02:34:56 +04:00
fs_unlock ( ) ;
2007-08-02 00:29:07 +04:00
if ( r & & ! monitor_dev_for_events ( cmd , lv , 1 ) )
2006-01-27 21:38:14 +03:00
stack ;
2005-12-02 23:35:07 +03:00
2009-04-10 14:00:04 +04:00
out :
2010-05-21 18:34:01 +04:00
if ( lv ) {
lv_release_replicator_vgs ( lv ) ;
2009-04-10 14:00:04 +04:00
vg_release ( lv - > vg ) ;
2010-05-21 18:34:01 +04:00
}
2009-04-10 14:00:04 +04:00
2003-07-05 02:34:56 +04:00
return r ;
2002-02-27 15:26:41 +03:00
}
2003-01-09 01:44:07 +03:00
2004-03-08 21:54:13 +03:00
/* Activate LV */
2005-08-15 03:18:28 +04:00
int lv_activate ( struct cmd_context * cmd , const char * lvid_s , int exclusive )
2004-03-08 21:54:13 +03:00
{
2009-10-30 16:07:49 +03:00
if ( ! _lv_activate ( cmd , lvid_s , exclusive , 0 ) )
return_0 ;
return 1 ;
2004-03-08 21:54:13 +03:00
}
/* Activate LV only if it passes filter */
2005-08-15 03:18:28 +04:00
int lv_activate_with_filter ( struct cmd_context * cmd , const char * lvid_s , int exclusive )
2004-03-08 21:54:13 +03:00
{
2009-10-30 16:07:49 +03:00
if ( ! _lv_activate ( cmd , lvid_s , exclusive , 1 ) )
return_0 ;
return 1 ;
2004-03-08 21:54:13 +03:00
}
2003-11-12 22:16:48 +03:00
int lv_mknodes ( struct cmd_context * cmd , const struct logical_volume * lv )
{
int r = 1 ;
2004-03-30 18:40:03 +04:00
if ( ! lv ) {
2005-10-17 03:03:59 +04:00
r = dm_mknodes ( NULL ) ;
2004-03-30 18:40:03 +04:00
fs_unlock ( ) ;
return r ;
}
2010-02-24 23:00:56 +03:00
if ( ! activation ( ) )
return 1 ;
2003-11-12 22:16:48 +03:00
2010-02-24 23:00:56 +03:00
r = dev_manager_mknodes ( lv ) ;
2003-11-12 22:16:48 +03:00
fs_unlock ( ) ;
return r ;
}
2005-10-25 23:08:21 +04:00
/*
* Does PV use VG somewhere in its construction ?
* Returns 1 on failure .
*/
2006-05-11 21:58:58 +04:00
int pv_uses_vg ( struct physical_volume * pv ,
2006-05-12 23:16:48 +04:00
struct volume_group * vg )
2005-10-25 23:08:21 +04:00
{
if ( ! activation ( ) )
return 0 ;
if ( ! dm_is_dm_major ( MAJOR ( pv - > dev - > dev ) ) )
return 0 ;
2006-05-11 21:58:58 +04:00
return dev_manager_device_uses_vg ( pv - > dev , vg ) ;
2005-10-25 23:08:21 +04:00
}
2006-05-16 20:48:31 +04:00
void activation_release ( void )
{
dev_manager_release ( ) ;
}
2003-07-05 02:34:56 +04:00
void activation_exit ( void )
{
dev_manager_exit ( ) ;
}
2003-01-09 01:44:07 +03:00
# endif