aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorLi Zefan <lizefan@huawei.com>2012-07-09 22:22:35 -0400
committerChris Mason <chris.mason@fusionio.com>2012-07-23 16:28:06 -0400
commit18077bb413687f96bd168efcfb2b8778529e3b74 (patch)
tree44adcefcc2177267437826b800800021cc2f4faf /fs/btrfs
parent293f7e07405a63975cee4e95a2cfa0c17b34b3aa (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.h53
-rw-r--r--fs/btrfs/struct-funcs.c196
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) \
1627u##bits btrfs_get_token_##bits(struct extent_buffer *eb, void *ptr, \
1628 unsigned long off, \
1629 struct btrfs_map_token *token); \
1630void btrfs_set_token_##bits(struct extent_buffer *eb, void *ptr, \
1631 unsigned long off, u##bits val, \
1632 struct btrfs_map_token *token); \
1633static 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} \
1638static 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
1644DECLARE_BTRFS_SETGET_BITS(8)
1645DECLARE_BTRFS_SETGET_BITS(16)
1646DECLARE_BTRFS_SETGET_BITS(32)
1647DECLARE_BTRFS_SETGET_BITS(64)
1648
1627#define BTRFS_SETGET_FUNCS(name, type, member, bits) \ 1649#define BTRFS_SETGET_FUNCS(name, type, member, bits) \
1628u##bits btrfs_##name(struct extent_buffer *eb, type *s); \ 1650static inline u##bits btrfs_##name(struct extent_buffer *eb, type *s) \
1629u##bits btrfs_token_##name(struct extent_buffer *eb, type *s, struct btrfs_map_token *token); \ 1651{ \
1630void 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); \
1631void 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} \
1655static 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} \
1661static 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} \
1667static 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) \
1635static inline u##bits btrfs_##name(struct extent_buffer *eb) \ 1676static 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
24static inline u8 get_unaligned_le8(const void *p)
25{
26 return *(u8 *)p;
27}
28
29static 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) \
45u##bits btrfs_##name(struct extent_buffer *eb, type *s); \ 53u##bits btrfs_get_token_##bits(struct extent_buffer *eb, void *ptr, \
46void btrfs_set_##name(struct extent_buffer *eb, type *s, u##bits val); \ 54 unsigned long off, \
47void btrfs_set_token_##name(struct extent_buffer *eb, type *s, u##bits val, struct btrfs_map_token *token); \ 55 struct btrfs_map_token *token) \
48u##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} \
85void btrfs_set_token_##name(struct extent_buffer *eb, \ 92void 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 } \
121void 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} \
126u##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" 131DEFINE_BTRFS_SETGET_BITS(8)
132DEFINE_BTRFS_SETGET_BITS(16)
133DEFINE_BTRFS_SETGET_BITS(32)
134DEFINE_BTRFS_SETGET_BITS(64)
133 135
134void btrfs_node_key(struct extent_buffer *eb, 136void 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)