{
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))
"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;
+}