summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorDavid Sterba <dsterba@suse.com>2020-04-30 18:57:55 +0300
committerDavid Sterba <dsterba@suse.com>2020-05-25 12:25:34 +0300
commit84da071f3df5a9c0df0352d1c52b0c36ddb1c53f (patch)
tree9afe4d666d6c5c7ce55f2b07602f514a38866f9b /fs
parentc60ac0ffd682fc04f564dd6f4cc1a77c0f94608b (diff)
downloadlinux-84da071f3df5a9c0df0352d1c52b0c36ddb1c53f.tar.xz
btrfs: optimize split page read in btrfs_get_##bits
The helper read_extent_buffer is called to do read of the data spanning two extent buffer pages. As the size is known, we can do the read directly in two steps. This removes one function call and compiler can optimize memcpy as the sizes are known at compile time. Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/struct-funcs.c17
1 files changed, 10 insertions, 7 deletions
diff --git a/fs/btrfs/struct-funcs.c b/fs/btrfs/struct-funcs.c
index 0b23aa0a32d5..46a7269bee07 100644
--- a/fs/btrfs/struct-funcs.c
+++ b/fs/btrfs/struct-funcs.c
@@ -90,17 +90,20 @@ u##bits btrfs_get_##bits(const struct extent_buffer *eb, \
{ \
const unsigned long member_offset = (unsigned long)ptr + off; \
const unsigned long oip = offset_in_page(member_offset); \
+ const unsigned long idx = member_offset >> PAGE_SHIFT; \
+ char *kaddr = page_address(eb->pages[idx]); \
const int size = sizeof(u##bits); \
- __le##bits leres; \
+ const int part = PAGE_SIZE - oip; \
+ u8 lebytes[sizeof(u##bits)]; \
\
ASSERT(check_setget_bounds(eb, ptr, off, size)); \
- if (oip + size <= PAGE_SIZE) { \
- const unsigned long idx = member_offset >> PAGE_SHIFT; \
- const char *kaddr = page_address(eb->pages[idx]); \
+ if (oip + size <= PAGE_SIZE) \
return get_unaligned_le##bits(kaddr + oip); \
- } \
- read_extent_buffer(eb, &leres, member_offset, size); \
- return le##bits##_to_cpu(leres); \
+ \
+ memcpy(lebytes, kaddr + oip, part); \
+ kaddr = page_address(eb->pages[idx + 1]); \
+ memcpy(lebytes + part, kaddr, size - part); \
+ return get_unaligned_le##bits(lebytes); \
} \
void btrfs_set_token_##bits(struct btrfs_map_token *token, \
const void *ptr, unsigned long off, \