diff --git a/WHATS_NEW b/WHATS_NEW index 66d770bbf..97ca66519 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,7 @@ Version 2.02.03 - =================================== + When choosing between identically-named VGs, also consider creation_host. + Provide total log suppression with 2. 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. diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c index 89ba9cf24..3832d9c72 100644 --- a/lib/cache/lvmcache.c +++ b/lib/cache/lvmcache.c @@ -364,6 +364,8 @@ static int _drop_vginfo(struct lvmcache_info *info) if (info->vginfo->vgname) dm_free(info->vginfo->vgname); + if (info->vginfo->creation_host) + dm_free(info->vginfo->creation_host); if (*info->vginfo->vgid) dm_hash_remove(_vgid_hash, info->vginfo->vgid); list_del(&info->vginfo->list); @@ -434,11 +436,12 @@ 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, + uint32_t vgstatus, const char *creation_host, struct lvmcache_vginfo *primary_vginfo) { struct lvmcache_vginfo *last_vginfo = primary_vginfo; char uuid_primary[64], uuid_new[64]; + int use_new = 0; /* Pre-existing VG takes precedence. Unexported VG takes precedence. */ if (primary_vginfo) { @@ -449,21 +452,56 @@ static int _insert_vginfo(struct lvmcache_vginfo *new_vginfo, const char *vgid, sizeof(uuid_primary))) return_0; - if (!(primary_vginfo->status & EXPORTED_VG) || - (vgstatus & EXPORTED_VG)) { - while (last_vginfo->next) - last_vginfo = last_vginfo->next; - last_vginfo->next = new_vginfo; + /* + * If Primary not exported, new exported => keep + * Else Primary exported, new not exported => change + * Else Primary has hostname for this machine => keep + * Else Primary has no hostname, new has one => change + * Else New has hostname for this machine => change + * Else Keep primary. + */ + if (!(primary_vginfo->status & EXPORTED_VG) && + (vgstatus & EXPORTED_VG)) + log_error("WARNING: Duplicate VG name %s: " + "Existing %s takes precedence over " + "exported %s", new_vginfo->vgname, + uuid_primary, uuid_new); + else if ((primary_vginfo->status & EXPORTED_VG) && + !(vgstatus & EXPORTED_VG)) { log_error("WARNING: Duplicate VG name %s: " - "%s takes precedence over %s", - new_vginfo->vgname, uuid_primary, - uuid_new); - return 1; - } else - log_error("WARNING: Duplicate VG name %s: Existing " "%s takes precedence over exported %s", new_vginfo->vgname, uuid_new, uuid_primary); + use_new = 1; + } else if (primary_vginfo->creation_host && + !strcmp(primary_vginfo->creation_host, + primary_vginfo->fmt->cmd->hostname)) + log_error("WARNING: Duplicate VG name %s: " + "Existing %s (created here) takes precedence " + "over %s", new_vginfo->vgname, uuid_primary, + uuid_new); + else if (!primary_vginfo->creation_host && creation_host) { + log_error("WARNING: Duplicate VG name %s: " + "%s (with creation_host) takes precedence over %s", + new_vginfo->vgname, uuid_new, + uuid_primary); + use_new = 1; + } else if (creation_host && + !strcmp(creation_host, + primary_vginfo->fmt->cmd->hostname)) { + log_error("WARNING: Duplicate VG name %s: " + "%s (created here) takes precedence over %s", + new_vginfo->vgname, uuid_new, + uuid_primary); + use_new = 1; + } + + if (!use_new) { + while (last_vginfo->next) + last_vginfo = last_vginfo->next; + last_vginfo->next = new_vginfo; + return 1; + } dm_hash_remove(_vgname_hash, primary_vginfo->vgname); } @@ -482,7 +520,7 @@ 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, - uint32_t vgstatus) + uint32_t vgstatus, const char *creation_host) { struct lvmcache_vginfo *vginfo, *primary_vginfo; @@ -515,7 +553,8 @@ 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, vgstatus, primary_vginfo)) { + if (!_insert_vginfo(vginfo, vgid, vgstatus, creation_host, + primary_vginfo)) { dm_free(vginfo->vgname); dm_free(vginfo); return 0; @@ -542,28 +581,49 @@ static int _lvmcache_update_vgname(struct lvmcache_info *info, return 1; } -static int _lvmcache_update_vgstatus(struct lvmcache_info *info, uint32_t vgstatus) +static int _lvmcache_update_vgstatus(struct lvmcache_info *info, uint32_t vgstatus, + const char *creation_host) { if (!info || !info->vginfo) return 1; if ((info->vginfo->status & EXPORTED_VG) != (vgstatus & EXPORTED_VG)) - log_debug("lvmcache: %s: VG %s exported", - dev_name(info->dev), + log_debug("lvmcache: %s: VG %s %s exported", + dev_name(info->dev), info->vginfo->vgname, vgstatus & EXPORTED_VG ? "now" : "no longer"); info->vginfo->status = vgstatus; + if (!creation_host) + return 1; + + if (info->vginfo->creation_host && !strcmp(creation_host, + info->vginfo->creation_host)) + return 1; + + if (info->vginfo->creation_host) + dm_free(info->vginfo->creation_host); + + if (!(info->vginfo->creation_host = dm_strdup(creation_host))) { + log_error("cache creation host alloc failed for %s", + creation_host); + return 0; + } + + log_debug("lvmcache: %s: VG %s: Set creation host to %s.", + dev_name(info->dev), info->vginfo->vgname, creation_host); + return 1; } int lvmcache_update_vgname_and_id(struct lvmcache_info *info, const char *vgname, const char *vgid, - uint32_t vgstatus) + uint32_t vgstatus, const char *creation_host) { - if (!_lvmcache_update_vgname(info, vgname, vgid, vgstatus) || + if (!_lvmcache_update_vgname(info, vgname, vgid, vgstatus, + creation_host) || !_lvmcache_update_vgid(info, vgid) || - !_lvmcache_update_vgstatus(info, vgstatus)) + !_lvmcache_update_vgstatus(info, vgstatus, creation_host)) return_0; return 1; @@ -583,7 +643,7 @@ int lvmcache_update_vg(struct volume_group *vg) if ((info = info_from_pvid(pvid_s)) && !lvmcache_update_vgname_and_id(info, vg->name, (char *) &vg->id, - vg->status)) + vg->status, NULL)) return_0; } @@ -689,7 +749,7 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid, return NULL; } - if (!lvmcache_update_vgname_and_id(info, vgname, vgid, vgstatus)) { + if (!lvmcache_update_vgname_and_id(info, vgname, vgid, vgstatus, NULL)) { if (!existing) { dm_hash_remove(_pvid_hash, pvid_s); strcpy(info->dev->pvid, ""); @@ -719,6 +779,8 @@ static void _lvmcache_destroy_vgnamelist(struct lvmcache_vginfo *vginfo) next = vginfo->next; if (vginfo->vgname) dm_free(vginfo->vgname); + if (vginfo->creation_host) + dm_free(vginfo->creation_host); dm_free(vginfo); } while ((vginfo = next)); } diff --git a/lib/cache/lvmcache.h b/lib/cache/lvmcache.h index 385ea830e..9bf9255ee 100644 --- a/lib/cache/lvmcache.h +++ b/lib/cache/lvmcache.h @@ -43,6 +43,7 @@ struct lvmcache_vginfo { char vgid[ID_LEN + 1]; char _padding[7]; struct lvmcache_vginfo *next; /* Another VG with same name? */ + char *creation_host; }; /* One per device */ @@ -75,7 +76,7 @@ void lvmcache_del(struct lvmcache_info *info); /* Update things */ int lvmcache_update_vgname_and_id(struct lvmcache_info *info, const char *vgname, const char *vgid, - uint32_t vgstatus); + uint32_t vgstatus, const char *hostname); 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 2f27bb0f7..57f2010e3 100644 --- a/lib/format_text/format-text.c +++ b/lib/format_text/format-text.c @@ -220,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, ORPHAN, 0); + lvmcache_update_vgname_and_id(info, ORPHAN, ORPHAN, 0, NULL); return NULL; } @@ -863,6 +863,7 @@ static int _scan_file(const struct format_type *fmt) NULL); if ((vg = _vg_read_file_name(fid, vgname, path))) + /* FIXME Store creation host in vg */ lvmcache_update_vg(vg); } @@ -875,7 +876,7 @@ static int _scan_file(const struct format_type *fmt) const char *vgname_from_mda(const struct format_type *fmt, struct device_area *dev_area, struct id *vgid, - uint32_t *vgstatus) + uint32_t *vgstatus, char **creation_host) { struct raw_locn *rlocn; struct mda_header *mdah; @@ -928,7 +929,7 @@ const char *vgname_from_mda(const struct format_type *fmt, (off_t) (dev_area->start + MDA_HEADER_SIZE), wrap, calc_crc, rlocn->checksum, - vgid, vgstatus))) + vgid, vgstatus, creation_host))) goto_out; /* Ignore this entry if the characters aren't permissible */ @@ -967,7 +968,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 = vgname_from_mda(fmt, &rl->dev_area, &vgid, &vgstatus))) { + if ((vgname = vgname_from_mda(fmt, &rl->dev_area, &vgid, &vgstatus, + NULL))) { 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 358f32b98..e916b795b 100644 --- a/lib/format_text/format-text.h +++ b/lib/format_text/format-text.h @@ -56,6 +56,6 @@ void del_mdas(struct list *mdas); const char *vgname_from_mda(const struct format_type *fmt, struct device_area *dev_area, struct id *vgid, - uint32_t *vgstatus); + uint32_t *vgstatus, char **creation_host); #endif diff --git a/lib/format_text/import-export.h b/lib/format_text/import-export.h index bf00c7fc3..62d4245d8 100644 --- a/lib/format_text/import-export.h +++ b/lib/format_text/import-export.h @@ -49,7 +49,8 @@ struct text_vg_version_ops { time_t *when, char **desc); const char *(*read_vgname) (const struct format_type *fmt, struct config_tree *cft, - struct id *vgid, uint32_t *vgstatus); + struct id *vgid, uint32_t *vgstatus, + char **creation_host); }; struct text_vg_version_ops *text_vg_vsn1_init(void); @@ -78,6 +79,7 @@ const char *text_vgname_import(const struct format_type *fmt, off_t offset, uint32_t size, off_t offset2, uint32_t size2, checksum_fn_t checksum_fn, uint32_t checksum, - struct id *vgid, uint32_t *vgstatus); + struct id *vgid, uint32_t *vgstatus, + char **creation_host); #endif diff --git a/lib/format_text/import.c b/lib/format_text/import.c index f2b7cf1a8..67be3f0b4 100644 --- a/lib/format_text/import.c +++ b/lib/format_text/import.c @@ -28,7 +28,8 @@ const char *text_vgname_import(const struct format_type *fmt, off_t offset, uint32_t size, off_t offset2, uint32_t size2, checksum_fn_t checksum_fn, uint32_t checksum, - struct id *vgid, uint32_t *vgstatus) + struct id *vgid, uint32_t *vgstatus, + char **creation_host) { struct config_tree *cft; struct text_vg_version_ops **vsn; @@ -57,7 +58,8 @@ const char *text_vgname_import(const struct format_type *fmt, if (!(*vsn)->check_version(cft)) continue; - if (!(vgname = (*vsn)->read_vgname(fmt, cft, vgid, vgstatus))) + if (!(vgname = (*vsn)->read_vgname(fmt, cft, vgid, vgstatus, + creation_host))) goto_out; break; diff --git a/lib/format_text/import_vsn1.c b/lib/format_text/import_vsn1.c index 4b8ca914d..9dc52c08e 100644 --- a/lib/format_text/import_vsn1.c +++ b/lib/format_text/import_vsn1.c @@ -802,11 +802,18 @@ static void _read_desc(struct dm_pool *mem, static const char *_read_vgname(const struct format_type *fmt, struct config_tree *cft, struct id *vgid, - uint32_t *vgstatus) + uint32_t *vgstatus, char **creation_host) { struct config_node *vgn, *cn; struct dm_pool *mem = fmt->cmd->mem; char *vgname; + int old_suppress; + + old_suppress = log_suppress(2); + *creation_host = dm_pool_strdup(mem, + find_config_str(cft->root, + "creation_host", "")); + log_suppress(old_suppress); /* skip any top-level values */ for (vgn = cft->root; (vgn && vgn->v); vgn = vgn->sib) ; diff --git a/lib/format_text/text_label.c b/lib/format_text/text_label.c index 144fbf987..ad92dbf6a 100644 --- a/lib/format_text/text_label.c +++ b/lib/format_text/text_label.c @@ -199,6 +199,7 @@ static int _read(struct labeller *l, struct device *dev, char *buf, struct mda_context *mdac; const char *vgname; uint32_t vgstatus; + char *creation_host; pvhdr = (struct pv_header *) ((void *) buf + xlate32(lh->offset_xl)); @@ -235,9 +236,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 = vgname_from_mda(info->fmt, &mdac->area, - &vgid, &vgstatus)) && + &vgid, &vgstatus, &creation_host)) && !lvmcache_update_vgname_and_id(info, vgname, - (char *) &vgid, vgstatus)) + (char *) &vgid, vgstatus, + creation_host)) return_0; } diff --git a/lib/label/label.c b/lib/label/label.c index 21f641bad..3f7c2f655 100644 --- a/lib/label/label.c +++ b/lib/label/label.c @@ -175,7 +175,8 @@ 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, ORPHAN, 0); + lvmcache_update_vgname_and_id(info, ORPHAN, ORPHAN, + 0, NULL); log_very_verbose("%s: No label detected", dev_name(dev)); } @@ -267,7 +268,8 @@ int label_read(struct device *dev, struct label **result) stack; if ((info = info_from_pvid(dev->pvid))) - lvmcache_update_vgname_and_id(info, ORPHAN, ORPHAN, 0); + lvmcache_update_vgname_and_id(info, ORPHAN, ORPHAN, + 0, NULL); goto out; } @@ -348,7 +350,8 @@ int label_verify(struct device *dev) stack; if ((info = info_from_pvid(dev->pvid))) - lvmcache_update_vgname_and_id(info, ORPHAN, ORPHAN, 0); + lvmcache_update_vgname_and_id(info, ORPHAN, ORPHAN, + 0, NULL); goto out; } diff --git a/lib/log/log.c b/lib/log/log.c index e1c301462..80501f97d 100644 --- a/lib/log/log.c +++ b/lib/log/log.c @@ -90,9 +90,13 @@ void init_syslog(int facility) _syslog = 1; } -void log_suppress(int suppress) +int log_suppress(int suppress) { + int old_suppress = _log_suppress; + _log_suppress = suppress; + + return old_suppress; } void release_log_memory(void) @@ -253,6 +257,9 @@ void print_log(int level, const char *file, int line, const char *format, ...) const char *message; const char *trformat; /* Translated format string */ + if (_log_suppress == 2) + return; + trformat = _(format); if (_lvm2_log_fn) { diff --git a/lib/log/log.h b/lib/log/log.h index 36eed30fd..7db9ea04e 100644 --- a/lib/log/log.h +++ b/lib/log/log.h @@ -86,8 +86,9 @@ int ignorelockingfailure(void); int lockingfailed(void); int security_level(void); -/* Suppress messages to stdout/stderr */ -void log_suppress(int suppress); +/* Suppress messages to stdout/stderr (1) or everywhere (2) */ +/* Returns previous setting */ +int log_suppress(int suppress); /* Suppress messages to syslog */ void syslog_suppress(int suppress);