mirror of
git://sourceware.org/git/lvm2.git
synced 2025-02-07 05:58:00 +03:00
vgimportclone: add native command
This is cleaner and more efficient than the script. The args and usage are unchanged.
This commit is contained in:
parent
dfc516f9bf
commit
ebd2758dab
@ -76,6 +76,7 @@ SOURCES =\
|
||||
filters/filter-partitioned.c \
|
||||
filters/filter-type.c \
|
||||
filters/filter-usable.c \
|
||||
filters/filter-internal.c \
|
||||
format_text/archive.c \
|
||||
format_text/archiver.c \
|
||||
format_text/export.c \
|
||||
|
@ -1053,7 +1053,7 @@ static int _init_dev_cache(struct cmd_context *cmd)
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define MAX_FILTERS 8
|
||||
#define MAX_FILTERS 9
|
||||
|
||||
static struct dev_filter *_init_lvmetad_filter_chain(struct cmd_context *cmd)
|
||||
{
|
||||
@ -1078,6 +1078,13 @@ static struct dev_filter *_init_lvmetad_filter_chain(struct cmd_context *cmd)
|
||||
nr_filt++;
|
||||
}
|
||||
|
||||
/* internal filter used by command processing. */
|
||||
if (!(filters[nr_filt] = internal_filter_create())) {
|
||||
log_error("Failed to create internal device filter");
|
||||
goto bad;
|
||||
}
|
||||
nr_filt++;
|
||||
|
||||
/* global regex filter. Optional. */
|
||||
if ((cn = find_config_tree_node(cmd, devices_global_filter_CFG, NULL))) {
|
||||
if (!(filters[nr_filt] = regex_filter_create(cn->v))) {
|
||||
|
81
lib/filters/filter-internal.c
Normal file
81
lib/filters/filter-internal.c
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2006 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* 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 Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "lib.h"
|
||||
#include "filter.h"
|
||||
|
||||
static DM_LIST_INIT(_allow_devs);
|
||||
|
||||
int internal_filter_allow(struct dm_pool *mem, struct device *dev)
|
||||
{
|
||||
struct device_list *devl;
|
||||
|
||||
if (!(devl = dm_pool_alloc(mem, sizeof(*devl)))) {
|
||||
log_error("device_list element allocation failed");
|
||||
return 0;
|
||||
}
|
||||
devl->dev = dev;
|
||||
|
||||
dm_list_add(&_allow_devs, &devl->list);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void internal_filter_clear(void)
|
||||
{
|
||||
dm_list_init(&_allow_devs);
|
||||
}
|
||||
|
||||
static int _passes_internal(struct dev_filter *f __attribute__((unused)),
|
||||
struct device *dev)
|
||||
{
|
||||
struct device_list *devl;
|
||||
|
||||
if (!internal_filtering())
|
||||
return 1;
|
||||
|
||||
dm_list_iterate_items(devl, &_allow_devs) {
|
||||
if (devl->dev == dev)
|
||||
return 1;
|
||||
}
|
||||
|
||||
log_debug_devs("%s: Skipping for internal filtering.", dev_name(dev));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _destroy(struct dev_filter *f)
|
||||
{
|
||||
if (f->use_count)
|
||||
log_error(INTERNAL_ERROR "Destroying internal filter while in use %u times.", f->use_count);
|
||||
|
||||
dm_free(f);
|
||||
}
|
||||
|
||||
struct dev_filter *internal_filter_create(void)
|
||||
{
|
||||
struct dev_filter *f;
|
||||
|
||||
if (!(f = dm_zalloc(sizeof(*f)))) {
|
||||
log_error("md filter allocation failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
f->passes_filter = _passes_internal;
|
||||
f->destroy = _destroy;
|
||||
f->use_count = 0;
|
||||
|
||||
log_debug_devs("internal filter initialised.");
|
||||
|
||||
return f;
|
||||
}
|
||||
|
@ -32,6 +32,10 @@ struct dev_filter *persistent_filter_create(struct dev_types *dt,
|
||||
const char *file);
|
||||
struct dev_filter *sysfs_filter_create(void);
|
||||
|
||||
struct dev_filter *internal_filter_create(void);
|
||||
int internal_filter_allow(struct dm_pool *mem, struct device *dev);
|
||||
void internal_filter_clear(void);
|
||||
|
||||
/*
|
||||
* patterns must be an array of strings of the form:
|
||||
* [ra]<sep><regex><sep>, eg,
|
||||
|
@ -3306,6 +3306,9 @@ static int _check_old_pv_ext_for_vg(struct volume_group *vg)
|
||||
!pvl->pv->fmt->ops->pv_needs_rewrite)
|
||||
continue;
|
||||
|
||||
if (_pv_in_pv_list(pvl->pv, &vg->pv_write_list))
|
||||
continue;
|
||||
|
||||
if (!pvl->pv->fmt->ops->pv_needs_rewrite(pvl->pv->fmt, pvl->pv,
|
||||
&pv_needs_rewrite))
|
||||
return_0;
|
||||
|
@ -26,6 +26,7 @@ static int _verbose_level = VERBOSE_BASE_LEVEL;
|
||||
static int _silent = 0;
|
||||
static int _test = 0;
|
||||
static int _md_filtering = 0;
|
||||
static int _internal_filtering = 0;
|
||||
static int _fwraid_filtering = 0;
|
||||
static int _pvmove = 0;
|
||||
static int _full_scan_done = 0; /* Restrict to one full scan during each cmd */
|
||||
@ -79,6 +80,11 @@ void init_md_filtering(int level)
|
||||
_md_filtering = level;
|
||||
}
|
||||
|
||||
void init_internal_filtering(int level)
|
||||
{
|
||||
_internal_filtering = level;
|
||||
}
|
||||
|
||||
void init_fwraid_filtering(int level)
|
||||
{
|
||||
_fwraid_filtering = level;
|
||||
@ -242,6 +248,11 @@ int md_filtering(void)
|
||||
return _md_filtering;
|
||||
}
|
||||
|
||||
int internal_filtering(void)
|
||||
{
|
||||
return _internal_filtering;
|
||||
}
|
||||
|
||||
int fwraid_filtering(void)
|
||||
{
|
||||
return _fwraid_filtering;
|
||||
|
@ -26,6 +26,7 @@ void init_verbose(int level);
|
||||
void init_silent(int silent);
|
||||
void init_test(int level);
|
||||
void init_md_filtering(int level);
|
||||
void init_internal_filtering(int level);
|
||||
void init_fwraid_filtering(int level);
|
||||
void init_pvmove(int level);
|
||||
void init_full_scan_done(int level);
|
||||
@ -60,6 +61,7 @@ void set_sysfs_dir_path(const char *path);
|
||||
|
||||
int test_mode(void);
|
||||
int md_filtering(void);
|
||||
int internal_filtering(void);
|
||||
int fwraid_filtering(void);
|
||||
int pvmove_mode(void);
|
||||
int full_scan_done(void);
|
||||
|
@ -31,7 +31,7 @@ endif
|
||||
LVMLIBS = @LVM2APP_LIB@ -ldevmapper
|
||||
endif
|
||||
|
||||
LVM_SCRIPTS = lvmdump.sh lvmconf.sh vgimportclone.sh
|
||||
LVM_SCRIPTS = lvmdump.sh lvmconf.sh
|
||||
DM_SCRIPTS =
|
||||
|
||||
ifeq ("@FSADM@", "yes")
|
||||
|
@ -321,7 +321,6 @@ LIB = $(addprefix lib/, $(LIB_SHARED) $(LIB_LOCAL) $(LIB_NOT) $(LIB_LINK_NOT) $(
|
||||
$(LN_S) -f $(abs_top_builddir)/tools/dmsetup lib/dmstats
|
||||
$(LN_S) -f $(abs_top_srcdir)/conf/thin-performance.profile lib/
|
||||
$(LN_S) -f $(abs_top_srcdir)/scripts/fsadm.sh lib/fsadm
|
||||
$(LN_S) -f $(abs_top_srcdir)/scripts/vgimportclone.sh lib/vgimportclone
|
||||
test "$(srcdir)" = . || for i in $(LIB_LVMLOCKD_CONF); do \
|
||||
$(LN_S) -f $(abs_top_srcdir)/test/lib/$$i lib/; done
|
||||
touch $@
|
||||
@ -333,7 +332,7 @@ endif
|
||||
|
||||
CLEAN_TARGETS += .lib-dir-stamp .tests-stamp $(LIB) $(addprefix lib/,\
|
||||
$(CMDS) clvmd dmeventd dmsetup dmstats lvmetad lvmpolld \
|
||||
harness thin-performance.profile fsadm vgimportclone \
|
||||
harness thin-performance.profile fsadm \
|
||||
dm-version-expected version-expected \
|
||||
paths-installed paths-installed-t paths-common paths-common-t)
|
||||
|
||||
|
@ -60,6 +60,7 @@ SOURCES =\
|
||||
vgmerge.c \
|
||||
vgmknodes.c \
|
||||
lvpoll.c \
|
||||
vgimportclone.c \
|
||||
vgreduce.c \
|
||||
vgremove.c \
|
||||
vgrename.c \
|
||||
|
@ -154,6 +154,7 @@ arg(autobackup_ARG, 'A', "autobackup", yes_no_arg, 0, 0)
|
||||
arg(activevolumegroups_ARG, 'A', "activevolumegroups", NULL, 0, 0)
|
||||
arg(background_ARG, 'b', "background", NULL, 0, 0)
|
||||
arg(backgroundfork_ARG, 'b', "background", NULL, 0, 0)
|
||||
arg(basevgname_ARG, 'n', "basevgname", string_arg, 0, 0)
|
||||
arg(blockdevice_ARG, 'b', "blockdevice", NULL, 0, 0)
|
||||
arg(chunksize_ARG, 'c', "chunksize", size_kb_arg, 0, 0)
|
||||
arg(clustered_ARG, 'c', "clustered", yes_no_arg, 0, 0)
|
||||
@ -170,6 +171,7 @@ arg(help_ARG, 'h', "help", NULL, 0, 0)
|
||||
arg(cache_ARG, 'H', "cache", NULL, 0, 0)
|
||||
arg(history_ARG, 'H', "history", NULL, 0, 0)
|
||||
arg(help2_ARG, '?', "", NULL, 0, 0)
|
||||
arg(import_ARG, 'i', "import", NULL, 0, 0)
|
||||
arg(interval_ARG, 'i', "interval", int_arg, 0, 0)
|
||||
arg(iop_version_ARG, 'i', "iop_version", NULL, 0, 0)
|
||||
arg(stripes_ARG, 'i', "stripes", int_arg, 0, 0)
|
||||
|
@ -1358,6 +1358,21 @@ xx(vgimport,
|
||||
|
||||
all_ARG, force_ARG, reportformat_ARG, select_ARG, test_ARG)
|
||||
|
||||
xx(vgimportclone,
|
||||
"Import a VG from cloned PVs",
|
||||
NO_LVMETAD_AUTOSCAN,
|
||||
"vgimportclone\n"
|
||||
"\t[-d|--debug]\n"
|
||||
"\t[-h|--help]\n"
|
||||
"\t[-i|--import]\n"
|
||||
"\t[-n|--basevgname]\n"
|
||||
"\t[-t|--test]\n"
|
||||
"\t[-v|--verbose]\n"
|
||||
"\t[--version]\n"
|
||||
"\t[PhysicalVolumePath...]\n",
|
||||
|
||||
basevgname_ARG, test_ARG, import_ARG)
|
||||
|
||||
xx(vgmerge,
|
||||
"Merge volume groups",
|
||||
0,
|
||||
|
363
tools/vgimportclone.c
Normal file
363
tools/vgimportclone.c
Normal file
@ -0,0 +1,363 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* 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 Lesser General Public License v.2.1.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "tools.h"
|
||||
#include "lvmcache.h"
|
||||
#include "lvmetad-client.h"
|
||||
#include "filter.h"
|
||||
|
||||
struct vgimportclone_params {
|
||||
unsigned done;
|
||||
unsigned total;
|
||||
|
||||
int import_vg;
|
||||
int found_args;
|
||||
struct dm_list arg_import;
|
||||
const char *base_vgname;
|
||||
const char *old_vgname;
|
||||
const char *new_vgname;
|
||||
};
|
||||
|
||||
struct vgimportclone_device {
|
||||
struct dm_list list;
|
||||
struct device *dev;
|
||||
unsigned found_in_vg : 1;
|
||||
};
|
||||
|
||||
static int _vgimportclone_pv_single(struct cmd_context *cmd, struct volume_group *vg,
|
||||
struct physical_volume *pv, struct processing_handle *handle)
|
||||
{
|
||||
struct vgimportclone_params *vp = (struct vgimportclone_params *) handle->custom_handle;
|
||||
struct vgimportclone_device *vd;
|
||||
|
||||
if (vg && is_orphan_vg(vg->name)) {
|
||||
log_error("Cannot import clone of orphan PV %s.", dev_name(pv->dev));
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
if (!(vd = dm_pool_zalloc(cmd->mem, sizeof(*vd)))) {
|
||||
log_error("alloc failed.");
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
vd->dev = pv->dev;
|
||||
dm_list_add(&vp->arg_import, &vd->list);
|
||||
|
||||
log_debug("vgimportclone dev %s VG %s found to import",
|
||||
dev_name(vd->dev), vg ? vg->name : "<none>");
|
||||
|
||||
vp->found_args++;
|
||||
|
||||
return ECMD_PROCESSED;
|
||||
}
|
||||
|
||||
static int _vgimportclone_vg_single(struct cmd_context *cmd, const char *vg_name,
|
||||
struct volume_group *vg, struct processing_handle *handle)
|
||||
{
|
||||
char uuid[64] __attribute__((aligned(8)));
|
||||
struct vgimportclone_params *vp = (struct vgimportclone_params *) handle->custom_handle;
|
||||
struct vgimportclone_device *vd;
|
||||
struct pv_list *pvl, *new_pvl;
|
||||
struct lv_list *lvl;
|
||||
int devs_used_for_lv = 0;
|
||||
int found;
|
||||
|
||||
if (vg_is_exported(vg) && !vp->import_vg) {
|
||||
log_error("VG %s is exported, use the --import option.", vg->name);
|
||||
goto_bad;
|
||||
}
|
||||
|
||||
if (vg_status(vg) & PARTIAL_VG) {
|
||||
log_error("VG %s is partial, it must be complete.", vg->name);
|
||||
goto_bad;
|
||||
}
|
||||
|
||||
/*
|
||||
* N.B. lvs_in_vg_activated() is not smart enough to distinguish
|
||||
* between LVs that are active in the original VG vs the cloned VG
|
||||
* that's being imported, so check DEV_USED_FOR_LV.
|
||||
*/
|
||||
dm_list_iterate_items(pvl, &vg->pvs) {
|
||||
if (pvl->pv->dev->flags & DEV_USED_FOR_LV) {
|
||||
log_error("Device %s has active LVs, deactivate first.", dev_name(pvl->pv->dev));
|
||||
devs_used_for_lv++;
|
||||
}
|
||||
}
|
||||
|
||||
if (devs_used_for_lv)
|
||||
goto_bad;
|
||||
|
||||
/*
|
||||
* The arg_import list must match the PVs in VG.
|
||||
*/
|
||||
|
||||
dm_list_iterate_items(pvl, &vg->pvs) {
|
||||
found = 0;
|
||||
|
||||
dm_list_iterate_items(vd, &vp->arg_import) {
|
||||
if (pvl->pv->dev != vd->dev)
|
||||
continue;
|
||||
vd->found_in_vg = 1;
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
if (!id_write_format(&pvl->pv->id, uuid, sizeof(uuid)))
|
||||
goto_bad;
|
||||
|
||||
/* all PVs in the VG must be imported together, pvl is missing from args. */
|
||||
log_error("PV with UUID %s is part of VG %s, but is not included in the devices to import.",
|
||||
uuid, vg->name);
|
||||
log_error("All PVs in the VG must be imported together.");
|
||||
goto_bad;
|
||||
}
|
||||
}
|
||||
|
||||
dm_list_iterate_items(vd, &vp->arg_import) {
|
||||
if (!vd->found_in_vg) {
|
||||
/* device arg is not in the VG. */
|
||||
log_error("Device %s was not found in VG %s.", dev_name(vd->dev), vg->name);
|
||||
log_error("The devices to import must match the devices in the VG.");
|
||||
goto_bad;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Write changes.
|
||||
*/
|
||||
|
||||
if (!archive(vg))
|
||||
return_ECMD_FAILED;
|
||||
|
||||
if (vp->import_vg)
|
||||
vg->status &= ~EXPORTED_VG;
|
||||
|
||||
if (!id_create(&vg->id))
|
||||
goto_bad;
|
||||
|
||||
/* Low level vg_write code needs old_name to be set! */
|
||||
vg->old_name = vg->name;
|
||||
|
||||
if (!(vg->name = dm_pool_strdup(vg->vgmem, vp->new_vgname)))
|
||||
goto_bad;
|
||||
|
||||
dm_list_iterate_items(pvl, &vg->pvs) {
|
||||
if (!(new_pvl = dm_pool_zalloc(vg->vgmem, sizeof(*new_pvl))))
|
||||
goto_bad;
|
||||
|
||||
new_pvl->pv = pvl->pv;
|
||||
|
||||
if (!(pvl->pv->vg_name = dm_pool_strdup(vg->vgmem, vp->new_vgname)))
|
||||
goto_bad;
|
||||
|
||||
if (vp->import_vg)
|
||||
new_pvl->pv->status &= ~EXPORTED_VG;
|
||||
|
||||
/* Low level pv_write code needs old_id to be set! */
|
||||
memcpy(&new_pvl->pv->old_id, &new_pvl->pv->id, sizeof(new_pvl->pv->id));
|
||||
|
||||
if (!id_create(&new_pvl->pv->id))
|
||||
goto_bad;
|
||||
|
||||
dm_list_add(&vg->pv_write_list, &new_pvl->list);
|
||||
}
|
||||
|
||||
dm_list_iterate_items(lvl, &vg->lvs)
|
||||
memcpy(&lvl->lv->lvid, &vg->id, sizeof(vg->id));
|
||||
|
||||
if (!vg_write(vg) || !vg_commit(vg))
|
||||
goto_bad;
|
||||
|
||||
return ECMD_PROCESSED;
|
||||
bad:
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
int vgimportclone(struct cmd_context *cmd, int argc, char **argv)
|
||||
{
|
||||
struct vgimportclone_params vp = { 0 };
|
||||
struct processing_handle *handle = NULL;
|
||||
struct dm_list vgnameids_on_system; /* vgnameid_list */
|
||||
struct vgnameid_list *vgnl;
|
||||
struct vgimportclone_device *vd;
|
||||
struct lvmcache_info *info;
|
||||
const char *vgname;
|
||||
char base_vgname[NAME_LEN] = { 0 };
|
||||
char tmp_vgname[NAME_LEN] = { 0 };
|
||||
unsigned int vgname_count;
|
||||
int lvmetad_rescan = 0;
|
||||
int ret = ECMD_FAILED;
|
||||
|
||||
if (!argc) {
|
||||
log_error("PV names required.");
|
||||
return EINVALID_CMD_LINE;
|
||||
}
|
||||
|
||||
dm_list_init(&vgnameids_on_system);
|
||||
dm_list_init(&vp.arg_import);
|
||||
|
||||
set_pv_notify(cmd);
|
||||
|
||||
vp.import_vg = arg_is_set(cmd, import_ARG);
|
||||
|
||||
if (lvmetad_used()) {
|
||||
lvmetad_set_disabled(cmd, LVMETAD_DISABLE_REASON_DUPLICATES);
|
||||
lvmetad_disconnect();
|
||||
lvmetad_rescan = 1;
|
||||
}
|
||||
|
||||
if (!(handle = init_processing_handle(cmd, NULL))) {
|
||||
log_error("Failed to initialize processing handle.");
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
handle->custom_handle = &vp;
|
||||
|
||||
if (!lock_vol(cmd, VG_GLOBAL, LCK_VG_WRITE, NULL)) {
|
||||
log_error("Unable to obtain global lock.");
|
||||
destroy_processing_handle(cmd, handle);
|
||||
return ECMD_FAILED;
|
||||
}
|
||||
|
||||
if (!lockd_gl(cmd, "ex", 0))
|
||||
goto_out;
|
||||
cmd->lockd_gl_disable = 1;
|
||||
|
||||
/*
|
||||
* Find the devices being imported which are named on the command line.
|
||||
* They may be in the list of unchosen duplicates.
|
||||
*/
|
||||
|
||||
log_debug("Finding devices to import.");
|
||||
cmd->command->flags |= ENABLE_DUPLICATE_DEVS;
|
||||
process_each_pv(cmd, argc, argv, NULL, 0, READ_ALLOW_EXPORTED, handle, _vgimportclone_pv_single);
|
||||
|
||||
if (vp.found_args != argc) {
|
||||
log_error("Failed to find all devices.");
|
||||
goto_out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the VG name of the PVs being imported, save as old_vgname.
|
||||
* N.B. If vd->dev is a duplicate, then it may not match info->dev.
|
||||
*/
|
||||
|
||||
dm_list_iterate_items(vd, &vp.arg_import) {
|
||||
if (!(info = lvmcache_info_from_pvid(vd->dev->pvid, NULL, 0))) {
|
||||
log_error("Failed to find PVID for device %s in lvmcache.", dev_name(vd->dev));
|
||||
goto_out;
|
||||
}
|
||||
|
||||
if (!(vgname = lvmcache_vgname_from_info(info))) {
|
||||
log_error("Failed to find VG name for device %s in lvmcache.", dev_name(vd->dev));
|
||||
goto_out;
|
||||
}
|
||||
|
||||
if (!vp.old_vgname) {
|
||||
if (!(vp.old_vgname = dm_pool_strdup(cmd->mem, vgname)))
|
||||
goto_out;
|
||||
} else {
|
||||
if (strcmp(vp.old_vgname, vgname)) {
|
||||
log_error("Devices must be from the same VG.");
|
||||
goto_out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Pick a new VG name, save as new_vgname. The new name begins with
|
||||
* the basevgname or old_vgname, plus a $i suffix, if necessary, to
|
||||
* make it unique. This requires comparing the old_vgname with all the
|
||||
* VG names on the system.
|
||||
*/
|
||||
|
||||
if (arg_is_set(cmd, basevgname_ARG)) {
|
||||
snprintf(base_vgname, sizeof(base_vgname) - 1, "%s", arg_str_value(cmd, basevgname_ARG, ""));
|
||||
memcpy(tmp_vgname, base_vgname, NAME_LEN);
|
||||
vgname_count = 0;
|
||||
} else {
|
||||
snprintf(base_vgname, sizeof(base_vgname) - 1, "%s", vp.old_vgname);
|
||||
snprintf(tmp_vgname, sizeof(tmp_vgname) - 1, "%s1", vp.old_vgname);
|
||||
vgname_count = 1;
|
||||
}
|
||||
|
||||
if (!get_vgnameids(cmd, &vgnameids_on_system, NULL, 0))
|
||||
goto_out;
|
||||
|
||||
retry_name:
|
||||
dm_list_iterate_items(vgnl, &vgnameids_on_system) {
|
||||
if (!strcmp(vgnl->vg_name, tmp_vgname)) {
|
||||
vgname_count++;
|
||||
snprintf(tmp_vgname, sizeof(tmp_vgname) - 1, "%s%u", base_vgname, vgname_count);
|
||||
goto retry_name;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(vp.new_vgname = dm_pool_strdup(cmd->mem, tmp_vgname)))
|
||||
goto_out;
|
||||
log_debug("Using new VG name %s.", vp.new_vgname);
|
||||
|
||||
/*
|
||||
* Create a device filter so that we are only working with the devices
|
||||
* in arg_import. With the original devs hidden (that arg_import were
|
||||
* cloned from), we can read and write the cloned PVs and VG without
|
||||
* touching the original PVs/VG.
|
||||
*/
|
||||
|
||||
init_internal_filtering(1);
|
||||
dm_list_iterate_items(vd, &vp.arg_import)
|
||||
internal_filter_allow(cmd->mem, vd->dev);
|
||||
lvmcache_destroy(cmd, 1, 0);
|
||||
dev_cache_full_scan(cmd->full_filter);
|
||||
|
||||
log_debug("Changing VG %s to %s.", vp.old_vgname, vp.new_vgname);
|
||||
|
||||
/* We don't care if the new name comes before the old in lock order. */
|
||||
lvmcache_lock_ordering(0);
|
||||
|
||||
if (!lock_vol(cmd, vp.new_vgname, LCK_VG_WRITE, NULL)) {
|
||||
log_error("Can't get lock for new VG name %s", vp.new_vgname);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = process_each_vg(cmd, 0, NULL, vp.old_vgname, NULL, READ_FOR_UPDATE | READ_ALLOW_EXPORTED, 0, handle, _vgimportclone_vg_single);
|
||||
|
||||
unlock_vg(cmd, vp.new_vgname);
|
||||
out:
|
||||
unlock_vg(cmd, VG_GLOBAL);
|
||||
internal_filter_clear();
|
||||
init_internal_filtering(0);
|
||||
lvmcache_lock_ordering(1);
|
||||
destroy_processing_handle(cmd, handle);
|
||||
|
||||
/* Enable lvmetad again if no duplicates are left. */
|
||||
if (lvmetad_rescan) {
|
||||
if (!lvmetad_connect(cmd)) {
|
||||
log_warn("WARNING: Failed to connect to lvmetad.");
|
||||
log_warn("WARNING: Update lvmetad with pvscan --cache.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!refresh_filters(cmd))
|
||||
stack;
|
||||
|
||||
if (!lvmetad_pvscan_all_devs(cmd, 1)) {
|
||||
log_warn("WARNING: Failed to scan devices.");
|
||||
log_warn("WARNING: Update lvmetad with pvscan --cache.");
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user