2001-10-04 21:48:55 +04:00
/*
2008-01-30 17:00:02 +03:00
* Copyright ( C ) 2001 - 2004 Sistina Software , Inc . All rights reserved .
2012-02-08 14:49:36 +04:00
* Copyright ( C ) 2004 - 2012 Red Hat , Inc . All rights reserved .
2001-10-04 21:48:55 +04:00
*
2004-03-30 23:35:44 +04:00
* 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 .
2004-03-30 23:35:44 +04: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-04 21:48:55 +04:00
*/
2002-11-18 17:01:16 +03:00
# include "lib.h"
2001-10-04 21:48:55 +04:00
# include "disk-rep.h"
2002-02-14 00:28:56 +03:00
# include "limits.h"
2001-10-16 00:29:15 +04:00
# include "display.h"
2002-02-11 23:50:53 +03:00
# include "toolcontext.h"
2002-11-18 17:01:16 +03:00
# include "lvm1-label.h"
# include "format1.h"
2004-09-16 22:40:56 +04:00
# include "segtype.h"
2010-09-22 17:45:21 +04:00
# include "pv_alloc.h"
2001-10-04 21:48:55 +04:00
2001-10-16 20:25:28 +04:00
/* VG consistency checks */
2010-09-22 17:45:21 +04:00
static int _check_vgs ( struct dm_list * pvs , struct volume_group * vg )
2001-10-04 21:48:55 +04:00
{
2008-11-04 01:14:30 +03:00
struct dm_list * pvh , * t ;
2001-10-25 17:08:29 +04:00
struct disk_list * dl = NULL ;
2001-10-16 20:25:28 +04:00
struct disk_list * first = NULL ;
2002-12-20 02:25:55 +03:00
uint32_t pv_count = 0 ;
uint32_t exported = 0 ;
int first_time = 1 ;
2002-01-29 20:23:33 +03:00
/*
* If there are exported and unexported PVs , ignore exported ones .
* This means an active VG won ' t be affected if disks are inserted
* bearing an exported VG with the same name .
2002-02-12 19:31:31 +03:00
*/
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( dl , pvs ) {
2002-12-20 02:25:55 +03:00
if ( first_time ) {
2002-01-29 20:23:33 +03:00
exported = dl - > pvd . pv_status & VG_EXPORTED ;
2002-12-20 02:25:55 +03:00
first_time = 0 ;
2002-01-29 20:23:33 +03:00
continue ;
}
if ( exported ! = ( dl - > pvd . pv_status & VG_EXPORTED ) ) {
/* Remove exported PVs */
2008-11-04 01:14:30 +03:00
dm_list_iterate_safe ( pvh , t , pvs ) {
dl = dm_list_item ( pvh , struct disk_list ) ;
2002-01-29 20:23:33 +03:00
if ( dl - > pvd . pv_status & VG_EXPORTED )
2008-11-04 01:14:30 +03:00
dm_list_del ( pvh ) ;
2002-01-29 20:23:33 +03:00
}
break ;
}
}
/* Remove any PVs with VG structs that differ from the first */
2008-11-04 01:14:30 +03:00
dm_list_iterate_safe ( pvh , t , pvs ) {
dl = dm_list_item ( pvh , struct disk_list ) ;
2002-01-29 20:23:33 +03:00
2001-10-09 18:26:45 +04:00
if ( ! first )
2001-10-16 20:25:28 +04:00
first = dl ;
2001-11-12 15:16:57 +03:00
2001-10-31 20:59:52 +03:00
else if ( memcmp ( & first - > vgd , & dl - > vgd , sizeof ( first - > vgd ) ) ) {
2002-01-28 00:30:47 +03:00
log_error ( " VG data differs between PVs %s and %s " ,
dev_name ( first - > dev ) , dev_name ( dl - > dev ) ) ;
2013-01-08 02:30:29 +04:00
log_debug_metadata ( " VG data on %s: %s %s % " PRIu32 " % " PRIu32
" % " PRIu32 " % " PRIu32 " % " PRIu32 " % "
PRIu32 " % " PRIu32 " % " PRIu32 " % " PRIu32
" % " PRIu32 " % " PRIu32 " % " PRIu32 " % "
PRIu32 " % " PRIu32 " % " PRIu32 ,
dev_name ( first - > dev ) , first - > vgd . vg_uuid ,
first - > vgd . vg_name_dummy ,
first - > vgd . vg_number , first - > vgd . vg_access ,
first - > vgd . vg_status , first - > vgd . lv_max ,
first - > vgd . lv_cur , first - > vgd . lv_open ,
first - > vgd . pv_max , first - > vgd . pv_cur ,
first - > vgd . pv_act , first - > vgd . dummy ,
first - > vgd . vgda , first - > vgd . pe_size ,
first - > vgd . pe_total , first - > vgd . pe_allocated ,
first - > vgd . pvg_total ) ;
log_debug_metadata ( " VG data on %s: %s %s % " PRIu32 " % " PRIu32
" % " PRIu32 " % " PRIu32 " % " PRIu32 " % "
PRIu32 " % " PRIu32 " % " PRIu32 " % " PRIu32
" % " PRIu32 " % " PRIu32 " % " PRIu32 " % "
PRIu32 " % " PRIu32 " % " PRIu32 ,
dev_name ( dl - > dev ) , dl - > vgd . vg_uuid ,
dl - > vgd . vg_name_dummy , dl - > vgd . vg_number ,
dl - > vgd . vg_access , dl - > vgd . vg_status ,
dl - > vgd . lv_max , dl - > vgd . lv_cur ,
dl - > vgd . lv_open , dl - > vgd . pv_max ,
dl - > vgd . pv_cur , dl - > vgd . pv_act , dl - > vgd . dummy ,
dl - > vgd . vgda , dl - > vgd . pe_size ,
dl - > vgd . pe_total , dl - > vgd . pe_allocated ,
dl - > vgd . pvg_total ) ;
2008-11-04 01:14:30 +03:00
dm_list_del ( pvh ) ;
2001-10-04 21:48:55 +04:00
return 0 ;
}
2001-10-16 20:25:28 +04:00
pv_count + + ;
}
/* On entry to fn, list known to be non-empty */
2003-08-20 19:48:27 +04:00
if ( pv_count ! = first - > vgd . pv_cur ) {
2002-01-29 20:23:33 +03:00
log_error ( " %d PV(s) found for VG %s: expected %d " ,
2003-08-20 19:48:27 +04:00
pv_count , first - > pvd . vg_name , first - > vgd . pv_cur ) ;
2010-09-22 17:45:21 +04:00
vg - > status | = PARTIAL_VG ;
2001-10-04 21:48:55 +04:00
}
return 1 ;
}
2010-09-22 17:45:21 +04:00
static int _fix_partial_vg ( struct volume_group * vg , struct dm_list * pvs )
{
uint32_t extent_count = 0 ;
struct disk_list * dl ;
struct dm_list * pvh ;
struct pv_list * pvl ;
2010-10-04 22:59:01 +04:00
struct lv_list * ll ;
struct lv_segment * seg ;
/*
* FIXME : code should remap missing segments to error segment .
* Also current mapping code allocates 1 segment per missing extent .
* For now bail out completely - allocated structures are not complete
*/
dm_list_iterate_items ( ll , & vg - > lvs )
dm_list_iterate_items ( seg , & ll - > lv - > segments ) {
/* area_count is always 1 here, s == 0 */
if ( seg_type ( seg , 0 ) ! = AREA_PV )
continue ;
if ( seg_pv ( seg , 0 ) )
continue ;
log_error ( " Partial mode support for missing lvm1 PVs and "
" partially available LVs is currently not implemented. " ) ;
return 0 ;
}
2010-09-22 17:45:21 +04:00
dm_list_iterate ( pvh , pvs ) {
dl = dm_list_item ( pvh , struct disk_list ) ;
extent_count + = dl - > pvd . pe_total ;
}
/* FIXME: move this to one place to pv_manip */
if ( ! ( pvl = dm_pool_zalloc ( vg - > vgmem , sizeof ( * pvl ) ) ) | |
! ( pvl - > pv = dm_pool_zalloc ( vg - > vgmem , sizeof ( * pvl - > pv ) ) ) )
return_0 ;
2010-10-04 22:59:01 +04:00
/* Use vg uuid with replaced first chars to "missing" as missing PV UUID */
memcpy ( & pvl - > pv - > id . uuid , vg - > id . uuid , sizeof ( pvl - > pv - > id . uuid ) ) ;
memcpy ( & pvl - > pv - > id . uuid , " missing " , 7 ) ;
2010-09-22 17:45:21 +04:00
if ( ! ( pvl - > pv - > vg_name = dm_pool_strdup ( vg - > vgmem , vg - > name ) ) )
goto_out ;
memcpy ( & pvl - > pv - > vgid , & vg - > id , sizeof ( vg - > id ) ) ;
pvl - > pv - > status | = MISSING_PV ;
dm_list_init ( & pvl - > pv - > tags ) ;
dm_list_init ( & pvl - > pv - > segments ) ;
pvl - > pv - > pe_size = vg - > extent_size ;
pvl - > pv - > pe_count = vg - > extent_count - extent_count ;
if ( ! alloc_pv_segment_whole_pv ( vg - > vgmem , pvl - > pv ) )
goto_out ;
add_pvl_to_vgs ( vg , pvl ) ;
2013-01-08 02:30:29 +04:00
log_debug_metadata ( " %s: partial VG, allocated missing PV using %d extents. " ,
vg - > name , pvl - > pv - > pe_count ) ;
2010-09-22 17:45:21 +04:00
return 1 ;
out :
dm_pool_free ( vg - > vgmem , pvl ) ;
return 0 ;
}
2011-03-10 15:43:29 +03:00
static struct volume_group * _format1_vg_read ( struct format_instance * fid ,
const char * vg_name ,
2012-02-29 06:35:35 +04:00
struct metadata_area * mda __attribute__ ( ( unused ) ) ,
int single_device __attribute__ ( ( unused ) ) )
2001-10-04 21:48:55 +04:00
{
2011-03-10 15:43:29 +03:00
struct volume_group * vg ;
2001-10-09 21:09:46 +04:00
struct disk_list * dl ;
2011-03-10 15:43:29 +03:00
DM_LIST_INIT ( pvs ) ;
/* Strip dev_dir if present */
2012-02-27 15:23:15 +04:00
if ( vg_name )
vg_name = strip_dir ( vg_name , fid - > fmt - > cmd - > dev_dir ) ;
2011-03-10 15:43:29 +03:00
if ( ! ( vg = alloc_vg ( " format1_vg_read " , fid - > fmt - > cmd , NULL ) ) )
return_NULL ;
2001-10-09 21:09:46 +04:00
2011-03-10 15:43:29 +03:00
if ( ! read_pvs_in_vg ( fid - > fmt , vg_name , fid - > fmt - > cmd - > filter ,
vg - > vgmem , & pvs ) )
2007-04-26 20:44:59 +04:00
goto_bad ;
2001-10-04 21:48:55 +04:00
2011-03-10 15:43:29 +03:00
if ( dm_list_empty ( & pvs ) )
2007-04-26 20:44:59 +04:00
goto_bad ;
2001-10-09 21:09:46 +04:00
2011-03-10 15:43:29 +03:00
if ( ! _check_vgs ( & pvs , vg ) )
2007-04-26 20:44:59 +04:00
goto_bad ;
2001-10-09 18:26:45 +04:00
2011-03-10 15:43:29 +03:00
dl = dm_list_item ( pvs . n , struct disk_list ) ;
2002-01-29 20:23:33 +03:00
2011-03-10 15:43:29 +03:00
if ( ! import_vg ( vg - > vgmem , vg , dl ) )
2007-04-26 20:44:59 +04:00
goto_bad ;
2001-10-04 21:48:55 +04:00
2011-03-10 15:43:29 +03:00
if ( ! import_pvs ( fid - > fmt , vg - > vgmem , vg , & pvs ) )
2007-04-26 20:44:59 +04:00
goto_bad ;
2001-10-04 21:48:55 +04:00
2011-03-10 15:43:29 +03:00
if ( ! import_lvs ( vg - > vgmem , vg , & pvs ) )
2007-04-26 20:44:59 +04:00
goto_bad ;
2001-10-04 21:48:55 +04:00
2011-03-10 15:43:29 +03:00
if ( ! import_extents ( fid - > fmt - > cmd , vg , & pvs ) )
2007-04-26 20:44:59 +04:00
goto_bad ;
2001-10-08 13:45:16 +04:00
2013-04-22 01:53:53 +04:00
/* FIXME: workaround - temporary assignment of fid */
vg - > fid = fid ;
if ( ! import_snapshots ( vg - > vgmem , vg , & pvs ) ) {
vg - > fid = NULL ;
2007-04-26 20:44:59 +04:00
goto_bad ;
2013-04-22 01:53:53 +04:00
}
vg - > fid = NULL ;
2002-02-13 14:43:29 +03:00
2010-09-22 17:45:21 +04:00
/* Fix extents counts by adding missing PV if partial VG */
2011-03-10 15:43:29 +03:00
if ( ( vg - > status & PARTIAL_VG ) & & ! _fix_partial_vg ( vg , & pvs ) )
2010-09-22 17:45:21 +04:00
goto_bad ;
2013-04-21 23:36:08 +04:00
vg_set_fid ( vg , fid ) ;
2001-10-04 21:48:55 +04:00
return vg ;
2009-04-10 13:59:18 +04:00
bad :
2012-02-13 14:53:31 +04:00
release_vg ( vg ) ;
2011-03-10 15:43:29 +03:00
2009-04-10 13:59:18 +04:00
return NULL ;
2001-10-04 21:48:55 +04:00
}
2004-03-08 20:25:59 +03:00
static struct disk_list * _flatten_pv ( struct format_instance * fid ,
2005-10-17 03:03:59 +04:00
struct dm_pool * mem , struct volume_group * vg ,
2001-10-09 18:26:45 +04:00
struct physical_volume * pv ,
2001-11-14 16:52:38 +03:00
const char * dev_dir )
2001-10-05 20:36:53 +04:00
{
2005-10-17 03:03:59 +04:00
struct disk_list * dl = dm_pool_alloc ( mem , sizeof ( * dl ) ) ;
2001-10-08 16:11:33 +04:00
2008-01-30 16:19:47 +03:00
if ( ! dl )
return_NULL ;
2001-10-09 14:47:52 +04:00
dl - > mem = mem ;
dl - > dev = pv - > dev ;
2008-11-04 01:14:30 +03:00
dm_list_init ( & dl - > uuids ) ;
dm_list_init ( & dl - > lvds ) ;
2001-10-09 14:47:52 +04:00
2004-03-08 20:25:59 +03:00
if ( ! export_pv ( fid - > fmt - > cmd , mem , vg , & dl - > pvd , pv ) | |
2001-10-31 20:59:52 +03:00
! export_vg ( & dl - > vgd , vg ) | |
2001-10-09 18:26:45 +04:00
! export_uuids ( dl , vg ) | |
2002-11-18 17:01:16 +03:00
! export_lvs ( dl , vg , pv , dev_dir ) | | ! calculate_layout ( dl ) ) {
2005-10-17 03:03:59 +04:00
dm_pool_free ( mem , dl ) ;
2008-01-30 16:19:47 +03:00
return_NULL ;
2001-10-09 14:47:52 +04:00
}
return dl ;
2001-10-05 20:36:53 +04:00
}
2005-10-17 03:03:59 +04:00
static int _flatten_vg ( struct format_instance * fid , struct dm_pool * mem ,
2002-04-24 22:20:51 +04:00
struct volume_group * vg ,
2008-11-04 01:14:30 +03:00
struct dm_list * pvds , const char * dev_dir ,
2001-10-11 18:10:18 +04:00
struct dev_filter * filter )
2001-10-05 20:36:53 +04:00
{
2001-10-09 14:47:52 +04:00
struct pv_list * pvl ;
2001-10-05 20:36:53 +04:00
struct disk_list * data ;
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( pvl , & vg - > pvs ) {
2008-01-30 16:19:47 +03:00
if ( ! ( data = _flatten_pv ( fid , mem , vg , pvl - > pv , dev_dir ) ) )
return_0 ;
2001-10-05 20:36:53 +04:00
2008-11-04 01:14:30 +03:00
dm_list_add ( pvds , & data - > list ) ;
2001-10-05 20:36:53 +04:00
}
2001-10-11 14:55:19 +04:00
2001-11-14 16:52:38 +03:00
export_numbers ( pvds , vg ) ;
export_pv_act ( pvds ) ;
2001-10-11 17:05:55 +04:00
2008-01-30 16:19:47 +03:00
if ( ! export_vg_number ( fid , pvds , vg - > name , filter ) )
return_0 ;
2001-10-11 18:10:18 +04:00
2001-10-05 20:36:53 +04:00
return 1 ;
}
2006-04-19 19:33:07 +04:00
static int _format1_vg_write ( struct format_instance * fid , struct volume_group * vg ,
2010-07-09 19:34:40 +04:00
struct metadata_area * mda __attribute__ ( ( unused ) ) )
2001-10-05 20:36:53 +04:00
{
2009-04-10 13:59:18 +04:00
struct dm_pool * mem = dm_pool_create ( " lvm1 vg_write " , VG_MEMPOOL_CHUNK ) ;
2008-11-04 01:14:30 +03:00
struct dm_list pvds ;
2001-10-05 20:36:53 +04:00
int r = 0 ;
2008-01-30 16:19:47 +03:00
if ( ! mem )
return_0 ;
2001-10-05 20:36:53 +04:00
2008-11-04 01:14:30 +03:00
dm_list_init ( & pvds ) ;
2001-10-10 17:09:40 +04:00
2002-04-24 22:20:51 +04:00
r = ( _flatten_vg ( fid , mem , vg , & pvds , fid - > fmt - > cmd - > dev_dir ,
fid - > fmt - > cmd - > filter ) & &
2013-03-25 17:30:40 +04:00
write_disks ( fid - > fmt , & pvds , 1 ) ) ;
2002-11-18 17:01:16 +03:00
2008-03-17 19:51:31 +03:00
lvmcache_update_vg ( vg , 0 ) ;
2005-10-17 03:03:59 +04:00
dm_pool_destroy ( mem ) ;
2001-10-05 20:36:53 +04:00
return r ;
}
2001-10-04 21:48:55 +04:00
2006-04-19 19:33:07 +04:00
static int _format1_pv_read ( const struct format_type * fmt , const char * pv_name ,
2011-02-21 15:15:59 +03:00
struct physical_volume * pv , int scan_label_only __attribute__ ( ( unused ) ) )
2001-10-09 12:58:52 +04:00
{
2005-10-17 03:03:59 +04:00
struct dm_pool * mem = dm_pool_create ( " lvm1 pv_read " , 1024 ) ;
2001-10-09 12:58:52 +04:00
struct disk_list * dl ;
2001-10-09 20:05:34 +04:00
struct device * dev ;
2002-04-24 22:20:51 +04:00
int r = 0 ;
2001-10-09 12:58:52 +04:00
2002-11-18 17:01:16 +03:00
log_very_verbose ( " Reading physical volume data %s from disk " , pv_name ) ;
2001-10-17 19:29:31 +04:00
2008-01-30 16:19:47 +03:00
if ( ! mem )
return_0 ;
2001-10-09 12:58:52 +04:00
2008-01-30 16:19:47 +03:00
if ( ! ( dev = dev_cache_get ( pv_name , fmt - > cmd - > filter ) ) )
goto_out ;
2001-10-09 20:05:34 +04:00
2008-01-30 16:19:47 +03:00
if ( ! ( dl = read_disk ( fmt , dev , mem , NULL ) ) )
goto_out ;
2001-10-09 12:58:52 +04:00
2008-01-30 16:19:47 +03:00
if ( ! import_pv ( fmt , fmt - > cmd - > mem , dl - > dev , NULL , pv , & dl - > pvd , & dl - > vgd ) )
goto_out ;
2001-10-09 12:58:52 +04:00
2002-11-18 17:01:16 +03:00
pv - > fmt = fmt ;
2002-04-24 22:20:51 +04:00
r = 1 ;
2001-10-09 12:58:52 +04:00
2002-04-24 22:20:51 +04:00
out :
2005-10-17 03:03:59 +04:00
dm_pool_destroy ( mem ) ;
2002-04-24 22:20:51 +04:00
return r ;
2001-10-09 12:58:52 +04:00
}
2011-02-21 15:20:18 +03:00
static int _format1_pv_initialise ( const struct format_type * fmt ,
int64_t label_sector __attribute__ ( ( unused ) ) ,
unsigned long data_alignment __attribute__ ( ( unused ) ) ,
unsigned long data_alignment_offset __attribute__ ( ( unused ) ) ,
2013-02-18 15:47:31 +04:00
struct pvcreate_restorable_params * rp ,
2011-02-21 15:20:18 +03:00
struct physical_volume * pv )
2001-10-08 21:53:43 +04:00
{
2002-02-20 21:29:30 +03:00
if ( pv - > size > MAX_PV_SIZE )
pv - > size - - ;
2002-02-15 04:26:16 +03:00
if ( pv - > size > MAX_PV_SIZE ) {
2002-11-18 17:01:16 +03:00
log_error ( " Physical volumes cannot be bigger than %s " ,
2006-05-10 01:23:51 +04:00
display_size ( fmt - > cmd , ( uint64_t ) MAX_PV_SIZE ) ) ;
2002-02-15 04:26:16 +03:00
return 0 ;
}
2002-11-18 17:01:16 +03:00
/* Nothing more to do if extent size isn't provided */
2013-02-18 15:47:31 +04:00
if ( ! rp - > extent_size )
2002-02-20 21:29:30 +03:00
return 1 ;
2002-02-15 17:33:59 +03:00
2001-10-10 14:55:55 +04:00
/*
* This works out pe_start and pe_count .
*/
2013-02-18 15:47:31 +04:00
if ( ! calculate_extent_count ( pv , rp - > extent_size , rp - > extent_count , rp - > pe_start ) )
2008-01-30 16:19:47 +03:00
return_0 ;
2001-10-10 14:55:55 +04:00
2002-11-18 17:01:16 +03:00
/* Retain existing extent locations exactly */
2013-02-18 15:47:31 +04:00
if ( ( ( rp - > pe_start | | rp - > extent_count ) & & ( rp - > pe_start ! = pv - > pe_start ) ) | |
( rp - > extent_count & & ( rp - > extent_count ! = pv - > pe_count ) ) ) {
2002-11-18 17:01:16 +03:00
log_error ( " Metadata would overwrite physical extents " ) ;
return 0 ;
}
2001-10-10 13:25:04 +04:00
return 1 ;
}
2011-02-21 15:20:18 +03:00
static int _format1_pv_setup ( const struct format_type * fmt ,
struct physical_volume * pv ,
2011-02-25 17:12:14 +03:00
struct volume_group * vg )
2011-02-21 15:20:18 +03:00
{
2013-02-18 15:47:31 +04:00
struct pvcreate_restorable_params rp = { . restorefile = NULL ,
. id = { { 0 } } ,
. idp = NULL ,
2013-05-28 14:37:22 +04:00
. ba_start = 0 ,
. ba_size = 0 ,
2013-02-18 15:47:31 +04:00
. pe_start = 0 ,
. extent_count = 0 ,
. extent_size = vg - > extent_size } ;
return _format1_pv_initialise ( fmt , - 1 , 0 , 0 , & rp , pv ) ;
2011-02-21 15:20:18 +03:00
}
2006-04-19 19:33:07 +04:00
static int _format1_lv_setup ( struct format_instance * fid , struct logical_volume * lv )
2002-01-24 20:16:36 +03:00
{
2002-02-14 00:28:56 +03:00
uint64_t max_size = UINT_MAX ;
2002-04-05 18:32:22 +04:00
if ( ! * lv - > lvid . s )
2003-11-06 19:58:38 +03:00
lvid_from_lvnum ( & lv - > lvid , & lv - > vg - > id , find_free_lvnum ( lv ) ) ;
2002-02-21 22:04:37 +03:00
2002-01-24 22:20:35 +03:00
if ( lv - > le_count > MAX_LE_TOTAL ) {
2002-01-28 00:30:47 +03:00
log_error ( " logical volumes cannot contain more than "
" %d extents. " , MAX_LE_TOTAL ) ;
2002-01-24 20:16:36 +03:00
return 0 ;
}
2002-02-14 00:28:56 +03:00
if ( lv - > size > max_size ) {
2002-12-12 23:55:49 +03:00
log_error ( " logical volumes cannot be larger than %s " ,
2006-05-10 01:23:51 +04:00
display_size ( fid - > fmt - > cmd , max_size ) ) ;
2002-02-14 00:28:56 +03:00
return 0 ;
}
2002-01-24 20:16:36 +03:00
return 1 ;
}
2011-02-21 15:26:27 +03:00
static int _format1_pv_write ( const struct format_type * fmt , struct physical_volume * pv )
2001-10-09 21:44:58 +04:00
{
2005-10-17 03:03:59 +04:00
struct dm_pool * mem ;
2001-10-10 14:05:29 +04:00
struct disk_list * dl ;
2008-11-04 01:14:30 +03:00
struct dm_list pvs ;
2003-07-05 02:34:56 +04:00
struct lvmcache_info * info ;
2011-06-01 23:29:31 +04:00
int pe_count , pe_size , pe_start ;
int r = 1 ;
2001-10-10 14:05:29 +04:00
2003-07-05 02:34:56 +04:00
if ( ! ( info = lvmcache_add ( fmt - > labeller , ( char * ) & pv - > id , pv - > dev ,
2008-01-30 16:19:47 +03:00
pv - > vg_name , NULL , 0 ) ) )
return_0 ;
2010-12-20 17:06:33 +03:00
2012-02-10 05:28:27 +04:00
lvmcache_update_pv ( info , pv , fmt ) ;
lvmcache_del_mdas ( info ) ;
2012-02-23 17:11:07 +04:00
lvmcache_del_das ( info ) ;
2013-05-28 14:37:22 +04:00
lvmcache_del_bas ( info ) ;
2002-11-18 17:01:16 +03:00
2008-11-04 01:14:30 +03:00
dm_list_init ( & pvs ) ;
2001-10-10 14:05:29 +04:00
2011-06-01 23:29:31 +04:00
pe_count = pv - > pe_count ;
pe_size = pv - > pe_size ;
pe_start = pv - > pe_start ;
2001-10-18 20:55:19 +04:00
/* Ensure any residual PE structure is gone */
2002-04-24 22:20:51 +04:00
pv - > pe_size = pv - > pe_count = 0 ;
2006-08-17 23:15:27 +04:00
pv - > pe_start = LVM1_PE_ALIGN ;
2001-10-18 20:55:19 +04:00
2008-01-30 16:19:47 +03:00
if ( ! ( mem = dm_pool_create ( " lvm1 pv_write " , 1024 ) ) )
return_0 ;
2001-10-10 14:05:29 +04:00
2007-04-26 20:44:59 +04:00
if ( ! ( dl = dm_pool_alloc ( mem , sizeof ( * dl ) ) ) )
goto_bad ;
2001-10-10 14:05:29 +04:00
dl - > mem = mem ;
dl - > dev = pv - > dev ;
2011-06-01 23:29:31 +04:00
dm_list_init ( & dl - > uuids ) ;
dm_list_init ( & dl - > lvds ) ;
2001-10-10 14:05:29 +04:00
2007-04-26 20:44:59 +04:00
if ( ! export_pv ( fmt - > cmd , mem , NULL , & dl - > pvd , pv ) )
goto_bad ;
2001-10-10 14:05:29 +04:00
2002-01-29 18:52:11 +03:00
/* must be set to be able to zero gap after PV structure in
dev_write in order to make other disk tools happy */
dl - > pvd . pv_on_disk . base = METADATA_BASE ;
dl - > pvd . pv_on_disk . size = PV_SIZE ;
2006-08-17 23:15:27 +04:00
dl - > pvd . pe_on_disk . base = LVM1_PE_ALIGN < < SECTOR_SHIFT ;
2002-01-29 18:52:11 +03:00
2008-11-04 01:14:30 +03:00
dm_list_add ( & pvs , & dl - > list ) ;
2013-03-25 17:30:40 +04:00
if ( ! write_disks ( fmt , & pvs , 0 ) )
2007-04-26 20:44:59 +04:00
goto_bad ;
2001-10-10 14:05:29 +04:00
2011-06-01 23:29:31 +04:00
goto out ;
2001-10-10 14:05:29 +04:00
2002-04-24 22:20:51 +04:00
bad :
2011-06-01 23:29:31 +04:00
r = 0 ;
out :
pv - > pe_size = pe_size ;
pv - > pe_count = pe_count ;
pv - > pe_start = pe_start ;
2005-10-17 03:03:59 +04:00
dm_pool_destroy ( mem ) ;
2011-06-01 23:29:31 +04:00
return r ;
2001-10-09 21:44:58 +04:00
}
2006-04-19 19:33:07 +04:00
static int _format1_vg_setup ( struct format_instance * fid , struct volume_group * vg )
2001-10-12 18:25:53 +04:00
{
/* just check max_pv and max_lv */
2003-11-06 23:33:34 +03:00
if ( ! vg - > max_lv | | vg - > max_lv > = MAX_LV )
2001-10-15 22:39:40 +04:00
vg - > max_lv = MAX_LV - 1 ;
2001-10-12 18:25:53 +04:00
2003-11-06 23:33:34 +03:00
if ( ! vg - > max_pv | | vg - > max_pv > = MAX_PV )
2001-10-15 22:39:40 +04:00
vg - > max_pv = MAX_PV - 1 ;
2001-10-12 18:25:53 +04:00
2001-10-16 00:29:15 +04:00
if ( vg - > extent_size > MAX_PE_SIZE | | vg - > extent_size < MIN_PE_SIZE ) {
log_error ( " Extent size must be between %s and %s " ,
2006-05-10 01:23:51 +04:00
display_size ( fid - > fmt - > cmd , ( uint64_t ) MIN_PE_SIZE ) ,
display_size ( fid - > fmt - > cmd , ( uint64_t ) MAX_PE_SIZE ) ) ;
2001-10-16 00:29:15 +04:00
return 0 ;
}
if ( vg - > extent_size % MIN_PE_SIZE ) {
log_error ( " Extent size must be multiple of %s " ,
2006-05-10 01:23:51 +04:00
display_size ( fid - > fmt - > cmd , ( uint64_t ) MIN_PE_SIZE ) ) ;
2001-10-16 00:29:15 +04:00
return 0 ;
}
/* Redundant? */
if ( vg - > extent_size & ( vg - > extent_size - 1 ) ) {
log_error ( " Extent size must be power of 2 " ) ;
return 0 ;
}
2001-10-12 18:25:53 +04:00
return 1 ;
}
2001-10-09 21:44:58 +04:00
2010-07-09 19:34:40 +04:00
static int _format1_segtype_supported ( struct format_instance * fid __attribute__ ( ( unused ) ) ,
2006-05-10 01:23:51 +04:00
const struct segment_type * segtype )
2004-09-14 17:56:18 +04:00
{
2008-01-30 16:19:47 +03:00
if ( ! ( segtype - > flags & SEG_FORMAT1_SUPPORT ) )
return_0 ;
2004-09-14 17:56:18 +04:00
return 1 ;
}
2002-11-18 17:01:16 +03:00
static struct metadata_area_ops _metadata_format1_ops = {
2006-05-10 01:23:51 +04:00
. vg_read = _format1_vg_read ,
. vg_write = _format1_vg_write ,
2002-11-18 17:01:16 +03:00
} ;
2006-04-19 19:33:07 +04:00
static struct format_instance * _format1_create_instance ( const struct format_type * fmt ,
2011-02-21 15:05:49 +03:00
const struct format_instance_ctx * fic )
2002-04-24 22:20:51 +04:00
{
struct format_instance * fid ;
struct metadata_area * mda ;
2011-03-11 17:30:27 +03:00
if ( ! ( fid = alloc_fid ( fmt , fic ) ) )
2008-01-30 16:19:47 +03:00
return_NULL ;
2002-04-24 22:20:51 +04:00
/* Define a NULL metadata area */
2011-03-11 18:10:16 +03:00
if ( ! ( mda = dm_pool_zalloc ( fid - > mem , sizeof ( * mda ) ) ) ) {
2011-03-11 17:38:38 +03:00
log_error ( " Unable to allocate metadata area structure "
" for lvm1 format " ) ;
goto bad ;
2002-04-24 22:20:51 +04:00
}
2002-11-18 17:01:16 +03:00
mda - > ops = & _metadata_format1_ops ;
2002-04-24 22:20:51 +04:00
mda - > metadata_locn = NULL ;
2010-10-05 21:34:05 +04:00
mda - > status = 0 ;
2010-06-29 00:32:44 +04:00
dm_list_add ( & fid - > metadata_areas_in_use , & mda - > list ) ;
2002-04-24 22:20:51 +04:00
return fid ;
2011-03-11 17:38:38 +03:00
bad :
dm_pool_destroy ( fid - > mem ) ;
return NULL ;
2002-04-24 22:20:51 +04:00
}
2011-03-11 17:38:38 +03:00
static void _format1_destroy_instance ( struct format_instance * fid )
2001-10-04 21:48:55 +04:00
{
2011-03-11 17:38:38 +03:00
if ( - - fid - > ref_count < = 1 )
dm_pool_destroy ( fid - > mem ) ;
2001-10-08 16:11:33 +04:00
}
2010-12-20 16:32:49 +03:00
static void _format1_destroy ( struct format_type * fmt )
2002-04-24 22:20:51 +04:00
{
2012-02-13 15:03:59 +04:00
if ( fmt - > orphan_vg )
free_orphan_vg ( fmt - > orphan_vg ) ;
2012-02-10 06:53:03 +04:00
2010-12-20 16:32:49 +03:00
dm_free ( fmt ) ;
2002-04-24 22:20:51 +04:00
}
2001-10-08 16:11:33 +04:00
2001-11-12 15:16:57 +03:00
static struct format_handler _format1_ops = {
2006-05-10 01:23:51 +04:00
. pv_read = _format1_pv_read ,
2011-02-21 15:20:18 +03:00
. pv_initialise = _format1_pv_initialise ,
2006-05-10 01:23:51 +04:00
. pv_setup = _format1_pv_setup ,
. pv_write = _format1_pv_write ,
. lv_setup = _format1_lv_setup ,
. vg_setup = _format1_vg_setup ,
. segtype_supported = _format1_segtype_supported ,
. create_instance = _format1_create_instance ,
. destroy_instance = _format1_destroy_instance ,
. destroy = _format1_destroy ,
2001-11-12 15:16:57 +03:00
} ;
2001-10-30 20:53:21 +03:00
2002-11-18 17:01:16 +03:00
# ifdef LVM1_INTERNAL
struct format_type * init_lvm1_format ( struct cmd_context * cmd )
# else /* Shared */
2003-04-15 17:24:42 +04:00
struct format_type * init_format ( struct cmd_context * cmd ) ;
2002-11-18 17:01:16 +03:00
struct format_type * init_format ( struct cmd_context * cmd )
# endif
2001-11-12 15:16:57 +03:00
{
2005-10-17 03:03:59 +04:00
struct format_type * fmt = dm_malloc ( sizeof ( * fmt ) ) ;
2012-02-10 06:53:03 +04:00
struct format_instance_ctx fic ;
struct format_instance * fid ;
2001-10-08 16:11:33 +04:00
2012-02-13 14:56:31 +04:00
if ( ! fmt ) {
log_error ( " Failed to allocate format1 format type structure. " ) ;
return NULL ;
}
2001-10-08 16:11:33 +04:00
2002-04-24 22:20:51 +04:00
fmt - > cmd = cmd ;
fmt - > ops = & _format1_ops ;
fmt - > name = FMT_LVM1_NAME ;
2002-11-18 17:01:16 +03:00
fmt - > alias = NULL ;
2008-02-06 18:47:28 +03:00
fmt - > orphan_vg_name = FMT_LVM1_ORPHAN_VG_NAME ;
2007-11-09 19:51:54 +03:00
fmt - > features = FMT_RESTRICTED_LVIDS | FMT_ORPHAN_ALLOCATABLE |
2014-01-14 07:27:45 +04:00
FMT_RESTRICTED_READAHEAD | FMT_OBSOLETE ;
2002-04-24 22:20:51 +04:00
fmt - > private = NULL ;
2001-10-08 16:11:33 +04:00
2012-02-23 17:11:07 +04:00
dm_list_init ( & fmt - > mda_ops ) ;
2002-11-18 17:01:16 +03:00
if ( ! ( fmt - > labeller = lvm1_labeller_create ( fmt ) ) ) {
log_error ( " Couldn't create lvm1 label handler. " ) ;
2012-02-08 14:49:36 +04:00
dm_free ( fmt ) ;
2002-11-18 17:01:16 +03:00
return NULL ;
}
2013-07-29 17:58:18 +04:00
if ( ! ( label_register_handler ( fmt - > labeller ) ) ) {
2002-11-18 17:01:16 +03:00
log_error ( " Couldn't register lvm1 label handler. " ) ;
2012-02-08 14:49:36 +04:00
fmt - > labeller - > ops - > destroy ( fmt - > labeller ) ;
dm_free ( fmt ) ;
2002-11-18 17:01:16 +03:00
return NULL ;
}
2012-02-15 05:44:58 +04:00
if ( ! ( fmt - > orphan_vg = alloc_vg ( " format1_orphan " , cmd , fmt - > orphan_vg_name ) ) ) {
2012-02-10 06:53:03 +04:00
log_error ( " Couldn't create lvm1 orphan VG. " ) ;
2012-02-13 14:56:31 +04:00
dm_free ( fmt ) ;
2012-02-10 06:53:03 +04:00
return NULL ;
}
2012-02-13 14:56:31 +04:00
2012-02-13 03:01:19 +04:00
fic . type = FMT_INSTANCE_AUX_MDAS ;
2012-02-10 06:53:03 +04:00
fic . context . vg_ref . vg_name = fmt - > orphan_vg_name ;
fic . context . vg_ref . vg_id = NULL ;
2012-02-13 14:56:31 +04:00
2012-02-10 06:53:03 +04:00
if ( ! ( fid = _format1_create_instance ( fmt , & fic ) ) ) {
2012-02-13 14:56:31 +04:00
_format1_destroy ( fmt ) ;
return_NULL ;
2012-02-10 06:53:03 +04:00
}
2012-02-13 14:56:31 +04:00
2012-02-10 06:53:03 +04:00
vg_set_fid ( fmt - > orphan_vg , fid ) ;
2004-09-14 21:37:51 +04:00
log_very_verbose ( " Initialised format: %s " , fmt - > name ) ;
2002-04-24 22:20:51 +04:00
return fmt ;
2001-10-04 21:48:55 +04:00
}