diff --git a/WHATS_NEW b/WHATS_NEW index 943aa0d0c..66d770bbf 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,7 @@ Version 2.02.03 - =================================== + Fix vgexport/vgimport to set/reset PV exported flag so pv_attr is correct. + Add vgid to struct physical_volume and pass with vg_name to some functions. If two or more VGs are found with the same name, use one that is not exported. Whenever vgname is captured, also capture vgid and whether exported. Remove an incorrect unlock_vg() from process_each_lv(). diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c index dfea63c84..89ba9cf24 100644 --- a/lib/cache/lvmcache.c +++ b/lib/cache/lvmcache.c @@ -106,7 +106,7 @@ struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname, const char *vgid) return vginfo; } -const struct format_type *fmt_from_vgname(const char *vgname) +const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid) { struct lvmcache_vginfo *vginfo; struct lvmcache_info *info; @@ -114,9 +114,9 @@ const struct format_type *fmt_from_vgname(const char *vgname) struct list *devh, *tmp; struct list devs; struct device_list *devl; - char vgid[ID_LEN + 1]; + char vgid_found[ID_LEN + 1]; - if (!(vginfo = vginfo_from_vgname(vgname, NULL))) + if (!(vginfo = vginfo_from_vgname(vgname, vgid))) return NULL; /* This function is normally called before reading metadata so @@ -128,7 +128,7 @@ const struct format_type *fmt_from_vgname(const char *vgname) list_add(&devs, &devl->list); } - memcpy(vgid, vginfo->vgid, sizeof(vgid)); + memcpy(vgid_found, vginfo->vgid, sizeof(vgid_found)); list_iterate_safe(devh, tmp, &devs) { devl = list_item(devh, struct device_list); @@ -138,8 +138,8 @@ const struct format_type *fmt_from_vgname(const char *vgname) } /* If vginfo changed, caller needs to rescan */ - if (!(vginfo = vginfo_from_vgname(vgname, NULL)) || - strncmp(vginfo->vgid, vgid, sizeof(vgid))) + if (!(vginfo = vginfo_from_vgname(vgname, vgid_found)) || + strncmp(vginfo->vgid, vgid_found, sizeof(vgid_found))) return NULL; return vginfo->fmt; @@ -163,6 +163,16 @@ struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid) return vginfo; } +const char *vgname_from_vgid(const char *vgid) +{ + struct lvmcache_vginfo *vginfo; + + if ((vginfo = vginfo_from_vgid(vgid))) + return vginfo->vgname; + + return NULL; +} + struct lvmcache_info *info_from_pvid(const char *pvid) { struct lvmcache_info *info; @@ -247,6 +257,29 @@ int lvmcache_label_scan(struct cmd_context *cmd, int full_scan) return r; } +struct list *lvmcache_get_vgids(struct cmd_context *cmd, int full_scan) +{ + struct list *vgids; + struct lvmcache_vginfo *vginfo; + + lvmcache_label_scan(cmd, full_scan); + + if (!(vgids = str_list_create(cmd->mem))) { + log_error("vgids list allocation failed"); + return NULL; + } + + list_iterate_items(vginfo, &_vginfos) { + if (!str_list_add(cmd->mem, vgids, + dm_pool_strdup(cmd->mem, vginfo->vgid))) { + log_error("strlist allocation failed"); + return NULL; + } + } + + return vgids; +} + struct list *lvmcache_get_vgnames(struct cmd_context *cmd, int full_scan) { struct list *vgnames; @@ -401,25 +434,36 @@ static int _lvmcache_update_vgid(struct lvmcache_info *info, const char *vgid) } static int _insert_vginfo(struct lvmcache_vginfo *new_vginfo, const char *vgid, + uint32_t vgstatus, struct lvmcache_vginfo *primary_vginfo) { struct lvmcache_vginfo *last_vginfo = primary_vginfo; - + char uuid_primary[64], uuid_new[64]; + /* Pre-existing VG takes precedence. Unexported VG takes precedence. */ if (primary_vginfo) { + if (!id_write_format((struct id *)vgid, uuid_new, sizeof(uuid_new))) + return_0; + + if (!id_write_format((struct id *)&primary_vginfo->vgid, uuid_primary, + sizeof(uuid_primary))) + return_0; + if (!(primary_vginfo->status & EXPORTED_VG) || - (new_vginfo->status & EXPORTED_VG)) { + (vgstatus & EXPORTED_VG)) { while (last_vginfo->next) last_vginfo = last_vginfo->next; last_vginfo->next = new_vginfo; - log_debug("VG %s: %s takes precedence over %s", - new_vginfo->vgname, primary_vginfo->vgid, - vgid); + log_error("WARNING: Duplicate VG name %s: " + "%s takes precedence over %s", + new_vginfo->vgname, uuid_primary, + uuid_new); return 1; } else - log_debug("VG %s: %s takes precedence over exported %s", - new_vginfo->vgname, vgid, - primary_vginfo->vgid); + log_error("WARNING: Duplicate VG name %s: Existing " + "%s takes precedence over exported %s", + new_vginfo->vgname, uuid_new, + uuid_primary); dm_hash_remove(_vgname_hash, primary_vginfo->vgname); } @@ -437,7 +481,8 @@ static int _insert_vginfo(struct lvmcache_vginfo *new_vginfo, const char *vgid, } static int _lvmcache_update_vgname(struct lvmcache_info *info, - const char *vgname, const char *vgid) + const char *vgname, const char *vgid, + uint32_t vgstatus) { struct lvmcache_vginfo *vginfo, *primary_vginfo; @@ -445,8 +490,10 @@ static int _lvmcache_update_vgname(struct lvmcache_info *info, * assume ORPHAN - we want every entry to have a vginfo * attached for scanning reasons. */ - if (!vgname && !info->vginfo) + if (!vgname && !info->vginfo) { vgname = ORPHAN; + vgid = ORPHAN; + } if (!vgname || (info->vginfo && !strcmp(info->vginfo->vgname, vgname))) return 1; @@ -468,7 +515,7 @@ static int _lvmcache_update_vgname(struct lvmcache_info *info, } list_init(&vginfo->infos); primary_vginfo = vginfo_from_vgname(vgname, NULL); - if (!_insert_vginfo(vginfo, vgid, primary_vginfo)) { + if (!_insert_vginfo(vginfo, vgid, vgstatus, primary_vginfo)) { dm_free(vginfo->vgname); dm_free(vginfo); return 0; @@ -514,7 +561,7 @@ int lvmcache_update_vgname_and_id(struct lvmcache_info *info, const char *vgname, const char *vgid, uint32_t vgstatus) { - if (!_lvmcache_update_vgname(info, vgname, vgid) || + if (!_lvmcache_update_vgname(info, vgname, vgid, vgstatus) || !_lvmcache_update_vgid(info, vgid) || !_lvmcache_update_vgstatus(info, vgstatus)) return_0; diff --git a/lib/cache/lvmcache.h b/lib/cache/lvmcache.h index 10a7ae950..385ea830e 100644 --- a/lib/cache/lvmcache.h +++ b/lib/cache/lvmcache.h @@ -82,11 +82,12 @@ void lvmcache_lock_vgname(const char *vgname, int read_only); void lvmcache_unlock_vgname(const char *vgname); /* Queries */ -const struct format_type *fmt_from_vgname(const char *vgname); +const struct format_type *fmt_from_vgname(const char *vgname, const char *vgid); struct lvmcache_vginfo *vginfo_from_vgname(const char *vgname, const char *vgid); struct lvmcache_vginfo *vginfo_from_vgid(const char *vgid); struct lvmcache_info *info_from_pvid(const char *pvid); +const char *vgname_from_vgid(const char *vgid); struct device *device_from_pvid(struct cmd_context *cmd, struct id *pvid); int vgs_locked(void); int vgname_is_locked(const char *vgname); @@ -95,4 +96,8 @@ int vgname_is_locked(const char *vgname); /* Set full_scan to 1 to reread every filtered device label */ struct list *lvmcache_get_vgnames(struct cmd_context *cmd, int full_scan); +/* Returns list of struct str_lists containing pool-allocated copy of vgids */ +/* Set full_scan to 1 to reread every filtered device label */ +struct list *lvmcache_get_vgids(struct cmd_context *cmd, int full_scan); + #endif diff --git a/lib/format1/disk-rep.h b/lib/format1/disk-rep.h index 13f57bc43..757ce1904 100644 --- a/lib/format1/disk-rep.h +++ b/lib/format1/disk-rep.h @@ -204,7 +204,8 @@ int write_disks(const struct format_type *fmt, struct list *pvds); */ int import_pv(struct dm_pool *mem, struct device *dev, struct volume_group *vg, - struct physical_volume *pv, struct pv_disk *pvd); + struct physical_volume *pv, struct pv_disk *pvd, + struct vg_disk *vgd); int export_pv(struct cmd_context *cmd, struct dm_pool *mem, struct volume_group *vg, struct pv_disk *pvd, struct physical_volume *pv); diff --git a/lib/format1/format1.c b/lib/format1/format1.c index a403eaeed..e2a336993 100644 --- a/lib/format1/format1.c +++ b/lib/format1/format1.c @@ -312,7 +312,7 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name, goto out; } - if (!import_pv(fmt->cmd->mem, dl->dev, NULL, pv, &dl->pvd)) { + if (!import_pv(fmt->cmd->mem, dl->dev, NULL, pv, &dl->pvd, &dl->vgd)) { stack; goto out; } @@ -502,6 +502,7 @@ static struct metadata_area_ops _metadata_format1_ops = { static struct format_instance *_create_instance(const struct format_type *fmt, const char *vgname, + const char *vgid, void *private) { struct format_instance *fid; diff --git a/lib/format1/import-export.c b/lib/format1/import-export.c index edb8853cd..5af0f45e6 100644 --- a/lib/format1/import-export.c +++ b/lib/format1/import-export.c @@ -49,7 +49,8 @@ static char *_create_lv_name(struct dm_pool *mem, const char *full_name) int import_pv(struct dm_pool *mem, struct device *dev, struct volume_group *vg, - struct physical_volume *pv, struct pv_disk *pvd) + struct physical_volume *pv, struct pv_disk *pvd, + struct vg_disk *vgd) { memset(pv, 0, sizeof(*pv)); memcpy(&pv->id, pvd->pv_uuid, ID_LEN); @@ -60,6 +61,8 @@ int import_pv(struct dm_pool *mem, struct device *dev, return 0; } + memcpy(&pv->vgid, vgd->vg_uuid, sizeof(vg->id)); + /* Store system_id from first PV if PV belongs to a VG */ if (vg && !*vg->system_id) strncpy(vg->system_id, pvd->system_id, NAME_LEN); @@ -426,7 +429,7 @@ int import_pvs(const struct format_type *fmt, struct dm_pool *mem, return 0; } - if (!import_pv(mem, dl->dev, vg, pvl->pv, &dl->pvd)) { + if (!import_pv(mem, dl->dev, vg, pvl->pv, &dl->pvd, &dl->vgd)) { stack; return 0; } diff --git a/lib/format_pool/format_pool.c b/lib/format_pool/format_pool.c index 6cae1040e..858ca0827 100644 --- a/lib/format_pool/format_pool.c +++ b/lib/format_pool/format_pool.c @@ -268,6 +268,7 @@ static struct metadata_area_ops _metadata_format_pool_ops = { static struct format_instance *_create_instance(const struct format_type *fmt, const char *vgname, + const char *vgid, void *private) { struct format_instance *fid; diff --git a/lib/format_pool/import_export.c b/lib/format_pool/import_export.c index 688d24bf9..e6f609999 100644 --- a/lib/format_pool/import_export.c +++ b/lib/format_pool/import_export.c @@ -165,6 +165,7 @@ int import_pool_pv(const struct format_type *fmt, struct dm_pool *mem, log_error("Unable to duplicate vg_name string"); return 0; } + memcpy(&pv->vgid, &vg->id, sizeof(vg->id)); pv->status = 0; pv->size = pd->pl_blocks; pv->pe_size = POOL_PE_SIZE; diff --git a/lib/format_text/archive.c b/lib/format_text/archive.c index a13f1af45..13265fef3 100644 --- a/lib/format_text/archive.c +++ b/lib/format_text/archive.c @@ -311,7 +311,7 @@ static void _display_archive(struct cmd_context *cmd, struct archive_file *af) if (!(context = create_text_context(cmd, af->path, NULL)) || !(tf = cmd->fmt_backup->ops->create_instance(cmd->fmt_backup, NULL, - context))) { + NULL, context))) { log_error("Couldn't create text instance object."); return; } diff --git a/lib/format_text/archiver.c b/lib/format_text/archiver.c index efd7a0499..5c6c6ef87 100644 --- a/lib/format_text/archiver.c +++ b/lib/format_text/archiver.c @@ -257,7 +257,7 @@ struct volume_group *backup_read_vg(struct cmd_context *cmd, if (!(context = create_text_context(cmd, file, cmd->cmd_line)) || !(tf = cmd->fmt_backup->ops->create_instance(cmd->fmt_backup, NULL, - context))) { + NULL, context))) { log_error("Couldn't create text format object."); return NULL; } @@ -286,7 +286,7 @@ int backup_restore_vg(struct cmd_context *cmd, struct volume_group *vg) /* Attempt to write out using currently active format */ if (!(vg->fid = cmd->fmt->ops->create_instance(cmd->fmt, vg->name, - NULL))) { + NULL, NULL))) { log_error("Failed to allocate format instance"); return 0; } @@ -365,7 +365,7 @@ int backup_to_file(const char *file, const char *desc, struct volume_group *vg) if (!(context = create_text_context(cmd, file, desc)) || !(tf = cmd->fmt_backup->ops->create_instance(cmd->fmt_backup, NULL, - context))) { + NULL, context))) { log_error("Couldn't create backup object."); return 0; } diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c index c88554310..2f27bb0f7 100644 --- a/lib/format_text/format-text.c +++ b/lib/format_text/format-text.c @@ -41,6 +41,7 @@ static struct format_instance *_create_text_instance(const struct format_type *fmt, const char *vgname, + const char *vgid, void *context); struct text_fid_context { @@ -219,7 +220,7 @@ static struct raw_locn *_find_vg_rlocn(struct device_area *dev_area, error: if ((info = info_from_pvid(dev_area->dev->pvid))) - lvmcache_update_vgname_and_id(info, ORPHAN, NULL, 0); + lvmcache_update_vgname_and_id(info, ORPHAN, ORPHAN, 0); return NULL; } @@ -858,7 +859,8 @@ static int _scan_file(const struct format_type *fmt) } /* FIXME stat file to see if it's changed */ - fid = _create_text_instance(fmt, NULL, NULL); + fid = _create_text_instance(fmt, NULL, NULL, + NULL); if ((vg = _vg_read_file_name(fid, vgname, path))) lvmcache_update_vg(vg); @@ -1271,7 +1273,7 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name, /* Have we already cached vgname? */ if (info->vginfo && info->vginfo->vgname && *info->vginfo->vgname && get_pv_from_vg_by_id(info->fmt, info->vginfo->vgname, - info->dev->pvid, pv)) { + info->vginfo->vgid, info->dev->pvid, pv)) { return 1; } @@ -1282,6 +1284,7 @@ static int _pv_read(const struct format_type *fmt, const char *pv_name, if (info->vginfo && info->vginfo->vgname && *info->vginfo->vgname && get_pv_from_vg_by_id(info->fmt, info->vginfo->vgname, + info->vginfo->vgid, info->dev->pvid, pv)) { return 1; } @@ -1476,6 +1479,7 @@ static int _pv_setup(const struct format_type *fmt, /* NULL vgname means use only the supplied context e.g. an archive file */ static struct format_instance *_create_text_instance(const struct format_type *fmt, const char *vgname, + const char *vgid, void *context) { struct format_instance *fid; @@ -1561,7 +1565,7 @@ static struct format_instance *_create_text_instance(const struct format_type /* Scan PVs in VG for any further MDAs */ lvmcache_label_scan(fmt->cmd, 0); - if (!(vginfo = vginfo_from_vgname(vgname, NULL))) { + if (!(vginfo = vginfo_from_vgname(vgname, vgid))) { stack; goto out; } diff --git a/lib/format_text/import_vsn1.c b/lib/format_text/import_vsn1.c index f9af12844..4b8ca914d 100644 --- a/lib/format_text/import_vsn1.c +++ b/lib/format_text/import_vsn1.c @@ -167,6 +167,8 @@ static int _read_pv(struct format_instance *fid, struct dm_pool *mem, return 0; } + memcpy(&pv->vgid, &vg->id, sizeof(vg->id)); + if (!(cn = find_config_node(pvn, "status"))) { log_error("Couldn't find status flags for physical volume."); return 0; diff --git a/lib/label/label.c b/lib/label/label.c index c74f22942..21f641bad 100644 --- a/lib/label/label.c +++ b/lib/label/label.c @@ -175,7 +175,7 @@ static struct labeller *_find_labeller(struct device *dev, char *buf, out: if (!found) { if ((info = info_from_pvid(dev->pvid))) - lvmcache_update_vgname_and_id(info, ORPHAN, NULL, 0); + lvmcache_update_vgname_and_id(info, ORPHAN, ORPHAN, 0); log_very_verbose("%s: No label detected", dev_name(dev)); } @@ -267,7 +267,7 @@ int label_read(struct device *dev, struct label **result) stack; if ((info = info_from_pvid(dev->pvid))) - lvmcache_update_vgname_and_id(info, ORPHAN, NULL, 0); + lvmcache_update_vgname_and_id(info, ORPHAN, ORPHAN, 0); goto out; } @@ -348,7 +348,7 @@ int label_verify(struct device *dev) stack; if ((info = info_from_pvid(dev->pvid))) - lvmcache_update_vgname_and_id(info, ORPHAN, NULL, 0); + lvmcache_update_vgname_and_id(info, ORPHAN, ORPHAN, 0); goto out; } diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c index 168fe8adb..c878974d6 100644 --- a/lib/metadata/metadata.c +++ b/lib/metadata/metadata.c @@ -71,6 +71,8 @@ static int _add_pv_to_vg(struct format_instance *fid, struct volume_group *vg, return 0; } + memcpy(&pv->vgid, &vg->id, sizeof(vg->id)); + /* Units of 512-byte sectors */ pv->pe_size = vg->extent_size; @@ -143,13 +145,14 @@ static int _copy_pv(struct physical_volume *pv_to, } int get_pv_from_vg_by_id(const struct format_type *fmt, const char *vg_name, - const char *id, struct physical_volume *pv) + const char *vgid, const char *pvid, + struct physical_volume *pv) { struct volume_group *vg; struct pv_list *pvl; int consistent = 0; - if (!(vg = vg_read(fmt->cmd, vg_name, &consistent))) { + if (!(vg = vg_read(fmt->cmd, vg_name, vgid, &consistent))) { log_error("get_pv_from_vg_by_id: vg_read failed to read VG %s", vg_name); return 0; @@ -160,7 +163,7 @@ int get_pv_from_vg_by_id(const struct format_type *fmt, const char *vg_name, vg_name); list_iterate_items(pvl, &vg->pvs) { - if (id_equal(&pvl->pv->id, (const struct id *) id)) { + if (id_equal(&pvl->pv->id, (const struct id *) pvid)) { if (!_copy_pv(pv, pvl->pv)) { stack; return 0; @@ -239,7 +242,7 @@ struct volume_group *vg_create(struct cmd_context *cmd, const char *vg_name, /* is this vg name already in use ? */ old_partial = partial_mode(); init_partial(1); - if (vg_read(cmd, vg_name, &consistent)) { + if (vg_read(cmd, vg_name, NULL, &consistent)) { log_err("A volume group called '%s' already exists.", vg_name); goto bad; } @@ -286,7 +289,7 @@ struct volume_group *vg_create(struct cmd_context *cmd, const char *vg_name, list_init(&vg->tags); if (!(vg->fid = cmd->fmt->ops->create_instance(cmd->fmt, vg_name, - NULL))) { + NULL, NULL))) { log_error("Failed to create format instance"); goto bad; } @@ -496,7 +499,7 @@ struct physical_volume *pv_create(const struct format_type *fmt, uint64_t pvmetadatasize, struct list *mdas) { struct dm_pool *mem = fmt->cmd->mem; - struct physical_volume *pv = dm_pool_alloc(mem, sizeof(*pv)); + struct physical_volume *pv = dm_pool_zalloc(mem, sizeof(*pv)); if (!pv) { stack; @@ -907,6 +910,7 @@ static struct volume_group *_vg_read_orphans(struct cmd_context *cmd) */ static struct volume_group *_vg_read(struct cmd_context *cmd, const char *vgname, + const char *vgid, int *consistent, int precommitted) { struct format_instance *fid; @@ -928,15 +932,15 @@ static struct volume_group *_vg_read(struct cmd_context *cmd, /* Find the vgname in the cache */ /* If it's not there we must do full scan to be completely sure */ - if (!(fmt = fmt_from_vgname(vgname))) { + if (!(fmt = fmt_from_vgname(vgname, vgid))) { lvmcache_label_scan(cmd, 0); - if (!(fmt = fmt_from_vgname(vgname))) { + if (!(fmt = fmt_from_vgname(vgname, vgid))) { if (memlock()) { stack; return NULL; } lvmcache_label_scan(cmd, 2); - if (!(fmt = fmt_from_vgname(vgname))) { + if (!(fmt = fmt_from_vgname(vgname, vgid))) { stack; return NULL; } @@ -947,7 +951,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd, use_precommitted = 0; /* create format instance with appropriate metadata area */ - if (!(fid = fmt->ops->create_instance(fmt, vgname, NULL))) { + if (!(fid = fmt->ops->create_instance(fmt, vgname, vgid, NULL))) { log_error("Failed to create format instance"); return NULL; } @@ -978,7 +982,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd, inconsistent = 0; lvmcache_label_scan(cmd, 2); - if (!(fmt = fmt_from_vgname(vgname))) { + if (!(fmt = fmt_from_vgname(vgname, vgid))) { stack; return NULL; } @@ -987,7 +991,7 @@ static struct volume_group *_vg_read(struct cmd_context *cmd, use_precommitted = 0; /* create format instance with appropriate metadata area */ - if (!(fid = fmt->ops->create_instance(fmt, vgname, NULL))) { + if (!(fid = fmt->ops->create_instance(fmt, vgname, vgid, NULL))) { log_error("Failed to create format instance"); return NULL; } @@ -1069,12 +1073,12 @@ static struct volume_group *_vg_read(struct cmd_context *cmd, } struct volume_group *vg_read(struct cmd_context *cmd, const char *vgname, - int *consistent) + const char *vgid, int *consistent) { struct volume_group *vg; struct lv_list *lvl; - if (!(vg = _vg_read(cmd, vgname, consistent, 0))) + if (!(vg = _vg_read(cmd, vgname, vgid, consistent, 0))) return NULL; if (!check_pv_segments(vg)) { @@ -1112,7 +1116,7 @@ static struct volume_group *_vg_read_by_vgid(struct cmd_context *cmd, /* Is corresponding vgname already cached? */ if ((vginfo = vginfo_from_vgid(vgid)) && vginfo->vgname && *vginfo->vgname) { - if ((vg = _vg_read(cmd, vginfo->vgname, + if ((vg = _vg_read(cmd, vginfo->vgname, vgid, &consistent, precommitted)) && !strncmp(vg->id.uuid, vgid, ID_LEN)) { if (!consistent) { @@ -1143,7 +1147,7 @@ static struct volume_group *_vg_read_by_vgid(struct cmd_context *cmd, if (!vgname || !*vgname) continue; // FIXME Unnecessary? consistent = 0; - if ((vg = _vg_read(cmd, vgname, &consistent, + if ((vg = _vg_read(cmd, vgname, vgid, &consistent, precommitted)) && !strncmp(vg->id.uuid, vgid, ID_LEN)) { if (!consistent) { @@ -1245,13 +1249,18 @@ struct list *get_vgs(struct cmd_context *cmd, int full_scan) return lvmcache_get_vgnames(cmd, full_scan); } +struct list *get_vgids(struct cmd_context *cmd, int full_scan) +{ + return lvmcache_get_vgids(cmd, full_scan); +} + struct list *get_pvs(struct cmd_context *cmd) { struct str_list *strl; struct list *results; - const char *vgname; + const char *vgname, *vgid; struct list *pvh, *tmp; - struct list *vgnames; + struct list *vgids; struct volume_group *vg; int consistent = 0; int old_partial; @@ -1267,7 +1276,7 @@ struct list *get_pvs(struct cmd_context *cmd) list_init(results); /* Get list of VGs */ - if (!(vgnames = get_vgs(cmd, 0))) { + if (!(vgids = get_vgids(cmd, 0))) { log_error("get_pvs: get_vgs failed"); return NULL; } @@ -1278,12 +1287,16 @@ struct list *get_pvs(struct cmd_context *cmd) old_pvmove = pvmove_mode(); init_partial(1); init_pvmove(1); - list_iterate_items(strl, vgnames) { - vgname = strl->str; - if (!vgname) + list_iterate_items(strl, vgids) { + vgid = strl->str; + if (!vgid) continue; /* FIXME Unnecessary? */ consistent = 0; - if (!(vg = vg_read(cmd, vgname, &consistent))) { + if (!(vgname = vgname_from_vgid(vgid))) { + stack; + continue; + } + if (!(vg = vg_read(cmd, vgname, vgid, &consistent))) { stack; continue; } diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h index 20459f045..1e5a43c9d 100644 --- a/lib/metadata/metadata.h +++ b/lib/metadata/metadata.h @@ -122,6 +122,7 @@ struct physical_volume { struct device *dev; const struct format_type *fmt; const char *vg_name; + struct id vgid; uint32_t status; uint64_t size; @@ -382,6 +383,7 @@ struct format_handler { */ struct format_instance *(*create_instance) (const struct format_type * fmt, const char *vgname, + const char *vgid, void *context); /* @@ -403,7 +405,7 @@ int vg_write(struct volume_group *vg); int vg_commit(struct volume_group *vg); int vg_revert(struct volume_group *vg); struct volume_group *vg_read(struct cmd_context *cmd, const char *vg_name, - int *consistent); + const char *vgid, int *consistent); struct physical_volume *pv_read(struct cmd_context *cmd, const char *pv_name, struct list *mdas, uint64_t *label_sector, int warnings); @@ -411,6 +413,7 @@ struct list *get_pvs(struct cmd_context *cmd); /* Set full_scan to 1 to re-read every (filtered) device label */ struct list *get_vgs(struct cmd_context *cmd, int full_scan); +struct list *get_vgids(struct cmd_context *cmd, int full_scan); int pv_write(struct cmd_context *cmd, struct physical_volume *pv, struct list *mdas, int64_t label_sector); @@ -478,7 +481,8 @@ struct pv_list *find_pv_in_vg(struct volume_group *vg, const char *pv_name); struct physical_volume *find_pv_in_vg_by_uuid(struct volume_group *vg, struct id *id); int get_pv_from_vg_by_id(const struct format_type *fmt, const char *vg_name, - const char *id, struct physical_volume *pv); + const char *vgid, const char *pvid, + struct physical_volume *pv); /* Find an LV within a given VG */ struct lv_list *find_lv_in_vg(struct volume_group *vg, const char *lv_name); diff --git a/tools/lvconvert.c b/tools/lvconvert.c index 316a2ea7e..2ea13f618 100644 --- a/tools/lvconvert.c +++ b/tools/lvconvert.c @@ -470,7 +470,7 @@ int lvconvert(struct cmd_context * cmd, int argc, char **argv) return ECMD_FAILED; } - if (!(vg = vg_read(cmd, lp.vg_name, &consistent))) { + if (!(vg = vg_read(cmd, lp.vg_name, NULL, &consistent))) { log_error("Volume group \"%s\" doesn't exist", lp.vg_name); goto error; } diff --git a/tools/lvcreate.c b/tools/lvcreate.c index afd9eb5a6..440902e43 100644 --- a/tools/lvcreate.c +++ b/tools/lvcreate.c @@ -444,7 +444,7 @@ static int _lvcreate(struct cmd_context *cmd, struct lvcreate_params *lp) /* does VG exist? */ log_verbose("Finding volume group \"%s\"", lp->vg_name); - if (!(vg = vg_read(cmd, lp->vg_name, &consistent))) { + if (!(vg = vg_read(cmd, lp->vg_name, NULL, &consistent))) { log_error("Volume group \"%s\" doesn't exist", lp->vg_name); return 0; } diff --git a/tools/lvrename.c b/tools/lvrename.c index b55c774a3..c538a9b04 100644 --- a/tools/lvrename.c +++ b/tools/lvrename.c @@ -106,7 +106,7 @@ int lvrename(struct cmd_context *cmd, int argc, char **argv) return ECMD_FAILED; } - if (!(vg = vg_read(cmd, vg_name, &consistent))) { + if (!(vg = vg_read(cmd, vg_name, NULL, &consistent))) { log_error("Volume group \"%s\" doesn't exist", vg_name); goto error; } diff --git a/tools/lvresize.c b/tools/lvresize.c index fc9724695..48fa77887 100644 --- a/tools/lvresize.c +++ b/tools/lvresize.c @@ -133,7 +133,7 @@ static int _lvresize(struct cmd_context *cmd, struct lvresize_params *lp) char size_buf[SIZE_BUF]; char lv_path[PATH_MAX]; - if (!(vg = vg_read(cmd, lp->vg_name, &consistent))) { + if (!(vg = vg_read(cmd, lp->vg_name, NULL, &consistent))) { log_error("Volume group %s doesn't exist", lp->vg_name); return ECMD_FAILED; } diff --git a/tools/pvchange.c b/tools/pvchange.c index 1526a03b2..dc9439bae 100644 --- a/tools/pvchange.c +++ b/tools/pvchange.c @@ -60,7 +60,7 @@ static int _pvchange_single(struct cmd_context *cmd, struct physical_volume *pv, return 0; } - if (!(vg = vg_read(cmd, pv->vg_name, &consistent))) { + if (!(vg = vg_read(cmd, pv->vg_name, NULL, &consistent))) { unlock_vg(cmd, pv->vg_name); log_error("Unable to find volume group of \"%s\"", pv_name); diff --git a/tools/pvmove.c b/tools/pvmove.c index ee9d9d4c0..50a5d1c9c 100644 --- a/tools/pvmove.c +++ b/tools/pvmove.c @@ -62,7 +62,7 @@ static struct volume_group *_get_vg(struct cmd_context *cmd, const char *vgname) return NULL; } - if (!(vg = vg_read(cmd, vgname, &consistent)) || !consistent) { + if (!(vg = vg_read(cmd, vgname, NULL, &consistent)) || !consistent) { log_error("Volume group \"%s\" doesn't exist", vgname); unlock_vg(cmd, vgname); return NULL; diff --git a/tools/pvresize.c b/tools/pvresize.c index 0a73fcef6..5458426db 100644 --- a/tools/pvresize.c +++ b/tools/pvresize.c @@ -70,7 +70,7 @@ static int _pvresize_single(struct cmd_context *cmd, return ECMD_FAILED; } - if (!(vg = vg_read(cmd, vg_name, &consistent))) { + if (!(vg = vg_read(cmd, vg_name, NULL, &consistent))) { unlock_vg(cmd, vg_name); log_error("Unable to find volume group of \"%s\"", pv_name); diff --git a/tools/reporter.c b/tools/reporter.c index f478c06ed..26fddaa26 100644 --- a/tools/reporter.c +++ b/tools/reporter.c @@ -65,7 +65,7 @@ static int _pvsegs_sub_single(struct cmd_context *cmd, struct volume_group *vg, return ECMD_FAILED; } - if (!(vg = vg_read(cmd, pv->vg_name, &consistent))) { + if (!(vg = vg_read(cmd, pv->vg_name, NULL, &consistent))) { log_error("Can't read %s: skipping", pv->vg_name); unlock_vg(cmd, pv->vg_name); return ECMD_FAILED; @@ -106,7 +106,7 @@ static int _pvs_single(struct cmd_context *cmd, struct volume_group *vg, return ECMD_FAILED; } - if (!(vg = vg_read(cmd, pv->vg_name, &consistent))) { + if (!(vg = vg_read(cmd, pv->vg_name, (char *)&pv->vgid, &consistent))) { log_error("Can't read %s: skipping", pv->vg_name); unlock_vg(cmd, pv->vg_name); return ECMD_FAILED; diff --git a/tools/toollib.c b/tools/toollib.c index 90805a6f6..0850a2e13 100644 --- a/tools/toollib.c +++ b/tools/toollib.c @@ -241,7 +241,7 @@ int process_each_lv(struct cmd_context *cmd, int argc, char **argv, consistent = 1; else consistent = 0; - if (!(vg = vg_read(cmd, vgname, &consistent)) || !consistent) { + if (!(vg = vg_read(cmd, vgname, NULL, &consistent)) || !consistent) { unlock_vg(cmd, vgname); if (!vg) log_error("Volume group \"%s\" " @@ -331,6 +331,7 @@ int process_each_segment_in_lv(struct cmd_context *cmd, } static int _process_one_vg(struct cmd_context *cmd, const char *vg_name, + const char *vgid, struct list *tags, struct list *arg_vgnames, int lock_type, int consistent, void *handle, int ret_max, @@ -348,7 +349,7 @@ static int _process_one_vg(struct cmd_context *cmd, const char *vg_name, } log_verbose("Finding volume group \"%s\"", vg_name); - vg = vg_read(cmd, vg_name, &consistent); + vg = vg_read(cmd, vg_name, vgid, &consistent); if (!list_empty(tags)) { /* Only process if a tag matches or it's on arg_vgnames */ @@ -380,10 +381,10 @@ int process_each_vg(struct cmd_context *cmd, int argc, char **argv, int ret_max = 0; struct str_list *sl; - struct list *vgnames; + struct list *vgnames, *vgids; struct list arg_vgnames, tags; - const char *vg_name; + const char *vg_name, *vgid; char *dev_dir = cmd->dev_dir; list_init(&tags); @@ -433,19 +434,29 @@ int process_each_vg(struct cmd_context *cmd, int argc, char **argv, if (!argc || !list_empty(&tags)) { log_verbose("Finding all volume groups"); - if (!(vgnames = get_vgs(cmd, 0)) || list_empty(vgnames)) { + if (!(vgids = get_vgids(cmd, 0)) || list_empty(vgids)) { log_error("No volume groups found"); return ret_max; } - } - - list_iterate_items(sl, vgnames) { - vg_name = sl->str; - if (!vg_name || !*vg_name) - continue; /* FIXME Unnecessary? */ - ret_max = _process_one_vg(cmd, vg_name, &tags, &arg_vgnames, - lock_type, consistent, handle, - ret_max, process_single); + list_iterate_items(sl, vgids) { + vgid = sl->str; + if (!vgid || !(vg_name = vgname_from_vgid(vgid)) || !*vg_name) + continue; + ret_max = _process_one_vg(cmd, vg_name, vgid, &tags, + &arg_vgnames, + lock_type, consistent, handle, + ret_max, process_single); + } + } else { + list_iterate_items(sl, vgnames) { + vg_name = sl->str; + if (!vg_name || !*vg_name) + continue; /* FIXME Unnecessary? */ + ret_max = _process_one_vg(cmd, vg_name, NULL, &tags, + &arg_vgnames, + lock_type, consistent, handle, + ret_max, process_single); + } } return ret_max; @@ -581,7 +592,7 @@ int process_each_pv(struct cmd_context *cmd, int argc, char **argv, if (!list_empty(&tags) && (vgnames = get_vgs(cmd, 0)) && !list_empty(vgnames)) { list_iterate_items(sll, vgnames) { - vg = vg_read(cmd, sll->str, &consistent); + vg = vg_read(cmd, sll->str, NULL, &consistent); if (!consistent) continue; ret = process_each_pv_in_vg(cmd, vg, &tags, @@ -966,7 +977,7 @@ struct volume_group *recover_vg(struct cmd_context *cmd, const char *vgname, return NULL; } - return vg_read(cmd, vgname, &consistent); + return vg_read(cmd, vgname, NULL, &consistent); } int apply_lvname_restrictions(const char *name) @@ -1045,7 +1056,7 @@ int zero_lv(struct cmd_context *cmd, struct logical_volume *lv) * also, more than 4k * say, reiserfs puts it's superblock 32k in, IIRC * k, I'll drop a fixme to that effect - * (I know the device is at least 4k, but not 32k) + * (I know the device is at least 4k, but not 32k) */ if (!(name = dm_pool_alloc(cmd->mem, PATH_MAX))) { log_error("Name allocation failed - device not zeroed"); diff --git a/tools/vgexport.c b/tools/vgexport.c index 19cad55f7..bff93bb5d 100644 --- a/tools/vgexport.c +++ b/tools/vgexport.c @@ -19,6 +19,9 @@ static int vgexport_single(struct cmd_context *cmd, const char *vg_name, struct volume_group *vg, int consistent, void *handle) { + struct pv_list *pvl; + struct physical_volume *pv; + if (!vg) { log_error("Unable to find volume group \"%s\"", vg_name); goto error; @@ -50,6 +53,11 @@ static int vgexport_single(struct cmd_context *cmd, const char *vg_name, vg->status |= EXPORTED_VG; + list_iterate_items(pvl, &vg->pvs) { + pv = pvl->pv; + pv->status |= EXPORTED_VG; + } + if (!vg_write(vg) || !vg_commit(vg)) goto error; diff --git a/tools/vgextend.c b/tools/vgextend.c index 581601679..825964987 100644 --- a/tools/vgextend.c +++ b/tools/vgextend.c @@ -48,7 +48,7 @@ int vgextend(struct cmd_context *cmd, int argc, char **argv) goto error; } - if (!(vg = vg_read(cmd, vg_name, &consistent)) || !consistent) { + if (!(vg = vg_read(cmd, vg_name, NULL, &consistent)) || !consistent) { log_error("Volume group \"%s\" not found.", vg_name); goto error; } diff --git a/tools/vgimport.c b/tools/vgimport.c index cc470b175..d95ef8d09 100644 --- a/tools/vgimport.c +++ b/tools/vgimport.c @@ -19,6 +19,9 @@ static int vgimport_single(struct cmd_context *cmd, const char *vg_name, struct volume_group *vg, int consistent, void *handle) { + struct pv_list *pvl; + struct physical_volume *pv; + if (!vg || !consistent) { log_error("Unable to find exported volume group \"%s\"", vg_name); @@ -40,6 +43,11 @@ static int vgimport_single(struct cmd_context *cmd, const char *vg_name, vg->status &= ~EXPORTED_VG; + list_iterate_items(pvl, &vg->pvs) { + pv = pvl->pv; + pv->status &= ~EXPORTED_VG; + } + if (!vg_write(vg) || !vg_commit(vg)) goto error; diff --git a/tools/vgmerge.c b/tools/vgmerge.c index fb6447082..4402df375 100644 --- a/tools/vgmerge.c +++ b/tools/vgmerge.c @@ -35,7 +35,7 @@ static int _vgmerge_single(struct cmd_context *cmd, const char *vg_name_to, return ECMD_FAILED; } - if (!(vg_to = vg_read(cmd, vg_name_to, &consistent)) || !consistent) { + if (!(vg_to = vg_read(cmd, vg_name_to, NULL, &consistent)) || !consistent) { log_error("Volume group \"%s\" doesn't exist", vg_name_to); unlock_vg(cmd, vg_name_to); return ECMD_FAILED; @@ -61,7 +61,7 @@ static int _vgmerge_single(struct cmd_context *cmd, const char *vg_name_to, } consistent = 1; - if (!(vg_from = vg_read(cmd, vg_name_from, &consistent)) || !consistent) { + if (!(vg_from = vg_read(cmd, vg_name_from, NULL, &consistent)) || !consistent) { log_error("Volume group \"%s\" doesn't exist", vg_name_from); goto error; } diff --git a/tools/vgreduce.c b/tools/vgreduce.c index 613af287a..0c535c81e 100644 --- a/tools/vgreduce.c +++ b/tools/vgreduce.c @@ -432,7 +432,7 @@ int vgreduce(struct cmd_context *cmd, int argc, char **argv) return ECMD_FAILED; } - if ((!(vg = vg_read(cmd, vg_name, &consistent)) || !consistent) && + if ((!(vg = vg_read(cmd, vg_name, NULL, &consistent)) || !consistent) && !arg_count(cmd, removemissing_ARG)) { log_error("Volume group \"%s\" doesn't exist", vg_name); unlock_vg(cmd, vg_name); @@ -449,7 +449,7 @@ int vgreduce(struct cmd_context *cmd, int argc, char **argv) init_partial(1); consistent = 0; - if (!(vg = vg_read(cmd, vg_name, &consistent))) { + if (!(vg = vg_read(cmd, vg_name, NULL, &consistent))) { log_error("Volume group \"%s\" not found", vg_name); unlock_vg(cmd, vg_name); return ECMD_FAILED; diff --git a/tools/vgrename.c b/tools/vgrename.c index aff32d814..b06cd05da 100644 --- a/tools/vgrename.c +++ b/tools/vgrename.c @@ -69,7 +69,7 @@ int vgrename(struct cmd_context *cmd, int argc, char **argv) return ECMD_FAILED; } - if (!(vg_old = vg_read(cmd, vg_name_old, &consistent)) || !consistent) { + if (!(vg_old = vg_read(cmd, vg_name_old, NULL, &consistent)) || !consistent) { log_error("Volume group \"%s\" doesn't exist", vg_name_old); unlock_vg(cmd, vg_name_old); return ECMD_FAILED; @@ -104,7 +104,7 @@ int vgrename(struct cmd_context *cmd, int argc, char **argv) } consistent = 0; - if ((vg_new = vg_read(cmd, vg_name_new, &consistent))) { + if ((vg_new = vg_read(cmd, vg_name_new, NULL, &consistent))) { log_error("New volume group \"%s\" already exists", vg_name_new); goto error; diff --git a/tools/vgsplit.c b/tools/vgsplit.c index 16504b32d..025347804 100644 --- a/tools/vgsplit.c +++ b/tools/vgsplit.c @@ -190,7 +190,7 @@ int vgsplit(struct cmd_context *cmd, int argc, char **argv) return ECMD_FAILED; } - if (!(vg_from = vg_read(cmd, vg_name_from, &consistent)) || !consistent) { + if (!(vg_from = vg_read(cmd, vg_name_from, NULL, &consistent)) || !consistent) { log_error("Volume group \"%s\" doesn't exist", vg_name_from); unlock_vg(cmd, vg_name_from); return ECMD_FAILED; @@ -216,7 +216,7 @@ int vgsplit(struct cmd_context *cmd, int argc, char **argv) } consistent = 0; - if ((vg_to = vg_read(cmd, vg_name_to, &consistent))) { + if ((vg_to = vg_read(cmd, vg_name_to, NULL, &consistent))) { /* FIXME Remove this restriction */ log_error("Volume group \"%s\" already exists", vg_name_to); goto error; @@ -287,7 +287,7 @@ int vgsplit(struct cmd_context *cmd, int argc, char **argv) /* Remove EXPORTED flag from new VG */ consistent = 1; - if (!(vg_to = vg_read(cmd, vg_name_to, &consistent)) || !consistent) { + if (!(vg_to = vg_read(cmd, vg_name_to, NULL, &consistent)) || !consistent) { log_error("Volume group \"%s\" became inconsistent: please " "fix manually", vg_name_to); goto error;