diff options
author | Li Zefan <lizefan@huawei.com> | 2012-07-09 22:22:35 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@fusionio.com> | 2012-07-23 16:28:06 -0400 |
commit | 18077bb413687f96bd168efcfb2b8778529e3b74 (patch) | |
tree | 44adcefcc2177267437826b800800021cc2f4faf /fs/btrfs | |
parent | 293f7e07405a63975cee4e95a2cfa0c17b34b3aa (diff) |
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>
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/ctree.h | 53 | ||||
-rw-r--r-- | fs/btrfs/struct-funcs.c | 196 |
2 files changed, 146 insertions, 103 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 6761490b91cd..a0ee2f8e0566 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -1623,13 +1623,54 @@ static inline void btrfs_init_map_token (struct btrfs_map_token *token) | |||
1623 | offsetof(type, member), \ | 1623 | offsetof(type, member), \ |
1624 | sizeof(((type *)0)->member))) | 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 | #define BTRFS_SETGET_FUNCS(name, type, member, bits) \ | 1649 | #define BTRFS_SETGET_FUNCS(name, type, member, bits) \ |
1628 | u##bits btrfs_##name(struct extent_buffer *eb, type *s); \ | 1650 | static inline 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); \ | 1651 | { \ |
1630 | void btrfs_set_token_##name(struct extent_buffer *eb, type *s, u##bits val, struct btrfs_map_token *token);\ | 1652 | BUILD_BUG_ON(sizeof(u##bits) != sizeof(((type *)0))->member); \ |
1631 | void btrfs_set_##name(struct extent_buffer *eb, type *s, u##bits val); | 1653 | return btrfs_get_##bits(eb, s, offsetof(type, member)); \ |
1632 | #endif | 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 | #define BTRFS_SETGET_HEADER_FUNCS(name, type, member, bits) \ | 1675 | #define BTRFS_SETGET_HEADER_FUNCS(name, type, member, bits) \ |
1635 | static inline u##bits btrfs_##name(struct extent_buffer *eb) \ | 1676 | static inline u##bits btrfs_##name(struct extent_buffer *eb) \ |
diff --git a/fs/btrfs/struct-funcs.c b/fs/btrfs/struct-funcs.c index c6ffa5812419..b976597b0721 100644 --- a/fs/btrfs/struct-funcs.c +++ b/fs/btrfs/struct-funcs.c | |||
@@ -17,15 +17,27 @@ | |||
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/highmem.h> | 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 | #include "ctree.h" |
22 | * definition for this BTRFS_SETGET_FUNCS macro, behind a #ifndef | 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 | * The end result is that anyone who #includes ctree.h gets a | 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 | 38 | * declaration for the btrfs_set_foo functions and btrfs_foo functions, |
26 | * | 39 | * which are wappers of btrfs_set_token_#bits functions and |
27 | * This file declares the macros and then #includes ctree.h, which results | 40 | * btrfs_get_token_#bits functions, which are defined in this file. |
28 | * in cpp creating the function here based on the template below. | ||
29 | * | 41 | * |
30 | * These setget functions do all the extent_buffer related mapping | 42 | * These setget functions do all the extent_buffer related mapping |
31 | * required to efficiently read and write specific fields in the extent | 43 | * required to efficiently read and write specific fields in the extent |
@@ -33,103 +45,93 @@ | |||
33 | * an unsigned long offset into the extent buffer which has been | 45 | * an unsigned long offset into the extent buffer which has been |
34 | * cast to a specific type. This gives us all the gcc type checking. | 46 | * cast to a specific type. This gives us all the gcc type checking. |
35 | * | 47 | * |
36 | * The extent buffer api is used to do all the kmapping and page | 48 | * The extent buffer api is used to do the page spanning work required to |
37 | * spanning work required to get extent buffers in highmem and have | 49 | * have a metadata blocksize different from the page size. |
38 | * a metadata blocksize different from the page size. | ||
39 | * | ||
40 | * The macro starts with a simple function prototype declaration so that | ||
41 | * sparse won't complain about it being static. | ||
42 | */ | 50 | */ |
43 | 51 | ||
44 | #define BTRFS_SETGET_FUNCS(name, type, member, bits) \ | 52 | #define DEFINE_BTRFS_SETGET_BITS(bits) \ |
45 | u##bits btrfs_##name(struct extent_buffer *eb, type *s); \ | 53 | u##bits btrfs_get_token_##bits(struct extent_buffer *eb, void *ptr, \ |
46 | void btrfs_set_##name(struct extent_buffer *eb, type *s, u##bits val); \ | 54 | unsigned long off, \ |
47 | void btrfs_set_token_##name(struct extent_buffer *eb, type *s, u##bits val, struct btrfs_map_token *token); \ | 55 | struct btrfs_map_token *token) \ |
48 | u##bits btrfs_token_##name(struct extent_buffer *eb, \ | ||
49 | type *s, struct btrfs_map_token *token) \ | ||
50 | { \ | 56 | { \ |
51 | unsigned long part_offset = (unsigned long)s; \ | 57 | unsigned long part_offset = (unsigned long)ptr; \ |
52 | unsigned long offset = part_offset + offsetof(type, member); \ | 58 | unsigned long offset = part_offset + off; \ |
53 | type *p; \ | 59 | void *p; \ |
54 | int err; \ | 60 | int err; \ |
55 | char *kaddr; \ | 61 | char *kaddr; \ |
56 | unsigned long map_start; \ | 62 | unsigned long map_start; \ |
57 | unsigned long map_len; \ | 63 | unsigned long map_len; \ |
58 | unsigned long mem_len = sizeof(((type *)0)->member); \ | 64 | int size = sizeof(u##bits); \ |
59 | u##bits res; \ | 65 | u##bits res; \ |
60 | if (token && token->kaddr && token->offset <= offset && \ | 66 | \ |
61 | token->eb == eb && \ | 67 | if (token && token->kaddr && token->offset <= offset && \ |
62 | (token->offset + PAGE_CACHE_SIZE >= offset + mem_len)) { \ | 68 | token->eb == eb && \ |
63 | kaddr = token->kaddr; \ | 69 | (token->offset + PAGE_CACHE_SIZE >= offset + size)) { \ |
64 | p = (type *)(kaddr + part_offset - token->offset); \ | 70 | kaddr = token->kaddr; \ |
65 | res = le##bits##_to_cpu(p->member); \ | 71 | p = kaddr + part_offset - token->offset; \ |
66 | return res; \ | 72 | res = get_unaligned_le##bits(p + off); \ |
67 | } \ | 73 | return res; \ |
68 | err = map_private_extent_buffer(eb, offset, \ | 74 | } \ |
69 | mem_len, \ | 75 | err = map_private_extent_buffer(eb, offset, size, \ |
70 | &kaddr, &map_start, &map_len); \ | 76 | &kaddr, &map_start, &map_len); \ |
71 | if (err) { \ | 77 | if (err) { \ |
72 | __le##bits leres; \ | 78 | __le##bits leres; \ |
73 | read_eb_member(eb, s, type, member, &leres); \ | 79 | \ |
74 | return le##bits##_to_cpu(leres); \ | 80 | read_extent_buffer(eb, &leres, offset, size); \ |
75 | } \ | 81 | return le##bits##_to_cpu(leres); \ |
76 | p = (type *)(kaddr + part_offset - map_start); \ | 82 | } \ |
77 | res = le##bits##_to_cpu(p->member); \ | 83 | p = kaddr + part_offset - map_start; \ |
78 | if (token) { \ | 84 | res = get_unaligned_le##bits(p + off); \ |
79 | token->kaddr = kaddr; \ | 85 | if (token) { \ |
80 | token->offset = map_start; \ | 86 | token->kaddr = kaddr; \ |
81 | token->eb = eb; \ | 87 | token->offset = map_start; \ |
82 | } \ | 88 | token->eb = eb; \ |
83 | return res; \ | 89 | } \ |
90 | return res; \ | ||
84 | } \ | 91 | } \ |
85 | void btrfs_set_token_##name(struct extent_buffer *eb, \ | 92 | void btrfs_set_token_##bits(struct extent_buffer *eb, \ |
86 | type *s, u##bits val, struct btrfs_map_token *token) \ | 93 | void *ptr, unsigned long off, u##bits val, \ |
94 | struct btrfs_map_token *token) \ | ||
87 | { \ | 95 | { \ |
88 | unsigned long part_offset = (unsigned long)s; \ | 96 | unsigned long part_offset = (unsigned long)ptr; \ |
89 | unsigned long offset = part_offset + offsetof(type, member); \ | 97 | unsigned long offset = part_offset + off; \ |
90 | type *p; \ | 98 | void *p; \ |
91 | int err; \ | 99 | int err; \ |
92 | char *kaddr; \ | 100 | char *kaddr; \ |
93 | unsigned long map_start; \ | 101 | unsigned long map_start; \ |
94 | unsigned long map_len; \ | 102 | unsigned long map_len; \ |
95 | unsigned long mem_len = sizeof(((type *)0)->member); \ | 103 | int size = sizeof(u##bits); \ |
96 | if (token && token->kaddr && token->offset <= offset && \ | 104 | \ |
97 | token->eb == eb && \ | 105 | if (token && token->kaddr && token->offset <= offset && \ |
98 | (token->offset + PAGE_CACHE_SIZE >= offset + mem_len)) { \ | 106 | token->eb == eb && \ |
99 | kaddr = token->kaddr; \ | 107 | (token->offset + PAGE_CACHE_SIZE >= offset + size)) { \ |
100 | p = (type *)(kaddr + part_offset - token->offset); \ | 108 | kaddr = token->kaddr; \ |
101 | p->member = cpu_to_le##bits(val); \ | 109 | p = kaddr + part_offset - token->offset; \ |
102 | return; \ | 110 | put_unaligned_le##bits(val, p + off); \ |
103 | } \ | 111 | return; \ |
104 | err = map_private_extent_buffer(eb, offset, \ | 112 | } \ |
105 | mem_len, \ | 113 | err = map_private_extent_buffer(eb, offset, size, \ |
106 | &kaddr, &map_start, &map_len); \ | 114 | &kaddr, &map_start, &map_len); \ |
107 | if (err) { \ | 115 | if (err) { \ |
108 | __le##bits val2; \ | 116 | __le##bits val2; \ |
109 | val2 = cpu_to_le##bits(val); \ | 117 | \ |
110 | write_eb_member(eb, s, type, member, &val2); \ | 118 | val2 = cpu_to_le##bits(val); \ |
111 | return; \ | 119 | write_extent_buffer(eb, &val2, offset, size); \ |
112 | } \ | 120 | return; \ |
113 | p = (type *)(kaddr + part_offset - map_start); \ | 121 | } \ |
114 | p->member = cpu_to_le##bits(val); \ | 122 | p = kaddr + part_offset - map_start; \ |
115 | if (token) { \ | 123 | put_unaligned_le##bits(val, p + off); \ |
116 | token->kaddr = kaddr; \ | 124 | if (token) { \ |
117 | token->offset = map_start; \ | 125 | token->kaddr = kaddr; \ |
118 | token->eb = eb; \ | 126 | token->offset = map_start; \ |
119 | } \ | 127 | token->eb = eb; \ |
120 | } \ | 128 | } \ |
121 | void btrfs_set_##name(struct extent_buffer *eb, \ | 129 | } |
122 | type *s, u##bits val) \ | ||
123 | { \ | ||
124 | btrfs_set_token_##name(eb, s, val, NULL); \ | ||
125 | } \ | ||
126 | u##bits btrfs_##name(struct extent_buffer *eb, \ | ||
127 | type *s) \ | ||
128 | { \ | ||
129 | return btrfs_token_##name(eb, s, NULL); \ | ||
130 | } \ | ||
131 | 130 | ||
132 | #include "ctree.h" | 131 | DEFINE_BTRFS_SETGET_BITS(8) |
132 | DEFINE_BTRFS_SETGET_BITS(16) | ||
133 | DEFINE_BTRFS_SETGET_BITS(32) | ||
134 | DEFINE_BTRFS_SETGET_BITS(64) | ||
133 | 135 | ||
134 | void btrfs_node_key(struct extent_buffer *eb, | 136 | void btrfs_node_key(struct extent_buffer *eb, |
135 | struct btrfs_disk_key *disk_key, int nr) | 137 | struct btrfs_disk_key *disk_key, int nr) |