mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 20:51:03 +02:00
Merge tag 'for-6.4-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull more btrfs fixes from David Sterba: - fix incorrect number of bitmap entries for space cache if loading is interrupted by some error - fix backref walking, this breaks a mode of LOGICAL_INO_V2 ioctl that is used in deduplication tools - zoned mode fixes: - properly finish zone reserved for relocation - correctly calculate super block zone end on ZNS - properly initialize new extent buffer for redirty - make mount option clear_cache work with block-group-tree, to rebuild free-space-tree instead of temporarily disabling it that would lead to a forced read-only mount - fix alignment check for offset when printing extent item * tag 'for-6.4-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: btrfs: make clear_cache mount option to rebuild FST without disabling it btrfs: zero the buffer before marking it dirty in btrfs_redirty_list_add btrfs: zoned: fix full zone super block reading on ZNS btrfs: zoned: zone finish data relocation BG with last IO btrfs: fix backref walking not returning all inode refs btrfs: fix space cache inconsistency after error loading it from disk btrfs: print-tree: parent bytenr must be aligned to sector size
This commit is contained in:
@@ -45,7 +45,8 @@ static int check_extent_in_eb(struct btrfs_backref_walk_ctx *ctx,
|
|||||||
int root_count;
|
int root_count;
|
||||||
bool cached;
|
bool cached;
|
||||||
|
|
||||||
if (!btrfs_file_extent_compression(eb, fi) &&
|
if (!ctx->ignore_extent_item_pos &&
|
||||||
|
!btrfs_file_extent_compression(eb, fi) &&
|
||||||
!btrfs_file_extent_encryption(eb, fi) &&
|
!btrfs_file_extent_encryption(eb, fi) &&
|
||||||
!btrfs_file_extent_other_encoding(eb, fi)) {
|
!btrfs_file_extent_other_encoding(eb, fi)) {
|
||||||
u64 data_offset;
|
u64 data_offset;
|
||||||
@@ -552,7 +553,7 @@ static int add_all_parents(struct btrfs_backref_walk_ctx *ctx,
|
|||||||
count++;
|
count++;
|
||||||
else
|
else
|
||||||
goto next;
|
goto next;
|
||||||
if (!ctx->ignore_extent_item_pos) {
|
if (!ctx->skip_inode_ref_list) {
|
||||||
ret = check_extent_in_eb(ctx, &key, eb, fi, &eie);
|
ret = check_extent_in_eb(ctx, &key, eb, fi, &eie);
|
||||||
if (ret == BTRFS_ITERATE_EXTENT_INODES_STOP ||
|
if (ret == BTRFS_ITERATE_EXTENT_INODES_STOP ||
|
||||||
ret < 0)
|
ret < 0)
|
||||||
@@ -564,7 +565,7 @@ static int add_all_parents(struct btrfs_backref_walk_ctx *ctx,
|
|||||||
eie, (void **)&old, GFP_NOFS);
|
eie, (void **)&old, GFP_NOFS);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
break;
|
break;
|
||||||
if (!ret && !ctx->ignore_extent_item_pos) {
|
if (!ret && !ctx->skip_inode_ref_list) {
|
||||||
while (old->next)
|
while (old->next)
|
||||||
old = old->next;
|
old = old->next;
|
||||||
old->next = eie;
|
old->next = eie;
|
||||||
@@ -1606,7 +1607,7 @@ again:
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (ref->count && ref->parent) {
|
if (ref->count && ref->parent) {
|
||||||
if (!ctx->ignore_extent_item_pos && !ref->inode_list &&
|
if (!ctx->skip_inode_ref_list && !ref->inode_list &&
|
||||||
ref->level == 0) {
|
ref->level == 0) {
|
||||||
struct btrfs_tree_parent_check check = { 0 };
|
struct btrfs_tree_parent_check check = { 0 };
|
||||||
struct extent_buffer *eb;
|
struct extent_buffer *eb;
|
||||||
@@ -1647,7 +1648,7 @@ again:
|
|||||||
(void **)&eie, GFP_NOFS);
|
(void **)&eie, GFP_NOFS);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
goto out;
|
||||||
if (!ret && !ctx->ignore_extent_item_pos) {
|
if (!ret && !ctx->skip_inode_ref_list) {
|
||||||
/*
|
/*
|
||||||
* We've recorded that parent, so we must extend
|
* We've recorded that parent, so we must extend
|
||||||
* its inode list here.
|
* its inode list here.
|
||||||
@@ -1743,7 +1744,7 @@ int btrfs_find_all_leafs(struct btrfs_backref_walk_ctx *ctx)
|
|||||||
static int btrfs_find_all_roots_safe(struct btrfs_backref_walk_ctx *ctx)
|
static int btrfs_find_all_roots_safe(struct btrfs_backref_walk_ctx *ctx)
|
||||||
{
|
{
|
||||||
const u64 orig_bytenr = ctx->bytenr;
|
const u64 orig_bytenr = ctx->bytenr;
|
||||||
const bool orig_ignore_extent_item_pos = ctx->ignore_extent_item_pos;
|
const bool orig_skip_inode_ref_list = ctx->skip_inode_ref_list;
|
||||||
bool roots_ulist_allocated = false;
|
bool roots_ulist_allocated = false;
|
||||||
struct ulist_iterator uiter;
|
struct ulist_iterator uiter;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@@ -1764,7 +1765,7 @@ static int btrfs_find_all_roots_safe(struct btrfs_backref_walk_ctx *ctx)
|
|||||||
roots_ulist_allocated = true;
|
roots_ulist_allocated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->ignore_extent_item_pos = true;
|
ctx->skip_inode_ref_list = true;
|
||||||
|
|
||||||
ULIST_ITER_INIT(&uiter);
|
ULIST_ITER_INIT(&uiter);
|
||||||
while (1) {
|
while (1) {
|
||||||
@@ -1789,7 +1790,7 @@ static int btrfs_find_all_roots_safe(struct btrfs_backref_walk_ctx *ctx)
|
|||||||
ulist_free(ctx->refs);
|
ulist_free(ctx->refs);
|
||||||
ctx->refs = NULL;
|
ctx->refs = NULL;
|
||||||
ctx->bytenr = orig_bytenr;
|
ctx->bytenr = orig_bytenr;
|
||||||
ctx->ignore_extent_item_pos = orig_ignore_extent_item_pos;
|
ctx->skip_inode_ref_list = orig_skip_inode_ref_list;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -1912,7 +1913,7 @@ int btrfs_is_data_extent_shared(struct btrfs_inode *inode, u64 bytenr,
|
|||||||
goto out_trans;
|
goto out_trans;
|
||||||
}
|
}
|
||||||
|
|
||||||
walk_ctx.ignore_extent_item_pos = true;
|
walk_ctx.skip_inode_ref_list = true;
|
||||||
walk_ctx.trans = trans;
|
walk_ctx.trans = trans;
|
||||||
walk_ctx.fs_info = fs_info;
|
walk_ctx.fs_info = fs_info;
|
||||||
walk_ctx.refs = &ctx->refs;
|
walk_ctx.refs = &ctx->refs;
|
||||||
|
@@ -60,6 +60,12 @@ struct btrfs_backref_walk_ctx {
|
|||||||
* @extent_item_pos is ignored.
|
* @extent_item_pos is ignored.
|
||||||
*/
|
*/
|
||||||
bool ignore_extent_item_pos;
|
bool ignore_extent_item_pos;
|
||||||
|
/*
|
||||||
|
* If true and bytenr corresponds to a data extent, then the inode list
|
||||||
|
* (each member describing inode number, file offset and root) is not
|
||||||
|
* added to each reference added to the @refs ulist.
|
||||||
|
*/
|
||||||
|
bool skip_inode_ref_list;
|
||||||
/* A valid transaction handle or NULL. */
|
/* A valid transaction handle or NULL. */
|
||||||
struct btrfs_trans_handle *trans;
|
struct btrfs_trans_handle *trans;
|
||||||
/*
|
/*
|
||||||
|
@@ -3121,23 +3121,34 @@ int btrfs_start_pre_rw_mount(struct btrfs_fs_info *fs_info)
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
const bool cache_opt = btrfs_test_opt(fs_info, SPACE_CACHE);
|
const bool cache_opt = btrfs_test_opt(fs_info, SPACE_CACHE);
|
||||||
bool clear_free_space_tree = false;
|
bool rebuild_free_space_tree = false;
|
||||||
|
|
||||||
if (btrfs_test_opt(fs_info, CLEAR_CACHE) &&
|
if (btrfs_test_opt(fs_info, CLEAR_CACHE) &&
|
||||||
btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) {
|
btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) {
|
||||||
clear_free_space_tree = true;
|
rebuild_free_space_tree = true;
|
||||||
} else if (btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE) &&
|
} else if (btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE) &&
|
||||||
!btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE_VALID)) {
|
!btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE_VALID)) {
|
||||||
btrfs_warn(fs_info, "free space tree is invalid");
|
btrfs_warn(fs_info, "free space tree is invalid");
|
||||||
clear_free_space_tree = true;
|
rebuild_free_space_tree = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clear_free_space_tree) {
|
if (rebuild_free_space_tree) {
|
||||||
btrfs_info(fs_info, "clearing free space tree");
|
btrfs_info(fs_info, "rebuilding free space tree");
|
||||||
ret = btrfs_clear_free_space_tree(fs_info);
|
ret = btrfs_rebuild_free_space_tree(fs_info);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
btrfs_warn(fs_info,
|
btrfs_warn(fs_info,
|
||||||
"failed to clear free space tree: %d", ret);
|
"failed to rebuild free space tree: %d", ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE) &&
|
||||||
|
!btrfs_test_opt(fs_info, FREE_SPACE_TREE)) {
|
||||||
|
btrfs_info(fs_info, "disabling free space tree");
|
||||||
|
ret = btrfs_delete_free_space_tree(fs_info);
|
||||||
|
if (ret) {
|
||||||
|
btrfs_warn(fs_info,
|
||||||
|
"failed to disable free space tree: %d", ret);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -870,15 +870,16 @@ static int __load_free_space_cache(struct btrfs_root *root, struct inode *inode,
|
|||||||
}
|
}
|
||||||
spin_lock(&ctl->tree_lock);
|
spin_lock(&ctl->tree_lock);
|
||||||
ret = link_free_space(ctl, e);
|
ret = link_free_space(ctl, e);
|
||||||
ctl->total_bitmaps++;
|
|
||||||
recalculate_thresholds(ctl);
|
|
||||||
spin_unlock(&ctl->tree_lock);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
spin_unlock(&ctl->tree_lock);
|
||||||
btrfs_err(fs_info,
|
btrfs_err(fs_info,
|
||||||
"Duplicate entries in free space cache, dumping");
|
"Duplicate entries in free space cache, dumping");
|
||||||
kmem_cache_free(btrfs_free_space_cachep, e);
|
kmem_cache_free(btrfs_free_space_cachep, e);
|
||||||
goto free_cache;
|
goto free_cache;
|
||||||
}
|
}
|
||||||
|
ctl->total_bitmaps++;
|
||||||
|
recalculate_thresholds(ctl);
|
||||||
|
spin_unlock(&ctl->tree_lock);
|
||||||
list_add_tail(&e->list, &bitmaps);
|
list_add_tail(&e->list, &bitmaps);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1252,7 +1252,7 @@ out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int btrfs_clear_free_space_tree(struct btrfs_fs_info *fs_info)
|
int btrfs_delete_free_space_tree(struct btrfs_fs_info *fs_info)
|
||||||
{
|
{
|
||||||
struct btrfs_trans_handle *trans;
|
struct btrfs_trans_handle *trans;
|
||||||
struct btrfs_root *tree_root = fs_info->tree_root;
|
struct btrfs_root *tree_root = fs_info->tree_root;
|
||||||
@@ -1298,6 +1298,54 @@ abort:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int btrfs_rebuild_free_space_tree(struct btrfs_fs_info *fs_info)
|
||||||
|
{
|
||||||
|
struct btrfs_trans_handle *trans;
|
||||||
|
struct btrfs_key key = {
|
||||||
|
.objectid = BTRFS_FREE_SPACE_TREE_OBJECTID,
|
||||||
|
.type = BTRFS_ROOT_ITEM_KEY,
|
||||||
|
.offset = 0,
|
||||||
|
};
|
||||||
|
struct btrfs_root *free_space_root = btrfs_global_root(fs_info, &key);
|
||||||
|
struct rb_node *node;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
trans = btrfs_start_transaction(free_space_root, 1);
|
||||||
|
if (IS_ERR(trans))
|
||||||
|
return PTR_ERR(trans);
|
||||||
|
|
||||||
|
set_bit(BTRFS_FS_CREATING_FREE_SPACE_TREE, &fs_info->flags);
|
||||||
|
set_bit(BTRFS_FS_FREE_SPACE_TREE_UNTRUSTED, &fs_info->flags);
|
||||||
|
|
||||||
|
ret = clear_free_space_tree(trans, free_space_root);
|
||||||
|
if (ret)
|
||||||
|
goto abort;
|
||||||
|
|
||||||
|
node = rb_first_cached(&fs_info->block_group_cache_tree);
|
||||||
|
while (node) {
|
||||||
|
struct btrfs_block_group *block_group;
|
||||||
|
|
||||||
|
block_group = rb_entry(node, struct btrfs_block_group,
|
||||||
|
cache_node);
|
||||||
|
ret = populate_free_space_tree(trans, block_group);
|
||||||
|
if (ret)
|
||||||
|
goto abort;
|
||||||
|
node = rb_next(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
btrfs_set_fs_compat_ro(fs_info, FREE_SPACE_TREE);
|
||||||
|
btrfs_set_fs_compat_ro(fs_info, FREE_SPACE_TREE_VALID);
|
||||||
|
clear_bit(BTRFS_FS_CREATING_FREE_SPACE_TREE, &fs_info->flags);
|
||||||
|
|
||||||
|
ret = btrfs_commit_transaction(trans);
|
||||||
|
clear_bit(BTRFS_FS_FREE_SPACE_TREE_UNTRUSTED, &fs_info->flags);
|
||||||
|
return ret;
|
||||||
|
abort:
|
||||||
|
btrfs_abort_transaction(trans, ret);
|
||||||
|
btrfs_end_transaction(trans);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int __add_block_group_free_space(struct btrfs_trans_handle *trans,
|
static int __add_block_group_free_space(struct btrfs_trans_handle *trans,
|
||||||
struct btrfs_block_group *block_group,
|
struct btrfs_block_group *block_group,
|
||||||
struct btrfs_path *path)
|
struct btrfs_path *path)
|
||||||
|
@@ -18,7 +18,8 @@ struct btrfs_caching_control;
|
|||||||
|
|
||||||
void set_free_space_tree_thresholds(struct btrfs_block_group *block_group);
|
void set_free_space_tree_thresholds(struct btrfs_block_group *block_group);
|
||||||
int btrfs_create_free_space_tree(struct btrfs_fs_info *fs_info);
|
int btrfs_create_free_space_tree(struct btrfs_fs_info *fs_info);
|
||||||
int btrfs_clear_free_space_tree(struct btrfs_fs_info *fs_info);
|
int btrfs_delete_free_space_tree(struct btrfs_fs_info *fs_info);
|
||||||
|
int btrfs_rebuild_free_space_tree(struct btrfs_fs_info *fs_info);
|
||||||
int load_free_space_tree(struct btrfs_caching_control *caching_ctl);
|
int load_free_space_tree(struct btrfs_caching_control *caching_ctl);
|
||||||
int add_block_group_free_space(struct btrfs_trans_handle *trans,
|
int add_block_group_free_space(struct btrfs_trans_handle *trans,
|
||||||
struct btrfs_block_group *block_group);
|
struct btrfs_block_group *block_group);
|
||||||
|
@@ -3108,6 +3108,9 @@ int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
|
|||||||
btrfs_rewrite_logical_zoned(ordered_extent);
|
btrfs_rewrite_logical_zoned(ordered_extent);
|
||||||
btrfs_zone_finish_endio(fs_info, ordered_extent->disk_bytenr,
|
btrfs_zone_finish_endio(fs_info, ordered_extent->disk_bytenr,
|
||||||
ordered_extent->disk_num_bytes);
|
ordered_extent->disk_num_bytes);
|
||||||
|
} else if (btrfs_is_data_reloc_root(inode->root)) {
|
||||||
|
btrfs_zone_finish_endio(fs_info, ordered_extent->disk_bytenr,
|
||||||
|
ordered_extent->disk_num_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test_bit(BTRFS_ORDERED_TRUNCATED, &ordered_extent->flags)) {
|
if (test_bit(BTRFS_ORDERED_TRUNCATED, &ordered_extent->flags)) {
|
||||||
|
@@ -151,10 +151,10 @@ static void print_extent_item(struct extent_buffer *eb, int slot, int type)
|
|||||||
pr_cont("shared data backref parent %llu count %u\n",
|
pr_cont("shared data backref parent %llu count %u\n",
|
||||||
offset, btrfs_shared_data_ref_count(eb, sref));
|
offset, btrfs_shared_data_ref_count(eb, sref));
|
||||||
/*
|
/*
|
||||||
* offset is supposed to be a tree block which
|
* Offset is supposed to be a tree block which must be
|
||||||
* must be aligned to nodesize.
|
* aligned to sectorsize.
|
||||||
*/
|
*/
|
||||||
if (!IS_ALIGNED(offset, eb->fs_info->nodesize))
|
if (!IS_ALIGNED(offset, eb->fs_info->sectorsize))
|
||||||
pr_info(
|
pr_info(
|
||||||
"\t\t\t(parent %llu not aligned to sectorsize %u)\n",
|
"\t\t\t(parent %llu not aligned to sectorsize %u)\n",
|
||||||
offset, eb->fs_info->sectorsize);
|
offset, eb->fs_info->sectorsize);
|
||||||
|
@@ -3422,7 +3422,7 @@ int add_data_references(struct reloc_control *rc,
|
|||||||
btrfs_release_path(path);
|
btrfs_release_path(path);
|
||||||
|
|
||||||
ctx.bytenr = extent_key->objectid;
|
ctx.bytenr = extent_key->objectid;
|
||||||
ctx.ignore_extent_item_pos = true;
|
ctx.skip_inode_ref_list = true;
|
||||||
ctx.fs_info = rc->extent_root->fs_info;
|
ctx.fs_info = rc->extent_root->fs_info;
|
||||||
|
|
||||||
ret = btrfs_find_all_leafs(&ctx);
|
ret = btrfs_find_all_leafs(&ctx);
|
||||||
|
@@ -828,8 +828,7 @@ out:
|
|||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
}
|
}
|
||||||
if (btrfs_fs_compat_ro(info, BLOCK_GROUP_TREE) &&
|
if (btrfs_fs_compat_ro(info, BLOCK_GROUP_TREE) &&
|
||||||
(btrfs_test_opt(info, CLEAR_CACHE) ||
|
!btrfs_test_opt(info, FREE_SPACE_TREE)) {
|
||||||
!btrfs_test_opt(info, FREE_SPACE_TREE))) {
|
|
||||||
btrfs_err(info, "cannot disable free space tree with block-group-tree feature");
|
btrfs_err(info, "cannot disable free space tree with block-group-tree feature");
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
}
|
}
|
||||||
|
@@ -122,10 +122,9 @@ static int sb_write_pointer(struct block_device *bdev, struct blk_zone *zones,
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < BTRFS_NR_SB_LOG_ZONES; i++) {
|
for (i = 0; i < BTRFS_NR_SB_LOG_ZONES; i++) {
|
||||||
u64 bytenr;
|
u64 zone_end = (zones[i].start + zones[i].capacity) << SECTOR_SHIFT;
|
||||||
|
u64 bytenr = ALIGN_DOWN(zone_end, BTRFS_SUPER_INFO_SIZE) -
|
||||||
bytenr = ((zones[i].start + zones[i].len)
|
BTRFS_SUPER_INFO_SIZE;
|
||||||
<< SECTOR_SHIFT) - BTRFS_SUPER_INFO_SIZE;
|
|
||||||
|
|
||||||
page[i] = read_cache_page_gfp(mapping,
|
page[i] = read_cache_page_gfp(mapping,
|
||||||
bytenr >> PAGE_SHIFT, GFP_NOFS);
|
bytenr >> PAGE_SHIFT, GFP_NOFS);
|
||||||
@@ -1610,11 +1609,11 @@ void btrfs_redirty_list_add(struct btrfs_transaction *trans,
|
|||||||
!list_empty(&eb->release_list))
|
!list_empty(&eb->release_list))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
memzero_extent_buffer(eb, 0, eb->len);
|
||||||
|
set_bit(EXTENT_BUFFER_NO_CHECK, &eb->bflags);
|
||||||
set_extent_buffer_dirty(eb);
|
set_extent_buffer_dirty(eb);
|
||||||
set_extent_bits_nowait(&trans->dirty_pages, eb->start,
|
set_extent_bits_nowait(&trans->dirty_pages, eb->start,
|
||||||
eb->start + eb->len - 1, EXTENT_DIRTY);
|
eb->start + eb->len - 1, EXTENT_DIRTY);
|
||||||
memzero_extent_buffer(eb, 0, eb->len);
|
|
||||||
set_bit(EXTENT_BUFFER_NO_CHECK, &eb->bflags);
|
|
||||||
|
|
||||||
spin_lock(&trans->releasing_ebs_lock);
|
spin_lock(&trans->releasing_ebs_lock);
|
||||||
list_add_tail(&eb->release_list, &trans->releasing_ebs);
|
list_add_tail(&eb->release_list, &trans->releasing_ebs);
|
||||||
|
Reference in New Issue
Block a user