diff options
| author | Takashi Iwai <tiwai@suse.de> | 2012-08-20 15:26:04 -0400 |
|---|---|---|
| committer | Takashi Iwai <tiwai@suse.de> | 2012-08-20 15:26:04 -0400 |
| commit | f0b433e9f362e0b7f0ce7d1489dd7feba068605d (patch) | |
| tree | d4bfd9489cf4a96a55d83af20919f477a846d585 /fs/btrfs/struct-funcs.c | |
| parent | fa2f5bf09610d3c216d4c74855edbe00d636467c (diff) | |
| parent | 28c42c28309244d0b15d1b385e33429d59997679 (diff) | |
Merge tag 'asoc-3.6' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus
ASoC: Additional updates for 3.6
A batch more bugfixes, all driver-specific and fairly small and
unremarkable in a global context. The biggest batch are for the newly
added Arizona drivers.
Diffstat (limited to 'fs/btrfs/struct-funcs.c')
| -rw-r--r-- | fs/btrfs/struct-funcs.c | 196 |
1 files changed, 99 insertions, 97 deletions
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) |
