[lvm-devel] [PATCH] Fix vg_write/vg_commit to not reset position in metadata ring buffer on vgrename
Dave Wysochanski
dwysocha at redhat.com
Fri Mar 26 16:15:08 UTC 2010
On Fri, 2010-03-26 at 14:56 +0100, Peter Rajnoha wrote:
> We should write metadata into next position in the ring buffer while calling vgrename.
> At this code level (_vg_write_raw), we're not able to determine if this is a rename
> or not. If yes, then accompanying VG structure passed here has a new name set,
> not the old one.
>
> When looking for a location where to put metadata next, we're given a NULL value because
> of failed VG name comparison (in _find_vg_rlocn) between the name in existing metadata
> and metadata we're just about to write.
>
> This resets the position in the ring buffer, overwriting any existing metadata
> (and also incorrectly updates the cache to "orphan" afterwards).
>
> This patch just adds old_name item in struct volume_group that we can check and use
> if necessary and detect renames at lower layers as well.
>
> Peter
>
> lib/format_text/format-text.c | 17 +++++++++++++----
> lib/metadata/metadata-exported.h | 1 +
> lib/metadata/metadata.c | 2 ++
> 3 files changed, 16 insertions(+), 4 deletions(-)
>
> diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c
> index ad4db34..4856d07 100644
> --- a/lib/format_text/format-text.c
> +++ b/lib/format_text/format-text.c
> @@ -380,6 +380,10 @@ static struct raw_locn *_find_vg_rlocn(struct device_area *dev_area,
> } else
> *precommitted = 0;
>
> + /* Do not check non-existent metadata. */
> + if (!rlocn->offset && !rlocn->size)
> + return NULL;
> +
> /* FIXME Loop through rlocns two-at-a-time. List null-terminated. */
> /* FIXME Ignore if checksum incorrect!!! */
> if (!dev_read(dev_area->dev, dev_area->start + rlocn->offset,
> @@ -387,9 +391,11 @@ static struct raw_locn *_find_vg_rlocn(struct device_area *dev_area,
> goto_bad;
>
> if (!strncmp(vgnamebuf, vgname, len = strlen(vgname)) &&
> - (isspace(vgnamebuf[len]) || vgnamebuf[len] == '{')) {
> + (isspace(vgnamebuf[len]) || vgnamebuf[len] == '{'))
> return rlocn;
> - }
> + else
> + log_debug("Volume group name found in metadata does "
> + "not match expected name %s.", vgname);
>
> bad:
> if ((info = info_from_pvid(dev_area->dev->pvid, 0)))
> @@ -542,7 +548,8 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg,
> if (!(mdah = _raw_read_mda_header(fid->fmt, &mdac->area)))
> goto_out;
>
> - rlocn = _find_vg_rlocn(&mdac->area, mdah, vg->name, &noprecommit);
> + rlocn = _find_vg_rlocn(&mdac->area, mdah,
> + vg->old_name ? vg->old_name : vg->name, &noprecommit);
> mdac->rlocn.offset = _next_rlocn_offset(rlocn, mdah);
>
> if (!fidtc->raw_metadata_buf &&
> @@ -647,7 +654,9 @@ static int _vg_commit_raw_rlocn(struct format_instance *fid,
> if (!(mdah = _raw_read_mda_header(fid->fmt, &mdac->area)))
> goto_out;
>
> - if (!(rlocn = _find_vg_rlocn(&mdac->area, mdah, vg->name, &noprecommit))) {
> + if (!(rlocn = _find_vg_rlocn(&mdac->area, mdah,
> + vg->old_name ? vg->old_name : vg->name,
> + &noprecommit))) {
> mdah->raw_locns[0].offset = 0;
> mdah->raw_locns[0].size = 0;
> mdah->raw_locns[0].checksum = 0;
> diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
> index 2f1405f..855ab47 100644
> --- a/lib/metadata/metadata-exported.h
> +++ b/lib/metadata/metadata-exported.h
> @@ -216,6 +216,7 @@ struct volume_group {
>
> struct id id;
> char *name;
> + char *old_name;
> char *system_id;
>
> uint32_t extent_size;
> diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
> index 020e897..867e004 100644
> --- a/lib/metadata/metadata.c
> +++ b/lib/metadata/metadata.c
> @@ -437,6 +437,8 @@ int vg_rename(struct cmd_context *cmd, struct volume_group *vg,
> struct dm_pool *mem = vg->vgmem;
> struct pv_list *pvl;
>
> + vg->old_name = vg->name;
> +
> if (!(vg->name = dm_pool_strdup(mem, new_name))) {
> log_error("vg->name allocation failed for '%s'", new_name);
> return 0;
>
Seems reasonable.
But while we're on this topic, can you explain why _find_vg_rlocn() is
necessary at all?
Why are we not just using a precommit or non-precommit area here. This
whole function looks like a hack and it makes some things harder. IMO
if we could get rid of it we'd be better off.
More information about the lvm-devel
mailing list