From 13b64bd18340a05aebd7e2da76cff7b888ed8234 Mon Sep 17 00:00:00 2001 From: Jon Bailey Date: Mon, 11 Aug 2025 12:51:42 +0100 Subject: [PATCH] erasure-code/consistency: Allow consistency checker to be able to deal with non-4k aligned buffers A parity returned to the client will be the size of shard 0, which may not be 4k aligned in optimised erasure coding. A parity returned through the encode function will always be 4k aligned. This change makes it so we truncate the encoded data down to the size of the client write before comparing them together in the consistency check so we know we are comparing them like-for-like Signed-off-by: Jon Bailey --- .../consistency/ConsistencyChecker.cc | 25 +++++++++++++++++++ src/erasure-code/consistency/ECEncoder.cc | 11 ++++++++ src/erasure-code/consistency/ECEncoder.h | 1 + .../consistency/ECEncoderSwitch.cc | 14 +++++++++++ .../consistency/ECEncoderSwitch.h | 1 + 5 files changed, 52 insertions(+) diff --git a/src/erasure-code/consistency/ConsistencyChecker.cc b/src/erasure-code/consistency/ConsistencyChecker.cc index da84ce1a8d1b8..af41e8e3df454 100644 --- a/src/erasure-code/consistency/ConsistencyChecker.cc +++ b/src/erasure-code/consistency/ConsistencyChecker.cc @@ -5,6 +5,7 @@ #include "ECReader.h" #include "ECEncoder.h" #include "ECEncoderSwitch.h" +#include "osd/ECUtil.h" using ConsistencyChecker = ceph::consistency::ConsistencyChecker; @@ -115,6 +116,30 @@ bool ConsistencyChecker::check_object_consistency(const std::string& oid, return false; } + // Encode always returns 4k aligned data + // A client read will always return parity with the same size as shard 0 + // We confirm the encoded data is the same or larger than the client read + ceph_assert(outbl->length() >= data_and_parity.second.length()); + // We check the difference is not larger than the page size multipled by the + // number of parities + ceph_assert(outbl->length() - data_and_parity.second.length() + <= (encoder.get_m() * encoder.get_chunk_size()) - encoder.get_m()); + // We truncate the encoded parity to the size of the client read for comparison + if (outbl->length() != data_and_parity.second.length()) + { + const int aligned_shard_length = outbl->length() / encoder.get_m(); + const int shard_data_length = data_and_parity.second.length() + / encoder.get_m(); + ceph::bufferlist newdata; + for (int i = 0; i < encoder.get_m(); i++) + { + ceph::bufferlist bl; + bl.substr_of(*outbl, i * aligned_shard_length, shard_data_length); + newdata.append(bl); + } + outbl = std::move(newdata); + } + return buffers_match(outbl.value(), data_and_parity.second); } diff --git a/src/erasure-code/consistency/ECEncoder.cc b/src/erasure-code/consistency/ECEncoder.cc index 504d6d80e2e1c..3be2f543a7897 100644 --- a/src/erasure-code/consistency/ECEncoder.cc +++ b/src/erasure-code/consistency/ECEncoder.cc @@ -198,6 +198,17 @@ int ECEncoder::get_m() { return stripe_info->get_m(); } + +/** + * Return chunksize for the stripe + * + * @returns int Chunksize for the stripe + */ +template +int ECEncoder::get_chunk_size() +{ + return stripe_info->get_chunk_size(); +} } } diff --git a/src/erasure-code/consistency/ECEncoder.h b/src/erasure-code/consistency/ECEncoder.h index 30f3e6d0b0353..2a5d8befc8213 100644 --- a/src/erasure-code/consistency/ECEncoder.h +++ b/src/erasure-code/consistency/ECEncoder.h @@ -29,6 +29,7 @@ class ECEncoder { std::optional do_encode(ceph::bufferlist inbl); int get_k(void); int get_m(void); + int get_chunk_size(void); }; } } \ No newline at end of file diff --git a/src/erasure-code/consistency/ECEncoderSwitch.cc b/src/erasure-code/consistency/ECEncoderSwitch.cc index 9ab97ebf9d89d..7a932afe1e926 100644 --- a/src/erasure-code/consistency/ECEncoderSwitch.cc +++ b/src/erasure-code/consistency/ECEncoderSwitch.cc @@ -57,3 +57,17 @@ int ECEncoderSwitch::get_m() return encoder_legacy.get_m(); } } + +/** + * Return chunksize for the stripe from the correct version of the encoder + * + * @returns int Chunksize for stripe + */ +int ECEncoderSwitch::get_chunk_size() +{ + if (optimizations_enabled) { + return encoder_optimized.get_chunk_size(); + } else { + return encoder_legacy.get_chunk_size(); + } +} diff --git a/src/erasure-code/consistency/ECEncoderSwitch.h b/src/erasure-code/consistency/ECEncoderSwitch.h index d86e911212ab8..8343206d75272 100644 --- a/src/erasure-code/consistency/ECEncoderSwitch.h +++ b/src/erasure-code/consistency/ECEncoderSwitch.h @@ -26,6 +26,7 @@ class ECEncoderSwitch { std::optional do_encode(ceph::bufferlist inbl); int get_k(void); int get_m(void); + int get_chunk_size(void); }; } } -- 2.39.5