2001-10-30 17:32:48 +03:00
/*
2008-01-30 17:00:02 +03:00
* Copyright ( C ) 2001 - 2004 Sistina Software , Inc . All rights reserved .
2007-08-21 00:55:30 +04:00
* Copyright ( C ) 2004 - 2007 Red Hat , Inc . All rights reserved .
2001-10-30 17:32:48 +03:00
*
2004-03-30 23:35:44 +04:00
* This file is part of LVM2 .
2001-10-30 17:32:48 +03:00
*
2004-03-30 23:35:44 +04:00
* 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 .
2001-10-30 17:32:48 +03: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-30 17:32:48 +03:00
*/
# include "tools.h"
2002-02-12 00:00:35 +03:00
static int lvchange_permission ( struct cmd_context * cmd ,
struct logical_volume * lv )
2001-10-30 17:32:48 +03:00
{
2002-12-20 02:25:55 +03:00
uint32_t lv_access ;
2007-01-10 22:56:39 +03:00
struct lvinfo info ;
2009-04-21 18:31:57 +04:00
int r = 0 ;
2001-10-30 17:32:48 +03:00
2002-12-20 02:25:55 +03:00
lv_access = arg_uint_value ( cmd , permission_ARG , 0 ) ;
2001-10-30 17:32:48 +03:00
if ( ( lv_access & LVM_WRITE ) & & ( lv - > status & LVM_WRITE ) ) {
2002-02-12 00:00:35 +03:00
log_error ( " Logical volume \" %s \" is already writable " ,
lv - > name ) ;
2001-10-30 17:32:48 +03:00
return 0 ;
}
if ( ! ( lv_access & LVM_WRITE ) & & ! ( lv - > status & LVM_WRITE ) ) {
2002-02-12 00:00:35 +03:00
log_error ( " Logical volume \" %s \" is already read only " ,
lv - > name ) ;
2001-10-30 17:32:48 +03:00
return 0 ;
}
2008-04-10 21:09:32 +04:00
if ( ( lv - > status & MIRRORED ) & & ( vg_is_clustered ( lv - > vg ) ) & &
2007-11-12 23:51:54 +03:00
lv_info ( cmd , lv , & info , 0 , 0 ) & & info . exists ) {
2007-01-10 22:56:39 +03:00
log_error ( " Cannot change permissions of mirror \" %s \" "
" while active. " , lv - > name ) ;
return 0 ;
}
2001-10-30 17:32:48 +03:00
if ( lv_access & LVM_WRITE ) {
lv - > status | = LVM_WRITE ;
2002-02-12 00:00:35 +03:00
log_verbose ( " Setting logical volume \" %s \" read/write " ,
lv - > name ) ;
2001-10-30 17:32:48 +03:00
} else {
lv - > status & = ~ LVM_WRITE ;
2002-02-12 00:00:35 +03:00
log_verbose ( " Setting logical volume \" %s \" read-only " ,
lv - > name ) ;
2001-10-30 17:32:48 +03:00
}
2003-07-05 02:34:56 +04:00
log_very_verbose ( " Updating logical volume \" %s \" on disk(s) " , lv - > name ) ;
2008-01-30 16:19:47 +03:00
if ( ! vg_write ( lv - > vg ) )
return_0 ;
2003-07-05 02:34:56 +04:00
2005-08-15 16:00:04 +04:00
if ( ! suspend_lv ( cmd , lv ) ) {
2002-02-21 00:30:27 +03:00
log_error ( " Failed to lock %s " , lv - > name ) ;
2003-07-05 02:34:56 +04:00
vg_revert ( lv - > vg ) ;
2009-04-21 18:31:57 +04:00
goto out ;
2002-02-21 00:30:27 +03:00
}
2003-07-05 02:34:56 +04:00
if ( ! vg_commit ( lv - > vg ) ) {
2005-08-15 16:00:04 +04:00
resume_lv ( cmd , lv ) ;
2009-04-21 18:31:57 +04:00
goto_out ;
2002-02-21 00:30:27 +03:00
}
2001-10-31 20:59:52 +03:00
2002-01-30 18:04:48 +03:00
log_very_verbose ( " Updating permissions for \" %s \" in kernel " , lv - > name ) ;
2005-08-15 16:00:04 +04:00
if ( ! resume_lv ( cmd , lv ) ) {
2002-04-24 22:20:51 +04:00
log_error ( " Problem reactivating %s " , lv - > name ) ;
2009-04-21 18:31:57 +04:00
goto out ;
2002-04-24 22:20:51 +04:00
}
2001-10-31 20:59:52 +03:00
2009-04-22 16:46:25 +04:00
r = 1 ;
2009-04-21 18:31:57 +04:00
out :
backup ( lv - > vg ) ;
return r ;
2001-10-30 17:32:48 +03:00
}
2007-01-20 01:21:45 +03:00
static int lvchange_monitoring ( struct cmd_context * cmd ,
struct logical_volume * lv )
2006-05-12 23:16:48 +04:00
{
struct lvinfo info ;
2007-11-12 23:51:54 +03:00
if ( ! lv_info ( cmd , lv , & info , 0 , 0 ) | | ! info . exists ) {
2006-05-12 23:16:48 +04:00
log_error ( " Logical volume, %s, is not active " , lv - > name ) ;
return 0 ;
}
2007-01-20 01:21:45 +03:00
/* do not monitor pvmove lv's */
2006-05-12 23:16:48 +04:00
if ( lv - > status & PVMOVE )
return 1 ;
2007-01-25 02:43:27 +03:00
if ( ( dmeventd_monitor_mode ( ) ! = DMEVENTD_MONITOR_IGNORE ) & &
! monitor_dev_for_events ( cmd , lv , dmeventd_monitor_mode ( ) ) )
2007-01-20 01:21:45 +03:00
stack ;
2006-05-12 23:16:48 +04:00
2007-01-20 01:21:45 +03:00
return 1 ;
2006-05-12 23:16:48 +04:00
}
2002-02-12 00:00:35 +03:00
static int lvchange_availability ( struct cmd_context * cmd ,
struct logical_volume * lv )
2001-10-30 17:32:48 +03:00
{
2004-05-24 17:44:10 +04:00
int activate ;
2004-05-05 21:56:20 +04:00
const char * pvname ;
2001-10-30 17:32:48 +03:00
2004-05-24 17:44:10 +04:00
activate = arg_uint_value ( cmd , available_ARG , 0 ) ;
2001-10-30 17:32:48 +03:00
2004-06-16 21:13:41 +04:00
if ( activate = = CHANGE_ALN ) {
log_verbose ( " Deactivating logical volume \" %s \" locally " ,
lv - > name ) ;
2008-01-30 16:19:47 +03:00
if ( ! deactivate_lv_local ( cmd , lv ) )
return_0 ;
2004-06-16 21:13:41 +04:00
} else if ( activate = = CHANGE_AN ) {
log_verbose ( " Deactivating logical volume \" %s \" " , lv - > name ) ;
2008-01-30 16:19:47 +03:00
if ( ! deactivate_lv ( cmd , lv ) )
return_0 ;
2004-06-16 21:13:41 +04:00
} else {
if ( lv_is_origin ( lv ) | | ( activate = = CHANGE_AE ) ) {
log_verbose ( " Activating logical volume \" %s \" "
" exclusively " , lv - > name ) ;
2008-01-30 16:19:47 +03:00
if ( ! activate_lv_excl ( cmd , lv ) )
return_0 ;
2004-06-16 21:13:41 +04:00
} else if ( activate = = CHANGE_ALY ) {
log_verbose ( " Activating logical volume \" %s \" locally " ,
lv - > name ) ;
2008-01-30 16:19:47 +03:00
if ( ! activate_lv_local ( cmd , lv ) )
return_0 ;
2004-06-16 21:13:41 +04:00
} else {
log_verbose ( " Activating logical volume \" %s \" " ,
lv - > name ) ;
2008-01-30 16:19:47 +03:00
if ( ! activate_lv ( cmd , lv ) )
return_0 ;
2004-05-05 21:56:20 +04:00
}
2004-06-16 21:13:41 +04:00
if ( ( lv - > status & LOCKED ) & &
( pvname = get_pvmove_pvname_from_lv ( lv ) ) ) {
2003-05-06 16:14:36 +04:00
log_verbose ( " Spawning background pvmove process for %s " ,
2004-05-05 21:56:20 +04:00
pvname ) ;
pvmove_poll ( cmd , pvname , 1 ) ;
2003-05-06 16:14:36 +04:00
}
2008-01-10 21:35:51 +03:00
if ( lv - > status & CONVERTING ) {
log_verbose ( " Spawning background lvconvert process for %s " ,
lv - > name ) ;
2009-06-01 18:43:27 +04:00
lvconvert_poll ( cmd , lv , 1 ) ;
2008-01-10 21:35:51 +03:00
}
2002-01-08 01:36:12 +03:00
}
2001-10-30 17:32:48 +03:00
return 1 ;
}
2004-03-27 00:24:03 +03:00
static int lvchange_refresh ( struct cmd_context * cmd , struct logical_volume * lv )
{
log_verbose ( " Refreshing logical volume \" %s \" (if active) " , lv - > name ) ;
2008-12-19 17:22:48 +03:00
return lv_refresh ( cmd , lv ) ;
2004-03-27 00:24:03 +03:00
}
2006-10-24 21:18:25 +04:00
static int lvchange_resync ( struct cmd_context * cmd ,
2006-10-24 03:03:55 +04:00
struct logical_volume * lv )
{
int active = 0 ;
2008-05-21 18:10:11 +04:00
int monitored ;
2006-10-24 03:03:55 +04:00
struct lvinfo info ;
struct logical_volume * log_lv ;
if ( ! ( lv - > status & MIRRORED ) ) {
log_error ( " Unable to resync %s because it is not mirrored. " ,
lv - > name ) ;
return 1 ;
}
if ( lv - > status & PVMOVE ) {
log_error ( " Unable to resync pvmove volume %s " , lv - > name ) ;
return 0 ;
}
if ( lv - > status & LOCKED ) {
log_error ( " Unable to resync locked volume %s " , lv - > name ) ;
return 0 ;
}
2007-11-12 23:51:54 +03:00
if ( lv_info ( cmd , lv , & info , 1 , 0 ) ) {
2006-10-24 03:03:55 +04:00
if ( info . open_count ) {
log_error ( " Can't resync open logical volume \" %s \" " ,
lv - > name ) ;
2009-05-20 13:55:33 +04:00
return 0 ;
2006-10-24 03:03:55 +04:00
}
2006-10-24 19:30:33 +04:00
if ( info . exists ) {
if ( ! arg_count ( cmd , yes_ARG ) & &
yes_no_prompt ( " Do you really want to deactivate "
2006-10-24 03:03:55 +04:00
" logical volume %s to resync it? [y/n]: " ,
lv - > name ) = = ' n ' ) {
log_print ( " Logical volume \" %s \" not resynced " ,
lv - > name ) ;
2009-05-20 13:55:33 +04:00
return 0 ;
2006-10-24 03:03:55 +04:00
}
2007-06-15 14:11:14 +04:00
if ( sigint_caught ( ) )
2009-05-20 13:55:33 +04:00
return 0 ;
2007-06-15 14:11:14 +04:00
2006-10-24 19:30:33 +04:00
active = 1 ;
}
2006-10-24 03:03:55 +04:00
}
2008-05-21 18:10:11 +04:00
/* Activate exclusively to ensure no nodes still have LV active */
monitored = dmeventd_monitor_mode ( ) ;
init_dmeventd_monitor ( 0 ) ;
2006-10-24 03:03:55 +04:00
if ( ! deactivate_lv ( cmd , lv ) ) {
log_error ( " Unable to deactivate %s for resync " , lv - > name ) ;
return 0 ;
}
2009-05-20 13:55:33 +04:00
if ( vg_is_clustered ( lv - > vg ) & & lv_is_active ( lv ) ) {
log_error ( " Can't get exclusive access to clustered volume %s " ,
lv - > name ) ;
return 0 ;
}
2008-05-21 18:10:11 +04:00
init_dmeventd_monitor ( monitored ) ;
2006-10-24 03:03:55 +04:00
log_lv = first_seg ( lv ) - > log_lv ;
log_very_verbose ( " Starting resync of %s%s%s mirror \" %s \" " ,
( active ) ? " active " : " " ,
2008-04-10 21:09:32 +04:00
vg_is_clustered ( lv - > vg ) ? " clustered " : " " ,
2006-10-24 03:03:55 +04:00
( log_lv ) ? " disk-logged " : " core-logged " ,
lv - > name ) ;
/*
* If this mirror has a core log ( i . e . ! log_lv ) ,
* then simply deactivating / activating will cause
* it to reset the sync status . We only need to
* worry about persistent logs .
*/
if ( ! log_lv & & ! ( lv - > status & MIRROR_NOTSYNCED ) ) {
if ( active & & ! activate_lv ( cmd , lv ) ) {
log_error ( " Failed to reactivate %s to resynchronize "
" mirror " , lv - > name ) ;
return 0 ;
}
return 1 ;
}
lv - > status & = ~ MIRROR_NOTSYNCED ;
if ( log_lv ) {
/* Separate mirror log so we can clear it */
2008-01-26 03:25:04 +03:00
detach_mirror_log ( first_seg ( lv ) ) ;
2006-10-24 03:03:55 +04:00
if ( ! vg_write ( lv - > vg ) ) {
log_error ( " Failed to write intermediate VG metadata. " ) ;
2008-01-26 03:25:04 +03:00
if ( ! attach_mirror_log ( first_seg ( lv ) , log_lv ) )
stack ;
if ( active & & ! activate_lv ( cmd , lv ) )
stack ;
2006-10-24 03:03:55 +04:00
return 0 ;
}
if ( ! vg_commit ( lv - > vg ) ) {
log_error ( " Failed to commit intermediate VG metadata. " ) ;
2008-01-26 03:25:04 +03:00
if ( ! attach_mirror_log ( first_seg ( lv ) , log_lv ) )
stack ;
if ( active & & ! activate_lv ( cmd , lv ) )
stack ;
2006-10-24 03:03:55 +04:00
return 0 ;
}
2009-04-21 18:31:57 +04:00
backup ( lv - > vg ) ;
2006-10-24 03:03:55 +04:00
if ( ! activate_lv ( cmd , log_lv ) ) {
log_error ( " Unable to activate %s for mirror log resync " ,
log_lv - > name ) ;
return 0 ;
}
log_very_verbose ( " Clearing log device %s " , log_lv - > name ) ;
2006-11-04 00:07:15 +03:00
if ( ! set_lv ( cmd , log_lv , log_lv - > size , 0 ) ) {
2006-10-24 03:03:55 +04:00
log_error ( " Unable to reset sync status for %s " , lv - > name ) ;
if ( ! deactivate_lv ( cmd , log_lv ) )
log_error ( " Failed to deactivate log LV after "
" wiping failed " ) ;
return 0 ;
}
if ( ! deactivate_lv ( cmd , log_lv ) ) {
log_error ( " Unable to deactivate log LV %s after wiping "
" for resync " , log_lv - > name ) ;
return 0 ;
}
/* Put mirror log back in place */
2008-01-26 03:25:04 +03:00
if ( ! attach_mirror_log ( first_seg ( lv ) , log_lv ) )
stack ;
2006-10-24 03:03:55 +04:00
}
log_very_verbose ( " Updating logical volume \" %s \" on disk(s) " , lv - > name ) ;
if ( ! vg_write ( lv - > vg ) | | ! vg_commit ( lv - > vg ) ) {
log_error ( " Failed to update metadata on disk. " ) ;
return 0 ;
}
if ( active & & ! activate_lv ( cmd , lv ) ) {
log_error ( " Failed to reactivate %s after resync " , lv - > name ) ;
return 0 ;
}
return 1 ;
}
2004-05-19 02:12:53 +04:00
static int lvchange_alloc ( struct cmd_context * cmd , struct logical_volume * lv )
2001-10-30 17:32:48 +03:00
{
2002-07-11 18:21:49 +04:00
int want_contiguous = 0 ;
2004-05-19 02:12:53 +04:00
alloc_policy_t alloc ;
2001-10-30 17:32:48 +03:00
2004-05-19 02:12:53 +04:00
want_contiguous = strcmp ( arg_str_value ( cmd , contiguous_ARG , " n " ) , " n " ) ;
alloc = want_contiguous ? ALLOC_CONTIGUOUS : ALLOC_INHERIT ;
2006-05-10 01:23:51 +04:00
alloc = arg_uint_value ( cmd , alloc_ARG , alloc ) ;
2001-10-30 17:32:48 +03:00
2004-05-19 02:12:53 +04:00
if ( alloc = = lv - > alloc ) {
2002-01-30 18:04:48 +03:00
log_error ( " Allocation policy of logical volume \" %s \" is "
2004-05-19 02:12:53 +04:00
" already %s " , lv - > name , get_alloc_string ( alloc ) ) ;
2001-10-30 17:32:48 +03:00
return 0 ;
}
2004-05-19 02:12:53 +04:00
lv - > alloc = alloc ;
2001-10-30 17:32:48 +03:00
2004-05-19 02:12:53 +04:00
/* FIXME If contiguous, check existing extents already are */
2001-10-30 17:32:48 +03:00
2004-05-19 02:12:53 +04:00
log_verbose ( " Setting contiguous allocation policy for \" %s \" to %s " ,
lv - > name , get_alloc_string ( alloc ) ) ;
2001-10-30 17:32:48 +03:00
2003-07-05 02:34:56 +04:00
log_very_verbose ( " Updating logical volume \" %s \" on disk(s) " , lv - > name ) ;
2004-05-19 02:12:53 +04:00
2009-04-21 18:31:57 +04:00
/* No need to suspend LV for this change */
if ( ! vg_write ( lv - > vg ) | | ! vg_commit ( lv - > vg ) )
2008-01-30 16:19:47 +03:00
return_0 ;
2003-07-05 02:34:56 +04:00
backup ( lv - > vg ) ;
2001-10-30 17:32:48 +03:00
return 1 ;
}
2002-02-12 00:00:35 +03:00
static int lvchange_readahead ( struct cmd_context * cmd ,
struct logical_volume * lv )
2001-10-30 17:32:48 +03:00
{
2006-05-10 01:23:51 +04:00
unsigned read_ahead = 0 ;
2007-12-05 22:24:32 +03:00
unsigned pagesize = ( unsigned ) lvm_getpagesize ( ) > > SECTOR_SHIFT ;
2009-04-21 18:31:57 +04:00
int r = 0 ;
2001-10-30 17:32:48 +03:00
2002-12-20 02:25:55 +03:00
read_ahead = arg_uint_value ( cmd , readahead_ARG , 0 ) ;
2001-10-30 17:32:48 +03:00
2007-11-09 19:51:54 +03:00
if ( read_ahead ! = DM_READ_AHEAD_AUTO & &
( lv - > vg - > fid - > fmt - > features & FMT_RESTRICTED_READAHEAD ) & &
( read_ahead < 2 | | read_ahead > 120 ) ) {
log_error ( " Metadata only supports readahead values between 2 and 120. " ) ;
2001-10-30 17:32:48 +03:00
return 0 ;
}
2007-12-05 22:24:32 +03:00
if ( read_ahead ! = DM_READ_AHEAD_AUTO & &
read_ahead ! = DM_READ_AHEAD_NONE & & read_ahead % pagesize ) {
2009-06-07 02:00:20 +04:00
if ( read_ahead < pagesize )
read_ahead = pagesize ;
else
read_ahead = ( read_ahead / pagesize ) * pagesize ;
log_warn ( " WARNING: Overriding readahead to %u sectors, a multiple "
" of %uK page size. " , read_ahead , pagesize > > 1 ) ;
2007-12-05 22:24:32 +03:00
}
2001-10-30 17:32:48 +03:00
if ( lv - > read_ahead = = read_ahead ) {
2008-06-18 15:32:14 +04:00
if ( read_ahead = = DM_READ_AHEAD_AUTO )
log_error ( " Read ahead is already auto for \" %s \" " , lv - > name ) ;
else
log_error ( " Read ahead is already %u for \" %s \" " ,
read_ahead , lv - > name ) ;
2001-10-30 17:32:48 +03:00
return 0 ;
}
lv - > read_ahead = read_ahead ;
2002-02-21 00:30:27 +03:00
2002-02-12 00:00:35 +03:00
log_verbose ( " Setting read ahead to %u for \" %s \" " , read_ahead ,
lv - > name ) ;
2001-10-30 17:32:48 +03:00
2003-07-05 02:34:56 +04:00
log_very_verbose ( " Updating logical volume \" %s \" on disk(s) " , lv - > name ) ;
2008-01-30 16:19:47 +03:00
if ( ! vg_write ( lv - > vg ) )
return_0 ;
2003-07-05 02:34:56 +04:00
2005-08-15 16:00:04 +04:00
if ( ! suspend_lv ( cmd , lv ) ) {
2002-02-21 00:30:27 +03:00
log_error ( " Failed to lock %s " , lv - > name ) ;
2003-07-05 02:34:56 +04:00
vg_revert ( lv - > vg ) ;
2009-04-21 18:31:57 +04:00
goto out ;
2002-02-21 00:30:27 +03:00
}
2001-10-31 20:59:52 +03:00
2003-07-05 02:34:56 +04:00
if ( ! vg_commit ( lv - > vg ) ) {
2005-08-15 16:00:04 +04:00
resume_lv ( cmd , lv ) ;
2009-04-21 18:31:57 +04:00
goto_out ;
2002-02-21 00:30:27 +03:00
}
2001-10-31 20:59:52 +03:00
2003-07-05 02:34:56 +04:00
log_very_verbose ( " Updating permissions for \" %s \" in kernel " , lv - > name ) ;
2005-08-15 16:00:04 +04:00
if ( ! resume_lv ( cmd , lv ) ) {
2002-04-24 22:20:51 +04:00
log_error ( " Problem reactivating %s " , lv - > name ) ;
2009-04-21 18:31:57 +04:00
goto out ;
2002-04-24 22:20:51 +04:00
}
2002-02-21 00:30:27 +03:00
2009-04-21 18:31:57 +04:00
r = 1 ;
out :
backup ( lv - > vg ) ;
return r ;
2001-10-30 17:32:48 +03:00
}
2002-02-01 20:54:39 +03:00
2002-02-12 00:00:35 +03:00
static int lvchange_persistent ( struct cmd_context * cmd ,
struct logical_volume * lv )
2002-02-01 20:54:39 +03:00
{
2003-07-11 21:10:19 +04:00
struct lvinfo info ;
2004-05-05 16:03:07 +04:00
int active = 0 ;
2002-02-25 15:56:16 +03:00
2002-02-12 00:00:35 +03:00
if ( ! strcmp ( arg_str_value ( cmd , persistent_ARG , " n " ) , " n " ) ) {
2002-02-01 20:54:39 +03:00
if ( ! ( lv - > status & FIXED_MINOR ) ) {
log_error ( " Minor number is already not persistent "
" for \" %s \" " , lv - > name ) ;
return 0 ;
}
lv - > status & = ~ FIXED_MINOR ;
lv - > minor = - 1 ;
2003-04-02 23:14:43 +04:00
lv - > major = - 1 ;
log_verbose ( " Disabling persistent device number for \" %s \" " ,
lv - > name ) ;
2002-02-01 20:54:39 +03:00
} else {
2003-04-02 23:14:43 +04:00
if ( ! arg_count ( cmd , minor_ARG ) & & lv - > minor < 0 ) {
2002-02-01 20:54:39 +03:00
log_error ( " Minor number must be specified with -My " ) ;
return 0 ;
}
2003-04-02 23:14:43 +04:00
if ( ! arg_count ( cmd , major_ARG ) & & lv - > major < 0 ) {
log_error ( " Major number must be specified with -My " ) ;
return 0 ;
}
2007-11-12 23:51:54 +03:00
if ( lv_info ( cmd , lv , & info , 0 , 0 ) & & info . exists )
2004-05-05 16:03:07 +04:00
active = 1 ;
2006-10-14 01:33:31 +04:00
if ( active & & ! arg_count ( cmd , force_ARG ) & &
yes_no_prompt ( " Logical volume %s will be "
" deactivated temporarily. "
" Continue? [y/n]: " , lv - > name ) = = ' n ' ) {
log_print ( " %s device number not changed. " ,
lv - > name ) ;
return 0 ;
2003-07-11 21:10:19 +04:00
}
2007-06-15 14:11:14 +04:00
if ( sigint_caught ( ) )
return 0 ;
2004-05-05 22:27:56 +04:00
log_verbose ( " Ensuring %s is inactive. " , lv - > name ) ;
2005-08-15 16:00:04 +04:00
if ( ! deactivate_lv ( cmd , lv ) ) {
2002-03-11 22:02:28 +03:00
log_error ( " %s: deactivation failed " , lv - > name ) ;
return 0 ;
}
2002-02-01 20:54:39 +03:00
lv - > status | = FIXED_MINOR ;
2003-04-02 23:14:43 +04:00
lv - > minor = arg_int_value ( cmd , minor_ARG , lv - > minor ) ;
lv - > major = arg_int_value ( cmd , major_ARG , lv - > major ) ;
log_verbose ( " Setting persistent device number to (%d, %d) "
" for \" %s \" " , lv - > major , lv - > minor , lv - > name ) ;
2006-07-10 23:39:14 +04:00
2002-02-01 20:54:39 +03:00
}
2003-07-05 02:34:56 +04:00
log_very_verbose ( " Updating logical volume \" %s \" on disk(s) " , lv - > name ) ;
2009-04-21 18:31:57 +04:00
if ( ! vg_write ( lv - > vg ) | | ! vg_commit ( lv - > vg ) )
2008-01-30 16:19:47 +03:00
return_0 ;
2003-07-05 02:34:56 +04:00
backup ( lv - > vg ) ;
2006-07-10 23:39:14 +04:00
if ( active ) {
log_verbose ( " Re-activating logical volume \" %s \" " , lv - > name ) ;
if ( ! activate_lv ( cmd , lv ) ) {
log_error ( " %s: reactivation failed " , lv - > name ) ;
return 0 ;
}
2002-04-24 22:20:51 +04:00
}
2002-02-21 00:30:27 +03:00
2002-02-01 20:54:39 +03:00
return 1 ;
}
2002-11-18 17:04:08 +03:00
2004-03-08 20:19:15 +03:00
static int lvchange_tag ( struct cmd_context * cmd , struct logical_volume * lv ,
int arg )
{
const char * tag ;
if ( ! ( tag = arg_str_value ( cmd , arg , NULL ) ) ) {
log_error ( " Failed to get tag " ) ;
return 0 ;
}
if ( ! ( lv - > vg - > fid - > fmt - > features & FMT_TAGS ) ) {
log_error ( " Logical volume %s/%s does not support tags " ,
lv - > vg - > name , lv - > name ) ;
return 0 ;
}
if ( ( arg = = addtag_ARG ) ) {
if ( ! str_list_add ( cmd - > mem , & lv - > tags , tag ) ) {
log_error ( " Failed to add tag %s to %s/%s " ,
tag , lv - > vg - > name , lv - > name ) ;
return 0 ;
}
} else {
if ( ! str_list_del ( & lv - > tags , tag ) ) {
log_error ( " Failed to remove tag %s from %s/%s " ,
tag , lv - > vg - > name , lv - > name ) ;
return 0 ;
}
}
log_very_verbose ( " Updating logical volume \" %s \" on disk(s) " , lv - > name ) ;
/* No need to suspend LV for this change */
2009-04-21 18:31:57 +04:00
if ( ! vg_write ( lv - > vg ) | | ! vg_commit ( lv - > vg ) )
2008-01-30 16:19:47 +03:00
return_0 ;
2004-03-08 20:19:15 +03:00
2009-04-21 18:31:57 +04:00
backup ( lv - > vg ) ;
2004-03-08 20:19:15 +03:00
return 1 ;
}
2005-03-22 01:55:12 +03:00
2002-11-18 17:04:08 +03:00
static int lvchange_single ( struct cmd_context * cmd , struct logical_volume * lv ,
2006-05-10 01:23:51 +04:00
void * handle __attribute ( ( unused ) ) )
2002-11-18 17:04:08 +03:00
{
2008-07-31 17:03:01 +04:00
int doit = 0 , docmds = 0 ;
2002-11-18 17:04:08 +03:00
int archived = 0 ;
2009-05-27 22:19:21 +04:00
struct logical_volume * origin ;
2002-11-18 17:04:08 +03:00
if ( ! ( lv - > vg - > status & LVM_WRITE ) & &
( arg_count ( cmd , contiguous_ARG ) | | arg_count ( cmd , permission_ARG ) | |
2004-05-19 02:12:53 +04:00
arg_count ( cmd , readahead_ARG ) | | arg_count ( cmd , persistent_ARG ) | |
arg_count ( cmd , alloc_ARG ) ) ) {
2002-11-18 17:04:08 +03:00
log_error ( " Only -a permitted with read-only volume "
" group \" %s \" " , lv - > vg - > name ) ;
return EINVALID_CMD_LINE ;
}
if ( lv_is_origin ( lv ) & &
( arg_count ( cmd , contiguous_ARG ) | | arg_count ( cmd , permission_ARG ) | |
2004-05-19 02:12:53 +04:00
arg_count ( cmd , readahead_ARG ) | | arg_count ( cmd , persistent_ARG ) | |
arg_count ( cmd , alloc_ARG ) ) ) {
2002-11-18 17:04:08 +03:00
log_error ( " Can't change logical volume \" %s \" under snapshot " ,
lv - > name ) ;
return ECMD_FAILED ;
}
2009-04-25 05:17:59 +04:00
if ( lv_is_cow ( lv ) & & ! lv_is_virtual_origin ( origin_from_cow ( lv ) ) & &
arg_count ( cmd , available_ARG ) ) {
2002-11-18 17:04:08 +03:00
log_error ( " Can't change snapshot logical volume \" %s \" " ,
lv - > name ) ;
return ECMD_FAILED ;
}
2003-05-06 16:14:36 +04:00
if ( lv - > status & PVMOVE ) {
log_error ( " Unable to change pvmove LV %s " , lv - > name ) ;
if ( arg_count ( cmd , available_ARG ) )
log_error ( " Use 'pvmove --abort' to abandon a pvmove " ) ;
return ECMD_FAILED ;
}
2005-06-01 20:51:55 +04:00
if ( lv - > status & MIRROR_LOG ) {
log_error ( " Unable to change mirror log LV %s directly " , lv - > name ) ;
return ECMD_FAILED ;
}
2005-06-03 18:49:51 +04:00
if ( lv - > status & MIRROR_IMAGE ) {
log_error ( " Unable to change mirror image LV %s directly " ,
lv - > name ) ;
return ECMD_FAILED ;
}
2009-05-27 22:19:21 +04:00
/* If LV is sparse, activate origin instead */
if ( arg_count ( cmd , available_ARG ) & & lv_is_cow ( lv ) & &
lv_is_virtual_origin ( origin = origin_from_cow ( lv ) ) )
lv = origin ;
if ( ! ( lv_is_visible ( lv ) ) & & ! lv_is_virtual_origin ( lv ) ) {
2005-06-03 18:49:51 +04:00
log_error ( " Unable to change internal LV %s directly " ,
lv - > name ) ;
return ECMD_FAILED ;
}
2007-01-25 02:43:27 +03:00
init_dmeventd_monitor ( arg_int_value ( cmd , monitor_ARG ,
2008-12-18 08:27:17 +03:00
( is_static ( ) | | arg_count ( cmd , ignoremonitoring_ARG ) ) ?
2007-01-25 02:43:27 +03:00
DMEVENTD_MONITOR_IGNORE : DEFAULT_DMEVENTD_MONITOR ) ) ;
2006-05-12 23:16:48 +04:00
2002-11-18 17:04:08 +03:00
/* access permission change */
if ( arg_count ( cmd , permission_ARG ) ) {
if ( ! archive ( lv - > vg ) )
return ECMD_FAILED ;
archived = 1 ;
doit + = lvchange_permission ( cmd , lv ) ;
2008-07-31 17:03:01 +04:00
docmds + + ;
2002-11-18 17:04:08 +03:00
}
/* allocation policy change */
2004-05-19 02:12:53 +04:00
if ( arg_count ( cmd , contiguous_ARG ) | | arg_count ( cmd , alloc_ARG ) ) {
2002-11-18 17:04:08 +03:00
if ( ! archived & & ! archive ( lv - > vg ) )
return ECMD_FAILED ;
archived = 1 ;
2004-05-19 02:12:53 +04:00
doit + = lvchange_alloc ( cmd , lv ) ;
2008-07-31 17:03:01 +04:00
docmds + + ;
2002-11-18 17:04:08 +03:00
}
/* read ahead sector change */
if ( arg_count ( cmd , readahead_ARG ) ) {
if ( ! archived & & ! archive ( lv - > vg ) )
return ECMD_FAILED ;
archived = 1 ;
doit + = lvchange_readahead ( cmd , lv ) ;
2008-07-31 17:03:01 +04:00
docmds + + ;
2002-11-18 17:04:08 +03:00
}
/* read ahead sector change */
if ( arg_count ( cmd , persistent_ARG ) ) {
if ( ! archived & & ! archive ( lv - > vg ) )
return ECMD_FAILED ;
archived = 1 ;
doit + = lvchange_persistent ( cmd , lv ) ;
2008-07-31 17:03:01 +04:00
docmds + + ;
2007-06-15 14:11:14 +04:00
if ( sigint_caught ( ) )
return ECMD_FAILED ;
2002-11-18 17:04:08 +03:00
}
2004-03-08 20:19:15 +03:00
/* add tag */
if ( arg_count ( cmd , addtag_ARG ) ) {
if ( ! archived & & ! archive ( lv - > vg ) )
return ECMD_FAILED ;
archived = 1 ;
doit + = lvchange_tag ( cmd , lv , addtag_ARG ) ;
2008-07-31 17:03:01 +04:00
docmds + + ;
2004-03-08 20:19:15 +03:00
}
/* del tag */
if ( arg_count ( cmd , deltag_ARG ) ) {
if ( ! archived & & ! archive ( lv - > vg ) )
return ECMD_FAILED ;
archived = 1 ;
doit + = lvchange_tag ( cmd , lv , deltag_ARG ) ;
2008-07-31 17:03:01 +04:00
docmds + + ;
2004-03-08 20:19:15 +03:00
}
2002-11-18 17:04:08 +03:00
if ( doit )
log_print ( " Logical volume \" %s \" changed " , lv - > name ) ;
2006-10-24 21:18:25 +04:00
if ( arg_count ( cmd , resync_ARG ) )
if ( ! lvchange_resync ( cmd , lv ) )
2006-10-24 03:03:55 +04:00
return ECMD_FAILED ;
2002-11-18 17:04:08 +03:00
/* availability change */
2006-05-12 23:16:48 +04:00
if ( arg_count ( cmd , available_ARG ) ) {
2002-11-18 17:04:08 +03:00
if ( ! lvchange_availability ( cmd , lv ) )
return ECMD_FAILED ;
2006-05-12 23:16:48 +04:00
}
2002-11-18 17:04:08 +03:00
2004-03-27 00:24:03 +03:00
if ( arg_count ( cmd , refresh_ARG ) )
if ( ! lvchange_refresh ( cmd , lv ) )
return ECMD_FAILED ;
2006-05-12 23:16:48 +04:00
if ( ! arg_count ( cmd , available_ARG ) & &
! arg_count ( cmd , refresh_ARG ) & &
arg_count ( cmd , monitor_ARG ) ) {
2007-01-20 01:21:45 +03:00
if ( ! lvchange_monitoring ( cmd , lv ) )
2006-05-12 23:16:48 +04:00
return ECMD_FAILED ;
}
2008-07-31 17:03:01 +04:00
if ( doit ! = docmds )
return ECMD_FAILED ;
2003-10-22 02:06:07 +04:00
return ECMD_PROCESSED ;
2002-11-18 17:04:08 +03:00
}
int lvchange ( struct cmd_context * cmd , int argc , char * * argv )
{
if ( ! arg_count ( cmd , available_ARG ) & & ! arg_count ( cmd , contiguous_ARG )
& & ! arg_count ( cmd , permission_ARG ) & & ! arg_count ( cmd , readahead_ARG )
2003-04-02 23:14:43 +04:00
& & ! arg_count ( cmd , minor_ARG ) & & ! arg_count ( cmd , major_ARG )
2004-03-08 20:19:15 +03:00
& & ! arg_count ( cmd , persistent_ARG ) & & ! arg_count ( cmd , addtag_ARG )
2004-05-19 02:12:53 +04:00
& & ! arg_count ( cmd , deltag_ARG ) & & ! arg_count ( cmd , refresh_ARG )
2006-10-24 03:03:55 +04:00
& & ! arg_count ( cmd , alloc_ARG ) & & ! arg_count ( cmd , monitor_ARG )
2006-10-24 21:18:25 +04:00
& & ! arg_count ( cmd , resync_ARG ) ) {
2006-05-12 23:16:48 +04:00
log_error ( " Need 1 or more of -a, -C, -j, -m, -M, -p, -r, "
2006-10-24 21:18:25 +04:00
" --resync, --refresh, --alloc, --addtag, --deltag "
2006-05-12 23:16:48 +04:00
" or --monitor " ) ;
2002-11-18 17:04:08 +03:00
return EINVALID_CMD_LINE ;
}
2009-07-15 09:47:55 +04:00
int avail_only =
! ( arg_count ( cmd , contiguous_ARG ) | | arg_count ( cmd , permission_ARG ) | |
2004-03-08 20:19:15 +03:00
arg_count ( cmd , readahead_ARG ) | | arg_count ( cmd , persistent_ARG ) | |
2004-03-27 00:24:03 +03:00
arg_count ( cmd , addtag_ARG ) | | arg_count ( cmd , deltag_ARG ) | |
2009-07-15 09:47:55 +04:00
arg_count ( cmd , refresh_ARG ) | | arg_count ( cmd , alloc_ARG ) | |
arg_count ( cmd , resync_ARG ) ) ;
if ( arg_count ( cmd , ignorelockingfailure_ARG ) & & ! avail_only ) {
2002-11-18 17:04:08 +03:00
log_error ( " Only -a permitted with --ignorelockingfailure " ) ;
return EINVALID_CMD_LINE ;
}
2009-07-15 09:47:55 +04:00
if ( avail_only )
cmd - > handles_missing_pvs = 1 ;
2002-11-18 17:04:08 +03:00
if ( ! argc ) {
log_error ( " Please give logical volume path(s) " ) ;
return EINVALID_CMD_LINE ;
}
2003-04-02 23:14:43 +04:00
if ( ( arg_count ( cmd , minor_ARG ) | | arg_count ( cmd , major_ARG ) ) & &
! arg_count ( cmd , persistent_ARG ) ) {
log_error ( " --major and --minor require -My " ) ;
return EINVALID_CMD_LINE ;
}
2002-11-18 17:04:08 +03:00
if ( arg_count ( cmd , minor_ARG ) & & argc ! = 1 ) {
log_error ( " Only give one logical volume when specifying minor " ) ;
return EINVALID_CMD_LINE ;
}
2004-05-19 02:12:53 +04:00
if ( arg_count ( cmd , contiguous_ARG ) & & arg_count ( cmd , alloc_ARG ) ) {
log_error ( " Only one of --alloc and --contiguous permitted " ) ;
return EINVALID_CMD_LINE ;
}
2009-07-15 09:48:36 +04:00
return process_each_lv ( cmd , argc , argv ,
avail_only ? 0 : READ_FOR_UPDATE , NULL ,
2002-11-18 17:04:08 +03:00
& lvchange_single ) ;
}