Merge tag 'for-6.19-rc5-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs fixes from David Sterba:
- with large folios in use, fix partial incorrect update of a reflinked
range
- fix potential deadlock in iget when lookup fails and eviction is
needed
- in send, validate inline extent type while detecting file holes
- fix memory leak after an error when creating a space info
- remove zone statistics from sysfs again, the output size limitations
make it unusable, we'll do it in another way in another release
- test fixes:
- return proper error codes from block remapping tests
- fix tree root leaks in qgroup tests after errors
* tag 'for-6.19-rc5-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
btrfs: remove zoned statistics from sysfs
btrfs: fix memory leaks in create_space_info() error paths
btrfs: invalidate pages instead of truncate after reflinking
btrfs: update the Kconfig string for CONFIG_BTRFS_EXPERIMENTAL
btrfs: send: check for inline extents in range_is_hole_in_parent()
btrfs: tests: fix return 0 on rmap test failure
btrfs: tests: fix root tree leak in btrfs_test_qgroups()
btrfs: release path before iget_failed() in btrfs_read_locked_inode()
This commit is contained in:
@@ -115,6 +115,10 @@ config BTRFS_EXPERIMENTAL
|
||||
|
||||
- extent tree v2 - complex rework of extent tracking
|
||||
|
||||
- large folio support
|
||||
- large folio and block size (> page size) support
|
||||
|
||||
- shutdown ioctl and auto-degradation support
|
||||
|
||||
- asynchronous checksum generation for data writes
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
@@ -4180,6 +4180,15 @@ cache_acl:
|
||||
|
||||
return 0;
|
||||
out:
|
||||
/*
|
||||
* We may have a read locked leaf and iget_failed() triggers inode
|
||||
* eviction which needs to release the delayed inode and that needs
|
||||
* to lock the delayed inode's mutex. This can cause a ABBA deadlock
|
||||
* with a task running delayed items, as that require first locking
|
||||
* the delayed inode's mutex and then modifying its subvolume btree.
|
||||
* So release the path before iget_failed().
|
||||
*/
|
||||
btrfs_release_path(path);
|
||||
iget_failed(vfs_inode);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -705,7 +705,6 @@ static noinline int btrfs_clone_files(struct file *file, struct file *file_src,
|
||||
struct inode *src = file_inode(file_src);
|
||||
struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
|
||||
int ret;
|
||||
int wb_ret;
|
||||
u64 len = olen;
|
||||
u64 bs = fs_info->sectorsize;
|
||||
u64 end;
|
||||
@@ -750,25 +749,29 @@ static noinline int btrfs_clone_files(struct file *file, struct file *file_src,
|
||||
btrfs_lock_extent(&BTRFS_I(inode)->io_tree, destoff, end, &cached_state);
|
||||
ret = btrfs_clone(src, inode, off, olen, len, destoff, 0);
|
||||
btrfs_unlock_extent(&BTRFS_I(inode)->io_tree, destoff, end, &cached_state);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* We may have copied an inline extent into a page of the destination
|
||||
* range, so wait for writeback to complete before truncating pages
|
||||
* range, so wait for writeback to complete before invalidating pages
|
||||
* from the page cache. This is a rare case.
|
||||
*/
|
||||
wb_ret = btrfs_wait_ordered_range(BTRFS_I(inode), destoff, len);
|
||||
ret = ret ? ret : wb_ret;
|
||||
ret = btrfs_wait_ordered_range(BTRFS_I(inode), destoff, len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Truncate page cache pages so that future reads will see the cloned
|
||||
* data immediately and not the previous data.
|
||||
* Invalidate page cache so that future reads will see the cloned data
|
||||
* immediately and not the previous data.
|
||||
*/
|
||||
truncate_inode_pages_range(&inode->i_data,
|
||||
round_down(destoff, PAGE_SIZE),
|
||||
round_up(destoff + len, PAGE_SIZE) - 1);
|
||||
ret = filemap_invalidate_inode(inode, false, destoff, end);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
btrfs_btree_balance_dirty(fs_info);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int btrfs_remap_file_range_prep(struct file *file_in, loff_t pos_in,
|
||||
|
||||
@@ -6383,6 +6383,8 @@ static int range_is_hole_in_parent(struct send_ctx *sctx,
|
||||
extent_end = btrfs_file_extent_end(path);
|
||||
if (extent_end <= start)
|
||||
goto next;
|
||||
if (btrfs_file_extent_type(leaf, fi) == BTRFS_FILE_EXTENT_INLINE)
|
||||
return 0;
|
||||
if (btrfs_file_extent_disk_bytenr(leaf, fi) == 0) {
|
||||
search_start = extent_end;
|
||||
goto next;
|
||||
|
||||
@@ -306,18 +306,22 @@ static int create_space_info(struct btrfs_fs_info *info, u64 flags)
|
||||
0);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
ret = btrfs_sysfs_add_space_info_type(space_info);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto out_free;
|
||||
|
||||
list_add(&space_info->list, &info->space_info);
|
||||
if (flags & BTRFS_BLOCK_GROUP_DATA)
|
||||
info->data_sinfo = space_info;
|
||||
|
||||
return ret;
|
||||
|
||||
out_free:
|
||||
kfree(space_info);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int btrfs_init_space_info(struct btrfs_fs_info *fs_info)
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
#include "misc.h"
|
||||
#include "fs.h"
|
||||
#include "accessors.h"
|
||||
#include "zoned.h"
|
||||
|
||||
/*
|
||||
* Structure name Path
|
||||
@@ -1189,56 +1188,6 @@ static ssize_t btrfs_commit_stats_store(struct kobject *kobj,
|
||||
}
|
||||
BTRFS_ATTR_RW(, commit_stats, btrfs_commit_stats_show, btrfs_commit_stats_store);
|
||||
|
||||
static ssize_t btrfs_zoned_stats_show(struct kobject *kobj,
|
||||
struct kobj_attribute *a, char *buf)
|
||||
{
|
||||
struct btrfs_fs_info *fs_info = to_fs_info(kobj);
|
||||
struct btrfs_block_group *bg;
|
||||
size_t ret = 0;
|
||||
|
||||
|
||||
if (!btrfs_is_zoned(fs_info))
|
||||
return ret;
|
||||
|
||||
spin_lock(&fs_info->zone_active_bgs_lock);
|
||||
ret += sysfs_emit_at(buf, ret, "active block-groups: %zu\n",
|
||||
list_count_nodes(&fs_info->zone_active_bgs));
|
||||
spin_unlock(&fs_info->zone_active_bgs_lock);
|
||||
|
||||
mutex_lock(&fs_info->reclaim_bgs_lock);
|
||||
spin_lock(&fs_info->unused_bgs_lock);
|
||||
ret += sysfs_emit_at(buf, ret, "\treclaimable: %zu\n",
|
||||
list_count_nodes(&fs_info->reclaim_bgs));
|
||||
ret += sysfs_emit_at(buf, ret, "\tunused: %zu\n",
|
||||
list_count_nodes(&fs_info->unused_bgs));
|
||||
spin_unlock(&fs_info->unused_bgs_lock);
|
||||
mutex_unlock(&fs_info->reclaim_bgs_lock);
|
||||
|
||||
ret += sysfs_emit_at(buf, ret, "\tneed reclaim: %s\n",
|
||||
str_true_false(btrfs_zoned_should_reclaim(fs_info)));
|
||||
|
||||
if (fs_info->data_reloc_bg)
|
||||
ret += sysfs_emit_at(buf, ret,
|
||||
"data relocation block-group: %llu\n",
|
||||
fs_info->data_reloc_bg);
|
||||
if (fs_info->treelog_bg)
|
||||
ret += sysfs_emit_at(buf, ret,
|
||||
"tree-log block-group: %llu\n",
|
||||
fs_info->treelog_bg);
|
||||
|
||||
spin_lock(&fs_info->zone_active_bgs_lock);
|
||||
ret += sysfs_emit_at(buf, ret, "active zones:\n");
|
||||
list_for_each_entry(bg, &fs_info->zone_active_bgs, active_bg_list) {
|
||||
ret += sysfs_emit_at(buf, ret,
|
||||
"\tstart: %llu, wp: %llu used: %llu, reserved: %llu, unusable: %llu\n",
|
||||
bg->start, bg->alloc_offset, bg->used,
|
||||
bg->reserved, bg->zone_unusable);
|
||||
}
|
||||
spin_unlock(&fs_info->zone_active_bgs_lock);
|
||||
return ret;
|
||||
}
|
||||
BTRFS_ATTR(, zoned_stats, btrfs_zoned_stats_show);
|
||||
|
||||
static ssize_t btrfs_clone_alignment_show(struct kobject *kobj,
|
||||
struct kobj_attribute *a, char *buf)
|
||||
{
|
||||
@@ -1651,7 +1600,6 @@ static const struct attribute *btrfs_attrs[] = {
|
||||
BTRFS_ATTR_PTR(, bg_reclaim_threshold),
|
||||
BTRFS_ATTR_PTR(, commit_stats),
|
||||
BTRFS_ATTR_PTR(, temp_fsid),
|
||||
BTRFS_ATTR_PTR(, zoned_stats),
|
||||
#ifdef CONFIG_BTRFS_EXPERIMENTAL
|
||||
BTRFS_ATTR_PTR(, offload_csum),
|
||||
#endif
|
||||
|
||||
@@ -1059,6 +1059,7 @@ static int test_rmap_block(struct btrfs_fs_info *fs_info,
|
||||
|
||||
if (out_stripe_len != BTRFS_STRIPE_LEN) {
|
||||
test_err("calculated stripe length doesn't match");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1066,12 +1067,14 @@ static int test_rmap_block(struct btrfs_fs_info *fs_info,
|
||||
for (i = 0; i < out_ndaddrs; i++)
|
||||
test_msg("mapped %llu", logical[i]);
|
||||
test_err("unexpected number of mapped addresses: %d", out_ndaddrs);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < out_ndaddrs; i++) {
|
||||
if (logical[i] != test->mapped_logical[i]) {
|
||||
test_err("unexpected logical address mapped");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -517,11 +517,11 @@ int btrfs_test_qgroups(u32 sectorsize, u32 nodesize)
|
||||
tmp_root->root_key.objectid = BTRFS_FS_TREE_OBJECTID;
|
||||
root->fs_info->fs_root = tmp_root;
|
||||
ret = btrfs_insert_fs_root(root->fs_info, tmp_root);
|
||||
btrfs_put_root(tmp_root);
|
||||
if (ret) {
|
||||
test_err("couldn't insert fs root %d", ret);
|
||||
goto out;
|
||||
}
|
||||
btrfs_put_root(tmp_root);
|
||||
|
||||
tmp_root = btrfs_alloc_dummy_root(fs_info);
|
||||
if (IS_ERR(tmp_root)) {
|
||||
@@ -532,11 +532,11 @@ int btrfs_test_qgroups(u32 sectorsize, u32 nodesize)
|
||||
|
||||
tmp_root->root_key.objectid = BTRFS_FIRST_FREE_OBJECTID;
|
||||
ret = btrfs_insert_fs_root(root->fs_info, tmp_root);
|
||||
btrfs_put_root(tmp_root);
|
||||
if (ret) {
|
||||
test_err("couldn't insert fs root %d", ret);
|
||||
test_err("couldn't insert subvolume root %d", ret);
|
||||
goto out;
|
||||
}
|
||||
btrfs_put_root(tmp_root);
|
||||
|
||||
test_msg("running qgroup tests");
|
||||
ret = test_no_shared_qgroup(root, sectorsize, nodesize);
|
||||
|
||||
Reference in New Issue
Block a user