mirror of
https://github.com/torvalds/linux.git
synced 2026-05-12 16:18:45 +02:00
for-7.1-rc1-tag
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEE8rQSAMVO+zA4DBdWxWXV+ddtWDsFAmnvdO8ACgkQxWXV+ddt
WDuLqA//fcHDOnClWHRRUaIWhhkMYm7gNZkXf2d+qyYLMtAP2Cv2sZ+aV+OkHp5D
/Gq1W1mUXZLabu0EV0xKICn01nwzWtbZwDO8Bo3+QEdLoAi2gITODsYyY8yeW9KO
GfSBPsom+d7ktVrjaYE7Ppcm6YifBjWNDDcC+MX7Kpy+OUqhyOtsJIaEeTwii9+P
eiyAAC1zqrHZtaQfLsY3WvM0baNaqlm1xURMjJPyRCAtjGpjZy1hK/iFsGcHRlfc
SR//WT/MRnUAFn8zlIBG0wNrk1IEIgPPiA7hAXMRGXFKo0C6ICYLl5MJQh/o/MUs
tFBdkBhtcX/Kynvwb059SyalXZzVhQvzaRN89ZGuDyalNiejRzb8F2oVCfKAVKIU
MdkKOjnR5b7BUzCcZ1cJf1LgX4SngYKTnXrNGHpW0fuUzX6moJEd4wbrgmHjk9ke
+TVdl2vcpAduvBU9idkpDAcUW998tcYmX/LyQhGYpR6k/4n2UdFZJPINqco3pOAO
RIFbIgEAq9rUi+GMSJdEDMO6xLmUYoI6vaw7uZSU6E04zJPiVIcixfRDCBKGPV5Q
Yl9PC3ViLSlgKWaG7UVl8PVaSkCQ7esbfPAnNI/+RBCUeehhSFygePcY+kH1k4LA
0qMne1abDysUVwolb/1de/fqkznLlB3SlA447HwdvwMI0mCSb7w=
=ajKs
-----END PGP SIGNATURE-----
Merge tag 'for-7.1-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs fixes from David Sterba:
- space reservation fixes:
- correctly undo 'may_use' accounting for remap tree
- avoid double decrement of 'may_use' when submitting async io
- actually enable the shutdown ioctl callback (not just the superblock
ops)
- raid stripe tree fixes when deleting extents
- add missing error handling
- fix various incorrect values set
- fix transaction state when removing a directory, possibly leading to
EIO during log replay
- additional b-tree node key checks during metadata readahead
- error handling and transaction abort updates
* tag 'for-7.1-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
btrfs: fix double-decrement of bytes_may_use in submit_one_async_extent()
btrfs: check return value of btrfs_partially_delete_raid_extent()
btrfs: handle -EAGAIN from btrfs_duplicate_item and refresh stale leaf pointer
btrfs: replace ASSERT with proper error handling in stripe lookup fallback
btrfs: fix wrong min_objectid in btrfs_previous_item() call
btrfs: fix raid stripe search missing entries at leaf boundaries
btrfs: copy devid in btrfs_partially_delete_raid_extent()
btrfs: handle unexpected free-space-tree key types
btrfs: fix missing last_unlink_trans update when removing a directory
btrfs: don't clobber errors in add_remap_tree_entries()
btrfs: enable shutdown ioctl for non-experimental builds
btrfs: apply first key check for readahead when possible
btrfs: abort transaction in do_remap_reloc_trans() on failure
btrfs: fix bytes_may_use leak in do_remap_reloc_trans()
btrfs: fix bytes_may_use leak in move_existing_remap()
This commit is contained in:
commit
73082fbdb1
|
|
@ -4641,7 +4641,8 @@ int try_release_extent_buffer(struct folio *folio)
|
|||
* to read the block we will not block on anything.
|
||||
*/
|
||||
void btrfs_readahead_tree_block(struct btrfs_fs_info *fs_info,
|
||||
u64 bytenr, u64 owner_root, u64 gen, int level)
|
||||
u64 bytenr, u64 owner_root, u64 gen, int level,
|
||||
const struct btrfs_key *first_key)
|
||||
{
|
||||
struct btrfs_tree_parent_check check = {
|
||||
.level = level,
|
||||
|
|
@ -4650,6 +4651,11 @@ void btrfs_readahead_tree_block(struct btrfs_fs_info *fs_info,
|
|||
struct extent_buffer *eb;
|
||||
int ret;
|
||||
|
||||
if (first_key) {
|
||||
memcpy(&check.first_key, first_key, sizeof(struct btrfs_key));
|
||||
check.has_first_key = true;
|
||||
}
|
||||
|
||||
eb = btrfs_find_create_tree_block(fs_info, bytenr, owner_root, level);
|
||||
if (IS_ERR(eb))
|
||||
return;
|
||||
|
|
@ -4677,9 +4683,13 @@ void btrfs_readahead_tree_block(struct btrfs_fs_info *fs_info,
|
|||
*/
|
||||
void btrfs_readahead_node_child(struct extent_buffer *node, int slot)
|
||||
{
|
||||
struct btrfs_key node_key;
|
||||
|
||||
btrfs_node_key_to_cpu(node, &node_key, slot);
|
||||
btrfs_readahead_tree_block(node->fs_info,
|
||||
btrfs_node_blockptr(node, slot),
|
||||
btrfs_header_owner(node),
|
||||
btrfs_node_ptr_generation(node, slot),
|
||||
btrfs_header_level(node) - 1);
|
||||
btrfs_header_level(node) - 1,
|
||||
&node_key);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -287,7 +287,8 @@ static inline void wait_on_extent_buffer_writeback(struct extent_buffer *eb)
|
|||
}
|
||||
|
||||
void btrfs_readahead_tree_block(struct btrfs_fs_info *fs_info,
|
||||
u64 bytenr, u64 owner_root, u64 gen, int level);
|
||||
u64 bytenr, u64 owner_root, u64 gen, int level,
|
||||
const struct btrfs_key *first_key);
|
||||
void btrfs_readahead_node_child(struct extent_buffer *node, int slot);
|
||||
|
||||
/* Note: this can be used in for loops without caching the value in a variable. */
|
||||
|
|
|
|||
|
|
@ -259,7 +259,11 @@ int btrfs_convert_free_space_to_bitmaps(struct btrfs_trans_handle *trans,
|
|||
nr++;
|
||||
path->slots[0]--;
|
||||
} else {
|
||||
ASSERT(0);
|
||||
btrfs_err(fs_info, "unexpected free space tree key type %u",
|
||||
found_key.type);
|
||||
ret = -EUCLEAN;
|
||||
btrfs_abort_transaction(trans, ret);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -405,7 +409,11 @@ int btrfs_convert_free_space_to_extents(struct btrfs_trans_handle *trans,
|
|||
|
||||
nr++;
|
||||
} else {
|
||||
ASSERT(0);
|
||||
btrfs_err(fs_info, "unexpected free space tree key type %u",
|
||||
found_key.type);
|
||||
ret = -EUCLEAN;
|
||||
btrfs_abort_transaction(trans, ret);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1518,7 +1526,11 @@ int btrfs_remove_block_group_free_space(struct btrfs_trans_handle *trans,
|
|||
nr++;
|
||||
path->slots[0]--;
|
||||
} else {
|
||||
ASSERT(0);
|
||||
btrfs_err(trans->fs_info, "unexpected free space tree key type %u",
|
||||
found_key.type);
|
||||
ret = -EUCLEAN;
|
||||
btrfs_abort_transaction(trans, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1153,7 +1153,7 @@ static void submit_one_async_extent(struct async_chunk *async_chunk,
|
|||
NULL, &cached,
|
||||
EXTENT_LOCKED | EXTENT_DELALLOC |
|
||||
EXTENT_DELALLOC_NEW |
|
||||
EXTENT_DEFRAG | EXTENT_DO_ACCOUNTING,
|
||||
EXTENT_DEFRAG | EXTENT_CLEAR_META_RESV,
|
||||
PAGE_UNLOCK | PAGE_START_WRITEBACK |
|
||||
PAGE_END_WRITEBACK);
|
||||
if (async_extent->cb)
|
||||
|
|
@ -4959,6 +4959,8 @@ static int btrfs_rmdir(struct inode *vfs_dir, struct dentry *dentry)
|
|||
if (ret)
|
||||
goto out;
|
||||
|
||||
btrfs_record_unlink_dir(trans, dir, inode, false);
|
||||
|
||||
/* now the directory is empty */
|
||||
ret = btrfs_unlink_inode(trans, dir, inode, &fname.disk_name);
|
||||
if (!ret)
|
||||
|
|
|
|||
|
|
@ -5102,7 +5102,6 @@ static int btrfs_ioctl_subvol_sync(struct btrfs_fs_info *fs_info, void __user *a
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BTRFS_EXPERIMENTAL
|
||||
static int btrfs_ioctl_shutdown(struct btrfs_fs_info *fs_info, unsigned long arg)
|
||||
{
|
||||
int ret = 0;
|
||||
|
|
@ -5134,10 +5133,12 @@ static int btrfs_ioctl_shutdown(struct btrfs_fs_info *fs_info, unsigned long arg
|
|||
case BTRFS_SHUTDOWN_FLAGS_NOLOGFLUSH:
|
||||
btrfs_force_shutdown(fs_info);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
long btrfs_ioctl(struct file *file, unsigned int
|
||||
cmd, unsigned long arg)
|
||||
|
|
@ -5294,10 +5295,8 @@ long btrfs_ioctl(struct file *file, unsigned int
|
|||
#endif
|
||||
case BTRFS_IOC_SUBVOL_SYNC_WAIT:
|
||||
return btrfs_ioctl_subvol_sync(fs_info, argp);
|
||||
#ifdef CONFIG_BTRFS_EXPERIMENTAL
|
||||
case BTRFS_IOC_SHUTDOWN:
|
||||
return btrfs_ioctl_shutdown(fs_info, arg);
|
||||
#endif
|
||||
}
|
||||
|
||||
return -ENOTTY;
|
||||
|
|
|
|||
|
|
@ -45,8 +45,11 @@ static int btrfs_partially_delete_raid_extent(struct btrfs_trans_handle *trans,
|
|||
|
||||
for (int i = 0; i < btrfs_num_raid_stripes(item_size); i++) {
|
||||
struct btrfs_raid_stride *stride = &extent->strides[i];
|
||||
u64 devid;
|
||||
u64 phys;
|
||||
|
||||
devid = btrfs_raid_stride_devid(leaf, stride);
|
||||
btrfs_set_stack_raid_stride_devid(&newitem->strides[i], devid);
|
||||
phys = btrfs_raid_stride_physical(leaf, stride) + frontpad;
|
||||
btrfs_set_stack_raid_stride_physical(&newitem->strides[i], phys);
|
||||
}
|
||||
|
|
@ -95,14 +98,26 @@ int btrfs_delete_raid_extent(struct btrfs_trans_handle *trans, u64 start, u64 le
|
|||
while (1) {
|
||||
key.objectid = start;
|
||||
key.type = BTRFS_RAID_STRIPE_KEY;
|
||||
key.offset = 0;
|
||||
key.offset = (u64)-1;
|
||||
|
||||
ret = btrfs_search_slot(trans, stripe_root, &key, path, -1, 1);
|
||||
if (ret < 0)
|
||||
break;
|
||||
|
||||
if (path->slots[0] == btrfs_header_nritems(path->nodes[0]))
|
||||
path->slots[0]--;
|
||||
/*
|
||||
* Search with offset=(u64)-1 ensures we land on the correct
|
||||
* leaf even when the target entry is the first item on a leaf.
|
||||
* Since no real entry has offset=(u64)-1, ret is always 1 and
|
||||
* slot points past the last entry with objectid==start (or
|
||||
* past the end of the leaf if that entry is the last item).
|
||||
* Back up one slot to find the actual entry.
|
||||
*/
|
||||
if (path->slots[0] == 0) {
|
||||
/* No entry with objectid <= start exists. */
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
path->slots[0]--;
|
||||
|
||||
leaf = path->nodes[0];
|
||||
slot = path->slots[0];
|
||||
|
|
@ -123,7 +138,7 @@ int btrfs_delete_raid_extent(struct btrfs_trans_handle *trans, u64 start, u64 le
|
|||
*/
|
||||
if (found_start > start) {
|
||||
if (slot == 0) {
|
||||
ret = btrfs_previous_item(stripe_root, path, start,
|
||||
ret = btrfs_previous_item(stripe_root, path, 0,
|
||||
BTRFS_RAID_STRIPE_KEY);
|
||||
if (ret) {
|
||||
if (ret > 0)
|
||||
|
|
@ -139,7 +154,10 @@ int btrfs_delete_raid_extent(struct btrfs_trans_handle *trans, u64 start, u64 le
|
|||
btrfs_item_key_to_cpu(leaf, &key, slot);
|
||||
found_start = key.objectid;
|
||||
found_end = found_start + key.offset;
|
||||
ASSERT(found_start <= start);
|
||||
if (found_start > start || found_end <= start) {
|
||||
ret = -ENOENT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (key.type != BTRFS_RAID_STRIPE_KEY)
|
||||
|
|
@ -176,9 +194,19 @@ int btrfs_delete_raid_extent(struct btrfs_trans_handle *trans, u64 start, u64 le
|
|||
|
||||
/* The "right" item. */
|
||||
ret = btrfs_duplicate_item(trans, stripe_root, path, &newkey);
|
||||
if (ret == -EAGAIN) {
|
||||
btrfs_release_path(path);
|
||||
continue;
|
||||
}
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
/*
|
||||
* btrfs_duplicate_item() may have triggered a leaf
|
||||
* split via setup_leaf_for_split(), so we must refresh
|
||||
* our leaf pointer from the path.
|
||||
*/
|
||||
leaf = path->nodes[0];
|
||||
item_size = btrfs_item_size(leaf, path->slots[0]);
|
||||
extent = btrfs_item_ptr(leaf, path->slots[0],
|
||||
struct btrfs_stripe_extent);
|
||||
|
|
@ -195,8 +223,9 @@ int btrfs_delete_raid_extent(struct btrfs_trans_handle *trans, u64 start, u64 le
|
|||
/* The "left" item. */
|
||||
path->slots[0]--;
|
||||
btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
|
||||
btrfs_partially_delete_raid_extent(trans, path, &key,
|
||||
diff_start, 0);
|
||||
ret = btrfs_partially_delete_raid_extent(trans, path,
|
||||
&key,
|
||||
diff_start, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -212,8 +241,11 @@ int btrfs_delete_raid_extent(struct btrfs_trans_handle *trans, u64 start, u64 le
|
|||
if (found_start < start) {
|
||||
u64 diff_start = start - found_start;
|
||||
|
||||
btrfs_partially_delete_raid_extent(trans, path, &key,
|
||||
diff_start, 0);
|
||||
ret = btrfs_partially_delete_raid_extent(trans, path,
|
||||
&key,
|
||||
diff_start, 0);
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
start += (key.offset - diff_start);
|
||||
length -= (key.offset - diff_start);
|
||||
|
|
@ -236,9 +268,10 @@ int btrfs_delete_raid_extent(struct btrfs_trans_handle *trans, u64 start, u64 le
|
|||
if (found_end > end) {
|
||||
u64 diff_end = found_end - end;
|
||||
|
||||
btrfs_partially_delete_raid_extent(trans, path, &key,
|
||||
key.offset - length,
|
||||
length);
|
||||
ret = btrfs_partially_delete_raid_extent(trans, path,
|
||||
&key,
|
||||
key.offset - length,
|
||||
length);
|
||||
ASSERT(key.offset - diff_end == length);
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2607,7 +2607,7 @@ int relocate_tree_blocks(struct btrfs_trans_handle *trans,
|
|||
if (!block->key_ready)
|
||||
btrfs_readahead_tree_block(fs_info, block->bytenr,
|
||||
block->owner, 0,
|
||||
block->level);
|
||||
block->level, NULL);
|
||||
}
|
||||
|
||||
/* Get first keys */
|
||||
|
|
@ -3876,7 +3876,7 @@ static int add_remap_tree_entries(struct btrfs_trans_handle *trans, struct btrfs
|
|||
ret = btrfs_insert_empty_items(trans, fs_info->remap_root, path, &batch);
|
||||
btrfs_release_path(path);
|
||||
|
||||
if (num_entries <= max_items)
|
||||
if (ret || num_entries <= max_items)
|
||||
break;
|
||||
|
||||
num_entries -= max_items;
|
||||
|
|
@ -4174,6 +4174,12 @@ static int move_existing_remap(struct btrfs_fs_info *fs_info,
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (ins.offset < length) {
|
||||
spin_lock(&sinfo->lock);
|
||||
btrfs_space_info_update_bytes_may_use(sinfo, ins.offset - length);
|
||||
spin_unlock(&sinfo->lock);
|
||||
}
|
||||
|
||||
dest_addr = ins.objectid;
|
||||
dest_length = ins.offset;
|
||||
|
||||
|
|
@ -5000,6 +5006,12 @@ static int do_remap_reloc_trans(struct btrfs_fs_info *fs_info,
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (ins.offset < remap_length) {
|
||||
spin_lock(&sinfo->lock);
|
||||
btrfs_space_info_update_bytes_may_use(sinfo, ins.offset - remap_length);
|
||||
spin_unlock(&sinfo->lock);
|
||||
}
|
||||
|
||||
made_reservation = true;
|
||||
|
||||
new_addr = ins.objectid;
|
||||
|
|
@ -5023,21 +5035,27 @@ static int do_remap_reloc_trans(struct btrfs_fs_info *fs_info,
|
|||
|
||||
if (bg_needs_free_space) {
|
||||
ret = btrfs_add_block_group_free_space(trans, dest_bg);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
btrfs_abort_transaction(trans, ret);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
ret = copy_remapped_data(fs_info, start, new_addr, length);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
btrfs_abort_transaction(trans, ret);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = btrfs_remove_from_free_space_tree(trans, new_addr, length);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
btrfs_abort_transaction(trans, ret);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = add_remap_entry(trans, path, src_bg, start, new_addr, length);
|
||||
if (ret) {
|
||||
btrfs_add_to_free_space_tree(trans, new_addr, length);
|
||||
btrfs_abort_transaction(trans, ret);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user