2002-01-03 15:46:48 +00:00
/*
* Copyright ( C ) 2001 Sistina Software ( UK ) Limited .
*
* This file is released under the GPL .
*/
2002-01-10 23:21:07 +00:00
# include "tools.h"
2002-01-03 15:46:48 +00:00
static struct {
int enabled ;
char * dir ;
unsigned int keep_days ;
unsigned int keep_number ;
} _archive_params ;
2002-02-11 21:00:35 +00:00
int archive_init ( const char * dir , unsigned int keep_days , unsigned int keep_min )
2002-01-03 15:46:48 +00:00
{
2002-01-09 13:17:14 +00:00
_archive_params . dir = NULL ;
if ( ! * dir )
return 1 ;
if ( ! create_dir ( dir ) )
return 0 ;
2002-01-03 15:46:48 +00:00
if ( ! ( _archive_params . dir = dbg_strdup ( dir ) ) ) {
2002-01-09 13:17:14 +00:00
log_error ( " Couldn't copy archive directory name. " ) ;
2002-01-03 15:46:48 +00:00
return 0 ;
}
_archive_params . keep_days = keep_days ;
2002-01-07 11:12:11 +00:00
_archive_params . keep_number = keep_min ;
2002-01-03 15:46:48 +00:00
_archive_params . enabled = 1 ;
return 1 ;
}
void archive_exit ( void )
{
2002-01-09 13:17:14 +00:00
if ( _archive_params . dir )
dbg_free ( _archive_params . dir ) ;
2002-01-03 15:46:48 +00:00
memset ( & _archive_params , 0 , sizeof ( _archive_params ) ) ;
}
2002-01-07 09:05:31 +00:00
void archive_enable ( int flag )
2002-01-03 15:46:48 +00:00
{
2002-01-07 09:05:31 +00:00
_archive_params . enabled = flag ;
2002-01-03 15:46:48 +00:00
}
2002-02-08 11:13:47 +00: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 15:46:48 +00:00
static int __archive ( struct volume_group * vg )
{
2002-02-08 11:13:47 +00:00
char * desc ;
if ( ! ( desc = _build_desc ( vg - > cmd - > mem , vg - > cmd - > cmd_line , 1 ) ) ) {
stack ;
return 0 ;
}
2002-01-03 15:46:48 +00:00
2002-02-08 11:58:18 +00:00
return archive_vg ( vg , _archive_params . dir , desc ,
_archive_params . keep_days ,
_archive_params . keep_number ) ;
2002-01-03 15:46:48 +00:00
}
int archive ( struct volume_group * vg )
{
2002-01-09 13:17:14 +00:00
if ( ! _archive_params . enabled | | ! _archive_params . dir )
2002-01-03 15:46:48 +00:00
return 1 ;
if ( test_mode ( ) ) {
2002-11-18 14:04:08 +00:00
log_verbose ( " Test mode: Skipping archiving of volume group. " ) ;
2002-01-03 15:46:48 +00:00
return 1 ;
}
2002-01-30 15:04:48 +00:00
log_verbose ( " Archiving volume group \" %s \" metadata. " , vg - > name ) ;
2002-01-03 15:46:48 +00:00
if ( ! __archive ( vg ) ) {
2002-01-30 15:04:48 +00:00
log_error ( " Volume group \" %s \" metadata archive failed. " ,
2002-01-09 13:17:14 +00:00
vg - > name ) ;
2002-01-03 15:46:48 +00:00
return 0 ;
}
return 1 ;
}
2002-02-11 20:50:53 +00:00
int archive_display ( struct cmd_context * cmd , const char * vg_name )
2002-02-11 11:43:17 +00:00
{
2002-11-18 14:04:08 +00:00
return archive_list ( cmd , _archive_params . dir , vg_name ) ;
2002-02-11 11:43:17 +00:00
}
2002-01-03 15:46:48 +00:00
static struct {
int enabled ;
char * dir ;
} _backup_params ;
int backup_init ( const char * dir )
{
2002-01-09 13:17:14 +00:00
_backup_params . dir = NULL ;
if ( ! * dir )
return 1 ;
if ( ! create_dir ( dir ) )
return 0 ;
2002-01-03 15:46:48 +00:00
if ( ! ( _backup_params . dir = dbg_strdup ( dir ) ) ) {
2002-01-09 13:17:14 +00:00
log_error ( " Couldn't copy backup directory name. " ) ;
2002-01-03 15:46:48 +00:00
return 0 ;
}
return 1 ;
}
void backup_exit ( void )
{
2002-01-09 13:17:14 +00:00
if ( _backup_params . dir )
dbg_free ( _backup_params . dir ) ;
2002-01-07 11:12:11 +00:00
memset ( & _backup_params , 0 , sizeof ( _backup_params ) ) ;
2002-01-03 15:46:48 +00:00
}
2002-01-07 09:05:31 +00:00
void backup_enable ( int flag )
{
_backup_params . enabled = flag ;
}
2002-01-03 15:46:48 +00:00
static int __backup ( struct volume_group * vg )
{
char name [ PATH_MAX ] ;
2002-02-08 11:13:47 +00:00
char * desc ;
if ( ! ( desc = _build_desc ( vg - > cmd - > mem , vg - > cmd - > cmd_line , 0 ) ) ) {
stack ;
return 0 ;
}
2002-01-03 15:46:48 +00:00
if ( lvm_snprintf ( name , sizeof ( name ) , " %s/%s " ,
_backup_params . dir , vg - > name ) < 0 ) {
2002-01-09 13:17:14 +00:00
log_error ( " Failed to generate volume group metadata backup "
" filename. " ) ;
2002-01-03 15:46:48 +00:00
return 0 ;
}
2002-01-30 15:04:48 +00:00
log_verbose ( " Creating volume group backup \" %s \" " , name ) ;
2002-01-09 13:17:14 +00:00
2002-11-18 14:04:08 +00:00
return backup_to_file ( name , desc , vg ) ;
2002-01-03 15:46:48 +00:00
}
int backup ( struct volume_group * vg )
{
2002-01-09 13:17:14 +00:00
if ( ! _backup_params . enabled | | ! _backup_params . dir ) {
log_print ( " WARNING: This metadata update is NOT backed up " ) ;
2002-01-03 15:46:48 +00:00
return 1 ;
2002-01-09 13:17:14 +00:00
}
2002-01-03 15:46:48 +00:00
if ( test_mode ( ) ) {
2002-11-18 14:04:08 +00:00
log_verbose ( " Test mode: Skipping volume group backup. " ) ;
2002-01-03 15:46:48 +00:00
return 1 ;
}
if ( ! __backup ( vg ) ) {
2002-01-09 13:17:14 +00:00
log_error ( " Backup of volume group %s metadata failed. " ,
vg - > name ) ;
2002-01-03 15:46:48 +00:00
return 0 ;
}
return 1 ;
}
2002-01-09 14:07:49 +00: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 14:04:08 +00:00
struct volume_group * backup_read_vg ( struct cmd_context * cmd ,
const char * vg_name , const char * file )
2002-01-10 14:27:47 +00:00
{
2002-12-19 23:25:55 +00:00
struct volume_group * vg = NULL ;
2002-01-10 14:27:47 +00:00
struct format_instance * tf ;
2002-11-18 14:04:08 +00:00
struct list * mdah ;
struct metadata_area * mda ;
2002-04-24 18:20:51 +00:00
void * context ;
2002-01-10 14:27:47 +00:00
2002-11-18 14:04:08 +00:00
if ( ! ( context = create_text_context ( cmd , file ,
2002-04-24 18:20:51 +00:00
cmd - > cmd_line ) ) | |
2002-11-18 14:04:08 +00:00
! ( tf = cmd - > fmt_backup - > ops - > create_instance ( cmd - > fmt_backup , NULL ,
context ) ) ) {
2002-01-10 14:27:47 +00:00
log_error ( " Couldn't create text format object. " ) ;
2002-02-08 11:13:47 +00:00
return NULL ;
2002-01-10 14:27:47 +00:00
}
2002-11-18 14:04:08 +00:00
list_iterate ( mdah , & tf - > metadata_areas ) {
mda = list_item ( mdah , struct metadata_area ) ;
if ( ! ( vg = mda - > ops - > vg_read ( tf , vg_name , mda ) ) )
stack ;
break ;
}
2002-01-10 14:27:47 +00:00
2002-04-24 18:20:51 +00:00
tf - > fmt - > ops - > destroy_instance ( tf ) ;
2002-01-10 23:21:07 +00:00
return vg ;
2002-01-10 14:27:47 +00:00
}
2002-11-18 14:04:08 +00:00
/* ORPHAN and VG locks held before calling this */
int backup_restore_vg ( struct cmd_context * cmd , struct volume_group * vg )
2002-01-10 14:27:47 +00:00
{
2002-11-18 14:04:08 +00:00
struct list * pvh ;
struct physical_volume * pv ;
2003-07-04 22:34:56 +00:00
struct lvmcache_info * info ;
2002-01-10 14:27:47 +00:00
/*
2002-11-18 14:04:08 +00:00
* FIXME : Check that the PVs referenced in the backup are
* not members of other existing VGs .
2002-01-10 14:27:47 +00:00
*/
2002-11-18 14:04:08 +00: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 14:27:47 +00:00
return 0 ;
}
2002-11-18 14:04:08 +00:00
/* Add any metadata areas on the PVs */
list_iterate ( pvh , & vg - > pvs ) {
pv = list_item ( pvh , struct pv_list ) - > pv ;
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 18:08:53 +00:00
pv_setup ( vg - > fid - > fmt , UINT64_C ( 0 ) , 0 , 0 , 0 ,
UINT64_C ( 0 ) , & vg - > fid - > metadata_areas , pv , vg ) ) {
2002-11-18 14:04:08 +00:00
log_error ( " Format-specific setup for %s failed " ,
dev_name ( pv - > dev ) ) ;
return 0 ;
}
2002-04-24 18:20:51 +00:00
}
2003-07-04 22:34:56 +00:00
if ( ! vg_write ( vg ) | | ! vg_commit ( vg ) ) {
2002-01-10 14:27:47 +00:00
stack ;
return 0 ;
}
return 1 ;
}
2002-11-18 14:04:08 +00: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 20:50:53 +00:00
int backup_restore ( struct cmd_context * cmd , const char * vg_name )
2002-01-10 14:27:47 +00: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 20:50:53 +00:00
return backup_restore_from_file ( cmd , vg_name , path ) ;
2002-01-10 14:27:47 +00:00
}
2002-11-18 14:04:08 +00:00
int backup_to_file ( const char * file , const char * desc , struct volume_group * vg )
{
2002-12-19 23:25:55 +00:00
int r = 0 ;
2002-11-18 14:04:08 +00:00
struct format_instance * tf ;
struct list * mdah ;
struct metadata_area * mda ;
void * context ;
struct cmd_context * cmd ;
cmd = vg - > cmd ;
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 */
list_iterate ( mdah , & tf - > metadata_areas ) {
mda = list_item ( mdah , struct metadata_area ) ;
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 ;
}