[lvm-devel] [PATCH 28/35] Implement _vg_metadata_balance and call from vg_write() path.
Dave Wysochanski
dwysocha at redhat.com
Tue Jun 22 03:06:01 UTC 2010
Implement metadata balancing by comparing the value of the
newly added vg_mda_copies field (--vgmetadatacopies parameter)
with the current count of of non-ignored mdas and ignoring or
unignoring mdas as necessary to get to the target count.
Also, as a safety check before returning, ensure we have at
least one mda enabled.
Signed-off-by: Dave Wysochanski <dwysocha at redhat.com>
---
lib/metadata/metadata.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 88 insertions(+), 0 deletions(-)
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index a597f3c..6f4cf60 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -58,6 +58,8 @@ static struct pv_list *_find_pv_in_vg_by_uuid(const struct volume_group *vg,
static uint32_t _vg_bad_status_bits(const struct volume_group *vg,
uint64_t status);
+static int _vg_metadata_balance(struct volume_group *vg);
+
const char _really_init[] =
"Really INITIALIZE physical volume \"%s\" of volume group \"%s\" [y/n]? ";
@@ -989,6 +991,91 @@ static int _recalc_extents(uint32_t *extents, const char *desc1,
return 1;
}
+static int _vg_ignore_mdas(struct volume_group *vg, uint32_t count)
+{
+ struct metadata_area *mda;
+
+ if (!count)
+ return 1;
+ /* FIXME: flip bits on random mdas */
+ dm_list_iterate_items(mda, &vg->fid->metadata_areas) {
+ if (!mda_is_ignored(mda)) {
+ mda_set_ignored(mda, 1);
+ count--;
+ }
+ if (!count)
+ return 1;
+ }
+ log_error("Unable to find %"PRIu32" metadata areas to ignore "
+ "on volume group %s", count, vg->name);
+ return 0;
+}
+
+static int _vg_unignore_mdas(struct volume_group *vg, uint32_t count)
+{
+ struct metadata_area *mda, *tmda;
+
+ if (!count)
+ return 1;
+ /* FIXME: flip bits on random mdas */
+ dm_list_iterate_items_safe(mda, tmda, &vg->fid->metadata_areas_ignored) {
+ if (mda_is_ignored(mda)) {
+ mda_set_ignored(mda, 0);
+ dm_list_move(&vg->fid->metadata_areas, &mda->list);
+ count--;
+ }
+ if (!count)
+ return 1;
+ }
+ dm_list_iterate_items(mda, &vg->fid->metadata_areas) {
+ if (mda_is_ignored(mda)) {
+ mda_set_ignored(mda, 0);
+ count--;
+ }
+ if (!count)
+ return 1;
+ }
+ log_error("Unable to find %"PRIu32" metadata areas to un-ignore "
+ "on volume group %s", count, vg->name);
+ return 0;
+}
+
+static int _vg_metadata_balance(struct volume_group *vg)
+{
+ uint32_t mda_copies, count;
+ int ret = 1;
+
+ mda_copies = vg_mda_count(vg) - vg_mda_count_ignored(vg);
+ if (!vg->mda_copies)
+ goto skip_balance;
+
+ if (mda_copies > vg->mda_copies) {
+ ret = _vg_ignore_mdas(vg, mda_copies - vg->mda_copies);
+ } else if (mda_copies < vg->mda_copies) {
+ /* not an error to have vg_mda_count larger than total mdas */
+ if (vg->mda_copies >= vg_mda_count(vg))
+ count = vg_mda_count_ignored(vg);
+ else
+ count = vg->mda_copies - mda_copies;
+ ret = _vg_unignore_mdas(vg, count);
+ }
+ if (!ret)
+ return ret;
+
+skip_balance:
+ /*
+ * Ensure at least one enabled mda.
+ * FIXME: check size of fid->metadata_areas; reason is because of how
+ * pv_setup works in the case of a pv with 2 mdas, one ignored and
+ * another not ignored; function needs refactoring to be correct.
+ */
+ if (!dm_list_size(&vg->fid->metadata_areas) ||
+ vg_mda_count(vg) == vg_mda_count_ignored(vg)) {
+ ret = _vg_unignore_mdas(vg, 1);
+ }
+ return ret;
+}
+
uint32_t vg_mda_copies(const struct volume_group *vg)
{
return vg->mda_copies;
@@ -2378,6 +2465,7 @@ int vg_write(struct volume_group *vg)
return 0;
}
+ _vg_metadata_balance(vg);
if (dm_list_empty(&vg->fid->metadata_areas)) {
log_error("Aborting vg_write: No metadata areas to write to!");
--
1.6.0.6
More information about the lvm-devel
mailing list