From 00a7c302ead32c0c38b7204db183d1b4388067dd Mon Sep 17 00:00:00 2001 From: Alasdair Kergon Date: Mon, 5 Nov 2007 17:17:55 +0000 Subject: [PATCH] Add pv_mda_free and vg_mda_free fields to reports for raw text format. --- WHATS_NEW | 2 ++ lib/format_text/format-text.c | 33 +++++++++++++++++++++--- lib/format_text/format-text.h | 3 ++- lib/format_text/layout.h | 1 + lib/format_text/text_label.c | 4 ++- lib/metadata/metadata.c | 2 +- lib/metadata/metadata.h | 6 +++++ lib/report/columns.h | 2 ++ lib/report/report.c | 47 +++++++++++++++++++++++++++++++++++ 9 files changed, 93 insertions(+), 7 deletions(-) diff --git a/WHATS_NEW b/WHATS_NEW index d74443c41..58fe520c4 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,7 @@ Version 2.02.29 - ================================== + Fix human-readable output of odd numbers of sectors. + Add pv_mda_free and vg_mda_free fields to reports for raw text format. Add LVM2 version to 'Generated by' comment in metadata. Show 'not usable' space when PV is too large for device in pvdisplay. Ignore and fix up any excessive device size found in metadata. diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c index e2fd9faf3..c83d7a821 100644 --- a/lib/format_text/format-text.c +++ b/lib/format_text/format-text.c @@ -83,6 +83,13 @@ static int _text_vg_setup(struct format_instance *fid __attribute((unused)), return 1; } +static uint64_t _mda_free_sectors_raw(struct metadata_area *mda) +{ + struct mda_context *mdac = (struct mda_context *) mda->metadata_locn; + + return mdac->free_sectors; +} + /* * Check if metadata area belongs to vg */ @@ -1043,7 +1050,8 @@ 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, char **creation_host) + uint32_t *vgstatus, char **creation_host, + uint64_t *mda_free_sectors) { struct raw_locn *rlocn; struct mda_header *mdah; @@ -1052,6 +1060,10 @@ const char *vgname_from_mda(const struct format_type *fmt, unsigned int len = 0; char buf[NAME_LEN + 1] __attribute((aligned(8))); char uuid[64] __attribute((aligned(8))); + uint64_t buffer_size, current_usage; + + if (mda_free_sectors) + *mda_free_sectors = ((dev_area->size - MDA_HEADER_SIZE) / 2) >> SECTOR_SHIFT; if (!dev_open(dev_area->dev)) { stack; @@ -1114,9 +1126,21 @@ const char *vgname_from_mda(const struct format_type *fmt, } log_debug("%s: Found metadata at %" PRIu64 " size %" PRIu64 - " for %s (%s)", + " (in area at %" PRIu64 " size %" PRIu64 + ") for %s (%s)", dev_name(dev_area->dev), dev_area->start + rlocn->offset, - rlocn->size, vgname, uuid); + rlocn->size, dev_area->start, dev_area->size, vgname, uuid); + + if (mda_free_sectors) { + current_usage = (rlocn->size + SECTOR_SIZE - UINT64_C(1)) - + (rlocn->size + SECTOR_SIZE - UINT64_C(1)) % SECTOR_SIZE; + buffer_size = mdah->size - MDA_HEADER_SIZE; + + if (current_usage * 2 >= buffer_size) + *mda_free_sectors = UINT64_C(0); + else + *mda_free_sectors = ((buffer_size - 2 * current_usage) / 2) >> SECTOR_SHIFT; + } out: if (!dev_close(dev_area->dev)) @@ -1143,7 +1167,7 @@ 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, - NULL))) { + NULL, NULL))) { if ((vg = _vg_read_raw_area(&fid, vgname, &rl->dev_area, 0))) lvmcache_update_vg(vg); @@ -1557,6 +1581,7 @@ static struct metadata_area_ops _metadata_text_raw_ops = { .vg_precommit = _vg_precommit_raw, .vg_commit = _vg_commit_raw, .vg_revert = _vg_revert_raw, + .mda_free_sectors = _mda_free_sectors_raw, .mda_in_vg = _mda_in_vg_raw, .pv_analyze_mda = _pv_analyze_mda_raw, }; diff --git a/lib/format_text/format-text.h b/lib/format_text/format-text.h index 247af634a..9d7f86233 100644 --- a/lib/format_text/format-text.h +++ b/lib/format_text/format-text.h @@ -57,6 +57,7 @@ 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, char **creation_host); + uint32_t *vgstatus, char **creation_host, + uint64_t *mda_free_sectors); #endif diff --git a/lib/format_text/layout.h b/lib/format_text/layout.h index 3fc0417e8..675eba951 100644 --- a/lib/format_text/layout.h +++ b/lib/format_text/layout.h @@ -75,6 +75,7 @@ struct mda_lists { struct mda_context { struct device_area area; + uint64_t free_sectors; struct raw_locn rlocn; /* Store inbetween write and commit */ }; diff --git a/lib/format_text/text_label.c b/lib/format_text/text_label.c index af5b8285b..ac78cec30 100644 --- a/lib/format_text/text_label.c +++ b/lib/format_text/text_label.c @@ -162,6 +162,7 @@ int add_mda(const struct format_type *fmt, struct dm_pool *mem, struct list *mda mdac->area.dev = dev; mdac->area.start = start; mdac->area.size = size; + mdac->free_sectors = UINT64_C(0); memset(&mdac->rlocn, 0, sizeof(mdac->rlocn)); list_add(mdas, &mdal->list); @@ -239,7 +240,8 @@ static int _text_read(struct labeller *l, struct device *dev, void *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, &creation_host)) && + &vgid, &vgstatus, &creation_host, + &mdac->free_sectors)) && !lvmcache_update_vgname_and_id(info, vgname, (char *) &vgid, vgstatus, creation_host)) diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c index 68844d6f5..a10009b1a 100644 --- a/lib/metadata/metadata.c +++ b/lib/metadata/metadata.c @@ -1820,7 +1820,7 @@ int pv_write_orphan(struct cmd_context *cmd, struct physical_volume *pv) */ int is_orphan_vg(const char *vg_name) { - return (vg_name[0] ? 0 : 1); + return (!strcmp(vg_name, ORPHAN) ? 1 : 0); } /** diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h index 78ec97812..1904343e2 100644 --- a/lib/metadata/metadata.h +++ b/lib/metadata/metadata.h @@ -113,6 +113,12 @@ struct metadata_area_ops { struct volume_group * vg, struct metadata_area * mda); int (*vg_remove) (struct format_instance * fi, struct volume_group * vg, struct metadata_area * mda); + + /* + * Returns number of free sectors in given metadata area. + */ + uint64_t (*mda_free_sectors) (struct metadata_area *mda); + /* * Check if metadata area belongs to vg */ diff --git a/lib/report/columns.h b/lib/report/columns.h index 75e37a063..58d24aac3 100644 --- a/lib/report/columns.h +++ b/lib/report/columns.h @@ -48,6 +48,7 @@ FIELD(PVS, pv, NUM, "PE", pe_count, 3, uint32, "pv_pe_count", "Total number of P FIELD(PVS, pv, NUM, "Alloc", pe_alloc_count, 5, uint32, "pv_pe_alloc_count", "Total number of allocated Physical Extents.") FIELD(PVS, pv, STR, "PV Tags", tags, 7, tags, "pv_tags", "Tags, if any.") FIELD(PVS, pv, NUM, "#PMda", id, 5, pvmdas, "pv_mda_count", "Number of metadata areas on this device.") +FIELD(PVS, pv, NUM, "#PMdaFree", id, 9, pvmdafree, "pv_mda_free", "Free metadata area space on this device in current units.") FIELD(VGS, vg, STR, "Fmt", cmd, 3, vgfmt, "vg_fmt", "Type of metadata.") FIELD(VGS, vg, STR, "VG UUID", id, 38, uuid, "vg_uuid", "Unique identifier.") @@ -67,6 +68,7 @@ FIELD(VGS, vg, NUM, "#SN", snapshot_count, 3, uint32, "snap_count", "Number of s FIELD(VGS, vg, NUM, "Seq", seqno, 3, uint32, "vg_seqno", "Revision number of internal metadata. Incremented whenever it changes.") FIELD(VGS, vg, STR, "VG Tags", tags, 7, tags, "vg_tags", "Tags, if any.") FIELD(VGS, vg, NUM, "#VMda", cmd, 5, vgmdas, "vg_mda_count", "Number of metadata areas in use by this VG.") +FIELD(VGS, vg, NUM, "#VMdaFree", cmd, 9, vgmdafree, "vg_mda_free", "Free metadata area space for this VG in current units.") FIELD(SEGS, seg, STR, "Type", list, 4, segtype, "segtype", "Type of LV segment") FIELD(SEGS, seg, NUM, "#Str", area_count, 4, uint32, "stripes", "Number of stripes or mirror legs.") diff --git a/lib/report/report.c b/lib/report/report.c index 96b2d0ead..776ed03cc 100644 --- a/lib/report/report.c +++ b/lib/report/report.c @@ -745,6 +745,53 @@ static int _vgmdas_disp(struct dm_report *rh, struct dm_pool *mem, return _uint32_disp(rh, mem, field, &count, private); } +static int _pvmdafree_disp(struct dm_report *rh, struct dm_pool *mem, + struct dm_report_field *field, + const void *data, void *private) +{ + struct lvmcache_info *info; + uint64_t freespace = UINT64_MAX, mda_free; + const char *pvid = (const char *)(&((struct id *) data)->uuid); + struct metadata_area *mda; + + info = info_from_pvid(pvid); + + list_iterate_items(mda, &info->mdas) { + if (!mda->ops->mda_free_sectors) + continue; + mda_free = mda->ops->mda_free_sectors(mda); + if (mda_free < freespace) + freespace = mda_free; + } + + if (freespace == UINT64_MAX) + freespace = UINT64_C(0); + + return _size64_disp(rh, mem, field, &freespace, private); +} + +static int _vgmdafree_disp(struct dm_report *rh, struct dm_pool *mem, + struct dm_report_field *field, + const void *data, void *private) +{ + const struct volume_group *vg = (const struct volume_group *) data; + uint64_t freespace = UINT64_MAX, mda_free; + struct metadata_area *mda; + + list_iterate_items(mda, &vg->fid->metadata_areas) { + if (!mda->ops->mda_free_sectors) + continue; + mda_free = mda->ops->mda_free_sectors(mda); + if (mda_free < freespace) + freespace = mda_free; + } + + if (freespace == UINT64_MAX) + freespace = UINT64_C(0); + + return _size64_disp(rh, mem, field, &freespace, private); +} + static int _lvsegcount_disp(struct dm_report *rh, struct dm_pool *mem, struct dm_report_field *field, const void *data, void *private)