summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2013-08-14 16:46:24 -0500
committerDavid Teigland <teigland@redhat.com>2013-08-14 17:02:57 -0500
commitc0e39af5f641764afad88bf74a33ad004e907cdf (patch)
treeb412ecdc8c2c7be55213658c019e83682ec8d9db
parent3f74bf79b2f1532c6c8f793004647a3b9272640b (diff)
downloadlvm2-dev-dct-process-part2.tar.gz
toollib: close vg devs after process_single_vgdev-dct-process-part2
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() through the code. 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.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;