From: Peter Rajnoha <prajnoha@redhat.com>
To: lvm-devel@redhat.com
Subject: [PATCH] Fix format instance handling in _vg_read
Date: Mon, 08 Aug 2011 17:58:42 +0200 [thread overview]
Message-ID: <4E4007B2.40901@redhat.com> (raw)
The _vg_read fn uses a global format_instance (the "fid") and then it tries to
call vg_read iteratively with the fid as a parameter (and so assigning it to
the vg struct), calling free_vg if the vg was found incorrect.
The problem is that free_vg would also free any fid it has assigned, so we need
to handle this somehow. To be sure that such situation does not happen, let's
increase the fid's ref_count before the iteration where we call vg_read and
decrement it afterwards. That way we can be sure that the fid is not destroyed
prematurely within the free_vg call in the iteration.
Since we create the fid manually and handle it manually in _vg_read fn, we need
to destroy it manually as well by calling the _destroy_fid fn directly if it's
not done withing the free_vg call.
This patch also adds a few missing free_vg calls.
Bad luck the vg_read is a bit complex, but we need this patch to avoid memory
leaks and premature destruction of the fid. This is the only place where we need
to do this magic. The _vg_read fn likes using the fid globally and fiddle with
it in an obscure way, so here's a small obscure fix :)
Peter
---
lib/metadata/metadata.c | 45 +++++++++++++++++++++++++++++++++++++++++----
1 files changed, 41 insertions(+), 4 deletions(-)
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index c8442d8..5f59021 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -2768,6 +2768,14 @@ static void _free_pv_list(struct dm_list *all_pvs)
pvl->pv->fid->fmt->ops->destroy_instance(pvl->pv->fid);
}
+static void _destroy_fid(struct format_instance **fid)
+{
+ if (*fid) {
+ (*fid)->fmt->ops->destroy_instance(*fid);
+ fid = NULL;
+ }
+}
+
int vg_missing_pv_count(const struct volume_group *vg)
{
int ret = 0;
@@ -2826,7 +2834,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
int warnings,
int *consistent, unsigned precommitted)
{
- struct format_instance *fid;
+ struct format_instance *fid = NULL;
struct format_instance_ctx fic;
const struct format_type *fmt;
struct volume_group *vg, *correct_vg = NULL;
@@ -2904,12 +2912,20 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
}
/* Store pvids for later so we can check if any are missing */
- if (!(pvids = lvmcache_get_pvids(cmd, vgname, vgid)))
+ if (!(pvids = lvmcache_get_pvids(cmd, vgname, vgid))) {
+ _destroy_fid(&fid);
return_NULL;
+ }
+ /*
+ * We use the fid globally here so prevent the free_vg
+ * call to destroy the fid - we may want to reuse it!
+ */
+ fid->ref_count++;
/* Ensure contents of all metadata areas match - else do recovery */
inconsistent_mda_count=0;
dm_list_iterate_items(mda, &fid->metadata_areas_in_use) {
+
if ((use_precommitted &&
!(vg = mda->ops->vg_read_precommit(fid, vgname, mda))) ||
(!use_precommitted &&
@@ -2945,6 +2961,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
if (vg != correct_vg)
free_vg(vg);
}
+ fid->ref_count--;
/* Ensure every PV in the VG was in the cache */
if (correct_vg) {
@@ -2976,8 +2993,10 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
}
if (dm_list_size(&info->mdas)) {
if (!fid_add_mdas(fid, &info->mdas,
- info->dev->pvid, ID_LEN))
+ info->dev->pvid, ID_LEN)) {
+ free_vg(correct_vg);
return_NULL;
+ }
log_debug("Empty mda found for VG %s.", vgname);
@@ -3006,8 +3025,10 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
*/
lvmcache_update_vg(correct_vg, correct_vg->status & PRECOMMITTED);
- if (!(pvids = lvmcache_get_pvids(cmd, vgname, vgid)))
+ if (!(pvids = lvmcache_get_pvids(cmd, vgname, vgid))) {
+ free_vg(correct_vg);
return_NULL;
+ }
}
}
@@ -3044,6 +3065,13 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
/* Failed to find VG where we expected it - full scan and retry */
if (!correct_vg) {
+ /*
+ * Free outstanding format instance that remained unassigned
+ * from previous step where we tried to get the "correct_vg",
+ * but we failed to do so (so there's a dangling fid now).
+ */
+ _destroy_fid(&fid);
+
inconsistent = 0;
/* Independent MDAs aren't supported under low memory */
@@ -3065,6 +3093,11 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
return NULL;
}
+ /*
+ * We use the fid globally here so prevent the free_vg
+ * call to destroy the fid - we may want to reuse it!
+ */
+ fid->ref_count++;
/* Ensure contents of all metadata areas match - else recover */
inconsistent_mda_count=0;
dm_list_iterate_items(mda, &fid->metadata_areas_in_use) {
@@ -3080,6 +3113,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
correct_vg = vg;
if (!_update_pv_list(cmd->mem, &all_pvs, correct_vg)) {
_free_pv_list(&all_pvs);
+ fid->ref_count--;
free_vg(vg);
return_NULL;
}
@@ -3103,6 +3137,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
if (!_update_pv_list(cmd->mem, &all_pvs, vg)) {
_free_pv_list(&all_pvs);
+ fid->ref_count--;
free_vg(vg);
free_vg(correct_vg);
return_NULL;
@@ -3119,10 +3154,12 @@ static struct volume_group *_vg_read(struct cmd_context *cmd,
if (vg != correct_vg)
free_vg(vg);
}
+ fid->ref_count--;
/* Give up looking */
if (!correct_vg) {
_free_pv_list(&all_pvs);
+ _destroy_fid(&fid);
return_NULL;
}
}
reply other threads:[~2011-08-08 15:58 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4E4007B2.40901@redhat.com \
--to=prajnoha@redhat.com \
--cc=lvm-devel@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.