2002-01-03 18:46:48 +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 .
2002-01-03 18:46:48 +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
2002-01-03 18:46:48 +03:00
*/
2002-01-11 02:21:07 +03:00
# include "tools.h"
2002-01-03 18:46:48 +03:00
static struct {
int enabled ;
char * dir ;
unsigned int keep_days ;
unsigned int keep_number ;
} _archive_params ;
2003-09-15 19:03:22 +04:00
static struct {
int enabled ;
char * dir ;
} _backup_params ;
2002-02-12 00:00:35 +03:00
int archive_init ( const char * dir , unsigned int keep_days , unsigned int keep_min )
2002-01-03 18:46:48 +03:00
{
2002-01-09 16:17:14 +03:00
_archive_params . dir = NULL ;
if ( ! * dir )
return 1 ;
if ( ! create_dir ( dir ) )
return 0 ;
2002-01-03 18:46:48 +03:00
if ( ! ( _archive_params . dir = dbg_strdup ( dir ) ) ) {
2002-01-09 16:17:14 +03:00
log_error ( " Couldn't copy archive directory name. " ) ;
2002-01-03 18:46:48 +03:00
return 0 ;
}
_archive_params . keep_days = keep_days ;
2002-01-07 14:12:11 +03:00
_archive_params . keep_number = keep_min ;
2002-01-03 18:46:48 +03:00
_archive_params . enabled = 1 ;
return 1 ;
}
void archive_exit ( void )
{
2002-01-09 16:17:14 +03:00
if ( _archive_params . dir )
dbg_free ( _archive_params . dir ) ;
2002-01-03 18:46:48 +03:00
memset ( & _archive_params , 0 , sizeof ( _archive_params ) ) ;
}
2002-01-07 12:05:31 +03:00
void archive_enable ( int flag )
2002-01-03 18:46:48 +03:00
{
2002-01-07 12:05:31 +03:00
_archive_params . enabled = flag ;
2002-01-03 18:46:48 +03:00
}
2002-02-08 14:13:47 +03:00
static char * _build_desc ( struct pool * mem , const char * line , int before )
{
size_t len = strlen ( line ) + 32 ;
char * buffer ;
if ( ! ( buffer = pool_zalloc ( mem , strlen ( line ) + 32 ) ) ) {
stack ;
return NULL ;
}
if ( snprintf ( buffer , len ,
" Created %s executing '%s' " ,
before ? " *before* " : " *after* " , line ) < 0 ) {
stack ;
return NULL ;
}
return buffer ;
}
2002-01-03 18:46:48 +03:00
static int __archive ( struct volume_group * vg )
{
2002-02-08 14:13:47 +03:00
char * desc ;
if ( ! ( desc = _build_desc ( vg - > cmd - > mem , vg - > cmd - > cmd_line , 1 ) ) ) {
stack ;
return 0 ;
}
2002-01-03 18:46:48 +03:00
2002-02-08 14:58:18 +03:00
return archive_vg ( vg , _archive_params . dir , desc ,
_archive_params . keep_days ,
_archive_params . keep_number ) ;
2002-01-03 18:46:48 +03:00
}
int archive ( struct volume_group * vg )
{
2002-01-09 16:17:14 +03:00
if ( ! _archive_params . enabled | | ! _archive_params . dir )
2002-01-03 18:46:48 +03:00
return 1 ;
if ( test_mode ( ) ) {
2002-11-18 17:04:08 +03:00
log_verbose ( " Test mode: Skipping archiving of volume group. " ) ;
2002-01-03 18:46:48 +03:00
return 1 ;
}
2002-01-30 18:04:48 +03:00
log_verbose ( " Archiving volume group \" %s \" metadata. " , vg - > name ) ;
2002-01-03 18:46:48 +03:00
if ( ! __archive ( vg ) ) {
2002-01-30 18:04:48 +03:00
log_error ( " Volume group \" %s \" metadata archive failed. " ,
2002-01-09 16:17:14 +03:00
vg - > name ) ;
2002-01-03 18:46:48 +03:00
return 0 ;
}
return 1 ;
}
2002-02-11 23:50:53 +03:00
int archive_display ( struct cmd_context * cmd , const char * vg_name )
2002-02-11 14:43:17 +03:00
{
2003-09-15 19:03:22 +04:00
int r1 , r2 ;
2002-02-11 14:43:17 +03:00
2003-09-15 19:03:22 +04:00
init_partial ( 1 ) ;
r1 = archive_list ( cmd , _archive_params . dir , vg_name ) ;
r2 = backup_list ( cmd , _backup_params . dir , vg_name ) ;
init_partial ( 0 ) ;
2002-01-03 18:46:48 +03:00
2003-09-15 19:03:22 +04:00
return r1 & & r2 ;
}
2002-01-03 18:46:48 +03:00
int backup_init ( const char * dir )
{
2002-01-09 16:17:14 +03:00
_backup_params . dir = NULL ;
if ( ! * dir )
return 1 ;
if ( ! create_dir ( dir ) )
return 0 ;
2002-01-03 18:46:48 +03:00
if ( ! ( _backup_params . dir = dbg_strdup ( dir ) ) ) {
2002-01-09 16:17:14 +03:00
log_error ( " Couldn't copy backup directory name. " ) ;
2002-01-03 18:46:48 +03:00
return 0 ;
}
return 1 ;
}
void backup_exit ( void )
{
2002-01-09 16:17:14 +03:00
if ( _backup_params . dir )
dbg_free ( _backup_params . dir ) ;
2002-01-07 14:12:11 +03:00
memset ( & _backup_params , 0 , sizeof ( _backup_params ) ) ;
2002-01-03 18:46:48 +03:00
}
2002-01-07 12:05:31 +03:00
void backup_enable ( int flag )
{
_backup_params . enabled = flag ;
}
2002-01-03 18:46:48 +03:00
static int __backup ( struct volume_group * vg )
{
char name [ PATH_MAX ] ;
2002-02-08 14:13:47 +03:00
char * desc ;
if ( ! ( desc = _build_desc ( vg - > cmd - > mem , vg - > cmd - > cmd_line , 0 ) ) ) {
stack ;
return 0 ;
}
2002-01-03 18:46:48 +03:00
if ( lvm_snprintf ( name , sizeof ( name ) , " %s/%s " ,
_backup_params . dir , vg - > name ) < 0 ) {
2002-01-09 16:17:14 +03:00
log_error ( " Failed to generate volume group metadata backup "
" filename. " ) ;
2002-01-03 18:46:48 +03:00
return 0 ;
}
2002-11-18 17:04:08 +03:00
return backup_to_file ( name , desc , vg ) ;
2002-01-03 18:46:48 +03:00
}
int backup ( struct volume_group * vg )
{
2002-01-09 16:17:14 +03:00
if ( ! _backup_params . enabled | | ! _backup_params . dir ) {
log_print ( " WARNING: This metadata update is NOT backed up " ) ;
2002-01-03 18:46:48 +03:00
return 1 ;
2002-01-09 16:17:14 +03:00
}
2002-01-03 18:46:48 +03:00
if ( test_mode ( ) ) {
2002-11-18 17:04:08 +03:00
log_verbose ( " Test mode: Skipping volume group backup. " ) ;
2002-01-03 18:46:48 +03:00
return 1 ;
}
if ( ! __backup ( vg ) ) {
2002-01-09 16:17:14 +03:00
log_error ( " Backup of volume group %s metadata failed. " ,
vg - > name ) ;
2002-01-03 18:46:48 +03:00
return 0 ;
}
return 1 ;
}
2002-01-09 17:07:49 +03:00
int backup_remove ( const char * vg_name )
{
char path [ PATH_MAX ] ;
if ( lvm_snprintf ( path , sizeof ( path ) , " %s/%s " ,
_backup_params . dir , vg_name ) < 0 ) {
log_err ( " Failed to generate backup filename (for removal). " ) ;
return 0 ;
}
/*
* Let this fail silently .
*/
unlink ( path ) ;
return 1 ;
}
2002-11-18 17:04:08 +03:00
struct volume_group * backup_read_vg ( struct cmd_context * cmd ,
const char * vg_name , const char * file )
2002-01-10 17:27:47 +03:00
{
2002-12-20 02:25:55 +03:00
struct volume_group * vg = NULL ;
2002-01-10 17:27:47 +03:00
struct format_instance * tf ;
2002-11-18 17:04:08 +03:00
struct metadata_area * mda ;
2002-04-24 22:20:51 +04:00
void * context ;
2002-01-10 17:27:47 +03:00
2002-11-18 17:04:08 +03:00
if ( ! ( context = create_text_context ( cmd , file ,
2002-04-24 22:20:51 +04:00
cmd - > cmd_line ) ) | |
2002-11-18 17:04:08 +03:00
! ( tf = cmd - > fmt_backup - > ops - > create_instance ( cmd - > fmt_backup , NULL ,
context ) ) ) {
2002-01-10 17:27:47 +03:00
log_error ( " Couldn't create text format object. " ) ;
2002-02-08 14:13:47 +03:00
return NULL ;
2002-01-10 17:27:47 +03:00
}
2003-10-16 00:02:46 +04:00
list_iterate_items ( mda , & tf - > metadata_areas ) {
2002-11-18 17:04:08 +03:00
if ( ! ( vg = mda - > ops - > vg_read ( tf , vg_name , mda ) ) )
stack ;
break ;
}
2002-01-10 17:27:47 +03:00
2002-04-24 22:20:51 +04:00
tf - > fmt - > ops - > destroy_instance ( tf ) ;
2002-01-11 02:21:07 +03:00
return vg ;
2002-01-10 17:27:47 +03:00
}
2002-11-18 17:04:08 +03:00
/* ORPHAN and VG locks held before calling this */
int backup_restore_vg ( struct cmd_context * cmd , struct volume_group * vg )
2002-01-10 17:27:47 +03:00
{
2003-10-16 00:02:46 +04:00
struct pv_list * pvl ;
2002-11-18 17:04:08 +03:00
struct physical_volume * pv ;
2003-07-05 02:34:56 +04:00
struct lvmcache_info * info ;
2002-01-10 17:27:47 +03:00
/*
2002-11-18 17:04:08 +03:00
* FIXME : Check that the PVs referenced in the backup are
* not members of other existing VGs .
2002-01-10 17:27:47 +03:00
*/
2002-11-18 17:04:08 +03:00
/* Attempt to write out using currently active format */
if ( ! ( vg - > fid = cmd - > fmt - > ops - > create_instance ( cmd - > fmt , vg - > name ,
NULL ) ) ) {
log_error ( " Failed to allocate format instance " ) ;
2002-01-10 17:27:47 +03:00
return 0 ;
}
2002-11-18 17:04:08 +03:00
/* Add any metadata areas on the PVs */
2003-10-16 00:02:46 +04:00
list_iterate_items ( pvl , & vg - > pvs ) {
pv = pvl - > pv ;
2002-11-18 17:04:08 +03:00
if ( ! ( info = info_from_pvid ( pv - > dev - > pvid ) ) ) {
log_error ( " PV %s missing from cache " ,
dev_name ( pv - > dev ) ) ;
return 0 ;
}
if ( cmd - > fmt ! = info - > fmt ) {
log_error ( " PV %s is a different format (%s) " ,
dev_name ( pv - > dev ) , info - > fmt - > name ) ;
return 0 ;
}
if ( ! vg - > fid - > fmt - > ops - >
2003-03-24 21:08:53 +03:00
pv_setup ( vg - > fid - > fmt , UINT64_C ( 0 ) , 0 , 0 , 0 ,
UINT64_C ( 0 ) , & vg - > fid - > metadata_areas , pv , vg ) ) {
2002-11-18 17:04:08 +03:00
log_error ( " Format-specific setup for %s failed " ,
dev_name ( pv - > dev ) ) ;
return 0 ;
}
2002-04-24 22:20:51 +04:00
}
2003-07-05 02:34:56 +04:00
if ( ! vg_write ( vg ) | | ! vg_commit ( vg ) ) {
2002-01-10 17:27:47 +03:00
stack ;
return 0 ;
}
return 1 ;
}
2002-11-18 17:04:08 +03:00
/* ORPHAN and VG locks held before calling this */
int backup_restore_from_file ( struct cmd_context * cmd , const char * vg_name ,
const char * file )
{
struct volume_group * vg ;
/*
* Read in the volume group from the text file .
*/
if ( ! ( vg = backup_read_vg ( cmd , vg_name , file ) ) ) {
stack ;
return 0 ;
}
return backup_restore_vg ( cmd , vg ) ;
}
2002-02-11 23:50:53 +03:00
int backup_restore ( struct cmd_context * cmd , const char * vg_name )
2002-01-10 17:27:47 +03:00
{
char path [ PATH_MAX ] ;
if ( lvm_snprintf ( path , sizeof ( path ) , " %s/%s " ,
_backup_params . dir , vg_name ) < 0 ) {
log_err ( " Failed to generate backup filename (for restore). " ) ;
return 0 ;
}
2002-02-11 23:50:53 +03:00
return backup_restore_from_file ( cmd , vg_name , path ) ;
2002-01-10 17:27:47 +03:00
}
2002-11-18 17:04:08 +03:00
int backup_to_file ( const char * file , const char * desc , struct volume_group * vg )
{
2002-12-20 02:25:55 +03:00
int r = 0 ;
2002-11-18 17:04:08 +03:00
struct format_instance * tf ;
struct metadata_area * mda ;
void * context ;
struct cmd_context * cmd ;
cmd = vg - > cmd ;
2004-06-19 22:55:29 +04:00
log_verbose ( " Creating volume group backup \" %s \" " , file ) ;
2002-11-18 17:04:08 +03:00
if ( ! ( context = create_text_context ( cmd , file , desc ) ) | |
! ( tf = cmd - > fmt_backup - > ops - > create_instance ( cmd - > fmt_backup , NULL ,
context ) ) ) {
log_error ( " Couldn't create backup object. " ) ;
return 0 ;
}
/* Write and commit the metadata area */
2003-10-16 00:02:46 +04:00
list_iterate_items ( mda , & tf - > metadata_areas ) {
2002-11-18 17:04:08 +03:00
if ( ! ( r = mda - > ops - > vg_write ( tf , vg , mda ) ) ) {
stack ;
continue ;
}
if ( mda - > ops - > vg_commit & &
! ( r = mda - > ops - > vg_commit ( tf , vg , mda ) ) ) {
stack ;
}
}
tf - > fmt - > ops - > destroy_instance ( tf ) ;
return r ;
}