2001-12-11 15:16:58 +03:00
/*
2008-01-30 17:00:02 +03:00
* Copyright ( C ) 2001 - 2004 Sistina Software , Inc . All rights reserved .
2009-02-23 01:11:58 +03:00
* Copyright ( C ) 2004 - 2009 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
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
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"
2009-02-23 01:11:58 +03:00
# include "lvm-version.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 ;
2011-04-08 18:21:34 +04:00
__attribute__ ( ( format ( printf , 3 , 0 ) ) )
2002-11-18 17:04:08 +03:00
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) \
2008-01-30 17:00:02 +03:00
do { \
2005-10-23 04:14:48 +04:00
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 - - ) {
2009-12-16 22:22:11 +03:00
log_error ( INTERNAL_ERROR " problem 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
2013-01-08 02:30:29 +04:00
log_debug_metadata ( " Doubling metadata output buffer to % " PRIu32 ,
f - > data . buf . size * 2 ) ;
2005-10-23 04:14:48 +04:00
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 ) & &
2008-01-30 16:19:47 +03:00
( ! _extend_buffer ( f ) ) )
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
2011-04-08 18:21:34 +04:00
__attribute__ ( ( format ( printf , 3 , 0 ) ) )
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 ' ;
2007-04-27 23:26:57 +04:00
fputs ( white_space , f - > data . fp ) ;
2002-11-18 17:04:08 +03:00
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 ) ;
2007-04-27 23:26:57 +04:00
fputs ( comment , f - > data . fp ) ;
2001-12-11 15:16:58 +03:00
}
2002-11-18 17:04:08 +03:00
fputc ( ' \n ' , f - > data . fp ) ;
return 1 ;
}
2011-04-08 18:21:34 +04:00
__attribute__ ( ( format ( printf , 3 , 0 ) ) )
2006-05-11 21:58:58 +04:00
static int _out_with_comment_raw ( struct formatter * f ,
2010-07-09 19:34:40 +04:00
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 ) ) {
2008-01-30 16:19:47 +03:00
if ( ! _extend_buffer ( f ) )
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 " ,
2006-11-10 21:24:11 +03:00
" Petabytes " ,
" Exabytes " ,
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 ;
2006-08-21 16:54:53 +04:00
return dm_snprintf ( buffer , s , " # %g %s " , d , _units [ i ] ) > 0 ;
2001-12-11 15:16:58 +03:00
}
2009-11-03 14:00:46 +03:00
/* increment indention level */
void out_inc_indent ( struct formatter * f )
{
_inc_indent ( f ) ;
}
/* decrement indention level */
void out_dec_indent ( struct formatter * f )
{
_dec_indent ( f ) ;
}
/* insert new line */
int out_newline ( struct formatter * f )
{
return f - > nl ( f ) ;
}
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
}
2007-11-09 19:51:54 +03:00
/*
2010-01-07 17:45:28 +03:00
* The normal output function with comment
2007-11-09 19:51:54 +03:00
*/
2010-01-07 17:45:28 +03:00
int out_text_with_comment ( struct formatter * f , const char * comment , const char * fmt , . . . )
2007-11-09 19:51:54 +03:00
{
va_list ap ;
int r ;
_out_with_comment ( f , comment , fmt , ap ) ;
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
}
2009-10-16 21:41:49 +04:00
static int _out_line ( const char * line , void * _f ) {
struct formatter * f = ( struct formatter * ) _f ;
return out_text ( f , " %s " , line ) ;
}
2011-08-30 18:55:15 +04:00
int out_config_node ( struct formatter * f , const struct dm_config_node * cn )
2009-10-16 21:41:49 +04:00
{
2011-08-30 18:55:15 +04:00
return dm_config_write_node ( cn , _out_line , f ) ;
2009-10-16 21:41:49 +04: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
{
2008-03-12 19:03:22 +03:00
char * buf ;
2001-12-20 14:52:54 +03:00
time_t t ;
t = time ( NULL ) ;
2007-11-04 22:16:34 +03:00
outf ( f , " # Generated by LVM2 version %s: %s " , LVM_VERSION , ctime ( & t ) ) ;
2004-05-05 01:25:57 +04:00
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
2011-08-30 18:55:15 +04:00
if ( ! ( buf = alloca ( dm_escaped_len ( desc ) ) ) ) {
2008-03-12 19:03:22 +03:00
log_error ( " temporary stack allocation for description "
" string failed " ) ;
return 0 ;
}
2011-08-30 18:55:15 +04:00
outf ( f , " description = \" %s \" " , dm_escape_double_quotes ( buf , 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 ;
}
2009-11-25 01:55:55 +03:00
static int _print_flag_config ( struct formatter * f , uint64_t status , int type )
2008-07-10 15:30:57 +04:00
{
char buffer [ 4096 ] ;
if ( ! print_flags ( status , type | STATUS_FLAG , buffer , sizeof ( buffer ) ) )
return_0 ;
outf ( f , " status = %s " , buffer ) ;
if ( ! print_flags ( status , type , buffer , sizeof ( buffer ) ) )
return_0 ;
outf ( f , " flags = %s " , buffer ) ;
return 1 ;
}
2010-11-29 15:19:58 +03:00
2014-01-31 01:09:28 +04:00
static int _out_tags ( struct formatter * f , struct dm_list * tagsl )
2010-11-29 15:19:58 +03:00
{
char * tag_buffer ;
2014-01-31 01:09:28 +04:00
if ( ! dm_list_empty ( tagsl ) ) {
if ( ! ( tag_buffer = alloc_printed_tags ( tagsl ) ) )
2010-11-29 15:19:58 +03:00
return_0 ;
if ( ! out_text ( f , " tags = %s " , tag_buffer ) ) {
dm_free ( tag_buffer ) ;
return_0 ;
}
dm_free ( tag_buffer ) ;
}
return 1 ;
}
2001-12-11 15:16:58 +03:00
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
2008-01-30 16:19:47 +03:00
if ( ! id_write_format ( & vg - > id , buffer , sizeof ( buffer ) ) )
return_0 ;
2001-12-11 15:16:58 +03:00
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
2012-02-23 17:11:07 +04:00
if ( vg - > fid & & vg - > fid - > fmt )
outf ( f , " format = \" %s \" # informational " , vg - > fid - > fmt - > name ) ;
2008-07-10 15:30:57 +04:00
if ( ! _print_flag_config ( f , vg - > status , VG_FLAGS ) )
2008-01-30 16:19:47 +03:00
return_0 ;
2004-03-08 20:19:15 +03:00
2010-11-29 15:19:58 +03:00
if ( ! _out_tags ( f , & vg - > tags ) )
return_0 ;
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
2010-01-07 17:40:46 +03:00
outsize ( f , ( uint64_t ) vg - > extent_size , " extent_size = %u " ,
vg - > extent_size ) ;
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 ) ) ;
}
2013-06-25 14:32:09 +04:00
if ( vg - > profile )
outf ( f , " profile = \" %s \" " , vg - > profile - > name ) ;
2010-06-29 00:37:10 +04:00
outf ( f , " metadata_copies = %u " , vg - > mda_copies ) ;
2004-05-19 02:12:53 +04:00
2001-12-11 15:16:58 +03:00
return 1 ;
}
/*
* Get the pv % d name from the formatters hash
* table .
*/
2009-05-19 13:48:32 +04:00
static const char * _get_pv_name_from_uuid ( struct formatter * f , char * uuid )
{
return dm_hash_lookup ( f - > pv_names , uuid ) ;
}
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
{
2010-07-09 19:34:40 +04:00
char uuid [ 64 ] __attribute__ ( ( aligned ( 8 ) ) ) ;
2009-05-19 13:48:32 +04:00
if ( ! pv | | ! id_write_format ( & pv - > id , uuid , sizeof ( uuid ) ) )
return_NULL ;
return _get_pv_name_from_uuid ( f , uuid ) ;
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 ;
2014-03-26 17:00:51 +04:00
char buffer [ PATH_MAX * 2 ] ;
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 ) ;
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( pvl , & vg - > pvs ) {
2005-06-01 20:51:55 +04:00
pv = pvl - > pv ;
2001-12-20 19:05:14 +03:00
2009-05-19 13:48:32 +04:00
if ( ! id_write_format ( & pv - > id , buffer , sizeof ( buffer ) ) )
return_0 ;
if ( ! ( name = _get_pv_name_from_uuid ( f , buffer ) ) )
2008-01-30 16:19:47 +03:00
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 , " %s { " , name ) ;
2001-12-11 15:16:58 +03:00
_inc_indent ( f ) ;
2004-05-05 01:25:57 +04:00
outf ( f , " id = \" %s \" " , buffer ) ;
2008-03-12 19:03:22 +03:00
2014-03-26 17:00:51 +04:00
if ( strlen ( pv_dev_name ( pv ) ) > = PATH_MAX ) {
log_error ( " pv device name size is out of bounds. " ) ;
2008-03-12 19:03:22 +03:00
return 0 ;
}
2010-01-07 17:40:46 +03:00
outhint ( f , " device = \" %s \" " ,
2014-03-26 17:00:51 +04:00
dm_escape_double_quotes ( buffer , pv_dev_name ( pv ) ) ) ;
2005-06-07 15:00:07 +04:00
outnl ( f ) ;
2001-12-11 15:16:58 +03:00
2008-07-10 15:30:57 +04:00
if ( ! _print_flag_config ( f , pv - > status , PV_FLAGS ) )
2008-01-30 16:19:47 +03:00
return_0 ;
2004-03-08 20:19:15 +03:00
2010-11-29 15:19:58 +03:00
if ( ! _out_tags ( f , & pv - > tags ) )
return_0 ;
2004-03-08 20:19:15 +03:00
2010-01-07 17:40:46 +03:00
outsize ( f , pv - > size , " dev_size = % " PRIu64 , pv - > size ) ;
2006-10-08 03:17:17 +04:00
2004-05-05 01:25:57 +04:00
outf ( f , " pe_start = % " PRIu64 , pv - > pe_start ) ;
2010-01-07 17:40:46 +03:00
outsize ( f , vg - > extent_size * ( uint64_t ) pv - > pe_count ,
" pe_count = %u " , pv - > pe_count ) ;
2001-12-11 15:16:58 +03:00
2013-05-28 14:37:22 +04:00
if ( pv - > ba_start & & pv - > ba_size ) {
outf ( f , " ba_start = % " PRIu64 , pv - > ba_start ) ;
outsize ( f , pv - > ba_size , " ba_size = % " PRIu64 , pv - > ba_size ) ;
2013-02-15 14:02:53 +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
}
_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-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 ) ;
2010-01-07 17:40:46 +03:00
outsize ( f , ( uint64_t ) seg - > len * vg - > extent_size ,
" extent_count = %u " , seg - > len ) ;
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
2010-11-29 15:19:58 +03:00
if ( ! _out_tags ( f , & seg - > tags ) )
return_0 ;
2004-03-08 20:19:15 +03:00
2004-05-11 20:01:58 +04:00
if ( seg - > segtype - > ops - > text_export & &
2008-01-30 16:19:47 +03:00
! seg - > segtype - > ops - > text_export ( seg , f ) )
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 :
2008-01-30 16:19:47 +03:00
if ( ! ( name = _get_pv_name ( f , seg_pv ( seg , s ) ) ) )
return_0 ;
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 :
2011-08-03 02:07:20 +04:00
if ( ! ( seg - > status & RAID ) ) {
outf ( f , " \" %s \" , %u%s " ,
seg_lv ( seg , s ) - > name ,
seg_le ( seg , s ) ,
( s = = seg - > area_count - 1 ) ? " " : " , " ) ;
continue ;
}
/* RAID devices are laid-out in metadata/data pairs */
if ( ! ( seg_lv ( seg , s ) - > status & RAID_IMAGE ) | |
! ( seg_metalv ( seg , s ) - > status & RAID_META ) ) {
log_error ( " RAID segment has non-RAID areas " ) ;
return 0 ;
}
outf ( f , " \" %s \" , \" %s \" %s " ,
seg_metalv ( seg , s ) - > name , seg_lv ( seg , s ) - > name ,
2004-05-05 01:25:57 +04:00
( s = = seg - > area_count - 1 ) ? " " : " , " ) ;
2011-08-03 02:07:20 +04:00
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 ;
2012-01-19 19:31:45 +04:00
struct tm * local_tm ;
time_t ts ;
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 */
2008-01-30 16:19:47 +03:00
if ( ! id_write_format ( & lv - > lvid . id [ 1 ] , buffer , sizeof ( buffer ) ) )
return_0 ;
2005-06-01 20:51:55 +04:00
outf ( f , " id = \" %s \" " , buffer ) ;
2008-07-10 15:30:57 +04:00
if ( ! _print_flag_config ( f , lv - > status , LV_FLAGS ) )
2008-01-30 16:19:47 +03:00
return_0 ;
2005-06-01 20:51:55 +04:00
2010-11-29 15:19:58 +03:00
if ( ! _out_tags ( f , & lv - > tags ) )
return_0 ;
2005-06-01 20:51:55 +04:00
2012-01-19 19:31:45 +04:00
if ( lv - > timestamp ) {
ts = ( time_t ) lv - > timestamp ;
strncpy ( buffer , " # " , sizeof ( buffer ) ) ;
if ( ! ( local_tm = localtime ( & ts ) ) | |
! strftime ( buffer + 2 , sizeof ( buffer ) - 2 ,
" %Y-%m-%d %T %z " , local_tm ) )
buffer [ 0 ] = 0 ;
outf ( f , " creation_host = \" %s \" " , lv - > hostname ) ;
outfc ( f , buffer , " creation_time = % " PRIu64 ,
lv - > timestamp ) ;
}
2005-06-01 20:51:55 +04:00
if ( lv - > alloc ! = ALLOC_INHERIT )
outf ( f , " allocation_policy = \" %s \" " ,
get_alloc_string ( lv - > alloc ) ) ;
2013-06-25 14:32:09 +04:00
if ( lv - > profile )
outf ( f , " profile = \" %s \" " , lv - > profile - > name ) ;
2007-11-09 19:51:54 +03:00
switch ( lv - > read_ahead ) {
case DM_READ_AHEAD_NONE :
2010-01-07 17:45:28 +03:00
outfc ( f , " # None " , " read_ahead = -1 " ) ;
2007-11-09 19:51:54 +03:00
break ;
case DM_READ_AHEAD_AUTO :
/* No output - use default */
break ;
default :
2005-06-01 20:51:55 +04:00
outf ( f , " read_ahead = %u " , lv - > read_ahead ) ;
2007-11-09 19:51:54 +03:00
}
2005-06-01 20:51:55 +04:00
if ( lv - > major > = 0 )
outf ( f , " major = %d " , lv - > major ) ;
if ( lv - > minor > = 0 )
outf ( f , " minor = %d " , lv - > minor ) ;
2008-11-04 01:14:30 +03:00
outf ( f , " segment_count = %u " , dm_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 ;
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( seg , & lv - > segments ) {
2008-01-30 16:19:47 +03:00
if ( ! _print_segment ( f , lv - > vg , seg_count + + , seg ) )
return_0 ;
2005-06-01 20:51:55 +04:00
}
_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 .
*/
2008-11-04 01:14:30 +03:00
if ( dm_list_empty ( & vg - > lvs ) )
2002-02-13 16:29:16 +03:00
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
*/
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( lvl , & vg - > lvs ) {
2009-05-14 01:27:43 +04:00
if ( ! ( lv_is_visible ( lvl - > lv ) ) )
2005-06-01 20:51:55 +04:00
continue ;
2008-01-30 16:19:47 +03:00
if ( ! _print_lv ( f , lvl - > lv ) )
return_0 ;
2005-06-01 20:51:55 +04:00
}
2002-02-21 18:26:44 +03:00
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( lvl , & vg - > lvs ) {
2009-05-14 01:27:43 +04:00
if ( ( lv_is_visible ( lvl - > lv ) ) )
2005-06-01 20:51:55 +04:00
continue ;
2008-01-30 16:19:47 +03:00
if ( ! _print_lv ( f , lvl - > lv ) )
return_0 ;
2001-12-11 15:16:58 +03:00
}
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 ;
2009-05-19 13:48:32 +04:00
char buffer [ 32 ] , * uuid , * name ;
2001-12-11 15:16:58 +03:00
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
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( pvl , & vg - > pvs ) {
2005-06-01 20:51:55 +04:00
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-08-21 16:54:53 +04:00
if ( dm_snprintf ( buffer , sizeof ( buffer ) , " pv%d " , count + + ) < 0 )
2006-05-17 00:53:13 +04:00
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
2009-05-19 13:48:32 +04:00
if ( ! ( uuid = dm_pool_zalloc ( f - > mem , 64 ) ) | |
! id_write_format ( & pv - > id , uuid , 64 ) )
return_0 ;
if ( ! dm_hash_insert ( f - > pv_names , uuid , name ) )
2006-05-17 00:53:13 +04:00
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 ;
2008-01-30 16:19:47 +03:00
if ( ! _build_pv_names ( f , vg ) )
goto_out ;
2001-12-11 15:16:58 +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 ;
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 :
2012-01-26 02:35:36 +04:00
if ( f - > mem ) {
2005-10-17 03:03:59 +04:00
dm_pool_destroy ( f - > mem ) ;
2012-01-26 02:35:36 +04:00
f - > mem = NULL ;
}
2001-12-11 15:16:58 +03:00
2012-01-26 02:35:36 +04:00
if ( f - > pv_names ) {
2005-10-17 03:03:59 +04:00
dm_hash_destroy ( f - > pv_names ) ;
2012-01-26 02:35:36 +04:00
f - > pv_names = NULL ;
}
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 ( ) ;
2010-10-01 01:06:50 +04:00
if ( ! ( f = dm_zalloc ( sizeof ( * f ) ) ) )
2008-01-30 16:19:47 +03:00
return_0 ;
2002-11-18 17:04:08 +03:00
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 */
2011-09-01 14:25:22 +04:00
size_t text_vg_export_raw ( struct volume_group * vg , const char * desc , char * * buf )
2002-11-18 17:04:08 +03:00
{
struct formatter * f ;
2011-09-01 14:25:22 +04:00
size_t r = 0 ;
2002-11-18 17:04:08 +03:00
_init ( ) ;
2010-10-01 01:06:50 +04:00
if ( ! ( f = dm_zalloc ( sizeof ( * f ) ) ) )
2008-01-30 16:19:47 +03:00
return_0 ;
2002-11-18 17:04:08 +03:00
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 ) ) {
2005-10-17 03:03:59 +04:00
dm_free ( f - > data . buf . start ) ;
2008-01-30 16:19:47 +03:00
goto_out ;
2002-11-18 17:04:08 +03:00
}
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 ;
}
2011-09-01 14:25:22 +04:00
size_t export_vg_to_buffer ( struct volume_group * vg , char * * buf )
2008-04-02 02:40:13 +04:00
{
return text_vg_export_raw ( vg , " " , buf ) ;
}
2013-03-17 19:25:12 +04:00
struct dm_config_tree * export_vg_to_config_tree ( struct volume_group * vg )
{
char * buf = NULL ;
struct dm_config_tree * vg_cft ;
if ( ! export_vg_to_buffer ( vg , & buf ) ) {
log_error ( " Could not format metadata for VG %s. " , vg - > name ) ;
return_NULL ;
}
if ( ! ( vg_cft = dm_config_from_string ( buf ) ) ) {
log_error ( " Error parsing metadata for VG %s. " , vg - > name ) ;
dm_free ( buf ) ;
return_NULL ;
}
dm_free ( buf ) ;
return vg_cft ;
}
2004-05-05 01:25:57 +04:00
# undef outf
2005-06-07 15:00:07 +04:00
# undef outnl