[PATCH v2] ocfs2: kill osb->system_file_mutex lock

Tetsuo Handa posted 1 patch 1 week ago
fs/ocfs2/ocfs2.h   | 2 --
fs/ocfs2/super.c   | 2 --
fs/ocfs2/sysfile.c | 9 +++------
3 files changed, 3 insertions(+), 10 deletions(-)
[PATCH v2] ocfs2: kill osb->system_file_mutex lock
Posted by Tetsuo Handa 1 week ago
Commit 43b10a20372d ("ocfs2: avoid system inode ref confusion by adding
mutex lock") tried to avoid a refcount leak caused by allowing multiple
threads to call igrab(inode). But addition of osb->system_file_mutex made
locking dependency complicated and is causing lockdep to warn about
possibility of AB-BA deadlock.

Since _ocfs2_get_system_file_inode() returns the same inode for the same
input arguments, we don't need to serialize _ocfs2_get_system_file_inode().
What we need to make sure is that igrab(inode) is called for only once().
Therefore, replace osb->system_file_mutex with cmpxchg()-based locking.

Fixes: 43b10a20372d ("ocfs2: avoid system inode ref confusion by adding mutex lock")
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
---
Changes in v2:
  Updated patch description.

 fs/ocfs2/ocfs2.h   | 2 --
 fs/ocfs2/super.c   | 2 --
 fs/ocfs2/sysfile.c | 9 +++------
 3 files changed, 3 insertions(+), 10 deletions(-)

diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
index 7b50e03dfa66..62cad6522c7a 100644
--- a/fs/ocfs2/ocfs2.h
+++ b/fs/ocfs2/ocfs2.h
@@ -494,8 +494,6 @@ struct ocfs2_super
 	struct rb_root	osb_rf_lock_tree;
 	struct ocfs2_refcount_tree *osb_ref_tree_lru;
 
-	struct mutex system_file_mutex;
-
 	/*
 	 * OCFS2 needs to schedule several different types of work which
 	 * require cluster locking, disk I/O, recovery waits, etc. Since these
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index b875f01c9756..6dd45c2153f8 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -1997,8 +1997,6 @@ static int ocfs2_initialize_super(struct super_block *sb,
 	spin_lock_init(&osb->osb_xattr_lock);
 	ocfs2_init_steal_slots(osb);
 
-	mutex_init(&osb->system_file_mutex);
-
 	atomic_set(&osb->alloc_stats.moves, 0);
 	atomic_set(&osb->alloc_stats.local_data, 0);
 	atomic_set(&osb->alloc_stats.bitmap_data, 0);
diff --git a/fs/ocfs2/sysfile.c b/fs/ocfs2/sysfile.c
index d53a6cc866be..67e492f4b828 100644
--- a/fs/ocfs2/sysfile.c
+++ b/fs/ocfs2/sysfile.c
@@ -98,11 +98,9 @@ struct inode *ocfs2_get_system_file_inode(struct ocfs2_super *osb,
 	} else
 		arr = get_local_system_inode(osb, type, slot);
 
-	mutex_lock(&osb->system_file_mutex);
 	if (arr && ((inode = *arr) != NULL)) {
 		/* get a ref in addition to the array ref */
 		inode = igrab(inode);
-		mutex_unlock(&osb->system_file_mutex);
 		BUG_ON(!inode);
 
 		return inode;
@@ -112,11 +110,10 @@ struct inode *ocfs2_get_system_file_inode(struct ocfs2_super *osb,
 	inode = _ocfs2_get_system_file_inode(osb, type, slot);
 
 	/* add one more if putting into array for first time */
-	if (arr && inode) {
-		*arr = igrab(inode);
-		BUG_ON(!*arr);
+	if (inode && arr && !*arr && !cmpxchg(&(*arr), NULL, inode)) {
+		inode = igrab(inode);
+		BUG_ON(!inode);
 	}
-	mutex_unlock(&osb->system_file_mutex);
 	return inode;
 }
 
-- 
2.54.0
Re: [PATCH v2] ocfs2: kill osb->system_file_mutex lock
Posted by Heming Zhao 1 week ago
On Mon, May 18, 2026 at 01:23:40PM +0900, Tetsuo Handa wrote:
> Commit 43b10a20372d ("ocfs2: avoid system inode ref confusion by adding
> mutex lock") tried to avoid a refcount leak caused by allowing multiple
> threads to call igrab(inode). But addition of osb->system_file_mutex made
> locking dependency complicated and is causing lockdep to warn about
> possibility of AB-BA deadlock.
> 
> Since _ocfs2_get_system_file_inode() returns the same inode for the same
> input arguments, we don't need to serialize _ocfs2_get_system_file_inode().
> What we need to make sure is that igrab(inode) is called for only once().
> Therefore, replace osb->system_file_mutex with cmpxchg()-based locking.
> 
> Fixes: 43b10a20372d ("ocfs2: avoid system inode ref confusion by adding mutex lock")
> Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>

LGTM. Thanks for the patch.
Reviewed-by: Heming Zhao <heming.zhao@suse.com>
> ---
> Changes in v2:
>   Updated patch description.
> 
>  fs/ocfs2/ocfs2.h   | 2 --
>  fs/ocfs2/super.c   | 2 --
>  fs/ocfs2/sysfile.c | 9 +++------
>  3 files changed, 3 insertions(+), 10 deletions(-)
> 
> diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
> index 7b50e03dfa66..62cad6522c7a 100644
> --- a/fs/ocfs2/ocfs2.h
> +++ b/fs/ocfs2/ocfs2.h
> @@ -494,8 +494,6 @@ struct ocfs2_super
>  	struct rb_root	osb_rf_lock_tree;
>  	struct ocfs2_refcount_tree *osb_ref_tree_lru;
>  
> -	struct mutex system_file_mutex;
> -
>  	/*
>  	 * OCFS2 needs to schedule several different types of work which
>  	 * require cluster locking, disk I/O, recovery waits, etc. Since these
> diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
> index b875f01c9756..6dd45c2153f8 100644
> --- a/fs/ocfs2/super.c
> +++ b/fs/ocfs2/super.c
> @@ -1997,8 +1997,6 @@ static int ocfs2_initialize_super(struct super_block *sb,
>  	spin_lock_init(&osb->osb_xattr_lock);
>  	ocfs2_init_steal_slots(osb);
>  
> -	mutex_init(&osb->system_file_mutex);
> -
>  	atomic_set(&osb->alloc_stats.moves, 0);
>  	atomic_set(&osb->alloc_stats.local_data, 0);
>  	atomic_set(&osb->alloc_stats.bitmap_data, 0);
> diff --git a/fs/ocfs2/sysfile.c b/fs/ocfs2/sysfile.c
> index d53a6cc866be..67e492f4b828 100644
> --- a/fs/ocfs2/sysfile.c
> +++ b/fs/ocfs2/sysfile.c
> @@ -98,11 +98,9 @@ struct inode *ocfs2_get_system_file_inode(struct ocfs2_super *osb,
>  	} else
>  		arr = get_local_system_inode(osb, type, slot);
>  
> -	mutex_lock(&osb->system_file_mutex);
>  	if (arr && ((inode = *arr) != NULL)) {
>  		/* get a ref in addition to the array ref */
>  		inode = igrab(inode);
> -		mutex_unlock(&osb->system_file_mutex);
>  		BUG_ON(!inode);
>  
>  		return inode;
> @@ -112,11 +110,10 @@ struct inode *ocfs2_get_system_file_inode(struct ocfs2_super *osb,
>  	inode = _ocfs2_get_system_file_inode(osb, type, slot);
>  
>  	/* add one more if putting into array for first time */
> -	if (arr && inode) {
> -		*arr = igrab(inode);
> -		BUG_ON(!*arr);
> +	if (inode && arr && !*arr && !cmpxchg(&(*arr), NULL, inode)) {
> +		inode = igrab(inode);
> +		BUG_ON(!inode);
>  	}
> -	mutex_unlock(&osb->system_file_mutex);
>  	return inode;
>  }
>  
> -- 
> 2.54.0
> 
>
Re: [PATCH v2] ocfs2: kill osb->system_file_mutex lock
Posted by Joseph Qi 6 days, 22 hours ago

On 5/18/26 12:56 PM, Heming Zhao wrote:
> On Mon, May 18, 2026 at 01:23:40PM +0900, Tetsuo Handa wrote:
>> Commit 43b10a20372d ("ocfs2: avoid system inode ref confusion by adding
>> mutex lock") tried to avoid a refcount leak caused by allowing multiple
>> threads to call igrab(inode). But addition of osb->system_file_mutex made
>> locking dependency complicated and is causing lockdep to warn about
>> possibility of AB-BA deadlock.
>>
>> Since _ocfs2_get_system_file_inode() returns the same inode for the same
>> input arguments, we don't need to serialize _ocfs2_get_system_file_inode().
>> What we need to make sure is that igrab(inode) is called for only once().
>> Therefore, replace osb->system_file_mutex with cmpxchg()-based locking.
>>
>> Fixes: 43b10a20372d ("ocfs2: avoid system inode ref confusion by adding mutex lock")
>> Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
> 
> LGTM. Thanks for the patch.
> Reviewed-by: Heming Zhao <heming.zhao@suse.com>

Acked-by: Joseph Qi <joseph.qi@linux.alibaba.com>
>> ---
>> Changes in v2:
>>   Updated patch description.
>>
>>  fs/ocfs2/ocfs2.h   | 2 --
>>  fs/ocfs2/super.c   | 2 --
>>  fs/ocfs2/sysfile.c | 9 +++------
>>  3 files changed, 3 insertions(+), 10 deletions(-)
>>
>> diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
>> index 7b50e03dfa66..62cad6522c7a 100644
>> --- a/fs/ocfs2/ocfs2.h
>> +++ b/fs/ocfs2/ocfs2.h
>> @@ -494,8 +494,6 @@ struct ocfs2_super
>>  	struct rb_root	osb_rf_lock_tree;
>>  	struct ocfs2_refcount_tree *osb_ref_tree_lru;
>>  
>> -	struct mutex system_file_mutex;
>> -
>>  	/*
>>  	 * OCFS2 needs to schedule several different types of work which
>>  	 * require cluster locking, disk I/O, recovery waits, etc. Since these
>> diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
>> index b875f01c9756..6dd45c2153f8 100644
>> --- a/fs/ocfs2/super.c
>> +++ b/fs/ocfs2/super.c
>> @@ -1997,8 +1997,6 @@ static int ocfs2_initialize_super(struct super_block *sb,
>>  	spin_lock_init(&osb->osb_xattr_lock);
>>  	ocfs2_init_steal_slots(osb);
>>  
>> -	mutex_init(&osb->system_file_mutex);
>> -
>>  	atomic_set(&osb->alloc_stats.moves, 0);
>>  	atomic_set(&osb->alloc_stats.local_data, 0);
>>  	atomic_set(&osb->alloc_stats.bitmap_data, 0);
>> diff --git a/fs/ocfs2/sysfile.c b/fs/ocfs2/sysfile.c
>> index d53a6cc866be..67e492f4b828 100644
>> --- a/fs/ocfs2/sysfile.c
>> +++ b/fs/ocfs2/sysfile.c
>> @@ -98,11 +98,9 @@ struct inode *ocfs2_get_system_file_inode(struct ocfs2_super *osb,
>>  	} else
>>  		arr = get_local_system_inode(osb, type, slot);
>>  
>> -	mutex_lock(&osb->system_file_mutex);
>>  	if (arr && ((inode = *arr) != NULL)) {
>>  		/* get a ref in addition to the array ref */
>>  		inode = igrab(inode);
>> -		mutex_unlock(&osb->system_file_mutex);
>>  		BUG_ON(!inode);
>>  
>>  		return inode;
>> @@ -112,11 +110,10 @@ struct inode *ocfs2_get_system_file_inode(struct ocfs2_super *osb,
>>  	inode = _ocfs2_get_system_file_inode(osb, type, slot);
>>  
>>  	/* add one more if putting into array for first time */
>> -	if (arr && inode) {
>> -		*arr = igrab(inode);
>> -		BUG_ON(!*arr);
>> +	if (inode && arr && !*arr && !cmpxchg(&(*arr), NULL, inode)) {
>> +		inode = igrab(inode);
>> +		BUG_ON(!inode);
>>  	}
>> -	mutex_unlock(&osb->system_file_mutex);
>>  	return inode;
>>  }
>>  
>> -- 
>> 2.54.0
>>
>>