summaryrefslogtreecommitdiff
path: root/fs/bcachefs/checksum.c
diff options
context:
space:
mode:
authorjpsollie <janpieter.sollie@edpnet.be>2021-06-17 11:29:59 +0200
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-22 17:09:07 -0400
commit80ff5d18ee975f201c8913be066ebedf887003f9 (patch)
treeebf6ec71d0ac0b391fb5771b0334efff99583283 /fs/bcachefs/checksum.c
parenta515d0a50c6e8bb9b8ce58d6e396b4c5eeea6905 (diff)
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.c95
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;