Skip to content

Commit

Permalink
btrfs: fix lockdep warnings on io_uring encoded reads
Browse files Browse the repository at this point in the history
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>
34310c4 ("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>
  • Loading branch information
Mark Harmstone authored and David Sterba committed Nov 29, 2024
1 parent 7c4e39f commit 22d2e48
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 0 deletions.
10 changes: 10 additions & 0 deletions fs/btrfs/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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:
Expand Down
10 changes: 10 additions & 0 deletions fs/btrfs/locking.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down

0 comments on commit 22d2e48

Please sign in to comment.