summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/cache/lvmcache.c12
-rw-r--r--lib/cache/lvmcache.h1
-rw-r--r--lib/device/dev-io.c12
-rw-r--r--lib/device/device.h1
-rw-r--r--tools/toollib.c39
5 files changed, 58 insertions, 7 deletions
diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c
index 770a1b37d..688f5dfd9 100644
--- a/lib/cache/lvmcache.c
+++ b/lib/cache/lvmcache.c
@@ -1649,6 +1649,18 @@ int lvmcache_pvid_is_locked(const char *pvid) {
return lvmcache_vgname_is_locked(info->vginfo->vgname);
}
+int lvmcache_pvid_is_in_vg(const char *pvid, const char *vgname)
+{
+ struct lvmcache_info *info;
+ info = lvmcache_info_from_pvid(pvid, 0);
+ if (!info || !info->vginfo)
+ return 0;
+
+ if (!strcmp(info->vginfo->vgname, vgname))
+ return 1;
+ return 0;
+}
+
int lvmcache_fid_add_mdas(struct lvmcache_info *info, struct format_instance *fid,
const char *id, int id_len)
{
diff --git a/lib/cache/lvmcache.h b/lib/cache/lvmcache.h
index bf2666444..5c23fb7ff 100644
--- a/lib/cache/lvmcache.h
+++ b/lib/cache/lvmcache.h
@@ -109,6 +109,7 @@ void lvmcache_drop_metadata(const char *vgname, int drop_precommitted);
void lvmcache_commit_metadata(const char *vgname);
int lvmcache_pvid_is_locked(const char *pvid);
+int lvmcache_pvid_is_in_vg(const char *pvid, const char *vgname);
int lvmcache_fid_add_mdas(struct lvmcache_info *info, struct format_instance *fid,
const char *id, int id_len);
int lvmcache_fid_add_mdas_pv(struct lvmcache_info *info, struct format_instance *fid);
diff --git a/lib/device/dev-io.c b/lib/device/dev-io.c
index 34e306417..feaeb71fd 100644
--- a/lib/device/dev-io.c
+++ b/lib/device/dev-io.c
@@ -625,6 +625,18 @@ int dev_close_immediate(struct device *dev)
return _dev_close(dev, 1);
}
+void dev_close_vg(const char *vgname)
+{
+ struct dm_list *doh, *doht;
+ struct device *dev;
+
+ dm_list_iterate_safe(doh, doht, &_open_devices) {
+ dev = dm_list_struct_base(doh, struct device, open_list);
+ if (dev->open_count < 1 && lvmcache_pvid_is_in_vg(dev->pvid, vgname))
+ _close(dev);
+ }
+}
+
void dev_close_all(void)
{
struct dm_list *doh, *doht;
diff --git a/lib/device/device.h b/lib/device/device.h
index 1d6304d4a..eed4c4de6 100644
--- a/lib/device/device.h
+++ b/lib/device/device.h
@@ -80,6 +80,7 @@ int dev_open_readonly_quiet(struct device *dev);
int dev_close(struct device *dev);
int dev_close_immediate(struct device *dev);
void dev_close_all(void);
+void dev_close_vg(const char *vgname);
int dev_test_excl(struct device *dev);
int dev_fd(struct device *dev);
diff --git a/tools/toollib.c b/tools/toollib.c
index 213e1160c..68c2eb17e 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -1493,22 +1493,38 @@ static struct vg_list *find_vgl(struct dm_list *vgl_list, const char *vg_name)
struct vg_list *vgl;
dm_list_iterate_items(vgl, vgl_list) {
- if (!strcmp(vg_name, vgl->vg->name))
+ if (vgl->vg && !strcmp(vg_name, vgl->vg->name))
return vgl;
}
return NULL;
}
+static void release_vgl(struct cmd_context *cmd, struct vg_list *vgl)
+{
+ if (!vgl->vg)
+ return;
+
+ if (is_orphan_vg(vgl->vg->name)) {
+ dev_close_vg(vgl->vg->name);
+ release_vg(vgl->vg);
+ } else if (vg_read_error(vgl->vg)) {
+ dev_close_vg(vgl->vg->name);
+ release_vg(vgl->vg);
+ } else {
+ dev_close_vg(vgl->vg->name);
+ unlock_vg(cmd, vgl->vg->name);
+ release_vg(vgl->vg);
+ }
+
+ vgl->vg = NULL;
+}
+
static void release_vg_list(struct cmd_context *cmd, struct dm_list *vgl_list)
{
struct vg_list *vgl;
- dm_list_iterate_items(vgl, vgl_list) {
- if (vg_read_error(vgl->vg))
- release_vg(vgl->vg);
- else
- unlock_and_release_vg(cmd, vgl->vg, vgl->vg->name);
- }
+ dm_list_iterate_items(vgl, vgl_list)
+ release_vgl(cmd, vgl);
}
static int read_vg_name_list(struct cmd_context *cmd, uint32_t flags,
@@ -1596,6 +1612,12 @@ static int process_vg_name_list(struct cmd_context *cmd, uint32_t flags,
if (process_vg)
ret = process_single_vg(cmd, vgname, vg, handle);
+ /*
+ * Close devices after each because open devices
+ * from one may cause the next to fail.
+ */
+ release_vgl(cmd, vgl);
+
if (ret > ret_max)
ret_max = ret;
if (sigint_caught())
@@ -1830,6 +1852,9 @@ static int process_lv_vg_name_list(struct cmd_context *cmd, uint32_t flags,
ret = process_each_lv_in_vg(cmd, vg, &lvnames, tags_arg,
handle, process_single_lv);
+
+ release_vgl(cmd, vgl);
+
if (ret > ret_max)
ret_max = ret;