2001-10-09 18:26:45 +04:00
/*
2008-01-30 17:00:02 +03:00
* Copyright ( C ) 2001 - 2004 Sistina Software , Inc . All rights reserved .
2007-08-21 00:55:30 +04:00
* Copyright ( C ) 2004 - 2006 Red Hat , Inc . All rights reserved .
2001-10-09 18:26:45 +04: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 .
2001-10-31 20:59:52 +03: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
2004-03-30 23:35:44 +04:00
*/
/*
* Translates between disk and in - core formats .
2001-10-09 18:26:45 +04:00
*/
2002-11-18 17:01:16 +03:00
# include "lib.h"
2001-10-09 18:26:45 +04:00
# include "disk-rep.h"
2002-01-29 20:23:33 +03:00
# include "lvm-string.h"
2004-03-08 20:25:59 +03:00
# include "toolcontext.h"
2004-09-16 22:40:56 +04:00
# include "segtype.h"
2005-04-20 00:58:25 +04:00
# include "pv_alloc.h"
2006-10-19 16:53:47 +04:00
# include "display.h"
2008-02-06 18:47:28 +03:00
# include "metadata.h"
2001-10-09 18:26:45 +04:00
2001-10-11 17:22:51 +04:00
# include <time.h>
2001-10-10 13:25:04 +04:00
2001-10-09 18:26:45 +04:00
static int _check_vg_name ( const char * name )
{
return strlen ( name ) < NAME_LEN ;
}
/*
* Extracts the last part of a path .
*/
2005-10-17 03:03:59 +04:00
static char * _create_lv_name ( struct dm_pool * mem , const char * full_name )
2001-10-09 18:26:45 +04:00
{
2001-10-11 14:08:44 +04:00
const char * ptr = strrchr ( full_name , ' / ' ) ;
if ( ! ptr )
ptr = full_name ;
else
ptr + + ;
2005-10-17 03:03:59 +04:00
return dm_pool_strdup ( mem , ptr ) ;
2001-10-09 18:26:45 +04:00
}
2006-10-19 16:53:47 +04:00
int import_pv ( const struct format_type * fmt , struct dm_pool * mem ,
struct device * dev , struct volume_group * vg ,
2006-04-13 01:23:04 +04:00
struct physical_volume * pv , struct pv_disk * pvd ,
struct vg_disk * vgd )
2001-10-09 18:26:45 +04:00
{
2006-10-19 16:53:47 +04:00
uint64_t size ;
2001-10-09 18:26:45 +04:00
memset ( pv , 0 , sizeof ( * pv ) ) ;
2001-10-11 14:08:44 +04:00
memcpy ( & pv - > id , pvd - > pv_uuid , ID_LEN ) ;
2001-10-09 18:26:45 +04:00
pv - > dev = dev ;
2007-11-02 23:40:05 +03:00
if ( ! * pvd - > vg_name )
2008-02-06 18:47:28 +03:00
pv - > vg_name = fmt - > orphan_vg_name ;
2007-11-02 23:40:05 +03:00
else if ( ! ( pv - > vg_name = dm_pool_strdup ( mem , ( char * ) pvd - > vg_name ) ) ) {
log_error ( " Volume Group name allocation failed. " ) ;
2001-10-09 18:26:45 +04:00
return 0 ;
}
2006-04-13 01:23:04 +04:00
memcpy ( & pv - > vgid , vgd - > vg_uuid , sizeof ( vg - > id ) ) ;
2002-01-30 15:47:29 +03:00
/* Store system_id from first PV if PV belongs to a VG */
2015-03-04 20:11:10 +03:00
if ( vg & & ! * vg - > lvm1_system_id )
2015-02-24 02:03:52 +03:00
strncpy ( vg - > lvm1_system_id , ( char * ) pvd - > system_id , NAME_LEN ) ;
2002-01-29 20:23:33 +03:00
2002-01-30 15:47:29 +03:00
if ( vg & &
2015-02-24 02:03:52 +03:00
strncmp ( vg - > lvm1_system_id , ( char * ) pvd - > system_id , sizeof ( pvd - > system_id ) ) )
2004-03-08 20:19:15 +03:00
log_very_verbose ( " System ID %s on %s differs from %s for "
" volume group " , pvd - > system_id ,
2015-02-24 02:03:52 +03:00
pv_dev_name ( pv ) , vg - > lvm1_system_id ) ;
2002-02-12 19:31:31 +03:00
/*
2002-01-29 20:23:33 +03:00
* If exported , we still need to flag in pv - > status too because
* we don ' t always have a struct volume_group when we need this .
*/
if ( pvd - > pv_status & VG_EXPORTED )
pv - > status | = EXPORTED_VG ;
2001-10-09 18:26:45 +04:00
if ( pvd - > pv_allocatable )
2002-01-10 18:09:51 +03:00
pv - > status | = ALLOCATABLE_PV ;
2001-10-09 18:26:45 +04:00
pv - > size = pvd - > pv_size ;
pv - > pe_size = pvd - > pe_size ;
pv - > pe_start = pvd - > pe_start ;
pv - > pe_count = pvd - > pe_total ;
2005-06-01 20:51:55 +04:00
pv - > pe_alloc_count = 0 ;
2008-09-19 08:28:58 +04:00
pv - > pe_align = 0 ;
2011-06-01 23:29:31 +04:00
pv - > is_labelled = 0 ; /* format1 PVs have no label */
pv - > label_sector = 0 ;
2001-11-27 19:37:33 +03:00
2007-11-05 04:47:49 +03:00
/* Fix up pv size if missing or impossibly large */
if ( ! pv - > size | | pv - > size > ( 1ULL < < 62 ) ) {
2006-10-19 16:53:47 +04:00
if ( ! dev_get_size ( dev , & pv - > size ) ) {
2007-10-12 18:29:32 +04:00
log_error ( " %s: Couldn't get size. " , pv_dev_name ( pv ) ) ;
2006-10-19 16:53:47 +04:00
return 0 ;
}
log_verbose ( " Fixing up missing format1 size (%s) "
" for PV %s " , display_size ( fmt - > cmd , pv - > size ) ,
2007-10-12 18:29:32 +04:00
pv_dev_name ( pv ) ) ;
2006-10-19 16:53:47 +04:00
if ( vg ) {
size = pv - > pe_count * ( uint64_t ) vg - > extent_size +
pv - > pe_start ;
if ( size > pv - > size )
2010-04-01 14:34:09 +04:00
log_warn ( " WARNING: Physical Volume %s is too "
" large for underlying device " ,
pv_dev_name ( pv ) ) ;
2006-10-19 16:53:47 +04:00
}
}
2008-11-04 01:14:30 +03:00
dm_list_init ( & pv - > tags ) ;
dm_list_init ( & pv - > segments ) ;
2005-04-20 00:58:25 +04:00
2008-01-30 16:19:47 +03:00
if ( ! alloc_pv_segment_whole_pv ( mem , pv ) )
return_0 ;
2004-03-08 20:19:15 +03:00
2001-10-09 18:26:45 +04:00
return 1 ;
}
2015-03-04 03:44:15 +03:00
int generate_lvm1_system_id ( struct cmd_context * cmd , char * s , const char * prefix )
2001-10-11 17:22:51 +04:00
{
2017-02-15 19:01:49 +03:00
if ( dm_snprintf ( s , NAME_LEN , " %s%s " FMTu64 ,
prefix , cmd - > hostname , ( uint64_t ) time ( NULL ) ) < 0 ) {
2015-02-24 02:03:52 +03:00
log_error ( " Generated LVM1 format system_id too long " ) ;
2002-01-29 20:23:33 +03:00
return 0 ;
}
2001-10-11 17:22:51 +04:00
return 1 ;
}
2010-07-09 19:34:40 +04:00
int export_pv ( struct cmd_context * cmd , struct dm_pool * mem __attribute__ ( ( unused ) ) ,
2004-03-08 20:25:59 +03:00
struct volume_group * vg ,
2002-01-29 20:23:33 +03:00
struct pv_disk * pvd , struct physical_volume * pv )
2001-10-09 18:26:45 +04:00
{
memset ( pvd , 0 , sizeof ( * pvd ) ) ;
pvd - > id [ 0 ] = ' H ' ;
pvd - > id [ 1 ] = ' M ' ;
pvd - > version = 1 ;
2001-10-11 14:08:44 +04:00
memcpy ( pvd - > pv_uuid , pv - > id . uuid , ID_LEN ) ;
2001-10-09 18:26:45 +04:00
2011-06-01 23:29:31 +04:00
if ( pv - > vg_name & & ! is_orphan ( pv ) & & ! ( pv - > status & UNLABELLED_PV ) ) {
2008-01-30 16:19:47 +03:00
if ( ! _check_vg_name ( pv - > vg_name ) )
return_0 ;
2006-05-10 01:23:51 +04:00
strncpy ( ( char * ) pvd - > vg_name , pv - > vg_name , sizeof ( pvd - > vg_name ) ) ;
2006-05-10 21:49:25 +04:00
}
2001-10-09 18:26:45 +04:00
2002-01-29 20:23:33 +03:00
/* Preserve existing system_id if it exists */
2015-03-04 04:00:51 +03:00
if ( vg & & vg - > lvm1_system_id & & * vg - > lvm1_system_id )
2015-02-24 02:03:52 +03:00
strncpy ( ( char * ) pvd - > system_id , vg - > lvm1_system_id , sizeof ( pvd - > system_id ) ) ;
2015-03-04 04:00:51 +03:00
else if ( vg & & vg - > system_id & & * vg - > system_id )
strncpy ( ( char * ) pvd - > system_id , vg - > system_id , sizeof ( pvd - > system_id ) ) ;
2002-01-29 20:23:33 +03:00
/* Is VG already exported or being exported? */
2009-09-14 23:44:15 +04:00
if ( vg & & vg_is_exported ( vg ) ) {
2002-01-29 20:23:33 +03:00
/* Does system_id need setting? */
2015-08-04 11:16:45 +03:00
if ( ! vg - > lvm1_system_id | | ! * vg - > lvm1_system_id | |
2015-02-24 02:03:52 +03:00
strncmp ( vg - > lvm1_system_id , EXPORTED_TAG ,
2002-01-29 22:19:37 +03:00
sizeof ( EXPORTED_TAG ) - 1 ) ) {
2015-03-04 03:44:15 +03:00
if ( ! generate_lvm1_system_id ( cmd , ( char * ) pvd - > system_id , EXPORTED_TAG ) )
2008-01-30 16:19:47 +03:00
return_0 ;
2002-01-29 20:23:33 +03:00
}
2006-05-10 01:23:51 +04:00
if ( strlen ( ( char * ) pvd - > vg_name ) + sizeof ( EXPORTED_TAG ) >
2002-01-29 20:23:33 +03:00
sizeof ( pvd - > vg_name ) ) {
log_error ( " Volume group name %s too long to export " ,
pvd - > vg_name ) ;
return 0 ;
}
2006-05-10 01:23:51 +04:00
strcat ( ( char * ) pvd - > vg_name , EXPORTED_TAG ) ;
2002-01-29 20:23:33 +03:00
}
/* Is VG being imported? */
2015-05-07 14:09:43 +03:00
if ( vg & & ! vg_is_exported ( vg ) & & vg - > lvm1_system_id & & * vg - > lvm1_system_id & &
2015-02-24 02:03:52 +03:00
! strncmp ( vg - > lvm1_system_id , EXPORTED_TAG , sizeof ( EXPORTED_TAG ) - 1 ) ) {
2015-03-04 03:44:15 +03:00
if ( ! generate_lvm1_system_id ( cmd , ( char * ) pvd - > system_id , IMPORTED_TAG ) )
2008-01-30 16:19:47 +03:00
return_0 ;
2002-01-29 20:23:33 +03:00
}
/* Generate system_id if PV is in VG */
2010-12-01 01:57:35 +03:00
if ( ! pvd - > system_id [ 0 ] )
2015-03-04 03:44:15 +03:00
if ( ! generate_lvm1_system_id ( cmd , ( char * ) pvd - > system_id , " " ) )
2008-01-30 16:19:47 +03:00
return_0 ;
2002-01-29 20:23:33 +03:00
/* Update internal system_id if we changed it */
2015-05-07 14:09:43 +03:00
if ( vg & & vg - > lvm1_system_id & &
2015-02-24 02:03:52 +03:00
( ! * vg - > lvm1_system_id | |
strncmp ( vg - > lvm1_system_id , ( char * ) pvd - > system_id , sizeof ( pvd - > system_id ) ) ) )
strncpy ( vg - > lvm1_system_id , ( char * ) pvd - > system_id , NAME_LEN ) ;
2002-01-29 20:23:33 +03:00
2001-10-09 18:26:45 +04:00
//pvd->pv_major = MAJOR(pv->dev);
2002-01-10 18:09:51 +03:00
if ( pv - > status & ALLOCATABLE_PV )
2001-10-11 17:34:17 +04:00
pvd - > pv_allocatable = PV_ALLOCATABLE ;
2001-10-09 18:26:45 +04:00
pvd - > pv_size = pv - > size ;
pvd - > lv_cur = 0 ; /* this is set when exporting the lv list */
2002-11-18 17:01:16 +03:00
if ( vg )
pvd - > pe_size = vg - > extent_size ;
else
pvd - > pe_size = pv - > pe_size ;
2001-10-09 18:26:45 +04:00
pvd - > pe_total = pv - > pe_count ;
2002-04-24 22:20:51 +04:00
pvd - > pe_allocated = pv - > pe_alloc_count ;
2001-10-09 18:26:45 +04:00
pvd - > pe_start = pv - > pe_start ;
2001-10-11 17:22:51 +04:00
2001-10-09 18:26:45 +04:00
return 1 ;
}
2005-10-17 03:03:59 +04:00
int import_vg ( struct dm_pool * mem ,
2008-09-19 10:42:00 +04:00
struct volume_group * vg , struct disk_list * dl )
2001-10-09 18:26:45 +04:00
{
2001-10-31 20:59:52 +03:00
struct vg_disk * vgd = & dl - > vgd ;
2001-10-11 14:08:44 +04:00
memcpy ( vg - > id . uuid , vgd - > vg_uuid , ID_LEN ) ;
2001-10-09 18:26:45 +04:00
2008-01-30 16:19:47 +03:00
if ( ! _check_vg_name ( ( char * ) dl - > pvd . vg_name ) )
return_0 ;
2001-10-09 18:26:45 +04:00
2008-01-30 16:19:47 +03:00
if ( ! ( vg - > name = dm_pool_strdup ( mem , ( char * ) dl - > pvd . vg_name ) ) )
return_0 ;
2001-10-09 18:26:45 +04:00
2015-02-24 02:03:52 +03:00
if ( ! ( vg - > lvm1_system_id = dm_pool_zalloc ( mem , NAME_LEN + 1 ) ) )
2008-01-30 16:19:47 +03:00
return_0 ;
2002-01-30 15:47:29 +03:00
2001-10-09 18:26:45 +04:00
if ( vgd - > vg_status & VG_EXPORTED )
vg - > status | = EXPORTED_VG ;
if ( vgd - > vg_status & VG_EXTENDABLE )
2002-01-10 18:09:51 +03:00
vg - > status | = RESIZEABLE_VG ;
2001-10-09 18:26:45 +04:00
2008-09-19 10:42:00 +04:00
if ( vgd - > vg_access & VG_READ )
2001-10-09 18:26:45 +04:00
vg - > status | = LVM_READ ;
2008-09-19 10:42:00 +04:00
if ( vgd - > vg_access & VG_WRITE )
2001-10-09 18:26:45 +04:00
vg - > status | = LVM_WRITE ;
if ( vgd - > vg_access & VG_CLUSTERED )
vg - > status | = CLUSTERED ;
if ( vgd - > vg_access & VG_SHARED )
vg - > status | = SHARED ;
vg - > extent_size = vgd - > pe_size ;
vg - > extent_count = vgd - > pe_total ;
2005-06-22 19:31:29 +04:00
vg - > free_count = vgd - > pe_total ;
2001-10-09 18:26:45 +04:00
vg - > max_lv = vgd - > lv_max ;
vg - > max_pv = vgd - > pv_max ;
2004-05-19 02:12:53 +04:00
vg - > alloc = ALLOC_NORMAL ;
2002-01-29 20:23:33 +03:00
2001-10-09 18:26:45 +04:00
return 1 ;
}
int export_vg ( struct vg_disk * vgd , struct volume_group * vg )
{
memset ( vgd , 0 , sizeof ( * vgd ) ) ;
2001-10-11 14:08:44 +04:00
memcpy ( vgd - > vg_uuid , vg - > id . uuid , ID_LEN ) ;
2001-10-09 18:26:45 +04:00
2001-10-11 19:09:31 +04:00
if ( vg - > status & LVM_READ )
2001-10-09 18:26:45 +04:00
vgd - > vg_access | = VG_READ ;
2015-03-05 19:13:05 +03:00
if ( vg - > status & LVM_WRITE )
2001-10-09 18:26:45 +04:00
vgd - > vg_access | = VG_WRITE ;
2008-04-10 21:09:32 +04:00
if ( vg_is_clustered ( vg ) )
2001-10-09 18:26:45 +04:00
vgd - > vg_access | = VG_CLUSTERED ;
if ( vg - > status & SHARED )
vgd - > vg_access | = VG_SHARED ;
2009-09-14 23:44:15 +04:00
if ( vg_is_exported ( vg ) )
2001-10-09 18:26:45 +04:00
vgd - > vg_status | = VG_EXPORTED ;
2009-09-15 22:35:13 +04:00
if ( vg_is_resizeable ( vg ) )
2001-10-09 18:26:45 +04:00
vgd - > vg_status | = VG_EXTENDABLE ;
vgd - > lv_max = vg - > max_lv ;
2009-05-14 01:27:43 +04:00
vgd - > lv_cur = vg_visible_lvs ( vg ) + snapshot_count ( vg ) ;
2001-10-09 18:26:45 +04:00
vgd - > pv_max = vg - > max_pv ;
vgd - > pv_cur = vg - > pv_count ;
vgd - > pe_size = vg - > extent_size ;
vgd - > pe_total = vg - > extent_count ;
vgd - > pe_allocated = vg - > extent_count - vg - > free_count ;
2001-10-11 17:22:51 +04:00
2001-10-09 18:26:45 +04:00
return 1 ;
}
2009-05-14 01:24:12 +04:00
int import_lv ( struct cmd_context * cmd , struct dm_pool * mem ,
struct logical_volume * lv , struct lv_disk * lvd )
2001-10-09 18:26:45 +04:00
{
2008-01-30 16:19:47 +03:00
if ( ! ( lv - > name = _create_lv_name ( mem , ( char * ) lvd - > lv_name ) ) )
return_0 ;
2001-10-09 18:26:45 +04:00
2002-11-18 17:01:16 +03:00
lv - > status | = VISIBLE_LV ;
2001-10-09 18:26:45 +04:00
if ( lvd - > lv_status & LV_SPINDOWN )
lv - > status | = SPINDOWN_LV ;
2002-02-01 20:54:39 +03:00
if ( lvd - > lv_status & LV_PERSISTENT_MINOR ) {
lv - > status | = FIXED_MINOR ;
lv - > minor = MINOR ( lvd - > lv_dev ) ;
2003-04-02 23:14:43 +04:00
lv - > major = MAJOR ( lvd - > lv_dev ) ;
} else {
lv - > major = - 1 ;
2002-02-01 20:54:39 +03:00
lv - > minor = - 1 ;
2003-04-02 23:14:43 +04:00
}
2002-02-01 20:54:39 +03:00
2001-10-09 18:26:45 +04:00
if ( lvd - > lv_access & LV_READ )
lv - > status | = LVM_READ ;
if ( lvd - > lv_access & LV_WRITE )
lv - > status | = LVM_WRITE ;
if ( lvd - > lv_badblock )
lv - > status | = BADBLOCK_ON ;
2002-11-18 17:01:16 +03:00
/* Drop the unused LV_STRICT here */
2001-11-12 20:55:05 +03:00
if ( lvd - > lv_allocation & LV_CONTIGUOUS )
2002-07-11 18:21:49 +04:00
lv - > alloc = ALLOC_CONTIGUOUS ;
2001-11-12 20:55:05 +03:00
else
2004-05-19 02:12:53 +04:00
lv - > alloc = ALLOC_NORMAL ;
2001-10-09 18:26:45 +04:00
2007-11-09 19:51:54 +03:00
if ( ! lvd - > lv_read_ahead )
2009-05-14 01:24:12 +04:00
lv - > read_ahead = cmd - > default_settings . read_ahead ;
2007-11-09 19:51:54 +03:00
else
lv - > read_ahead = lvd - > lv_read_ahead ;
2002-04-24 22:20:51 +04:00
lv - > size = lvd - > lv_size ;
lv - > le_count = lvd - > lv_allocated_le ;
2001-10-09 18:26:45 +04:00
return 1 ;
}
2002-11-18 17:01:16 +03:00
static void _export_lv ( struct lv_disk * lvd , struct volume_group * vg ,
struct logical_volume * lv , const char * dev_dir )
2001-10-09 18:26:45 +04:00
{
memset ( lvd , 0 , sizeof ( * lvd ) ) ;
2006-05-10 01:23:51 +04:00
snprintf ( ( char * ) lvd - > lv_name , sizeof ( lvd - > lv_name ) , " %s%s/%s " ,
2001-11-14 16:52:38 +03:00
dev_dir , vg - > name , lv - > name ) ;
2001-10-09 18:26:45 +04:00
2014-07-03 23:31:15 +04:00
( void ) dm_strncpy ( ( char * ) lvd - > vg_name , vg - > name , sizeof ( lvd - > vg_name ) ) ;
2001-10-09 18:26:45 +04:00
if ( lv - > status & LVM_READ )
lvd - > lv_access | = LV_READ ;
2015-03-05 19:13:05 +03:00
if ( lv - > status & LVM_WRITE )
2001-10-09 18:26:45 +04:00
lvd - > lv_access | = LV_WRITE ;
if ( lv - > status & SPINDOWN_LV )
lvd - > lv_status | = LV_SPINDOWN ;
2002-02-01 20:54:39 +03:00
if ( lv - > status & FIXED_MINOR ) {
lvd - > lv_status | = LV_PERSISTENT_MINOR ;
2003-04-02 23:14:43 +04:00
lvd - > lv_dev = MKDEV ( lv - > major , lv - > minor ) ;
2003-11-06 19:58:38 +03:00
} else {
lvd - > lv_dev = MKDEV ( LVM_BLK_MAJOR , lvnum_from_lvid ( & lv - > lvid ) ) ;
2002-02-01 20:54:39 +03:00
}
2007-11-09 19:51:54 +03:00
if ( lv - > read_ahead = = DM_READ_AHEAD_AUTO | |
lv - > read_ahead = = DM_READ_AHEAD_NONE )
lvd - > lv_read_ahead = 0 ;
else
lvd - > lv_read_ahead = lv - > read_ahead ;
2003-04-25 02:23:24 +04:00
lvd - > lv_stripes =
2008-11-04 01:14:30 +03:00
dm_list_item ( lv - > segments . n , struct lv_segment ) - > area_count ;
2003-04-25 02:23:24 +04:00
lvd - > lv_stripesize =
2008-11-04 01:14:30 +03:00
dm_list_item ( lv - > segments . n , struct lv_segment ) - > stripe_size ;
2001-10-29 18:34:56 +03:00
2002-04-24 22:20:51 +04:00
lvd - > lv_size = lv - > size ;
lvd - > lv_allocated_le = lv - > le_count ;
2001-10-09 18:26:45 +04:00
if ( lv - > status & BADBLOCK_ON )
lvd - > lv_badblock = LV_BADBLOCK_ON ;
2002-07-11 18:21:49 +04:00
if ( lv - > alloc = = ALLOC_CONTIGUOUS )
2001-11-12 20:55:05 +03:00
lvd - > lv_allocation | = LV_CONTIGUOUS ;
2001-10-09 18:26:45 +04:00
}
2002-12-20 02:25:55 +03:00
int export_extents ( struct disk_list * dl , uint32_t lv_num ,
2002-04-24 22:20:51 +04:00
struct logical_volume * lv , struct physical_volume * pv )
2001-10-09 18:26:45 +04:00
{
2001-11-27 19:37:33 +03:00
struct pe_disk * ped ;
2002-11-18 17:01:16 +03:00
struct lv_segment * seg ;
2001-11-27 20:29:56 +03:00
uint32_t pe , s ;
2001-10-09 18:26:45 +04:00
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( seg , & lv - > segments ) {
2003-04-25 02:23:24 +04:00
for ( s = 0 ; s < seg - > area_count ; s + + ) {
2004-05-05 01:25:57 +04:00
if ( ! ( seg - > segtype - > flags & SEG_FORMAT1_SUPPORT ) ) {
log_error ( " Segment type %s in LV %s: "
" unsupported by format1 " ,
2016-12-25 02:29:30 +03:00
lvseg_name ( seg ) , lv - > name ) ;
2003-04-25 02:23:24 +04:00
return 0 ;
}
2005-06-01 20:51:55 +04:00
if ( seg_type ( seg , s ) ! = AREA_PV ) {
2005-06-14 21:54:48 +04:00
log_error ( " Non-PV stripe found in LV %s: "
2003-04-25 02:23:24 +04:00
" unsupported by format1 " , lv - > name ) ;
return 0 ;
}
2005-06-01 20:51:55 +04:00
if ( seg_pv ( seg , s ) ! = pv )
2002-04-24 22:20:51 +04:00
continue ; /* not our pv */
2001-10-09 18:26:45 +04:00
2003-04-25 02:23:24 +04:00
for ( pe = 0 ; pe < ( seg - > len / seg - > area_count ) ; pe + + ) {
2005-06-01 20:51:55 +04:00
ped = & dl - > extents [ pe + seg_pe ( seg , s ) ] ;
2001-11-27 19:37:33 +03:00
ped - > lv_num = lv_num ;
2003-04-25 02:23:24 +04:00
ped - > le_num = ( seg - > le / seg - > area_count ) + pe +
s * ( lv - > le_count / seg - > area_count ) ;
2001-10-09 18:26:45 +04:00
}
}
}
return 1 ;
}
2005-10-17 03:03:59 +04:00
int import_pvs ( const struct format_type * fmt , struct dm_pool * mem ,
2010-04-06 18:04:20 +04:00
struct volume_group * vg , struct dm_list * pvds )
2001-10-09 18:26:45 +04:00
{
struct disk_list * dl ;
struct pv_list * pvl ;
2010-04-06 18:04:20 +04:00
vg - > pv_count = 0 ;
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( dl , pvds ) {
2005-10-17 03:03:59 +04:00
if ( ! ( pvl = dm_pool_zalloc ( mem , sizeof ( * pvl ) ) ) | |
2008-01-30 16:19:47 +03:00
! ( pvl - > pv = dm_pool_alloc ( mem , sizeof ( * pvl - > pv ) ) ) )
return_0 ;
2001-10-09 18:26:45 +04:00
2008-01-30 16:19:47 +03:00
if ( ! import_pv ( fmt , mem , dl - > dev , vg , pvl - > pv , & dl - > pvd , & dl - > vgd ) )
return_0 ;
2001-10-09 18:26:45 +04:00
2002-11-18 17:01:16 +03:00
pvl - > pv - > fmt = fmt ;
2010-04-06 18:04:54 +04:00
add_pvl_to_vgs ( vg , pvl ) ;
2001-10-09 18:26:45 +04:00
}
return 1 ;
}
2005-10-17 03:03:59 +04:00
static struct logical_volume * _add_lv ( struct dm_pool * mem ,
2001-10-09 18:26:45 +04:00
struct volume_group * vg ,
struct lv_disk * lvd )
{
struct logical_volume * lv ;
2009-09-28 21:46:15 +04:00
if ( ! ( lv = alloc_lv ( mem ) ) )
2008-01-30 16:19:47 +03:00
return_NULL ;
2001-10-09 18:26:45 +04:00
2009-05-14 01:24:12 +04:00
lvid_from_lvnum ( & lv - > lvid , & vg - > id , lvd - > lv_number ) ;
2009-05-14 01:25:01 +04:00
if ( ! import_lv ( vg - > cmd , mem , lv , lvd ) )
goto_bad ;
2001-10-09 18:26:45 +04:00
2009-05-14 01:25:01 +04:00
if ( ! link_lv_to_vg ( vg , lv ) )
goto_bad ;
2001-10-09 18:26:45 +04:00
return lv ;
2009-05-14 01:25:01 +04:00
bad :
dm_pool_free ( mem , lv ) ;
return NULL ;
2001-10-09 18:26:45 +04:00
}
2008-11-04 01:14:30 +03:00
int import_lvs ( struct dm_pool * mem , struct volume_group * vg , struct dm_list * pvds )
2001-10-09 18:26:45 +04:00
{
struct disk_list * dl ;
struct lvd_list * ll ;
struct lv_disk * lvd ;
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( dl , pvds ) {
dm_list_iterate_items ( ll , & dl - > lvds ) {
2001-10-31 20:59:52 +03:00
lvd = & ll - > lvd ;
2001-10-09 18:26:45 +04:00
2006-05-10 01:23:51 +04:00
if ( ! find_lv ( vg , ( char * ) lvd - > lv_name ) & &
2008-01-30 16:19:47 +03:00
! _add_lv ( mem , vg , lvd ) )
return_0 ;
2001-10-09 18:26:45 +04:00
}
}
return 1 ;
}
2002-02-13 14:43:29 +03:00
/* FIXME: tidy */
2001-10-09 18:26:45 +04:00
int export_lvs ( struct disk_list * dl , struct volume_group * vg ,
2001-11-14 16:52:38 +03:00
struct physical_volume * pv , const char * dev_dir )
2001-10-09 18:26:45 +04:00
{
2002-02-13 14:43:29 +03:00
int r = 0 ;
2001-10-09 18:26:45 +04:00
struct lv_list * ll ;
struct lvd_list * lvdl ;
2002-12-20 02:25:55 +03:00
size_t len ;
uint32_t lv_num ;
2005-10-17 03:03:59 +04:00
struct dm_hash_table * lvd_hash ;
2002-02-13 14:43:29 +03:00
2008-01-30 16:19:47 +03:00
if ( ! _check_vg_name ( vg - > name ) )
return_0 ;
2002-11-18 17:01:16 +03:00
2008-01-30 16:19:47 +03:00
if ( ! ( lvd_hash = dm_hash_create ( 32 ) ) )
return_0 ;
2001-10-10 18:56:53 +04:00
/*
* setup the pv ' s extents array
*/
2001-10-31 20:59:52 +03:00
len = sizeof ( struct pe_disk ) * dl - > pvd . pe_total ;
2010-10-01 01:06:50 +04:00
if ( ! ( dl - > extents = dm_pool_zalloc ( dl - > mem , len ) ) )
2008-01-30 16:19:47 +03:00
goto_out ;
2001-10-10 18:56:53 +04:00
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( ll , & vg - > lvs ) {
2016-12-13 02:09:15 +03:00
if ( lv_is_snapshot ( ll - > lv ) )
2005-04-07 16:39:44 +04:00
continue ;
2008-01-30 16:19:47 +03:00
if ( ! ( lvdl = dm_pool_alloc ( dl - > mem , sizeof ( * lvdl ) ) ) )
goto_out ;
2001-10-09 18:26:45 +04:00
2002-11-18 17:01:16 +03:00
_export_lv ( & lvdl - > lvd , vg , ll - > lv , dev_dir ) ;
2002-02-13 14:43:29 +03:00
2002-03-05 23:03:09 +03:00
lv_num = lvnum_from_lvid ( & ll - > lv - > lvid ) ;
2001-11-10 01:01:04 +03:00
lvdl - > lvd . lv_number = lv_num ;
2002-02-13 14:43:29 +03:00
2008-01-30 16:19:47 +03:00
if ( ! dm_hash_insert ( lvd_hash , ll - > lv - > name , & lvdl - > lvd ) )
goto_out ;
2002-02-13 14:43:29 +03:00
2008-01-30 16:19:47 +03:00
if ( ! export_extents ( dl , lv_num + 1 , ll - > lv , pv ) )
goto_out ;
2001-10-09 18:26:45 +04:00
2005-04-07 16:39:44 +04:00
if ( lv_is_origin ( ll - > lv ) )
lvdl - > lvd . lv_access | = LV_SNAPSHOT_ORG ;
2002-02-13 14:43:29 +03:00
2005-04-07 16:39:44 +04:00
if ( lv_is_cow ( ll - > lv ) ) {
lvdl - > lvd . lv_access | = LV_SNAPSHOT ;
lvdl - > lvd . lv_chunk_size = ll - > lv - > snapshot - > chunk_size ;
lvdl - > lvd . lv_snapshot_minor =
lvnum_from_lvid ( & ll - > lv - > snapshot - > origin - > lvid ) ;
2002-02-13 14:43:29 +03:00
}
2008-11-04 01:14:30 +03:00
dm_list_add ( & dl - > lvds , & lvdl - > list ) ;
2005-04-07 16:39:44 +04:00
dl - > pvd . lv_cur + + ;
2002-02-13 14:43:29 +03:00
}
r = 1 ;
2002-04-24 22:20:51 +04:00
out :
2005-10-17 03:03:59 +04:00
dm_hash_destroy ( lvd_hash ) ;
2002-02-13 14:43:29 +03:00
return r ;
}
/*
* FIXME : More inefficient code .
*/
2010-07-09 19:34:40 +04:00
int import_snapshots ( struct dm_pool * mem __attribute__ ( ( unused ) ) , struct volume_group * vg ,
2008-11-04 01:14:30 +03:00
struct dm_list * pvds )
2002-02-13 14:43:29 +03:00
{
2012-06-21 23:19:28 +04:00
struct logical_volume * lvs [ MAX_LV ] = { 0 } ;
2002-02-13 14:43:29 +03:00
struct disk_list * dl ;
2005-06-01 20:51:55 +04:00
struct lvd_list * ll ;
2002-02-13 14:43:29 +03:00
struct lv_disk * lvd ;
2002-02-21 22:04:37 +03:00
int lvnum ;
2002-02-13 14:43:29 +03:00
struct logical_volume * org , * cow ;
2002-02-21 22:04:37 +03:00
/* build an index of lv numbers */
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( dl , pvds ) {
dm_list_iterate_items ( ll , & dl - > lvds ) {
2005-06-01 20:51:55 +04:00
lvd = & ll - > lvd ;
2002-02-13 14:43:29 +03:00
2002-02-21 22:04:37 +03:00
lvnum = lvd - > lv_number ;
2002-02-13 14:43:29 +03:00
2006-05-10 01:23:51 +04:00
if ( lvnum > = MAX_LV ) {
2009-07-16 00:02:46 +04:00
log_error ( " Logical volume number "
" out of bounds. " ) ;
2002-02-13 14:43:29 +03:00
return 0 ;
}
2002-02-21 22:04:37 +03:00
if ( ! lvs [ lvnum ] & &
2006-05-10 01:23:51 +04:00
! ( lvs [ lvnum ] = find_lv ( vg , ( char * ) lvd - > lv_name ) ) ) {
2009-07-16 00:02:46 +04:00
log_error ( " Couldn't find logical volume '%s'. " ,
lvd - > lv_name ) ;
2002-02-13 14:43:29 +03:00
return 0 ;
}
}
}
/*
* Now iterate through yet again adding the snapshots .
*/
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( dl , pvds ) {
dm_list_iterate_items ( ll , & dl - > lvds ) {
2005-06-01 20:51:55 +04:00
lvd = & ll - > lvd ;
2002-02-13 14:43:29 +03:00
2002-02-21 00:24:45 +03:00
if ( ! ( lvd - > lv_access & LV_SNAPSHOT ) )
2002-02-13 14:43:29 +03:00
continue ;
2002-02-21 22:04:37 +03:00
lvnum = lvd - > lv_number ;
cow = lvs [ lvnum ] ;
2002-02-13 14:43:29 +03:00
if ( ! ( org = lvs [ lvd - > lv_snapshot_minor ] ) ) {
2009-07-16 00:02:46 +04:00
log_error ( " Couldn't find origin logical volume "
" for snapshot '%s'. " , lvd - > lv_name ) ;
2002-02-13 14:43:29 +03:00
return 0 ;
}
/* we may have already added this snapshot */
2002-02-20 22:04:55 +03:00
if ( lv_is_cow ( cow ) )
2002-02-13 14:43:29 +03:00
continue ;
/* insert the snapshot */
2009-05-14 01:21:58 +04:00
if ( ! vg_add_snapshot ( org , cow , NULL ,
2008-01-30 17:00:02 +03:00
org - > le_count ,
2002-11-18 17:01:16 +03:00
lvd - > lv_chunk_size ) ) {
2009-07-16 00:02:46 +04:00
log_error ( " Couldn't add snapshot. " ) ;
2002-02-13 14:43:29 +03:00
return 0 ;
}
}
}
2001-10-09 18:26:45 +04:00
return 1 ;
}
int export_uuids ( struct disk_list * dl , struct volume_group * vg )
{
struct uuid_list * ul ;
struct pv_list * pvl ;
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( pvl , & vg - > pvs ) {
2008-01-30 16:19:47 +03:00
if ( ! ( ul = dm_pool_alloc ( dl - > mem , sizeof ( * ul ) ) ) )
return_0 ;
2001-10-09 18:26:45 +04:00
2001-10-11 14:08:44 +04:00
memset ( ul - > uuid , 0 , sizeof ( ul - > uuid ) ) ;
2002-01-21 19:05:23 +03:00
memcpy ( ul - > uuid , pvl - > pv - > id . uuid , ID_LEN ) ;
2001-10-09 18:26:45 +04:00
2008-11-04 01:14:30 +03:00
dm_list_add ( & dl - > uuids , & ul - > list ) ;
2001-10-09 18:26:45 +04:00
}
return 1 ;
}
2001-10-11 14:55:19 +04:00
/*
2002-02-21 22:04:37 +03:00
* This calculates the nasty pv_number field
* used by LVM1 .
2001-10-11 14:55:19 +04:00
*/
2010-07-09 19:34:40 +04:00
void export_numbers ( struct dm_list * pvds , struct volume_group * vg __attribute__ ( ( unused ) ) )
2001-10-11 14:55:19 +04:00
{
struct disk_list * dl ;
2001-10-11 20:31:09 +04:00
int pv_num = 1 ;
2001-10-11 14:55:19 +04:00
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( dl , pvds )
2001-10-31 20:59:52 +03:00
dl - > pvd . pv_number = pv_num + + ;
2001-10-11 14:55:19 +04:00
}
2001-10-11 17:05:55 +04:00
/*
* Calculate vg_disk - > pv_act .
*/
2008-11-04 01:14:30 +03:00
void export_pv_act ( struct dm_list * pvds )
2001-10-11 17:05:55 +04:00
{
struct disk_list * dl ;
int act = 0 ;
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( dl , pvds )
2001-10-31 20:59:52 +03:00
if ( dl - > pvd . pv_status & PV_ACTIVE )
2001-10-11 17:05:55 +04:00
act + + ;
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( dl , pvds )
2001-10-31 20:59:52 +03:00
dl - > vgd . pv_act = act ;
2001-10-11 17:05:55 +04:00
}
2001-10-11 18:10:18 +04:00
2008-11-04 01:14:30 +03:00
int export_vg_number ( struct format_instance * fid , struct dm_list * pvds ,
2002-04-24 22:20:51 +04:00
const char * vg_name , struct dev_filter * filter )
2001-10-11 18:10:18 +04:00
{
struct disk_list * dl ;
int vg_num ;
2008-01-30 16:19:47 +03:00
if ( ! get_free_vg_number ( fid , filter , vg_name , & vg_num ) )
return_0 ;
2001-10-11 18:10:18 +04:00
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( dl , pvds )
2001-10-31 20:59:52 +03:00
dl - > vgd . vg_number = vg_num ;
2001-10-11 18:10:18 +04:00
return 1 ;
}