Commit 1dc3731d authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-6.4-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux

Pull btrfs fixes from David Sterba:

 - fix backward leaf iteration which could possibly return the same key

 - fix assertion when device add and balance race for exclusive
   operation

 - fix regression when freeing device, state tree would leak after
   device replace

 - fix attempt to clear space cache v1 when block-group-tree is enabled

 - fix potential i_size corruption when encoded write races with send v2
   and enabled no-holes (the race is hard to hit though, the window is a
   few instructions wide)

 - fix wrong bitmap API use when checking empty zones, parameters were
   swapped but not causing a bug due to other code

 - prevent potential qgroup leak if subvolume create does not commit
   transaction (which is pending in the development queue)

 - error handling and reporting:
     - abort transaction when sibling keys check fails for leaves
     - print extent buffers when sibling keys check fails

* tag 'for-6.4-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: don't free qgroup space unless specified
  btrfs: fix encoded write i_size corruption with no-holes
  btrfs: zoned: fix wrong use of bitops API in btrfs_ensure_empty_zones
  btrfs: properly reject clear_cache and v1 cache for block-group-tree
  btrfs: print extent buffers when sibling keys check fails
  btrfs: abort transaction when sibling keys check fails for leaves
  btrfs: fix leak of source device allocation state after device replace
  btrfs: fix assertion of exclop condition when starting balance
  btrfs: fix btrfs_prev_leaf() to not return the same key twice
parents ba0ad6ed d246331b
...@@ -124,7 +124,8 @@ static u64 block_rsv_release_bytes(struct btrfs_fs_info *fs_info, ...@@ -124,7 +124,8 @@ static u64 block_rsv_release_bytes(struct btrfs_fs_info *fs_info,
} else { } else {
num_bytes = 0; num_bytes = 0;
} }
if (block_rsv->qgroup_rsv_reserved >= block_rsv->qgroup_rsv_size) { if (qgroup_to_release_ret &&
block_rsv->qgroup_rsv_reserved >= block_rsv->qgroup_rsv_size) {
qgroup_to_release = block_rsv->qgroup_rsv_reserved - qgroup_to_release = block_rsv->qgroup_rsv_reserved -
block_rsv->qgroup_rsv_size; block_rsv->qgroup_rsv_size;
block_rsv->qgroup_rsv_reserved = block_rsv->qgroup_rsv_size; block_rsv->qgroup_rsv_reserved = block_rsv->qgroup_rsv_size;
......
...@@ -2627,6 +2627,10 @@ static bool check_sibling_keys(struct extent_buffer *left, ...@@ -2627,6 +2627,10 @@ static bool check_sibling_keys(struct extent_buffer *left,
} }
if (btrfs_comp_cpu_keys(&left_last, &right_first) >= 0) { if (btrfs_comp_cpu_keys(&left_last, &right_first) >= 0) {
btrfs_crit(left->fs_info, "left extent buffer:");
btrfs_print_tree(left, false);
btrfs_crit(left->fs_info, "right extent buffer:");
btrfs_print_tree(right, false);
btrfs_crit(left->fs_info, btrfs_crit(left->fs_info,
"bad key order, sibling blocks, left last (%llu %u %llu) right first (%llu %u %llu)", "bad key order, sibling blocks, left last (%llu %u %llu) right first (%llu %u %llu)",
left_last.objectid, left_last.type, left_last.objectid, left_last.type,
...@@ -3215,6 +3219,7 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -3215,6 +3219,7 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
if (check_sibling_keys(left, right)) { if (check_sibling_keys(left, right)) {
ret = -EUCLEAN; ret = -EUCLEAN;
btrfs_abort_transaction(trans, ret);
btrfs_tree_unlock(right); btrfs_tree_unlock(right);
free_extent_buffer(right); free_extent_buffer(right);
return ret; return ret;
...@@ -3433,6 +3438,7 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -3433,6 +3438,7 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
if (check_sibling_keys(left, right)) { if (check_sibling_keys(left, right)) {
ret = -EUCLEAN; ret = -EUCLEAN;
btrfs_abort_transaction(trans, ret);
goto out; goto out;
} }
return __push_leaf_left(trans, path, min_data_size, empty, left, return __push_leaf_left(trans, path, min_data_size, empty, left,
...@@ -4478,10 +4484,12 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root, ...@@ -4478,10 +4484,12 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root,
int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path) int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path)
{ {
struct btrfs_key key; struct btrfs_key key;
struct btrfs_key orig_key;
struct btrfs_disk_key found_key; struct btrfs_disk_key found_key;
int ret; int ret;
btrfs_item_key_to_cpu(path->nodes[0], &key, 0); btrfs_item_key_to_cpu(path->nodes[0], &key, 0);
orig_key = key;
if (key.offset > 0) { if (key.offset > 0) {
key.offset--; key.offset--;
...@@ -4498,8 +4506,36 @@ int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path) ...@@ -4498,8 +4506,36 @@ int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path)
btrfs_release_path(path); btrfs_release_path(path);
ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
if (ret < 0) if (ret <= 0)
return ret; return ret;
/*
* Previous key not found. Even if we were at slot 0 of the leaf we had
* before releasing the path and calling btrfs_search_slot(), we now may
* be in a slot pointing to the same original key - this can happen if
* after we released the path, one of more items were moved from a
* sibling leaf into the front of the leaf we had due to an insertion
* (see push_leaf_right()).
* If we hit this case and our slot is > 0 and just decrement the slot
* so that the caller does not process the same key again, which may or
* may not break the caller, depending on its logic.
*/
if (path->slots[0] < btrfs_header_nritems(path->nodes[0])) {
btrfs_item_key(path->nodes[0], &found_key, path->slots[0]);
ret = comp_keys(&found_key, &orig_key);
if (ret == 0) {
if (path->slots[0] > 0) {
path->slots[0]--;
return 0;
}
/*
* At slot 0, same key as before, it means orig_key is
* the lowest, leftmost, key in the tree. We're done.
*/
return 1;
}
}
btrfs_item_key(path->nodes[0], &found_key, 0); btrfs_item_key(path->nodes[0], &found_key, 0);
ret = comp_keys(&found_key, &key); ret = comp_keys(&found_key, &key);
/* /*
......
...@@ -52,13 +52,13 @@ void btrfs_inode_safe_disk_i_size_write(struct btrfs_inode *inode, u64 new_i_siz ...@@ -52,13 +52,13 @@ void btrfs_inode_safe_disk_i_size_write(struct btrfs_inode *inode, u64 new_i_siz
u64 start, end, i_size; u64 start, end, i_size;
int ret; int ret;
spin_lock(&inode->lock);
i_size = new_i_size ?: i_size_read(&inode->vfs_inode); i_size = new_i_size ?: i_size_read(&inode->vfs_inode);
if (btrfs_fs_incompat(fs_info, NO_HOLES)) { if (btrfs_fs_incompat(fs_info, NO_HOLES)) {
inode->disk_i_size = i_size; inode->disk_i_size = i_size;
return; goto out_unlock;
} }
spin_lock(&inode->lock);
ret = find_contiguous_extent_bit(&inode->file_extent_tree, 0, &start, ret = find_contiguous_extent_bit(&inode->file_extent_tree, 0, &start,
&end, EXTENT_DIRTY); &end, EXTENT_DIRTY);
if (!ret && start == 0) if (!ret && start == 0)
...@@ -66,6 +66,7 @@ void btrfs_inode_safe_disk_i_size_write(struct btrfs_inode *inode, u64 new_i_siz ...@@ -66,6 +66,7 @@ void btrfs_inode_safe_disk_i_size_write(struct btrfs_inode *inode, u64 new_i_siz
else else
i_size = 0; i_size = 0;
inode->disk_i_size = i_size; inode->disk_i_size = i_size;
out_unlock:
spin_unlock(&inode->lock); spin_unlock(&inode->lock);
} }
......
...@@ -454,7 +454,9 @@ void btrfs_exclop_balance(struct btrfs_fs_info *fs_info, ...@@ -454,7 +454,9 @@ void btrfs_exclop_balance(struct btrfs_fs_info *fs_info,
case BTRFS_EXCLOP_BALANCE_PAUSED: case BTRFS_EXCLOP_BALANCE_PAUSED:
spin_lock(&fs_info->super_lock); spin_lock(&fs_info->super_lock);
ASSERT(fs_info->exclusive_operation == BTRFS_EXCLOP_BALANCE || ASSERT(fs_info->exclusive_operation == BTRFS_EXCLOP_BALANCE ||
fs_info->exclusive_operation == BTRFS_EXCLOP_DEV_ADD); fs_info->exclusive_operation == BTRFS_EXCLOP_DEV_ADD ||
fs_info->exclusive_operation == BTRFS_EXCLOP_NONE ||
fs_info->exclusive_operation == BTRFS_EXCLOP_BALANCE_PAUSED);
fs_info->exclusive_operation = BTRFS_EXCLOP_BALANCE_PAUSED; fs_info->exclusive_operation = BTRFS_EXCLOP_BALANCE_PAUSED;
spin_unlock(&fs_info->super_lock); spin_unlock(&fs_info->super_lock);
break; break;
......
...@@ -826,7 +826,12 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options, ...@@ -826,7 +826,12 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options,
!btrfs_test_opt(info, CLEAR_CACHE)) { !btrfs_test_opt(info, CLEAR_CACHE)) {
btrfs_err(info, "cannot disable free space tree"); btrfs_err(info, "cannot disable free space tree");
ret = -EINVAL; ret = -EINVAL;
}
if (btrfs_fs_compat_ro(info, BLOCK_GROUP_TREE) &&
(btrfs_test_opt(info, CLEAR_CACHE) ||
!btrfs_test_opt(info, FREE_SPACE_TREE))) {
btrfs_err(info, "cannot disable free space tree with block-group-tree feature");
ret = -EINVAL;
} }
if (!ret) if (!ret)
ret = btrfs_check_mountopts_zoned(info); ret = btrfs_check_mountopts_zoned(info);
......
...@@ -395,6 +395,7 @@ void btrfs_free_device(struct btrfs_device *device) ...@@ -395,6 +395,7 @@ void btrfs_free_device(struct btrfs_device *device)
{ {
WARN_ON(!list_empty(&device->post_commit_list)); WARN_ON(!list_empty(&device->post_commit_list));
rcu_string_free(device->name); rcu_string_free(device->name);
extent_io_tree_release(&device->alloc_state);
btrfs_destroy_dev_zone_info(device); btrfs_destroy_dev_zone_info(device);
kfree(device); kfree(device);
} }
......
...@@ -1168,12 +1168,12 @@ int btrfs_ensure_empty_zones(struct btrfs_device *device, u64 start, u64 size) ...@@ -1168,12 +1168,12 @@ int btrfs_ensure_empty_zones(struct btrfs_device *device, u64 start, u64 size)
return -ERANGE; return -ERANGE;
/* All the zones are conventional */ /* All the zones are conventional */
if (find_next_bit(zinfo->seq_zones, begin, end) == end) if (find_next_bit(zinfo->seq_zones, end, begin) == end)
return 0; return 0;
/* All the zones are sequential and empty */ /* All the zones are sequential and empty */
if (find_next_zero_bit(zinfo->seq_zones, begin, end) == end && if (find_next_zero_bit(zinfo->seq_zones, end, begin) == end &&
find_next_zero_bit(zinfo->empty_zones, begin, end) == end) find_next_zero_bit(zinfo->empty_zones, end, begin) == end)
return 0; return 0;
for (pos = start; pos < start + size; pos += zinfo->zone_size) { for (pos = start; pos < start + size; pos += zinfo->zone_size) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment