fs/ocfs2/refcounttree.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
Acquiring the locks in refcounttree should follow
the ip_alloc --> ip_xattr ordering, as done by multiple
code paths in ocfs2; otherwise, we risk an ABBA deadlock
(i.e in the start transaction path).
Reported-by: syzbot+1fed2de07d8e11a3ec1b@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=1fed2de07d8e11a3ec1b
Tested-by: syzbot+1fed2de07d8e11a3ec1b@syzkaller.appspotmail.com
Reviewed-by: Tetsuo Handa <penguin-kernel@i-love.sakura.ne.jp>
Signed-off-by: Diogo Jahchan Koike <djahchankoike@gmail.com>
---
fs/ocfs2/refcounttree.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c
index 8f732742b26e..c8467b92b64e 100644
--- a/fs/ocfs2/refcounttree.c
+++ b/fs/ocfs2/refcounttree.c
@@ -928,8 +928,8 @@ int ocfs2_try_remove_refcount_tree(struct inode *inode,
struct ocfs2_inode_info *oi = OCFS2_I(inode);
struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
- down_write(&oi->ip_xattr_sem);
down_write(&oi->ip_alloc_sem);
+ down_write(&oi->ip_xattr_sem);
if (oi->ip_clusters)
goto out;
@@ -945,8 +945,8 @@ int ocfs2_try_remove_refcount_tree(struct inode *inode,
if (ret)
mlog_errno(ret);
out:
- up_write(&oi->ip_alloc_sem);
up_write(&oi->ip_xattr_sem);
+ up_write(&oi->ip_alloc_sem);
return 0;
}
--
2.43.0
On 2025/07/15 7:15, Diogo Jahchan Koike wrote: > Acquiring the locks in refcounttree should follow > the ip_alloc --> ip_xattr ordering, as done by multiple > code paths in ocfs2; otherwise, we risk an ABBA deadlock > (i.e in the start transaction path). I noticed that ocfs2_reflink() in the same file wants similar change. down_write(&OCFS2_I(inode)->ip_xattr_sem); down_write(&OCFS2_I(inode)->ip_alloc_sem); error = __ocfs2_reflink(old_dentry, old_bh, new_orphan_inode, preserve); up_write(&OCFS2_I(inode)->ip_alloc_sem); up_write(&OCFS2_I(inode)->ip_xattr_sem);
On 2025/07/15 11:51, Tetsuo Handa wrote: > On 2025/07/15 7:15, Diogo Jahchan Koike wrote: >> Acquiring the locks in refcounttree should follow >> the ip_alloc --> ip_xattr ordering, as done by multiple >> code paths in ocfs2; otherwise, we risk an ABBA deadlock >> (i.e in the start transaction path). > > I noticed that ocfs2_reflink() in the same file wants similar change. > > down_write(&OCFS2_I(inode)->ip_xattr_sem); > down_write(&OCFS2_I(inode)->ip_alloc_sem); > error = __ocfs2_reflink(old_dentry, old_bh, > new_orphan_inode, preserve); > up_write(&OCFS2_I(inode)->ip_alloc_sem); > up_write(&OCFS2_I(inode)->ip_xattr_sem); > Moreover, I noticed that e.g. ocfs2_xattr_set_handle() firstly acquires ip_xatr_sem and then ocfs2_xattr_ibody_find() might acquire ip_alloc_sem. Diogo, where do you see the ip_alloc --> ip_xattr ordering? Unless we unify to either ip_alloc --> ip_xattr ordering or ip_xattr --> ip_alloc ordering (or replace ip_xattr with ip_alloc), this patch simply changes the location of lockdep warning?
On 2025/07/18 22:54, Tetsuo Handa wrote: > On 2025/07/15 11:51, Tetsuo Handa wrote: >> On 2025/07/15 7:15, Diogo Jahchan Koike wrote: >>> Acquiring the locks in refcounttree should follow >>> the ip_alloc --> ip_xattr ordering, as done by multiple >>> code paths in ocfs2; otherwise, we risk an ABBA deadlock >>> (i.e in the start transaction path). >> >> I noticed that ocfs2_reflink() in the same file wants similar change. >> >> down_write(&OCFS2_I(inode)->ip_xattr_sem); >> down_write(&OCFS2_I(inode)->ip_alloc_sem); >> error = __ocfs2_reflink(old_dentry, old_bh, >> new_orphan_inode, preserve); >> up_write(&OCFS2_I(inode)->ip_alloc_sem); >> up_write(&OCFS2_I(inode)->ip_xattr_sem); >> > > Moreover, I noticed that e.g. ocfs2_xattr_set_handle() firstly acquires > ip_xatr_sem and then ocfs2_xattr_ibody_find() might acquire ip_alloc_sem. > > Diogo, where do you see the ip_alloc --> ip_xattr ordering? > > Unless we unify to either ip_alloc --> ip_xattr ordering or > ip_xattr --> ip_alloc ordering (or replace ip_xattr with ip_alloc), > this patch simply changes the location of lockdep warning? > Since I couldn't find direct ip_alloc --> ip_xattr ordering, I tried effectively replacing ip_xattr with ip_alloc at https://lkml.kernel.org/r/687be24a.a70a0220.693ce.0092.GAE@google.com and got sb_internal --> ip_alloc v.s. ip_alloc --> sb_internal ordering problem, as with other lockdep reports in ocfs2 subsystem at https://syzkaller.appspot.com/upstream/s/ocfs2 . In the team network driver, this kind of ordering issues has been addressed by simplifying locking dependency at https://lkml.kernel.org/r/20250623153147.3413631-1-sdf@fomichev.me . ocfs2 developers, can you simplify locking dependency in ocfs2, by killing several locks and reordering the locks?
© 2016 - 2025 Red Hat, Inc.