Skip to content

Commit

Permalink
Merge branch 'for-next-next-v6.12-20241009' into for-next-20241009
Browse files Browse the repository at this point in the history
  • Loading branch information
kdave committed Oct 9, 2024
2 parents de5b27f + 9d65b5a commit a6f63ff
Show file tree
Hide file tree
Showing 45 changed files with 1,110 additions and 815 deletions.
27 changes: 27 additions & 0 deletions fs/btrfs/Kconfig
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
# misc-next marker

config BTRFS_FS
tristate "Btrfs filesystem support"
Expand Down Expand Up @@ -78,6 +79,32 @@ config BTRFS_ASSERT

If unsure, say N.

config BTRFS_EXPERIMENTAL
bool "Btrfs experimental features"
depends on BTRFS_FS
default n
help
Enable experimental features. These features may not be stable enough
for end users. This is meant for btrfs developers or users who wish
to test the functionality and report problems.

Current list:

- extent map shrinker - performance problems with too frequent shrinks

- send stream protocol v3 - fs-verity support

- checksum offload mode - sysfs knob to affect when checksums are
calculated (at IO time, or in a thread)

- raid-stripe-tree - additional mapping of extents to devices to
support RAID1* profiles on zoned devices,
RAID56 not yet supported

- extent tree v2 - complex rework of extent tracking

If unsure, say N.

config BTRFS_FS_REF_VERIFY
bool "Btrfs with the ref verify tool compiled in"
depends on BTRFS_FS
Expand Down
3 changes: 2 additions & 1 deletion fs/btrfs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,5 @@ btrfs-$(CONFIG_FS_VERITY) += verity.o
btrfs-$(CONFIG_BTRFS_FS_RUN_SANITY_TESTS) += tests/free-space-tests.o \
tests/extent-buffer-tests.o tests/btrfs-tests.o \
tests/extent-io-tests.o tests/inode-tests.o tests/qgroup-tests.o \
tests/free-space-tree-tests.o tests/extent-map-tests.o
tests/free-space-tree-tests.o tests/extent-map-tests.o \
tests/raid-stripe-tree-tests.o
105 changes: 36 additions & 69 deletions fs/btrfs/backref.c
Original file line number Diff line number Diff line change
Expand Up @@ -3021,9 +3021,6 @@ void btrfs_backref_init_cache(struct btrfs_fs_info *fs_info,
cache->rb_root = RB_ROOT;
for (i = 0; i < BTRFS_MAX_LEVEL; i++)
INIT_LIST_HEAD(&cache->pending[i]);
INIT_LIST_HEAD(&cache->changed);
INIT_LIST_HEAD(&cache->detached);
INIT_LIST_HEAD(&cache->leaves);
INIT_LIST_HEAD(&cache->pending_edge);
INIT_LIST_HEAD(&cache->useless_node);
cache->fs_info = fs_info;
Expand Down Expand Up @@ -3131,29 +3128,17 @@ void btrfs_backref_drop_node(struct btrfs_backref_cache *tree,
void btrfs_backref_cleanup_node(struct btrfs_backref_cache *cache,
struct btrfs_backref_node *node)
{
struct btrfs_backref_node *upper;
struct btrfs_backref_edge *edge;

if (!node)
return;

BUG_ON(!node->lowest && !node->detached);
while (!list_empty(&node->upper)) {
edge = list_entry(node->upper.next, struct btrfs_backref_edge,
list[LOWER]);
upper = edge->node[UPPER];
list_del(&edge->list[LOWER]);
list_del(&edge->list[UPPER]);
btrfs_backref_free_edge(cache, edge);

/*
* Add the node to leaf node list if no other child block
* cached.
*/
if (list_empty(&upper->lower)) {
list_add_tail(&upper->lower, &cache->leaves);
upper->lowest = 1;
}
}

btrfs_backref_drop_node(cache, node);
Expand All @@ -3165,33 +3150,13 @@ void btrfs_backref_cleanup_node(struct btrfs_backref_cache *cache,
void btrfs_backref_release_cache(struct btrfs_backref_cache *cache)
{
struct btrfs_backref_node *node;
int i;

while (!list_empty(&cache->detached)) {
node = list_entry(cache->detached.next,
struct btrfs_backref_node, list);
btrfs_backref_cleanup_node(cache, node);
}

while (!list_empty(&cache->leaves)) {
node = list_entry(cache->leaves.next,
struct btrfs_backref_node, lower);
while ((node = rb_entry_safe(rb_first(&cache->rb_root),
struct btrfs_backref_node, rb_node)))
btrfs_backref_cleanup_node(cache, node);
}

for (i = 0; i < BTRFS_MAX_LEVEL; i++) {
while (!list_empty(&cache->pending[i])) {
node = list_first_entry(&cache->pending[i],
struct btrfs_backref_node,
list);
btrfs_backref_cleanup_node(cache, node);
}
}
ASSERT(list_empty(&cache->pending_edge));
ASSERT(list_empty(&cache->useless_node));
ASSERT(list_empty(&cache->changed));
ASSERT(list_empty(&cache->detached));
ASSERT(RB_EMPTY_ROOT(&cache->rb_root));
ASSERT(!cache->nr_nodes);
ASSERT(!cache->nr_edges);
}
Expand Down Expand Up @@ -3315,8 +3280,16 @@ static int handle_indirect_tree_backref(struct btrfs_trans_handle *trans,
root = btrfs_get_fs_root(fs_info, ref_key->offset, false);
if (IS_ERR(root))
return PTR_ERR(root);
if (!test_bit(BTRFS_ROOT_SHAREABLE, &root->state))
cur->cowonly = 1;

/*
* We shouldn't be using backref cache for non shareable roots, ASSERT
* for developers, return -EUCLEAN for users.
*/
if (!test_bit(BTRFS_ROOT_SHAREABLE, &root->state)) {
btrfs_put_root(root);
ASSERT(0);
return -EUCLEAN;
}

if (btrfs_root_level(&root->root_item) == cur->level) {
/* Tree root */
Expand Down Expand Up @@ -3402,8 +3375,20 @@ static int handle_indirect_tree_backref(struct btrfs_trans_handle *trans,
goto out;
}
upper->owner = btrfs_header_owner(eb);
if (!test_bit(BTRFS_ROOT_SHAREABLE, &root->state))
upper->cowonly = 1;

/*
* We shouldn't be using backref cache for non shareable
* roots, ASSERT for developers, return -EUCLEAN for
* users.
*/
if (!test_bit(BTRFS_ROOT_SHAREABLE, &root->state)) {
btrfs_put_root(root);
btrfs_backref_free_edge(cache, edge);
btrfs_backref_free_node(cache, upper);
ASSERT(0);
ret = -EUCLEAN;
goto out;
}

/*
* If we know the block isn't shared we can avoid
Expand Down Expand Up @@ -3594,15 +3579,11 @@ int btrfs_backref_finish_upper_links(struct btrfs_backref_cache *cache,

ASSERT(start->checked);

/* Insert this node to cache if it's not COW-only */
if (!start->cowonly) {
rb_node = rb_simple_insert(&cache->rb_root, start->bytenr,
&start->rb_node);
if (rb_node)
btrfs_backref_panic(cache->fs_info, start->bytenr,
-EEXIST);
list_add_tail(&start->lower, &cache->leaves);
}
rb_node = rb_simple_insert(&cache->rb_root, start->bytenr,
&start->rb_node);
if (rb_node)
btrfs_backref_panic(cache->fs_info, start->bytenr,
-EEXIST);

/*
* Use breadth first search to iterate all related edges.
Expand Down Expand Up @@ -3641,11 +3622,6 @@ int btrfs_backref_finish_upper_links(struct btrfs_backref_cache *cache,
* parents have already been linked.
*/
if (!RB_EMPTY_NODE(&upper->rb_node)) {
if (upper->lowest) {
list_del_init(&upper->lower);
upper->lowest = 0;
}

list_add_tail(&edge->list[UPPER], &upper->lower);
continue;
}
Expand All @@ -3656,23 +3632,14 @@ int btrfs_backref_finish_upper_links(struct btrfs_backref_cache *cache,
return -EUCLEAN;
}

/* Sanity check, COW-only node has non-COW-only parent */
if (start->cowonly != upper->cowonly) {
ASSERT(0);
rb_node = rb_simple_insert(&cache->rb_root, upper->bytenr,
&upper->rb_node);
if (rb_node) {
btrfs_backref_panic(cache->fs_info,
upper->bytenr, -EEXIST);
return -EUCLEAN;
}

/* Only cache non-COW-only (subvolume trees) tree blocks */
if (!upper->cowonly) {
rb_node = rb_simple_insert(&cache->rb_root, upper->bytenr,
&upper->rb_node);
if (rb_node) {
btrfs_backref_panic(cache->fs_info,
upper->bytenr, -EEXIST);
return -EUCLEAN;
}
}

list_add_tail(&edge->list[UPPER], &upper->lower);

/*
Expand Down
16 changes: 6 additions & 10 deletions fs/btrfs/backref.h
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,12 @@ struct btrfs_backref_node {
u64 bytenr;
}; /* Use rb_simple_node for search/insert */

/*
* This is a sanity check, whenever we cow a block we will update
* new_bytenr with it's current location, and we will check this in
* various places to validate that the cache makes sense, it shouldn't
* be used for anything else.
*/
u64 new_bytenr;
/* Objectid of tree block owner, can be not uptodate */
u64 owner;
Expand All @@ -335,10 +341,6 @@ struct btrfs_backref_node {
struct extent_buffer *eb;
/* Level of the tree block */
unsigned int level:8;
/* Is the block in a non-shareable tree */
unsigned int cowonly:1;
/* 1 if no child node is in the cache */
unsigned int lowest:1;
/* Is the extent buffer locked */
unsigned int locked:1;
/* Has the block been processed */
Expand Down Expand Up @@ -391,12 +393,6 @@ struct btrfs_backref_cache {
* level blocks may not reflect the new location
*/
struct list_head pending[BTRFS_MAX_LEVEL];
/* List of backref nodes with no child node */
struct list_head leaves;
/* List of blocks that have been COWed in current transaction */
struct list_head changed;
/* List of detached backref node. */
struct list_head detached;

u64 last_trans;

Expand Down
2 changes: 1 addition & 1 deletion fs/btrfs/bio.c
Original file line number Diff line number Diff line change
Expand Up @@ -598,7 +598,7 @@ static bool should_async_write(struct btrfs_bio *bbio)
{
bool auto_csum_mode = true;

#ifdef CONFIG_BTRFS_DEBUG
#ifdef CONFIG_BTRFS_EXPERIMENTAL
struct btrfs_fs_devices *fs_devices = bbio->fs_info->fs_devices;
enum btrfs_offload_csum_mode csum_mode = READ_ONCE(fs_devices->offload_csum_mode);

Expand Down
2 changes: 1 addition & 1 deletion fs/btrfs/block-group.c
Original file line number Diff line number Diff line change
Expand Up @@ -2797,7 +2797,7 @@ void btrfs_create_pending_block_groups(struct btrfs_trans_handle *trans)
* uncompressed data size, because the compression is only done
* when writeback triggered and we don't know how much space we
* are actually going to need, so we reserve the uncompressed
* size because the data may be uncompressible in the worst case.
* size because the data may be incompressible in the worst case.
*/
if (ret == 0) {
bool used;
Expand Down
1 change: 0 additions & 1 deletion fs/btrfs/btrfs_inode.h
Original file line number Diff line number Diff line change
Expand Up @@ -577,7 +577,6 @@ void btrfs_merge_delalloc_extent(struct btrfs_inode *inode, struct extent_state
struct extent_state *other);
void btrfs_split_delalloc_extent(struct btrfs_inode *inode,
struct extent_state *orig, u64 split);
void btrfs_set_range_writeback(struct btrfs_inode *inode, u64 start, u64 end);
void btrfs_evict_inode(struct inode *inode);
struct inode *btrfs_alloc_inode(struct super_block *sb);
void btrfs_destroy_inode(struct inode *inode);
Expand Down
3 changes: 3 additions & 0 deletions fs/btrfs/compression.c
Original file line number Diff line number Diff line change
Expand Up @@ -1030,13 +1030,16 @@ int btrfs_compress_folios(unsigned int type_level, struct address_space *mapping
{
int type = btrfs_compress_type(type_level);
int level = btrfs_compress_level(type_level);
const unsigned long orig_len = *total_out;
struct list_head *workspace;
int ret;

level = btrfs_compress_set_level(type, level);
workspace = get_workspace(type, level);
ret = compression_compress_pages(type, workspace, mapping, start, folios,
out_folios, total_in, total_out);
/* The total read-in bytes should be no larger than the input. */
ASSERT(*total_in <= orig_len);
put_workspace(type, workspace);
return ret;
}
Expand Down
19 changes: 10 additions & 9 deletions fs/btrfs/delayed-ref.c
Original file line number Diff line number Diff line change
Expand Up @@ -830,7 +830,6 @@ static void init_delayed_ref_head(struct btrfs_delayed_ref_head *head_ref,
qrecord->data_rsv = reserved;
qrecord->data_rsv_refroot = generic_ref->ref_root;
}
qrecord->bytenr = generic_ref->bytenr;
qrecord->num_bytes = generic_ref->num_bytes;
qrecord->old_roots = NULL;
}
Expand All @@ -849,6 +848,7 @@ add_delayed_ref_head(struct btrfs_trans_handle *trans,
struct btrfs_qgroup_extent_record *qrecord,
int action, bool *qrecord_inserted_ret)
{
struct btrfs_fs_info *fs_info = trans->fs_info;
struct btrfs_delayed_ref_head *existing;
struct btrfs_delayed_ref_root *delayed_refs;
bool qrecord_inserted = false;
Expand All @@ -859,11 +859,12 @@ add_delayed_ref_head(struct btrfs_trans_handle *trans,
if (qrecord) {
int ret;

ret = btrfs_qgroup_trace_extent_nolock(trans->fs_info,
delayed_refs, qrecord);
ret = btrfs_qgroup_trace_extent_nolock(fs_info, delayed_refs, qrecord,
head_ref->bytenr);
if (ret) {
/* Clean up if insertion fails or item exists. */
xa_release(&delayed_refs->dirty_extents, qrecord->bytenr);
xa_release(&delayed_refs->dirty_extents,
head_ref->bytenr >> fs_info->sectorsize_bits);
/* Caller responsible for freeing qrecord on error. */
if (ret < 0)
return ERR_PTR(ret);
Expand All @@ -873,7 +874,7 @@ add_delayed_ref_head(struct btrfs_trans_handle *trans,
}
}

trace_add_delayed_ref_head(trans->fs_info, head_ref, action);
trace_add_delayed_ref_head(fs_info, head_ref, action);

existing = htree_insert(&delayed_refs->href_root,
&head_ref->href_node);
Expand All @@ -895,8 +896,7 @@ add_delayed_ref_head(struct btrfs_trans_handle *trans,
if (head_ref->is_data && head_ref->ref_mod < 0) {
delayed_refs->pending_csums += head_ref->num_bytes;
trans->delayed_ref_csum_deletions +=
btrfs_csum_bytes_to_leaves(trans->fs_info,
head_ref->num_bytes);
btrfs_csum_bytes_to_leaves(fs_info, head_ref->num_bytes);
}
delayed_refs->num_heads++;
delayed_refs->num_heads_ready++;
Expand Down Expand Up @@ -1030,7 +1030,8 @@ static int add_delayed_ref(struct btrfs_trans_handle *trans,
goto free_head_ref;
}
if (xa_reserve(&trans->transaction->delayed_refs.dirty_extents,
generic_ref->bytenr, GFP_NOFS)) {
generic_ref->bytenr >> fs_info->sectorsize_bits,
GFP_NOFS)) {
ret = -ENOMEM;
goto free_record;
}
Expand Down Expand Up @@ -1073,7 +1074,7 @@ static int add_delayed_ref(struct btrfs_trans_handle *trans,
kmem_cache_free(btrfs_delayed_ref_node_cachep, node);

if (qrecord_inserted)
return btrfs_qgroup_trace_extent_post(trans, record);
return btrfs_qgroup_trace_extent_post(trans, record, head_ref->bytenr);
return 0;

free_record:
Expand Down
10 changes: 9 additions & 1 deletion fs/btrfs/delayed-ref.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,15 @@ struct btrfs_delayed_ref_root {
/* head ref rbtree */
struct rb_root_cached href_root;

/* Track dirty extent records. */
/*
* Track dirty extent records.
* The keys correspond to the logical address of the extent ("bytenr")
* right shifted by fs_info->sectorsize_bits. This is both to get a more
* dense index space (optimizes xarray structure) and because indexes in
* xarrays are of "unsigned long" type, meaning they are 32 bits wide on
* 32 bits platforms, limiting the extent range to 4G which is too low
* and makes it unusable (truncated index values) on 32 bits platforms.
*/
struct xarray dirty_extents;

/* this spin lock protects the rbtree and the entries inside */
Expand Down
Loading

0 comments on commit a6f63ff

Please sign in to comment.