2004-06-07 23:10:21 +04:00
/*
* Copyright ( C ) 1997 - 2004 Sistina Software , Inc . All rights reserved .
* Copyright ( C ) 2004 Red Hat , Inc . All rights reserved .
*
* 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
*/
# include "lib.h"
# include "pool.h"
# include "label.h"
# include "metadata.h"
# include "lvmcache.h"
# include "disk_rep.h"
2005-01-20 21:12:41 +03:00
# include "sptype_names.h"
2004-06-07 23:10:21 +04:00
# include "lv_alloc.h"
2005-04-20 00:58:25 +04:00
# include "pv_alloc.h"
2004-06-07 23:10:21 +04:00
# include "str_list.h"
# include "display.h"
2004-09-16 22:40:56 +04:00
# include "segtype.h"
2004-06-07 23:10:21 +04:00
/* This file contains only imports at the moment... */
int import_pool_vg ( struct volume_group * vg , struct pool * mem , struct list * pls )
{
struct pool_list * pl ;
2005-06-01 20:51:55 +04:00
list_iterate_items ( pl , pls ) {
2004-06-07 23:10:21 +04:00
vg - > extent_count + =
( ( pl - > pd . pl_blocks ) / POOL_PE_SIZE ) ;
vg - > pv_count + + ;
if ( vg - > name )
continue ;
vg - > name = pool_strdup ( mem , pl - > pd . pl_pool_name ) ;
get_pool_vg_uuid ( & vg - > id , & pl - > pd ) ;
vg - > extent_size = POOL_PE_SIZE ;
vg - > status | = LVM_READ | LVM_WRITE | CLUSTERED | SHARED ;
vg - > free_count = 0 ;
vg - > max_lv = 1 ;
vg - > max_pv = POOL_MAX_DEVICES ;
vg - > alloc = ALLOC_NORMAL ;
vg - > lv_count = 0 ;
}
return 1 ;
}
int import_pool_lvs ( struct volume_group * vg , struct pool * mem , struct list * pls )
{
struct pool_list * pl ;
struct lv_list * lvl = pool_zalloc ( mem , sizeof ( * lvl ) ) ;
struct logical_volume * lv ;
if ( ! lvl ) {
log_error ( " Unable to allocate lv list structure " ) ;
return 0 ;
}
if ( ! ( lvl - > lv = pool_zalloc ( mem , sizeof ( * lvl - > lv ) ) ) ) {
log_error ( " Unable to allocate logical volume structure " ) ;
return 0 ;
}
lv = lvl - > lv ;
lv - > status = 0 ;
lv - > vg = vg ;
lv - > alloc = ALLOC_NORMAL ;
lv - > size = 0 ;
lv - > name = NULL ;
lv - > le_count = 0 ;
lv - > read_ahead = 0 ;
2005-04-07 16:39:44 +04:00
lv - > snapshot = NULL ;
list_init ( & lv - > snapshot_segs ) ;
2004-06-07 23:10:21 +04:00
list_init ( & lv - > segments ) ;
list_init ( & lv - > tags ) ;
2005-06-01 20:51:55 +04:00
list_iterate_items ( pl , pls ) {
2004-06-07 23:10:21 +04:00
lv - > size + = pl - > pd . pl_blocks ;
if ( lv - > name )
continue ;
if ( ! ( lv - > name = pool_strdup ( mem , pl - > pd . pl_pool_name ) ) ) {
stack ;
return 0 ;
}
get_pool_lv_uuid ( lv - > lvid . id , & pl - > pd ) ;
log_debug ( " Calculated lv uuid for lv %s: %s " , lv - > name ,
lv - > lvid . s ) ;
lv - > status | = VISIBLE_LV | LVM_READ | LVM_WRITE ;
lv - > major = POOL_MAJOR ;
/* for pool a minor of 0 is dynamic */
if ( pl - > pd . pl_minor ) {
lv - > status | = FIXED_MINOR ;
2005-02-09 20:49:36 +03:00
lv - > minor = pl - > pd . pl_minor + MINOR_OFFSET ;
2004-06-07 23:10:21 +04:00
} else {
lv - > minor = - 1 ;
}
2005-04-07 16:39:44 +04:00
lv - > snapshot = NULL ;
list_init ( & lv - > snapshot_segs ) ;
2004-06-07 23:10:21 +04:00
list_init ( & lv - > segments ) ;
list_init ( & lv - > tags ) ;
}
lv - > le_count = lv - > size / POOL_PE_SIZE ;
lvl - > lv = lv ;
list_add ( & vg - > lvs , & lvl - > list ) ;
vg - > lv_count + + ;
return 1 ;
}
int import_pool_pvs ( const struct format_type * fmt , struct volume_group * vg ,
struct list * pvs , struct pool * mem , struct list * pls )
{
struct pv_list * pvl ;
struct pool_list * pl ;
2005-06-01 20:51:55 +04:00
list_iterate_items ( pl , pls ) {
2004-06-07 23:10:21 +04:00
if ( ! ( pvl = pool_zalloc ( mem , sizeof ( * pvl ) ) ) ) {
log_error ( " Unable to allocate pv list structure " ) ;
return 0 ;
}
if ( ! ( pvl - > pv = pool_zalloc ( mem , sizeof ( * pvl - > pv ) ) ) ) {
log_error ( " Unable to allocate pv structure " ) ;
return 0 ;
}
if ( ! import_pool_pv ( fmt , mem , vg , pvl - > pv , pl ) ) {
return 0 ;
}
pl - > pv = pvl - > pv ;
pvl - > mdas = NULL ;
2004-08-18 01:55:23 +04:00
pvl - > pe_ranges = NULL ;
2004-06-07 23:10:21 +04:00
list_add ( pvs , & pvl - > list ) ;
}
return 1 ;
}
int import_pool_pv ( const struct format_type * fmt , struct pool * mem ,
struct volume_group * vg , struct physical_volume * pv ,
struct pool_list * pl )
{
struct pool_disk * pd = & pl - > pd ;
memset ( pv , 0 , sizeof ( * pv ) ) ;
get_pool_pv_uuid ( & pv - > id , pd ) ;
pv - > fmt = fmt ;
pv - > dev = pl - > dev ;
if ( ! ( pv - > vg_name = pool_strdup ( mem , pd - > pl_pool_name ) ) ) {
log_error ( " Unable to duplicate vg_name string " ) ;
return 0 ;
}
pv - > status = 0 ;
pv - > size = pd - > pl_blocks ;
pv - > pe_size = POOL_PE_SIZE ;
pv - > pe_start = POOL_PE_START ;
pv - > pe_count = pv - > size / POOL_PE_SIZE ;
2005-06-01 20:51:55 +04:00
pv - > pe_alloc_count = 0 ;
2004-06-07 23:10:21 +04:00
list_init ( & pv - > tags ) ;
2005-04-20 00:58:25 +04:00
list_init ( & pv - > segments ) ;
if ( ! alloc_pv_segment_whole_pv ( mem , pv ) ) {
stack ;
return 0 ;
}
2004-06-07 23:10:21 +04:00
return 1 ;
}
static const char * _cvt_sptype ( uint32_t sptype )
{
int i ;
for ( i = 0 ; sptype_names [ i ] . name [ 0 ] ; i + + ) {
if ( sptype = = sptype_names [ i ] . label ) {
break ;
}
}
log_debug ( " Found sptype %X and converted it to %s " ,
sptype , sptype_names [ i ] . name ) ;
return sptype_names [ i ] . name ;
}
static int _add_stripe_seg ( struct pool * mem ,
struct user_subpool * usp , struct logical_volume * lv ,
uint32_t * le_cur )
{
struct lv_segment * seg ;
2005-04-22 19:44:00 +04:00
struct segment_type * segtype ;
2004-06-07 23:10:21 +04:00
int j ;
2005-04-22 19:44:00 +04:00
uint32_t area_len ;
2004-06-07 23:10:21 +04:00
2005-04-22 19:43:02 +04:00
if ( usp - > striping & ( usp - > striping - 1 ) ) {
2004-06-07 23:10:21 +04:00
log_error ( " Stripe size must be a power of 2 " ) ;
return 0 ;
}
2005-04-22 19:44:00 +04:00
area_len = ( usp - > devs [ 0 ] . blocks ) / POOL_PE_SIZE ;
2004-06-07 23:10:21 +04:00
2005-04-22 19:44:00 +04:00
if ( ! ( segtype = get_segtype_from_string ( lv - > vg - > cmd ,
" striped " ) ) ) {
stack ;
return 0 ;
}
2004-06-07 23:10:21 +04:00
2005-04-22 19:44:00 +04:00
if ( ! ( seg = alloc_lv_segment ( mem , segtype , lv , * le_cur ,
area_len * usp - > num_devs , 0 ,
2005-06-01 20:51:55 +04:00
usp - > striping , NULL , usp - > num_devs ,
area_len , 0 , 0 , 0 ) ) ) {
2005-04-22 19:44:00 +04:00
log_error ( " Unable to allocate striped lv_segment structure " ) ;
return 0 ;
}
2004-06-07 23:10:21 +04:00
2005-04-22 19:44:00 +04:00
for ( j = 0 ; j < usp - > num_devs ; j + + )
2005-05-03 21:28:23 +04:00
if ( ! set_lv_segment_area_pv ( seg , j , usp - > devs [ j ] . pv , 0 ) ) {
stack ;
return 0 ;
}
2005-04-22 19:44:00 +04:00
/* add the subpool type to the segment tag list */
str_list_add ( mem , & seg - > tags , _cvt_sptype ( usp - > type ) ) ;
2005-04-22 19:43:02 +04:00
2004-06-07 23:10:21 +04:00
list_add ( & lv - > segments , & seg - > list ) ;
2005-04-22 19:43:02 +04:00
2005-04-22 19:44:00 +04:00
* le_cur + = seg - > len ;
2004-06-07 23:10:21 +04:00
return 1 ;
}
static int _add_linear_seg ( struct pool * mem ,
struct user_subpool * usp , struct logical_volume * lv ,
uint32_t * le_cur )
{
struct lv_segment * seg ;
2005-04-22 19:44:00 +04:00
struct segment_type * segtype ;
2004-06-07 23:10:21 +04:00
int j ;
2005-04-22 19:44:00 +04:00
uint32_t area_len ;
if ( ! ( segtype = get_segtype_from_string ( lv - > vg - > cmd , " striped " ) ) ) {
stack ;
return 0 ;
}
2004-06-07 23:10:21 +04:00
for ( j = 0 ; j < usp - > num_devs ; j + + ) {
2005-04-22 19:44:00 +04:00
area_len = ( usp - > devs [ j ] . blocks ) / POOL_PE_SIZE ;
if ( ! ( seg = alloc_lv_segment ( mem , segtype , lv , * le_cur ,
area_len , 0 , usp - > striping ,
2005-06-01 20:51:55 +04:00
NULL , 1 , area_len ,
POOL_PE_SIZE , 0 , 0 ) ) ) {
2004-06-07 23:10:21 +04:00
log_error ( " Unable to allocate linear lv_segment "
" structure " ) ;
return 0 ;
}
2005-04-22 19:44:00 +04:00
2004-06-07 23:10:21 +04:00
/* add the subpool type to the segment tag list */
str_list_add ( mem , & seg - > tags , _cvt_sptype ( usp - > type ) ) ;
2005-05-03 21:28:23 +04:00
if ( ! set_lv_segment_area_pv ( seg , 0 , usp - > devs [ j ] . pv , 0 ) ) {
stack ;
return 0 ;
}
2004-06-07 23:10:21 +04:00
list_add ( & lv - > segments , & seg - > list ) ;
2005-04-22 19:44:00 +04:00
* le_cur + = seg - > len ;
2004-06-07 23:10:21 +04:00
}
2005-04-22 19:44:00 +04:00
2004-06-07 23:10:21 +04:00
return 1 ;
}
int import_pool_segments ( struct list * lvs , struct pool * mem ,
struct user_subpool * usp , int subpools )
{
struct lv_list * lvl ;
struct logical_volume * lv ;
uint32_t le_cur = 0 ;
int i ;
2005-06-01 20:51:55 +04:00
list_iterate_items ( lvl , lvs ) {
2004-06-07 23:10:21 +04:00
lv = lvl - > lv ;
2005-04-07 16:39:44 +04:00
if ( lv - > status & SNAPSHOT )
continue ;
2004-06-07 23:10:21 +04:00
for ( i = 0 ; i < subpools ; i + + ) {
if ( usp [ i ] . striping ) {
if ( ! _add_stripe_seg ( mem , & usp [ i ] , lv , & le_cur ) ) {
stack ;
return 0 ;
}
} else {
if ( ! _add_linear_seg ( mem , & usp [ i ] , lv , & le_cur ) ) {
stack ;
return 0 ;
}
}
}
}
return 1 ;
}