2001-12-17 22:46:10 +03:00
/*
* Copyright ( C ) 2001 Sistina Software ( UK ) Limited .
*
* This file is released under the LGPL .
*/
2002-01-11 02:21:07 +03:00
# include "metadata.h"
2001-12-17 22:46:10 +03:00
# include "import-export.h"
2002-01-10 19:48:28 +03:00
# include "pool.h"
# include "log.h"
2002-01-10 21:12:26 +03:00
# include "uuid.h"
2002-01-11 14:09:12 +03:00
# include "hash.h"
2002-02-11 23:50:53 +03:00
# include "toolcontext.h"
2001-12-17 22:46:10 +03:00
2002-04-24 22:20:51 +04:00
typedef int ( * section_fn ) ( struct format_instance * fid , struct pool * mem ,
struct volume_group * vg , struct config_node * pvn ,
struct config_node * vgn ,
struct hash_table * pv_hash , struct uuid_map * um ) ;
2002-01-10 14:18:08 +03:00
2002-01-10 19:48:28 +03:00
# define _read_int32(root, path, result) \
get_config_uint32 ( root , path , ' / ' , result )
2002-01-10 14:18:08 +03:00
2002-02-14 17:52:21 +03:00
# define _read_uint32(root, path, result) \
get_config_uint32 ( root , path , ' / ' , result )
2002-01-10 19:48:28 +03:00
# define _read_int64(root, path, result) \
get_config_uint64 ( root , path , ' / ' , result )
2002-01-10 14:18:08 +03:00
2002-01-10 21:12:26 +03:00
static int _read_id ( struct id * id , struct config_node * cn , const char * path )
{
struct config_value * cv ;
if ( ! ( cn = find_config_node ( cn , path , ' / ' ) ) ) {
log_err ( " Couldn't find uuid. " ) ;
return 0 ;
}
cv = cn - > v ;
if ( ! cv | | ! cv - > v . str ) {
log_err ( " uuid must be a string. " ) ;
return 0 ;
}
if ( ! id_read_format ( id , cv - > v . str ) ) {
log_err ( " Invalid uuid. " ) ;
return 0 ;
}
return 1 ;
}
2002-04-24 22:20:51 +04:00
static int _read_pv ( struct format_instance * fid , struct pool * mem ,
2002-01-10 19:48:28 +03:00
struct volume_group * vg , struct config_node * pvn ,
2002-01-11 14:09:12 +03:00
struct config_node * vgn ,
2002-04-24 22:20:51 +04:00
struct hash_table * pv_hash , struct uuid_map * um )
2002-01-10 14:18:08 +03:00
{
struct physical_volume * pv ;
2002-01-10 19:48:28 +03:00
struct pv_list * pvl ;
2002-01-10 14:18:08 +03:00
struct config_node * cn ;
2002-01-21 19:05:23 +03:00
if ( ! ( pvl = pool_zalloc ( mem , sizeof ( * pvl ) ) ) | |
! ( pvl - > pv = pool_zalloc ( mem , sizeof ( * pvl - > pv ) ) ) ) {
2002-01-10 14:18:08 +03:00
stack ;
return 0 ;
}
2002-01-21 19:05:23 +03:00
pv = pvl - > pv ;
2002-01-10 19:48:28 +03:00
2002-01-15 20:37:23 +03:00
/*
* Add the pv to the pv hash for quick lookup when we read
* the lv segments .
*/
if ( ! hash_insert ( pv_hash , pvn - > key , pv ) ) {
stack ;
return 0 ;
}
if ( ! ( pvn = pvn - > child ) ) {
log_err ( " Empty pv section. " ) ;
return 0 ;
}
if ( ! _read_id ( & pv - > id , pvn , " id " ) ) {
2002-01-10 14:18:08 +03:00
log_err ( " Couldn't read uuid for volume group. " ) ;
2002-01-10 19:48:28 +03:00
return 0 ;
2002-01-10 14:18:08 +03:00
}
/*
2002-01-15 20:37:23 +03:00
* Use the uuid map to convert the uuid into a device .
2002-01-10 14:18:08 +03:00
*/
2002-01-15 20:37:23 +03:00
if ( ! ( pv - > dev = uuid_map_lookup ( um , & pv - > id ) ) ) {
char buffer [ 64 ] ;
2002-04-30 21:12:37 +04:00
if ( ! id_write_format ( & pv - > id , buffer , sizeof ( buffer ) ) )
2002-01-15 20:37:23 +03:00
log_err ( " Couldn't find device. " ) ;
2002-04-30 21:12:37 +04:00
else
log_err ( " Couldn't find device with uuid '%s'. " , buffer ) ;
2002-01-15 20:37:23 +03:00
2002-04-30 21:12:37 +04:00
if ( partial_mode ( ) )
vg - > status | = PARTIAL_VG ;
else
return 0 ;
2002-01-15 20:37:23 +03:00
}
2002-01-10 14:18:08 +03:00
if ( ! ( pv - > vg_name = pool_strdup ( mem , vg - > name ) ) ) {
stack ;
return 0 ;
}
2002-01-15 20:37:23 +03:00
if ( ! ( cn = find_config_node ( pvn , " status " , ' / ' ) ) ) {
2002-01-10 14:18:08 +03:00
log_err ( " Couldn't find status flags for physical volume. " ) ;
return 0 ;
}
if ( ! ( read_flags ( & pv - > status , PV_FLAGS , cn - > v ) ) ) {
log_err ( " Couldn't read status flags for physical volume. " ) ;
return 0 ;
}
if ( ! _read_int64 ( pvn , " pe_start " , & pv - > pe_start ) ) {
log_err ( " Couldn't read extent size for volume group. " ) ;
return 0 ;
}
if ( ! _read_int32 ( pvn , " pe_count " , & pv - > pe_count ) ) {
log_err ( " Couldn't find extent count (pe_count) for "
" physical volume. " ) ;
return 0 ;
}
/* adjust the volume group. */
vg - > extent_count + = pv - > pe_count ;
vg - > free_count + = pv - > pe_count ;
2002-01-25 23:21:13 +03:00
pv - > pe_size = vg - > extent_size ;
2002-01-10 14:18:08 +03:00
pv - > size = pv - > pe_size * ( uint64_t ) pv - > pe_count ;
2002-04-24 22:20:51 +04:00
pv - > pe_alloc_count = 0 ;
pv - > fid = fid ;
2002-01-10 14:18:08 +03:00
2002-01-15 20:37:23 +03:00
vg - > pv_count + + ;
2002-01-10 19:48:28 +03:00
list_add ( & vg - > pvs , & pvl - > list ) ;
2002-01-11 14:09:12 +03:00
2002-01-10 14:18:08 +03:00
return 1 ;
}
static void _insert_segment ( struct logical_volume * lv ,
struct stripe_segment * seg )
{
struct list * segh ;
struct stripe_segment * comp ;
2002-04-24 22:20:51 +04:00
list_iterate ( segh , & lv - > segments ) {
2002-01-10 14:18:08 +03:00
comp = list_item ( segh , struct stripe_segment ) ;
if ( comp - > le > seg - > le ) {
list_add ( & comp - > list , & seg - > list ) ;
return ;
}
}
2002-01-15 20:37:23 +03:00
lv - > le_count + = seg - > len ;
2002-01-10 19:48:28 +03:00
list_add ( & lv - > segments , & seg - > list ) ;
2002-01-10 14:18:08 +03:00
}
static int _read_segment ( struct pool * mem , struct volume_group * vg ,
2002-01-11 14:09:12 +03:00
struct logical_volume * lv , struct config_node * sn ,
struct hash_table * pv_hash )
2002-01-10 14:18:08 +03:00
{
2002-01-10 19:48:28 +03:00
int s ;
2002-01-15 20:37:23 +03:00
uint32_t stripes ;
2002-01-10 14:18:08 +03:00
struct stripe_segment * seg ;
struct config_node * cn ;
2002-01-10 19:48:28 +03:00
struct config_value * cv ;
2002-01-15 20:37:23 +03:00
const char * seg_name = sn - > key ;
2002-01-10 14:18:08 +03:00
2002-01-15 20:37:23 +03:00
if ( ! ( sn = sn - > child ) ) {
log_err ( " Empty segment section. " ) ;
return 0 ;
}
if ( ! _read_int32 ( sn , " stripes " , & stripes ) ) {
2002-04-24 22:20:51 +04:00
log_err ( " Couldn't read 'stripes' for segment '%s'. " , sn - > key ) ;
2002-01-15 20:37:23 +03:00
return 0 ;
}
if ( ! ( seg = pool_zalloc ( mem , sizeof ( * seg ) +
( sizeof ( seg - > area [ 0 ] ) * stripes ) ) ) ) {
2002-01-10 14:18:08 +03:00
stack ;
return 0 ;
}
2002-01-15 20:37:23 +03:00
seg - > stripes = stripes ;
2002-04-16 23:41:54 +04:00
seg - > lv = lv ;
2002-01-10 14:18:08 +03:00
if ( ! _read_int32 ( sn , " start_extent " , & seg - > le ) ) {
log_err ( " Couldn't read 'start_extent' for segment '%s'. " ,
sn - > key ) ;
return 0 ;
}
if ( ! _read_int32 ( sn , " extent_count " , & seg - > len ) ) {
log_err ( " Couldn't read 'extent_count' for segment '%s'. " ,
sn - > key ) ;
return 0 ;
}
if ( seg - > stripes = = 0 ) {
log_err ( " Zero stripes is *not* allowed for segment '%s'. " ,
sn - > key ) ;
return 0 ;
}
if ( ( seg - > stripes ! = 1 ) & &
! _read_int32 ( sn , " stripe_size " , & seg - > stripe_size ) ) {
log_err ( " Couldn't read 'stripe_size' for segment '%s'. " ,
sn - > key ) ;
return 0 ;
}
2002-01-10 19:48:28 +03:00
if ( ! ( cn = find_config_node ( sn , " areas " , ' / ' ) ) ) {
2002-01-10 14:18:08 +03:00
log_err ( " Couldn't find 'areas' array for segment '%s'. " ,
sn - > key ) ;
return 0 ;
}
/*
* Read the stripes from the ' areas ' array .
2002-01-10 19:48:28 +03:00
* FIXME : we could move this to a separate function .
2002-01-10 14:18:08 +03:00
*/
for ( cv = cn - > v , s = 0 ; cv & & s < seg - > stripes ; s + + , cv = cv - > next ) {
/* first we read the pv */
const char * bad = " Badly formed areas array for segment '%s'. " ;
struct physical_volume * pv ;
uint32_t allocated ;
if ( cv - > type ! = CFG_STRING ) {
log_err ( bad , sn - > key ) ;
return 0 ;
}
2002-01-11 14:09:12 +03:00
if ( ! ( pv = hash_lookup ( pv_hash , cv - > v . str ) ) ) {
2002-01-15 20:37:23 +03:00
log_err ( " Couldn't find physical volume '%s' for "
2002-01-10 14:18:08 +03:00
" segment '%s'. " ,
2002-04-24 22:20:51 +04:00
cn - > v - > v . str ? cn - > v - > v . str : " NULL " , seg_name ) ;
return 0 ;
2002-01-10 14:18:08 +03:00
}
seg - > area [ s ] . pv = pv ;
if ( ! ( cv = cv - > next ) ) {
log_err ( bad , sn - > key ) ;
return 0 ;
}
if ( cv - > type ! = CFG_INT ) {
log_err ( bad , sn - > key ) ;
return 0 ;
}
seg - > area [ s ] . pe = cv - > v . i ;
/*
* Adjust the extent counts in the pv and vg .
*/
allocated = seg - > len / seg - > stripes ;
2002-04-24 22:20:51 +04:00
pv - > pe_alloc_count + = allocated ;
2002-01-10 14:18:08 +03:00
vg - > free_count - = allocated ;
}
/*
* Check we read the correct number of stripes .
*/
if ( cv | | ( s < seg - > stripes ) ) {
log_err ( " Incorrect number of stripes in 'area' array "
2002-01-15 20:37:23 +03:00
" for segment '%s'. " , seg_name ) ;
2002-01-10 14:18:08 +03:00
return 0 ;
}
/*
* Insert into correct part of segment list .
*/
_insert_segment ( lv , seg ) ;
return 1 ;
}
static int _read_segments ( struct pool * mem , struct volume_group * vg ,
2002-01-11 14:09:12 +03:00
struct logical_volume * lv , struct config_node * lvn ,
struct hash_table * pv_hash )
2002-01-10 14:18:08 +03:00
{
struct config_node * sn ;
int count = 0 , seg_count ;
2002-01-15 20:37:23 +03:00
for ( sn = lvn ; sn ; sn = sn - > sib ) {
2002-01-10 14:18:08 +03:00
/*
* All sub - sections are assumed to be segments .
*/
2002-01-15 20:37:23 +03:00
if ( ! sn - > v ) {
2002-01-11 14:09:12 +03:00
if ( ! _read_segment ( mem , vg , lv , sn , pv_hash ) ) {
2002-01-10 14:18:08 +03:00
stack ;
return 0 ;
}
count + + ;
}
}
if ( ! _read_int32 ( lvn , " segment_count " , & seg_count ) ) {
log_err ( " Couldn't read segment count for logical volume. " ) ;
return 0 ;
}
2002-01-10 19:48:28 +03:00
if ( seg_count ! = count ) {
2002-01-10 14:18:08 +03:00
log_err ( " segment_count and actual number of segments "
" disagree. " ) ;
return 0 ;
}
/*
* Check there are no gaps or overlaps in the lv .
*/
if ( ! lv_check_segments ( lv ) ) {
stack ;
return 0 ;
}
/*
* Merge segments in case someones been editing things by hand .
*/
if ( ! lv_merge_segments ( lv ) ) {
stack ;
return 0 ;
}
return 1 ;
}
2002-04-24 22:20:51 +04:00
static int _read_lv ( struct format_instance * fid , struct pool * mem ,
2002-01-10 19:48:28 +03:00
struct volume_group * vg , struct config_node * lvn ,
2002-01-15 20:37:23 +03:00
struct config_node * vgn , struct hash_table * pv_hash ,
struct uuid_map * um )
2002-01-10 14:18:08 +03:00
{
struct logical_volume * lv ;
2002-01-10 19:48:28 +03:00
struct lv_list * lvl ;
2002-01-10 14:18:08 +03:00
struct config_node * cn ;
2002-01-21 19:49:32 +03:00
if ( ! ( lvl = pool_zalloc ( mem , sizeof ( * lvl ) ) ) | |
! ( lvl - > lv = pool_zalloc ( mem , sizeof ( * lvl - > lv ) ) ) ) {
2002-01-10 14:18:08 +03:00
stack ;
return 0 ;
}
2002-01-21 19:49:32 +03:00
lv = lvl - > lv ;
2002-01-10 19:48:28 +03:00
2002-01-10 14:18:08 +03:00
if ( ! ( lv - > name = pool_strdup ( mem , lvn - > key ) ) ) {
stack ;
return 0 ;
}
2002-01-15 20:37:23 +03:00
if ( ! ( lvn = lvn - > child ) ) {
log_err ( " Empty logical volume section. " ) ;
return 0 ;
}
2002-01-10 14:18:08 +03:00
lv - > vg = vg ;
2002-03-05 23:03:09 +03:00
/* FIXME: read full lvid */
if ( ! _read_id ( & lv - > lvid . id [ 1 ] , lvn , " id " ) ) {
2002-04-24 22:20:51 +04:00
log_err ( " Couldn't read uuid for logical volume %s. " , lv - > name ) ;
2002-02-21 18:26:44 +03:00
return 0 ;
}
2002-03-05 23:03:09 +03:00
memcpy ( & lv - > lvid . id [ 0 ] , & lv - > vg - > id , sizeof ( lv - > lvid . id [ 0 ] ) ) ;
2002-01-10 14:18:08 +03:00
if ( ! ( cn = find_config_node ( lvn , " status " , ' / ' ) ) ) {
log_err ( " Couldn't find status flags for logical volume. " ) ;
return 0 ;
}
if ( ! ( read_flags ( & lv - > status , LV_FLAGS , cn - > v ) ) ) {
log_err ( " Couldn't read status flags for logical volume. " ) ;
return 0 ;
}
2002-02-01 20:54:39 +03:00
lv - > minor = - 1 ;
2002-02-11 14:43:17 +03:00
if ( ( lv - > status & FIXED_MINOR ) & &
2002-02-01 20:54:39 +03:00
! _read_int32 ( lvn , " minor " , & lv - > minor ) ) {
log_error ( " Couldn't read 'minor' value for logical volume. " ) ;
return 0 ;
}
2002-01-10 14:18:08 +03:00
if ( ! _read_int32 ( lvn , " read_ahead " , & lv - > read_ahead ) ) {
log_err ( " Couldn't read 'read_ahead' value for "
" logical volume. " ) ;
return 0 ;
}
list_init ( & lv - > segments ) ;
2002-01-11 14:09:12 +03:00
if ( ! _read_segments ( mem , vg , lv , lvn , pv_hash ) ) {
2002-01-10 14:18:08 +03:00
stack ;
return 0 ;
}
2002-01-15 20:37:23 +03:00
lv - > size = ( uint64_t ) lv - > le_count * ( uint64_t ) vg - > extent_size ;
2002-01-10 14:18:08 +03:00
2002-01-15 20:37:23 +03:00
vg - > lv_count + + ;
2002-01-10 19:48:28 +03:00
list_add ( & vg - > lvs , & lvl - > list ) ;
2002-01-10 14:18:08 +03:00
return 1 ;
}
2002-04-24 22:20:51 +04:00
static int _read_snapshot ( struct format_instance * fid , struct pool * mem ,
2002-02-13 16:29:16 +03:00
struct volume_group * vg , struct config_node * sn ,
struct config_node * vgn , struct hash_table * pv_hash ,
struct uuid_map * um )
{
uint32_t chunk_size ;
const char * org_name , * cow_name ;
struct logical_volume * org , * cow ;
if ( ! ( sn = sn - > child ) ) {
log_err ( " Empty snapshot section. " ) ;
return 0 ;
}
if ( ! _read_uint32 ( sn , " chunk_size " , & chunk_size ) ) {
log_err ( " Couldn't read chunk size for snapshot. " ) ;
return 0 ;
}
if ( ! ( cow_name = find_config_str ( sn , " cow_store " , ' / ' , NULL ) ) ) {
log_err ( " Snapshot cow storage not specified. " ) ;
return 0 ;
}
if ( ! ( org_name = find_config_str ( sn , " origin " , ' / ' , NULL ) ) ) {
log_err ( " Snapshot origin not specified. " ) ;
return 0 ;
}
if ( ! ( cow = find_lv ( vg , cow_name ) ) ) {
log_err ( " Unknown logical volume specified for "
" snapshot cow store. " ) ;
return 0 ;
}
if ( ! ( org = find_lv ( vg , org_name ) ) ) {
log_err ( " Unknown logical volume specified for "
" snapshot origin. " ) ;
return 0 ;
}
2002-02-21 21:31:48 +03:00
if ( ! vg_add_snapshot ( org , cow , 1 , chunk_size ) ) {
2002-02-13 16:29:16 +03:00
stack ;
return 0 ;
}
return 1 ;
}
2002-04-24 22:20:51 +04:00
static int _read_sections ( struct format_instance * fid ,
const char * section , section_fn fn ,
2002-01-10 14:18:08 +03:00
struct pool * mem ,
2002-01-11 14:09:12 +03:00
struct volume_group * vg , struct config_node * vgn ,
2002-01-15 20:37:23 +03:00
struct hash_table * pv_hash ,
2002-04-24 22:20:51 +04:00
struct uuid_map * um , int optional )
2002-01-10 14:18:08 +03:00
{
struct config_node * n ;
2002-01-10 19:48:28 +03:00
if ( ! ( n = find_config_node ( vgn , section , ' / ' ) ) ) {
2002-02-13 16:29:16 +03:00
if ( ! optional ) {
log_err ( " Couldn't find section '%s'. " , section ) ;
return 0 ;
}
return 1 ;
2002-01-10 14:18:08 +03:00
}
for ( n = n - > child ; n ; n = n - > sib ) {
2002-04-24 22:20:51 +04:00
if ( ! fn ( fid , mem , vg , n , vgn , pv_hash , um ) ) {
2002-01-10 14:18:08 +03:00
stack ;
return 0 ;
}
}
return 1 ;
}
2001-12-17 22:46:10 +03:00
2002-04-24 22:20:51 +04:00
static struct volume_group * _read_vg ( struct format_instance * fid ,
2002-02-26 19:48:52 +03:00
struct config_file * cf ,
2002-01-15 20:37:23 +03:00
struct uuid_map * um )
2001-12-17 22:46:10 +03:00
{
2002-02-11 14:43:17 +03:00
struct config_node * vgn , * cn ;
2001-12-17 22:46:10 +03:00
struct volume_group * vg ;
2002-01-11 14:09:12 +03:00
struct hash_table * pv_hash = NULL ;
2002-04-24 22:20:51 +04:00
struct pool * mem = fid - > fmt - > cmd - > mem ;
2001-12-17 22:46:10 +03:00
2002-02-11 14:43:17 +03:00
/* skip any top-level values */
2002-04-24 22:20:51 +04:00
for ( vgn = cf - > root ; ( vgn & & vgn - > v ) ; vgn = vgn - > sib ) ;
2002-01-10 14:18:08 +03:00
2002-02-11 14:43:17 +03:00
if ( ! vgn ) {
2002-01-15 20:37:23 +03:00
log_err ( " Couldn't find volume group in file. " ) ;
2001-12-17 22:46:10 +03:00
return NULL ;
}
if ( ! ( vg = pool_zalloc ( mem , sizeof ( * vg ) ) ) ) {
stack ;
return NULL ;
}
2002-04-24 22:20:51 +04:00
vg - > cmd = fid - > fmt - > cmd ;
/* FIXME Determine format type from file contents */
/* eg Set to instance of fmt1 here if reading a format1 backup? */
vg - > fid = fid ;
2001-12-17 22:46:10 +03:00
2002-01-15 20:37:23 +03:00
if ( ! ( vg - > name = pool_strdup ( mem , vgn - > key ) ) ) {
stack ;
2002-01-10 14:18:08 +03:00
goto bad ;
}
2002-02-01 20:54:39 +03:00
if ( ! ( vg - > system_id = pool_zalloc ( mem , NAME_LEN ) ) ) {
stack ;
goto bad ;
}
2002-01-15 20:37:23 +03:00
vgn = vgn - > child ;
2002-02-11 14:43:17 +03:00
2002-02-01 20:54:39 +03:00
if ( ( cn = find_config_node ( vgn , " system_id " , ' / ' ) ) & & cn - > v ) {
if ( ! cn - > v - > v . str ) {
log_error ( " system_id must be a string " ) ;
goto bad ;
}
strncpy ( vg - > system_id , cn - > v - > v . str , NAME_LEN ) ;
}
2002-01-15 20:37:23 +03:00
if ( ! _read_id ( & vg - > id , vgn , " id " ) ) {
2002-04-24 22:20:51 +04:00
log_err ( " Couldn't read uuid for volume group %s. " , vg - > name ) ;
goto bad ;
}
if ( ! _read_int32 ( vgn , " seqno " , & vg - > seqno ) ) {
log_err ( " Couldn't read 'seqno' for volume group %s. " , vg - > name ) ;
2002-01-10 14:18:08 +03:00
goto bad ;
}
if ( ! ( cn = find_config_node ( vgn , " status " , ' / ' ) ) ) {
2002-01-16 21:10:08 +03:00
log_err ( " Couldn't find status flags for volume group %s. " ,
vg - > name ) ;
2002-01-10 14:18:08 +03:00
goto bad ;
}
if ( ! ( read_flags ( & vg - > status , VG_FLAGS , cn - > v ) ) ) {
2002-01-16 21:10:08 +03:00
log_err ( " Couldn't read status flags for volume group %s. " ,
vg - > name ) ;
2002-01-10 14:18:08 +03:00
goto bad ;
}
if ( ! _read_int32 ( vgn , " extent_size " , & vg - > extent_size ) ) {
2002-01-16 21:10:08 +03:00
log_err ( " Couldn't read extent size for volume group %s. " ,
vg - > name ) ;
2002-01-10 14:18:08 +03:00
goto bad ;
}
/*
* ' extent_count ' and ' free_count ' get filled in
* implicitly when reading in the pv ' s and lv ' s .
*/
if ( ! _read_int32 ( vgn , " max_lv " , & vg - > max_lv ) ) {
2002-01-16 21:10:08 +03:00
log_err ( " Couldn't read 'max_lv' for volume group %s. " ,
vg - > name ) ;
2002-01-10 14:18:08 +03:00
goto bad ;
}
2002-01-10 19:48:28 +03:00
if ( ! _read_int32 ( vgn , " max_pv " , & vg - > max_pv ) ) {
2002-01-16 21:10:08 +03:00
log_err ( " Couldn't read 'max_pv' for volume group %s. " ,
vg - > name ) ;
2002-01-10 14:18:08 +03:00
goto bad ;
}
2002-01-11 14:09:12 +03:00
/*
* The pv hash memoises the pv section names - > pv
* structures .
*/
if ( ! ( pv_hash = hash_create ( 32 ) ) ) {
log_err ( " Couldn't create hash table. " ) ;
goto bad ;
}
2002-01-10 14:18:08 +03:00
list_init ( & vg - > pvs ) ;
2002-04-24 22:20:51 +04:00
if ( ! _read_sections ( fid , " physical_volumes " , _read_pv , mem , vg ,
2002-02-13 16:29:16 +03:00
vgn , pv_hash , um , 0 ) ) {
2002-01-16 21:10:08 +03:00
log_err ( " Couldn't find all physical volumes for volume "
" group %s. " , vg - > name ) ;
2002-01-10 14:18:08 +03:00
goto bad ;
}
list_init ( & vg - > lvs ) ;
2002-04-24 22:20:51 +04:00
if ( ! _read_sections ( fid , " logical_volumes " , _read_lv , mem , vg ,
2002-02-13 16:29:16 +03:00
vgn , pv_hash , um , 1 ) ) {
2002-01-10 14:18:08 +03:00
log_err ( " Couldn't read all logical volumes for volume "
2002-01-16 21:10:08 +03:00
" group %s. " , vg - > name ) ;
2002-01-10 14:18:08 +03:00
goto bad ;
2002-02-13 16:29:16 +03:00
}
list_init ( & vg - > snapshots ) ;
2002-04-24 22:20:51 +04:00
if ( ! _read_sections ( fid , " snapshots " , _read_snapshot , mem , vg ,
2002-02-13 16:29:16 +03:00
vgn , pv_hash , um , 1 ) ) {
log_err ( " Couldn't read all snapshots for volume group %s. " ,
vg - > name ) ;
goto bad ;
2002-01-10 14:18:08 +03:00
}
2002-01-11 14:09:12 +03:00
hash_destroy ( pv_hash ) ;
2002-04-30 21:12:37 +04:00
if ( vg - > status & PARTIAL_VG ) {
vg - > status & = ~ LVM_WRITE ;
vg - > status | = LVM_READ ;
}
2002-01-10 14:18:08 +03:00
/*
* Finished .
*/
return vg ;
2002-04-24 22:20:51 +04:00
bad :
2002-01-11 14:09:12 +03:00
if ( pv_hash )
hash_destroy ( pv_hash ) ;
2002-01-10 14:18:08 +03:00
pool_free ( mem , vg ) ;
return NULL ;
2001-12-17 22:46:10 +03:00
}
2002-02-11 14:43:17 +03:00
static void _read_desc ( struct pool * mem ,
2002-04-24 22:20:51 +04:00
struct config_file * cf , time_t * when , char * * desc )
2002-02-11 14:43:17 +03:00
{
const char * d ;
unsigned int u = 0u ;
d = find_config_str ( cf - > root , " description " , ' / ' , " " ) ;
* desc = pool_strdup ( mem , d ) ;
get_config_uint32 ( cf - > root , " creation_time " , ' / ' , & u ) ;
* when = u ;
}
2002-04-24 22:20:51 +04:00
struct volume_group * text_vg_import ( struct format_instance * fid ,
2002-01-15 20:37:23 +03:00
const char * file ,
2002-02-11 14:43:17 +03:00
struct uuid_map * um ,
2002-04-24 22:20:51 +04:00
time_t * when , char * * desc )
2001-12-17 22:46:10 +03:00
{
struct volume_group * vg = NULL ;
struct config_file * cf ;
2002-02-11 14:43:17 +03:00
* desc = NULL ;
* when = 0 ;
2001-12-17 22:46:10 +03:00
if ( ! ( cf = create_config_file ( ) ) ) {
stack ;
goto out ;
}
if ( ! read_config ( cf , file ) ) {
2002-01-16 21:10:08 +03:00
log_error ( " Couldn't read volume group file. " ) ;
2001-12-17 22:46:10 +03:00
goto out ;
}
2002-04-24 22:20:51 +04:00
if ( ! ( vg = _read_vg ( fid , cf , um ) ) ) {
2001-12-17 22:46:10 +03:00
stack ;
2002-01-16 21:10:08 +03:00
goto out ;
}
2001-12-17 22:46:10 +03:00
2002-04-24 22:20:51 +04:00
_read_desc ( fid - > fmt - > cmd - > mem , cf , when , desc ) ;
2002-02-11 14:43:17 +03:00
2002-04-24 22:20:51 +04:00
out :
2001-12-17 22:46:10 +03:00
destroy_config_file ( cf ) ;
return vg ;
}