Skip to content

Commit e2f0c56

Browse files
committed
Merge tag 'for-5.10-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs fixes from David Sterba: "A handful of minor fixes and updates: - handle missing device replace item on mount (syzbot report) - fix space reservation calculation when finishing relocation - fix memory leak on error path in ref-verify (debugging feature) - fix potential overflow during defrag on 32bit arches - minor code update to silence smatch warning - minor error message updates" * tag 'for-5.10-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: btrfs: ref-verify: fix memory leak in btrfs_ref_tree_mod btrfs: dev-replace: fail mount if we don't have replace item with target device btrfs: scrub: update message regarding read-only status btrfs: clean up NULL checks in qgroup_unreserve_range() btrfs: fix min reserved size calculation in merge_reloc_root btrfs: print the block rsv type when we fail our reservation btrfs: fix potential overflow in cluster_pages_for_defrag on 32bit arch
2 parents 52d1998 + 468600c commit e2f0c56

File tree

8 files changed

+48
-39
lines changed

8 files changed

+48
-39
lines changed

fs/btrfs/block-rsv.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,8 @@ struct btrfs_block_rsv *btrfs_use_block_rsv(struct btrfs_trans_handle *trans,
511511
/*DEFAULT_RATELIMIT_BURST*/ 1);
512512
if (__ratelimit(&_rs))
513513
WARN(1, KERN_DEBUG
514-
"BTRFS: block rsv returned %d\n", ret);
514+
"BTRFS: block rsv %d returned %d\n",
515+
block_rsv->type, ret);
515516
}
516517
try_reserve:
517518
ret = btrfs_reserve_metadata_bytes(root, block_rsv, blocksize,

fs/btrfs/dev-replace.c

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,17 @@ int btrfs_init_dev_replace(struct btrfs_fs_info *fs_info)
9191
ret = btrfs_search_slot(NULL, dev_root, &key, path, 0, 0);
9292
if (ret) {
9393
no_valid_dev_replace_entry_found:
94+
/*
95+
* We don't have a replace item or it's corrupted. If there is
96+
* a replace target, fail the mount.
97+
*/
98+
if (btrfs_find_device(fs_info->fs_devices,
99+
BTRFS_DEV_REPLACE_DEVID, NULL, NULL, false)) {
100+
btrfs_err(fs_info,
101+
"found replace target device without a valid replace item");
102+
ret = -EUCLEAN;
103+
goto out;
104+
}
94105
ret = 0;
95106
dev_replace->replace_state =
96107
BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED;
@@ -143,8 +154,19 @@ int btrfs_init_dev_replace(struct btrfs_fs_info *fs_info)
143154
case BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED:
144155
case BTRFS_IOCTL_DEV_REPLACE_STATE_FINISHED:
145156
case BTRFS_IOCTL_DEV_REPLACE_STATE_CANCELED:
146-
dev_replace->srcdev = NULL;
147-
dev_replace->tgtdev = NULL;
157+
/*
158+
* We don't have an active replace item but if there is a
159+
* replace target, fail the mount.
160+
*/
161+
if (btrfs_find_device(fs_info->fs_devices,
162+
BTRFS_DEV_REPLACE_DEVID, NULL, NULL, false)) {
163+
btrfs_err(fs_info,
164+
"replace devid present without an active replace item");
165+
ret = -EUCLEAN;
166+
} else {
167+
dev_replace->srcdev = NULL;
168+
dev_replace->tgtdev = NULL;
169+
}
148170
break;
149171
case BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED:
150172
case BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED:

fs/btrfs/ioctl.c

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1274,6 +1274,7 @@ static int cluster_pages_for_defrag(struct inode *inode,
12741274
u64 page_start;
12751275
u64 page_end;
12761276
u64 page_cnt;
1277+
u64 start = (u64)start_index << PAGE_SHIFT;
12771278
int ret;
12781279
int i;
12791280
int i_done;
@@ -1290,8 +1291,7 @@ static int cluster_pages_for_defrag(struct inode *inode,
12901291
page_cnt = min_t(u64, (u64)num_pages, (u64)file_end - start_index + 1);
12911292

12921293
ret = btrfs_delalloc_reserve_space(BTRFS_I(inode), &data_reserved,
1293-
start_index << PAGE_SHIFT,
1294-
page_cnt << PAGE_SHIFT);
1294+
start, page_cnt << PAGE_SHIFT);
12951295
if (ret)
12961296
return ret;
12971297
i_done = 0;
@@ -1380,8 +1380,7 @@ static int cluster_pages_for_defrag(struct inode *inode,
13801380
btrfs_mod_outstanding_extents(BTRFS_I(inode), 1);
13811381
spin_unlock(&BTRFS_I(inode)->lock);
13821382
btrfs_delalloc_release_space(BTRFS_I(inode), data_reserved,
1383-
start_index << PAGE_SHIFT,
1384-
(page_cnt - i_done) << PAGE_SHIFT, true);
1383+
start, (page_cnt - i_done) << PAGE_SHIFT, true);
13851384
}
13861385

13871386

@@ -1408,8 +1407,7 @@ static int cluster_pages_for_defrag(struct inode *inode,
14081407
put_page(pages[i]);
14091408
}
14101409
btrfs_delalloc_release_space(BTRFS_I(inode), data_reserved,
1411-
start_index << PAGE_SHIFT,
1412-
page_cnt << PAGE_SHIFT, true);
1410+
start, page_cnt << PAGE_SHIFT, true);
14131411
btrfs_delalloc_release_extents(BTRFS_I(inode), page_cnt << PAGE_SHIFT);
14141412
extent_changeset_free(data_reserved);
14151413
return ret;

fs/btrfs/qgroup.c

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3435,24 +3435,20 @@ static int qgroup_unreserve_range(struct btrfs_inode *inode,
34353435
{
34363436
struct rb_node *node;
34373437
struct rb_node *next;
3438-
struct ulist_node *entry = NULL;
3438+
struct ulist_node *entry;
34393439
int ret = 0;
34403440

34413441
node = reserved->range_changed.root.rb_node;
3442+
if (!node)
3443+
return 0;
34423444
while (node) {
34433445
entry = rb_entry(node, struct ulist_node, rb_node);
34443446
if (entry->val < start)
34453447
node = node->rb_right;
3446-
else if (entry)
3447-
node = node->rb_left;
34483448
else
3449-
break;
3449+
node = node->rb_left;
34503450
}
34513451

3452-
/* Empty changeset */
3453-
if (!entry)
3454-
return 0;
3455-
34563452
if (entry->val > start && rb_prev(&entry->rb_node))
34573453
entry = rb_entry(rb_prev(&entry->rb_node), struct ulist_node,
34583454
rb_node);

fs/btrfs/ref-verify.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -860,6 +860,7 @@ int btrfs_ref_tree_mod(struct btrfs_fs_info *fs_info,
860860
"dropping a ref for a root that doesn't have a ref on the block");
861861
dump_block_entry(fs_info, be);
862862
dump_ref_action(fs_info, ra);
863+
kfree(ref);
863864
kfree(ra);
864865
goto out_unlock;
865866
}

fs/btrfs/relocation.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1648,6 +1648,7 @@ static noinline_for_stack int merge_reloc_root(struct reloc_control *rc,
16481648
struct btrfs_root_item *root_item;
16491649
struct btrfs_path *path;
16501650
struct extent_buffer *leaf;
1651+
int reserve_level;
16511652
int level;
16521653
int max_level;
16531654
int replaced = 0;
@@ -1696,7 +1697,8 @@ static noinline_for_stack int merge_reloc_root(struct reloc_control *rc,
16961697
* Thus the needed metadata size is at most root_level * nodesize,
16971698
* and * 2 since we have two trees to COW.
16981699
*/
1699-
min_reserved = fs_info->nodesize * btrfs_root_level(root_item) * 2;
1700+
reserve_level = max_t(int, 1, btrfs_root_level(root_item));
1701+
min_reserved = fs_info->nodesize * reserve_level * 2;
17001702
memset(&next_key, 0, sizeof(next_key));
17011703

17021704
while (1) {

fs/btrfs/scrub.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3866,8 +3866,9 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start,
38663866
if (!is_dev_replace && !readonly &&
38673867
!test_bit(BTRFS_DEV_STATE_WRITEABLE, &dev->dev_state)) {
38683868
mutex_unlock(&fs_info->fs_devices->device_list_mutex);
3869-
btrfs_err_in_rcu(fs_info, "scrub: device %s is not writable",
3870-
rcu_str_deref(dev->name));
3869+
btrfs_err_in_rcu(fs_info,
3870+
"scrub on devid %llu: filesystem on %s is not writable",
3871+
devid, rcu_str_deref(dev->name));
38713872
ret = -EROFS;
38723873
goto out;
38733874
}

fs/btrfs/volumes.c

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,22 +1056,13 @@ static void __btrfs_free_extra_devids(struct btrfs_fs_devices *fs_devices,
10561056
continue;
10571057
}
10581058

1059-
if (device->devid == BTRFS_DEV_REPLACE_DEVID) {
1060-
/*
1061-
* In the first step, keep the device which has
1062-
* the correct fsid and the devid that is used
1063-
* for the dev_replace procedure.
1064-
* In the second step, the dev_replace state is
1065-
* read from the device tree and it is known
1066-
* whether the procedure is really active or
1067-
* not, which means whether this device is
1068-
* used or whether it should be removed.
1069-
*/
1070-
if (step == 0 || test_bit(BTRFS_DEV_STATE_REPLACE_TGT,
1071-
&device->dev_state)) {
1072-
continue;
1073-
}
1074-
}
1059+
/*
1060+
* We have already validated the presence of BTRFS_DEV_REPLACE_DEVID,
1061+
* in btrfs_init_dev_replace() so just continue.
1062+
*/
1063+
if (device->devid == BTRFS_DEV_REPLACE_DEVID)
1064+
continue;
1065+
10751066
if (device->bdev) {
10761067
blkdev_put(device->bdev, device->mode);
10771068
device->bdev = NULL;
@@ -1080,9 +1071,6 @@ static void __btrfs_free_extra_devids(struct btrfs_fs_devices *fs_devices,
10801071
if (test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state)) {
10811072
list_del_init(&device->dev_alloc_list);
10821073
clear_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state);
1083-
if (!test_bit(BTRFS_DEV_STATE_REPLACE_TGT,
1084-
&device->dev_state))
1085-
fs_devices->rw_devices--;
10861074
}
10871075
list_del_init(&device->dev_list);
10881076
fs_devices->num_devices--;

0 commit comments

Comments
 (0)