From 1ec963e46835eb50947f37d1caba63d0c482d081 Mon Sep 17 00:00:00 2001 From: Vitaliy Filippov Date: Mon, 11 May 2026 15:57:21 +0300 Subject: [PATCH] Fix ec_find_good for misplaced objects with extra corrupted chunks --- src/osd/osd_rmw.cpp | 4 +-- src/osd/osd_rmw_test.cpp | 53 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/src/osd/osd_rmw.cpp b/src/osd/osd_rmw.cpp index 29022aab..a13712ca 100644 --- a/src/osd/osd_rmw.cpp +++ b/src/osd/osd_rmw.cpp @@ -1281,7 +1281,7 @@ std::vector ec_find_good(osd_rmw_stripe_t *stripes, int stripe_count, int p std::vector> live_variants(pg_size); int eq_to[stripe_count]; int live_roles = 0, live_total = 0; - for (int i = 0; i < pg_size; i++) + for (int i = 0; i < stripe_count; i++) { eq_to[i] = i; } @@ -1381,7 +1381,7 @@ std::vector ec_find_good(osd_rmw_stripe_t *stripes, int stripe_count, int p for (i = 0; i < pg_minsize; i++) { subvar[i]++; - if (subvar[i] < live_variants[combination[i]].size()) + if (subvar[i] < live_variants[comb_to_subset[combination[i]]].size()) break; subvar[i] = 0; } diff --git a/src/osd/osd_rmw_test.cpp b/src/osd/osd_rmw_test.cpp index c936ccc8..914f0207 100644 --- a/src/osd/osd_rmw_test.cpp +++ b/src/osd/osd_rmw_test.cpp @@ -31,6 +31,7 @@ void test_recover_22_d2(); void test_ec43_error_bruteforce(); void test_recover_53_d5(); void test_recover_22(); +void test_ec_find_good_multi_chunks(); int main(int narg, char *args[]) { @@ -69,6 +70,7 @@ int main(int narg, char *args[]) test_recover_22_d2(); // Error bruteforce test_ec43_error_bruteforce(); + test_ec_find_good_multi_chunks(); // Test 19 test_recover_53_d5(); // Test 20 @@ -1345,3 +1347,54 @@ void test_recover_22() free(write_buf); use_ec(4, 2, false); } + +void test_ec_find_good_multi_chunks() +{ + use_ec(7, 4, true); + osd_num_t osd_set[7] = { 1, 2, 3, 4, 5, 6, 7 }; + osd_rmw_stripe_t stripes[15] = {}; + split_stripes(4, 4096, 0, 4096 * 4, stripes); + uint8_t *write_buf = (uint8_t*)malloc_or_die(4096 * 15); + set_pattern(write_buf+0*4096, 4096, PATTERN0); + set_pattern(write_buf+1*4096, 4096, PATTERN1); + set_pattern(write_buf+2*4096, 4096, PATTERN2); + set_pattern(write_buf+3*4096, 4096, PATTERN3); + uint8_t *rmw_buf = (uint8_t*)calc_rmw(write_buf, stripes, osd_set, 7, 4, 7, osd_set, 4096, 0); + calc_rmw_parity_ec(stripes, 7, 4, osd_set, osd_set, 4096, 0); + check_pattern(stripes[4].write_buf, 4096, PATTERN0^PATTERN1^PATTERN2^PATTERN3); + check_pattern(stripes[5].write_buf, 4096, 0xfcee568ba36371ac); // 2nd EC chunk + check_pattern(stripes[6].write_buf, 4096, 0x139274739ae6f387); // 3rd EC chunk + memcpy(write_buf+4*4096, stripes[4].write_buf, 4096); + memcpy(write_buf+5*4096, stripes[5].write_buf, 4096); + memcpy(write_buf+6*4096, stripes[6].write_buf, 4096); + // Make 15 chunks + for (int i = 0; i < 15; i++) + { + stripes[i].read_start = 0; + stripes[i].read_end = 4096; + stripes[i].read_buf = write_buf+i*4096; + stripes[i].write_buf = NULL; + stripes[i].role = i; + stripes[i].osd_num = i+1; + } + for (int i = 7; i < 14; i++) + { + stripes[i].role = i % 7; + memcpy(write_buf+i*4096, write_buf + (i%7)*4096, 4096); + } + stripes[14].role = 6; + memcpy(write_buf+14*4096, write_buf + 6*4096, 4096); + // Corrupt chunks 0-6 and chunk 13, make role 0 absent + stripes[0].read_error = true; + stripes[7].read_error = true; + for (int i = 0; i < 7; i++) + memset(write_buf+i*4096, i*10+1, 4096); + memset(write_buf+13*4096, 8*10+1, 4096); + // Find errors + auto res = ec_find_good(stripes, 15, 7, 4, false, 4096, 0, 100, true); + assert_eq_vec(res, std::vector({8, 9, 10, 11, 12, 14})); + // Done + free(rmw_buf); + free(write_buf); + use_ec(7, 4, false); +}