diff options
author | David Miller <davem@davemloft.net> | 2008-02-15 11:19:58 -0500 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2008-02-15 11:19:58 -0500 |
commit | 8871a0eaa98d951727e97c615d831af9a60432ae (patch) | |
tree | 7701fa42a830e2fba095199bfe25c62b42b9d36e /ctree.h | |
parent | 0c6513b1d120ba99a3d5f3641cb059723245ec00 (diff) |
Unaligned access fixes
The first problem is that these SETGET macros lose typing information,
and therefore can't see the 'packed' attribute and therefore take
unaligned access SIGBUS signals on sparc64 when trying to derefernce
the member.
The next problem is a similar issue in btrfs_name_hash(). This gets
passed things like &key.offset which is a member of a packed
structure, losing this packed'ness information btrfs_name_hash()
performs a potentially unaligned memory access, again resulting in a
SIGBUS.
Diffstat (limited to 'ctree.h')
-rw-r--r-- | ctree.h | 14 |
1 files changed, 6 insertions, 8 deletions
@@ -451,18 +451,16 @@ static inline void btrfs_set_##name(struct extent_buffer *eb, \ static inline u##bits btrfs_##name(struct extent_buffer *eb, \ type *s) \ { \ - unsigned long offset = (unsigned long)s + \ - offsetof(type, member); \ - __le##bits *tmp = (__le##bits *)(eb->data + offset); \ - return le##bits##_to_cpu(*tmp); \ + unsigned long offset = (unsigned long)s; \ + type *p = (type *) (eb->data + offset); \ + return le##bits##_to_cpu(p->member); \ } \ static inline void btrfs_set_##name(struct extent_buffer *eb, \ type *s, u##bits val) \ { \ - unsigned long offset = (unsigned long)s + \ - offsetof(type, member); \ - __le##bits *tmp = (__le##bits *)(eb->data + offset); \ - *tmp = cpu_to_le##bits(val); \ + unsigned long offset = (unsigned long)s; \ + type *p = (type *) (eb->data + offset); \ + p->member = cpu_to_le##bits(val); \ } #define BTRFS_SETGET_STACK_FUNCS(name, type, member, bits) \ |