[PATCH v2 2/2] fs/ext4/xattr: Check for 'xattr_sem' inside 'ext4_xattr_delete_inode'

From: Bhupesh
Date: Tue Jan 28 2025 - 03:28:46 EST


Once we are inside the 'ext4_xattr_delete_inode' function and trying
to delete the inode, the 'xattr_sem' should be unlocked.

We need trylock here to avoid false-positive warning from lockdep
about reclaim circular dependency.

This makes the 'ext4_xattr_delete_inode' implementation mimic the
existing 'ext2_xattr_delete_inode' implementation and thus avoid
similar lockdep issues while deleting inodes.

Signed-off-by: Bhupesh <bhupesh@xxxxxxxxxx>
---
fs/ext4/xattr.c | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index 6ff94cdf1515..b98267c09b00 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -2935,7 +2935,20 @@ int ext4_xattr_delete_inode(handle_t *handle, struct inode *inode,
struct ext4_iloc iloc = { .bh = NULL };
struct ext4_xattr_entry *entry;
struct inode *ea_inode;
- int error;
+ int error = 0;
+
+ /*
+ * We are the only ones holding inode reference. The xattr_sem should
+ * better be unlocked! We could as well just not acquire xattr_sem at
+ * all but this makes the code more futureproof. OTOH we need trylock
+ * here to avoid false-positive warning from lockdep about reclaim
+ * circular dependency.
+ */
+ if (WARN_ON_ONCE(!down_write_trylock(&EXT4_I(inode)->xattr_sem)))
+ return error;
+
+ if (!EXT4_I(inode)->i_file_acl)
+ goto cleanup;

error = ext4_journal_ensure_credits(handle, extra_credits,
ext4_free_metadata_revoke_credits(inode->i_sb, 1));
@@ -3024,6 +3037,7 @@ int ext4_xattr_delete_inode(handle_t *handle, struct inode *inode,
cleanup:
brelse(iloc.bh);
brelse(bh);
+ up_write(&EXT4_I(inode)->xattr_sem);
return error;
}

--
2.38.1