2001-10-04 21:48:55 +04:00
/*
* Copyright ( C ) 2001 Sistina Software ( UK ) Limited .
*
* This file is released under the GPL .
*/
# include "disk-rep.h"
# include "dbg_malloc.h"
# include "pool.h"
# include "hash.h"
# include "list.h"
2001-10-08 13:45:16 +04:00
# include "log.h"
2001-10-04 21:48:55 +04:00
2001-10-08 21:28:49 +04:00
static int _import_vg ( struct pool * mem ,
struct volume_group * vg , struct list_head * pvs )
2001-10-04 21:48:55 +04:00
{
struct list_head * tmp ;
struct disk_list * dl ;
struct vg_disk * first = NULL ;
/* check all the vg's are the same */
list_for_each ( tmp , pvs ) {
dl = list_entry ( tmp , struct disk_list , list ) ;
if ( ! first ) {
first = & dl - > vg ;
2001-10-08 20:08:16 +04:00
memcpy ( & vg - > id . uuid , & first - > vg_uuid , ID_LEN ) ;
2001-10-08 21:28:49 +04:00
if ( ! ( vg - > name = pool_strdup ( mem , dl - > pv . vg_name ) ) ) {
stack ;
return 0 ;
}
2001-10-08 13:45:16 +04:00
// FIXME: encode flags
//vg->status = first->vg_status;
//vg->access = first->vg_access;
2001-10-04 21:48:55 +04:00
vg - > extent_size = first - > pe_size ;
vg - > extent_count = first - > pe_total ;
vg - > free_count = first - > pe_total - first - > pe_allocated ;
vg - > max_lv = first - > lv_max ;
vg - > max_pv = first - > pv_max ;
} else if ( memcmp ( first , & dl - > vg , sizeof ( * first ) ) ) {
log_err ( " vg data differs on pvs \n " ) ;
return 0 ;
}
}
2001-10-08 21:53:43 +04:00
return first ? 1 : 0 ;
2001-10-04 21:48:55 +04:00
}
2001-10-08 21:53:43 +04:00
static int _import_pvs ( struct pool * mem , struct list_head * pvs ,
struct list_head * results , int * count )
2001-10-04 21:48:55 +04:00
{
struct list_head * tmp ;
struct disk_list * dl ;
struct pv_list * pvl ;
struct physical_volume * pv ;
2001-10-08 21:53:43 +04:00
* count = 0 ;
2001-10-04 21:48:55 +04:00
list_for_each ( tmp , pvs ) {
dl = list_entry ( tmp , struct disk_list , list ) ;
pvl = pool_alloc ( mem , sizeof ( * pvl ) ) ;
2001-10-08 20:08:16 +04:00
memset ( pvl , 0 , sizeof ( * pvl ) ) ;
2001-10-04 21:48:55 +04:00
if ( ! pvl ) {
stack ;
return 0 ;
}
pv = & pvl - > pv ;
memcpy ( & pv - > id , & dl - > pv . pv_uuid , ID_LEN ) ;
2001-10-08 20:08:16 +04:00
pv - > dev = dl - > dev ;
2001-10-08 13:45:16 +04:00
pv - > vg_name = pool_strdup ( mem , dl - > pv . vg_name ) ;
2001-10-04 21:48:55 +04:00
if ( ! pv - > vg_name ) {
stack ;
return 0 ;
}
2001-10-08 13:45:16 +04:00
// FIXME: finish
//pv->exported = ??;
2001-10-04 21:48:55 +04:00
pv - > status = dl - > pv . pv_status ;
pv - > size = dl - > pv . pv_size ;
pv - > pe_size = dl - > pv . pv_size ;
2001-10-08 13:45:16 +04:00
pv - > pe_start = dl - > pv . pe_start ;
pv - > pe_count = dl - > pv . pe_total ;
pv - > pe_allocated = dl - > pv . pe_allocated ;
2001-10-04 21:48:55 +04:00
2001-10-08 21:53:43 +04:00
list_add ( & pvl - > list , results ) ;
( * count ) + + ;
2001-10-04 21:48:55 +04:00
}
return 1 ;
}
2001-10-05 17:59:44 +04:00
static struct logical_volume * _find_lv ( struct volume_group * vg ,
2001-10-04 21:48:55 +04:00
const char * name )
{
struct list_head * tmp ;
struct logical_volume * lv ;
2001-10-08 13:45:16 +04:00
struct lv_list * ll ;
2001-10-04 21:48:55 +04:00
list_for_each ( tmp , & vg - > lvs ) {
2001-10-08 13:45:16 +04:00
ll = list_entry ( tmp , struct lv_list , list ) ;
lv = & ll - > lv ;
2001-10-04 21:48:55 +04:00
if ( ! strcmp ( name , lv - > name ) )
return lv ;
}
return NULL ;
}
2001-10-08 16:11:33 +04:00
static struct physical_volume * _find_pv ( struct volume_group * vg ,
2001-10-08 13:45:16 +04:00
struct device * dev )
{
struct list_head * tmp ;
struct physical_volume * pv ;
struct pv_list * pl ;
2001-10-08 20:08:16 +04:00
list_for_each ( tmp , & vg - > pvs ) {
2001-10-08 13:45:16 +04:00
pl = list_entry ( tmp , struct pv_list , list ) ;
pv = & pl - > pv ;
if ( dev = = pv - > dev )
return pv ;
}
return NULL ;
}
static struct logical_volume * _add_lv ( struct pool * mem ,
struct volume_group * vg ,
2001-10-04 21:48:55 +04:00
struct lv_disk * lvd )
{
2001-10-08 20:08:16 +04:00
struct lv_list * ll = pool_alloc ( mem , sizeof ( * ll ) ) ;
struct logical_volume * lv ;
2001-10-04 21:48:55 +04:00
2001-10-08 20:08:16 +04:00
if ( ! ll ) {
2001-10-04 21:48:55 +04:00
stack ;
return 0 ;
}
2001-10-08 20:08:16 +04:00
lv = & ll - > lv ;
2001-10-04 21:48:55 +04:00
2001-10-08 20:08:16 +04:00
memset ( & lv - > id . uuid , 0 , sizeof ( lv - > id ) ) ;
2001-10-08 13:45:16 +04:00
if ( ! ( lv - > name = pool_strdup ( mem , lvd - > lv_name ) ) ) {
2001-10-04 21:48:55 +04:00
stack ;
return 0 ;
}
2001-10-08 13:45:16 +04:00
// FIXME: finish
//lv->access = lvd->lv_access;
//lv->status = lvd->lv_status;
2001-10-04 21:48:55 +04:00
lv - > open = lvd - > lv_open ;
lv - > size = lvd - > lv_size ;
2001-10-08 13:45:16 +04:00
lv - > le_count = lvd - > lv_allocated_le ;
2001-10-04 21:48:55 +04:00
lv - > map = pool_alloc ( mem , sizeof ( struct pe_specifier ) * lv - > le_count ) ;
if ( ! lv - > map ) {
stack ;
return 0 ;
}
2001-10-08 20:08:16 +04:00
list_add ( & ll - > list , & vg - > lvs ) ;
2001-10-08 21:28:49 +04:00
vg - > lv_count + + ;
2001-10-08 20:08:16 +04:00
2001-10-08 13:45:16 +04:00
return lv ;
2001-10-04 21:48:55 +04:00
}
static int _import_lvs ( struct pool * mem , struct volume_group * vg ,
struct list_head * pvs )
{
2001-10-08 13:45:16 +04:00
struct list_head * tmp , * tmp2 ;
2001-10-04 21:48:55 +04:00
struct disk_list * dl ;
2001-10-08 13:45:16 +04:00
struct lvd_list * ll ;
2001-10-04 21:48:55 +04:00
struct lv_disk * lvd ;
list_for_each ( tmp , pvs ) {
dl = list_entry ( tmp , struct disk_list , list ) ;
list_for_each ( tmp2 , & dl - > lvs ) {
2001-10-08 13:45:16 +04:00
ll = list_entry ( tmp2 , struct lvd_list , list ) ;
2001-10-05 17:59:44 +04:00
lvd = & ll - > lv ;
2001-10-08 13:45:16 +04:00
if ( ! _find_lv ( vg , lvd - > lv_name ) & &
! _add_lv ( mem , vg , lvd ) ) {
2001-10-04 21:48:55 +04:00
stack ;
return 0 ;
}
}
}
return 1 ;
}
2001-10-08 13:45:16 +04:00
static int _fill_lv_array ( struct logical_volume * * lvs ,
2001-10-05 17:59:44 +04:00
struct volume_group * vg , struct disk_list * dl )
{
struct list_head * tmp ;
struct logical_volume * lv ;
int i = 0 ;
list_for_each ( tmp , & dl - > lvs ) {
2001-10-08 13:45:16 +04:00
struct lvd_list * ll = list_entry ( tmp , struct lvd_list , list ) ;
2001-10-05 17:59:44 +04:00
2001-10-08 13:45:16 +04:00
if ( ! ( lv = _find_lv ( vg , ll - > lv . lv_name ) ) ) {
2001-10-05 17:59:44 +04:00
stack ;
return 0 ;
}
lvs [ i ] = lv ;
i + + ;
}
return 1 ;
}
2001-10-04 21:48:55 +04:00
static int _import_extents ( struct pool * mem , struct volume_group * vg ,
struct list_head * pvs )
{
struct list_head * tmp ;
struct disk_list * dl ;
2001-10-08 13:45:16 +04:00
struct logical_volume * lv , * lvs [ MAX_LV ] ;
2001-10-04 21:48:55 +04:00
struct physical_volume * pv ;
struct pe_disk * e ;
2001-10-05 20:36:53 +04:00
int i ;
uint32_t lv_num , le ;
2001-10-04 21:48:55 +04:00
list_for_each ( tmp , pvs ) {
dl = list_entry ( tmp , struct disk_list , list ) ;
2001-10-08 13:45:16 +04:00
pv = _find_pv ( vg , dl - > dev ) ;
2001-10-04 21:48:55 +04:00
e = dl - > extents ;
2001-10-05 17:59:44 +04:00
/* build an array of lv's for this pv */
if ( ! _fill_lv_array ( lvs , vg , dl ) ) {
stack ;
return 0 ;
}
2001-10-04 21:48:55 +04:00
for ( i = 0 ; i < dl - > pv . pe_total ; i + + ) {
2001-10-05 17:59:44 +04:00
lv_num = e [ i ] . lv_num ;
if ( lv_num = = UNMAPPED_EXTENT )
lv - > map [ le ] . pv = NULL ;
2001-10-04 21:48:55 +04:00
2001-10-08 20:08:16 +04:00
else if ( lv_num > dl - > pv . lv_cur ) {
2001-10-05 17:59:44 +04:00
log_err ( " invalid lv in extent map \n " ) ;
return 0 ;
2001-10-08 13:45:16 +04:00
} else {
2001-10-08 20:08:16 +04:00
lv_num - - ;
2001-10-05 20:36:53 +04:00
lv = lvs [ lv_num ] ;
2001-10-04 21:48:55 +04:00
le = e [ i ] . le_num ;
2001-10-05 17:59:44 +04:00
2001-10-04 21:48:55 +04:00
lv - > map [ le ] . pv = pv ;
lv - > map [ le ] . pe = i ;
}
}
}
return 1 ;
}
2001-10-08 13:45:16 +04:00
static struct volume_group * _build_vg ( struct pool * mem , struct list_head * pvs )
2001-10-04 21:48:55 +04:00
{
struct volume_group * vg = pool_alloc ( mem , sizeof ( * vg ) ) ;
if ( ! vg ) {
stack ;
return 0 ;
}
memset ( vg , 0 , sizeof ( * vg ) ) ;
2001-10-08 20:08:16 +04:00
INIT_LIST_HEAD ( & vg - > pvs ) ;
INIT_LIST_HEAD ( & vg - > lvs ) ;
2001-10-08 21:28:49 +04:00
if ( ! _import_vg ( mem , vg , pvs ) )
2001-10-04 21:48:55 +04:00
goto bad ;
2001-10-08 21:53:43 +04:00
if ( ! _import_pvs ( mem , pvs , & vg - > pvs , & vg - > pv_count ) )
2001-10-04 21:48:55 +04:00
goto bad ;
if ( ! _import_lvs ( mem , vg , pvs ) )
goto bad ;
2001-10-08 13:45:16 +04:00
if ( ! _import_extents ( mem , vg , pvs ) )
goto bad ;
2001-10-04 21:48:55 +04:00
return vg ;
bad :
stack ;
pool_free ( mem , vg ) ;
return NULL ;
}
2001-10-08 13:45:16 +04:00
static struct volume_group * _vg_read ( struct io_space * is , const char * vg_name )
2001-10-04 21:48:55 +04:00
{
struct pool * mem = pool_create ( 1024 * 10 ) ;
struct list_head pvs ;
struct volume_group * vg ;
2001-10-08 20:08:16 +04:00
INIT_LIST_HEAD ( & pvs ) ;
2001-10-04 21:48:55 +04:00
if ( ! mem ) {
stack ;
return NULL ;
}
if ( ! read_pvs_in_vg ( vg_name , is - > filter , mem , & pvs ) ) {
stack ;
return NULL ;
}
if ( ! ( vg = _build_vg ( is - > mem , & pvs ) ) ) {
stack ;
}
pool_destroy ( mem ) ;
return vg ;
}
2001-10-08 13:45:16 +04:00
#if 0
static struct disk_list * _flatten_pv ( struct pool * mem , struct volume_group * vg ,
struct physical_volume * pv )
2001-10-05 20:36:53 +04:00
{
2001-10-08 16:11:33 +04:00
2001-10-05 20:36:53 +04:00
}
static int _flatten_vg ( struct pool * mem , struct volume_group * vg ,
struct list_head * pvs )
{
struct list_head * tmp ;
struct physical_volume * pv ;
struct disk_list * data ;
list_for_each ( tmp , & vg - > pvs ) {
pv = list_entry ( tmp , struct physical_volume , list ) ;
if ( ! ( data = _flatten_pv ( vg , pv ) ) ) {
stack ;
return 0 ;
}
list_add ( & data - > list , pvs ) ;
}
return 1 ;
}
static int _vg_write ( struct io_space * is , struct volume_group * vg )
{
struct pool * mem = pool_create ( 1024 * 10 ) ;
struct list_head pvs ;
int r = 0 ;
if ( ! mem ) {
stack ;
return 0 ;
}
r = _flatten_vg ( mem , vg , & pvs ) & & write_pvs ( & pvs ) ;
pool_destroy ( mem ) ;
return r ;
}
2001-10-08 13:45:16 +04:00
# endif
2001-10-04 21:48:55 +04:00
2001-10-08 21:53:43 +04:00
static struct list_head * _get_pvs ( struct io_space * is )
{
struct pool * mem = pool_create ( 1024 * 10 ) ;
struct list_head pvs , * results ;
uint32_t count ;
if ( ! mem ) {
stack ;
return NULL ;
}
if ( ! ( results = pool_alloc ( is - > mem , sizeof ( * results ) ) ) ) {
stack ;
return NULL ;
}
INIT_LIST_HEAD ( & pvs ) ;
INIT_LIST_HEAD ( results ) ;
if ( ! read_pvs_in_vg ( NULL , is - > filter , mem , & pvs ) ) {
stack ;
goto bad ;
}
2001-10-09 12:11:52 +04:00
if ( ! _import_pvs ( is - > mem , & pvs , results , & count ) ) {
2001-10-08 21:53:43 +04:00
stack ;
goto bad ;
}
pool_destroy ( mem ) ;
return results ;
bad :
pool_destroy ( mem ) ;
pool_free ( mem , results ) ;
return NULL ;
}
2001-10-08 16:11:33 +04:00
void _destroy ( struct io_space * ios )
2001-10-04 21:48:55 +04:00
{
2001-10-08 16:11:33 +04:00
dbg_free ( ios - > prefix ) ;
dbg_free ( ios ) ;
}
struct io_space * create_lvm1_format ( const char * prefix , struct pool * mem ,
struct dev_filter * filter )
{
struct io_space * ios = dbg_malloc ( sizeof ( * ios ) ) ;
2001-10-09 12:11:52 +04:00
ios - > get_vgs = NULL ;
ios - > get_pvs = _get_pvs ;
2001-10-08 16:11:33 +04:00
ios - > pv_read = NULL ;
ios - > pv_write = NULL ;
ios - > vg_read = _vg_read ;
ios - > vg_write = NULL ;
ios - > destroy = _destroy ;
ios - > prefix = dbg_malloc ( strlen ( prefix ) + 1 ) ;
if ( ! ios - > prefix ) {
stack ;
dbg_free ( ios ) ;
return 0 ;
}
strcpy ( ios - > prefix , prefix ) ;
ios - > mem = mem ;
ios - > filter = filter ;
ios - > private = NULL ;
return ios ;
2001-10-04 21:48:55 +04:00
}