Commit feffde68 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull btrfs fixes from David Sterba:

 - add lockdep annotations for io_uring/encoded read integration, inode
   lock is held when returning to userspace

 - properly reflect experimental config option to sysfs

 - handle NULL root in case the rescue mode accepts invalid/damaged tree
   roots (rescue=ibadroot)

 - regression fix of a deadlock between transaction and extent locks

 - fix pending bio accounting bug in encoded read ioctl

 - fix NOWAIT mode when checking references for NOCOW files

 - fix use-after-free in a rb-tree cleanup in ref-verify debugging tool

* tag 'for-6.13-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: fix lockdep warnings on io_uring encoded reads
  btrfs: ref-verify: fix use-after-free after invalid ref action
  btrfs: add a sanity check for btrfs root in btrfs_search_slot()
  btrfs: don't loop for nowait writes when checking for cross references
  btrfs: sysfs: advertise experimental features only if CONFIG_BTRFS_EXPERIMENTAL=y
  btrfs: fix deadlock between transaction commits and extent locks
  btrfs: fix use-after-free in btrfs_encoded_read_endio()
parents 3d246949 22d2e48e
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -2046,7 +2046,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root *root,
		      const struct btrfs_key *key, struct btrfs_path *p,
		      int ins_len, int cow)
{
	struct btrfs_fs_info *fs_info = root->fs_info;
	struct btrfs_fs_info *fs_info;
	struct extent_buffer *b;
	int slot;
	int ret;
@@ -2059,6 +2059,10 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root *root,
	int min_write_lock_level;
	int prev_cmp;

	if (!root)
		return -EINVAL;

	fs_info = root->fs_info;
	might_sleep();

	lowest_level = p->lowest_level;
+1 −1
Original line number Diff line number Diff line
@@ -2422,7 +2422,7 @@ int btrfs_cross_ref_exist(struct btrfs_root *root, u64 objectid, u64 offset,
			goto out;

		ret = check_delayed_ref(root, path, objectid, offset, bytenr);
	} while (ret == -EAGAIN);
	} while (ret == -EAGAIN && !path->nowait);

out:
	btrfs_release_path(path);
+14 −4
Original line number Diff line number Diff line
@@ -3063,6 +3063,19 @@ int btrfs_finish_one_ordered(struct btrfs_ordered_extent *ordered_extent)
			goto out;
	}

	/*
	 * If it's a COW write we need to lock the extent range as we will be
	 * inserting/replacing file extent items and unpinning an extent map.
	 * This must be taken before joining a transaction, as it's a higher
	 * level lock (like the inode's VFS lock), otherwise we can run into an
	 * ABBA deadlock with other tasks (transactions work like a lock,
	 * depending on their current state).
	 */
	if (!test_bit(BTRFS_ORDERED_NOCOW, &ordered_extent->flags)) {
		clear_bits |= EXTENT_LOCKED;
		lock_extent(io_tree, start, end, &cached_state);
	}

	if (freespace_inode)
		trans = btrfs_join_transaction_spacecache(root);
	else
@@ -3099,9 +3112,6 @@ int btrfs_finish_one_ordered(struct btrfs_ordered_extent *ordered_extent)
		goto out;
	}

	clear_bits |= EXTENT_LOCKED;
	lock_extent(io_tree, start, end, &cached_state);

	if (test_bit(BTRFS_ORDERED_COMPRESSED, &ordered_extent->flags))
		compress_type = ordered_extent->compress_type;
	if (test_bit(BTRFS_ORDERED_PREALLOC, &ordered_extent->flags)) {
@@ -9089,7 +9099,7 @@ static void btrfs_encoded_read_endio(struct btrfs_bio *bbio)
		 */
		WRITE_ONCE(priv->status, bbio->bio.bi_status);
	}
	if (atomic_dec_return(&priv->pending) == 0) {
	if (atomic_dec_and_test(&priv->pending)) {
		int err = blk_status_to_errno(READ_ONCE(priv->status));

		if (priv->uring_ctx) {
+10 −0
Original line number Diff line number Diff line
@@ -4751,6 +4751,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;
@@ -4859,6 +4862,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:
+10 −0
Original line number Diff line number Diff line
@@ -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.
Loading