From f41daf6d5b5f1bdc10a06800d2604d50fec3f5a5 Mon Sep 17 00:00:00 2001 From: Radoslaw Zarzynski Date: Sun, 9 Jun 2024 08:28:42 +0000 Subject: [PATCH] osd: decode_concat() always honors want_to_read Signed-off-by: Radoslaw Zarzynski --- src/erasure-code/ErasureCode.cc | 8 +++++- .../erasure-code/TestErasureCodeExample.cc | 17 ++++++++++-- .../erasure-code/TestErasureCodeJerasure.cc | 27 +++++++++++++++++++ 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/src/erasure-code/ErasureCode.cc b/src/erasure-code/ErasureCode.cc index ef92ea7219d89..b27273c172fd6 100644 --- a/src/erasure-code/ErasureCode.cc +++ b/src/erasure-code/ErasureCode.cc @@ -356,7 +356,13 @@ int ErasureCode::decode_concat(const set& want_to_read, int r = _decode(want_to_read, chunks, &decoded_map); if (r == 0) { for (unsigned int i = 0; i < get_data_chunk_count(); i++) { - if (decoded_map.contains(chunk_index(i))) { + // XXX: the ErasureCodeInterface allows `decode()` to return + // *at least* `want_to_read chunks`; that is, they may more. + // Some implementations are consistently exact but jerasure + // is quirky: it outputs more only when deailing with degraded. + // The check below uniforms the behavior. + if (want_to_read.contains(chunk_index(i)) && + decoded_map.contains(chunk_index(i))) { decoded->claim_append(decoded_map[chunk_index(i)]); } } diff --git a/src/test/erasure-code/TestErasureCodeExample.cc b/src/test/erasure-code/TestErasureCodeExample.cc index ce89cba337245..9e67b9c9ca70e 100644 --- a/src/test/erasure-code/TestErasureCodeExample.cc +++ b/src/test/erasure-code/TestErasureCodeExample.cc @@ -194,16 +194,29 @@ TEST(ErasureCodeExample, decode) bufferlist out; EXPECT_EQ(0, example.decode_concat(encoded, &out)); bufferlist usable; + EXPECT_EQ(2u*encoded[0].length(), out.length()); usable.substr_of(out, 0, in.length()); EXPECT_TRUE(usable == in); // partial chunk decode - map partial_decode; - partial_decode[0] = encoded[0]; + map partial_decode = encoded; set partial_want_to_read{want_to_encode, want_to_encode+1}; + EXPECT_EQ(1u, partial_want_to_read.size()); + out.clear(); EXPECT_EQ(0, example.decode_concat(partial_want_to_read, partial_decode, &out)); + EXPECT_EQ(out.length(), encoded[0].length()); + + // partial degraded chunk decode + partial_decode = encoded; + partial_decode.erase(0); + EXPECT_EQ(1, partial_want_to_read.size()); + out.clear(); + EXPECT_EQ(0, example.decode_concat(partial_want_to_read, + partial_decode, + &out)); + EXPECT_EQ(out.length(), encoded[0].length()); // cannot recover map degraded; diff --git a/src/test/erasure-code/TestErasureCodeJerasure.cc b/src/test/erasure-code/TestErasureCodeJerasure.cc index 835f3c7b6c8f8..3946892c8aa63 100644 --- a/src/test/erasure-code/TestErasureCodeJerasure.cc +++ b/src/test/erasure-code/TestErasureCodeJerasure.cc @@ -127,6 +127,33 @@ TYPED_TEST(ErasureCodeTest, encode_decode) EXPECT_EQ(0, memcmp(decoded[1].c_str(), in.c_str() + length, in.length() - length)); } + + // partial decode with the exact-sized decode_concat() + { + map partial_decode = encoded; + // we have everything but want only the first chunk + set partial_want_to_read = { 0 }; + EXPECT_EQ(1u, partial_want_to_read.size()); + bufferlist out; + EXPECT_EQ(0, jerasure.decode_concat(partial_want_to_read, + partial_decode, + &out)); + EXPECT_EQ(out.length(), partial_decode[0].length()); + } + + // partial degraded decode with the exact-sized decode_concat() + { + map partial_decode = encoded; + // we have everything but what we really want + partial_decode.erase(0); + set partial_want_to_read = { 0 }; + EXPECT_EQ(1u, partial_want_to_read.size()); + bufferlist out; + EXPECT_EQ(0, jerasure.decode_concat(partial_want_to_read, + partial_decode, + &out)); + EXPECT_EQ(out.length(), encoded[0].length()); + } } } -- 2.39.5