From 9ad0f81084cca4be9b7de3f2c8f0c6ecb1d51f6c Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Fri, 9 Mar 2018 11:30:45 -0800 Subject: [PATCH] scoutfs: add some lock/item consistency checks Add some tests to the locking paths to see if we violate item caching rules. As we finish locking calls we make sure that the item cache is consistent with the lock mode. And we make sure that we don't free locks before they've been unlocked and had a chance to check the item cache. Signed-off-by: Zach Brown --- kmod/src/lock.c | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/kmod/src/lock.c b/kmod/src/lock.c index e3178bc8..d5eeced1 100644 --- a/kmod/src/lock.c +++ b/kmod/src/lock.c @@ -178,6 +178,7 @@ static void lock_free(struct lock_info *linfo, struct scoutfs_lock *lock) trace_scoutfs_lock_free(sb, lock); scoutfs_inc_counter(sb, lock_free); + BUG_ON(!linfo->shutdown && lock->granted_mode != DLM_LOCK_IV); BUG_ON(delayed_work_pending(&lock->grace_work)); if (lock->debug_locks_id) @@ -542,6 +543,8 @@ static void scoutfs_lock_ast(void *arg) struct super_block *sb = lock->sb; DECLARE_LOCK_INFO(sb, linfo); int status = lock->lksb.sb_status; + bool cached; + bool dirty; scoutfs_inc_counter(sb, lock_ast); @@ -571,8 +574,41 @@ static void scoutfs_lock_ast(void *arg) lock->work_mode = DLM_LOCK_IV; trace_scoutfs_lock_ast(sb, lock); - lock_process(linfo, lock); + /* + * Catch lock modes with cached items that violate the item + * cache consistency rules. + * + * We can never have dirty items if we're calling the dlm and + * changing lock modes. We can't have cached items if we're not + * in the two modes that allow caching. + */ + cached = lock->start && scoutfs_item_range_cached(sb, lock->start, + lock->end, false); + dirty = lock->start && scoutfs_item_range_cached(sb, lock->start, + lock->end, true); + if (WARN_ON_ONCE(dirty || + (cached && lock->granted_mode != DLM_LOCK_PR && + lock->granted_mode != DLM_LOCK_EX))) { + scoutfs_err_sk(sb, "lock item cache consistency violation, cached %u dirty %u: name "LN_FMT" start "SK_FMT" end "SK_FMT" refresh_gen %llu error %d granted %d bast %d prev %d work %d waiters: pr %u ex %u cw %u users: pr %u ex %u cw %u dlmlksb: status %d lkid 0x%x flags 0x%x\n", + cached, dirty, + LN_ARG(&lock->name), SK_ARG(lock->start), + SK_ARG(lock->end), lock->refresh_gen, lock->error, + lock->granted_mode, lock->bast_mode, + lock->work_prev_mode, lock->work_mode, + lock->waiters[DLM_LOCK_PR], + lock->waiters[DLM_LOCK_EX], + lock->waiters[DLM_LOCK_CW], + lock->users[DLM_LOCK_PR], + lock->users[DLM_LOCK_EX], + lock->users[DLM_LOCK_CW], + lock->lksb.sb_status, + lock->lksb.sb_lkid, + lock->lksb.sb_flags); + BUG(); + } + + lock_process(linfo, lock); spin_unlock(&linfo->lock); }