2002-11-18 17:04:08 +03:00
/*
2008-01-30 17:00:02 +03:00
* Copyright ( C ) 2002 - 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 .
2002-11-18 17:04:08 +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 ,
* Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
2002-11-18 17:04:08 +03:00
*/
# include "lib.h"
# include "format-text.h"
# include "layout.h"
# include "label.h"
# include "xlate.h"
2004-05-05 01:25:57 +04:00
# include "lvmcache.h"
2002-11-18 17:04:08 +03:00
# include <sys/stat.h>
# include <fcntl.h>
2010-07-09 19:34:40 +04:00
static int _text_can_handle ( struct labeller * l __attribute__ ( ( unused ) ) ,
2006-12-01 02:11:42 +03:00
void * buf ,
2010-07-09 19:34:40 +04:00
uint64_t sector __attribute__ ( ( unused ) ) )
2002-11-18 17:04:08 +03:00
{
struct label_header * lh = ( struct label_header * ) buf ;
2006-05-10 01:23:51 +04:00
if ( ! strncmp ( ( char * ) lh - > type , LVM2_LABEL , sizeof ( lh - > type ) ) )
2002-11-18 17:04:08 +03:00
return 1 ;
return 0 ;
}
2012-02-10 05:28:27 +04:00
struct _da_setup_baton {
struct disk_locn * pvh_dlocn_xl ;
struct device * dev ;
} ;
2012-02-23 17:11:07 +04:00
static int _da_setup ( struct disk_locn * da , void * baton )
2012-02-10 05:28:27 +04:00
{
struct _da_setup_baton * p = baton ;
2012-02-23 17:11:07 +04:00
p - > pvh_dlocn_xl - > offset = xlate64 ( da - > offset ) ;
p - > pvh_dlocn_xl - > size = xlate64 ( da - > size ) ;
2012-02-10 05:28:27 +04:00
p - > pvh_dlocn_xl + + ;
return 1 ;
}
static int _mda_setup ( struct metadata_area * mda , void * baton )
{
struct _da_setup_baton * p = baton ;
struct mda_context * mdac = ( struct mda_context * ) mda - > metadata_locn ;
if ( mdac - > area . dev ! = p - > dev )
return 1 ;
p - > pvh_dlocn_xl - > offset = xlate64 ( mdac - > area . start ) ;
p - > pvh_dlocn_xl - > size = xlate64 ( mdac - > area . size ) ;
p - > pvh_dlocn_xl + + ;
return 1 ;
}
2006-12-01 02:11:42 +03:00
static int _text_write ( struct label * label , void * buf )
2002-11-18 17:04:08 +03:00
{
struct label_header * lh = ( struct label_header * ) buf ;
struct pv_header * pvhdr ;
2003-07-05 02:34:56 +04:00
struct lvmcache_info * info ;
2012-02-10 05:28:27 +04:00
struct _da_setup_baton baton ;
2010-07-09 19:34:40 +04:00
char buffer [ 64 ] __attribute__ ( ( aligned ( 8 ) ) ) ;
2009-02-21 02:19:28 +03:00
int da1 , mda1 , mda2 ;
2002-11-18 17:04:08 +03:00
/* FIXME Move to where label is created */
strncpy ( label - > type , LVM2_LABEL , sizeof ( label - > type ) ) ;
2006-05-10 01:23:51 +04:00
strncpy ( ( char * ) lh - > type , label - > type , sizeof ( label - > type ) ) ;
2002-11-18 17:04:08 +03:00
2011-02-18 17:34:41 +03:00
pvhdr = ( struct pv_header * ) ( ( char * ) buf + xlate32 ( lh - > offset_xl ) ) ;
2003-07-05 02:34:56 +04:00
info = ( struct lvmcache_info * ) label - > info ;
2012-02-10 05:28:27 +04:00
pvhdr - > device_size_xl = xlate64 ( lvmcache_device_size ( info ) ) ;
memcpy ( pvhdr - > pv_uuid , & lvmcache_device ( info ) - > pvid , sizeof ( struct id ) ) ;
2009-02-21 02:19:28 +03:00
if ( ! id_write_format ( ( const struct id * ) pvhdr - > pv_uuid , buffer ,
sizeof ( buffer ) ) ) {
stack ;
buffer [ 0 ] = ' \0 ' ;
}
2002-11-18 17:04:08 +03:00
2012-02-10 05:28:27 +04:00
baton . dev = lvmcache_device ( info ) ;
2002-11-18 17:04:08 +03:00
/* List of data areas (holding PEs) */
2012-02-10 05:28:27 +04:00
baton . pvh_dlocn_xl = & pvhdr - > disk_areas_xl [ 0 ] ;
lvmcache_foreach_da ( info , _da_setup , & baton ) ;
2002-11-18 17:04:08 +03:00
/* NULL-termination */
2012-02-10 05:28:27 +04:00
baton . pvh_dlocn_xl - > offset = xlate64 ( UINT64_C ( 0 ) ) ;
baton . pvh_dlocn_xl - > size = xlate64 ( UINT64_C ( 0 ) ) ;
baton . pvh_dlocn_xl + + ;
2002-11-18 17:04:08 +03:00
/* List of metadata area header locations */
2012-02-10 05:28:27 +04:00
lvmcache_foreach_mda ( info , _mda_setup , & baton ) ;
2002-11-18 17:04:08 +03:00
/* NULL-termination */
2012-02-10 05:28:27 +04:00
baton . pvh_dlocn_xl - > offset = xlate64 ( UINT64_C ( 0 ) ) ;
baton . pvh_dlocn_xl - > size = xlate64 ( UINT64_C ( 0 ) ) ;
2002-11-18 17:04:08 +03:00
2009-02-21 02:19:28 +03:00
/* Create debug message with da and mda locations */
if ( xlate64 ( pvhdr - > disk_areas_xl [ 0 ] . offset ) | |
xlate64 ( pvhdr - > disk_areas_xl [ 0 ] . size ) )
da1 = 0 ;
else
da1 = - 1 ;
mda1 = da1 + 2 ;
mda2 = mda1 + 1 ;
if ( ! xlate64 ( pvhdr - > disk_areas_xl [ mda1 ] . offset ) & &
! xlate64 ( pvhdr - > disk_areas_xl [ mda1 ] . size ) )
mda1 = mda2 = 0 ;
else if ( ! xlate64 ( pvhdr - > disk_areas_xl [ mda2 ] . offset ) & &
! xlate64 ( pvhdr - > disk_areas_xl [ mda2 ] . size ) )
mda2 = 0 ;
log_debug ( " %s: Preparing PV label header %s size % " PRIu64 " with "
" %s%.* " PRIu64 " %s%.* " PRIu64 " %s "
" %s%.* " PRIu64 " %s%.* " PRIu64 " %s "
" %s%.* " PRIu64 " %s%.* " PRIu64 " %s " ,
2012-02-10 05:28:27 +04:00
dev_name ( lvmcache_device ( info ) ) , buffer , lvmcache_device_size ( info ) ,
2009-02-21 02:19:28 +03:00
( da1 > - 1 ) ? " da1 ( " : " " ,
( da1 > - 1 ) ? 1 : 0 ,
( da1 > - 1 ) ? xlate64 ( pvhdr - > disk_areas_xl [ da1 ] . offset ) > > SECTOR_SHIFT : 0 ,
( da1 > - 1 ) ? " s, " : " " ,
( da1 > - 1 ) ? 1 : 0 ,
( da1 > - 1 ) ? xlate64 ( pvhdr - > disk_areas_xl [ da1 ] . size ) > > SECTOR_SHIFT : 0 ,
( da1 > - 1 ) ? " s) " : " " ,
mda1 ? " mda1 ( " : " " ,
mda1 ? 1 : 0 ,
mda1 ? xlate64 ( pvhdr - > disk_areas_xl [ mda1 ] . offset ) > > SECTOR_SHIFT : 0 ,
mda1 ? " s, " : " " ,
mda1 ? 1 : 0 ,
mda1 ? xlate64 ( pvhdr - > disk_areas_xl [ mda1 ] . size ) > > SECTOR_SHIFT : 0 ,
mda1 ? " s) " : " " ,
mda2 ? " mda2 ( " : " " ,
mda2 ? 1 : 0 ,
mda2 ? xlate64 ( pvhdr - > disk_areas_xl [ mda2 ] . offset ) > > SECTOR_SHIFT : 0 ,
mda2 ? " s, " : " " ,
mda2 ? 1 : 0 ,
mda2 ? xlate64 ( pvhdr - > disk_areas_xl [ mda2 ] . size ) > > SECTOR_SHIFT : 0 ,
mda2 ? " s) " : " " ) ;
2009-02-22 22:00:26 +03:00
if ( da1 < 0 ) {
2009-12-16 22:22:11 +03:00
log_error ( INTERNAL_ERROR " %s label header currently requires "
2012-02-10 05:28:27 +04:00
" a data area. " , dev_name ( lvmcache_device ( info ) ) ) ;
2009-02-22 22:00:26 +03:00
return 0 ;
}
2002-11-18 17:04:08 +03:00
return 1 ;
}
2008-11-04 01:14:30 +03:00
int add_da ( struct dm_pool * mem , struct dm_list * das ,
2002-11-18 17:04:08 +03:00
uint64_t start , uint64_t size )
{
struct data_area_list * dal ;
if ( ! mem ) {
2005-10-17 03:03:59 +04:00
if ( ! ( dal = dm_malloc ( sizeof ( * dal ) ) ) ) {
2002-11-18 17:04:08 +03:00
log_error ( " struct data_area_list allocation failed " ) ;
return 0 ;
}
} else {
2005-10-17 03:03:59 +04:00
if ( ! ( dal = dm_pool_alloc ( mem , sizeof ( * dal ) ) ) ) {
2002-11-18 17:04:08 +03:00
log_error ( " struct data_area_list allocation failed " ) ;
return 0 ;
}
}
dal - > disk_locn . offset = start ;
dal - > disk_locn . size = size ;
2008-11-04 01:14:30 +03:00
dm_list_add ( das , & dal - > list ) ;
2002-11-18 17:04:08 +03:00
return 1 ;
}
2008-11-04 01:14:30 +03:00
void del_das ( struct dm_list * das )
2002-11-18 17:04:08 +03:00
{
2008-11-04 01:14:30 +03:00
struct dm_list * dah , * tmp ;
2002-11-18 17:04:08 +03:00
struct data_area_list * da ;
2008-11-04 01:14:30 +03:00
dm_list_iterate_safe ( dah , tmp , das ) {
da = dm_list_item ( dah , struct data_area_list ) ;
dm_list_del ( & da - > list ) ;
2005-10-17 03:03:59 +04:00
dm_free ( da ) ;
2002-11-18 17:04:08 +03:00
}
}
2010-06-30 16:17:24 +04:00
/* FIXME: refactor this function with other mda constructor code */
2008-11-04 01:14:30 +03:00
int add_mda ( const struct format_type * fmt , struct dm_pool * mem , struct dm_list * mdas ,
2010-06-30 16:17:24 +04:00
struct device * dev , uint64_t start , uint64_t size , unsigned ignored )
2002-11-18 17:04:08 +03:00
{
/* FIXME List size restricted by pv_header SECTOR_SIZE */
struct metadata_area * mdal ;
struct mda_lists * mda_lists = ( struct mda_lists * ) fmt - > private ;
struct mda_context * mdac ;
if ( ! mem ) {
2005-10-17 03:03:59 +04:00
if ( ! ( mdal = dm_malloc ( sizeof ( struct metadata_area ) ) ) ) {
2002-11-18 17:04:08 +03:00
log_error ( " struct mda_list allocation failed " ) ;
return 0 ;
}
2005-10-17 03:03:59 +04:00
if ( ! ( mdac = dm_malloc ( sizeof ( struct mda_context ) ) ) ) {
2002-11-18 17:04:08 +03:00
log_error ( " struct mda_context allocation failed " ) ;
2005-10-17 03:03:59 +04:00
dm_free ( mdal ) ;
2002-11-18 17:04:08 +03:00
return 0 ;
}
} else {
2005-10-17 03:03:59 +04:00
if ( ! ( mdal = dm_pool_alloc ( mem , sizeof ( struct metadata_area ) ) ) ) {
2002-11-18 17:04:08 +03:00
log_error ( " struct mda_list allocation failed " ) ;
return 0 ;
}
2005-10-17 03:03:59 +04:00
if ( ! ( mdac = dm_pool_alloc ( mem , sizeof ( struct mda_context ) ) ) ) {
2002-11-18 17:04:08 +03:00
log_error ( " struct mda_context allocation failed " ) ;
return 0 ;
}
}
mdal - > ops = mda_lists - > raw_ops ;
mdal - > metadata_locn = mdac ;
2010-10-05 21:34:05 +04:00
mdal - > status = 0 ;
2002-11-18 17:04:08 +03:00
mdac - > area . dev = dev ;
mdac - > area . start = start ;
mdac - > area . size = size ;
2007-11-05 20:17:55 +03:00
mdac - > free_sectors = UINT64_C ( 0 ) ;
2002-11-18 17:04:08 +03:00
memset ( & mdac - > rlocn , 0 , sizeof ( mdac - > rlocn ) ) ;
2010-06-30 16:17:24 +04:00
mda_set_ignored ( mdal , ignored ) ;
2002-11-18 17:04:08 +03:00
2008-11-04 01:14:30 +03:00
dm_list_add ( mdas , & mdal - > list ) ;
2002-11-18 17:04:08 +03:00
return 1 ;
}
2008-11-04 01:14:30 +03:00
void del_mdas ( struct dm_list * mdas )
2002-11-18 17:04:08 +03:00
{
2008-11-04 01:14:30 +03:00
struct dm_list * mdah , * tmp ;
2002-11-18 17:04:08 +03:00
struct metadata_area * mda ;
2008-11-04 01:14:30 +03:00
dm_list_iterate_safe ( mdah , tmp , mdas ) {
mda = dm_list_item ( mdah , struct metadata_area ) ;
2005-10-17 03:03:59 +04:00
dm_free ( mda - > metadata_locn ) ;
2008-11-04 01:14:30 +03:00
dm_list_del ( & mda - > list ) ;
2005-10-17 03:03:59 +04:00
dm_free ( mda ) ;
2002-11-18 17:04:08 +03:00
}
}
2010-07-09 19:34:40 +04:00
static int _text_initialise_label ( struct labeller * l __attribute__ ( ( unused ) ) ,
2006-05-11 21:58:58 +04:00
struct label * label )
2002-11-18 17:04:08 +03:00
{
strncpy ( label - > type , LVM2_LABEL , sizeof ( label - > type ) ) ;
return 1 ;
}
2012-02-10 05:28:27 +04:00
struct _update_mda_baton {
struct lvmcache_info * info ;
struct label * label ;
} ;
static int _update_mda ( struct metadata_area * mda , void * baton )
{
struct _update_mda_baton * p = baton ;
const struct format_type * fmt = p - > label - > labeller - > private ; // Oh dear.
struct mda_context * mdac = ( struct mda_context * ) mda - > metadata_locn ;
struct mda_header * mdah ;
2012-02-23 17:11:07 +04:00
const char * vgname = NULL ;
2012-02-10 05:28:27 +04:00
struct id vgid ;
uint64_t vgstatus ;
char * creation_host ;
if ( ! dev_open_readonly ( mdac - > area . dev ) ) {
mda_set_ignored ( mda , 1 ) ;
stack ;
return 1 ;
}
if ( ! ( mdah = raw_read_mda_header ( fmt , & mdac - > area ) ) ) {
stack ;
goto close_dev ;
}
mda_set_ignored ( mda , rlocn_is_ignored ( mdah - > raw_locns ) ) ;
if ( mda_is_ignored ( mda ) ) {
log_debug ( " Ignoring mda on device %s at offset % " PRIu64 ,
dev_name ( mdac - > area . dev ) ,
mdac - > area . start ) ;
if ( ! dev_close ( mdac - > area . dev ) )
stack ;
return 1 ;
}
if ( ( vgname = vgname_from_mda ( fmt , mdah ,
& mdac - > area ,
& vgid , & vgstatus , & creation_host ,
& mdac - > free_sectors ) ) & &
! lvmcache_update_vgname_and_id ( p - > info , vgname ,
( char * ) & vgid , vgstatus ,
creation_host ) ) {
if ( ! dev_close ( mdac - > area . dev ) )
stack ;
return_0 ;
}
close_dev :
if ( ! dev_close ( mdac - > area . dev ) )
stack ;
return 1 ;
}
2006-12-01 02:11:42 +03:00
static int _text_read ( struct labeller * l , struct device * dev , void * buf ,
2002-11-18 17:04:08 +03:00
struct label * * label )
{
struct label_header * lh = ( struct label_header * ) buf ;
struct pv_header * pvhdr ;
2003-07-05 02:34:56 +04:00
struct lvmcache_info * info ;
2002-11-18 17:04:08 +03:00
struct disk_locn * dlocn_xl ;
uint64_t offset ;
2012-02-10 05:28:27 +04:00
struct _update_mda_baton baton ;
2002-11-18 17:04:08 +03:00
2011-02-18 17:34:41 +03:00
pvhdr = ( struct pv_header * ) ( ( char * ) buf + xlate32 ( lh - > offset_xl ) ) ;
2002-11-18 17:04:08 +03:00
2008-02-06 18:47:28 +03:00
if ( ! ( info = lvmcache_add ( l , ( char * ) pvhdr - > pv_uuid , dev ,
FMT_TEXT_ORPHAN_VG_NAME ,
FMT_TEXT_ORPHAN_VG_NAME , 0 ) ) )
2006-04-11 17:55:59 +04:00
return_0 ;
2002-11-18 17:04:08 +03:00
2012-02-10 05:28:27 +04:00
* label = lvmcache_get_label ( info ) ;
2002-11-18 17:04:08 +03:00
2012-02-10 05:28:27 +04:00
lvmcache_set_device_size ( info , xlate64 ( pvhdr - > device_size_xl ) ) ;
2002-11-18 17:04:08 +03:00
2012-02-10 05:28:27 +04:00
lvmcache_del_das ( info ) ;
lvmcache_del_mdas ( info ) ;
2002-11-18 17:04:08 +03:00
/* Data areas holding the PEs */
dlocn_xl = pvhdr - > disk_areas_xl ;
while ( ( offset = xlate64 ( dlocn_xl - > offset ) ) ) {
2012-02-10 05:28:27 +04:00
lvmcache_add_da ( info , offset , xlate64 ( dlocn_xl - > size ) ) ;
2002-11-18 17:04:08 +03:00
dlocn_xl + + ;
}
/* Metadata area headers */
dlocn_xl + + ;
while ( ( offset = xlate64 ( dlocn_xl - > offset ) ) ) {
2012-02-10 05:28:27 +04:00
lvmcache_add_mda ( info , dev , offset , xlate64 ( dlocn_xl - > size ) , 0 ) ;
2002-11-18 17:04:08 +03:00
dlocn_xl + + ;
}
2012-02-10 05:28:27 +04:00
baton . info = info ;
baton . label = * label ;
2002-11-18 17:04:08 +03:00
2012-02-10 05:28:27 +04:00
lvmcache_foreach_mda ( info , _update_mda , & baton ) ;
lvmcache_make_valid ( info ) ;
2002-11-18 17:04:08 +03:00
return 1 ;
}
2010-07-09 19:34:40 +04:00
static void _text_destroy_label ( struct labeller * l __attribute__ ( ( unused ) ) ,
2006-05-11 21:58:58 +04:00
struct label * label )
2002-11-18 17:04:08 +03:00
{
2003-07-05 02:34:56 +04:00
struct lvmcache_info * info = ( struct lvmcache_info * ) label - > info ;
2002-11-18 17:04:08 +03:00
2012-02-10 05:28:27 +04:00
lvmcache_del_mdas ( info ) ;
lvmcache_del_das ( info ) ;
2002-11-18 17:04:08 +03:00
}
2006-04-19 19:33:07 +04:00
static void _fmt_text_destroy ( struct labeller * l )
2002-11-18 17:04:08 +03:00
{
2005-10-17 03:03:59 +04:00
dm_free ( l ) ;
2002-11-18 17:04:08 +03:00
}
struct label_ops _text_ops = {
2006-05-10 01:23:51 +04:00
. can_handle = _text_can_handle ,
. write = _text_write ,
. read = _text_read ,
. verify = _text_can_handle ,
. initialise_label = _text_initialise_label ,
. destroy_label = _text_destroy_label ,
. destroy = _fmt_text_destroy ,
2002-11-18 17:04:08 +03:00
} ;
2002-12-20 02:25:55 +03:00
struct labeller * text_labeller_create ( const struct format_type * fmt )
2002-11-18 17:04:08 +03:00
{
struct labeller * l ;
2005-10-17 03:03:59 +04:00
if ( ! ( l = dm_malloc ( sizeof ( * l ) ) ) ) {
2009-07-16 00:02:46 +04:00
log_error ( " Couldn't allocate labeller object. " ) ;
2002-11-18 17:04:08 +03:00
return NULL ;
}
l - > ops = & _text_ops ;
2002-12-20 02:25:55 +03:00
l - > private = ( const void * ) fmt ;
2002-11-18 17:04:08 +03:00
return l ;
}