diff options
author | David Teigland <teigland@redhat.com> | 2017-08-04 13:45:25 -0500 |
---|---|---|
committer | David Teigland <teigland@redhat.com> | 2017-10-18 10:03:57 -0500 |
commit | 30e380a5b85492135539cec424d21d6a160def23 (patch) | |
tree | 370a7d82a25a4ea310b6927254fc1ffab68584a5 | |
parent | 08aaaa5a72fadc7f14785718bbd2815ba3c21024 (diff) | |
download | lvm2-30e380a5b85492135539cec424d21d6a160def23.tar.gz |
vg_read: avoid another extraneous device read
when using async read data.
This is the short disk read that validates VG metadata
before reading the full metadata. There's a nearly
identical function in the label scan path, as this one
in the vg_read path. The other version was already
adapted to use the label read data, but this one was
missed.
-rw-r--r-- | lib/format_text/format-text.c | 44 |
1 files changed, 31 insertions, 13 deletions
diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c index 3755169ba..ac70947c2 100644 --- a/lib/format_text/format-text.c +++ b/lib/format_text/format-text.c @@ -414,8 +414,14 @@ static int _raw_write_mda_header(const struct format_type *fmt, return 1; } -static struct raw_locn *_find_vg_rlocn(struct device_area *dev_area, +/* + * FIXME: unify this with read_metadata_location() which is used + * in the label scanning path. + */ + +static struct raw_locn *_read_metadata_location_vg(struct device_area *dev_area, struct mda_header *mdah, + struct label_read_data *ld, const char *vgname, int *precommitted) { @@ -450,11 +456,20 @@ static struct raw_locn *_find_vg_rlocn(struct device_area *dev_area, if (!*vgname) return rlocn; - /* 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, - sizeof(vgnamebuf), vgnamebuf)) - goto_bad; + /* + * Verify that the VG metadata pointed to by the rlocn + * begins with a valid vgname. + */ + if (!ld || (ld->buf_len < dev_area->start + rlocn->offset + NAME_LEN)) { + /* 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, + sizeof(vgnamebuf), vgnamebuf)) + goto_bad; + } else { + memset(vgnamebuf, 0, sizeof(vgnamebuf)); + memcpy(vgnamebuf, ld->buf + dev_area->start + rlocn->offset, NAME_LEN); + } if (!strncmp(vgnamebuf, vgname, len = strlen(vgname)) && (isspace(vgnamebuf[len]) || vgnamebuf[len] == '{')) @@ -503,7 +518,7 @@ static int _raw_holds_vgname(struct format_instance *fid, if (!(mdah = raw_read_mda_header(fid->fmt, dev_area, NULL))) return_0; - if (_find_vg_rlocn(dev_area, mdah, vgname, &noprecommit)) + if (_read_metadata_location_vg(dev_area, mdah, NULL, vgname, &noprecommit)) r = 1; if (!dev_close(dev_area->dev)) @@ -530,7 +545,7 @@ static struct volume_group *_vg_read_raw_area(struct format_instance *fid, if (!(mdah = raw_read_mda_header(fid->fmt, area, ld))) goto_out; - if (!(rlocn = _find_vg_rlocn(area, mdah, vgname, &precommitted))) { + if (!(rlocn = _read_metadata_location_vg(area, mdah, ld, vgname, &precommitted))) { log_debug_metadata("VG %s not found on %s", vgname, dev_name(area->dev)); goto out; } @@ -558,7 +573,7 @@ static struct volume_group *_vg_read_raw_area(struct format_instance *fid, that skips parsing the metadata which also returns NULL. */ } - log_debug_metadata("Read metadata from %s at %"PRIu64" size %"PRIu64" for VG %s", + log_debug_metadata("Found metadata on %s at %"PRIu64" size %"PRIu64" for VG %s", dev_name(area->dev), area->start + rlocn->offset, rlocn->size, @@ -646,7 +661,7 @@ static int _vg_write_raw(struct format_instance *fid, struct volume_group *vg, if (!(mdah = raw_read_mda_header(fid->fmt, &mdac->area, NULL))) goto_out; - rlocn = _find_vg_rlocn(&mdac->area, mdah, old_vg_name ? : vg->name, &noprecommit); + rlocn = _read_metadata_location_vg(&mdac->area, mdah, NULL, old_vg_name ? : vg->name, &noprecommit); mdac->rlocn.offset = _next_rlocn_offset(rlocn, mdah); if (!fidtc->raw_metadata_buf && @@ -752,7 +767,7 @@ static int _vg_commit_raw_rlocn(struct format_instance *fid, if (!(mdah = raw_read_mda_header(fid->fmt, &mdac->area, NULL))) goto_out; - if (!(rlocn = _find_vg_rlocn(&mdac->area, mdah, old_vg_name ? : vg->name, &noprecommit))) { + if (!(rlocn = _read_metadata_location_vg(&mdac->area, mdah, NULL, old_vg_name ? : vg->name, &noprecommit))) { mdah->raw_locns[0].offset = 0; mdah->raw_locns[0].size = 0; mdah->raw_locns[0].checksum = 0; @@ -862,7 +877,7 @@ static int _vg_remove_raw(struct format_instance *fid, struct volume_group *vg, if (!(mdah = raw_read_mda_header(fid->fmt, &mdac->area, NULL))) goto_out; - if (!(rlocn = _find_vg_rlocn(&mdac->area, mdah, vg->name, &noprecommit))) { + if (!(rlocn = _read_metadata_location_vg(&mdac->area, mdah, NULL, vg->name, &noprecommit))) { rlocn = &mdah->raw_locns[0]; mdah->raw_locns[1].offset = 0; } @@ -1201,7 +1216,10 @@ int read_metadata_location(const struct format_type *fmt, return 0; } - /* Do quick check for a vgname */ + /* + * Verify that the VG metadata pointed to by the rlocn + * begins with a valid vgname. + */ if (!ld || (ld->buf_len < dev_area->start + rlocn->offset + NAME_LEN)) { if (!dev_read(dev_area->dev, dev_area->start + rlocn->offset, NAME_LEN, buf)) return_0; |