diff options
author | Kent Overstreet <kent.overstreet@linux.dev> | 2023-05-14 01:41:57 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-05-14 23:02:24 -0400 |
commit | 6afd007c0b357ee48c2c2807fc92e51b7beb522b (patch) | |
tree | e87e1b1606d49c5e951276456d22eb86cb2e9812 | |
parent | c3d801598235f9c0f43a93f38dca55a997352c08 (diff) |
__bch2_bkey_unpack_key(): avoid unaligned access
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r-- | fs/bcachefs/bkey.c | 16 | ||||
-rw-r--r-- | fs/bcachefs/btree_types.h | 1 |
2 files changed, 11 insertions, 6 deletions
diff --git a/fs/bcachefs/bkey.c b/fs/bcachefs/bkey.c index e16f8541d863..128d96766c0d 100644 --- a/fs/bcachefs/bkey.c +++ b/fs/bcachefs/bkey.c @@ -23,9 +23,9 @@ struct bkey_format_processed bch2_bkey_format_postprocess(const struct bkey_form { struct bkey_format_processed ret = { .f = f, .aligned = true }; #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - unsigned bit_offset = f.key_u64s * 64; + unsigned offset = f.key_u64s * 64; #else - unsigned bit_offset = KEY_PACKED_BITS_START; + unsigned offset = KEY_PACKED_BITS_START; #endif for (unsigned i = 0; i < BKEY_NR_FIELDS; i++) { @@ -37,13 +37,16 @@ struct bkey_format_processed bch2_bkey_format_postprocess(const struct bkey_form } #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - bit_offset -= bits; + offset -= bits; #endif - ret.offset[i] = bit_offset / 8; + + ret.shift[i] = min(offset & 63, 64 - bits); + ret.offset[i] = (offset - ret.shift[i]) / 8; + ret.mask[i] = bits ? ~0ULL >> (64 - bits) : 0; + #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ - bit_offset += bits; + offset += bits; #endif - ret.mask[i] = bits ? ~0ULL >> (64 - bits) : 0; } return ret; @@ -223,6 +226,7 @@ static u64 get_aligned_field(const struct bkey_format_processed *f, { u64 v = get_unaligned((u64 *) (((u8 *) in->_data) + f->offset[field_idx])); + v >>= f->shift[field_idx]; v &= f->mask[field_idx]; return v + le64_to_cpu(f->f.field_offset[field_idx]); diff --git a/fs/bcachefs/btree_types.h b/fs/bcachefs/btree_types.h index b76486ffbba1..38c3ec685240 100644 --- a/fs/bcachefs/btree_types.h +++ b/fs/bcachefs/btree_types.h @@ -72,6 +72,7 @@ struct bkey_format_processed { struct bkey_format f; bool aligned; u8 offset[6]; + u8 shift[6]; u64 mask[6]; }; |