]> sourceware.org Git - lvm2.git/commitdiff
vgimportclone: add native command
authorDavid Teigland <teigland@redhat.com>
Wed, 25 May 2016 18:57:33 +0000 (13:57 -0500)
committerDavid Teigland <teigland@redhat.com>
Wed, 22 Jun 2016 18:13:10 +0000 (13:13 -0500)
This is cleaner and more efficient than the script.
The args and usage are unchanged.

13 files changed:
lib/Makefile.in
lib/commands/toolcontext.c
lib/filters/filter-internal.c [new file with mode: 0644]
lib/filters/filter.h
lib/metadata/metadata.c
lib/misc/lvm-globals.c
lib/misc/lvm-globals.h
scripts/Makefile.in
test/Makefile.in
tools/Makefile.in
tools/args.h
tools/commands.h
tools/vgimportclone.c [new file with mode: 0644]

index 467ef9077bb1a9d4af1a9412666d7a964c70f959..451d96d8fa9c3fa52458e436714e8e5583a372e6 100644 (file)
@@ -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 \
index 75f19c9f414c25067fc7edf5dece8195412b6c35..3ee941082b2c2c66365936d78529b587cf89cdb5 100644 (file)
@@ -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))) {
diff --git a/lib/filters/filter-internal.c b/lib/filters/filter-internal.c
new file mode 100644 (file)
index 0000000..1a58a37
--- /dev/null
@@ -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;
+}
+
index ebd25e2bef38582804ca7272b3eb70ea7543e86f..d75f6e11ce1a258176a55cd5986555c957dae3bd 100644 (file)
@@ -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,
index ea42fb70de20f96d3728f964b01f63f03be7bce8..9b1fd314846829f7fdd63cd7a00b2d19a490e293 100644 (file)
@@ -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;
index b7af353ae800b19a69447945ebee5572588ecc46..9c78f3e3367ff80da0933b039b654d381fe8c1b9 100644 (file)
@@ -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;
index 77c01b41307f7af6e53cf9227a79f353949d38b5..14a7d43666c293f7dd967b731bc3ac8247eb372f 100644 (file)
@@ -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);
index 9c3d72d9d898ba223893eabd5a19c7554f9ec37b..e6742393b65a9d2842449df56cb6b414934a595f 100644 (file)
@@ -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")
index 59fcc96c9303123e59809845b9ff935f86e4a035..f48d6ead9171705d5c56d8bace3d1debef176f97 100644 (file)
@@ -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)
 
index 8dfac7fd73779609d1cf3aa687a68d0e653f3da7..d93c31b4dafe4a14aefc4a670db3cfacc15d2169 100644 (file)
@@ -60,6 +60,7 @@ SOURCES =\
        vgmerge.c \
        vgmknodes.c \
        lvpoll.c \
+       vgimportclone.c \
        vgreduce.c \
        vgremove.c \
        vgrename.c \
index 670d6a0e08364a0fce690ce51630ca596720b4c3..59025139dadd67eb6a8a533912b599d0c0390c94 100644 (file)
@@ -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)
index c0b3f3b8f7cde102055007ca2f839f8c9acba0c8..ed86b7fc2bd70f7b716162e13e2d45d543fce1f0 100644 (file)
@@ -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,
diff --git a/tools/vgimportclone.c b/tools/vgimportclone.c
new file mode 100644 (file)
index 0000000..7028fbb
--- /dev/null
@@ -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;
+}
+
This page took 0.06445 seconds and 5 git commands to generate.