Skip to content

Commit 9609134

Browse files
committed
Merge tag 'for-5.16-rc5-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs fixes from David Sterba: "A few more fixes, almost all error handling one-liners and for stable. - regression fix in directory logging items - regression fix of extent buffer status bits handling after an error - fix memory leak in error handling path in tree-log - fix freeing invalid anon device number when handling errors during subvolume creation - fix warning when freeing leaf after subvolume creation failure - fix missing blkdev put in device scan error handling - fix invalid delayed ref after subvolume creation failure" * tag 'for-5.16-rc5-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: btrfs: fix missing blkdev_put() call in btrfs_scan_one_device() btrfs: fix warning when freeing leaf after subvolume creation failure btrfs: fix invalid delayed ref after subvolume creation failure btrfs: check WRITE_ERR when trying to read an extent buffer btrfs: fix missing last dir item offset update when logging directory btrfs: fix double free of anon_dev after failure to create subvolume btrfs: fix memory leak in __add_inode_ref()
2 parents f1f05ef + 4989d4a commit 9609134

File tree

10 files changed

+54
-24
lines changed

10 files changed

+54
-24
lines changed

fs/btrfs/ctree.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -463,8 +463,8 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
463463
BUG_ON(ret < 0);
464464
rcu_assign_pointer(root->node, cow);
465465

466-
btrfs_free_tree_block(trans, root, buf, parent_start,
467-
last_ref);
466+
btrfs_free_tree_block(trans, btrfs_root_id(root), buf,
467+
parent_start, last_ref);
468468
free_extent_buffer(buf);
469469
add_root_to_dirty_list(root);
470470
} else {
@@ -485,8 +485,8 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
485485
return ret;
486486
}
487487
}
488-
btrfs_free_tree_block(trans, root, buf, parent_start,
489-
last_ref);
488+
btrfs_free_tree_block(trans, btrfs_root_id(root), buf,
489+
parent_start, last_ref);
490490
}
491491
if (unlock_orig)
492492
btrfs_tree_unlock(buf);
@@ -927,7 +927,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
927927
free_extent_buffer(mid);
928928

929929
root_sub_used(root, mid->len);
930-
btrfs_free_tree_block(trans, root, mid, 0, 1);
930+
btrfs_free_tree_block(trans, btrfs_root_id(root), mid, 0, 1);
931931
/* once for the root ptr */
932932
free_extent_buffer_stale(mid);
933933
return 0;
@@ -986,7 +986,8 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
986986
btrfs_tree_unlock(right);
987987
del_ptr(root, path, level + 1, pslot + 1);
988988
root_sub_used(root, right->len);
989-
btrfs_free_tree_block(trans, root, right, 0, 1);
989+
btrfs_free_tree_block(trans, btrfs_root_id(root), right,
990+
0, 1);
990991
free_extent_buffer_stale(right);
991992
right = NULL;
992993
} else {
@@ -1031,7 +1032,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
10311032
btrfs_tree_unlock(mid);
10321033
del_ptr(root, path, level + 1, pslot);
10331034
root_sub_used(root, mid->len);
1034-
btrfs_free_tree_block(trans, root, mid, 0, 1);
1035+
btrfs_free_tree_block(trans, btrfs_root_id(root), mid, 0, 1);
10351036
free_extent_buffer_stale(mid);
10361037
mid = NULL;
10371038
} else {
@@ -4032,7 +4033,7 @@ static noinline void btrfs_del_leaf(struct btrfs_trans_handle *trans,
40324033
root_sub_used(root, leaf->len);
40334034

40344035
atomic_inc(&leaf->refs);
4035-
btrfs_free_tree_block(trans, root, leaf, 0, 1);
4036+
btrfs_free_tree_block(trans, btrfs_root_id(root), leaf, 0, 1);
40364037
free_extent_buffer_stale(leaf);
40374038
}
40384039
/*

fs/btrfs/ctree.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2257,6 +2257,11 @@ static inline bool btrfs_root_dead(const struct btrfs_root *root)
22572257
return (root->root_item.flags & cpu_to_le64(BTRFS_ROOT_SUBVOL_DEAD)) != 0;
22582258
}
22592259

2260+
static inline u64 btrfs_root_id(const struct btrfs_root *root)
2261+
{
2262+
return root->root_key.objectid;
2263+
}
2264+
22602265
/* struct btrfs_root_backup */
22612266
BTRFS_SETGET_STACK_FUNCS(backup_tree_root, struct btrfs_root_backup,
22622267
tree_root, 64);
@@ -2719,7 +2724,7 @@ struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans,
27192724
u64 empty_size,
27202725
enum btrfs_lock_nesting nest);
27212726
void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
2722-
struct btrfs_root *root,
2727+
u64 root_id,
27232728
struct extent_buffer *buf,
27242729
u64 parent, int last_ref);
27252730
int btrfs_alloc_reserved_file_extent(struct btrfs_trans_handle *trans,

fs/btrfs/disk-io.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1732,6 +1732,14 @@ static struct btrfs_root *btrfs_get_root_ref(struct btrfs_fs_info *fs_info,
17321732
}
17331733
return root;
17341734
fail:
1735+
/*
1736+
* If our caller provided us an anonymous device, then it's his
1737+
* responsability to free it in case we fail. So we have to set our
1738+
* root's anon_dev to 0 to avoid a double free, once by btrfs_put_root()
1739+
* and once again by our caller.
1740+
*/
1741+
if (anon_dev)
1742+
root->anon_dev = 0;
17351743
btrfs_put_root(root);
17361744
return ERR_PTR(ret);
17371745
}

fs/btrfs/extent-tree.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3275,20 +3275,20 @@ static noinline int check_ref_cleanup(struct btrfs_trans_handle *trans,
32753275
}
32763276

32773277
void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
3278-
struct btrfs_root *root,
3278+
u64 root_id,
32793279
struct extent_buffer *buf,
32803280
u64 parent, int last_ref)
32813281
{
3282-
struct btrfs_fs_info *fs_info = root->fs_info;
3282+
struct btrfs_fs_info *fs_info = trans->fs_info;
32833283
struct btrfs_ref generic_ref = { 0 };
32843284
int ret;
32853285

32863286
btrfs_init_generic_ref(&generic_ref, BTRFS_DROP_DELAYED_REF,
32873287
buf->start, buf->len, parent);
32883288
btrfs_init_tree_ref(&generic_ref, btrfs_header_level(buf),
3289-
root->root_key.objectid, 0, false);
3289+
root_id, 0, false);
32903290

3291-
if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID) {
3291+
if (root_id != BTRFS_TREE_LOG_OBJECTID) {
32923292
btrfs_ref_tree_mod(fs_info, &generic_ref);
32933293
ret = btrfs_add_delayed_tree_ref(trans, &generic_ref, NULL);
32943294
BUG_ON(ret); /* -ENOMEM */
@@ -3298,7 +3298,7 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
32983298
struct btrfs_block_group *cache;
32993299
bool must_pin = false;
33003300

3301-
if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID) {
3301+
if (root_id != BTRFS_TREE_LOG_OBJECTID) {
33023302
ret = check_ref_cleanup(trans, buf->start);
33033303
if (!ret) {
33043304
btrfs_redirty_list_add(trans->transaction, buf);
@@ -5472,7 +5472,8 @@ static noinline int walk_up_proc(struct btrfs_trans_handle *trans,
54725472
goto owner_mismatch;
54735473
}
54745474

5475-
btrfs_free_tree_block(trans, root, eb, parent, wc->refs[level] == 1);
5475+
btrfs_free_tree_block(trans, btrfs_root_id(root), eb, parent,
5476+
wc->refs[level] == 1);
54765477
out:
54775478
wc->refs[level] = 0;
54785479
wc->flags[level] = 0;

fs/btrfs/extent_io.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6611,6 +6611,14 @@ int read_extent_buffer_pages(struct extent_buffer *eb, int wait, int mirror_num)
66116611
if (test_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags))
66126612
return 0;
66136613

6614+
/*
6615+
* We could have had EXTENT_BUFFER_UPTODATE cleared by the write
6616+
* operation, which could potentially still be in flight. In this case
6617+
* we simply want to return an error.
6618+
*/
6619+
if (unlikely(test_bit(EXTENT_BUFFER_WRITE_ERR, &eb->bflags)))
6620+
return -EIO;
6621+
66146622
if (eb->fs_info->sectorsize < PAGE_SIZE)
66156623
return read_extent_buffer_subpage(eb, wait, mirror_num);
66166624

fs/btrfs/free-space-tree.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1256,8 +1256,8 @@ int btrfs_clear_free_space_tree(struct btrfs_fs_info *fs_info)
12561256
btrfs_tree_lock(free_space_root->node);
12571257
btrfs_clean_tree_block(free_space_root->node);
12581258
btrfs_tree_unlock(free_space_root->node);
1259-
btrfs_free_tree_block(trans, free_space_root, free_space_root->node,
1260-
0, 1);
1259+
btrfs_free_tree_block(trans, btrfs_root_id(free_space_root),
1260+
free_space_root->node, 0, 1);
12611261

12621262
btrfs_put_root(free_space_root);
12631263

fs/btrfs/ioctl.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -617,11 +617,13 @@ static noinline int create_subvol(struct user_namespace *mnt_userns,
617617
* Since we don't abort the transaction in this case, free the
618618
* tree block so that we don't leak space and leave the
619619
* filesystem in an inconsistent state (an extent item in the
620-
* extent tree without backreferences). Also no need to have
621-
* the tree block locked since it is not in any tree at this
622-
* point, so no other task can find it and use it.
620+
* extent tree with a backreference for a root that does not
621+
* exists).
623622
*/
624-
btrfs_free_tree_block(trans, root, leaf, 0, 1);
623+
btrfs_tree_lock(leaf);
624+
btrfs_clean_tree_block(leaf);
625+
btrfs_tree_unlock(leaf);
626+
btrfs_free_tree_block(trans, objectid, leaf, 0, 1);
625627
free_extent_buffer(leaf);
626628
goto fail;
627629
}

fs/btrfs/qgroup.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1219,7 +1219,8 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info)
12191219
btrfs_tree_lock(quota_root->node);
12201220
btrfs_clean_tree_block(quota_root->node);
12211221
btrfs_tree_unlock(quota_root->node);
1222-
btrfs_free_tree_block(trans, quota_root, quota_root->node, 0, 1);
1222+
btrfs_free_tree_block(trans, btrfs_root_id(quota_root),
1223+
quota_root->node, 0, 1);
12231224

12241225
btrfs_put_root(quota_root);
12251226

fs/btrfs/tree-log.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1181,6 +1181,7 @@ static inline int __add_inode_ref(struct btrfs_trans_handle *trans,
11811181
parent_objectid, victim_name,
11821182
victim_name_len);
11831183
if (ret < 0) {
1184+
kfree(victim_name);
11841185
return ret;
11851186
} else if (!ret) {
11861187
ret = -ENOENT;
@@ -3977,6 +3978,7 @@ static noinline int log_dir_items(struct btrfs_trans_handle *trans,
39773978
goto done;
39783979
}
39793980
if (btrfs_header_generation(path->nodes[0]) != trans->transid) {
3981+
ctx->last_dir_item_offset = min_key.offset;
39803982
ret = overwrite_item(trans, log, dst_path,
39813983
path->nodes[0], path->slots[0],
39823984
&min_key);

fs/btrfs/volumes.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1370,8 +1370,10 @@ struct btrfs_device *btrfs_scan_one_device(const char *path, fmode_t flags,
13701370

13711371
bytenr_orig = btrfs_sb_offset(0);
13721372
ret = btrfs_sb_log_location_bdev(bdev, 0, READ, &bytenr);
1373-
if (ret)
1374-
return ERR_PTR(ret);
1373+
if (ret) {
1374+
device = ERR_PTR(ret);
1375+
goto error_bdev_put;
1376+
}
13751377

13761378
disk_super = btrfs_read_disk_super(bdev, bytenr, bytenr_orig);
13771379
if (IS_ERR(disk_super)) {

0 commit comments

Comments
 (0)