summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2013-04-11 15:34:30 -0500
committerDavid Teigland <teigland@redhat.com>2013-04-11 15:48:07 -0500
commitd06d3239a4dcf30edd6baed84894bf91a6a2a10a (patch)
tree7e6d71355fbd6681d2f98de95ecf61c5f092f2a8
parent07096b7058c78b65e0e37ace02346d77f6f9b854 (diff)
downloadlvm2-dev-dct-process.tar.gz
toollib: close vg devs after process_single_vgdev-dct-process
This test was failing at vg1: vgsplit-stacked.sh: vgchange -a n $vg $vg1 because a pv in $vg was an lv from $vg1, and because the devs in $vg were still open after processing $vg, the lv from $vg1 was still open, causing vgchange to fail on $vg1 with: Can't deactivate volume group "@PREFIX@vg1" with 1 open logical volume(s) I'm not sure that closing the devs this way is correct, because I've not been able to make sense of the way devices are closed otherwise. There seems to be a liberal sprinkling of dev_close_all(). I also don't see how the devs would have been closed before the recent changes, but apparently they were because this test was passing.
-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.c40
5 files changed, 57 insertions, 9 deletions
diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c
index 9b5947035..1e5eacc39 100644
--- a/lib/cache/lvmcache.c
+++ b/lib/cache/lvmcache.c
@@ -1351,6 +1351,18 @@ int lvmcache_pvid_is_locked(const char *pvid) {
return lockcache_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 e543adcb9..e68bc6d6f 100644
--- a/lib/cache/lvmcache.h
+++ b/lib/cache/lvmcache.h
@@ -103,6 +103,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 2846cafd9..be8523f36 100644
--- a/lib/device/dev-io.c
+++ b/lib/device/dev-io.c
@@ -623,6 +623,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 8c32a03b4..5b43bff8c 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 16a78cfe3..3fd9d828e 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -1267,24 +1267,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 (is_orphan_vg(vgl->vg->name))
- release_vg(vgl->vg);
- else 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,
@@ -1385,6 +1399,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())
@@ -1620,6 +1640,8 @@ 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;
if (sigint_caught())