2001-10-30 17:32:48 +03:00
/*
2004-03-30 23:35:44 +04:00
* Copyright ( C ) 2001 - 2004 Sistina Software , Inc . All rights reserved .
* Copyright ( C ) 2004 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
* of the GNU General Public License v .2 .
2001-10-30 17:32:48 +03:00
*
* You should have received a copy of the GNU 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 ;
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 ;
}
2007-01-10 22:56:39 +03:00
if ( ( lv - > status & MIRRORED ) & & ( lv - > vg - > status & CLUSTERED ) & &
lv_info ( cmd , lv , & info , 0 ) & & info . exists ) {
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 ) ;
if ( ! vg_write ( lv - > vg ) ) {
stack ;
return 0 ;
}
backup ( lv - > vg ) ;
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 ) ;
2002-02-21 00:30:27 +03:00
return 0 ;
}
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 ) ;
2001-10-31 20:59:52 +03:00
return 0 ;
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 ) ;
return 0 ;
}
2001-10-31 20:59:52 +03:00
2001-10-30 17:32:48 +03:00
return 1 ;
}
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 ;
if ( ! lv_info ( cmd , lv , & info , 0 ) | | ! info . exists ) {
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 ) ;
2005-08-15 16:00:04 +04:00
if ( ! deactivate_lv_local ( cmd , lv ) ) {
2004-06-16 21:13:41 +04:00
stack ;
return 0 ;
}
} else if ( activate = = CHANGE_AN ) {
log_verbose ( " Deactivating logical volume \" %s \" " , lv - > name ) ;
2005-08-15 16:00:04 +04:00
if ( ! deactivate_lv ( cmd , lv ) ) {
2004-06-16 21:13:41 +04:00
stack ;
return 0 ;
}
} else {
2005-03-22 01:55:12 +03:00
if ( lockingfailed ( ) & & ( lv - > vg - > status & CLUSTERED ) ) {
2006-10-24 03:03:55 +04:00
log_verbose ( " Locking failed: ignoring clustered "
2005-03-22 01:55:12 +03:00
" logical volume %s " , lv - > name ) ;
2006-10-24 03:03:55 +04:00
return 0 ;
}
2005-03-22 01:55:12 +03:00
2004-06-16 21:13:41 +04:00
if ( lv_is_origin ( lv ) | | ( activate = = CHANGE_AE ) ) {
log_verbose ( " Activating logical volume \" %s \" "
" exclusively " , lv - > name ) ;
2005-08-15 16:00:04 +04:00
if ( ! activate_lv_excl ( cmd , lv ) ) {
2004-05-05 21:56:20 +04:00
stack ;
return 0 ;
}
2004-06-16 21:13:41 +04:00
} else if ( activate = = CHANGE_ALY ) {
log_verbose ( " Activating logical volume \" %s \" locally " ,
lv - > name ) ;
2005-08-15 16:00:04 +04:00
if ( ! activate_lv_local ( cmd , lv ) ) {
2004-06-16 21:13:41 +04:00
stack ;
return 0 ;
}
} else {
log_verbose ( " Activating logical volume \" %s \" " ,
lv - > name ) ;
2005-08-15 16:00:04 +04:00
if ( ! activate_lv ( cmd , lv ) ) {
2004-06-16 21:13:41 +04:00
stack ;
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
}
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 ) ;
2005-08-15 16:00:04 +04:00
if ( ! suspend_lv ( cmd , lv ) | | ! resume_lv ( cmd , lv ) )
2004-03-27 00:24:03 +03:00
return 0 ;
return 1 ;
}
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 ;
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 ;
}
if ( lv_info ( cmd , lv , & info , 1 ) ) {
if ( info . open_count ) {
log_error ( " Can't resync open logical volume \" %s \" " ,
lv - > name ) ;
return ECMD_FAILED ;
}
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 ) ;
return ECMD_FAILED ;
}
2006-10-24 19:30:33 +04:00
active = 1 ;
}
2006-10-24 03:03:55 +04:00
}
if ( ( lv - > vg - > status & CLUSTERED ) & & ! activate_lv_excl ( cmd , lv ) ) {
log_error ( " Can't get exclusive access to clustered volume %s " ,
lv - > name ) ;
return ECMD_FAILED ;
}
if ( ! deactivate_lv ( cmd , lv ) ) {
log_error ( " Unable to deactivate %s for resync " , lv - > name ) ;
return 0 ;
}
log_lv = first_seg ( lv ) - > log_lv ;
log_very_verbose ( " Starting resync of %s%s%s mirror \" %s \" " ,
( active ) ? " active " : " " ,
( lv - > vg - > status & CLUSTERED ) ? " clustered " : " " ,
( 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 */
first_seg ( lv ) - > log_lv = NULL ;
log_lv - > status & = ~ MIRROR_LOG ;
log_lv - > status | = VISIBLE_LV ;
if ( ! vg_write ( lv - > vg ) ) {
log_error ( " Failed to write intermediate VG metadata. " ) ;
if ( active ) {
first_seg ( lv ) - > log_lv = log_lv ;
log_lv - > status | = MIRROR_LOG ;
log_lv - > status & = ~ VISIBLE_LV ;
if ( ! activate_lv ( cmd , lv ) )
stack ;
}
return 0 ;
}
backup ( lv - > vg ) ;
if ( ! vg_commit ( lv - > vg ) ) {
log_error ( " Failed to commit intermediate VG metadata. " ) ;
if ( active ) {
first_seg ( lv ) - > log_lv = log_lv ;
log_lv - > status | = MIRROR_LOG ;
log_lv - > status & = ~ VISIBLE_LV ;
if ( ! activate_lv ( cmd , lv ) )
stack ;
}
return 0 ;
}
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 */
first_seg ( lv ) - > log_lv = log_lv ;
log_lv - > status | = MIRROR_LOG ;
log_lv - > status & = ~ VISIBLE_LV ;
}
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
2003-07-05 02:34:56 +04:00
if ( ! vg_write ( lv - > vg ) ) {
stack ;
return 0 ;
}
backup ( lv - > vg ) ;
2004-03-08 20:19:15 +03:00
/* No need to suspend LV for this change */
2003-07-05 02:34:56 +04:00
if ( ! vg_commit ( lv - > vg ) ) {
2004-03-08 20:19:15 +03:00
stack ;
2002-04-24 22:20:51 +04:00
return 0 ;
}
2002-02-21 00:30:27 +03:00
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 ;
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
2002-07-11 18:21:49 +04:00
/******* FIXME Ranges?
2001-10-30 17:32:48 +03:00
if ( read_ahead < LVM_MIN_READ_AHEAD | | read_ahead > LVM_MAX_READ_AHEAD ) {
log_error ( " read ahead sector argument is invalid " ) ;
return 0 ;
}
* * * * * * * */
if ( lv - > read_ahead = = read_ahead ) {
2002-01-30 18:04:48 +03:00
log_error ( " Read ahead is already %u for \" %s \" " ,
2001-10-30 17:32:48 +03:00
read_ahead , lv - > name ) ;
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 ) ;
if ( ! vg_write ( lv - > vg ) ) {
stack ;
return 0 ;
}
backup ( lv - > vg ) ;
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 ) ;
2002-02-21 00:30:27 +03:00
return 0 ;
}
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 ) ;
2001-10-31 20:59:52 +03:00
return 0 ;
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 ) ;
return 0 ;
}
2002-02-21 00:30:27 +03:00
2001-10-30 17:32:48 +03:00
return 1 ;
}
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 ;
}
2006-10-14 01:33:31 +04:00
if ( lv_info ( cmd , lv , & info , 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
}
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 ) ;
if ( ! vg_write ( lv - > vg ) ) {
stack ;
return 0 ;
}
backup ( lv - > vg ) ;
if ( ! vg_commit ( lv - > vg ) ) {
2006-07-10 23:39:14 +04:00
stack ;
2002-02-01 20:54:39 +03:00
return 0 ;
2002-02-21 00:30:27 +03:00
}
2002-02-01 20:54:39 +03:00
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 ) ;
if ( ! vg_write ( lv - > vg ) ) {
stack ;
return 0 ;
}
backup ( lv - > vg ) ;
/* No need to suspend LV for this change */
if ( ! vg_commit ( lv - > vg ) ) {
stack ;
return 0 ;
}
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
{
int doit = 0 ;
int archived = 0 ;
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 ;
}
if ( lv_is_cow ( lv ) ) {
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 ;
}
if ( ! ( lv - > status & VISIBLE_LV ) ) {
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 ,
cmd - > is_static ?
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 ) ;
}
/* 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 ) ;
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 ) ;
}
/* 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 ) ;
}
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 ) ;
}
/* 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 ) ;
}
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 ;
}
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 ;
}
if ( arg_count ( cmd , ignorelockingfailure_ARG ) & &
( 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 ) | |
2004-05-19 02:12:53 +04:00
arg_count ( cmd , refresh_ARG ) | | arg_count ( cmd , alloc_ARG ) ) ) {
2002-11-18 17:04:08 +03:00
log_error ( " Only -a permitted with --ignorelockingfailure " ) ;
return EINVALID_CMD_LINE ;
}
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 ;
}
2002-11-18 17:04:08 +03:00
return process_each_lv ( cmd , argc , argv , LCK_VG_WRITE , NULL ,
& lvchange_single ) ;
}