2001-10-30 17:32:48 +03:00
/*
* Copyright ( C ) 2001 Sistina Software
*
* LVM is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 , or ( at your option )
* any later version .
*
* LVM is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with LVM ; see the file COPYING . If not , write to
* the Free Software Foundation , 59 Temple Place - Suite 330 ,
* Boston , MA 02111 - 1307 , USA .
*
*/
# include "tools.h"
2002-02-11 23:50:53 +03:00
static int lvchange_single ( struct cmd_context * cmd , struct logical_volume * lv ) ;
2002-02-12 00:00:35 +03:00
static int lvchange_permission ( struct cmd_context * cmd ,
struct logical_volume * lv ) ;
static int lvchange_availability ( struct cmd_context * cmd ,
struct logical_volume * lv ) ;
static int lvchange_contiguous ( struct cmd_context * cmd ,
struct logical_volume * lv ) ;
static int lvchange_readahead ( struct cmd_context * cmd ,
struct logical_volume * lv ) ;
static int lvchange_persistent ( struct cmd_context * cmd ,
struct logical_volume * lv ) ;
2002-02-11 23:50:53 +03:00
int lvchange ( struct cmd_context * cmd , int argc , char * * argv )
2001-10-30 17:32:48 +03:00
{
2002-02-12 00:00:35 +03:00
if ( ! arg_count ( cmd , available_ARG ) & & ! arg_count ( cmd , contiguous_ARG )
& & ! arg_count ( cmd , permission_ARG ) & & ! arg_count ( cmd , readahead_ARG )
& & ! arg_count ( cmd , minor_ARG ) & & ! arg_count ( cmd , persistent_ARG ) ) {
2002-02-01 20:54:39 +03:00
log_error ( " One or more of -a, -C, -m, -M, -p or -r required " ) ;
2001-10-30 17:32:48 +03:00
return EINVALID_CMD_LINE ;
}
if ( ! argc ) {
log_error ( " Please give logical volume path(s) " ) ;
return EINVALID_CMD_LINE ;
}
2002-02-12 00:00:35 +03:00
if ( arg_count ( cmd , minor_ARG ) & & argc ! = 1 ) {
2002-02-01 20:54:39 +03:00
log_error ( " Only give one logical volume when specifying minor " ) ;
return EINVALID_CMD_LINE ;
}
2002-04-15 20:27:39 +04:00
return process_each_lv ( cmd , argc , argv , LCK_VG_WRITE , & lvchange_single ) ;
2001-10-30 17:32:48 +03:00
}
2002-02-11 23:50:53 +03:00
static int lvchange_single ( struct cmd_context * cmd , struct logical_volume * lv )
2001-10-30 17:32:48 +03:00
{
int doit = 0 ;
2002-01-11 02:21:07 +03:00
int archived = 0 ;
2001-10-30 17:32:48 +03:00
2002-02-12 00:00:35 +03:00
if ( ! ( lv - > vg - > status & LVM_WRITE ) & &
( arg_count ( cmd , contiguous_ARG ) | | arg_count ( cmd , permission_ARG ) | |
arg_count ( cmd , readahead_ARG ) | | arg_count ( cmd , persistent_ARG ) ) ) {
2002-02-01 20:54:39 +03:00
log_error ( " Only -a permitted with read-only volume "
" group \" %s \" " , lv - > vg - > name ) ;
2002-01-29 20:23:33 +03:00
return EINVALID_CMD_LINE ;
}
2002-03-18 16:09:27 +03:00
if ( lv_is_origin ( lv ) & &
( arg_count ( cmd , contiguous_ARG ) | | arg_count ( cmd , permission_ARG ) | |
arg_count ( cmd , readahead_ARG ) | | arg_count ( cmd , persistent_ARG ) ) ) {
2002-01-30 18:04:48 +03:00
log_error ( " Can't change logical volume \" %s \" under snapshot " ,
2001-11-14 21:38:07 +03:00
lv - > name ) ;
2001-10-30 17:32:48 +03:00
return ECMD_FAILED ;
}
2002-02-20 22:04:55 +03:00
if ( lv_is_cow ( lv ) ) {
2002-02-12 00:00:35 +03:00
log_error ( " Can't change snapshot logical volume \" %s \" " ,
2002-02-01 20:54:39 +03:00
lv - > name ) ;
2001-10-30 17:32:48 +03:00
return ECMD_FAILED ;
}
/* access permission change */
2002-02-12 00:00:35 +03:00
if ( arg_count ( cmd , permission_ARG ) ) {
2002-01-11 02:21:07 +03:00
if ( ! archive ( lv - > vg ) )
return ECMD_FAILED ;
archived = 1 ;
2002-02-11 23:50:53 +03:00
doit + = lvchange_permission ( cmd , lv ) ;
2002-01-11 02:21:07 +03:00
}
2001-10-30 17:32:48 +03:00
/* allocation policy change */
2002-02-12 00:00:35 +03:00
if ( arg_count ( cmd , contiguous_ARG ) ) {
2002-01-11 02:21:07 +03:00
if ( ! archived & & ! archive ( lv - > vg ) )
return ECMD_FAILED ;
archived = 1 ;
2002-02-11 23:50:53 +03:00
doit + = lvchange_contiguous ( cmd , lv ) ;
2002-01-11 02:21:07 +03:00
}
2001-10-30 17:32:48 +03:00
/* read ahead sector change */
2002-02-12 00:00:35 +03:00
if ( arg_count ( cmd , readahead_ARG ) ) {
2002-01-11 02:21:07 +03:00
if ( ! archived & & ! archive ( lv - > vg ) )
return ECMD_FAILED ;
archived = 1 ;
2002-02-11 23:50:53 +03:00
doit + = lvchange_readahead ( cmd , lv ) ;
2001-10-30 17:32:48 +03:00
}
2002-02-01 20:54:39 +03:00
/* read ahead sector change */
2002-02-12 00:00:35 +03:00
if ( arg_count ( cmd , persistent_ARG ) ) {
2002-02-01 20:54:39 +03:00
if ( ! archived & & ! archive ( lv - > vg ) )
return ECMD_FAILED ;
archived = 1 ;
2002-02-11 23:50:53 +03:00
doit + = lvchange_persistent ( cmd , lv ) ;
2002-02-01 20:54:39 +03:00
}
2002-01-11 02:21:07 +03:00
if ( doit )
2002-01-30 18:04:48 +03:00
log_print ( " Logical volume \" %s \" changed " , lv - > name ) ;
2002-01-11 02:21:07 +03:00
/* availability change */
2002-02-12 00:00:35 +03:00
if ( arg_count ( cmd , available_ARG ) )
2002-02-11 23:50:53 +03:00
if ( ! lvchange_availability ( cmd , lv ) )
2002-01-11 02:21:07 +03:00
return ECMD_FAILED ;
2001-10-30 17:32:48 +03:00
return 0 ;
}
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
{
int lv_access ;
2002-02-12 00:00:35 +03:00
lv_access = arg_int_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 ;
}
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
}
2002-03-05 23:03:09 +03:00
if ( ! lock_vol ( cmd , lv - > lvid . s , LCK_LV_SUSPEND | LCK_HOLD ) ) {
2002-02-21 00:30:27 +03:00
log_error ( " Failed to lock %s " , lv - > name ) ;
return 0 ;
}
2002-01-30 18:04:48 +03:00
log_very_verbose ( " Updating logical volume \" %s \" on disk(s) " , lv - > name ) ;
2002-04-24 22:20:51 +04:00
if ( ! ( lv - > vg ) ) {
/* FIXME: Attempt reversion? */
unlock_lv ( cmd , lv - > lvid . s ) ;
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-07 14:12:11 +03:00
backup ( lv - > vg ) ;
2002-01-01 00:27:39 +03:00
2002-01-30 18:04:48 +03:00
log_very_verbose ( " Updating permissions for \" %s \" in kernel " , lv - > name ) ;
2002-04-24 22:20:51 +04:00
if ( ! unlock_lv ( cmd , lv - > lvid . s ) ) {
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 ;
}
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
{
2002-01-11 02:21:07 +03:00
int activate = 0 ;
2001-10-30 17:32:48 +03:00
2002-02-12 00:00:35 +03:00
if ( strcmp ( arg_str_value ( cmd , available_ARG , " n " ) , " n " ) )
2002-01-11 02:21:07 +03:00
activate = 1 ;
2001-10-30 17:32:48 +03:00
2002-02-12 00:00:35 +03:00
if ( arg_count ( cmd , minor_ARG ) ) {
lv - > minor = arg_int_value ( cmd , minor_ARG , - 1 ) ;
2002-02-01 20:54:39 +03:00
}
2002-01-11 02:21:07 +03:00
if ( activate ) {
2002-03-18 16:09:27 +03:00
/* FIXME Tighter locking if lv_is_origin() */
2002-01-30 18:04:48 +03:00
log_verbose ( " Activating logical volume \" %s \" " , lv - > name ) ;
2002-03-05 23:03:09 +03:00
if ( ! lock_vol ( cmd , lv - > lvid . s , LCK_LV_ACTIVATE ) )
2002-01-11 02:21:07 +03:00
return 0 ;
} else {
2002-01-30 18:04:48 +03:00
log_verbose ( " Deactivating logical volume \" %s \" " , lv - > name ) ;
2002-03-05 23:03:09 +03:00
if ( ! lock_vol ( cmd , lv - > lvid . s , LCK_LV_DEACTIVATE ) )
2002-01-11 02:21:07 +03:00
return 0 ;
2002-01-08 01:36:12 +03:00
}
2001-10-30 17:32:48 +03:00
return 1 ;
}
2002-02-12 00:00:35 +03:00
static int lvchange_contiguous ( struct cmd_context * cmd ,
struct logical_volume * lv )
2001-10-30 17:32:48 +03:00
{
int lv_allocation = 0 ;
2002-02-12 00:00:35 +03:00
if ( strcmp ( arg_str_value ( cmd , contiguous_ARG , " n " ) , " n " ) )
2001-10-30 17:32:48 +03:00
lv_allocation | = ALLOC_CONTIGUOUS ;
if ( ( lv_allocation & ALLOC_CONTIGUOUS ) & &
( lv - > status & ALLOC_CONTIGUOUS ) ) {
2002-01-30 18:04:48 +03:00
log_error ( " Allocation policy of logical volume \" %s \" is "
2001-10-30 17:32:48 +03:00
" already contiguous " , lv - > name ) ;
return 0 ;
}
if ( ! ( lv_allocation & ALLOC_CONTIGUOUS ) & &
! ( lv - > status & ALLOC_CONTIGUOUS ) ) {
2002-02-12 00:00:35 +03:00
log_error
( " Allocation policy of logical volume \" %s \" is already "
" not contiguous " , lv - > name ) ;
2001-10-30 17:32:48 +03:00
return 0 ;
}
/******** FIXME lv_check_contiguous?
if ( ( lv_allocation & ALLOC_CONTIGUOUS )
& & ( ret = lv_check_contiguous ( vg , lv_index + 1 ) ) = = FALSE ) {
2002-01-30 18:04:48 +03:00
log_error ( " No contiguous logical volume \" %s \" " , lv - > name ) ;
2001-10-30 17:32:48 +03:00
return 0 ;
* * * * * * * * */
if ( lv_allocation & ALLOC_CONTIGUOUS ) {
lv - > status | = ALLOC_CONTIGUOUS ;
2002-01-30 18:04:48 +03:00
log_verbose ( " Setting contiguous allocation policy for \" %s \" " ,
2001-11-14 21:38:07 +03:00
lv - > name ) ;
2001-10-30 17:32:48 +03:00
} else {
lv - > status & = ~ ALLOC_CONTIGUOUS ;
2002-01-30 18:04:48 +03:00
log_verbose ( " Removing contiguous allocation policy for \" %s \" " ,
2001-10-30 17:32:48 +03:00
lv - > name ) ;
}
2002-03-05 23:03:09 +03:00
if ( ! lock_vol ( cmd , lv - > lvid . s , LCK_LV_SUSPEND | LCK_HOLD ) ) {
2002-02-21 00:30:27 +03:00
log_error ( " Failed to lock %s " , lv - > name ) ;
return 0 ;
}
2001-10-31 20:59:52 +03:00
2002-02-21 00:30:27 +03:00
log_very_verbose ( " Updating logical volume \" %s \" on disk(s) " , lv - > name ) ;
2002-04-24 22:20:51 +04:00
if ( ! vg_write ( lv - > vg ) ) {
/* FIXME: Attempt reversion? */
unlock_lv ( cmd , lv - > lvid . s ) ;
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-07 14:12:11 +03:00
backup ( lv - > vg ) ;
2002-01-01 00:27:39 +03:00
2002-04-24 22:20:51 +04:00
if ( ! unlock_lv ( cmd , lv - > lvid . s ) ) {
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-21 00:30:27 +03:00
2001-10-30 17:32:48 +03:00
}
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
{
int read_ahead = 0 ;
2002-02-12 00:00:35 +03:00
read_ahead = arg_int_value ( cmd , readahead_ARG , 0 ) ;
2001-10-30 17:32:48 +03:00
/******* FIXME Ranges?
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
2002-03-05 23:03:09 +03:00
if ( ! lock_vol ( cmd , lv - > lvid . s , LCK_LV_SUSPEND | LCK_HOLD ) ) {
2002-02-21 00:30:27 +03:00
log_error ( " Failed to lock %s " , lv - > name ) ;
return 0 ;
}
2001-10-31 20:59:52 +03:00
2002-02-21 00:30:27 +03:00
log_very_verbose ( " Updating logical volume \" %s \" on disk(s) " , lv - > name ) ;
2002-04-24 22:20:51 +04:00
if ( ! vg_write ( lv - > vg ) ) {
/* FIXME: Attempt reversion? */
unlock_lv ( cmd , lv - > lvid . s ) ;
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-07 14:12:11 +03:00
backup ( lv - > vg ) ;
2002-01-01 00:27:39 +03:00
2002-04-24 22:20:51 +04:00
if ( ! unlock_lv ( cmd , lv - > lvid . s ) ) {
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
{
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 ;
log_verbose ( " Disabling persistent minor for \" %s \" " , lv - > name ) ;
} else {
2002-02-12 00:00:35 +03:00
if ( ! arg_count ( cmd , minor_ARG ) ) {
2002-02-01 20:54:39 +03:00
log_error ( " Minor number must be specified with -My " ) ;
return 0 ;
}
2002-03-26 16:41:37 +03:00
log_verbose ( " Ensuring %s is inactive. Reactivate with -ay. " ,
lv - > name ) ;
2002-03-11 22:02:28 +03:00
if ( ! lock_vol ( cmd , lv - > lvid . s , LCK_LV_DEACTIVATE ) ) {
log_error ( " %s: deactivation failed " , lv - > name ) ;
return 0 ;
}
2002-02-01 20:54:39 +03:00
lv - > status | = FIXED_MINOR ;
2002-02-12 00:00:35 +03:00
lv - > minor = arg_int_value ( cmd , minor_ARG , - 1 ) ;
2002-02-01 20:54:39 +03:00
log_verbose ( " Setting persistent minor number to %d for \" %s \" " ,
lv - > minor , lv - > name ) ;
}
2002-03-05 23:03:09 +03:00
if ( ! lock_vol ( cmd , lv - > lvid . s , LCK_LV_SUSPEND | LCK_HOLD ) ) {
2002-02-21 00:30:27 +03:00
log_error ( " Failed to lock %s " , lv - > name ) ;
return 0 ;
}
2002-02-01 20:54:39 +03:00
2002-02-21 00:30:27 +03:00
log_very_verbose ( " Updating logical volume \" %s \" on disk(s) " , lv - > name ) ;
2002-04-24 22:20:51 +04:00
if ( ! vg_write ( lv - > vg ) ) {
/* FIXME: Attempt reversion? */
unlock_lv ( cmd , lv - > lvid . s ) ;
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
backup ( lv - > vg ) ;
2002-04-24 22:20:51 +04:00
if ( ! unlock_lv ( cmd , lv - > lvid . s ) ) {
log_error ( " Problem reactivating %s " , lv - > name ) ;
return 0 ;
}
2002-02-21 00:30:27 +03:00
2002-02-01 20:54:39 +03:00
return 1 ;
}