2001-11-21 12:20:05 +03:00
/*
2008-01-30 17:00:02 +03:00
* Copyright ( C ) 2001 - 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 .
2001-11-21 12:20:05 +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-11-21 12:20:05 +03:00
*/
2002-11-18 17:04:08 +03:00
# include "lib.h"
2001-11-21 12:20:05 +03:00
# include "format-text.h"
2002-01-07 12:16:20 +03:00
# include "import-export.h"
2002-11-18 17:04:08 +03:00
# include "device.h"
2002-01-09 22:16:48 +03:00
# include "lvm-file.h"
2001-11-21 12:20:05 +03:00
# include "config.h"
2002-02-22 14:44:56 +03:00
# include "display.h"
2002-02-11 23:50:53 +03:00
# include "toolcontext.h"
2002-04-24 22:20:51 +04:00
# include "lvm-string.h"
2002-11-18 17:04:08 +03:00
# include "uuid.h"
# include "layout.h"
# include "crc.h"
# include "xlate.h"
# include "label.h"
2004-05-05 01:25:57 +04:00
# include "lvmcache.h"
2012-02-23 17:11:07 +04:00
# include "lvmetad.h"
2014-02-20 12:07:38 +04:00
# include "memlock.h"
2001-11-21 12:20:05 +03:00
2002-01-09 22:16:48 +03:00
# include <unistd.h>
2009-02-22 22:00:26 +03:00
# include <sys/param.h>
2002-01-09 22:16:48 +03:00
# include <limits.h>
2002-04-24 22:20:51 +04:00
# include <dirent.h>
2002-11-18 17:04:08 +03:00
# include <ctype.h>
2002-01-09 22:16:48 +03:00
2017-12-11 20:08:29 +03:00
/*
* Round up offset within buffer to next location that is an exact multiple of alignment .
* ( We shouldn ' t assume the start of the metadata area was aligned the same way when it was created . )
*/
# define ALIGN_ABSOLUTE(offset, buffer_start, alignment) ((offset) + (alignment) - UINT64_C(1) - ((buffer_start) + (offset) + (alignment) - UINT64_C(1)) % (alignment))
2011-02-21 15:05:49 +03:00
static struct format_instance * _text_create_text_instance ( const struct format_type * fmt ,
const struct format_instance_ctx * fic ) ;
2002-02-22 14:44:56 +03:00
2005-10-23 04:14:48 +04:00
struct text_fid_context {
char * raw_metadata_buf ;
uint32_t raw_metadata_buf_size ;
} ;
2002-04-24 22:20:51 +04:00
struct dir_list {
2008-11-04 01:14:30 +03:00
struct dm_list list ;
2002-04-24 22:20:51 +04:00
char dir [ 0 ] ;
} ;
2002-11-18 17:04:08 +03:00
struct raw_list {
2008-11-04 01:14:30 +03:00
struct dm_list list ;
2002-11-18 17:04:08 +03:00
struct device_area dev_area ;
} ;
2010-06-29 00:29:57 +04:00
int rlocn_is_ignored ( const struct raw_locn * rlocn )
{
return ( rlocn - > flags & RAW_LOCN_IGNORED ? 1 : 0 ) ;
}
2010-06-30 21:13:05 +04:00
void rlocn_set_ignored ( struct raw_locn * rlocn , unsigned mda_ignored )
2010-06-29 00:29:57 +04:00
{
2010-06-30 21:13:05 +04:00
if ( mda_ignored )
2010-06-29 00:29:57 +04:00
rlocn - > flags | = RAW_LOCN_IGNORED ;
else
rlocn - > flags & = ~ RAW_LOCN_IGNORED ;
}
2001-11-21 12:20:05 +03:00
/*
2002-12-20 02:25:55 +03:00
* NOTE : Currently there can be only one vg per text file .
2001-11-21 12:20:05 +03:00
*/
2014-10-14 21:12:15 +04:00
/*
* Only used by vgcreate .
*/
static int _text_vg_setup ( struct format_instance * fid ,
2006-05-11 21:58:58 +04:00
struct volume_group * vg )
2001-11-21 12:20:05 +03:00
{
2014-10-14 21:12:15 +04:00
if ( ! vg_check_new_extent_size ( vg - > fid - > fmt , vg - > extent_size ) )
return_0 ;
2002-04-24 22:20:51 +04:00
2002-02-22 14:44:56 +03:00
return 1 ;
2001-11-21 12:20:05 +03:00
}
2007-11-05 20:17:55 +03:00
static uint64_t _mda_free_sectors_raw ( struct metadata_area * mda )
{
struct mda_context * mdac = ( struct mda_context * ) mda - > metadata_locn ;
return mdac - > free_sectors ;
}
2009-01-10 01:44:33 +03:00
static uint64_t _mda_total_sectors_raw ( struct metadata_area * mda )
{
struct mda_context * mdac = ( struct mda_context * ) mda - > metadata_locn ;
return mdac - > area . size > > SECTOR_SHIFT ;
}
2007-03-23 15:43:17 +03:00
/*
* Check if metadata area belongs to vg
*/
2010-07-09 19:34:40 +04:00
static int _mda_in_vg_raw ( struct format_instance * fid __attribute__ ( ( unused ) ) ,
2007-03-23 15:43:17 +03:00
struct volume_group * vg , struct metadata_area * mda )
{
struct mda_context * mdac = ( struct mda_context * ) mda - > metadata_locn ;
struct pv_list * pvl ;
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( pvl , & vg - > pvs )
2007-03-23 15:43:17 +03:00
if ( pvl - > pv - > dev = = mdac - > area . dev )
return 1 ;
return 0 ;
}
2010-06-29 00:31:38 +04:00
static unsigned _mda_locns_match_raw ( struct metadata_area * mda1 ,
struct metadata_area * mda2 )
{
struct mda_context * mda1c = ( struct mda_context * ) mda1 - > metadata_locn ;
struct mda_context * mda2c = ( struct mda_context * ) mda2 - > metadata_locn ;
if ( ( mda1c - > area . dev = = mda2c - > area . dev ) & &
( mda1c - > area . start = = mda2c - > area . start ) & &
( mda1c - > area . size = = mda2c - > area . size ) )
return 1 ;
return 0 ;
}
2011-06-15 21:45:02 +04:00
static struct device * _mda_get_device_raw ( struct metadata_area * mda )
{
struct mda_context * mdac = ( struct mda_context * ) mda - > metadata_locn ;
return mdac - > area . dev ;
}
2007-04-26 01:10:55 +04:00
/*
* For circular region between region_start and region_start + region_size ,
* back up one SECTOR_SIZE from ' region_ptr ' and return the value .
* This allows reverse traversal through text metadata area to find old
* metadata .
*
* Parameters :
* region_start : start of the region ( bytes )
* region_size : size of the region ( bytes )
* region_ptr : pointer within the region ( bytes )
* NOTE : region_start < = region_ptr < = region_start + region_size
*/
static uint64_t _get_prev_sector_circular ( uint64_t region_start ,
uint64_t region_size ,
uint64_t region_ptr )
{
if ( region_ptr > = region_start + SECTOR_SIZE )
return region_ptr - SECTOR_SIZE ;
2017-07-19 17:16:12 +03:00
return ( region_start + region_size - SECTOR_SIZE ) ;
2007-04-26 01:10:55 +04:00
}
/*
* Analyze a metadata area for old metadata records in the circular buffer .
* This function just looks through and makes a first pass at the data in
* the sectors for particular things .
* FIXME : do something with each metadata area ( try to extract vg , write
* raw data to file , etc )
*/
static int _pv_analyze_mda_raw ( const struct format_type * fmt ,
struct metadata_area * mda )
{
struct mda_header * mdah ;
struct raw_locn * rlocn ;
uint64_t area_start ;
uint64_t area_size ;
2008-07-31 17:07:01 +04:00
uint64_t prev_sector , prev_sector2 ;
2007-04-26 01:10:55 +04:00
uint64_t latest_mrec_offset ;
uint64_t offset ;
uint64_t offset2 ;
2007-08-22 18:38:18 +04:00
size_t size ;
size_t size2 ;
2017-12-19 04:12:18 +03:00
char * buf = NULL ;
2007-04-26 01:10:55 +04:00
struct device_area * area ;
struct mda_context * mdac ;
2017-12-16 00:12:19 +03:00
unsigned circular = 0 ;
2007-04-26 01:10:55 +04:00
int r = 0 ;
mdac = ( struct mda_context * ) mda - > metadata_locn ;
2017-12-11 18:32:53 +03:00
log_print ( " Found text metadata area: offset= " FMTu64 " , size= "
FMTu64 , mdac - > area . start , mdac - > area . size ) ;
2007-04-26 01:10:55 +04:00
area = & mdac - > area ;
2011-05-28 13:48:14 +04:00
if ( ! dev_open_readonly ( area - > dev ) )
2007-04-26 01:10:55 +04:00
return_0 ;
2017-12-15 17:57:05 +03:00
if ( ! ( mdah = raw_read_mda_header ( fmt - > cmd - > mem , area , mda_is_primary ( mda ) ) ) )
2007-04-26 01:10:55 +04:00
goto_out ;
rlocn = mdah - > raw_locns ;
/*
* The device area includes the metadata header as well as the
* records , so remove the metadata header from the start and size
*/
area_start = area - > start + MDA_HEADER_SIZE ;
area_size = area - > size - MDA_HEADER_SIZE ;
latest_mrec_offset = rlocn - > offset + area - > start ;
/*
* Start searching at rlocn ( point of live metadata ) and go
* backwards .
*/
prev_sector = _get_prev_sector_circular ( area_start , area_size ,
latest_mrec_offset ) ;
offset = prev_sector ;
size = SECTOR_SIZE ;
offset2 = size2 = 0 ;
2010-11-29 14:16:58 +03:00
2007-04-26 01:10:55 +04:00
while ( prev_sector ! = latest_mrec_offset ) {
2008-07-31 17:07:01 +04:00
prev_sector2 = prev_sector ;
2007-04-26 01:10:55 +04:00
prev_sector = _get_prev_sector_circular ( area_start , area_size ,
prev_sector ) ;
2008-07-31 17:07:01 +04:00
if ( prev_sector > prev_sector2 )
goto_out ;
2007-04-26 01:10:55 +04:00
/*
* FIXME : for some reason , the whole metadata region from
* area - > start to area - > start + area - > size is not used .
* Only ~ 32 KB seems to contain valid metadata records
* ( LVM2 format - format_text ) . As a result , I end up with
2011-08-30 18:55:15 +04:00
* " dm_config_maybe_section " returning true when there ' s no valid
2007-04-26 01:10:55 +04:00
* metadata in a sector ( sectors with all nulls ) .
*/
2017-12-16 00:12:19 +03:00
circular = size2 ? 1 : 0 ;
if ( circular ) {
2017-12-16 01:34:26 +03:00
if ( ! ( buf = dev_read_circular ( area - > dev , offset , size , offset2 , size2 , MDA_CONTENT_REASON ( mda_is_primary ( mda ) ) ) ) )
2017-12-16 00:12:19 +03:00
goto_out ;
2017-12-19 04:12:18 +03:00
} else if ( ! ( buf = dev_read ( area - > dev , offset , size , MDA_CONTENT_REASON ( mda_is_primary ( mda ) ) ) ) )
2017-12-16 01:34:26 +03:00
goto_out ;
2007-04-26 01:10:55 +04:00
/*
* FIXME : We could add more sophisticated metadata detection
*/
2011-08-30 18:55:15 +04:00
if ( dm_config_maybe_section ( buf , size + size2 ) ) {
2007-04-26 01:10:55 +04:00
/* FIXME: Validate region, pull out timestamp?, etc */
/* FIXME: Do something with this region */
log_verbose ( " Found LVM2 metadata record at "
2017-12-11 18:32:53 +03:00
" offset= " FMTu64 " , size= " FMTsize_t " , "
" offset2= " FMTu64 " size2= " FMTsize_t ,
2007-04-26 01:10:55 +04:00
offset , size , offset2 , size2 ) ;
offset = prev_sector ;
size = SECTOR_SIZE ;
offset2 = size2 = 0 ;
} else {
/*
* Not a complete metadata record , assume we have
* metadata and just increase the size and offset .
* Start the second region if the previous sector is
* wrapping around towards the end of the disk .
*/
if ( prev_sector > offset ) {
offset2 = prev_sector ;
size2 + = SECTOR_SIZE ;
} else {
offset = prev_sector ;
size + = SECTOR_SIZE ;
}
}
2011-08-29 17:37:36 +04:00
dm_free ( buf ) ;
2007-04-26 01:10:55 +04:00
buf = NULL ;
}
r = 1 ;
out :
2017-07-16 11:22:20 +03:00
dm_free ( buf ) ;
2007-04-26 01:10:55 +04:00
if ( ! dev_close ( area - > dev ) )
stack ;
return r ;
}
2010-07-09 19:34:40 +04:00
static int _text_lv_setup ( struct format_instance * fid __attribute__ ( ( unused ) ) ,
2006-05-11 21:58:58 +04:00
struct logical_volume * lv )
2001-11-21 12:20:05 +03:00
{
2008-01-30 17:00:02 +03:00
/******** FIXME Any LV size restriction?
2002-02-22 14:44:56 +03:00
uint64_t max_size = UINT_MAX ;
2001-11-21 12:20:05 +03:00
2002-02-22 14:44:56 +03:00
if ( lv - > size > max_size ) {
2006-05-10 01:23:51 +04:00
char * dummy = display_size ( max_size ) ;
2002-02-22 14:44:56 +03:00
log_error ( " logical volumes cannot be larger than %s " , dummy ) ;
2005-10-17 03:03:59 +04:00
dm_free ( dummy ) ;
2002-02-22 14:44:56 +03:00
return 0 ;
}
2002-11-18 19:21:00 +03:00
*/
2005-01-20 21:11:53 +03:00
if ( ! * lv - > lvid . s & & ! lvid_create ( & lv - > lvid , & lv - > vg - > id ) ) {
log_error ( " Random lvid creation failed for %s/%s. " ,
lv - > vg - > name , lv - > name ) ;
return 0 ;
}
2002-02-22 14:44:56 +03:00
return 1 ;
2001-11-21 12:20:05 +03:00
}
2002-11-18 17:04:08 +03:00
static void _xlate_mdah ( struct mda_header * mdah )
{
struct raw_locn * rl ;
mdah - > version = xlate32 ( mdah - > version ) ;
mdah - > start = xlate64 ( mdah - > start ) ;
mdah - > size = xlate64 ( mdah - > size ) ;
rl = & mdah - > raw_locns [ 0 ] ;
while ( rl - > offset ) {
rl - > checksum = xlate32 ( rl - > checksum ) ;
rl - > offset = xlate64 ( rl - > offset ) ;
rl - > size = xlate64 ( rl - > size ) ;
rl + + ;
}
}
2017-12-07 06:34:59 +03:00
static int _raw_read_mda_header ( struct mda_header * mdah , struct device_area * dev_area , int primary_mda )
2002-11-18 17:04:08 +03:00
{
2014-02-28 19:21:09 +04:00
if ( ! dev_open_readonly ( dev_area - > dev ) )
2014-02-28 02:06:42 +04:00
return_0 ;
2002-11-18 17:04:08 +03:00
2017-12-19 04:12:18 +03:00
if ( ! dev_read_buf ( dev_area - > dev , dev_area - > start , MDA_HEADER_SIZE , MDA_HEADER_REASON ( primary_mda ) , mdah ) ) {
2014-04-04 05:28:10 +04:00
if ( ! dev_close ( dev_area - > dev ) )
stack ;
2014-02-28 02:06:42 +04:00
return_0 ;
2014-03-25 17:53:06 +04:00
}
2002-11-18 17:04:08 +03:00
2014-02-28 19:21:09 +04:00
if ( ! dev_close ( dev_area - > dev ) )
return_0 ;
2010-09-27 23:09:34 +04:00
if ( mdah - > checksum_xl ! = xlate32 ( calc_crc ( INITIAL_CRC , ( uint8_t * ) mdah - > magic ,
2002-11-18 17:04:08 +03:00
MDA_HEADER_SIZE -
sizeof ( mdah - > checksum_xl ) ) ) ) {
Add device name to output of error messages in raw_read_mda_header().
It would be helpful if we had the device name when something like
a mda_header checksum error occurs.
Before:
./tools/lvm pvs -opv_name,vg_name,uuid,mda_count,pv_mda_count_ignored,vg_mda_count,vg_mda_count_ignored,vg_mda_copies
Incorrect metadata area header checksum
PV VG PV UUID #PMda #PMdaIgn #VMda #VMdaIgn #VMdaCps
/dev/loop0 vgtest2 sVv26t-gjpb-Rcau-uBDO-Cx04-GbRR-6Ssq7e 2 0 4 0 4
/dev/loop1 vgtest2 zXWStT-qE8F-mbkc-RfgH-aytv-mptF-Y5Ce09 2 0 4 0 4
/dev/loop2 riCpK9-9G8r-LlIp-i2oh-mb3N-CUzk-u5YpuR 1 0 0 0 0
/dev/loop3 vgtest tQCUjm-rmyd-i92d-4eeE-UYBW-v1vQ-kRaA17 2 0 4 2 0
/dev/loop4 vgtest ZRvpeI-p8F1-ccVW-BBac-xhl1-aGXU-CbP0oo 2 2 4 2 0
After:
./tools/lvm pvs -opv_name,vg_name,uuid,mda_count,pv_mda_count_ignored,vg_mda_count,vg_mda_count_ignored,vg_mda_copies
Incorrect metadata area header checksum on /dev/loop2 at offset 4096
PV VG PV UUID #PMda #PMdaIgn #VMda #VMdaIgn #VMdaCps
/dev/loop0 vgtest2 sVv26t-gjpb-Rcau-uBDO-Cx04-GbRR-6Ssq7e 2 0 4 0 4
/dev/loop1 vgtest2 zXWStT-qE8F-mbkc-RfgH-aytv-mptF-Y5Ce09 2 0 4 0 4
/dev/loop2 riCpK9-9G8r-LlIp-i2oh-mb3N-CUzk-u5YpuR 1 0 0 0 0
/dev/loop3 vgtest tQCUjm-rmyd-i92d-4eeE-UYBW-v1vQ-kRaA17 2 0 4 2 0
/dev/loop4 vgtest ZRvpeI-p8F1-ccVW-BBac-xhl1-aGXU-CbP0oo 2 2 4 2 0
2010-06-22 23:18:27 +04:00
log_error ( " Incorrect metadata area header checksum on %s "
2017-12-11 18:32:53 +03:00
" at offset " FMTu64 , dev_name ( dev_area - > dev ) ,
Add device name to output of error messages in raw_read_mda_header().
It would be helpful if we had the device name when something like
a mda_header checksum error occurs.
Before:
./tools/lvm pvs -opv_name,vg_name,uuid,mda_count,pv_mda_count_ignored,vg_mda_count,vg_mda_count_ignored,vg_mda_copies
Incorrect metadata area header checksum
PV VG PV UUID #PMda #PMdaIgn #VMda #VMdaIgn #VMdaCps
/dev/loop0 vgtest2 sVv26t-gjpb-Rcau-uBDO-Cx04-GbRR-6Ssq7e 2 0 4 0 4
/dev/loop1 vgtest2 zXWStT-qE8F-mbkc-RfgH-aytv-mptF-Y5Ce09 2 0 4 0 4
/dev/loop2 riCpK9-9G8r-LlIp-i2oh-mb3N-CUzk-u5YpuR 1 0 0 0 0
/dev/loop3 vgtest tQCUjm-rmyd-i92d-4eeE-UYBW-v1vQ-kRaA17 2 0 4 2 0
/dev/loop4 vgtest ZRvpeI-p8F1-ccVW-BBac-xhl1-aGXU-CbP0oo 2 2 4 2 0
After:
./tools/lvm pvs -opv_name,vg_name,uuid,mda_count,pv_mda_count_ignored,vg_mda_count,vg_mda_count_ignored,vg_mda_copies
Incorrect metadata area header checksum on /dev/loop2 at offset 4096
PV VG PV UUID #PMda #PMdaIgn #VMda #VMdaIgn #VMdaCps
/dev/loop0 vgtest2 sVv26t-gjpb-Rcau-uBDO-Cx04-GbRR-6Ssq7e 2 0 4 0 4
/dev/loop1 vgtest2 zXWStT-qE8F-mbkc-RfgH-aytv-mptF-Y5Ce09 2 0 4 0 4
/dev/loop2 riCpK9-9G8r-LlIp-i2oh-mb3N-CUzk-u5YpuR 1 0 0 0 0
/dev/loop3 vgtest tQCUjm-rmyd-i92d-4eeE-UYBW-v1vQ-kRaA17 2 0 4 2 0
/dev/loop4 vgtest ZRvpeI-p8F1-ccVW-BBac-xhl1-aGXU-CbP0oo 2 2 4 2 0
2010-06-22 23:18:27 +04:00
dev_area - > start ) ;
2014-02-28 02:06:42 +04:00
return 0 ;
2002-11-18 17:04:08 +03:00
}
_xlate_mdah ( mdah ) ;
2006-05-10 01:23:51 +04:00
if ( strncmp ( ( char * ) mdah - > magic , FMTT_MAGIC , sizeof ( mdah - > magic ) ) ) {
Add device name to output of error messages in raw_read_mda_header().
It would be helpful if we had the device name when something like
a mda_header checksum error occurs.
Before:
./tools/lvm pvs -opv_name,vg_name,uuid,mda_count,pv_mda_count_ignored,vg_mda_count,vg_mda_count_ignored,vg_mda_copies
Incorrect metadata area header checksum
PV VG PV UUID #PMda #PMdaIgn #VMda #VMdaIgn #VMdaCps
/dev/loop0 vgtest2 sVv26t-gjpb-Rcau-uBDO-Cx04-GbRR-6Ssq7e 2 0 4 0 4
/dev/loop1 vgtest2 zXWStT-qE8F-mbkc-RfgH-aytv-mptF-Y5Ce09 2 0 4 0 4
/dev/loop2 riCpK9-9G8r-LlIp-i2oh-mb3N-CUzk-u5YpuR 1 0 0 0 0
/dev/loop3 vgtest tQCUjm-rmyd-i92d-4eeE-UYBW-v1vQ-kRaA17 2 0 4 2 0
/dev/loop4 vgtest ZRvpeI-p8F1-ccVW-BBac-xhl1-aGXU-CbP0oo 2 2 4 2 0
After:
./tools/lvm pvs -opv_name,vg_name,uuid,mda_count,pv_mda_count_ignored,vg_mda_count,vg_mda_count_ignored,vg_mda_copies
Incorrect metadata area header checksum on /dev/loop2 at offset 4096
PV VG PV UUID #PMda #PMdaIgn #VMda #VMdaIgn #VMdaCps
/dev/loop0 vgtest2 sVv26t-gjpb-Rcau-uBDO-Cx04-GbRR-6Ssq7e 2 0 4 0 4
/dev/loop1 vgtest2 zXWStT-qE8F-mbkc-RfgH-aytv-mptF-Y5Ce09 2 0 4 0 4
/dev/loop2 riCpK9-9G8r-LlIp-i2oh-mb3N-CUzk-u5YpuR 1 0 0 0 0
/dev/loop3 vgtest tQCUjm-rmyd-i92d-4eeE-UYBW-v1vQ-kRaA17 2 0 4 2 0
/dev/loop4 vgtest ZRvpeI-p8F1-ccVW-BBac-xhl1-aGXU-CbP0oo 2 2 4 2 0
2010-06-22 23:18:27 +04:00
log_error ( " Wrong magic number in metadata area header on %s "
2017-12-11 18:32:53 +03:00
" at offset " FMTu64 , dev_name ( dev_area - > dev ) ,
Add device name to output of error messages in raw_read_mda_header().
It would be helpful if we had the device name when something like
a mda_header checksum error occurs.
Before:
./tools/lvm pvs -opv_name,vg_name,uuid,mda_count,pv_mda_count_ignored,vg_mda_count,vg_mda_count_ignored,vg_mda_copies
Incorrect metadata area header checksum
PV VG PV UUID #PMda #PMdaIgn #VMda #VMdaIgn #VMdaCps
/dev/loop0 vgtest2 sVv26t-gjpb-Rcau-uBDO-Cx04-GbRR-6Ssq7e 2 0 4 0 4
/dev/loop1 vgtest2 zXWStT-qE8F-mbkc-RfgH-aytv-mptF-Y5Ce09 2 0 4 0 4
/dev/loop2 riCpK9-9G8r-LlIp-i2oh-mb3N-CUzk-u5YpuR 1 0 0 0 0
/dev/loop3 vgtest tQCUjm-rmyd-i92d-4eeE-UYBW-v1vQ-kRaA17 2 0 4 2 0
/dev/loop4 vgtest ZRvpeI-p8F1-ccVW-BBac-xhl1-aGXU-CbP0oo 2 2 4 2 0
After:
./tools/lvm pvs -opv_name,vg_name,uuid,mda_count,pv_mda_count_ignored,vg_mda_count,vg_mda_count_ignored,vg_mda_copies
Incorrect metadata area header checksum on /dev/loop2 at offset 4096
PV VG PV UUID #PMda #PMdaIgn #VMda #VMdaIgn #VMdaCps
/dev/loop0 vgtest2 sVv26t-gjpb-Rcau-uBDO-Cx04-GbRR-6Ssq7e 2 0 4 0 4
/dev/loop1 vgtest2 zXWStT-qE8F-mbkc-RfgH-aytv-mptF-Y5Ce09 2 0 4 0 4
/dev/loop2 riCpK9-9G8r-LlIp-i2oh-mb3N-CUzk-u5YpuR 1 0 0 0 0
/dev/loop3 vgtest tQCUjm-rmyd-i92d-4eeE-UYBW-v1vQ-kRaA17 2 0 4 2 0
/dev/loop4 vgtest ZRvpeI-p8F1-ccVW-BBac-xhl1-aGXU-CbP0oo 2 2 4 2 0
2010-06-22 23:18:27 +04:00
dev_area - > start ) ;
2014-02-28 02:06:42 +04:00
return 0 ;
2002-11-18 17:04:08 +03:00
}
if ( mdah - > version ! = FMTT_VERSION ) {
Add device name to output of error messages in raw_read_mda_header().
It would be helpful if we had the device name when something like
a mda_header checksum error occurs.
Before:
./tools/lvm pvs -opv_name,vg_name,uuid,mda_count,pv_mda_count_ignored,vg_mda_count,vg_mda_count_ignored,vg_mda_copies
Incorrect metadata area header checksum
PV VG PV UUID #PMda #PMdaIgn #VMda #VMdaIgn #VMdaCps
/dev/loop0 vgtest2 sVv26t-gjpb-Rcau-uBDO-Cx04-GbRR-6Ssq7e 2 0 4 0 4
/dev/loop1 vgtest2 zXWStT-qE8F-mbkc-RfgH-aytv-mptF-Y5Ce09 2 0 4 0 4
/dev/loop2 riCpK9-9G8r-LlIp-i2oh-mb3N-CUzk-u5YpuR 1 0 0 0 0
/dev/loop3 vgtest tQCUjm-rmyd-i92d-4eeE-UYBW-v1vQ-kRaA17 2 0 4 2 0
/dev/loop4 vgtest ZRvpeI-p8F1-ccVW-BBac-xhl1-aGXU-CbP0oo 2 2 4 2 0
After:
./tools/lvm pvs -opv_name,vg_name,uuid,mda_count,pv_mda_count_ignored,vg_mda_count,vg_mda_count_ignored,vg_mda_copies
Incorrect metadata area header checksum on /dev/loop2 at offset 4096
PV VG PV UUID #PMda #PMdaIgn #VMda #VMdaIgn #VMdaCps
/dev/loop0 vgtest2 sVv26t-gjpb-Rcau-uBDO-Cx04-GbRR-6Ssq7e 2 0 4 0 4
/dev/loop1 vgtest2 zXWStT-qE8F-mbkc-RfgH-aytv-mptF-Y5Ce09 2 0 4 0 4
/dev/loop2 riCpK9-9G8r-LlIp-i2oh-mb3N-CUzk-u5YpuR 1 0 0 0 0
/dev/loop3 vgtest tQCUjm-rmyd-i92d-4eeE-UYBW-v1vQ-kRaA17 2 0 4 2 0
/dev/loop4 vgtest ZRvpeI-p8F1-ccVW-BBac-xhl1-aGXU-CbP0oo 2 2 4 2 0
2010-06-22 23:18:27 +04:00
log_error ( " Incompatible metadata area header version: %d on %s "
2017-12-11 18:32:53 +03:00
" at offset " FMTu64 , mdah - > version ,
Add device name to output of error messages in raw_read_mda_header().
It would be helpful if we had the device name when something like
a mda_header checksum error occurs.
Before:
./tools/lvm pvs -opv_name,vg_name,uuid,mda_count,pv_mda_count_ignored,vg_mda_count,vg_mda_count_ignored,vg_mda_copies
Incorrect metadata area header checksum
PV VG PV UUID #PMda #PMdaIgn #VMda #VMdaIgn #VMdaCps
/dev/loop0 vgtest2 sVv26t-gjpb-Rcau-uBDO-Cx04-GbRR-6Ssq7e 2 0 4 0 4
/dev/loop1 vgtest2 zXWStT-qE8F-mbkc-RfgH-aytv-mptF-Y5Ce09 2 0 4 0 4
/dev/loop2 riCpK9-9G8r-LlIp-i2oh-mb3N-CUzk-u5YpuR 1 0 0 0 0
/dev/loop3 vgtest tQCUjm-rmyd-i92d-4eeE-UYBW-v1vQ-kRaA17 2 0 4 2 0
/dev/loop4 vgtest ZRvpeI-p8F1-ccVW-BBac-xhl1-aGXU-CbP0oo 2 2 4 2 0
After:
./tools/lvm pvs -opv_name,vg_name,uuid,mda_count,pv_mda_count_ignored,vg_mda_count,vg_mda_count_ignored,vg_mda_copies
Incorrect metadata area header checksum on /dev/loop2 at offset 4096
PV VG PV UUID #PMda #PMdaIgn #VMda #VMdaIgn #VMdaCps
/dev/loop0 vgtest2 sVv26t-gjpb-Rcau-uBDO-Cx04-GbRR-6Ssq7e 2 0 4 0 4
/dev/loop1 vgtest2 zXWStT-qE8F-mbkc-RfgH-aytv-mptF-Y5Ce09 2 0 4 0 4
/dev/loop2 riCpK9-9G8r-LlIp-i2oh-mb3N-CUzk-u5YpuR 1 0 0 0 0
/dev/loop3 vgtest tQCUjm-rmyd-i92d-4eeE-UYBW-v1vQ-kRaA17 2 0 4 2 0
/dev/loop4 vgtest ZRvpeI-p8F1-ccVW-BBac-xhl1-aGXU-CbP0oo 2 2 4 2 0
2010-06-22 23:18:27 +04:00
dev_name ( dev_area - > dev ) , dev_area - > start ) ;
2014-02-28 02:06:42 +04:00
return 0 ;
2002-11-18 17:04:08 +03:00
}
if ( mdah - > start ! = dev_area - > start ) {
2017-12-11 18:32:53 +03:00
log_error ( " Incorrect start sector in metadata area header: "
FMTu64 " on %s at offset " FMTu64 , mdah - > start ,
Add device name to output of error messages in raw_read_mda_header().
It would be helpful if we had the device name when something like
a mda_header checksum error occurs.
Before:
./tools/lvm pvs -opv_name,vg_name,uuid,mda_count,pv_mda_count_ignored,vg_mda_count,vg_mda_count_ignored,vg_mda_copies
Incorrect metadata area header checksum
PV VG PV UUID #PMda #PMdaIgn #VMda #VMdaIgn #VMdaCps
/dev/loop0 vgtest2 sVv26t-gjpb-Rcau-uBDO-Cx04-GbRR-6Ssq7e 2 0 4 0 4
/dev/loop1 vgtest2 zXWStT-qE8F-mbkc-RfgH-aytv-mptF-Y5Ce09 2 0 4 0 4
/dev/loop2 riCpK9-9G8r-LlIp-i2oh-mb3N-CUzk-u5YpuR 1 0 0 0 0
/dev/loop3 vgtest tQCUjm-rmyd-i92d-4eeE-UYBW-v1vQ-kRaA17 2 0 4 2 0
/dev/loop4 vgtest ZRvpeI-p8F1-ccVW-BBac-xhl1-aGXU-CbP0oo 2 2 4 2 0
After:
./tools/lvm pvs -opv_name,vg_name,uuid,mda_count,pv_mda_count_ignored,vg_mda_count,vg_mda_count_ignored,vg_mda_copies
Incorrect metadata area header checksum on /dev/loop2 at offset 4096
PV VG PV UUID #PMda #PMdaIgn #VMda #VMdaIgn #VMdaCps
/dev/loop0 vgtest2 sVv26t-gjpb-Rcau-uBDO-Cx04-GbRR-6Ssq7e 2 0 4 0 4
/dev/loop1 vgtest2 zXWStT-qE8F-mbkc-RfgH-aytv-mptF-Y5Ce09 2 0 4 0 4
/dev/loop2 riCpK9-9G8r-LlIp-i2oh-mb3N-CUzk-u5YpuR 1 0 0 0 0
/dev/loop3 vgtest tQCUjm-rmyd-i92d-4eeE-UYBW-v1vQ-kRaA17 2 0 4 2 0
/dev/loop4 vgtest ZRvpeI-p8F1-ccVW-BBac-xhl1-aGXU-CbP0oo 2 2 4 2 0
2010-06-22 23:18:27 +04:00
dev_name ( dev_area - > dev ) , dev_area - > start ) ;
2014-02-28 02:06:42 +04:00
return 0 ;
2002-11-18 17:04:08 +03:00
}
2014-02-28 02:06:42 +04:00
return 1 ;
}
2007-01-10 00:12:41 +03:00
2017-12-15 17:57:05 +03:00
struct mda_header * raw_read_mda_header ( struct dm_pool * mem , struct device_area * dev_area , int primary_mda )
2014-02-28 02:06:42 +04:00
{
struct mda_header * mdah ;
2017-12-15 17:57:05 +03:00
if ( ! ( mdah = dm_pool_alloc ( mem , MDA_HEADER_SIZE ) ) ) {
2014-02-28 02:06:42 +04:00
log_error ( " struct mda_header allocation failed " ) ;
return NULL ;
}
2017-12-07 06:34:59 +03:00
if ( ! _raw_read_mda_header ( mdah , dev_area , primary_mda ) ) {
2017-12-15 17:57:05 +03:00
dm_pool_free ( mem , mdah ) ;
2014-02-28 02:06:42 +04:00
return NULL ;
}
return mdah ;
2002-11-18 17:04:08 +03:00
}
2002-12-20 02:25:55 +03:00
static int _raw_write_mda_header ( const struct format_type * fmt ,
2017-12-07 06:34:59 +03:00
struct device * dev , int primary_mda ,
2002-11-18 17:04:08 +03:00
uint64_t start_byte , struct mda_header * mdah )
{
2006-05-10 01:23:51 +04:00
strncpy ( ( char * ) mdah - > magic , FMTT_MAGIC , sizeof ( mdah - > magic ) ) ;
2002-11-18 17:04:08 +03:00
mdah - > version = FMTT_VERSION ;
mdah - > start = start_byte ;
_xlate_mdah ( mdah ) ;
2010-09-27 23:09:34 +04:00
mdah - > checksum_xl = xlate32 ( calc_crc ( INITIAL_CRC , ( uint8_t * ) mdah - > magic ,
2002-11-18 17:04:08 +03:00
MDA_HEADER_SIZE -
sizeof ( mdah - > checksum_xl ) ) ) ;
2017-12-07 06:34:59 +03:00
if ( ! dev_write ( dev , start_byte , MDA_HEADER_SIZE , MDA_HEADER_REASON ( primary_mda ) , mdah ) )
2008-01-30 16:19:47 +03:00
return_0 ;
2002-11-18 17:04:08 +03:00
return 1 ;
}
static struct raw_locn * _find_vg_rlocn ( struct device_area * dev_area ,
2017-12-07 06:34:59 +03:00
struct mda_header * mdah , int primary_mda ,
2005-04-06 22:59:55 +04:00
const char * vgname ,
2005-10-31 23:15:28 +03:00
int * precommitted )
2002-11-18 17:04:08 +03:00
{
2002-12-20 02:25:55 +03:00
size_t len ;
2005-10-31 23:15:28 +03:00
struct raw_locn * rlocn , * rlocn_precommitted ;
2005-03-22 01:40:35 +03:00
struct lvmcache_info * info ;
2015-03-19 02:43:02 +03:00
struct lvmcache_vgsummary vgsummary_orphan = {
. vgname = FMT_TEXT_ORPHAN_VG_NAME ,
} ;
2017-10-28 00:42:00 +03:00
int rlocn_was_ignored ;
2017-12-19 04:12:18 +03:00
char * buf ;
2015-03-19 02:43:02 +03:00
memcpy ( & vgsummary_orphan . vgid , FMT_TEXT_ORPHAN_VG_NAME , sizeof ( FMT_TEXT_ORPHAN_VG_NAME ) ) ;
2002-11-18 17:04:08 +03:00
2005-04-06 22:59:55 +04:00
rlocn = mdah - > raw_locns ; /* Slot 0 */
2005-10-31 23:15:28 +03:00
rlocn_precommitted = rlocn + 1 ; /* Slot 1 */
2005-04-06 22:59:55 +04:00
2017-10-28 00:42:00 +03:00
rlocn_was_ignored = rlocn_is_ignored ( rlocn ) ;
2005-10-31 23:15:28 +03:00
/* Should we use precommitted metadata? */
if ( * precommitted & & rlocn_precommitted - > size & &
( rlocn_precommitted - > offset ! = rlocn - > offset ) ) {
rlocn = rlocn_precommitted ;
} else
* precommitted = 0 ;
2002-11-18 17:04:08 +03:00
2010-04-14 17:09:16 +04:00
/* Do not check non-existent metadata. */
if ( ! rlocn - > offset & & ! rlocn - > size )
return NULL ;
/*
* Don ' t try to check existing metadata
* if given vgname is an empty string .
*/
if ( ! * vgname )
return rlocn ;
2017-10-28 00:42:00 +03:00
/*
* If live rlocn has ignored flag , data will be out - of - date so skip further checks .
*/
if ( rlocn_was_ignored )
return rlocn ;
2005-04-06 22:59:55 +04:00
/* FIXME Loop through rlocns two-at-a-time. List null-terminated. */
2002-11-18 17:04:08 +03:00
/* FIXME Ignore if checksum incorrect!!! */
2017-12-19 04:12:18 +03:00
if ( ! ( buf = dev_read ( dev_area - > dev , dev_area - > start + rlocn - > offset ,
NAME_LEN + 2 , MDA_CONTENT_REASON ( primary_mda ) ) ) )
2008-01-30 16:19:47 +03:00
goto_bad ;
2005-04-06 22:59:55 +04:00
2017-12-19 04:12:18 +03:00
if ( ! strncmp ( buf , vgname , len = strlen ( vgname ) ) & &
( isspace ( * ( buf + len ) ) | | * ( buf + len ) = = ' { ' ) ) {
dm_free ( buf ) ;
2005-04-06 22:59:55 +04:00
return rlocn ;
2017-12-19 04:12:18 +03:00
}
dm_free ( buf ) ;
2017-07-19 17:16:12 +03:00
2017-12-11 18:32:53 +03:00
log_debug_metadata ( " Volume group name found in %smetadata on %s at " FMTu64 " does "
2017-09-22 20:02:58 +03:00
" not match expected name %s. " ,
2017-10-28 00:42:00 +03:00
* precommitted ? " precommitted " : " " ,
2017-09-22 20:02:58 +03:00
dev_name ( dev_area - > dev ) , dev_area - > start + rlocn - > offset , vgname ) ;
2002-11-18 17:04:08 +03:00
2008-01-30 16:19:47 +03:00
bad :
2016-06-06 22:04:17 +03:00
if ( ( info = lvmcache_info_from_pvid ( dev_area - > dev - > pvid , dev_area - > dev , 0 ) ) & &
2015-08-18 14:48:53 +03:00
! lvmcache_update_vgname_and_id ( info , & vgsummary_orphan ) )
stack ;
2005-03-22 01:40:35 +03:00
2002-11-18 17:04:08 +03:00
return NULL ;
}
2005-04-06 20:35:33 +04:00
/*
2017-12-12 21:36:54 +03:00
* Find first aligned offset after end of existing metadata .
* Based on the alignment provided , this is the exact offset to use for the new metadata .
* The caller is responsible for validating the result .
2005-04-06 20:35:33 +04:00
*/
2017-12-08 04:11:34 +03:00
static uint64_t _next_rlocn_offset ( struct raw_locn * rlocn , struct mda_header * mdah , uint64_t mdac_area_start , uint64_t alignment )
2002-11-18 17:04:08 +03:00
{
2017-12-12 21:46:25 +03:00
uint64_t old_end , new_start_offset ;
int old_wrapped = 0 ; /* Does the old metadata wrap around? */
2017-12-08 04:11:34 +03:00
2005-04-06 20:35:33 +04:00
if ( ! rlocn )
/* Find an empty slot */
2017-12-12 21:36:54 +03:00
/* FIXME Assumes only one VG per mdah for now */
2017-12-12 23:57:36 +03:00
return ALIGN_ABSOLUTE ( MDA_HEADER_SIZE , mdac_area_start , alignment ) ;
2017-12-08 04:11:34 +03:00
2017-12-12 21:46:25 +03:00
/* First find the end of the old metadata */
old_end = rlocn - > offset + rlocn - > size ;
if ( old_end > mdah - > size ) {
old_wrapped = 1 ;
old_end - = ( mdah - > size - MDA_HEADER_SIZE ) ;
}
2017-12-11 23:25:03 +03:00
/* Calculate new start position relative to start of buffer rounded up to absolute alignment */
2017-12-12 21:46:25 +03:00
new_start_offset = ALIGN_ABSOLUTE ( old_end , mdac_area_start , alignment ) ;
2002-11-18 17:04:08 +03:00
2017-12-12 23:57:36 +03:00
/* If new location is beyond the end of the buffer, return to start of circular buffer and realign */
if ( new_start_offset > = mdah - > size ) {
/* If the start of the buffer is occupied, move past it */
if ( old_wrapped | | rlocn - > offset = = MDA_HEADER_SIZE )
new_start_offset = old_end ;
else
new_start_offset = MDA_HEADER_SIZE ;
new_start_offset = ALIGN_ABSOLUTE ( new_start_offset , mdac_area_start , alignment ) ;
}
2017-12-08 04:11:34 +03:00
2017-12-12 23:57:36 +03:00
/*
* Note that we don ' t check here that this location isn ' t inside the existing metadata .
* If it is , then it means this value of alignment cannot be used .
*/
2017-12-08 04:11:34 +03:00
return new_start_offset ;
2002-11-18 17:04:08 +03:00
}
static int _raw_holds_vgname ( struct format_instance * fid ,
struct device_area * dev_area , const char * vgname )
{
int r = 0 ;
2005-10-31 23:15:28 +03:00
int noprecommit = 0 ;
2005-04-06 20:35:33 +04:00
struct mda_header * mdah ;
2002-11-18 17:04:08 +03:00
2011-05-28 13:48:14 +04:00
if ( ! dev_open_readonly ( dev_area - > dev ) )
2008-01-30 16:19:47 +03:00
return_0 ;
2002-11-18 17:04:08 +03:00
2017-12-15 17:57:05 +03:00
if ( ! ( mdah = raw_read_mda_header ( fid - > fmt - > cmd - > mem , dev_area , 0 ) ) )
2008-01-30 16:19:47 +03:00
return_0 ;
2005-04-06 20:35:33 +04:00
2017-12-07 06:34:59 +03:00
if ( _find_vg_rlocn ( dev_area , mdah , 0 , vgname , & noprecommit ) )
2002-11-18 17:04:08 +03:00
r = 1 ;
if ( ! dev_close ( dev_area - > dev ) )
stack ;
return r ;
}
static struct volume_group * _vg_read_raw_area ( struct format_instance * fid ,
const char * vgname ,
2005-04-06 22:59:55 +04:00
struct device_area * area ,
2015-03-19 02:43:02 +03:00
struct cached_vg_fmtdata * * vg_fmtdata ,
unsigned * use_previous_vg ,
2012-02-29 06:35:35 +04:00
int precommitted ,
2017-12-07 06:34:59 +03:00
int single_device , int primary_mda )
2002-11-18 17:04:08 +03:00
{
struct volume_group * vg = NULL ;
struct raw_locn * rlocn ;
struct mda_header * mdah ;
time_t when ;
char * desc ;
2002-12-20 02:25:55 +03:00
uint32_t wrap = 0 ;
2002-11-18 17:04:08 +03:00
2017-12-15 17:57:05 +03:00
if ( ! ( mdah = raw_read_mda_header ( fid - > fmt - > cmd - > mem , area , primary_mda ) ) )
2008-01-30 16:19:47 +03:00
goto_out ;
2002-11-18 17:04:08 +03:00
2017-12-07 06:34:59 +03:00
if ( ! ( rlocn = _find_vg_rlocn ( area , mdah , primary_mda , vgname , & precommitted ) ) ) {
2013-01-08 02:30:29 +04:00
log_debug_metadata ( " VG %s not found on %s " , vgname , dev_name ( area - > dev ) ) ;
2002-11-18 17:04:08 +03:00
goto out ;
}
if ( rlocn - > offset + rlocn - > size > mdah - > size )
2002-12-20 02:25:55 +03:00
wrap = ( uint32_t ) ( ( rlocn - > offset + rlocn - > size ) - mdah - > size ) ;
2002-11-18 17:04:08 +03:00
if ( wrap > rlocn - > offset ) {
2017-12-11 18:59:40 +03:00
log_error ( " VG %s metadata on %s ( " FMTu64 " bytes) too large for circular buffer ( " FMTu64 " bytes) " ,
vgname , dev_name ( area - > dev ) , rlocn - > size , mdah - > size - MDA_HEADER_SIZE ) ;
2002-11-18 17:04:08 +03:00
goto out ;
}
2002-12-20 02:25:55 +03:00
/* FIXME 64-bit */
2015-03-19 02:43:02 +03:00
if ( ! ( vg = text_vg_import_fd ( fid , NULL , vg_fmtdata , use_previous_vg , single_device , area - > dev ,
2017-12-07 06:34:59 +03:00
primary_mda ,
2002-12-20 02:25:55 +03:00
( off_t ) ( area - > start + rlocn - > offset ) ,
( uint32_t ) ( rlocn - > size - wrap ) ,
( off_t ) ( area - > start + MDA_HEADER_SIZE ) ,
wrap , calc_crc , rlocn - > checksum , & when ,
2015-03-19 02:43:02 +03:00
& desc ) ) & & ( ! use_previous_vg | | ! * use_previous_vg ) )
2008-01-30 16:19:47 +03:00
goto_out ;
2015-03-19 02:43:02 +03:00
if ( vg )
2017-12-11 18:32:53 +03:00
log_debug_metadata ( " Read %s %smetadata (%u) from %s at " FMTu64 " size "
FMTu64 , vg - > name , precommitted ? " pre-commit " : " " ,
2015-03-19 02:43:02 +03:00
vg - > seqno , dev_name ( area - > dev ) ,
area - > start + rlocn - > offset , rlocn - > size ) ;
else
2017-12-11 18:32:53 +03:00
log_debug_metadata ( " Skipped reading %smetadata from %s at " FMTu64 " size "
FMTu64 " with matching checksum. " , precommitted ? " pre-commit " : " " ,
2015-03-19 02:43:02 +03:00
dev_name ( area - > dev ) ,
area - > start + rlocn - > offset , rlocn - > size ) ;
2002-11-18 17:04:08 +03:00
2015-03-19 14:14:47 +03:00
if ( vg & & precommitted )
2005-10-31 23:15:28 +03:00
vg - > status | = PRECOMMITTED ;
2002-11-18 17:04:08 +03:00
out :
return vg ;
}
static struct volume_group * _vg_read_raw ( struct format_instance * fid ,
const char * vgname ,
2012-02-29 06:35:35 +04:00
struct metadata_area * mda ,
2015-03-19 02:43:02 +03:00
struct cached_vg_fmtdata * * vg_fmtdata ,
unsigned * use_previous_vg ,
2012-02-29 06:35:35 +04:00
int single_device )
2002-11-18 17:04:08 +03:00
{
struct mda_context * mdac = ( struct mda_context * ) mda - > metadata_locn ;
2010-06-29 00:30:30 +04:00
struct volume_group * vg ;
2011-05-28 13:48:14 +04:00
if ( ! dev_open_readonly ( mdac - > area . dev ) )
2010-06-29 00:30:30 +04:00
return_NULL ;
2017-12-07 06:34:59 +03:00
vg = _vg_read_raw_area ( fid , vgname , & mdac - > area , vg_fmtdata , use_previous_vg , 0 , single_device , mda_is_primary ( mda ) ) ;
2010-06-29 00:30:30 +04:00
if ( ! dev_close ( mdac - > area . dev ) )
stack ;
2002-11-18 17:04:08 +03:00
2010-06-29 00:30:30 +04:00
return vg ;
2005-04-06 22:59:55 +04:00
}
static struct volume_group * _vg_read_precommit_raw ( struct format_instance * fid ,
const char * vgname ,
2015-03-19 02:43:02 +03:00
struct metadata_area * mda ,
struct cached_vg_fmtdata * * vg_fmtdata ,
unsigned * use_previous_vg )
2005-04-06 22:59:55 +04:00
{
struct mda_context * mdac = ( struct mda_context * ) mda - > metadata_locn ;
2010-06-29 00:30:30 +04:00
struct volume_group * vg ;
2005-04-06 22:59:55 +04:00
2011-05-28 13:48:14 +04:00
if ( ! dev_open_readonly ( mdac - > area . dev ) )
2010-06-29 00:30:30 +04:00
return_NULL ;
2017-12-07 06:34:59 +03:00
vg = _vg_read_raw_area ( fid , vgname , & mdac - > area , vg_fmtdata , use_previous_vg , 1 , 0 , mda_is_primary ( mda ) ) ;
2010-06-29 00:30:30 +04:00
if ( ! dev_close ( mdac - > area . dev ) )
stack ;
return vg ;
2002-11-18 17:04:08 +03:00
}
2017-12-11 20:08:29 +03:00
static int _metadata_fits_into_buffer ( struct mda_context * mdac , struct mda_header * mdah ,
struct raw_locn * rlocn , uint64_t new_wrap )
{
uint64_t old_wrap = 0 ; /* Amount of wrap around in existing metadata */
2017-12-12 21:46:25 +03:00
uint64_t old_end = 0 ; /* The (byte after the) end of the existing metadata */
uint64_t new_end ; /* The (byte after the) end of the new metadata */
uint64_t old_start = 0 ; /* The start of the existing metadata */
uint64_t new_start = mdac - > rlocn . offset ; /* The proposed start of the new metadata */
2017-12-11 20:08:29 +03:00
2017-12-12 23:57:36 +03:00
/*
* If the ( aligned ) start of the new metadata is already beyond the end
* of the buffer this means it didn ' t fit with the given alignment .
* ( The caller has already tried to wrap it back to the start
* of the buffer but the alignment pushed it back outside . )
*/
if ( new_start > = mdah - > size )
return_0 ;
2017-12-12 21:36:54 +03:00
/* Does the total amount of metadata, old and new, fit inside the buffer? */
if ( MDA_HEADER_SIZE + ( rlocn ? rlocn - > size : 0 ) + mdac - > rlocn . size > = mdah - > size )
return_0 ;
2017-12-11 20:08:29 +03:00
2017-12-12 21:46:25 +03:00
/* If there's existing metadata, set old_start, old_end and old_wrap. */
2017-12-12 21:36:54 +03:00
if ( rlocn ) {
2017-12-12 21:46:25 +03:00
old_start = rlocn - > offset ;
old_end = old_start + rlocn - > size ;
/* Does the existing metadata wrap around the end of the buffer? */
if ( old_end > mdah - > size )
old_wrap = old_end - mdah - > size ;
2017-12-12 21:36:54 +03:00
}
2017-12-12 23:57:36 +03:00
new_end = new_wrap ? new_wrap + MDA_HEADER_SIZE : new_start + mdac - > rlocn . size ;
2017-12-11 20:08:29 +03:00
/* If both wrap around, there's necessarily overlap */
if ( new_wrap & & old_wrap )
return_0 ;
2017-12-12 21:36:54 +03:00
/* If there's no existing metadata, we're OK */
if ( ! rlocn )
return 1 ;
2017-12-11 20:08:29 +03:00
2017-12-12 21:36:54 +03:00
/* If either wraps around, there's overlap if the new end falls beyond the old start */
2017-12-12 21:46:25 +03:00
if ( ( new_wrap | | old_wrap ) & & ( new_end > old_start ) )
2017-12-11 20:08:29 +03:00
return_0 ;
2017-12-12 23:57:36 +03:00
/* If there's no wrap, check there's no overlap */
if ( ! new_wrap & & ! old_wrap & & ( old_end > new_start ) & & ( old_start < new_end ) )
return_0 ;
2017-12-11 20:08:29 +03:00
return 1 ;
}
2002-11-18 17:04:08 +03:00
static int _vg_write_raw ( struct format_instance * fid , struct volume_group * vg ,
struct metadata_area * mda )
{
struct mda_context * mdac = ( struct mda_context * ) mda - > metadata_locn ;
2005-10-23 04:14:48 +04:00
struct text_fid_context * fidtc = ( struct text_fid_context * ) fid - > private ;
2002-11-18 17:04:08 +03:00
struct raw_locn * rlocn ;
struct mda_header * mdah ;
2005-06-01 20:51:55 +04:00
struct pv_list * pvl ;
2002-11-18 17:04:08 +03:00
int r = 0 ;
2017-12-13 01:52:22 +03:00
uint64_t new_wrap = 0 ; /* Number of bytes of new metadata that wrap around to start of buffer */
2017-12-12 23:57:36 +03:00
uint64_t alignment = MDA_ALIGNMENT ;
2002-11-18 17:04:08 +03:00
int found = 0 ;
2005-10-31 23:15:28 +03:00
int noprecommit = 0 ;
2017-10-06 04:12:42 +03:00
const char * old_vg_name = NULL ;
2017-12-16 00:12:19 +03:00
uint64_t new_size_rounded = 0 ;
2002-11-18 17:04:08 +03:00
/* Ignore any mda on a PV outside the VG. vgsplit relies on this */
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( pvl , & vg - > pvs ) {
2005-06-01 20:51:55 +04:00
if ( pvl - > pv - > dev = = mdac - > area . dev ) {
2002-11-18 17:04:08 +03:00
found = 1 ;
2017-10-06 04:12:42 +03:00
if ( pvl - > pv - > status & PV_MOVED_VG )
old_vg_name = vg - > old_name ;
2002-11-18 17:04:08 +03:00
break ;
}
}
if ( ! found )
return 1 ;
2017-12-12 21:36:54 +03:00
/*
* This is paired with the following closes :
* - at the end of this fn if returning 0
* - in _vg_commit_raw_rlocn regardless of return code
* which handles commit ( but not pre - commit ) and revert .
*/
2008-01-30 16:19:47 +03:00
if ( ! dev_open ( mdac - > area . dev ) )
return_0 ;
2002-11-18 17:04:08 +03:00
2017-12-15 17:57:05 +03:00
if ( ! ( mdah = raw_read_mda_header ( fid - > fmt - > cmd - > mem , & mdac - > area , mda_is_primary ( mda ) ) ) )
2008-01-30 16:19:47 +03:00
goto_out ;
2002-11-18 17:04:08 +03:00
2017-12-13 01:52:22 +03:00
/* Following space is zero-filled up to the next MDA_ALIGNMENT boundary */
2005-10-23 04:14:48 +04:00
if ( ! fidtc - > raw_metadata_buf & &
! ( fidtc - > raw_metadata_buf_size =
text_vg_export_raw ( vg , " " , & fidtc - > raw_metadata_buf ) ) ) {
2002-11-18 17:04:08 +03:00
log_error ( " VG %s metadata writing failed " , vg - > name ) ;
goto out ;
}
2017-12-08 04:11:34 +03:00
rlocn = _find_vg_rlocn ( & mdac - > area , mdah , mda_is_primary ( mda ) , old_vg_name ? : vg - > name , & noprecommit ) ;
2005-10-23 04:14:48 +04:00
mdac - > rlocn . size = fidtc - > raw_metadata_buf_size ;
2017-12-12 21:36:54 +03:00
/* Find where the new metadata would be written with our preferred alignment */
mdac - > rlocn . offset = _next_rlocn_offset ( rlocn , mdah , mdac - > area . start , alignment ) ;
2017-12-11 20:08:29 +03:00
2017-12-12 23:57:36 +03:00
/* If metadata extends beyond the buffer, return to the start instead of wrapping it */
2002-11-18 17:04:08 +03:00
if ( mdac - > rlocn . offset + mdac - > rlocn . size > mdah - > size )
2017-12-12 23:57:36 +03:00
mdac - > rlocn . offset = ALIGN_ABSOLUTE ( MDA_HEADER_SIZE , mdac - > area . start , alignment ) ;
2002-11-18 17:04:08 +03:00
2017-12-12 23:57:36 +03:00
/*
* If the metadata doesn ' t fit into the buffer correctly with these
* settings , fall back to the 512 - byte alignment used by the original
* LVM2 code and allow the metadata to be split into two parts ,
* wrapping around from the end of the circular buffer back to the
* beginning .
*/
if ( ! _metadata_fits_into_buffer ( mdac , mdah , rlocn , 0 ) ) {
alignment = MDA_ORIGINAL_ALIGNMENT ;
mdac - > rlocn . offset = _next_rlocn_offset ( rlocn , mdah , mdac - > area . start , alignment ) ;
/* Does the new metadata wrap around? */
if ( mdac - > rlocn . offset + mdac - > rlocn . size > mdah - > size )
new_wrap = ( mdac - > rlocn . offset + mdac - > rlocn . size ) - mdah - > size ;
else
new_wrap = 0 ;
if ( ! _metadata_fits_into_buffer ( mdac , mdah , rlocn , new_wrap ) ) {
log_error ( " VG %s metadata on %s ( " FMTu64 " bytes) too large for circular buffer ( " FMTu64 " bytes with " FMTu64 " used) " ,
vg - > name , dev_name ( mdac - > area . dev ) , mdac - > rlocn . size , mdah - > size - MDA_HEADER_SIZE , rlocn ? rlocn - > size : 0 ) ;
goto out ;
}
2017-12-13 01:52:22 +03:00
new_size_rounded = mdac - > rlocn . size ;
} else {
/* Round up to a multiple of the new alignment */
if ( mdac - > rlocn . offset + new_size_rounded < mdah - > size )
new_size_rounded = ( mdac - > rlocn . size | ( alignment - 1 ) ) + 1 ;
else
new_size_rounded = mdac - > rlocn . size ;
2002-11-18 17:04:08 +03:00
}
2017-12-13 01:52:22 +03:00
log_debug_metadata ( " Writing %s metadata to %s at " FMTu64 " len " FMTu64 " (rounded to " FMTu64 " ) of " FMTu64 " aligned to " FMTu64 ,
2013-01-08 02:30:29 +04:00
vg - > name , dev_name ( mdac - > area . dev ) , mdac - > area . start +
2017-12-13 01:52:22 +03:00
mdac - > rlocn . offset , mdac - > rlocn . size - new_wrap , new_size_rounded , mdac - > rlocn . size , alignment ) ;
2002-11-18 17:04:08 +03:00
2017-12-13 01:52:22 +03:00
if ( ! new_wrap ) {
/* Write text out, in alignment-sized blocks */
if ( ! dev_write ( mdac - > area . dev , mdac - > area . start + mdac - > rlocn . offset ,
( size_t ) new_size_rounded , MDA_CONTENT_REASON ( mda_is_primary ( mda ) ) ,
fidtc - > raw_metadata_buf ) )
goto_out ;
} else {
/* Write text out, circularly */
if ( ! dev_write ( mdac - > area . dev , mdac - > area . start + mdac - > rlocn . offset ,
( size_t ) ( mdac - > rlocn . size - new_wrap ) , MDA_CONTENT_REASON ( mda_is_primary ( mda ) ) ,
fidtc - > raw_metadata_buf ) )
goto_out ;
2002-11-18 17:04:08 +03:00
2017-12-11 18:59:40 +03:00
log_debug_metadata ( " Writing wrapped metadata to %s at " FMTu64 " len " FMTu64 " of " FMTu64 ,
2013-01-08 02:30:29 +04:00
dev_name ( mdac - > area . dev ) , mdac - > area . start +
2017-12-11 18:59:40 +03:00
MDA_HEADER_SIZE , new_wrap , mdac - > rlocn . size ) ;
2002-11-18 17:04:08 +03:00
2017-12-05 02:18:56 +03:00
if ( ! dev_write ( mdac - > area . dev , mdac - > area . start + MDA_HEADER_SIZE ,
2017-12-07 06:34:59 +03:00
( size_t ) new_wrap , MDA_CONTENT_REASON ( mda_is_primary ( mda ) ) ,
2017-12-05 02:18:56 +03:00
fidtc - > raw_metadata_buf + mdac - > rlocn . size - new_wrap ) )
2008-01-30 16:19:47 +03:00
goto_out ;
2002-11-18 17:04:08 +03:00
}
2010-09-27 23:09:34 +04:00
mdac - > rlocn . checksum = calc_crc ( INITIAL_CRC , ( uint8_t * ) fidtc - > raw_metadata_buf ,
2002-12-20 02:25:55 +03:00
( uint32_t ) ( mdac - > rlocn . size -
new_wrap ) ) ;
2002-11-18 17:04:08 +03:00
if ( new_wrap )
mdac - > rlocn . checksum = calc_crc ( mdac - > rlocn . checksum ,
2010-09-27 23:09:34 +04:00
( uint8_t * ) fidtc - > raw_metadata_buf +
2005-10-23 04:14:48 +04:00
mdac - > rlocn . size -
2008-10-17 04:55:46 +04:00
new_wrap , ( uint32_t ) new_wrap ) ;
2002-11-18 17:04:08 +03:00
r = 1 ;
out :
2008-10-01 00:37:52 +04:00
if ( ! r ) {
if ( ! dev_close ( mdac - > area . dev ) )
stack ;
2014-03-24 12:20:18 +04:00
dm_free ( fidtc - > raw_metadata_buf ) ;
fidtc - > raw_metadata_buf = NULL ;
2008-10-01 00:37:52 +04:00
}
2002-11-18 17:04:08 +03:00
return r ;
}
2005-04-06 22:59:55 +04:00
static int _vg_commit_raw_rlocn ( struct format_instance * fid ,
struct volume_group * vg ,
struct metadata_area * mda ,
int precommit )
2002-11-18 17:04:08 +03:00
{
struct mda_context * mdac = ( struct mda_context * ) mda - > metadata_locn ;
2005-10-23 04:14:48 +04:00
struct text_fid_context * fidtc = ( struct text_fid_context * ) fid - > private ;
2002-11-18 17:04:08 +03:00
struct mda_header * mdah ;
struct raw_locn * rlocn ;
2005-06-01 20:51:55 +04:00
struct pv_list * pvl ;
2002-11-18 17:04:08 +03:00
int r = 0 ;
int found = 0 ;
2005-10-31 23:15:28 +03:00
int noprecommit = 0 ;
2017-10-06 04:12:42 +03:00
const char * old_vg_name = NULL ;
2002-11-18 17:04:08 +03:00
/* Ignore any mda on a PV outside the VG. vgsplit relies on this */
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( pvl , & vg - > pvs ) {
2005-06-01 20:51:55 +04:00
if ( pvl - > pv - > dev = = mdac - > area . dev ) {
2002-11-18 17:04:08 +03:00
found = 1 ;
2017-10-06 04:12:42 +03:00
if ( pvl - > pv - > status & PV_MOVED_VG )
old_vg_name = vg - > old_name ;
2002-11-18 17:04:08 +03:00
break ;
}
}
if ( ! found )
return 1 ;
2017-12-15 17:57:05 +03:00
if ( ! ( mdah = raw_read_mda_header ( fid - > fmt - > cmd - > mem , & mdac - > area , mda_is_primary ( mda ) ) ) )
2008-01-30 16:19:47 +03:00
goto_out ;
2002-11-18 17:04:08 +03:00
2017-12-07 06:34:59 +03:00
if ( ! ( rlocn = _find_vg_rlocn ( & mdac - > area , mdah , mda_is_primary ( mda ) , old_vg_name ? : vg - > name , & noprecommit ) ) ) {
2005-04-06 22:59:55 +04:00
mdah - > raw_locns [ 0 ] . offset = 0 ;
2005-10-31 23:15:28 +03:00
mdah - > raw_locns [ 0 ] . size = 0 ;
mdah - > raw_locns [ 0 ] . checksum = 0 ;
2002-11-18 17:04:08 +03:00
mdah - > raw_locns [ 1 ] . offset = 0 ;
2005-10-31 23:15:28 +03:00
mdah - > raw_locns [ 1 ] . size = 0 ;
mdah - > raw_locns [ 1 ] . checksum = 0 ;
2005-04-06 22:59:55 +04:00
mdah - > raw_locns [ 2 ] . offset = 0 ;
2005-10-31 23:15:28 +03:00
mdah - > raw_locns [ 2 ] . size = 0 ;
mdah - > raw_locns [ 2 ] . checksum = 0 ;
2005-04-06 22:59:55 +04:00
rlocn = & mdah - > raw_locns [ 0 ] ;
2017-10-28 00:42:00 +03:00
} else if ( precommit & & rlocn_is_ignored ( rlocn ) & & ! mda_is_ignored ( mda ) ) {
/*
* If precommitting into a previously - ignored mda , wipe the live rlocn
* as a precaution so that nothing can use it by mistake .
*/
mdah - > raw_locns [ 0 ] . offset = 0 ;
mdah - > raw_locns [ 0 ] . size = 0 ;
mdah - > raw_locns [ 0 ] . checksum = 0 ;
2002-11-18 17:04:08 +03:00
}
2005-04-06 22:59:55 +04:00
if ( precommit )
rlocn + + ;
2005-10-31 23:15:28 +03:00
else {
/* If not precommitting, wipe the precommitted rlocn */
mdah - > raw_locns [ 1 ] . offset = 0 ;
mdah - > raw_locns [ 1 ] . size = 0 ;
mdah - > raw_locns [ 1 ] . checksum = 0 ;
}
/* Is there new metadata to commit? */
if ( mdac - > rlocn . size ) {
rlocn - > offset = mdac - > rlocn . offset ;
rlocn - > size = mdac - > rlocn . size ;
rlocn - > checksum = mdac - > rlocn . checksum ;
2017-12-11 23:25:03 +03:00
log_debug_metadata ( " %sCommitting %s %smetadata (%u) to %s header at " FMTu64 " (offset " FMTu64 " , size " FMTu64 " ) " ,
precommit ? " Pre- " : " " , vg - > name , mda_is_ignored ( mda ) ? " (ignored) " : " " , vg - > seqno ,
dev_name ( mdac - > area . dev ) , mdac - > area . start , mdac - > rlocn . offset , mdac - > rlocn . size ) ;
2005-10-31 23:15:28 +03:00
} else
2017-10-28 00:42:00 +03:00
log_debug_metadata ( " Wiping pre-committed %s %smetadata from %s "
2017-12-11 18:32:53 +03:00
" header at " FMTu64 , vg - > name ,
2017-10-28 00:42:00 +03:00
mda_is_ignored ( mda ) ? " (ignored) " : " " ,
2013-01-08 02:30:29 +04:00
dev_name ( mdac - > area . dev ) , mdac - > area . start ) ;
2005-04-06 22:59:55 +04:00
2010-06-29 00:31:18 +04:00
rlocn_set_ignored ( mdah - > raw_locns , mda_is_ignored ( mda ) ) ;
2012-02-23 17:11:07 +04:00
2017-12-07 06:34:59 +03:00
if ( ! _raw_write_mda_header ( fid - > fmt , mdac - > area . dev , mda_is_primary ( mda ) , mdac - > area . start ,
2002-11-18 17:04:08 +03:00
mdah ) ) {
2008-08-16 13:46:55 +04:00
dm_pool_free ( fid - > fmt - > cmd - > mem , mdah ) ;
2002-11-18 17:04:08 +03:00
log_error ( " Failed to write metadata area header " ) ;
goto out ;
}
r = 1 ;
out :
2005-10-23 04:14:48 +04:00
if ( ! precommit ) {
2017-12-12 21:36:54 +03:00
/* This is an paired with the open at the start of _vg_write_raw */
2005-10-23 04:14:48 +04:00
if ( ! dev_close ( mdac - > area . dev ) )
stack ;
2014-03-24 12:20:18 +04:00
dm_free ( fidtc - > raw_metadata_buf ) ;
fidtc - > raw_metadata_buf = NULL ;
2005-10-23 04:14:48 +04:00
}
2002-11-18 17:04:08 +03:00
return r ;
}
2005-04-06 22:59:55 +04:00
static int _vg_commit_raw ( struct format_instance * fid , struct volume_group * vg ,
struct metadata_area * mda )
{
return _vg_commit_raw_rlocn ( fid , vg , mda , 0 ) ;
}
static int _vg_precommit_raw ( struct format_instance * fid ,
struct volume_group * vg ,
struct metadata_area * mda )
{
return _vg_commit_raw_rlocn ( fid , vg , mda , 1 ) ;
}
2003-07-05 02:34:56 +04:00
/* Close metadata area devices */
static int _vg_revert_raw ( struct format_instance * fid , struct volume_group * vg ,
struct metadata_area * mda )
{
struct mda_context * mdac = ( struct mda_context * ) mda - > metadata_locn ;
2005-06-01 20:51:55 +04:00
struct pv_list * pvl ;
2003-07-05 02:34:56 +04:00
int found = 0 ;
/* Ignore any mda on a PV outside the VG. vgsplit relies on this */
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( pvl , & vg - > pvs ) {
2005-06-01 20:51:55 +04:00
if ( pvl - > pv - > dev = = mdac - > area . dev ) {
2003-07-05 02:34:56 +04:00
found = 1 ;
break ;
}
}
if ( ! found )
return 1 ;
2005-10-31 23:15:28 +03:00
/* Wipe pre-committed metadata */
mdac - > rlocn . size = 0 ;
return _vg_commit_raw_rlocn ( fid , vg , mda , 0 ) ;
2003-07-05 02:34:56 +04:00
}
2002-11-18 17:04:08 +03:00
static int _vg_remove_raw ( struct format_instance * fid , struct volume_group * vg ,
struct metadata_area * mda )
{
struct mda_context * mdac = ( struct mda_context * ) mda - > metadata_locn ;
struct mda_header * mdah ;
struct raw_locn * rlocn ;
int r = 0 ;
2005-10-31 23:15:28 +03:00
int noprecommit = 0 ;
2002-11-18 17:04:08 +03:00
2008-01-30 16:19:47 +03:00
if ( ! dev_open ( mdac - > area . dev ) )
return_0 ;
2002-11-18 17:04:08 +03:00
2017-12-15 17:57:05 +03:00
if ( ! ( mdah = raw_read_mda_header ( fid - > fmt - > cmd - > mem , & mdac - > area , mda_is_primary ( mda ) ) ) )
2008-01-30 16:19:47 +03:00
goto_out ;
2002-11-18 17:04:08 +03:00
2017-12-07 06:34:59 +03:00
if ( ! ( rlocn = _find_vg_rlocn ( & mdac - > area , mdah , mda_is_primary ( mda ) , vg - > name , & noprecommit ) ) ) {
2002-11-18 17:04:08 +03:00
rlocn = & mdah - > raw_locns [ 0 ] ;
mdah - > raw_locns [ 1 ] . offset = 0 ;
}
rlocn - > offset = 0 ;
rlocn - > size = 0 ;
rlocn - > checksum = 0 ;
2010-06-29 00:31:18 +04:00
rlocn_set_ignored ( mdah - > raw_locns , mda_is_ignored ( mda ) ) ;
2002-11-18 17:04:08 +03:00
2017-12-07 06:34:59 +03:00
if ( ! _raw_write_mda_header ( fid - > fmt , mdac - > area . dev , mda_is_primary ( mda ) , mdac - > area . start ,
2002-11-18 17:04:08 +03:00
mdah ) ) {
2008-08-16 13:46:55 +04:00
dm_pool_free ( fid - > fmt - > cmd - > mem , mdah ) ;
2002-11-18 17:04:08 +03:00
log_error ( " Failed to write metadata area header " ) ;
goto out ;
}
r = 1 ;
out :
if ( ! dev_close ( mdac - > area . dev ) )
stack ;
return r ;
}
static struct volume_group * _vg_read_file_name ( struct format_instance * fid ,
const char * vgname ,
2005-04-06 22:59:55 +04:00
const char * read_path )
2001-11-21 12:20:05 +03:00
{
2002-01-10 17:27:47 +03:00
struct volume_group * vg ;
2002-02-11 14:43:17 +03:00
time_t when ;
char * desc ;
2002-01-10 17:27:47 +03:00
2008-01-30 16:19:47 +03:00
if ( ! ( vg = text_vg_import_file ( fid , read_path , & when , & desc ) ) )
return_NULL ;
2002-01-10 17:27:47 +03:00
/*
* Currently you can only have a single volume group per
* text file ( this restriction may remain ) . We need to
* check that it contains the correct volume group .
*/
2002-11-18 17:04:08 +03:00
if ( vgname & & strcmp ( vgname , vg - > name ) ) {
2013-06-18 23:50:29 +04:00
fid - > ref_count + + ; /* Preserve FID after vg release */
2011-08-11 00:25:29 +04:00
release_vg ( vg ) ;
2009-07-16 00:02:46 +04:00
log_error ( " '%s' does not contain volume group '%s'. " ,
read_path , vgname ) ;
2002-01-10 17:27:47 +03:00
return NULL ;
2017-07-19 17:16:12 +03:00
}
log_debug_metadata ( " Read volume group %s from %s " , vg - > name , read_path ) ;
2002-01-10 17:27:47 +03:00
return vg ;
2001-11-21 12:20:05 +03:00
}
2002-11-18 17:04:08 +03:00
static struct volume_group * _vg_read_file ( struct format_instance * fid ,
const char * vgname ,
2012-02-29 06:35:35 +04:00
struct metadata_area * mda ,
2015-03-19 02:43:02 +03:00
struct cached_vg_fmtdata * * vg_fmtdata ,
unsigned * use_previous_vg __attribute__ ( ( unused ) ) ,
2012-02-29 06:35:35 +04:00
int single_device __attribute__ ( ( unused ) ) )
2002-11-18 17:04:08 +03:00
{
struct text_context * tc = ( struct text_context * ) mda - > metadata_locn ;
return _vg_read_file_name ( fid , vgname , tc - > path_live ) ;
}
2005-04-06 22:59:55 +04:00
static struct volume_group * _vg_read_precommit_file ( struct format_instance * fid ,
const char * vgname ,
2015-03-19 02:43:02 +03:00
struct metadata_area * mda ,
struct cached_vg_fmtdata * * vg_fmtdata ,
unsigned * use_previous_vg __attribute__ ( ( unused ) ) )
2005-04-06 22:59:55 +04:00
{
struct text_context * tc = ( struct text_context * ) mda - > metadata_locn ;
2005-10-31 23:15:28 +03:00
struct volume_group * vg ;
2005-04-06 22:59:55 +04:00
2005-10-31 23:15:28 +03:00
if ( ( vg = _vg_read_file_name ( fid , vgname , tc - > path_edit ) ) )
vg - > status | = PRECOMMITTED ;
else
vg = _vg_read_file_name ( fid , vgname , tc - > path_live ) ;
return vg ;
2005-04-06 22:59:55 +04:00
}
2010-07-09 19:34:40 +04:00
static int _vg_write_file ( struct format_instance * fid __attribute__ ( ( unused ) ) ,
2007-08-22 18:38:18 +04:00
struct volume_group * vg , struct metadata_area * mda )
2001-11-21 12:20:05 +03:00
{
2002-11-18 17:04:08 +03:00
struct text_context * tc = ( struct text_context * ) mda - > metadata_locn ;
2002-01-15 20:37:23 +03:00
2002-01-07 12:05:31 +03:00
FILE * fp ;
2002-01-10 17:27:47 +03:00
int fd ;
2002-01-09 22:16:48 +03:00
char * slash ;
char temp_file [ PATH_MAX ] , temp_dir [ PATH_MAX ] ;
2007-07-02 15:17:21 +04:00
slash = strrchr ( tc - > path_edit , ' / ' ) ;
2001-11-21 12:20:05 +03:00
2002-01-09 22:16:48 +03:00
if ( slash = = 0 )
strcpy ( temp_dir , " . " ) ;
2002-04-24 22:20:51 +04:00
else if ( slash - tc - > path_edit < PATH_MAX ) {
2002-12-20 02:25:55 +03:00
strncpy ( temp_dir , tc - > path_edit ,
( size_t ) ( slash - tc - > path_edit ) ) ;
2002-04-24 22:20:51 +04:00
temp_dir [ slash - tc - > path_edit ] = ' \0 ' ;
2002-01-10 17:27:47 +03:00
2002-01-09 22:16:48 +03:00
} else {
log_error ( " Text format failed to determine directory. " ) ;
return 0 ;
}
2008-12-07 07:27:56 +03:00
if ( ! create_temp_name ( temp_dir , temp_file , sizeof ( temp_file ) , & fd ,
& vg - > cmd - > rand_seed ) ) {
2009-07-16 00:02:46 +04:00
log_error ( " Couldn't create temporary text file name. " ) ;
2002-02-25 01:31:55 +03:00
return 0 ;
}
2002-01-09 22:16:48 +03:00
if ( ! ( fp = fdopen ( fd , " w " ) ) ) {
log_sys_error ( " fdopen " , temp_file ) ;
2007-01-25 17:37:48 +03:00
if ( close ( fd ) )
log_sys_error ( " fclose " , temp_file ) ;
2002-01-07 12:05:31 +03:00
return 0 ;
}
2001-11-21 12:20:05 +03:00
2013-01-08 02:30:29 +04:00
log_debug_metadata ( " Writing %s metadata to %s " , vg - > name , temp_file ) ;
2002-11-18 17:04:08 +03:00
if ( ! text_vg_export_file ( vg , tc - > desc , fp ) ) {
2002-01-09 22:16:48 +03:00
log_error ( " Failed to write metadata to %s. " , temp_file ) ;
2007-01-25 17:37:48 +03:00
if ( fclose ( fp ) )
log_sys_error ( " fclose " , temp_file ) ;
2002-01-09 16:07:03 +03:00
return 0 ;
}
2005-09-01 22:37:22 +04:00
if ( fsync ( fd ) & & ( errno ! = EROFS ) & & ( errno ! = EINVAL ) ) {
2002-04-24 22:20:51 +04:00
log_sys_error ( " fsync " , tc - > path_edit ) ;
2007-01-25 17:37:48 +03:00
if ( fclose ( fp ) )
log_sys_error ( " fclose " , tc - > path_edit ) ;
2002-04-24 22:20:51 +04:00
return 0 ;
}
2007-07-24 21:48:08 +04:00
if ( lvm_fclose ( fp , tc - > path_edit ) )
return_0 ;
2002-04-24 22:20:51 +04:00
2016-04-20 13:45:15 +03:00
log_debug_metadata ( " Renaming %s to %s " , temp_file , tc - > path_edit ) ;
2002-04-24 22:20:51 +04:00
if ( rename ( temp_file , tc - > path_edit ) ) {
log_error ( " %s: rename to %s failed: %s " , temp_file ,
tc - > path_edit , strerror ( errno ) ) ;
return 0 ;
}
return 1 ;
}
2010-07-09 19:34:40 +04:00
static int _vg_commit_file_backup ( struct format_instance * fid __attribute__ ( ( unused ) ) ,
2002-11-18 17:04:08 +03:00
struct volume_group * vg ,
struct metadata_area * mda )
2002-04-24 22:20:51 +04:00
{
2002-11-18 17:04:08 +03:00
struct text_context * tc = ( struct text_context * ) mda - > metadata_locn ;
if ( test_mode ( ) ) {
log_verbose ( " Test mode: Skipping committing %s metadata (%u) " ,
vg - > name , vg - > seqno ) ;
if ( unlink ( tc - > path_edit ) ) {
2013-01-08 02:30:29 +04:00
log_debug_metadata ( " Unlinking %s " , tc - > path_edit ) ;
2002-11-18 17:04:08 +03:00
log_sys_error ( " unlink " , tc - > path_edit ) ;
return 0 ;
}
} else {
2013-01-08 02:30:29 +04:00
log_debug_metadata ( " Committing %s metadata (%u) " , vg - > name , vg - > seqno ) ;
log_debug_metadata ( " Renaming %s to %s " , tc - > path_edit , tc - > path_live ) ;
2002-11-18 17:04:08 +03:00
if ( rename ( tc - > path_edit , tc - > path_live ) ) {
log_error ( " %s: rename to %s failed: %s " , tc - > path_edit ,
2002-12-06 01:56:22 +03:00
tc - > path_live , strerror ( errno ) ) ;
2002-11-18 17:04:08 +03:00
return 0 ;
}
}
2002-12-06 01:56:22 +03:00
sync_dir ( tc - > path_edit ) ;
2002-04-24 22:20:51 +04:00
return 1 ;
}
2002-11-18 17:04:08 +03:00
static int _vg_commit_file ( struct format_instance * fid , struct volume_group * vg ,
struct metadata_area * mda )
2002-04-24 22:20:51 +04:00
{
2002-11-18 17:04:08 +03:00
struct text_context * tc = ( struct text_context * ) mda - > metadata_locn ;
2011-03-11 17:45:17 +03:00
const char * slash ;
2007-08-06 18:57:48 +04:00
char new_name [ PATH_MAX ] ;
2002-12-20 02:25:55 +03:00
size_t len ;
2002-04-24 22:20:51 +04:00
2002-11-18 17:04:08 +03:00
if ( ! _vg_commit_file_backup ( fid , vg , mda ) )
2002-01-07 12:05:31 +03:00
return 0 ;
2001-11-21 12:20:05 +03:00
2002-11-18 17:04:08 +03:00
/* vgrename? */
2007-07-02 15:17:21 +04:00
if ( ( slash = strrchr ( tc - > path_live , ' / ' ) ) )
2002-11-18 17:04:08 +03:00
slash = slash + 1 ;
else
slash = tc - > path_live ;
if ( strcmp ( slash , vg - > name ) ) {
len = slash - tc - > path_live ;
2017-06-27 12:37:24 +03:00
if ( ( len + strlen ( vg - > name ) ) > ( sizeof ( new_name ) - 1 ) ) {
log_error ( " Renaming path %s is too long for VG %s. " ,
tc - > path_live , vg - > name ) ;
return 0 ;
}
2007-08-06 18:57:48 +04:00
strncpy ( new_name , tc - > path_live , len ) ;
strcpy ( new_name + len , vg - > name ) ;
2013-01-08 02:30:29 +04:00
log_debug_metadata ( " Renaming %s to %s " , tc - > path_live , new_name ) ;
2002-11-18 17:04:08 +03:00
if ( test_mode ( ) )
log_verbose ( " Test mode: Skipping rename " ) ;
else {
2007-08-06 18:57:48 +04:00
if ( rename ( tc - > path_live , new_name ) ) {
2002-11-18 17:04:08 +03:00
log_error ( " %s: rename to %s failed: %s " ,
2007-08-06 18:57:48 +04:00
tc - > path_live , new_name ,
2002-11-18 17:04:08 +03:00
strerror ( errno ) ) ;
2007-08-06 18:57:48 +04:00
sync_dir ( new_name ) ;
2002-11-18 17:04:08 +03:00
return 0 ;
}
}
}
2002-04-24 22:20:51 +04:00
return 1 ;
}
2010-07-09 19:34:40 +04:00
static int _vg_remove_file ( struct format_instance * fid __attribute__ ( ( unused ) ) ,
struct volume_group * vg __attribute__ ( ( unused ) ) ,
2002-11-18 17:04:08 +03:00
struct metadata_area * mda )
2002-04-24 22:20:51 +04:00
{
2002-11-18 17:04:08 +03:00
struct text_context * tc = ( struct text_context * ) mda - > metadata_locn ;
2002-04-24 22:20:51 +04:00
if ( path_exists ( tc - > path_edit ) & & unlink ( tc - > path_edit ) ) {
log_sys_error ( " unlink " , tc - > path_edit ) ;
2002-01-09 22:16:48 +03:00
return 0 ;
}
2002-04-24 22:20:51 +04:00
if ( path_exists ( tc - > path_live ) & & unlink ( tc - > path_live ) ) {
log_sys_error ( " unlink " , tc - > path_live ) ;
return 0 ;
}
2002-12-06 01:56:22 +03:00
sync_dir ( tc - > path_live ) ;
2002-04-24 22:20:51 +04:00
2002-01-07 12:05:31 +03:00
return 1 ;
2001-11-21 12:20:05 +03:00
}
2010-12-11 01:39:52 +03:00
static int _scan_file ( const struct format_type * fmt , const char * vgname )
2002-04-24 22:20:51 +04:00
{
struct dirent * dirent ;
struct dir_list * dl ;
2008-11-04 01:14:30 +03:00
struct dm_list * dir_list ;
2002-04-24 22:20:51 +04:00
char * tmp ;
DIR * d ;
2002-11-18 17:04:08 +03:00
struct volume_group * vg ;
struct format_instance * fid ;
2011-02-21 15:07:03 +03:00
struct format_instance_ctx fic ;
2002-11-18 17:04:08 +03:00
char path [ PATH_MAX ] ;
2010-12-11 01:39:52 +03:00
char * scanned_vgname ;
2002-04-24 22:20:51 +04:00
2002-11-18 17:04:08 +03:00
dir_list = & ( ( struct mda_lists * ) fmt - > private ) - > dirs ;
2002-04-24 22:20:51 +04:00
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( dl , dir_list ) {
2002-04-24 22:20:51 +04:00
if ( ! ( d = opendir ( dl - > dir ) ) ) {
log_sys_error ( " opendir " , dl - > dir ) ;
continue ;
}
while ( ( dirent = readdir ( d ) ) )
if ( strcmp ( dirent - > d_name , " . " ) & &
strcmp ( dirent - > d_name , " .. " ) & &
( ! ( tmp = strstr ( dirent - > d_name , " .tmp " ) ) | |
tmp ! = dirent - > d_name + strlen ( dirent - > d_name )
2002-11-18 17:04:08 +03:00
- 4 ) ) {
2010-12-11 01:39:52 +03:00
scanned_vgname = dirent - > d_name ;
/* If vgname supplied, only scan that one VG */
if ( vgname & & strcmp ( vgname , scanned_vgname ) )
continue ;
2006-08-21 16:54:53 +04:00
if ( dm_snprintf ( path , PATH_MAX , " %s/%s " ,
2010-12-11 01:39:52 +03:00
dl - > dir , scanned_vgname ) < 0 ) {
2002-11-18 17:04:08 +03:00
log_error ( " Name too long %s/%s " ,
2010-12-11 01:39:52 +03:00
dl - > dir , scanned_vgname ) ;
2002-11-18 17:04:08 +03:00
break ;
}
/* FIXME stat file to see if it's changed */
2011-02-21 15:07:03 +03:00
/* FIXME: Check this fid is OK! */
2012-02-13 03:01:19 +04:00
fic . type = FMT_INSTANCE_PRIVATE_MDAS ;
2011-02-21 15:07:03 +03:00
fic . context . private = NULL ;
2012-12-15 00:34:28 +04:00
if ( ! ( fid = _text_create_text_instance ( fmt , & fic ) ) ) {
stack ;
break ;
}
2010-12-11 01:39:52 +03:00
if ( ( vg = _vg_read_file_name ( fid , scanned_vgname ,
2010-09-30 18:12:14 +04:00
path ) ) ) {
2006-04-13 21:32:24 +04:00
/* FIXME Store creation host in vg */
2008-03-17 19:51:31 +03:00
lvmcache_update_vg ( vg , 0 ) ;
2011-08-11 00:25:29 +04:00
release_vg ( vg ) ;
2010-09-30 18:12:14 +04:00
}
2002-11-18 17:04:08 +03:00
}
2002-04-24 22:20:51 +04:00
if ( closedir ( d ) )
log_sys_error ( " closedir " , dl - > dir ) ;
2002-02-22 14:44:56 +03:00
}
2002-11-18 17:04:08 +03:00
return 1 ;
2002-02-22 14:44:56 +03:00
}
2015-03-19 02:43:02 +03:00
int vgname_from_mda ( const struct format_type * fmt ,
2017-12-07 06:34:59 +03:00
struct mda_header * mdah , int primary_mda , struct device_area * dev_area ,
2015-03-19 02:43:02 +03:00
struct lvmcache_vgsummary * vgsummary , uint64_t * mda_free_sectors )
2002-02-22 14:44:56 +03:00
{
2002-11-18 17:04:08 +03:00
struct raw_locn * rlocn ;
2006-04-11 17:55:59 +04:00
uint32_t wrap = 0 ;
2006-04-12 21:54:11 +04:00
unsigned int len = 0 ;
2010-07-09 19:34:40 +04:00
char buf [ NAME_LEN + 1 ] __attribute__ ( ( aligned ( 8 ) ) ) ;
2007-11-05 20:17:55 +03:00
uint64_t buffer_size , current_usage ;
2015-03-19 02:43:02 +03:00
unsigned used_cached_metadata = 0 ;
2007-11-05 20:17:55 +03:00
if ( mda_free_sectors )
* mda_free_sectors = ( ( dev_area - > size - MDA_HEADER_SIZE ) / 2 ) > > SECTOR_SHIFT ;
2002-11-18 17:04:08 +03:00
Allow raw_read_mda_header to be called from text_label.c.
We'd like to pass in mda_header to vgname_from_mda(). In order to
do this, we need to call raw_read_mda_header() from text_label.c,
_text_read(), which gets called from the label_read() path, and
peers into the metadata and update vginfo cache. We should check
the disable bit here, and if set, not peer into the vg metadata,
thus reducing the I/O to disk.
In the process, move vgname_from_mda() to layout.h, since the fn
only gets called from format_text code, and we need the mda_header
definition from the private layout.h.
Signed-off-by: Dave Wysochanski <dwysocha@redhat.com>
2010-06-29 00:31:01 +04:00
if ( ! mdah ) {
log_error ( INTERNAL_ERROR " vgname_from_mda called with NULL pointer for mda_header " ) ;
2015-03-19 02:43:02 +03:00
return 0 ;
Allow raw_read_mda_header to be called from text_label.c.
We'd like to pass in mda_header to vgname_from_mda(). In order to
do this, we need to call raw_read_mda_header() from text_label.c,
_text_read(), which gets called from the label_read() path, and
peers into the metadata and update vginfo cache. We should check
the disable bit here, and if set, not peer into the vg metadata,
thus reducing the I/O to disk.
In the process, move vgname_from_mda() to layout.h, since the fn
only gets called from format_text code, and we need the mda_header
definition from the private layout.h.
Signed-off-by: Dave Wysochanski <dwysocha@redhat.com>
2010-06-29 00:31:01 +04:00
}
2002-02-25 01:31:55 +03:00
2006-04-11 17:55:59 +04:00
/* FIXME Cope with returning a list */
2002-11-18 17:04:08 +03:00
rlocn = mdah - > raw_locns ;
2009-03-03 19:35:32 +03:00
/*
* If no valid offset , do not try to search for vgname
*/
2015-03-06 11:04:31 +03:00
if ( ! rlocn - > offset ) {
log_debug ( " %s: found metadata with offset 0. " ,
dev_name ( dev_area - > dev ) ) ;
2015-03-19 02:43:02 +03:00
return 0 ;
2015-03-06 11:04:31 +03:00
}
2009-03-03 19:35:32 +03:00
2006-04-12 21:54:11 +04:00
/* Do quick check for a vgname */
2017-12-19 04:12:18 +03:00
if ( ! dev_read_buf ( dev_area - > dev , dev_area - > start + rlocn - > offset ,
NAME_LEN , MDA_CONTENT_REASON ( primary_mda ) , buf ) )
2015-03-19 02:43:02 +03:00
return_0 ;
2006-04-12 21:54:11 +04:00
while ( buf [ len ] & & ! isspace ( buf [ len ] ) & & buf [ len ] ! = ' { ' & &
len < ( NAME_LEN - 1 ) )
len + + ;
buf [ len ] = ' \0 ' ;
/* Ignore this entry if the characters aren't permissible */
if ( ! validate_name ( buf ) )
2015-03-19 02:43:02 +03:00
return_0 ;
2006-04-12 21:54:11 +04:00
/* We found a VG - now check the metadata */
2006-04-11 17:55:59 +04:00
if ( rlocn - > offset + rlocn - > size > mdah - > size )
wrap = ( uint32_t ) ( ( rlocn - > offset + rlocn - > size ) - mdah - > size ) ;
2002-11-18 17:04:08 +03:00
2006-04-11 17:55:59 +04:00
if ( wrap > rlocn - > offset ) {
2017-12-11 18:59:40 +03:00
log_error ( " %s: metadata ( " FMTu64 " bytes) too large for circular buffer ( " FMTu64 " bytes) " ,
dev_name ( dev_area - > dev ) , rlocn - > size , mdah - > size - MDA_HEADER_SIZE ) ;
2015-03-19 02:43:02 +03:00
return 0 ;
2006-04-11 17:55:59 +04:00
}
2002-11-18 17:04:08 +03:00
2015-03-19 02:43:02 +03:00
/* Did we see this metadata before? */
vgsummary - > mda_checksum = rlocn - > checksum ;
vgsummary - > mda_size = rlocn - > size ;
if ( lvmcache_lookup_mda ( vgsummary ) )
used_cached_metadata = 1 ;
2015-03-06 12:24:26 +03:00
2006-04-11 17:55:59 +04:00
/* FIXME 64-bit */
2017-12-07 06:34:59 +03:00
if ( ! text_vgsummary_import ( fmt , dev_area - > dev , MDA_CONTENT_REASON ( primary_mda ) ,
2015-03-19 02:43:02 +03:00
( off_t ) ( dev_area - > start + rlocn - > offset ) ,
( uint32_t ) ( rlocn - > size - wrap ) ,
( off_t ) ( dev_area - > start + MDA_HEADER_SIZE ) ,
wrap , calc_crc , vgsummary - > vgname ? 1 : 0 ,
vgsummary ) )
return_0 ;
2006-04-11 17:55:59 +04:00
/* Ignore this entry if the characters aren't permissible */
2015-03-19 02:43:02 +03:00
if ( ! validate_name ( vgsummary - > vgname ) )
return_0 ;
2002-02-22 14:44:56 +03:00
2017-12-11 23:25:03 +03:00
log_debug_metadata ( " %s: %s metadata at " FMTu64 " size " FMTu64 " with wrap " FMTu32
2017-12-11 18:32:53 +03:00
" (in area at " FMTu64 " size " FMTu64
2016-04-12 14:06:16 +03:00
" ) for %s ( " FMTVGID " ) " ,
2015-03-19 02:43:02 +03:00
dev_name ( dev_area - > dev ) ,
used_cached_metadata ? " Using cached " : " Found " ,
dev_area - > start + rlocn - > offset ,
2017-12-11 23:25:03 +03:00
rlocn - > size , wrap , dev_area - > start , dev_area - > size , vgsummary - > vgname ,
2016-04-12 14:06:16 +03:00
( char * ) & vgsummary - > vgid ) ;
2007-11-05 20:17:55 +03:00
if ( mda_free_sectors ) {
2017-12-12 23:57:36 +03:00
current_usage = ALIGN_ABSOLUTE ( rlocn - > size , dev_area - > start + rlocn - > offset , MDA_ALIGNMENT ) ;
2017-12-11 20:08:29 +03:00
2007-11-05 20:17:55 +03:00
buffer_size = mdah - > size - MDA_HEADER_SIZE ;
if ( current_usage * 2 > = buffer_size )
* mda_free_sectors = UINT64_C ( 0 ) ;
else
* mda_free_sectors = ( ( buffer_size - 2 * current_usage ) / 2 ) > > SECTOR_SHIFT ;
}
2006-04-11 17:55:59 +04:00
2015-03-19 02:43:02 +03:00
return 1 ;
2002-02-22 14:44:56 +03:00
}
2010-12-11 01:39:52 +03:00
static int _scan_raw ( const struct format_type * fmt , const char * vgname __attribute__ ( ( unused ) ) )
2002-02-22 14:44:56 +03:00
{
2002-11-18 17:04:08 +03:00
struct raw_list * rl ;
2008-11-04 01:14:30 +03:00
struct dm_list * raw_list ;
2002-11-18 17:04:08 +03:00
struct volume_group * vg ;
struct format_instance fid ;
2015-03-19 02:43:02 +03:00
struct lvmcache_vgsummary vgsummary = { 0 } ;
Allow raw_read_mda_header to be called from text_label.c.
We'd like to pass in mda_header to vgname_from_mda(). In order to
do this, we need to call raw_read_mda_header() from text_label.c,
_text_read(), which gets called from the label_read() path, and
peers into the metadata and update vginfo cache. We should check
the disable bit here, and if set, not peer into the vg metadata,
thus reducing the I/O to disk.
In the process, move vgname_from_mda() to layout.h, since the fn
only gets called from format_text code, and we need the mda_header
definition from the private layout.h.
Signed-off-by: Dave Wysochanski <dwysocha@redhat.com>
2010-06-29 00:31:01 +04:00
struct mda_header * mdah ;
2002-11-18 17:04:08 +03:00
raw_list = & ( ( struct mda_lists * ) fmt - > private ) - > raws ;
fid . fmt = fmt ;
2010-06-29 00:32:44 +04:00
dm_list_init ( & fid . metadata_areas_in_use ) ;
2010-06-29 00:33:22 +04:00
dm_list_init ( & fid . metadata_areas_ignored ) ;
2002-11-18 17:04:08 +03:00
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( rl , raw_list ) {
2002-11-18 17:04:08 +03:00
/* FIXME We're reading mdah twice here... */
2011-05-28 13:48:14 +04:00
if ( ! dev_open_readonly ( rl - > dev_area . dev ) ) {
2010-06-29 00:30:46 +04:00
stack ;
continue ;
}
2017-12-15 17:57:05 +03:00
if ( ! ( mdah = raw_read_mda_header ( fmt - > cmd - > mem , & rl - > dev_area , 0 ) ) ) {
Allow raw_read_mda_header to be called from text_label.c.
We'd like to pass in mda_header to vgname_from_mda(). In order to
do this, we need to call raw_read_mda_header() from text_label.c,
_text_read(), which gets called from the label_read() path, and
peers into the metadata and update vginfo cache. We should check
the disable bit here, and if set, not peer into the vg metadata,
thus reducing the I/O to disk.
In the process, move vgname_from_mda() to layout.h, since the fn
only gets called from format_text code, and we need the mda_header
definition from the private layout.h.
Signed-off-by: Dave Wysochanski <dwysocha@redhat.com>
2010-06-29 00:31:01 +04:00
stack ;
goto close_dev ;
}
2015-03-06 12:24:26 +03:00
/* TODO: caching as in vgname_from_mda() (trigger this code?) */
2017-12-07 06:34:59 +03:00
if ( vgname_from_mda ( fmt , mdah , 0 , & rl - > dev_area , & vgsummary , NULL ) ) {
vg = _vg_read_raw_area ( & fid , vgsummary . vgname , & rl - > dev_area , NULL , NULL , 0 , 0 , 0 ) ;
2010-06-29 00:30:30 +04:00
if ( vg )
2008-03-17 19:51:31 +03:00
lvmcache_update_vg ( vg , 0 ) ;
2002-11-18 17:04:08 +03:00
}
Allow raw_read_mda_header to be called from text_label.c.
We'd like to pass in mda_header to vgname_from_mda(). In order to
do this, we need to call raw_read_mda_header() from text_label.c,
_text_read(), which gets called from the label_read() path, and
peers into the metadata and update vginfo cache. We should check
the disable bit here, and if set, not peer into the vg metadata,
thus reducing the I/O to disk.
In the process, move vgname_from_mda() to layout.h, since the fn
only gets called from format_text code, and we need the mda_header
definition from the private layout.h.
Signed-off-by: Dave Wysochanski <dwysocha@redhat.com>
2010-06-29 00:31:01 +04:00
close_dev :
2010-06-29 00:30:46 +04:00
if ( ! dev_close ( rl - > dev_area . dev ) )
stack ;
2002-11-18 17:04:08 +03:00
}
2002-04-24 22:20:51 +04:00
return 1 ;
2002-11-18 17:04:08 +03:00
}
2010-12-11 01:39:52 +03:00
static int _text_scan ( const struct format_type * fmt , const char * vgname )
2002-11-18 17:04:08 +03:00
{
2010-12-11 01:39:52 +03:00
return ( _scan_file ( fmt , vgname ) & _scan_raw ( fmt , vgname ) ) ;
2002-11-18 17:04:08 +03:00
}
2012-02-10 05:28:27 +04:00
struct _write_single_mda_baton {
const struct format_type * fmt ;
struct physical_volume * pv ;
} ;
static int _write_single_mda ( struct metadata_area * mda , void * baton )
{
struct _write_single_mda_baton * p = baton ;
struct mda_context * mdac ;
2012-06-21 23:19:28 +04:00
char buf [ MDA_HEADER_SIZE ] __attribute__ ( ( aligned ( 8 ) ) ) = { 0 } ;
2012-02-10 05:28:27 +04:00
struct mda_header * mdah = ( struct mda_header * ) buf ;
mdac = mda - > metadata_locn ;
mdah - > size = mdac - > area . size ;
rlocn_set_ignored ( mdah - > raw_locns , mda_is_ignored ( mda ) ) ;
2017-12-07 06:34:59 +03:00
if ( ! _raw_write_mda_header ( p - > fmt , mdac - > area . dev , mda_is_primary ( mda ) ,
2012-02-10 05:28:27 +04:00
mdac - > area . start , mdah ) ) {
if ( ! dev_close ( p - > pv - > dev ) )
stack ;
return_0 ;
}
return 1 ;
}
2016-02-12 12:59:27 +03:00
static int _set_ext_flags ( struct physical_volume * pv , struct lvmcache_info * info )
{
uint32_t ext_flags = lvmcache_ext_flags ( info ) ;
if ( is_orphan ( pv ) )
ext_flags & = ~ PV_EXT_USED ;
else
ext_flags | = PV_EXT_USED ;
lvmcache_set_ext_version ( info , PV_HEADER_EXTENSION_VSN ) ;
lvmcache_set_ext_flags ( info , ext_flags ) ;
return 1 ;
}
2015-04-09 23:13:55 +03:00
/* Only for orphans - FIXME That's not true any more */
2011-02-21 15:26:27 +03:00
static int _text_pv_write ( const struct format_type * fmt , struct physical_volume * pv )
2002-11-18 17:04:08 +03:00
{
2011-02-21 15:26:27 +03:00
struct format_instance * fid = pv - > fid ;
2011-02-21 15:31:28 +03:00
const char * pvid = ( const char * ) ( * pv - > old_id . uuid ? & pv - > old_id : & pv - > id ) ;
2002-11-18 17:04:08 +03:00
struct label * label ;
2003-07-05 02:34:56 +04:00
struct lvmcache_info * info ;
2002-11-18 17:04:08 +03:00
struct mda_context * mdac ;
struct metadata_area * mda ;
2012-02-10 05:28:27 +04:00
struct _write_single_mda_baton baton ;
2011-02-21 15:26:27 +03:00
unsigned mda_index ;
2002-11-18 17:04:08 +03:00
2011-02-21 15:26:27 +03:00
/* Add a new cache entry with PV info or update existing one. */
if ( ! ( info = lvmcache_add ( fmt - > labeller , ( const char * ) & pv - > id ,
2015-04-09 23:13:55 +03:00
pv - > dev , pv - > vg_name ,
2015-04-11 03:55:24 +03:00
is_orphan_vg ( pv - > vg_name ) ? pv - > vg_name : pv - > vg ? ( const char * ) & pv - > vg - > id : NULL , 0 ) ) )
2008-01-30 16:19:47 +03:00
return_0 ;
2011-02-21 15:26:27 +03:00
2012-02-10 05:28:27 +04:00
label = lvmcache_get_label ( info ) ;
2011-06-01 23:29:31 +04:00
label - > sector = pv - > label_sector ;
format-text: label: fix missing dev assignment for struct label in _text_pv_write
When using lvm shell, some structures which are cached in memory may be
reused. This happens for the struct label (a part of lvmcache_info
structure) when lvmetad is used in which case the PV scan is not
done that would normally overwrite these label structures in memory
and making them up-to-date.
This is all consequence of the fact that struct lvmcache_info and
struct label are not always assigned in the same part of the code.
For example, if lvmetad *is not* used, parts of the struct label are
reassigned in label_read fn while struct lvmcache_info is created
elsewhere. No part of the code reused struct label (and its "dev"
field) before calling label_read fn. That's why the real bug is
hidden when using lvm shell without lvmetad.
However, with lvmetad and lvm shell, the situation is a bit different.
The label_read fn is not called if lvmetad *is* used, hence the
struct label may have ended up not initialized properly.
There was missing assignment for the dev field in struct label
in _text_pv_write fn which caused this problem to appear in
lvm shell with lvmetad, for example:
Before this patch:
lvm> pvcreate /dev/sda
Physical volume "/dev/sda" successfully created
lvm> pvs /dev/sda
PV VG Fmt Attr PSize PFree
unknown device lvm2 --- 128.00m 128.00m
With this patch applied:
lvm> pvcreate /dev/sda
Physical volume "/dev/sda" successfully created
lvm> pvs /dev/sda
PV VG Fmt Attr PSize PFree
/dev/sda lvm2 --- 128.00m 128.00m
Also, this problem had not appeared before changes introduced
by commits e1a63905d14cc73352b905c70cb4084b7e521e33 through
3a6f91d7139119bea664050a957cbc21490398bc which, among other
things, added proper label field type reporting. Before, label
reporting was the same as using struct physical_volume which
has its own dev field assigned and so this problem was not exposed.
2015-09-15 18:38:02 +03:00
label - > dev = pv - > dev ;
2002-11-18 17:04:08 +03:00
2012-02-10 05:28:27 +04:00
lvmcache_update_pv ( info , pv , fmt ) ;
2002-11-18 17:04:08 +03:00
2011-02-21 15:26:27 +03:00
/* Flush all cached metadata areas, we will reenter new/modified ones. */
2012-02-10 05:28:27 +04:00
lvmcache_del_mdas ( info ) ;
2011-02-21 15:26:27 +03:00
/*
* Add all new or modified metadata areas for this PV stored in
* its format instance . If this PV is not part of a VG yet ,
* pv - > fid will be used . Otherwise pv - > vg - > fid will be used .
* The fid_get_mda_indexed fn can handle that transparently ,
* just pass the right format_instance in .
*/
for ( mda_index = 0 ; mda_index < FMT_TEXT_MAX_MDAS_PER_PV ; mda_index + + ) {
2011-02-21 15:31:28 +03:00
if ( ! ( mda = fid_get_mda_indexed ( fid , pvid , ID_LEN , mda_index ) ) )
2011-02-21 15:26:27 +03:00
continue ;
mdac = ( struct mda_context * ) mda - > metadata_locn ;
2017-12-11 18:32:53 +03:00
log_debug_metadata ( " Creating metadata area on %s at sector "
FMTu64 " size " FMTu64 " sectors " ,
2013-01-08 02:30:29 +04:00
dev_name ( mdac - > area . dev ) ,
mdac - > area . start > > SECTOR_SHIFT ,
mdac - > area . size > > SECTOR_SHIFT ) ;
2012-02-10 05:28:27 +04:00
// if fmt is not the same as info->fmt we are in trouble
2013-11-22 16:25:27 +04:00
if ( ! lvmcache_add_mda ( info , mdac - > area . dev ,
mdac - > area . start , mdac - > area . size ,
mda_is_ignored ( mda ) ) )
return_0 ;
2002-11-18 17:04:08 +03:00
}
2013-05-28 14:37:22 +04:00
if ( ! lvmcache_update_bas ( info , pv ) )
2013-02-15 14:02:53 +04:00
return_0 ;
2009-07-31 01:15:17 +04:00
/*
2011-02-21 15:26:27 +03:00
* FIXME : Allow writing zero offset / size data area to disk .
* This requires defining a special value since we can ' t
* write offset / size that is 0 / 0 - this is already reserved
* as a delimiter in data / metadata area area list in PV header
* ( needs exploring compatibility with older lvm2 ) .
*/
/*
* We can ' t actually write pe_start = 0 ( a data area offset )
* in PV header now . We need to replace this value here . This can
* happen with vgcfgrestore with redefined pe_start or
* pvcreate - - restorefile . However , we can can have this value in
* metadata which will override the value in the PV header .
2009-07-31 01:15:17 +04:00
*/
2002-11-18 17:04:08 +03:00
2012-02-10 05:28:27 +04:00
if ( ! lvmcache_update_das ( info , pv ) )
2008-01-30 16:19:47 +03:00
return_0 ;
2002-11-18 17:04:08 +03:00
2008-01-30 16:19:47 +03:00
if ( ! dev_open ( pv - > dev ) )
return_0 ;
2002-11-18 17:04:08 +03:00
2012-02-10 05:28:27 +04:00
baton . pv = pv ;
baton . fmt = fmt ;
2002-11-18 17:04:08 +03:00
2012-02-10 05:28:27 +04:00
if ( ! lvmcache_foreach_mda ( info , _write_single_mda , & baton ) )
return_0 ;
2016-02-12 12:59:27 +03:00
if ( ! _set_ext_flags ( pv , info ) )
return_0 ;
2012-02-10 05:28:27 +04:00
if ( ! label_write ( pv - > dev , label ) ) {
2012-02-28 14:11:35 +04:00
stack ;
if ( ! dev_close ( pv - > dev ) )
stack ;
return 0 ;
2008-07-17 01:32:38 +04:00
}
2002-11-18 17:04:08 +03:00
2011-02-21 15:26:27 +03:00
/*
* FIXME : We should probably use the format instance ' s metadata
* areas for label_write and only if it ' s successful ,
* update the cache afterwards ?
*/
2008-01-30 16:19:47 +03:00
if ( ! dev_close ( pv - > dev ) )
return_0 ;
2002-11-18 17:04:08 +03:00
return 1 ;
}
2016-02-12 15:53:06 +03:00
static int _text_pv_needs_rewrite ( const struct format_type * fmt , struct physical_volume * pv ,
int * needs_rewrite )
{
struct lvmcache_info * info ;
uint32_t ext_vsn ;
* needs_rewrite = 0 ;
2016-02-12 14:05:59 +03:00
if ( ! pv - > is_labelled )
return 1 ;
2016-06-06 22:04:17 +03:00
if ( ! ( info = lvmcache_info_from_pvid ( ( const char * ) & pv - > id , pv - > dev , 0 ) ) ) {
2016-02-12 15:53:06 +03:00
log_error ( " Failed to find cached info for PV %s. " , pv_dev_name ( pv ) ) ;
return 0 ;
}
ext_vsn = lvmcache_ext_version ( info ) ;
if ( ext_vsn < PV_HEADER_EXTENSION_VSN )
* needs_rewrite = 1 ;
return 1 ;
}
2008-11-04 01:14:30 +03:00
static int _add_raw ( struct dm_list * raw_list , struct device_area * dev_area )
2002-02-22 14:44:56 +03:00
{
2002-11-18 17:04:08 +03:00
struct raw_list * rl ;
/* Already present? */
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( rl , raw_list ) {
2002-11-18 17:04:08 +03:00
/* FIXME Check size/overlap consistency too */
if ( rl - > dev_area . dev = = dev_area - > dev & &
2005-06-01 20:51:55 +04:00
rl - > dev_area . start = = dev_area - > start )
return 1 ;
2002-11-18 17:04:08 +03:00
}
2002-04-24 22:20:51 +04:00
2005-10-17 03:03:59 +04:00
if ( ! ( rl = dm_malloc ( sizeof ( struct raw_list ) ) ) ) {
2002-11-18 17:04:08 +03:00
log_error ( " _add_raw allocation failed " ) ;
return 0 ;
}
memcpy ( & rl - > dev_area , dev_area , sizeof ( * dev_area ) ) ;
2008-11-04 01:14:30 +03:00
dm_list_add ( raw_list , & rl - > list ) ;
2002-11-18 17:04:08 +03:00
return 1 ;
}
2010-02-02 19:26:34 +03:00
/*
2010-06-29 00:31:59 +04:00
* Copy constructor for a metadata_locn .
2010-02-02 19:26:34 +03:00
*/
2010-06-29 00:31:59 +04:00
static void * _metadata_locn_copy_raw ( struct dm_pool * mem , void * metadata_locn )
2010-02-02 19:26:34 +03:00
{
struct mda_context * mdac , * mdac_new ;
2010-06-29 00:31:59 +04:00
mdac = ( struct mda_context * ) metadata_locn ;
2010-02-02 19:26:34 +03:00
if ( ! ( mdac_new = dm_pool_alloc ( mem , sizeof ( * mdac_new ) ) ) ) {
log_error ( " mda_context allocation failed " ) ;
return NULL ;
}
memcpy ( mdac_new , mdac , sizeof ( * mdac ) ) ;
2010-02-16 02:53:15 +03:00
2010-06-29 00:31:59 +04:00
return mdac_new ;
2010-02-02 19:26:34 +03:00
}
2010-06-30 02:37:32 +04:00
/*
* Return a string description of the metadata location .
*/
2010-06-30 17:51:11 +04:00
static const char * _metadata_locn_name_raw ( void * metadata_locn )
2010-06-30 02:37:32 +04:00
{
2010-06-30 17:51:11 +04:00
struct mda_context * mdac = ( struct mda_context * ) metadata_locn ;
2010-06-30 02:37:32 +04:00
return dev_name ( mdac - > area . dev ) ;
}
2010-08-26 16:22:05 +04:00
static uint64_t _metadata_locn_offset_raw ( void * metadata_locn )
2010-06-30 17:51:11 +04:00
{
struct mda_context * mdac = ( struct mda_context * ) metadata_locn ;
return mdac - > area . start ;
}
2010-02-02 19:26:34 +03:00
2008-07-31 14:50:18 +04:00
static int _text_pv_read ( const struct format_type * fmt , const char * pv_name ,
2011-02-21 15:15:59 +03:00
struct physical_volume * pv , int scan_label_only )
2008-07-31 14:50:18 +04:00
{
2012-02-23 17:11:07 +04:00
struct lvmcache_info * info ;
2008-07-31 14:50:18 +04:00
struct device * dev ;
if ( ! ( dev = dev_cache_get ( pv_name , fmt - > cmd - > filter ) ) )
return_0 ;
2016-04-14 01:00:01 +03:00
if ( lvmetad_used ( ) ) {
2016-06-06 22:04:17 +03:00
info = lvmcache_info_from_pvid ( dev - > pvid , dev , 0 ) ;
2012-03-03 00:46:36 +04:00
if ( ! info & & ! lvmetad_pv_lookup_by_dev ( fmt - > cmd , dev , NULL ) )
2012-02-23 17:11:07 +04:00
return 0 ;
2016-06-06 22:04:17 +03:00
info = lvmcache_info_from_pvid ( dev - > pvid , dev , 0 ) ;
2012-02-23 17:11:07 +04:00
} else {
struct label * label ;
if ( ! ( label_read ( dev , & label , UINT64_C ( 0 ) ) ) )
return_0 ;
info = label - > info ;
}
2008-07-31 14:50:18 +04:00
2012-04-10 16:26:27 +04:00
if ( ! info )
return_0 ;
2012-02-23 17:11:07 +04:00
if ( ! lvmcache_populate_pv_fields ( info , pv , scan_label_only ) )
2008-07-31 14:50:18 +04:00
return 0 ;
2002-04-24 22:20:51 +04:00
return 1 ;
2002-02-22 14:44:56 +03:00
}
2011-02-21 15:20:18 +03:00
static int _text_pv_initialise ( const struct format_type * fmt ,
2016-02-19 00:31:27 +03:00
struct pv_create_args * pva ,
2011-02-21 15:20:18 +03:00
struct physical_volume * pv )
{
2016-02-19 00:31:27 +03:00
unsigned long data_alignment = pva - > data_alignment ;
unsigned long data_alignment_offset = pva - > data_alignment_offset ;
2013-02-15 14:02:53 +04:00
unsigned long adjustment , final_alignment = 0 ;
2011-02-21 15:20:18 +03:00
if ( ! data_alignment )
2013-06-25 14:30:34 +04:00
data_alignment = find_config_tree_int ( pv - > fmt - > cmd , devices_data_alignment_CFG , NULL ) * 2 ;
2011-02-21 15:20:18 +03:00
if ( set_pe_align ( pv , data_alignment ) ! = data_alignment & &
data_alignment ) {
log_error ( " %s: invalid data alignment of "
" %lu sectors (requested %lu sectors) " ,
pv_dev_name ( pv ) , pv - > pe_align , data_alignment ) ;
return 0 ;
}
if ( set_pe_align_offset ( pv , data_alignment_offset ) ! = data_alignment_offset & &
data_alignment_offset ) {
log_error ( " %s: invalid data alignment offset of "
" %lu sectors (requested %lu sectors) " ,
pv_dev_name ( pv ) , pv - > pe_align_offset , data_alignment_offset ) ;
return 0 ;
}
if ( pv - > pe_align < pv - > pe_align_offset ) {
log_error ( " %s: pe_align (%lu sectors) must not be less "
" than pe_align_offset (%lu sectors) " ,
pv_dev_name ( pv ) , pv - > pe_align , pv - > pe_align_offset ) ;
return 0 ;
}
2013-02-15 14:02:53 +04:00
final_alignment = pv - > pe_align + pv - > pe_align_offset ;
if ( pv - > size < final_alignment ) {
2013-02-21 17:47:49 +04:00
log_error ( " %s: Data alignment must not exceed device size. " ,
pv_dev_name ( pv ) ) ;
return 0 ;
}
2016-02-19 00:31:27 +03:00
if ( pv - > size < final_alignment + pva - > ba_size ) {
2013-05-28 14:37:22 +04:00
log_error ( " %s: Bootloader area with data-aligned start must "
2013-02-15 14:02:53 +04:00
" not exceed device size. " , pv_dev_name ( pv ) ) ;
return 0 ;
}
2016-02-19 00:31:27 +03:00
if ( pva - > pe_start = = PV_PE_START_CALC ) {
2013-02-15 14:02:53 +04:00
/*
2013-05-28 14:37:22 +04:00
* Calculate new PE start and bootloader area start value .
2013-02-15 14:02:53 +04:00
* Make sure both are properly aligned !
2014-04-10 16:18:59 +04:00
* If PE start can ' t be aligned because BA is taking
2013-02-15 14:02:53 +04:00
* the whole space , make PE start equal to the PV size
* which effectively disables DA - it will have zero size .
* This needs to be done as we can ' t have a PV without any DA .
2014-04-10 16:18:59 +04:00
* But we still want to support a PV with BA only !
2013-02-15 14:02:53 +04:00
*/
2016-02-19 00:31:27 +03:00
if ( pva - > ba_size ) {
2013-05-28 14:37:22 +04:00
pv - > ba_start = final_alignment ;
2016-02-19 00:31:27 +03:00
pv - > ba_size = pva - > ba_size ;
if ( ( adjustment = pva - > ba_size % pv - > pe_align ) )
2013-05-28 14:37:22 +04:00
pv - > ba_size + = pv - > pe_align - adjustment ;
if ( pv - > size < pv - > ba_start + pv - > ba_size )
pv - > ba_size = pv - > size - pv - > ba_start ;
pv - > pe_start = pv - > ba_start + pv - > ba_size ;
2013-02-15 14:02:53 +04:00
} else
pv - > pe_start = final_alignment ;
} else {
/*
* Try to keep the value of PE start set to a firm value if
* requested . This is useful when restoring existing PE start
2014-04-10 16:18:59 +04:00
* value ( e . g . backups ) . Also , if creating a BA , try to place
2013-02-15 14:02:53 +04:00
* it in between the final alignment and existing PE start
* if possible .
*/
2016-02-19 00:31:27 +03:00
pv - > pe_start = pva - > pe_start ;
if ( pva - > ba_size ) {
if ( ( pva - > ba_start & & pva - > ba_start + pva - > ba_size > pva - > pe_start ) | |
( pva - > pe_start < = final_alignment ) | |
( pva - > pe_start - final_alignment < pva - > ba_size ) ) {
2013-05-28 14:37:22 +04:00
log_error ( " %s: Bootloader area would overlap "
2013-02-15 14:02:53 +04:00
" data area. " , pv_dev_name ( pv ) ) ;
return 0 ;
}
2017-07-19 17:16:12 +03:00
pv - > ba_start = pva - > ba_start ? : final_alignment ;
pv - > ba_size = pva - > ba_size ;
2013-02-15 14:02:53 +04:00
}
}
2011-02-21 15:20:18 +03:00
2016-02-19 00:31:27 +03:00
if ( pva - > extent_size )
pv - > pe_size = pva - > extent_size ;
2011-02-21 15:20:18 +03:00
2016-02-19 00:31:27 +03:00
if ( pva - > extent_count )
pv - > pe_count = pva - > extent_count ;
2011-02-21 15:20:18 +03:00
2015-05-07 12:08:49 +03:00
if ( ( pv - > pe_start + pv - > pe_count * ( uint64_t ) pv - > pe_size - 1 ) > pv - > size ) {
2011-02-21 15:20:18 +03:00
log_error ( " Physical extents end beyond end of device %s. " ,
2015-05-07 12:08:49 +03:00
pv_dev_name ( pv ) ) ;
2011-02-21 15:20:18 +03:00
return 0 ;
}
2016-02-19 00:31:27 +03:00
if ( pva - > label_sector ! = - 1 )
pv - > label_sector = pva - > label_sector ;
2011-02-21 15:20:18 +03:00
return 1 ;
}
2011-03-11 17:38:38 +03:00
static void _text_destroy_instance ( struct format_instance * fid )
2001-11-21 12:20:05 +03:00
{
2011-03-11 17:38:38 +03:00
if ( - - fid - > ref_count < = 1 ) {
2012-02-13 03:01:19 +04:00
if ( fid - > metadata_areas_index )
2012-02-10 06:53:03 +04:00
dm_hash_destroy ( fid - > metadata_areas_index ) ;
2011-03-11 17:38:38 +03:00
dm_pool_destroy ( fid - > mem ) ;
}
2002-04-24 22:20:51 +04:00
}
2008-11-04 01:14:30 +03:00
static void _free_dirs ( struct dm_list * dir_list )
2002-04-24 22:20:51 +04:00
{
2008-11-04 01:14:30 +03:00
struct dm_list * dl , * tmp ;
2002-04-24 22:20:51 +04:00
2008-11-04 01:14:30 +03:00
dm_list_iterate_safe ( dl , tmp , dir_list ) {
dm_list_del ( dl ) ;
2005-10-17 03:03:59 +04:00
dm_free ( dl ) ;
2002-04-24 22:20:51 +04:00
}
}
2008-11-04 01:14:30 +03:00
static void _free_raws ( struct dm_list * raw_list )
2002-11-18 17:04:08 +03:00
{
2008-11-04 01:14:30 +03:00
struct dm_list * rl , * tmp ;
2002-11-18 17:04:08 +03:00
2008-11-04 01:14:30 +03:00
dm_list_iterate_safe ( rl , tmp , raw_list ) {
dm_list_del ( rl ) ;
2005-10-17 03:03:59 +04:00
dm_free ( rl ) ;
2002-11-18 17:04:08 +03:00
}
}
2010-12-20 16:32:49 +03:00
static void _text_destroy ( struct format_type * fmt )
2002-04-24 22:20:51 +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
2002-04-24 22:20:51 +04:00
if ( fmt - > private ) {
2002-11-18 17:04:08 +03:00
_free_dirs ( & ( ( struct mda_lists * ) fmt - > private ) - > dirs ) ;
_free_raws ( & ( ( struct mda_lists * ) fmt - > private ) - > raws ) ;
2005-10-17 03:03:59 +04:00
dm_free ( fmt - > private ) ;
2002-04-24 22:20:51 +04:00
}
2010-12-20 16:32:49 +03:00
dm_free ( fmt ) ;
2002-04-24 22:20:51 +04:00
}
2002-11-18 17:04:08 +03:00
static struct metadata_area_ops _metadata_text_file_ops = {
2006-05-10 01:23:51 +04:00
. vg_read = _vg_read_file ,
. vg_read_precommit = _vg_read_precommit_file ,
. vg_write = _vg_write_file ,
. vg_remove = _vg_remove_file ,
. vg_commit = _vg_commit_file
2002-11-18 17:04:08 +03:00
} ;
static struct metadata_area_ops _metadata_text_file_backup_ops = {
2006-05-10 01:23:51 +04:00
. vg_read = _vg_read_file ,
. vg_write = _vg_write_file ,
. vg_remove = _vg_remove_file ,
. vg_commit = _vg_commit_file_backup
2002-11-18 17:04:08 +03:00
} ;
2012-08-11 12:37:28 +04:00
static int _mda_export_text_raw ( struct metadata_area * mda ,
struct dm_config_tree * cft ,
struct dm_config_node * parent ) ;
2012-02-23 17:11:07 +04:00
static int _mda_import_text_raw ( struct lvmcache_info * info , const struct dm_config_node * cn ) ;
2002-11-18 17:04:08 +03:00
static struct metadata_area_ops _metadata_text_raw_ops = {
2006-05-10 01:23:51 +04:00
. vg_read = _vg_read_raw ,
. vg_read_precommit = _vg_read_precommit_raw ,
. vg_write = _vg_write_raw ,
. vg_remove = _vg_remove_raw ,
. vg_precommit = _vg_precommit_raw ,
. vg_commit = _vg_commit_raw ,
2007-03-23 15:43:17 +03:00
. vg_revert = _vg_revert_raw ,
2010-06-29 00:31:59 +04:00
. mda_metadata_locn_copy = _metadata_locn_copy_raw ,
2010-06-30 17:51:11 +04:00
. mda_metadata_locn_name = _metadata_locn_name_raw ,
. mda_metadata_locn_offset = _metadata_locn_offset_raw ,
2007-11-05 20:17:55 +03:00
. mda_free_sectors = _mda_free_sectors_raw ,
2009-01-10 01:44:33 +03:00
. mda_total_sectors = _mda_total_sectors_raw ,
2007-03-23 15:43:17 +03:00
. mda_in_vg = _mda_in_vg_raw ,
2007-04-26 01:10:55 +04:00
. pv_analyze_mda = _pv_analyze_mda_raw ,
2011-06-15 21:45:02 +04:00
. mda_locns_match = _mda_locns_match_raw ,
2012-02-23 17:11:07 +04:00
. mda_get_device = _mda_get_device_raw ,
. mda_export_text = _mda_export_text_raw ,
. mda_import_text = _mda_import_text_raw
2002-11-18 17:04:08 +03:00
} ;
2012-08-11 12:37:28 +04:00
static int _mda_export_text_raw ( struct metadata_area * mda ,
struct dm_config_tree * cft ,
struct dm_config_node * parent )
2012-02-23 17:11:07 +04:00
{
struct mda_context * mdc = ( struct mda_context * ) mda - > metadata_locn ;
2014-02-28 02:06:42 +04:00
char mdah [ MDA_HEADER_SIZE ] ; /* temporary */
2017-12-07 06:34:59 +03:00
if ( ! mdc | | ! _raw_read_mda_header ( ( struct mda_header * ) mdah , & mdc - > area , mda_is_primary ( mda ) ) )
2014-02-28 02:06:42 +04:00
return 1 ; /* pretend the MDA does not exist */
2012-02-23 21:59:32 +04:00
2012-08-11 12:37:28 +04:00
return config_make_nodes ( cft , parent , NULL ,
2017-12-11 18:32:53 +03:00
" ignore = " FMTd64 , ( int64_t ) mda_is_ignored ( mda ) ,
" start = " FMTd64 , ( int64_t ) mdc - > area . start ,
" size = " FMTd64 , ( int64_t ) mdc - > area . size ,
" free_sectors = " FMTd64 , ( int64_t ) mdc - > free_sectors ,
2012-08-11 12:37:28 +04:00
NULL ) ? 1 : 0 ;
2012-02-23 17:11:07 +04:00
}
static int _mda_import_text_raw ( struct lvmcache_info * info , const struct dm_config_node * cn )
{
2012-02-23 21:59:32 +04:00
struct device * device ;
uint64_t offset ;
uint64_t size ;
int ignore ;
2012-02-23 17:11:07 +04:00
if ( ! cn - > child )
return 0 ;
2012-02-23 21:59:32 +04:00
cn = cn - > child ;
device = lvmcache_device ( info ) ;
2013-08-06 15:37:42 +04:00
size = dm_config_find_int64 ( cn , " size " , 0 ) ;
2012-02-23 17:11:07 +04:00
if ( ! device | | ! size )
return 0 ;
2013-08-06 15:37:42 +04:00
offset = dm_config_find_int64 ( cn , " start " , 0 ) ;
2012-02-23 21:59:32 +04:00
ignore = dm_config_find_int ( cn , " ignore " , 0 ) ;
2012-02-23 17:11:07 +04:00
lvmcache_add_mda ( info , device , offset , size , ignore ) ;
2012-02-23 21:59:32 +04:00
2012-02-23 17:11:07 +04:00
return 1 ;
}
2006-04-19 19:33:07 +04:00
static int _text_pv_setup ( const struct format_type * fmt ,
2011-02-21 15:24:15 +03:00
struct physical_volume * pv ,
struct volume_group * vg )
2002-11-18 17:04:08 +03:00
{
2011-02-21 15:24:15 +03:00
struct format_instance * fid = pv - > fid ;
2011-02-21 15:31:28 +03:00
const char * pvid = ( const char * ) ( * pv - > old_id . uuid ? & pv - > old_id : & pv - > id ) ;
2011-02-25 16:59:47 +03:00
struct lvmcache_info * info ;
2011-02-21 15:24:15 +03:00
unsigned mda_index ;
2011-03-02 13:23:29 +03:00
struct metadata_area * pv_mda , * pv_mda_copy ;
2011-02-21 15:24:15 +03:00
struct mda_context * pv_mdac ;
2006-11-10 21:24:11 +03:00
uint64_t pe_count ;
2011-02-21 15:24:15 +03:00
uint64_t size_reduction = 0 ;
2002-11-18 17:04:08 +03:00
2011-02-25 16:59:47 +03:00
/* If PV has its own format instance, add mdas from pv->fid to vg->fid. */
if ( pv - > fid ! = vg - > fid ) {
for ( mda_index = 0 ; mda_index < FMT_TEXT_MAX_MDAS_PER_PV ; mda_index + + ) {
if ( ! ( pv_mda = fid_get_mda_indexed ( fid , pvid , ID_LEN , mda_index ) ) )
continue ;
2002-11-18 17:04:08 +03:00
2011-02-25 16:59:47 +03:00
/* Be sure it's not already in VG's format instance! */
2011-03-02 13:23:29 +03:00
if ( ! fid_get_mda_indexed ( vg - > fid , pvid , ID_LEN , mda_index ) ) {
2012-02-13 15:09:25 +04:00
if ( ! ( pv_mda_copy = mda_copy ( vg - > fid - > mem , pv_mda ) ) )
return_0 ;
2011-03-02 13:23:29 +03:00
fid_add_mda ( vg - > fid , pv_mda_copy , pvid , ID_LEN , mda_index ) ;
}
2011-02-25 16:59:47 +03:00
}
}
/*
* Otherwise , if the PV is already a part of the VG ( pv - > fid = = vg - > fid ) ,
* reread PV mda information from the cache and add it to vg - > fid .
*/
else {
2012-02-23 17:11:07 +04:00
if ( ! pv - > dev | |
2016-06-06 22:04:17 +03:00
! ( info = lvmcache_info_from_pvid ( pv - > dev - > pvid , pv - > dev , 0 ) ) ) {
2011-02-25 16:59:47 +03:00
log_error ( " PV %s missing from cache " , pv_dev_name ( pv ) ) ;
return 0 ;
}
2012-02-10 05:28:27 +04:00
if ( ! lvmcache_check_format ( info , fmt ) )
return_0 ;
2011-02-25 16:59:47 +03:00
2012-02-10 05:28:27 +04:00
if ( ! lvmcache_fid_add_mdas_pv ( info , fid ) )
2011-02-25 16:59:47 +03:00
return_0 ;
2011-02-21 15:24:15 +03:00
}
2002-11-18 17:04:08 +03:00
2011-02-21 15:24:15 +03:00
/* If there's the 2nd mda, we need to reduce
* usable size for further pe_count calculation ! */
if ( ( pv_mda = fid_get_mda_indexed ( fid , pvid , ID_LEN , 1 ) ) & &
( pv_mdac = pv_mda - > metadata_locn ) )
size_reduction = pv_mdac - > area . size > > SECTOR_SHIFT ;
2006-10-06 02:02:52 +04:00
2011-02-21 15:24:15 +03:00
/* From now on, VG format instance will be used. */
2011-03-11 17:50:13 +03:00
pv_set_fid ( pv , vg - > fid ) ;
2009-07-30 21:45:28 +04:00
2011-02-21 15:24:15 +03:00
/* FIXME Cope with genuine pe_count 0 */
2009-07-30 21:45:28 +04:00
2011-02-21 15:24:15 +03:00
/* If missing, estimate pv->size from file-based metadata */
if ( ! pv - > size & & pv - > pe_count )
pv - > size = pv - > pe_count * ( uint64_t ) vg - > extent_size +
pv - > pe_start + size_reduction ;
2009-07-31 01:15:17 +04:00
2011-02-21 15:24:15 +03:00
/* Recalculate number of extents that will fit */
2012-05-09 16:30:56 +04:00
if ( ! pv - > pe_count & & vg - > extent_size ) {
2011-02-21 15:24:15 +03:00
pe_count = ( pv - > size - pv - > pe_start - size_reduction ) /
vg - > extent_size ;
if ( pe_count > UINT32_MAX ) {
log_error ( " PV %s too large for extent size %s. " ,
pv_dev_name ( pv ) ,
display_size ( vg - > cmd , ( uint64_t ) vg - > extent_size ) ) ;
return 0 ;
}
pv - > pe_count = ( uint32_t ) pe_count ;
2002-11-18 17:04:08 +03:00
}
return 1 ;
}
2011-03-11 17:45:17 +03:00
static void * _create_text_context ( struct dm_pool * mem , struct text_context * tc )
{
struct text_context * new_tc ;
const char * path ;
char * tmp ;
if ( ! tc )
return NULL ;
path = tc - > path_live ;
if ( ( tmp = strstr ( path , " .tmp " ) ) & & ( tmp = = path + strlen ( path ) - 4 ) ) {
log_error ( " %s: Volume group filename may not end in .tmp " ,
path ) ;
return NULL ;
}
if ( ! ( new_tc = dm_pool_alloc ( mem , sizeof ( * new_tc ) ) ) )
return_NULL ;
if ( ! ( new_tc - > path_live = dm_pool_strdup ( mem , path ) ) )
goto_bad ;
/* If path_edit not defined, create one from path_live with .tmp suffix. */
if ( ! tc - > path_edit ) {
if ( ! ( tmp = dm_pool_alloc ( mem , strlen ( path ) + 5 ) ) )
goto_bad ;
sprintf ( tmp , " %s.tmp " , path ) ;
new_tc - > path_edit = tmp ;
}
else if ( ! ( new_tc - > path_edit = dm_pool_strdup ( mem , tc - > path_edit ) ) )
goto_bad ;
if ( ! ( new_tc - > desc = tc - > desc ? dm_pool_strdup ( mem , tc - > desc )
: dm_pool_strdup ( mem , " " ) ) )
goto_bad ;
return ( void * ) new_tc ;
bad :
dm_pool_free ( mem , new_tc ) ;
log_error ( " Couldn't allocate text format context object. " ) ;
return NULL ;
}
2011-02-21 15:05:49 +03:00
static int _create_vg_text_instance ( struct format_instance * fid ,
const struct format_instance_ctx * fic )
{
2011-11-18 23:31:09 +04:00
static char path [ PATH_MAX ] ;
2011-02-21 15:05:49 +03:00
uint32_t type = fic - > type ;
2005-10-23 04:14:48 +04:00
struct text_fid_context * fidtc ;
2010-06-29 00:35:17 +04:00
struct metadata_area * mda ;
2010-02-02 19:26:34 +03:00
struct mda_context * mdac ;
2002-04-24 22:20:51 +04:00
struct dir_list * dl ;
2002-11-18 17:04:08 +03:00
struct raw_list * rl ;
2010-06-29 00:35:17 +04:00
struct dm_list * dir_list , * raw_list ;
2011-03-11 17:45:17 +03:00
struct text_context tc ;
2003-07-05 02:34:56 +04:00
struct lvmcache_vginfo * vginfo ;
2011-02-21 15:05:49 +03:00
const char * vg_name , * vg_id ;
2002-04-24 22:20:51 +04:00
2005-10-23 04:14:48 +04:00
if ( ! ( fidtc = ( struct text_fid_context * )
2011-03-11 18:10:16 +03:00
dm_pool_zalloc ( fid - > mem , sizeof ( * fidtc ) ) ) ) {
2005-10-23 04:14:48 +04:00
log_error ( " Couldn't allocate text_fid_context. " ) ;
2011-02-21 15:05:49 +03:00
return 0 ;
2005-10-23 04:14:48 +04:00
}
fid - > private = ( void * ) fidtc ;
2002-04-24 22:20:51 +04:00
2011-02-21 15:05:49 +03:00
if ( type & FMT_INSTANCE_PRIVATE_MDAS ) {
2011-03-11 18:10:16 +03:00
if ( ! ( mda = dm_pool_zalloc ( fid - > mem , sizeof ( * mda ) ) ) )
2011-02-21 15:05:49 +03:00
return_0 ;
2002-11-18 17:04:08 +03:00
mda - > ops = & _metadata_text_file_backup_ops ;
2011-03-11 18:10:16 +03:00
mda - > metadata_locn = _create_text_context ( fid - > mem , fic - > context . private ) ;
2010-10-05 21:34:05 +04:00
mda - > status = 0 ;
2012-02-10 06:53:03 +04:00
fid - > metadata_areas_index = NULL ;
2011-02-21 15:05:49 +03:00
fid_add_mda ( fid , mda , NULL , 0 , 0 ) ;
2002-04-24 22:20:51 +04:00
} else {
2011-02-21 15:05:49 +03:00
vg_name = fic - > context . vg_ref . vg_name ;
vg_id = fic - > context . vg_ref . vg_id ;
2002-04-24 22:20:51 +04:00
2012-02-10 06:53:03 +04:00
if ( ! ( fid - > metadata_areas_index = dm_hash_create ( 128 ) ) ) {
2011-02-21 15:05:49 +03:00
log_error ( " Couldn't create metadata index for format "
" instance of VG %s. " , vg_name ) ;
return 0 ;
2002-04-24 22:20:51 +04:00
}
2002-11-18 17:04:08 +03:00
2011-02-21 15:05:49 +03:00
if ( type & FMT_INSTANCE_AUX_MDAS ) {
dir_list = & ( ( struct mda_lists * ) fid - > fmt - > private ) - > dirs ;
dm_list_iterate_items ( dl , dir_list ) {
if ( dm_snprintf ( path , PATH_MAX , " %s/%s " , dl - > dir , vg_name ) < 0 ) {
log_error ( " Name too long %s/%s " , dl - > dir , vg_name ) ;
return 0 ;
}
2011-03-11 18:10:16 +03:00
if ( ! ( mda = dm_pool_zalloc ( fid - > mem , sizeof ( * mda ) ) ) )
2011-02-21 15:05:49 +03:00
return_0 ;
mda - > ops = & _metadata_text_file_ops ;
2011-03-11 17:45:17 +03:00
tc . path_live = path ;
tc . path_edit = tc . desc = NULL ;
2011-03-11 18:10:16 +03:00
mda - > metadata_locn = _create_text_context ( fid - > mem , & tc ) ;
2011-02-21 15:05:49 +03:00
mda - > status = 0 ;
fid_add_mda ( fid , mda , NULL , 0 , 0 ) ;
}
raw_list = & ( ( struct mda_lists * ) fid - > fmt - > private ) - > raws ;
dm_list_iterate_items ( rl , raw_list ) {
/* FIXME Cache this; rescan below if some missing */
if ( ! _raw_holds_vgname ( fid , & rl - > dev_area , vg_name ) )
continue ;
2011-03-11 18:10:16 +03:00
if ( ! ( mda = dm_pool_zalloc ( fid - > mem , sizeof ( * mda ) ) ) )
2011-02-21 15:05:49 +03:00
return_0 ;
2011-03-11 18:10:16 +03:00
if ( ! ( mdac = dm_pool_zalloc ( fid - > mem , sizeof ( * mdac ) ) ) )
2011-02-21 15:05:49 +03:00
return_0 ;
mda - > metadata_locn = mdac ;
/* FIXME Allow multiple dev_areas inside area */
memcpy ( & mdac - > area , & rl - > dev_area , sizeof ( mdac - > area ) ) ;
mda - > ops = & _metadata_text_raw_ops ;
mda - > status = 0 ;
/* FIXME MISTAKE? mda->metadata_locn = context; */
fid_add_mda ( fid , mda , NULL , 0 , 0 ) ;
}
2002-11-18 17:04:08 +03:00
}
2011-02-21 15:05:49 +03:00
if ( type & FMT_INSTANCE_MDAS ) {
2014-02-18 20:52:05 +04:00
/*
* TODO in theory , this function should be never reached
* while in critical_section ( ) , because lvmcache ' s
* cached_vg should be valid . However , this assumption
* sometimes fails ( possibly due to inconsistent
* ( precommit ) metadata and / or missing devices ) , and
* calling lvmcache_label_scan inside the critical
* section may be fatal ( i . e . deadlock ) .
*/
if ( ! critical_section ( ) )
/* Scan PVs in VG for any further MDAs */
2017-07-13 19:05:49 +03:00
/*
* FIXME Only scan PVs believed to be in the VG .
*/
2015-12-01 23:09:01 +03:00
lvmcache_label_scan ( fid - > fmt - > cmd ) ;
2014-02-18 20:52:05 +04:00
2012-02-10 05:28:27 +04:00
if ( ! ( vginfo = lvmcache_vginfo_from_vgname ( vg_name , vg_id ) ) )
goto_out ;
if ( ! lvmcache_fid_add_mdas_vg ( vginfo , fid ) )
2011-02-21 15:05:49 +03:00
goto_out ;
2002-11-18 17:04:08 +03:00
}
2011-02-21 15:05:49 +03:00
2017-07-13 19:05:49 +03:00
/* FIXME If PV list or raw metadata area count are not as expected rescan */
2002-04-24 22:20:51 +04:00
}
2011-02-21 15:05:49 +03:00
out :
return 1 ;
}
2011-03-02 13:19:14 +03:00
static int _add_metadata_area_to_pv ( struct physical_volume * pv ,
unsigned mda_index ,
uint64_t mda_start ,
uint64_t mda_size ,
unsigned mda_ignored )
2011-02-21 15:17:26 +03:00
{
struct metadata_area * mda ;
struct mda_context * mdac ;
struct mda_lists * mda_lists = ( struct mda_lists * ) pv - > fmt - > private ;
if ( mda_index > = FMT_TEXT_MAX_MDAS_PER_PV ) {
log_error ( INTERNAL_ERROR " can't add metadata area with "
" index %u to PV %s. Metadata "
" layout not supported by %s format. " ,
mda_index , dev_name ( pv - > dev ) ,
pv - > fmt - > name ) ;
}
2011-03-11 18:10:16 +03:00
if ( ! ( mda = dm_pool_zalloc ( pv - > fid - > mem , sizeof ( struct metadata_area ) ) ) ) {
2011-02-21 15:17:26 +03:00
log_error ( " struct metadata_area allocation failed " ) ;
return 0 ;
}
2011-03-11 18:10:16 +03:00
if ( ! ( mdac = dm_pool_zalloc ( pv - > fid - > mem , sizeof ( struct mda_context ) ) ) ) {
2011-02-21 15:17:26 +03:00
log_error ( " struct mda_context allocation failed " ) ;
dm_free ( mda ) ;
return 0 ;
}
mda - > ops = mda_lists - > raw_ops ;
mda - > metadata_locn = mdac ;
mda - > status = 0 ;
mdac - > area . dev = pv - > dev ;
mdac - > area . start = mda_start ;
mdac - > area . size = mda_size ;
mdac - > free_sectors = UINT64_C ( 0 ) ;
memset ( & mdac - > rlocn , 0 , sizeof ( mdac - > rlocn ) ) ;
mda_set_ignored ( mda , mda_ignored ) ;
fid_add_mda ( pv - > fid , mda , ( char * ) & pv - > id , ID_LEN , mda_index ) ;
return 1 ;
}
2012-02-10 06:53:03 +04:00
static int _text_pv_remove_metadata_area ( const struct format_type * fmt ,
struct physical_volume * pv ,
unsigned mda_index ) ;
2011-02-21 15:17:26 +03:00
static int _text_pv_add_metadata_area ( const struct format_type * fmt ,
struct physical_volume * pv ,
int pe_start_locked ,
unsigned mda_index ,
uint64_t mda_size ,
unsigned mda_ignored )
{
struct format_instance * fid = pv - > fid ;
2011-02-21 15:31:28 +03:00
const char * pvid = ( const char * ) ( * pv - > old_id . uuid ? & pv - > old_id : & pv - > id ) ;
2017-08-15 14:23:51 +03:00
uint64_t ba_size , pe_start , first_unallocated ;
2011-02-21 15:17:26 +03:00
uint64_t alignment , alignment_offset ;
uint64_t disk_size ;
uint64_t mda_start ;
2011-02-25 16:50:02 +03:00
uint64_t adjustment , limit , tmp_mda_size ;
2011-02-21 15:17:26 +03:00
uint64_t wipe_size = 8 < < SECTOR_SHIFT ;
size_t page_size = lvm_getpagesize ( ) ;
struct metadata_area * mda ;
struct mda_context * mdac ;
2011-02-25 16:50:02 +03:00
const char * limit_name ;
int limit_applied = 0 ;
2011-02-21 15:17:26 +03:00
if ( mda_index > = FMT_TEXT_MAX_MDAS_PER_PV ) {
log_error ( INTERNAL_ERROR " invalid index of value %u used "
" while trying to add metadata area on PV %s. "
" Metadata layout not supported by %s format. " ,
mda_index , pv_dev_name ( pv ) , fmt - > name ) ;
return 0 ;
}
pe_start = pv - > pe_start < < SECTOR_SHIFT ;
2013-05-28 14:37:22 +04:00
ba_size = pv - > ba_size < < SECTOR_SHIFT ;
2011-02-21 15:17:26 +03:00
alignment = pv - > pe_align < < SECTOR_SHIFT ;
alignment_offset = pv - > pe_align_offset < < SECTOR_SHIFT ;
disk_size = pv - > size < < SECTOR_SHIFT ;
mda_size = mda_size < < SECTOR_SHIFT ;
if ( fid_get_mda_indexed ( fid , pvid , ID_LEN , mda_index ) ) {
2012-02-10 06:53:03 +04:00
if ( ! _text_pv_remove_metadata_area ( fmt , pv , mda_index ) ) {
log_error ( INTERNAL_ERROR " metadata area with index %u already "
" exists on PV %s and removal failed. " ,
mda_index , pv_dev_name ( pv ) ) ;
return 0 ;
}
2011-02-21 15:17:26 +03:00
}
/* First metadata area at the start of the device. */
if ( mda_index = = 0 ) {
/*
* Try to fit MDA0 end within given pe_start limit if its value
* is locked . If it ' s not locked , count with any existing MDA1 .
* If there ' s no MDA1 , just use disk size as the limit .
*/
2011-02-25 16:50:02 +03:00
if ( pe_start_locked ) {
2011-02-21 15:17:26 +03:00
limit = pe_start ;
2011-02-25 16:50:02 +03:00
limit_name = " pe_start " ;
}
2011-02-21 15:17:26 +03:00
else if ( ( mda = fid_get_mda_indexed ( fid , pvid , ID_LEN , 1 ) ) & &
2011-02-25 16:50:02 +03:00
( mdac = mda - > metadata_locn ) ) {
2011-02-21 15:17:26 +03:00
limit = mdac - > area . start ;
2011-02-25 16:50:02 +03:00
limit_name = " MDA1 start " ;
}
else {
2011-02-21 15:17:26 +03:00
limit = disk_size ;
2011-02-25 16:50:02 +03:00
limit_name = " disk size " ;
}
2011-02-21 15:17:26 +03:00
2013-05-28 14:37:22 +04:00
/* Adjust limits for bootloader area if present. */
if ( ba_size ) {
limit - = ba_size ;
limit_name = " ba_start " ;
2013-02-15 14:02:53 +04:00
}
2011-02-21 15:17:26 +03:00
if ( limit > disk_size )
goto bad ;
mda_start = LABEL_SCAN_SIZE ;
/* Align MDA0 start with page size if possible. */
if ( limit - mda_start > = MDA_SIZE_MIN ) {
if ( ( adjustment = mda_start % page_size ) )
mda_start + = ( page_size - adjustment ) ;
}
/* Align MDA0 end position with given alignment if possible. */
2011-02-25 16:50:02 +03:00
if ( alignment & &
( adjustment = ( mda_start + mda_size ) % alignment ) ) {
tmp_mda_size = mda_size + alignment - adjustment ;
if ( mda_start + tmp_mda_size < = limit )
mda_size = tmp_mda_size ;
2011-02-21 15:17:26 +03:00
}
/* Align MDA0 end position with given alignment offset if possible. */
2015-11-16 03:04:21 +03:00
if ( alignment & & alignment_offset & &
2011-02-21 15:17:26 +03:00
( ( ( mda_start + mda_size ) % alignment ) = = 0 ) ) {
2011-02-25 16:50:02 +03:00
tmp_mda_size = mda_size + alignment_offset ;
if ( mda_start + tmp_mda_size < = limit )
mda_size = tmp_mda_size ;
2011-02-21 15:17:26 +03:00
}
if ( mda_start + mda_size > limit ) {
/*
* Try to decrease the MDA0 size with twice the
* alignment and then align with given alignment .
* If pe_start is locked , skip this type of
* alignment since it would be useless .
* Check first whether we can apply that !
*/
2013-11-24 22:00:53 +04:00
if ( ! pe_start_locked & & alignment & &
2011-02-21 15:17:26 +03:00
( ( limit - mda_start ) > alignment * 2 ) ) {
mda_size = limit - mda_start - alignment * 2 ;
if ( ( adjustment = ( mda_start + mda_size ) % alignment ) )
mda_size + = ( alignment - adjustment ) ;
/* Still too much? Then there's nothing else to do. */
if ( mda_start + mda_size > limit )
goto bad ;
}
/* Otherwise, give up and take any usable space. */
else
mda_size = limit - mda_start ;
2011-02-25 16:50:02 +03:00
limit_applied = 1 ;
2011-02-21 15:17:26 +03:00
}
/*
* If PV ' s pe_start is not locked , update pe_start value with the
* start of the area that follows the MDA0 we ' ve just calculated .
*/
if ( ! pe_start_locked ) {
2013-05-28 14:37:22 +04:00
if ( ba_size ) {
pv - > ba_start = ( mda_start + mda_size ) > > SECTOR_SHIFT ;
pv - > pe_start = pv - > ba_start + pv - > ba_size ;
2013-02-15 14:02:53 +04:00
} else
pv - > pe_start = ( mda_start + mda_size ) > > SECTOR_SHIFT ;
2011-02-21 15:17:26 +03:00
}
}
/* Second metadata area at the end of the device. */
else {
/*
* Try to fit MDA1 start within given pe_end or pe_start limit
2011-02-25 16:50:02 +03:00
* if defined or locked . If pe_start is not defined yet , count
* with any existing MDA0 . If MDA0 does not exist , just use
* LABEL_SCAN_SIZE .
2017-08-15 14:23:51 +03:00
*
* The first_unallocated here is the first unallocated byte
* beyond existing pe_end if there is any preallocated data area
* reserved already so we can take that as lower limit for our MDA1
* start calculation . If data area is not reserved yet , we set
* first_unallocated to 0 , meaning this is not our limiting factor
* and we will look at other limiting factors if they exist .
* Of course , if we have preallocated data area , we also must
* have pe_start assigned too ( simply , data area needs its start
* and end specification ) .
2011-02-21 15:17:26 +03:00
*/
2017-08-15 14:23:51 +03:00
first_unallocated = pv - > pe_count ? ( pv - > pe_start + pv - > pe_count *
( uint64_t ) pv - > pe_size ) < < SECTOR_SHIFT
: 0 ;
2011-02-25 16:50:02 +03:00
if ( pe_start | | pe_start_locked ) {
2017-08-15 14:23:51 +03:00
limit = first_unallocated ? first_unallocated : pe_start ;
limit_name = first_unallocated ? " pe_end " : " pe_start " ;
2013-02-15 14:02:53 +04:00
} else {
if ( ( mda = fid_get_mda_indexed ( fid , pvid , ID_LEN , 0 ) ) & &
( mdac = mda - > metadata_locn ) ) {
limit = mdac - > area . start + mdac - > area . size ;
limit_name = " MDA0 end " ;
}
else {
limit = LABEL_SCAN_SIZE ;
limit_name = " label scan size " ;
}
2013-05-28 14:37:22 +04:00
/* Adjust limits for bootloader area if present. */
if ( ba_size ) {
limit + = ba_size ;
limit_name = " ba_end " ;
2013-02-15 14:02:53 +04:00
}
2011-02-25 16:50:02 +03:00
}
2011-02-21 15:17:26 +03:00
2017-08-15 14:23:51 +03:00
if ( limit > = disk_size )
2011-02-21 15:17:26 +03:00
goto bad ;
2011-02-25 16:50:02 +03:00
if ( mda_size > disk_size ) {
mda_size = disk_size - limit ;
limit_applied = 1 ;
2011-02-21 15:17:26 +03:00
}
2011-02-25 16:50:02 +03:00
mda_start = disk_size - mda_size ;
/* If MDA1 size is too big, just take any usable space. */
if ( disk_size - mda_size < limit ) {
2011-02-21 15:17:26 +03:00
mda_size = disk_size - limit ;
2011-02-25 16:50:02 +03:00
mda_start = disk_size - mda_size ;
limit_applied = 1 ;
}
/* Otherwise, try to align MDA1 start if possible. */
else if ( alignment & &
( adjustment = mda_start % alignment ) ) {
tmp_mda_size = mda_size + adjustment ;
if ( tmp_mda_size < disk_size & &
disk_size - tmp_mda_size > = limit ) {
mda_size = tmp_mda_size ;
mda_start = disk_size - mda_size ;
}
}
2011-02-21 15:17:26 +03:00
}
2011-02-25 16:50:02 +03:00
if ( limit_applied )
log_very_verbose ( " Using limited metadata area size on %s "
2017-12-11 18:32:53 +03:00
" with value " FMTu64 " (limited by %s of "
2015-07-06 17:09:17 +03:00
FMTu64 " ). " , pv_dev_name ( pv ) ,
2011-02-25 16:50:02 +03:00
mda_size , limit_name , limit ) ;
2011-02-21 15:17:26 +03:00
if ( mda_size ) {
2015-10-30 14:02:29 +03:00
if ( mda_size < MDA_SIZE_MIN ) {
2017-12-11 18:32:53 +03:00
log_error ( " Metadata area size too small: " FMTu64 " bytes. "
2015-10-30 14:02:29 +03:00
" It must be at least %u bytes. " , mda_size , MDA_SIZE_MIN ) ;
goto bad ;
}
2011-02-21 15:17:26 +03:00
/* Wipe metadata area with zeroes. */
2017-07-20 10:57:09 +03:00
if ( ! dev_set ( pv - > dev , mda_start ,
2017-12-05 02:18:56 +03:00
( size_t ) ( ( mda_size > wipe_size ) ? wipe_size : mda_size ) ,
2017-12-07 06:34:59 +03:00
MDA_HEADER_REASON ( ! mda_index ) , 0 ) ) {
2017-12-05 02:18:56 +03:00
log_error ( " Failed to wipe new metadata area "
" at the %s of the %s " ,
mda_index ? " end " : " start " ,
pv_dev_name ( pv ) ) ;
return 0 ;
2011-02-21 15:17:26 +03:00
}
/* Finally, add new metadata area to PV's format instance. */
2011-03-02 13:19:14 +03:00
if ( ! _add_metadata_area_to_pv ( pv , mda_index , mda_start ,
mda_size , mda_ignored ) )
2011-02-21 15:17:26 +03:00
return_0 ;
}
return 1 ;
bad :
log_error ( " Not enough space available for metadata area "
" with index %u on PV %s. " , mda_index , pv_dev_name ( pv ) ) ;
return 0 ;
}
2011-03-02 13:19:14 +03:00
static int _remove_metadata_area_from_pv ( struct physical_volume * pv ,
unsigned mda_index )
2011-02-21 15:17:54 +03:00
{
if ( mda_index > = FMT_TEXT_MAX_MDAS_PER_PV ) {
log_error ( INTERNAL_ERROR " can't remove metadata area with "
" index %u from PV %s. Metadata "
" layou not supported by %s format. " ,
mda_index , dev_name ( pv - > dev ) ,
pv - > fmt - > name ) ;
return 0 ;
}
return fid_remove_mda ( pv - > fid , NULL , ( const char * ) & pv - > id ,
ID_LEN , mda_index ) ;
}
static int _text_pv_remove_metadata_area ( const struct format_type * fmt ,
struct physical_volume * pv ,
unsigned mda_index )
{
2011-03-02 13:19:14 +03:00
return _remove_metadata_area_from_pv ( pv , mda_index ) ;
2011-02-21 15:17:54 +03:00
}
2011-02-21 15:27:26 +03:00
static int _text_pv_resize ( const struct format_type * fmt ,
struct physical_volume * pv ,
struct volume_group * vg ,
uint64_t size )
{
struct format_instance * fid = pv - > fid ;
2011-02-21 15:31:28 +03:00
const char * pvid = ( const char * ) ( * pv - > old_id . uuid ? & pv - > old_id : & pv - > id ) ;
2011-02-21 15:27:26 +03:00
struct metadata_area * mda ;
struct mda_context * mdac ;
uint64_t size_reduction ;
uint64_t mda_size ;
unsigned mda_ignored ;
/*
* First , set the new size and update the cache and reset pe_count .
* ( pe_count must be reset otherwise it would be considered as
* a limiting factor while moving the mda ! )
*/
pv - > size = size ;
pv - > pe_count = 0 ;
/* If there's an mda at the end, move it to a new position. */
if ( ( mda = fid_get_mda_indexed ( fid , pvid , ID_LEN , 1 ) ) & &
( mdac = mda - > metadata_locn ) ) {
/* FIXME: Maybe MDA0 size would be better? */
mda_size = mdac - > area . size > > SECTOR_SHIFT ;
mda_ignored = mda_is_ignored ( mda ) ;
if ( ! _text_pv_remove_metadata_area ( fmt , pv , 1 ) | |
! _text_pv_add_metadata_area ( fmt , pv , 1 , 1 , mda_size ,
mda_ignored ) ) {
log_error ( " Failed to move metadata area with index 1 "
" while resizing PV %s. " , pv_dev_name ( pv ) ) ;
return 0 ;
}
}
/* If there's a VG, reduce size by counting in pe_start and metadata areas. */
2014-01-17 05:12:04 +04:00
if ( vg & & ! is_orphan_vg ( vg - > name ) ) {
2011-02-21 15:27:26 +03:00
size_reduction = pv_pe_start ( pv ) ;
if ( ( mda = fid_get_mda_indexed ( fid , pvid , ID_LEN , 1 ) ) & &
( mdac = mda - > metadata_locn ) )
size_reduction + = mdac - > area . size > > SECTOR_SHIFT ;
pv - > size - = size_reduction ;
}
return 1 ;
}
2011-02-21 15:05:49 +03:00
static struct format_instance * _text_create_text_instance ( const struct format_type * fmt ,
2011-03-11 17:30:27 +03:00
const struct format_instance_ctx * fic )
2011-02-21 15:05:49 +03:00
{
struct format_instance * fid ;
2011-03-11 17:30:27 +03:00
if ( ! ( fid = alloc_fid ( fmt , fic ) ) )
return_NULL ;
2011-02-21 15:05:49 +03:00
2012-12-14 22:43:42 +04:00
if ( ! _create_vg_text_instance ( fid , fic ) ) {
dm_pool_destroy ( fid - > mem ) ;
return_NULL ;
}
2011-02-21 15:05:49 +03:00
2012-12-14 22:43:42 +04:00
return fid ;
2002-04-24 22:20:51 +04:00
}
2001-11-21 12:20:05 +03:00
static struct format_handler _text_handler = {
2006-05-10 01:23:51 +04:00
. scan = _text_scan ,
. pv_read = _text_pv_read ,
2011-02-21 15:20:18 +03:00
. pv_initialise = _text_pv_initialise ,
2006-05-10 01:23:51 +04:00
. pv_setup = _text_pv_setup ,
2011-02-21 15:17:26 +03:00
. pv_add_metadata_area = _text_pv_add_metadata_area ,
2011-02-21 15:17:54 +03:00
. pv_remove_metadata_area = _text_pv_remove_metadata_area ,
2011-02-21 15:27:26 +03:00
. pv_resize = _text_pv_resize ,
2006-05-10 01:23:51 +04:00
. pv_write = _text_pv_write ,
2016-02-12 15:53:06 +03:00
. pv_needs_rewrite = _text_pv_needs_rewrite ,
2006-05-10 01:23:51 +04:00
. vg_setup = _text_vg_setup ,
. lv_setup = _text_lv_setup ,
. create_instance = _text_create_text_instance ,
. destroy_instance = _text_destroy_instance ,
. destroy = _text_destroy
2001-11-21 12:20:05 +03:00
} ;
2008-11-04 01:14:30 +03:00
static int _add_dir ( const char * dir , struct dm_list * dir_list )
2001-11-21 12:20:05 +03:00
{
2002-04-24 22:20:51 +04:00
struct dir_list * dl ;
2001-11-21 12:20:05 +03:00
2007-07-28 16:26:21 +04:00
if ( dm_create_dir ( dir ) ) {
2008-11-04 01:14:30 +03:00
if ( ! ( dl = dm_malloc ( sizeof ( struct dm_list ) + strlen ( dir ) + 1 ) ) ) {
2002-04-24 22:20:51 +04:00
log_error ( " _add_dir allocation failed " ) ;
return 0 ;
}
2002-11-18 17:04:08 +03:00
log_very_verbose ( " Adding text format metadata dir: %s " , dir ) ;
2002-04-24 22:20:51 +04:00
strcpy ( dl - > dir , dir ) ;
2008-11-04 01:14:30 +03:00
dm_list_add ( dir_list , & dl - > list ) ;
2002-04-24 22:20:51 +04:00
return 1 ;
2001-11-21 12:20:05 +03:00
}
2002-04-24 22:20:51 +04:00
return 0 ;
}
2002-02-08 14:13:47 +03:00
2002-11-18 17:04:08 +03:00
static int _get_config_disk_area ( struct cmd_context * cmd ,
2011-08-30 18:55:15 +04:00
const struct dm_config_node * cn , struct dm_list * raw_list )
2002-11-18 17:04:08 +03:00
{
struct device_area dev_area ;
2010-12-20 16:12:55 +03:00
const char * id_str ;
2002-11-18 17:04:08 +03:00
struct id id ;
if ( ! ( cn = cn - > child ) ) {
log_error ( " Empty metadata disk_area section of config file " ) ;
return 0 ;
}
2011-08-30 18:55:15 +04:00
if ( ! dm_config_get_uint64 ( cn , " start_sector " , & dev_area . start ) ) {
2002-11-18 17:04:08 +03:00
log_error ( " Missing start_sector in metadata disk_area section "
" of config file " ) ;
return 0 ;
}
dev_area . start < < = SECTOR_SHIFT ;
2011-08-30 18:55:15 +04:00
if ( ! dm_config_get_uint64 ( cn , " size " , & dev_area . size ) ) {
2002-11-18 17:04:08 +03:00
log_error ( " Missing size in metadata disk_area section "
" of config file " ) ;
return 0 ;
}
dev_area . size < < = SECTOR_SHIFT ;
2011-08-30 18:55:15 +04:00
if ( ! dm_config_get_str ( cn , " id " , & id_str ) ) {
2002-11-18 17:04:08 +03:00
log_error ( " Missing uuid in metadata disk_area section "
" of config file " ) ;
return 0 ;
}
if ( ! id_read_format ( & id , id_str ) ) {
log_error ( " Invalid uuid in metadata disk_area section "
" of config file: %s " , id_str ) ;
return 0 ;
}
2012-02-10 05:28:27 +04:00
if ( ! ( dev_area . dev = lvmcache_device_from_pvid ( cmd , & id , NULL , NULL ) ) ) {
2010-07-09 19:34:40 +04:00
char buffer [ 64 ] __attribute__ ( ( aligned ( 8 ) ) ) ;
2002-11-18 17:04:08 +03:00
if ( ! id_write_format ( & id , buffer , sizeof ( buffer ) ) )
2009-07-16 00:02:46 +04:00
log_error ( " Couldn't find device. " ) ;
2002-11-18 17:04:08 +03:00
else
2009-07-16 00:02:46 +04:00
log_error ( " Couldn't find device with uuid '%s'. " ,
buffer ) ;
2002-11-18 17:04:08 +03:00
return 0 ;
}
return _add_raw ( raw_list , & dev_area ) ;
}
2002-04-24 22:20:51 +04:00
struct format_type * create_text_format ( struct cmd_context * cmd )
{
2012-02-10 06:53:03 +04:00
struct format_instance_ctx fic ;
struct format_instance * fid ;
2002-04-24 22:20:51 +04:00
struct format_type * fmt ;
2011-08-30 18:55:15 +04:00
const struct dm_config_node * cn ;
const struct dm_config_value * cv ;
2002-11-18 17:04:08 +03:00
struct mda_lists * mda_lists ;
2002-04-24 22:20:51 +04:00
2012-02-13 14:56:31 +04:00
if ( ! ( fmt = dm_malloc ( sizeof ( * fmt ) ) ) ) {
log_error ( " Failed to allocate text format type structure. " ) ;
return NULL ;
}
2001-11-21 12:20:05 +03:00
2002-04-24 22:20:51 +04:00
fmt - > cmd = cmd ;
fmt - > ops = & _text_handler ;
fmt - > name = FMT_TEXT_NAME ;
2002-11-18 17:04:08 +03:00
fmt - > alias = FMT_TEXT_ALIAS ;
2008-02-06 18:47:28 +03:00
fmt - > orphan_vg_name = ORPHAN_VG_NAME ( FMT_TEXT_NAME ) ;
2005-04-06 22:59:55 +04:00
fmt - > features = FMT_SEGMENTS | FMT_MDAS | FMT_TAGS | FMT_PRECOMMIT |
2006-04-30 02:08:43 +04:00
FMT_UNLIMITED_VOLS | FMT_RESIZE_PV |
2014-10-14 21:12:15 +04:00
FMT_UNLIMITED_STRIPESIZE | FMT_BAS | FMT_CONFIG_PROFILE |
2016-02-12 14:58:59 +03:00
FMT_NON_POWER2_EXTENTS | FMT_PV_FLAGS ;
2002-04-24 22:20:51 +04:00
2005-10-17 03:03:59 +04:00
if ( ! ( mda_lists = dm_malloc ( sizeof ( struct mda_lists ) ) ) ) {
2002-04-24 22:20:51 +04:00
log_error ( " Failed to allocate dir_list " ) ;
2006-05-10 01:23:51 +04:00
dm_free ( fmt ) ;
2002-04-24 22:20:51 +04:00
return NULL ;
2002-01-15 20:37:23 +03:00
}
2008-11-04 01:14:30 +03:00
dm_list_init ( & mda_lists - > dirs ) ;
dm_list_init ( & mda_lists - > raws ) ;
2002-11-18 17:04:08 +03:00
mda_lists - > file_ops = & _metadata_text_file_ops ;
mda_lists - > raw_ops = & _metadata_text_raw_ops ;
fmt - > private = ( void * ) mda_lists ;
2002-01-15 20:37:23 +03:00
2012-02-23 17:11:07 +04:00
dm_list_init ( & fmt - > mda_ops ) ;
dm_list_add ( & fmt - > mda_ops , & _metadata_text_raw_ops . list ) ;
2002-11-18 17:04:08 +03:00
if ( ! ( fmt - > labeller = text_labeller_create ( fmt ) ) ) {
log_error ( " Couldn't create text label handler. " ) ;
2012-02-13 14:56:31 +04:00
goto bad ;
2002-04-24 22:20:51 +04:00
}
2001-11-21 12:20:05 +03:00
2013-07-29 17:58:18 +04:00
if ( ! ( label_register_handler ( fmt - > labeller ) ) ) {
2002-11-18 17:04:08 +03:00
log_error ( " Couldn't register text label handler. " ) ;
2012-02-08 14:49:36 +04:00
fmt - > labeller - > ops - > destroy ( fmt - > labeller ) ;
2012-02-13 14:56:31 +04:00
goto bad ;
2002-11-18 17:04:08 +03:00
}
2015-07-08 12:22:24 +03:00
if ( ( cn = find_config_tree_array ( cmd , metadata_dirs_CFG , NULL ) ) ) {
2002-11-18 17:04:08 +03:00
for ( cv = cn - > v ; cv ; cv = cv - > next ) {
2011-08-30 18:55:15 +04:00
if ( cv - > type ! = DM_CFG_STRING ) {
2002-11-18 17:04:08 +03:00
log_error ( " Invalid string in config file: "
" metadata/dirs " ) ;
2012-02-13 14:56:31 +04:00
goto bad ;
2002-11-18 17:04:08 +03:00
}
if ( ! _add_dir ( cv - > v . str , & mda_lists - > dirs ) ) {
2009-03-24 00:13:37 +03:00
log_error ( " Failed to add %s to text format "
" metadata directory list " , cv - > v . str ) ;
2012-02-13 14:56:31 +04:00
goto bad ;
2002-11-18 17:04:08 +03:00
}
2010-12-11 01:39:52 +03:00
cmd - > independent_metadata_areas = 1 ;
2002-04-24 22:20:51 +04:00
}
2002-11-18 17:04:08 +03:00
}
2002-02-08 14:13:47 +03:00
2013-12-13 19:43:01 +04:00
if ( ( cn = find_config_tree_node ( cmd , metadata_disk_areas_CFG_SUBSECTION , NULL ) ) ) {
/* FIXME: disk_areas do not work with lvmetad - the "id" can't be found. */
2004-09-14 21:37:51 +04:00
for ( cn = cn - > child ; cn ; cn = cn - > sib ) {
if ( ! _get_config_disk_area ( cmd , cn , & mda_lists - > raws ) )
2012-02-13 14:56:31 +04:00
goto_bad ;
2010-12-11 01:39:52 +03:00
cmd - > independent_metadata_areas = 1 ;
2004-09-14 21:37:51 +04:00
}
2002-04-24 22:20:51 +04:00
}
2002-02-08 14:13:47 +03:00
2012-02-13 14:56:31 +04:00
if ( ! ( fmt - > orphan_vg = alloc_vg ( " text_orphan " , cmd , fmt - > orphan_vg_name ) ) )
goto_bad ;
2012-02-10 06:53:03 +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
if ( ! ( fid = _text_create_text_instance ( fmt , & fic ) ) )
goto_bad ;
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 ) ;
2002-04-24 22:20:51 +04:00
return fmt ;
2012-02-13 14:56:31 +04:00
bad :
2012-02-08 14:49:36 +04:00
_text_destroy ( fmt ) ;
2002-02-08 14:13:47 +03:00
return NULL ;
2001-11-21 12:20:05 +03:00
}