This series fixes three related issues in o2hb_region_pin(), all are
from the original implementation in commit:
58a3158a5d17 ("ocfs2/cluster: Pin/unpin o2hb regions"):
1) It is called with o2hb_live_lock (a spinlock) held, but the
underlying configfs_depend_item() sleeps (takes inode rwsem and
pins the filesystem). This triggers BUG under
CONFIG_DEBUG_ATOMIC_SLEEP.
2) When called from the configfs drop_item callback, it creates a
lock order inversion: parent inode_lock -> configfs root
inode_lock, which can deadlock against subsystem unregistration
paths taking root -> parent.
3) If pinning fails partway through o2hb_region_inc_user(), the
o2hb_dependent_users counter is leaked and partially-pinned
regions are never released, leaving heartbeat regions
unprotected on subsequent mounts.
Patch 1 reworks o2hb_region_pin() to drop o2hb_live_lock across
each sleeping configfs_depend_item() call, using a config_item
reference to keep the region alive while unlocked.
Patch 2 adds a from_callback parameter to select
configfs_depend_item_unlocked() when called from configfs context,
avoiding the inode_lock nesting.
Patch 3 fixes the error path in o2hb_region_inc_user() to unpin
and decrement the counter on failure.
Joseph Qi (3):
ocfs2: cluster: don't sleep while holding o2hb_live_lock in
o2hb_region_pin()
ocfs2: cluster: avoid lock order inversion in o2hb_region_pin() from
drop_item
ocfs2: cluster: fix o2hb_dependent_users leak on pin failure
fs/ocfs2/cluster/heartbeat.c | 146 ++++++++++++++++++++++++++-------
fs/ocfs2/cluster/nodemanager.c | 6 ++
fs/ocfs2/cluster/nodemanager.h | 1 +
3 files changed, 122 insertions(+), 31 deletions(-)
--
2.39.3