From e803b10bca1539aed13a1ab8a9cf540a5d120347 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Fri, 12 Jan 2018 12:53:23 -0800 Subject: [PATCH] scoutfs: drop lock refcnt/users under task ref If scoutfs_unlock() sees that it isn't the last task using a lock it just returns. It doesn't unlock the lock and it doesn't drop the lock refcnt and users. This leaks the lock refcnt and users because find_alloc_scoutfs_lock() always increments them when it finds a lock. Inflated counts will stop the shrinker from freeing the locks and eventually the counts will wrap and could cause locks to be freed while they're still in use. We can either always drop the refcnt/users in unlock or we can drop them in lock as we notice that our task already has the lock. I chose to have the task ref hold one refcnt/users which are only dropped as the final task unlocks. Signed-off-by: Zach Brown --- kmod/src/lock.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kmod/src/lock.c b/kmod/src/lock.c index 128afa96..4d347c7b 100644 --- a/kmod/src/lock.c +++ b/kmod/src/lock.c @@ -732,6 +732,8 @@ static int lock_name_keys(struct super_block *sb, int mode, int flags, */ BUG_ON(!ocfs2_levels_compat(&lock->lockres, mode)); get_task_ref(ref); + dec_lock_users(lock); + put_scoutfs_lock(sb, lock); ret = 0; goto out; }