diff mbox series

[v2] btrfs: fix lockdep warnings on io_uring encoded reads

Message ID 20241115154925.1175086-1-maharmstone@fb.com (mailing list archive)
State New
Headers show
Series [v2] btrfs: fix lockdep warnings on io_uring encoded reads | expand

Commit Message

Mark Harmstone Nov. 15, 2024, 3:49 p.m. UTC
Lockdep doesn't like the fact that btrfs_uring_read_extent() returns to
userspace still holding the inode lock, even though we release it once
the I/O finishes. Add calls to rwsem_release() and rwsem_acquire_read() to
work round this.

Signed-off-by: Mark Harmstone <maharmstone@fb.com>
Reported-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
---
Changelog:
v2: Add btrfs_lockdep_inode_acquire and btrfs_lockdep_inode_release
helpers, and remove unneeded CONFIG_DEBUG_LOCK_ALLOC #ifdefs.

 fs/btrfs/ioctl.c   | 10 ++++++++++
 fs/btrfs/locking.h | 10 ++++++++++
 2 files changed, 20 insertions(+)
diff mbox series

Patch

diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 1fdeb216bf6c..f8680e7cc974 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -4752,6 +4752,9 @@  static void btrfs_uring_read_finished(struct io_uring_cmd *cmd, unsigned int iss
 	size_t page_offset;
 	ssize_t ret;
 
+	/* The inode lock has already been acquired in btrfs_uring_read_extent.  */
+	btrfs_lockdep_inode_acquire(inode, i_rwsem);
+
 	if (priv->err) {
 		ret = priv->err;
 		goto out;
@@ -4860,6 +4863,13 @@  static int btrfs_uring_read_extent(struct kiocb *iocb, struct iov_iter *iter,
 	 * and inode and freeing the allocations.
 	 */
 
+	/*
+	 * We're returning to userspace with the inode lock held, and that's
+	 * okay - it'll get unlocked in a worker thread.  Call
+	 * btrfs_lockdep_inode_release() to avoid confusing lockdep.
+	 */
+	btrfs_lockdep_inode_release(inode, i_rwsem);
+
 	return -EIOCBQUEUED;
 
 out_fail:
diff --git a/fs/btrfs/locking.h b/fs/btrfs/locking.h
index 46c8be2afab1..35036b151bf5 100644
--- a/fs/btrfs/locking.h
+++ b/fs/btrfs/locking.h
@@ -128,6 +128,16 @@  enum btrfs_lockdep_trans_states {
 #define btrfs_lockdep_release(owner, lock)					\
 	rwsem_release(&owner->lock##_map, _THIS_IP_)
 
+/*
+ * Used to account for the fact that when doing io_uring encoded I/O, we can
+ * return to userspace with the inode lock still held.
+ */
+#define btrfs_lockdep_inode_acquire(owner, lock)				\
+	rwsem_acquire_read(&owner->vfs_inode.lock.dep_map, 0, 0, _THIS_IP_)
+
+#define btrfs_lockdep_inode_release(owner, lock)				\
+	rwsem_release(&owner->vfs_inode.lock.dep_map, _THIS_IP_)
+
 /*
  * Macros for the transaction states wait events, similar to the generic wait
  * event macros.