[PATCH 5/7] btrfs: accessors: compile-time fast path for u16

David Sterba
2025-07-01T17:24:19Z

Reading/writing 2 bytes (u16) may need 2 folios to be written to, each
time it's just one byte so using memcpy for that is an overkill.
Add a branch for the split case so that memcpy is now used for u32 and
u64. Another side effect is that the u16 types now don't need additional
stack space, everything fits to registers.

Stack usage is reduced:

btrfs_get_16 -8 (32 -> 24)
btrfs_set_16 -16 (32 -> 16)

Code size reduction:

text data bss dec hex filename
1454691 115665 16088 1586444 18350c pre/btrfs.ko
1454459 115665 16088 1586212 183424 post/btrfs.ko

DELTA: -232

Signed-off-by: David Sterba <dsterba@suse.com>
---
fs/btrfs/accessors.c | 25 ++++++++++++++++++-------
1 file changed, 18 insertions(+), 7 deletions(-)

diff --git a/fs/btrfs/accessors.c b/fs/btrfs/accessors.c
index 547e9f8fb87d61..8df404b5f6a334 100644
--- a/fs/btrfs/accessors.c
+++ b/fs/btrfs/accessors.c
@@ -59,9 +59,15 @@ u##bits btrfs_get_##bits(const struct extent_buffer *eb, \
likely(sizeof(u##bits) <= part)) \
return get_unaligned_le##bits(kaddr + oil); \
\
- memcpy(lebytes, kaddr + oil, part); \
- kaddr = folio_address(eb->folios[idx + 1]); \
- memcpy(lebytes + part, kaddr, sizeof(u##bits) - part); \
+ if (sizeof(u##bits) == 2) { \
+ lebytes[0] = *(kaddr + oil); \
+ kaddr = folio_address(eb->folios[idx + 1]); \
+ lebytes[1] = *kaddr; \
+ } else { \
+ memcpy(lebytes, kaddr + oil, part); \
+ kaddr = folio_address(eb->folios[idx + 1]); \
+ memcpy(lebytes + part, kaddr, sizeof(u##bits) - part); \
+ } \
return get_unaligned_le##bits(lebytes); \
} \
void btrfs_set_##bits(const struct extent_buffer *eb, void *ptr, \
@@ -84,11 +90,16 @@ void btrfs_set_##bits(const struct extent_buffer *eb, void *ptr, \
put_unaligned_le##bits(val, kaddr + oil); \
return; \
} \
- \
put_unaligned_le##bits(val, lebytes); \
- memcpy(kaddr + oil, lebytes, part); \
- kaddr = folio_address(eb->folios[idx + 1]); \
- memcpy(kaddr, lebytes + part, sizeof(u##bits) - part); \
+ if (sizeof(u##bits) == 2) { \
+ *(kaddr + oil) = lebytes[0]; \
+ kaddr = folio_address(eb->folios[idx + 1]); \
+ *kaddr = lebytes[1]; \
+ } else { \
+ memcpy(kaddr + oil, lebytes, part); \
+ kaddr = folio_address(eb->folios[idx + 1]); \
+ memcpy(kaddr, lebytes + part, sizeof(u##bits) - part); \
+ } \
}

DEFINE_BTRFS_SETGET_BITS(8)
--
2.49.0