2002-01-03 18:46:48 +03:00
/*
2008-01-30 17:00:02 +03:00
* Copyright ( C ) 2001 - 2004 Sistina Software , Inc . All rights reserved .
2007-08-21 00:55:30 +04:00
* Copyright ( C ) 2004 - 2007 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
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 ,
2016-01-21 13:49:46 +03:00
* Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA
2002-01-03 18:46:48 +03:00
*/
2018-05-14 12:30:20 +03:00
# include "lib/misc/lib.h"
# include "lib/format_text/archiver.h"
# include "lib/format_text/format-text.h"
# include "lib/misc/lvm-string.h"
2021-02-26 03:23:50 +03:00
# include "lib/misc/lvm-signal.h"
2018-05-14 12:30:20 +03:00
# include "lib/cache/lvmcache.h"
# include "lib/mm/memlock.h"
# include "lib/commands/toolcontext.h"
# include "lib/locking/locking.h"
2002-01-11 02:21:07 +03:00
2005-05-17 17:46:38 +04:00
# include <unistd.h>
struct archive_params {
2002-01-03 18:46:48 +03:00
int enabled ;
char * dir ;
unsigned int keep_days ;
unsigned int keep_number ;
2005-05-17 17:46:38 +04:00
} ;
2002-01-03 18:46:48 +03:00
2005-05-17 17:46:38 +04:00
struct backup_params {
2003-09-15 19:03:22 +04:00
int enabled ;
char * dir ;
2016-12-18 18:36:33 +03:00
int suppress ;
2005-05-17 17:46:38 +04:00
} ;
2003-09-15 19:03:22 +04:00
2005-05-17 17:46:38 +04:00
int archive_init ( struct cmd_context * cmd , const char * dir ,
2008-12-11 06:32:56 +03:00
unsigned int keep_days , unsigned int keep_min ,
int enabled )
2002-01-03 18:46:48 +03:00
{
2010-09-09 17:07:13 +04:00
archive_exit ( cmd ) ;
2005-10-17 03:03:59 +04:00
if ( ! ( cmd - > archive_params = dm_pool_zalloc ( cmd - > libmem ,
2005-05-24 21:37:39 +04:00
sizeof ( * cmd - > archive_params ) ) ) ) {
2005-05-17 17:46:38 +04:00
log_error ( " archive_params alloc failed " ) ;
return 0 ;
}
cmd - > archive_params - > dir = NULL ;
2002-01-09 16:17:14 +03:00
if ( ! * dir )
return 1 ;
2018-06-08 15:40:53 +03:00
if ( ! ( cmd - > archive_params - > dir = 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 ;
}
2005-05-17 17:46:38 +04:00
cmd - > archive_params - > keep_days = keep_days ;
cmd - > archive_params - > keep_number = keep_min ;
2008-12-11 06:32:56 +03:00
archive_enable ( cmd , enabled ) ;
2005-05-17 17:46:38 +04:00
2002-01-03 18:46:48 +03:00
return 1 ;
}
2005-05-17 17:46:38 +04:00
void archive_exit ( struct cmd_context * cmd )
2002-01-03 18:46:48 +03:00
{
2009-07-09 02:18:32 +04:00
if ( ! cmd - > archive_params )
return ;
2018-06-08 15:40:53 +03:00
free ( cmd - > archive_params - > dir ) ;
2005-05-17 17:46:38 +04:00
memset ( cmd - > archive_params , 0 , sizeof ( * cmd - > archive_params ) ) ;
2002-01-03 18:46:48 +03:00
}
2005-05-17 17:46:38 +04:00
void archive_enable ( struct cmd_context * cmd , int flag )
2002-01-03 18:46:48 +03:00
{
2005-05-17 17:46:38 +04:00
cmd - > archive_params - > enabled = flag ;
2002-01-03 18:46:48 +03:00
}
2005-10-17 03:03:59 +04:00
static char * _build_desc ( struct dm_pool * mem , const char * line , int before )
2002-02-08 14:13:47 +03:00
{
size_t len = strlen ( line ) + 32 ;
char * buffer ;
2012-02-08 16:50:10 +04:00
if ( ! ( buffer = dm_pool_alloc ( mem , len ) ) ) {
log_error ( " Failed to allocate desc. " ) ;
return NULL ;
}
2002-02-08 14:13:47 +03:00
2012-02-08 16:50:10 +04:00
if ( dm_snprintf ( buffer , len , " Created %s executing '%s' " ,
before ? " *before* " : " *after* " , line ) < 0 ) {
log_error ( " Failed to build desc. " ) ;
return NULL ;
}
2002-02-08 14:13:47 +03:00
return buffer ;
}
2015-12-03 19:32:47 +03:00
static int _archive ( struct volume_group * vg , int compulsory )
2002-01-03 18:46:48 +03:00
{
2002-02-08 14:13:47 +03:00
char * desc ;
2014-01-17 03:02:59 +04:00
/* Don't archive orphan VGs. */
if ( is_orphan_vg ( vg - > name ) )
return 1 ;
2013-06-30 20:01:19 +04:00
if ( vg_is_archived ( vg ) )
return 1 ; /* VG has been already archived */
2013-07-02 13:07:15 +04:00
if ( ! vg - > cmd - > archive_params - > enabled | | ! vg - > cmd - > archive_params - > dir ) {
vg - > status | = ARCHIVED_VG ;
2002-01-03 18:46:48 +03:00
return 1 ;
2013-07-02 13:07:15 +04:00
}
2002-01-03 18:46:48 +03:00
if ( test_mode ( ) ) {
2013-07-02 13:07:15 +04:00
vg - > status | = ARCHIVED_VG ;
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 ;
}
2015-12-03 19:32:47 +03:00
if ( ! dm_create_dir ( vg - > cmd - > archive_params - > dir ) ) {
2015-12-05 00:04:14 +03:00
if ( compulsory )
return_0 ;
return 1 ;
2015-12-03 19:32:47 +03:00
}
2005-05-03 21:31:56 +04:00
2005-05-17 17:44:02 +04:00
/* Trap a read-only file system */
2008-01-30 17:00:02 +03:00
if ( ( access ( vg - > cmd - > archive_params - > dir , R_OK | W_OK | X_OK ) = = - 1 ) & &
2015-12-03 19:32:47 +03:00
( errno = = EROFS ) ) {
2015-12-05 00:04:14 +03:00
if ( compulsory ) {
log_error ( " Cannot archive volume group metadata for %s to read-only filesystem. " ,
vg - > name ) ;
return 0 ;
}
return 1 ;
2015-12-03 19:32:47 +03:00
}
2005-05-17 17:44:02 +04:00
log_verbose ( " Archiving volume group \" %s \" metadata (seqno %u). " , vg - > name ,
vg - > seqno ) ;
2015-12-03 19:32:47 +03:00
if ( ! ( desc = _build_desc ( vg - > cmd - > mem , vg - > cmd - > cmd_line , 1 ) ) )
return_0 ;
if ( ! archive_vg ( vg , vg - > cmd - > archive_params - > dir , desc ,
vg - > cmd - > archive_params - > keep_days ,
vg - > cmd - > archive_params - > keep_number ) )
return_0 ;
2002-01-03 18:46:48 +03:00
2013-06-30 20:01:19 +04:00
vg - > status | = ARCHIVED_VG ;
2002-01-03 18:46:48 +03:00
return 1 ;
}
2015-12-03 19:32:47 +03:00
int archive ( struct volume_group * vg )
{
2021-02-26 03:23:50 +03:00
int r ;
sigint_allow ( ) ;
r = _archive ( vg , 1 ) ;
sigint_restore ( ) ;
return r ;
2015-12-03 19:32:47 +03:00
}
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
2005-05-17 17:46:38 +04:00
r1 = archive_list ( cmd , cmd - > archive_params - > dir , vg_name ) ;
r2 = backup_list ( cmd , cmd - > backup_params - > dir , vg_name ) ;
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
2007-06-09 02:38:48 +04:00
int archive_display_file ( struct cmd_context * cmd , const char * file )
{
int r ;
r = archive_list_file ( cmd , file ) ;
return r ;
}
2008-12-11 06:33:35 +03:00
int backup_init ( struct cmd_context * cmd , const char * dir ,
int enabled )
2002-01-03 18:46:48 +03:00
{
2010-09-09 17:07:13 +04:00
backup_exit ( cmd ) ;
2005-10-17 03:03:59 +04:00
if ( ! ( cmd - > backup_params = dm_pool_zalloc ( cmd - > libmem ,
2009-03-24 00:56:32 +03:00
sizeof ( * cmd - > backup_params ) ) ) ) {
log_error ( " backup_params alloc failed " ) ;
2005-05-17 17:46:38 +04:00
return 0 ;
}
cmd - > backup_params - > dir = NULL ;
2002-01-09 16:17:14 +03:00
if ( ! * dir )
return 1 ;
2018-06-08 15:40:53 +03:00
if ( ! ( cmd - > backup_params - > dir = 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 ;
}
2008-12-11 06:33:35 +03:00
backup_enable ( cmd , enabled ) ;
2002-01-03 18:46:48 +03:00
return 1 ;
}
2005-05-17 17:46:38 +04:00
void backup_exit ( struct cmd_context * cmd )
2002-01-03 18:46:48 +03:00
{
2009-07-09 02:18:32 +04:00
if ( ! cmd - > backup_params )
return ;
2018-06-08 15:40:53 +03:00
free ( cmd - > backup_params - > dir ) ;
2005-05-17 17:46:38 +04:00
memset ( cmd - > backup_params , 0 , sizeof ( * cmd - > backup_params ) ) ;
2002-01-03 18:46:48 +03:00
}
2005-05-17 17:46:38 +04:00
void backup_enable ( struct cmd_context * cmd , int flag )
2002-01-07 12:05:31 +03:00
{
2005-05-17 17:46:38 +04:00
cmd - > backup_params - > enabled = flag ;
2002-01-07 12:05:31 +03:00
}
2015-12-03 19:32:47 +03:00
static int _backup ( struct volume_group * vg )
2002-01-03 18:46:48 +03:00
{
char name [ PATH_MAX ] ;
2002-02-08 14:13:47 +03:00
char * desc ;
2021-02-26 03:23:50 +03:00
int r ;
2002-02-08 14:13:47 +03:00
2008-01-30 16:19:47 +03:00
if ( ! ( desc = _build_desc ( vg - > cmd - > mem , vg - > cmd - > cmd_line , 0 ) ) )
return_0 ;
2002-01-03 18:46:48 +03:00
2006-08-21 16:54:53 +04:00
if ( dm_snprintf ( name , sizeof ( name ) , " %s/%s " ,
2005-05-17 17:46:38 +04:00
vg - > cmd - > 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 ;
}
2021-02-26 03:23:50 +03:00
sigint_allow ( ) ;
r = backup_to_file ( name , desc , vg ) ;
sigint_restore ( ) ;
return r ;
2002-01-03 18:46:48 +03:00
}
2009-04-22 13:39:45 +04:00
int backup_locally ( struct volume_group * vg )
2002-01-03 18:46:48 +03:00
{
2005-05-17 17:46:38 +04:00
if ( ! vg - > cmd - > backup_params - > enabled | | ! vg - > cmd - > backup_params - > dir ) {
2016-12-18 18:36:33 +03:00
log_warn_suppress ( vg - > cmd - > backup_params - > suppress + + ,
" 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 ( ) ) {
2011-02-28 23:50:01 +03:00
log_verbose ( " Test mode: Skipping backup of volume group. " ) ;
2002-01-03 18:46:48 +03:00
return 1 ;
}
2007-07-28 16:26:21 +04:00
if ( ! dm_create_dir ( vg - > cmd - > backup_params - > dir ) )
2005-05-03 21:31:56 +04:00
return 0 ;
2005-05-17 17:44:02 +04:00
/* Trap a read-only file system */
2008-01-30 17:00:02 +03:00
if ( ( access ( vg - > cmd - > backup_params - > dir , R_OK | W_OK | X_OK ) = = - 1 ) & &
2015-12-03 19:32:47 +03:00
( errno = = EROFS ) ) {
2015-12-05 00:04:14 +03:00
/* Will take a backup next time when FS is writable */
log_debug ( " Skipping backup of volume group on read-only filesystem. " ) ;
2008-01-30 17:00:02 +03:00
return 0 ;
2015-12-03 19:32:47 +03:00
}
2005-05-17 17:44:02 +04:00
2015-12-03 19:32:47 +03:00
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
2009-04-22 13:39:45 +04:00
int backup ( struct volume_group * vg )
{
2021-02-26 03:01:29 +03:00
vg - > needs_backup = 0 ;
2014-09-19 17:31:41 +04:00
/* Unlock memory if possible */
memlock_unlock ( vg - > cmd ) ;
2014-01-17 03:02:59 +04:00
/* Don't back up orphan VGs. */
if ( is_orphan_vg ( vg - > name ) )
return 1 ;
2009-04-22 13:39:45 +04:00
return backup_locally ( vg ) ;
}
2005-05-17 17:46:38 +04:00
int backup_remove ( struct cmd_context * cmd , const char * vg_name )
2002-01-09 17:07:49 +03:00
{
char path [ PATH_MAX ] ;
2006-08-21 16:54:53 +04:00
if ( dm_snprintf ( path , sizeof ( path ) , " %s/%s " ,
2005-05-17 17:46:38 +04:00
cmd - > backup_params - > dir , vg_name ) < 0 ) {
2009-07-16 00:02:46 +04:00
log_error ( " Failed to generate backup filename (for removal). " ) ;
2002-01-09 17:07:49 +03:00
return 0 ;
}
/*
* Let this fail silently .
*/
2011-01-05 18:06:10 +03:00
if ( unlink ( path ) )
log_sys_debug ( " unlink " , path ) ;
2002-01-09 17:07:49 +03:00
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 ;
2011-02-21 15:07:03 +03:00
struct format_instance_ctx fic ;
2011-03-11 17:45:17 +03:00
struct text_context tc = { . path_live = file ,
. path_edit = NULL ,
. desc = cmd - > cmd_line } ;
2002-11-18 17:04:08 +03:00
struct metadata_area * mda ;
2002-01-10 17:27:47 +03:00
2012-02-13 03:01:19 +04:00
fic . type = FMT_INSTANCE_PRIVATE_MDAS ;
2011-03-11 17:45:17 +03:00
fic . context . private = & tc ;
if ( ! ( tf = cmd - > fmt_backup - > ops - > create_instance ( cmd - > fmt_backup , & fic ) ) ) {
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
}
2010-06-29 00:32:44 +04:00
dm_list_iterate_items ( mda , & tf - > metadata_areas_in_use ) {
2020-01-28 19:33:15 +03:00
if ( ! ( vg = mda - > ops - > vg_read ( cmd , tf , vg_name , mda , NULL , NULL ) ) )
2002-11-18 17:04:08 +03:00
stack ;
break ;
}
2002-01-10 17:27:47 +03:00
2019-02-05 20:32:54 +03:00
if ( vg )
2021-02-06 01:16:03 +03:00
set_pv_devices ( tf , vg ) ;
2019-02-05 20:32:54 +03:00
2011-03-11 18:08:31 +03:00
if ( ! vg )
tf - > fmt - > ops - > destroy_instance ( tf ) ;
2002-01-11 02:21:07 +03:00
return vg ;
2002-01-10 17:27:47 +03:00
}
2016-02-16 22:22:50 +03:00
static int _restore_vg_should_write_pv ( struct physical_volume * pv , int do_pvcreate )
2015-03-26 16:20:46 +03:00
{
struct lvmcache_info * info ;
2016-02-16 22:22:50 +03:00
if ( do_pvcreate )
2015-03-26 16:20:46 +03:00
return 1 ;
if ( ! ( pv - > fmt - > features & FMT_PV_FLAGS ) )
return 0 ;
2016-06-21 00:02:07 +03:00
if ( ! pv - > dev ) {
log_error ( " Failed to find device for PV. " ) ;
return - 1 ;
}
2016-06-06 22:04:17 +03:00
if ( ! ( info = lvmcache_info_from_pvid ( pv - > dev - > pvid , pv - > dev , 0 ) ) ) {
2015-03-26 16:20:46 +03:00
log_error ( " Failed to find cached info for PV %s. " , pv_dev_name ( pv ) ) ;
return - 1 ;
}
/*
* We ' re restoring a VG and if the PV_EXT_USED
* flag is not set yet in PV , we need to set it now !
* This may happen if we have plain PVs without a VG
* and we ' re restoring former VG from backup on top
* of these PVs .
*/
if ( ! ( lvmcache_ext_flags ( info ) & PV_EXT_USED ) )
return 1 ;
return 0 ;
}
2002-11-18 17:04:08 +03:00
/* ORPHAN and VG locks held before calling this */
2015-03-26 16:20:46 +03:00
int backup_restore_vg ( struct cmd_context * cmd , struct volume_group * vg ,
2016-06-18 00:37:30 +03:00
int do_pvcreate , struct pv_create_args * pva )
2002-01-10 17:27:47 +03:00
{
2015-03-26 16:20:46 +03:00
struct dm_list new_pvs ;
struct pv_list * pvl , * new_pvl ;
struct physical_volume * existing_pv , * pv ;
2016-02-23 14:12:29 +03:00
struct dm_list * pvs = & vg - > pvs ;
2011-02-21 15:07:03 +03:00
struct format_instance * fid ;
struct format_instance_ctx fic ;
2015-03-26 16:20:46 +03:00
int should_write_pv ;
uint32_t tmp_extent_size ;
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
2015-03-26 16:20:46 +03:00
/* Prepare new PVs if needed. */
2016-02-16 22:22:50 +03:00
if ( do_pvcreate ) {
2015-03-26 16:20:46 +03:00
dm_list_init ( & new_pvs ) ;
dm_list_iterate_items ( pvl , & vg - > pvs ) {
existing_pv = pvl - > pv ;
2016-02-19 00:31:27 +03:00
pva - > id = existing_pv - > id ;
pva - > idp = & pva - > id ;
pva - > pe_start = pv_pe_start ( existing_pv ) ;
pva - > extent_count = pv_pe_count ( existing_pv ) ;
pva - > extent_size = pv_pe_size ( existing_pv ) ;
2015-03-26 16:20:46 +03:00
/* pe_end = pv_pe_count(existing_pv) * pv_pe_size(existing_pv) + pe_start - 1 */
2016-02-19 00:31:27 +03:00
if ( ! ( pv = pv_create ( cmd , pv_dev ( existing_pv ) , pva ) ) ) {
2015-03-26 16:20:46 +03:00
log_error ( " Failed to setup physical volume \" %s \" . " ,
pv_dev_name ( existing_pv ) ) ;
return 0 ;
}
pv - > vg_name = vg - > name ;
pv - > vgid = vg - > id ;
if ( ! ( new_pvl = dm_pool_zalloc ( vg - > vgmem , sizeof ( * new_pvl ) ) ) ) {
log_error ( " Failed to allocate PV list item for \" %s \" . " ,
pv_dev_name ( pvl - > pv ) ) ;
return 0 ;
}
2016-02-16 22:22:50 +03:00
2015-03-26 16:20:46 +03:00
new_pvl - > pv = pv ;
dm_list_add ( & new_pvs , & new_pvl - > list ) ;
2017-12-11 18:32:53 +03:00
log_verbose ( " Set up physical volume for \" %s \" with " FMTu64
2015-03-26 16:20:46 +03:00
" available sectors. " , pv_dev_name ( pv ) , pv_size ( pv ) ) ;
}
pvs = & new_pvs ;
}
2002-11-18 17:04:08 +03:00
/* Attempt to write out using currently active format */
2012-02-13 03:01:19 +04:00
fic . type = FMT_INSTANCE_AUX_MDAS ;
2011-02-21 15:07:03 +03:00
fic . context . vg_ref . vg_name = vg - > name ;
fic . context . vg_ref . vg_id = NULL ;
2011-02-21 15:10:58 +03:00
if ( ! ( fid = cmd - > fmt - > ops - > create_instance ( cmd - > fmt , & fic ) ) ) {
2015-03-26 16:20:46 +03:00
log_error ( " Failed to allocate format instance. " ) ;
2002-01-10 17:27:47 +03:00
return 0 ;
}
2015-03-26 16:20:46 +03:00
2016-02-16 22:22:50 +03:00
if ( do_pvcreate ) {
2015-03-26 16:20:46 +03:00
log_verbose ( " Deleting existing metadata for VG %s. " , vg - > name ) ;
if ( ! vg_remove_mdas ( vg ) ) {
cmd - > fmt - > ops - > destroy_instance ( fid ) ;
log_error ( " Removal of existing metadata for VG %s failed. " , vg - > name ) ;
return 0 ;
}
}
2011-02-21 15:10:58 +03:00
vg_set_fid ( vg , fid ) ;
2002-01-10 17:27:47 +03:00
2010-04-14 17:09:16 +04:00
/*
* Setting vg - > old_name to a blank value will explicitly
* disable any attempt to check VG name in existing metadata .
*/
2013-11-22 16:12:35 +04:00
if ( ! ( vg - > old_name = dm_pool_strdup ( vg - > vgmem , " " ) ) ) {
log_error ( " Failed to duplicate empty name. " ) ;
return 0 ;
}
2010-04-14 17:09:16 +04:00
2002-11-18 17:04:08 +03:00
/* Add any metadata areas on the PVs */
2015-03-26 16:20:46 +03:00
dm_list_iterate_items ( pvl , pvs ) {
2016-02-16 22:22:50 +03:00
if ( ( should_write_pv = _restore_vg_should_write_pv ( pvl - > pv , do_pvcreate ) ) < 0 )
2015-03-26 16:20:46 +03:00
return_0 ;
if ( should_write_pv ) {
2016-02-16 22:22:50 +03:00
if ( ! ( new_pvl = dm_pool_zalloc ( vg - > vgmem , sizeof ( * new_pvl ) ) ) ) {
2015-03-26 16:20:46 +03:00
log_error ( " Failed to allocate structure for scheduled "
" writing of PV '%s'. " , pv_dev_name ( pvl - > pv ) ) ;
2015-03-12 16:49:10 +03:00
return 0 ;
}
2015-03-26 16:20:46 +03:00
2016-02-16 22:22:50 +03:00
new_pvl - > pv = pvl - > pv ;
dm_list_add ( & vg - > pv_write_list , & new_pvl - > list ) ;
2015-03-12 16:49:10 +03:00
}
2015-03-26 16:20:46 +03:00
/* Add any metadata areas on the PV. */
tmp_extent_size = vg - > extent_size ;
2011-02-25 17:12:14 +03:00
vg - > extent_size = 0 ;
2011-02-25 16:59:47 +03:00
if ( ! vg - > fid - > fmt - > ops - > pv_setup ( vg - > fid - > fmt , pvl - > pv , vg ) ) {
2015-03-26 16:20:46 +03:00
vg - > extent_size = tmp_extent_size ;
log_error ( " Format-specific setup for %s failed. " ,
2011-02-25 16:59:47 +03:00
pv_dev_name ( pvl - > pv ) ) ;
2002-11-18 17:04:08 +03:00
return 0 ;
}
2015-03-26 16:20:46 +03:00
vg - > extent_size = tmp_extent_size ;
2002-04-24 22:20:51 +04:00
}
2016-02-16 22:22:50 +03:00
if ( do_pvcreate ) {
dm_list_iterate_items ( pvl , & vg - > pv_write_list ) {
struct device * dev = pv_dev ( pvl - > pv ) ;
const char * pv_name = dev_name ( dev ) ;
if ( ! label_remove ( dev ) ) {
log_error ( " Failed to wipe existing label on %s " , pv_name ) ;
return 0 ;
}
log_verbose ( " Zeroing start of device %s " , pv_name ) ;
2018-02-27 20:26:04 +03:00
if ( ! dev_write_zeros ( dev , 0 , 2048 ) ) {
2016-02-16 22:22:50 +03:00
log_error ( " %s not wiped: aborting " , pv_name ) ;
return 0 ;
}
}
}
2013-09-18 13:22:49 +04:00
if ( ! vg_write ( vg ) )
return_0 ;
if ( ! vg_commit ( vg ) )
2008-01-30 16:19:47 +03:00
return_0 ;
2002-01-10 17:27:47 +03:00
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 ,
2012-11-27 02:45:35 +04:00
const char * file , int force )
2002-11-18 17:04:08 +03:00
{
struct volume_group * vg ;
2009-05-19 13:45:33 +04:00
int missing_pvs , r = 0 ;
2012-01-20 15:01:13 +04:00
const struct lv_list * lvl ;
2002-11-18 17:04:08 +03:00
/*
* Read in the volume group from the text file .
*/
2008-01-30 16:19:47 +03:00
if ( ! ( vg = backup_read_vg ( cmd , vg_name , file ) ) )
return_0 ;
2002-11-18 17:04:08 +03:00
2012-01-20 15:01:13 +04:00
/* FIXME: Restore support is missing for now */
2012-11-27 02:45:35 +04:00
dm_list_iterate_items ( lvl , & vg - > lvs ) {
2012-01-20 15:01:13 +04:00
if ( lv_is_thin_type ( lvl - > lv ) ) {
2012-11-27 02:45:35 +04:00
if ( ! force ) {
log_error ( " Consider using option --force to restore "
" Volume Group %s with thin volumes. " ,
vg - > name ) ;
goto out ;
} else {
log_warn ( " WARNING: Forced restore of Volume Group "
" %s with thin volumes. " , vg - > name ) ;
break ;
}
2012-01-20 15:01:13 +04:00
}
2012-11-27 02:45:35 +04:00
}
2012-01-20 15:01:13 +04:00
2009-05-19 13:45:33 +04:00
missing_pvs = vg_missing_pv_count ( vg ) ;
if ( missing_pvs = = 0 )
2016-06-18 00:37:30 +03:00
r = backup_restore_vg ( cmd , vg , 0 , NULL ) ;
2009-05-19 13:45:33 +04:00
else
log_error ( " Cannot restore Volume Group %s with %i PVs "
" marked as missing. " , vg - > name , missing_pvs ) ;
2009-03-24 16:16:34 +03:00
2012-01-20 15:01:13 +04:00
out :
2011-08-11 00:25:29 +04:00
release_vg ( vg ) ;
2009-04-10 14:00:37 +04:00
return r ;
2002-11-18 17:04:08 +03:00
}
2012-11-27 02:45:35 +04:00
int backup_restore ( struct cmd_context * cmd , const char * vg_name , int force )
2002-01-10 17:27:47 +03:00
{
char path [ PATH_MAX ] ;
2006-08-21 16:54:53 +04:00
if ( dm_snprintf ( path , sizeof ( path ) , " %s/%s " ,
2005-05-17 17:46:38 +04:00
cmd - > backup_params - > dir , vg_name ) < 0 ) {
2009-07-16 00:02:46 +04:00
log_error ( " Failed to generate backup filename (for restore). " ) ;
2002-01-10 17:27:47 +03:00
return 0 ;
}
2012-11-27 02:45:35 +04:00
return backup_restore_from_file ( cmd , vg_name , path , force ) ;
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 ;
2011-02-21 15:07:03 +03:00
struct format_instance_ctx fic ;
2011-03-11 17:45:17 +03:00
struct text_context tc = { . path_live = file ,
. path_edit = NULL ,
. desc = desc } ;
2002-11-18 17:04:08 +03:00
struct metadata_area * mda ;
struct cmd_context * cmd ;
cmd = vg - > cmd ;
2005-05-17 17:44:02 +04:00
log_verbose ( " Creating volume group backup \" %s \" (seqno %u). " , file , vg - > seqno ) ;
2004-06-19 22:55:29 +04:00
2012-02-13 03:01:19 +04:00
fic . type = FMT_INSTANCE_PRIVATE_MDAS ;
2011-03-11 17:45:17 +03:00
fic . context . private = & tc ;
if ( ! ( tf = cmd - > fmt_backup - > ops - > create_instance ( cmd - > fmt_backup , & fic ) ) ) {
2002-11-18 17:04:08 +03:00
log_error ( " Couldn't create backup object. " ) ;
return 0 ;
}
2013-07-17 16:49:21 +04:00
if ( dm_list_empty ( & tf - > metadata_areas_in_use ) ) {
2010-06-29 19:03:59 +04:00
log_error ( INTERNAL_ERROR " No in use metadata areas to write. " ) ;
2011-03-11 18:08:31 +03:00
tf - > fmt - > ops - > destroy_instance ( tf ) ;
2010-06-29 19:03:59 +04:00
return 0 ;
}
2002-11-18 17:04:08 +03:00
/* Write and commit the metadata area */
2010-06-29 00:32:44 +04:00
dm_list_iterate_items ( mda , & tf - > metadata_areas_in_use ) {
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 ;
}
2005-05-17 17:44:02 +04:00
/*
* Update backup ( and archive ) if they ' re out - of - date or don ' t exist .
2015-12-05 00:04:14 +03:00
*
* This function is not supposed to log_error
* when the filesystem with archive / backup dir is read - only .
2005-05-17 17:44:02 +04:00
*/
void check_current_backup ( struct volume_group * vg )
{
char path [ PATH_MAX ] ;
struct volume_group * vg_backup ;
2009-04-03 01:34:41 +04:00
int old_suppress ;
2005-05-17 17:44:02 +04:00
2014-03-19 03:20:39 +04:00
if ( ! vg - > cmd - > backup_params - > enabled | | ! vg - > cmd - > backup_params - > dir ) {
log_debug ( " Skipping check for current backup, since backup is disabled. " ) ;
return ;
}
2009-09-14 23:44:15 +04:00
if ( vg_is_exported ( vg ) )
2005-05-17 17:44:02 +04:00
return ;
2006-08-21 16:54:53 +04:00
if ( dm_snprintf ( path , sizeof ( path ) , " %s/%s " ,
2015-12-03 19:32:47 +03:00
vg - > cmd - > backup_params - > dir , vg - > name ) < 0 ) {
log_warn ( " WARNING: Failed to generate backup pathname %s/%s. " ,
vg - > cmd - > backup_params - > dir , vg - > name ) ;
2005-05-17 17:44:02 +04:00
return ;
}
2009-04-03 01:34:41 +04:00
old_suppress = log_suppress ( 1 ) ;
2005-05-17 17:44:02 +04:00
/* Up-to-date backup exists? */
if ( ( vg_backup = backup_read_vg ( vg - > cmd , vg - > name , path ) ) & &
( vg - > seqno = = vg_backup - > seqno ) & &
2009-03-24 01:57:27 +03:00
( id_equal ( & vg - > id , & vg_backup - > id ) ) ) {
2009-04-03 01:34:41 +04:00
log_suppress ( old_suppress ) ;
2011-08-11 00:25:29 +04:00
release_vg ( vg_backup ) ;
2005-05-17 17:44:02 +04:00
return ;
2009-03-24 01:57:27 +03:00
}
2009-04-03 01:34:41 +04:00
log_suppress ( old_suppress ) ;
2005-05-17 17:44:02 +04:00
2009-04-10 14:00:37 +04:00
if ( vg_backup ) {
2015-12-03 19:32:47 +03:00
if ( ! _archive ( vg_backup , 0 ) )
2010-12-22 16:45:33 +03:00
stack ;
2011-08-11 00:25:29 +04:00
release_vg ( vg_backup ) ;
2009-04-10 14:00:37 +04:00
}
2015-12-03 19:32:47 +03:00
if ( ! _archive ( vg , 0 ) )
2010-12-22 16:45:33 +03:00
stack ;
if ( ! backup_locally ( vg ) )
stack ;
2005-05-17 17:44:02 +04:00
}