Verify bitmaps during scrub

This commit is contained in:
Vitaliy Filippov
2026-06-13 19:56:06 +03:00
parent 553cc8ef87
commit f3d662bac7
3 changed files with 26 additions and 9 deletions
+12 -2
View File
@@ -1199,6 +1199,7 @@ static std::vector<int> ec_check_combination(osd_rmw_stripe_t *stripes, int stri
auto & bs = brute_stripes[src.role]; auto & bs = brute_stripes[src.role];
bs.bmp_buf = src.bmp_buf; bs.bmp_buf = src.bmp_buf;
bs.write_buf = bs.read_buf = src.read_buf; bs.write_buf = bs.read_buf = src.read_buf;
bs.role = subset[i];
} }
for (int i = 0; i < pg_size; i++) for (int i = 0; i < pg_size; i++)
{ {
@@ -1209,13 +1210,21 @@ static std::vector<int> ec_check_combination(osd_rmw_stripe_t *stripes, int stri
bs.missing = true; bs.missing = true;
assert(tmp_buf.size() >= (i+1)*(chunk_size+bitmap_size)); 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.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) else if (i >= pg_minsize)
{ {
// parity chunks are regenerated in their write_bufs, so use a temporary buffer // parity chunks are regenerated in their write_bufs, so use a temporary buffer
assert(tmp_buf.size() >= (i+1)*(chunk_size+bitmap_size)); assert(tmp_buf.size() >= (i+1)*(chunk_size+bitmap_size));
bs.write_buf = tmp_buf.data() + i*(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) if (is_xor)
@@ -1242,7 +1251,8 @@ static std::vector<int> ec_check_combination(osd_rmw_stripe_t *stripes, int stri
// source chunk, mark OK // source chunk, mark OK
good_set.push_back(i); 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 // matching chunk, mark OK
good_set.push_back(i); good_set.push_back(i);
+11 -6
View File
@@ -1218,13 +1218,17 @@ void test_ec43_error_bruteforce()
osd_num_t osd_set[7] = { 1, 2, 3, 4, 5, 6, 7 }; osd_num_t osd_set[7] = { 1, 2, 3, 4, 5, 6, 7 };
osd_rmw_stripe_t stripes[7] = {}; osd_rmw_stripe_t stripes[7] = {};
split_stripes(4, 4096, 0, 4096 * 4, stripes); 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); uint8_t *write_buf = (uint8_t*)malloc_or_die(4096 * 7);
set_pattern(write_buf+0*4096, 4096, PATTERN0); set_pattern(write_buf+0*4096, 4096, PATTERN0);
set_pattern(write_buf+1*4096, 4096, PATTERN1); set_pattern(write_buf+1*4096, 4096, PATTERN1);
set_pattern(write_buf+2*4096, 4096, PATTERN2); set_pattern(write_buf+2*4096, 4096, PATTERN2);
set_pattern(write_buf+3*4096, 4096, PATTERN3); 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); 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, 0); 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[4].write_buf, 4096, PATTERN0^PATTERN1^PATTERN2^PATTERN3);
check_pattern(stripes[5].write_buf, 4096, 0xfcee568ba36371ac); // 2nd EC chunk check_pattern(stripes[5].write_buf, 4096, 0xfcee568ba36371ac); // 2nd EC chunk
check_pattern(stripes[6].write_buf, 4096, 0x139274739ae6f387); // 3rd 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; stripes[i].osd_num = i+1;
} }
// All good chunks // 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<int>({0, 1, 2, 3, 4, 5, 6})); assert_eq_vec(res, std::vector<int>({0, 1, 2, 3, 4, 5, 6}));
// 1 missing chunk // 1 missing chunk
set_pattern(write_buf+1*4096, 4096, 0); 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<int>({0, 2, 3, 4, 5, 6})); assert_eq_vec(res, std::vector<int>({0, 2, 3, 4, 5, 6}));
// 2 missing chunks // 2 missing chunks
set_pattern(write_buf+1*4096, 4096, 0); set_pattern(write_buf+1*4096, 4096, 0);
set_pattern(write_buf+5*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<int>({0, 2, 3, 4, 6})); assert_eq_vec(res, std::vector<int>({0, 2, 3, 4, 6}));
// 3 missing chunks // 3 missing chunks
set_pattern(write_buf+1*4096, 4096, 0); set_pattern(write_buf+1*4096, 4096, 0);
set_pattern(write_buf+5*4096, 4096, 0); set_pattern(write_buf+5*4096, 4096, 0);
set_pattern(write_buf+6*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<int>()); assert_eq_vec(res, std::vector<int>());
// Done // Done
free(rmw_buf); free(rmw_buf);
free(write_buf); free(write_buf);
free(bmp_buf);
use_ec(7, 4, false); use_ec(7, 4, false);
} }
+3 -1
View File
@@ -474,7 +474,9 @@ void osd_t::scrub_check_results(osd_op_t *cur_op)
for (int other = 0; other < role; other++) for (int other = 0; other < role; other++)
{ {
// Only compare with unique chunks (eq_to[other] == 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]; eq_to[role] = eq_to[other];
break; break;