2001-12-11 15:16:58 +03:00
/*
2004-03-30 23:35:44 +04:00
* Copyright ( C ) 2001 - 2004 Sistina Software , Inc . All rights reserved .
* Copyright ( C ) 2004 Red Hat , Inc . All rights reserved .
2001-12-11 15:16:58 +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
* of the GNU General Public License v .2 .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software Foundation ,
* Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
2001-12-11 15:16:58 +03:00
*/
2002-11-18 17:04:08 +03:00
# include "lib.h"
2001-12-11 15:18:56 +03:00
# include "import-export.h"
2001-12-11 15:16:58 +03:00
# include "metadata.h"
2002-07-11 18:21:49 +04:00
# include "display.h"
2002-11-18 17:04:08 +03:00
# include "lvm-string.h"
2004-09-16 22:40:56 +04:00
# include "segtype.h"
2004-05-05 01:25:57 +04:00
# include "text_export.h"
2001-12-11 15:16:58 +03:00
2001-12-20 14:52:54 +03:00
# include <stdarg.h>
# include <time.h>
2002-11-18 17:04:08 +03:00
# include <sys/utsname.h>
2001-12-11 15:16:58 +03:00
2002-11-18 17:04:08 +03:00
struct formatter ;
typedef int ( * out_with_comment_fn ) ( struct formatter * f , const char * comment ,
const char * fmt , va_list ap ) ;
2005-06-07 15:00:07 +04:00
typedef int ( * nl_fn ) ( struct formatter * f ) ;
2005-10-23 04:14:48 +04:00
/*
* Macro for formatted output .
* out_with_comment_fn returns - 1 if data didn ' t fit and buffer was expanded .
* Then argument list is reset and out_with_comment_fn is called again .
*/
# define _out_with_comment(f, buffer, fmt, ap) \
do { \
va_start ( ap , fmt ) ; \
r = f - > out_with_comment ( f , buffer , fmt , ap ) ; \
va_end ( ap ) ; \
} while ( r = = - 1 )
2002-11-18 17:04:08 +03:00
/*
* The first half of this file deals with
* exporting the vg , ie . writing it to a file .
*/
2001-12-11 15:16:58 +03:00
struct formatter {
2005-10-17 03:03:59 +04:00
struct dm_pool * mem ; /* pv names allocated from here */
struct dm_hash_table * pv_names ; /* dev_name -> pv_name (eg, pv1) */
2001-12-11 15:16:58 +03:00
2002-11-18 17:04:08 +03:00
union {
FILE * fp ; /* where we're writing to */
struct {
2005-06-07 15:00:07 +04:00
char * start ;
2002-11-18 17:04:08 +03:00
uint32_t size ;
uint32_t used ;
} buf ;
} data ;
out_with_comment_fn out_with_comment ;
nl_fn nl ;
2001-12-20 19:05:14 +03:00
2002-11-18 17:04:08 +03:00
int indent ; /* current level of indentation */
2001-12-20 19:05:14 +03:00
int error ;
2002-11-18 17:04:08 +03:00
int header ; /* 1 => comments at start; 0 => end */
2001-12-11 15:16:58 +03:00
} ;
2002-11-18 17:04:08 +03:00
static struct utsname _utsname ;
static void _init ( void )
{
static int _initialised = 0 ;
if ( _initialised )
return ;
if ( uname ( & _utsname ) ) {
log_error ( " uname failed: %s " , strerror ( errno ) ) ;
memset ( & _utsname , 0 , sizeof ( _utsname ) ) ;
}
_initialised = 1 ;
}
2001-12-20 19:05:14 +03:00
/*
* Formatting functions .
*/
2001-12-11 15:16:58 +03:00
# define MAX_INDENT 5
static void _inc_indent ( struct formatter * f )
{
if ( + + f - > indent > MAX_INDENT )
f - > indent = MAX_INDENT ;
}
static void _dec_indent ( struct formatter * f )
{
2001-12-20 19:05:14 +03:00
if ( ! f - > indent - - ) {
2002-01-28 00:30:47 +03:00
log_error ( " Internal error tracking indentation " ) ;
2001-12-11 15:16:58 +03:00
f - > indent = 0 ;
}
}
/*
* Newline function for prettier layout .
*/
2005-06-07 15:00:07 +04:00
static int _nl_file ( struct formatter * f )
2001-12-11 15:16:58 +03:00
{
2002-11-18 17:04:08 +03:00
fprintf ( f - > data . fp , " \n " ) ;
2005-06-07 15:00:07 +04:00
return 1 ;
2002-11-18 17:04:08 +03:00
}
2005-10-23 04:14:48 +04:00
static int _extend_buffer ( struct formatter * f )
2002-11-18 17:04:08 +03:00
{
2005-06-07 15:00:07 +04:00
char * newbuf ;
2002-11-18 17:04:08 +03:00
2005-10-23 04:14:48 +04:00
log_debug ( " Doubling metadata output buffer to % " PRIu32 ,
f - > data . buf . size * 2 ) ;
if ( ! ( newbuf = dm_realloc ( f - > data . buf . start ,
f - > data . buf . size * 2 ) ) ) {
log_error ( " Buffer reallocation failed. " ) ;
return 0 ;
}
f - > data . buf . start = newbuf ;
f - > data . buf . size * = 2 ;
return 1 ;
}
static int _nl_raw ( struct formatter * f )
{
/* If metadata doesn't fit, extend buffer */
if ( ( f - > data . buf . used + 2 > f - > data . buf . size ) & &
( ! _extend_buffer ( f ) ) ) {
stack ;
return 0 ;
2005-06-07 15:00:07 +04:00
}
* ( f - > data . buf . start + f - > data . buf . used ) = ' \n ' ;
2002-11-18 17:04:08 +03:00
f - > data . buf . used + = 1 ;
2005-06-07 15:00:07 +04:00
* ( f - > data . buf . start + f - > data . buf . used ) = ' \0 ' ;
return 1 ;
2001-12-11 15:16:58 +03:00
}
# define COMMENT_TAB 6
2002-11-18 17:04:08 +03:00
static int _out_with_comment_file ( struct formatter * f , const char * comment ,
const char * fmt , va_list ap )
2001-12-11 15:16:58 +03:00
{
int i ;
char white_space [ MAX_INDENT + 1 ] ;
2002-11-18 17:04:08 +03:00
if ( ferror ( f - > data . fp ) )
return 0 ;
2001-12-20 19:05:14 +03:00
2001-12-11 15:16:58 +03:00
for ( i = 0 ; i < f - > indent ; i + + )
white_space [ i ] = ' \t ' ;
white_space [ i ] = ' \0 ' ;
2002-11-18 17:04:08 +03:00
fprintf ( f - > data . fp , white_space ) ;
i = vfprintf ( f - > data . fp , fmt , ap ) ;
2001-12-11 15:16:58 +03:00
if ( comment ) {
/*
* line comments up if possible .
*/
i + = 8 * f - > indent ;
i / = 8 ;
i + + ;
do
2002-11-18 17:04:08 +03:00
fputc ( ' \t ' , f - > data . fp ) ;
2001-12-11 15:16:58 +03:00
while ( + + i < COMMENT_TAB ) ;
2002-11-18 17:04:08 +03:00
fprintf ( f - > data . fp , comment ) ;
2001-12-11 15:16:58 +03:00
}
2002-11-18 17:04:08 +03:00
fputc ( ' \n ' , f - > data . fp ) ;
return 1 ;
}
2006-05-11 21:58:58 +04:00
static int _out_with_comment_raw ( struct formatter * f ,
const char * comment __attribute ( ( unused ) ) ,
2002-11-18 17:04:08 +03:00
const char * fmt , va_list ap )
{
int n ;
2005-06-07 15:00:07 +04:00
n = vsnprintf ( f - > data . buf . start + f - > data . buf . used ,
f - > data . buf . size - f - > data . buf . used , fmt , ap ) ;
2002-11-18 17:04:08 +03:00
2005-10-23 04:14:48 +04:00
/* If metadata doesn't fit, extend buffer */
2005-06-07 15:00:07 +04:00
if ( n < 0 | | ( n + f - > data . buf . used + 2 > f - > data . buf . size ) ) {
2005-10-23 04:14:48 +04:00
if ( ! _extend_buffer ( f ) ) {
2005-06-07 15:00:07 +04:00
stack ;
return 0 ;
}
2005-10-23 04:14:48 +04:00
return - 1 ; /* Retry */
2005-06-07 15:00:07 +04:00
}
2002-11-18 17:04:08 +03:00
f - > data . buf . used + = n ;
2005-06-07 15:00:07 +04:00
outnl ( f ) ;
2002-11-18 17:04:08 +03:00
return 1 ;
2001-12-11 15:16:58 +03:00
}
/*
* Formats a string , converting a size specified
* in 512 - byte sectors to a more human readable
* form ( eg , megabytes ) . We may want to lift this
* for other code to use .
*/
static int _sectors_to_units ( uint64_t sectors , char * buffer , size_t s )
{
2002-12-20 02:25:55 +03:00
static const char * _units [ ] = {
2001-12-11 15:16:58 +03:00
" Kilobytes " ,
" Megabytes " ,
" Gigabytes " ,
2002-11-18 17:04:08 +03:00
" Terabytes " ,
2001-12-11 15:16:58 +03:00
NULL
2002-04-24 22:20:51 +04:00
} ;
2001-12-11 15:16:58 +03:00
int i ;
double d = ( double ) sectors ;
/* to convert to K */
d / = 2.0 ;
2002-04-24 22:20:51 +04:00
for ( i = 0 ; ( d > 1024.0 ) & & _units [ i ] ; i + + )
2001-12-11 15:16:58 +03:00
d / = 1024.0 ;
2001-12-31 22:09:51 +03:00
return lvm_snprintf ( buffer , s , " # %g %s " , d , _units [ i ] ) > 0 ;
2001-12-11 15:16:58 +03:00
}
/*
* Appends a comment giving a size in more easily
* readable form ( eg , 4 M instead of 8096 ) .
*/
2004-05-05 01:25:57 +04:00
int out_size ( struct formatter * f , uint64_t size , const char * fmt , . . . )
2001-12-11 15:16:58 +03:00
{
char buffer [ 64 ] ;
va_list ap ;
2002-11-18 17:04:08 +03:00
int r ;
2001-12-11 15:16:58 +03:00
2002-11-18 17:04:08 +03:00
if ( ! _sectors_to_units ( size , buffer , sizeof ( buffer ) ) )
return 0 ;
2001-12-11 15:16:58 +03:00
2005-10-23 04:14:48 +04:00
_out_with_comment ( f , buffer , fmt , ap ) ;
2002-11-18 17:04:08 +03:00
return r ;
2001-12-11 15:16:58 +03:00
}
/*
* Appends a comment indicating that the line is
* only a hint .
*/
2004-05-05 01:25:57 +04:00
int out_hint ( struct formatter * f , const char * fmt , . . . )
2001-12-11 15:16:58 +03:00
{
va_list ap ;
2002-11-18 17:04:08 +03:00
int r ;
2001-12-11 15:16:58 +03:00
2005-10-23 04:14:48 +04:00
_out_with_comment ( f , " # Hint only " , fmt , ap ) ;
2002-11-18 17:04:08 +03:00
return r ;
2001-12-11 15:16:58 +03:00
}
/*
* The normal output function .
*/
2004-05-05 01:25:57 +04:00
int out_text ( struct formatter * f , const char * fmt , . . . )
2001-12-11 15:16:58 +03:00
{
va_list ap ;
2002-11-18 17:04:08 +03:00
int r ;
2001-12-11 15:16:58 +03:00
2005-10-23 04:14:48 +04:00
_out_with_comment ( f , NULL , fmt , ap ) ;
2002-11-18 17:04:08 +03:00
return r ;
2001-12-11 15:16:58 +03:00
}
2002-02-08 14:13:47 +03:00
static int _print_header ( struct formatter * f ,
2006-05-11 21:58:58 +04:00
const char * desc )
2001-12-11 15:16:58 +03:00
{
2001-12-20 14:52:54 +03:00
time_t t ;
t = time ( NULL ) ;
2004-05-05 01:25:57 +04:00
outf ( f , " # Generated by LVM2: %s " , ctime ( & t ) ) ;
outf ( f , CONTENTS_FIELD " = \" " CONTENTS_VALUE " \" " ) ;
outf ( f , FORMAT_VERSION_FIELD " = %d " , FORMAT_VERSION_VALUE ) ;
2005-06-07 15:00:07 +04:00
outnl ( f ) ;
2002-02-08 14:13:47 +03:00
2004-05-05 01:25:57 +04:00
outf ( f , " description = \" %s \" " , desc ) ;
2005-06-07 15:00:07 +04:00
outnl ( f ) ;
2004-05-05 01:25:57 +04:00
outf ( f , " creation_host = \" %s \" \t # %s %s %s %s %s " , _utsname . nodename ,
_utsname . sysname , _utsname . nodename , _utsname . release ,
_utsname . version , _utsname . machine ) ;
outf ( f , " creation_time = %lu \t # %s " , t , ctime ( & t ) ) ;
2002-02-08 14:13:47 +03:00
2001-12-11 15:16:58 +03:00
return 1 ;
}
static int _print_vg ( struct formatter * f , struct volume_group * vg )
{
2004-03-08 20:19:15 +03:00
char buffer [ 4096 ] ;
2001-12-11 15:16:58 +03:00
2001-12-20 14:52:54 +03:00
if ( ! id_write_format ( & vg - > id , buffer , sizeof ( buffer ) ) ) {
2001-12-11 15:16:58 +03:00
stack ;
return 0 ;
}
2004-05-05 01:25:57 +04:00
outf ( f , " id = \" %s \" " , buffer ) ;
2001-12-11 15:16:58 +03:00
2004-05-05 01:25:57 +04:00
outf ( f , " seqno = %u " , vg - > seqno ) ;
2004-03-08 20:19:15 +03:00
2001-12-20 14:52:54 +03:00
if ( ! print_flags ( vg - > status , VG_FLAGS , buffer , sizeof ( buffer ) ) ) {
2001-12-11 15:16:58 +03:00
stack ;
return 0 ;
}
2004-05-05 01:25:57 +04:00
outf ( f , " status = %s " , buffer ) ;
2004-03-08 20:19:15 +03:00
if ( ! list_empty ( & vg - > tags ) ) {
if ( ! print_tags ( & vg - > tags , buffer , sizeof ( buffer ) ) ) {
stack ;
return 0 ;
}
2004-05-05 01:25:57 +04:00
outf ( f , " tags = %s " , buffer ) ;
2004-03-08 20:19:15 +03:00
}
2002-01-29 20:23:33 +03:00
if ( vg - > system_id & & * vg - > system_id )
2004-05-05 01:25:57 +04:00
outf ( f , " system_id = \" %s \" " , vg - > system_id ) ;
2004-03-08 20:19:15 +03:00
2004-05-05 01:25:57 +04:00
if ( ! out_size ( f , ( uint64_t ) vg - > extent_size , " extent_size = %u " ,
vg - > extent_size ) ) {
2002-11-18 17:04:08 +03:00
stack ;
return 0 ;
}
2004-05-05 01:25:57 +04:00
outf ( f , " max_lv = %u " , vg - > max_lv ) ;
outf ( f , " max_pv = %u " , vg - > max_pv ) ;
2001-12-11 15:16:58 +03:00
2004-05-19 02:12:53 +04:00
/* Default policy is NORMAL; INHERIT is meaningless */
if ( vg - > alloc ! = ALLOC_NORMAL & & vg - > alloc ! = ALLOC_INHERIT ) {
2005-06-07 15:00:07 +04:00
outnl ( f ) ;
2004-05-19 02:12:53 +04:00
outf ( f , " allocation_policy = \" %s \" " ,
get_alloc_string ( vg - > alloc ) ) ;
}
2001-12-11 15:16:58 +03:00
return 1 ;
}
/*
* Get the pv % d name from the formatters hash
* table .
*/
2006-04-19 19:33:07 +04:00
static const char * _get_pv_name ( struct formatter * f , struct physical_volume * pv )
2001-12-11 15:16:58 +03:00
{
2002-02-08 14:13:47 +03:00
return ( pv ) ? ( const char * )
2005-10-17 03:03:59 +04:00
dm_hash_lookup ( f - > pv_names , dev_name ( pv - > dev ) ) : " Missing " ;
2001-12-11 15:16:58 +03:00
}
static int _print_pvs ( struct formatter * f , struct volume_group * vg )
{
2005-06-01 20:51:55 +04:00
struct pv_list * pvl ;
2001-12-11 15:16:58 +03:00
struct physical_volume * pv ;
2004-03-08 20:19:15 +03:00
char buffer [ 4096 ] ;
2001-12-11 15:16:58 +03:00
const char * name ;
2004-05-05 01:25:57 +04:00
outf ( f , " physical_volumes { " ) ;
2001-12-11 15:16:58 +03:00
_inc_indent ( f ) ;
2005-06-01 20:51:55 +04:00
list_iterate_items ( pvl , & vg - > pvs ) {
pv = pvl - > pv ;
2001-12-20 19:05:14 +03:00
2001-12-11 15:16:58 +03:00
if ( ! ( name = _get_pv_name ( f , pv ) ) ) {
stack ;
return 0 ;
}
2005-06-07 15:00:07 +04:00
outnl ( f ) ;
2004-05-05 01:25:57 +04:00
outf ( f , " %s { " , name ) ;
2001-12-11 15:16:58 +03:00
_inc_indent ( f ) ;
2001-12-20 14:52:54 +03:00
if ( ! id_write_format ( & pv - > id , buffer , sizeof ( buffer ) ) ) {
2001-12-11 15:16:58 +03:00
stack ;
return 0 ;
}
2004-05-05 01:25:57 +04:00
outf ( f , " id = \" %s \" " , buffer ) ;
if ( ! out_hint ( f , " device = \" %s \" " , dev_name ( pv - > dev ) ) ) {
2002-11-18 17:04:08 +03:00
stack ;
return 0 ;
}
2005-06-07 15:00:07 +04:00
outnl ( f ) ;
2001-12-11 15:16:58 +03:00
2002-04-24 22:20:51 +04:00
if ( ! print_flags ( pv - > status , PV_FLAGS , buffer , sizeof ( buffer ) ) ) {
2001-12-11 15:16:58 +03:00
stack ;
return 0 ;
}
2004-05-05 01:25:57 +04:00
outf ( f , " status = %s " , buffer ) ;
2004-03-08 20:19:15 +03:00
if ( ! list_empty ( & pv - > tags ) ) {
if ( ! print_tags ( & pv - > tags , buffer , sizeof ( buffer ) ) ) {
stack ;
return 0 ;
}
2004-05-05 01:25:57 +04:00
outf ( f , " tags = %s " , buffer ) ;
2004-03-08 20:19:15 +03:00
}
2004-05-05 01:25:57 +04:00
outf ( f , " pe_start = % " PRIu64 , pv - > pe_start ) ;
if ( ! out_size ( f , vg - > extent_size * ( uint64_t ) pv - > pe_count ,
" pe_count = %u " , pv - > pe_count ) ) {
2002-11-18 17:04:08 +03:00
stack ;
return 0 ;
}
2001-12-11 15:16:58 +03:00
_dec_indent ( f ) ;
2004-05-05 01:25:57 +04:00
outf ( f , " } " ) ;
2001-12-11 15:16:58 +03:00
}
_dec_indent ( f ) ;
2004-05-05 01:25:57 +04:00
outf ( f , " } " ) ;
2001-12-11 15:16:58 +03:00
return 1 ;
}
static int _print_segment ( struct formatter * f , struct volume_group * vg ,
2002-11-18 17:04:08 +03:00
int count , struct lv_segment * seg )
2001-12-11 15:16:58 +03:00
{
2004-03-08 20:19:15 +03:00
char buffer [ 4096 ] ;
2001-12-11 15:16:58 +03:00
2004-05-05 01:25:57 +04:00
outf ( f , " segment%u { " , count ) ;
2001-12-11 15:16:58 +03:00
_inc_indent ( f ) ;
2004-05-05 01:25:57 +04:00
outf ( f , " start_extent = %u " , seg - > le ) ;
if ( ! out_size ( f , ( uint64_t ) seg - > len * vg - > extent_size ,
" extent_count = %u " , seg - > len ) ) {
2002-11-18 17:04:08 +03:00
stack ;
return 0 ;
}
2001-12-11 15:16:58 +03:00
2005-06-07 15:00:07 +04:00
outnl ( f ) ;
2004-05-05 01:25:57 +04:00
outf ( f , " type = \" %s \" " , seg - > segtype - > name ) ;
2001-12-11 15:16:58 +03:00
2004-03-08 20:19:15 +03:00
if ( ! list_empty ( & seg - > tags ) ) {
if ( ! print_tags ( & seg - > tags , buffer , sizeof ( buffer ) ) ) {
stack ;
return 0 ;
}
2004-05-05 01:25:57 +04:00
outf ( f , " tags = %s " , buffer ) ;
2004-03-08 20:19:15 +03:00
}
2004-05-11 20:01:58 +04:00
if ( seg - > segtype - > ops - > text_export & &
! seg - > segtype - > ops - > text_export ( seg , f ) ) {
2004-05-05 01:25:57 +04:00
stack ;
return 0 ;
}
2003-04-25 02:23:24 +04:00
2004-05-05 01:25:57 +04:00
_dec_indent ( f ) ;
outf ( f , " } " ) ;
2001-12-11 15:16:58 +03:00
2004-05-05 01:25:57 +04:00
return 1 ;
}
2003-05-06 16:02:36 +04:00
2004-05-05 01:25:57 +04:00
int out_areas ( struct formatter * f , const struct lv_segment * seg ,
const char * type )
{
const char * name ;
unsigned int s ;
2002-11-18 17:04:08 +03:00
2005-06-07 15:00:07 +04:00
outnl ( f ) ;
2003-04-25 02:23:24 +04:00
2004-05-05 01:25:57 +04:00
outf ( f , " %ss = [ " , type ) ;
_inc_indent ( f ) ;
2002-11-18 17:04:08 +03:00
2004-05-05 01:25:57 +04:00
for ( s = 0 ; s < seg - > area_count ; s + + ) {
2005-06-01 20:51:55 +04:00
switch ( seg_type ( seg , s ) ) {
2004-05-05 01:25:57 +04:00
case AREA_PV :
2005-06-01 20:51:55 +04:00
if ( ! ( name = _get_pv_name ( f , seg_pv ( seg , s ) ) ) ) {
2004-05-05 01:25:57 +04:00
stack ;
return 0 ;
2002-11-18 17:04:08 +03:00
}
2001-12-11 15:16:58 +03:00
2004-05-05 01:25:57 +04:00
outf ( f , " \" %s \" , %u%s " , name ,
2005-06-01 20:51:55 +04:00
seg_pe ( seg , s ) ,
2004-05-05 01:25:57 +04:00
( s = = seg - > area_count - 1 ) ? " " : " , " ) ;
break ;
case AREA_LV :
outf ( f , " \" %s \" , %u%s " ,
2005-06-01 20:51:55 +04:00
seg_lv ( seg , s ) - > name ,
seg_le ( seg , s ) ,
2004-05-05 01:25:57 +04:00
( s = = seg - > area_count - 1 ) ? " " : " , " ) ;
2005-06-14 21:54:48 +04:00
break ;
case AREA_UNASSIGNED :
return 0 ;
2004-05-05 01:25:57 +04:00
}
2001-12-11 15:16:58 +03:00
}
_dec_indent ( f ) ;
2004-05-05 01:25:57 +04:00
outf ( f , " ] " ) ;
2001-12-11 15:16:58 +03:00
return 1 ;
}
2005-06-01 20:51:55 +04:00
static int _print_lv ( struct formatter * f , struct logical_volume * lv )
2001-12-20 14:52:54 +03:00
{
2005-06-01 20:51:55 +04:00
struct lv_segment * seg ;
char buffer [ 4096 ] ;
int seg_count ;
2001-12-20 14:52:54 +03:00
2005-06-07 15:00:07 +04:00
outnl ( f ) ;
2005-06-01 20:51:55 +04:00
outf ( f , " %s { " , lv - > name ) ;
_inc_indent ( f ) ;
2001-12-20 14:52:54 +03:00
2005-06-01 20:51:55 +04:00
/* FIXME: Write full lvid */
if ( ! id_write_format ( & lv - > lvid . id [ 1 ] , buffer , sizeof ( buffer ) ) ) {
stack ;
return 0 ;
}
outf ( f , " id = \" %s \" " , buffer ) ;
if ( ! print_flags ( lv - > status , LV_FLAGS , buffer , sizeof ( buffer ) ) ) {
stack ;
return 0 ;
}
outf ( f , " status = %s " , buffer ) ;
if ( ! list_empty ( & lv - > tags ) ) {
if ( ! print_tags ( & lv - > tags , buffer , sizeof ( buffer ) ) ) {
stack ;
return 0 ;
}
outf ( f , " tags = %s " , buffer ) ;
}
if ( lv - > alloc ! = ALLOC_INHERIT )
outf ( f , " allocation_policy = \" %s \" " ,
get_alloc_string ( lv - > alloc ) ) ;
if ( lv - > read_ahead )
outf ( f , " read_ahead = %u " , lv - > read_ahead ) ;
if ( lv - > major > = 0 )
outf ( f , " major = %d " , lv - > major ) ;
if ( lv - > minor > = 0 )
outf ( f , " minor = %d " , lv - > minor ) ;
outf ( f , " segment_count = %u " , list_size ( & lv - > segments ) ) ;
2005-06-07 15:00:07 +04:00
outnl ( f ) ;
2005-06-01 20:51:55 +04:00
seg_count = 1 ;
list_iterate_items ( seg , & lv - > segments ) {
if ( ! _print_segment ( f , lv - > vg , seg_count + + , seg ) ) {
stack ;
return 0 ;
}
}
_dec_indent ( f ) ;
outf ( f , " } " ) ;
return 1 ;
2001-12-20 14:52:54 +03:00
}
2001-12-11 15:16:58 +03:00
static int _print_lvs ( struct formatter * f , struct volume_group * vg )
{
2005-06-01 20:51:55 +04:00
struct lv_list * lvl ;
2001-12-11 15:16:58 +03:00
2002-02-13 16:29:16 +03:00
/*
* Don ' t bother with an lv section if there are no lvs .
*/
if ( list_empty ( & vg - > lvs ) )
return 1 ;
2004-05-05 01:25:57 +04:00
outf ( f , " logical_volumes { " ) ;
2001-12-11 15:16:58 +03:00
_inc_indent ( f ) ;
2005-06-01 20:51:55 +04:00
/*
* Write visible LVs first
*/
list_iterate_items ( lvl , & vg - > lvs ) {
if ( ! ( lvl - > lv - > status & VISIBLE_LV ) )
continue ;
if ( ! _print_lv ( f , lvl - > lv ) ) {
2002-02-21 18:26:44 +03:00
stack ;
return 0 ;
}
2005-06-01 20:51:55 +04:00
}
2002-02-21 18:26:44 +03:00
2005-06-01 20:51:55 +04:00
list_iterate_items ( lvl , & vg - > lvs ) {
if ( ( lvl - > lv - > status & VISIBLE_LV ) )
continue ;
if ( ! _print_lv ( f , lvl - > lv ) ) {
2001-12-11 15:16:58 +03:00
stack ;
return 0 ;
}
}
2002-02-13 16:29:16 +03:00
_dec_indent ( f ) ;
2004-05-05 01:25:57 +04:00
outf ( f , " } " ) ;
2002-02-13 16:29:16 +03:00
return 1 ;
}
2001-12-11 15:16:58 +03:00
/*
* In the text format we refer to pv ' s as ' pv1 ' ,
* ' pv2 ' etc . This function builds a hash table
* to enable a quick lookup from device - > name .
*/
2002-04-24 22:20:51 +04:00
static int _build_pv_names ( struct formatter * f , struct volume_group * vg )
2001-12-11 15:16:58 +03:00
{
int count = 0 ;
2005-06-01 20:51:55 +04:00
struct pv_list * pvl ;
2001-12-11 15:16:58 +03:00
struct physical_volume * pv ;
char buffer [ 32 ] , * name ;
2006-05-17 00:53:13 +04:00
if ( ! ( f - > mem = dm_pool_create ( " text pv_names " , 512 ) ) )
return_0 ;
2001-12-11 15:16:58 +03:00
2006-05-17 00:53:13 +04:00
if ( ! ( f - > pv_names = dm_hash_create ( 128 ) ) )
return_0 ;
2001-12-11 15:16:58 +03:00
2005-06-01 20:51:55 +04:00
list_iterate_items ( pvl , & vg - > pvs ) {
pv = pvl - > pv ;
2001-12-11 15:16:58 +03:00
2003-04-25 02:23:24 +04:00
/* FIXME But skip if there's already an LV called pv%d ! */
2006-05-17 00:53:13 +04:00
if ( lvm_snprintf ( buffer , sizeof ( buffer ) , " pv%d " , count + + ) < 0 )
return_0 ;
2001-12-11 15:16:58 +03:00
2006-05-17 00:53:13 +04:00
if ( ! ( name = dm_pool_strdup ( f - > mem , buffer ) ) )
return_0 ;
2001-12-11 15:16:58 +03:00
2006-05-17 00:53:13 +04:00
if ( ! dm_hash_insert ( f - > pv_names , dev_name ( pv - > dev ) , name ) )
return_0 ;
2001-12-11 15:16:58 +03:00
}
return 1 ;
}
2002-11-18 17:04:08 +03:00
static int _text_vg_export ( struct formatter * f ,
struct volume_group * vg , const char * desc )
2001-12-11 15:16:58 +03:00
{
int r = 0 ;
if ( ! _build_pv_names ( f , vg ) ) {
stack ;
goto out ;
}
2006-05-11 21:58:58 +04:00
if ( f - > header & & ! _print_header ( f , desc ) )
2006-05-17 00:53:13 +04:00
goto_out ;
2002-11-18 17:04:08 +03:00
2004-05-05 01:25:57 +04:00
if ( ! out_text ( f , " %s { " , vg - > name ) )
2006-05-17 00:53:13 +04:00
goto_out ;
2001-12-11 15:16:58 +03:00
2001-12-20 14:52:54 +03:00
_inc_indent ( f ) ;
2001-12-11 15:16:58 +03:00
if ( ! _print_vg ( f , vg ) )
2006-05-17 00:53:13 +04:00
goto_out ;
2001-12-11 15:16:58 +03:00
2005-06-07 15:00:07 +04:00
outnl ( f ) ;
2001-12-11 15:16:58 +03:00
if ( ! _print_pvs ( f , vg ) )
2006-05-17 00:53:13 +04:00
goto_out ;
2001-12-11 15:16:58 +03:00
2005-06-07 15:00:07 +04:00
outnl ( f ) ;
2001-12-11 15:16:58 +03:00
if ( ! _print_lvs ( f , vg ) )
2006-05-17 00:53:13 +04:00
goto_out ;
2001-12-11 15:16:58 +03:00
2002-11-18 17:04:08 +03:00
_dec_indent ( f ) ;
2004-05-05 01:25:57 +04:00
if ( ! out_text ( f , " } " ) )
2006-05-17 00:53:13 +04:00
goto_out ;
2002-02-13 16:29:16 +03:00
2006-05-11 21:58:58 +04:00
if ( ! f - > header & & ! _print_header ( f , desc ) )
2006-05-17 00:53:13 +04:00
goto_out ;
2001-12-11 15:16:58 +03:00
2002-11-18 17:04:08 +03:00
r = 1 ;
2001-12-11 15:16:58 +03:00
2002-04-24 22:20:51 +04:00
out :
2001-12-11 15:16:58 +03:00
if ( f - > mem )
2005-10-17 03:03:59 +04:00
dm_pool_destroy ( f - > mem ) ;
2001-12-11 15:16:58 +03:00
if ( f - > pv_names )
2005-10-17 03:03:59 +04:00
dm_hash_destroy ( f - > pv_names ) ;
2001-12-11 15:16:58 +03:00
2002-11-18 17:04:08 +03:00
return r ;
}
int text_vg_export_file ( struct volume_group * vg , const char * desc , FILE * fp )
{
struct formatter * f ;
int r ;
_init ( ) ;
2005-10-17 03:03:59 +04:00
if ( ! ( f = dm_malloc ( sizeof ( * f ) ) ) ) {
2002-11-18 17:04:08 +03:00
stack ;
return 0 ;
}
memset ( f , 0 , sizeof ( * f ) ) ;
f - > data . fp = fp ;
f - > indent = 0 ;
f - > header = 1 ;
f - > out_with_comment = & _out_with_comment_file ;
f - > nl = & _nl_file ;
r = _text_vg_export ( f , vg , desc ) ;
if ( r )
r = ! ferror ( f - > data . fp ) ;
2005-10-17 03:03:59 +04:00
dm_free ( f ) ;
2001-12-11 15:16:58 +03:00
return r ;
}
2002-11-18 17:04:08 +03:00
/* Returns amount of buffer used incl. terminating NUL */
2005-06-07 15:00:07 +04:00
int text_vg_export_raw ( struct volume_group * vg , const char * desc , char * * buf )
2002-11-18 17:04:08 +03:00
{
struct formatter * f ;
2005-06-07 15:00:07 +04:00
int r = 0 ;
2002-11-18 17:04:08 +03:00
_init ( ) ;
2005-10-17 03:03:59 +04:00
if ( ! ( f = dm_malloc ( sizeof ( * f ) ) ) ) {
2002-11-18 17:04:08 +03:00
stack ;
return 0 ;
}
memset ( f , 0 , sizeof ( * f ) ) ;
2005-06-07 15:00:07 +04:00
f - > data . buf . size = 65536 ; /* Initial metadata limit */
2005-10-17 03:03:59 +04:00
if ( ! ( f - > data . buf . start = dm_malloc ( f - > data . buf . size ) ) ) {
2005-06-07 15:00:07 +04:00
log_error ( " text_export buffer allocation failed " ) ;
goto out ;
}
2002-11-18 17:04:08 +03:00
f - > indent = 0 ;
f - > header = 0 ;
f - > out_with_comment = & _out_with_comment_raw ;
f - > nl = & _nl_raw ;
if ( ! _text_vg_export ( f , vg , desc ) ) {
stack ;
2005-10-17 03:03:59 +04:00
dm_free ( f - > data . buf . start ) ;
2002-11-18 17:04:08 +03:00
goto out ;
}
r = f - > data . buf . used + 1 ;
2005-06-07 15:00:07 +04:00
* buf = f - > data . buf . start ;
2002-11-18 17:04:08 +03:00
out :
2005-10-17 03:03:59 +04:00
dm_free ( f ) ;
2002-11-18 17:04:08 +03:00
return r ;
}
2004-05-05 01:25:57 +04:00
# undef outf
2005-06-07 15:00:07 +04:00
# undef outnl