btrfs: fix lockdep warnings on io_uring encoded reads

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.

Reported-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
34310c442e ("btrfs: add io_uring command for encoded reads (ENCODED_READ ioctl)")
Signed-off-by: Mark Harmstone <maharmstone@fb.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
Mark Harmstone 2024-11-15 15:49:17 +00:00 committed by David Sterba
parent 7c4e39f9d2
commit 22d2e48e31
2 changed files with 20 additions and 0 deletions

View File

@ -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:

View File

@ -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.