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 .
2007-08-21 00:55:30 +04:00
* Copyright ( C ) 2004 - 2007 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
2007-08-21 00:55:30 +04:00
* of the GNU Lesser General Public License v .2 .1 .
2001-11-07 11:50:07 +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-01 19:29:39 +04:00
*/
# include "tools.h"
2008-01-09 03:18:36 +03:00
# include "metadata.h"
2001-10-01 19:29:39 +04:00
2005-01-05 20:25:25 +03:00
struct pvcreate_params {
int zero ;
2008-07-21 23:27:22 +04:00
uint64_t size ;
int pvmetadatacopies ;
uint64_t pvmetadatasize ;
2008-07-23 23:29:58 +04:00
int64_t labelsector ;
2005-01-05 20:25:25 +03:00
} ;
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
2008-07-24 19:25:09 +04:00
/* FIXME Check partition type is LVM unless --force is given */
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
2008-01-09 03:18:36 +03:00
/*
2008-01-30 17:00:02 +03:00
* If a PV has no MDAs it may appear to be an orphan until the
* metadata is read off another PV in the same VG . Detecting
* this means checking every VG by scanning every PV on the
* system .
2008-01-09 03:18:36 +03:00
*/
if ( pv & & is_orphan ( pv ) ) {
2008-01-16 21:15:26 +03:00
if ( ! scan_vgs_for_pvs ( cmd ) )
return_0 ;
2008-01-09 03:18:36 +03:00
pv = pv_read ( cmd , name , NULL , NULL , 0 ) ;
}
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 */
2007-06-14 19:48:05 +04:00
if ( pv & & ! is_orphan ( pv ) & & arg_count ( cmd , force_ARG ) ! = 2 ) {
2002-01-30 18:04:48 +03:00
log_error ( " Can't initialize physical volume \" %s \" of "
2007-06-16 02:16:55 +04:00
" volume group \" %s \" without -ff " , name , pv_vg_name ( pv ) ) ;
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 */
2007-06-14 19:48:05 +04:00
if ( pv & & ! is_orphan ( pv ) & & ! arg_count ( cmd , yes_ARG ) & &
2007-06-16 02:16:55 +04:00
yes_no_prompt ( _really_init , name , pv_vg_name ( pv ) ) = = ' 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
}
2007-06-15 14:11:14 +04:00
if ( sigint_caught ( ) )
return 0 ;
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 ( ) ) {
2007-11-02 23:40:05 +03:00
unlock_vg ( cmd , VG_ORPHANS ) ;
2005-03-22 01:40:35 +03:00
2004-11-19 22:25:07 +03:00
persistent_filter_wipe ( cmd - > filter ) ;
2008-04-08 16:49:21 +04:00
lvmcache_destroy ( cmd , 1 ) ;
2005-03-22 01:40:35 +03:00
2004-11-19 22:25:07 +03:00
init_md_filtering ( 0 ) ;
2007-11-02 23:40:05 +03:00
if ( ! lock_vol ( cmd , VG_ORPHANS , 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 ) ) {
2007-11-22 04:25:06 +03:00
/* FIXME Detect whether device-mapper itself is still using it */
2005-10-04 01:10:41 +04:00
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 ) ) | |
2008-01-30 17:00:02 +03:00
arg_count ( cmd , yes_ARG ) | |
2004-11-19 22:25:07 +03:00
( 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 ;
}
}
2007-06-15 14:11:14 +04:00
if ( sigint_caught ( ) )
return 0 ;
2007-06-14 19:48:05 +04:00
if ( pv & & ! is_orphan ( pv ) & & arg_count ( cmd , force_ARG ) ) {
2007-06-28 21:33:44 +04:00
log_warn ( " WARNING: Forcing physical volume creation on "
2002-01-30 18:04:48 +03:00
" %s%s%s%s " , name ,
2007-06-14 19:48:05 +04:00
! is_orphan ( pv ) ? " of volume group \" " : " " ,
2007-06-16 02:16:55 +04:00
! is_orphan ( pv ) ? pv_vg_name ( pv ) : " " ,
2007-06-14 19:48:05 +04:00
! is_orphan ( pv ) ? " \" " : " " ) ;
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 ;
2007-06-13 02:41:27 +04:00
void * pv ;
void * 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-01-16 21:10:08 +03:00
struct device * dev ;
2002-11-18 17:04:08 +03:00
struct list mdas ;
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
}
2007-06-16 02:16:55 +04:00
pe_start = pv_pe_start ( existing_pv ) ;
extent_size = pv_pe_size ( existing_pv ) ;
extent_count = pv_pe_count ( existing_pv ) ;
2002-11-18 17:04:08 +03:00
}
2007-11-02 23:40:05 +03:00
if ( ! lock_vol ( cmd , VG_ORPHANS , 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
2007-06-15 14:11:14 +04:00
if ( sigint_caught ( ) )
goto error ;
2002-11-18 17:04:08 +03:00
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 ) ;
2008-07-21 23:27:22 +04:00
if ( ! ( pv = pv_create ( cmd , dev , idp , pp - > size , pe_start ,
extent_count , extent_size , pp - > pvmetadatacopies ,
pp - > 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
2007-06-16 02:16:55 +04:00
" available sectors " , pv_name , pv_size ( pv ) ) ;
2002-11-18 17:04:08 +03:00
/* Wipe existing label first */
2007-06-16 02:16:55 +04:00
if ( ! label_remove ( pv_dev ( pv ) ) ) {
2002-11-18 17:04:08 +03:00
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 ) ;
2007-06-13 02:41:27 +04:00
if ( ! ( pv_write ( cmd , ( struct physical_volume * ) pv , & mdas ,
2008-07-23 23:29:58 +04:00
pp - > 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
2007-11-02 23:40:05 +03:00
unlock_vg ( cmd , VG_ORPHANS ) ;
2003-10-22 02:06:07 +04:00
return ECMD_PROCESSED ;
2002-11-18 17:04:08 +03:00
error :
2007-11-02 23:40:05 +03:00
unlock_vg ( cmd , VG_ORPHANS ) ;
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
2008-07-21 23:26:33 +04:00
/*
2008-07-21 23:27:22 +04:00
* Intial sanity checking of command - line arguments and fill in ' pp ' fields .
*
* Input arguments :
* cmd , argc , argv
*
* Output arguments :
* pp : structure allocated by caller , fields written / validated here
2008-07-21 23:26:33 +04:00
*/
2008-07-21 23:27:22 +04:00
static int pvcreate_validate_params ( struct cmd_context * cmd ,
int argc , char * * argv ,
struct pvcreate_params * pp )
2001-10-12 14:32:06 +04:00
{
if ( ! argc ) {
log_error ( " Please enter a physical volume path " ) ;
2008-07-21 23:26:33 +04:00
return 0 ;
2001-10-12 14:32:06 +04:00
}
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 " ) ;
2008-07-21 23:26:33 +04:00
return 0 ;
2002-11-18 17:04:08 +03:00
}
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 " ) ;
2008-07-21 23:26:33 +04:00
return 0 ;
2002-01-16 21:10:08 +03:00
}
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 " ) ;
2008-07-21 23:26:33 +04:00
return 0 ;
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 ) ;
2008-07-21 23:26:33 +04:00
return 0 ;
2008-07-23 23:29:58 +04:00
} else {
pp - > labelsector = arg_int64_value ( cmd , labelsector_ARG ,
DEFAULT_LABELSECTOR ) ;
2002-11-18 17:04:08 +03:00
}
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 " ) ;
2008-07-21 23:26:33 +04:00
return 0 ;
2002-11-18 17:04:08 +03:00
}
if ( arg_count ( cmd , metadatacopies_ARG ) & &
arg_int_value ( cmd , metadatacopies_ARG , - 1 ) > 2 ) {
log_error ( " Metadatacopies may only be 0, 1 or 2 " ) ;
2008-07-21 23:26:33 +04:00
return 0 ;
2002-11-18 17:04:08 +03:00
}
2005-01-05 20:25:25 +03:00
if ( arg_count ( cmd , zero_ARG ) )
2008-07-21 23:26:33 +04:00
pp - > zero = strcmp ( arg_str_value ( cmd , zero_ARG , " y " ) , " n " ) ;
2005-01-05 20:25:25 +03:00
else if ( arg_count ( cmd , restorefile_ARG ) | | arg_count ( cmd , uuidstr_ARG ) )
2008-07-21 23:26:33 +04:00
pp - > zero = 0 ;
2005-01-05 20:25:25 +03:00
else
2008-07-21 23:26:33 +04:00
pp - > zero = 1 ;
2008-07-21 23:27:22 +04:00
if ( arg_sign_value ( cmd , physicalvolumesize_ARG , 0 ) = = SIGN_MINUS ) {
log_error ( " Physical volume size may not be negative " ) ;
return 0 ;
}
pp - > size = arg_uint64_value ( cmd , physicalvolumesize_ARG , UINT64_C ( 0 ) ) ;
2008-07-21 23:26:33 +04:00
2008-07-21 23:27:22 +04:00
if ( arg_sign_value ( cmd , metadatasize_ARG , 0 ) = = SIGN_MINUS ) {
log_error ( " Metadata size may not be negative " ) ;
return 0 ;
}
pp - > pvmetadatasize = arg_uint64_value ( cmd , metadatasize_ARG , UINT64_C ( 0 ) ) ;
if ( ! pp - > pvmetadatasize )
pp - > pvmetadatasize = find_config_tree_int ( cmd ,
" metadata/pvmetadatasize " ,
DEFAULT_PVMETADATASIZE ) ;
pp - > pvmetadatacopies = arg_int_value ( cmd , metadatacopies_ARG , - 1 ) ;
if ( pp - > pvmetadatacopies < 0 )
pp - > pvmetadatacopies = find_config_tree_int ( cmd ,
" metadata/pvmetadatacopies " ,
DEFAULT_PVMETADATACOPIES ) ;
2008-07-21 23:26:33 +04:00
return 1 ;
}
2008-07-21 23:27:22 +04:00
2008-07-21 23:26:33 +04:00
int pvcreate ( struct cmd_context * cmd , int argc , char * * argv )
{
int i , r ;
int ret = ECMD_PROCESSED ;
struct pvcreate_params pp ;
2008-07-21 23:27:22 +04:00
if ( ! pvcreate_validate_params ( cmd , argc , argv , & pp ) ) {
2008-07-21 23:26:33 +04:00
return EINVALID_CMD_LINE ;
}
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 ;
2007-06-15 14:11:14 +04:00
if ( sigint_caught ( ) )
return ret ;
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
}