2004-06-07 23:10:21 +04:00
/*
2008-01-30 17:00:02 +03:00
* Copyright ( C ) 1997 - 2004 Sistina Software , Inc . All rights reserved .
2012-02-08 14:49:36 +04:00
* Copyright ( C ) 2004 - 2012 Red Hat , Inc . All rights reserved .
2004-06-07 23:10:21 +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-06-07 23:10:21 +04:00
*
2007-08-21 00:55:30 +04:00
* You should have received a copy of the GNU Lesser General Public License
2004-06-07 23:10:21 +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
*/
# include "lib.h"
# include "label.h"
# include "metadata.h"
# include "limits.h"
# include "display.h"
# include "toolcontext.h"
# include "lvmcache.h"
# include "disk_rep.h"
# include "format_pool.h"
# include "pool_label.h"
/* Must be called after pvs are imported */
2008-11-04 01:14:30 +03:00
static struct user_subpool * _build_usp ( struct dm_list * pls , struct dm_pool * mem ,
2004-06-07 23:10:21 +04:00
int * sps )
{
struct pool_list * pl ;
struct user_subpool * usp = NULL , * cur_sp = NULL ;
struct user_device * cur_dev = NULL ;
/*
* FIXME : Need to do some checks here - I ' m tempted to add a
* user_pool structure and build the entire thing to check against .
*/
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( pl , pls ) {
2004-06-07 23:10:21 +04:00
* sps = pl - > pd . pl_subpools ;
2005-10-17 03:03:59 +04:00
if ( ! usp & & ( ! ( usp = dm_pool_zalloc ( mem , sizeof ( * usp ) * ( * sps ) ) ) ) ) {
2004-06-07 23:10:21 +04:00
log_error ( " Unable to allocate %d subpool structures " ,
* sps ) ;
return 0 ;
}
if ( cur_sp ! = & usp [ pl - > pd . pl_sp_id ] ) {
cur_sp = & usp [ pl - > pd . pl_sp_id ] ;
cur_sp - > id = pl - > pd . pl_sp_id ;
cur_sp - > striping = pl - > pd . pl_striping ;
cur_sp - > num_devs = pl - > pd . pl_sp_devs ;
cur_sp - > type = pl - > pd . pl_sp_type ;
cur_sp - > initialized = 1 ;
}
if ( ! cur_sp - > devs & &
( ! ( cur_sp - > devs =
2005-10-17 03:03:59 +04:00
dm_pool_zalloc ( mem ,
2004-06-07 23:10:21 +04:00
sizeof ( * usp - > devs ) * pl - > pd . pl_sp_devs ) ) ) ) {
log_error ( " Unable to allocate %d pool_device "
" structures " , pl - > pd . pl_sp_devs ) ;
return 0 ;
}
2005-06-01 20:51:55 +04:00
2004-06-07 23:10:21 +04:00
cur_dev = & cur_sp - > devs [ pl - > pd . pl_sp_devid ] ;
cur_dev - > sp_id = cur_sp - > id ;
cur_dev - > devid = pl - > pd . pl_sp_id ;
cur_dev - > blocks = pl - > pd . pl_blocks ;
cur_dev - > pv = pl - > pv ;
cur_dev - > initialized = 1 ;
}
return usp ;
}
2010-12-20 16:19:13 +03:00
static int _check_usp ( const char * vgname , struct user_subpool * usp , int sp_count )
2004-06-07 23:10:21 +04:00
{
2006-05-10 01:23:51 +04:00
int i ;
unsigned j ;
2004-06-07 23:10:21 +04:00
for ( i = 0 ; i < sp_count ; i + + ) {
if ( ! usp [ i ] . initialized ) {
log_error ( " Missing subpool %d in pool %s " , i , vgname ) ;
return 0 ;
}
for ( j = 0 ; j < usp [ i ] . num_devs ; j + + ) {
if ( ! usp [ i ] . devs [ j ] . initialized ) {
2006-05-10 01:23:51 +04:00
log_error ( " Missing device %u for subpool %d "
2004-06-07 23:10:21 +04:00
" in pool %s " , j , i , vgname ) ;
return 0 ;
}
}
}
return 1 ;
}
2011-03-10 15:43:29 +03:00
static struct volume_group * _pool_vg_read ( struct format_instance * fid ,
const char * vg_name ,
struct metadata_area * mda __attribute__ ( ( unused ) ) )
2004-06-07 23:10:21 +04:00
{
2011-03-10 15:43:29 +03:00
struct volume_group * vg ;
struct user_subpool * usp ;
2004-06-07 23:10:21 +04:00
int sp_count ;
2011-03-10 15:43:29 +03:00
DM_LIST_INIT ( pds ) ;
2004-06-07 23:10:21 +04:00
2011-03-10 15:43:29 +03:00
/* We can safely ignore the mda passed in */
/* Strip dev_dir if present */
vg_name = strip_dir ( vg_name , fid - > fmt - > cmd - > dev_dir ) ;
/* Set vg_name through read_pool_pds() */
if ( ! ( vg = alloc_vg ( " pool_vg_read " , fid - > fmt - > cmd , NULL ) ) )
return_NULL ;
/* Read all the pvs in the vg */
if ( ! read_pool_pds ( fid - > fmt , vg_name , vg - > vgmem , & pds ) )
goto_bad ;
2004-06-07 23:10:21 +04:00
2011-03-11 17:50:13 +03:00
vg_set_fid ( vg , fid ) ;
2011-03-10 15:43:29 +03:00
/* Setting pool seqno to 1 because the code always did this,
* although we don ' t think it ' s needed . */
2004-06-07 23:10:21 +04:00
vg - > seqno = 1 ;
2011-03-10 15:43:29 +03:00
if ( ! import_pool_vg ( vg , vg - > vgmem , & pds ) )
goto_bad ;
2004-06-07 23:10:21 +04:00
2011-03-10 15:43:29 +03:00
if ( ! import_pool_pvs ( fid - > fmt , vg , vg - > vgmem , & pds ) )
goto_bad ;
2004-06-07 23:10:21 +04:00
2011-03-10 15:43:29 +03:00
if ( ! import_pool_lvs ( vg , vg - > vgmem , & pds ) )
goto_bad ;
2004-06-07 23:10:21 +04:00
/*
* I need an intermediate subpool structure that contains all the
* relevant info for this . Then i can iterate through the subpool
* structures for checking , and create the segments
*/
2011-03-10 15:43:29 +03:00
if ( ! ( usp = _build_usp ( & pds , vg - > vgmem , & sp_count ) ) )
goto_bad ;
2004-06-07 23:10:21 +04:00
/*
* check the subpool structures - we can ' t handle partial VGs in
* the pool format , so this will error out if we ' re missing PVs
*/
2008-01-30 16:19:47 +03:00
if ( ! _check_usp ( vg - > name , usp , sp_count ) )
2011-03-10 15:43:29 +03:00
goto_bad ;
2004-06-07 23:10:21 +04:00
2011-03-10 15:43:29 +03:00
if ( ! import_pool_segments ( & vg - > lvs , vg - > vgmem , usp , sp_count ) )
goto_bad ;
2004-06-07 23:10:21 +04:00
return vg ;
2011-03-10 15:43:29 +03:00
bad :
2011-08-11 00:25:29 +04:00
release_vg ( vg ) ;
2004-06-07 23:10:21 +04:00
2009-04-10 13:59:18 +04:00
return NULL ;
2004-06-07 23:10:21 +04:00
}
2011-02-21 15:20:18 +03:00
static int _pool_pv_initialise ( const struct format_type * fmt __attribute__ ( ( unused ) ) ,
int64_t label_sector __attribute__ ( ( unused ) ) ,
uint64_t pe_start __attribute__ ( ( unused ) ) ,
uint32_t extent_count __attribute__ ( ( unused ) ) ,
uint32_t extent_size __attribute__ ( ( unused ) ) ,
unsigned long data_alignment __attribute__ ( ( unused ) ) ,
unsigned long data_alignment_offset __attribute__ ( ( unused ) ) ,
struct physical_volume * pv __attribute__ ( ( unused ) ) )
{
return 1 ;
}
2010-07-09 19:34:40 +04:00
static int _pool_pv_setup ( const struct format_type * fmt __attribute__ ( ( unused ) ) ,
struct physical_volume * pv __attribute__ ( ( unused ) ) ,
struct volume_group * vg __attribute__ ( ( unused ) ) )
2004-06-07 23:10:21 +04:00
{
return 1 ;
}
2006-04-19 19:33:07 +04:00
static int _pool_pv_read ( const struct format_type * fmt , const char * pv_name ,
2007-08-22 18:38:18 +04:00
struct physical_volume * pv ,
2010-07-09 19:34:40 +04:00
int scan_label_only __attribute__ ( ( unused ) ) )
2004-06-07 23:10:21 +04:00
{
2005-10-17 03:03:59 +04:00
struct dm_pool * mem = dm_pool_create ( " pool pv_read " , 1024 ) ;
2004-06-07 23:10:21 +04:00
struct pool_list * pl ;
struct device * dev ;
int r = 0 ;
log_very_verbose ( " Reading physical volume data %s from disk " , pv_name ) ;
2008-01-30 16:19:47 +03:00
if ( ! mem )
return_0 ;
2004-06-07 23:10:21 +04:00
2008-01-30 16:19:47 +03:00
if ( ! ( dev = dev_cache_get ( pv_name , fmt - > cmd - > filter ) ) )
goto_out ;
2004-06-07 23:10:21 +04:00
/*
* I need to read the disk and populate a pv structure here
* I ' ll probably need to abstract some of this later for the
* vg_read code
*/
2008-01-30 16:19:47 +03:00
if ( ! ( pl = read_pool_disk ( fmt , dev , mem , NULL ) ) )
goto_out ;
2004-06-07 23:10:21 +04:00
2008-06-11 17:14:41 +04:00
if ( ! import_pool_pv ( fmt , fmt - > cmd - > mem , NULL , pv , pl ) )
2008-01-30 16:19:47 +03:00
goto_out ;
2004-06-07 23:10:21 +04:00
pv - > fmt = fmt ;
r = 1 ;
out :
2005-10-17 03:03:59 +04:00
dm_pool_destroy ( mem ) ;
2004-06-07 23:10:21 +04:00
return r ;
}
/* *INDENT-OFF* */
static struct metadata_area_ops _metadata_format_pool_ops = {
2006-05-10 01:23:51 +04:00
. vg_read = _pool_vg_read ,
2004-06-07 23:10:21 +04:00
} ;
/* *INDENT-ON* */
2006-04-19 19:33:07 +04:00
static struct format_instance * _pool_create_instance ( const struct format_type * fmt ,
2011-02-21 15:05:49 +03:00
const struct format_instance_ctx * fic )
2004-06-07 23:10:21 +04:00
{
struct format_instance * fid ;
struct metadata_area * mda ;
2011-03-11 17:30:27 +03:00
if ( ! ( fid = alloc_fid ( fmt , fic ) ) )
return_NULL ;
2004-06-07 23:10:21 +04:00
/* Define a NULL metadata area */
2011-03-11 18:10:16 +03:00
if ( ! ( mda = dm_pool_zalloc ( fid - > mem , sizeof ( * mda ) ) ) ) {
2004-06-07 23:10:21 +04:00
log_error ( " Unable to allocate metadata area structure "
" for pool format " ) ;
2011-03-11 17:38:38 +03:00
goto bad ;
2004-06-07 23:10:21 +04:00
}
mda - > ops = & _metadata_format_pool_ops ;
mda - > metadata_locn = NULL ;
2010-10-05 21:34:05 +04:00
mda - > status = 0 ;
2010-06-29 00:32:44 +04:00
dm_list_add ( & fid - > metadata_areas_in_use , & mda - > list ) ;
2004-06-07 23:10:21 +04:00
return fid ;
2011-03-11 17:38:38 +03:00
bad :
dm_pool_destroy ( fid - > mem ) ;
return NULL ;
2004-06-07 23:10:21 +04:00
}
2011-03-11 17:38:38 +03:00
static void _pool_destroy_instance ( struct format_instance * fid )
2004-06-07 23:10:21 +04:00
{
2011-03-11 17:38:38 +03:00
if ( - - fid - > ref_count < = 1 )
dm_pool_destroy ( fid - > mem ) ;
2004-06-07 23:10:21 +04:00
}
2010-12-20 16:32:49 +03:00
static void _pool_destroy ( struct format_type * fmt )
2004-06-07 23:10:21 +04:00
{
2012-02-13 15:03:59 +04:00
if ( fmt - > orphan_vg )
free_orphan_vg ( fmt - > orphan_vg ) ;
2012-02-10 06:53:03 +04:00
2010-12-20 16:32:49 +03:00
dm_free ( fmt ) ;
2004-06-07 23:10:21 +04:00
}
/* *INDENT-OFF* */
static struct format_handler _format_pool_ops = {
2006-05-10 01:23:51 +04:00
. pv_read = _pool_pv_read ,
2011-02-21 15:20:18 +03:00
. pv_initialise = _pool_pv_initialise ,
2006-05-10 01:23:51 +04:00
. pv_setup = _pool_pv_setup ,
. create_instance = _pool_create_instance ,
. destroy_instance = _pool_destroy_instance ,
. destroy = _pool_destroy ,
2004-06-07 23:10:21 +04:00
} ;
/* *INDENT-ON */
# ifdef POOL_INTERNAL
struct format_type * init_pool_format ( struct cmd_context * cmd )
# else /* Shared */
struct format_type * init_format ( struct cmd_context * cmd ) ;
struct format_type * init_format ( struct cmd_context * cmd )
# endif
{
2005-10-17 03:03:59 +04:00
struct format_type * fmt = dm_malloc ( sizeof ( * fmt ) ) ;
2012-02-10 06:53:03 +04:00
struct format_instance_ctx fic ;
struct format_instance * fid ;
2004-06-07 23:10:21 +04:00
if ( ! fmt ) {
log_error ( " Unable to allocate format type structure for pool "
" format " ) ;
return NULL ;
}
fmt - > cmd = cmd ;
fmt - > ops = & _format_pool_ops ;
fmt - > name = FMT_POOL_NAME ;
fmt - > alias = NULL ;
2008-04-08 16:49:21 +04:00
fmt - > orphan_vg_name = FMT_POOL_ORPHAN_VG_NAME ;
2004-06-07 23:10:21 +04:00
fmt - > features = 0 ;
fmt - > private = NULL ;
if ( ! ( fmt - > labeller = pool_labeller_create ( fmt ) ) ) {
log_error ( " Couldn't create pool label handler. " ) ;
2012-02-08 14:49:36 +04:00
dm_free ( fmt ) ;
2004-06-07 23:10:21 +04:00
return NULL ;
}
if ( ! ( label_register_handler ( FMT_POOL_NAME , fmt - > labeller ) ) ) {
log_error ( " Couldn't register pool label handler. " ) ;
2012-02-08 14:49:36 +04:00
fmt - > labeller - > ops - > destroy ( fmt - > labeller ) ;
dm_free ( fmt ) ;
2004-06-07 23:10:21 +04:00
return NULL ;
}
2012-02-15 05:44:58 +04:00
if ( ! ( fmt - > orphan_vg = alloc_vg ( " pool_orphan " , cmd , fmt - > orphan_vg_name ) ) ) {
2012-02-10 06:53:03 +04:00
log_error ( " Couldn't create lvm1 orphan VG. " ) ;
2012-02-13 14:56:31 +04:00
dm_free ( fmt ) ;
2012-02-10 06:53:03 +04:00
return NULL ;
}
2012-02-13 14:56:31 +04:00
2012-02-13 03:01:19 +04:00
fic . type = FMT_INSTANCE_AUX_MDAS ;
2012-02-10 06:53:03 +04:00
fic . context . vg_ref . vg_name = fmt - > orphan_vg_name ;
fic . context . vg_ref . vg_id = NULL ;
2012-02-13 14:56:31 +04:00
2012-02-10 06:53:03 +04:00
if ( ! ( fid = _pool_create_instance ( fmt , & fic ) ) ) {
2012-02-13 14:56:31 +04:00
_pool_destroy ( fmt ) ;
2012-02-10 06:53:03 +04:00
return NULL ;
}
2012-02-13 14:56:31 +04:00
2012-02-10 06:53:03 +04:00
vg_set_fid ( fmt - > orphan_vg , fid ) ;
2004-09-14 21:37:51 +04:00
log_very_verbose ( " Initialised format: %s " , fmt - > name ) ;
2004-06-07 23:10:21 +04:00
return fmt ;
}