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 .
2007-08-21 00:55:30 +04:00
* Copyright ( C ) 2004 - 2007 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"
2001-10-04 21:48:55 +04:00
2001-10-16 20:25:28 +04:00
/* VG consistency checks */
2008-11-04 01:14:30 +03:00
static int _check_vgs ( struct dm_list * pvs )
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 ) ) ;
2004-01-02 17:04:44 +03:00
log_debug ( " 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 ( " 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 ) ;
2001-10-04 21:48:55 +04:00
}
return 1 ;
}
2002-04-24 22:20:51 +04:00
static struct volume_group * _build_vg ( struct format_instance * fid ,
2008-11-04 01:14:30 +03:00
struct dm_list * pvs )
2001-10-04 21:48:55 +04:00
{
2005-10-17 03:03:59 +04:00
struct dm_pool * mem = fid - > fmt - > cmd - > mem ;
struct volume_group * vg = dm_pool_alloc ( mem , sizeof ( * vg ) ) ;
2001-10-09 21:09:46 +04:00
struct disk_list * dl ;
2001-10-15 22:39:40 +04:00
if ( ! vg )
2007-04-26 20:44:59 +04:00
goto_bad ;
2001-10-04 21:48:55 +04:00
2008-11-04 01:14:30 +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
2001-10-04 21:48:55 +04:00
memset ( vg , 0 , sizeof ( * vg ) ) ;
2002-04-24 22:20:51 +04:00
vg - > cmd = fid - > fmt - > cmd ;
vg - > fid = fid ;
vg - > seqno = 0 ;
2008-11-04 01:14:30 +03:00
dm_list_init ( & vg - > pvs ) ;
dm_list_init ( & vg - > lvs ) ;
dm_list_init ( & vg - > tags ) ;
2001-10-08 20:08:16 +04:00
2008-09-19 10:42:00 +04:00
if ( ! _check_vgs ( pvs ) )
2007-04-26 20:44:59 +04:00
goto_bad ;
2001-10-09 18:26:45 +04:00
2008-11-04 01:14:30 +03:00
dl = dm_list_item ( pvs - > n , struct disk_list ) ;
2002-01-29 20:23:33 +03:00
2008-09-19 10:42:00 +04:00
if ( ! import_vg ( mem , vg , dl ) )
2007-04-26 20:44:59 +04:00
goto_bad ;
2001-10-04 21:48:55 +04:00
2002-11-18 17:01:16 +03:00
if ( ! import_pvs ( fid - > fmt , mem , vg , pvs , & vg - > pvs , & vg - > pv_count ) )
2007-04-26 20:44:59 +04:00
goto_bad ;
2001-10-04 21:48:55 +04:00
2001-10-09 18:26:45 +04:00
if ( ! import_lvs ( mem , vg , pvs ) )
2007-04-26 20:44:59 +04:00
goto_bad ;
2001-10-04 21:48:55 +04:00
2004-05-05 01:25:57 +04: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
2002-02-13 14:43:29 +03:00
if ( ! import_snapshots ( mem , vg , pvs ) )
2007-04-26 20:44:59 +04:00
goto_bad ;
2002-02-13 14:43:29 +03:00
2001-10-04 21:48:55 +04:00
return vg ;
2002-04-24 22:20:51 +04:00
bad :
2005-10-17 03:03:59 +04:00
dm_pool_free ( mem , vg ) ;
2001-10-04 21:48:55 +04:00
return NULL ;
}
2006-04-19 19:33:07 +04:00
static struct volume_group * _format1_vg_read ( struct format_instance * fid ,
2002-11-18 17:01:16 +03:00
const char * vg_name ,
2007-08-22 18:38:18 +04:00
struct metadata_area * mda __attribute ( ( unused ) ) )
2001-10-04 21:48:55 +04:00
{
2005-10-17 03:03:59 +04:00
struct dm_pool * mem = dm_pool_create ( " lvm1 vg_read " , 1024 * 10 ) ;
2008-11-04 01:14:30 +03:00
struct dm_list pvs ;
2001-11-12 18:10:01 +03:00
struct volume_group * vg = NULL ;
2008-11-04 01:14:30 +03:00
dm_list_init ( & pvs ) ;
2001-10-04 21:48:55 +04:00
2008-01-30 16:19:47 +03:00
if ( ! mem )
return_NULL ;
2001-10-04 21:48:55 +04:00
2002-04-24 22:20:51 +04:00
/* Strip dev_dir if present */
vg_name = strip_dir ( vg_name , fid - > fmt - > cmd - > dev_dir ) ;
2001-10-12 01:35:55 +04:00
2002-04-24 22:20:51 +04:00
if ( ! read_pvs_in_vg
2007-04-26 20:44:59 +04:00
( fid - > fmt , vg_name , fid - > fmt - > cmd - > filter , mem , & pvs ) )
goto_bad ;
2001-10-04 21:48:55 +04:00
2007-04-26 20:44:59 +04:00
if ( ! ( vg = _build_vg ( fid , & pvs ) ) )
goto_bad ;
2001-11-12 18:10:01 +03:00
2002-04-24 22:20:51 +04:00
bad :
2005-10-17 03:03:59 +04:00
dm_pool_destroy ( mem ) ;
2001-10-04 21:48:55 +04:00
return vg ;
}
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 ,
2007-08-22 18:38:18 +04:00
struct metadata_area * mda __attribute ( ( unused ) ) )
2001-10-05 20:36:53 +04:00
{
2005-10-17 03:03:59 +04:00
struct dm_pool * mem = dm_pool_create ( " lvm1 vg_write " , 1024 * 10 ) ;
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 ) & &
write_disks ( fid - > fmt , & pvds ) ) ;
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 ,
2009-02-26 02:29:06 +03:00
struct physical_volume * pv , struct dm_list * mdas __attribute ( ( unused ) ) ,
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
}
2006-04-19 19:33:07 +04:00
static int _format1_pv_setup ( const struct format_type * fmt ,
2002-11-18 17:01:16 +03:00
uint64_t pe_start , uint32_t extent_count ,
uint32_t extent_size ,
2009-02-22 22:00:26 +03:00
unsigned long data_alignment __attribute ( ( unused ) ) ,
2007-08-22 18:38:18 +04:00
int pvmetadatacopies __attribute ( ( unused ) ) ,
2008-11-04 01:14:30 +03:00
uint64_t pvmetadatasize __attribute ( ( unused ) ) , struct dm_list * mdas __attribute ( ( unused ) ) ,
2007-08-22 18:38:18 +04:00
struct physical_volume * pv , struct volume_group * vg __attribute ( ( unused ) ) )
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 */
if ( ! 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 .
*/
2008-01-30 16:19:47 +03:00
if ( ! calculate_extent_count ( pv , extent_size , extent_count , pe_start ) )
return_0 ;
2001-10-10 14:55:55 +04:00
2002-11-18 17:01:16 +03:00
/* Retain existing extent locations exactly */
if ( ( ( pe_start | | extent_count ) & & ( pe_start ! = pv - > pe_start ) ) | |
( extent_count & & ( extent_count ! = pv - > pe_count ) ) ) {
log_error ( " Metadata would overwrite physical extents " ) ;
return 0 ;
}
2001-10-10 13:25:04 +04:00
return 1 ;
}
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 ;
}
2006-04-19 19:33:07 +04:00
static int _format1_pv_write ( const struct format_type * fmt , struct physical_volume * pv ,
2008-11-04 01:14:30 +03:00
struct dm_list * mdas __attribute ( ( unused ) ) , int64_t sector __attribute ( ( unused ) ) )
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 ;
2002-11-18 17:01:16 +03:00
struct label * label ;
2003-07-05 02:34:56 +04:00
struct lvmcache_info * info ;
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 ;
2002-11-18 17:01:16 +03:00
label = info - > label ;
info - > device_size = pv - > size < < SECTOR_SHIFT ;
info - > fmt = fmt ;
2008-11-04 01:14:30 +03:00
dm_list_init ( & info - > mdas ) ;
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
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 ;
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 ) ;
2007-04-26 20:44:59 +04:00
if ( ! write_disks ( fmt , & pvs ) )
goto_bad ;
2001-10-10 14:05:29 +04:00
2005-10-17 03:03:59 +04:00
dm_pool_destroy ( mem ) ;
2001-10-09 21:44:58 +04:00
return 1 ;
2001-10-10 14:05:29 +04:00
2002-04-24 22:20:51 +04:00
bad :
2005-10-17 03:03:59 +04:00
dm_pool_destroy ( mem ) ;
2001-10-10 14:05:29 +04:00
return 0 ;
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
2008-01-30 17:00:02 +03: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 ,
2007-08-22 18:38:18 +04:00
const char * vgname __attribute ( ( unused ) ) ,
const char * vgid __attribute ( ( unused ) ) ,
void * private __attribute ( ( unused ) ) )
2002-04-24 22:20:51 +04:00
{
struct format_instance * fid ;
struct metadata_area * mda ;
2008-01-30 16:19:47 +03:00
if ( ! ( fid = dm_pool_alloc ( fmt - > cmd - > mem , sizeof ( * fid ) ) ) )
return_NULL ;
2002-04-24 22:20:51 +04:00
fid - > fmt = fmt ;
2008-11-04 01:14:30 +03:00
dm_list_init ( & fid - > metadata_areas ) ;
2002-04-24 22:20:51 +04:00
/* Define a NULL metadata area */
2005-10-17 03:03:59 +04:00
if ( ! ( mda = dm_pool_alloc ( fmt - > cmd - > mem , sizeof ( * mda ) ) ) ) {
dm_pool_free ( fmt - > cmd - > mem , fid ) ;
2008-01-30 16:19:47 +03:00
return_NULL ;
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 ;
2008-11-04 01:14:30 +03:00
dm_list_add ( & fid - > metadata_areas , & mda - > list ) ;
2002-04-24 22:20:51 +04:00
return fid ;
}
2007-08-22 18:38:18 +04:00
static void _format1_destroy_instance ( struct format_instance * fid __attribute ( ( unused ) ) )
2001-10-04 21:48:55 +04:00
{
2002-04-24 22:20:51 +04:00
return ;
2001-10-08 16:11:33 +04:00
}
2006-04-19 19:33:07 +04:00
static void _format1_destroy ( const struct format_type * fmt )
2002-04-24 22:20:51 +04:00
{
2005-10-17 03:03:59 +04:00
dm_free ( ( void * ) 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 ,
. 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 ) ) ;
2001-10-08 16:11:33 +04:00
2008-01-30 16:19:47 +03:00
if ( ! fmt )
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 |
FMT_RESTRICTED_READAHEAD ;
2002-04-24 22:20:51 +04:00
fmt - > private = NULL ;
2001-10-08 16:11:33 +04:00
2002-11-18 17:01:16 +03:00
if ( ! ( fmt - > labeller = lvm1_labeller_create ( fmt ) ) ) {
log_error ( " Couldn't create lvm1 label handler. " ) ;
return NULL ;
}
if ( ! ( label_register_handler ( FMT_LVM1_NAME , fmt - > labeller ) ) ) {
log_error ( " Couldn't register lvm1 label handler. " ) ;
return NULL ;
}
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
}