2001-10-04 21:48:55 +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-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
* of the GNU General Public License v .2 .
*
* You should have received a copy of the GNU General Public License
* 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"
# include "pool.h"
# include "hash.h"
2002-02-14 00:28:56 +03:00
# include "limits.h"
2001-10-04 21:48:55 +04:00
# include "list.h"
2001-10-16 00:29:15 +04:00
# include "display.h"
2002-02-11 23:50:53 +03:00
# include "toolcontext.h"
2003-07-05 02:34:56 +04:00
# include "lvmcache.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
2003-08-20 19:48:27 +04:00
# define FMT_LVM1_NAME "lvm1"
2001-10-16 20:25:28 +04:00
/* VG consistency checks */
2002-01-29 20:23:33 +03:00
static int _check_vgs ( struct list * pvs , int * partial )
2001-10-04 21:48:55 +04:00
{
2002-01-29 20:23:33 +03:00
struct 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
* partial = 0 ;
2001-10-04 21:48:55 +04:00
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
*/
2001-10-31 15:47:01 +03:00
list_iterate ( pvh , pvs ) {
dl = list_item ( pvh , struct disk_list ) ;
2001-10-04 21:48:55 +04:00
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 */
list_iterate_safe ( pvh , t , pvs ) {
dl = list_item ( pvh , struct disk_list ) ;
if ( dl - > pvd . pv_status & VG_EXPORTED )
list_del ( pvh ) ;
}
break ;
}
}
/* Remove any PVs with VG structs that differ from the first */
list_iterate_safe ( pvh , t , pvs ) {
dl = list_item ( pvh , struct disk_list ) ;
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 ) ;
2002-01-29 20:23:33 +03:00
list_del ( pvh ) ;
if ( partial_mode ( ) ) {
* partial = 1 ;
continue ;
}
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 ) ;
2002-01-29 20:23:33 +03:00
if ( ! partial_mode ( ) )
return 0 ;
* partial = 1 ;
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 ,
2002-02-13 14:43:29 +03:00
struct list * pvs )
2001-10-04 21:48:55 +04:00
{
2002-04-24 22:20:51 +04:00
struct pool * mem = fid - > fmt - > cmd - > mem ;
2001-10-04 21:48:55 +04:00
struct volume_group * vg = pool_alloc ( mem , sizeof ( * vg ) ) ;
2001-10-09 21:09:46 +04:00
struct disk_list * dl ;
2002-01-29 20:23:33 +03:00
int partial ;
2001-10-09 21:09:46 +04:00
2001-10-15 22:39:40 +04:00
if ( ! vg )
goto bad ;
2001-10-04 21:48:55 +04:00
2001-10-15 22:39:40 +04:00
if ( list_empty ( pvs ) )
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 ;
2001-10-31 15:47:01 +03:00
list_init ( & vg - > pvs ) ;
list_init ( & vg - > lvs ) ;
2004-03-08 20:19:15 +03:00
list_init ( & vg - > tags ) ;
2001-10-08 20:08:16 +04:00
2002-01-29 20:23:33 +03:00
if ( ! _check_vgs ( pvs , & partial ) )
2001-10-15 22:39:40 +04:00
goto bad ;
2001-10-09 18:26:45 +04:00
2002-01-29 20:23:33 +03:00
dl = list_item ( pvs - > n , struct disk_list ) ;
if ( ! import_vg ( mem , vg , dl , partial ) )
2001-10-04 21:48:55 +04:00
goto bad ;
2002-11-18 17:01:16 +03:00
if ( ! import_pvs ( fid - > fmt , mem , vg , pvs , & vg - > pvs , & vg - > pv_count ) )
2001-10-04 21:48:55 +04:00
goto bad ;
2001-10-09 18:26:45 +04:00
if ( ! import_lvs ( mem , vg , pvs ) )
2001-10-04 21:48:55 +04:00
goto bad ;
2004-05-05 01:25:57 +04:00
if ( ! import_extents ( fid - > fmt - > cmd , vg , pvs ) )
2001-10-08 13:45:16 +04:00
goto bad ;
2002-02-13 14:43:29 +03:00
if ( ! import_snapshots ( mem , vg , pvs ) )
goto bad ;
2001-10-04 21:48:55 +04:00
return vg ;
2002-04-24 22:20:51 +04:00
bad :
2001-10-04 21:48:55 +04:00
stack ;
pool_free ( mem , vg ) ;
return NULL ;
}
2002-04-24 22:20:51 +04:00
static struct volume_group * _vg_read ( struct format_instance * fid ,
2002-11-18 17:01:16 +03:00
const char * vg_name ,
struct metadata_area * mda )
2001-10-04 21:48:55 +04:00
{
2004-11-23 21:23:23 +03:00
struct pool * mem = pool_create ( " lvm1 vg_read " , 1024 * 10 ) ;
2001-10-31 15:47:01 +03:00
struct list pvs ;
2001-11-12 18:10:01 +03:00
struct volume_group * vg = NULL ;
2001-10-31 15:47:01 +03:00
list_init ( & pvs ) ;
2001-10-04 21:48:55 +04:00
if ( ! mem ) {
stack ;
return NULL ;
}
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
( fid - > fmt , vg_name , fid - > fmt - > cmd - > filter , mem , & pvs ) ) {
2001-10-04 21:48:55 +04:00
stack ;
2001-11-12 18:10:01 +03:00
goto bad ;
2001-10-04 21:48:55 +04:00
}
2002-04-24 22:20:51 +04:00
if ( ! ( vg = _build_vg ( fid , & pvs ) ) ) {
2001-10-04 21:48:55 +04:00
stack ;
2001-11-12 18:10:01 +03:00
goto bad ;
}
2002-04-24 22:20:51 +04:00
bad :
2001-10-04 21:48:55 +04:00
pool_destroy ( mem ) ;
return vg ;
}
2004-03-08 20:25:59 +03:00
static struct disk_list * _flatten_pv ( struct format_instance * fid ,
struct 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
{
2001-10-09 14:47:52 +04:00
struct disk_list * dl = pool_alloc ( mem , sizeof ( * dl ) ) ;
2001-10-08 16:11:33 +04:00
2001-10-09 14:47:52 +04:00
if ( ! dl ) {
stack ;
return NULL ;
}
dl - > mem = mem ;
dl - > dev = pv - > dev ;
2001-10-31 15:47:01 +03:00
list_init ( & dl - > uuids ) ;
2001-10-31 20:59:52 +03:00
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 ) ) {
2001-10-09 14:47:52 +04:00
stack ;
2001-10-15 22:39:40 +04:00
pool_free ( mem , dl ) ;
2001-10-09 14:47:52 +04:00
return NULL ;
}
return dl ;
2001-10-05 20:36:53 +04:00
}
2002-04-24 22:20:51 +04:00
static int _flatten_vg ( struct format_instance * fid , struct pool * mem ,
struct volume_group * vg ,
2001-11-14 16:52:38 +03:00
struct 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-31 15:47:01 +03:00
struct list * pvh ;
2001-10-09 14:47:52 +04:00
struct pv_list * pvl ;
2001-10-05 20:36:53 +04:00
struct disk_list * data ;
2001-10-31 15:47:01 +03:00
list_iterate ( pvh , & vg - > pvs ) {
pvl = list_item ( pvh , struct pv_list ) ;
2001-10-05 20:36:53 +04:00
2004-03-08 20:25:59 +03:00
if ( ! ( data = _flatten_pv ( fid , mem , vg , pvl - > pv , dev_dir ) ) ) {
2001-10-05 20:36:53 +04:00
stack ;
return 0 ;
}
2001-11-14 16:52:38 +03:00
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
2002-04-24 22:20:51 +04:00
if ( ! export_vg_number ( fid , pvds , vg - > name , filter ) ) {
2001-10-11 18:10:18 +04:00
stack ;
return 0 ;
}
2001-10-05 20:36:53 +04:00
return 1 ;
}
2002-04-24 22:20:51 +04:00
static int _vg_write ( struct format_instance * fid , struct volume_group * vg ,
2002-11-18 17:01:16 +03:00
struct metadata_area * mda )
2001-10-05 20:36:53 +04:00
{
2004-11-23 21:23:23 +03:00
struct pool * mem = pool_create ( " lvm1 vg_write " , 1024 * 10 ) ;
2001-11-14 16:52:38 +03:00
struct list pvds ;
2001-10-05 20:36:53 +04:00
int r = 0 ;
if ( ! mem ) {
stack ;
return 0 ;
}
2001-11-14 16:52:38 +03:00
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
2003-07-05 02:34:56 +04:00
lvmcache_update_vg ( vg ) ;
2001-10-05 20:36:53 +04:00
pool_destroy ( mem ) ;
return r ;
}
2001-10-04 21:48:55 +04:00
2002-12-20 02:25:55 +03:00
static int _pv_read ( const struct format_type * fmt , const char * pv_name ,
struct physical_volume * pv , struct list * mdas )
2001-10-09 12:58:52 +04:00
{
2004-11-23 21:23:23 +03:00
struct pool * mem = 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
2001-10-09 12:58:52 +04:00
if ( ! mem ) {
stack ;
2002-04-24 22:20:51 +04:00
return 0 ;
2001-10-09 12:58:52 +04:00
}
2002-11-18 17:01:16 +03:00
if ( ! ( dev = dev_cache_get ( pv_name , fmt - > cmd - > filter ) ) ) {
2001-10-09 20:05:34 +04:00
stack ;
2001-11-12 15:16:57 +03:00
goto out ;
2001-10-09 20:05:34 +04:00
}
2002-04-24 22:20:51 +04:00
if ( ! ( dl = read_disk ( fmt , dev , mem , NULL ) ) ) {
2001-10-09 12:58:52 +04:00
stack ;
2001-11-12 15:16:57 +03:00
goto out ;
2001-10-09 12:58:52 +04:00
}
2002-04-24 22:20:51 +04:00
if ( ! import_pv ( fmt - > cmd - > mem , dl - > dev , NULL , pv , & dl - > pvd ) ) {
2001-10-09 12:58:52 +04:00
stack ;
2001-11-12 15:16:57 +03:00
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 :
2001-10-09 12:58:52 +04:00
pool_destroy ( mem ) ;
2002-04-24 22:20:51 +04:00
return r ;
2001-10-09 12:58:52 +04:00
}
2002-12-20 02:25:55 +03:00
static int _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 ,
int pvmetadatacopies ,
uint64_t pvmetadatasize , struct list * mdas ,
struct physical_volume * pv , struct volume_group * vg )
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 " ,
2004-06-07 19:22:43 +04:00
display_size ( fmt - > cmd , ( uint64_t ) MAX_PV_SIZE ,
2002-12-20 02:25:55 +03:00
SIZE_SHORT ) ) ;
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 .
*/
2003-12-09 20:51:39 +03:00
if ( ! calculate_extent_count ( pv , extent_size , extent_count , pe_start ) ) {
2001-10-10 14:55:55 +04:00
stack ;
return 0 ;
}
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 ;
}
2002-04-24 22:20:51 +04:00
static int _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 " ,
2004-06-07 19:22:43 +04:00
display_size ( fid - > fmt - > cmd , max_size ,
2002-12-12 23:55:49 +03:00
SIZE_SHORT ) ) ;
2002-02-14 00:28:56 +03:00
return 0 ;
}
2002-01-24 20:16:36 +03:00
return 1 ;
}
2002-12-20 02:25:55 +03:00
static int _pv_write ( const struct format_type * fmt , struct physical_volume * pv ,
2002-11-18 17:01:16 +03:00
struct list * mdas , int64_t sector )
2001-10-09 21:44:58 +04:00
{
2001-10-10 14:05:29 +04:00
struct pool * mem ;
struct disk_list * dl ;
2001-10-31 15:47:01 +03:00
struct 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 ,
pv - > vg_name , NULL ) ) ) {
2002-11-18 17:01:16 +03:00
stack ;
2001-10-10 14:05:29 +04:00
return 0 ;
}
2002-11-18 17:01:16 +03:00
label = info - > label ;
info - > device_size = pv - > size < < SECTOR_SHIFT ;
info - > fmt = fmt ;
list_init ( & info - > mdas ) ;
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 ;
pv - > pe_start = PE_ALIGN ;
2001-10-18 20:55:19 +04:00
2004-11-23 21:23:23 +03:00
if ( ! ( mem = pool_create ( " lvm1 pv_write " , 1024 ) ) ) {
2001-10-10 14:05:29 +04:00
stack ;
return 0 ;
}
if ( ! ( dl = pool_alloc ( mem , sizeof ( * dl ) ) ) ) {
stack ;
2001-10-15 22:39:40 +04:00
goto bad ;
2001-10-10 14:05:29 +04:00
}
dl - > mem = mem ;
dl - > dev = pv - > dev ;
2004-03-08 20:25:59 +03:00
if ( ! export_pv ( fmt - > cmd , mem , NULL , & dl - > pvd , pv ) ) {
2001-10-10 14:05:29 +04:00
stack ;
goto bad ;
}
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 ;
2002-11-18 17:01:16 +03:00
dl - > pvd . pe_on_disk . base = PE_ALIGN < < SECTOR_SHIFT ;
2002-01-29 18:52:11 +03:00
2001-10-31 15:47:01 +03:00
list_add ( & pvs , & dl - > list ) ;
2002-11-18 17:01:16 +03:00
if ( ! write_disks ( fmt , & pvs ) ) {
2001-10-10 14:05:29 +04:00
stack ;
goto bad ;
}
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 :
2001-10-10 14:05:29 +04:00
pool_destroy ( mem ) ;
return 0 ;
2001-10-09 21:44:58 +04:00
}
2002-12-20 02:25:55 +03:00
static int _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 " ,
2004-06-07 19:22:43 +04:00
display_size ( fid - > fmt - > cmd , ( uint64_t ) MIN_PE_SIZE ,
SIZE_SHORT ) ,
display_size ( fid - > fmt - > cmd , ( uint64_t ) MAX_PE_SIZE ,
SIZE_SHORT ) ) ;
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 " ,
2004-06-07 19:22:43 +04:00
display_size ( fid - > fmt - > cmd , ( uint64_t ) MIN_PE_SIZE ,
SIZE_SHORT ) ) ;
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
2004-09-14 17:56:18 +04:00
static int _segtype_supported ( struct format_instance * fid ,
struct segment_type * segtype )
{
if ( ! ( segtype - > flags & SEG_FORMAT1_SUPPORT ) ) {
stack ;
return 0 ;
}
return 1 ;
}
2002-11-18 17:01:16 +03:00
static struct metadata_area_ops _metadata_format1_ops = {
vg_read : _vg_read ,
vg_write : _vg_write ,
} ;
2002-12-20 02:25:55 +03:00
static struct format_instance * _create_instance ( const struct format_type * fmt ,
const char * vgname ,
void * private )
2002-04-24 22:20:51 +04:00
{
struct format_instance * fid ;
struct metadata_area * mda ;
if ( ! ( fid = pool_alloc ( fmt - > cmd - > mem , sizeof ( * fid ) ) ) ) {
stack ;
return NULL ;
}
fid - > fmt = fmt ;
list_init ( & fid - > metadata_areas ) ;
/* Define a NULL metadata area */
if ( ! ( mda = pool_alloc ( fmt - > cmd - > mem , sizeof ( * mda ) ) ) ) {
stack ;
pool_free ( fmt - > cmd - > mem , fid ) ;
return NULL ;
}
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 ;
list_add ( & fid - > metadata_areas , & mda - > list ) ;
return fid ;
}
2002-12-20 02:25:55 +03:00
static void _destroy_instance ( struct format_instance * fid )
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
}
2002-12-20 02:25:55 +03:00
static void _destroy ( const struct format_type * fmt )
2002-04-24 22:20:51 +04:00
{
2002-12-20 02:25:55 +03:00
dbg_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 = {
2002-11-18 17:01:16 +03:00
pv_read : _pv_read ,
pv_setup : _pv_setup ,
pv_write : _pv_write ,
lv_setup : _lv_setup ,
vg_setup : _vg_setup ,
2004-09-14 17:56:18 +04:00
segtype_supported : _segtype_supported ,
2002-04-24 22:20:51 +04:00
create_instance : _create_instance ,
destroy_instance : _destroy_instance ,
2002-11-18 17:01:16 +03:00
destroy : _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
{
2002-04-24 22:20:51 +04:00
struct format_type * fmt = dbg_malloc ( sizeof ( * fmt ) ) ;
2001-10-08 16:11:33 +04:00
2002-04-24 22:20:51 +04:00
if ( ! fmt ) {
2001-10-08 16:11:33 +04:00
stack ;
2001-11-12 15:16:57 +03:00
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 ;
2003-11-06 23:15:13 +03:00
fmt - > features = FMT_RESTRICTED_LVIDS | FMT_ORPHAN_ALLOCATABLE ;
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
}