diff --git a/lib/metadata/lv.c b/lib/metadata/lv.c index 41de7a5d1..283b8c498 100644 --- a/lib/metadata/lv.c +++ b/lib/metadata/lv.c @@ -745,6 +745,12 @@ char *lv_active_dup(struct dm_pool *mem, const struct logical_volume *lv) { const char *s; + if (vg_is_clustered(lv->vg)) { + //const struct logical_volume *lvo = lv; + lv = lv_lock_holder(lv); + //log_debug("Holder for %s => %s.", lvo->name, lv->name); + } + if (!lv_is_active(lv)) s = ""; /* not active */ else if (!vg_is_clustered(lv->vg)) @@ -755,7 +761,39 @@ char *lv_active_dup(struct dm_pool *mem, const struct logical_volume *lv) "local exclusive" : "remote exclusive"; else /* locally active */ s = lv_is_active_but_not_locally(lv) ? - "remotely" : "locally"; + "remotely" : "locally"; return dm_pool_strdup(mem, s); } + +/* For given LV find recursively the LV which holds lock for it */ +const struct logical_volume *lv_lock_holder(const struct logical_volume *lv) +{ + const struct seg_list *sl; + + if (lv_is_cow(lv)) + return lv_lock_holder(origin_from_cow(lv)); + + if (lv_is_thin_pool(lv)) + /* Find any active LV from the pool */ + dm_list_iterate_items(sl, &lv->segs_using_this_lv) + if (lv_is_active(sl->seg->lv)) { + log_debug("Thin volume \"%s\" is active.", sl->seg->lv->name); + return sl->seg->lv; + } + + /* For other types, by default look for the first user */ + dm_list_iterate_items(sl, &lv->segs_using_this_lv) { + /* FIXME: complete this exception list */ + if (lv_is_thin_volume(lv) && + lv_is_thin_volume(sl->seg->lv) && + first_seg(lv)->pool_lv == sl->seg->pool_lv) + continue; /* Skip thin snaphost */ + if (lv_is_external_origin(lv) && + lv_is_thin_volume(sl->seg->lv)) + continue; /* Skip external origin */ + return lv_lock_holder(sl->seg->lv); + } + + return lv; +} diff --git a/lib/metadata/lv.h b/lib/metadata/lv.h index bac8bc2ee..ed0d7452d 100644 --- a/lib/metadata/lv.h +++ b/lib/metadata/lv.h @@ -90,4 +90,5 @@ const char *lv_layer(const struct logical_volume *lv); int lv_active_change(struct cmd_context *cmd, struct logical_volume *lv, activation_change_t activate); char *lv_active_dup(struct dm_pool *mem, const struct logical_volume *lv); +const struct logical_volume *lv_lock_holder(const struct logical_volume *lv); #endif /* _LVM_LV_H */