From ca9cbd92c40affa5ea5597de2d0ebd18382d9dab Mon Sep 17 00:00:00 2001 From: Zdenek Kabelac Date: Tue, 27 Feb 2018 14:13:00 +0100 Subject: [PATCH] activation: add base lv component function Introduce: lv_is_component() check is LV is actually a component device. lv_component_is_active() checking if any component device is active. lv_holder_is_active() is any component holding device is active. --- WHATS_NEW | 1 + lib/activate/activate.c | 111 ++++++++++++++++++++++++++++++- lib/activate/activate.h | 7 +- lib/activate/dev_manager.c | 2 +- lib/metadata/metadata-exported.h | 11 +++ 5 files changed, 129 insertions(+), 3 deletions(-) diff --git a/WHATS_NEW b/WHATS_NEW index b282caa8d..9656da722 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,6 @@ Version 2.02.178 - ===================================== + Extend internal library to recognize and work with component LV. Skip duplicate check for active LV when prompting for its removal. Activate correct lock holding LV when it is cached. Do not modify archived metadata when removing striped raid. diff --git a/lib/activate/activate.c b/lib/activate/activate.c index f5e9ef962..aa230fe88 100644 --- a/lib/activate/activate.c +++ b/lib/activate/activate.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. - * Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved. + * Copyright (C) 2004-2018 Red Hat, Inc. All rights reserved. * * This file is part of LVM2. * @@ -2860,3 +2860,112 @@ void activation_exit(void) dev_manager_exit(); } #endif + +static int _component_cb(struct logical_volume *lv, void *data) +{ + struct logical_volume **component_lv = (struct logical_volume **) data; + + if (lv_is_locked(lv) || lv_is_pvmove(lv) ||/* ignoring */ + /* thin-pool is special and it's using layered device */ + (lv_is_thin_pool(lv) && pool_is_active(lv))) + return -1; + + if (lv_is_active(lv)) { + if (!lv_is_component(lv) || lv_is_visible(lv)) + return -1; /* skip whole subtree */ + + log_debug_activation("Found active component LV %s.", display_lvname(lv)); + *component_lv = lv; + return 0; /* break any further processing */ + } + + return 1; +} + +/* + * Finds out for any LV if any of its component LVs are active. + * Function first checks if an existing LV is visible and active eventually + * it's lock holding LV is already active. In such case sub LV cannot be + * actived alone and no further checking is needed. + * + * Returns active component LV if there is such. + */ +const struct logical_volume *lv_component_is_active(const struct logical_volume *lv) +{ + const struct logical_volume *component_lv = NULL; + const struct logical_volume *holder_lv = lv_lock_holder(lv); + + if ((holder_lv != lv) && lv_is_active(holder_lv)) + return NULL; /* Lock holding LV is active, do not check components */ + + if (_component_cb((struct logical_volume *) lv, &holder_lv) == 1) + (void) for_each_sub_lv((struct logical_volume *) lv, _component_cb, + (void*) &component_lv); + + return component_lv; +} + +/* + * Finds out if any LV above is active, as stacked device tree can be composed of + * chained set of LVs. + * + * Returns active holder LV if there is such. + */ +const struct logical_volume *lv_holder_is_active(const struct logical_volume *lv) +{ + const struct logical_volume *holder; + const struct seg_list *sl; + + if (lv_is_locked(lv) || lv_is_pvmove(lv)) + return NULL; /* Skip pvmove/locked LV tracking */ + + dm_list_iterate_items(sl, &lv->segs_using_this_lv) { + /* Recursive call for upper-stack holder */ + if ((holder = lv_holder_is_active(sl->seg->lv))) + return holder; + + if (lv_is_active(sl->seg->lv)) { + log_debug_activation("Found active holder LV %s.", display_lvname(sl->seg->lv)); + return sl->seg->lv; + } + } + + return NULL; +} + +static int _deactivate_sub_lv_cb(struct logical_volume *lv, void *data) +{ + struct logical_volume **slv = data; + + if (lv_is_thin_pool(lv) || lv_is_external_origin(lv)) + return -1; + + if (!deactivate_lv(lv->vg->cmd, lv)) { + *slv = lv; + return 0; + } + + return 1; +} + +/* + * Deactivates LV toghether with explicit deactivation call made also for all its component LVs. + */ +int deactivate_lv_with_sub_lv(const struct logical_volume *lv) +{ + struct logical_volume *flv; + + if (!deactivate_lv(lv->vg->cmd, lv)) { + log_error("Cannot deactivate logical volume %s.", + display_lvname(lv)); + return 0; + } + + if (!for_each_sub_lv((struct logical_volume *)lv, _deactivate_sub_lv_cb, &flv)) { + log_error("Cannot deactivate subvolume %s of logical volume %s.", + display_lvname(flv), display_lvname(lv)); + return 0; + } + + return 1; +} diff --git a/lib/activate/activate.h b/lib/activate/activate.h index 8d068676b..dc4d3cdeb 100644 --- a/lib/activate/activate.h +++ b/lib/activate/activate.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. - * Copyright (C) 2004-2016 Red Hat, Inc. All rights reserved. + * Copyright (C) 2004-2018 Red Hat, Inc. All rights reserved. * * This file is part of LVM2. * @@ -198,6 +198,11 @@ int lv_is_active_exclusive(const struct logical_volume *lv); int lv_is_active_exclusive_locally(const struct logical_volume *lv); int lv_is_active_exclusive_remotely(const struct logical_volume *lv); +/* Check is any component LV is active */ +const struct logical_volume *lv_component_is_active(const struct logical_volume *lv); +const struct logical_volume *lv_holder_is_active(const struct logical_volume *lv); +int deactivate_lv_with_sub_lv(const struct logical_volume *lv); + int lv_has_target_type(struct dm_pool *mem, const struct logical_volume *lv, const char *layer, const char *target_type); diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c index 2faf1ccef..8bf0e47dc 100644 --- a/lib/activate/dev_manager.c +++ b/lib/activate/dev_manager.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved. - * Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved. + * Copyright (C) 2004-2018 Red Hat, Inc. All rights reserved. * * This file is part of LVM2. * diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h index 71df95553..cd7ff8acd 100644 --- a/lib/metadata/metadata-exported.h +++ b/lib/metadata/metadata-exported.h @@ -253,6 +253,17 @@ #define lv_is_removed(lv) (((lv)->status & LV_REMOVED) ? 1 : 0) +/* Recognize component LV (matching lib/misc/lvm-string.c _lvname_has_reserved_component_string()) */ +#define lv_is_component(lv) (lv_is_cache_origin(lv) || ((lv)->status & (\ + CACHE_POOL_DATA |\ + CACHE_POOL_METADATA |\ + MIRROR_IMAGE |\ + MIRROR_LOG |\ + RAID_IMAGE |\ + RAID_META |\ + THIN_POOL_DATA |\ + THIN_POOL_METADATA)) ? 1 : 0) + int lv_layout_and_role(struct dm_pool *mem, const struct logical_volume *lv, struct dm_list **layout, struct dm_list **role); -- 2.43.5