diff --git a/WHATS_NEW b/WHATS_NEW index 7c03af425..2f67f934e 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,6 +1,7 @@ Version 2.02.03 - =================================== - Capture vgid in more places. + Whenever vgname is captured, also capture vgid. + Remove an incorrect unlock_vg() from process_each_lv(). Update extent size information in vgchange and vgcreate man pages. Introduce origin_from_cow() and lv_is_visible(). pvremove without -f now fails if there's no PV label. diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c index 99fa6fa92..2fc12b160 100644 --- a/lib/cache/lvmcache.c +++ b/lib/cache/lvmcache.c @@ -348,7 +348,7 @@ static int _lvmcache_update_pvid(struct lvmcache_info *info, const char *pvid) return 1; } -static int _lvmcache_update_vgid(struct lvmcache_info *info, const char *vgid) +int lvmcache_update_vgid(struct lvmcache_info *info, const char *vgid) { if (!vgid || !info->vginfo || !strncmp(info->vginfo->vgid, vgid, sizeof(info->vginfo->vgid))) @@ -369,8 +369,8 @@ static int _lvmcache_update_vgid(struct lvmcache_info *info, const char *vgid) return 0; } - log_debug("lvmcache: %s: setting VGID to %s", dev_name(info->dev), - info->vginfo->vgid); + log_debug("lvmcache: %s: setting %s VGID to %s", dev_name(info->dev), + info->vginfo->vgname, info->vginfo->vgid); return 1; } @@ -425,8 +425,11 @@ int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname) /* FIXME Check consistency of list! */ vginfo->fmt = info->fmt; - log_debug("lvmcache: %s now %s%s", dev_name(info->dev), - *vgname ? "in VG " : "orphaned", vgname); + log_debug("lvmcache: %s: now %s%s%s%s%s", dev_name(info->dev), + *vgname ? "in VG " : "orphaned", vgname, + vginfo->vgid[0] ? " (" : "", + vginfo->vgid[0] ? vginfo->vgid : "", + vginfo->vgid[0] ? ")" : ""); return 1; } @@ -446,7 +449,7 @@ int lvmcache_update_vg(struct volume_group *vg) if ((info = info_from_pvid(pvid_s))) { lvmcache_update_vgname(info, vg->name); if (!vgid_updated) { - _lvmcache_update_vgid(info, (char *) &vg->id); + lvmcache_update_vgid(info, (char *) &vg->id); vgid_updated = 1; } } @@ -563,7 +566,7 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid, return NULL; } - if (!_lvmcache_update_vgid(info, vgid)) + if (!lvmcache_update_vgid(info, vgid)) /* Non-critical */ stack; diff --git a/lib/cache/lvmcache.h b/lib/cache/lvmcache.h index 7b074da25..ca86c169a 100644 --- a/lib/cache/lvmcache.h +++ b/lib/cache/lvmcache.h @@ -69,6 +69,7 @@ void lvmcache_del(struct lvmcache_info *info); /* Update things */ int lvmcache_update_vgname(struct lvmcache_info *info, const char *vgname); +int lvmcache_update_vgid(struct lvmcache_info *info, const char *vgid); int lvmcache_update_vg(struct volume_group *vg); void lvmcache_lock_vgname(const char *vgname, int read_only); diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c index 07b0ddb0d..70511bb13 100644 --- a/lib/format_text/format-text.c +++ b/lib/format_text/format-text.c @@ -871,65 +871,72 @@ static int _scan_file(const struct format_type *fmt) return 1; } -int vgname_from_mda(const struct format_type *fmt, struct device_area *dev_area, - char *buf, uint32_t size) +const char *vgname_from_mda(const struct format_type *fmt, + struct device_area *dev_area, struct id *vgid) { struct raw_locn *rlocn; struct mda_header *mdah; - unsigned int len; - int r = 0; + uint32_t wrap = 0; + const char *vgname = NULL; if (!dev_open(dev_area->dev)) { stack; - return 0; + return NULL; } - if (!(mdah = _raw_read_mda_header(fmt, dev_area))) { - stack; + if (!(mdah = _raw_read_mda_header(fmt, dev_area))) + goto_out; + + /* FIXME Cope with returning a list */ + rlocn = mdah->raw_locns; + + if (rlocn->offset + rlocn->size > mdah->size) + wrap = (uint32_t) ((rlocn->offset + rlocn->size) - mdah->size); + + if (wrap > rlocn->offset) { + log_error("%s: metadata too large for circular buffer", + dev_name(dev_area->dev)); goto out; } - rlocn = mdah->raw_locns; + /* FIXME 64-bit */ + if (!(vgname = text_vgname_import(fmt, dev_area->dev, + (off_t) (dev_area->start + + rlocn->offset), + (uint32_t) (rlocn->size - wrap), + (off_t) (dev_area->start + + MDA_HEADER_SIZE), + wrap, calc_crc, rlocn->checksum, + vgid))) + goto_out; - while (rlocn->offset) { - if (!dev_read(dev_area->dev, dev_area->start + rlocn->offset, - size, buf)) { - stack; - goto out; - } - len = 0; - while (buf[len] && !isspace(buf[len]) && buf[len] != '{' && - len < (size - 1)) - len++; - buf[len] = '\0'; - - /* Ignore this entry if the characters aren't permissible */ - if (!validate_name(buf)) { - stack; - goto out; - } - - r = 1; - break; - - /* FIXME Cope with returning a list */ - rlocn++; + /* Ignore this entry if the characters aren't permissible */ + if (!validate_name(vgname)) { + stack; + vgname = NULL; + goto out; } + log_debug("%s: Found metadata at %" PRIu64 " size %" PRIu64 + " for %s (%s)", + dev_name(dev_area->dev), dev_area->start + rlocn->offset, + rlocn->size, vgname, vgid->uuid); + out: if (!dev_close(dev_area->dev)) stack; - return r; + return vgname; } static int _scan_raw(const struct format_type *fmt) { struct raw_list *rl; struct list *raw_list; - char vgnamebuf[NAME_LEN + 2]; + const char *vgname; struct volume_group *vg; struct format_instance fid; + struct id vgid; raw_list = &((struct mda_lists *) fmt->private)->raws; @@ -938,9 +945,8 @@ static int _scan_raw(const struct format_type *fmt) list_iterate_items(rl, raw_list) { /* FIXME We're reading mdah twice here... */ - if (vgname_from_mda(fmt, &rl->dev_area, vgnamebuf, - sizeof(vgnamebuf))) { - if ((vg = _vg_read_raw_area(&fid, vgnamebuf, + if ((vgname = vgname_from_mda(fmt, &rl->dev_area, &vgid))) { + if ((vg = _vg_read_raw_area(&fid, vgname, &rl->dev_area, 0))) lvmcache_update_vg(vg); } diff --git a/lib/format_text/format-text.h b/lib/format_text/format-text.h index 8cef0ed36..b8bdb95ee 100644 --- a/lib/format_text/format-text.h +++ b/lib/format_text/format-text.h @@ -54,7 +54,7 @@ int add_mda(const struct format_type *fmt, struct dm_pool *mem, struct list *mda struct device *dev, uint64_t start, uint64_t size); void del_mdas(struct list *mdas); -int vgname_from_mda(const struct format_type *fmt, struct device_area *dev_area, - char *buf, uint32_t size); +const char *vgname_from_mda(const struct format_type *fmt, + struct device_area *dev_area, struct id *vgid); #endif diff --git a/lib/format_text/import-export.h b/lib/format_text/import-export.h index d90227b0e..df8d37526 100644 --- a/lib/format_text/import-export.h +++ b/lib/format_text/import-export.h @@ -47,6 +47,9 @@ struct text_vg_version_ops { struct config_tree * cf); void (*read_desc) (struct dm_pool * mem, struct config_tree * cf, time_t *when, char **desc); + const char *(*read_vgname) (const struct format_type *fmt, + struct config_tree *cft, + struct id *vgid); }; struct text_vg_version_ops *text_vg_vsn1_init(void); @@ -70,5 +73,11 @@ struct volume_group *text_vg_import_fd(struct format_instance *fid, checksum_fn_t checksum_fn, uint32_t checksum, time_t *when, char **desc); +const char *text_vgname_import(const struct format_type *fmt, + struct device *dev, + off_t offset, uint32_t size, + off_t offset2, uint32_t size2, + checksum_fn_t checksum_fn, uint32_t checksum, + struct id *vgid); #endif diff --git a/lib/format_text/import.c b/lib/format_text/import.c index 91f0b8c6c..95a8abc9d 100644 --- a/lib/format_text/import.c +++ b/lib/format_text/import.c @@ -23,6 +23,51 @@ /* FIXME Use tidier inclusion method */ static struct text_vg_version_ops *(_text_vsn_list[2]); +const char *text_vgname_import(const struct format_type *fmt, + struct device *dev, + off_t offset, uint32_t size, + off_t offset2, uint32_t size2, + checksum_fn_t checksum_fn, uint32_t checksum, + struct id *vgid) +{ + struct config_tree *cft; + struct text_vg_version_ops **vsn; + const char *vgname; + + static int _initialised = 0; + + if (!_initialised) { + _text_vsn_list[0] = text_vg_vsn1_init(); + _text_vsn_list[1] = NULL; + _initialised = 1; + } + + if (!(cft = create_config_tree(NULL))) + goto_out; + + if ((!dev && !read_config_file(cft)) || + (dev && !read_config_fd(cft, dev, offset, size, + offset2, size2, checksum_fn, checksum))) + goto_out; + + /* + * Find a set of version functions that can read this file + */ + for (vsn = &_text_vsn_list[0]; *vsn; vsn++) { + if (!(*vsn)->check_version(cft)) + continue; + + if (!(vgname = (*vsn)->read_vgname(fmt, cft, vgid))) + goto_out; + + break; + } + + out: + destroy_config_tree(cft); + return vgname; +} + struct volume_group *text_vg_import_fd(struct format_instance *fid, const char *file, struct device *dev, diff --git a/lib/format_text/import_vsn1.c b/lib/format_text/import_vsn1.c index 14d9abf3f..36ac655a1 100644 --- a/lib/format_text/import_vsn1.c +++ b/lib/format_text/import_vsn1.c @@ -798,10 +798,39 @@ static void _read_desc(struct dm_pool *mem, *when = u; } +static const char *_read_vgname(const struct format_type *fmt, + struct config_tree *cft, struct id *vgid) +{ + struct config_node *vgn; + struct dm_pool *mem = fmt->cmd->mem; + char *vgname; + + /* skip any top-level values */ + for (vgn = cft->root; (vgn && vgn->v); vgn = vgn->sib) ; + + if (!vgn) { + log_error("Couldn't find volume group in file."); + return 0; + } + + if (!(vgname = dm_pool_strdup(mem, vgn->key))) + return_0; + + vgn = vgn->child; + + if (!_read_id(vgid, vgn, "id")) { + log_error("Couldn't read uuid for volume group %s.", vgname); + return 0; + } + + return vgname; +} + static struct text_vg_version_ops _vsn1_ops = { check_version:_check_version, read_vg:_read_vg, - read_desc:_read_desc + read_desc:_read_desc, + read_vgname:_read_vgname }; struct text_vg_version_ops *text_vg_vsn1_init(void) diff --git a/lib/format_text/text_label.c b/lib/format_text/text_label.c index 5425eba1c..3f9a8fc7c 100644 --- a/lib/format_text/text_label.c +++ b/lib/format_text/text_label.c @@ -195,13 +195,14 @@ static int _read(struct labeller *l, struct device *dev, char *buf, struct disk_locn *dlocn_xl; uint64_t offset; struct metadata_area *mda; - char vgnamebuf[NAME_LEN + 2]; + struct id vgid; struct mda_context *mdac; + const char *vgname; pvhdr = (struct pv_header *) ((void *) buf + xlate32(lh->offset_xl)); if (!(info = lvmcache_add(l, pvhdr->pv_uuid, dev, NULL, NULL))) - return 0; + return_0; *label = info->label; info->device_size = xlate64(pvhdr->device_size_xl); @@ -232,10 +233,10 @@ static int _read(struct labeller *l, struct device *dev, char *buf, list_iterate_items(mda, &info->mdas) { mdac = (struct mda_context *) mda->metadata_locn; - if (vgname_from_mda(info->fmt, &mdac->area, vgnamebuf, - sizeof(vgnamebuf))) { - lvmcache_update_vgname(info, vgnamebuf); - /* FIXME Also store vgid */ + if ((vgname = vgname_from_mda(info->fmt, &mdac->area, + &vgid))) { + lvmcache_update_vgname(info, vgname); + lvmcache_update_vgid(info, (char *) &vgid); } } diff --git a/lib/label/label.c b/lib/label/label.c index 866e7f03e..e22144e31 100644 --- a/lib/label/label.c +++ b/lib/label/label.c @@ -117,15 +117,6 @@ static struct labeller *_find_labeller(struct device *dev, char *buf, int found = 0; char readbuf[LABEL_SCAN_SIZE]; - if (!dev_open(dev)) { - stack; - - if ((info = info_from_pvid(dev->pvid))) - lvmcache_update_vgname(info, ORPHAN); - - return NULL; - } - if (!dev_read(dev, UINT64_C(0), LABEL_SCAN_SIZE, readbuf)) { log_debug("%s: Failed to read label area", dev_name(dev)); goto out; @@ -188,9 +179,6 @@ static struct labeller *_find_labeller(struct device *dev, char *buf, log_very_verbose("%s: No label detected", dev_name(dev)); } - if (!dev_close(dev)) - stack; - return r; } @@ -272,16 +260,28 @@ int label_read(struct device *dev, struct label **result) char buf[LABEL_SIZE]; struct labeller *l; uint64_t sector; - int r; + struct lvmcache_info *info; + int r = 0; - if (!(l = _find_labeller(dev, buf, §or))) { + if (!dev_open(dev)) { stack; - return 0; + + if ((info = info_from_pvid(dev->pvid))) + lvmcache_update_vgname(info, ORPHAN); + + goto out; } + if (!(l = _find_labeller(dev, buf, §or))) + goto_out; + if ((r = (l->ops->read)(l, dev, buf, result)) && result && *result) (*result)->sector = sector; + out: + if (!dev_close(dev)) + stack; + return r; } @@ -335,18 +335,34 @@ int label_write(struct device *dev, struct label *label) return r; } +/* Unused */ int label_verify(struct device *dev) { struct labeller *l; char buf[LABEL_SIZE]; uint64_t sector; + struct lvmcache_info *info; + int r = 0; - if (!(l = _find_labeller(dev, buf, §or))) { + if (!dev_open(dev)) { stack; - return 0; + + if ((info = info_from_pvid(dev->pvid))) + lvmcache_update_vgname(info, ORPHAN); + + goto out; } - return ((l->ops->verify) ? l->ops->verify(l, buf, sector) : 1); + if (!(l = _find_labeller(dev, buf, §or))) + goto_out; + + r = l->ops->verify ? l->ops->verify(l, buf, sector) : 1; + + out: + if (!dev_close(dev)) + stack; + + return r; } void label_destroy(struct label *label)