2005-10-31 05:37:29 +03:00
/*
2008-01-30 17:00:02 +03:00
* Copyright ( C ) 2001 - 2004 Sistina Software , Inc . All rights reserved .
2005-10-31 05:37:29 +03:00
* Copyright ( C ) 2004 - 2005 Red Hat , Inc . All rights reserved .
* Copyright ( C ) 2005 Zak Kipling . All rights reserved .
*
* 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 .
2005-10-31 05:37:29 +03:00
*
2007-08-21 00:55:30 +04:00
* You should have received a copy of the GNU Lesser General Public License
2005-10-31 05:37:29 +03:00
* along with this program ; if not , write to the Free Software Foundation ,
* Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
# include "tools.h"
2011-02-28 16:19:02 +03:00
# include "metadata.h"
2005-10-31 05:37:29 +03:00
struct pvresize_params {
uint64_t new_size ;
unsigned done ;
unsigned total ;
} ;
2007-11-17 00:16:20 +03:00
static int _pv_resize_single ( struct cmd_context * cmd ,
struct volume_group * vg ,
struct physical_volume * pv ,
const uint64_t new_size )
2007-11-16 01:11:18 +03:00
{
struct pv_list * pvl ;
uint64_t size = 0 ;
2009-04-10 14:01:38 +04:00
int r = 0 ;
2007-11-16 01:11:18 +03:00
const char * pv_name = pv_dev_name ( pv ) ;
2010-05-19 05:16:40 +04:00
const char * vg_name = pv_vg_name ( pv ) ;
2009-04-10 14:01:38 +04:00
struct volume_group * old_vg = vg ;
2011-02-28 20:08:09 +03:00
int vg_needs_pv_write = 0 ;
2007-11-16 01:11:18 +03:00
2010-05-19 05:16:40 +04:00
if ( is_orphan_vg ( vg_name ) ) {
2007-11-16 01:11:18 +03:00
if ( ! lock_vol ( cmd , vg_name , LCK_VG_WRITE ) ) {
log_error ( " Can't get lock for orphans " ) ;
return 0 ;
}
2011-06-01 23:29:31 +04:00
if ( ! ( pv = pv_read ( cmd , pv_name , 1 , 0 ) ) ) {
2007-11-16 01:11:18 +03:00
unlock_vg ( cmd , vg_name ) ;
log_error ( " Unable to read PV \" %s \" " , pv_name ) ;
return 0 ;
}
} else {
2009-07-01 20:59:37 +04:00
vg = vg_read_for_update ( cmd , vg_name , NULL , 0 ) ;
2007-11-16 01:11:18 +03:00
2009-12-11 16:11:56 +03:00
if ( vg_read_error ( vg ) ) {
2011-08-11 00:25:29 +04:00
release_vg ( vg ) ;
2009-12-11 16:11:56 +03:00
log_error ( " Unable to read volume group \" %s \" . " ,
vg_name ) ;
return 0 ;
}
2007-11-16 01:11:18 +03:00
if ( ! ( pvl = find_pv_in_vg ( vg , pv_name ) ) ) {
log_error ( " Unable to find \" %s \" in volume group \" %s \" " ,
pv_name , vg - > name ) ;
2010-05-19 05:16:40 +04:00
goto out ;
2007-11-16 01:11:18 +03:00
}
pv = pvl - > pv ;
if ( ! archive ( vg ) )
2010-05-19 05:16:40 +04:00
goto out ;
2007-11-16 01:11:18 +03:00
}
if ( ! ( pv - > fmt - > features & FMT_RESIZE_PV ) ) {
log_error ( " Physical volume %s format does not support resizing. " ,
pv_name ) ;
2010-05-19 05:16:40 +04:00
goto out ;
2007-11-16 01:11:18 +03:00
}
/* Get new size */
if ( ! dev_get_size ( pv_dev ( pv ) , & size ) ) {
log_error ( " %s: Couldn't get size. " , pv_name ) ;
2010-05-19 05:16:40 +04:00
goto out ;
2007-11-16 01:11:18 +03:00
}
2009-07-07 05:18:35 +04:00
2007-11-16 01:11:18 +03:00
if ( new_size ) {
if ( new_size > size )
log_warn ( " WARNING: %s: Overriding real size. "
" You could lose data. " , pv_name ) ;
log_verbose ( " %s: Pretending size is % " PRIu64 " not % " PRIu64
" sectors. " , pv_name , new_size , pv_size ( pv ) ) ;
size = new_size ;
}
log_verbose ( " Resizing volume \" %s \" to % " PRIu64 " sectors. " ,
pv_name , pv_size ( pv ) ) ;
2011-02-21 15:27:26 +03:00
if ( ! pv_resize ( pv , vg , size ) )
goto_out ;
2007-11-16 01:11:18 +03:00
log_verbose ( " Updating physical volume \" %s \" " , pv_name ) ;
2011-02-28 16:19:02 +03:00
/* Write PV label only if this an orphan PV or it has 2nd mda. */
if ( ( is_orphan_vg ( vg_name ) | |
2011-02-28 20:08:09 +03:00
( vg_needs_pv_write = ( fid_get_mda_indexed ( vg - > fid ,
( const char * ) & pv - > id , ID_LEN , 1 ) ! = NULL ) ) ) & &
2011-02-28 16:19:02 +03:00
! pv_write ( cmd , pv , 1 ) ) {
log_error ( " Failed to store physical volume \" %s \" " ,
pv_name ) ;
goto out ;
}
2010-05-19 05:16:40 +04:00
if ( ! is_orphan_vg ( vg_name ) ) {
2007-11-16 01:11:18 +03:00
if ( ! vg_write ( vg ) | | ! vg_commit ( vg ) ) {
log_error ( " Failed to store physical volume \" %s \" in "
2010-10-25 16:01:38 +04:00
" volume group \" %s \" " , pv_name , vg_name ) ;
2010-05-19 05:16:40 +04:00
goto out ;
2007-11-16 01:11:18 +03:00
}
backup ( vg ) ;
}
log_print ( " Physical volume \" %s \" changed " , pv_name ) ;
2009-04-10 14:01:38 +04:00
r = 1 ;
2010-05-19 05:16:40 +04:00
out :
2011-02-28 20:08:09 +03:00
if ( ! r & & vg_needs_pv_write )
log_error ( " Use pvcreate and vgcfgrestore "
" to repair from archived metadata. " ) ;
2009-04-10 14:01:38 +04:00
unlock_vg ( cmd , vg_name ) ;
2011-03-11 17:56:56 +03:00
if ( is_orphan_vg ( vg_name ) )
free_pv_fid ( pv ) ;
2009-04-10 14:01:38 +04:00
if ( ! old_vg )
2011-08-11 00:25:29 +04:00
release_vg ( vg ) ;
2009-04-10 14:01:38 +04:00
return r ;
2007-11-16 01:11:18 +03:00
}
2007-08-31 00:16:01 +04:00
static int _pvresize_single ( struct cmd_context * cmd ,
struct volume_group * vg ,
struct physical_volume * pv ,
void * handle )
{
struct pvresize_params * params = ( struct pvresize_params * ) handle ;
params - > total + + ;
2005-10-31 05:37:29 +03:00
2009-09-15 02:47:49 +04:00
if ( ! _pv_resize_single ( cmd , vg , pv , params - > new_size ) ) {
stack ;
2007-08-31 00:16:01 +04:00
return ECMD_FAILED ;
2009-09-15 02:47:49 +04:00
}
2007-08-31 00:16:01 +04:00
2005-10-31 05:37:29 +03:00
params - > done + + ;
2007-08-31 00:16:01 +04:00
return ECMD_PROCESSED ;
2005-10-31 05:37:29 +03:00
}
int pvresize ( struct cmd_context * cmd , int argc , char * * argv )
{
struct pvresize_params params ;
int ret ;
if ( ! argc ) {
log_error ( " Please supply physical volume(s) " ) ;
return EINVALID_CMD_LINE ;
}
if ( arg_sign_value ( cmd , physicalvolumesize_ARG , 0 ) = = SIGN_MINUS ) {
log_error ( " Physical volume size may not be negative " ) ;
return 0 ;
}
params . new_size = arg_uint64_value ( cmd , physicalvolumesize_ARG ,
2007-11-14 03:08:25 +03:00
UINT64_C ( 0 ) ) ;
2005-10-31 05:37:29 +03:00
params . done = 0 ;
params . total = 0 ;
2009-07-15 09:50:22 +04:00
ret = process_each_pv ( cmd , argc , argv , NULL , READ_FOR_UPDATE , 0 , & params ,
2007-11-14 21:41:05 +03:00
_pvresize_single ) ;
2005-10-31 05:37:29 +03:00
log_print ( " %d physical volume(s) resized / %d physical volume(s) "
" not resized " , params . done , params . total - params . done ) ;
return ret ;
}