2001-10-04 21:48:55 +04:00
/*
* Copyright ( C ) 2001 Sistina Software ( UK ) Limited .
*
2001-10-31 15:47:01 +03:00
* This file is released under the LGPL .
2001-10-04 21:48:55 +04:00
*/
# include "disk-rep.h"
# include "pool.h"
2001-10-08 13:45:16 +04:00
# include "xlate.h"
# include "log.h"
2001-12-13 03:07:29 +03:00
# include "vgcache.h"
2001-10-04 21:48:55 +04:00
2001-11-14 13:01:52 +03:00
# include <sys/types.h>
# include <sys/stat.h>
# include <fcntl.h>
2001-10-05 19:48:05 +04:00
# define fail do {stack; return 0;} while(0)
2001-10-04 21:48:55 +04:00
# define xx16(v) disk->v = xlate16(disk->v)
# define xx32(v) disk->v = xlate32(disk->v)
# define xx64(v) disk->v = xlate64(disk->v)
/*
* Functions to perform the endian conversion
* between disk and core . The same code works
* both ways of course .
*/
2001-10-31 20:59:52 +03:00
static void _xlate_pvd ( struct pv_disk * disk )
2001-10-04 21:48:55 +04:00
{
2001-12-13 03:07:29 +03:00
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 ) ;
xx32 ( 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 ) ;
2001-10-04 21:48:55 +04:00
xx32 ( pe_start ) ;
}
2001-10-31 20:59:52 +03:00
static void _xlate_lvd ( struct lv_disk * disk )
2001-10-04 21:48:55 +04:00
{
2001-12-13 03:07:29 +03:00
xx32 ( lv_access ) ;
xx32 ( lv_status ) ;
xx32 ( lv_open ) ;
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 ) ;
xx16 ( dummy ) ;
xx32 ( lv_allocated_le ) ;
xx32 ( lv_stripes ) ;
xx32 ( lv_stripesize ) ;
xx32 ( lv_badblock ) ;
xx32 ( lv_allocation ) ;
xx32 ( lv_io_timeout ) ;
xx32 ( lv_read_ahead ) ;
2001-10-04 21:48:55 +04:00
}
2001-10-31 20:59:52 +03:00
static void _xlate_vgd ( struct vg_disk * disk )
2001-10-04 21:48:55 +04:00
{
2001-12-13 03:07:29 +03:00
xx32 ( vg_number ) ;
xx32 ( vg_access ) ;
xx32 ( vg_status ) ;
xx32 ( lv_max ) ;
xx32 ( lv_cur ) ;
xx32 ( lv_open ) ;
xx32 ( pv_max ) ;
xx32 ( pv_cur ) ;
xx32 ( pv_act ) ;
xx32 ( dummy ) ;
xx32 ( vgda ) ;
xx32 ( pe_size ) ;
xx32 ( pe_total ) ;
xx32 ( pe_allocated ) ;
xx32 ( pvg_total ) ;
2001-10-04 21:48:55 +04:00
}
2001-10-05 19:20:40 +04:00
static void _xlate_extents ( struct pe_disk * extents , int count )
2001-10-04 21:48:55 +04:00
{
2001-10-05 19:20:40 +04:00
int i ;
for ( i = 0 ; i < count ; i + + ) {
extents [ i ] . lv_num = xlate16 ( extents [ i ] . lv_num ) ;
extents [ i ] . le_num = xlate16 ( extents [ i ] . le_num ) ;
2001-10-04 21:48:55 +04:00
}
2001-10-05 19:20:40 +04:00
}
2001-10-04 21:48:55 +04:00
2001-10-10 13:36:29 +04:00
/*
* Handle both minor metadata formats .
*/
static int _munge_formats ( struct pv_disk * pvd )
{
uint32_t pe_start ;
switch ( pvd - > version ) {
case 1 :
2001-10-11 14:08:44 +04:00
pvd - > pe_start = ( ( pvd - > pe_on_disk . base +
pvd - > pe_on_disk . size ) / SECTOR_SIZE ) ;
2001-10-10 13:36:29 +04:00
break ;
case 2 :
pvd - > version = 1 ;
pe_start = pvd - > pe_start * SECTOR_SIZE ;
pvd - > pe_on_disk . size = pe_start - pvd - > pe_on_disk . base ;
break ;
default :
return 0 ;
}
return 1 ;
}
2001-10-31 20:59:52 +03:00
static int _read_pvd ( struct disk_list * data )
2001-10-05 19:20:40 +04:00
{
2001-10-31 20:59:52 +03:00
struct pv_disk * pvd = & data - > pvd ;
2001-10-05 19:48:05 +04:00
if ( dev_read ( data - > dev , 0 , sizeof ( * pvd ) , pvd ) ! = sizeof ( * pvd ) )
fail ;
2001-10-31 20:59:52 +03:00
_xlate_pvd ( pvd ) ;
2001-10-10 13:36:29 +04:00
2001-10-10 16:45:20 +04:00
return 1 ;
2001-10-04 21:48:55 +04:00
}
2001-10-31 20:59:52 +03:00
static int _read_lvd ( struct device * dev , ulong pos , struct lv_disk * disk )
2001-10-04 21:48:55 +04:00
{
2001-10-05 19:48:05 +04:00
if ( dev_read ( dev , pos , sizeof ( * disk ) , disk ) ! = sizeof ( * disk ) )
fail ;
2001-10-31 20:59:52 +03:00
_xlate_lvd ( disk ) ;
2001-10-05 19:20:40 +04:00
2001-10-04 21:48:55 +04:00
return 1 ;
}
2001-10-31 20:59:52 +03:00
static int _read_vgd ( struct disk_list * data )
2001-10-04 21:48:55 +04:00
{
2001-10-31 20:59:52 +03:00
struct vg_disk * vgd = & data - > vgd ;
unsigned long pos = data - > pvd . vg_on_disk . base ;
2001-10-05 19:48:05 +04:00
if ( dev_read ( data - > dev , pos , sizeof ( * vgd ) , vgd ) ! = sizeof ( * vgd ) )
fail ;
2001-10-31 20:59:52 +03:00
_xlate_vgd ( vgd ) ;
2001-10-04 21:48:55 +04:00
return 1 ;
}
2001-10-05 19:20:40 +04:00
static int _read_uuids ( struct disk_list * data )
2001-10-04 21:48:55 +04:00
{
int num_read = 0 ;
struct uuid_list * ul ;
char buffer [ NAME_LEN ] ;
2001-10-31 20:59:52 +03:00
ulong pos = data - > pvd . pv_uuidlist_on_disk . base ;
ulong end = pos + data - > pvd . pv_uuidlist_on_disk . size ;
2001-10-04 21:48:55 +04:00
2001-12-13 03:07:29 +03:00
while ( pos < end & & num_read < data - > vgd . pv_cur ) {
2001-10-05 19:20:40 +04:00
if ( dev_read ( data - > dev , pos , sizeof ( buffer ) , buffer ) ! =
2001-10-05 19:48:05 +04:00
sizeof ( buffer ) )
fail ;
2001-10-04 21:48:55 +04:00
2001-10-05 19:48:05 +04:00
if ( ! ( ul = pool_alloc ( data - > mem , sizeof ( * ul ) ) ) )
fail ;
2001-10-04 21:48:55 +04:00
memcpy ( ul - > uuid , buffer , NAME_LEN ) ;
2001-11-28 02:12:06 +03:00
ul - > uuid [ NAME_LEN - 1 ] = ' \0 ' ;
2001-10-04 21:48:55 +04:00
2001-10-31 15:47:01 +03:00
list_add ( & data - > uuids , & ul - > list ) ;
2001-10-04 21:48:55 +04:00
pos + = NAME_LEN ;
num_read + + ;
}
2001-10-05 19:20:40 +04:00
2001-10-04 21:48:55 +04:00
return 1 ;
}
2001-11-13 21:52:52 +03:00
static inline int _check_lvd ( struct lv_disk * lvd )
2001-10-11 14:08:44 +04:00
{
2001-11-13 21:52:52 +03:00
return ! ( lvd - > lv_name [ 0 ] = = ' \0 ' ) ;
2001-10-11 14:08:44 +04:00
}
2001-10-05 19:20:40 +04:00
static int _read_lvs ( struct disk_list * data )
2001-10-04 21:48:55 +04:00
{
2001-11-13 21:52:52 +03:00
int i , read = 0 ;
2001-10-04 21:48:55 +04:00
unsigned long pos ;
2001-10-08 13:45:16 +04:00
struct lvd_list * ll ;
2001-11-13 21:52:52 +03:00
struct vg_disk * vgd = & data - > vgd ;
2001-10-04 21:48:55 +04:00
2001-12-13 03:07:29 +03:00
for ( i = 0 ; ( i < vgd - > lv_max ) & & ( read < vgd - > lv_cur ) ; i + + ) {
2001-10-31 20:59:52 +03:00
pos = data - > pvd . lv_on_disk . base + ( i * sizeof ( struct lv_disk ) ) ;
2001-10-08 13:45:16 +04:00
ll = pool_alloc ( data - > mem , sizeof ( * ll ) ) ;
2001-10-04 21:48:55 +04:00
2001-10-05 19:48:05 +04:00
if ( ! ll )
fail ;
2001-10-04 21:48:55 +04:00
2001-10-31 20:59:52 +03:00
if ( ! _read_lvd ( data - > dev , pos , & ll - > lvd ) )
2001-10-05 19:48:05 +04:00
fail ;
2001-10-04 21:48:55 +04:00
2001-10-31 20:59:52 +03:00
if ( ! _check_lvd ( & ll - > lvd ) )
2001-11-13 21:52:52 +03:00
continue ;
2001-10-11 14:08:44 +04:00
2001-11-13 21:52:52 +03:00
read + + ;
2001-10-31 20:59:52 +03:00
list_add ( & data - > lvds , & ll - > list ) ;
2001-10-04 21:48:55 +04:00
}
return 1 ;
}
2001-10-05 19:20:40 +04:00
static int _read_extents ( struct disk_list * data )
2001-10-04 21:48:55 +04:00
{
2001-10-31 20:59:52 +03:00
size_t len = sizeof ( struct pe_disk ) * data - > pvd . pe_total ;
2001-10-04 21:48:55 +04:00
struct pe_disk * extents = pool_alloc ( data - > mem , len ) ;
2001-10-31 20:59:52 +03:00
unsigned long pos = data - > pvd . pe_on_disk . base ;
2001-10-04 21:48:55 +04:00
2001-10-05 19:48:05 +04:00
if ( ! extents )
fail ;
if ( dev_read ( data - > dev , pos , len , extents ) ! = len )
fail ;
2001-10-04 21:48:55 +04:00
2001-10-31 20:59:52 +03:00
_xlate_extents ( extents , data - > pvd . pe_total ) ;
2001-10-04 21:48:55 +04:00
data - > extents = extents ;
2001-10-05 19:20:40 +04:00
2001-10-04 21:48:55 +04:00
return 1 ;
}
2001-11-14 13:01:52 +03:00
static struct disk_list * __read_disk ( struct device * dev , struct pool * mem ,
const char * vg_name )
2001-10-04 21:48:55 +04:00
{
2001-10-05 19:20:40 +04:00
struct disk_list * data = pool_alloc ( mem , sizeof ( * data ) ) ;
2001-10-25 18:04:18 +04:00
const char * name = dev_name ( dev ) ;
2001-11-12 19:00:52 +03:00
if ( ! data ) {
stack ;
return NULL ;
}
2001-10-05 19:20:40 +04:00
data - > dev = dev ;
data - > mem = mem ;
2001-10-31 15:47:01 +03:00
list_init ( & data - > uuids ) ;
2001-10-31 20:59:52 +03:00
list_init ( & data - > lvds ) ;
2001-10-05 19:20:40 +04:00
2001-10-31 20:59:52 +03:00
if ( ! _read_pvd ( data ) ) {
2001-10-25 18:04:18 +04:00
log_debug ( " Failed to read PV data from %s " , name ) ;
2001-10-05 19:20:40 +04:00
goto bad ;
2001-10-04 21:48:55 +04:00
}
2001-10-31 20:59:52 +03:00
if ( data - > pvd . id [ 0 ] ! = ' H ' | | data - > pvd . id [ 1 ] ! = ' M ' ) {
2001-10-10 20:36:32 +04:00
log_very_verbose ( " %s does not have a valid PV identifier " ,
2001-10-25 18:04:18 +04:00
name ) ;
2001-10-05 19:20:40 +04:00
goto bad ;
}
2001-10-31 20:59:52 +03:00
if ( ! _munge_formats ( & data - > pvd ) ) {
2001-10-11 14:08:44 +04:00
log_very_verbose ( " Unknown metadata version %d found on %s " ,
2001-10-31 20:59:52 +03:00
data - > pvd . version , name ) ;
2001-10-10 16:45:20 +04:00
goto bad ;
}
2001-12-13 03:07:29 +03:00
/* Update VG cache with whatever we found */
vgcache_add ( data - > pvd . vg_name , dev ) ;
2001-10-10 16:28:10 +04:00
/*
* is it an orphan ?
*/
2001-10-31 20:59:52 +03:00
if ( data - > pvd . vg_name = = ' \0 ' ) {
2001-10-25 18:04:18 +04:00
log_very_verbose ( " %s is not a member of any VG " , name ) ;
2001-10-10 16:42:03 +04:00
return data ;
2001-10-10 16:45:20 +04:00
}
2001-10-10 16:28:10 +04:00
2001-10-31 20:59:52 +03:00
if ( vg_name & & strcmp ( vg_name , data - > pvd . vg_name ) ) {
2001-10-10 16:45:20 +04:00
log_very_verbose ( " %s is not a member of the VG %s " ,
2001-10-25 18:04:18 +04:00
name , vg_name ) ;
2001-10-05 19:20:40 +04:00
goto bad ;
2001-10-04 21:48:55 +04:00
}
2001-10-31 20:59:52 +03:00
if ( ! _read_vgd ( data ) ) {
2001-10-25 18:04:18 +04:00
log_error ( " Failed to read VG data from PV (%s) " , name ) ;
2001-10-05 19:20:40 +04:00
goto bad ;
2001-10-04 21:48:55 +04:00
}
2001-10-05 19:20:40 +04:00
if ( ! _read_uuids ( data ) ) {
2001-10-25 18:04:18 +04:00
log_error ( " Failed to read PV uuid list from %s " , name ) ;
2001-10-05 19:20:40 +04:00
goto bad ;
2001-10-04 21:48:55 +04:00
}
2001-10-05 19:20:40 +04:00
if ( ! _read_lvs ( data ) ) {
2001-10-25 18:04:18 +04:00
log_error ( " Failed to read LV's from %s " , name ) ;
2001-10-05 19:20:40 +04:00
goto bad ;
2001-10-04 21:48:55 +04:00
}
2001-10-05 19:20:40 +04:00
if ( ! _read_extents ( data ) ) {
2001-10-25 18:04:18 +04:00
log_error ( " Failed to read extents from %s " , name ) ;
2001-10-05 19:20:40 +04:00
goto bad ;
2001-10-04 21:48:55 +04:00
}
2001-10-31 20:59:52 +03:00
log_very_verbose ( " Found %s in VG %s " , name , data - > pvd . vg_name ) ;
2001-10-29 16:52:23 +03:00
2001-10-05 19:20:40 +04:00
return data ;
2001-12-13 03:07:29 +03:00
bad :
2001-10-08 13:45:16 +04:00
pool_free ( data - > mem , data ) ;
2001-10-05 19:20:40 +04:00
return NULL ;
2001-10-04 21:48:55 +04:00
}
2001-11-14 13:01:52 +03:00
struct disk_list * read_disk ( struct device * dev , struct pool * mem ,
const char * vg_name )
{
struct disk_list * r ;
if ( ! dev_open ( dev , O_RDONLY ) ) {
stack ;
return NULL ;
}
r = __read_disk ( dev , mem , vg_name ) ;
if ( ! dev_close ( dev ) )
stack ;
return r ;
}
2001-10-04 21:48:55 +04:00
/*
2001-12-13 03:07:29 +03:00
* Build a list of pv_d ' s structures , allocated from mem .
* We keep track of the first object allocated form the pool
* so we can free off all the memory if something goes wrong .
2001-10-04 21:48:55 +04:00
*/
2001-10-08 13:45:16 +04:00
int read_pvs_in_vg ( const char * vg_name , struct dev_filter * filter ,
2001-10-31 15:47:01 +03:00
struct pool * mem , struct list * head )
2001-10-04 21:48:55 +04:00
{
2001-12-13 18:08:58 +03:00
struct dev_iter * iter ;
2001-10-04 21:48:55 +04:00
struct device * dev ;
struct disk_list * data = NULL ;
2001-12-13 03:07:29 +03:00
struct list * pvdh , * pvdh2 ;
/* Fast path if we already saw this VG and cached the list of PVs */
if ( ( pvdh = vgcache_find ( vg_name ) ) ) {
list_iterate ( pvdh2 , pvdh ) {
dev = list_item ( pvdh2 , struct pvdev_list ) - > dev ;
if ( ( data = read_disk ( dev , mem , vg_name ) ) )
list_add ( head , & data - > list ) ;
}
/* Did we find the whole VG? */
if ( ! vg_name | | ! * vg_name | |
( data & & * data - > pvd . vg_name & &
list_size ( head ) = = data - > vgd . pv_cur ) )
return 1 ;
2001-12-13 18:08:58 +03:00
/* Something changed. Remove the hints. */
2001-12-13 03:07:29 +03:00
list_init ( head ) ;
vgcache_del ( vg_name ) ;
}
2001-12-13 18:08:58 +03:00
if ( ! ( iter = dev_iter_create ( filter ) ) ) {
log_error ( " read_pvs_in_vg: dev_iter_create failed " ) ;
return 0 ;
}
2001-12-13 03:07:29 +03:00
/* Otherwise do a complete scan */
2001-10-04 21:48:55 +04:00
for ( dev = dev_iter_get ( iter ) ; dev ; dev = dev_iter_get ( iter ) ) {
2001-12-13 03:07:29 +03:00
if ( ( data = read_disk ( dev , mem , vg_name ) ) ) {
2001-10-31 15:47:01 +03:00
list_add ( head , & data - > list ) ;
2001-12-13 03:07:29 +03:00
}
2001-10-05 19:20:40 +04:00
}
2001-10-08 13:45:16 +04:00
dev_iter_destroy ( iter ) ;
2001-10-16 20:25:28 +04:00
if ( list_empty ( head ) )
return 0 ;
2001-10-05 19:20:40 +04:00
return 1 ;
}
2001-10-31 20:59:52 +03:00
static int _write_vgd ( struct disk_list * data )
2001-10-05 19:20:40 +04:00
{
2001-10-31 20:59:52 +03:00
struct vg_disk * vgd = & data - > vgd ;
unsigned long pos = data - > pvd . vg_on_disk . base ;
2001-10-05 19:20:40 +04:00
2001-10-31 20:59:52 +03:00
_xlate_vgd ( vgd ) ;
2001-10-05 19:48:05 +04:00
if ( dev_write ( data - > dev , pos , sizeof ( * vgd ) , vgd ) ! = sizeof ( * vgd ) )
fail ;
2001-10-31 20:59:52 +03:00
_xlate_vgd ( vgd ) ;
2001-10-05 19:20:40 +04:00
return 1 ;
}
static int _write_uuids ( struct disk_list * data )
{
struct uuid_list * ul ;
2001-10-31 15:47:01 +03:00
struct list * uh ;
2001-10-31 20:59:52 +03:00
ulong pos = data - > pvd . pv_uuidlist_on_disk . base ;
ulong end = pos + data - > pvd . pv_uuidlist_on_disk . size ;
2001-10-05 19:20:40 +04:00
2001-10-31 15:47:01 +03:00
list_iterate ( uh , & data - > uuids ) {
2001-10-05 19:20:40 +04:00
if ( pos > = end ) {
2001-10-10 16:45:20 +04:00
log_error ( " Too many uuids to fit on %s " ,
2001-10-25 18:04:18 +04:00
dev_name ( data - > dev ) ) ;
2001-10-05 19:20:40 +04:00
return 0 ;
}
2001-10-31 15:47:01 +03:00
ul = list_item ( uh , struct uuid_list ) ;
2001-10-10 17:24:16 +04:00
if ( dev_write ( data - > dev , pos , NAME_LEN , ul - > uuid ) ! = NAME_LEN )
2001-10-05 19:48:05 +04:00
fail ;
2001-10-05 19:20:40 +04:00
pos + = NAME_LEN ;
}
2001-10-04 21:48:55 +04:00
2001-10-05 19:20:40 +04:00
return 1 ;
}
2001-10-04 21:48:55 +04:00
2001-10-31 20:59:52 +03:00
static int _write_lvd ( struct device * dev , ulong pos , struct lv_disk * disk )
2001-10-05 19:20:40 +04:00
{
2001-10-31 20:59:52 +03:00
_xlate_lvd ( disk ) ;
2001-10-05 19:48:05 +04:00
if ( dev_write ( dev , pos , sizeof ( * disk ) , disk ) ! = sizeof ( * disk ) )
fail ;
2001-10-31 20:59:52 +03:00
_xlate_lvd ( disk ) ;
2001-10-05 19:20:40 +04:00
2001-10-04 21:48:55 +04:00
return 1 ;
2001-10-05 19:20:40 +04:00
}
2001-10-04 21:48:55 +04:00
2001-10-05 19:20:40 +04:00
static int _write_lvs ( struct disk_list * data )
{
2001-10-31 15:47:01 +03:00
struct list * lvh ;
2001-10-08 13:45:16 +04:00
unsigned long pos ;
2001-10-05 19:20:40 +04:00
2001-11-10 01:01:04 +03:00
pos = data - > pvd . lv_on_disk . base ;
2001-11-13 21:52:52 +03:00
if ( ! dev_zero ( data - > dev , pos , data - > pvd . lv_on_disk . size ) ) {
2001-11-14 16:52:38 +03:00
log_error ( " Couldn't zero lv area on device '%s' " ,
2001-12-13 03:07:29 +03:00
dev_name ( data - > dev ) ) ;
2001-11-13 21:52:52 +03:00
return 0 ;
}
2001-10-31 20:59:52 +03:00
list_iterate ( lvh , & data - > lvds ) {
2001-10-31 15:47:01 +03:00
struct lvd_list * ll = list_item ( lvh , struct lvd_list ) ;
2001-10-05 19:20:40 +04:00
2001-10-31 20:59:52 +03:00
if ( ! _write_lvd ( data - > dev , pos , & ll - > lvd ) )
2001-10-05 19:48:05 +04:00
fail ;
2001-10-05 19:20:40 +04:00
pos + = sizeof ( struct lv_disk ) ;
}
return 1 ;
}
static int _write_extents ( struct disk_list * data )
{
2001-10-31 20:59:52 +03:00
size_t len = sizeof ( struct pe_disk ) * data - > pvd . pe_total ;
2001-10-05 19:20:40 +04:00
struct pe_disk * extents = data - > extents ;
2001-10-31 20:59:52 +03:00
unsigned long pos = data - > pvd . pe_on_disk . base ;
2001-10-05 19:20:40 +04:00
2001-10-31 20:59:52 +03:00
_xlate_extents ( extents , data - > pvd . pe_total ) ;
2001-10-11 14:08:44 +04:00
if ( dev_write ( data - > dev , pos , len , extents ) ! = len )
2001-10-05 19:48:05 +04:00
fail ;
2001-10-31 20:59:52 +03:00
_xlate_extents ( extents , data - > pvd . pe_total ) ;
2001-10-05 19:20:40 +04:00
return 1 ;
}
2001-10-31 20:59:52 +03:00
static int _write_pvd ( struct disk_list * data )
2001-10-05 19:20:40 +04:00
{
2001-10-31 20:59:52 +03:00
struct pv_disk * disk = & data - > pvd ;
2001-10-05 19:20:40 +04:00
2001-10-31 20:59:52 +03:00
_xlate_pvd ( disk ) ;
2001-10-10 16:45:20 +04:00
if ( dev_write ( data - > dev , 0 , sizeof ( * disk ) , disk ) ! = sizeof ( * disk ) )
2001-10-05 19:48:05 +04:00
fail ;
2001-10-31 20:59:52 +03:00
_xlate_pvd ( disk ) ;
2001-10-05 19:20:40 +04:00
return 1 ;
}
2001-11-14 13:01:52 +03:00
/*
* assumes the device has been opened .
*/
static int __write_all_pvd ( struct disk_list * data )
2001-10-05 19:20:40 +04:00
{
2001-10-25 18:04:18 +04:00
const char * pv_name = dev_name ( data - > dev ) ;
2001-10-05 19:20:40 +04:00
2001-10-31 20:59:52 +03:00
if ( ! _write_pvd ( data ) ) {
2001-10-10 16:45:20 +04:00
log_error ( " Failed to write PV structure onto %s " , pv_name ) ;
2001-10-05 19:20:40 +04:00
return 0 ;
}
2001-12-13 18:08:58 +03:00
vgcache_add ( data - > pvd . vg_name , data - > dev ) ;
2001-10-10 14:05:29 +04:00
/*
* Stop here for orphan pv ' s .
*/
2001-10-31 20:59:52 +03:00
if ( data - > pvd . vg_name [ 0 ] = = ' \0 ' )
2001-10-10 14:05:29 +04:00
return 1 ;
2001-10-31 20:59:52 +03:00
if ( ! _write_vgd ( data ) ) {
2001-10-10 16:45:20 +04:00
log_error ( " Failed to write VG data to %s " , pv_name ) ;
2001-10-05 19:20:40 +04:00
return 0 ;
}
if ( ! _write_uuids ( data ) ) {
2001-10-10 16:45:20 +04:00
log_error ( " Failed to write PV uuid list to %s " , pv_name ) ;
2001-10-05 19:20:40 +04:00
return 0 ;
}
if ( ! _write_lvs ( data ) ) {
2001-10-10 16:45:20 +04:00
log_error ( " Failed to write LV's to %s " , pv_name ) ;
2001-10-05 19:20:40 +04:00
return 0 ;
}
if ( ! _write_extents ( data ) ) {
2001-10-10 16:45:20 +04:00
log_error ( " Failed to write extents to %s " , pv_name ) ;
2001-10-05 19:20:40 +04:00
return 0 ;
}
return 1 ;
}
2001-11-14 13:01:52 +03:00
/*
* opens the device and hands to the above fn .
*/
static int _write_all_pvd ( struct disk_list * data )
{
int r ;
if ( ! dev_open ( data - > dev , O_WRONLY ) ) {
stack ;
return 0 ;
}
r = __write_all_pvd ( data ) ;
if ( ! dev_close ( data - > dev ) )
stack ;
return r ;
}
2001-10-05 19:20:40 +04:00
/*
* Writes all the given pv ' s to disk . Does very
* little sanity checking , so make sure correct
2001-10-05 19:48:05 +04:00
* data is passed to here .
*/
2001-11-14 13:01:52 +03:00
int write_disks ( struct list * pvs )
2001-10-05 19:20:40 +04:00
{
2001-10-31 15:47:01 +03:00
struct list * pvh ;
2001-10-05 19:20:40 +04:00
struct disk_list * dl ;
2001-10-31 15:47:01 +03:00
list_iterate ( pvh , pvs ) {
dl = list_item ( pvh , struct disk_list ) ;
2001-10-31 20:59:52 +03:00
if ( ! ( _write_all_pvd ( dl ) ) )
2001-10-05 19:48:05 +04:00
fail ;
2001-10-25 18:04:18 +04:00
log_debug ( " Successfully wrote data to %s " , dev_name ( dl - > dev ) ) ;
2001-10-05 19:20:40 +04:00
}
return 1 ;
2001-10-04 21:48:55 +04:00
}