diff options
author | jpsollie <janpieter.sollie@edpnet.be> | 2021-06-17 11:29:59 +0200 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-22 17:09:07 -0400 |
commit | 80ff5d18ee975f201c8913be066ebedf887003f9 (patch) | |
tree | ebf6ec71d0ac0b391fb5771b0334efff99583283 /fs/bcachefs/checksum.c | |
parent | a515d0a50c6e8bb9b8ce58d6e396b4c5eeea6905 (diff) | |
download | linux-80ff5d18ee975f201c8913be066ebedf887003f9.tar.gz linux-80ff5d18ee975f201c8913be066ebedf887003f9.tar.bz2 linux-80ff5d18ee975f201c8913be066ebedf887003f9.zip |
bcachefs: Prepare checksums for more advanced algorithms
Perform abstraction of hash calculation for advanced checksum algorithms.
Algorithms like xxhash do not store their state as a u64 int.
Signed-off-by: jpsollie <janpieter.sollie@edpnet.be>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs/bcachefs/checksum.c')
-rw-r--r-- | fs/bcachefs/checksum.c | 95 |
1 files changed, 59 insertions, 36 deletions
diff --git a/fs/bcachefs/checksum.c b/fs/bcachefs/checksum.c index 3d88719ba86c..6c23a9073dbf 100644 --- a/fs/bcachefs/checksum.c +++ b/fs/bcachefs/checksum.c @@ -16,53 +16,68 @@ #include <crypto/skcipher.h> #include <keys/user-type.h> -static u64 bch2_checksum_init(unsigned type) +/* + * bch2_checksum state is an abstraction of the checksum state calculated over different pages. + * it features page merging without having the checksum algorithm lose its state. + * for native checksum aglorithms (like crc), a default seed value will do. + * for hash-like algorithms, a state needs to be stored + */ + +struct bch2_checksum_state { + union { + u64 seed; + }; + unsigned int type; +}; + +static void bch2_checksum_init(struct bch2_checksum_state *state) { - switch (type) { + switch (state->type) { case BCH_CSUM_NONE: - return 0; - case BCH_CSUM_CRC32C_NONZERO: - return U32_MAX; - case BCH_CSUM_CRC64_NONZERO: - return U64_MAX; case BCH_CSUM_CRC32C: - return 0; case BCH_CSUM_CRC64: - return 0; + state->seed = 0; + break; + case BCH_CSUM_CRC32C_NONZERO: + state->seed = U32_MAX; + break; + case BCH_CSUM_CRC64_NONZERO: + state->seed = U64_MAX; + break; default: BUG(); } } -static u64 bch2_checksum_final(unsigned type, u64 crc) +static u64 bch2_checksum_final(const struct bch2_checksum_state *state) { - switch (type) { + switch (state->type) { case BCH_CSUM_NONE: - return 0; - case BCH_CSUM_CRC32C_NONZERO: - return crc ^ U32_MAX; - case BCH_CSUM_CRC64_NONZERO: - return crc ^ U64_MAX; case BCH_CSUM_CRC32C: - return crc; case BCH_CSUM_CRC64: - return crc; + return state->seed; + case BCH_CSUM_CRC32C_NONZERO: + return state->seed ^ U32_MAX; + case BCH_CSUM_CRC64_NONZERO: + return state->seed ^ U64_MAX; default: BUG(); } } -static u64 bch2_checksum_update(unsigned type, u64 crc, const void *data, size_t len) +static void bch2_checksum_update(struct bch2_checksum_state *state, const void *data, size_t len) { - switch (type) { + switch (state->type) { case BCH_CSUM_NONE: - return 0; + return; case BCH_CSUM_CRC32C_NONZERO: case BCH_CSUM_CRC32C: - return crc32c(crc, data, len); + state->seed = crc32c(state->seed, data, len); + break; case BCH_CSUM_CRC64_NONZERO: case BCH_CSUM_CRC64: - return crc64_be(crc, data, len); + state->seed = crc64_be(state->seed, data, len); + break; default: BUG(); } @@ -141,12 +156,14 @@ struct bch_csum bch2_checksum(struct bch_fs *c, unsigned type, case BCH_CSUM_CRC64_NONZERO: case BCH_CSUM_CRC32C: case BCH_CSUM_CRC64: { - u64 crc = bch2_checksum_init(type); + struct bch2_checksum_state state; - crc = bch2_checksum_update(type, crc, data, len); - crc = bch2_checksum_final(type, crc); + state.type = type; - return (struct bch_csum) { .lo = cpu_to_le64(crc) }; + bch2_checksum_init(&state); + bch2_checksum_update(&state, data, len); + + return (struct bch_csum) { .lo = cpu_to_le64(bch2_checksum_final(&state)) }; } case BCH_CSUM_CHACHA20_POLY1305_80: @@ -190,23 +207,23 @@ static struct bch_csum __bch2_checksum_bio(struct bch_fs *c, unsigned type, case BCH_CSUM_CRC64_NONZERO: case BCH_CSUM_CRC32C: case BCH_CSUM_CRC64: { - u64 crc = bch2_checksum_init(type); + struct bch2_checksum_state state; + + state.type = type; + bch2_checksum_init(&state); #ifdef CONFIG_HIGHMEM __bio_for_each_segment(bv, bio, *iter, *iter) { void *p = kmap_atomic(bv.bv_page) + bv.bv_offset; - crc = bch2_checksum_update(type, - crc, p, bv.bv_len); + bch2_checksum_update(&state, p, bv.bv_len); kunmap_atomic(p); } #else __bio_for_each_bvec(bv, bio, *iter, *iter) - crc = bch2_checksum_update(type, crc, - page_address(bv.bv_page) + bv.bv_offset, + bch2_checksum_update(&state, page_address(bv.bv_page) + bv.bv_offset, bv.bv_len); #endif - crc = bch2_checksum_final(type, crc); - return (struct bch_csum) { .lo = cpu_to_le64(crc) }; + return (struct bch_csum) { .lo = cpu_to_le64(bch2_checksum_final(&state)) }; } case BCH_CSUM_CHACHA20_POLY1305_80: @@ -284,16 +301,22 @@ void bch2_encrypt_bio(struct bch_fs *c, unsigned type, struct bch_csum bch2_checksum_merge(unsigned type, struct bch_csum a, struct bch_csum b, size_t b_len) { + struct bch2_checksum_state state; + + state.type = type; + bch2_checksum_init(&state); + state.seed = a.lo; + BUG_ON(!bch2_checksum_mergeable(type)); while (b_len) { unsigned b = min_t(unsigned, b_len, PAGE_SIZE); - a.lo = bch2_checksum_update(type, a.lo, + bch2_checksum_update(&state, page_address(ZERO_PAGE(0)), b); b_len -= b; } - + a.lo = bch2_checksum_final(&state); a.lo ^= b.lo; a.hi ^= b.hi; return a; |