2001-12-17 22:46:10 +03:00
/*
2008-01-30 17:00:02 +03:00
* Copyright ( C ) 2001 - 2004 Sistina Software , Inc . All rights reserved .
2018-04-20 18:43:50 +03:00
* Copyright ( C ) 2004 - 2008 Red Hat , Inc . All rights reserved .
2001-12-17 22:46:10 +03: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
2007-08-21 00:55:30 +04:00
* of the GNU Lesser General Public License v .2 .1 .
2004-03-30 23:35:44 +04:00
*
2007-08-21 00:55:30 +04:00
* You should have received a copy of the GNU Lesser General Public License
2004-03-30 23:35:44 +04:00
* along with this program ; if not , write to the Free Software Foundation ,
2016-01-21 13:49:46 +03:00
* Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA
2001-12-17 22:46:10 +03:00
*/
2018-05-14 12:30:20 +03:00
# include "lib/misc/lib.h"
# include "lib/metadata/metadata.h"
2001-12-17 22:46:10 +03:00
# include "import-export.h"
2002-11-18 17:04:08 +03:00
/* FIXME Use tidier inclusion method */
static struct text_vg_version_ops * ( _text_vsn_list [ 2 ] ) ;
2008-03-13 15:33:22 +03:00
static int _text_import_initialised = 0 ;
2010-08-03 17:06:35 +04:00
static void _init_text_import ( void )
2008-03-13 15:33:22 +03:00
{
if ( _text_import_initialised )
return ;
_text_vsn_list [ 0 ] = text_vg_vsn1_init ( ) ;
_text_vsn_list [ 1 ] = NULL ;
_text_import_initialised = 1 ;
}
2015-03-06 12:24:26 +03:00
/*
* Find out vgname on a given device .
*/
2018-02-07 00:18:11 +03:00
int text_read_metadata_summary ( const struct format_type * fmt ,
2017-12-07 06:34:59 +03:00
struct device * dev , dev_io_reason_t reason ,
2015-03-19 02:43:02 +03:00
off_t offset , uint32_t size ,
off_t offset2 , uint32_t size2 ,
checksum_fn_t checksum_fn ,
2018-04-20 18:43:50 +03:00
int checksum_only ,
struct lvmcache_vgsummary * vgsummary )
2006-04-11 17:55:59 +04:00
{
2018-04-20 18:43:50 +03:00
struct dm_config_tree * cft ;
struct text_vg_version_ops * * vsn ;
int r = 0 ;
2006-04-11 17:55:59 +04:00
2008-03-13 15:33:22 +03:00
_init_text_import ( ) ;
2006-04-11 17:55:59 +04:00
2018-04-20 18:43:50 +03:00
if ( ! ( cft = config_open ( CONFIG_FILE_SPECIAL , NULL , 0 ) ) )
2015-03-19 02:43:02 +03:00
return_0 ;
2006-04-11 17:55:59 +04:00
2018-02-07 00:18:11 +03:00
if ( dev ) {
log_debug_metadata ( " Reading metadata summary from %s at %llu size %d (+%d) " ,
dev_name ( dev ) , ( unsigned long long ) offset ,
size , size2 ) ;
if ( ! config_file_read_fd ( cft , dev , reason , offset , size ,
2018-04-20 18:43:50 +03:00
offset2 , size2 , checksum_fn ,
vgsummary - > mda_checksum ,
2018-02-07 00:18:11 +03:00
checksum_only , 1 ) ) {
/* FIXME: handle errors */
log_error ( " Couldn't read volume group metadata from %s. " , dev_name ( dev ) ) ;
goto out ;
}
} else {
if ( ! config_file_read ( cft ) ) {
log_error ( " Couldn't read volume group metadata from file. " ) ;
goto out ;
}
2018-01-03 19:00:52 +03:00
}
2018-04-20 18:43:50 +03:00
if ( checksum_only ) {
/* Checksum matches already-cached content - no need to reparse. */
2018-02-07 00:18:11 +03:00
log_debug_metadata ( " Skipped parsing metadata on %s " , dev_name ( dev ) ) ;
2018-04-20 18:43:50 +03:00
r = 1 ;
2015-03-19 02:43:02 +03:00
goto out ;
}
2015-03-06 12:24:26 +03:00
2008-01-30 17:00:02 +03:00
/*
2006-04-11 17:55:59 +04:00
* Find a set of version functions that can read this file
*/
for ( vsn = & _text_vsn_list [ 0 ] ; * vsn ; vsn + + ) {
2018-04-20 18:43:50 +03:00
if ( ! ( * vsn ) - > check_version ( cft ) )
2006-04-11 17:55:59 +04:00
continue ;
2018-04-20 18:43:50 +03:00
if ( ! ( * vsn ) - > read_vgsummary ( fmt , cft , vgsummary ) )
2006-04-11 17:55:59 +04:00
goto_out ;
2018-04-20 18:43:50 +03:00
r = 1 ;
2006-04-11 17:55:59 +04:00
break ;
}
2018-04-20 18:43:50 +03:00
out :
config_destroy ( cft ) ;
return r ;
2018-01-03 19:00:52 +03:00
}
2015-03-19 02:43:02 +03:00
2018-04-20 18:43:50 +03:00
struct cached_vg_fmtdata {
uint32_t cached_mda_checksum ;
size_t cached_mda_size ;
} ;
2018-02-07 00:18:11 +03:00
struct volume_group * text_read_metadata ( struct format_instance * fid ,
2002-11-18 17:04:08 +03:00
const char * file ,
2015-03-19 02:43:02 +03:00
struct cached_vg_fmtdata * * vg_fmtdata ,
unsigned * use_previous_vg ,
2017-12-07 06:34:59 +03:00
struct device * dev , int primary_mda ,
2002-11-18 17:04:08 +03:00
off_t offset , uint32_t size ,
off_t offset2 , uint32_t size2 ,
checksum_fn_t checksum_fn ,
2018-04-20 18:43:50 +03:00
uint32_t checksum ,
2002-11-18 17:04:08 +03:00
time_t * when , char * * desc )
2002-01-10 14:18:08 +03:00
{
2018-04-20 18:43:50 +03:00
struct volume_group * vg = NULL ;
struct dm_config_tree * cft ;
struct text_vg_version_ops * * vsn ;
int skip_parse ;
2002-01-10 14:18:08 +03:00
2018-02-07 00:18:11 +03:00
/*
* This struct holds the checksum and size of the VG metadata
* that was read from a previous device . When we read the VG
* metadata from this device , we can skip parsing it into a
* cft ( saving time ) if the checksum of the metadata buffer
* we read from this device matches the size / checksum saved in
* the mda_header / rlocn struct on this device , and matches the
* size / checksum from the previous device .
*/
2015-03-19 02:43:02 +03:00
if ( vg_fmtdata & & ! * vg_fmtdata & &
! ( * vg_fmtdata = dm_pool_zalloc ( fid - > mem , sizeof ( * * vg_fmtdata ) ) ) ) {
log_error ( " Failed to allocate VG fmtdata for text format. " ) ;
return NULL ;
}
2018-01-03 19:00:52 +03:00
_init_text_import ( ) ;
2002-01-10 19:48:28 +03:00
2018-04-20 18:43:50 +03:00
* desc = NULL ;
* when = 0 ;
2018-01-03 19:00:52 +03:00
2018-04-20 18:43:50 +03:00
if ( ! ( cft = config_open ( CONFIG_FILE_SPECIAL , file , 0 ) ) )
2006-05-10 21:51:02 +04:00
return_NULL ;
2002-01-10 14:18:08 +03:00
2015-03-19 02:43:02 +03:00
/* Does the metadata match the already-cached VG? */
2018-04-20 18:43:50 +03:00
skip_parse = vg_fmtdata & &
( ( * vg_fmtdata ) - > cached_mda_checksum = = checksum ) & &
( ( * vg_fmtdata ) - > cached_mda_size = = ( size + size2 ) ) ;
2018-02-07 00:18:11 +03:00
if ( dev ) {
log_debug_metadata ( " Reading metadata from %s at %llu size %d (+%d) " ,
dev_name ( dev ) , ( unsigned long long ) offset ,
size , size2 ) ;
if ( ! config_file_read_fd ( cft , dev , MDA_CONTENT_REASON ( primary_mda ) , offset , size ,
2018-04-20 18:43:50 +03:00
offset2 , size2 , checksum_fn , checksum ,
2018-02-07 00:18:11 +03:00
skip_parse , 1 ) ) {
/* FIXME: handle errors */
log_error ( " Couldn't read volume group metadata from %s. " , dev_name ( dev ) ) ;
goto out ;
}
} else {
if ( ! config_file_read ( cft ) ) {
log_error ( " Couldn't read volume group metadata from file. " ) ;
goto out ;
}
}
2012-03-26 15:35:26 +04:00
2018-04-20 18:43:50 +03:00
if ( skip_parse ) {
if ( use_previous_vg )
* use_previous_vg = 1 ;
2018-02-07 00:18:11 +03:00
log_debug_metadata ( " Skipped parsing metadata on %s " , dev_name ( dev ) ) ;
2018-04-20 18:43:50 +03:00
goto out ;
}
/*
* Find a set of version functions that can read this file
*/
for ( vsn = & _text_vsn_list [ 0 ] ; * vsn ; vsn + + ) {
if ( ! ( * vsn ) - > check_version ( cft ) )
continue ;
2018-02-07 00:18:11 +03:00
if ( ! ( vg = ( * vsn ) - > read_vg ( fid , cft , 0 ) ) )
2018-04-20 18:43:50 +03:00
goto_out ;
( * vsn ) - > read_desc ( vg - > vgmem , cft , when , desc ) ;
break ;
}
if ( vg & & vg_fmtdata & & * vg_fmtdata ) {
( * vg_fmtdata ) - > cached_mda_size = ( size + size2 ) ;
( * vg_fmtdata ) - > cached_mda_checksum = checksum ;
2001-12-17 22:46:10 +03:00
}
2002-04-24 22:20:51 +04:00
2018-04-20 18:43:50 +03:00
if ( use_previous_vg )
* use_previous_vg = 0 ;
2015-03-19 02:43:02 +03:00
2018-04-20 18:43:50 +03:00
out :
config_destroy ( cft ) ;
return vg ;
2001-12-17 22:46:10 +03:00
}
2018-02-07 00:18:11 +03:00
struct volume_group * text_read_metadata_file ( struct format_instance * fid ,
2002-11-18 17:04:08 +03:00
const char * file ,
time_t * when , char * * desc )
2002-02-11 14:43:17 +03:00
{
2018-02-07 00:18:11 +03:00
return text_read_metadata ( fid , file , NULL , NULL , NULL , 0 ,
( off_t ) 0 , 0 , ( off_t ) 0 , 0 , NULL , 0 ,
when , desc ) ;
2001-12-17 22:46:10 +03:00
}
2008-04-02 02:40:13 +04:00
2015-06-10 17:25:57 +03:00
static struct volume_group * _import_vg_from_config_tree ( const struct dm_config_tree * cft ,
struct format_instance * fid ,
unsigned allow_lvmetad_extensions )
2008-04-02 02:40:13 +04:00
{
struct volume_group * vg = NULL ;
struct text_vg_version_ops * * vsn ;
2011-06-17 18:39:10 +04:00
int vg_missing ;
2008-04-02 02:40:13 +04:00
_init_text_import ( ) ;
for ( vsn = & _text_vsn_list [ 0 ] ; * vsn ; vsn + + ) {
if ( ! ( * vsn ) - > check_version ( cft ) )
continue ;
2010-03-17 05:11:18 +03:00
/*
* The only path to this point uses cached vgmetadata ,
* so it can use cached PV state too .
*/
2018-02-07 00:18:11 +03:00
if ( ! ( vg = ( * vsn ) - > read_vg ( fid , cft , allow_lvmetad_extensions ) ) )
2008-04-02 02:40:13 +04:00
stack ;
2019-02-05 20:32:54 +03:00
else {
set_pv_devices ( fid , vg ) ;
if ( ( vg_missing = vg_missing_pv_count ( vg ) ) )
log_verbose ( " There are %d physical volumes missing. " , vg_missing ) ;
2011-06-17 18:39:10 +04:00
vg_mark_partial_lvs ( vg , 1 ) ;
/* FIXME: move this code inside read_vg() */
}
2008-04-02 02:40:13 +04:00
break ;
}
return vg ;
}
2015-06-10 17:25:57 +03:00
struct volume_group * import_vg_from_config_tree ( const struct dm_config_tree * cft ,
struct format_instance * fid )
{
return _import_vg_from_config_tree ( cft , fid , 0 ) ;
}