2001-10-01 19:29:39 +04: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-11-07 11:50:07 +03:00
*
2004-03-30 23:35:44 +04:00
* This file is part of LVM2 .
2001-11-07 11:50:07 +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-11-07 11:50:07 +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-01 19:29:39 +04:00
*/
# include "tools.h"
2005-01-05 20:25:25 +03:00
struct pvcreate_params {
int zero ;
} ;
2001-10-12 14:32:06 +04:00
const char _really_init [ ] =
2002-01-30 18:04:48 +03:00
" Really INITIALIZE physical volume \" %s \" of volume group \" %s \" [y/n]? " ;
2001-10-01 19:29:39 +04:00
2001-10-12 14:32:06 +04:00
/*
* See if we may pvcreate on this device .
* 0 indicates we may not .
*/
2002-02-11 23:50:53 +03:00
static int pvcreate_check ( struct cmd_context * cmd , const char * name )
2001-10-01 19:29:39 +04:00
{
2001-10-12 14:32:06 +04:00
struct physical_volume * pv ;
2004-11-19 22:25:07 +03:00
struct device * dev ;
uint64_t md_superblock ;
2001-10-01 19:29:39 +04:00
2001-10-12 14:32:06 +04:00
/* is the partition type set correctly ? */
2002-02-20 21:29:30 +03:00
if ( ( arg_count ( cmd , force_ARG ) < 1 ) & & ! is_lvm_partition ( name ) ) {
log_error ( " %s: Not LVM partition type: use -f to override " ,
name ) ;
2001-10-12 14:32:06 +04:00
return 0 ;
2002-02-20 21:29:30 +03:00
}
2001-10-01 19:29:39 +04:00
2004-11-19 22:25:07 +03:00
/* Is there a pv here already? */
2003-07-05 02:34:56 +04:00
/* FIXME Use partial mode here? */
2004-11-19 22:25:07 +03:00
pv = pv_read ( cmd , name , NULL , NULL , 0 ) ;
2001-10-01 19:29:39 +04:00
2002-01-29 22:19:37 +03:00
/* Allow partial & exported VGs to be destroyed. */
2004-11-19 22:25:07 +03:00
/* We must have -ff to overwrite a non orphan */
if ( pv & & pv - > vg_name [ 0 ] & & arg_count ( cmd , force_ARG ) ! = 2 ) {
2002-01-30 18:04:48 +03:00
log_error ( " Can't initialize physical volume \" %s \" of "
" volume group \" %s \" without -ff " , name , pv - > vg_name ) ;
2001-10-12 14:32:06 +04:00
return 0 ;
2001-10-01 19:29:39 +04:00
}
2001-10-12 14:32:06 +04:00
/* prompt */
2004-11-19 22:25:07 +03:00
if ( pv & & pv - > vg_name [ 0 ] & & ! arg_count ( cmd , yes_ARG ) & &
2001-10-12 14:32:06 +04:00
yes_no_prompt ( _really_init , name , pv - > vg_name ) = = ' n ' ) {
2002-02-20 21:29:30 +03:00
log_print ( " %s: physical volume not initialized " , name ) ;
2001-10-12 14:32:06 +04:00
return 0 ;
2001-10-01 19:29:39 +04:00
}
2004-11-19 22:25:07 +03:00
dev = dev_cache_get ( name , cmd - > filter ) ;
/* Is there an md superblock here? */
if ( ! dev & & md_filtering ( ) ) {
2005-10-03 22:16:44 +04:00
unlock_vg ( cmd , ORPHAN ) ;
2005-03-22 01:40:35 +03:00
2004-11-19 22:25:07 +03:00
persistent_filter_wipe ( cmd - > filter ) ;
lvmcache_destroy ( ) ;
2005-03-22 01:40:35 +03:00
2004-11-19 22:25:07 +03:00
init_md_filtering ( 0 ) ;
2005-10-03 22:16:44 +04:00
if ( ! lock_vol ( cmd , ORPHAN , LCK_VG_WRITE ) ) {
2004-11-19 22:25:07 +03:00
log_error ( " Can't get lock for orphan PVs " ) ;
init_md_filtering ( 1 ) ;
return 0 ;
}
dev = dev_cache_get ( name , cmd - > filter ) ;
init_md_filtering ( 1 ) ;
}
if ( ! dev ) {
2005-12-08 20:49:34 +03:00
log_error ( " Device %s not found (or ignored by filtering). " , name ) ;
2004-11-19 22:25:07 +03:00
return 0 ;
}
2005-10-04 01:10:41 +04:00
if ( ! dev_test_excl ( dev ) ) {
log_error ( " Can't open %s exclusively. Mounted filesystem? " ,
name ) ;
return 0 ;
}
2004-11-19 22:25:07 +03:00
/* Wipe superblock? */
if ( dev_is_md ( dev , & md_superblock ) & &
( ( ! arg_count ( cmd , uuidstr_ARG ) & &
! arg_count ( cmd , restorefile_ARG ) ) | |
arg_count ( cmd , yes_ARG ) | |
( yes_no_prompt ( " Software RAID md superblock "
" detected on %s. Wipe it? [y/n] " , name ) = = ' y ' ) ) ) {
log_print ( " Wiping software RAID md superblock on %s " , name ) ;
2006-05-11 22:39:24 +04:00
if ( ! dev_set ( dev , md_superblock , 4 , 0 ) ) {
2004-11-19 22:25:07 +03:00
log_error ( " Failed to wipe RAID md superblock on %s " ,
name ) ;
return 0 ;
}
}
if ( pv & & pv - > vg_name [ 0 ] & & arg_count ( cmd , force_ARG ) ) {
2001-10-15 22:39:40 +04:00
log_print ( " WARNING: Forcing physical volume creation on "
2002-01-30 18:04:48 +03:00
" %s%s%s%s " , name ,
pv - > vg_name [ 0 ] ? " of volume group \" " : " " ,
pv - > vg_name [ 0 ] ? pv - > vg_name : " " ,
pv - > vg_name [ 0 ] ? " \" " : " " ) ;
2001-10-01 19:29:39 +04:00
}
2001-10-12 14:32:06 +04:00
return 1 ;
}
2003-10-22 02:06:07 +04:00
static int pvcreate_single ( struct cmd_context * cmd , const char * pv_name ,
void * handle )
2001-10-12 14:32:06 +04:00
{
2005-01-05 20:25:25 +03:00
struct pvcreate_params * pp = ( struct pvcreate_params * ) handle ;
2002-11-18 17:04:08 +03:00
struct physical_volume * pv , * existing_pv ;
2002-01-16 21:10:08 +03:00
struct id id , * idp = NULL ;
2002-12-20 02:25:55 +03:00
const char * uuid = NULL ;
2002-02-15 04:26:16 +03:00
uint64_t size = 0 ;
2002-01-16 21:10:08 +03:00
struct device * dev ;
2002-11-18 17:04:08 +03:00
struct list mdas ;
int pvmetadatacopies ;
uint64_t pvmetadatasize ;
struct volume_group * vg ;
2002-12-20 02:25:55 +03:00
const char * restorefile ;
2002-11-18 17:04:08 +03:00
uint64_t pe_start = 0 ;
uint32_t extent_count = 0 , extent_size = 0 ;
2002-01-16 21:10:08 +03:00
2002-02-12 00:00:35 +03:00
if ( arg_count ( cmd , uuidstr_ARG ) ) {
uuid = arg_str_value ( cmd , uuidstr_ARG , " " ) ;
2002-01-16 21:10:08 +03:00
if ( ! id_read_format ( & id , uuid ) )
2003-10-22 02:06:07 +04:00
return EINVALID_CMD_LINE ;
2002-11-18 17:04:08 +03:00
if ( ( dev = device_from_pvid ( cmd , & id ) ) & &
( dev ! = dev_cache_get ( pv_name , cmd - > filter ) ) ) {
2002-01-30 18:04:48 +03:00
log_error ( " uuid %s already in use on \" %s \" " , uuid ,
2002-01-16 21:10:08 +03:00
dev_name ( dev ) ) ;
2003-10-22 02:06:07 +04:00
return ECMD_FAILED ;
2002-01-16 21:10:08 +03:00
}
idp = & id ;
}
2001-10-02 02:12:10 +04:00
2002-11-18 17:04:08 +03:00
if ( arg_count ( cmd , restorefile_ARG ) ) {
restorefile = arg_str_value ( cmd , restorefile_ARG , " " ) ;
/* The uuid won't already exist */
init_partial ( 1 ) ;
if ( ! ( vg = backup_read_vg ( cmd , NULL , restorefile ) ) ) {
log_error ( " Unable to read volume group from %s " ,
restorefile ) ;
2003-10-22 02:06:07 +04:00
return ECMD_FAILED ;
2002-11-18 17:04:08 +03:00
}
init_partial ( 0 ) ;
if ( ! ( existing_pv = find_pv_in_vg_by_uuid ( vg , idp ) ) ) {
log_error ( " Can't find uuid %s in backup file %s " ,
uuid , restorefile ) ;
2003-10-22 02:06:07 +04:00
return ECMD_FAILED ;
2002-11-18 17:04:08 +03:00
}
pe_start = existing_pv - > pe_start ;
extent_size = existing_pv - > pe_size ;
extent_count = existing_pv - > pe_count ;
}
2005-10-03 22:16:44 +04:00
if ( ! lock_vol ( cmd , ORPHAN , LCK_VG_WRITE ) ) {
2002-11-18 17:04:08 +03:00
log_error ( " Can't get lock for orphan PVs " ) ;
2003-10-22 02:06:07 +04:00
return ECMD_FAILED ;
2002-11-18 17:04:08 +03:00
}
if ( ! pvcreate_check ( cmd , pv_name ) )
goto error ;
2001-10-01 19:29:39 +04:00
2003-09-15 19:04:39 +04:00
if ( arg_sign_value ( cmd , physicalvolumesize_ARG , 0 ) = = SIGN_MINUS ) {
log_error ( " Physical volume size may not be negative " ) ;
goto error ;
}
2003-03-24 21:08:53 +03:00
size = arg_uint64_value ( cmd , physicalvolumesize_ARG , UINT64_C ( 0 ) ) * 2 ;
2002-04-24 22:20:51 +04:00
2003-09-15 19:04:39 +04:00
if ( arg_sign_value ( cmd , metadatasize_ARG , 0 ) = = SIGN_MINUS ) {
log_error ( " Metadata size may not be negative " ) ;
goto error ;
}
2003-03-24 21:08:53 +03:00
pvmetadatasize = arg_uint64_value ( cmd , metadatasize_ARG , UINT64_C ( 0 ) )
2002-12-20 02:25:55 +03:00
* 2 ;
2002-11-18 17:04:08 +03:00
if ( ! pvmetadatasize )
2006-05-16 20:48:31 +04:00
pvmetadatasize = find_config_tree_int ( cmd ,
2002-11-18 17:04:08 +03:00
" metadata/pvmetadatasize " ,
2004-03-08 21:28:45 +03:00
DEFAULT_PVMETADATASIZE ) ;
2002-11-18 17:04:08 +03:00
pvmetadatacopies = arg_int_value ( cmd , metadatacopies_ARG , - 1 ) ;
if ( pvmetadatacopies < 0 )
2006-05-16 20:48:31 +04:00
pvmetadatacopies = find_config_tree_int ( cmd ,
2002-11-18 17:04:08 +03:00
" metadata/pvmetadatacopies " ,
DEFAULT_PVMETADATACOPIES ) ;
if ( ! ( dev = dev_cache_get ( pv_name , cmd - > filter ) ) ) {
2004-09-14 18:54:58 +04:00
log_error ( " %s: Couldn't find device. Check your filters? " ,
pv_name ) ;
2002-11-18 17:04:08 +03:00
goto error ;
2002-04-24 22:20:51 +04:00
}
2002-11-18 17:04:08 +03:00
list_init ( & mdas ) ;
if ( ! ( pv = pv_create ( cmd - > fmt , dev , idp , size , pe_start ,
extent_count , extent_size ,
pvmetadatacopies , pvmetadatasize , & mdas ) ) ) {
2002-02-20 21:29:30 +03:00
log_error ( " Failed to setup physical volume \" %s \" " , pv_name ) ;
2002-11-18 17:04:08 +03:00
goto error ;
2001-10-02 02:12:10 +04:00
}
2002-01-30 18:04:48 +03:00
log_verbose ( " Set up physical volume for \" %s \" with % " PRIu64
2002-11-18 17:04:08 +03:00
" available sectors " , pv_name , pv - > size ) ;
/* Wipe existing label first */
if ( ! label_remove ( pv - > dev ) ) {
log_error ( " Failed to wipe existing label on %s " , pv_name ) ;
goto error ;
}
2001-10-01 19:29:39 +04:00
2005-01-05 20:25:25 +03:00
if ( pp - > zero ) {
log_verbose ( " Zeroing start of device %s " , pv_name ) ;
if ( ! dev_open_quiet ( dev ) ) {
log_error ( " %s not opened: device not zeroed " , pv_name ) ;
goto error ;
}
2005-10-04 01:10:41 +04:00
2006-05-11 22:39:24 +04:00
if ( ! dev_set ( dev , UINT64_C ( 0 ) , ( size_t ) 2048 , 0 ) ) {
2005-10-04 01:10:41 +04:00
log_error ( " %s not wiped: aborting " , pv_name ) ;
dev_close ( dev ) ;
goto error ;
}
2005-01-05 20:25:25 +03:00
dev_close ( dev ) ;
}
2002-02-20 21:29:30 +03:00
log_very_verbose ( " Writing physical volume data to disk \" %s \" " ,
pv_name ) ;
2002-12-20 02:25:55 +03:00
if ( ! ( pv_write ( cmd , pv , & mdas , arg_int64_value ( cmd , labelsector_ARG ,
DEFAULT_LABELSECTOR ) ) ) ) {
2002-01-30 18:04:48 +03:00
log_error ( " Failed to write physical volume \" %s \" " , pv_name ) ;
2002-11-18 17:04:08 +03:00
goto error ;
2001-10-01 19:29:39 +04:00
}
2002-01-30 18:04:48 +03:00
log_print ( " Physical volume \" %s \" successfully created " , pv_name ) ;
2002-11-18 17:04:08 +03:00
2005-10-03 22:16:44 +04:00
unlock_vg ( cmd , ORPHAN ) ;
2003-10-22 02:06:07 +04:00
return ECMD_PROCESSED ;
2002-11-18 17:04:08 +03:00
error :
2005-10-03 22:16:44 +04:00
unlock_vg ( cmd , ORPHAN ) ;
2003-10-22 02:06:07 +04:00
return ECMD_FAILED ;
2001-10-12 14:32:06 +04:00
}
2001-10-01 19:29:39 +04:00
2002-02-11 23:50:53 +03:00
int pvcreate ( struct cmd_context * cmd , int argc , char * * argv )
2001-10-12 14:32:06 +04:00
{
2003-10-22 02:06:07 +04:00
int i , r ;
int ret = ECMD_PROCESSED ;
2005-01-05 20:25:25 +03:00
struct pvcreate_params pp ;
2001-10-01 19:29:39 +04:00
2001-10-12 14:32:06 +04:00
if ( ! argc ) {
log_error ( " Please enter a physical volume path " ) ;
return EINVALID_CMD_LINE ;
}
2001-10-01 19:29:39 +04:00
2002-11-18 17:04:08 +03:00
if ( arg_count ( cmd , restorefile_ARG ) & & ! arg_count ( cmd , uuidstr_ARG ) ) {
log_error ( " --uuid is required with --restorefile " ) ;
return EINVALID_CMD_LINE ;
}
2002-02-12 00:00:35 +03:00
if ( arg_count ( cmd , uuidstr_ARG ) & & argc ! = 1 ) {
2002-01-16 21:10:08 +03:00
log_error ( " Can only set uuid on one volume at once " ) ;
return EINVALID_CMD_LINE ;
}
2002-02-12 00:00:35 +03:00
if ( arg_count ( cmd , yes_ARG ) & & ! arg_count ( cmd , force_ARG ) ) {
2001-10-12 16:21:43 +04:00
log_error ( " Option y can only be given with option f " ) ;
2001-10-12 14:32:06 +04:00
return EINVALID_CMD_LINE ;
2001-10-01 19:29:39 +04:00
}
2002-11-18 17:04:08 +03:00
if ( arg_int_value ( cmd , labelsector_ARG , 0 ) > = LABEL_SCAN_SECTORS ) {
log_error ( " labelsector must be less than %lu " ,
LABEL_SCAN_SECTORS ) ;
return EINVALID_CMD_LINE ;
}
if ( ! ( cmd - > fmt - > features & FMT_MDAS ) & &
( arg_count ( cmd , metadatacopies_ARG ) | |
arg_count ( cmd , metadatasize_ARG ) ) ) {
log_error ( " Metadata parameters only apply to text format " ) ;
return EINVALID_CMD_LINE ;
}
if ( arg_count ( cmd , metadatacopies_ARG ) & &
arg_int_value ( cmd , metadatacopies_ARG , - 1 ) > 2 ) {
log_error ( " Metadatacopies may only be 0, 1 or 2 " ) ;
return EINVALID_CMD_LINE ;
}
2005-01-05 20:25:25 +03:00
if ( arg_count ( cmd , zero_ARG ) )
pp . zero = strcmp ( arg_str_value ( cmd , zero_ARG , " y " ) , " n " ) ;
else if ( arg_count ( cmd , restorefile_ARG ) | | arg_count ( cmd , uuidstr_ARG ) )
pp . zero = 0 ;
else
pp . zero = 1 ;
2001-10-12 14:32:06 +04:00
for ( i = 0 ; i < argc ; i + + ) {
2005-01-05 20:25:25 +03:00
r = pvcreate_single ( cmd , argv [ i ] , & pp ) ;
2003-10-22 02:06:07 +04:00
if ( r > ret )
ret = r ;
2001-10-12 14:32:06 +04:00
}
2001-10-01 19:29:39 +04:00
2003-10-22 02:06:07 +04:00
return ret ;
2001-10-01 19:29:39 +04:00
}