Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Btrfs: rewrite BTRFS_SETGET_FUNCS

BTRFS_SETGET_FUNCS macro is used to generate btrfs_set_foo() and
btrfs_foo() functions, which read and write specific fields in the
extent buffer.

The total number of set/get functions is ~200, but in fact we only
need 8 functions: 2 for u8 field, 2 for u16, 2 for u32 and 2 for u64.

It results in redunction of ~37K bytes.

text data bss dec hex filename
629661 12489 216 642366 9cd3e fs/btrfs/btrfs.o.orig
592637 12489 216 605342 93c9e fs/btrfs/btrfs.o

Signed-off-by: Li Zefan <lizefan@huawei.com>

authored by

Li Zefan and committed by
Chris Mason
18077bb4 293f7e07

+146 -103
+47 -6
fs/btrfs/ctree.h
··· 1623 1623 offsetof(type, member), \ 1624 1624 sizeof(((type *)0)->member))) 1625 1625 1626 - #ifndef BTRFS_SETGET_FUNCS 1626 + #define DECLARE_BTRFS_SETGET_BITS(bits) \ 1627 + u##bits btrfs_get_token_##bits(struct extent_buffer *eb, void *ptr, \ 1628 + unsigned long off, \ 1629 + struct btrfs_map_token *token); \ 1630 + void btrfs_set_token_##bits(struct extent_buffer *eb, void *ptr, \ 1631 + unsigned long off, u##bits val, \ 1632 + struct btrfs_map_token *token); \ 1633 + static inline u##bits btrfs_get_##bits(struct extent_buffer *eb, void *ptr, \ 1634 + unsigned long off) \ 1635 + { \ 1636 + return btrfs_get_token_##bits(eb, ptr, off, NULL); \ 1637 + } \ 1638 + static inline void btrfs_set_##bits(struct extent_buffer *eb, void *ptr, \ 1639 + unsigned long off, u##bits val) \ 1640 + { \ 1641 + btrfs_set_token_##bits(eb, ptr, off, val, NULL); \ 1642 + } 1643 + 1644 + DECLARE_BTRFS_SETGET_BITS(8) 1645 + DECLARE_BTRFS_SETGET_BITS(16) 1646 + DECLARE_BTRFS_SETGET_BITS(32) 1647 + DECLARE_BTRFS_SETGET_BITS(64) 1648 + 1627 1649 #define BTRFS_SETGET_FUNCS(name, type, member, bits) \ 1628 - u##bits btrfs_##name(struct extent_buffer *eb, type *s); \ 1629 - u##bits btrfs_token_##name(struct extent_buffer *eb, type *s, struct btrfs_map_token *token); \ 1630 - void btrfs_set_token_##name(struct extent_buffer *eb, type *s, u##bits val, struct btrfs_map_token *token);\ 1631 - void btrfs_set_##name(struct extent_buffer *eb, type *s, u##bits val); 1632 - #endif 1650 + static inline u##bits btrfs_##name(struct extent_buffer *eb, type *s) \ 1651 + { \ 1652 + BUILD_BUG_ON(sizeof(u##bits) != sizeof(((type *)0))->member); \ 1653 + return btrfs_get_##bits(eb, s, offsetof(type, member)); \ 1654 + } \ 1655 + static inline void btrfs_set_##name(struct extent_buffer *eb, type *s, \ 1656 + u##bits val) \ 1657 + { \ 1658 + BUILD_BUG_ON(sizeof(u##bits) != sizeof(((type *)0))->member); \ 1659 + btrfs_set_##bits(eb, s, offsetof(type, member), val); \ 1660 + } \ 1661 + static inline u##bits btrfs_token_##name(struct extent_buffer *eb, type *s, \ 1662 + struct btrfs_map_token *token) \ 1663 + { \ 1664 + BUILD_BUG_ON(sizeof(u##bits) != sizeof(((type *)0))->member); \ 1665 + return btrfs_get_token_##bits(eb, s, offsetof(type, member), token); \ 1666 + } \ 1667 + static inline void btrfs_set_token_##name(struct extent_buffer *eb, \ 1668 + type *s, u##bits val, \ 1669 + struct btrfs_map_token *token) \ 1670 + { \ 1671 + BUILD_BUG_ON(sizeof(u##bits) != sizeof(((type *)0))->member); \ 1672 + btrfs_set_token_##bits(eb, s, offsetof(type, member), val, token); \ 1673 + } 1633 1674 1634 1675 #define BTRFS_SETGET_HEADER_FUNCS(name, type, member, bits) \ 1635 1676 static inline u##bits btrfs_##name(struct extent_buffer *eb) \
+99 -97
fs/btrfs/struct-funcs.c
··· 17 17 */ 18 18 19 19 #include <linux/highmem.h> 20 + #include <asm/unaligned.h> 20 21 21 - /* this is some deeply nasty code. ctree.h has a different 22 - * definition for this BTRFS_SETGET_FUNCS macro, behind a #ifndef 22 + #include "ctree.h" 23 + 24 + static inline u8 get_unaligned_le8(const void *p) 25 + { 26 + return *(u8 *)p; 27 + } 28 + 29 + static inline void put_unaligned_le8(u8 val, void *p) 30 + { 31 + *(u8 *)p = val; 32 + } 33 + 34 + /* 35 + * this is some deeply nasty code. 23 36 * 24 37 * The end result is that anyone who #includes ctree.h gets a 25 - * declaration for the btrfs_set_foo functions and btrfs_foo functions 26 - * 27 - * This file declares the macros and then #includes ctree.h, which results 28 - * in cpp creating the function here based on the template below. 38 + * declaration for the btrfs_set_foo functions and btrfs_foo functions, 39 + * which are wappers of btrfs_set_token_#bits functions and 40 + * btrfs_get_token_#bits functions, which are defined in this file. 29 41 * 30 42 * These setget functions do all the extent_buffer related mapping 31 43 * required to efficiently read and write specific fields in the extent ··· 45 33 * an unsigned long offset into the extent buffer which has been 46 34 * cast to a specific type. This gives us all the gcc type checking. 47 35 * 48 - * The extent buffer api is used to do all the kmapping and page 49 - * spanning work required to get extent buffers in highmem and have 50 - * a metadata blocksize different from the page size. 51 - * 52 - * The macro starts with a simple function prototype declaration so that 53 - * sparse won't complain about it being static. 36 + * The extent buffer api is used to do the page spanning work required to 37 + * have a metadata blocksize different from the page size. 54 38 */ 55 39 56 - #define BTRFS_SETGET_FUNCS(name, type, member, bits) \ 57 - u##bits btrfs_##name(struct extent_buffer *eb, type *s); \ 58 - void btrfs_set_##name(struct extent_buffer *eb, type *s, u##bits val); \ 59 - void btrfs_set_token_##name(struct extent_buffer *eb, type *s, u##bits val, struct btrfs_map_token *token); \ 60 - u##bits btrfs_token_##name(struct extent_buffer *eb, \ 61 - type *s, struct btrfs_map_token *token) \ 40 + #define DEFINE_BTRFS_SETGET_BITS(bits) \ 41 + u##bits btrfs_get_token_##bits(struct extent_buffer *eb, void *ptr, \ 42 + unsigned long off, \ 43 + struct btrfs_map_token *token) \ 62 44 { \ 63 - unsigned long part_offset = (unsigned long)s; \ 64 - unsigned long offset = part_offset + offsetof(type, member); \ 65 - type *p; \ 66 - int err; \ 67 - char *kaddr; \ 68 - unsigned long map_start; \ 69 - unsigned long map_len; \ 70 - unsigned long mem_len = sizeof(((type *)0)->member); \ 71 - u##bits res; \ 72 - if (token && token->kaddr && token->offset <= offset && \ 73 - token->eb == eb && \ 74 - (token->offset + PAGE_CACHE_SIZE >= offset + mem_len)) { \ 75 - kaddr = token->kaddr; \ 76 - p = (type *)(kaddr + part_offset - token->offset); \ 77 - res = le##bits##_to_cpu(p->member); \ 78 - return res; \ 79 - } \ 80 - err = map_private_extent_buffer(eb, offset, \ 81 - mem_len, \ 82 - &kaddr, &map_start, &map_len); \ 83 - if (err) { \ 84 - __le##bits leres; \ 85 - read_eb_member(eb, s, type, member, &leres); \ 86 - return le##bits##_to_cpu(leres); \ 87 - } \ 88 - p = (type *)(kaddr + part_offset - map_start); \ 89 - res = le##bits##_to_cpu(p->member); \ 90 - if (token) { \ 91 - token->kaddr = kaddr; \ 92 - token->offset = map_start; \ 93 - token->eb = eb; \ 94 - } \ 95 - return res; \ 45 + unsigned long part_offset = (unsigned long)ptr; \ 46 + unsigned long offset = part_offset + off; \ 47 + void *p; \ 48 + int err; \ 49 + char *kaddr; \ 50 + unsigned long map_start; \ 51 + unsigned long map_len; \ 52 + int size = sizeof(u##bits); \ 53 + u##bits res; \ 54 + \ 55 + if (token && token->kaddr && token->offset <= offset && \ 56 + token->eb == eb && \ 57 + (token->offset + PAGE_CACHE_SIZE >= offset + size)) { \ 58 + kaddr = token->kaddr; \ 59 + p = kaddr + part_offset - token->offset; \ 60 + res = get_unaligned_le##bits(p + off); \ 61 + return res; \ 62 + } \ 63 + err = map_private_extent_buffer(eb, offset, size, \ 64 + &kaddr, &map_start, &map_len); \ 65 + if (err) { \ 66 + __le##bits leres; \ 67 + \ 68 + read_extent_buffer(eb, &leres, offset, size); \ 69 + return le##bits##_to_cpu(leres); \ 70 + } \ 71 + p = kaddr + part_offset - map_start; \ 72 + res = get_unaligned_le##bits(p + off); \ 73 + if (token) { \ 74 + token->kaddr = kaddr; \ 75 + token->offset = map_start; \ 76 + token->eb = eb; \ 77 + } \ 78 + return res; \ 96 79 } \ 97 - void btrfs_set_token_##name(struct extent_buffer *eb, \ 98 - type *s, u##bits val, struct btrfs_map_token *token) \ 80 + void btrfs_set_token_##bits(struct extent_buffer *eb, \ 81 + void *ptr, unsigned long off, u##bits val, \ 82 + struct btrfs_map_token *token) \ 99 83 { \ 100 - unsigned long part_offset = (unsigned long)s; \ 101 - unsigned long offset = part_offset + offsetof(type, member); \ 102 - type *p; \ 103 - int err; \ 104 - char *kaddr; \ 105 - unsigned long map_start; \ 106 - unsigned long map_len; \ 107 - unsigned long mem_len = sizeof(((type *)0)->member); \ 108 - if (token && token->kaddr && token->offset <= offset && \ 109 - token->eb == eb && \ 110 - (token->offset + PAGE_CACHE_SIZE >= offset + mem_len)) { \ 111 - kaddr = token->kaddr; \ 112 - p = (type *)(kaddr + part_offset - token->offset); \ 113 - p->member = cpu_to_le##bits(val); \ 114 - return; \ 115 - } \ 116 - err = map_private_extent_buffer(eb, offset, \ 117 - mem_len, \ 118 - &kaddr, &map_start, &map_len); \ 119 - if (err) { \ 120 - __le##bits val2; \ 121 - val2 = cpu_to_le##bits(val); \ 122 - write_eb_member(eb, s, type, member, &val2); \ 123 - return; \ 124 - } \ 125 - p = (type *)(kaddr + part_offset - map_start); \ 126 - p->member = cpu_to_le##bits(val); \ 127 - if (token) { \ 128 - token->kaddr = kaddr; \ 129 - token->offset = map_start; \ 130 - token->eb = eb; \ 131 - } \ 132 - } \ 133 - void btrfs_set_##name(struct extent_buffer *eb, \ 134 - type *s, u##bits val) \ 135 - { \ 136 - btrfs_set_token_##name(eb, s, val, NULL); \ 137 - } \ 138 - u##bits btrfs_##name(struct extent_buffer *eb, \ 139 - type *s) \ 140 - { \ 141 - return btrfs_token_##name(eb, s, NULL); \ 142 - } \ 84 + unsigned long part_offset = (unsigned long)ptr; \ 85 + unsigned long offset = part_offset + off; \ 86 + void *p; \ 87 + int err; \ 88 + char *kaddr; \ 89 + unsigned long map_start; \ 90 + unsigned long map_len; \ 91 + int size = sizeof(u##bits); \ 92 + \ 93 + if (token && token->kaddr && token->offset <= offset && \ 94 + token->eb == eb && \ 95 + (token->offset + PAGE_CACHE_SIZE >= offset + size)) { \ 96 + kaddr = token->kaddr; \ 97 + p = kaddr + part_offset - token->offset; \ 98 + put_unaligned_le##bits(val, p + off); \ 99 + return; \ 100 + } \ 101 + err = map_private_extent_buffer(eb, offset, size, \ 102 + &kaddr, &map_start, &map_len); \ 103 + if (err) { \ 104 + __le##bits val2; \ 105 + \ 106 + val2 = cpu_to_le##bits(val); \ 107 + write_extent_buffer(eb, &val2, offset, size); \ 108 + return; \ 109 + } \ 110 + p = kaddr + part_offset - map_start; \ 111 + put_unaligned_le##bits(val, p + off); \ 112 + if (token) { \ 113 + token->kaddr = kaddr; \ 114 + token->offset = map_start; \ 115 + token->eb = eb; \ 116 + } \ 117 + } 143 118 144 - #include "ctree.h" 119 + DEFINE_BTRFS_SETGET_BITS(8) 120 + DEFINE_BTRFS_SETGET_BITS(16) 121 + DEFINE_BTRFS_SETGET_BITS(32) 122 + DEFINE_BTRFS_SETGET_BITS(64) 145 123 146 124 void btrfs_node_key(struct extent_buffer *eb, 147 125 struct btrfs_disk_key *disk_key, int nr)