From bc1adc32cbd593dd1839526da82521b429b13141 Mon Sep 17 00:00:00 2001 From: Zdenek Kabelac Date: Wed, 28 Feb 2018 17:00:33 +0100 Subject: [PATCH] lv_manip: enhance for_each_sub_lv Fix missing 'externalLV' traversing for thins with external origins. Replace extra for_each_sub_lv_except_pools() with better internal logic allowing selectively to cut of processed subLV tree. Extend error code for function 'fn()' when it returns -1 it will stop futher tree scan for given LV. Also a bit simplify code to have only one place that is calling 'fn()' and use level counter to know depth of traversing. Update renaming travering to skip trees for pools and external origins. --- WHATS_NEW | 1 + lib/metadata/lv_manip.c | 72 ++++++++++++++++++++--------------------- lib/metadata/metadata.h | 3 -- 3 files changed, 37 insertions(+), 39 deletions(-) diff --git a/WHATS_NEW b/WHATS_NEW index 57919306b..6a0a0dcde 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,6 @@ Version 2.02.178 - ===================================== + Add external_origin visiting in for_each_sub_lv(). Ensure cluster commands drop their device cache before locking VG. Do not report LV as remotely active when it's locally exclusive in cluster. Add deprecate messages for usage of mirrors with mirrorlog. diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c index ac30dadeb..35c805ce3 100644 --- a/lib/metadata/lv_manip.c +++ b/lib/metadata/lv_manip.c @@ -4341,53 +4341,62 @@ static int _rename_cb(struct logical_volume *lv, void *data) return _rename_sub_lv(lv, lv_names->old, lv_names->new); } +static int _rename_skip_pools_externals_cb(struct logical_volume *lv, void *data) +{ + if (lv_is_pool(lv) || lv_is_external_origin(lv)) + return -1; /* and skip subLVs */ + + return _rename_cb(lv, data); +} + /* * Loop down sub LVs and call fn for each. * fn is responsible to log necessary information on failure. + * Return value '0' stops whole traversal. + * Return value '-1' stops subtree traversal. */ -static int _for_each_sub_lv(struct logical_volume *lv, int skip_pools, +static int _for_each_sub_lv(struct logical_volume *lv, int level, int (*fn)(struct logical_volume *lv, void *data), void *data) { struct logical_volume *org; struct lv_segment *seg; uint32_t s; + int r; + + if (!lv) + return 1; + + if (level++) { + if (!(r = fn(lv, data))) + return_0; + /* Only r == 1 lets you run for_each... */ + if (r == -1) + return 1; + } if (lv_is_cow(lv) && lv_is_virtual_origin(org = origin_from_cow(lv))) { - if (!fn(org, data)) - return_0; - if (!_for_each_sub_lv(org, skip_pools, fn, data)) + if (!_for_each_sub_lv(org, level, fn, data)) return_0; } dm_list_iterate_items(seg, &lv->segments) { - if (seg->log_lv) { - if (!fn(seg->log_lv, data)) - return_0; - if (!_for_each_sub_lv(seg->log_lv, skip_pools, fn, data)) - return_0; - } + if (!_for_each_sub_lv(seg->external_lv, level, fn, data)) + return_0; - if (seg->metadata_lv) { - if (!fn(seg->metadata_lv, data)) - return_0; - if (!_for_each_sub_lv(seg->metadata_lv, skip_pools, fn, data)) - return_0; - } + if (!_for_each_sub_lv(seg->log_lv, level, fn, data)) + return_0; - if (seg->pool_lv && !skip_pools) { - if (!fn(seg->pool_lv, data)) - return_0; - if (!_for_each_sub_lv(seg->pool_lv, skip_pools, fn, data)) - return_0; - } + if (!_for_each_sub_lv(seg->metadata_lv, level, fn, data)) + return_0; + + if (!_for_each_sub_lv(seg->pool_lv, level, fn, data)) + return_0; for (s = 0; s < seg->area_count; s++) { if (seg_type(seg, s) != AREA_LV) continue; - if (!fn(seg_lv(seg, s), data)) - return_0; - if (!_for_each_sub_lv(seg_lv(seg, s), skip_pools, fn, data)) + if (!_for_each_sub_lv(seg_lv(seg, s), level, fn, data)) return_0; } @@ -4398,9 +4407,7 @@ static int _for_each_sub_lv(struct logical_volume *lv, int skip_pools, for (s = 0; s < seg->area_count; s++) { if ((seg_metatype(seg, s) != AREA_LV) || !seg_metalv(seg, s)) continue; - if (!fn(seg_metalv(seg, s), data)) - return_0; - if (!_for_each_sub_lv(seg_metalv(seg, s), skip_pools, fn, data)) + if (!_for_each_sub_lv(seg_metalv(seg, s), level, fn, data)) return_0; } } @@ -4415,13 +4422,6 @@ int for_each_sub_lv(struct logical_volume *lv, return _for_each_sub_lv(lv, 0, fn, data); } -int for_each_sub_lv_except_pools(struct logical_volume *lv, - int (*fn)(struct logical_volume *lv, void *data), - void *data) -{ - return _for_each_sub_lv(lv, 1, fn, data); -} - /* * Core of LV renaming routine. * VG must be locked by caller. @@ -4475,7 +4475,7 @@ int lv_rename_update(struct cmd_context *cmd, struct logical_volume *lv, } /* rename sub LVs */ - if (!for_each_sub_lv_except_pools(lv, _rename_cb, (void *) &lv_names)) + if (!for_each_sub_lv(lv, _rename_skip_pools_externals_cb, (void *) &lv_names)) return_0; /* rename main LV */ diff --git a/lib/metadata/metadata.h b/lib/metadata/metadata.h index df660a73b..f6b19f44b 100644 --- a/lib/metadata/metadata.h +++ b/lib/metadata/metadata.h @@ -444,9 +444,6 @@ int add_glv_to_indirect_glvs(struct dm_pool *mem, int remove_glv_from_indirect_glvs(struct generic_logical_volume *origin_glv, struct generic_logical_volume *glv); -int for_each_sub_lv_except_pools(struct logical_volume *lv, - int (*fn)(struct logical_volume *lv, void *data), - void *data); int for_each_sub_lv(struct logical_volume *lv, int (*fn)(struct logical_volume *lv, void *data), void *data);