Commit 18077bb413687f96bd168efcfb2b8778529e3b74

Authored by Li Zefan
Committed by Chris Mason
1 parent 293f7e0740

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>

Showing 2 changed files with 146 additions and 103 deletions Side-by-side Diff

... ... @@ -1623,13 +1623,54 @@
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) \
fs/btrfs/struct-funcs.c
... ... @@ -17,119 +17,121 @@
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
  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.
26 41 *
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.
29   - *
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
32 44 * buffers. Every pointer to metadata items in btrfs is really just
33 45 * an unsigned long offset into the extent buffer which has been
34 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
37   - * spanning work required to get extent buffers in highmem and have
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.
  48 + * The extent buffer api is used to do the page spanning work required to
  49 + * have a metadata blocksize different from the page size.
42 50 */
43 51  
44   -#define BTRFS_SETGET_FUNCS(name, type, member, bits) \
45   -u##bits btrfs_##name(struct extent_buffer *eb, type *s); \
46   -void btrfs_set_##name(struct extent_buffer *eb, type *s, u##bits val); \
47   -void btrfs_set_token_##name(struct extent_buffer *eb, type *s, u##bits val, struct btrfs_map_token *token); \
48   -u##bits btrfs_token_##name(struct extent_buffer *eb, \
49   - type *s, struct btrfs_map_token *token) \
  52 +#define DEFINE_BTRFS_SETGET_BITS(bits) \
  53 +u##bits btrfs_get_token_##bits(struct extent_buffer *eb, void *ptr, \
  54 + unsigned long off, \
  55 + struct btrfs_map_token *token) \
50 56 { \
51   - unsigned long part_offset = (unsigned long)s; \
52   - unsigned long offset = part_offset + offsetof(type, member); \
53   - type *p; \
54   - int err; \
55   - char *kaddr; \
56   - unsigned long map_start; \
57   - unsigned long map_len; \
58   - unsigned long mem_len = sizeof(((type *)0)->member); \
59   - u##bits res; \
60   - if (token && token->kaddr && token->offset <= offset && \
61   - token->eb == eb && \
62   - (token->offset + PAGE_CACHE_SIZE >= offset + mem_len)) { \
63   - kaddr = token->kaddr; \
64   - p = (type *)(kaddr + part_offset - token->offset); \
65   - res = le##bits##_to_cpu(p->member); \
66   - return res; \
67   - } \
68   - err = map_private_extent_buffer(eb, offset, \
69   - mem_len, \
70   - &kaddr, &map_start, &map_len); \
71   - if (err) { \
72   - __le##bits leres; \
73   - read_eb_member(eb, s, type, member, &leres); \
74   - return le##bits##_to_cpu(leres); \
75   - } \
76   - p = (type *)(kaddr + part_offset - map_start); \
77   - res = le##bits##_to_cpu(p->member); \
78   - if (token) { \
79   - token->kaddr = kaddr; \
80   - token->offset = map_start; \
81   - token->eb = eb; \
82   - } \
83   - return res; \
  57 + unsigned long part_offset = (unsigned long)ptr; \
  58 + unsigned long offset = part_offset + off; \
  59 + void *p; \
  60 + int err; \
  61 + char *kaddr; \
  62 + unsigned long map_start; \
  63 + unsigned long map_len; \
  64 + int size = sizeof(u##bits); \
  65 + u##bits res; \
  66 + \
  67 + if (token && token->kaddr && token->offset <= offset && \
  68 + token->eb == eb && \
  69 + (token->offset + PAGE_CACHE_SIZE >= offset + size)) { \
  70 + kaddr = token->kaddr; \
  71 + p = kaddr + part_offset - token->offset; \
  72 + res = get_unaligned_le##bits(p + off); \
  73 + return res; \
  74 + } \
  75 + err = map_private_extent_buffer(eb, offset, size, \
  76 + &kaddr, &map_start, &map_len); \
  77 + if (err) { \
  78 + __le##bits leres; \
  79 + \
  80 + read_extent_buffer(eb, &leres, offset, size); \
  81 + return le##bits##_to_cpu(leres); \
  82 + } \
  83 + p = kaddr + part_offset - map_start; \
  84 + res = get_unaligned_le##bits(p + off); \
  85 + if (token) { \
  86 + token->kaddr = kaddr; \
  87 + token->offset = map_start; \
  88 + token->eb = eb; \
  89 + } \
  90 + return res; \
84 91 } \
85   -void btrfs_set_token_##name(struct extent_buffer *eb, \
86   - type *s, u##bits val, struct btrfs_map_token *token) \
  92 +void btrfs_set_token_##bits(struct extent_buffer *eb, \
  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; \
89   - unsigned long offset = part_offset + offsetof(type, member); \
90   - type *p; \
91   - int err; \
92   - char *kaddr; \
93   - unsigned long map_start; \
94   - unsigned long map_len; \
95   - unsigned long mem_len = sizeof(((type *)0)->member); \
96   - if (token && token->kaddr && token->offset <= offset && \
97   - token->eb == eb && \
98   - (token->offset + PAGE_CACHE_SIZE >= offset + mem_len)) { \
99   - kaddr = token->kaddr; \
100   - p = (type *)(kaddr + part_offset - token->offset); \
101   - p->member = cpu_to_le##bits(val); \
102   - return; \
103   - } \
104   - err = map_private_extent_buffer(eb, offset, \
105   - mem_len, \
106   - &kaddr, &map_start, &map_len); \
107   - if (err) { \
108   - __le##bits val2; \
109   - val2 = cpu_to_le##bits(val); \
110   - write_eb_member(eb, s, type, member, &val2); \
111   - return; \
112   - } \
113   - p = (type *)(kaddr + part_offset - map_start); \
114   - p->member = cpu_to_le##bits(val); \
115   - if (token) { \
116   - token->kaddr = kaddr; \
117   - token->offset = map_start; \
118   - token->eb = eb; \
119   - } \
120   -} \
121   -void btrfs_set_##name(struct extent_buffer *eb, \
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   -} \
  96 + unsigned long part_offset = (unsigned long)ptr; \
  97 + unsigned long offset = part_offset + off; \
  98 + void *p; \
  99 + int err; \
  100 + char *kaddr; \
  101 + unsigned long map_start; \
  102 + unsigned long map_len; \
  103 + int size = sizeof(u##bits); \
  104 + \
  105 + if (token && token->kaddr && token->offset <= offset && \
  106 + token->eb == eb && \
  107 + (token->offset + PAGE_CACHE_SIZE >= offset + size)) { \
  108 + kaddr = token->kaddr; \
  109 + p = kaddr + part_offset - token->offset; \
  110 + put_unaligned_le##bits(val, p + off); \
  111 + return; \
  112 + } \
  113 + err = map_private_extent_buffer(eb, offset, size, \
  114 + &kaddr, &map_start, &map_len); \
  115 + if (err) { \
  116 + __le##bits val2; \
  117 + \
  118 + val2 = cpu_to_le##bits(val); \
  119 + write_extent_buffer(eb, &val2, offset, size); \
  120 + return; \
  121 + } \
  122 + p = kaddr + part_offset - map_start; \
  123 + put_unaligned_le##bits(val, p + off); \
  124 + if (token) { \
  125 + token->kaddr = kaddr; \
  126 + token->offset = map_start; \
  127 + token->eb = eb; \
  128 + } \
  129 +}
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 136 void btrfs_node_key(struct extent_buffer *eb,
135 137 struct btrfs_disk_key *disk_key, int nr)