diff options
-rw-r--r-- | lib/cache/lvmcache.c | 12 | ||||
-rw-r--r-- | lib/cache/lvmcache.h | 1 | ||||
-rw-r--r-- | lib/device/dev-io.c | 12 | ||||
-rw-r--r-- | lib/device/device.h | 1 | ||||
-rw-r--r-- | tools/toollib.c | 39 |
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; |