* [PATCH] btrfs: remove extent buffer's redundant `len` member field
@ 2025-04-29 15:17 Daniel Vacek
2025-04-29 22:34 ` Qu Wenruo
` (3 more replies)
0 siblings, 4 replies; 35+ messages in thread
From: Daniel Vacek @ 2025-04-29 15:17 UTC (permalink / raw)
To: Chris Mason, Josef Bacik, David Sterba
Cc: Daniel Vacek, linux-btrfs, linux-kernel
Even super block nowadays uses nodesize for eb->len. This is since commits
551561c34663 ("btrfs: don't pass nodesize to __alloc_extent_buffer()")
da17066c4047 ("btrfs: pull node/sector/stripe sizes out of root and into fs_info")
ce3e69847e3e ("btrfs: sink parameter len to alloc_extent_buffer")
a83fffb75d09 ("btrfs: sink blocksize parameter to btrfs_find_create_tree_block")
With these the eb->len is not really useful anymore. Let's use the nodesize
directly where applicable.
Signed-off-by: Daniel Vacek <neelx@suse.com>
---
[RFC]
* Shall the eb_len() helper better be called eb_nodesize()? Or even rather
opencoded and not used at all?
fs/btrfs/accessors.c | 4 +--
fs/btrfs/disk-io.c | 11 ++++---
fs/btrfs/extent-tree.c | 28 +++++++++--------
fs/btrfs/extent_io.c | 54 ++++++++++++++------------------
fs/btrfs/extent_io.h | 11 +++++--
fs/btrfs/ioctl.c | 2 +-
fs/btrfs/relocation.c | 2 +-
fs/btrfs/subpage.c | 8 ++---
fs/btrfs/tests/extent-io-tests.c | 12 +++----
fs/btrfs/zoned.c | 2 +-
10 files changed, 67 insertions(+), 67 deletions(-)
diff --git a/fs/btrfs/accessors.c b/fs/btrfs/accessors.c
index e3716516ca387..a2bdbc7990906 100644
--- a/fs/btrfs/accessors.c
+++ b/fs/btrfs/accessors.c
@@ -14,10 +14,10 @@ static bool check_setget_bounds(const struct extent_buffer *eb,
{
const unsigned long member_offset = (unsigned long)ptr + off;
- if (unlikely(member_offset + size > eb->len)) {
+ if (unlikely(member_offset + size > eb_len(eb))) {
btrfs_warn(eb->fs_info,
"bad eb member %s: ptr 0x%lx start %llu member offset %lu size %d",
- (member_offset > eb->len ? "start" : "end"),
+ (member_offset > eb_len(eb) ? "start" : "end"),
(unsigned long)ptr, eb->start, member_offset, size);
return false;
}
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 3592300ae3e2e..31eb7419fe11f 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -190,7 +190,7 @@ static int btrfs_repair_eb_io_failure(const struct extent_buffer *eb,
for (int i = 0; i < num_extent_folios(eb); i++) {
struct folio *folio = eb->folios[i];
u64 start = max_t(u64, eb->start, folio_pos(folio));
- u64 end = min_t(u64, eb->start + eb->len,
+ u64 end = min_t(u64, eb->start + fs_info->nodesize,
folio_pos(folio) + eb->folio_size);
u32 len = end - start;
phys_addr_t paddr = PFN_PHYS(folio_pfn(folio)) +
@@ -230,7 +230,7 @@ int btrfs_read_extent_buffer(struct extent_buffer *eb,
break;
num_copies = btrfs_num_copies(fs_info,
- eb->start, eb->len);
+ eb->start, fs_info->nodesize);
if (num_copies == 1)
break;
@@ -260,6 +260,7 @@ blk_status_t btree_csum_one_bio(struct btrfs_bio *bbio)
{
struct extent_buffer *eb = bbio->private;
struct btrfs_fs_info *fs_info = eb->fs_info;
+ u32 nodesize = fs_info->nodesize;
u64 found_start = btrfs_header_bytenr(eb);
u64 last_trans;
u8 result[BTRFS_CSUM_SIZE];
@@ -268,7 +269,7 @@ blk_status_t btree_csum_one_bio(struct btrfs_bio *bbio)
/* Btree blocks are always contiguous on disk. */
if (WARN_ON_ONCE(bbio->file_offset != eb->start))
return BLK_STS_IOERR;
- if (WARN_ON_ONCE(bbio->bio.bi_iter.bi_size != eb->len))
+ if (WARN_ON_ONCE(bbio->bio.bi_iter.bi_size != nodesize))
return BLK_STS_IOERR;
/*
@@ -277,7 +278,7 @@ blk_status_t btree_csum_one_bio(struct btrfs_bio *bbio)
* ordering of I/O without unnecessarily writing out data.
*/
if (test_bit(EXTENT_BUFFER_ZONED_ZEROOUT, &eb->bflags)) {
- memzero_extent_buffer(eb, 0, eb->len);
+ memzero_extent_buffer(eb, 0, nodesize);
return BLK_STS_OK;
}
@@ -883,7 +884,7 @@ struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans,
btrfs_set_root_generation(&root->root_item, trans->transid);
btrfs_set_root_level(&root->root_item, 0);
btrfs_set_root_refs(&root->root_item, 1);
- btrfs_set_root_used(&root->root_item, leaf->len);
+ btrfs_set_root_used(&root->root_item, fs_info->nodesize);
btrfs_set_root_last_snapshot(&root->root_item, 0);
btrfs_set_root_dirid(&root->root_item, 0);
if (is_fstree(objectid))
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index e0811a86d0cbd..25560a162d93e 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -2211,7 +2211,7 @@ int btrfs_set_disk_extent_flags(struct btrfs_trans_handle *trans,
extent_op->update_flags = true;
extent_op->update_key = false;
- ret = btrfs_add_delayed_extent_op(trans, eb->start, eb->len,
+ ret = btrfs_add_delayed_extent_op(trans, eb->start, eb_len(eb),
btrfs_header_level(eb), extent_op);
if (ret)
btrfs_free_delayed_extent_op(extent_op);
@@ -2660,10 +2660,10 @@ int btrfs_pin_extent_for_log_replay(struct btrfs_trans_handle *trans,
if (ret)
goto out;
- pin_down_extent(trans, cache, eb->start, eb->len, 0);
+ pin_down_extent(trans, cache, eb->start, eb_len(eb), 0);
/* remove us from the free space cache (if we're there at all) */
- ret = btrfs_remove_free_space(cache, eb->start, eb->len);
+ ret = btrfs_remove_free_space(cache, eb->start, eb_len(eb));
out:
btrfs_put_block_group(cache);
return ret;
@@ -3436,13 +3436,14 @@ int btrfs_free_tree_block(struct btrfs_trans_handle *trans,
{
struct btrfs_fs_info *fs_info = trans->fs_info;
struct btrfs_block_group *bg;
+ u32 nodesize = fs_info->nodesize;
int ret;
if (root_id != BTRFS_TREE_LOG_OBJECTID) {
struct btrfs_ref generic_ref = {
.action = BTRFS_DROP_DELAYED_REF,
.bytenr = buf->start,
- .num_bytes = buf->len,
+ .num_bytes = nodesize,
.parent = parent,
.owning_root = btrfs_header_owner(buf),
.ref_root = root_id,
@@ -3478,7 +3479,7 @@ int btrfs_free_tree_block(struct btrfs_trans_handle *trans,
bg = btrfs_lookup_block_group(fs_info, buf->start);
if (btrfs_header_flag(buf, BTRFS_HEADER_FLAG_WRITTEN)) {
- pin_down_extent(trans, bg, buf->start, buf->len, 1);
+ pin_down_extent(trans, bg, buf->start, nodesize, 1);
btrfs_put_block_group(bg);
goto out;
}
@@ -3502,17 +3503,17 @@ int btrfs_free_tree_block(struct btrfs_trans_handle *trans,
if (test_bit(BTRFS_FS_TREE_MOD_LOG_USERS, &fs_info->flags)
|| btrfs_is_zoned(fs_info)) {
- pin_down_extent(trans, bg, buf->start, buf->len, 1);
+ pin_down_extent(trans, bg, buf->start, nodesize, 1);
btrfs_put_block_group(bg);
goto out;
}
WARN_ON(test_bit(EXTENT_BUFFER_DIRTY, &buf->bflags));
- btrfs_add_free_space(bg, buf->start, buf->len);
- btrfs_free_reserved_bytes(bg, buf->len, 0);
+ btrfs_add_free_space(bg, buf->start, nodesize);
+ btrfs_free_reserved_bytes(bg, nodesize, 0);
btrfs_put_block_group(bg);
- trace_btrfs_reserved_extent_free(fs_info, buf->start, buf->len);
+ trace_btrfs_reserved_extent_free(fs_info, buf->start, nodesize);
out:
return 0;
@@ -4768,7 +4769,7 @@ int btrfs_pin_reserved_extent(struct btrfs_trans_handle *trans,
return -ENOSPC;
}
- ret = pin_down_extent(trans, cache, eb->start, eb->len, 1);
+ ret = pin_down_extent(trans, cache, eb->start, eb_len(eb), 1);
btrfs_put_block_group(cache);
return ret;
}
@@ -5050,6 +5051,7 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root,
struct btrfs_fs_info *fs_info = root->fs_info;
struct extent_buffer *buf;
u64 lockdep_owner = owner;
+ u32 nodesize = fs_info->nodesize;
buf = btrfs_find_create_tree_block(fs_info, bytenr, owner, level);
if (IS_ERR(buf))
@@ -5107,16 +5109,16 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root,
*/
if (buf->log_index == 0)
btrfs_set_extent_bit(&root->dirty_log_pages, buf->start,
- buf->start + buf->len - 1,
+ buf->start + nodesize - 1,
EXTENT_DIRTY, NULL);
else
btrfs_set_extent_bit(&root->dirty_log_pages, buf->start,
- buf->start + buf->len - 1,
+ buf->start + nodesize - 1,
EXTENT_NEW, NULL);
} else {
buf->log_index = -1;
btrfs_set_extent_bit(&trans->transaction->dirty_pages, buf->start,
- buf->start + buf->len - 1, EXTENT_DIRTY, NULL);
+ buf->start + nodesize - 1, EXTENT_DIRTY, NULL);
}
/* this returns a buffer locked for blocking */
return buf;
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 20cdddd924852..e4050fd5db285 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -76,8 +76,8 @@ void btrfs_extent_buffer_leak_debug_check(struct btrfs_fs_info *fs_info)
eb = list_first_entry(&fs_info->allocated_ebs,
struct extent_buffer, leak_list);
pr_err(
- "BTRFS: buffer leak start %llu len %u refs %d bflags %lu owner %llu\n",
- eb->start, eb->len, atomic_read(&eb->refs), eb->bflags,
+ "BTRFS: buffer leak start %llu refs %d bflags %lu owner %llu\n",
+ eb->start, atomic_read(&eb->refs), eb->bflags,
btrfs_header_owner(eb));
list_del(&eb->leak_list);
WARN_ON_ONCE(1);
@@ -1746,8 +1746,8 @@ static noinline_for_stack bool lock_extent_buffer_for_io(struct extent_buffer *e
btrfs_set_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN);
percpu_counter_add_batch(&fs_info->dirty_metadata_bytes,
- -eb->len,
- fs_info->dirty_metadata_batch);
+ -fs_info->nodesize,
+ fs_info->dirty_metadata_batch);
ret = true;
} else {
spin_unlock(&eb->refs_lock);
@@ -1953,7 +1953,7 @@ static unsigned int buffer_tree_get_ebs_tag(struct btrfs_fs_info *fs_info,
rcu_read_lock();
while ((eb = find_get_eb(&xas, end, tag)) != NULL) {
if (!eb_batch_add(batch, eb)) {
- *start = (eb->start + eb->len) >> fs_info->sectorsize_bits;
+ *start = (eb->start + fs_info->nodesize) >> fs_info->sectorsize_bits;
goto out;
}
}
@@ -2020,7 +2020,7 @@ static void prepare_eb_write(struct extent_buffer *eb)
nritems = btrfs_header_nritems(eb);
if (btrfs_header_level(eb) > 0) {
end = btrfs_node_key_ptr_offset(eb, nritems);
- memzero_extent_buffer(eb, end, eb->len - end);
+ memzero_extent_buffer(eb, end, eb_len(eb) - end);
} else {
/*
* Leaf:
@@ -2056,7 +2056,7 @@ static noinline_for_stack void write_one_eb(struct extent_buffer *eb,
struct folio *folio = eb->folios[i];
u64 range_start = max_t(u64, eb->start, folio_pos(folio));
u32 range_len = min_t(u64, folio_pos(folio) + folio_size(folio),
- eb->start + eb->len) - range_start;
+ eb->start + fs_info->nodesize) - range_start;
folio_lock(folio);
btrfs_meta_folio_clear_dirty(folio, eb);
@@ -2171,7 +2171,7 @@ int btree_write_cache_pages(struct address_space *mapping,
if (ctx.zoned_bg) {
/* Mark the last eb in the block group. */
btrfs_schedule_zone_finish_bg(ctx.zoned_bg, eb);
- ctx.zoned_bg->meta_write_pointer += eb->len;
+ ctx.zoned_bg->meta_write_pointer += fs_info->nodesize;
}
write_one_eb(eb, wbc);
}
@@ -2807,7 +2807,6 @@ static struct extent_buffer *__alloc_extent_buffer(struct btrfs_fs_info *fs_info
eb = kmem_cache_zalloc(extent_buffer_cache, GFP_NOFS|__GFP_NOFAIL);
eb->start = start;
- eb->len = fs_info->nodesize;
eb->fs_info = fs_info;
init_rwsem(&eb->lock);
@@ -2816,8 +2815,6 @@ static struct extent_buffer *__alloc_extent_buffer(struct btrfs_fs_info *fs_info
spin_lock_init(&eb->refs_lock);
atomic_set(&eb->refs, 1);
- ASSERT(eb->len <= BTRFS_MAX_METADATA_BLOCKSIZE);
-
return eb;
}
@@ -3505,7 +3502,7 @@ void btrfs_clear_buffer_dirty(struct btrfs_trans_handle *trans,
return;
buffer_tree_clear_mark(eb, PAGECACHE_TAG_DIRTY);
- percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, -eb->len,
+ percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, -fs_info->nodesize,
fs_info->dirty_metadata_batch);
for (int i = 0; i < num_extent_folios(eb); i++) {
@@ -3557,8 +3554,8 @@ void set_extent_buffer_dirty(struct extent_buffer *eb)
if (subpage)
folio_unlock(eb->folios[0]);
percpu_counter_add_batch(&eb->fs_info->dirty_metadata_bytes,
- eb->len,
- eb->fs_info->dirty_metadata_batch);
+ eb_len(eb),
+ eb->fs_info->dirty_metadata_batch);
}
#ifdef CONFIG_BTRFS_DEBUG
for (int i = 0; i < num_extent_folios(eb); i++)
@@ -3670,7 +3667,7 @@ int read_extent_buffer_pages_nowait(struct extent_buffer *eb, int mirror_num,
struct folio *folio = eb->folios[i];
u64 range_start = max_t(u64, eb->start, folio_pos(folio));
u32 range_len = min_t(u64, folio_pos(folio) + folio_size(folio),
- eb->start + eb->len) - range_start;
+ eb->start + eb_len(eb)) - range_start;
bio_add_folio_nofail(&bbio->bio, folio, range_len,
offset_in_folio(folio, range_start));
@@ -3698,8 +3695,8 @@ static bool report_eb_range(const struct extent_buffer *eb, unsigned long start,
unsigned long len)
{
btrfs_warn(eb->fs_info,
- "access to eb bytenr %llu len %u out of range start %lu len %lu",
- eb->start, eb->len, start, len);
+ "access to eb bytenr %llu out of range start %lu len %lu",
+ eb->start, start, len);
DEBUG_WARN();
return true;
@@ -3717,8 +3714,8 @@ static inline int check_eb_range(const struct extent_buffer *eb,
{
unsigned long offset;
- /* start, start + len should not go beyond eb->len nor overflow */
- if (unlikely(check_add_overflow(start, len, &offset) || offset > eb->len))
+ /* start, start + len should not go beyond nodesize nor overflow */
+ if (unlikely(check_add_overflow(start, len, &offset) || offset > eb_len(eb)))
return report_eb_range(eb, start, len);
return false;
@@ -3774,8 +3771,8 @@ int read_extent_buffer_to_user_nofault(const struct extent_buffer *eb,
unsigned long i = get_eb_folio_index(eb, start);
int ret = 0;
- WARN_ON(start > eb->len);
- WARN_ON(start + len > eb->start + eb->len);
+ WARN_ON(start > eb_len(eb));
+ WARN_ON(start + len > eb->start + eb_len(eb));
if (eb->addr) {
if (copy_to_user_nofault(dstv, eb->addr + start, len))
@@ -3866,8 +3863,8 @@ static void assert_eb_folio_uptodate(const struct extent_buffer *eb, int i)
folio = eb->folios[0];
ASSERT(i == 0);
if (WARN_ON(!btrfs_subpage_test_uptodate(fs_info, folio,
- eb->start, eb->len)))
- btrfs_subpage_dump_bitmap(fs_info, folio, eb->start, eb->len);
+ eb->start, fs_info->nodesize)))
+ btrfs_subpage_dump_bitmap(fs_info, folio, eb->start, fs_info->nodesize);
} else {
WARN_ON(!folio_test_uptodate(folio));
}
@@ -3960,12 +3957,10 @@ void copy_extent_buffer_full(const struct extent_buffer *dst,
const int unit_size = src->folio_size;
unsigned long cur = 0;
- ASSERT(dst->len == src->len);
-
- while (cur < src->len) {
+ while (cur < eb_len(src)) {
unsigned long index = get_eb_folio_index(src, cur);
unsigned long offset = get_eb_offset_in_folio(src, cur);
- unsigned long cur_len = min(src->len, unit_size - offset);
+ unsigned long cur_len = min(eb_len(src), unit_size - offset);
void *addr = folio_address(src->folios[index]) + offset;
write_extent_buffer(dst, addr, cur, cur_len);
@@ -3980,7 +3975,6 @@ void copy_extent_buffer(const struct extent_buffer *dst,
unsigned long len)
{
const int unit_size = dst->folio_size;
- u64 dst_len = dst->len;
size_t cur;
size_t offset;
char *kaddr;
@@ -3990,8 +3984,6 @@ void copy_extent_buffer(const struct extent_buffer *dst,
check_eb_range(src, src_offset, len))
return;
- WARN_ON(src->len != dst_len);
-
offset = get_eb_offset_in_folio(dst, dst_offset);
while (len > 0) {
@@ -4266,7 +4258,7 @@ static int try_release_subpage_extent_buffer(struct folio *folio)
xa_unlock_irq(&fs_info->buffer_tree);
break;
}
- cur = eb->start + eb->len;
+ cur = eb->start + fs_info->nodesize;
/*
* The same as try_release_extent_buffer(), to ensure the eb
diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h
index 1415679d7f88c..9a842eea47d6d 100644
--- a/fs/btrfs/extent_io.h
+++ b/fs/btrfs/extent_io.h
@@ -16,6 +16,7 @@
#include "messages.h"
#include "ulist.h"
#include "misc.h"
+#include "fs.h"
struct page;
struct file;
@@ -80,7 +81,6 @@ void __cold extent_buffer_free_cachep(void);
#define INLINE_EXTENT_BUFFER_PAGES (BTRFS_MAX_METADATA_BLOCKSIZE / PAGE_SIZE)
struct extent_buffer {
u64 start;
- u32 len;
u32 folio_size;
unsigned long bflags;
struct btrfs_fs_info *fs_info;
@@ -263,17 +263,22 @@ void btrfs_readahead_tree_block(struct btrfs_fs_info *fs_info,
u64 bytenr, u64 owner_root, u64 gen, int level);
void btrfs_readahead_node_child(struct extent_buffer *node, int slot);
+static inline u32 eb_len(const struct extent_buffer *eb)
+{
+ return eb->fs_info->nodesize;
+}
+
/* Note: this can be used in for loops without caching the value in a variable. */
static inline int __pure num_extent_pages(const struct extent_buffer *eb)
{
/*
* For sectorsize == PAGE_SIZE case, since nodesize is always aligned to
- * sectorsize, it's just eb->len >> PAGE_SHIFT.
+ * sectorsize, it's just nodesize >> PAGE_SHIFT.
*
* For sectorsize < PAGE_SIZE case, we could have nodesize < PAGE_SIZE,
* thus have to ensure we get at least one page.
*/
- return (eb->len >> PAGE_SHIFT) ?: 1;
+ return (eb_len(eb) >> PAGE_SHIFT) ?: 1;
}
/*
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 68fac77fb95d1..6be2d56d44917 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -598,7 +598,7 @@ static noinline int create_subvol(struct mnt_idmap *idmap,
btrfs_set_root_generation(root_item, trans->transid);
btrfs_set_root_level(root_item, 0);
btrfs_set_root_refs(root_item, 1);
- btrfs_set_root_used(root_item, leaf->len);
+ btrfs_set_root_used(root_item, fs_info->nodesize);
btrfs_set_root_last_snapshot(root_item, 0);
btrfs_set_root_generation_v2(root_item,
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index 6287e71ebad5f..5086485a4ae21 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -4352,7 +4352,7 @@ int btrfs_reloc_cow_block(struct btrfs_trans_handle *trans,
mark_block_processed(rc, node);
if (first_cow && level > 0)
- rc->nodes_relocated += buf->len;
+ rc->nodes_relocated += fs_info->nodesize;
}
if (level == 0 && first_cow && rc->stage == UPDATE_DATA_PTRS)
diff --git a/fs/btrfs/subpage.c b/fs/btrfs/subpage.c
index d4f0192334936..711792f32e9ce 100644
--- a/fs/btrfs/subpage.c
+++ b/fs/btrfs/subpage.c
@@ -631,7 +631,7 @@ void btrfs_meta_folio_set_##name(struct folio *folio, const struct extent_buffer
folio_set_func(folio); \
return; \
} \
- btrfs_subpage_set_##name(eb->fs_info, folio, eb->start, eb->len); \
+ btrfs_subpage_set_##name(eb->fs_info, folio, eb->start, eb_len(eb)); \
} \
void btrfs_meta_folio_clear_##name(struct folio *folio, const struct extent_buffer *eb) \
{ \
@@ -639,13 +639,13 @@ void btrfs_meta_folio_clear_##name(struct folio *folio, const struct extent_buff
folio_clear_func(folio); \
return; \
} \
- btrfs_subpage_clear_##name(eb->fs_info, folio, eb->start, eb->len); \
+ btrfs_subpage_clear_##name(eb->fs_info, folio, eb->start, eb_len(eb)); \
} \
bool btrfs_meta_folio_test_##name(struct folio *folio, const struct extent_buffer *eb) \
{ \
if (!btrfs_meta_is_subpage(eb->fs_info)) \
return folio_test_func(folio); \
- return btrfs_subpage_test_##name(eb->fs_info, folio, eb->start, eb->len); \
+ return btrfs_subpage_test_##name(eb->fs_info, folio, eb->start, eb_len(eb)); \
}
IMPLEMENT_BTRFS_PAGE_OPS(uptodate, folio_mark_uptodate, folio_clear_uptodate,
folio_test_uptodate);
@@ -765,7 +765,7 @@ bool btrfs_meta_folio_clear_and_test_dirty(struct folio *folio, const struct ext
return true;
}
- last = btrfs_subpage_clear_and_test_dirty(eb->fs_info, folio, eb->start, eb->len);
+ last = btrfs_subpage_clear_and_test_dirty(eb->fs_info, folio, eb->start, eb_len(eb));
if (last) {
folio_clear_dirty_for_io(folio);
return true;
diff --git a/fs/btrfs/tests/extent-io-tests.c b/fs/btrfs/tests/extent-io-tests.c
index 00da54f0164c9..657f8f1d9263e 100644
--- a/fs/btrfs/tests/extent-io-tests.c
+++ b/fs/btrfs/tests/extent-io-tests.c
@@ -342,7 +342,7 @@ static int check_eb_bitmap(unsigned long *bitmap, struct extent_buffer *eb)
{
unsigned long i;
- for (i = 0; i < eb->len * BITS_PER_BYTE; i++) {
+ for (i = 0; i < eb_len(eb) * BITS_PER_BYTE; i++) {
int bit, bit1;
bit = !!test_bit(i, bitmap);
@@ -411,7 +411,7 @@ static int test_bitmap_clear(const char *name, unsigned long *bitmap,
static int __test_eb_bitmaps(unsigned long *bitmap, struct extent_buffer *eb)
{
unsigned long i, j;
- unsigned long byte_len = eb->len;
+ unsigned long byte_len = eb_len(eb);
u32 x;
int ret;
@@ -670,7 +670,7 @@ static int test_find_first_clear_extent_bit(void)
static void dump_eb_and_memory_contents(struct extent_buffer *eb, void *memory,
const char *test_name)
{
- for (int i = 0; i < eb->len; i++) {
+ for (int i = 0; i < eb_len(eb); i++) {
struct page *page = folio_page(eb->folios[i >> PAGE_SHIFT], 0);
void *addr = page_address(page) + offset_in_page(i);
@@ -686,7 +686,7 @@ static void dump_eb_and_memory_contents(struct extent_buffer *eb, void *memory,
static int verify_eb_and_memory(struct extent_buffer *eb, void *memory,
const char *test_name)
{
- for (int i = 0; i < (eb->len >> PAGE_SHIFT); i++) {
+ for (int i = 0; i < (eb_len(eb) >> PAGE_SHIFT); i++) {
void *eb_addr = folio_address(eb->folios[i]);
if (memcmp(memory + (i << PAGE_SHIFT), eb_addr, PAGE_SIZE) != 0) {
@@ -703,8 +703,8 @@ static int verify_eb_and_memory(struct extent_buffer *eb, void *memory,
*/
static void init_eb_and_memory(struct extent_buffer *eb, void *memory)
{
- get_random_bytes(memory, eb->len);
- write_extent_buffer(eb, memory, 0, eb->len);
+ get_random_bytes(memory, eb_len(eb));
+ write_extent_buffer(eb, memory, 0, eb_len(eb));
}
static int test_eb_mem_ops(u32 sectorsize, u32 nodesize)
diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c
index 9d42bf2bfd746..c7a8cdd87c509 100644
--- a/fs/btrfs/zoned.c
+++ b/fs/btrfs/zoned.c
@@ -2422,7 +2422,7 @@ void btrfs_schedule_zone_finish_bg(struct btrfs_block_group *bg,
struct extent_buffer *eb)
{
if (!test_bit(BLOCK_GROUP_FLAG_SEQUENTIAL_ZONE, &bg->runtime_flags) ||
- eb->start + eb->len * 2 <= bg->start + bg->zone_capacity)
+ eb->start + eb_len(eb) * 2 <= bg->start + bg->zone_capacity)
return;
if (WARN_ON(bg->zone_finish_work.func == btrfs_zone_finish_endio_workfn)) {
--
2.47.2
^ permalink raw reply related [flat|nested] 35+ messages in thread* Re: [PATCH] btrfs: remove extent buffer's redundant `len` member field 2025-04-29 15:17 [PATCH] btrfs: remove extent buffer's redundant `len` member field Daniel Vacek @ 2025-04-29 22:34 ` Qu Wenruo 2025-04-30 8:03 ` David Sterba ` (2 subsequent siblings) 3 siblings, 0 replies; 35+ messages in thread From: Qu Wenruo @ 2025-04-29 22:34 UTC (permalink / raw) To: Daniel Vacek, Chris Mason, Josef Bacik, David Sterba Cc: linux-btrfs, linux-kernel 在 2025/4/30 00:47, Daniel Vacek 写道: > Even super block nowadays uses nodesize for eb->len. This is since commits > > 551561c34663 ("btrfs: don't pass nodesize to __alloc_extent_buffer()") > da17066c4047 ("btrfs: pull node/sector/stripe sizes out of root and into fs_info") > ce3e69847e3e ("btrfs: sink parameter len to alloc_extent_buffer") > a83fffb75d09 ("btrfs: sink blocksize parameter to btrfs_find_create_tree_block") > > With these the eb->len is not really useful anymore. Let's use the nodesize > directly where applicable. The idea looks great to me, and all the call sites look good too. > > Signed-off-by: Daniel Vacek <neelx@suse.com> > --- > [RFC] > * Shall the eb_len() helper better be called eb_nodesize()? Or even rather > opencoded and not used at all? However the name eb_len() is a little too generic. Nodesize is a little easier to understand. > > fs/btrfs/accessors.c | 4 +-- > fs/btrfs/disk-io.c | 11 ++++--- > fs/btrfs/extent-tree.c | 28 +++++++++-------- > fs/btrfs/extent_io.c | 54 ++++++++++++++------------------ > fs/btrfs/extent_io.h | 11 +++++-- > fs/btrfs/ioctl.c | 2 +- > fs/btrfs/relocation.c | 2 +- > fs/btrfs/subpage.c | 8 ++--- > fs/btrfs/tests/extent-io-tests.c | 12 +++---- > fs/btrfs/zoned.c | 2 +- > 10 files changed, 67 insertions(+), 67 deletions(-) > > diff --git a/fs/btrfs/accessors.c b/fs/btrfs/accessors.c > index e3716516ca387..a2bdbc7990906 100644 > --- a/fs/btrfs/accessors.c > +++ b/fs/btrfs/accessors.c > @@ -14,10 +14,10 @@ static bool check_setget_bounds(const struct extent_buffer *eb, > { > const unsigned long member_offset = (unsigned long)ptr + off; > > - if (unlikely(member_offset + size > eb->len)) { > + if (unlikely(member_offset + size > eb_len(eb))) { > btrfs_warn(eb->fs_info, > "bad eb member %s: ptr 0x%lx start %llu member offset %lu size %d", > - (member_offset > eb->len ? "start" : "end"), > + (member_offset > eb_len(eb) ? "start" : "end"), > (unsigned long)ptr, eb->start, member_offset, size); > return false; > } > diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c > index 3592300ae3e2e..31eb7419fe11f 100644 > --- a/fs/btrfs/disk-io.c > +++ b/fs/btrfs/disk-io.c > @@ -190,7 +190,7 @@ static int btrfs_repair_eb_io_failure(const struct extent_buffer *eb, > for (int i = 0; i < num_extent_folios(eb); i++) { > struct folio *folio = eb->folios[i]; > u64 start = max_t(u64, eb->start, folio_pos(folio)); > - u64 end = min_t(u64, eb->start + eb->len, > + u64 end = min_t(u64, eb->start + fs_info->nodesize, > folio_pos(folio) + eb->folio_size); > u32 len = end - start; > phys_addr_t paddr = PFN_PHYS(folio_pfn(folio)) + > @@ -230,7 +230,7 @@ int btrfs_read_extent_buffer(struct extent_buffer *eb, > break; > > num_copies = btrfs_num_copies(fs_info, > - eb->start, eb->len); > + eb->start, fs_info->nodesize); > if (num_copies == 1) > break; > > @@ -260,6 +260,7 @@ blk_status_t btree_csum_one_bio(struct btrfs_bio *bbio) > { > struct extent_buffer *eb = bbio->private; > struct btrfs_fs_info *fs_info = eb->fs_info; > + u32 nodesize = fs_info->nodesize; Minor nitpick, @nodesize can be made const. Otherwise looks good to me. Thanks, Qu ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH] btrfs: remove extent buffer's redundant `len` member field 2025-04-29 15:17 [PATCH] btrfs: remove extent buffer's redundant `len` member field Daniel Vacek 2025-04-29 22:34 ` Qu Wenruo @ 2025-04-30 8:03 ` David Sterba 2025-04-30 8:21 ` Daniel Vacek 2025-04-30 8:05 ` Filipe Manana 2025-05-02 13:37 ` [PATCH v2 0/2] btrfs: eb struct cleanups Daniel Vacek 3 siblings, 1 reply; 35+ messages in thread From: David Sterba @ 2025-04-30 8:03 UTC (permalink / raw) To: Daniel Vacek Cc: Chris Mason, Josef Bacik, David Sterba, linux-btrfs, linux-kernel On Tue, Apr 29, 2025 at 05:17:57PM +0200, Daniel Vacek wrote: > Even super block nowadays uses nodesize for eb->len. This is since commits > > 551561c34663 ("btrfs: don't pass nodesize to __alloc_extent_buffer()") > da17066c4047 ("btrfs: pull node/sector/stripe sizes out of root and into fs_info") > ce3e69847e3e ("btrfs: sink parameter len to alloc_extent_buffer") > a83fffb75d09 ("btrfs: sink blocksize parameter to btrfs_find_create_tree_block") > > With these the eb->len is not really useful anymore. Let's use the nodesize > directly where applicable. I've had this patch in my local branch for some years from the times we were optimizing extent buffer size. The size on release config is 240 bytes. The goal was to get it under 256 and keep it aligned. Removing eb->len does not change the structure size and leaves a hole struct extent_buffer { u64 start; /* 0 8 */ - u32 len; /* 8 4 */ - u32 folio_size; /* 12 4 */ + u32 folio_size; /* 8 4 */ + + /* XXX 4 bytes hole, try to pack */ + long unsigned int bflags; /* 16 8 */ struct btrfs_fs_info * fs_info; /* 24 8 */ void * addr; /* 32 8 */ @@ -5554,8 +5556,8 @@ struct extent_buffer { struct rw_semaphore lock; /* 72 40 */ struct folio * folios[16]; /* 112 128 */ - /* size: 240, cachelines: 4, members: 14 */ - /* sum members: 238, holes: 1, sum holes: 2 */ + /* size: 240, cachelines: 4, members: 13 */ + /* sum members: 234, holes: 2, sum holes: 6 */ /* forced alignments: 1, forced holes: 1, sum forced holes: 2 */ /* last cacheline: 48 bytes */ } __attribute__((__aligned__(8))); The benefit of duplicating the length in each eb is that it's in the same cacheline as the other members that are used for offset calculations or bit manipulations. Going to the fs_info->nodesize may or may not hit a cache, also because it needs to do 2 pointer dereferences, so from that perspective I think it's making it worse. I don't think we need to do the optimization right now, but maybe in the future if there's a need to add something to eb. Still we can use the remaining 16 bytes up to 256 without making things worse. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH] btrfs: remove extent buffer's redundant `len` member field 2025-04-30 8:03 ` David Sterba @ 2025-04-30 8:21 ` Daniel Vacek 2025-04-30 12:31 ` Daniel Vacek 2025-04-30 13:30 ` David Sterba 0 siblings, 2 replies; 35+ messages in thread From: Daniel Vacek @ 2025-04-30 8:21 UTC (permalink / raw) To: dsterba; +Cc: Chris Mason, Josef Bacik, David Sterba, linux-btrfs, linux-kernel On Wed, 30 Apr 2025 at 10:03, David Sterba <dsterba@suse.cz> wrote: > > On Tue, Apr 29, 2025 at 05:17:57PM +0200, Daniel Vacek wrote: > > Even super block nowadays uses nodesize for eb->len. This is since commits > > > > 551561c34663 ("btrfs: don't pass nodesize to __alloc_extent_buffer()") > > da17066c4047 ("btrfs: pull node/sector/stripe sizes out of root and into fs_info") > > ce3e69847e3e ("btrfs: sink parameter len to alloc_extent_buffer") > > a83fffb75d09 ("btrfs: sink blocksize parameter to btrfs_find_create_tree_block") > > > > With these the eb->len is not really useful anymore. Let's use the nodesize > > directly where applicable. > > I've had this patch in my local branch for some years from the times we > were optimizing extent buffer size. The size on release config is 240 > bytes. The goal was to get it under 256 and keep it aligned. > > Removing eb->len does not change the structure size and leaves a hole > > struct extent_buffer { > u64 start; /* 0 8 */ > - u32 len; /* 8 4 */ > - u32 folio_size; /* 12 4 */ > + u32 folio_size; /* 8 4 */ > + > + /* XXX 4 bytes hole, try to pack */ > + > long unsigned int bflags; /* 16 8 */ > struct btrfs_fs_info * fs_info; /* 24 8 */ > void * addr; /* 32 8 */ > @@ -5554,8 +5556,8 @@ struct extent_buffer { > struct rw_semaphore lock; /* 72 40 */ > struct folio * folios[16]; /* 112 128 */ > > - /* size: 240, cachelines: 4, members: 14 */ > - /* sum members: 238, holes: 1, sum holes: 2 */ > + /* size: 240, cachelines: 4, members: 13 */ > + /* sum members: 234, holes: 2, sum holes: 6 */ > /* forced alignments: 1, forced holes: 1, sum forced holes: 2 */ > /* last cacheline: 48 bytes */ > } __attribute__((__aligned__(8))); > > The benefit of duplicating the length in each eb is that it's in the > same cacheline as the other members that are used for offset > calculations or bit manipulations. > > Going to the fs_info->nodesize may or may not hit a cache, also because > it needs to do 2 pointer dereferences, so from that perspective I think > it's making it worse. I was considering that. Since fs_info is shared for all ebs and other stuff like transactions, etc. I think the cache is hot most of the time and there will be hardly any performance difference observable. Though without benchmarks this is just a speculation (on both sides). > I don't think we need to do the optimization right now, but maybe in the > future if there's a need to add something to eb. Still we can use the > remaining 16 bytes up to 256 without making things worse. This really depends on configuration. On my laptop (Debian -rt kernel) the eb struct is actually 272 bytes as the rt_mutex is significantly heavier than raw spin lock. And -rt is a first class citizen nowadays, often used in Kubernetes deployments like 5G RAN telco, dpdk and such. I think it would be nice to slim the struct below 256 bytes even there if that's your aim. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH] btrfs: remove extent buffer's redundant `len` member field 2025-04-30 8:21 ` Daniel Vacek @ 2025-04-30 12:31 ` Daniel Vacek 2025-05-02 10:30 ` David Sterba 2025-04-30 13:30 ` David Sterba 1 sibling, 1 reply; 35+ messages in thread From: Daniel Vacek @ 2025-04-30 12:31 UTC (permalink / raw) To: dsterba; +Cc: Chris Mason, Josef Bacik, David Sterba, linux-btrfs, linux-kernel On Wed, 30 Apr 2025 at 10:21, Daniel Vacek <neelx@suse.com> wrote: > > On Wed, 30 Apr 2025 at 10:03, David Sterba <dsterba@suse.cz> wrote: > > > > On Tue, Apr 29, 2025 at 05:17:57PM +0200, Daniel Vacek wrote: > > > Even super block nowadays uses nodesize for eb->len. This is since commits > > > > > > 551561c34663 ("btrfs: don't pass nodesize to __alloc_extent_buffer()") > > > da17066c4047 ("btrfs: pull node/sector/stripe sizes out of root and into fs_info") > > > ce3e69847e3e ("btrfs: sink parameter len to alloc_extent_buffer") > > > a83fffb75d09 ("btrfs: sink blocksize parameter to btrfs_find_create_tree_block") > > > > > > With these the eb->len is not really useful anymore. Let's use the nodesize > > > directly where applicable. > > > > I've had this patch in my local branch for some years from the times we > > were optimizing extent buffer size. The size on release config is 240 > > bytes. The goal was to get it under 256 and keep it aligned. > > > > Removing eb->len does not change the structure size and leaves a hole > > > > struct extent_buffer { > > u64 start; /* 0 8 */ > > - u32 len; /* 8 4 */ > > - u32 folio_size; /* 12 4 */ > > + u32 folio_size; /* 8 4 */ > > + > > + /* XXX 4 bytes hole, try to pack */ > > + > > long unsigned int bflags; /* 16 8 */ > > struct btrfs_fs_info * fs_info; /* 24 8 */ > > void * addr; /* 32 8 */ > > @@ -5554,8 +5556,8 @@ struct extent_buffer { > > struct rw_semaphore lock; /* 72 40 */ > > struct folio * folios[16]; /* 112 128 */ > > > > - /* size: 240, cachelines: 4, members: 14 */ > > - /* sum members: 238, holes: 1, sum holes: 2 */ > > + /* size: 240, cachelines: 4, members: 13 */ > > + /* sum members: 234, holes: 2, sum holes: 6 */ > > /* forced alignments: 1, forced holes: 1, sum forced holes: 2 */ > > /* last cacheline: 48 bytes */ > > } __attribute__((__aligned__(8))); > > > > The benefit of duplicating the length in each eb is that it's in the > > same cacheline as the other members that are used for offset > > calculations or bit manipulations. > > > > Going to the fs_info->nodesize may or may not hit a cache, also because > > it needs to do 2 pointer dereferences, so from that perspective I think > > it's making it worse. > > I was considering that. Since fs_info is shared for all ebs and other > stuff like transactions, etc. I think the cache is hot most of the > time and there will be hardly any performance difference observable. > Though without benchmarks this is just a speculation (on both sides). > > > I don't think we need to do the optimization right now, but maybe in the > > future if there's a need to add something to eb. Still we can use the > > remaining 16 bytes up to 256 without making things worse. > > This really depends on configuration. On my laptop (Debian -rt kernel) > the eb struct is actually 272 bytes as the rt_mutex is significantly > heavier than raw spin lock. And -rt is a first class citizen nowadays, > often used in Kubernetes deployments like 5G RAN telco, dpdk and such. > I think it would be nice to slim the struct below 256 bytes even there > if that's your aim. Eventually we can get there by using ushort for bflags and moving log_index and folio_shift to fill the hole. Let me know what you think. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH] btrfs: remove extent buffer's redundant `len` member field 2025-04-30 12:31 ` Daniel Vacek @ 2025-05-02 10:30 ` David Sterba 2025-05-02 11:23 ` Daniel Vacek 0 siblings, 1 reply; 35+ messages in thread From: David Sterba @ 2025-05-02 10:30 UTC (permalink / raw) To: Daniel Vacek Cc: Chris Mason, Josef Bacik, David Sterba, linux-btrfs, linux-kernel On Wed, Apr 30, 2025 at 02:31:33PM +0200, Daniel Vacek wrote: > On Wed, 30 Apr 2025 at 10:21, Daniel Vacek <neelx@suse.com> wrote: > > > > On Wed, 30 Apr 2025 at 10:03, David Sterba <dsterba@suse.cz> wrote: > > > > > > On Tue, Apr 29, 2025 at 05:17:57PM +0200, Daniel Vacek wrote: > > > > Even super block nowadays uses nodesize for eb->len. This is since commits > > > > > > > > 551561c34663 ("btrfs: don't pass nodesize to __alloc_extent_buffer()") > > > > da17066c4047 ("btrfs: pull node/sector/stripe sizes out of root and into fs_info") > > > > ce3e69847e3e ("btrfs: sink parameter len to alloc_extent_buffer") > > > > a83fffb75d09 ("btrfs: sink blocksize parameter to btrfs_find_create_tree_block") > > > > > > > > With these the eb->len is not really useful anymore. Let's use the nodesize > > > > directly where applicable. > > > > > > I've had this patch in my local branch for some years from the times we > > > were optimizing extent buffer size. The size on release config is 240 > > > bytes. The goal was to get it under 256 and keep it aligned. > > > > > > Removing eb->len does not change the structure size and leaves a hole > > > > > > struct extent_buffer { > > > u64 start; /* 0 8 */ > > > - u32 len; /* 8 4 */ > > > - u32 folio_size; /* 12 4 */ > > > + u32 folio_size; /* 8 4 */ > > > + > > > + /* XXX 4 bytes hole, try to pack */ > > > + > > > long unsigned int bflags; /* 16 8 */ > > > struct btrfs_fs_info * fs_info; /* 24 8 */ > > > void * addr; /* 32 8 */ > > > @@ -5554,8 +5556,8 @@ struct extent_buffer { > > > struct rw_semaphore lock; /* 72 40 */ > > > struct folio * folios[16]; /* 112 128 */ > > > > > > - /* size: 240, cachelines: 4, members: 14 */ > > > - /* sum members: 238, holes: 1, sum holes: 2 */ > > > + /* size: 240, cachelines: 4, members: 13 */ > > > + /* sum members: 234, holes: 2, sum holes: 6 */ > > > /* forced alignments: 1, forced holes: 1, sum forced holes: 2 */ > > > /* last cacheline: 48 bytes */ > > > } __attribute__((__aligned__(8))); > > > > > > The benefit of duplicating the length in each eb is that it's in the > > > same cacheline as the other members that are used for offset > > > calculations or bit manipulations. > > > > > > Going to the fs_info->nodesize may or may not hit a cache, also because > > > it needs to do 2 pointer dereferences, so from that perspective I think > > > it's making it worse. > > > > I was considering that. Since fs_info is shared for all ebs and other > > stuff like transactions, etc. I think the cache is hot most of the > > time and there will be hardly any performance difference observable. > > Though without benchmarks this is just a speculation (on both sides). > > > > > I don't think we need to do the optimization right now, but maybe in the > > > future if there's a need to add something to eb. Still we can use the > > > remaining 16 bytes up to 256 without making things worse. > > > > This really depends on configuration. On my laptop (Debian -rt kernel) > > the eb struct is actually 272 bytes as the rt_mutex is significantly > > heavier than raw spin lock. And -rt is a first class citizen nowadays, > > often used in Kubernetes deployments like 5G RAN telco, dpdk and such. > > I think it would be nice to slim the struct below 256 bytes even there > > if that's your aim. > > Eventually we can get there by using ushort for bflags and moving > log_index and folio_shift to fill the hole. > Let me know what you think. The bflags are atomic bits and this requires unsigned long. Also the short int type is something we want to avoid because it's not a natural type on many architectures and generates worse code. I don't think we need to optimize for RT kernels, it's now part of mainline kernel but by far not a common configuration. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH] btrfs: remove extent buffer's redundant `len` member field 2025-05-02 10:30 ` David Sterba @ 2025-05-02 11:23 ` Daniel Vacek 0 siblings, 0 replies; 35+ messages in thread From: Daniel Vacek @ 2025-05-02 11:23 UTC (permalink / raw) To: dsterba; +Cc: Chris Mason, Josef Bacik, David Sterba, linux-btrfs, linux-kernel On Fri, 2 May 2025 at 12:30, David Sterba <dsterba@suse.cz> wrote: > > On Wed, Apr 30, 2025 at 02:31:33PM +0200, Daniel Vacek wrote: > > On Wed, 30 Apr 2025 at 10:21, Daniel Vacek <neelx@suse.com> wrote: > > > > > > On Wed, 30 Apr 2025 at 10:03, David Sterba <dsterba@suse.cz> wrote: > > > > > > > > On Tue, Apr 29, 2025 at 05:17:57PM +0200, Daniel Vacek wrote: > > > > > Even super block nowadays uses nodesize for eb->len. This is since commits > > > > > > > > > > 551561c34663 ("btrfs: don't pass nodesize to __alloc_extent_buffer()") > > > > > da17066c4047 ("btrfs: pull node/sector/stripe sizes out of root and into fs_info") > > > > > ce3e69847e3e ("btrfs: sink parameter len to alloc_extent_buffer") > > > > > a83fffb75d09 ("btrfs: sink blocksize parameter to btrfs_find_create_tree_block") > > > > > > > > > > With these the eb->len is not really useful anymore. Let's use the nodesize > > > > > directly where applicable. > > > > > > > > I've had this patch in my local branch for some years from the times we > > > > were optimizing extent buffer size. The size on release config is 240 > > > > bytes. The goal was to get it under 256 and keep it aligned. > > > > > > > > Removing eb->len does not change the structure size and leaves a hole > > > > > > > > struct extent_buffer { > > > > u64 start; /* 0 8 */ > > > > - u32 len; /* 8 4 */ > > > > - u32 folio_size; /* 12 4 */ > > > > + u32 folio_size; /* 8 4 */ > > > > + > > > > + /* XXX 4 bytes hole, try to pack */ > > > > + > > > > long unsigned int bflags; /* 16 8 */ > > > > struct btrfs_fs_info * fs_info; /* 24 8 */ > > > > void * addr; /* 32 8 */ > > > > @@ -5554,8 +5556,8 @@ struct extent_buffer { > > > > struct rw_semaphore lock; /* 72 40 */ > > > > struct folio * folios[16]; /* 112 128 */ > > > > > > > > - /* size: 240, cachelines: 4, members: 14 */ > > > > - /* sum members: 238, holes: 1, sum holes: 2 */ > > > > + /* size: 240, cachelines: 4, members: 13 */ > > > > + /* sum members: 234, holes: 2, sum holes: 6 */ > > > > /* forced alignments: 1, forced holes: 1, sum forced holes: 2 */ > > > > /* last cacheline: 48 bytes */ > > > > } __attribute__((__aligned__(8))); > > > > > > > > The benefit of duplicating the length in each eb is that it's in the > > > > same cacheline as the other members that are used for offset > > > > calculations or bit manipulations. > > > > > > > > Going to the fs_info->nodesize may or may not hit a cache, also because > > > > it needs to do 2 pointer dereferences, so from that perspective I think > > > > it's making it worse. > > > > > > I was considering that. Since fs_info is shared for all ebs and other > > > stuff like transactions, etc. I think the cache is hot most of the > > > time and there will be hardly any performance difference observable. > > > Though without benchmarks this is just a speculation (on both sides). > > > > > > > I don't think we need to do the optimization right now, but maybe in the > > > > future if there's a need to add something to eb. Still we can use the > > > > remaining 16 bytes up to 256 without making things worse. > > > > > > This really depends on configuration. On my laptop (Debian -rt kernel) > > > the eb struct is actually 272 bytes as the rt_mutex is significantly > > > heavier than raw spin lock. And -rt is a first class citizen nowadays, > > > often used in Kubernetes deployments like 5G RAN telco, dpdk and such. > > > I think it would be nice to slim the struct below 256 bytes even there > > > if that's your aim. > > > > Eventually we can get there by using ushort for bflags and moving > > log_index and folio_shift to fill the hole. > > Let me know what you think. > > The bflags are atomic bits and this requires unsigned long. Also the I realized and dropped that idea. Which means we can save just 8 bytes on -rt and nothing on default config. Still a good win for free. I mean in case we end up removing the `len` field. > short int type is something we want to avoid because it's not a natural > type on many architectures and generates worse code. I don't think we > need to optimize for RT kernels, it's now part of mainline kernel but by > far not a common configuration. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH] btrfs: remove extent buffer's redundant `len` member field 2025-04-30 8:21 ` Daniel Vacek 2025-04-30 12:31 ` Daniel Vacek @ 2025-04-30 13:30 ` David Sterba 2025-04-30 14:13 ` Daniel Vacek 1 sibling, 1 reply; 35+ messages in thread From: David Sterba @ 2025-04-30 13:30 UTC (permalink / raw) To: Daniel Vacek Cc: Chris Mason, Josef Bacik, David Sterba, linux-btrfs, linux-kernel On Wed, Apr 30, 2025 at 10:21:18AM +0200, Daniel Vacek wrote: > > The benefit of duplicating the length in each eb is that it's in the > > same cacheline as the other members that are used for offset > > calculations or bit manipulations. > > > > Going to the fs_info->nodesize may or may not hit a cache, also because > > it needs to do 2 pointer dereferences, so from that perspective I think > > it's making it worse. > > I was considering that. Since fs_info is shared for all ebs and other > stuff like transactions, etc. I think the cache is hot most of the > time and there will be hardly any performance difference observable. > Though without benchmarks this is just a speculation (on both sides). The comparison is between "always access 1 cacheline" and "hope that the other cacheline is hot", yeah we don't have benchmarks for that but the first access pattern is not conditional. > > I don't think we need to do the optimization right now, but maybe in the > > future if there's a need to add something to eb. Still we can use the > > remaining 16 bytes up to 256 without making things worse. > > This really depends on configuration. On my laptop (Debian -rt kernel) > the eb struct is actually 272 bytes as the rt_mutex is significantly > heavier than raw spin lock. And -rt is a first class citizen nowadays, > often used in Kubernetes deployments like 5G RAN telco, dpdk and such. > I think it would be nice to slim the struct below 256 bytes even there > if that's your aim. I configured and built RT kernel to see if it's possible to go to 256 bytes on RT and it seems yes with a big sacrifice of removing several struct members that cache values like folio_size or folio_shift and generating worse code. As 272 is a multiple of 16 it's a reasonable size and we don't need to optimize further. The number of ebs in one slab is 30, with the non-rt build it's 34, which sounds OK. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH] btrfs: remove extent buffer's redundant `len` member field 2025-04-30 13:30 ` David Sterba @ 2025-04-30 14:13 ` Daniel Vacek 2025-05-02 10:56 ` David Sterba 0 siblings, 1 reply; 35+ messages in thread From: Daniel Vacek @ 2025-04-30 14:13 UTC (permalink / raw) To: dsterba; +Cc: Chris Mason, Josef Bacik, David Sterba, linux-btrfs, linux-kernel On Wed, 30 Apr 2025 at 15:30, David Sterba <dsterba@suse.cz> wrote: > > On Wed, Apr 30, 2025 at 10:21:18AM +0200, Daniel Vacek wrote: > > > The benefit of duplicating the length in each eb is that it's in the > > > same cacheline as the other members that are used for offset > > > calculations or bit manipulations. > > > > > > Going to the fs_info->nodesize may or may not hit a cache, also because > > > it needs to do 2 pointer dereferences, so from that perspective I think > > > it's making it worse. > > > > I was considering that. Since fs_info is shared for all ebs and other > > stuff like transactions, etc. I think the cache is hot most of the > > time and there will be hardly any performance difference observable. > > Though without benchmarks this is just a speculation (on both sides). > > The comparison is between "always access 1 cacheline" and "hope that the > other cacheline is hot", yeah we don't have benchmarks for that but the > first access pattern is not conditional. That's quite right. Though in many places we already have fs_info anyways so it's rather accessing a cacheline in eb vs. accessing a cacheline in fs_info. In the former case it's likely a hot memory due to accessing surrounding members anyways, while in the later case is hopefully hot as it's a heavily shared resource accessed when processing other ebs or transactions. But yeah, in some places we don't have the fs_info pointer yet and two accesses are still needed. In theory fs_info could be shuffled to move nodesize to the same cacheline with buffer_tree. Would that feel better to you? > > > I don't think we need to do the optimization right now, but maybe in the > > > future if there's a need to add something to eb. Still we can use the > > > remaining 16 bytes up to 256 without making things worse. > > > > This really depends on configuration. On my laptop (Debian -rt kernel) > > the eb struct is actually 272 bytes as the rt_mutex is significantly > > heavier than raw spin lock. And -rt is a first class citizen nowadays, > > often used in Kubernetes deployments like 5G RAN telco, dpdk and such. > > I think it would be nice to slim the struct below 256 bytes even there > > if that's your aim. > > I configured and built RT kernel to see if it's possible to go to 256 > bytes on RT and it seems yes with a big sacrifice of removing several > struct members that cache values like folio_size or folio_shift and > generating worse code. > > As 272 is a multiple of 16 it's a reasonable size and we don't need to > optimize further. The number of ebs in one slab is 30, with the non-rt > build it's 34, which sounds OK. That sounds fair. Well the 256 bytes were your argument in the first place. Still, with this: --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h @@ -82,7 +82,10 @@ void __cold extent_buffer_free_cachep(void); struct extent_buffer { u64 start; u32 folio_size; - unsigned long bflags; + u8 folio_shift; + /* >= 0 if eb belongs to a log tree, -1 otherwise */ + s8 log_index; + unsigned short bflags; struct btrfs_fs_info *fs_info; /* @@ -94,9 +97,6 @@ struct extent_buffer { spinlock_t refs_lock; atomic_t refs; int read_mirror; - /* >= 0 if eb belongs to a log tree, -1 otherwise */ - s8 log_index; - u8 folio_shift; struct rcu_head rcu_head; struct rw_semaphore lock; you're down to 256 even on -rt. And the great part is I don't see any sacrifices (other than accessing a cacheline in fs_info). We're only using 8 flags now, so there is still some room left for another 8 if needed in the future. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH] btrfs: remove extent buffer's redundant `len` member field 2025-04-30 14:13 ` Daniel Vacek @ 2025-05-02 10:56 ` David Sterba 2025-05-02 12:03 ` Daniel Vacek 0 siblings, 1 reply; 35+ messages in thread From: David Sterba @ 2025-05-02 10:56 UTC (permalink / raw) To: Daniel Vacek Cc: Chris Mason, Josef Bacik, David Sterba, linux-btrfs, linux-kernel On Wed, Apr 30, 2025 at 04:13:20PM +0200, Daniel Vacek wrote: > On Wed, 30 Apr 2025 at 15:30, David Sterba <dsterba@suse.cz> wrote: > > > > On Wed, Apr 30, 2025 at 10:21:18AM +0200, Daniel Vacek wrote: > > > > The benefit of duplicating the length in each eb is that it's in the > > > > same cacheline as the other members that are used for offset > > > > calculations or bit manipulations. > > > > > > > > Going to the fs_info->nodesize may or may not hit a cache, also because > > > > it needs to do 2 pointer dereferences, so from that perspective I think > > > > it's making it worse. > > > > > > I was considering that. Since fs_info is shared for all ebs and other > > > stuff like transactions, etc. I think the cache is hot most of the > > > time and there will be hardly any performance difference observable. > > > Though without benchmarks this is just a speculation (on both sides). > > > > The comparison is between "always access 1 cacheline" and "hope that the > > other cacheline is hot", yeah we don't have benchmarks for that but the > > first access pattern is not conditional. > > That's quite right. Though in many places we already have fs_info > anyways so it's rather accessing a cacheline in eb vs. accessing a > cacheline in fs_info. In the former case it's likely a hot memory due > to accessing surrounding members anyways, while in the later case is > hopefully hot as it's a heavily shared resource accessed when > processing other ebs or transactions. > But yeah, in some places we don't have the fs_info pointer yet and two > accesses are still needed. The fs_info got added to eb because it used to be passed as parameter to many functions. > In theory fs_info could be shuffled to move nodesize to the same > cacheline with buffer_tree. Would that feel better to you? We'd get conflicting requirements for ordering in fs_info. Right now the nodesize/sectorsize/... are in once cacheline in fs_info and they're often used together in many functions. Reordering it to fit eb usage pattern may work but I'm not convinced we need it. > > > > I don't think we need to do the optimization right now, but maybe in the > > > > future if there's a need to add something to eb. Still we can use the > > > > remaining 16 bytes up to 256 without making things worse. > > > > > > This really depends on configuration. On my laptop (Debian -rt kernel) > > > the eb struct is actually 272 bytes as the rt_mutex is significantly > > > heavier than raw spin lock. And -rt is a first class citizen nowadays, > > > often used in Kubernetes deployments like 5G RAN telco, dpdk and such. > > > I think it would be nice to slim the struct below 256 bytes even there > > > if that's your aim. > > > > I configured and built RT kernel to see if it's possible to go to 256 > > bytes on RT and it seems yes with a big sacrifice of removing several > > struct members that cache values like folio_size or folio_shift and > > generating worse code. > > > > As 272 is a multiple of 16 it's a reasonable size and we don't need to > > optimize further. The number of ebs in one slab is 30, with the non-rt > > build it's 34, which sounds OK. > > That sounds fair. Well the 256 bytes were your argument in the first place. Yeah, 256 is a nice number because it aligns with cachelines on multiple architectures, this is useful for splitting the structure to the "data accessed together" and locking/refcounting. It's a tentative goal, we used to have larger eb size due to own locking implementation but with rwsems it got close/under 256. The current size 240 is 1/4 of cacheline shifted so it's not all clean but whe have some wiggle room for adding new members or cached values, like folio_size/folio_shift/addr. > > Still, with this: > > --- a/fs/btrfs/extent_io.h > +++ b/fs/btrfs/extent_io.h > @@ -82,7 +82,10 @@ void __cold extent_buffer_free_cachep(void); > struct extent_buffer { > u64 start; > u32 folio_size; > - unsigned long bflags; > + u8 folio_shift; > + /* >= 0 if eb belongs to a log tree, -1 otherwise */ > + s8 log_index; > + unsigned short bflags; This does not compile because of set_bit/clear_bit/wait_on_bit API requirements. > struct btrfs_fs_info *fs_info; > > /* > @@ -94,9 +97,6 @@ struct extent_buffer { > spinlock_t refs_lock; > atomic_t refs; > int read_mirror; > - /* >= 0 if eb belongs to a log tree, -1 otherwise */ > - s8 log_index; > - u8 folio_shift; > struct rcu_head rcu_head; > > struct rw_semaphore lock; > > you're down to 256 even on -rt. And the great part is I don't see any > sacrifices (other than accessing a cacheline in fs_info). We're only > using 8 flags now, so there is still some room left for another 8 if > needed in the future. Which means that the size on non-rt would be something like 228, roughly calculating the savings and the increase due to spinloct_t going from 4 -> 32 bytes. Also I'd like to see the generated assembly after the suggested reordering. The eb may not be perfect, I think there could be false sharing of refs_lock and refs but this is a wild guess and based only on code observation. You may have more luck with other data structures with unnecessary holes but please optimize for non-RT first. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH] btrfs: remove extent buffer's redundant `len` member field 2025-05-02 10:56 ` David Sterba @ 2025-05-02 12:03 ` Daniel Vacek 2025-05-05 14:10 ` David Sterba 0 siblings, 1 reply; 35+ messages in thread From: Daniel Vacek @ 2025-05-02 12:03 UTC (permalink / raw) To: dsterba; +Cc: Chris Mason, Josef Bacik, David Sterba, linux-btrfs, linux-kernel On Fri, 2 May 2025 at 12:56, David Sterba <dsterba@suse.cz> wrote: > > On Wed, Apr 30, 2025 at 04:13:20PM +0200, Daniel Vacek wrote: > > On Wed, 30 Apr 2025 at 15:30, David Sterba <dsterba@suse.cz> wrote: > > > > > > On Wed, Apr 30, 2025 at 10:21:18AM +0200, Daniel Vacek wrote: > > > > > The benefit of duplicating the length in each eb is that it's in the > > > > > same cacheline as the other members that are used for offset > > > > > calculations or bit manipulations. > > > > > > > > > > Going to the fs_info->nodesize may or may not hit a cache, also because > > > > > it needs to do 2 pointer dereferences, so from that perspective I think > > > > > it's making it worse. > > > > > > > > I was considering that. Since fs_info is shared for all ebs and other > > > > stuff like transactions, etc. I think the cache is hot most of the > > > > time and there will be hardly any performance difference observable. > > > > Though without benchmarks this is just a speculation (on both sides). > > > > > > The comparison is between "always access 1 cacheline" and "hope that the > > > other cacheline is hot", yeah we don't have benchmarks for that but the > > > first access pattern is not conditional. > > > > That's quite right. Though in many places we already have fs_info > > anyways so it's rather accessing a cacheline in eb vs. accessing a > > cacheline in fs_info. In the former case it's likely a hot memory due > > to accessing surrounding members anyways, while in the later case is > > hopefully hot as it's a heavily shared resource accessed when > > processing other ebs or transactions. > > But yeah, in some places we don't have the fs_info pointer yet and two > > accesses are still needed. > > The fs_info got added to eb because it used to be passed as parameter to > many functions. Makes sense. > > In theory fs_info could be shuffled to move nodesize to the same > > cacheline with buffer_tree. Would that feel better to you? > > We'd get conflicting requirements for ordering in fs_info. Right now > the nodesize/sectorsize/... are in once cacheline in fs_info and they're > often used together in many functions. Reordering it to fit eb usage > pattern may work but I'm not convinced we need it. I agree. > > > > > I don't think we need to do the optimization right now, but maybe in the > > > > > future if there's a need to add something to eb. Still we can use the > > > > > remaining 16 bytes up to 256 without making things worse. > > > > > > > > This really depends on configuration. On my laptop (Debian -rt kernel) > > > > the eb struct is actually 272 bytes as the rt_mutex is significantly > > > > heavier than raw spin lock. And -rt is a first class citizen nowadays, > > > > often used in Kubernetes deployments like 5G RAN telco, dpdk and such. > > > > I think it would be nice to slim the struct below 256 bytes even there > > > > if that's your aim. > > > > > > I configured and built RT kernel to see if it's possible to go to 256 > > > bytes on RT and it seems yes with a big sacrifice of removing several > > > struct members that cache values like folio_size or folio_shift and > > > generating worse code. > > > > > > As 272 is a multiple of 16 it's a reasonable size and we don't need to > > > optimize further. The number of ebs in one slab is 30, with the non-rt > > > build it's 34, which sounds OK. > > > > That sounds fair. Well the 256 bytes were your argument in the first place. > > Yeah, 256 is a nice number because it aligns with cachelines on multiple > architectures, this is useful for splitting the structure to the "data > accessed together" and locking/refcounting. It's a tentative goal, we > used to have larger eb size due to own locking implementation but with > rwsems it got close/under 256. > > The current size 240 is 1/4 of cacheline shifted so it's not all clean > but whe have some wiggle room for adding new members or cached values, > like folio_size/folio_shift/addr. Sounds like we could force align to cacheline or explicitly pad to 256B? The later could be a bit tricky though. > > > > Still, with this: > > > > --- a/fs/btrfs/extent_io.h > > +++ b/fs/btrfs/extent_io.h > > @@ -82,7 +82,10 @@ void __cold extent_buffer_free_cachep(void); > > struct extent_buffer { > > u64 start; > > u32 folio_size; > > - unsigned long bflags; > > + u8 folio_shift; > > + /* >= 0 if eb belongs to a log tree, -1 otherwise */ > > + s8 log_index; > > + unsigned short bflags; > > This does not compile because of set_bit/clear_bit/wait_on_bit API > requirements. Yeah, I realized when I tried to implement it. It was just an email idea when sent. > > struct btrfs_fs_info *fs_info; > > > > /* > > @@ -94,9 +97,6 @@ struct extent_buffer { > > spinlock_t refs_lock; > > atomic_t refs; > > int read_mirror; > > - /* >= 0 if eb belongs to a log tree, -1 otherwise */ > > - s8 log_index; > > - u8 folio_shift; > > struct rcu_head rcu_head; > > > > struct rw_semaphore lock; > > > > you're down to 256 even on -rt. And the great part is I don't see any > > sacrifices (other than accessing a cacheline in fs_info). We're only > > using 8 flags now, so there is still some room left for another 8 if > > needed in the future. > > Which means that the size on non-rt would be something like 228, roughly > calculating the savings and the increase due to spinloct_t going from > 4 -> 32 bytes. Also I'd like to see the generated assembly after the > suggested reordering. If I see correctly the non-rt will not change when I keep ulong bflags. The -rt build goes down to 264 bytes. That's a bit better for free but still not ideal from alignment POV. > The eb may not be perfect, I think there could be false sharing of > refs_lock and refs but this is a wild guess and based only on code refs_lock and refs look like they share the same cacheline in every case. At least on x86. But still, the slab object is not aligned in the first place. Luckily the two fields roam together. Out of curiosity, is there any past experience where this kind of optimizations make a difference within a filesystem code? I can imagine perhaps for fast devices like NVDIMM or DAX the CPU may become the bottleneck? Or are nowadays NVMe devices already fast enough to saturate the CPU? I faintly recall one issue where I debugged a CPU which could not keep up with handling the interrupts of finished IO on NVMe submitted by other CPUs. Though that was on xfs (or maybe ext4) not on btrfs. But that was a power-play of one against the rest as the interrupt was not balanced or spread to more CPUs. > observation. You may have more luck with other data structures with > unnecessary holes but please optimize for non-RT first. Clearly non-rt is the default and most important. No questions here. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH] btrfs: remove extent buffer's redundant `len` member field 2025-05-02 12:03 ` Daniel Vacek @ 2025-05-05 14:10 ` David Sterba 2025-05-05 16:19 ` Daniel Vacek 0 siblings, 1 reply; 35+ messages in thread From: David Sterba @ 2025-05-05 14:10 UTC (permalink / raw) To: Daniel Vacek Cc: dsterba, Chris Mason, Josef Bacik, David Sterba, linux-btrfs, linux-kernel On Fri, May 02, 2025 at 02:03:55PM +0200, Daniel Vacek wrote: > > Yeah, 256 is a nice number because it aligns with cachelines on multiple > > architectures, this is useful for splitting the structure to the "data > > accessed together" and locking/refcounting. It's a tentative goal, we > > used to have larger eb size due to own locking implementation but with > > rwsems it got close/under 256. > > > > The current size 240 is 1/4 of cacheline shifted so it's not all clean > > but whe have some wiggle room for adding new members or cached values, > > like folio_size/folio_shift/addr. > > Sounds like we could force align to cacheline or explicitly pad to > 256B? The later could be a bit tricky though. We could and we also have conflicting goals: - alignment (with some waste) - more objects packed into the slab which is 8K More objects mean better chance to satisfy allocations, that are right now NOFAIL, so blocking metadata operations with worse consequences. > > > struct btrfs_fs_info *fs_info; > > > > > > /* > > > @@ -94,9 +97,6 @@ struct extent_buffer { > > > spinlock_t refs_lock; > > > atomic_t refs; > > > int read_mirror; > > > - /* >= 0 if eb belongs to a log tree, -1 otherwise */ > > > - s8 log_index; > > > - u8 folio_shift; > > > struct rcu_head rcu_head; > > > > > > struct rw_semaphore lock; > > > > > > you're down to 256 even on -rt. And the great part is I don't see any > > > sacrifices (other than accessing a cacheline in fs_info). We're only > > > using 8 flags now, so there is still some room left for another 8 if > > > needed in the future. > > > > Which means that the size on non-rt would be something like 228, roughly > > calculating the savings and the increase due to spinloct_t going from > > 4 -> 32 bytes. Also I'd like to see the generated assembly after the > > suggested reordering. > > If I see correctly the non-rt will not change when I keep ulong > bflags. The -rt build goes down to 264 bytes. That's a bit better for > free but still not ideal from alignment POV. > > > The eb may not be perfect, I think there could be false sharing of > > refs_lock and refs but this is a wild guess and based only on code > > refs_lock and refs look like they share the same cacheline in every > case. At least on x86. > But still, the slab object is not aligned in the first place. Luckily > the two fields roam together. > > Out of curiosity, is there any past experience where this kind of > optimizations make a difference within a filesystem code? > I can imagine perhaps for fast devices like NVDIMM or DAX the CPU may > become the bottleneck? Or are nowadays NVMe devices already fast > enough to saturate the CPU? I don't have a specific example. This is tricky to measure and historically the devices were slow so any IO and waiting made the cache effects irrelevant. With NVMe, modern CPUs we might start seeing that. Instrumentation or profiling of the structures can do that, there are tools for that but the variability of the hardware combinations and runtime conditions makes it hard so I'm resorting to more "static" approach and go after known good patterns like alignment or placement related to cachelines (manually or with ____cacheline_aligned_in_smp). > I faintly recall one issue where I debugged a CPU which could not keep > up with handling the interrupts of finished IO on NVMe submitted by > other CPUs. Though that was on xfs (or maybe ext4) not on btrfs. But > that was a power-play of one against the rest as the interrupt was not > balanced or spread to more CPUs. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH] btrfs: remove extent buffer's redundant `len` member field 2025-05-05 14:10 ` David Sterba @ 2025-05-05 16:19 ` Daniel Vacek 0 siblings, 0 replies; 35+ messages in thread From: Daniel Vacek @ 2025-05-05 16:19 UTC (permalink / raw) To: dsterba; +Cc: Chris Mason, Josef Bacik, David Sterba, linux-btrfs, linux-kernel On Mon, 5 May 2025 at 16:10, David Sterba <dsterba@suse.cz> wrote: > > On Fri, May 02, 2025 at 02:03:55PM +0200, Daniel Vacek wrote: > > > Yeah, 256 is a nice number because it aligns with cachelines on multiple > > > architectures, this is useful for splitting the structure to the "data > > > accessed together" and locking/refcounting. It's a tentative goal, we > > > used to have larger eb size due to own locking implementation but with > > > rwsems it got close/under 256. > > > > > > The current size 240 is 1/4 of cacheline shifted so it's not all clean > > > but whe have some wiggle room for adding new members or cached values, > > > like folio_size/folio_shift/addr. > > > > Sounds like we could force align to cacheline or explicitly pad to > > 256B? The later could be a bit tricky though. > > We could and we also have conflicting goals: > > - alignment (with some waste) > > - more objects packed into the slab which is 8K tl.dr> In the end I think it's all about the wasted memory. Either there's a good reason for it when the alignment is required or there is not and the slab can be packed. In the latter case there is no point for discussing cache line misses, IMO. Am I right? Slab allocator is not so simple. By default (but can be tuned globally or per slab cache) slabs are allocated up to order 3, so 32Ki on x86. But the allocator tries to keep the order lower if at the least minimum number of (4*floor(log2(nr_cpus))+4) objects fit in. So a bigger object size results in higher order of slabs (up to o3) with about the same number of objects per slab. And vice versa. In general, the tradeoff is more about wasted memory, see calculate_order() and calc_slab_order(). But also the downside is that higher order slab which wastes less memory could be harder to allocate after some uptime and memory fragmentation. Anyways, this is a job for slab and it does a good job already so that you do not need to be all that concerned about it. Still, some concern is always good. Note, slab also honors the alignment of the given structure. So in the end it ultimately depends on the alignment of struct extent_buffer. If you really wanted to have some members hot in the same cacheline, we could declare the structure with ____cacheline_aligned_in_smp. Otherwise some objects may have the desired fields shared and some may not. Well, at least that would be the case if we used KMEM_CACHE() macro which we don't at the moment. We still use the old kmem_cache_create() API and we are requesting an alignment of 0. So the objects are placed completely freely within the slab. ==== And a bit off topic but still related. I'm a bit more concerned about wasting 3 xarray slots for each eb (only 1/4 of the slots are being used due to deprecated legacy). Each leaf can store only up to 16 ebs while there are 64 slots. That's because we are still indexing by sector size and not by node size. The xarray/radix tree could save 75% of the memory it is using now. At least for the common case of 4Ki sector size and 16Ki node size. > More objects mean better chance to satisfy allocations, that are right > now NOFAIL, so blocking metadata operations with worse consequences. Right, the more objects per slab the better amortized the allocation overhead is. That's perfectly clear, no questions about it. But as I mentioned this is mostly decided by the slab allocator. Yet, I understand your concerns. > > > > struct btrfs_fs_info *fs_info; > > > > > > > > /* > > > > @@ -94,9 +97,6 @@ struct extent_buffer { > > > > spinlock_t refs_lock; > > > > atomic_t refs; > > > > int read_mirror; > > > > - /* >= 0 if eb belongs to a log tree, -1 otherwise */ > > > > - s8 log_index; > > > > - u8 folio_shift; > > > > struct rcu_head rcu_head; > > > > > > > > struct rw_semaphore lock; > > > > > > > > you're down to 256 even on -rt. And the great part is I don't see any > > > > sacrifices (other than accessing a cacheline in fs_info). We're only > > > > using 8 flags now, so there is still some room left for another 8 if > > > > needed in the future. > > > > > > Which means that the size on non-rt would be something like 228, roughly > > > calculating the savings and the increase due to spinloct_t going from > > > 4 -> 32 bytes. Also I'd like to see the generated assembly after the > > > suggested reordering. > > > > If I see correctly the non-rt will not change when I keep ulong > > bflags. The -rt build goes down to 264 bytes. That's a bit better for > > free but still not ideal from alignment POV. > > > > > The eb may not be perfect, I think there could be false sharing of > > > refs_lock and refs but this is a wild guess and based only on code > > > > refs_lock and refs look like they share the same cacheline in every > > case. At least on x86. > > But still, the slab object is not aligned in the first place. Luckily > > the two fields roam together. > > > > Out of curiosity, is there any past experience where this kind of > > optimizations make a difference within a filesystem code? > > I can imagine perhaps for fast devices like NVDIMM or DAX the CPU may > > become the bottleneck? Or are nowadays NVMe devices already fast > > enough to saturate the CPU? > > I don't have a specific example. This is tricky to measure and > historically the devices were slow so any IO and waiting made the cache > effects irrelevant. With NVMe, modern CPUs we might start seeing that. > Instrumentation or profiling of the structures can do that, there are > tools for that but the variability of the hardware combinations and > runtime conditions makes it hard so I'm resorting to more "static" > approach and go after known good patterns like alignment or placement > related to cachelines (manually or with ____cacheline_aligned_in_smp). Yeah, I know perf's cache to cache proved to be especially useful in the past with the network stack and other parts of the kernel. But that may be a bit different use-case. > > I faintly recall one issue where I debugged a CPU which could not keep > > up with handling the interrupts of finished IO on NVMe submitted by > > other CPUs. Though that was on xfs (or maybe ext4) not on btrfs. But > > that was a power-play of one against the rest as the interrupt was not > > balanced or spread to more CPUs. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH] btrfs: remove extent buffer's redundant `len` member field 2025-04-29 15:17 [PATCH] btrfs: remove extent buffer's redundant `len` member field Daniel Vacek 2025-04-29 22:34 ` Qu Wenruo 2025-04-30 8:03 ` David Sterba @ 2025-04-30 8:05 ` Filipe Manana 2025-04-30 8:26 ` Daniel Vacek 2025-05-02 13:37 ` [PATCH v2 0/2] btrfs: eb struct cleanups Daniel Vacek 3 siblings, 1 reply; 35+ messages in thread From: Filipe Manana @ 2025-04-30 8:05 UTC (permalink / raw) To: Daniel Vacek Cc: Chris Mason, Josef Bacik, David Sterba, linux-btrfs, linux-kernel On Tue, Apr 29, 2025 at 4:19 PM Daniel Vacek <neelx@suse.com> wrote: > > Even super block nowadays uses nodesize for eb->len. This is since commits > > 551561c34663 ("btrfs: don't pass nodesize to __alloc_extent_buffer()") > da17066c4047 ("btrfs: pull node/sector/stripe sizes out of root and into fs_info") > ce3e69847e3e ("btrfs: sink parameter len to alloc_extent_buffer") > a83fffb75d09 ("btrfs: sink blocksize parameter to btrfs_find_create_tree_block") > > With these the eb->len is not really useful anymore. Let's use the nodesize > directly where applicable. > > Signed-off-by: Daniel Vacek <neelx@suse.com> > --- > [RFC] > * Shall the eb_len() helper better be called eb_nodesize()? Or even rather > opencoded and not used at all? > > fs/btrfs/accessors.c | 4 +-- > fs/btrfs/disk-io.c | 11 ++++--- > fs/btrfs/extent-tree.c | 28 +++++++++-------- > fs/btrfs/extent_io.c | 54 ++++++++++++++------------------ > fs/btrfs/extent_io.h | 11 +++++-- > fs/btrfs/ioctl.c | 2 +- > fs/btrfs/relocation.c | 2 +- > fs/btrfs/subpage.c | 8 ++--- > fs/btrfs/tests/extent-io-tests.c | 12 +++---- > fs/btrfs/zoned.c | 2 +- > 10 files changed, 67 insertions(+), 67 deletions(-) > > diff --git a/fs/btrfs/accessors.c b/fs/btrfs/accessors.c > index e3716516ca387..a2bdbc7990906 100644 > --- a/fs/btrfs/accessors.c > +++ b/fs/btrfs/accessors.c > @@ -14,10 +14,10 @@ static bool check_setget_bounds(const struct extent_buffer *eb, > { > const unsigned long member_offset = (unsigned long)ptr + off; > > - if (unlikely(member_offset + size > eb->len)) { > + if (unlikely(member_offset + size > eb_len(eb))) { > btrfs_warn(eb->fs_info, > "bad eb member %s: ptr 0x%lx start %llu member offset %lu size %d", > - (member_offset > eb->len ? "start" : "end"), > + (member_offset > eb_len(eb) ? "start" : "end"), > (unsigned long)ptr, eb->start, member_offset, size); > return false; > } > diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c > index 3592300ae3e2e..31eb7419fe11f 100644 > --- a/fs/btrfs/disk-io.c > +++ b/fs/btrfs/disk-io.c > @@ -190,7 +190,7 @@ static int btrfs_repair_eb_io_failure(const struct extent_buffer *eb, > for (int i = 0; i < num_extent_folios(eb); i++) { > struct folio *folio = eb->folios[i]; > u64 start = max_t(u64, eb->start, folio_pos(folio)); > - u64 end = min_t(u64, eb->start + eb->len, > + u64 end = min_t(u64, eb->start + fs_info->nodesize, > folio_pos(folio) + eb->folio_size); > u32 len = end - start; > phys_addr_t paddr = PFN_PHYS(folio_pfn(folio)) + > @@ -230,7 +230,7 @@ int btrfs_read_extent_buffer(struct extent_buffer *eb, > break; > > num_copies = btrfs_num_copies(fs_info, > - eb->start, eb->len); > + eb->start, fs_info->nodesize); > if (num_copies == 1) > break; > > @@ -260,6 +260,7 @@ blk_status_t btree_csum_one_bio(struct btrfs_bio *bbio) > { > struct extent_buffer *eb = bbio->private; > struct btrfs_fs_info *fs_info = eb->fs_info; > + u32 nodesize = fs_info->nodesize; > u64 found_start = btrfs_header_bytenr(eb); > u64 last_trans; > u8 result[BTRFS_CSUM_SIZE]; > @@ -268,7 +269,7 @@ blk_status_t btree_csum_one_bio(struct btrfs_bio *bbio) > /* Btree blocks are always contiguous on disk. */ > if (WARN_ON_ONCE(bbio->file_offset != eb->start)) > return BLK_STS_IOERR; > - if (WARN_ON_ONCE(bbio->bio.bi_iter.bi_size != eb->len)) > + if (WARN_ON_ONCE(bbio->bio.bi_iter.bi_size != nodesize)) > return BLK_STS_IOERR; > > /* > @@ -277,7 +278,7 @@ blk_status_t btree_csum_one_bio(struct btrfs_bio *bbio) > * ordering of I/O without unnecessarily writing out data. > */ > if (test_bit(EXTENT_BUFFER_ZONED_ZEROOUT, &eb->bflags)) { > - memzero_extent_buffer(eb, 0, eb->len); > + memzero_extent_buffer(eb, 0, nodesize); > return BLK_STS_OK; > } > > @@ -883,7 +884,7 @@ struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans, > btrfs_set_root_generation(&root->root_item, trans->transid); > btrfs_set_root_level(&root->root_item, 0); > btrfs_set_root_refs(&root->root_item, 1); > - btrfs_set_root_used(&root->root_item, leaf->len); > + btrfs_set_root_used(&root->root_item, fs_info->nodesize); > btrfs_set_root_last_snapshot(&root->root_item, 0); > btrfs_set_root_dirid(&root->root_item, 0); > if (is_fstree(objectid)) > diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c > index e0811a86d0cbd..25560a162d93e 100644 > --- a/fs/btrfs/extent-tree.c > +++ b/fs/btrfs/extent-tree.c > @@ -2211,7 +2211,7 @@ int btrfs_set_disk_extent_flags(struct btrfs_trans_handle *trans, > extent_op->update_flags = true; > extent_op->update_key = false; > > - ret = btrfs_add_delayed_extent_op(trans, eb->start, eb->len, > + ret = btrfs_add_delayed_extent_op(trans, eb->start, eb_len(eb), > btrfs_header_level(eb), extent_op); > if (ret) > btrfs_free_delayed_extent_op(extent_op); > @@ -2660,10 +2660,10 @@ int btrfs_pin_extent_for_log_replay(struct btrfs_trans_handle *trans, > if (ret) > goto out; > > - pin_down_extent(trans, cache, eb->start, eb->len, 0); > + pin_down_extent(trans, cache, eb->start, eb_len(eb), 0); > > /* remove us from the free space cache (if we're there at all) */ > - ret = btrfs_remove_free_space(cache, eb->start, eb->len); > + ret = btrfs_remove_free_space(cache, eb->start, eb_len(eb)); > out: > btrfs_put_block_group(cache); > return ret; > @@ -3436,13 +3436,14 @@ int btrfs_free_tree_block(struct btrfs_trans_handle *trans, > { > struct btrfs_fs_info *fs_info = trans->fs_info; > struct btrfs_block_group *bg; > + u32 nodesize = fs_info->nodesize; > int ret; > > if (root_id != BTRFS_TREE_LOG_OBJECTID) { > struct btrfs_ref generic_ref = { > .action = BTRFS_DROP_DELAYED_REF, > .bytenr = buf->start, > - .num_bytes = buf->len, > + .num_bytes = nodesize, > .parent = parent, > .owning_root = btrfs_header_owner(buf), > .ref_root = root_id, > @@ -3478,7 +3479,7 @@ int btrfs_free_tree_block(struct btrfs_trans_handle *trans, > bg = btrfs_lookup_block_group(fs_info, buf->start); > > if (btrfs_header_flag(buf, BTRFS_HEADER_FLAG_WRITTEN)) { > - pin_down_extent(trans, bg, buf->start, buf->len, 1); > + pin_down_extent(trans, bg, buf->start, nodesize, 1); > btrfs_put_block_group(bg); > goto out; > } > @@ -3502,17 +3503,17 @@ int btrfs_free_tree_block(struct btrfs_trans_handle *trans, > > if (test_bit(BTRFS_FS_TREE_MOD_LOG_USERS, &fs_info->flags) > || btrfs_is_zoned(fs_info)) { > - pin_down_extent(trans, bg, buf->start, buf->len, 1); > + pin_down_extent(trans, bg, buf->start, nodesize, 1); > btrfs_put_block_group(bg); > goto out; > } > > WARN_ON(test_bit(EXTENT_BUFFER_DIRTY, &buf->bflags)); > > - btrfs_add_free_space(bg, buf->start, buf->len); > - btrfs_free_reserved_bytes(bg, buf->len, 0); > + btrfs_add_free_space(bg, buf->start, nodesize); > + btrfs_free_reserved_bytes(bg, nodesize, 0); > btrfs_put_block_group(bg); > - trace_btrfs_reserved_extent_free(fs_info, buf->start, buf->len); > + trace_btrfs_reserved_extent_free(fs_info, buf->start, nodesize); > > out: > return 0; > @@ -4768,7 +4769,7 @@ int btrfs_pin_reserved_extent(struct btrfs_trans_handle *trans, > return -ENOSPC; > } > > - ret = pin_down_extent(trans, cache, eb->start, eb->len, 1); > + ret = pin_down_extent(trans, cache, eb->start, eb_len(eb), 1); > btrfs_put_block_group(cache); > return ret; > } > @@ -5050,6 +5051,7 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root, > struct btrfs_fs_info *fs_info = root->fs_info; > struct extent_buffer *buf; > u64 lockdep_owner = owner; > + u32 nodesize = fs_info->nodesize; > > buf = btrfs_find_create_tree_block(fs_info, bytenr, owner, level); > if (IS_ERR(buf)) > @@ -5107,16 +5109,16 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root, > */ > if (buf->log_index == 0) > btrfs_set_extent_bit(&root->dirty_log_pages, buf->start, > - buf->start + buf->len - 1, > + buf->start + nodesize - 1, > EXTENT_DIRTY, NULL); > else > btrfs_set_extent_bit(&root->dirty_log_pages, buf->start, > - buf->start + buf->len - 1, > + buf->start + nodesize - 1, > EXTENT_NEW, NULL); > } else { > buf->log_index = -1; > btrfs_set_extent_bit(&trans->transaction->dirty_pages, buf->start, > - buf->start + buf->len - 1, EXTENT_DIRTY, NULL); > + buf->start + nodesize - 1, EXTENT_DIRTY, NULL); > } > /* this returns a buffer locked for blocking */ > return buf; > diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c > index 20cdddd924852..e4050fd5db285 100644 > --- a/fs/btrfs/extent_io.c > +++ b/fs/btrfs/extent_io.c > @@ -76,8 +76,8 @@ void btrfs_extent_buffer_leak_debug_check(struct btrfs_fs_info *fs_info) > eb = list_first_entry(&fs_info->allocated_ebs, > struct extent_buffer, leak_list); > pr_err( > - "BTRFS: buffer leak start %llu len %u refs %d bflags %lu owner %llu\n", > - eb->start, eb->len, atomic_read(&eb->refs), eb->bflags, > + "BTRFS: buffer leak start %llu refs %d bflags %lu owner %llu\n", > + eb->start, atomic_read(&eb->refs), eb->bflags, > btrfs_header_owner(eb)); > list_del(&eb->leak_list); > WARN_ON_ONCE(1); > @@ -1746,8 +1746,8 @@ static noinline_for_stack bool lock_extent_buffer_for_io(struct extent_buffer *e > > btrfs_set_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN); > percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, > - -eb->len, > - fs_info->dirty_metadata_batch); > + -fs_info->nodesize, > + fs_info->dirty_metadata_batch); > ret = true; > } else { > spin_unlock(&eb->refs_lock); > @@ -1953,7 +1953,7 @@ static unsigned int buffer_tree_get_ebs_tag(struct btrfs_fs_info *fs_info, > rcu_read_lock(); > while ((eb = find_get_eb(&xas, end, tag)) != NULL) { > if (!eb_batch_add(batch, eb)) { > - *start = (eb->start + eb->len) >> fs_info->sectorsize_bits; > + *start = (eb->start + fs_info->nodesize) >> fs_info->sectorsize_bits; > goto out; > } > } > @@ -2020,7 +2020,7 @@ static void prepare_eb_write(struct extent_buffer *eb) > nritems = btrfs_header_nritems(eb); > if (btrfs_header_level(eb) > 0) { > end = btrfs_node_key_ptr_offset(eb, nritems); > - memzero_extent_buffer(eb, end, eb->len - end); > + memzero_extent_buffer(eb, end, eb_len(eb) - end); > } else { > /* > * Leaf: > @@ -2056,7 +2056,7 @@ static noinline_for_stack void write_one_eb(struct extent_buffer *eb, > struct folio *folio = eb->folios[i]; > u64 range_start = max_t(u64, eb->start, folio_pos(folio)); > u32 range_len = min_t(u64, folio_pos(folio) + folio_size(folio), > - eb->start + eb->len) - range_start; > + eb->start + fs_info->nodesize) - range_start; > > folio_lock(folio); > btrfs_meta_folio_clear_dirty(folio, eb); > @@ -2171,7 +2171,7 @@ int btree_write_cache_pages(struct address_space *mapping, > if (ctx.zoned_bg) { > /* Mark the last eb in the block group. */ > btrfs_schedule_zone_finish_bg(ctx.zoned_bg, eb); > - ctx.zoned_bg->meta_write_pointer += eb->len; > + ctx.zoned_bg->meta_write_pointer += fs_info->nodesize; > } > write_one_eb(eb, wbc); > } > @@ -2807,7 +2807,6 @@ static struct extent_buffer *__alloc_extent_buffer(struct btrfs_fs_info *fs_info > > eb = kmem_cache_zalloc(extent_buffer_cache, GFP_NOFS|__GFP_NOFAIL); > eb->start = start; > - eb->len = fs_info->nodesize; > eb->fs_info = fs_info; > init_rwsem(&eb->lock); > > @@ -2816,8 +2815,6 @@ static struct extent_buffer *__alloc_extent_buffer(struct btrfs_fs_info *fs_info > spin_lock_init(&eb->refs_lock); > atomic_set(&eb->refs, 1); > > - ASSERT(eb->len <= BTRFS_MAX_METADATA_BLOCKSIZE); > - > return eb; > } > > @@ -3505,7 +3502,7 @@ void btrfs_clear_buffer_dirty(struct btrfs_trans_handle *trans, > return; > > buffer_tree_clear_mark(eb, PAGECACHE_TAG_DIRTY); > - percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, -eb->len, > + percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, -fs_info->nodesize, > fs_info->dirty_metadata_batch); > > for (int i = 0; i < num_extent_folios(eb); i++) { > @@ -3557,8 +3554,8 @@ void set_extent_buffer_dirty(struct extent_buffer *eb) > if (subpage) > folio_unlock(eb->folios[0]); > percpu_counter_add_batch(&eb->fs_info->dirty_metadata_bytes, > - eb->len, > - eb->fs_info->dirty_metadata_batch); > + eb_len(eb), > + eb->fs_info->dirty_metadata_batch); > } > #ifdef CONFIG_BTRFS_DEBUG > for (int i = 0; i < num_extent_folios(eb); i++) > @@ -3670,7 +3667,7 @@ int read_extent_buffer_pages_nowait(struct extent_buffer *eb, int mirror_num, > struct folio *folio = eb->folios[i]; > u64 range_start = max_t(u64, eb->start, folio_pos(folio)); > u32 range_len = min_t(u64, folio_pos(folio) + folio_size(folio), > - eb->start + eb->len) - range_start; > + eb->start + eb_len(eb)) - range_start; > > bio_add_folio_nofail(&bbio->bio, folio, range_len, > offset_in_folio(folio, range_start)); > @@ -3698,8 +3695,8 @@ static bool report_eb_range(const struct extent_buffer *eb, unsigned long start, > unsigned long len) > { > btrfs_warn(eb->fs_info, > - "access to eb bytenr %llu len %u out of range start %lu len %lu", > - eb->start, eb->len, start, len); > + "access to eb bytenr %llu out of range start %lu len %lu", > + eb->start, start, len); > DEBUG_WARN(); > > return true; > @@ -3717,8 +3714,8 @@ static inline int check_eb_range(const struct extent_buffer *eb, > { > unsigned long offset; > > - /* start, start + len should not go beyond eb->len nor overflow */ > - if (unlikely(check_add_overflow(start, len, &offset) || offset > eb->len)) > + /* start, start + len should not go beyond nodesize nor overflow */ > + if (unlikely(check_add_overflow(start, len, &offset) || offset > eb_len(eb))) > return report_eb_range(eb, start, len); > > return false; > @@ -3774,8 +3771,8 @@ int read_extent_buffer_to_user_nofault(const struct extent_buffer *eb, > unsigned long i = get_eb_folio_index(eb, start); > int ret = 0; > > - WARN_ON(start > eb->len); > - WARN_ON(start + len > eb->start + eb->len); > + WARN_ON(start > eb_len(eb)); > + WARN_ON(start + len > eb->start + eb_len(eb)); > > if (eb->addr) { > if (copy_to_user_nofault(dstv, eb->addr + start, len)) > @@ -3866,8 +3863,8 @@ static void assert_eb_folio_uptodate(const struct extent_buffer *eb, int i) > folio = eb->folios[0]; > ASSERT(i == 0); > if (WARN_ON(!btrfs_subpage_test_uptodate(fs_info, folio, > - eb->start, eb->len))) > - btrfs_subpage_dump_bitmap(fs_info, folio, eb->start, eb->len); > + eb->start, fs_info->nodesize))) > + btrfs_subpage_dump_bitmap(fs_info, folio, eb->start, fs_info->nodesize); > } else { > WARN_ON(!folio_test_uptodate(folio)); > } > @@ -3960,12 +3957,10 @@ void copy_extent_buffer_full(const struct extent_buffer *dst, > const int unit_size = src->folio_size; > unsigned long cur = 0; > > - ASSERT(dst->len == src->len); > - > - while (cur < src->len) { > + while (cur < eb_len(src)) { > unsigned long index = get_eb_folio_index(src, cur); > unsigned long offset = get_eb_offset_in_folio(src, cur); > - unsigned long cur_len = min(src->len, unit_size - offset); > + unsigned long cur_len = min(eb_len(src), unit_size - offset); > void *addr = folio_address(src->folios[index]) + offset; > > write_extent_buffer(dst, addr, cur, cur_len); > @@ -3980,7 +3975,6 @@ void copy_extent_buffer(const struct extent_buffer *dst, > unsigned long len) > { > const int unit_size = dst->folio_size; > - u64 dst_len = dst->len; > size_t cur; > size_t offset; > char *kaddr; > @@ -3990,8 +3984,6 @@ void copy_extent_buffer(const struct extent_buffer *dst, > check_eb_range(src, src_offset, len)) > return; > > - WARN_ON(src->len != dst_len); > - > offset = get_eb_offset_in_folio(dst, dst_offset); > > while (len > 0) { > @@ -4266,7 +4258,7 @@ static int try_release_subpage_extent_buffer(struct folio *folio) > xa_unlock_irq(&fs_info->buffer_tree); > break; > } > - cur = eb->start + eb->len; > + cur = eb->start + fs_info->nodesize; > > /* > * The same as try_release_extent_buffer(), to ensure the eb > diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h > index 1415679d7f88c..9a842eea47d6d 100644 > --- a/fs/btrfs/extent_io.h > +++ b/fs/btrfs/extent_io.h > @@ -16,6 +16,7 @@ > #include "messages.h" > #include "ulist.h" > #include "misc.h" > +#include "fs.h" > > struct page; > struct file; > @@ -80,7 +81,6 @@ void __cold extent_buffer_free_cachep(void); > #define INLINE_EXTENT_BUFFER_PAGES (BTRFS_MAX_METADATA_BLOCKSIZE / PAGE_SIZE) > struct extent_buffer { > u64 start; > - u32 len; > u32 folio_size; > unsigned long bflags; > struct btrfs_fs_info *fs_info; > @@ -263,17 +263,22 @@ void btrfs_readahead_tree_block(struct btrfs_fs_info *fs_info, > u64 bytenr, u64 owner_root, u64 gen, int level); > void btrfs_readahead_node_child(struct extent_buffer *node, int slot); > > +static inline u32 eb_len(const struct extent_buffer *eb) > +{ > + return eb->fs_info->nodesize; > +} Please always add a "btrfs_" prefix to the name of exported functions. In this case I don't think adding this helper adds any value. We can just do eb->fs_info->nodesize everywhere and in some places we already have fs_info in a local variable and can just do fs_info->nodesize. Thanks. > + > /* Note: this can be used in for loops without caching the value in a variable. */ > static inline int __pure num_extent_pages(const struct extent_buffer *eb) > { > /* > * For sectorsize == PAGE_SIZE case, since nodesize is always aligned to > - * sectorsize, it's just eb->len >> PAGE_SHIFT. > + * sectorsize, it's just nodesize >> PAGE_SHIFT. > * > * For sectorsize < PAGE_SIZE case, we could have nodesize < PAGE_SIZE, > * thus have to ensure we get at least one page. > */ > - return (eb->len >> PAGE_SHIFT) ?: 1; > + return (eb_len(eb) >> PAGE_SHIFT) ?: 1; > } > > /* > diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c > index 68fac77fb95d1..6be2d56d44917 100644 > --- a/fs/btrfs/ioctl.c > +++ b/fs/btrfs/ioctl.c > @@ -598,7 +598,7 @@ static noinline int create_subvol(struct mnt_idmap *idmap, > btrfs_set_root_generation(root_item, trans->transid); > btrfs_set_root_level(root_item, 0); > btrfs_set_root_refs(root_item, 1); > - btrfs_set_root_used(root_item, leaf->len); > + btrfs_set_root_used(root_item, fs_info->nodesize); > btrfs_set_root_last_snapshot(root_item, 0); > > btrfs_set_root_generation_v2(root_item, > diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c > index 6287e71ebad5f..5086485a4ae21 100644 > --- a/fs/btrfs/relocation.c > +++ b/fs/btrfs/relocation.c > @@ -4352,7 +4352,7 @@ int btrfs_reloc_cow_block(struct btrfs_trans_handle *trans, > mark_block_processed(rc, node); > > if (first_cow && level > 0) > - rc->nodes_relocated += buf->len; > + rc->nodes_relocated += fs_info->nodesize; > } > > if (level == 0 && first_cow && rc->stage == UPDATE_DATA_PTRS) > diff --git a/fs/btrfs/subpage.c b/fs/btrfs/subpage.c > index d4f0192334936..711792f32e9ce 100644 > --- a/fs/btrfs/subpage.c > +++ b/fs/btrfs/subpage.c > @@ -631,7 +631,7 @@ void btrfs_meta_folio_set_##name(struct folio *folio, const struct extent_buffer > folio_set_func(folio); \ > return; \ > } \ > - btrfs_subpage_set_##name(eb->fs_info, folio, eb->start, eb->len); \ > + btrfs_subpage_set_##name(eb->fs_info, folio, eb->start, eb_len(eb)); \ > } \ > void btrfs_meta_folio_clear_##name(struct folio *folio, const struct extent_buffer *eb) \ > { \ > @@ -639,13 +639,13 @@ void btrfs_meta_folio_clear_##name(struct folio *folio, const struct extent_buff > folio_clear_func(folio); \ > return; \ > } \ > - btrfs_subpage_clear_##name(eb->fs_info, folio, eb->start, eb->len); \ > + btrfs_subpage_clear_##name(eb->fs_info, folio, eb->start, eb_len(eb)); \ > } \ > bool btrfs_meta_folio_test_##name(struct folio *folio, const struct extent_buffer *eb) \ > { \ > if (!btrfs_meta_is_subpage(eb->fs_info)) \ > return folio_test_func(folio); \ > - return btrfs_subpage_test_##name(eb->fs_info, folio, eb->start, eb->len); \ > + return btrfs_subpage_test_##name(eb->fs_info, folio, eb->start, eb_len(eb)); \ > } > IMPLEMENT_BTRFS_PAGE_OPS(uptodate, folio_mark_uptodate, folio_clear_uptodate, > folio_test_uptodate); > @@ -765,7 +765,7 @@ bool btrfs_meta_folio_clear_and_test_dirty(struct folio *folio, const struct ext > return true; > } > > - last = btrfs_subpage_clear_and_test_dirty(eb->fs_info, folio, eb->start, eb->len); > + last = btrfs_subpage_clear_and_test_dirty(eb->fs_info, folio, eb->start, eb_len(eb)); > if (last) { > folio_clear_dirty_for_io(folio); > return true; > diff --git a/fs/btrfs/tests/extent-io-tests.c b/fs/btrfs/tests/extent-io-tests.c > index 00da54f0164c9..657f8f1d9263e 100644 > --- a/fs/btrfs/tests/extent-io-tests.c > +++ b/fs/btrfs/tests/extent-io-tests.c > @@ -342,7 +342,7 @@ static int check_eb_bitmap(unsigned long *bitmap, struct extent_buffer *eb) > { > unsigned long i; > > - for (i = 0; i < eb->len * BITS_PER_BYTE; i++) { > + for (i = 0; i < eb_len(eb) * BITS_PER_BYTE; i++) { > int bit, bit1; > > bit = !!test_bit(i, bitmap); > @@ -411,7 +411,7 @@ static int test_bitmap_clear(const char *name, unsigned long *bitmap, > static int __test_eb_bitmaps(unsigned long *bitmap, struct extent_buffer *eb) > { > unsigned long i, j; > - unsigned long byte_len = eb->len; > + unsigned long byte_len = eb_len(eb); > u32 x; > int ret; > > @@ -670,7 +670,7 @@ static int test_find_first_clear_extent_bit(void) > static void dump_eb_and_memory_contents(struct extent_buffer *eb, void *memory, > const char *test_name) > { > - for (int i = 0; i < eb->len; i++) { > + for (int i = 0; i < eb_len(eb); i++) { > struct page *page = folio_page(eb->folios[i >> PAGE_SHIFT], 0); > void *addr = page_address(page) + offset_in_page(i); > > @@ -686,7 +686,7 @@ static void dump_eb_and_memory_contents(struct extent_buffer *eb, void *memory, > static int verify_eb_and_memory(struct extent_buffer *eb, void *memory, > const char *test_name) > { > - for (int i = 0; i < (eb->len >> PAGE_SHIFT); i++) { > + for (int i = 0; i < (eb_len(eb) >> PAGE_SHIFT); i++) { > void *eb_addr = folio_address(eb->folios[i]); > > if (memcmp(memory + (i << PAGE_SHIFT), eb_addr, PAGE_SIZE) != 0) { > @@ -703,8 +703,8 @@ static int verify_eb_and_memory(struct extent_buffer *eb, void *memory, > */ > static void init_eb_and_memory(struct extent_buffer *eb, void *memory) > { > - get_random_bytes(memory, eb->len); > - write_extent_buffer(eb, memory, 0, eb->len); > + get_random_bytes(memory, eb_len(eb)); > + write_extent_buffer(eb, memory, 0, eb_len(eb)); > } > > static int test_eb_mem_ops(u32 sectorsize, u32 nodesize) > diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c > index 9d42bf2bfd746..c7a8cdd87c509 100644 > --- a/fs/btrfs/zoned.c > +++ b/fs/btrfs/zoned.c > @@ -2422,7 +2422,7 @@ void btrfs_schedule_zone_finish_bg(struct btrfs_block_group *bg, > struct extent_buffer *eb) > { > if (!test_bit(BLOCK_GROUP_FLAG_SEQUENTIAL_ZONE, &bg->runtime_flags) || > - eb->start + eb->len * 2 <= bg->start + bg->zone_capacity) > + eb->start + eb_len(eb) * 2 <= bg->start + bg->zone_capacity) > return; > > if (WARN_ON(bg->zone_finish_work.func == btrfs_zone_finish_endio_workfn)) { > -- > 2.47.2 > > ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH] btrfs: remove extent buffer's redundant `len` member field 2025-04-30 8:05 ` Filipe Manana @ 2025-04-30 8:26 ` Daniel Vacek 2025-04-30 8:34 ` Filipe Manana 0 siblings, 1 reply; 35+ messages in thread From: Daniel Vacek @ 2025-04-30 8:26 UTC (permalink / raw) To: Filipe Manana Cc: Chris Mason, Josef Bacik, David Sterba, linux-btrfs, linux-kernel On Wed, 30 Apr 2025 at 10:06, Filipe Manana <fdmanana@kernel.org> wrote: > > On Tue, Apr 29, 2025 at 4:19 PM Daniel Vacek <neelx@suse.com> wrote: > > > > Even super block nowadays uses nodesize for eb->len. This is since commits > > > > 551561c34663 ("btrfs: don't pass nodesize to __alloc_extent_buffer()") > > da17066c4047 ("btrfs: pull node/sector/stripe sizes out of root and into fs_info") > > ce3e69847e3e ("btrfs: sink parameter len to alloc_extent_buffer") > > a83fffb75d09 ("btrfs: sink blocksize parameter to btrfs_find_create_tree_block") > > > > With these the eb->len is not really useful anymore. Let's use the nodesize > > directly where applicable. > > > > Signed-off-by: Daniel Vacek <neelx@suse.com> > > --- > > [RFC] > > * Shall the eb_len() helper better be called eb_nodesize()? Or even rather > > opencoded and not used at all? > > > > fs/btrfs/accessors.c | 4 +-- > > fs/btrfs/disk-io.c | 11 ++++--- > > fs/btrfs/extent-tree.c | 28 +++++++++-------- > > fs/btrfs/extent_io.c | 54 ++++++++++++++------------------ > > fs/btrfs/extent_io.h | 11 +++++-- > > fs/btrfs/ioctl.c | 2 +- > > fs/btrfs/relocation.c | 2 +- > > fs/btrfs/subpage.c | 8 ++--- > > fs/btrfs/tests/extent-io-tests.c | 12 +++---- > > fs/btrfs/zoned.c | 2 +- > > 10 files changed, 67 insertions(+), 67 deletions(-) > > > > diff --git a/fs/btrfs/accessors.c b/fs/btrfs/accessors.c > > index e3716516ca387..a2bdbc7990906 100644 > > --- a/fs/btrfs/accessors.c > > +++ b/fs/btrfs/accessors.c > > @@ -14,10 +14,10 @@ static bool check_setget_bounds(const struct extent_buffer *eb, > > { > > const unsigned long member_offset = (unsigned long)ptr + off; > > > > - if (unlikely(member_offset + size > eb->len)) { > > + if (unlikely(member_offset + size > eb_len(eb))) { > > btrfs_warn(eb->fs_info, > > "bad eb member %s: ptr 0x%lx start %llu member offset %lu size %d", > > - (member_offset > eb->len ? "start" : "end"), > > + (member_offset > eb_len(eb) ? "start" : "end"), > > (unsigned long)ptr, eb->start, member_offset, size); > > return false; > > } > > diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c > > index 3592300ae3e2e..31eb7419fe11f 100644 > > --- a/fs/btrfs/disk-io.c > > +++ b/fs/btrfs/disk-io.c > > @@ -190,7 +190,7 @@ static int btrfs_repair_eb_io_failure(const struct extent_buffer *eb, > > for (int i = 0; i < num_extent_folios(eb); i++) { > > struct folio *folio = eb->folios[i]; > > u64 start = max_t(u64, eb->start, folio_pos(folio)); > > - u64 end = min_t(u64, eb->start + eb->len, > > + u64 end = min_t(u64, eb->start + fs_info->nodesize, > > folio_pos(folio) + eb->folio_size); > > u32 len = end - start; > > phys_addr_t paddr = PFN_PHYS(folio_pfn(folio)) + > > @@ -230,7 +230,7 @@ int btrfs_read_extent_buffer(struct extent_buffer *eb, > > break; > > > > num_copies = btrfs_num_copies(fs_info, > > - eb->start, eb->len); > > + eb->start, fs_info->nodesize); > > if (num_copies == 1) > > break; > > > > @@ -260,6 +260,7 @@ blk_status_t btree_csum_one_bio(struct btrfs_bio *bbio) > > { > > struct extent_buffer *eb = bbio->private; > > struct btrfs_fs_info *fs_info = eb->fs_info; > > + u32 nodesize = fs_info->nodesize; > > u64 found_start = btrfs_header_bytenr(eb); > > u64 last_trans; > > u8 result[BTRFS_CSUM_SIZE]; > > @@ -268,7 +269,7 @@ blk_status_t btree_csum_one_bio(struct btrfs_bio *bbio) > > /* Btree blocks are always contiguous on disk. */ > > if (WARN_ON_ONCE(bbio->file_offset != eb->start)) > > return BLK_STS_IOERR; > > - if (WARN_ON_ONCE(bbio->bio.bi_iter.bi_size != eb->len)) > > + if (WARN_ON_ONCE(bbio->bio.bi_iter.bi_size != nodesize)) > > return BLK_STS_IOERR; > > > > /* > > @@ -277,7 +278,7 @@ blk_status_t btree_csum_one_bio(struct btrfs_bio *bbio) > > * ordering of I/O without unnecessarily writing out data. > > */ > > if (test_bit(EXTENT_BUFFER_ZONED_ZEROOUT, &eb->bflags)) { > > - memzero_extent_buffer(eb, 0, eb->len); > > + memzero_extent_buffer(eb, 0, nodesize); > > return BLK_STS_OK; > > } > > > > @@ -883,7 +884,7 @@ struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans, > > btrfs_set_root_generation(&root->root_item, trans->transid); > > btrfs_set_root_level(&root->root_item, 0); > > btrfs_set_root_refs(&root->root_item, 1); > > - btrfs_set_root_used(&root->root_item, leaf->len); > > + btrfs_set_root_used(&root->root_item, fs_info->nodesize); > > btrfs_set_root_last_snapshot(&root->root_item, 0); > > btrfs_set_root_dirid(&root->root_item, 0); > > if (is_fstree(objectid)) > > diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c > > index e0811a86d0cbd..25560a162d93e 100644 > > --- a/fs/btrfs/extent-tree.c > > +++ b/fs/btrfs/extent-tree.c > > @@ -2211,7 +2211,7 @@ int btrfs_set_disk_extent_flags(struct btrfs_trans_handle *trans, > > extent_op->update_flags = true; > > extent_op->update_key = false; > > > > - ret = btrfs_add_delayed_extent_op(trans, eb->start, eb->len, > > + ret = btrfs_add_delayed_extent_op(trans, eb->start, eb_len(eb), > > btrfs_header_level(eb), extent_op); > > if (ret) > > btrfs_free_delayed_extent_op(extent_op); > > @@ -2660,10 +2660,10 @@ int btrfs_pin_extent_for_log_replay(struct btrfs_trans_handle *trans, > > if (ret) > > goto out; > > > > - pin_down_extent(trans, cache, eb->start, eb->len, 0); > > + pin_down_extent(trans, cache, eb->start, eb_len(eb), 0); > > > > /* remove us from the free space cache (if we're there at all) */ > > - ret = btrfs_remove_free_space(cache, eb->start, eb->len); > > + ret = btrfs_remove_free_space(cache, eb->start, eb_len(eb)); > > out: > > btrfs_put_block_group(cache); > > return ret; > > @@ -3436,13 +3436,14 @@ int btrfs_free_tree_block(struct btrfs_trans_handle *trans, > > { > > struct btrfs_fs_info *fs_info = trans->fs_info; > > struct btrfs_block_group *bg; > > + u32 nodesize = fs_info->nodesize; > > int ret; > > > > if (root_id != BTRFS_TREE_LOG_OBJECTID) { > > struct btrfs_ref generic_ref = { > > .action = BTRFS_DROP_DELAYED_REF, > > .bytenr = buf->start, > > - .num_bytes = buf->len, > > + .num_bytes = nodesize, > > .parent = parent, > > .owning_root = btrfs_header_owner(buf), > > .ref_root = root_id, > > @@ -3478,7 +3479,7 @@ int btrfs_free_tree_block(struct btrfs_trans_handle *trans, > > bg = btrfs_lookup_block_group(fs_info, buf->start); > > > > if (btrfs_header_flag(buf, BTRFS_HEADER_FLAG_WRITTEN)) { > > - pin_down_extent(trans, bg, buf->start, buf->len, 1); > > + pin_down_extent(trans, bg, buf->start, nodesize, 1); > > btrfs_put_block_group(bg); > > goto out; > > } > > @@ -3502,17 +3503,17 @@ int btrfs_free_tree_block(struct btrfs_trans_handle *trans, > > > > if (test_bit(BTRFS_FS_TREE_MOD_LOG_USERS, &fs_info->flags) > > || btrfs_is_zoned(fs_info)) { > > - pin_down_extent(trans, bg, buf->start, buf->len, 1); > > + pin_down_extent(trans, bg, buf->start, nodesize, 1); > > btrfs_put_block_group(bg); > > goto out; > > } > > > > WARN_ON(test_bit(EXTENT_BUFFER_DIRTY, &buf->bflags)); > > > > - btrfs_add_free_space(bg, buf->start, buf->len); > > - btrfs_free_reserved_bytes(bg, buf->len, 0); > > + btrfs_add_free_space(bg, buf->start, nodesize); > > + btrfs_free_reserved_bytes(bg, nodesize, 0); > > btrfs_put_block_group(bg); > > - trace_btrfs_reserved_extent_free(fs_info, buf->start, buf->len); > > + trace_btrfs_reserved_extent_free(fs_info, buf->start, nodesize); > > > > out: > > return 0; > > @@ -4768,7 +4769,7 @@ int btrfs_pin_reserved_extent(struct btrfs_trans_handle *trans, > > return -ENOSPC; > > } > > > > - ret = pin_down_extent(trans, cache, eb->start, eb->len, 1); > > + ret = pin_down_extent(trans, cache, eb->start, eb_len(eb), 1); > > btrfs_put_block_group(cache); > > return ret; > > } > > @@ -5050,6 +5051,7 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root, > > struct btrfs_fs_info *fs_info = root->fs_info; > > struct extent_buffer *buf; > > u64 lockdep_owner = owner; > > + u32 nodesize = fs_info->nodesize; > > > > buf = btrfs_find_create_tree_block(fs_info, bytenr, owner, level); > > if (IS_ERR(buf)) > > @@ -5107,16 +5109,16 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root, > > */ > > if (buf->log_index == 0) > > btrfs_set_extent_bit(&root->dirty_log_pages, buf->start, > > - buf->start + buf->len - 1, > > + buf->start + nodesize - 1, > > EXTENT_DIRTY, NULL); > > else > > btrfs_set_extent_bit(&root->dirty_log_pages, buf->start, > > - buf->start + buf->len - 1, > > + buf->start + nodesize - 1, > > EXTENT_NEW, NULL); > > } else { > > buf->log_index = -1; > > btrfs_set_extent_bit(&trans->transaction->dirty_pages, buf->start, > > - buf->start + buf->len - 1, EXTENT_DIRTY, NULL); > > + buf->start + nodesize - 1, EXTENT_DIRTY, NULL); > > } > > /* this returns a buffer locked for blocking */ > > return buf; > > diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c > > index 20cdddd924852..e4050fd5db285 100644 > > --- a/fs/btrfs/extent_io.c > > +++ b/fs/btrfs/extent_io.c > > @@ -76,8 +76,8 @@ void btrfs_extent_buffer_leak_debug_check(struct btrfs_fs_info *fs_info) > > eb = list_first_entry(&fs_info->allocated_ebs, > > struct extent_buffer, leak_list); > > pr_err( > > - "BTRFS: buffer leak start %llu len %u refs %d bflags %lu owner %llu\n", > > - eb->start, eb->len, atomic_read(&eb->refs), eb->bflags, > > + "BTRFS: buffer leak start %llu refs %d bflags %lu owner %llu\n", > > + eb->start, atomic_read(&eb->refs), eb->bflags, > > btrfs_header_owner(eb)); > > list_del(&eb->leak_list); > > WARN_ON_ONCE(1); > > @@ -1746,8 +1746,8 @@ static noinline_for_stack bool lock_extent_buffer_for_io(struct extent_buffer *e > > > > btrfs_set_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN); > > percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, > > - -eb->len, > > - fs_info->dirty_metadata_batch); > > + -fs_info->nodesize, > > + fs_info->dirty_metadata_batch); > > ret = true; > > } else { > > spin_unlock(&eb->refs_lock); > > @@ -1953,7 +1953,7 @@ static unsigned int buffer_tree_get_ebs_tag(struct btrfs_fs_info *fs_info, > > rcu_read_lock(); > > while ((eb = find_get_eb(&xas, end, tag)) != NULL) { > > if (!eb_batch_add(batch, eb)) { > > - *start = (eb->start + eb->len) >> fs_info->sectorsize_bits; > > + *start = (eb->start + fs_info->nodesize) >> fs_info->sectorsize_bits; > > goto out; > > } > > } > > @@ -2020,7 +2020,7 @@ static void prepare_eb_write(struct extent_buffer *eb) > > nritems = btrfs_header_nritems(eb); > > if (btrfs_header_level(eb) > 0) { > > end = btrfs_node_key_ptr_offset(eb, nritems); > > - memzero_extent_buffer(eb, end, eb->len - end); > > + memzero_extent_buffer(eb, end, eb_len(eb) - end); > > } else { > > /* > > * Leaf: > > @@ -2056,7 +2056,7 @@ static noinline_for_stack void write_one_eb(struct extent_buffer *eb, > > struct folio *folio = eb->folios[i]; > > u64 range_start = max_t(u64, eb->start, folio_pos(folio)); > > u32 range_len = min_t(u64, folio_pos(folio) + folio_size(folio), > > - eb->start + eb->len) - range_start; > > + eb->start + fs_info->nodesize) - range_start; > > > > folio_lock(folio); > > btrfs_meta_folio_clear_dirty(folio, eb); > > @@ -2171,7 +2171,7 @@ int btree_write_cache_pages(struct address_space *mapping, > > if (ctx.zoned_bg) { > > /* Mark the last eb in the block group. */ > > btrfs_schedule_zone_finish_bg(ctx.zoned_bg, eb); > > - ctx.zoned_bg->meta_write_pointer += eb->len; > > + ctx.zoned_bg->meta_write_pointer += fs_info->nodesize; > > } > > write_one_eb(eb, wbc); > > } > > @@ -2807,7 +2807,6 @@ static struct extent_buffer *__alloc_extent_buffer(struct btrfs_fs_info *fs_info > > > > eb = kmem_cache_zalloc(extent_buffer_cache, GFP_NOFS|__GFP_NOFAIL); > > eb->start = start; > > - eb->len = fs_info->nodesize; > > eb->fs_info = fs_info; > > init_rwsem(&eb->lock); > > > > @@ -2816,8 +2815,6 @@ static struct extent_buffer *__alloc_extent_buffer(struct btrfs_fs_info *fs_info > > spin_lock_init(&eb->refs_lock); > > atomic_set(&eb->refs, 1); > > > > - ASSERT(eb->len <= BTRFS_MAX_METADATA_BLOCKSIZE); > > - > > return eb; > > } > > > > @@ -3505,7 +3502,7 @@ void btrfs_clear_buffer_dirty(struct btrfs_trans_handle *trans, > > return; > > > > buffer_tree_clear_mark(eb, PAGECACHE_TAG_DIRTY); > > - percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, -eb->len, > > + percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, -fs_info->nodesize, > > fs_info->dirty_metadata_batch); > > > > for (int i = 0; i < num_extent_folios(eb); i++) { > > @@ -3557,8 +3554,8 @@ void set_extent_buffer_dirty(struct extent_buffer *eb) > > if (subpage) > > folio_unlock(eb->folios[0]); > > percpu_counter_add_batch(&eb->fs_info->dirty_metadata_bytes, > > - eb->len, > > - eb->fs_info->dirty_metadata_batch); > > + eb_len(eb), > > + eb->fs_info->dirty_metadata_batch); > > } > > #ifdef CONFIG_BTRFS_DEBUG > > for (int i = 0; i < num_extent_folios(eb); i++) > > @@ -3670,7 +3667,7 @@ int read_extent_buffer_pages_nowait(struct extent_buffer *eb, int mirror_num, > > struct folio *folio = eb->folios[i]; > > u64 range_start = max_t(u64, eb->start, folio_pos(folio)); > > u32 range_len = min_t(u64, folio_pos(folio) + folio_size(folio), > > - eb->start + eb->len) - range_start; > > + eb->start + eb_len(eb)) - range_start; > > > > bio_add_folio_nofail(&bbio->bio, folio, range_len, > > offset_in_folio(folio, range_start)); > > @@ -3698,8 +3695,8 @@ static bool report_eb_range(const struct extent_buffer *eb, unsigned long start, > > unsigned long len) > > { > > btrfs_warn(eb->fs_info, > > - "access to eb bytenr %llu len %u out of range start %lu len %lu", > > - eb->start, eb->len, start, len); > > + "access to eb bytenr %llu out of range start %lu len %lu", > > + eb->start, start, len); > > DEBUG_WARN(); > > > > return true; > > @@ -3717,8 +3714,8 @@ static inline int check_eb_range(const struct extent_buffer *eb, > > { > > unsigned long offset; > > > > - /* start, start + len should not go beyond eb->len nor overflow */ > > - if (unlikely(check_add_overflow(start, len, &offset) || offset > eb->len)) > > + /* start, start + len should not go beyond nodesize nor overflow */ > > + if (unlikely(check_add_overflow(start, len, &offset) || offset > eb_len(eb))) > > return report_eb_range(eb, start, len); > > > > return false; > > @@ -3774,8 +3771,8 @@ int read_extent_buffer_to_user_nofault(const struct extent_buffer *eb, > > unsigned long i = get_eb_folio_index(eb, start); > > int ret = 0; > > > > - WARN_ON(start > eb->len); > > - WARN_ON(start + len > eb->start + eb->len); > > + WARN_ON(start > eb_len(eb)); > > + WARN_ON(start + len > eb->start + eb_len(eb)); > > > > if (eb->addr) { > > if (copy_to_user_nofault(dstv, eb->addr + start, len)) > > @@ -3866,8 +3863,8 @@ static void assert_eb_folio_uptodate(const struct extent_buffer *eb, int i) > > folio = eb->folios[0]; > > ASSERT(i == 0); > > if (WARN_ON(!btrfs_subpage_test_uptodate(fs_info, folio, > > - eb->start, eb->len))) > > - btrfs_subpage_dump_bitmap(fs_info, folio, eb->start, eb->len); > > + eb->start, fs_info->nodesize))) > > + btrfs_subpage_dump_bitmap(fs_info, folio, eb->start, fs_info->nodesize); > > } else { > > WARN_ON(!folio_test_uptodate(folio)); > > } > > @@ -3960,12 +3957,10 @@ void copy_extent_buffer_full(const struct extent_buffer *dst, > > const int unit_size = src->folio_size; > > unsigned long cur = 0; > > > > - ASSERT(dst->len == src->len); > > - > > - while (cur < src->len) { > > + while (cur < eb_len(src)) { > > unsigned long index = get_eb_folio_index(src, cur); > > unsigned long offset = get_eb_offset_in_folio(src, cur); > > - unsigned long cur_len = min(src->len, unit_size - offset); > > + unsigned long cur_len = min(eb_len(src), unit_size - offset); > > void *addr = folio_address(src->folios[index]) + offset; > > > > write_extent_buffer(dst, addr, cur, cur_len); > > @@ -3980,7 +3975,6 @@ void copy_extent_buffer(const struct extent_buffer *dst, > > unsigned long len) > > { > > const int unit_size = dst->folio_size; > > - u64 dst_len = dst->len; > > size_t cur; > > size_t offset; > > char *kaddr; > > @@ -3990,8 +3984,6 @@ void copy_extent_buffer(const struct extent_buffer *dst, > > check_eb_range(src, src_offset, len)) > > return; > > > > - WARN_ON(src->len != dst_len); > > - > > offset = get_eb_offset_in_folio(dst, dst_offset); > > > > while (len > 0) { > > @@ -4266,7 +4258,7 @@ static int try_release_subpage_extent_buffer(struct folio *folio) > > xa_unlock_irq(&fs_info->buffer_tree); > > break; > > } > > - cur = eb->start + eb->len; > > + cur = eb->start + fs_info->nodesize; > > > > /* > > * The same as try_release_extent_buffer(), to ensure the eb > > diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h > > index 1415679d7f88c..9a842eea47d6d 100644 > > --- a/fs/btrfs/extent_io.h > > +++ b/fs/btrfs/extent_io.h > > @@ -16,6 +16,7 @@ > > #include "messages.h" > > #include "ulist.h" > > #include "misc.h" > > +#include "fs.h" > > > > struct page; > > struct file; > > @@ -80,7 +81,6 @@ void __cold extent_buffer_free_cachep(void); > > #define INLINE_EXTENT_BUFFER_PAGES (BTRFS_MAX_METADATA_BLOCKSIZE / PAGE_SIZE) > > struct extent_buffer { > > u64 start; > > - u32 len; > > u32 folio_size; > > unsigned long bflags; > > struct btrfs_fs_info *fs_info; > > @@ -263,17 +263,22 @@ void btrfs_readahead_tree_block(struct btrfs_fs_info *fs_info, > > u64 bytenr, u64 owner_root, u64 gen, int level); > > void btrfs_readahead_node_child(struct extent_buffer *node, int slot); > > > > +static inline u32 eb_len(const struct extent_buffer *eb) > > +{ > > + return eb->fs_info->nodesize; > > +} > > Please always add a "btrfs_" prefix to the name of exported functions. It's static inline, not exported. But I'm happy just opencoding it instead. Thanks. > In this case I don't think adding this helper adds any value. > We can just do eb->fs_info->nodesize everywhere and in some places we > already have fs_info in a local variable and can just do > fs_info->nodesize. > > Thanks. > > > + > > /* Note: this can be used in for loops without caching the value in a variable. */ > > static inline int __pure num_extent_pages(const struct extent_buffer *eb) > > { > > /* > > * For sectorsize == PAGE_SIZE case, since nodesize is always aligned to > > - * sectorsize, it's just eb->len >> PAGE_SHIFT. > > + * sectorsize, it's just nodesize >> PAGE_SHIFT. > > * > > * For sectorsize < PAGE_SIZE case, we could have nodesize < PAGE_SIZE, > > * thus have to ensure we get at least one page. > > */ > > - return (eb->len >> PAGE_SHIFT) ?: 1; > > + return (eb_len(eb) >> PAGE_SHIFT) ?: 1; > > } > > > > /* > > diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c > > index 68fac77fb95d1..6be2d56d44917 100644 > > --- a/fs/btrfs/ioctl.c > > +++ b/fs/btrfs/ioctl.c > > @@ -598,7 +598,7 @@ static noinline int create_subvol(struct mnt_idmap *idmap, > > btrfs_set_root_generation(root_item, trans->transid); > > btrfs_set_root_level(root_item, 0); > > btrfs_set_root_refs(root_item, 1); > > - btrfs_set_root_used(root_item, leaf->len); > > + btrfs_set_root_used(root_item, fs_info->nodesize); > > btrfs_set_root_last_snapshot(root_item, 0); > > > > btrfs_set_root_generation_v2(root_item, > > diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c > > index 6287e71ebad5f..5086485a4ae21 100644 > > --- a/fs/btrfs/relocation.c > > +++ b/fs/btrfs/relocation.c > > @@ -4352,7 +4352,7 @@ int btrfs_reloc_cow_block(struct btrfs_trans_handle *trans, > > mark_block_processed(rc, node); > > > > if (first_cow && level > 0) > > - rc->nodes_relocated += buf->len; > > + rc->nodes_relocated += fs_info->nodesize; > > } > > > > if (level == 0 && first_cow && rc->stage == UPDATE_DATA_PTRS) > > diff --git a/fs/btrfs/subpage.c b/fs/btrfs/subpage.c > > index d4f0192334936..711792f32e9ce 100644 > > --- a/fs/btrfs/subpage.c > > +++ b/fs/btrfs/subpage.c > > @@ -631,7 +631,7 @@ void btrfs_meta_folio_set_##name(struct folio *folio, const struct extent_buffer > > folio_set_func(folio); \ > > return; \ > > } \ > > - btrfs_subpage_set_##name(eb->fs_info, folio, eb->start, eb->len); \ > > + btrfs_subpage_set_##name(eb->fs_info, folio, eb->start, eb_len(eb)); \ > > } \ > > void btrfs_meta_folio_clear_##name(struct folio *folio, const struct extent_buffer *eb) \ > > { \ > > @@ -639,13 +639,13 @@ void btrfs_meta_folio_clear_##name(struct folio *folio, const struct extent_buff > > folio_clear_func(folio); \ > > return; \ > > } \ > > - btrfs_subpage_clear_##name(eb->fs_info, folio, eb->start, eb->len); \ > > + btrfs_subpage_clear_##name(eb->fs_info, folio, eb->start, eb_len(eb)); \ > > } \ > > bool btrfs_meta_folio_test_##name(struct folio *folio, const struct extent_buffer *eb) \ > > { \ > > if (!btrfs_meta_is_subpage(eb->fs_info)) \ > > return folio_test_func(folio); \ > > - return btrfs_subpage_test_##name(eb->fs_info, folio, eb->start, eb->len); \ > > + return btrfs_subpage_test_##name(eb->fs_info, folio, eb->start, eb_len(eb)); \ > > } > > IMPLEMENT_BTRFS_PAGE_OPS(uptodate, folio_mark_uptodate, folio_clear_uptodate, > > folio_test_uptodate); > > @@ -765,7 +765,7 @@ bool btrfs_meta_folio_clear_and_test_dirty(struct folio *folio, const struct ext > > return true; > > } > > > > - last = btrfs_subpage_clear_and_test_dirty(eb->fs_info, folio, eb->start, eb->len); > > + last = btrfs_subpage_clear_and_test_dirty(eb->fs_info, folio, eb->start, eb_len(eb)); > > if (last) { > > folio_clear_dirty_for_io(folio); > > return true; > > diff --git a/fs/btrfs/tests/extent-io-tests.c b/fs/btrfs/tests/extent-io-tests.c > > index 00da54f0164c9..657f8f1d9263e 100644 > > --- a/fs/btrfs/tests/extent-io-tests.c > > +++ b/fs/btrfs/tests/extent-io-tests.c > > @@ -342,7 +342,7 @@ static int check_eb_bitmap(unsigned long *bitmap, struct extent_buffer *eb) > > { > > unsigned long i; > > > > - for (i = 0; i < eb->len * BITS_PER_BYTE; i++) { > > + for (i = 0; i < eb_len(eb) * BITS_PER_BYTE; i++) { > > int bit, bit1; > > > > bit = !!test_bit(i, bitmap); > > @@ -411,7 +411,7 @@ static int test_bitmap_clear(const char *name, unsigned long *bitmap, > > static int __test_eb_bitmaps(unsigned long *bitmap, struct extent_buffer *eb) > > { > > unsigned long i, j; > > - unsigned long byte_len = eb->len; > > + unsigned long byte_len = eb_len(eb); > > u32 x; > > int ret; > > > > @@ -670,7 +670,7 @@ static int test_find_first_clear_extent_bit(void) > > static void dump_eb_and_memory_contents(struct extent_buffer *eb, void *memory, > > const char *test_name) > > { > > - for (int i = 0; i < eb->len; i++) { > > + for (int i = 0; i < eb_len(eb); i++) { > > struct page *page = folio_page(eb->folios[i >> PAGE_SHIFT], 0); > > void *addr = page_address(page) + offset_in_page(i); > > > > @@ -686,7 +686,7 @@ static void dump_eb_and_memory_contents(struct extent_buffer *eb, void *memory, > > static int verify_eb_and_memory(struct extent_buffer *eb, void *memory, > > const char *test_name) > > { > > - for (int i = 0; i < (eb->len >> PAGE_SHIFT); i++) { > > + for (int i = 0; i < (eb_len(eb) >> PAGE_SHIFT); i++) { > > void *eb_addr = folio_address(eb->folios[i]); > > > > if (memcmp(memory + (i << PAGE_SHIFT), eb_addr, PAGE_SIZE) != 0) { > > @@ -703,8 +703,8 @@ static int verify_eb_and_memory(struct extent_buffer *eb, void *memory, > > */ > > static void init_eb_and_memory(struct extent_buffer *eb, void *memory) > > { > > - get_random_bytes(memory, eb->len); > > - write_extent_buffer(eb, memory, 0, eb->len); > > + get_random_bytes(memory, eb_len(eb)); > > + write_extent_buffer(eb, memory, 0, eb_len(eb)); > > } > > > > static int test_eb_mem_ops(u32 sectorsize, u32 nodesize) > > diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c > > index 9d42bf2bfd746..c7a8cdd87c509 100644 > > --- a/fs/btrfs/zoned.c > > +++ b/fs/btrfs/zoned.c > > @@ -2422,7 +2422,7 @@ void btrfs_schedule_zone_finish_bg(struct btrfs_block_group *bg, > > struct extent_buffer *eb) > > { > > if (!test_bit(BLOCK_GROUP_FLAG_SEQUENTIAL_ZONE, &bg->runtime_flags) || > > - eb->start + eb->len * 2 <= bg->start + bg->zone_capacity) > > + eb->start + eb_len(eb) * 2 <= bg->start + bg->zone_capacity) > > return; > > > > if (WARN_ON(bg->zone_finish_work.func == btrfs_zone_finish_endio_workfn)) { > > -- > > 2.47.2 > > > > ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH] btrfs: remove extent buffer's redundant `len` member field 2025-04-30 8:26 ` Daniel Vacek @ 2025-04-30 8:34 ` Filipe Manana 2025-04-30 8:50 ` Daniel Vacek 0 siblings, 1 reply; 35+ messages in thread From: Filipe Manana @ 2025-04-30 8:34 UTC (permalink / raw) To: Daniel Vacek Cc: Chris Mason, Josef Bacik, David Sterba, linux-btrfs, linux-kernel On Wed, Apr 30, 2025 at 9:26 AM Daniel Vacek <neelx@suse.com> wrote: > > On Wed, 30 Apr 2025 at 10:06, Filipe Manana <fdmanana@kernel.org> wrote: > > > > On Tue, Apr 29, 2025 at 4:19 PM Daniel Vacek <neelx@suse.com> wrote: > > > > > > Even super block nowadays uses nodesize for eb->len. This is since commits > > > > > > 551561c34663 ("btrfs: don't pass nodesize to __alloc_extent_buffer()") > > > da17066c4047 ("btrfs: pull node/sector/stripe sizes out of root and into fs_info") > > > ce3e69847e3e ("btrfs: sink parameter len to alloc_extent_buffer") > > > a83fffb75d09 ("btrfs: sink blocksize parameter to btrfs_find_create_tree_block") > > > > > > With these the eb->len is not really useful anymore. Let's use the nodesize > > > directly where applicable. > > > > > > Signed-off-by: Daniel Vacek <neelx@suse.com> > > > --- > > > [RFC] > > > * Shall the eb_len() helper better be called eb_nodesize()? Or even rather > > > opencoded and not used at all? > > > > > > fs/btrfs/accessors.c | 4 +-- > > > fs/btrfs/disk-io.c | 11 ++++--- > > > fs/btrfs/extent-tree.c | 28 +++++++++-------- > > > fs/btrfs/extent_io.c | 54 ++++++++++++++------------------ > > > fs/btrfs/extent_io.h | 11 +++++-- > > > fs/btrfs/ioctl.c | 2 +- > > > fs/btrfs/relocation.c | 2 +- > > > fs/btrfs/subpage.c | 8 ++--- > > > fs/btrfs/tests/extent-io-tests.c | 12 +++---- > > > fs/btrfs/zoned.c | 2 +- > > > 10 files changed, 67 insertions(+), 67 deletions(-) > > > > > > diff --git a/fs/btrfs/accessors.c b/fs/btrfs/accessors.c > > > index e3716516ca387..a2bdbc7990906 100644 > > > --- a/fs/btrfs/accessors.c > > > +++ b/fs/btrfs/accessors.c > > > @@ -14,10 +14,10 @@ static bool check_setget_bounds(const struct extent_buffer *eb, > > > { > > > const unsigned long member_offset = (unsigned long)ptr + off; > > > > > > - if (unlikely(member_offset + size > eb->len)) { > > > + if (unlikely(member_offset + size > eb_len(eb))) { > > > btrfs_warn(eb->fs_info, > > > "bad eb member %s: ptr 0x%lx start %llu member offset %lu size %d", > > > - (member_offset > eb->len ? "start" : "end"), > > > + (member_offset > eb_len(eb) ? "start" : "end"), > > > (unsigned long)ptr, eb->start, member_offset, size); > > > return false; > > > } > > > diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c > > > index 3592300ae3e2e..31eb7419fe11f 100644 > > > --- a/fs/btrfs/disk-io.c > > > +++ b/fs/btrfs/disk-io.c > > > @@ -190,7 +190,7 @@ static int btrfs_repair_eb_io_failure(const struct extent_buffer *eb, > > > for (int i = 0; i < num_extent_folios(eb); i++) { > > > struct folio *folio = eb->folios[i]; > > > u64 start = max_t(u64, eb->start, folio_pos(folio)); > > > - u64 end = min_t(u64, eb->start + eb->len, > > > + u64 end = min_t(u64, eb->start + fs_info->nodesize, > > > folio_pos(folio) + eb->folio_size); > > > u32 len = end - start; > > > phys_addr_t paddr = PFN_PHYS(folio_pfn(folio)) + > > > @@ -230,7 +230,7 @@ int btrfs_read_extent_buffer(struct extent_buffer *eb, > > > break; > > > > > > num_copies = btrfs_num_copies(fs_info, > > > - eb->start, eb->len); > > > + eb->start, fs_info->nodesize); > > > if (num_copies == 1) > > > break; > > > > > > @@ -260,6 +260,7 @@ blk_status_t btree_csum_one_bio(struct btrfs_bio *bbio) > > > { > > > struct extent_buffer *eb = bbio->private; > > > struct btrfs_fs_info *fs_info = eb->fs_info; > > > + u32 nodesize = fs_info->nodesize; > > > u64 found_start = btrfs_header_bytenr(eb); > > > u64 last_trans; > > > u8 result[BTRFS_CSUM_SIZE]; > > > @@ -268,7 +269,7 @@ blk_status_t btree_csum_one_bio(struct btrfs_bio *bbio) > > > /* Btree blocks are always contiguous on disk. */ > > > if (WARN_ON_ONCE(bbio->file_offset != eb->start)) > > > return BLK_STS_IOERR; > > > - if (WARN_ON_ONCE(bbio->bio.bi_iter.bi_size != eb->len)) > > > + if (WARN_ON_ONCE(bbio->bio.bi_iter.bi_size != nodesize)) > > > return BLK_STS_IOERR; > > > > > > /* > > > @@ -277,7 +278,7 @@ blk_status_t btree_csum_one_bio(struct btrfs_bio *bbio) > > > * ordering of I/O without unnecessarily writing out data. > > > */ > > > if (test_bit(EXTENT_BUFFER_ZONED_ZEROOUT, &eb->bflags)) { > > > - memzero_extent_buffer(eb, 0, eb->len); > > > + memzero_extent_buffer(eb, 0, nodesize); > > > return BLK_STS_OK; > > > } > > > > > > @@ -883,7 +884,7 @@ struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans, > > > btrfs_set_root_generation(&root->root_item, trans->transid); > > > btrfs_set_root_level(&root->root_item, 0); > > > btrfs_set_root_refs(&root->root_item, 1); > > > - btrfs_set_root_used(&root->root_item, leaf->len); > > > + btrfs_set_root_used(&root->root_item, fs_info->nodesize); > > > btrfs_set_root_last_snapshot(&root->root_item, 0); > > > btrfs_set_root_dirid(&root->root_item, 0); > > > if (is_fstree(objectid)) > > > diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c > > > index e0811a86d0cbd..25560a162d93e 100644 > > > --- a/fs/btrfs/extent-tree.c > > > +++ b/fs/btrfs/extent-tree.c > > > @@ -2211,7 +2211,7 @@ int btrfs_set_disk_extent_flags(struct btrfs_trans_handle *trans, > > > extent_op->update_flags = true; > > > extent_op->update_key = false; > > > > > > - ret = btrfs_add_delayed_extent_op(trans, eb->start, eb->len, > > > + ret = btrfs_add_delayed_extent_op(trans, eb->start, eb_len(eb), > > > btrfs_header_level(eb), extent_op); > > > if (ret) > > > btrfs_free_delayed_extent_op(extent_op); > > > @@ -2660,10 +2660,10 @@ int btrfs_pin_extent_for_log_replay(struct btrfs_trans_handle *trans, > > > if (ret) > > > goto out; > > > > > > - pin_down_extent(trans, cache, eb->start, eb->len, 0); > > > + pin_down_extent(trans, cache, eb->start, eb_len(eb), 0); > > > > > > /* remove us from the free space cache (if we're there at all) */ > > > - ret = btrfs_remove_free_space(cache, eb->start, eb->len); > > > + ret = btrfs_remove_free_space(cache, eb->start, eb_len(eb)); > > > out: > > > btrfs_put_block_group(cache); > > > return ret; > > > @@ -3436,13 +3436,14 @@ int btrfs_free_tree_block(struct btrfs_trans_handle *trans, > > > { > > > struct btrfs_fs_info *fs_info = trans->fs_info; > > > struct btrfs_block_group *bg; > > > + u32 nodesize = fs_info->nodesize; > > > int ret; > > > > > > if (root_id != BTRFS_TREE_LOG_OBJECTID) { > > > struct btrfs_ref generic_ref = { > > > .action = BTRFS_DROP_DELAYED_REF, > > > .bytenr = buf->start, > > > - .num_bytes = buf->len, > > > + .num_bytes = nodesize, > > > .parent = parent, > > > .owning_root = btrfs_header_owner(buf), > > > .ref_root = root_id, > > > @@ -3478,7 +3479,7 @@ int btrfs_free_tree_block(struct btrfs_trans_handle *trans, > > > bg = btrfs_lookup_block_group(fs_info, buf->start); > > > > > > if (btrfs_header_flag(buf, BTRFS_HEADER_FLAG_WRITTEN)) { > > > - pin_down_extent(trans, bg, buf->start, buf->len, 1); > > > + pin_down_extent(trans, bg, buf->start, nodesize, 1); > > > btrfs_put_block_group(bg); > > > goto out; > > > } > > > @@ -3502,17 +3503,17 @@ int btrfs_free_tree_block(struct btrfs_trans_handle *trans, > > > > > > if (test_bit(BTRFS_FS_TREE_MOD_LOG_USERS, &fs_info->flags) > > > || btrfs_is_zoned(fs_info)) { > > > - pin_down_extent(trans, bg, buf->start, buf->len, 1); > > > + pin_down_extent(trans, bg, buf->start, nodesize, 1); > > > btrfs_put_block_group(bg); > > > goto out; > > > } > > > > > > WARN_ON(test_bit(EXTENT_BUFFER_DIRTY, &buf->bflags)); > > > > > > - btrfs_add_free_space(bg, buf->start, buf->len); > > > - btrfs_free_reserved_bytes(bg, buf->len, 0); > > > + btrfs_add_free_space(bg, buf->start, nodesize); > > > + btrfs_free_reserved_bytes(bg, nodesize, 0); > > > btrfs_put_block_group(bg); > > > - trace_btrfs_reserved_extent_free(fs_info, buf->start, buf->len); > > > + trace_btrfs_reserved_extent_free(fs_info, buf->start, nodesize); > > > > > > out: > > > return 0; > > > @@ -4768,7 +4769,7 @@ int btrfs_pin_reserved_extent(struct btrfs_trans_handle *trans, > > > return -ENOSPC; > > > } > > > > > > - ret = pin_down_extent(trans, cache, eb->start, eb->len, 1); > > > + ret = pin_down_extent(trans, cache, eb->start, eb_len(eb), 1); > > > btrfs_put_block_group(cache); > > > return ret; > > > } > > > @@ -5050,6 +5051,7 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root, > > > struct btrfs_fs_info *fs_info = root->fs_info; > > > struct extent_buffer *buf; > > > u64 lockdep_owner = owner; > > > + u32 nodesize = fs_info->nodesize; > > > > > > buf = btrfs_find_create_tree_block(fs_info, bytenr, owner, level); > > > if (IS_ERR(buf)) > > > @@ -5107,16 +5109,16 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root, > > > */ > > > if (buf->log_index == 0) > > > btrfs_set_extent_bit(&root->dirty_log_pages, buf->start, > > > - buf->start + buf->len - 1, > > > + buf->start + nodesize - 1, > > > EXTENT_DIRTY, NULL); > > > else > > > btrfs_set_extent_bit(&root->dirty_log_pages, buf->start, > > > - buf->start + buf->len - 1, > > > + buf->start + nodesize - 1, > > > EXTENT_NEW, NULL); > > > } else { > > > buf->log_index = -1; > > > btrfs_set_extent_bit(&trans->transaction->dirty_pages, buf->start, > > > - buf->start + buf->len - 1, EXTENT_DIRTY, NULL); > > > + buf->start + nodesize - 1, EXTENT_DIRTY, NULL); > > > } > > > /* this returns a buffer locked for blocking */ > > > return buf; > > > diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c > > > index 20cdddd924852..e4050fd5db285 100644 > > > --- a/fs/btrfs/extent_io.c > > > +++ b/fs/btrfs/extent_io.c > > > @@ -76,8 +76,8 @@ void btrfs_extent_buffer_leak_debug_check(struct btrfs_fs_info *fs_info) > > > eb = list_first_entry(&fs_info->allocated_ebs, > > > struct extent_buffer, leak_list); > > > pr_err( > > > - "BTRFS: buffer leak start %llu len %u refs %d bflags %lu owner %llu\n", > > > - eb->start, eb->len, atomic_read(&eb->refs), eb->bflags, > > > + "BTRFS: buffer leak start %llu refs %d bflags %lu owner %llu\n", > > > + eb->start, atomic_read(&eb->refs), eb->bflags, > > > btrfs_header_owner(eb)); > > > list_del(&eb->leak_list); > > > WARN_ON_ONCE(1); > > > @@ -1746,8 +1746,8 @@ static noinline_for_stack bool lock_extent_buffer_for_io(struct extent_buffer *e > > > > > > btrfs_set_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN); > > > percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, > > > - -eb->len, > > > - fs_info->dirty_metadata_batch); > > > + -fs_info->nodesize, > > > + fs_info->dirty_metadata_batch); > > > ret = true; > > > } else { > > > spin_unlock(&eb->refs_lock); > > > @@ -1953,7 +1953,7 @@ static unsigned int buffer_tree_get_ebs_tag(struct btrfs_fs_info *fs_info, > > > rcu_read_lock(); > > > while ((eb = find_get_eb(&xas, end, tag)) != NULL) { > > > if (!eb_batch_add(batch, eb)) { > > > - *start = (eb->start + eb->len) >> fs_info->sectorsize_bits; > > > + *start = (eb->start + fs_info->nodesize) >> fs_info->sectorsize_bits; > > > goto out; > > > } > > > } > > > @@ -2020,7 +2020,7 @@ static void prepare_eb_write(struct extent_buffer *eb) > > > nritems = btrfs_header_nritems(eb); > > > if (btrfs_header_level(eb) > 0) { > > > end = btrfs_node_key_ptr_offset(eb, nritems); > > > - memzero_extent_buffer(eb, end, eb->len - end); > > > + memzero_extent_buffer(eb, end, eb_len(eb) - end); > > > } else { > > > /* > > > * Leaf: > > > @@ -2056,7 +2056,7 @@ static noinline_for_stack void write_one_eb(struct extent_buffer *eb, > > > struct folio *folio = eb->folios[i]; > > > u64 range_start = max_t(u64, eb->start, folio_pos(folio)); > > > u32 range_len = min_t(u64, folio_pos(folio) + folio_size(folio), > > > - eb->start + eb->len) - range_start; > > > + eb->start + fs_info->nodesize) - range_start; > > > > > > folio_lock(folio); > > > btrfs_meta_folio_clear_dirty(folio, eb); > > > @@ -2171,7 +2171,7 @@ int btree_write_cache_pages(struct address_space *mapping, > > > if (ctx.zoned_bg) { > > > /* Mark the last eb in the block group. */ > > > btrfs_schedule_zone_finish_bg(ctx.zoned_bg, eb); > > > - ctx.zoned_bg->meta_write_pointer += eb->len; > > > + ctx.zoned_bg->meta_write_pointer += fs_info->nodesize; > > > } > > > write_one_eb(eb, wbc); > > > } > > > @@ -2807,7 +2807,6 @@ static struct extent_buffer *__alloc_extent_buffer(struct btrfs_fs_info *fs_info > > > > > > eb = kmem_cache_zalloc(extent_buffer_cache, GFP_NOFS|__GFP_NOFAIL); > > > eb->start = start; > > > - eb->len = fs_info->nodesize; > > > eb->fs_info = fs_info; > > > init_rwsem(&eb->lock); > > > > > > @@ -2816,8 +2815,6 @@ static struct extent_buffer *__alloc_extent_buffer(struct btrfs_fs_info *fs_info > > > spin_lock_init(&eb->refs_lock); > > > atomic_set(&eb->refs, 1); > > > > > > - ASSERT(eb->len <= BTRFS_MAX_METADATA_BLOCKSIZE); > > > - > > > return eb; > > > } > > > > > > @@ -3505,7 +3502,7 @@ void btrfs_clear_buffer_dirty(struct btrfs_trans_handle *trans, > > > return; > > > > > > buffer_tree_clear_mark(eb, PAGECACHE_TAG_DIRTY); > > > - percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, -eb->len, > > > + percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, -fs_info->nodesize, > > > fs_info->dirty_metadata_batch); > > > > > > for (int i = 0; i < num_extent_folios(eb); i++) { > > > @@ -3557,8 +3554,8 @@ void set_extent_buffer_dirty(struct extent_buffer *eb) > > > if (subpage) > > > folio_unlock(eb->folios[0]); > > > percpu_counter_add_batch(&eb->fs_info->dirty_metadata_bytes, > > > - eb->len, > > > - eb->fs_info->dirty_metadata_batch); > > > + eb_len(eb), > > > + eb->fs_info->dirty_metadata_batch); > > > } > > > #ifdef CONFIG_BTRFS_DEBUG > > > for (int i = 0; i < num_extent_folios(eb); i++) > > > @@ -3670,7 +3667,7 @@ int read_extent_buffer_pages_nowait(struct extent_buffer *eb, int mirror_num, > > > struct folio *folio = eb->folios[i]; > > > u64 range_start = max_t(u64, eb->start, folio_pos(folio)); > > > u32 range_len = min_t(u64, folio_pos(folio) + folio_size(folio), > > > - eb->start + eb->len) - range_start; > > > + eb->start + eb_len(eb)) - range_start; > > > > > > bio_add_folio_nofail(&bbio->bio, folio, range_len, > > > offset_in_folio(folio, range_start)); > > > @@ -3698,8 +3695,8 @@ static bool report_eb_range(const struct extent_buffer *eb, unsigned long start, > > > unsigned long len) > > > { > > > btrfs_warn(eb->fs_info, > > > - "access to eb bytenr %llu len %u out of range start %lu len %lu", > > > - eb->start, eb->len, start, len); > > > + "access to eb bytenr %llu out of range start %lu len %lu", > > > + eb->start, start, len); > > > DEBUG_WARN(); > > > > > > return true; > > > @@ -3717,8 +3714,8 @@ static inline int check_eb_range(const struct extent_buffer *eb, > > > { > > > unsigned long offset; > > > > > > - /* start, start + len should not go beyond eb->len nor overflow */ > > > - if (unlikely(check_add_overflow(start, len, &offset) || offset > eb->len)) > > > + /* start, start + len should not go beyond nodesize nor overflow */ > > > + if (unlikely(check_add_overflow(start, len, &offset) || offset > eb_len(eb))) > > > return report_eb_range(eb, start, len); > > > > > > return false; > > > @@ -3774,8 +3771,8 @@ int read_extent_buffer_to_user_nofault(const struct extent_buffer *eb, > > > unsigned long i = get_eb_folio_index(eb, start); > > > int ret = 0; > > > > > > - WARN_ON(start > eb->len); > > > - WARN_ON(start + len > eb->start + eb->len); > > > + WARN_ON(start > eb_len(eb)); > > > + WARN_ON(start + len > eb->start + eb_len(eb)); > > > > > > if (eb->addr) { > > > if (copy_to_user_nofault(dstv, eb->addr + start, len)) > > > @@ -3866,8 +3863,8 @@ static void assert_eb_folio_uptodate(const struct extent_buffer *eb, int i) > > > folio = eb->folios[0]; > > > ASSERT(i == 0); > > > if (WARN_ON(!btrfs_subpage_test_uptodate(fs_info, folio, > > > - eb->start, eb->len))) > > > - btrfs_subpage_dump_bitmap(fs_info, folio, eb->start, eb->len); > > > + eb->start, fs_info->nodesize))) > > > + btrfs_subpage_dump_bitmap(fs_info, folio, eb->start, fs_info->nodesize); > > > } else { > > > WARN_ON(!folio_test_uptodate(folio)); > > > } > > > @@ -3960,12 +3957,10 @@ void copy_extent_buffer_full(const struct extent_buffer *dst, > > > const int unit_size = src->folio_size; > > > unsigned long cur = 0; > > > > > > - ASSERT(dst->len == src->len); > > > - > > > - while (cur < src->len) { > > > + while (cur < eb_len(src)) { > > > unsigned long index = get_eb_folio_index(src, cur); > > > unsigned long offset = get_eb_offset_in_folio(src, cur); > > > - unsigned long cur_len = min(src->len, unit_size - offset); > > > + unsigned long cur_len = min(eb_len(src), unit_size - offset); > > > void *addr = folio_address(src->folios[index]) + offset; > > > > > > write_extent_buffer(dst, addr, cur, cur_len); > > > @@ -3980,7 +3975,6 @@ void copy_extent_buffer(const struct extent_buffer *dst, > > > unsigned long len) > > > { > > > const int unit_size = dst->folio_size; > > > - u64 dst_len = dst->len; > > > size_t cur; > > > size_t offset; > > > char *kaddr; > > > @@ -3990,8 +3984,6 @@ void copy_extent_buffer(const struct extent_buffer *dst, > > > check_eb_range(src, src_offset, len)) > > > return; > > > > > > - WARN_ON(src->len != dst_len); > > > - > > > offset = get_eb_offset_in_folio(dst, dst_offset); > > > > > > while (len > 0) { > > > @@ -4266,7 +4258,7 @@ static int try_release_subpage_extent_buffer(struct folio *folio) > > > xa_unlock_irq(&fs_info->buffer_tree); > > > break; > > > } > > > - cur = eb->start + eb->len; > > > + cur = eb->start + fs_info->nodesize; > > > > > > /* > > > * The same as try_release_extent_buffer(), to ensure the eb > > > diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h > > > index 1415679d7f88c..9a842eea47d6d 100644 > > > --- a/fs/btrfs/extent_io.h > > > +++ b/fs/btrfs/extent_io.h > > > @@ -16,6 +16,7 @@ > > > #include "messages.h" > > > #include "ulist.h" > > > #include "misc.h" > > > +#include "fs.h" > > > > > > struct page; > > > struct file; > > > @@ -80,7 +81,6 @@ void __cold extent_buffer_free_cachep(void); > > > #define INLINE_EXTENT_BUFFER_PAGES (BTRFS_MAX_METADATA_BLOCKSIZE / PAGE_SIZE) > > > struct extent_buffer { > > > u64 start; > > > - u32 len; > > > u32 folio_size; > > > unsigned long bflags; > > > struct btrfs_fs_info *fs_info; > > > @@ -263,17 +263,22 @@ void btrfs_readahead_tree_block(struct btrfs_fs_info *fs_info, > > > u64 bytenr, u64 owner_root, u64 gen, int level); > > > void btrfs_readahead_node_child(struct extent_buffer *node, int slot); > > > > > > +static inline u32 eb_len(const struct extent_buffer *eb) > > > +{ > > > + return eb->fs_info->nodesize; > > > +} > > > > Please always add a "btrfs_" prefix to the name of exported functions. > > It's static inline, not exported. But I'm happy just opencoding it > instead. Thanks. Exported in the sense that it's in a header and visible to any C files that include it, not in the sense of being exported with EXPORT_SYMBOL_GPL() for example. This is our coding style convention: https://btrfs.readthedocs.io/en/latest/dev/Development-notes.html#function-declarations static functions inside a C file can omit the prefix. > > > In this case I don't think adding this helper adds any value. > > We can just do eb->fs_info->nodesize everywhere and in some places we > > already have fs_info in a local variable and can just do > > fs_info->nodesize. > > > > Thanks. > > > > > + > > > /* Note: this can be used in for loops without caching the value in a variable. */ > > > static inline int __pure num_extent_pages(const struct extent_buffer *eb) > > > { > > > /* > > > * For sectorsize == PAGE_SIZE case, since nodesize is always aligned to > > > - * sectorsize, it's just eb->len >> PAGE_SHIFT. > > > + * sectorsize, it's just nodesize >> PAGE_SHIFT. > > > * > > > * For sectorsize < PAGE_SIZE case, we could have nodesize < PAGE_SIZE, > > > * thus have to ensure we get at least one page. > > > */ > > > - return (eb->len >> PAGE_SHIFT) ?: 1; > > > + return (eb_len(eb) >> PAGE_SHIFT) ?: 1; > > > } > > > > > > /* > > > diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c > > > index 68fac77fb95d1..6be2d56d44917 100644 > > > --- a/fs/btrfs/ioctl.c > > > +++ b/fs/btrfs/ioctl.c > > > @@ -598,7 +598,7 @@ static noinline int create_subvol(struct mnt_idmap *idmap, > > > btrfs_set_root_generation(root_item, trans->transid); > > > btrfs_set_root_level(root_item, 0); > > > btrfs_set_root_refs(root_item, 1); > > > - btrfs_set_root_used(root_item, leaf->len); > > > + btrfs_set_root_used(root_item, fs_info->nodesize); > > > btrfs_set_root_last_snapshot(root_item, 0); > > > > > > btrfs_set_root_generation_v2(root_item, > > > diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c > > > index 6287e71ebad5f..5086485a4ae21 100644 > > > --- a/fs/btrfs/relocation.c > > > +++ b/fs/btrfs/relocation.c > > > @@ -4352,7 +4352,7 @@ int btrfs_reloc_cow_block(struct btrfs_trans_handle *trans, > > > mark_block_processed(rc, node); > > > > > > if (first_cow && level > 0) > > > - rc->nodes_relocated += buf->len; > > > + rc->nodes_relocated += fs_info->nodesize; > > > } > > > > > > if (level == 0 && first_cow && rc->stage == UPDATE_DATA_PTRS) > > > diff --git a/fs/btrfs/subpage.c b/fs/btrfs/subpage.c > > > index d4f0192334936..711792f32e9ce 100644 > > > --- a/fs/btrfs/subpage.c > > > +++ b/fs/btrfs/subpage.c > > > @@ -631,7 +631,7 @@ void btrfs_meta_folio_set_##name(struct folio *folio, const struct extent_buffer > > > folio_set_func(folio); \ > > > return; \ > > > } \ > > > - btrfs_subpage_set_##name(eb->fs_info, folio, eb->start, eb->len); \ > > > + btrfs_subpage_set_##name(eb->fs_info, folio, eb->start, eb_len(eb)); \ > > > } \ > > > void btrfs_meta_folio_clear_##name(struct folio *folio, const struct extent_buffer *eb) \ > > > { \ > > > @@ -639,13 +639,13 @@ void btrfs_meta_folio_clear_##name(struct folio *folio, const struct extent_buff > > > folio_clear_func(folio); \ > > > return; \ > > > } \ > > > - btrfs_subpage_clear_##name(eb->fs_info, folio, eb->start, eb->len); \ > > > + btrfs_subpage_clear_##name(eb->fs_info, folio, eb->start, eb_len(eb)); \ > > > } \ > > > bool btrfs_meta_folio_test_##name(struct folio *folio, const struct extent_buffer *eb) \ > > > { \ > > > if (!btrfs_meta_is_subpage(eb->fs_info)) \ > > > return folio_test_func(folio); \ > > > - return btrfs_subpage_test_##name(eb->fs_info, folio, eb->start, eb->len); \ > > > + return btrfs_subpage_test_##name(eb->fs_info, folio, eb->start, eb_len(eb)); \ > > > } > > > IMPLEMENT_BTRFS_PAGE_OPS(uptodate, folio_mark_uptodate, folio_clear_uptodate, > > > folio_test_uptodate); > > > @@ -765,7 +765,7 @@ bool btrfs_meta_folio_clear_and_test_dirty(struct folio *folio, const struct ext > > > return true; > > > } > > > > > > - last = btrfs_subpage_clear_and_test_dirty(eb->fs_info, folio, eb->start, eb->len); > > > + last = btrfs_subpage_clear_and_test_dirty(eb->fs_info, folio, eb->start, eb_len(eb)); > > > if (last) { > > > folio_clear_dirty_for_io(folio); > > > return true; > > > diff --git a/fs/btrfs/tests/extent-io-tests.c b/fs/btrfs/tests/extent-io-tests.c > > > index 00da54f0164c9..657f8f1d9263e 100644 > > > --- a/fs/btrfs/tests/extent-io-tests.c > > > +++ b/fs/btrfs/tests/extent-io-tests.c > > > @@ -342,7 +342,7 @@ static int check_eb_bitmap(unsigned long *bitmap, struct extent_buffer *eb) > > > { > > > unsigned long i; > > > > > > - for (i = 0; i < eb->len * BITS_PER_BYTE; i++) { > > > + for (i = 0; i < eb_len(eb) * BITS_PER_BYTE; i++) { > > > int bit, bit1; > > > > > > bit = !!test_bit(i, bitmap); > > > @@ -411,7 +411,7 @@ static int test_bitmap_clear(const char *name, unsigned long *bitmap, > > > static int __test_eb_bitmaps(unsigned long *bitmap, struct extent_buffer *eb) > > > { > > > unsigned long i, j; > > > - unsigned long byte_len = eb->len; > > > + unsigned long byte_len = eb_len(eb); > > > u32 x; > > > int ret; > > > > > > @@ -670,7 +670,7 @@ static int test_find_first_clear_extent_bit(void) > > > static void dump_eb_and_memory_contents(struct extent_buffer *eb, void *memory, > > > const char *test_name) > > > { > > > - for (int i = 0; i < eb->len; i++) { > > > + for (int i = 0; i < eb_len(eb); i++) { > > > struct page *page = folio_page(eb->folios[i >> PAGE_SHIFT], 0); > > > void *addr = page_address(page) + offset_in_page(i); > > > > > > @@ -686,7 +686,7 @@ static void dump_eb_and_memory_contents(struct extent_buffer *eb, void *memory, > > > static int verify_eb_and_memory(struct extent_buffer *eb, void *memory, > > > const char *test_name) > > > { > > > - for (int i = 0; i < (eb->len >> PAGE_SHIFT); i++) { > > > + for (int i = 0; i < (eb_len(eb) >> PAGE_SHIFT); i++) { > > > void *eb_addr = folio_address(eb->folios[i]); > > > > > > if (memcmp(memory + (i << PAGE_SHIFT), eb_addr, PAGE_SIZE) != 0) { > > > @@ -703,8 +703,8 @@ static int verify_eb_and_memory(struct extent_buffer *eb, void *memory, > > > */ > > > static void init_eb_and_memory(struct extent_buffer *eb, void *memory) > > > { > > > - get_random_bytes(memory, eb->len); > > > - write_extent_buffer(eb, memory, 0, eb->len); > > > + get_random_bytes(memory, eb_len(eb)); > > > + write_extent_buffer(eb, memory, 0, eb_len(eb)); > > > } > > > > > > static int test_eb_mem_ops(u32 sectorsize, u32 nodesize) > > > diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c > > > index 9d42bf2bfd746..c7a8cdd87c509 100644 > > > --- a/fs/btrfs/zoned.c > > > +++ b/fs/btrfs/zoned.c > > > @@ -2422,7 +2422,7 @@ void btrfs_schedule_zone_finish_bg(struct btrfs_block_group *bg, > > > struct extent_buffer *eb) > > > { > > > if (!test_bit(BLOCK_GROUP_FLAG_SEQUENTIAL_ZONE, &bg->runtime_flags) || > > > - eb->start + eb->len * 2 <= bg->start + bg->zone_capacity) > > > + eb->start + eb_len(eb) * 2 <= bg->start + bg->zone_capacity) > > > return; > > > > > > if (WARN_ON(bg->zone_finish_work.func == btrfs_zone_finish_endio_workfn)) { > > > -- > > > 2.47.2 > > > > > > ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH] btrfs: remove extent buffer's redundant `len` member field 2025-04-30 8:34 ` Filipe Manana @ 2025-04-30 8:50 ` Daniel Vacek 2025-04-30 10:26 ` Filipe Manana 0 siblings, 1 reply; 35+ messages in thread From: Daniel Vacek @ 2025-04-30 8:50 UTC (permalink / raw) To: Filipe Manana Cc: Chris Mason, Josef Bacik, David Sterba, linux-btrfs, linux-kernel On Wed, 30 Apr 2025 at 10:34, Filipe Manana <fdmanana@kernel.org> wrote: > > On Wed, Apr 30, 2025 at 9:26 AM Daniel Vacek <neelx@suse.com> wrote: > > > > On Wed, 30 Apr 2025 at 10:06, Filipe Manana <fdmanana@kernel.org> wrote: > > > > > > On Tue, Apr 29, 2025 at 4:19 PM Daniel Vacek <neelx@suse.com> wrote: > > > > > > > > Even super block nowadays uses nodesize for eb->len. This is since commits > > > > > > > > 551561c34663 ("btrfs: don't pass nodesize to __alloc_extent_buffer()") > > > > da17066c4047 ("btrfs: pull node/sector/stripe sizes out of root and into fs_info") > > > > ce3e69847e3e ("btrfs: sink parameter len to alloc_extent_buffer") > > > > a83fffb75d09 ("btrfs: sink blocksize parameter to btrfs_find_create_tree_block") > > > > > > > > With these the eb->len is not really useful anymore. Let's use the nodesize > > > > directly where applicable. > > > > > > > > Signed-off-by: Daniel Vacek <neelx@suse.com> > > > > --- > > > > [RFC] > > > > * Shall the eb_len() helper better be called eb_nodesize()? Or even rather > > > > opencoded and not used at all? > > > > > > > > fs/btrfs/accessors.c | 4 +-- > > > > fs/btrfs/disk-io.c | 11 ++++--- > > > > fs/btrfs/extent-tree.c | 28 +++++++++-------- > > > > fs/btrfs/extent_io.c | 54 ++++++++++++++------------------ > > > > fs/btrfs/extent_io.h | 11 +++++-- > > > > fs/btrfs/ioctl.c | 2 +- > > > > fs/btrfs/relocation.c | 2 +- > > > > fs/btrfs/subpage.c | 8 ++--- > > > > fs/btrfs/tests/extent-io-tests.c | 12 +++---- > > > > fs/btrfs/zoned.c | 2 +- > > > > 10 files changed, 67 insertions(+), 67 deletions(-) > > > > > > > > diff --git a/fs/btrfs/accessors.c b/fs/btrfs/accessors.c > > > > index e3716516ca387..a2bdbc7990906 100644 > > > > --- a/fs/btrfs/accessors.c > > > > +++ b/fs/btrfs/accessors.c > > > > @@ -14,10 +14,10 @@ static bool check_setget_bounds(const struct extent_buffer *eb, > > > > { > > > > const unsigned long member_offset = (unsigned long)ptr + off; > > > > > > > > - if (unlikely(member_offset + size > eb->len)) { > > > > + if (unlikely(member_offset + size > eb_len(eb))) { > > > > btrfs_warn(eb->fs_info, > > > > "bad eb member %s: ptr 0x%lx start %llu member offset %lu size %d", > > > > - (member_offset > eb->len ? "start" : "end"), > > > > + (member_offset > eb_len(eb) ? "start" : "end"), > > > > (unsigned long)ptr, eb->start, member_offset, size); > > > > return false; > > > > } > > > > diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c > > > > index 3592300ae3e2e..31eb7419fe11f 100644 > > > > --- a/fs/btrfs/disk-io.c > > > > +++ b/fs/btrfs/disk-io.c > > > > @@ -190,7 +190,7 @@ static int btrfs_repair_eb_io_failure(const struct extent_buffer *eb, > > > > for (int i = 0; i < num_extent_folios(eb); i++) { > > > > struct folio *folio = eb->folios[i]; > > > > u64 start = max_t(u64, eb->start, folio_pos(folio)); > > > > - u64 end = min_t(u64, eb->start + eb->len, > > > > + u64 end = min_t(u64, eb->start + fs_info->nodesize, > > > > folio_pos(folio) + eb->folio_size); > > > > u32 len = end - start; > > > > phys_addr_t paddr = PFN_PHYS(folio_pfn(folio)) + > > > > @@ -230,7 +230,7 @@ int btrfs_read_extent_buffer(struct extent_buffer *eb, > > > > break; > > > > > > > > num_copies = btrfs_num_copies(fs_info, > > > > - eb->start, eb->len); > > > > + eb->start, fs_info->nodesize); > > > > if (num_copies == 1) > > > > break; > > > > > > > > @@ -260,6 +260,7 @@ blk_status_t btree_csum_one_bio(struct btrfs_bio *bbio) > > > > { > > > > struct extent_buffer *eb = bbio->private; > > > > struct btrfs_fs_info *fs_info = eb->fs_info; > > > > + u32 nodesize = fs_info->nodesize; > > > > u64 found_start = btrfs_header_bytenr(eb); > > > > u64 last_trans; > > > > u8 result[BTRFS_CSUM_SIZE]; > > > > @@ -268,7 +269,7 @@ blk_status_t btree_csum_one_bio(struct btrfs_bio *bbio) > > > > /* Btree blocks are always contiguous on disk. */ > > > > if (WARN_ON_ONCE(bbio->file_offset != eb->start)) > > > > return BLK_STS_IOERR; > > > > - if (WARN_ON_ONCE(bbio->bio.bi_iter.bi_size != eb->len)) > > > > + if (WARN_ON_ONCE(bbio->bio.bi_iter.bi_size != nodesize)) > > > > return BLK_STS_IOERR; > > > > > > > > /* > > > > @@ -277,7 +278,7 @@ blk_status_t btree_csum_one_bio(struct btrfs_bio *bbio) > > > > * ordering of I/O without unnecessarily writing out data. > > > > */ > > > > if (test_bit(EXTENT_BUFFER_ZONED_ZEROOUT, &eb->bflags)) { > > > > - memzero_extent_buffer(eb, 0, eb->len); > > > > + memzero_extent_buffer(eb, 0, nodesize); > > > > return BLK_STS_OK; > > > > } > > > > > > > > @@ -883,7 +884,7 @@ struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans, > > > > btrfs_set_root_generation(&root->root_item, trans->transid); > > > > btrfs_set_root_level(&root->root_item, 0); > > > > btrfs_set_root_refs(&root->root_item, 1); > > > > - btrfs_set_root_used(&root->root_item, leaf->len); > > > > + btrfs_set_root_used(&root->root_item, fs_info->nodesize); > > > > btrfs_set_root_last_snapshot(&root->root_item, 0); > > > > btrfs_set_root_dirid(&root->root_item, 0); > > > > if (is_fstree(objectid)) > > > > diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c > > > > index e0811a86d0cbd..25560a162d93e 100644 > > > > --- a/fs/btrfs/extent-tree.c > > > > +++ b/fs/btrfs/extent-tree.c > > > > @@ -2211,7 +2211,7 @@ int btrfs_set_disk_extent_flags(struct btrfs_trans_handle *trans, > > > > extent_op->update_flags = true; > > > > extent_op->update_key = false; > > > > > > > > - ret = btrfs_add_delayed_extent_op(trans, eb->start, eb->len, > > > > + ret = btrfs_add_delayed_extent_op(trans, eb->start, eb_len(eb), > > > > btrfs_header_level(eb), extent_op); > > > > if (ret) > > > > btrfs_free_delayed_extent_op(extent_op); > > > > @@ -2660,10 +2660,10 @@ int btrfs_pin_extent_for_log_replay(struct btrfs_trans_handle *trans, > > > > if (ret) > > > > goto out; > > > > > > > > - pin_down_extent(trans, cache, eb->start, eb->len, 0); > > > > + pin_down_extent(trans, cache, eb->start, eb_len(eb), 0); > > > > > > > > /* remove us from the free space cache (if we're there at all) */ > > > > - ret = btrfs_remove_free_space(cache, eb->start, eb->len); > > > > + ret = btrfs_remove_free_space(cache, eb->start, eb_len(eb)); > > > > out: > > > > btrfs_put_block_group(cache); > > > > return ret; > > > > @@ -3436,13 +3436,14 @@ int btrfs_free_tree_block(struct btrfs_trans_handle *trans, > > > > { > > > > struct btrfs_fs_info *fs_info = trans->fs_info; > > > > struct btrfs_block_group *bg; > > > > + u32 nodesize = fs_info->nodesize; > > > > int ret; > > > > > > > > if (root_id != BTRFS_TREE_LOG_OBJECTID) { > > > > struct btrfs_ref generic_ref = { > > > > .action = BTRFS_DROP_DELAYED_REF, > > > > .bytenr = buf->start, > > > > - .num_bytes = buf->len, > > > > + .num_bytes = nodesize, > > > > .parent = parent, > > > > .owning_root = btrfs_header_owner(buf), > > > > .ref_root = root_id, > > > > @@ -3478,7 +3479,7 @@ int btrfs_free_tree_block(struct btrfs_trans_handle *trans, > > > > bg = btrfs_lookup_block_group(fs_info, buf->start); > > > > > > > > if (btrfs_header_flag(buf, BTRFS_HEADER_FLAG_WRITTEN)) { > > > > - pin_down_extent(trans, bg, buf->start, buf->len, 1); > > > > + pin_down_extent(trans, bg, buf->start, nodesize, 1); > > > > btrfs_put_block_group(bg); > > > > goto out; > > > > } > > > > @@ -3502,17 +3503,17 @@ int btrfs_free_tree_block(struct btrfs_trans_handle *trans, > > > > > > > > if (test_bit(BTRFS_FS_TREE_MOD_LOG_USERS, &fs_info->flags) > > > > || btrfs_is_zoned(fs_info)) { > > > > - pin_down_extent(trans, bg, buf->start, buf->len, 1); > > > > + pin_down_extent(trans, bg, buf->start, nodesize, 1); > > > > btrfs_put_block_group(bg); > > > > goto out; > > > > } > > > > > > > > WARN_ON(test_bit(EXTENT_BUFFER_DIRTY, &buf->bflags)); > > > > > > > > - btrfs_add_free_space(bg, buf->start, buf->len); > > > > - btrfs_free_reserved_bytes(bg, buf->len, 0); > > > > + btrfs_add_free_space(bg, buf->start, nodesize); > > > > + btrfs_free_reserved_bytes(bg, nodesize, 0); > > > > btrfs_put_block_group(bg); > > > > - trace_btrfs_reserved_extent_free(fs_info, buf->start, buf->len); > > > > + trace_btrfs_reserved_extent_free(fs_info, buf->start, nodesize); > > > > > > > > out: > > > > return 0; > > > > @@ -4768,7 +4769,7 @@ int btrfs_pin_reserved_extent(struct btrfs_trans_handle *trans, > > > > return -ENOSPC; > > > > } > > > > > > > > - ret = pin_down_extent(trans, cache, eb->start, eb->len, 1); > > > > + ret = pin_down_extent(trans, cache, eb->start, eb_len(eb), 1); > > > > btrfs_put_block_group(cache); > > > > return ret; > > > > } > > > > @@ -5050,6 +5051,7 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root, > > > > struct btrfs_fs_info *fs_info = root->fs_info; > > > > struct extent_buffer *buf; > > > > u64 lockdep_owner = owner; > > > > + u32 nodesize = fs_info->nodesize; > > > > > > > > buf = btrfs_find_create_tree_block(fs_info, bytenr, owner, level); > > > > if (IS_ERR(buf)) > > > > @@ -5107,16 +5109,16 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root, > > > > */ > > > > if (buf->log_index == 0) > > > > btrfs_set_extent_bit(&root->dirty_log_pages, buf->start, > > > > - buf->start + buf->len - 1, > > > > + buf->start + nodesize - 1, > > > > EXTENT_DIRTY, NULL); > > > > else > > > > btrfs_set_extent_bit(&root->dirty_log_pages, buf->start, > > > > - buf->start + buf->len - 1, > > > > + buf->start + nodesize - 1, > > > > EXTENT_NEW, NULL); > > > > } else { > > > > buf->log_index = -1; > > > > btrfs_set_extent_bit(&trans->transaction->dirty_pages, buf->start, > > > > - buf->start + buf->len - 1, EXTENT_DIRTY, NULL); > > > > + buf->start + nodesize - 1, EXTENT_DIRTY, NULL); > > > > } > > > > /* this returns a buffer locked for blocking */ > > > > return buf; > > > > diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c > > > > index 20cdddd924852..e4050fd5db285 100644 > > > > --- a/fs/btrfs/extent_io.c > > > > +++ b/fs/btrfs/extent_io.c > > > > @@ -76,8 +76,8 @@ void btrfs_extent_buffer_leak_debug_check(struct btrfs_fs_info *fs_info) > > > > eb = list_first_entry(&fs_info->allocated_ebs, > > > > struct extent_buffer, leak_list); > > > > pr_err( > > > > - "BTRFS: buffer leak start %llu len %u refs %d bflags %lu owner %llu\n", > > > > - eb->start, eb->len, atomic_read(&eb->refs), eb->bflags, > > > > + "BTRFS: buffer leak start %llu refs %d bflags %lu owner %llu\n", > > > > + eb->start, atomic_read(&eb->refs), eb->bflags, > > > > btrfs_header_owner(eb)); > > > > list_del(&eb->leak_list); > > > > WARN_ON_ONCE(1); > > > > @@ -1746,8 +1746,8 @@ static noinline_for_stack bool lock_extent_buffer_for_io(struct extent_buffer *e > > > > > > > > btrfs_set_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN); > > > > percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, > > > > - -eb->len, > > > > - fs_info->dirty_metadata_batch); > > > > + -fs_info->nodesize, > > > > + fs_info->dirty_metadata_batch); > > > > ret = true; > > > > } else { > > > > spin_unlock(&eb->refs_lock); > > > > @@ -1953,7 +1953,7 @@ static unsigned int buffer_tree_get_ebs_tag(struct btrfs_fs_info *fs_info, > > > > rcu_read_lock(); > > > > while ((eb = find_get_eb(&xas, end, tag)) != NULL) { > > > > if (!eb_batch_add(batch, eb)) { > > > > - *start = (eb->start + eb->len) >> fs_info->sectorsize_bits; > > > > + *start = (eb->start + fs_info->nodesize) >> fs_info->sectorsize_bits; > > > > goto out; > > > > } > > > > } > > > > @@ -2020,7 +2020,7 @@ static void prepare_eb_write(struct extent_buffer *eb) > > > > nritems = btrfs_header_nritems(eb); > > > > if (btrfs_header_level(eb) > 0) { > > > > end = btrfs_node_key_ptr_offset(eb, nritems); > > > > - memzero_extent_buffer(eb, end, eb->len - end); > > > > + memzero_extent_buffer(eb, end, eb_len(eb) - end); > > > > } else { > > > > /* > > > > * Leaf: > > > > @@ -2056,7 +2056,7 @@ static noinline_for_stack void write_one_eb(struct extent_buffer *eb, > > > > struct folio *folio = eb->folios[i]; > > > > u64 range_start = max_t(u64, eb->start, folio_pos(folio)); > > > > u32 range_len = min_t(u64, folio_pos(folio) + folio_size(folio), > > > > - eb->start + eb->len) - range_start; > > > > + eb->start + fs_info->nodesize) - range_start; > > > > > > > > folio_lock(folio); > > > > btrfs_meta_folio_clear_dirty(folio, eb); > > > > @@ -2171,7 +2171,7 @@ int btree_write_cache_pages(struct address_space *mapping, > > > > if (ctx.zoned_bg) { > > > > /* Mark the last eb in the block group. */ > > > > btrfs_schedule_zone_finish_bg(ctx.zoned_bg, eb); > > > > - ctx.zoned_bg->meta_write_pointer += eb->len; > > > > + ctx.zoned_bg->meta_write_pointer += fs_info->nodesize; > > > > } > > > > write_one_eb(eb, wbc); > > > > } > > > > @@ -2807,7 +2807,6 @@ static struct extent_buffer *__alloc_extent_buffer(struct btrfs_fs_info *fs_info > > > > > > > > eb = kmem_cache_zalloc(extent_buffer_cache, GFP_NOFS|__GFP_NOFAIL); > > > > eb->start = start; > > > > - eb->len = fs_info->nodesize; > > > > eb->fs_info = fs_info; > > > > init_rwsem(&eb->lock); > > > > > > > > @@ -2816,8 +2815,6 @@ static struct extent_buffer *__alloc_extent_buffer(struct btrfs_fs_info *fs_info > > > > spin_lock_init(&eb->refs_lock); > > > > atomic_set(&eb->refs, 1); > > > > > > > > - ASSERT(eb->len <= BTRFS_MAX_METADATA_BLOCKSIZE); > > > > - > > > > return eb; > > > > } > > > > > > > > @@ -3505,7 +3502,7 @@ void btrfs_clear_buffer_dirty(struct btrfs_trans_handle *trans, > > > > return; > > > > > > > > buffer_tree_clear_mark(eb, PAGECACHE_TAG_DIRTY); > > > > - percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, -eb->len, > > > > + percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, -fs_info->nodesize, > > > > fs_info->dirty_metadata_batch); > > > > > > > > for (int i = 0; i < num_extent_folios(eb); i++) { > > > > @@ -3557,8 +3554,8 @@ void set_extent_buffer_dirty(struct extent_buffer *eb) > > > > if (subpage) > > > > folio_unlock(eb->folios[0]); > > > > percpu_counter_add_batch(&eb->fs_info->dirty_metadata_bytes, > > > > - eb->len, > > > > - eb->fs_info->dirty_metadata_batch); > > > > + eb_len(eb), > > > > + eb->fs_info->dirty_metadata_batch); > > > > } > > > > #ifdef CONFIG_BTRFS_DEBUG > > > > for (int i = 0; i < num_extent_folios(eb); i++) > > > > @@ -3670,7 +3667,7 @@ int read_extent_buffer_pages_nowait(struct extent_buffer *eb, int mirror_num, > > > > struct folio *folio = eb->folios[i]; > > > > u64 range_start = max_t(u64, eb->start, folio_pos(folio)); > > > > u32 range_len = min_t(u64, folio_pos(folio) + folio_size(folio), > > > > - eb->start + eb->len) - range_start; > > > > + eb->start + eb_len(eb)) - range_start; > > > > > > > > bio_add_folio_nofail(&bbio->bio, folio, range_len, > > > > offset_in_folio(folio, range_start)); > > > > @@ -3698,8 +3695,8 @@ static bool report_eb_range(const struct extent_buffer *eb, unsigned long start, > > > > unsigned long len) > > > > { > > > > btrfs_warn(eb->fs_info, > > > > - "access to eb bytenr %llu len %u out of range start %lu len %lu", > > > > - eb->start, eb->len, start, len); > > > > + "access to eb bytenr %llu out of range start %lu len %lu", > > > > + eb->start, start, len); > > > > DEBUG_WARN(); > > > > > > > > return true; > > > > @@ -3717,8 +3714,8 @@ static inline int check_eb_range(const struct extent_buffer *eb, > > > > { > > > > unsigned long offset; > > > > > > > > - /* start, start + len should not go beyond eb->len nor overflow */ > > > > - if (unlikely(check_add_overflow(start, len, &offset) || offset > eb->len)) > > > > + /* start, start + len should not go beyond nodesize nor overflow */ > > > > + if (unlikely(check_add_overflow(start, len, &offset) || offset > eb_len(eb))) > > > > return report_eb_range(eb, start, len); > > > > > > > > return false; > > > > @@ -3774,8 +3771,8 @@ int read_extent_buffer_to_user_nofault(const struct extent_buffer *eb, > > > > unsigned long i = get_eb_folio_index(eb, start); > > > > int ret = 0; > > > > > > > > - WARN_ON(start > eb->len); > > > > - WARN_ON(start + len > eb->start + eb->len); > > > > + WARN_ON(start > eb_len(eb)); > > > > + WARN_ON(start + len > eb->start + eb_len(eb)); > > > > > > > > if (eb->addr) { > > > > if (copy_to_user_nofault(dstv, eb->addr + start, len)) > > > > @@ -3866,8 +3863,8 @@ static void assert_eb_folio_uptodate(const struct extent_buffer *eb, int i) > > > > folio = eb->folios[0]; > > > > ASSERT(i == 0); > > > > if (WARN_ON(!btrfs_subpage_test_uptodate(fs_info, folio, > > > > - eb->start, eb->len))) > > > > - btrfs_subpage_dump_bitmap(fs_info, folio, eb->start, eb->len); > > > > + eb->start, fs_info->nodesize))) > > > > + btrfs_subpage_dump_bitmap(fs_info, folio, eb->start, fs_info->nodesize); > > > > } else { > > > > WARN_ON(!folio_test_uptodate(folio)); > > > > } > > > > @@ -3960,12 +3957,10 @@ void copy_extent_buffer_full(const struct extent_buffer *dst, > > > > const int unit_size = src->folio_size; > > > > unsigned long cur = 0; > > > > > > > > - ASSERT(dst->len == src->len); > > > > - > > > > - while (cur < src->len) { > > > > + while (cur < eb_len(src)) { > > > > unsigned long index = get_eb_folio_index(src, cur); > > > > unsigned long offset = get_eb_offset_in_folio(src, cur); > > > > - unsigned long cur_len = min(src->len, unit_size - offset); > > > > + unsigned long cur_len = min(eb_len(src), unit_size - offset); > > > > void *addr = folio_address(src->folios[index]) + offset; > > > > > > > > write_extent_buffer(dst, addr, cur, cur_len); > > > > @@ -3980,7 +3975,6 @@ void copy_extent_buffer(const struct extent_buffer *dst, > > > > unsigned long len) > > > > { > > > > const int unit_size = dst->folio_size; > > > > - u64 dst_len = dst->len; > > > > size_t cur; > > > > size_t offset; > > > > char *kaddr; > > > > @@ -3990,8 +3984,6 @@ void copy_extent_buffer(const struct extent_buffer *dst, > > > > check_eb_range(src, src_offset, len)) > > > > return; > > > > > > > > - WARN_ON(src->len != dst_len); > > > > - > > > > offset = get_eb_offset_in_folio(dst, dst_offset); > > > > > > > > while (len > 0) { > > > > @@ -4266,7 +4258,7 @@ static int try_release_subpage_extent_buffer(struct folio *folio) > > > > xa_unlock_irq(&fs_info->buffer_tree); > > > > break; > > > > } > > > > - cur = eb->start + eb->len; > > > > + cur = eb->start + fs_info->nodesize; > > > > > > > > /* > > > > * The same as try_release_extent_buffer(), to ensure the eb > > > > diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h > > > > index 1415679d7f88c..9a842eea47d6d 100644 > > > > --- a/fs/btrfs/extent_io.h > > > > +++ b/fs/btrfs/extent_io.h > > > > @@ -16,6 +16,7 @@ > > > > #include "messages.h" > > > > #include "ulist.h" > > > > #include "misc.h" > > > > +#include "fs.h" > > > > > > > > struct page; > > > > struct file; > > > > @@ -80,7 +81,6 @@ void __cold extent_buffer_free_cachep(void); > > > > #define INLINE_EXTENT_BUFFER_PAGES (BTRFS_MAX_METADATA_BLOCKSIZE / PAGE_SIZE) > > > > struct extent_buffer { > > > > u64 start; > > > > - u32 len; > > > > u32 folio_size; > > > > unsigned long bflags; > > > > struct btrfs_fs_info *fs_info; > > > > @@ -263,17 +263,22 @@ void btrfs_readahead_tree_block(struct btrfs_fs_info *fs_info, > > > > u64 bytenr, u64 owner_root, u64 gen, int level); > > > > void btrfs_readahead_node_child(struct extent_buffer *node, int slot); > > > > > > > > +static inline u32 eb_len(const struct extent_buffer *eb) > > > > +{ > > > > + return eb->fs_info->nodesize; > > > > +} > > > > > > Please always add a "btrfs_" prefix to the name of exported functions. > > > > It's static inline, not exported. But I'm happy just opencoding it > > instead. Thanks. > > Exported in the sense that it's in a header and visible to any C files > that include it, not in the sense of being exported with > EXPORT_SYMBOL_GPL() for example. > This is our coding style convention: > > https://btrfs.readthedocs.io/en/latest/dev/Development-notes.html#function-declarations > > static functions inside a C file can omit the prefix. Nah, thanks again. I was not aware of that. Will keep it in mind. Still, it doesn't make sense to me to be honest. I mean specifically with this example. The header file is also private to btrfs, no public API. Personally I wouldn't differentiate if it's a source or a header file. The code can be freely moved around. And with the prefix the code would end up more bloated and less readable, IMO. But let's not start any flamewars here. > > > > > In this case I don't think adding this helper adds any value. > > > We can just do eb->fs_info->nodesize everywhere and in some places we > > > already have fs_info in a local variable and can just do > > > fs_info->nodesize. > > > > > > Thanks. > > > > > > > + > > > > /* Note: this can be used in for loops without caching the value in a variable. */ > > > > static inline int __pure num_extent_pages(const struct extent_buffer *eb) > > > > { > > > > /* > > > > * For sectorsize == PAGE_SIZE case, since nodesize is always aligned to > > > > - * sectorsize, it's just eb->len >> PAGE_SHIFT. > > > > + * sectorsize, it's just nodesize >> PAGE_SHIFT. > > > > * > > > > * For sectorsize < PAGE_SIZE case, we could have nodesize < PAGE_SIZE, > > > > * thus have to ensure we get at least one page. > > > > */ > > > > - return (eb->len >> PAGE_SHIFT) ?: 1; > > > > + return (eb_len(eb) >> PAGE_SHIFT) ?: 1; > > > > } > > > > > > > > /* > > > > diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c > > > > index 68fac77fb95d1..6be2d56d44917 100644 > > > > --- a/fs/btrfs/ioctl.c > > > > +++ b/fs/btrfs/ioctl.c > > > > @@ -598,7 +598,7 @@ static noinline int create_subvol(struct mnt_idmap *idmap, > > > > btrfs_set_root_generation(root_item, trans->transid); > > > > btrfs_set_root_level(root_item, 0); > > > > btrfs_set_root_refs(root_item, 1); > > > > - btrfs_set_root_used(root_item, leaf->len); > > > > + btrfs_set_root_used(root_item, fs_info->nodesize); > > > > btrfs_set_root_last_snapshot(root_item, 0); > > > > > > > > btrfs_set_root_generation_v2(root_item, > > > > diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c > > > > index 6287e71ebad5f..5086485a4ae21 100644 > > > > --- a/fs/btrfs/relocation.c > > > > +++ b/fs/btrfs/relocation.c > > > > @@ -4352,7 +4352,7 @@ int btrfs_reloc_cow_block(struct btrfs_trans_handle *trans, > > > > mark_block_processed(rc, node); > > > > > > > > if (first_cow && level > 0) > > > > - rc->nodes_relocated += buf->len; > > > > + rc->nodes_relocated += fs_info->nodesize; > > > > } > > > > > > > > if (level == 0 && first_cow && rc->stage == UPDATE_DATA_PTRS) > > > > diff --git a/fs/btrfs/subpage.c b/fs/btrfs/subpage.c > > > > index d4f0192334936..711792f32e9ce 100644 > > > > --- a/fs/btrfs/subpage.c > > > > +++ b/fs/btrfs/subpage.c > > > > @@ -631,7 +631,7 @@ void btrfs_meta_folio_set_##name(struct folio *folio, const struct extent_buffer > > > > folio_set_func(folio); \ > > > > return; \ > > > > } \ > > > > - btrfs_subpage_set_##name(eb->fs_info, folio, eb->start, eb->len); \ > > > > + btrfs_subpage_set_##name(eb->fs_info, folio, eb->start, eb_len(eb)); \ > > > > } \ > > > > void btrfs_meta_folio_clear_##name(struct folio *folio, const struct extent_buffer *eb) \ > > > > { \ > > > > @@ -639,13 +639,13 @@ void btrfs_meta_folio_clear_##name(struct folio *folio, const struct extent_buff > > > > folio_clear_func(folio); \ > > > > return; \ > > > > } \ > > > > - btrfs_subpage_clear_##name(eb->fs_info, folio, eb->start, eb->len); \ > > > > + btrfs_subpage_clear_##name(eb->fs_info, folio, eb->start, eb_len(eb)); \ > > > > } \ > > > > bool btrfs_meta_folio_test_##name(struct folio *folio, const struct extent_buffer *eb) \ > > > > { \ > > > > if (!btrfs_meta_is_subpage(eb->fs_info)) \ > > > > return folio_test_func(folio); \ > > > > - return btrfs_subpage_test_##name(eb->fs_info, folio, eb->start, eb->len); \ > > > > + return btrfs_subpage_test_##name(eb->fs_info, folio, eb->start, eb_len(eb)); \ > > > > } > > > > IMPLEMENT_BTRFS_PAGE_OPS(uptodate, folio_mark_uptodate, folio_clear_uptodate, > > > > folio_test_uptodate); > > > > @@ -765,7 +765,7 @@ bool btrfs_meta_folio_clear_and_test_dirty(struct folio *folio, const struct ext > > > > return true; > > > > } > > > > > > > > - last = btrfs_subpage_clear_and_test_dirty(eb->fs_info, folio, eb->start, eb->len); > > > > + last = btrfs_subpage_clear_and_test_dirty(eb->fs_info, folio, eb->start, eb_len(eb)); > > > > if (last) { > > > > folio_clear_dirty_for_io(folio); > > > > return true; > > > > diff --git a/fs/btrfs/tests/extent-io-tests.c b/fs/btrfs/tests/extent-io-tests.c > > > > index 00da54f0164c9..657f8f1d9263e 100644 > > > > --- a/fs/btrfs/tests/extent-io-tests.c > > > > +++ b/fs/btrfs/tests/extent-io-tests.c > > > > @@ -342,7 +342,7 @@ static int check_eb_bitmap(unsigned long *bitmap, struct extent_buffer *eb) > > > > { > > > > unsigned long i; > > > > > > > > - for (i = 0; i < eb->len * BITS_PER_BYTE; i++) { > > > > + for (i = 0; i < eb_len(eb) * BITS_PER_BYTE; i++) { > > > > int bit, bit1; > > > > > > > > bit = !!test_bit(i, bitmap); > > > > @@ -411,7 +411,7 @@ static int test_bitmap_clear(const char *name, unsigned long *bitmap, > > > > static int __test_eb_bitmaps(unsigned long *bitmap, struct extent_buffer *eb) > > > > { > > > > unsigned long i, j; > > > > - unsigned long byte_len = eb->len; > > > > + unsigned long byte_len = eb_len(eb); > > > > u32 x; > > > > int ret; > > > > > > > > @@ -670,7 +670,7 @@ static int test_find_first_clear_extent_bit(void) > > > > static void dump_eb_and_memory_contents(struct extent_buffer *eb, void *memory, > > > > const char *test_name) > > > > { > > > > - for (int i = 0; i < eb->len; i++) { > > > > + for (int i = 0; i < eb_len(eb); i++) { > > > > struct page *page = folio_page(eb->folios[i >> PAGE_SHIFT], 0); > > > > void *addr = page_address(page) + offset_in_page(i); > > > > > > > > @@ -686,7 +686,7 @@ static void dump_eb_and_memory_contents(struct extent_buffer *eb, void *memory, > > > > static int verify_eb_and_memory(struct extent_buffer *eb, void *memory, > > > > const char *test_name) > > > > { > > > > - for (int i = 0; i < (eb->len >> PAGE_SHIFT); i++) { > > > > + for (int i = 0; i < (eb_len(eb) >> PAGE_SHIFT); i++) { > > > > void *eb_addr = folio_address(eb->folios[i]); > > > > > > > > if (memcmp(memory + (i << PAGE_SHIFT), eb_addr, PAGE_SIZE) != 0) { > > > > @@ -703,8 +703,8 @@ static int verify_eb_and_memory(struct extent_buffer *eb, void *memory, > > > > */ > > > > static void init_eb_and_memory(struct extent_buffer *eb, void *memory) > > > > { > > > > - get_random_bytes(memory, eb->len); > > > > - write_extent_buffer(eb, memory, 0, eb->len); > > > > + get_random_bytes(memory, eb_len(eb)); > > > > + write_extent_buffer(eb, memory, 0, eb_len(eb)); > > > > } > > > > > > > > static int test_eb_mem_ops(u32 sectorsize, u32 nodesize) > > > > diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c > > > > index 9d42bf2bfd746..c7a8cdd87c509 100644 > > > > --- a/fs/btrfs/zoned.c > > > > +++ b/fs/btrfs/zoned.c > > > > @@ -2422,7 +2422,7 @@ void btrfs_schedule_zone_finish_bg(struct btrfs_block_group *bg, > > > > struct extent_buffer *eb) > > > > { > > > > if (!test_bit(BLOCK_GROUP_FLAG_SEQUENTIAL_ZONE, &bg->runtime_flags) || > > > > - eb->start + eb->len * 2 <= bg->start + bg->zone_capacity) > > > > + eb->start + eb_len(eb) * 2 <= bg->start + bg->zone_capacity) > > > > return; > > > > > > > > if (WARN_ON(bg->zone_finish_work.func == btrfs_zone_finish_endio_workfn)) { > > > > -- > > > > 2.47.2 > > > > > > > > ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH] btrfs: remove extent buffer's redundant `len` member field 2025-04-30 8:50 ` Daniel Vacek @ 2025-04-30 10:26 ` Filipe Manana 2025-04-30 11:09 ` Johannes Thumshirn 2025-04-30 12:06 ` Daniel Vacek 0 siblings, 2 replies; 35+ messages in thread From: Filipe Manana @ 2025-04-30 10:26 UTC (permalink / raw) To: Daniel Vacek Cc: Chris Mason, Josef Bacik, David Sterba, linux-btrfs, linux-kernel On Wed, Apr 30, 2025 at 9:50 AM Daniel Vacek <neelx@suse.com> wrote: > > On Wed, 30 Apr 2025 at 10:34, Filipe Manana <fdmanana@kernel.org> wrote: > > > > On Wed, Apr 30, 2025 at 9:26 AM Daniel Vacek <neelx@suse.com> wrote: > > > > > > On Wed, 30 Apr 2025 at 10:06, Filipe Manana <fdmanana@kernel.org> wrote: > > > > > > > > On Tue, Apr 29, 2025 at 4:19 PM Daniel Vacek <neelx@suse.com> wrote: > > > > > > > > > > Even super block nowadays uses nodesize for eb->len. This is since commits > > > > > > > > > > 551561c34663 ("btrfs: don't pass nodesize to __alloc_extent_buffer()") > > > > > da17066c4047 ("btrfs: pull node/sector/stripe sizes out of root and into fs_info") > > > > > ce3e69847e3e ("btrfs: sink parameter len to alloc_extent_buffer") > > > > > a83fffb75d09 ("btrfs: sink blocksize parameter to btrfs_find_create_tree_block") > > > > > > > > > > With these the eb->len is not really useful anymore. Let's use the nodesize > > > > > directly where applicable. > > > > > > > > > > Signed-off-by: Daniel Vacek <neelx@suse.com> > > > > > --- > > > > > [RFC] > > > > > * Shall the eb_len() helper better be called eb_nodesize()? Or even rather > > > > > opencoded and not used at all? > > > > > > > > > > fs/btrfs/accessors.c | 4 +-- > > > > > fs/btrfs/disk-io.c | 11 ++++--- > > > > > fs/btrfs/extent-tree.c | 28 +++++++++-------- > > > > > fs/btrfs/extent_io.c | 54 ++++++++++++++------------------ > > > > > fs/btrfs/extent_io.h | 11 +++++-- > > > > > fs/btrfs/ioctl.c | 2 +- > > > > > fs/btrfs/relocation.c | 2 +- > > > > > fs/btrfs/subpage.c | 8 ++--- > > > > > fs/btrfs/tests/extent-io-tests.c | 12 +++---- > > > > > fs/btrfs/zoned.c | 2 +- > > > > > 10 files changed, 67 insertions(+), 67 deletions(-) > > > > > > > > > > diff --git a/fs/btrfs/accessors.c b/fs/btrfs/accessors.c > > > > > index e3716516ca387..a2bdbc7990906 100644 > > > > > --- a/fs/btrfs/accessors.c > > > > > +++ b/fs/btrfs/accessors.c > > > > > @@ -14,10 +14,10 @@ static bool check_setget_bounds(const struct extent_buffer *eb, > > > > > { > > > > > const unsigned long member_offset = (unsigned long)ptr + off; > > > > > > > > > > - if (unlikely(member_offset + size > eb->len)) { > > > > > + if (unlikely(member_offset + size > eb_len(eb))) { > > > > > btrfs_warn(eb->fs_info, > > > > > "bad eb member %s: ptr 0x%lx start %llu member offset %lu size %d", > > > > > - (member_offset > eb->len ? "start" : "end"), > > > > > + (member_offset > eb_len(eb) ? "start" : "end"), > > > > > (unsigned long)ptr, eb->start, member_offset, size); > > > > > return false; > > > > > } > > > > > diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c > > > > > index 3592300ae3e2e..31eb7419fe11f 100644 > > > > > --- a/fs/btrfs/disk-io.c > > > > > +++ b/fs/btrfs/disk-io.c > > > > > @@ -190,7 +190,7 @@ static int btrfs_repair_eb_io_failure(const struct extent_buffer *eb, > > > > > for (int i = 0; i < num_extent_folios(eb); i++) { > > > > > struct folio *folio = eb->folios[i]; > > > > > u64 start = max_t(u64, eb->start, folio_pos(folio)); > > > > > - u64 end = min_t(u64, eb->start + eb->len, > > > > > + u64 end = min_t(u64, eb->start + fs_info->nodesize, > > > > > folio_pos(folio) + eb->folio_size); > > > > > u32 len = end - start; > > > > > phys_addr_t paddr = PFN_PHYS(folio_pfn(folio)) + > > > > > @@ -230,7 +230,7 @@ int btrfs_read_extent_buffer(struct extent_buffer *eb, > > > > > break; > > > > > > > > > > num_copies = btrfs_num_copies(fs_info, > > > > > - eb->start, eb->len); > > > > > + eb->start, fs_info->nodesize); > > > > > if (num_copies == 1) > > > > > break; > > > > > > > > > > @@ -260,6 +260,7 @@ blk_status_t btree_csum_one_bio(struct btrfs_bio *bbio) > > > > > { > > > > > struct extent_buffer *eb = bbio->private; > > > > > struct btrfs_fs_info *fs_info = eb->fs_info; > > > > > + u32 nodesize = fs_info->nodesize; > > > > > u64 found_start = btrfs_header_bytenr(eb); > > > > > u64 last_trans; > > > > > u8 result[BTRFS_CSUM_SIZE]; > > > > > @@ -268,7 +269,7 @@ blk_status_t btree_csum_one_bio(struct btrfs_bio *bbio) > > > > > /* Btree blocks are always contiguous on disk. */ > > > > > if (WARN_ON_ONCE(bbio->file_offset != eb->start)) > > > > > return BLK_STS_IOERR; > > > > > - if (WARN_ON_ONCE(bbio->bio.bi_iter.bi_size != eb->len)) > > > > > + if (WARN_ON_ONCE(bbio->bio.bi_iter.bi_size != nodesize)) > > > > > return BLK_STS_IOERR; > > > > > > > > > > /* > > > > > @@ -277,7 +278,7 @@ blk_status_t btree_csum_one_bio(struct btrfs_bio *bbio) > > > > > * ordering of I/O without unnecessarily writing out data. > > > > > */ > > > > > if (test_bit(EXTENT_BUFFER_ZONED_ZEROOUT, &eb->bflags)) { > > > > > - memzero_extent_buffer(eb, 0, eb->len); > > > > > + memzero_extent_buffer(eb, 0, nodesize); > > > > > return BLK_STS_OK; > > > > > } > > > > > > > > > > @@ -883,7 +884,7 @@ struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans, > > > > > btrfs_set_root_generation(&root->root_item, trans->transid); > > > > > btrfs_set_root_level(&root->root_item, 0); > > > > > btrfs_set_root_refs(&root->root_item, 1); > > > > > - btrfs_set_root_used(&root->root_item, leaf->len); > > > > > + btrfs_set_root_used(&root->root_item, fs_info->nodesize); > > > > > btrfs_set_root_last_snapshot(&root->root_item, 0); > > > > > btrfs_set_root_dirid(&root->root_item, 0); > > > > > if (is_fstree(objectid)) > > > > > diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c > > > > > index e0811a86d0cbd..25560a162d93e 100644 > > > > > --- a/fs/btrfs/extent-tree.c > > > > > +++ b/fs/btrfs/extent-tree.c > > > > > @@ -2211,7 +2211,7 @@ int btrfs_set_disk_extent_flags(struct btrfs_trans_handle *trans, > > > > > extent_op->update_flags = true; > > > > > extent_op->update_key = false; > > > > > > > > > > - ret = btrfs_add_delayed_extent_op(trans, eb->start, eb->len, > > > > > + ret = btrfs_add_delayed_extent_op(trans, eb->start, eb_len(eb), > > > > > btrfs_header_level(eb), extent_op); > > > > > if (ret) > > > > > btrfs_free_delayed_extent_op(extent_op); > > > > > @@ -2660,10 +2660,10 @@ int btrfs_pin_extent_for_log_replay(struct btrfs_trans_handle *trans, > > > > > if (ret) > > > > > goto out; > > > > > > > > > > - pin_down_extent(trans, cache, eb->start, eb->len, 0); > > > > > + pin_down_extent(trans, cache, eb->start, eb_len(eb), 0); > > > > > > > > > > /* remove us from the free space cache (if we're there at all) */ > > > > > - ret = btrfs_remove_free_space(cache, eb->start, eb->len); > > > > > + ret = btrfs_remove_free_space(cache, eb->start, eb_len(eb)); > > > > > out: > > > > > btrfs_put_block_group(cache); > > > > > return ret; > > > > > @@ -3436,13 +3436,14 @@ int btrfs_free_tree_block(struct btrfs_trans_handle *trans, > > > > > { > > > > > struct btrfs_fs_info *fs_info = trans->fs_info; > > > > > struct btrfs_block_group *bg; > > > > > + u32 nodesize = fs_info->nodesize; > > > > > int ret; > > > > > > > > > > if (root_id != BTRFS_TREE_LOG_OBJECTID) { > > > > > struct btrfs_ref generic_ref = { > > > > > .action = BTRFS_DROP_DELAYED_REF, > > > > > .bytenr = buf->start, > > > > > - .num_bytes = buf->len, > > > > > + .num_bytes = nodesize, > > > > > .parent = parent, > > > > > .owning_root = btrfs_header_owner(buf), > > > > > .ref_root = root_id, > > > > > @@ -3478,7 +3479,7 @@ int btrfs_free_tree_block(struct btrfs_trans_handle *trans, > > > > > bg = btrfs_lookup_block_group(fs_info, buf->start); > > > > > > > > > > if (btrfs_header_flag(buf, BTRFS_HEADER_FLAG_WRITTEN)) { > > > > > - pin_down_extent(trans, bg, buf->start, buf->len, 1); > > > > > + pin_down_extent(trans, bg, buf->start, nodesize, 1); > > > > > btrfs_put_block_group(bg); > > > > > goto out; > > > > > } > > > > > @@ -3502,17 +3503,17 @@ int btrfs_free_tree_block(struct btrfs_trans_handle *trans, > > > > > > > > > > if (test_bit(BTRFS_FS_TREE_MOD_LOG_USERS, &fs_info->flags) > > > > > || btrfs_is_zoned(fs_info)) { > > > > > - pin_down_extent(trans, bg, buf->start, buf->len, 1); > > > > > + pin_down_extent(trans, bg, buf->start, nodesize, 1); > > > > > btrfs_put_block_group(bg); > > > > > goto out; > > > > > } > > > > > > > > > > WARN_ON(test_bit(EXTENT_BUFFER_DIRTY, &buf->bflags)); > > > > > > > > > > - btrfs_add_free_space(bg, buf->start, buf->len); > > > > > - btrfs_free_reserved_bytes(bg, buf->len, 0); > > > > > + btrfs_add_free_space(bg, buf->start, nodesize); > > > > > + btrfs_free_reserved_bytes(bg, nodesize, 0); > > > > > btrfs_put_block_group(bg); > > > > > - trace_btrfs_reserved_extent_free(fs_info, buf->start, buf->len); > > > > > + trace_btrfs_reserved_extent_free(fs_info, buf->start, nodesize); > > > > > > > > > > out: > > > > > return 0; > > > > > @@ -4768,7 +4769,7 @@ int btrfs_pin_reserved_extent(struct btrfs_trans_handle *trans, > > > > > return -ENOSPC; > > > > > } > > > > > > > > > > - ret = pin_down_extent(trans, cache, eb->start, eb->len, 1); > > > > > + ret = pin_down_extent(trans, cache, eb->start, eb_len(eb), 1); > > > > > btrfs_put_block_group(cache); > > > > > return ret; > > > > > } > > > > > @@ -5050,6 +5051,7 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root, > > > > > struct btrfs_fs_info *fs_info = root->fs_info; > > > > > struct extent_buffer *buf; > > > > > u64 lockdep_owner = owner; > > > > > + u32 nodesize = fs_info->nodesize; > > > > > > > > > > buf = btrfs_find_create_tree_block(fs_info, bytenr, owner, level); > > > > > if (IS_ERR(buf)) > > > > > @@ -5107,16 +5109,16 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root, > > > > > */ > > > > > if (buf->log_index == 0) > > > > > btrfs_set_extent_bit(&root->dirty_log_pages, buf->start, > > > > > - buf->start + buf->len - 1, > > > > > + buf->start + nodesize - 1, > > > > > EXTENT_DIRTY, NULL); > > > > > else > > > > > btrfs_set_extent_bit(&root->dirty_log_pages, buf->start, > > > > > - buf->start + buf->len - 1, > > > > > + buf->start + nodesize - 1, > > > > > EXTENT_NEW, NULL); > > > > > } else { > > > > > buf->log_index = -1; > > > > > btrfs_set_extent_bit(&trans->transaction->dirty_pages, buf->start, > > > > > - buf->start + buf->len - 1, EXTENT_DIRTY, NULL); > > > > > + buf->start + nodesize - 1, EXTENT_DIRTY, NULL); > > > > > } > > > > > /* this returns a buffer locked for blocking */ > > > > > return buf; > > > > > diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c > > > > > index 20cdddd924852..e4050fd5db285 100644 > > > > > --- a/fs/btrfs/extent_io.c > > > > > +++ b/fs/btrfs/extent_io.c > > > > > @@ -76,8 +76,8 @@ void btrfs_extent_buffer_leak_debug_check(struct btrfs_fs_info *fs_info) > > > > > eb = list_first_entry(&fs_info->allocated_ebs, > > > > > struct extent_buffer, leak_list); > > > > > pr_err( > > > > > - "BTRFS: buffer leak start %llu len %u refs %d bflags %lu owner %llu\n", > > > > > - eb->start, eb->len, atomic_read(&eb->refs), eb->bflags, > > > > > + "BTRFS: buffer leak start %llu refs %d bflags %lu owner %llu\n", > > > > > + eb->start, atomic_read(&eb->refs), eb->bflags, > > > > > btrfs_header_owner(eb)); > > > > > list_del(&eb->leak_list); > > > > > WARN_ON_ONCE(1); > > > > > @@ -1746,8 +1746,8 @@ static noinline_for_stack bool lock_extent_buffer_for_io(struct extent_buffer *e > > > > > > > > > > btrfs_set_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN); > > > > > percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, > > > > > - -eb->len, > > > > > - fs_info->dirty_metadata_batch); > > > > > + -fs_info->nodesize, > > > > > + fs_info->dirty_metadata_batch); > > > > > ret = true; > > > > > } else { > > > > > spin_unlock(&eb->refs_lock); > > > > > @@ -1953,7 +1953,7 @@ static unsigned int buffer_tree_get_ebs_tag(struct btrfs_fs_info *fs_info, > > > > > rcu_read_lock(); > > > > > while ((eb = find_get_eb(&xas, end, tag)) != NULL) { > > > > > if (!eb_batch_add(batch, eb)) { > > > > > - *start = (eb->start + eb->len) >> fs_info->sectorsize_bits; > > > > > + *start = (eb->start + fs_info->nodesize) >> fs_info->sectorsize_bits; > > > > > goto out; > > > > > } > > > > > } > > > > > @@ -2020,7 +2020,7 @@ static void prepare_eb_write(struct extent_buffer *eb) > > > > > nritems = btrfs_header_nritems(eb); > > > > > if (btrfs_header_level(eb) > 0) { > > > > > end = btrfs_node_key_ptr_offset(eb, nritems); > > > > > - memzero_extent_buffer(eb, end, eb->len - end); > > > > > + memzero_extent_buffer(eb, end, eb_len(eb) - end); > > > > > } else { > > > > > /* > > > > > * Leaf: > > > > > @@ -2056,7 +2056,7 @@ static noinline_for_stack void write_one_eb(struct extent_buffer *eb, > > > > > struct folio *folio = eb->folios[i]; > > > > > u64 range_start = max_t(u64, eb->start, folio_pos(folio)); > > > > > u32 range_len = min_t(u64, folio_pos(folio) + folio_size(folio), > > > > > - eb->start + eb->len) - range_start; > > > > > + eb->start + fs_info->nodesize) - range_start; > > > > > > > > > > folio_lock(folio); > > > > > btrfs_meta_folio_clear_dirty(folio, eb); > > > > > @@ -2171,7 +2171,7 @@ int btree_write_cache_pages(struct address_space *mapping, > > > > > if (ctx.zoned_bg) { > > > > > /* Mark the last eb in the block group. */ > > > > > btrfs_schedule_zone_finish_bg(ctx.zoned_bg, eb); > > > > > - ctx.zoned_bg->meta_write_pointer += eb->len; > > > > > + ctx.zoned_bg->meta_write_pointer += fs_info->nodesize; > > > > > } > > > > > write_one_eb(eb, wbc); > > > > > } > > > > > @@ -2807,7 +2807,6 @@ static struct extent_buffer *__alloc_extent_buffer(struct btrfs_fs_info *fs_info > > > > > > > > > > eb = kmem_cache_zalloc(extent_buffer_cache, GFP_NOFS|__GFP_NOFAIL); > > > > > eb->start = start; > > > > > - eb->len = fs_info->nodesize; > > > > > eb->fs_info = fs_info; > > > > > init_rwsem(&eb->lock); > > > > > > > > > > @@ -2816,8 +2815,6 @@ static struct extent_buffer *__alloc_extent_buffer(struct btrfs_fs_info *fs_info > > > > > spin_lock_init(&eb->refs_lock); > > > > > atomic_set(&eb->refs, 1); > > > > > > > > > > - ASSERT(eb->len <= BTRFS_MAX_METADATA_BLOCKSIZE); > > > > > - > > > > > return eb; > > > > > } > > > > > > > > > > @@ -3505,7 +3502,7 @@ void btrfs_clear_buffer_dirty(struct btrfs_trans_handle *trans, > > > > > return; > > > > > > > > > > buffer_tree_clear_mark(eb, PAGECACHE_TAG_DIRTY); > > > > > - percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, -eb->len, > > > > > + percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, -fs_info->nodesize, > > > > > fs_info->dirty_metadata_batch); > > > > > > > > > > for (int i = 0; i < num_extent_folios(eb); i++) { > > > > > @@ -3557,8 +3554,8 @@ void set_extent_buffer_dirty(struct extent_buffer *eb) > > > > > if (subpage) > > > > > folio_unlock(eb->folios[0]); > > > > > percpu_counter_add_batch(&eb->fs_info->dirty_metadata_bytes, > > > > > - eb->len, > > > > > - eb->fs_info->dirty_metadata_batch); > > > > > + eb_len(eb), > > > > > + eb->fs_info->dirty_metadata_batch); > > > > > } > > > > > #ifdef CONFIG_BTRFS_DEBUG > > > > > for (int i = 0; i < num_extent_folios(eb); i++) > > > > > @@ -3670,7 +3667,7 @@ int read_extent_buffer_pages_nowait(struct extent_buffer *eb, int mirror_num, > > > > > struct folio *folio = eb->folios[i]; > > > > > u64 range_start = max_t(u64, eb->start, folio_pos(folio)); > > > > > u32 range_len = min_t(u64, folio_pos(folio) + folio_size(folio), > > > > > - eb->start + eb->len) - range_start; > > > > > + eb->start + eb_len(eb)) - range_start; > > > > > > > > > > bio_add_folio_nofail(&bbio->bio, folio, range_len, > > > > > offset_in_folio(folio, range_start)); > > > > > @@ -3698,8 +3695,8 @@ static bool report_eb_range(const struct extent_buffer *eb, unsigned long start, > > > > > unsigned long len) > > > > > { > > > > > btrfs_warn(eb->fs_info, > > > > > - "access to eb bytenr %llu len %u out of range start %lu len %lu", > > > > > - eb->start, eb->len, start, len); > > > > > + "access to eb bytenr %llu out of range start %lu len %lu", > > > > > + eb->start, start, len); > > > > > DEBUG_WARN(); > > > > > > > > > > return true; > > > > > @@ -3717,8 +3714,8 @@ static inline int check_eb_range(const struct extent_buffer *eb, > > > > > { > > > > > unsigned long offset; > > > > > > > > > > - /* start, start + len should not go beyond eb->len nor overflow */ > > > > > - if (unlikely(check_add_overflow(start, len, &offset) || offset > eb->len)) > > > > > + /* start, start + len should not go beyond nodesize nor overflow */ > > > > > + if (unlikely(check_add_overflow(start, len, &offset) || offset > eb_len(eb))) > > > > > return report_eb_range(eb, start, len); > > > > > > > > > > return false; > > > > > @@ -3774,8 +3771,8 @@ int read_extent_buffer_to_user_nofault(const struct extent_buffer *eb, > > > > > unsigned long i = get_eb_folio_index(eb, start); > > > > > int ret = 0; > > > > > > > > > > - WARN_ON(start > eb->len); > > > > > - WARN_ON(start + len > eb->start + eb->len); > > > > > + WARN_ON(start > eb_len(eb)); > > > > > + WARN_ON(start + len > eb->start + eb_len(eb)); > > > > > > > > > > if (eb->addr) { > > > > > if (copy_to_user_nofault(dstv, eb->addr + start, len)) > > > > > @@ -3866,8 +3863,8 @@ static void assert_eb_folio_uptodate(const struct extent_buffer *eb, int i) > > > > > folio = eb->folios[0]; > > > > > ASSERT(i == 0); > > > > > if (WARN_ON(!btrfs_subpage_test_uptodate(fs_info, folio, > > > > > - eb->start, eb->len))) > > > > > - btrfs_subpage_dump_bitmap(fs_info, folio, eb->start, eb->len); > > > > > + eb->start, fs_info->nodesize))) > > > > > + btrfs_subpage_dump_bitmap(fs_info, folio, eb->start, fs_info->nodesize); > > > > > } else { > > > > > WARN_ON(!folio_test_uptodate(folio)); > > > > > } > > > > > @@ -3960,12 +3957,10 @@ void copy_extent_buffer_full(const struct extent_buffer *dst, > > > > > const int unit_size = src->folio_size; > > > > > unsigned long cur = 0; > > > > > > > > > > - ASSERT(dst->len == src->len); > > > > > - > > > > > - while (cur < src->len) { > > > > > + while (cur < eb_len(src)) { > > > > > unsigned long index = get_eb_folio_index(src, cur); > > > > > unsigned long offset = get_eb_offset_in_folio(src, cur); > > > > > - unsigned long cur_len = min(src->len, unit_size - offset); > > > > > + unsigned long cur_len = min(eb_len(src), unit_size - offset); > > > > > void *addr = folio_address(src->folios[index]) + offset; > > > > > > > > > > write_extent_buffer(dst, addr, cur, cur_len); > > > > > @@ -3980,7 +3975,6 @@ void copy_extent_buffer(const struct extent_buffer *dst, > > > > > unsigned long len) > > > > > { > > > > > const int unit_size = dst->folio_size; > > > > > - u64 dst_len = dst->len; > > > > > size_t cur; > > > > > size_t offset; > > > > > char *kaddr; > > > > > @@ -3990,8 +3984,6 @@ void copy_extent_buffer(const struct extent_buffer *dst, > > > > > check_eb_range(src, src_offset, len)) > > > > > return; > > > > > > > > > > - WARN_ON(src->len != dst_len); > > > > > - > > > > > offset = get_eb_offset_in_folio(dst, dst_offset); > > > > > > > > > > while (len > 0) { > > > > > @@ -4266,7 +4258,7 @@ static int try_release_subpage_extent_buffer(struct folio *folio) > > > > > xa_unlock_irq(&fs_info->buffer_tree); > > > > > break; > > > > > } > > > > > - cur = eb->start + eb->len; > > > > > + cur = eb->start + fs_info->nodesize; > > > > > > > > > > /* > > > > > * The same as try_release_extent_buffer(), to ensure the eb > > > > > diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h > > > > > index 1415679d7f88c..9a842eea47d6d 100644 > > > > > --- a/fs/btrfs/extent_io.h > > > > > +++ b/fs/btrfs/extent_io.h > > > > > @@ -16,6 +16,7 @@ > > > > > #include "messages.h" > > > > > #include "ulist.h" > > > > > #include "misc.h" > > > > > +#include "fs.h" > > > > > > > > > > struct page; > > > > > struct file; > > > > > @@ -80,7 +81,6 @@ void __cold extent_buffer_free_cachep(void); > > > > > #define INLINE_EXTENT_BUFFER_PAGES (BTRFS_MAX_METADATA_BLOCKSIZE / PAGE_SIZE) > > > > > struct extent_buffer { > > > > > u64 start; > > > > > - u32 len; > > > > > u32 folio_size; > > > > > unsigned long bflags; > > > > > struct btrfs_fs_info *fs_info; > > > > > @@ -263,17 +263,22 @@ void btrfs_readahead_tree_block(struct btrfs_fs_info *fs_info, > > > > > u64 bytenr, u64 owner_root, u64 gen, int level); > > > > > void btrfs_readahead_node_child(struct extent_buffer *node, int slot); > > > > > > > > > > +static inline u32 eb_len(const struct extent_buffer *eb) > > > > > +{ > > > > > + return eb->fs_info->nodesize; > > > > > +} > > > > > > > > Please always add a "btrfs_" prefix to the name of exported functions. > > > > > > It's static inline, not exported. But I'm happy just opencoding it > > > instead. Thanks. > > > > Exported in the sense that it's in a header and visible to any C files > > that include it, not in the sense of being exported with > > EXPORT_SYMBOL_GPL() for example. > > This is our coding style convention: > > > > https://btrfs.readthedocs.io/en/latest/dev/Development-notes.html#function-declarations > > > > static functions inside a C file can omit the prefix. > > Nah, thanks again. I was not aware of that. Will keep it in mind. > > Still, it doesn't make sense to me to be honest. I mean specifically > with this example. The header file is also private to btrfs, no public > API. Personally I wouldn't differentiate if it's a source or a header > file. The code can be freely moved around. And with the prefix the > code would end up more bloated and less readable, IMO. But let's not > start any flamewars here. I'd disagree about less readability. Reading code that calls a function with the btrfs prefix makes it clear it's a btrfs specific function. Looking at ext4 and xfs, functions declared or defined in their headers have a "ext4_", "ext_" or "xfs_" prefix. > > > > > > > > In this case I don't think adding this helper adds any value. > > > > We can just do eb->fs_info->nodesize everywhere and in some places we > > > > already have fs_info in a local variable and can just do > > > > fs_info->nodesize. > > > > > > > > Thanks. > > > > > > > > > + > > > > > /* Note: this can be used in for loops without caching the value in a variable. */ > > > > > static inline int __pure num_extent_pages(const struct extent_buffer *eb) > > > > > { > > > > > /* > > > > > * For sectorsize == PAGE_SIZE case, since nodesize is always aligned to > > > > > - * sectorsize, it's just eb->len >> PAGE_SHIFT. > > > > > + * sectorsize, it's just nodesize >> PAGE_SHIFT. > > > > > * > > > > > * For sectorsize < PAGE_SIZE case, we could have nodesize < PAGE_SIZE, > > > > > * thus have to ensure we get at least one page. > > > > > */ > > > > > - return (eb->len >> PAGE_SHIFT) ?: 1; > > > > > + return (eb_len(eb) >> PAGE_SHIFT) ?: 1; > > > > > } > > > > > > > > > > /* > > > > > diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c > > > > > index 68fac77fb95d1..6be2d56d44917 100644 > > > > > --- a/fs/btrfs/ioctl.c > > > > > +++ b/fs/btrfs/ioctl.c > > > > > @@ -598,7 +598,7 @@ static noinline int create_subvol(struct mnt_idmap *idmap, > > > > > btrfs_set_root_generation(root_item, trans->transid); > > > > > btrfs_set_root_level(root_item, 0); > > > > > btrfs_set_root_refs(root_item, 1); > > > > > - btrfs_set_root_used(root_item, leaf->len); > > > > > + btrfs_set_root_used(root_item, fs_info->nodesize); > > > > > btrfs_set_root_last_snapshot(root_item, 0); > > > > > > > > > > btrfs_set_root_generation_v2(root_item, > > > > > diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c > > > > > index 6287e71ebad5f..5086485a4ae21 100644 > > > > > --- a/fs/btrfs/relocation.c > > > > > +++ b/fs/btrfs/relocation.c > > > > > @@ -4352,7 +4352,7 @@ int btrfs_reloc_cow_block(struct btrfs_trans_handle *trans, > > > > > mark_block_processed(rc, node); > > > > > > > > > > if (first_cow && level > 0) > > > > > - rc->nodes_relocated += buf->len; > > > > > + rc->nodes_relocated += fs_info->nodesize; > > > > > } > > > > > > > > > > if (level == 0 && first_cow && rc->stage == UPDATE_DATA_PTRS) > > > > > diff --git a/fs/btrfs/subpage.c b/fs/btrfs/subpage.c > > > > > index d4f0192334936..711792f32e9ce 100644 > > > > > --- a/fs/btrfs/subpage.c > > > > > +++ b/fs/btrfs/subpage.c > > > > > @@ -631,7 +631,7 @@ void btrfs_meta_folio_set_##name(struct folio *folio, const struct extent_buffer > > > > > folio_set_func(folio); \ > > > > > return; \ > > > > > } \ > > > > > - btrfs_subpage_set_##name(eb->fs_info, folio, eb->start, eb->len); \ > > > > > + btrfs_subpage_set_##name(eb->fs_info, folio, eb->start, eb_len(eb)); \ > > > > > } \ > > > > > void btrfs_meta_folio_clear_##name(struct folio *folio, const struct extent_buffer *eb) \ > > > > > { \ > > > > > @@ -639,13 +639,13 @@ void btrfs_meta_folio_clear_##name(struct folio *folio, const struct extent_buff > > > > > folio_clear_func(folio); \ > > > > > return; \ > > > > > } \ > > > > > - btrfs_subpage_clear_##name(eb->fs_info, folio, eb->start, eb->len); \ > > > > > + btrfs_subpage_clear_##name(eb->fs_info, folio, eb->start, eb_len(eb)); \ > > > > > } \ > > > > > bool btrfs_meta_folio_test_##name(struct folio *folio, const struct extent_buffer *eb) \ > > > > > { \ > > > > > if (!btrfs_meta_is_subpage(eb->fs_info)) \ > > > > > return folio_test_func(folio); \ > > > > > - return btrfs_subpage_test_##name(eb->fs_info, folio, eb->start, eb->len); \ > > > > > + return btrfs_subpage_test_##name(eb->fs_info, folio, eb->start, eb_len(eb)); \ > > > > > } > > > > > IMPLEMENT_BTRFS_PAGE_OPS(uptodate, folio_mark_uptodate, folio_clear_uptodate, > > > > > folio_test_uptodate); > > > > > @@ -765,7 +765,7 @@ bool btrfs_meta_folio_clear_and_test_dirty(struct folio *folio, const struct ext > > > > > return true; > > > > > } > > > > > > > > > > - last = btrfs_subpage_clear_and_test_dirty(eb->fs_info, folio, eb->start, eb->len); > > > > > + last = btrfs_subpage_clear_and_test_dirty(eb->fs_info, folio, eb->start, eb_len(eb)); > > > > > if (last) { > > > > > folio_clear_dirty_for_io(folio); > > > > > return true; > > > > > diff --git a/fs/btrfs/tests/extent-io-tests.c b/fs/btrfs/tests/extent-io-tests.c > > > > > index 00da54f0164c9..657f8f1d9263e 100644 > > > > > --- a/fs/btrfs/tests/extent-io-tests.c > > > > > +++ b/fs/btrfs/tests/extent-io-tests.c > > > > > @@ -342,7 +342,7 @@ static int check_eb_bitmap(unsigned long *bitmap, struct extent_buffer *eb) > > > > > { > > > > > unsigned long i; > > > > > > > > > > - for (i = 0; i < eb->len * BITS_PER_BYTE; i++) { > > > > > + for (i = 0; i < eb_len(eb) * BITS_PER_BYTE; i++) { > > > > > int bit, bit1; > > > > > > > > > > bit = !!test_bit(i, bitmap); > > > > > @@ -411,7 +411,7 @@ static int test_bitmap_clear(const char *name, unsigned long *bitmap, > > > > > static int __test_eb_bitmaps(unsigned long *bitmap, struct extent_buffer *eb) > > > > > { > > > > > unsigned long i, j; > > > > > - unsigned long byte_len = eb->len; > > > > > + unsigned long byte_len = eb_len(eb); > > > > > u32 x; > > > > > int ret; > > > > > > > > > > @@ -670,7 +670,7 @@ static int test_find_first_clear_extent_bit(void) > > > > > static void dump_eb_and_memory_contents(struct extent_buffer *eb, void *memory, > > > > > const char *test_name) > > > > > { > > > > > - for (int i = 0; i < eb->len; i++) { > > > > > + for (int i = 0; i < eb_len(eb); i++) { > > > > > struct page *page = folio_page(eb->folios[i >> PAGE_SHIFT], 0); > > > > > void *addr = page_address(page) + offset_in_page(i); > > > > > > > > > > @@ -686,7 +686,7 @@ static void dump_eb_and_memory_contents(struct extent_buffer *eb, void *memory, > > > > > static int verify_eb_and_memory(struct extent_buffer *eb, void *memory, > > > > > const char *test_name) > > > > > { > > > > > - for (int i = 0; i < (eb->len >> PAGE_SHIFT); i++) { > > > > > + for (int i = 0; i < (eb_len(eb) >> PAGE_SHIFT); i++) { > > > > > void *eb_addr = folio_address(eb->folios[i]); > > > > > > > > > > if (memcmp(memory + (i << PAGE_SHIFT), eb_addr, PAGE_SIZE) != 0) { > > > > > @@ -703,8 +703,8 @@ static int verify_eb_and_memory(struct extent_buffer *eb, void *memory, > > > > > */ > > > > > static void init_eb_and_memory(struct extent_buffer *eb, void *memory) > > > > > { > > > > > - get_random_bytes(memory, eb->len); > > > > > - write_extent_buffer(eb, memory, 0, eb->len); > > > > > + get_random_bytes(memory, eb_len(eb)); > > > > > + write_extent_buffer(eb, memory, 0, eb_len(eb)); > > > > > } > > > > > > > > > > static int test_eb_mem_ops(u32 sectorsize, u32 nodesize) > > > > > diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c > > > > > index 9d42bf2bfd746..c7a8cdd87c509 100644 > > > > > --- a/fs/btrfs/zoned.c > > > > > +++ b/fs/btrfs/zoned.c > > > > > @@ -2422,7 +2422,7 @@ void btrfs_schedule_zone_finish_bg(struct btrfs_block_group *bg, > > > > > struct extent_buffer *eb) > > > > > { > > > > > if (!test_bit(BLOCK_GROUP_FLAG_SEQUENTIAL_ZONE, &bg->runtime_flags) || > > > > > - eb->start + eb->len * 2 <= bg->start + bg->zone_capacity) > > > > > + eb->start + eb_len(eb) * 2 <= bg->start + bg->zone_capacity) > > > > > return; > > > > > > > > > > if (WARN_ON(bg->zone_finish_work.func == btrfs_zone_finish_endio_workfn)) { > > > > > -- > > > > > 2.47.2 > > > > > > > > > > ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH] btrfs: remove extent buffer's redundant `len` member field 2025-04-30 10:26 ` Filipe Manana @ 2025-04-30 11:09 ` Johannes Thumshirn 2025-04-30 12:09 ` Daniel Vacek 2025-04-30 12:06 ` Daniel Vacek 1 sibling, 1 reply; 35+ messages in thread From: Johannes Thumshirn @ 2025-04-30 11:09 UTC (permalink / raw) To: Filipe Manana Cc: Daniel Vacek, Chris Mason, Josef Bacik, David Sterba, linux-btrfs, linux-kernel On Wed, Apr 30, 2025 at 11:26:08AM +0100, Filipe Manana wrote: > On Wed, Apr 30, 2025 at 9:50 AM Daniel Vacek <neelx@suse.com> wrote: > > > > Nah, thanks again. I was not aware of that. Will keep it in mind. > > > > Still, it doesn't make sense to me to be honest. I mean specifically > > with this example. The header file is also private to btrfs, no public > > API. Personally I wouldn't differentiate if it's a source or a header > > file. The code can be freely moved around. And with the prefix the > > code would end up more bloated and less readable, IMO. But let's not > > start any flamewars here. > > I'd disagree about less readability. Reading code that calls a > function with the btrfs prefix makes it clear it's a btrfs specific > function. > Looking at ext4 and xfs, functions declared or defined in their > headers have a "ext4_", "ext_" or "xfs_" prefix. To add my $.02 here, it is also a matter of namespacing. There's nothing more anoying than having two functions with the same name in different subsystems. IIRC we did have this with the in_range() function, that is available globally and there has been a btrfs specific as well. Byte, Johannes ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH] btrfs: remove extent buffer's redundant `len` member field 2025-04-30 11:09 ` Johannes Thumshirn @ 2025-04-30 12:09 ` Daniel Vacek 0 siblings, 0 replies; 35+ messages in thread From: Daniel Vacek @ 2025-04-30 12:09 UTC (permalink / raw) To: Johannes Thumshirn Cc: Filipe Manana, Chris Mason, Josef Bacik, David Sterba, linux-btrfs, linux-kernel On Wed, 30 Apr 2025 at 13:09, Johannes Thumshirn <morbidrsa@gmail.com> wrote: > > On Wed, Apr 30, 2025 at 11:26:08AM +0100, Filipe Manana wrote: > > On Wed, Apr 30, 2025 at 9:50 AM Daniel Vacek <neelx@suse.com> wrote: > > > > > > Nah, thanks again. I was not aware of that. Will keep it in mind. > > > > > > Still, it doesn't make sense to me to be honest. I mean specifically > > > with this example. The header file is also private to btrfs, no public > > > API. Personally I wouldn't differentiate if it's a source or a header > > > file. The code can be freely moved around. And with the prefix the > > > code would end up more bloated and less readable, IMO. But let's not > > > start any flamewars here. > > > > I'd disagree about less readability. Reading code that calls a > > function with the btrfs prefix makes it clear it's a btrfs specific > > function. > > Looking at ext4 and xfs, functions declared or defined in their > > headers have a "ext4_", "ext_" or "xfs_" prefix. > > To add my $.02 here, it is also a matter of namespacing. There's nothing more > anoying than having two functions with the same name in different subsystems. > IIRC we did have this with the in_range() function, that is available globally > and there has been a btrfs specific as well. Yeah, I've been there. Unloading debug symbols of some module(s) from the debugger due to collisions/aliases. That indeed can be very annoying. > Byte, > Johannes ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH] btrfs: remove extent buffer's redundant `len` member field 2025-04-30 10:26 ` Filipe Manana 2025-04-30 11:09 ` Johannes Thumshirn @ 2025-04-30 12:06 ` Daniel Vacek 2025-04-30 12:33 ` Filipe Manana 1 sibling, 1 reply; 35+ messages in thread From: Daniel Vacek @ 2025-04-30 12:06 UTC (permalink / raw) To: Filipe Manana Cc: Chris Mason, Josef Bacik, David Sterba, linux-btrfs, linux-kernel On Wed, 30 Apr 2025 at 12:26, Filipe Manana <fdmanana@kernel.org> wrote: > > On Wed, Apr 30, 2025 at 9:50 AM Daniel Vacek <neelx@suse.com> wrote: > > > > On Wed, 30 Apr 2025 at 10:34, Filipe Manana <fdmanana@kernel.org> wrote: > > > > > > On Wed, Apr 30, 2025 at 9:26 AM Daniel Vacek <neelx@suse.com> wrote: > > > > > > > > On Wed, 30 Apr 2025 at 10:06, Filipe Manana <fdmanana@kernel.org> wrote: > > > > > > > > > > On Tue, Apr 29, 2025 at 4:19 PM Daniel Vacek <neelx@suse.com> wrote: > > > > > > > > > > > > Even super block nowadays uses nodesize for eb->len. This is since commits > > > > > > > > > > > > 551561c34663 ("btrfs: don't pass nodesize to __alloc_extent_buffer()") > > > > > > da17066c4047 ("btrfs: pull node/sector/stripe sizes out of root and into fs_info") > > > > > > ce3e69847e3e ("btrfs: sink parameter len to alloc_extent_buffer") > > > > > > a83fffb75d09 ("btrfs: sink blocksize parameter to btrfs_find_create_tree_block") > > > > > > > > > > > > With these the eb->len is not really useful anymore. Let's use the nodesize > > > > > > directly where applicable. > > > > > > > > > > > > Signed-off-by: Daniel Vacek <neelx@suse.com> > > > > > > --- > > > > > > [RFC] > > > > > > * Shall the eb_len() helper better be called eb_nodesize()? Or even rather > > > > > > opencoded and not used at all? ... > > > > > > +static inline u32 eb_len(const struct extent_buffer *eb) > > > > > > +{ > > > > > > + return eb->fs_info->nodesize; > > > > > > +} > > > > > > > > > > Please always add a "btrfs_" prefix to the name of exported functions. > > > > > > > > It's static inline, not exported. But I'm happy just opencoding it > > > > instead. Thanks. > > > > > > Exported in the sense that it's in a header and visible to any C files > > > that include it, not in the sense of being exported with > > > EXPORT_SYMBOL_GPL() for example. > > > This is our coding style convention: > > > > > > https://btrfs.readthedocs.io/en/latest/dev/Development-notes.html#function-declarations > > > > > > static functions inside a C file can omit the prefix. > > > > Nah, thanks again. I was not aware of that. Will keep it in mind. > > > > Still, it doesn't make sense to me to be honest. I mean specifically > > with this example. The header file is also private to btrfs, no public > > API. Personally I wouldn't differentiate if it's a source or a header > > file. The code can be freely moved around. And with the prefix the > > code would end up more bloated and less readable, IMO. But let's not > > start any flamewars here. > > I'd disagree about less readability. Reading code that calls a > function with the btrfs prefix makes it clear it's a btrfs specific > function. > Looking at ext4 and xfs, functions declared or defined in their > headers have a "ext4_", "ext_" or "xfs_" prefix. I see. Makes sense. Does this also apply to preprocessor macros? I don't see them mentioned in the development notes. I'm asking as I did consider using a macro which would look a bit cleaner perhaps, just one line instead of four. But it would also miss the type checking. So I guess the naming convention should also apply to macros, right? Finally quickly checking I see a lot of functions like eg. free_extent_buffer(), free_extent_buffer_stale() and many others violating the rule. I guess we should also clean up and rename them, right? > > > > > In this case I don't think adding this helper adds any value. > > > > > We can just do eb->fs_info->nodesize everywhere and in some places we > > > > > already have fs_info in a local variable and can just do > > > > > fs_info->nodesize. > > > > > > > > > > Thanks. > > > > > > > > > > > + > > > > > > /* Note: this can be used in for loops without caching the value in a variable. */ > > > > > > static inline int __pure num_extent_pages(const struct extent_buffer *eb) > > > > > > { > > > > > > /* > > > > > > * For sectorsize == PAGE_SIZE case, since nodesize is always aligned to > > > > > > - * sectorsize, it's just eb->len >> PAGE_SHIFT. > > > > > > + * sectorsize, it's just nodesize >> PAGE_SHIFT. > > > > > > * > > > > > > * For sectorsize < PAGE_SIZE case, we could have nodesize < PAGE_SIZE, > > > > > > * thus have to ensure we get at least one page. > > > > > > */ > > > > > > - return (eb->len >> PAGE_SHIFT) ?: 1; > > > > > > + return (eb_len(eb) >> PAGE_SHIFT) ?: 1; > > > > > > } > > > > > > > > > > > > /* > > > > > > diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c > > > > > > index 68fac77fb95d1..6be2d56d44917 100644 > > > > > > --- a/fs/btrfs/ioctl.c > > > > > > +++ b/fs/btrfs/ioctl.c > > > > > > @@ -598,7 +598,7 @@ static noinline int create_subvol(struct mnt_idmap *idmap, > > > > > > btrfs_set_root_generation(root_item, trans->transid); > > > > > > btrfs_set_root_level(root_item, 0); > > > > > > btrfs_set_root_refs(root_item, 1); > > > > > > - btrfs_set_root_used(root_item, leaf->len); > > > > > > + btrfs_set_root_used(root_item, fs_info->nodesize); > > > > > > btrfs_set_root_last_snapshot(root_item, 0); > > > > > > > > > > > > btrfs_set_root_generation_v2(root_item, > > > > > > diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c > > > > > > index 6287e71ebad5f..5086485a4ae21 100644 > > > > > > --- a/fs/btrfs/relocation.c > > > > > > +++ b/fs/btrfs/relocation.c > > > > > > @@ -4352,7 +4352,7 @@ int btrfs_reloc_cow_block(struct btrfs_trans_handle *trans, > > > > > > mark_block_processed(rc, node); > > > > > > > > > > > > if (first_cow && level > 0) > > > > > > - rc->nodes_relocated += buf->len; > > > > > > + rc->nodes_relocated += fs_info->nodesize; > > > > > > } > > > > > > > > > > > > if (level == 0 && first_cow && rc->stage == UPDATE_DATA_PTRS) > > > > > > diff --git a/fs/btrfs/subpage.c b/fs/btrfs/subpage.c > > > > > > index d4f0192334936..711792f32e9ce 100644 > > > > > > --- a/fs/btrfs/subpage.c > > > > > > +++ b/fs/btrfs/subpage.c > > > > > > @@ -631,7 +631,7 @@ void btrfs_meta_folio_set_##name(struct folio *folio, const struct extent_buffer > > > > > > folio_set_func(folio); \ > > > > > > return; \ > > > > > > } \ > > > > > > - btrfs_subpage_set_##name(eb->fs_info, folio, eb->start, eb->len); \ > > > > > > + btrfs_subpage_set_##name(eb->fs_info, folio, eb->start, eb_len(eb)); \ > > > > > > } \ > > > > > > void btrfs_meta_folio_clear_##name(struct folio *folio, const struct extent_buffer *eb) \ > > > > > > { \ > > > > > > @@ -639,13 +639,13 @@ void btrfs_meta_folio_clear_##name(struct folio *folio, const struct extent_buff > > > > > > folio_clear_func(folio); \ > > > > > > return; \ > > > > > > } \ > > > > > > - btrfs_subpage_clear_##name(eb->fs_info, folio, eb->start, eb->len); \ > > > > > > + btrfs_subpage_clear_##name(eb->fs_info, folio, eb->start, eb_len(eb)); \ > > > > > > } \ > > > > > > bool btrfs_meta_folio_test_##name(struct folio *folio, const struct extent_buffer *eb) \ > > > > > > { \ > > > > > > if (!btrfs_meta_is_subpage(eb->fs_info)) \ > > > > > > return folio_test_func(folio); \ > > > > > > - return btrfs_subpage_test_##name(eb->fs_info, folio, eb->start, eb->len); \ > > > > > > + return btrfs_subpage_test_##name(eb->fs_info, folio, eb->start, eb_len(eb)); \ > > > > > > } > > > > > > IMPLEMENT_BTRFS_PAGE_OPS(uptodate, folio_mark_uptodate, folio_clear_uptodate, > > > > > > folio_test_uptodate); > > > > > > @@ -765,7 +765,7 @@ bool btrfs_meta_folio_clear_and_test_dirty(struct folio *folio, const struct ext > > > > > > return true; > > > > > > } > > > > > > > > > > > > - last = btrfs_subpage_clear_and_test_dirty(eb->fs_info, folio, eb->start, eb->len); > > > > > > + last = btrfs_subpage_clear_and_test_dirty(eb->fs_info, folio, eb->start, eb_len(eb)); > > > > > > if (last) { > > > > > > folio_clear_dirty_for_io(folio); > > > > > > return true; > > > > > > diff --git a/fs/btrfs/tests/extent-io-tests.c b/fs/btrfs/tests/extent-io-tests.c > > > > > > index 00da54f0164c9..657f8f1d9263e 100644 > > > > > > --- a/fs/btrfs/tests/extent-io-tests.c > > > > > > +++ b/fs/btrfs/tests/extent-io-tests.c > > > > > > @@ -342,7 +342,7 @@ static int check_eb_bitmap(unsigned long *bitmap, struct extent_buffer *eb) > > > > > > { > > > > > > unsigned long i; > > > > > > > > > > > > - for (i = 0; i < eb->len * BITS_PER_BYTE; i++) { > > > > > > + for (i = 0; i < eb_len(eb) * BITS_PER_BYTE; i++) { > > > > > > int bit, bit1; > > > > > > > > > > > > bit = !!test_bit(i, bitmap); > > > > > > @@ -411,7 +411,7 @@ static int test_bitmap_clear(const char *name, unsigned long *bitmap, > > > > > > static int __test_eb_bitmaps(unsigned long *bitmap, struct extent_buffer *eb) > > > > > > { > > > > > > unsigned long i, j; > > > > > > - unsigned long byte_len = eb->len; > > > > > > + unsigned long byte_len = eb_len(eb); > > > > > > u32 x; > > > > > > int ret; > > > > > > > > > > > > @@ -670,7 +670,7 @@ static int test_find_first_clear_extent_bit(void) > > > > > > static void dump_eb_and_memory_contents(struct extent_buffer *eb, void *memory, > > > > > > const char *test_name) > > > > > > { > > > > > > - for (int i = 0; i < eb->len; i++) { > > > > > > + for (int i = 0; i < eb_len(eb); i++) { > > > > > > struct page *page = folio_page(eb->folios[i >> PAGE_SHIFT], 0); > > > > > > void *addr = page_address(page) + offset_in_page(i); > > > > > > > > > > > > @@ -686,7 +686,7 @@ static void dump_eb_and_memory_contents(struct extent_buffer *eb, void *memory, > > > > > > static int verify_eb_and_memory(struct extent_buffer *eb, void *memory, > > > > > > const char *test_name) > > > > > > { > > > > > > - for (int i = 0; i < (eb->len >> PAGE_SHIFT); i++) { > > > > > > + for (int i = 0; i < (eb_len(eb) >> PAGE_SHIFT); i++) { > > > > > > void *eb_addr = folio_address(eb->folios[i]); > > > > > > > > > > > > if (memcmp(memory + (i << PAGE_SHIFT), eb_addr, PAGE_SIZE) != 0) { > > > > > > @@ -703,8 +703,8 @@ static int verify_eb_and_memory(struct extent_buffer *eb, void *memory, > > > > > > */ > > > > > > static void init_eb_and_memory(struct extent_buffer *eb, void *memory) > > > > > > { > > > > > > - get_random_bytes(memory, eb->len); > > > > > > - write_extent_buffer(eb, memory, 0, eb->len); > > > > > > + get_random_bytes(memory, eb_len(eb)); > > > > > > + write_extent_buffer(eb, memory, 0, eb_len(eb)); > > > > > > } > > > > > > > > > > > > static int test_eb_mem_ops(u32 sectorsize, u32 nodesize) > > > > > > diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c > > > > > > index 9d42bf2bfd746..c7a8cdd87c509 100644 > > > > > > --- a/fs/btrfs/zoned.c > > > > > > +++ b/fs/btrfs/zoned.c > > > > > > @@ -2422,7 +2422,7 @@ void btrfs_schedule_zone_finish_bg(struct btrfs_block_group *bg, > > > > > > struct extent_buffer *eb) > > > > > > { > > > > > > if (!test_bit(BLOCK_GROUP_FLAG_SEQUENTIAL_ZONE, &bg->runtime_flags) || > > > > > > - eb->start + eb->len * 2 <= bg->start + bg->zone_capacity) > > > > > > + eb->start + eb_len(eb) * 2 <= bg->start + bg->zone_capacity) > > > > > > return; > > > > > > > > > > > > if (WARN_ON(bg->zone_finish_work.func == btrfs_zone_finish_endio_workfn)) { > > > > > > -- > > > > > > 2.47.2 > > > > > > > > > > > > ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH] btrfs: remove extent buffer's redundant `len` member field 2025-04-30 12:06 ` Daniel Vacek @ 2025-04-30 12:33 ` Filipe Manana 2025-04-30 12:53 ` Daniel Vacek 0 siblings, 1 reply; 35+ messages in thread From: Filipe Manana @ 2025-04-30 12:33 UTC (permalink / raw) To: Daniel Vacek Cc: Chris Mason, Josef Bacik, David Sterba, linux-btrfs, linux-kernel On Wed, Apr 30, 2025 at 1:06 PM Daniel Vacek <neelx@suse.com> wrote: > > On Wed, 30 Apr 2025 at 12:26, Filipe Manana <fdmanana@kernel.org> wrote: > > > > On Wed, Apr 30, 2025 at 9:50 AM Daniel Vacek <neelx@suse.com> wrote: > > > > > > On Wed, 30 Apr 2025 at 10:34, Filipe Manana <fdmanana@kernel.org> wrote: > > > > > > > > On Wed, Apr 30, 2025 at 9:26 AM Daniel Vacek <neelx@suse.com> wrote: > > > > > > > > > > On Wed, 30 Apr 2025 at 10:06, Filipe Manana <fdmanana@kernel.org> wrote: > > > > > > > > > > > > On Tue, Apr 29, 2025 at 4:19 PM Daniel Vacek <neelx@suse.com> wrote: > > > > > > > > > > > > > > Even super block nowadays uses nodesize for eb->len. This is since commits > > > > > > > > > > > > > > 551561c34663 ("btrfs: don't pass nodesize to __alloc_extent_buffer()") > > > > > > > da17066c4047 ("btrfs: pull node/sector/stripe sizes out of root and into fs_info") > > > > > > > ce3e69847e3e ("btrfs: sink parameter len to alloc_extent_buffer") > > > > > > > a83fffb75d09 ("btrfs: sink blocksize parameter to btrfs_find_create_tree_block") > > > > > > > > > > > > > > With these the eb->len is not really useful anymore. Let's use the nodesize > > > > > > > directly where applicable. > > > > > > > > > > > > > > Signed-off-by: Daniel Vacek <neelx@suse.com> > > > > > > > --- > > > > > > > [RFC] > > > > > > > * Shall the eb_len() helper better be called eb_nodesize()? Or even rather > > > > > > > opencoded and not used at all? > ... > > > > > > > +static inline u32 eb_len(const struct extent_buffer *eb) > > > > > > > +{ > > > > > > > + return eb->fs_info->nodesize; > > > > > > > +} > > > > > > > > > > > > Please always add a "btrfs_" prefix to the name of exported functions. > > > > > > > > > > It's static inline, not exported. But I'm happy just opencoding it > > > > > instead. Thanks. > > > > > > > > Exported in the sense that it's in a header and visible to any C files > > > > that include it, not in the sense of being exported with > > > > EXPORT_SYMBOL_GPL() for example. > > > > This is our coding style convention: > > > > > > > > https://btrfs.readthedocs.io/en/latest/dev/Development-notes.html#function-declarations > > > > > > > > static functions inside a C file can omit the prefix. > > > > > > Nah, thanks again. I was not aware of that. Will keep it in mind. > > > > > > Still, it doesn't make sense to me to be honest. I mean specifically > > > with this example. The header file is also private to btrfs, no public > > > API. Personally I wouldn't differentiate if it's a source or a header > > > file. The code can be freely moved around. And with the prefix the > > > code would end up more bloated and less readable, IMO. But let's not > > > start any flamewars here. > > > > I'd disagree about less readability. Reading code that calls a > > function with the btrfs prefix makes it clear it's a btrfs specific > > function. > > Looking at ext4 and xfs, functions declared or defined in their > > headers have a "ext4_", "ext_" or "xfs_" prefix. > > I see. Makes sense. > Does this also apply to preprocessor macros? I don't see them > mentioned in the development notes. > I'm asking as I did consider using a macro which would look a bit > cleaner perhaps, just one line instead of four. But it would also miss > the type checking. > So I guess the naming convention should also apply to macros, right? > > Finally quickly checking I see a lot of functions like eg. > free_extent_buffer(), free_extent_buffer_stale() and many others > violating the rule. I guess we should also clean up and rename them, > right? Haven't you seen patchsets from me in the last few weeks renaming functions from extent-io-tree.h and extent_map.h? You'll see examples of where the prefix is missing, and this happens for very old code, we rename things from time to time. In those two cases I was motivated due to the need to add more functions soon, or having added some new ones not long ago, to make everything consistent in those headers/modules by making sure all have the "btrfs_" prefix. > > > > > > > In this case I don't think adding this helper adds any value. > > > > > > We can just do eb->fs_info->nodesize everywhere and in some places we > > > > > > already have fs_info in a local variable and can just do > > > > > > fs_info->nodesize. > > > > > > > > > > > > Thanks. > > > > > > > > > > > > > + > > > > > > > /* Note: this can be used in for loops without caching the value in a variable. */ > > > > > > > static inline int __pure num_extent_pages(const struct extent_buffer *eb) > > > > > > > { > > > > > > > /* > > > > > > > * For sectorsize == PAGE_SIZE case, since nodesize is always aligned to > > > > > > > - * sectorsize, it's just eb->len >> PAGE_SHIFT. > > > > > > > + * sectorsize, it's just nodesize >> PAGE_SHIFT. > > > > > > > * > > > > > > > * For sectorsize < PAGE_SIZE case, we could have nodesize < PAGE_SIZE, > > > > > > > * thus have to ensure we get at least one page. > > > > > > > */ > > > > > > > - return (eb->len >> PAGE_SHIFT) ?: 1; > > > > > > > + return (eb_len(eb) >> PAGE_SHIFT) ?: 1; > > > > > > > } > > > > > > > > > > > > > > /* > > > > > > > diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c > > > > > > > index 68fac77fb95d1..6be2d56d44917 100644 > > > > > > > --- a/fs/btrfs/ioctl.c > > > > > > > +++ b/fs/btrfs/ioctl.c > > > > > > > @@ -598,7 +598,7 @@ static noinline int create_subvol(struct mnt_idmap *idmap, > > > > > > > btrfs_set_root_generation(root_item, trans->transid); > > > > > > > btrfs_set_root_level(root_item, 0); > > > > > > > btrfs_set_root_refs(root_item, 1); > > > > > > > - btrfs_set_root_used(root_item, leaf->len); > > > > > > > + btrfs_set_root_used(root_item, fs_info->nodesize); > > > > > > > btrfs_set_root_last_snapshot(root_item, 0); > > > > > > > > > > > > > > btrfs_set_root_generation_v2(root_item, > > > > > > > diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c > > > > > > > index 6287e71ebad5f..5086485a4ae21 100644 > > > > > > > --- a/fs/btrfs/relocation.c > > > > > > > +++ b/fs/btrfs/relocation.c > > > > > > > @@ -4352,7 +4352,7 @@ int btrfs_reloc_cow_block(struct btrfs_trans_handle *trans, > > > > > > > mark_block_processed(rc, node); > > > > > > > > > > > > > > if (first_cow && level > 0) > > > > > > > - rc->nodes_relocated += buf->len; > > > > > > > + rc->nodes_relocated += fs_info->nodesize; > > > > > > > } > > > > > > > > > > > > > > if (level == 0 && first_cow && rc->stage == UPDATE_DATA_PTRS) > > > > > > > diff --git a/fs/btrfs/subpage.c b/fs/btrfs/subpage.c > > > > > > > index d4f0192334936..711792f32e9ce 100644 > > > > > > > --- a/fs/btrfs/subpage.c > > > > > > > +++ b/fs/btrfs/subpage.c > > > > > > > @@ -631,7 +631,7 @@ void btrfs_meta_folio_set_##name(struct folio *folio, const struct extent_buffer > > > > > > > folio_set_func(folio); \ > > > > > > > return; \ > > > > > > > } \ > > > > > > > - btrfs_subpage_set_##name(eb->fs_info, folio, eb->start, eb->len); \ > > > > > > > + btrfs_subpage_set_##name(eb->fs_info, folio, eb->start, eb_len(eb)); \ > > > > > > > } \ > > > > > > > void btrfs_meta_folio_clear_##name(struct folio *folio, const struct extent_buffer *eb) \ > > > > > > > { \ > > > > > > > @@ -639,13 +639,13 @@ void btrfs_meta_folio_clear_##name(struct folio *folio, const struct extent_buff > > > > > > > folio_clear_func(folio); \ > > > > > > > return; \ > > > > > > > } \ > > > > > > > - btrfs_subpage_clear_##name(eb->fs_info, folio, eb->start, eb->len); \ > > > > > > > + btrfs_subpage_clear_##name(eb->fs_info, folio, eb->start, eb_len(eb)); \ > > > > > > > } \ > > > > > > > bool btrfs_meta_folio_test_##name(struct folio *folio, const struct extent_buffer *eb) \ > > > > > > > { \ > > > > > > > if (!btrfs_meta_is_subpage(eb->fs_info)) \ > > > > > > > return folio_test_func(folio); \ > > > > > > > - return btrfs_subpage_test_##name(eb->fs_info, folio, eb->start, eb->len); \ > > > > > > > + return btrfs_subpage_test_##name(eb->fs_info, folio, eb->start, eb_len(eb)); \ > > > > > > > } > > > > > > > IMPLEMENT_BTRFS_PAGE_OPS(uptodate, folio_mark_uptodate, folio_clear_uptodate, > > > > > > > folio_test_uptodate); > > > > > > > @@ -765,7 +765,7 @@ bool btrfs_meta_folio_clear_and_test_dirty(struct folio *folio, const struct ext > > > > > > > return true; > > > > > > > } > > > > > > > > > > > > > > - last = btrfs_subpage_clear_and_test_dirty(eb->fs_info, folio, eb->start, eb->len); > > > > > > > + last = btrfs_subpage_clear_and_test_dirty(eb->fs_info, folio, eb->start, eb_len(eb)); > > > > > > > if (last) { > > > > > > > folio_clear_dirty_for_io(folio); > > > > > > > return true; > > > > > > > diff --git a/fs/btrfs/tests/extent-io-tests.c b/fs/btrfs/tests/extent-io-tests.c > > > > > > > index 00da54f0164c9..657f8f1d9263e 100644 > > > > > > > --- a/fs/btrfs/tests/extent-io-tests.c > > > > > > > +++ b/fs/btrfs/tests/extent-io-tests.c > > > > > > > @@ -342,7 +342,7 @@ static int check_eb_bitmap(unsigned long *bitmap, struct extent_buffer *eb) > > > > > > > { > > > > > > > unsigned long i; > > > > > > > > > > > > > > - for (i = 0; i < eb->len * BITS_PER_BYTE; i++) { > > > > > > > + for (i = 0; i < eb_len(eb) * BITS_PER_BYTE; i++) { > > > > > > > int bit, bit1; > > > > > > > > > > > > > > bit = !!test_bit(i, bitmap); > > > > > > > @@ -411,7 +411,7 @@ static int test_bitmap_clear(const char *name, unsigned long *bitmap, > > > > > > > static int __test_eb_bitmaps(unsigned long *bitmap, struct extent_buffer *eb) > > > > > > > { > > > > > > > unsigned long i, j; > > > > > > > - unsigned long byte_len = eb->len; > > > > > > > + unsigned long byte_len = eb_len(eb); > > > > > > > u32 x; > > > > > > > int ret; > > > > > > > > > > > > > > @@ -670,7 +670,7 @@ static int test_find_first_clear_extent_bit(void) > > > > > > > static void dump_eb_and_memory_contents(struct extent_buffer *eb, void *memory, > > > > > > > const char *test_name) > > > > > > > { > > > > > > > - for (int i = 0; i < eb->len; i++) { > > > > > > > + for (int i = 0; i < eb_len(eb); i++) { > > > > > > > struct page *page = folio_page(eb->folios[i >> PAGE_SHIFT], 0); > > > > > > > void *addr = page_address(page) + offset_in_page(i); > > > > > > > > > > > > > > @@ -686,7 +686,7 @@ static void dump_eb_and_memory_contents(struct extent_buffer *eb, void *memory, > > > > > > > static int verify_eb_and_memory(struct extent_buffer *eb, void *memory, > > > > > > > const char *test_name) > > > > > > > { > > > > > > > - for (int i = 0; i < (eb->len >> PAGE_SHIFT); i++) { > > > > > > > + for (int i = 0; i < (eb_len(eb) >> PAGE_SHIFT); i++) { > > > > > > > void *eb_addr = folio_address(eb->folios[i]); > > > > > > > > > > > > > > if (memcmp(memory + (i << PAGE_SHIFT), eb_addr, PAGE_SIZE) != 0) { > > > > > > > @@ -703,8 +703,8 @@ static int verify_eb_and_memory(struct extent_buffer *eb, void *memory, > > > > > > > */ > > > > > > > static void init_eb_and_memory(struct extent_buffer *eb, void *memory) > > > > > > > { > > > > > > > - get_random_bytes(memory, eb->len); > > > > > > > - write_extent_buffer(eb, memory, 0, eb->len); > > > > > > > + get_random_bytes(memory, eb_len(eb)); > > > > > > > + write_extent_buffer(eb, memory, 0, eb_len(eb)); > > > > > > > } > > > > > > > > > > > > > > static int test_eb_mem_ops(u32 sectorsize, u32 nodesize) > > > > > > > diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c > > > > > > > index 9d42bf2bfd746..c7a8cdd87c509 100644 > > > > > > > --- a/fs/btrfs/zoned.c > > > > > > > +++ b/fs/btrfs/zoned.c > > > > > > > @@ -2422,7 +2422,7 @@ void btrfs_schedule_zone_finish_bg(struct btrfs_block_group *bg, > > > > > > > struct extent_buffer *eb) > > > > > > > { > > > > > > > if (!test_bit(BLOCK_GROUP_FLAG_SEQUENTIAL_ZONE, &bg->runtime_flags) || > > > > > > > - eb->start + eb->len * 2 <= bg->start + bg->zone_capacity) > > > > > > > + eb->start + eb_len(eb) * 2 <= bg->start + bg->zone_capacity) > > > > > > > return; > > > > > > > > > > > > > > if (WARN_ON(bg->zone_finish_work.func == btrfs_zone_finish_endio_workfn)) { > > > > > > > -- > > > > > > > 2.47.2 > > > > > > > > > > > > > > ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH] btrfs: remove extent buffer's redundant `len` member field 2025-04-30 12:33 ` Filipe Manana @ 2025-04-30 12:53 ` Daniel Vacek 0 siblings, 0 replies; 35+ messages in thread From: Daniel Vacek @ 2025-04-30 12:53 UTC (permalink / raw) To: Filipe Manana Cc: Chris Mason, Josef Bacik, David Sterba, linux-btrfs, linux-kernel On Wed, 30 Apr 2025 at 14:34, Filipe Manana <fdmanana@kernel.org> wrote: > > On Wed, Apr 30, 2025 at 1:06 PM Daniel Vacek <neelx@suse.com> wrote: > > > > On Wed, 30 Apr 2025 at 12:26, Filipe Manana <fdmanana@kernel.org> wrote: > > > > > > On Wed, Apr 30, 2025 at 9:50 AM Daniel Vacek <neelx@suse.com> wrote: > > > > > > > > On Wed, 30 Apr 2025 at 10:34, Filipe Manana <fdmanana@kernel.org> wrote: > > > > > > > > > > On Wed, Apr 30, 2025 at 9:26 AM Daniel Vacek <neelx@suse.com> wrote: > > > > > > > > > > > > On Wed, 30 Apr 2025 at 10:06, Filipe Manana <fdmanana@kernel.org> wrote: > > > > > > > > > > > > > > On Tue, Apr 29, 2025 at 4:19 PM Daniel Vacek <neelx@suse.com> wrote: > > > > > > > > > > > > > > > > Even super block nowadays uses nodesize for eb->len. This is since commits > > > > > > > > > > > > > > > > 551561c34663 ("btrfs: don't pass nodesize to __alloc_extent_buffer()") > > > > > > > > da17066c4047 ("btrfs: pull node/sector/stripe sizes out of root and into fs_info") > > > > > > > > ce3e69847e3e ("btrfs: sink parameter len to alloc_extent_buffer") > > > > > > > > a83fffb75d09 ("btrfs: sink blocksize parameter to btrfs_find_create_tree_block") > > > > > > > > > > > > > > > > With these the eb->len is not really useful anymore. Let's use the nodesize > > > > > > > > directly where applicable. > > > > > > > > > > > > > > > > Signed-off-by: Daniel Vacek <neelx@suse.com> > > > > > > > > --- > > > > > > > > [RFC] > > > > > > > > * Shall the eb_len() helper better be called eb_nodesize()? Or even rather > > > > > > > > opencoded and not used at all? > > ... > > > > > > > > +static inline u32 eb_len(const struct extent_buffer *eb) > > > > > > > > +{ > > > > > > > > + return eb->fs_info->nodesize; > > > > > > > > +} > > > > > > > > > > > > > > Please always add a "btrfs_" prefix to the name of exported functions. > > > > > > > > > > > > It's static inline, not exported. But I'm happy just opencoding it > > > > > > instead. Thanks. > > > > > > > > > > Exported in the sense that it's in a header and visible to any C files > > > > > that include it, not in the sense of being exported with > > > > > EXPORT_SYMBOL_GPL() for example. > > > > > This is our coding style convention: > > > > > > > > > > https://btrfs.readthedocs.io/en/latest/dev/Development-notes.html#function-declarations > > > > > > > > > > static functions inside a C file can omit the prefix. > > > > > > > > Nah, thanks again. I was not aware of that. Will keep it in mind. > > > > > > > > Still, it doesn't make sense to me to be honest. I mean specifically > > > > with this example. The header file is also private to btrfs, no public > > > > API. Personally I wouldn't differentiate if it's a source or a header > > > > file. The code can be freely moved around. And with the prefix the > > > > code would end up more bloated and less readable, IMO. But let's not > > > > start any flamewars here. > > > > > > I'd disagree about less readability. Reading code that calls a > > > function with the btrfs prefix makes it clear it's a btrfs specific > > > function. > > > Looking at ext4 and xfs, functions declared or defined in their > > > headers have a "ext4_", "ext_" or "xfs_" prefix. > > > > I see. Makes sense. > > Does this also apply to preprocessor macros? I don't see them > > mentioned in the development notes. > > I'm asking as I did consider using a macro which would look a bit > > cleaner perhaps, just one line instead of four. But it would also miss > > the type checking. > > So I guess the naming convention should also apply to macros, right? > > > > Finally quickly checking I see a lot of functions like eg. > > free_extent_buffer(), free_extent_buffer_stale() and many others > > violating the rule. I guess we should also clean up and rename them, > > right? > > Haven't you seen patchsets from me in the last few weeks renaming > functions from extent-io-tree.h and extent_map.h? Yeah, I noticed and I like them. That's great stuff. I think we're moving in the right direction. > You'll see examples of where the prefix is missing, and this happens > for very old code, we rename things from time to time. > In those two cases I was motivated due to the need to add more > functions soon, or having added some new ones not long ago, to make > everything consistent in those headers/modules by making sure all have > the "btrfs_" prefix. ^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH v2 0/2] btrfs: eb struct cleanups 2025-04-29 15:17 [PATCH] btrfs: remove extent buffer's redundant `len` member field Daniel Vacek ` (2 preceding siblings ...) 2025-04-30 8:05 ` Filipe Manana @ 2025-05-02 13:37 ` Daniel Vacek 2025-05-02 13:37 ` [PATCH v2 1/2] btrfs: remove extent buffer's redundant `len` member field Daniel Vacek 2025-05-02 13:37 ` [PATCH v2 " Daniel Vacek 3 siblings, 2 replies; 35+ messages in thread From: Daniel Vacek @ 2025-05-02 13:37 UTC (permalink / raw) To: David Sterba; +Cc: Daniel Vacek, linux-btrfs, linux-kernel This series is about the first patch. See the details there. The second patch is just a small followup size optimization. v1 is here: https://lore.kernel.org/linux-btrfs/20250429151800.649010-1-neelx@suse.com/ To: David Sterba <dsterba@suse.com> Cc: linux-btrfs@vger.kernel.org Cc: linux-kernel@vger.kernel.org Daniel Vacek (2): btrfs: remove extent buffer's redundant `len` member field btrfs: rearrange the extent buffer structure members fs/btrfs/accessors.c | 4 +-- fs/btrfs/disk-io.c | 11 +++--- fs/btrfs/extent-tree.c | 28 ++++++++------- fs/btrfs/extent_io.c | 59 ++++++++++++++------------------ fs/btrfs/extent_io.h | 12 +++---- fs/btrfs/ioctl.c | 2 +- fs/btrfs/relocation.c | 2 +- fs/btrfs/subpage.c | 12 ++++--- fs/btrfs/tests/extent-io-tests.c | 12 +++---- fs/btrfs/zoned.c | 2 +- 10 files changed, 72 insertions(+), 72 deletions(-) -- 2.47.2 ^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH v2 1/2] btrfs: remove extent buffer's redundant `len` member field 2025-05-02 13:37 ` [PATCH v2 0/2] btrfs: eb struct cleanups Daniel Vacek @ 2025-05-02 13:37 ` Daniel Vacek 2025-05-02 17:35 ` Boris Burkov 2025-05-05 11:50 ` [PATCH v3 0/2] btrfs: eb struct cleanups Daniel Vacek 2025-05-02 13:37 ` [PATCH v2 " Daniel Vacek 1 sibling, 2 replies; 35+ messages in thread From: Daniel Vacek @ 2025-05-02 13:37 UTC (permalink / raw) To: David Sterba, Chris Mason, Josef Bacik Cc: Daniel Vacek, linux-btrfs, linux-kernel Even super block nowadays uses nodesize for eb->len. This is since commits 551561c34663 ("btrfs: don't pass nodesize to __alloc_extent_buffer()") da17066c4047 ("btrfs: pull node/sector/stripe sizes out of root and into fs_info") ce3e69847e3e ("btrfs: sink parameter len to alloc_extent_buffer") a83fffb75d09 ("btrfs: sink blocksize parameter to btrfs_find_create_tree_block") With these the eb->len is not really useful anymore. Let's use the nodesize directly where applicable. Signed-off-by: Daniel Vacek <neelx@suse.com> --- v2 changes: - rebased to this week's for-next - use plain eb->fs_info->nodesize instead of a helper function as suggested by Filipe and Wenruo - constify local nodesize variables as suggested by Wenruo --- fs/btrfs/accessors.c | 4 +-- fs/btrfs/disk-io.c | 11 +++--- fs/btrfs/extent-tree.c | 28 ++++++++------- fs/btrfs/extent_io.c | 59 ++++++++++++++------------------ fs/btrfs/extent_io.h | 6 ++-- fs/btrfs/ioctl.c | 2 +- fs/btrfs/relocation.c | 2 +- fs/btrfs/subpage.c | 12 ++++--- fs/btrfs/tests/extent-io-tests.c | 12 +++---- fs/btrfs/zoned.c | 2 +- 10 files changed, 69 insertions(+), 69 deletions(-) diff --git a/fs/btrfs/accessors.c b/fs/btrfs/accessors.c index e3716516ca387..6839251b09a18 100644 --- a/fs/btrfs/accessors.c +++ b/fs/btrfs/accessors.c @@ -14,10 +14,10 @@ static bool check_setget_bounds(const struct extent_buffer *eb, { const unsigned long member_offset = (unsigned long)ptr + off; - if (unlikely(member_offset + size > eb->len)) { + if (unlikely(member_offset + size > eb->fs_info->nodesize)) { btrfs_warn(eb->fs_info, "bad eb member %s: ptr 0x%lx start %llu member offset %lu size %d", - (member_offset > eb->len ? "start" : "end"), + (member_offset > eb->fs_info->nodesize ? "start" : "end"), (unsigned long)ptr, eb->start, member_offset, size); return false; } diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 308e8f384ecbb..2bf4df92474cb 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -190,7 +190,7 @@ static int btrfs_repair_eb_io_failure(const struct extent_buffer *eb, for (int i = 0; i < num_extent_folios(eb); i++) { struct folio *folio = eb->folios[i]; u64 start = max_t(u64, eb->start, folio_pos(folio)); - u64 end = min_t(u64, eb->start + eb->len, + u64 end = min_t(u64, eb->start + fs_info->nodesize, folio_pos(folio) + eb->folio_size); u32 len = end - start; phys_addr_t paddr = PFN_PHYS(folio_pfn(folio)) + @@ -230,7 +230,7 @@ int btrfs_read_extent_buffer(struct extent_buffer *eb, break; num_copies = btrfs_num_copies(fs_info, - eb->start, eb->len); + eb->start, fs_info->nodesize); if (num_copies == 1) break; @@ -260,6 +260,7 @@ int btree_csum_one_bio(struct btrfs_bio *bbio) { struct extent_buffer *eb = bbio->private; struct btrfs_fs_info *fs_info = eb->fs_info; + const u32 nodesize = fs_info->nodesize; u64 found_start = btrfs_header_bytenr(eb); u64 last_trans; u8 result[BTRFS_CSUM_SIZE]; @@ -268,7 +269,7 @@ int btree_csum_one_bio(struct btrfs_bio *bbio) /* Btree blocks are always contiguous on disk. */ if (WARN_ON_ONCE(bbio->file_offset != eb->start)) return -EIO; - if (WARN_ON_ONCE(bbio->bio.bi_iter.bi_size != eb->len)) + if (WARN_ON_ONCE(bbio->bio.bi_iter.bi_size != fs_info->nodesize)) return -EIO; /* @@ -277,7 +278,7 @@ int btree_csum_one_bio(struct btrfs_bio *bbio) * ordering of I/O without unnecessarily writing out data. */ if (test_bit(EXTENT_BUFFER_ZONED_ZEROOUT, &eb->bflags)) { - memzero_extent_buffer(eb, 0, eb->len); + memzero_extent_buffer(eb, 0, nodesize); return 0; } @@ -881,7 +882,7 @@ struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans, btrfs_set_root_generation(&root->root_item, trans->transid); btrfs_set_root_level(&root->root_item, 0); btrfs_set_root_refs(&root->root_item, 1); - btrfs_set_root_used(&root->root_item, leaf->len); + btrfs_set_root_used(&root->root_item, fs_info->nodesize); btrfs_set_root_last_snapshot(&root->root_item, 0); btrfs_set_root_dirid(&root->root_item, 0); if (is_fstree(objectid)) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 527bffab75e5c..7b90ed007ef2e 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -2186,7 +2186,7 @@ int btrfs_set_disk_extent_flags(struct btrfs_trans_handle *trans, extent_op->update_flags = true; extent_op->update_key = false; - ret = btrfs_add_delayed_extent_op(trans, eb->start, eb->len, + ret = btrfs_add_delayed_extent_op(trans, eb->start, eb->fs_info->nodesize, btrfs_header_level(eb), extent_op); if (ret) btrfs_free_delayed_extent_op(extent_op); @@ -2635,10 +2635,10 @@ int btrfs_pin_extent_for_log_replay(struct btrfs_trans_handle *trans, if (ret) goto out; - pin_down_extent(trans, cache, eb->start, eb->len, 0); + pin_down_extent(trans, cache, eb->start, eb->fs_info->nodesize, 0); /* remove us from the free space cache (if we're there at all) */ - ret = btrfs_remove_free_space(cache, eb->start, eb->len); + ret = btrfs_remove_free_space(cache, eb->start, eb->fs_info->nodesize); out: btrfs_put_block_group(cache); return ret; @@ -3434,13 +3434,14 @@ int btrfs_free_tree_block(struct btrfs_trans_handle *trans, { struct btrfs_fs_info *fs_info = trans->fs_info; struct btrfs_block_group *bg; + const u32 nodesize = fs_info->nodesize; int ret; if (root_id != BTRFS_TREE_LOG_OBJECTID) { struct btrfs_ref generic_ref = { .action = BTRFS_DROP_DELAYED_REF, .bytenr = buf->start, - .num_bytes = buf->len, + .num_bytes = nodesize, .parent = parent, .owning_root = btrfs_header_owner(buf), .ref_root = root_id, @@ -3476,7 +3477,7 @@ int btrfs_free_tree_block(struct btrfs_trans_handle *trans, bg = btrfs_lookup_block_group(fs_info, buf->start); if (btrfs_header_flag(buf, BTRFS_HEADER_FLAG_WRITTEN)) { - pin_down_extent(trans, bg, buf->start, buf->len, 1); + pin_down_extent(trans, bg, buf->start, nodesize, 1); btrfs_put_block_group(bg); goto out; } @@ -3500,17 +3501,17 @@ int btrfs_free_tree_block(struct btrfs_trans_handle *trans, if (test_bit(BTRFS_FS_TREE_MOD_LOG_USERS, &fs_info->flags) || btrfs_is_zoned(fs_info)) { - pin_down_extent(trans, bg, buf->start, buf->len, 1); + pin_down_extent(trans, bg, buf->start, nodesize, 1); btrfs_put_block_group(bg); goto out; } WARN_ON(test_bit(EXTENT_BUFFER_DIRTY, &buf->bflags)); - btrfs_add_free_space(bg, buf->start, buf->len); - btrfs_free_reserved_bytes(bg, buf->len, 0); + btrfs_add_free_space(bg, buf->start, nodesize); + btrfs_free_reserved_bytes(bg, nodesize, 0); btrfs_put_block_group(bg); - trace_btrfs_reserved_extent_free(fs_info, buf->start, buf->len); + trace_btrfs_reserved_extent_free(fs_info, buf->start, nodesize); out: return 0; @@ -4752,7 +4753,7 @@ int btrfs_pin_reserved_extent(struct btrfs_trans_handle *trans, return -ENOSPC; } - ret = pin_down_extent(trans, cache, eb->start, eb->len, 1); + ret = pin_down_extent(trans, cache, eb->start, eb->fs_info->nodesize, 1); btrfs_put_block_group(cache); return ret; } @@ -5034,6 +5035,7 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_fs_info *fs_info = root->fs_info; struct extent_buffer *buf; u64 lockdep_owner = owner; + const u32 nodesize = fs_info->nodesize; buf = btrfs_find_create_tree_block(fs_info, bytenr, owner, level); if (IS_ERR(buf)) @@ -5091,16 +5093,16 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root, */ if (buf->log_index == 0) btrfs_set_extent_bit(&root->dirty_log_pages, buf->start, - buf->start + buf->len - 1, + buf->start + nodesize - 1, EXTENT_DIRTY, NULL); else btrfs_set_extent_bit(&root->dirty_log_pages, buf->start, - buf->start + buf->len - 1, + buf->start + nodesize - 1, EXTENT_NEW, NULL); } else { buf->log_index = -1; btrfs_set_extent_bit(&trans->transaction->dirty_pages, buf->start, - buf->start + buf->len - 1, EXTENT_DIRTY, NULL); + buf->start + nodesize - 1, EXTENT_DIRTY, NULL); } /* this returns a buffer locked for blocking */ return buf; diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index d889d8fcf1d27..a34644bb4b146 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -76,8 +76,8 @@ void btrfs_extent_buffer_leak_debug_check(struct btrfs_fs_info *fs_info) eb = list_first_entry(&fs_info->allocated_ebs, struct extent_buffer, leak_list); pr_err( - "BTRFS: buffer leak start %llu len %u refs %d bflags %lu owner %llu\n", - eb->start, eb->len, atomic_read(&eb->refs), eb->bflags, + "BTRFS: buffer leak start %llu refs %d bflags %lu owner %llu\n", + eb->start, atomic_read(&eb->refs), eb->bflags, btrfs_header_owner(eb)); list_del(&eb->leak_list); WARN_ON_ONCE(1); @@ -1788,8 +1788,8 @@ static noinline_for_stack bool lock_extent_buffer_for_io(struct extent_buffer *e btrfs_set_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN); percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, - -eb->len, - fs_info->dirty_metadata_batch); + -fs_info->nodesize, + fs_info->dirty_metadata_batch); ret = true; } else { spin_unlock(&eb->refs_lock); @@ -1986,7 +1986,7 @@ static unsigned int buffer_tree_get_ebs_tag(struct btrfs_fs_info *fs_info, rcu_read_lock(); while ((eb = find_get_eb(&xas, end, tag)) != NULL) { if (!eb_batch_add(batch, eb)) { - *start = (eb->start + eb->len) >> fs_info->sectorsize_bits; + *start = (eb->start + fs_info->nodesize) >> fs_info->sectorsize_bits; goto out; } } @@ -2050,7 +2050,7 @@ static void prepare_eb_write(struct extent_buffer *eb) nritems = btrfs_header_nritems(eb); if (btrfs_header_level(eb) > 0) { end = btrfs_node_key_ptr_offset(eb, nritems); - memzero_extent_buffer(eb, end, eb->len - end); + memzero_extent_buffer(eb, end, eb->fs_info->nodesize - end); } else { /* * Leaf: @@ -2086,7 +2086,7 @@ static noinline_for_stack void write_one_eb(struct extent_buffer *eb, struct folio *folio = eb->folios[i]; u64 range_start = max_t(u64, eb->start, folio_pos(folio)); u32 range_len = min_t(u64, folio_pos(folio) + folio_size(folio), - eb->start + eb->len) - range_start; + eb->start + fs_info->nodesize) - range_start; folio_lock(folio); btrfs_meta_folio_clear_dirty(folio, eb); @@ -2200,7 +2200,7 @@ int btree_write_cache_pages(struct address_space *mapping, if (ctx.zoned_bg) { /* Mark the last eb in the block group. */ btrfs_schedule_zone_finish_bg(ctx.zoned_bg, eb); - ctx.zoned_bg->meta_write_pointer += eb->len; + ctx.zoned_bg->meta_write_pointer += fs_info->nodesize; } write_one_eb(eb, wbc); } @@ -2836,7 +2836,6 @@ static struct extent_buffer *__alloc_extent_buffer(struct btrfs_fs_info *fs_info eb = kmem_cache_zalloc(extent_buffer_cache, GFP_NOFS|__GFP_NOFAIL); eb->start = start; - eb->len = fs_info->nodesize; eb->fs_info = fs_info; init_rwsem(&eb->lock); @@ -2845,8 +2844,6 @@ static struct extent_buffer *__alloc_extent_buffer(struct btrfs_fs_info *fs_info spin_lock_init(&eb->refs_lock); atomic_set(&eb->refs, 1); - ASSERT(eb->len <= BTRFS_MAX_METADATA_BLOCKSIZE); - return eb; } @@ -3558,7 +3555,7 @@ void btrfs_clear_buffer_dirty(struct btrfs_trans_handle *trans, return; buffer_tree_clear_mark(eb, PAGECACHE_TAG_DIRTY); - percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, -eb->len, + percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, -fs_info->nodesize, fs_info->dirty_metadata_batch); for (int i = 0; i < num_extent_folios(eb); i++) { @@ -3589,7 +3586,8 @@ void set_extent_buffer_dirty(struct extent_buffer *eb) WARN_ON(test_bit(EXTENT_BUFFER_ZONED_ZEROOUT, &eb->bflags)); if (!was_dirty) { - bool subpage = btrfs_meta_is_subpage(eb->fs_info); + struct btrfs_fs_info *fs_info = eb->fs_info; + bool subpage = btrfs_meta_is_subpage(fs_info); /* * For subpage case, we can have other extent buffers in the @@ -3609,9 +3607,9 @@ void set_extent_buffer_dirty(struct extent_buffer *eb) buffer_tree_set_mark(eb, PAGECACHE_TAG_DIRTY); if (subpage) folio_unlock(eb->folios[0]); - percpu_counter_add_batch(&eb->fs_info->dirty_metadata_bytes, - eb->len, - eb->fs_info->dirty_metadata_batch); + percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, + fs_info->nodesize, + fs_info->dirty_metadata_batch); } #ifdef CONFIG_BTRFS_DEBUG for (int i = 0; i < num_extent_folios(eb); i++) @@ -3723,7 +3721,7 @@ int read_extent_buffer_pages_nowait(struct extent_buffer *eb, int mirror_num, struct folio *folio = eb->folios[i]; u64 range_start = max_t(u64, eb->start, folio_pos(folio)); u32 range_len = min_t(u64, folio_pos(folio) + folio_size(folio), - eb->start + eb->len) - range_start; + eb->start + eb->fs_info->nodesize) - range_start; bio_add_folio_nofail(&bbio->bio, folio, range_len, offset_in_folio(folio, range_start)); @@ -3751,8 +3749,8 @@ static bool report_eb_range(const struct extent_buffer *eb, unsigned long start, unsigned long len) { btrfs_warn(eb->fs_info, - "access to eb bytenr %llu len %u out of range start %lu len %lu", - eb->start, eb->len, start, len); + "access to eb bytenr %llu out of range start %lu len %lu", + eb->start, start, len); DEBUG_WARN(); return true; @@ -3770,8 +3768,8 @@ static inline int check_eb_range(const struct extent_buffer *eb, { unsigned long offset; - /* start, start + len should not go beyond eb->len nor overflow */ - if (unlikely(check_add_overflow(start, len, &offset) || offset > eb->len)) + /* start, start + len should not go beyond nodesize nor overflow */ + if (unlikely(check_add_overflow(start, len, &offset) || offset > eb->fs_info->nodesize)) return report_eb_range(eb, start, len); return false; @@ -3827,8 +3825,8 @@ int read_extent_buffer_to_user_nofault(const struct extent_buffer *eb, unsigned long i = get_eb_folio_index(eb, start); int ret = 0; - WARN_ON(start > eb->len); - WARN_ON(start + len > eb->start + eb->len); + WARN_ON(start > eb->fs_info->nodesize); + WARN_ON(start + len > eb->start + eb->fs_info->nodesize); if (eb->addr) { if (copy_to_user_nofault(dstv, eb->addr + start, len)) @@ -3919,8 +3917,8 @@ static void assert_eb_folio_uptodate(const struct extent_buffer *eb, int i) folio = eb->folios[0]; ASSERT(i == 0); if (WARN_ON(!btrfs_subpage_test_uptodate(fs_info, folio, - eb->start, eb->len))) - btrfs_subpage_dump_bitmap(fs_info, folio, eb->start, eb->len); + eb->start, fs_info->nodesize))) + btrfs_subpage_dump_bitmap(fs_info, folio, eb->start, fs_info->nodesize); } else { WARN_ON(!folio_test_uptodate(folio)); } @@ -4013,12 +4011,10 @@ void copy_extent_buffer_full(const struct extent_buffer *dst, const int unit_size = src->folio_size; unsigned long cur = 0; - ASSERT(dst->len == src->len); - - while (cur < src->len) { + while (cur < src->fs_info->nodesize) { unsigned long index = get_eb_folio_index(src, cur); unsigned long offset = get_eb_offset_in_folio(src, cur); - unsigned long cur_len = min(src->len, unit_size - offset); + unsigned long cur_len = min(src->fs_info->nodesize, unit_size - offset); void *addr = folio_address(src->folios[index]) + offset; write_extent_buffer(dst, addr, cur, cur_len); @@ -4033,7 +4029,6 @@ void copy_extent_buffer(const struct extent_buffer *dst, unsigned long len) { const int unit_size = dst->folio_size; - u64 dst_len = dst->len; size_t cur; size_t offset; char *kaddr; @@ -4043,8 +4038,6 @@ void copy_extent_buffer(const struct extent_buffer *dst, check_eb_range(src, src_offset, len)) return; - WARN_ON(src->len != dst_len); - offset = get_eb_offset_in_folio(dst, dst_offset); while (len > 0) { @@ -4315,7 +4308,7 @@ static int try_release_subpage_extent_buffer(struct folio *folio) xa_unlock_irq(&fs_info->buffer_tree); break; } - cur = eb->start + eb->len; + cur = eb->start + fs_info->nodesize; /* * The same as try_release_extent_buffer(), to ensure the eb diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index e36e8d6a00bc5..7a8451c11630a 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h @@ -16,6 +16,7 @@ #include "messages.h" #include "ulist.h" #include "misc.h" +#include "fs.h" struct page; struct file; @@ -86,7 +87,6 @@ void __cold extent_buffer_free_cachep(void); #define INLINE_EXTENT_BUFFER_PAGES (BTRFS_MAX_METADATA_BLOCKSIZE / PAGE_SIZE) struct extent_buffer { u64 start; - u32 len; u32 folio_size; unsigned long bflags; struct btrfs_fs_info *fs_info; @@ -274,12 +274,12 @@ static inline int __pure num_extent_pages(const struct extent_buffer *eb) { /* * For sectorsize == PAGE_SIZE case, since nodesize is always aligned to - * sectorsize, it's just eb->len >> PAGE_SHIFT. + * sectorsize, it's just nodesize >> PAGE_SHIFT. * * For sectorsize < PAGE_SIZE case, we could have nodesize < PAGE_SIZE, * thus have to ensure we get at least one page. */ - return (eb->len >> PAGE_SHIFT) ?: 1; + return (eb->fs_info->nodesize >> PAGE_SHIFT) ?: 1; } /* diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index a498fe524c907..d06008ff63de9 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -598,7 +598,7 @@ static noinline int create_subvol(struct mnt_idmap *idmap, btrfs_set_root_generation(root_item, trans->transid); btrfs_set_root_level(root_item, 0); btrfs_set_root_refs(root_item, 1); - btrfs_set_root_used(root_item, leaf->len); + btrfs_set_root_used(root_item, fs_info->nodesize); btrfs_set_root_last_snapshot(root_item, 0); btrfs_set_root_generation_v2(root_item, diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 0a6325ebf266f..59cdc6e1ec0e8 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -4353,7 +4353,7 @@ int btrfs_reloc_cow_block(struct btrfs_trans_handle *trans, mark_block_processed(rc, node); if (first_cow && level > 0) - rc->nodes_relocated += buf->len; + rc->nodes_relocated += fs_info->nodesize; } if (level == 0 && first_cow && rc->stage == UPDATE_DATA_PTRS) diff --git a/fs/btrfs/subpage.c b/fs/btrfs/subpage.c index d4f0192334936..64c212f76ff12 100644 --- a/fs/btrfs/subpage.c +++ b/fs/btrfs/subpage.c @@ -631,7 +631,8 @@ void btrfs_meta_folio_set_##name(struct folio *folio, const struct extent_buffer folio_set_func(folio); \ return; \ } \ - btrfs_subpage_set_##name(eb->fs_info, folio, eb->start, eb->len); \ + btrfs_subpage_set_##name(eb->fs_info, folio, eb->start, \ + eb->fs_info->nodesize); \ } \ void btrfs_meta_folio_clear_##name(struct folio *folio, const struct extent_buffer *eb) \ { \ @@ -639,13 +640,15 @@ void btrfs_meta_folio_clear_##name(struct folio *folio, const struct extent_buff folio_clear_func(folio); \ return; \ } \ - btrfs_subpage_clear_##name(eb->fs_info, folio, eb->start, eb->len); \ + btrfs_subpage_clear_##name(eb->fs_info, folio, eb->start, \ + eb->fs_info->nodesize); \ } \ bool btrfs_meta_folio_test_##name(struct folio *folio, const struct extent_buffer *eb) \ { \ if (!btrfs_meta_is_subpage(eb->fs_info)) \ return folio_test_func(folio); \ - return btrfs_subpage_test_##name(eb->fs_info, folio, eb->start, eb->len); \ + return btrfs_subpage_test_##name(eb->fs_info, folio, eb->start, \ + eb->fs_info->nodesize); \ } IMPLEMENT_BTRFS_PAGE_OPS(uptodate, folio_mark_uptodate, folio_clear_uptodate, folio_test_uptodate); @@ -765,7 +768,8 @@ bool btrfs_meta_folio_clear_and_test_dirty(struct folio *folio, const struct ext return true; } - last = btrfs_subpage_clear_and_test_dirty(eb->fs_info, folio, eb->start, eb->len); + last = btrfs_subpage_clear_and_test_dirty(eb->fs_info, folio, eb->start, + eb->fs_info->nodesize); if (last) { folio_clear_dirty_for_io(folio); return true; diff --git a/fs/btrfs/tests/extent-io-tests.c b/fs/btrfs/tests/extent-io-tests.c index 00da54f0164c9..697d558808103 100644 --- a/fs/btrfs/tests/extent-io-tests.c +++ b/fs/btrfs/tests/extent-io-tests.c @@ -342,7 +342,7 @@ static int check_eb_bitmap(unsigned long *bitmap, struct extent_buffer *eb) { unsigned long i; - for (i = 0; i < eb->len * BITS_PER_BYTE; i++) { + for (i = 0; i < eb->fs_info->nodesize * BITS_PER_BYTE; i++) { int bit, bit1; bit = !!test_bit(i, bitmap); @@ -411,7 +411,7 @@ static int test_bitmap_clear(const char *name, unsigned long *bitmap, static int __test_eb_bitmaps(unsigned long *bitmap, struct extent_buffer *eb) { unsigned long i, j; - unsigned long byte_len = eb->len; + unsigned long byte_len = eb->fs_info->nodesize; u32 x; int ret; @@ -670,7 +670,7 @@ static int test_find_first_clear_extent_bit(void) static void dump_eb_and_memory_contents(struct extent_buffer *eb, void *memory, const char *test_name) { - for (int i = 0; i < eb->len; i++) { + for (int i = 0; i < eb->fs_info->nodesize; i++) { struct page *page = folio_page(eb->folios[i >> PAGE_SHIFT], 0); void *addr = page_address(page) + offset_in_page(i); @@ -686,7 +686,7 @@ static void dump_eb_and_memory_contents(struct extent_buffer *eb, void *memory, static int verify_eb_and_memory(struct extent_buffer *eb, void *memory, const char *test_name) { - for (int i = 0; i < (eb->len >> PAGE_SHIFT); i++) { + for (int i = 0; i < (eb->fs_info->nodesize >> PAGE_SHIFT); i++) { void *eb_addr = folio_address(eb->folios[i]); if (memcmp(memory + (i << PAGE_SHIFT), eb_addr, PAGE_SIZE) != 0) { @@ -703,8 +703,8 @@ static int verify_eb_and_memory(struct extent_buffer *eb, void *memory, */ static void init_eb_and_memory(struct extent_buffer *eb, void *memory) { - get_random_bytes(memory, eb->len); - write_extent_buffer(eb, memory, 0, eb->len); + get_random_bytes(memory, eb->fs_info->nodesize); + write_extent_buffer(eb, memory, 0, eb->fs_info->nodesize); } static int test_eb_mem_ops(u32 sectorsize, u32 nodesize) diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c index 271c958909cd8..0b87f2e2ee75e 100644 --- a/fs/btrfs/zoned.c +++ b/fs/btrfs/zoned.c @@ -2416,7 +2416,7 @@ void btrfs_schedule_zone_finish_bg(struct btrfs_block_group *bg, struct extent_buffer *eb) { if (!test_bit(BLOCK_GROUP_FLAG_SEQUENTIAL_ZONE, &bg->runtime_flags) || - eb->start + eb->len * 2 <= bg->start + bg->zone_capacity) + eb->start + eb->fs_info->nodesize * 2 <= bg->start + bg->zone_capacity) return; if (WARN_ON(bg->zone_finish_work.func == btrfs_zone_finish_endio_workfn)) { -- 2.47.2 ^ permalink raw reply related [flat|nested] 35+ messages in thread
* Re: [PATCH v2 1/2] btrfs: remove extent buffer's redundant `len` member field 2025-05-02 13:37 ` [PATCH v2 1/2] btrfs: remove extent buffer's redundant `len` member field Daniel Vacek @ 2025-05-02 17:35 ` Boris Burkov 2025-05-05 8:23 ` Daniel Vacek 2025-05-05 11:50 ` [PATCH v3 0/2] btrfs: eb struct cleanups Daniel Vacek 1 sibling, 1 reply; 35+ messages in thread From: Boris Burkov @ 2025-05-02 17:35 UTC (permalink / raw) To: Daniel Vacek Cc: David Sterba, Chris Mason, Josef Bacik, linux-btrfs, linux-kernel On Fri, May 02, 2025 at 03:37:22PM +0200, Daniel Vacek wrote: > Even super block nowadays uses nodesize for eb->len. This is since commits > > 551561c34663 ("btrfs: don't pass nodesize to __alloc_extent_buffer()") > da17066c4047 ("btrfs: pull node/sector/stripe sizes out of root and into fs_info") > ce3e69847e3e ("btrfs: sink parameter len to alloc_extent_buffer") > a83fffb75d09 ("btrfs: sink blocksize parameter to btrfs_find_create_tree_block") > > With these the eb->len is not really useful anymore. Let's use the nodesize > directly where applicable. Transformations look good to me. I think it might be a little neater to add a static inline helper that does eb->fs_info->nodesize to make that a bit easier to type (kinda like btrfs_root_id()) but I'm happy with this too. Reviewed-by: Boris Burkov <boris@bur.io> > > Signed-off-by: Daniel Vacek <neelx@suse.com> > --- > > v2 changes: > - rebased to this week's for-next > - use plain eb->fs_info->nodesize instead of a helper function as suggested > by Filipe and Wenruo > - constify local nodesize variables as suggested by Wenruo > > --- > fs/btrfs/accessors.c | 4 +-- > fs/btrfs/disk-io.c | 11 +++--- > fs/btrfs/extent-tree.c | 28 ++++++++------- > fs/btrfs/extent_io.c | 59 ++++++++++++++------------------ > fs/btrfs/extent_io.h | 6 ++-- > fs/btrfs/ioctl.c | 2 +- > fs/btrfs/relocation.c | 2 +- > fs/btrfs/subpage.c | 12 ++++--- > fs/btrfs/tests/extent-io-tests.c | 12 +++---- > fs/btrfs/zoned.c | 2 +- > 10 files changed, 69 insertions(+), 69 deletions(-) > > diff --git a/fs/btrfs/accessors.c b/fs/btrfs/accessors.c > index e3716516ca387..6839251b09a18 100644 > --- a/fs/btrfs/accessors.c > +++ b/fs/btrfs/accessors.c > @@ -14,10 +14,10 @@ static bool check_setget_bounds(const struct extent_buffer *eb, > { > const unsigned long member_offset = (unsigned long)ptr + off; > > - if (unlikely(member_offset + size > eb->len)) { > + if (unlikely(member_offset + size > eb->fs_info->nodesize)) { > btrfs_warn(eb->fs_info, > "bad eb member %s: ptr 0x%lx start %llu member offset %lu size %d", > - (member_offset > eb->len ? "start" : "end"), > + (member_offset > eb->fs_info->nodesize ? "start" : "end"), > (unsigned long)ptr, eb->start, member_offset, size); > return false; > } > diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c > index 308e8f384ecbb..2bf4df92474cb 100644 > --- a/fs/btrfs/disk-io.c > +++ b/fs/btrfs/disk-io.c > @@ -190,7 +190,7 @@ static int btrfs_repair_eb_io_failure(const struct extent_buffer *eb, > for (int i = 0; i < num_extent_folios(eb); i++) { > struct folio *folio = eb->folios[i]; > u64 start = max_t(u64, eb->start, folio_pos(folio)); > - u64 end = min_t(u64, eb->start + eb->len, > + u64 end = min_t(u64, eb->start + fs_info->nodesize, > folio_pos(folio) + eb->folio_size); > u32 len = end - start; > phys_addr_t paddr = PFN_PHYS(folio_pfn(folio)) + > @@ -230,7 +230,7 @@ int btrfs_read_extent_buffer(struct extent_buffer *eb, > break; > > num_copies = btrfs_num_copies(fs_info, > - eb->start, eb->len); > + eb->start, fs_info->nodesize); > if (num_copies == 1) > break; > > @@ -260,6 +260,7 @@ int btree_csum_one_bio(struct btrfs_bio *bbio) > { > struct extent_buffer *eb = bbio->private; > struct btrfs_fs_info *fs_info = eb->fs_info; > + const u32 nodesize = fs_info->nodesize; > u64 found_start = btrfs_header_bytenr(eb); > u64 last_trans; > u8 result[BTRFS_CSUM_SIZE]; > @@ -268,7 +269,7 @@ int btree_csum_one_bio(struct btrfs_bio *bbio) > /* Btree blocks are always contiguous on disk. */ > if (WARN_ON_ONCE(bbio->file_offset != eb->start)) > return -EIO; > - if (WARN_ON_ONCE(bbio->bio.bi_iter.bi_size != eb->len)) > + if (WARN_ON_ONCE(bbio->bio.bi_iter.bi_size != fs_info->nodesize)) You could also use the nodesize local variable here. > return -EIO; > > /* > @@ -277,7 +278,7 @@ int btree_csum_one_bio(struct btrfs_bio *bbio) > * ordering of I/O without unnecessarily writing out data. > */ > if (test_bit(EXTENT_BUFFER_ZONED_ZEROOUT, &eb->bflags)) { > - memzero_extent_buffer(eb, 0, eb->len); > + memzero_extent_buffer(eb, 0, nodesize); > return 0; > } > > @@ -881,7 +882,7 @@ struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans, > btrfs_set_root_generation(&root->root_item, trans->transid); > btrfs_set_root_level(&root->root_item, 0); > btrfs_set_root_refs(&root->root_item, 1); > - btrfs_set_root_used(&root->root_item, leaf->len); > + btrfs_set_root_used(&root->root_item, fs_info->nodesize); > btrfs_set_root_last_snapshot(&root->root_item, 0); > btrfs_set_root_dirid(&root->root_item, 0); > if (is_fstree(objectid)) > diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c > index 527bffab75e5c..7b90ed007ef2e 100644 > --- a/fs/btrfs/extent-tree.c > +++ b/fs/btrfs/extent-tree.c > @@ -2186,7 +2186,7 @@ int btrfs_set_disk_extent_flags(struct btrfs_trans_handle *trans, > extent_op->update_flags = true; > extent_op->update_key = false; > > - ret = btrfs_add_delayed_extent_op(trans, eb->start, eb->len, > + ret = btrfs_add_delayed_extent_op(trans, eb->start, eb->fs_info->nodesize, > btrfs_header_level(eb), extent_op); > if (ret) > btrfs_free_delayed_extent_op(extent_op); > @@ -2635,10 +2635,10 @@ int btrfs_pin_extent_for_log_replay(struct btrfs_trans_handle *trans, > if (ret) > goto out; > > - pin_down_extent(trans, cache, eb->start, eb->len, 0); > + pin_down_extent(trans, cache, eb->start, eb->fs_info->nodesize, 0); > > /* remove us from the free space cache (if we're there at all) */ > - ret = btrfs_remove_free_space(cache, eb->start, eb->len); > + ret = btrfs_remove_free_space(cache, eb->start, eb->fs_info->nodesize); > out: > btrfs_put_block_group(cache); > return ret; > @@ -3434,13 +3434,14 @@ int btrfs_free_tree_block(struct btrfs_trans_handle *trans, > { > struct btrfs_fs_info *fs_info = trans->fs_info; > struct btrfs_block_group *bg; > + const u32 nodesize = fs_info->nodesize; > int ret; > > if (root_id != BTRFS_TREE_LOG_OBJECTID) { > struct btrfs_ref generic_ref = { > .action = BTRFS_DROP_DELAYED_REF, > .bytenr = buf->start, > - .num_bytes = buf->len, > + .num_bytes = nodesize, > .parent = parent, > .owning_root = btrfs_header_owner(buf), > .ref_root = root_id, > @@ -3476,7 +3477,7 @@ int btrfs_free_tree_block(struct btrfs_trans_handle *trans, > bg = btrfs_lookup_block_group(fs_info, buf->start); > > if (btrfs_header_flag(buf, BTRFS_HEADER_FLAG_WRITTEN)) { > - pin_down_extent(trans, bg, buf->start, buf->len, 1); > + pin_down_extent(trans, bg, buf->start, nodesize, 1); > btrfs_put_block_group(bg); > goto out; > } > @@ -3500,17 +3501,17 @@ int btrfs_free_tree_block(struct btrfs_trans_handle *trans, > > if (test_bit(BTRFS_FS_TREE_MOD_LOG_USERS, &fs_info->flags) > || btrfs_is_zoned(fs_info)) { > - pin_down_extent(trans, bg, buf->start, buf->len, 1); > + pin_down_extent(trans, bg, buf->start, nodesize, 1); > btrfs_put_block_group(bg); > goto out; > } > > WARN_ON(test_bit(EXTENT_BUFFER_DIRTY, &buf->bflags)); > > - btrfs_add_free_space(bg, buf->start, buf->len); > - btrfs_free_reserved_bytes(bg, buf->len, 0); > + btrfs_add_free_space(bg, buf->start, nodesize); > + btrfs_free_reserved_bytes(bg, nodesize, 0); > btrfs_put_block_group(bg); > - trace_btrfs_reserved_extent_free(fs_info, buf->start, buf->len); > + trace_btrfs_reserved_extent_free(fs_info, buf->start, nodesize); > > out: > return 0; > @@ -4752,7 +4753,7 @@ int btrfs_pin_reserved_extent(struct btrfs_trans_handle *trans, > return -ENOSPC; > } > > - ret = pin_down_extent(trans, cache, eb->start, eb->len, 1); > + ret = pin_down_extent(trans, cache, eb->start, eb->fs_info->nodesize, 1); > btrfs_put_block_group(cache); > return ret; > } > @@ -5034,6 +5035,7 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root, > struct btrfs_fs_info *fs_info = root->fs_info; > struct extent_buffer *buf; > u64 lockdep_owner = owner; > + const u32 nodesize = fs_info->nodesize; > > buf = btrfs_find_create_tree_block(fs_info, bytenr, owner, level); > if (IS_ERR(buf)) > @@ -5091,16 +5093,16 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root, > */ > if (buf->log_index == 0) > btrfs_set_extent_bit(&root->dirty_log_pages, buf->start, > - buf->start + buf->len - 1, > + buf->start + nodesize - 1, > EXTENT_DIRTY, NULL); > else > btrfs_set_extent_bit(&root->dirty_log_pages, buf->start, > - buf->start + buf->len - 1, > + buf->start + nodesize - 1, > EXTENT_NEW, NULL); > } else { > buf->log_index = -1; > btrfs_set_extent_bit(&trans->transaction->dirty_pages, buf->start, > - buf->start + buf->len - 1, EXTENT_DIRTY, NULL); > + buf->start + nodesize - 1, EXTENT_DIRTY, NULL); > } > /* this returns a buffer locked for blocking */ > return buf; > diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c > index d889d8fcf1d27..a34644bb4b146 100644 > --- a/fs/btrfs/extent_io.c > +++ b/fs/btrfs/extent_io.c > @@ -76,8 +76,8 @@ void btrfs_extent_buffer_leak_debug_check(struct btrfs_fs_info *fs_info) > eb = list_first_entry(&fs_info->allocated_ebs, > struct extent_buffer, leak_list); > pr_err( > - "BTRFS: buffer leak start %llu len %u refs %d bflags %lu owner %llu\n", > - eb->start, eb->len, atomic_read(&eb->refs), eb->bflags, > + "BTRFS: buffer leak start %llu refs %d bflags %lu owner %llu\n", > + eb->start, atomic_read(&eb->refs), eb->bflags, > btrfs_header_owner(eb)); > list_del(&eb->leak_list); > WARN_ON_ONCE(1); > @@ -1788,8 +1788,8 @@ static noinline_for_stack bool lock_extent_buffer_for_io(struct extent_buffer *e > > btrfs_set_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN); > percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, > - -eb->len, > - fs_info->dirty_metadata_batch); > + -fs_info->nodesize, > + fs_info->dirty_metadata_batch); > ret = true; > } else { > spin_unlock(&eb->refs_lock); > @@ -1986,7 +1986,7 @@ static unsigned int buffer_tree_get_ebs_tag(struct btrfs_fs_info *fs_info, > rcu_read_lock(); > while ((eb = find_get_eb(&xas, end, tag)) != NULL) { > if (!eb_batch_add(batch, eb)) { > - *start = (eb->start + eb->len) >> fs_info->sectorsize_bits; > + *start = (eb->start + fs_info->nodesize) >> fs_info->sectorsize_bits; > goto out; > } > } > @@ -2050,7 +2050,7 @@ static void prepare_eb_write(struct extent_buffer *eb) > nritems = btrfs_header_nritems(eb); > if (btrfs_header_level(eb) > 0) { > end = btrfs_node_key_ptr_offset(eb, nritems); > - memzero_extent_buffer(eb, end, eb->len - end); > + memzero_extent_buffer(eb, end, eb->fs_info->nodesize - end); > } else { > /* > * Leaf: > @@ -2086,7 +2086,7 @@ static noinline_for_stack void write_one_eb(struct extent_buffer *eb, > struct folio *folio = eb->folios[i]; > u64 range_start = max_t(u64, eb->start, folio_pos(folio)); > u32 range_len = min_t(u64, folio_pos(folio) + folio_size(folio), > - eb->start + eb->len) - range_start; > + eb->start + fs_info->nodesize) - range_start; > > folio_lock(folio); > btrfs_meta_folio_clear_dirty(folio, eb); > @@ -2200,7 +2200,7 @@ int btree_write_cache_pages(struct address_space *mapping, > if (ctx.zoned_bg) { > /* Mark the last eb in the block group. */ > btrfs_schedule_zone_finish_bg(ctx.zoned_bg, eb); > - ctx.zoned_bg->meta_write_pointer += eb->len; > + ctx.zoned_bg->meta_write_pointer += fs_info->nodesize; > } > write_one_eb(eb, wbc); > } > @@ -2836,7 +2836,6 @@ static struct extent_buffer *__alloc_extent_buffer(struct btrfs_fs_info *fs_info > > eb = kmem_cache_zalloc(extent_buffer_cache, GFP_NOFS|__GFP_NOFAIL); > eb->start = start; > - eb->len = fs_info->nodesize; > eb->fs_info = fs_info; > init_rwsem(&eb->lock); > > @@ -2845,8 +2844,6 @@ static struct extent_buffer *__alloc_extent_buffer(struct btrfs_fs_info *fs_info > spin_lock_init(&eb->refs_lock); > atomic_set(&eb->refs, 1); > > - ASSERT(eb->len <= BTRFS_MAX_METADATA_BLOCKSIZE); > - > return eb; > } > > @@ -3558,7 +3555,7 @@ void btrfs_clear_buffer_dirty(struct btrfs_trans_handle *trans, > return; > > buffer_tree_clear_mark(eb, PAGECACHE_TAG_DIRTY); > - percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, -eb->len, > + percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, -fs_info->nodesize, > fs_info->dirty_metadata_batch); > > for (int i = 0; i < num_extent_folios(eb); i++) { > @@ -3589,7 +3586,8 @@ void set_extent_buffer_dirty(struct extent_buffer *eb) > WARN_ON(test_bit(EXTENT_BUFFER_ZONED_ZEROOUT, &eb->bflags)); > > if (!was_dirty) { > - bool subpage = btrfs_meta_is_subpage(eb->fs_info); > + struct btrfs_fs_info *fs_info = eb->fs_info; > + bool subpage = btrfs_meta_is_subpage(fs_info); > > /* > * For subpage case, we can have other extent buffers in the > @@ -3609,9 +3607,9 @@ void set_extent_buffer_dirty(struct extent_buffer *eb) > buffer_tree_set_mark(eb, PAGECACHE_TAG_DIRTY); > if (subpage) > folio_unlock(eb->folios[0]); > - percpu_counter_add_batch(&eb->fs_info->dirty_metadata_bytes, > - eb->len, > - eb->fs_info->dirty_metadata_batch); > + percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, > + fs_info->nodesize, > + fs_info->dirty_metadata_batch); > } > #ifdef CONFIG_BTRFS_DEBUG > for (int i = 0; i < num_extent_folios(eb); i++) > @@ -3723,7 +3721,7 @@ int read_extent_buffer_pages_nowait(struct extent_buffer *eb, int mirror_num, > struct folio *folio = eb->folios[i]; > u64 range_start = max_t(u64, eb->start, folio_pos(folio)); > u32 range_len = min_t(u64, folio_pos(folio) + folio_size(folio), > - eb->start + eb->len) - range_start; > + eb->start + eb->fs_info->nodesize) - range_start; > > bio_add_folio_nofail(&bbio->bio, folio, range_len, > offset_in_folio(folio, range_start)); > @@ -3751,8 +3749,8 @@ static bool report_eb_range(const struct extent_buffer *eb, unsigned long start, > unsigned long len) > { > btrfs_warn(eb->fs_info, > - "access to eb bytenr %llu len %u out of range start %lu len %lu", > - eb->start, eb->len, start, len); > + "access to eb bytenr %llu out of range start %lu len %lu", > + eb->start, start, len); I think including the nodesize (or eb end..) would sill be useful. > DEBUG_WARN(); > > return true; > @@ -3770,8 +3768,8 @@ static inline int check_eb_range(const struct extent_buffer *eb, > { > unsigned long offset; > > - /* start, start + len should not go beyond eb->len nor overflow */ > - if (unlikely(check_add_overflow(start, len, &offset) || offset > eb->len)) > + /* start, start + len should not go beyond nodesize nor overflow */ > + if (unlikely(check_add_overflow(start, len, &offset) || offset > eb->fs_info->nodesize)) > return report_eb_range(eb, start, len); > > return false; > @@ -3827,8 +3825,8 @@ int read_extent_buffer_to_user_nofault(const struct extent_buffer *eb, > unsigned long i = get_eb_folio_index(eb, start); > int ret = 0; > > - WARN_ON(start > eb->len); > - WARN_ON(start + len > eb->start + eb->len); > + WARN_ON(start > eb->fs_info->nodesize); > + WARN_ON(start + len > eb->start + eb->fs_info->nodesize); > > if (eb->addr) { > if (copy_to_user_nofault(dstv, eb->addr + start, len)) > @@ -3919,8 +3917,8 @@ static void assert_eb_folio_uptodate(const struct extent_buffer *eb, int i) > folio = eb->folios[0]; > ASSERT(i == 0); > if (WARN_ON(!btrfs_subpage_test_uptodate(fs_info, folio, > - eb->start, eb->len))) > - btrfs_subpage_dump_bitmap(fs_info, folio, eb->start, eb->len); > + eb->start, fs_info->nodesize))) > + btrfs_subpage_dump_bitmap(fs_info, folio, eb->start, fs_info->nodesize); > } else { > WARN_ON(!folio_test_uptodate(folio)); > } > @@ -4013,12 +4011,10 @@ void copy_extent_buffer_full(const struct extent_buffer *dst, > const int unit_size = src->folio_size; > unsigned long cur = 0; > > - ASSERT(dst->len == src->len); > - > - while (cur < src->len) { > + while (cur < src->fs_info->nodesize) { > unsigned long index = get_eb_folio_index(src, cur); > unsigned long offset = get_eb_offset_in_folio(src, cur); > - unsigned long cur_len = min(src->len, unit_size - offset); > + unsigned long cur_len = min(src->fs_info->nodesize, unit_size - offset); > void *addr = folio_address(src->folios[index]) + offset; > > write_extent_buffer(dst, addr, cur, cur_len); > @@ -4033,7 +4029,6 @@ void copy_extent_buffer(const struct extent_buffer *dst, > unsigned long len) > { > const int unit_size = dst->folio_size; > - u64 dst_len = dst->len; > size_t cur; > size_t offset; > char *kaddr; > @@ -4043,8 +4038,6 @@ void copy_extent_buffer(const struct extent_buffer *dst, > check_eb_range(src, src_offset, len)) > return; > > - WARN_ON(src->len != dst_len); > - > offset = get_eb_offset_in_folio(dst, dst_offset); > > while (len > 0) { > @@ -4315,7 +4308,7 @@ static int try_release_subpage_extent_buffer(struct folio *folio) > xa_unlock_irq(&fs_info->buffer_tree); > break; > } > - cur = eb->start + eb->len; > + cur = eb->start + fs_info->nodesize; > > /* > * The same as try_release_extent_buffer(), to ensure the eb > diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h > index e36e8d6a00bc5..7a8451c11630a 100644 > --- a/fs/btrfs/extent_io.h > +++ b/fs/btrfs/extent_io.h > @@ -16,6 +16,7 @@ > #include "messages.h" > #include "ulist.h" > #include "misc.h" > +#include "fs.h" > > struct page; > struct file; > @@ -86,7 +87,6 @@ void __cold extent_buffer_free_cachep(void); > #define INLINE_EXTENT_BUFFER_PAGES (BTRFS_MAX_METADATA_BLOCKSIZE / PAGE_SIZE) > struct extent_buffer { > u64 start; > - u32 len; > u32 folio_size; > unsigned long bflags; > struct btrfs_fs_info *fs_info; > @@ -274,12 +274,12 @@ static inline int __pure num_extent_pages(const struct extent_buffer *eb) > { > /* > * For sectorsize == PAGE_SIZE case, since nodesize is always aligned to > - * sectorsize, it's just eb->len >> PAGE_SHIFT. > + * sectorsize, it's just nodesize >> PAGE_SHIFT. > * > * For sectorsize < PAGE_SIZE case, we could have nodesize < PAGE_SIZE, > * thus have to ensure we get at least one page. > */ > - return (eb->len >> PAGE_SHIFT) ?: 1; > + return (eb->fs_info->nodesize >> PAGE_SHIFT) ?: 1; > } > > /* > diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c > index a498fe524c907..d06008ff63de9 100644 > --- a/fs/btrfs/ioctl.c > +++ b/fs/btrfs/ioctl.c > @@ -598,7 +598,7 @@ static noinline int create_subvol(struct mnt_idmap *idmap, > btrfs_set_root_generation(root_item, trans->transid); > btrfs_set_root_level(root_item, 0); > btrfs_set_root_refs(root_item, 1); > - btrfs_set_root_used(root_item, leaf->len); > + btrfs_set_root_used(root_item, fs_info->nodesize); > btrfs_set_root_last_snapshot(root_item, 0); > > btrfs_set_root_generation_v2(root_item, > diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c > index 0a6325ebf266f..59cdc6e1ec0e8 100644 > --- a/fs/btrfs/relocation.c > +++ b/fs/btrfs/relocation.c > @@ -4353,7 +4353,7 @@ int btrfs_reloc_cow_block(struct btrfs_trans_handle *trans, > mark_block_processed(rc, node); > > if (first_cow && level > 0) > - rc->nodes_relocated += buf->len; > + rc->nodes_relocated += fs_info->nodesize; > } > > if (level == 0 && first_cow && rc->stage == UPDATE_DATA_PTRS) > diff --git a/fs/btrfs/subpage.c b/fs/btrfs/subpage.c > index d4f0192334936..64c212f76ff12 100644 > --- a/fs/btrfs/subpage.c > +++ b/fs/btrfs/subpage.c > @@ -631,7 +631,8 @@ void btrfs_meta_folio_set_##name(struct folio *folio, const struct extent_buffer > folio_set_func(folio); \ > return; \ > } \ > - btrfs_subpage_set_##name(eb->fs_info, folio, eb->start, eb->len); \ > + btrfs_subpage_set_##name(eb->fs_info, folio, eb->start, \ > + eb->fs_info->nodesize); \ > } \ > void btrfs_meta_folio_clear_##name(struct folio *folio, const struct extent_buffer *eb) \ > { \ > @@ -639,13 +640,15 @@ void btrfs_meta_folio_clear_##name(struct folio *folio, const struct extent_buff > folio_clear_func(folio); \ > return; \ > } \ > - btrfs_subpage_clear_##name(eb->fs_info, folio, eb->start, eb->len); \ > + btrfs_subpage_clear_##name(eb->fs_info, folio, eb->start, \ > + eb->fs_info->nodesize); \ > } \ > bool btrfs_meta_folio_test_##name(struct folio *folio, const struct extent_buffer *eb) \ > { \ > if (!btrfs_meta_is_subpage(eb->fs_info)) \ > return folio_test_func(folio); \ > - return btrfs_subpage_test_##name(eb->fs_info, folio, eb->start, eb->len); \ > + return btrfs_subpage_test_##name(eb->fs_info, folio, eb->start, \ > + eb->fs_info->nodesize); \ > } > IMPLEMENT_BTRFS_PAGE_OPS(uptodate, folio_mark_uptodate, folio_clear_uptodate, > folio_test_uptodate); > @@ -765,7 +768,8 @@ bool btrfs_meta_folio_clear_and_test_dirty(struct folio *folio, const struct ext > return true; > } > > - last = btrfs_subpage_clear_and_test_dirty(eb->fs_info, folio, eb->start, eb->len); > + last = btrfs_subpage_clear_and_test_dirty(eb->fs_info, folio, eb->start, > + eb->fs_info->nodesize); > if (last) { > folio_clear_dirty_for_io(folio); > return true; > diff --git a/fs/btrfs/tests/extent-io-tests.c b/fs/btrfs/tests/extent-io-tests.c > index 00da54f0164c9..697d558808103 100644 > --- a/fs/btrfs/tests/extent-io-tests.c > +++ b/fs/btrfs/tests/extent-io-tests.c > @@ -342,7 +342,7 @@ static int check_eb_bitmap(unsigned long *bitmap, struct extent_buffer *eb) > { > unsigned long i; > > - for (i = 0; i < eb->len * BITS_PER_BYTE; i++) { > + for (i = 0; i < eb->fs_info->nodesize * BITS_PER_BYTE; i++) { > int bit, bit1; > > bit = !!test_bit(i, bitmap); > @@ -411,7 +411,7 @@ static int test_bitmap_clear(const char *name, unsigned long *bitmap, > static int __test_eb_bitmaps(unsigned long *bitmap, struct extent_buffer *eb) > { > unsigned long i, j; > - unsigned long byte_len = eb->len; > + unsigned long byte_len = eb->fs_info->nodesize; > u32 x; > int ret; > > @@ -670,7 +670,7 @@ static int test_find_first_clear_extent_bit(void) > static void dump_eb_and_memory_contents(struct extent_buffer *eb, void *memory, > const char *test_name) > { > - for (int i = 0; i < eb->len; i++) { > + for (int i = 0; i < eb->fs_info->nodesize; i++) { > struct page *page = folio_page(eb->folios[i >> PAGE_SHIFT], 0); > void *addr = page_address(page) + offset_in_page(i); > > @@ -686,7 +686,7 @@ static void dump_eb_and_memory_contents(struct extent_buffer *eb, void *memory, > static int verify_eb_and_memory(struct extent_buffer *eb, void *memory, > const char *test_name) > { > - for (int i = 0; i < (eb->len >> PAGE_SHIFT); i++) { > + for (int i = 0; i < (eb->fs_info->nodesize >> PAGE_SHIFT); i++) { > void *eb_addr = folio_address(eb->folios[i]); > > if (memcmp(memory + (i << PAGE_SHIFT), eb_addr, PAGE_SIZE) != 0) { > @@ -703,8 +703,8 @@ static int verify_eb_and_memory(struct extent_buffer *eb, void *memory, > */ > static void init_eb_and_memory(struct extent_buffer *eb, void *memory) > { > - get_random_bytes(memory, eb->len); > - write_extent_buffer(eb, memory, 0, eb->len); > + get_random_bytes(memory, eb->fs_info->nodesize); > + write_extent_buffer(eb, memory, 0, eb->fs_info->nodesize); > } > > static int test_eb_mem_ops(u32 sectorsize, u32 nodesize) > diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c > index 271c958909cd8..0b87f2e2ee75e 100644 > --- a/fs/btrfs/zoned.c > +++ b/fs/btrfs/zoned.c > @@ -2416,7 +2416,7 @@ void btrfs_schedule_zone_finish_bg(struct btrfs_block_group *bg, > struct extent_buffer *eb) > { > if (!test_bit(BLOCK_GROUP_FLAG_SEQUENTIAL_ZONE, &bg->runtime_flags) || > - eb->start + eb->len * 2 <= bg->start + bg->zone_capacity) > + eb->start + eb->fs_info->nodesize * 2 <= bg->start + bg->zone_capacity) > return; > > if (WARN_ON(bg->zone_finish_work.func == btrfs_zone_finish_endio_workfn)) { > -- > 2.47.2 > ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v2 1/2] btrfs: remove extent buffer's redundant `len` member field 2025-05-02 17:35 ` Boris Burkov @ 2025-05-05 8:23 ` Daniel Vacek 0 siblings, 0 replies; 35+ messages in thread From: Daniel Vacek @ 2025-05-05 8:23 UTC (permalink / raw) To: Boris Burkov Cc: David Sterba, Chris Mason, Josef Bacik, linux-btrfs, linux-kernel On Fri, 2 May 2025 at 19:34, Boris Burkov <boris@bur.io> wrote: > > On Fri, May 02, 2025 at 03:37:22PM +0200, Daniel Vacek wrote: > > Even super block nowadays uses nodesize for eb->len. This is since commits > > > > 551561c34663 ("btrfs: don't pass nodesize to __alloc_extent_buffer()") > > da17066c4047 ("btrfs: pull node/sector/stripe sizes out of root and into fs_info") > > ce3e69847e3e ("btrfs: sink parameter len to alloc_extent_buffer") > > a83fffb75d09 ("btrfs: sink blocksize parameter to btrfs_find_create_tree_block") > > > > With these the eb->len is not really useful anymore. Let's use the nodesize > > directly where applicable. > > Transformations look good to me. I think it might be a little neater to > add a static inline helper that does eb->fs_info->nodesize to make that > a bit easier to type (kinda like btrfs_root_id()) but I'm happy with > this too. > > Reviewed-by: Boris Burkov <boris@bur.io> > > > > > Signed-off-by: Daniel Vacek <neelx@suse.com> > > --- > > > > v2 changes: > > - rebased to this week's for-next > > - use plain eb->fs_info->nodesize instead of a helper function as suggested > > by Filipe and Wenruo > > - constify local nodesize variables as suggested by Wenruo > > > > --- > > fs/btrfs/accessors.c | 4 +-- > > fs/btrfs/disk-io.c | 11 +++--- > > fs/btrfs/extent-tree.c | 28 ++++++++------- > > fs/btrfs/extent_io.c | 59 ++++++++++++++------------------ > > fs/btrfs/extent_io.h | 6 ++-- > > fs/btrfs/ioctl.c | 2 +- > > fs/btrfs/relocation.c | 2 +- > > fs/btrfs/subpage.c | 12 ++++--- > > fs/btrfs/tests/extent-io-tests.c | 12 +++---- > > fs/btrfs/zoned.c | 2 +- > > 10 files changed, 69 insertions(+), 69 deletions(-) > > > > diff --git a/fs/btrfs/accessors.c b/fs/btrfs/accessors.c > > index e3716516ca387..6839251b09a18 100644 > > --- a/fs/btrfs/accessors.c > > +++ b/fs/btrfs/accessors.c > > @@ -14,10 +14,10 @@ static bool check_setget_bounds(const struct extent_buffer *eb, > > { > > const unsigned long member_offset = (unsigned long)ptr + off; > > > > - if (unlikely(member_offset + size > eb->len)) { > > + if (unlikely(member_offset + size > eb->fs_info->nodesize)) { > > btrfs_warn(eb->fs_info, > > "bad eb member %s: ptr 0x%lx start %llu member offset %lu size %d", > > - (member_offset > eb->len ? "start" : "end"), > > + (member_offset > eb->fs_info->nodesize ? "start" : "end"), > > (unsigned long)ptr, eb->start, member_offset, size); > > return false; > > } > > diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c > > index 308e8f384ecbb..2bf4df92474cb 100644 > > --- a/fs/btrfs/disk-io.c > > +++ b/fs/btrfs/disk-io.c > > @@ -190,7 +190,7 @@ static int btrfs_repair_eb_io_failure(const struct extent_buffer *eb, > > for (int i = 0; i < num_extent_folios(eb); i++) { > > struct folio *folio = eb->folios[i]; > > u64 start = max_t(u64, eb->start, folio_pos(folio)); > > - u64 end = min_t(u64, eb->start + eb->len, > > + u64 end = min_t(u64, eb->start + fs_info->nodesize, > > folio_pos(folio) + eb->folio_size); > > u32 len = end - start; > > phys_addr_t paddr = PFN_PHYS(folio_pfn(folio)) + > > @@ -230,7 +230,7 @@ int btrfs_read_extent_buffer(struct extent_buffer *eb, > > break; > > > > num_copies = btrfs_num_copies(fs_info, > > - eb->start, eb->len); > > + eb->start, fs_info->nodesize); > > if (num_copies == 1) > > break; > > > > @@ -260,6 +260,7 @@ int btree_csum_one_bio(struct btrfs_bio *bbio) > > { > > struct extent_buffer *eb = bbio->private; > > struct btrfs_fs_info *fs_info = eb->fs_info; > > + const u32 nodesize = fs_info->nodesize; > > u64 found_start = btrfs_header_bytenr(eb); > > u64 last_trans; > > u8 result[BTRFS_CSUM_SIZE]; > > @@ -268,7 +269,7 @@ int btree_csum_one_bio(struct btrfs_bio *bbio) > > /* Btree blocks are always contiguous on disk. */ > > if (WARN_ON_ONCE(bbio->file_offset != eb->start)) > > return -EIO; > > - if (WARN_ON_ONCE(bbio->bio.bi_iter.bi_size != eb->len)) > > + if (WARN_ON_ONCE(bbio->bio.bi_iter.bi_size != fs_info->nodesize)) > > You could also use the nodesize local variable here. Good catch. This happened due to the rebase, this chunk is new to v2 and I missed that I actually made the new local variable here. Thanks. > > return -EIO; > > > > /* > > @@ -277,7 +278,7 @@ int btree_csum_one_bio(struct btrfs_bio *bbio) > > * ordering of I/O without unnecessarily writing out data. > > */ > > if (test_bit(EXTENT_BUFFER_ZONED_ZEROOUT, &eb->bflags)) { > > - memzero_extent_buffer(eb, 0, eb->len); > > + memzero_extent_buffer(eb, 0, nodesize); > > return 0; > > } > > > > @@ -881,7 +882,7 @@ struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans, > > btrfs_set_root_generation(&root->root_item, trans->transid); > > btrfs_set_root_level(&root->root_item, 0); > > btrfs_set_root_refs(&root->root_item, 1); > > - btrfs_set_root_used(&root->root_item, leaf->len); > > + btrfs_set_root_used(&root->root_item, fs_info->nodesize); > > btrfs_set_root_last_snapshot(&root->root_item, 0); > > btrfs_set_root_dirid(&root->root_item, 0); > > if (is_fstree(objectid)) > > diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c > > index 527bffab75e5c..7b90ed007ef2e 100644 > > --- a/fs/btrfs/extent-tree.c > > +++ b/fs/btrfs/extent-tree.c > > @@ -2186,7 +2186,7 @@ int btrfs_set_disk_extent_flags(struct btrfs_trans_handle *trans, > > extent_op->update_flags = true; > > extent_op->update_key = false; > > > > - ret = btrfs_add_delayed_extent_op(trans, eb->start, eb->len, > > + ret = btrfs_add_delayed_extent_op(trans, eb->start, eb->fs_info->nodesize, > > btrfs_header_level(eb), extent_op); > > if (ret) > > btrfs_free_delayed_extent_op(extent_op); > > @@ -2635,10 +2635,10 @@ int btrfs_pin_extent_for_log_replay(struct btrfs_trans_handle *trans, > > if (ret) > > goto out; > > > > - pin_down_extent(trans, cache, eb->start, eb->len, 0); > > + pin_down_extent(trans, cache, eb->start, eb->fs_info->nodesize, 0); > > > > /* remove us from the free space cache (if we're there at all) */ > > - ret = btrfs_remove_free_space(cache, eb->start, eb->len); > > + ret = btrfs_remove_free_space(cache, eb->start, eb->fs_info->nodesize); > > out: > > btrfs_put_block_group(cache); > > return ret; > > @@ -3434,13 +3434,14 @@ int btrfs_free_tree_block(struct btrfs_trans_handle *trans, > > { > > struct btrfs_fs_info *fs_info = trans->fs_info; > > struct btrfs_block_group *bg; > > + const u32 nodesize = fs_info->nodesize; > > int ret; > > > > if (root_id != BTRFS_TREE_LOG_OBJECTID) { > > struct btrfs_ref generic_ref = { > > .action = BTRFS_DROP_DELAYED_REF, > > .bytenr = buf->start, > > - .num_bytes = buf->len, > > + .num_bytes = nodesize, > > .parent = parent, > > .owning_root = btrfs_header_owner(buf), > > .ref_root = root_id, > > @@ -3476,7 +3477,7 @@ int btrfs_free_tree_block(struct btrfs_trans_handle *trans, > > bg = btrfs_lookup_block_group(fs_info, buf->start); > > > > if (btrfs_header_flag(buf, BTRFS_HEADER_FLAG_WRITTEN)) { > > - pin_down_extent(trans, bg, buf->start, buf->len, 1); > > + pin_down_extent(trans, bg, buf->start, nodesize, 1); > > btrfs_put_block_group(bg); > > goto out; > > } > > @@ -3500,17 +3501,17 @@ int btrfs_free_tree_block(struct btrfs_trans_handle *trans, > > > > if (test_bit(BTRFS_FS_TREE_MOD_LOG_USERS, &fs_info->flags) > > || btrfs_is_zoned(fs_info)) { > > - pin_down_extent(trans, bg, buf->start, buf->len, 1); > > + pin_down_extent(trans, bg, buf->start, nodesize, 1); > > btrfs_put_block_group(bg); > > goto out; > > } > > > > WARN_ON(test_bit(EXTENT_BUFFER_DIRTY, &buf->bflags)); > > > > - btrfs_add_free_space(bg, buf->start, buf->len); > > - btrfs_free_reserved_bytes(bg, buf->len, 0); > > + btrfs_add_free_space(bg, buf->start, nodesize); > > + btrfs_free_reserved_bytes(bg, nodesize, 0); > > btrfs_put_block_group(bg); > > - trace_btrfs_reserved_extent_free(fs_info, buf->start, buf->len); > > + trace_btrfs_reserved_extent_free(fs_info, buf->start, nodesize); > > > > out: > > return 0; > > @@ -4752,7 +4753,7 @@ int btrfs_pin_reserved_extent(struct btrfs_trans_handle *trans, > > return -ENOSPC; > > } > > > > - ret = pin_down_extent(trans, cache, eb->start, eb->len, 1); > > + ret = pin_down_extent(trans, cache, eb->start, eb->fs_info->nodesize, 1); > > btrfs_put_block_group(cache); > > return ret; > > } > > @@ -5034,6 +5035,7 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root, > > struct btrfs_fs_info *fs_info = root->fs_info; > > struct extent_buffer *buf; > > u64 lockdep_owner = owner; > > + const u32 nodesize = fs_info->nodesize; > > > > buf = btrfs_find_create_tree_block(fs_info, bytenr, owner, level); > > if (IS_ERR(buf)) > > @@ -5091,16 +5093,16 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root, > > */ > > if (buf->log_index == 0) > > btrfs_set_extent_bit(&root->dirty_log_pages, buf->start, > > - buf->start + buf->len - 1, > > + buf->start + nodesize - 1, > > EXTENT_DIRTY, NULL); > > else > > btrfs_set_extent_bit(&root->dirty_log_pages, buf->start, > > - buf->start + buf->len - 1, > > + buf->start + nodesize - 1, > > EXTENT_NEW, NULL); > > } else { > > buf->log_index = -1; > > btrfs_set_extent_bit(&trans->transaction->dirty_pages, buf->start, > > - buf->start + buf->len - 1, EXTENT_DIRTY, NULL); > > + buf->start + nodesize - 1, EXTENT_DIRTY, NULL); > > } > > /* this returns a buffer locked for blocking */ > > return buf; > > diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c > > index d889d8fcf1d27..a34644bb4b146 100644 > > --- a/fs/btrfs/extent_io.c > > +++ b/fs/btrfs/extent_io.c > > @@ -76,8 +76,8 @@ void btrfs_extent_buffer_leak_debug_check(struct btrfs_fs_info *fs_info) > > eb = list_first_entry(&fs_info->allocated_ebs, > > struct extent_buffer, leak_list); > > pr_err( > > - "BTRFS: buffer leak start %llu len %u refs %d bflags %lu owner %llu\n", > > - eb->start, eb->len, atomic_read(&eb->refs), eb->bflags, > > + "BTRFS: buffer leak start %llu refs %d bflags %lu owner %llu\n", > > + eb->start, atomic_read(&eb->refs), eb->bflags, > > btrfs_header_owner(eb)); > > list_del(&eb->leak_list); > > WARN_ON_ONCE(1); > > @@ -1788,8 +1788,8 @@ static noinline_for_stack bool lock_extent_buffer_for_io(struct extent_buffer *e > > > > btrfs_set_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN); > > percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, > > - -eb->len, > > - fs_info->dirty_metadata_batch); > > + -fs_info->nodesize, > > + fs_info->dirty_metadata_batch); > > ret = true; > > } else { > > spin_unlock(&eb->refs_lock); > > @@ -1986,7 +1986,7 @@ static unsigned int buffer_tree_get_ebs_tag(struct btrfs_fs_info *fs_info, > > rcu_read_lock(); > > while ((eb = find_get_eb(&xas, end, tag)) != NULL) { > > if (!eb_batch_add(batch, eb)) { > > - *start = (eb->start + eb->len) >> fs_info->sectorsize_bits; > > + *start = (eb->start + fs_info->nodesize) >> fs_info->sectorsize_bits; > > goto out; > > } > > } > > @@ -2050,7 +2050,7 @@ static void prepare_eb_write(struct extent_buffer *eb) > > nritems = btrfs_header_nritems(eb); > > if (btrfs_header_level(eb) > 0) { > > end = btrfs_node_key_ptr_offset(eb, nritems); > > - memzero_extent_buffer(eb, end, eb->len - end); > > + memzero_extent_buffer(eb, end, eb->fs_info->nodesize - end); > > } else { > > /* > > * Leaf: > > @@ -2086,7 +2086,7 @@ static noinline_for_stack void write_one_eb(struct extent_buffer *eb, > > struct folio *folio = eb->folios[i]; > > u64 range_start = max_t(u64, eb->start, folio_pos(folio)); > > u32 range_len = min_t(u64, folio_pos(folio) + folio_size(folio), > > - eb->start + eb->len) - range_start; > > + eb->start + fs_info->nodesize) - range_start; > > > > folio_lock(folio); > > btrfs_meta_folio_clear_dirty(folio, eb); > > @@ -2200,7 +2200,7 @@ int btree_write_cache_pages(struct address_space *mapping, > > if (ctx.zoned_bg) { > > /* Mark the last eb in the block group. */ > > btrfs_schedule_zone_finish_bg(ctx.zoned_bg, eb); > > - ctx.zoned_bg->meta_write_pointer += eb->len; > > + ctx.zoned_bg->meta_write_pointer += fs_info->nodesize; > > } > > write_one_eb(eb, wbc); > > } > > @@ -2836,7 +2836,6 @@ static struct extent_buffer *__alloc_extent_buffer(struct btrfs_fs_info *fs_info > > > > eb = kmem_cache_zalloc(extent_buffer_cache, GFP_NOFS|__GFP_NOFAIL); > > eb->start = start; > > - eb->len = fs_info->nodesize; > > eb->fs_info = fs_info; > > init_rwsem(&eb->lock); > > > > @@ -2845,8 +2844,6 @@ static struct extent_buffer *__alloc_extent_buffer(struct btrfs_fs_info *fs_info > > spin_lock_init(&eb->refs_lock); > > atomic_set(&eb->refs, 1); > > > > - ASSERT(eb->len <= BTRFS_MAX_METADATA_BLOCKSIZE); > > - > > return eb; > > } > > > > @@ -3558,7 +3555,7 @@ void btrfs_clear_buffer_dirty(struct btrfs_trans_handle *trans, > > return; > > > > buffer_tree_clear_mark(eb, PAGECACHE_TAG_DIRTY); > > - percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, -eb->len, > > + percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, -fs_info->nodesize, > > fs_info->dirty_metadata_batch); > > > > for (int i = 0; i < num_extent_folios(eb); i++) { > > @@ -3589,7 +3586,8 @@ void set_extent_buffer_dirty(struct extent_buffer *eb) > > WARN_ON(test_bit(EXTENT_BUFFER_ZONED_ZEROOUT, &eb->bflags)); > > > > if (!was_dirty) { > > - bool subpage = btrfs_meta_is_subpage(eb->fs_info); > > + struct btrfs_fs_info *fs_info = eb->fs_info; > > + bool subpage = btrfs_meta_is_subpage(fs_info); > > > > /* > > * For subpage case, we can have other extent buffers in the > > @@ -3609,9 +3607,9 @@ void set_extent_buffer_dirty(struct extent_buffer *eb) > > buffer_tree_set_mark(eb, PAGECACHE_TAG_DIRTY); > > if (subpage) > > folio_unlock(eb->folios[0]); > > - percpu_counter_add_batch(&eb->fs_info->dirty_metadata_bytes, > > - eb->len, > > - eb->fs_info->dirty_metadata_batch); > > + percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, > > + fs_info->nodesize, > > + fs_info->dirty_metadata_batch); > > } > > #ifdef CONFIG_BTRFS_DEBUG > > for (int i = 0; i < num_extent_folios(eb); i++) > > @@ -3723,7 +3721,7 @@ int read_extent_buffer_pages_nowait(struct extent_buffer *eb, int mirror_num, > > struct folio *folio = eb->folios[i]; > > u64 range_start = max_t(u64, eb->start, folio_pos(folio)); > > u32 range_len = min_t(u64, folio_pos(folio) + folio_size(folio), > > - eb->start + eb->len) - range_start; > > + eb->start + eb->fs_info->nodesize) - range_start; > > > > bio_add_folio_nofail(&bbio->bio, folio, range_len, > > offset_in_folio(folio, range_start)); > > @@ -3751,8 +3749,8 @@ static bool report_eb_range(const struct extent_buffer *eb, unsigned long start, > > unsigned long len) > > { > > btrfs_warn(eb->fs_info, > > - "access to eb bytenr %llu len %u out of range start %lu len %lu", > > - eb->start, eb->len, start, len); > > + "access to eb bytenr %llu out of range start %lu len %lu", > > + eb->start, start, len); > > I think including the nodesize (or eb end..) would sill be useful. > > > DEBUG_WARN(); > > > > return true; > > @@ -3770,8 +3768,8 @@ static inline int check_eb_range(const struct extent_buffer *eb, > > { > > unsigned long offset; > > > > - /* start, start + len should not go beyond eb->len nor overflow */ > > - if (unlikely(check_add_overflow(start, len, &offset) || offset > eb->len)) > > + /* start, start + len should not go beyond nodesize nor overflow */ > > + if (unlikely(check_add_overflow(start, len, &offset) || offset > eb->fs_info->nodesize)) > > return report_eb_range(eb, start, len); > > > > return false; > > @@ -3827,8 +3825,8 @@ int read_extent_buffer_to_user_nofault(const struct extent_buffer *eb, > > unsigned long i = get_eb_folio_index(eb, start); > > int ret = 0; > > > > - WARN_ON(start > eb->len); > > - WARN_ON(start + len > eb->start + eb->len); > > + WARN_ON(start > eb->fs_info->nodesize); > > + WARN_ON(start + len > eb->start + eb->fs_info->nodesize); > > > > if (eb->addr) { > > if (copy_to_user_nofault(dstv, eb->addr + start, len)) > > @@ -3919,8 +3917,8 @@ static void assert_eb_folio_uptodate(const struct extent_buffer *eb, int i) > > folio = eb->folios[0]; > > ASSERT(i == 0); > > if (WARN_ON(!btrfs_subpage_test_uptodate(fs_info, folio, > > - eb->start, eb->len))) > > - btrfs_subpage_dump_bitmap(fs_info, folio, eb->start, eb->len); > > + eb->start, fs_info->nodesize))) > > + btrfs_subpage_dump_bitmap(fs_info, folio, eb->start, fs_info->nodesize); > > } else { > > WARN_ON(!folio_test_uptodate(folio)); > > } > > @@ -4013,12 +4011,10 @@ void copy_extent_buffer_full(const struct extent_buffer *dst, > > const int unit_size = src->folio_size; > > unsigned long cur = 0; > > > > - ASSERT(dst->len == src->len); > > - > > - while (cur < src->len) { > > + while (cur < src->fs_info->nodesize) { > > unsigned long index = get_eb_folio_index(src, cur); > > unsigned long offset = get_eb_offset_in_folio(src, cur); > > - unsigned long cur_len = min(src->len, unit_size - offset); > > + unsigned long cur_len = min(src->fs_info->nodesize, unit_size - offset); > > void *addr = folio_address(src->folios[index]) + offset; > > > > write_extent_buffer(dst, addr, cur, cur_len); > > @@ -4033,7 +4029,6 @@ void copy_extent_buffer(const struct extent_buffer *dst, > > unsigned long len) > > { > > const int unit_size = dst->folio_size; > > - u64 dst_len = dst->len; > > size_t cur; > > size_t offset; > > char *kaddr; > > @@ -4043,8 +4038,6 @@ void copy_extent_buffer(const struct extent_buffer *dst, > > check_eb_range(src, src_offset, len)) > > return; > > > > - WARN_ON(src->len != dst_len); > > - > > offset = get_eb_offset_in_folio(dst, dst_offset); > > > > while (len > 0) { > > @@ -4315,7 +4308,7 @@ static int try_release_subpage_extent_buffer(struct folio *folio) > > xa_unlock_irq(&fs_info->buffer_tree); > > break; > > } > > - cur = eb->start + eb->len; > > + cur = eb->start + fs_info->nodesize; > > > > /* > > * The same as try_release_extent_buffer(), to ensure the eb > > diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h > > index e36e8d6a00bc5..7a8451c11630a 100644 > > --- a/fs/btrfs/extent_io.h > > +++ b/fs/btrfs/extent_io.h > > @@ -16,6 +16,7 @@ > > #include "messages.h" > > #include "ulist.h" > > #include "misc.h" > > +#include "fs.h" > > > > struct page; > > struct file; > > @@ -86,7 +87,6 @@ void __cold extent_buffer_free_cachep(void); > > #define INLINE_EXTENT_BUFFER_PAGES (BTRFS_MAX_METADATA_BLOCKSIZE / PAGE_SIZE) > > struct extent_buffer { > > u64 start; > > - u32 len; > > u32 folio_size; > > unsigned long bflags; > > struct btrfs_fs_info *fs_info; > > @@ -274,12 +274,12 @@ static inline int __pure num_extent_pages(const struct extent_buffer *eb) > > { > > /* > > * For sectorsize == PAGE_SIZE case, since nodesize is always aligned to > > - * sectorsize, it's just eb->len >> PAGE_SHIFT. > > + * sectorsize, it's just nodesize >> PAGE_SHIFT. > > * > > * For sectorsize < PAGE_SIZE case, we could have nodesize < PAGE_SIZE, > > * thus have to ensure we get at least one page. > > */ > > - return (eb->len >> PAGE_SHIFT) ?: 1; > > + return (eb->fs_info->nodesize >> PAGE_SHIFT) ?: 1; > > } > > > > /* > > diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c > > index a498fe524c907..d06008ff63de9 100644 > > --- a/fs/btrfs/ioctl.c > > +++ b/fs/btrfs/ioctl.c > > @@ -598,7 +598,7 @@ static noinline int create_subvol(struct mnt_idmap *idmap, > > btrfs_set_root_generation(root_item, trans->transid); > > btrfs_set_root_level(root_item, 0); > > btrfs_set_root_refs(root_item, 1); > > - btrfs_set_root_used(root_item, leaf->len); > > + btrfs_set_root_used(root_item, fs_info->nodesize); > > btrfs_set_root_last_snapshot(root_item, 0); > > > > btrfs_set_root_generation_v2(root_item, > > diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c > > index 0a6325ebf266f..59cdc6e1ec0e8 100644 > > --- a/fs/btrfs/relocation.c > > +++ b/fs/btrfs/relocation.c > > @@ -4353,7 +4353,7 @@ int btrfs_reloc_cow_block(struct btrfs_trans_handle *trans, > > mark_block_processed(rc, node); > > > > if (first_cow && level > 0) > > - rc->nodes_relocated += buf->len; > > + rc->nodes_relocated += fs_info->nodesize; > > } > > > > if (level == 0 && first_cow && rc->stage == UPDATE_DATA_PTRS) > > diff --git a/fs/btrfs/subpage.c b/fs/btrfs/subpage.c > > index d4f0192334936..64c212f76ff12 100644 > > --- a/fs/btrfs/subpage.c > > +++ b/fs/btrfs/subpage.c > > @@ -631,7 +631,8 @@ void btrfs_meta_folio_set_##name(struct folio *folio, const struct extent_buffer > > folio_set_func(folio); \ > > return; \ > > } \ > > - btrfs_subpage_set_##name(eb->fs_info, folio, eb->start, eb->len); \ > > + btrfs_subpage_set_##name(eb->fs_info, folio, eb->start, \ > > + eb->fs_info->nodesize); \ > > } \ > > void btrfs_meta_folio_clear_##name(struct folio *folio, const struct extent_buffer *eb) \ > > { \ > > @@ -639,13 +640,15 @@ void btrfs_meta_folio_clear_##name(struct folio *folio, const struct extent_buff > > folio_clear_func(folio); \ > > return; \ > > } \ > > - btrfs_subpage_clear_##name(eb->fs_info, folio, eb->start, eb->len); \ > > + btrfs_subpage_clear_##name(eb->fs_info, folio, eb->start, \ > > + eb->fs_info->nodesize); \ > > } \ > > bool btrfs_meta_folio_test_##name(struct folio *folio, const struct extent_buffer *eb) \ > > { \ > > if (!btrfs_meta_is_subpage(eb->fs_info)) \ > > return folio_test_func(folio); \ > > - return btrfs_subpage_test_##name(eb->fs_info, folio, eb->start, eb->len); \ > > + return btrfs_subpage_test_##name(eb->fs_info, folio, eb->start, \ > > + eb->fs_info->nodesize); \ > > } > > IMPLEMENT_BTRFS_PAGE_OPS(uptodate, folio_mark_uptodate, folio_clear_uptodate, > > folio_test_uptodate); > > @@ -765,7 +768,8 @@ bool btrfs_meta_folio_clear_and_test_dirty(struct folio *folio, const struct ext > > return true; > > } > > > > - last = btrfs_subpage_clear_and_test_dirty(eb->fs_info, folio, eb->start, eb->len); > > + last = btrfs_subpage_clear_and_test_dirty(eb->fs_info, folio, eb->start, > > + eb->fs_info->nodesize); > > if (last) { > > folio_clear_dirty_for_io(folio); > > return true; > > diff --git a/fs/btrfs/tests/extent-io-tests.c b/fs/btrfs/tests/extent-io-tests.c > > index 00da54f0164c9..697d558808103 100644 > > --- a/fs/btrfs/tests/extent-io-tests.c > > +++ b/fs/btrfs/tests/extent-io-tests.c > > @@ -342,7 +342,7 @@ static int check_eb_bitmap(unsigned long *bitmap, struct extent_buffer *eb) > > { > > unsigned long i; > > > > - for (i = 0; i < eb->len * BITS_PER_BYTE; i++) { > > + for (i = 0; i < eb->fs_info->nodesize * BITS_PER_BYTE; i++) { > > int bit, bit1; > > > > bit = !!test_bit(i, bitmap); > > @@ -411,7 +411,7 @@ static int test_bitmap_clear(const char *name, unsigned long *bitmap, > > static int __test_eb_bitmaps(unsigned long *bitmap, struct extent_buffer *eb) > > { > > unsigned long i, j; > > - unsigned long byte_len = eb->len; > > + unsigned long byte_len = eb->fs_info->nodesize; > > u32 x; > > int ret; > > > > @@ -670,7 +670,7 @@ static int test_find_first_clear_extent_bit(void) > > static void dump_eb_and_memory_contents(struct extent_buffer *eb, void *memory, > > const char *test_name) > > { > > - for (int i = 0; i < eb->len; i++) { > > + for (int i = 0; i < eb->fs_info->nodesize; i++) { > > struct page *page = folio_page(eb->folios[i >> PAGE_SHIFT], 0); > > void *addr = page_address(page) + offset_in_page(i); > > > > @@ -686,7 +686,7 @@ static void dump_eb_and_memory_contents(struct extent_buffer *eb, void *memory, > > static int verify_eb_and_memory(struct extent_buffer *eb, void *memory, > > const char *test_name) > > { > > - for (int i = 0; i < (eb->len >> PAGE_SHIFT); i++) { > > + for (int i = 0; i < (eb->fs_info->nodesize >> PAGE_SHIFT); i++) { > > void *eb_addr = folio_address(eb->folios[i]); > > > > if (memcmp(memory + (i << PAGE_SHIFT), eb_addr, PAGE_SIZE) != 0) { > > @@ -703,8 +703,8 @@ static int verify_eb_and_memory(struct extent_buffer *eb, void *memory, > > */ > > static void init_eb_and_memory(struct extent_buffer *eb, void *memory) > > { > > - get_random_bytes(memory, eb->len); > > - write_extent_buffer(eb, memory, 0, eb->len); > > + get_random_bytes(memory, eb->fs_info->nodesize); > > + write_extent_buffer(eb, memory, 0, eb->fs_info->nodesize); > > } > > > > static int test_eb_mem_ops(u32 sectorsize, u32 nodesize) > > diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c > > index 271c958909cd8..0b87f2e2ee75e 100644 > > --- a/fs/btrfs/zoned.c > > +++ b/fs/btrfs/zoned.c > > @@ -2416,7 +2416,7 @@ void btrfs_schedule_zone_finish_bg(struct btrfs_block_group *bg, > > struct extent_buffer *eb) > > { > > if (!test_bit(BLOCK_GROUP_FLAG_SEQUENTIAL_ZONE, &bg->runtime_flags) || > > - eb->start + eb->len * 2 <= bg->start + bg->zone_capacity) > > + eb->start + eb->fs_info->nodesize * 2 <= bg->start + bg->zone_capacity) > > return; > > > > if (WARN_ON(bg->zone_finish_work.func == btrfs_zone_finish_endio_workfn)) { > > -- > > 2.47.2 > > ^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH v3 0/2] btrfs: eb struct cleanups 2025-05-02 13:37 ` [PATCH v2 1/2] btrfs: remove extent buffer's redundant `len` member field Daniel Vacek 2025-05-02 17:35 ` Boris Burkov @ 2025-05-05 11:50 ` Daniel Vacek 2025-05-05 11:50 ` [PATCH v3 1/2] btrfs: remove extent buffer's redundant `len` member field Daniel Vacek 2025-05-05 11:50 ` [PATCH v3 2/2] btrfs: rearrange the extent buffer structure members Daniel Vacek 1 sibling, 2 replies; 35+ messages in thread From: Daniel Vacek @ 2025-05-05 11:50 UTC (permalink / raw) To: Chris Mason, Josef Bacik, David Sterba Cc: Daniel Vacek, linux-btrfs, linux-kernel This series is about the first patch. See the details there. The second patch is just a small followup size optimization. v1: https://lore.kernel.org/linux-btrfs/20250429151800.649010-1-neelx@suse.com/ v2: https://lore.kernel.org/linux-btrfs/20250502133725.1210587-2-neelx@suse.com/ To: Chris Mason <clm@fb.com> To: Josef Bacik <josef@toxicpanda.com> To: David Sterba <dsterba@suse.com> Cc: linux-btrfs@vger.kernel.org Cc: linux-kernel@vger.kernel.org Daniel Vacek (2): btrfs: remove extent buffer's redundant `len` member field btrfs: rearrange the extent buffer structure members fs/btrfs/accessors.c | 4 +-- fs/btrfs/disk-io.c | 11 +++--- fs/btrfs/extent-tree.c | 28 ++++++++------- fs/btrfs/extent_io.c | 59 ++++++++++++++------------------ fs/btrfs/extent_io.h | 12 +++---- fs/btrfs/ioctl.c | 2 +- fs/btrfs/relocation.c | 2 +- fs/btrfs/subpage.c | 12 ++++--- fs/btrfs/tests/extent-io-tests.c | 12 +++---- fs/btrfs/zoned.c | 2 +- 10 files changed, 72 insertions(+), 72 deletions(-) -- 2.47.2 ^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH v3 1/2] btrfs: remove extent buffer's redundant `len` member field 2025-05-05 11:50 ` [PATCH v3 0/2] btrfs: eb struct cleanups Daniel Vacek @ 2025-05-05 11:50 ` Daniel Vacek 2025-05-05 15:18 ` David Sterba 2025-05-05 11:50 ` [PATCH v3 2/2] btrfs: rearrange the extent buffer structure members Daniel Vacek 1 sibling, 1 reply; 35+ messages in thread From: Daniel Vacek @ 2025-05-05 11:50 UTC (permalink / raw) To: Chris Mason, Josef Bacik, David Sterba Cc: Daniel Vacek, Boris Burkov, linux-btrfs, linux-kernel Even super block nowadays uses nodesize for eb->len. This is since commits 551561c34663 ("btrfs: don't pass nodesize to __alloc_extent_buffer()") da17066c4047 ("btrfs: pull node/sector/stripe sizes out of root and into fs_info") ce3e69847e3e ("btrfs: sink parameter len to alloc_extent_buffer") a83fffb75d09 ("btrfs: sink blocksize parameter to btrfs_find_create_tree_block") With these the eb->len is not really useful anymore. Let's use the nodesize directly where applicable. Signed-off-by: Daniel Vacek <neelx@suse.com> Reviewed-by: Boris Burkov <boris@bur.io> --- v3 changes: - use local variable nodesize directly in btree_csum_one_bio(), spotted by Boris - include nodesize in the warning logged by report_eb_range(), suggested by Boris v2 changes: - https://lore.kernel.org/linux-btrfs/20250502133725.1210587-2-neelx@suse.com/ - rebased to this week's for-next - use plain eb->fs_info->nodesize instead of a helper function as suggested by Filipe and Wenruo - constify local nodesize variables as suggested by Wenruo v1: https://lore.kernel.org/linux-btrfs/20250429151800.649010-1-neelx@suse.com/ --- fs/btrfs/accessors.c | 4 +-- fs/btrfs/disk-io.c | 11 +++--- fs/btrfs/extent-tree.c | 28 ++++++++------- fs/btrfs/extent_io.c | 59 ++++++++++++++------------------ fs/btrfs/extent_io.h | 6 ++-- fs/btrfs/ioctl.c | 2 +- fs/btrfs/relocation.c | 2 +- fs/btrfs/subpage.c | 12 ++++--- fs/btrfs/tests/extent-io-tests.c | 12 +++---- fs/btrfs/zoned.c | 2 +- 10 files changed, 69 insertions(+), 69 deletions(-) diff --git a/fs/btrfs/accessors.c b/fs/btrfs/accessors.c index e3716516ca387..6839251b09a18 100644 --- a/fs/btrfs/accessors.c +++ b/fs/btrfs/accessors.c @@ -14,10 +14,10 @@ static bool check_setget_bounds(const struct extent_buffer *eb, { const unsigned long member_offset = (unsigned long)ptr + off; - if (unlikely(member_offset + size > eb->len)) { + if (unlikely(member_offset + size > eb->fs_info->nodesize)) { btrfs_warn(eb->fs_info, "bad eb member %s: ptr 0x%lx start %llu member offset %lu size %d", - (member_offset > eb->len ? "start" : "end"), + (member_offset > eb->fs_info->nodesize ? "start" : "end"), (unsigned long)ptr, eb->start, member_offset, size); return false; } diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 5bcf11246ba66..2f819446cef1c 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -190,7 +190,7 @@ static int btrfs_repair_eb_io_failure(const struct extent_buffer *eb, for (int i = 0; i < num_extent_folios(eb); i++) { struct folio *folio = eb->folios[i]; u64 start = max_t(u64, eb->start, folio_pos(folio)); - u64 end = min_t(u64, eb->start + eb->len, + u64 end = min_t(u64, eb->start + fs_info->nodesize, folio_pos(folio) + eb->folio_size); u32 len = end - start; phys_addr_t paddr = PFN_PHYS(folio_pfn(folio)) + @@ -230,7 +230,7 @@ int btrfs_read_extent_buffer(struct extent_buffer *eb, break; num_copies = btrfs_num_copies(fs_info, - eb->start, eb->len); + eb->start, fs_info->nodesize); if (num_copies == 1) break; @@ -260,6 +260,7 @@ int btree_csum_one_bio(struct btrfs_bio *bbio) { struct extent_buffer *eb = bbio->private; struct btrfs_fs_info *fs_info = eb->fs_info; + const u32 nodesize = fs_info->nodesize; u64 found_start = btrfs_header_bytenr(eb); u64 last_trans; u8 result[BTRFS_CSUM_SIZE]; @@ -268,7 +269,7 @@ int btree_csum_one_bio(struct btrfs_bio *bbio) /* Btree blocks are always contiguous on disk. */ if (WARN_ON_ONCE(bbio->file_offset != eb->start)) return -EIO; - if (WARN_ON_ONCE(bbio->bio.bi_iter.bi_size != eb->len)) + if (WARN_ON_ONCE(bbio->bio.bi_iter.bi_size != nodesize)) return -EIO; /* @@ -277,7 +278,7 @@ int btree_csum_one_bio(struct btrfs_bio *bbio) * ordering of I/O without unnecessarily writing out data. */ if (test_bit(EXTENT_BUFFER_ZONED_ZEROOUT, &eb->bflags)) { - memzero_extent_buffer(eb, 0, eb->len); + memzero_extent_buffer(eb, 0, nodesize); return 0; } @@ -881,7 +882,7 @@ struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans, btrfs_set_root_generation(&root->root_item, trans->transid); btrfs_set_root_level(&root->root_item, 0); btrfs_set_root_refs(&root->root_item, 1); - btrfs_set_root_used(&root->root_item, leaf->len); + btrfs_set_root_used(&root->root_item, fs_info->nodesize); btrfs_set_root_last_snapshot(&root->root_item, 0); btrfs_set_root_dirid(&root->root_item, 0); if (is_fstree(objectid)) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 64e8c653ae8f3..e1cce5b011993 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -2186,7 +2186,7 @@ int btrfs_set_disk_extent_flags(struct btrfs_trans_handle *trans, extent_op->update_flags = true; extent_op->update_key = false; - ret = btrfs_add_delayed_extent_op(trans, eb->start, eb->len, + ret = btrfs_add_delayed_extent_op(trans, eb->start, eb->fs_info->nodesize, btrfs_header_level(eb), extent_op); if (ret) btrfs_free_delayed_extent_op(extent_op); @@ -2635,10 +2635,10 @@ int btrfs_pin_extent_for_log_replay(struct btrfs_trans_handle *trans, if (ret) goto out; - pin_down_extent(trans, cache, eb->start, eb->len, 0); + pin_down_extent(trans, cache, eb->start, eb->fs_info->nodesize, 0); /* remove us from the free space cache (if we're there at all) */ - ret = btrfs_remove_free_space(cache, eb->start, eb->len); + ret = btrfs_remove_free_space(cache, eb->start, eb->fs_info->nodesize); out: btrfs_put_block_group(cache); return ret; @@ -3434,13 +3434,14 @@ int btrfs_free_tree_block(struct btrfs_trans_handle *trans, { struct btrfs_fs_info *fs_info = trans->fs_info; struct btrfs_block_group *bg; + const u32 nodesize = fs_info->nodesize; int ret; if (root_id != BTRFS_TREE_LOG_OBJECTID) { struct btrfs_ref generic_ref = { .action = BTRFS_DROP_DELAYED_REF, .bytenr = buf->start, - .num_bytes = buf->len, + .num_bytes = nodesize, .parent = parent, .owning_root = btrfs_header_owner(buf), .ref_root = root_id, @@ -3476,7 +3477,7 @@ int btrfs_free_tree_block(struct btrfs_trans_handle *trans, bg = btrfs_lookup_block_group(fs_info, buf->start); if (btrfs_header_flag(buf, BTRFS_HEADER_FLAG_WRITTEN)) { - pin_down_extent(trans, bg, buf->start, buf->len, 1); + pin_down_extent(trans, bg, buf->start, nodesize, 1); btrfs_put_block_group(bg); goto out; } @@ -3500,17 +3501,17 @@ int btrfs_free_tree_block(struct btrfs_trans_handle *trans, if (test_bit(BTRFS_FS_TREE_MOD_LOG_USERS, &fs_info->flags) || btrfs_is_zoned(fs_info)) { - pin_down_extent(trans, bg, buf->start, buf->len, 1); + pin_down_extent(trans, bg, buf->start, nodesize, 1); btrfs_put_block_group(bg); goto out; } WARN_ON(test_bit(EXTENT_BUFFER_DIRTY, &buf->bflags)); - btrfs_add_free_space(bg, buf->start, buf->len); - btrfs_free_reserved_bytes(bg, buf->len, 0); + btrfs_add_free_space(bg, buf->start, nodesize); + btrfs_free_reserved_bytes(bg, nodesize, 0); btrfs_put_block_group(bg); - trace_btrfs_reserved_extent_free(fs_info, buf->start, buf->len); + trace_btrfs_reserved_extent_free(fs_info, buf->start, nodesize); out: return 0; @@ -4766,7 +4767,7 @@ int btrfs_pin_reserved_extent(struct btrfs_trans_handle *trans, return -ENOSPC; } - ret = pin_down_extent(trans, cache, eb->start, eb->len, 1); + ret = pin_down_extent(trans, cache, eb->start, eb->fs_info->nodesize, 1); btrfs_put_block_group(cache); return ret; } @@ -5048,6 +5049,7 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_fs_info *fs_info = root->fs_info; struct extent_buffer *buf; u64 lockdep_owner = owner; + const u32 nodesize = fs_info->nodesize; buf = btrfs_find_create_tree_block(fs_info, bytenr, owner, level); if (IS_ERR(buf)) @@ -5105,16 +5107,16 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root, */ if (buf->log_index == 0) btrfs_set_extent_bit(&root->dirty_log_pages, buf->start, - buf->start + buf->len - 1, + buf->start + nodesize - 1, EXTENT_DIRTY, NULL); else btrfs_set_extent_bit(&root->dirty_log_pages, buf->start, - buf->start + buf->len - 1, + buf->start + nodesize - 1, EXTENT_NEW, NULL); } else { buf->log_index = -1; btrfs_set_extent_bit(&trans->transaction->dirty_pages, buf->start, - buf->start + buf->len - 1, EXTENT_DIRTY, NULL); + buf->start + nodesize - 1, EXTENT_DIRTY, NULL); } /* this returns a buffer locked for blocking */ return buf; diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index fa757f3da64fa..0df5534a834ad 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -76,8 +76,8 @@ void btrfs_extent_buffer_leak_debug_check(struct btrfs_fs_info *fs_info) eb = list_first_entry(&fs_info->allocated_ebs, struct extent_buffer, leak_list); pr_err( - "BTRFS: buffer leak start %llu len %u refs %d bflags %lu owner %llu\n", - eb->start, eb->len, atomic_read(&eb->refs), eb->bflags, + "BTRFS: buffer leak start %llu refs %d bflags %lu owner %llu\n", + eb->start, atomic_read(&eb->refs), eb->bflags, btrfs_header_owner(eb)); list_del(&eb->leak_list); WARN_ON_ONCE(1); @@ -1788,8 +1788,8 @@ static noinline_for_stack bool lock_extent_buffer_for_io(struct extent_buffer *e btrfs_set_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN); percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, - -eb->len, - fs_info->dirty_metadata_batch); + -fs_info->nodesize, + fs_info->dirty_metadata_batch); ret = true; } else { spin_unlock(&eb->refs_lock); @@ -1986,7 +1986,7 @@ static unsigned int buffer_tree_get_ebs_tag(struct btrfs_fs_info *fs_info, rcu_read_lock(); while ((eb = find_get_eb(&xas, end, tag)) != NULL) { if (!eb_batch_add(batch, eb)) { - *start = (eb->start + eb->len) >> fs_info->sectorsize_bits; + *start = (eb->start + fs_info->nodesize) >> fs_info->sectorsize_bits; goto out; } } @@ -2050,7 +2050,7 @@ static void prepare_eb_write(struct extent_buffer *eb) nritems = btrfs_header_nritems(eb); if (btrfs_header_level(eb) > 0) { end = btrfs_node_key_ptr_offset(eb, nritems); - memzero_extent_buffer(eb, end, eb->len - end); + memzero_extent_buffer(eb, end, eb->fs_info->nodesize - end); } else { /* * Leaf: @@ -2086,7 +2086,7 @@ static noinline_for_stack void write_one_eb(struct extent_buffer *eb, struct folio *folio = eb->folios[i]; u64 range_start = max_t(u64, eb->start, folio_pos(folio)); u32 range_len = min_t(u64, folio_pos(folio) + folio_size(folio), - eb->start + eb->len) - range_start; + eb->start + fs_info->nodesize) - range_start; folio_lock(folio); btrfs_meta_folio_clear_dirty(folio, eb); @@ -2200,7 +2200,7 @@ int btree_write_cache_pages(struct address_space *mapping, if (ctx.zoned_bg) { /* Mark the last eb in the block group. */ btrfs_schedule_zone_finish_bg(ctx.zoned_bg, eb); - ctx.zoned_bg->meta_write_pointer += eb->len; + ctx.zoned_bg->meta_write_pointer += fs_info->nodesize; } write_one_eb(eb, wbc); } @@ -2836,7 +2836,6 @@ static struct extent_buffer *__alloc_extent_buffer(struct btrfs_fs_info *fs_info eb = kmem_cache_zalloc(extent_buffer_cache, GFP_NOFS|__GFP_NOFAIL); eb->start = start; - eb->len = fs_info->nodesize; eb->fs_info = fs_info; init_rwsem(&eb->lock); @@ -2845,8 +2844,6 @@ static struct extent_buffer *__alloc_extent_buffer(struct btrfs_fs_info *fs_info spin_lock_init(&eb->refs_lock); atomic_set(&eb->refs, 1); - ASSERT(eb->len <= BTRFS_MAX_METADATA_BLOCKSIZE); - return eb; } @@ -3558,7 +3555,7 @@ void btrfs_clear_buffer_dirty(struct btrfs_trans_handle *trans, return; buffer_tree_clear_mark(eb, PAGECACHE_TAG_DIRTY); - percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, -eb->len, + percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, -fs_info->nodesize, fs_info->dirty_metadata_batch); for (int i = 0; i < num_extent_folios(eb); i++) { @@ -3589,7 +3586,8 @@ void set_extent_buffer_dirty(struct extent_buffer *eb) WARN_ON(test_bit(EXTENT_BUFFER_ZONED_ZEROOUT, &eb->bflags)); if (!was_dirty) { - bool subpage = btrfs_meta_is_subpage(eb->fs_info); + struct btrfs_fs_info *fs_info = eb->fs_info; + bool subpage = btrfs_meta_is_subpage(fs_info); /* * For subpage case, we can have other extent buffers in the @@ -3609,9 +3607,9 @@ void set_extent_buffer_dirty(struct extent_buffer *eb) buffer_tree_set_mark(eb, PAGECACHE_TAG_DIRTY); if (subpage) folio_unlock(eb->folios[0]); - percpu_counter_add_batch(&eb->fs_info->dirty_metadata_bytes, - eb->len, - eb->fs_info->dirty_metadata_batch); + percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, + fs_info->nodesize, + fs_info->dirty_metadata_batch); } #ifdef CONFIG_BTRFS_DEBUG for (int i = 0; i < num_extent_folios(eb); i++) @@ -3723,7 +3721,7 @@ int read_extent_buffer_pages_nowait(struct extent_buffer *eb, int mirror_num, struct folio *folio = eb->folios[i]; u64 range_start = max_t(u64, eb->start, folio_pos(folio)); u32 range_len = min_t(u64, folio_pos(folio) + folio_size(folio), - eb->start + eb->len) - range_start; + eb->start + eb->fs_info->nodesize) - range_start; bio_add_folio_nofail(&bbio->bio, folio, range_len, offset_in_folio(folio, range_start)); @@ -3751,8 +3749,8 @@ static bool report_eb_range(const struct extent_buffer *eb, unsigned long start, unsigned long len) { btrfs_warn(eb->fs_info, - "access to eb bytenr %llu len %u out of range start %lu len %lu", - eb->start, eb->len, start, len); + "access to eb bytenr %llu nodesize %u out of range start %lu len %lu", + eb->start, eb->fs_info->nodesize, start, len); DEBUG_WARN(); return true; @@ -3770,8 +3768,8 @@ static inline int check_eb_range(const struct extent_buffer *eb, { unsigned long offset; - /* start, start + len should not go beyond eb->len nor overflow */ - if (unlikely(check_add_overflow(start, len, &offset) || offset > eb->len)) + /* start, start + len should not go beyond nodesize nor overflow */ + if (unlikely(check_add_overflow(start, len, &offset) || offset > eb->fs_info->nodesize)) return report_eb_range(eb, start, len); return false; @@ -3827,8 +3825,8 @@ int read_extent_buffer_to_user_nofault(const struct extent_buffer *eb, unsigned long i = get_eb_folio_index(eb, start); int ret = 0; - WARN_ON(start > eb->len); - WARN_ON(start + len > eb->start + eb->len); + WARN_ON(start > eb->fs_info->nodesize); + WARN_ON(start + len > eb->start + eb->fs_info->nodesize); if (eb->addr) { if (copy_to_user_nofault(dstv, eb->addr + start, len)) @@ -3919,8 +3917,8 @@ static void assert_eb_folio_uptodate(const struct extent_buffer *eb, int i) folio = eb->folios[0]; ASSERT(i == 0); if (WARN_ON(!btrfs_subpage_test_uptodate(fs_info, folio, - eb->start, eb->len))) - btrfs_subpage_dump_bitmap(fs_info, folio, eb->start, eb->len); + eb->start, fs_info->nodesize))) + btrfs_subpage_dump_bitmap(fs_info, folio, eb->start, fs_info->nodesize); } else { WARN_ON(!folio_test_uptodate(folio)); } @@ -4013,12 +4011,10 @@ void copy_extent_buffer_full(const struct extent_buffer *dst, const int unit_size = src->folio_size; unsigned long cur = 0; - ASSERT(dst->len == src->len); - - while (cur < src->len) { + while (cur < src->fs_info->nodesize) { unsigned long index = get_eb_folio_index(src, cur); unsigned long offset = get_eb_offset_in_folio(src, cur); - unsigned long cur_len = min(src->len, unit_size - offset); + unsigned long cur_len = min(src->fs_info->nodesize, unit_size - offset); void *addr = folio_address(src->folios[index]) + offset; write_extent_buffer(dst, addr, cur, cur_len); @@ -4033,7 +4029,6 @@ void copy_extent_buffer(const struct extent_buffer *dst, unsigned long len) { const int unit_size = dst->folio_size; - u64 dst_len = dst->len; size_t cur; size_t offset; char *kaddr; @@ -4043,8 +4038,6 @@ void copy_extent_buffer(const struct extent_buffer *dst, check_eb_range(src, src_offset, len)) return; - WARN_ON(src->len != dst_len); - offset = get_eb_offset_in_folio(dst, dst_offset); while (len > 0) { @@ -4315,7 +4308,7 @@ static int try_release_subpage_extent_buffer(struct folio *folio) xa_unlock_irq(&fs_info->buffer_tree); break; } - cur = eb->start + eb->len; + cur = eb->start + fs_info->nodesize; /* * The same as try_release_extent_buffer(), to ensure the eb diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index e36e8d6a00bc5..7a8451c11630a 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h @@ -16,6 +16,7 @@ #include "messages.h" #include "ulist.h" #include "misc.h" +#include "fs.h" struct page; struct file; @@ -86,7 +87,6 @@ void __cold extent_buffer_free_cachep(void); #define INLINE_EXTENT_BUFFER_PAGES (BTRFS_MAX_METADATA_BLOCKSIZE / PAGE_SIZE) struct extent_buffer { u64 start; - u32 len; u32 folio_size; unsigned long bflags; struct btrfs_fs_info *fs_info; @@ -274,12 +274,12 @@ static inline int __pure num_extent_pages(const struct extent_buffer *eb) { /* * For sectorsize == PAGE_SIZE case, since nodesize is always aligned to - * sectorsize, it's just eb->len >> PAGE_SHIFT. + * sectorsize, it's just nodesize >> PAGE_SHIFT. * * For sectorsize < PAGE_SIZE case, we could have nodesize < PAGE_SIZE, * thus have to ensure we get at least one page. */ - return (eb->len >> PAGE_SHIFT) ?: 1; + return (eb->fs_info->nodesize >> PAGE_SHIFT) ?: 1; } /* diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index a498fe524c907..d06008ff63de9 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -598,7 +598,7 @@ static noinline int create_subvol(struct mnt_idmap *idmap, btrfs_set_root_generation(root_item, trans->transid); btrfs_set_root_level(root_item, 0); btrfs_set_root_refs(root_item, 1); - btrfs_set_root_used(root_item, leaf->len); + btrfs_set_root_used(root_item, fs_info->nodesize); btrfs_set_root_last_snapshot(root_item, 0); btrfs_set_root_generation_v2(root_item, diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 02086191630d0..fb194790406ff 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -4353,7 +4353,7 @@ int btrfs_reloc_cow_block(struct btrfs_trans_handle *trans, mark_block_processed(rc, node); if (first_cow && level > 0) - rc->nodes_relocated += buf->len; + rc->nodes_relocated += fs_info->nodesize; } if (level == 0 && first_cow && rc->stage == UPDATE_DATA_PTRS) diff --git a/fs/btrfs/subpage.c b/fs/btrfs/subpage.c index d4f0192334936..64c212f76ff12 100644 --- a/fs/btrfs/subpage.c +++ b/fs/btrfs/subpage.c @@ -631,7 +631,8 @@ void btrfs_meta_folio_set_##name(struct folio *folio, const struct extent_buffer folio_set_func(folio); \ return; \ } \ - btrfs_subpage_set_##name(eb->fs_info, folio, eb->start, eb->len); \ + btrfs_subpage_set_##name(eb->fs_info, folio, eb->start, \ + eb->fs_info->nodesize); \ } \ void btrfs_meta_folio_clear_##name(struct folio *folio, const struct extent_buffer *eb) \ { \ @@ -639,13 +640,15 @@ void btrfs_meta_folio_clear_##name(struct folio *folio, const struct extent_buff folio_clear_func(folio); \ return; \ } \ - btrfs_subpage_clear_##name(eb->fs_info, folio, eb->start, eb->len); \ + btrfs_subpage_clear_##name(eb->fs_info, folio, eb->start, \ + eb->fs_info->nodesize); \ } \ bool btrfs_meta_folio_test_##name(struct folio *folio, const struct extent_buffer *eb) \ { \ if (!btrfs_meta_is_subpage(eb->fs_info)) \ return folio_test_func(folio); \ - return btrfs_subpage_test_##name(eb->fs_info, folio, eb->start, eb->len); \ + return btrfs_subpage_test_##name(eb->fs_info, folio, eb->start, \ + eb->fs_info->nodesize); \ } IMPLEMENT_BTRFS_PAGE_OPS(uptodate, folio_mark_uptodate, folio_clear_uptodate, folio_test_uptodate); @@ -765,7 +768,8 @@ bool btrfs_meta_folio_clear_and_test_dirty(struct folio *folio, const struct ext return true; } - last = btrfs_subpage_clear_and_test_dirty(eb->fs_info, folio, eb->start, eb->len); + last = btrfs_subpage_clear_and_test_dirty(eb->fs_info, folio, eb->start, + eb->fs_info->nodesize); if (last) { folio_clear_dirty_for_io(folio); return true; diff --git a/fs/btrfs/tests/extent-io-tests.c b/fs/btrfs/tests/extent-io-tests.c index 00da54f0164c9..697d558808103 100644 --- a/fs/btrfs/tests/extent-io-tests.c +++ b/fs/btrfs/tests/extent-io-tests.c @@ -342,7 +342,7 @@ static int check_eb_bitmap(unsigned long *bitmap, struct extent_buffer *eb) { unsigned long i; - for (i = 0; i < eb->len * BITS_PER_BYTE; i++) { + for (i = 0; i < eb->fs_info->nodesize * BITS_PER_BYTE; i++) { int bit, bit1; bit = !!test_bit(i, bitmap); @@ -411,7 +411,7 @@ static int test_bitmap_clear(const char *name, unsigned long *bitmap, static int __test_eb_bitmaps(unsigned long *bitmap, struct extent_buffer *eb) { unsigned long i, j; - unsigned long byte_len = eb->len; + unsigned long byte_len = eb->fs_info->nodesize; u32 x; int ret; @@ -670,7 +670,7 @@ static int test_find_first_clear_extent_bit(void) static void dump_eb_and_memory_contents(struct extent_buffer *eb, void *memory, const char *test_name) { - for (int i = 0; i < eb->len; i++) { + for (int i = 0; i < eb->fs_info->nodesize; i++) { struct page *page = folio_page(eb->folios[i >> PAGE_SHIFT], 0); void *addr = page_address(page) + offset_in_page(i); @@ -686,7 +686,7 @@ static void dump_eb_and_memory_contents(struct extent_buffer *eb, void *memory, static int verify_eb_and_memory(struct extent_buffer *eb, void *memory, const char *test_name) { - for (int i = 0; i < (eb->len >> PAGE_SHIFT); i++) { + for (int i = 0; i < (eb->fs_info->nodesize >> PAGE_SHIFT); i++) { void *eb_addr = folio_address(eb->folios[i]); if (memcmp(memory + (i << PAGE_SHIFT), eb_addr, PAGE_SIZE) != 0) { @@ -703,8 +703,8 @@ static int verify_eb_and_memory(struct extent_buffer *eb, void *memory, */ static void init_eb_and_memory(struct extent_buffer *eb, void *memory) { - get_random_bytes(memory, eb->len); - write_extent_buffer(eb, memory, 0, eb->len); + get_random_bytes(memory, eb->fs_info->nodesize); + write_extent_buffer(eb, memory, 0, eb->fs_info->nodesize); } static int test_eb_mem_ops(u32 sectorsize, u32 nodesize) diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c index 271c958909cd8..0b87f2e2ee75e 100644 --- a/fs/btrfs/zoned.c +++ b/fs/btrfs/zoned.c @@ -2416,7 +2416,7 @@ void btrfs_schedule_zone_finish_bg(struct btrfs_block_group *bg, struct extent_buffer *eb) { if (!test_bit(BLOCK_GROUP_FLAG_SEQUENTIAL_ZONE, &bg->runtime_flags) || - eb->start + eb->len * 2 <= bg->start + bg->zone_capacity) + eb->start + eb->fs_info->nodesize * 2 <= bg->start + bg->zone_capacity) return; if (WARN_ON(bg->zone_finish_work.func == btrfs_zone_finish_endio_workfn)) { -- 2.47.2 ^ permalink raw reply related [flat|nested] 35+ messages in thread
* Re: [PATCH v3 1/2] btrfs: remove extent buffer's redundant `len` member field 2025-05-05 11:50 ` [PATCH v3 1/2] btrfs: remove extent buffer's redundant `len` member field Daniel Vacek @ 2025-05-05 15:18 ` David Sterba 2025-05-05 17:53 ` Daniel Vacek 0 siblings, 1 reply; 35+ messages in thread From: David Sterba @ 2025-05-05 15:18 UTC (permalink / raw) To: Daniel Vacek Cc: Chris Mason, Josef Bacik, David Sterba, Boris Burkov, linux-btrfs, linux-kernel On Mon, May 05, 2025 at 01:50:54PM +0200, Daniel Vacek wrote: > Even super block nowadays uses nodesize for eb->len. This is since commits > > 551561c34663 ("btrfs: don't pass nodesize to __alloc_extent_buffer()") > da17066c4047 ("btrfs: pull node/sector/stripe sizes out of root and into fs_info") > ce3e69847e3e ("btrfs: sink parameter len to alloc_extent_buffer") > a83fffb75d09 ("btrfs: sink blocksize parameter to btrfs_find_create_tree_block") > > With these the eb->len is not really useful anymore. Let's use the nodesize > directly where applicable. You haven't updated the changelog despite we had a discussion about the potential drawbacks, so this should be here. But I'm not convinced this is a good change. The eb size does not change so no better packing in the slab and the caching of length in the same cacheline is lost. In the assebly it's clear where the pointer dereference is added, using an example from btrfs_get_token_8(): mov 0x8(%rbp),%r9d vs mov 0x18(%rbp),%r10 mov 0xd38(%r10),%r9d And there's a new register dependency. The eb operations are most of the time performed on memory structures and not just in connnection with IO, I think this could be measurable on a fast device with metadata heavy workload. So I'd rather see some numbers this will not decrease performance. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v3 1/2] btrfs: remove extent buffer's redundant `len` member field 2025-05-05 15:18 ` David Sterba @ 2025-05-05 17:53 ` Daniel Vacek 2025-05-13 0:32 ` David Sterba 0 siblings, 1 reply; 35+ messages in thread From: Daniel Vacek @ 2025-05-05 17:53 UTC (permalink / raw) To: dsterba Cc: Chris Mason, Josef Bacik, David Sterba, Boris Burkov, linux-btrfs, linux-kernel On Mon, 5 May 2025 at 17:18, David Sterba <dsterba@suse.cz> wrote: > > On Mon, May 05, 2025 at 01:50:54PM +0200, Daniel Vacek wrote: > > Even super block nowadays uses nodesize for eb->len. This is since commits > > > > 551561c34663 ("btrfs: don't pass nodesize to __alloc_extent_buffer()") > > da17066c4047 ("btrfs: pull node/sector/stripe sizes out of root and into fs_info") > > ce3e69847e3e ("btrfs: sink parameter len to alloc_extent_buffer") > > a83fffb75d09 ("btrfs: sink blocksize parameter to btrfs_find_create_tree_block") > > > > With these the eb->len is not really useful anymore. Let's use the nodesize > > directly where applicable. > > You haven't updated the changelog despite we had a discussion about the > potential drawbacks, so this should be here. But I'm not convinced this Right. That's because I was not sure we came to any conclusion yet. I thought this discussion was still ongoing. I understand that so far this is still all just a theory and any premature conclusions may be misleading. But yeah, I may write some kind of a warning or a disclaimer mentioning the suspicion. Just so that it gets documented and it is clear it was considered, even though maybe without a clear conclusion. > is a good change. The eb size does not change so no better packing in > the slab and the caching of length in the same cacheline is lost. So to be perfectly clear, what sharing do you mean? Is it the eb->start and eb->len you talking about? In other words, when getting `start` you also get `len` for free? Since the structure is 8 bytes aligned, they may eventually still end up in two cachelines. Luckily the size of the structure is 0 mod 16 so just out of the luck this never happens and they are always in the same cache line. But this may break with future changes, so it is not rock solid the way it is now. > In the assebly it's clear where the pointer dereference is added, using > an example from btrfs_get_token_8(): > > mov 0x8(%rbp),%r9d > > vs > > mov 0x18(%rbp),%r10 > mov 0xd38(%r10),%r9d I understand that. Again, this is what I originally considered. Not all the functions end up like this but there are definitely some. And by a rule of a thumb it's roughly half of them, give or take. That sounds like a good reason to be concerned. My reasoning was that the fs_info->nodesize is accessed by many so the chances are it will be hot in cache. But you're right that this may not always be the case. It depends. The question remains if that makes a difference? Another (IMO valid) point is that I believe the code will dereference many other pointers before getting here so this may seem like a drop in the sea. It's not like this was a tight loop scattering over hundreds random memory addresses. For example when this code is reached from a syscall, the syscall itself will have significantly higher overhead then one additional dereference. And I think the same applies when reached from an interrupt. Otherwise this would be visible on perf profile (which none of us performed yet). Still, I'd say reading the assembly is a good indication of possible issues to be concerned with. But it's not always the best one. An observed performance regression would be. I'll be happy to conduct any suggested benchmarks. Though as you mentioned this may be also picky on the used HW. So even though we don't see any regressions with our testing, one day someone may find some if we merged this change. In which case we can always revert. I have to say I'm pretty happy with the positive feedback from the other reviewers. So far you're the only one raising this concern. So how do we conclude this? If you don't want this cleanup I'd opt at least for rename eb->len ==>> eb->nodesize. > And there's a new register dependency. The eb operations are most of the > time performed on memory structures and not just in connnection with IO, > I think this could be measurable on a fast device with metadata heavy > workload. So I'd rather see some numbers this will not decrease > performance. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v3 1/2] btrfs: remove extent buffer's redundant `len` member field 2025-05-05 17:53 ` Daniel Vacek @ 2025-05-13 0:32 ` David Sterba 2025-05-13 10:43 ` Daniel Vacek 0 siblings, 1 reply; 35+ messages in thread From: David Sterba @ 2025-05-13 0:32 UTC (permalink / raw) To: Daniel Vacek Cc: dsterba, Chris Mason, Josef Bacik, David Sterba, Boris Burkov, linux-btrfs, linux-kernel On Mon, May 05, 2025 at 07:53:16PM +0200, Daniel Vacek wrote: > On Mon, 5 May 2025 at 17:18, David Sterba <dsterba@suse.cz> wrote: > > > > On Mon, May 05, 2025 at 01:50:54PM +0200, Daniel Vacek wrote: > > > Even super block nowadays uses nodesize for eb->len. This is since commits > > > > > > 551561c34663 ("btrfs: don't pass nodesize to __alloc_extent_buffer()") > > > da17066c4047 ("btrfs: pull node/sector/stripe sizes out of root and into fs_info") > > > ce3e69847e3e ("btrfs: sink parameter len to alloc_extent_buffer") > > > a83fffb75d09 ("btrfs: sink blocksize parameter to btrfs_find_create_tree_block") > > > > > > With these the eb->len is not really useful anymore. Let's use the nodesize > > > directly where applicable. > > > > You haven't updated the changelog despite we had a discussion about the > > potential drawbacks, so this should be here. But I'm not convinced this > > Right. That's because I was not sure we came to any conclusion yet. I > thought this discussion was still ongoing. I understand that so far > this is still all just a theory and any premature conclusions may be > misleading. > > But yeah, I may write some kind of a warning or a disclaimer > mentioning the suspicion. Just so that it gets documented and it is > clear it was considered, even though maybe without a clear conclusion. > > > is a good change. The eb size does not change so no better packing in > > the slab and the caching of length in the same cacheline is lost. > > So to be perfectly clear, what sharing do you mean? Is it the > eb->start and eb->len you talking about? In other words, when getting > `start` you also get `len` for free? Yes, basically. > Since the structure is 8 bytes aligned, they may eventually still end > up in two cachelines. Luckily the size of the structure is 0 mod 16 so > just out of the luck this never happens and they are always in the > same cache line. But this may break with future changes, so it is not > rock solid the way it is now. Yes, with structures not perfectly aligned to a cacheline (64B) there will be times when the access needs fetching two cachelines. With locks it can result in various cacheline bouncing patterns when various allocated structures are aligned to 8 bytes, giving 8 possible groups of "misaligned" structure instances. There's also a big assumption that the CPU cache prefetcher is clever enough to average out many bad patterns. What I try to do on the source code level is to be able to reason about the high level access patterns, like "used at the same time -> close together in the structure". > > In the assebly it's clear where the pointer dereference is added, using > > an example from btrfs_get_token_8(): > > > > mov 0x8(%rbp),%r9d > > > > vs > > > > mov 0x18(%rbp),%r10 > > mov 0xd38(%r10),%r9d > > I understand that. Again, this is what I originally considered. Not > all the functions end up like this but there are definitely some. And > by a rule of a thumb it's roughly half of them, give or take. That > sounds like a good reason to be concerned. > > My reasoning was that the fs_info->nodesize is accessed by many so the > chances are it will be hot in cache. But you're right that this may > not always be the case. It depends. The question remains if that makes > a difference? > > Another (IMO valid) point is that I believe the code will dereference > many other pointers before getting here so this may seem like a drop > in the sea. It's not like this was a tight loop scattering over > hundreds random memory addresses. > For example when this code is reached from a syscall, the syscall > itself will have significantly higher overhead then one additional > dereference. And I think the same applies when reached from an > interrupt. > Otherwise this would be visible on perf profile (which none of us > performed yet). Yeah and I don't intend to do so other than to verify your measurements and calims that this patch does not make things worse at least. The burden is on the patch submitter. > Still, I'd say reading the assembly is a good indication of possible > issues to be concerned with. But it's not always the best one. An > observed performance regression would be. > I'll be happy to conduct any suggested benchmarks. Though as you > mentioned this may be also picky on the used HW. I'd say any contemporary hardware is good, I don't think the internal CPU algorithms of prefetching or branch predictions change that often. A difference that I would consider significant is 5% in either direction. > So even though we > don't see any regressions with our testing, one day someone may find > some if we merged this change. In which case we can always revert. > > I have to say I'm pretty happy with the positive feedback from the > other reviewers. So far you're the only one raising this concern. I don't dispute the feedback from others, the patch is not wrong on itself, it removes a redundant member. However I don't see it as a simple change because I also spent some time looking into that particular structure, shrinking size, member ordering and access patterns that I am questioning the runtime performance implications. My local eb->len removal patch is from 2020 and I decided not to send it because I was not able to prove to myself it'd be for the better. This is what I base my feedback on. > So how do we conclude this? I don't agree to add this patch due to the following main points: - no struct size change, ie. same number of objects in the slab - disputed cacheline behaviour, numbers showing improvement or not making it worse needed > If you don't want this cleanup I'd opt at least for rename eb->len > ==>> eb->nodesize. This sounds like an unnecessary churn. 'length' related to a structure is natural, nodesize is a property of the whole filesystem, we're used to eb->len, I don't any benefit to increase the cognitive load. ^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v3 1/2] btrfs: remove extent buffer's redundant `len` member field 2025-05-13 0:32 ` David Sterba @ 2025-05-13 10:43 ` Daniel Vacek 0 siblings, 0 replies; 35+ messages in thread From: Daniel Vacek @ 2025-05-13 10:43 UTC (permalink / raw) To: dsterba Cc: Chris Mason, Josef Bacik, David Sterba, Boris Burkov, linux-btrfs, linux-kernel On Tue, 13 May 2025 at 02:32, David Sterba <dsterba@suse.cz> wrote: > > On Mon, May 05, 2025 at 07:53:16PM +0200, Daniel Vacek wrote: > > On Mon, 5 May 2025 at 17:18, David Sterba <dsterba@suse.cz> wrote: > > > > > > On Mon, May 05, 2025 at 01:50:54PM +0200, Daniel Vacek wrote: > > > > Even super block nowadays uses nodesize for eb->len. This is since commits > > > > > > > > 551561c34663 ("btrfs: don't pass nodesize to __alloc_extent_buffer()") > > > > da17066c4047 ("btrfs: pull node/sector/stripe sizes out of root and into fs_info") > > > > ce3e69847e3e ("btrfs: sink parameter len to alloc_extent_buffer") > > > > a83fffb75d09 ("btrfs: sink blocksize parameter to btrfs_find_create_tree_block") > > > > > > > > With these the eb->len is not really useful anymore. Let's use the nodesize > > > > directly where applicable. > > > > > > You haven't updated the changelog despite we had a discussion about the > > > potential drawbacks, so this should be here. But I'm not convinced this > > > > Right. That's because I was not sure we came to any conclusion yet. I > > thought this discussion was still ongoing. I understand that so far > > this is still all just a theory and any premature conclusions may be > > misleading. > > > > But yeah, I may write some kind of a warning or a disclaimer > > mentioning the suspicion. Just so that it gets documented and it is > > clear it was considered, even though maybe without a clear conclusion. > > > > > is a good change. The eb size does not change so no better packing in > > > the slab and the caching of length in the same cacheline is lost. > > > > So to be perfectly clear, what sharing do you mean? Is it the > > eb->start and eb->len you talking about? In other words, when getting > > `start` you also get `len` for free? > > Yes, basically. > > > Since the structure is 8 bytes aligned, they may eventually still end > > up in two cachelines. Luckily the size of the structure is 0 mod 16 so > > just out of the luck this never happens and they are always in the > > same cache line. But this may break with future changes, so it is not > > rock solid the way it is now. > > Yes, with structures not perfectly aligned to a cacheline (64B) there > will be times when the access needs fetching two cachelines. With locks > it can result in various cacheline bouncing patterns when various > allocated structures are aligned to 8 bytes, giving 8 possible groups of > "misaligned" structure instances. > > There's also a big assumption that the CPU cache prefetcher is clever > enough to average out many bad patterns. What I try to do on the source > code level is to be able to reason about the high level access patterns, > like "used at the same time -> close together in the structure". That makes sense. The closer they are the higher the chance they end up in the same cacheline if the object itself is free of alignment. > > > In the assebly it's clear where the pointer dereference is added, using > > > an example from btrfs_get_token_8(): > > > > > > mov 0x8(%rbp),%r9d > > > > > > vs > > > > > > mov 0x18(%rbp),%r10 > > > mov 0xd38(%r10),%r9d > > > > I understand that. Again, this is what I originally considered. Not > > all the functions end up like this but there are definitely some. And > > by a rule of a thumb it's roughly half of them, give or take. That > > sounds like a good reason to be concerned. > > > > My reasoning was that the fs_info->nodesize is accessed by many so the > > chances are it will be hot in cache. But you're right that this may > > not always be the case. It depends. The question remains if that makes > > a difference? > > > > Another (IMO valid) point is that I believe the code will dereference > > many other pointers before getting here so this may seem like a drop > > in the sea. It's not like this was a tight loop scattering over > > hundreds random memory addresses. > > For example when this code is reached from a syscall, the syscall > > itself will have significantly higher overhead then one additional > > dereference. And I think the same applies when reached from an > > interrupt. > > Otherwise this would be visible on perf profile (which none of us > > performed yet). > > Yeah and I don't intend to do so other than to verify your measurements > and calims that this patch does not make things worse at least. The > burden is on the patch submitter. Totally. I'll run some profiles to see if anything significant is visible. Not sure what workload to use though? I guess fio would be a good starting point? Though we agreed that this also depends on the actual HW used. Whatever numbers I present, if my CPU is fast enough and my storage is slow enough, I'll hardly ever find any issue. I think this needs more broader testing than just one's claims that this is OK for me (provided my results would suggest so). So how about pushing this to misc-next to get some broader testing and see if there are any issues in the bigger scope? > > Still, I'd say reading the assembly is a good indication of possible > > issues to be concerned with. But it's not always the best one. An > > observed performance regression would be. > > I'll be happy to conduct any suggested benchmarks. Though as you > > mentioned this may be also picky on the used HW. > > I'd say any contemporary hardware is good, I don't think the internal > CPU algorithms of prefetching or branch predictions change that often. A > difference that I would consider significant is 5% in either direction. I meant the storage part rather than the CPU. Though the CPUs also differ in cache sizes between consumer and server parts. > > So even though we > > don't see any regressions with our testing, one day someone may find > > some if we merged this change. In which case we can always revert. > > > > I have to say I'm pretty happy with the positive feedback from the > > other reviewers. So far you're the only one raising this concern. > > I don't dispute the feedback from others, the patch is not wrong on > itself, it removes a redundant member. However I don't see it as a > simple change because I also spent some time looking into that > particular structure, shrinking size, member ordering and access > patterns that I am questioning the runtime performance implications. With that experience, would you suggest any other tests than fio where a performance change could be visible? Something I can focus on? > My local eb->len removal patch is from 2020 and I decided not to send it > because I was not able to prove to myself it'd be for the better. This > is what I base my feedback on. I understand. Let's see what we can do about it. > > So how do we conclude this? > > I don't agree to add this patch due to the following main points: > > - no struct size change, ie. same number of objects in the slab Right. That makes sense as the original idea was about code cleanup and not about reducing the struct size in terms of bytes. I did not think a cleanup needs to be justified by reducing the struct size. Even without that I believe it's still a good cleanup. The struct is still reduced by one member (with a new hole now). Moreover with the followup patch the size is actually reduced at least for -rt configs by filling the new hole so that the later hole is not created at all. This wins 8 bytes for -rt. Not much and maybe not worth it. Or is it? That said, as long as the removed member was not meant to cache the fs-wide value for performance reasons. I did not see any documentation or code comments suggesting that's the case (even you're not able to tell for sure) and so I thought it may be fine to remove this eb->len field. Which brings us to the point below. > - disputed cacheline behaviour, numbers showing improvement or not > making it worse needed I'll look into this. As I said, any hints are welcome otherwise I'll start with fio and I'll compare the perf profiles of some functions which access the data. Let me know if I can do anything better than that, please. > > If you don't want this cleanup I'd opt at least for rename eb->len > > ==>> eb->nodesize. > > This sounds like an unnecessary churn. 'length' related to a structure > is natural, nodesize is a property of the whole filesystem, we're used > to eb->len, I don't any benefit to increase the cognitive load. Now, our points of view differ here. For someone new to the codebase, I need to carry on the additional information that eb->len actually means the nodesize. In other words without digging this detail up the code just hides that fact. Since it's always set to nodesize, it does not really mean 'length' as in any arbitrary length, like 12345 bytes. And that's what I was trying to clean up. See? Does it make sense? Also that's why as an alternative I suggested renaming the member if removing it is not really favorable. And I thought it can also have implications maybe at some places when you realize that what's being used in the expression as eb->len really means the fs-wide nodesize. After all, with this insight I realized that the buffer_tree is inefficient as we're wasting the slots using the tree really sparsely. Since there are no shorter ebs, those empty slots can never be filled. So using the right name actually makes sense, IMO. For code clarity. But I can also understand your point and I can get used to it. It just does not feel right to me, but it's not a big deal. I just mentioned it to know others' POV and explain the intention one way or the other. ^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH v3 2/2] btrfs: rearrange the extent buffer structure members 2025-05-05 11:50 ` [PATCH v3 0/2] btrfs: eb struct cleanups Daniel Vacek 2025-05-05 11:50 ` [PATCH v3 1/2] btrfs: remove extent buffer's redundant `len` member field Daniel Vacek @ 2025-05-05 11:50 ` Daniel Vacek 1 sibling, 0 replies; 35+ messages in thread From: Daniel Vacek @ 2025-05-05 11:50 UTC (permalink / raw) To: Chris Mason, Josef Bacik, David Sterba Cc: Daniel Vacek, linux-btrfs, linux-kernel Fill in the hole after the removed `len` field. There should be no difference on default config but it cuts the size down by 8 bytes on -rt kernels due to different lock sizes and alignment. This way we can completely get rid of the other hole which was there before. Signed-off-by: Daniel Vacek <neelx@suse.com> --- This patch is new in v2. No changes for v3. @Dave> What assembly would you like to see? >@@ -10148,30 +10148,27 @@ > struct extent_buffer { > u64 start; /* 0 8 */ > u32 folio_size; /* 8 4 */ >+ u8 folio_shift; /* 12 1 */ >+ s8 log_index; /* 13 1 */ > >- /* XXX 4 bytes hole, try to pack */ >+ /* XXX 2 bytes hole, try to pack */ > > long unsigned int bflags; /* 16 8 */ > struct btrfs_fs_info * fs_info; /* 24 8 */ > void * addr; /* 32 8 */ > spinlock_t refs_lock; /* 40 32 */ > /* --- cacheline 1 boundary (64 bytes) was 8 bytes ago --- */ > atomic_t refs; /* 72 4 */ > int read_mirror; /* 76 4 */ >- s8 log_index; /* 80 1 */ >- u8 folio_shift; /* 81 1 */ >+ struct callback_head callback_head __attribute__((__aligned__(8))); /* 80 16 */ >+ struct rw_semaphore lock; /* 96 40 */ >+ /* --- cacheline 2 boundary (128 bytes) was 8 bytes ago --- */ >+ struct folio * folios[16]; /* 136 128 */ > >- /* XXX 6 bytes hole, try to pack */ >- >- struct callback_head callback_head __attribute__((__aligned__(8))); /* 88 16 */ >- struct rw_semaphore lock; /* 104 40 */ >- /* --- cacheline 2 boundary (128 bytes) was 16 bytes ago --- */ >- struct folio * folios[16]; /* 144 128 */ >- >- /* size: 272, cachelines: 5, members: 13 */ >- /* sum members: 262, holes: 2, sum holes: 10 */ >- /* forced alignments: 1, forced holes: 1, sum forced holes: 6 */ >- /* last cacheline: 16 bytes */ >+ /* size: 264, cachelines: 5, members: 13 */ >+ /* sum members: 262, holes: 1, sum holes: 2 */ >+ /* forced alignments: 1 */ >+ /* last cacheline: 8 bytes */ > } __attribute__((__aligned__(8))); Here the refs_lock and refs are split to different cachelines. But the slab object is not aligned anyways so this is inevitable anyways on -rt. For non-rt they always move together as they fit into 8 bytes aligned. So that's not an issue for non-rt. --- fs/btrfs/extent_io.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index 7a8451c11630a..5162d2da767ad 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h @@ -88,6 +88,9 @@ void __cold extent_buffer_free_cachep(void); struct extent_buffer { u64 start; u32 folio_size; + u8 folio_shift; + /* >= 0 if eb belongs to a log tree, -1 otherwise */ + s8 log_index; unsigned long bflags; struct btrfs_fs_info *fs_info; @@ -100,9 +103,6 @@ struct extent_buffer { spinlock_t refs_lock; atomic_t refs; int read_mirror; - /* >= 0 if eb belongs to a log tree, -1 otherwise */ - s8 log_index; - u8 folio_shift; struct rcu_head rcu_head; struct rw_semaphore lock; -- 2.47.2 ^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v2 2/2] btrfs: rearrange the extent buffer structure members 2025-05-02 13:37 ` [PATCH v2 0/2] btrfs: eb struct cleanups Daniel Vacek 2025-05-02 13:37 ` [PATCH v2 1/2] btrfs: remove extent buffer's redundant `len` member field Daniel Vacek @ 2025-05-02 13:37 ` Daniel Vacek 1 sibling, 0 replies; 35+ messages in thread From: Daniel Vacek @ 2025-05-02 13:37 UTC (permalink / raw) To: David Sterba, Chris Mason, Josef Bacik Cc: Daniel Vacek, linux-btrfs, linux-kernel Fill in the hole after the removed `len` field. There should be no difference on default config but it cuts the size down by 8 bytes on -rt kernels due to different lock sizes and alignment. This way we can completely get rid of the other hole which was there before. Signed-off-by: Daniel Vacek <neelx@suse.com> --- This patch is new in v2. @Dave> What assembly would you like to see? >@@ -10148,30 +10148,27 @@ > struct extent_buffer { > u64 start; /* 0 8 */ > u32 folio_size; /* 8 4 */ >+ u8 folio_shift; /* 12 1 */ >+ s8 log_index; /* 13 1 */ > >- /* XXX 4 bytes hole, try to pack */ >+ /* XXX 2 bytes hole, try to pack */ > > long unsigned int bflags; /* 16 8 */ > struct btrfs_fs_info * fs_info; /* 24 8 */ > void * addr; /* 32 8 */ > spinlock_t refs_lock; /* 40 32 */ > /* --- cacheline 1 boundary (64 bytes) was 8 bytes ago --- */ > atomic_t refs; /* 72 4 */ > int read_mirror; /* 76 4 */ >- s8 log_index; /* 80 1 */ >- u8 folio_shift; /* 81 1 */ >+ struct callback_head callback_head __attribute__((__aligned__(8))); /* 80 16 */ >+ struct rw_semaphore lock; /* 96 40 */ >+ /* --- cacheline 2 boundary (128 bytes) was 8 bytes ago --- */ >+ struct folio * folios[16]; /* 136 128 */ > >- /* XXX 6 bytes hole, try to pack */ >- >- struct callback_head callback_head __attribute__((__aligned__(8))); /* 88 16 */ >- struct rw_semaphore lock; /* 104 40 */ >- /* --- cacheline 2 boundary (128 bytes) was 16 bytes ago --- */ >- struct folio * folios[16]; /* 144 128 */ >- >- /* size: 272, cachelines: 5, members: 13 */ >- /* sum members: 262, holes: 2, sum holes: 10 */ >- /* forced alignments: 1, forced holes: 1, sum forced holes: 6 */ >- /* last cacheline: 16 bytes */ >+ /* size: 264, cachelines: 5, members: 13 */ >+ /* sum members: 262, holes: 1, sum holes: 2 */ >+ /* forced alignments: 1 */ >+ /* last cacheline: 8 bytes */ > } __attribute__((__aligned__(8))); Here the refs_lock and refs are split to different cachelines. But the slab object is not aligned anyways so this is inevitable anyways on -rt. For non-rt they always move together as they fit into 8 bytes aligned. So that's not an issue for non-rt. --- fs/btrfs/extent_io.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index 7a8451c11630a..5162d2da767ad 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h @@ -88,6 +88,9 @@ void __cold extent_buffer_free_cachep(void); struct extent_buffer { u64 start; u32 folio_size; + u8 folio_shift; + /* >= 0 if eb belongs to a log tree, -1 otherwise */ + s8 log_index; unsigned long bflags; struct btrfs_fs_info *fs_info; @@ -100,9 +103,6 @@ struct extent_buffer { spinlock_t refs_lock; atomic_t refs; int read_mirror; - /* >= 0 if eb belongs to a log tree, -1 otherwise */ - s8 log_index; - u8 folio_shift; struct rcu_head rcu_head; struct rw_semaphore lock; -- 2.47.2 ^ permalink raw reply related [flat|nested] 35+ messages in thread
end of thread, other threads:[~2025-05-13 10:43 UTC | newest] Thread overview: 35+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-04-29 15:17 [PATCH] btrfs: remove extent buffer's redundant `len` member field Daniel Vacek 2025-04-29 22:34 ` Qu Wenruo 2025-04-30 8:03 ` David Sterba 2025-04-30 8:21 ` Daniel Vacek 2025-04-30 12:31 ` Daniel Vacek 2025-05-02 10:30 ` David Sterba 2025-05-02 11:23 ` Daniel Vacek 2025-04-30 13:30 ` David Sterba 2025-04-30 14:13 ` Daniel Vacek 2025-05-02 10:56 ` David Sterba 2025-05-02 12:03 ` Daniel Vacek 2025-05-05 14:10 ` David Sterba 2025-05-05 16:19 ` Daniel Vacek 2025-04-30 8:05 ` Filipe Manana 2025-04-30 8:26 ` Daniel Vacek 2025-04-30 8:34 ` Filipe Manana 2025-04-30 8:50 ` Daniel Vacek 2025-04-30 10:26 ` Filipe Manana 2025-04-30 11:09 ` Johannes Thumshirn 2025-04-30 12:09 ` Daniel Vacek 2025-04-30 12:06 ` Daniel Vacek 2025-04-30 12:33 ` Filipe Manana 2025-04-30 12:53 ` Daniel Vacek 2025-05-02 13:37 ` [PATCH v2 0/2] btrfs: eb struct cleanups Daniel Vacek 2025-05-02 13:37 ` [PATCH v2 1/2] btrfs: remove extent buffer's redundant `len` member field Daniel Vacek 2025-05-02 17:35 ` Boris Burkov 2025-05-05 8:23 ` Daniel Vacek 2025-05-05 11:50 ` [PATCH v3 0/2] btrfs: eb struct cleanups Daniel Vacek 2025-05-05 11:50 ` [PATCH v3 1/2] btrfs: remove extent buffer's redundant `len` member field Daniel Vacek 2025-05-05 15:18 ` David Sterba 2025-05-05 17:53 ` Daniel Vacek 2025-05-13 0:32 ` David Sterba 2025-05-13 10:43 ` Daniel Vacek 2025-05-05 11:50 ` [PATCH v3 2/2] btrfs: rearrange the extent buffer structure members Daniel Vacek 2025-05-02 13:37 ` [PATCH v2 " Daniel Vacek
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox