diff --git a/src/osd/osd_rmw.cpp b/src/osd/osd_rmw.cpp index a11bf788..94b68529 100644 --- a/src/osd/osd_rmw.cpp +++ b/src/osd/osd_rmw.cpp @@ -1199,6 +1199,7 @@ static std::vector ec_check_combination(osd_rmw_stripe_t *stripes, int stri auto & bs = brute_stripes[src.role]; bs.bmp_buf = src.bmp_buf; bs.write_buf = bs.read_buf = src.read_buf; + bs.role = subset[i]; } for (int i = 0; i < pg_size; i++) { @@ -1209,13 +1210,21 @@ static std::vector ec_check_combination(osd_rmw_stripe_t *stripes, int stri bs.missing = true; assert(tmp_buf.size() >= (i+1)*(chunk_size+bitmap_size)); bs.read_buf = bs.write_buf = tmp_buf.data() + i*(chunk_size+bitmap_size); - bs.bmp_buf = bs.read_buf + chunk_size; + if (bitmap_size) + { + bs.bmp_buf = bs.write_buf + chunk_size; + } } else if (i >= pg_minsize) { // parity chunks are regenerated in their write_bufs, so use a temporary buffer assert(tmp_buf.size() >= (i+1)*(chunk_size+bitmap_size)); bs.write_buf = tmp_buf.data() + i*(chunk_size+bitmap_size); + if (bitmap_size) + { + bs.bmp_buf = bs.write_buf + chunk_size; + memcpy(bs.bmp_buf, stripes[i].bmp_buf, bitmap_size); + } } } if (is_xor) @@ -1242,7 +1251,8 @@ static std::vector ec_check_combination(osd_rmw_stripe_t *stripes, int stri // source chunk, mark OK good_set.push_back(i); } - else if (memcmp(stripes[i].role < pg_minsize ? bs.read_buf : bs.write_buf, stripes[i].read_buf, chunk_size) == 0) + else if (memcmp(stripes[i].role < pg_minsize ? bs.read_buf : bs.write_buf, stripes[i].read_buf, chunk_size) == 0 && + (!bitmap_size || memcmp(bs.bmp_buf, stripes[i].bmp_buf, bitmap_size) == 0)) { // matching chunk, mark OK good_set.push_back(i); diff --git a/src/osd/osd_rmw_test.cpp b/src/osd/osd_rmw_test.cpp index 5023bb9e..eeeb561e 100644 --- a/src/osd/osd_rmw_test.cpp +++ b/src/osd/osd_rmw_test.cpp @@ -1218,13 +1218,17 @@ void test_ec43_error_bruteforce() osd_num_t osd_set[7] = { 1, 2, 3, 4, 5, 6, 7 }; osd_rmw_stripe_t stripes[7] = {}; split_stripes(4, 4096, 0, 4096 * 4, stripes); + uint8_t *bmp_buf = (uint8_t*)malloc_or_die(4 * 7); + memset(bmp_buf, 0xff, 4 * 4); + for (int i = 0; i < 7; i++) + stripes[i].bmp_buf = bmp_buf + i*4; uint8_t *write_buf = (uint8_t*)malloc_or_die(4096 * 7); 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); + uint8_t *rmw_buf = (uint8_t*)calc_rmw(write_buf, stripes, osd_set, 7, 4, 7, osd_set, 4096, 4); + calc_rmw_parity_ec(stripes, 7, 4, osd_set, osd_set, 4096, 4); 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 @@ -1242,26 +1246,27 @@ void test_ec43_error_bruteforce() stripes[i].osd_num = i+1; } // All good chunks - auto res = ec_find_good(stripes, 7, 7, 4, false, 4096, 0, 100, true); + auto res = ec_find_good(stripes, 7, 7, 4, false, 4096, 4, 100, true); assert_eq_vec(res, std::vector({0, 1, 2, 3, 4, 5, 6})); // 1 missing chunk set_pattern(write_buf+1*4096, 4096, 0); - res = ec_find_good(stripes, 7, 7, 4, false, 4096, 0, 100, true); + res = ec_find_good(stripes, 7, 7, 4, false, 4096, 4, 100, true); assert_eq_vec(res, std::vector({0, 2, 3, 4, 5, 6})); // 2 missing chunks set_pattern(write_buf+1*4096, 4096, 0); set_pattern(write_buf+5*4096, 4096, 0); - res = ec_find_good(stripes, 7, 7, 4, false, 4096, 0, 100, true); + res = ec_find_good(stripes, 7, 7, 4, false, 4096, 4, 100, true); assert_eq_vec(res, std::vector({0, 2, 3, 4, 6})); // 3 missing chunks set_pattern(write_buf+1*4096, 4096, 0); set_pattern(write_buf+5*4096, 4096, 0); set_pattern(write_buf+6*4096, 4096, 0); - res = ec_find_good(stripes, 7, 7, 4, false, 4096, 0, 100, true); + res = ec_find_good(stripes, 7, 7, 4, false, 4096, 4, 100, true); assert_eq_vec(res, std::vector()); // Done free(rmw_buf); free(write_buf); + free(bmp_buf); use_ec(7, 4, false); } diff --git a/src/osd/osd_scrub.cpp b/src/osd/osd_scrub.cpp index c2efb7b6..6f898de6 100644 --- a/src/osd/osd_scrub.cpp +++ b/src/osd/osd_scrub.cpp @@ -474,7 +474,9 @@ void osd_t::scrub_check_results(osd_op_t *cur_op) for (int other = 0; other < role; other++) { // Only compare with unique chunks (eq_to[other] == other) - if (eq_to[other] == other && memcmp(op_data->stripes[role].read_buf, op_data->stripes[other].read_buf, bs_block_size) == 0) + if (eq_to[other] == other && + memcmp(op_data->stripes[role].read_buf, op_data->stripes[other].read_buf, bs_block_size) == 0 && + memcmp(op_data->stripes[role].bmp_buf, op_data->stripes[other].bmp_buf, clean_entry_bitmap_size) == 0) { eq_to[role] = eq_to[other]; break;