Skip to content

Commit feffde6

Browse files
committed
Merge tag 'for-6.13-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
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()
2 parents 3d24694 + 22d2e48 commit feffde6

File tree

7 files changed

+43
-8
lines changed

7 files changed

+43
-8
lines changed

fs/btrfs/ctree.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2046,7 +2046,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root *root,
20462046
const struct btrfs_key *key, struct btrfs_path *p,
20472047
int ins_len, int cow)
20482048
{
2049-
struct btrfs_fs_info *fs_info = root->fs_info;
2049+
struct btrfs_fs_info *fs_info;
20502050
struct extent_buffer *b;
20512051
int slot;
20522052
int ret;
@@ -2059,6 +2059,10 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root *root,
20592059
int min_write_lock_level;
20602060
int prev_cmp;
20612061

2062+
if (!root)
2063+
return -EINVAL;
2064+
2065+
fs_info = root->fs_info;
20622066
might_sleep();
20632067

20642068
lowest_level = p->lowest_level;

fs/btrfs/extent-tree.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2422,7 +2422,7 @@ int btrfs_cross_ref_exist(struct btrfs_root *root, u64 objectid, u64 offset,
24222422
goto out;
24232423

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

24272427
out:
24282428
btrfs_release_path(path);

fs/btrfs/inode.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3063,6 +3063,19 @@ int btrfs_finish_one_ordered(struct btrfs_ordered_extent *ordered_extent)
30633063
goto out;
30643064
}
30653065

3066+
/*
3067+
* If it's a COW write we need to lock the extent range as we will be
3068+
* inserting/replacing file extent items and unpinning an extent map.
3069+
* This must be taken before joining a transaction, as it's a higher
3070+
* level lock (like the inode's VFS lock), otherwise we can run into an
3071+
* ABBA deadlock with other tasks (transactions work like a lock,
3072+
* depending on their current state).
3073+
*/
3074+
if (!test_bit(BTRFS_ORDERED_NOCOW, &ordered_extent->flags)) {
3075+
clear_bits |= EXTENT_LOCKED;
3076+
lock_extent(io_tree, start, end, &cached_state);
3077+
}
3078+
30663079
if (freespace_inode)
30673080
trans = btrfs_join_transaction_spacecache(root);
30683081
else
@@ -3099,9 +3112,6 @@ int btrfs_finish_one_ordered(struct btrfs_ordered_extent *ordered_extent)
30993112
goto out;
31003113
}
31013114

3102-
clear_bits |= EXTENT_LOCKED;
3103-
lock_extent(io_tree, start, end, &cached_state);
3104-
31053115
if (test_bit(BTRFS_ORDERED_COMPRESSED, &ordered_extent->flags))
31063116
compress_type = ordered_extent->compress_type;
31073117
if (test_bit(BTRFS_ORDERED_PREALLOC, &ordered_extent->flags)) {
@@ -9089,7 +9099,7 @@ static void btrfs_encoded_read_endio(struct btrfs_bio *bbio)
90899099
*/
90909100
WRITE_ONCE(priv->status, bbio->bio.bi_status);
90919101
}
9092-
if (atomic_dec_return(&priv->pending) == 0) {
9102+
if (atomic_dec_and_test(&priv->pending)) {
90939103
int err = blk_status_to_errno(READ_ONCE(priv->status));
90949104

90959105
if (priv->uring_ctx) {

fs/btrfs/ioctl.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4751,6 +4751,9 @@ static void btrfs_uring_read_finished(struct io_uring_cmd *cmd, unsigned int iss
47514751
size_t page_offset;
47524752
ssize_t ret;
47534753

4754+
/* The inode lock has already been acquired in btrfs_uring_read_extent. */
4755+
btrfs_lockdep_inode_acquire(inode, i_rwsem);
4756+
47544757
if (priv->err) {
47554758
ret = priv->err;
47564759
goto out;
@@ -4859,6 +4862,13 @@ static int btrfs_uring_read_extent(struct kiocb *iocb, struct iov_iter *iter,
48594862
* and inode and freeing the allocations.
48604863
*/
48614864

4865+
/*
4866+
* We're returning to userspace with the inode lock held, and that's
4867+
* okay - it'll get unlocked in a worker thread. Call
4868+
* btrfs_lockdep_inode_release() to avoid confusing lockdep.
4869+
*/
4870+
btrfs_lockdep_inode_release(inode, i_rwsem);
4871+
48624872
return -EIOCBQUEUED;
48634873

48644874
out_fail:

fs/btrfs/locking.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,16 @@ enum btrfs_lockdep_trans_states {
128128
#define btrfs_lockdep_release(owner, lock) \
129129
rwsem_release(&owner->lock##_map, _THIS_IP_)
130130

131+
/*
132+
* Used to account for the fact that when doing io_uring encoded I/O, we can
133+
* return to userspace with the inode lock still held.
134+
*/
135+
#define btrfs_lockdep_inode_acquire(owner, lock) \
136+
rwsem_acquire_read(&owner->vfs_inode.lock.dep_map, 0, 0, _THIS_IP_)
137+
138+
#define btrfs_lockdep_inode_release(owner, lock) \
139+
rwsem_release(&owner->vfs_inode.lock.dep_map, _THIS_IP_)
140+
131141
/*
132142
* Macros for the transaction states wait events, similar to the generic wait
133143
* event macros.

fs/btrfs/ref-verify.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -857,6 +857,7 @@ int btrfs_ref_tree_mod(struct btrfs_fs_info *fs_info,
857857
"dropping a ref for a root that doesn't have a ref on the block");
858858
dump_block_entry(fs_info, be);
859859
dump_ref_action(fs_info, ra);
860+
rb_erase(&ref->node, &be->refs);
860861
kfree(ref);
861862
kfree(ra);
862863
goto out_unlock;

fs/btrfs/sysfs.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ BTRFS_FEAT_ATTR_INCOMPAT(simple_quota, SIMPLE_QUOTA);
295295
#ifdef CONFIG_BLK_DEV_ZONED
296296
BTRFS_FEAT_ATTR_INCOMPAT(zoned, ZONED);
297297
#endif
298-
#ifdef CONFIG_BTRFS_DEBUG
298+
#ifdef CONFIG_BTRFS_EXPERIMENTAL
299299
/* Remove once support for extent tree v2 is feature complete */
300300
BTRFS_FEAT_ATTR_INCOMPAT(extent_tree_v2, EXTENT_TREE_V2);
301301
/* Remove once support for raid stripe tree is feature complete. */
@@ -329,7 +329,7 @@ static struct attribute *btrfs_supported_feature_attrs[] = {
329329
#ifdef CONFIG_BLK_DEV_ZONED
330330
BTRFS_FEAT_ATTR_PTR(zoned),
331331
#endif
332-
#ifdef CONFIG_BTRFS_DEBUG
332+
#ifdef CONFIG_BTRFS_EXPERIMENTAL
333333
BTRFS_FEAT_ATTR_PTR(extent_tree_v2),
334334
BTRFS_FEAT_ATTR_PTR(raid_stripe_tree),
335335
#endif

0 commit comments

Comments
 (0)