2001-09-25 16:49:28 +04:00
/*
* Copyright ( C ) 2001 Sistina Software
*
* This LVM library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation ; either
* version 2 of the License , or ( at your option ) any later version .
*
* This LVM library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Library General Public License for more details .
*
* You should have received a copy of the GNU Library General Public
* License along with this LVM library ; if not , write to the Free
* Software Foundation , Inc . , 59 Temple Place - Suite 330 , Boston ,
* MA 02111 - 1307 , USA
*/
# include <stdio.h>
# include <unistd.h>
# include <fcntl.h>
# include <string.h>
# include <errno.h>
# include <sys/stat.h>
2001-10-01 19:14:39 +04:00
# include "dbg_malloc.h"
# include "dev-manager.h"
# include "log.h"
# include "metadata.h"
2001-09-25 16:49:28 +04:00
/*
* FIXME : these should not allocate memory
*/
pv_t * pv_copy_from_disk ( pv_disk_t * pv_disk )
{
pv_t * pv ;
if ( ! pv_disk | | ! ( pv = ( pv_t * ) dbg_malloc ( sizeof ( * pv ) ) ) )
return 0 ;
# define xx16(v) pv->v = LVM_TO_CORE16(pv_disk->v)
# define xx32(v) pv->v = LVM_TO_CORE32(pv_disk->v)
memset ( pv , 0 , sizeof ( * pv ) ) ;
strncpy ( pv - > id , pv_disk - > id , sizeof ( pv - > id ) ) ;
xx16 ( version ) ;
xx32 ( pv_on_disk . base ) ;
xx32 ( pv_on_disk . size ) ;
xx32 ( vg_on_disk . base ) ;
xx32 ( vg_on_disk . size ) ;
xx32 ( pv_uuidlist_on_disk . base ) ;
xx32 ( pv_uuidlist_on_disk . size ) ;
xx32 ( lv_on_disk . base ) ;
xx32 ( lv_on_disk . size ) ;
xx32 ( pe_on_disk . base ) ;
xx32 ( pe_on_disk . size ) ;
memset ( pv - > pv_name , 0 , sizeof ( pv - > pv_name ) ) ;
memset ( pv - > pv_uuid , 0 , sizeof ( pv - > pv_uuid ) ) ;
memcpy ( pv - > pv_uuid , pv_disk - > pv_uuid , UUID_LEN ) ;
strncpy ( pv - > vg_name , pv_disk - > vg_name , sizeof ( pv - > vg_name ) ) ;
strncpy ( pv - > system_id , pv_disk - > system_id , sizeof ( pv - > system_id ) ) ;
pv - > pv_dev = LVM_TO_CORE32 ( pv_disk - > pv_major ) ;
xx32 ( pv_number ) ;
xx32 ( pv_status ) ;
xx32 ( pv_allocatable ) ;
xx32 ( pv_size ) ;
xx32 ( lv_cur ) ;
xx32 ( pe_size ) ;
xx32 ( pe_total ) ;
xx32 ( pe_allocated ) ;
pv - > pe_stale = 0 ;
xx32 ( pe_start ) ;
# undef xx16
# undef xx32
return pv ;
}
pv_disk_t * pv_copy_to_disk ( pv_t * pv_core )
{
pv_disk_t * pv ;
if ( ! pv_core | | ! ( pv = dbg_malloc ( sizeof ( * pv ) ) ) )
return 0 ;
# define xx16(v) pv->v = LVM_TO_DISK16(pv_core->v)
# define xx32(v) pv->v = LVM_TO_DISK32(pv_core->v)
memset ( pv , 0 , sizeof ( * pv ) ) ;
strncpy ( pv - > id , pv_core - > id , sizeof ( pv - > id ) ) ;
xx16 ( version ) ;
xx32 ( pv_on_disk . base ) ;
xx32 ( pv_on_disk . size ) ;
xx32 ( vg_on_disk . base ) ;
xx32 ( vg_on_disk . size ) ;
xx32 ( pv_uuidlist_on_disk . base ) ;
xx32 ( pv_uuidlist_on_disk . size ) ;
xx32 ( lv_on_disk . base ) ;
xx32 ( lv_on_disk . size ) ;
xx32 ( pe_on_disk . base ) ;
xx32 ( pe_on_disk . size ) ;
memcpy ( pv - > pv_uuid , pv_core - > pv_uuid , UUID_LEN ) ;
strncpy ( pv - > vg_name , pv_core - > vg_name , sizeof ( pv - > vg_name ) ) ;
strncpy ( pv - > system_id , pv_core - > system_id , sizeof ( pv - > system_id ) ) ;
/* core type is kdev_t; but no matter what it is,
only store major for check in pv_read ( ) */
pv - > pv_major = LVM_TO_DISK32 ( MAJOR ( pv_core - > pv_dev ) ) ;
xx32 ( pv_number ) ;
xx32 ( pv_status ) ;
xx32 ( pv_allocatable ) ;
xx32 ( pv_size ) ;
xx32 ( lv_cur ) ;
xx32 ( pe_size ) ;
xx32 ( pe_total ) ;
xx32 ( pe_allocated ) ;
xx32 ( pe_start ) ;
# undef xx16
# undef xx32
return pv ;
}
lv_t * lv_copy_from_disk ( lv_disk_t * lv_disk )
{
lv_t * lv ;
if ( ! lv_disk | | ! ( lv = dbg_malloc ( sizeof ( * lv ) ) ) )
return 0 ;
memset ( lv , 0 , sizeof ( * lv ) ) ;
# define xx16(v) lv->v = LVM_TO_CORE16(lv_disk->v)
# define xx32(v) lv->v = LVM_TO_CORE32(lv_disk->v)
strncpy ( lv - > lv_name , lv_disk - > lv_name , sizeof ( lv - > lv_name ) ) ;
strncpy ( lv - > vg_name , lv_disk - > vg_name , sizeof ( lv - > vg_name ) ) ;
xx32 ( lv_access ) ;
xx32 ( lv_status ) ;
lv - > lv_open = 0 ;
xx32 ( lv_dev ) ;
xx32 ( lv_number ) ;
xx32 ( lv_mirror_copies ) ;
xx32 ( lv_recovery ) ;
xx32 ( lv_schedule ) ;
xx32 ( lv_size ) ;
lv - > lv_current_pe = NULL ;
xx32 ( lv_allocated_le ) ;
lv - > lv_current_le = lv - > lv_allocated_le ;
xx32 ( lv_stripes ) ;
xx32 ( lv_stripesize ) ;
xx32 ( lv_badblock ) ;
xx32 ( lv_allocation ) ;
xx32 ( lv_io_timeout ) ;
xx32 ( lv_read_ahead ) ;
lv - > lv_snapshot_org = NULL ;
lv - > lv_snapshot_prev = NULL ;
lv - > lv_snapshot_next = NULL ;
lv - > lv_block_exception = NULL ;
lv - > lv_remap_ptr = 0 ;
lv - > lv_remap_end = 0 ;
xx32 ( lv_snapshot_minor ) ;
xx16 ( lv_chunk_size ) ;
# undef xx32
# undef xx16
return lv ;
}
lv_disk_t * lv_copy_to_disk ( lv_t * lv_core )
{
lv_disk_t * lv ;
if ( ! lv_core | | ! ( lv = dbg_malloc ( sizeof ( * lv ) ) ) )
return 0 ;
memset ( lv , 0 , sizeof ( * lv ) ) ;
# define xx16(v) lv->v = LVM_TO_DISK16(lv_core->v)
# define xx32(v) lv->v = LVM_TO_DISK32(lv_core->v)
strncpy ( lv - > lv_name , lv_core - > lv_name , sizeof ( lv - > lv_name ) ) ;
strncpy ( lv - > vg_name , lv_core - > vg_name , sizeof ( lv - > vg_name ) ) ;
xx32 ( lv_access ) ;
xx32 ( lv_status ) ;
lv - > lv_open = 0 ;
xx32 ( lv_dev ) ;
xx32 ( lv_number ) ;
xx32 ( lv_mirror_copies ) ;
xx32 ( lv_recovery ) ;
xx32 ( lv_schedule ) ;
xx32 ( lv_size ) ;
xx32 ( lv_snapshot_minor ) ;
xx16 ( lv_chunk_size ) ;
lv - > dummy = 0 ;
xx32 ( lv_allocated_le ) ;
xx32 ( lv_stripes ) ;
xx32 ( lv_stripesize ) ;
xx32 ( lv_badblock ) ;
xx32 ( lv_allocation ) ;
xx32 ( lv_io_timeout ) ;
xx32 ( lv_read_ahead ) ;
# undef xx32
# undef xx16
return lv ;
}
vg_t * vg_copy_from_disk ( vg_disk_t * vg_disk )
{
vg_t * vg ;
if ( ! vg_disk | | ! ( vg = dbg_malloc ( sizeof ( * vg ) ) ) )
return 0 ;
# define xx32(v) vg->v = LVM_TO_CORE32(vg_disk->v)
memset ( vg , 0 , sizeof ( vg_t ) ) ;
xx32 ( vg_number ) ;
xx32 ( vg_access ) ;
xx32 ( vg_status ) ;
xx32 ( lv_max ) ;
xx32 ( lv_cur ) ;
vg - > lv_open = 0 ;
xx32 ( pv_max ) ;
xx32 ( pv_cur ) ;
xx32 ( pv_act ) ;
vg - > dummy = 0 ;
xx32 ( vgda ) ;
xx32 ( pe_size ) ;
xx32 ( pe_total ) ;
xx32 ( pe_allocated ) ;
xx32 ( pvg_total ) ;
# undef xx32
memset ( & vg - > pv , 0 , sizeof ( vg - > pv ) ) ;
memset ( & vg - > lv , 0 , sizeof ( vg - > lv ) ) ;
memset ( vg - > vg_uuid , 0 , sizeof ( vg - > vg_uuid ) ) ;
memcpy ( vg - > vg_uuid , vg_disk - > vg_uuid , UUID_LEN ) ;
return vg ;
}
vg_disk_t * vg_copy_to_disk ( vg_t * vg_core )
{
vg_disk_t * vg ;
if ( ! vg_core | |
/* FIXME: vg_check_consistency(vg_core) || */
! ( vg = dbg_malloc ( sizeof ( * vg ) ) ) )
return 0 ;
memset ( vg , 0 , sizeof ( * vg ) ) ;
# define xx32(v) vg->v = LVM_TO_DISK32(vg_core->v)
xx32 ( vg_number ) ;
xx32 ( vg_access ) ;
xx32 ( vg_status ) ;
xx32 ( lv_max ) ;
xx32 ( lv_cur ) ;
vg - > lv_open = 0 ;
xx32 ( pv_max ) ;
xx32 ( pv_cur ) ;
xx32 ( pv_act ) ;
vg - > dummy = 0 ;
xx32 ( vgda ) ;
xx32 ( pe_size ) ;
xx32 ( pe_total ) ;
xx32 ( pe_allocated ) ;
xx32 ( pvg_total ) ;
# undef xx32
memcpy ( vg - > vg_uuid , vg_core - > vg_uuid , UUID_LEN ) ;
return vg ;
}
pe_disk_t * pe_copy_from_disk ( pe_disk_t * pe_file , int count )
{
int i ;
pe_disk_t * pe ;
size_t s = sizeof ( * pe ) * count ;
if ( ! pe_file | | count < = 0 | | ! ( pe = dbg_malloc ( s ) ) )
return 0 ;
memset ( pe , 0 , s ) ;
for ( i = 0 ; i < count ; i + + ) {
pe [ i ] . lv_num = LVM_TO_CORE16 ( pe_file [ i ] . lv_num ) ;
pe [ i ] . le_num = LVM_TO_CORE16 ( pe_file [ i ] . le_num ) ;
}
return pe ;
}
pe_disk_t * pe_copy_to_disk ( pe_disk_t * pe_core , int count )
{
int i ;
pe_disk_t * pe ;
size_t s = sizeof ( * pe ) * count ;
if ( ! pe_core | | count < = 0 | | ! ( pe = dbg_malloc ( s ) ) )
return 0 ;
memset ( pe , 0 , s ) ;
for ( i = 0 ; i < count ; i + + ) {
pe [ i ] . lv_num = LVM_TO_DISK16 ( pe_core [ i ] . lv_num ) ;
pe [ i ] . le_num = LVM_TO_DISK16 ( pe_core [ i ] . le_num ) ;
}
return pe ;
}
pv_t * pv_read_lvm_v1 ( struct dev_mgr * dm , const char * pv_name )
{
int pv_handle = - 1 ;
ssize_t read_ret ;
ssize_t bytes_read = 0 ;
static pv_disk_t pv_this ;
struct stat stat_b ;
pv_t * pv = NULL ;
struct device * pv_dev ;
if ( ( pv_handle = open ( pv_name , O_RDONLY ) ) = = - 1 ) {
log_error ( " %s: open failed: %s " , pv_name , strerror ( errno ) ) ;
return NULL ;
}
if ( ( fstat ( pv_handle , & stat_b ) ) ) {
log_error ( " %s: fstat failed: %s " , pv_name , strerror ( errno ) ) ;
goto pv_read_lvm_v1_out ;
}
while ( ( bytes_read < sizeof ( pv_this ) & &
( read_ret = read ( pv_handle , & pv_this + bytes_read ,
sizeof ( pv_this ) - bytes_read ) ) ! = - 1 ) )
bytes_read + = read_ret ;
if ( read_ret = = - 1 ) {
log_error ( " %s: read failed: %s " , pv_name , strerror ( errno ) ) ;
goto pv_read_lvm_v1_out ;
}
pv = pv_copy_from_disk ( & pv_this ) ;
/* correct for imported/moved volumes */
if ( ! ( pv_dev = dev_by_dev ( dm , stat_b . st_rdev ) ) ) {
log_error ( " Device missing from cache " ) ;
goto pv_read_lvm_v1_out ;
}
memset ( pv - > pv_name , 0 , sizeof ( pv - > pv_name ) ) ;
strncpy ( pv - > pv_name , pv_dev - > name , sizeof ( pv - > pv_name ) - 1 ) ;
/* FIXME: Deleted version / consistency / export checks! */
pv - > pv_dev = stat_b . st_rdev ;
pv_read_lvm_v1_out :
if ( pv_handle ! = - 1 )
close ( pv_handle ) ;
return pv ;
}
pe_disk_t * pv_read_pe_lvm_v1 ( const char * pv_name , const pv_t * pv )
{
int pv_handle = - 1 ;
uint size = 0 ;
ssize_t read_ret ;
ssize_t bytes_read = 0 ;
pe_disk_t * pe = NULL ;
pe_disk_t * pe_this ;
size = pv - > pe_total * sizeof ( pe_disk_t ) ;
if ( size > pv - > pe_on_disk . size ) {
log_error ( " PEs extend beyond end of volume group! " ) ;
return pe ; /*NULL*/
}
if ( ( pv_handle = open ( pv_name , O_RDONLY ) ) = = - 1 ) {
log_error ( " %s: open failed: %s " , pv_name , strerror ( errno ) ) ;
goto pv_read_pe_out ;
}
if ( lseek ( pv_handle , pv - > pe_on_disk . base , SEEK_SET ) ! =
pv - > pe_on_disk . base ) {
log_error ( " %s: lseek to PE failed: %s " , pv_name , strerror ( errno ) ) ;
goto pv_read_pe_out ;
}
if ( ! ( pe_this = dbg_malloc ( size ) ) ) {
log_error ( " PE malloc failed " ) ;
goto pv_read_pe_out ;
}
while ( ( bytes_read < size & &
( read_ret = read ( pv_handle , ( void * ) pe_this + bytes_read ,
size - bytes_read ) ) ! = - 1 ) )
bytes_read + = read_ret ;
if ( read_ret = = - 1 ) {
log_error ( " %s: read failed: %s " , pv_name , strerror ( errno ) ) ;
goto pv_read_pe_out ;
}
pe = pe_copy_from_disk ( pe_this , pv - > pe_total ) ;
pv_read_pe_out :
if ( pv_handle ! = - 1 )
close ( pv_handle ) ;
dbg_free ( pe_this ) ;
return pe ;
}
lv_disk_t * pv_read_lvs_lvm_v1 ( const pv_t * pv )
{
int pv_handle = - 1 ;
uint size = 0 ;
ssize_t read_ret ;
ssize_t bytes_read = 0 ;
lv_disk_t * lvs ;
/* FIXME: replace lv_cur? */
size = pv - > lv_cur * sizeof ( lv_disk_t ) ;
if ( ( pv_handle = open ( pv - > pv_name , O_RDONLY ) ) = = - 1 ) {
log_error ( " %s: open failed: %s " , pv - > pv_name , strerror ( errno ) ) ;
goto pv_read_lvs_out ;
}
if ( lseek ( pv_handle , pv - > lv_on_disk . base , SEEK_SET ) ! =
pv - > lv_on_disk . base ) {
log_error ( " %s: lseek to LV failed: %s " , pv - > pv_name , strerror ( errno ) ) ;
goto pv_read_lvs_out ;
}
if ( ! ( lvs = dbg_malloc ( size ) ) ) {
log_error ( " PE malloc failed " ) ;
goto pv_read_lvs_out ;
}
while ( ( bytes_read < size & &
( read_ret = read ( pv_handle , ( void * ) lvs + bytes_read ,
size - bytes_read ) ) ! = - 1 ) )
bytes_read + = read_ret ;
if ( read_ret = = - 1 ) {
log_error ( " %s: read failed: %s " , pv - > pv_name , strerror ( errno ) ) ;
goto pv_read_lvs_out ;
}
pv_read_lvs_out :
if ( pv_handle ! = - 1 )
close ( pv_handle ) ;
/* Caller frees */
return lvs ;
}