Fix scrub bitmap comparison

This commit is contained in:
Vitaliy Filippov
2026-06-15 01:31:19 +03:00
parent 51ecbadb12
commit ac20f605f6
+11 -17
View File
@@ -1176,23 +1176,27 @@ static std::vector<int> ec_check_combination(osd_rmw_stripe_t *stripes, int stri
int *subset, int pg_size, int pg_minsize, bool is_xor, int *subset, int pg_size, int pg_minsize, bool is_xor,
uint32_t chunk_size, uint32_t bitmap_size, std::vector<uint8_t>& tmp_buf) uint32_t chunk_size, uint32_t bitmap_size, std::vector<uint8_t>& tmp_buf)
{ {
osd_num_t fake_osd_set[pg_size]; osd_num_t fake_osd_set[pg_size], fake_osd_set_mod[pg_size];
for (int i = 0; i < pg_size; i++) for (int i = 0; i < pg_size; i++)
{ {
fake_osd_set[i] = i+1; fake_osd_set[i] = i+1;
fake_osd_set_mod[i] = i+2;
} }
osd_rmw_stripe_t brute_stripes[pg_size]; osd_rmw_stripe_t brute_stripes[pg_size];
memset(brute_stripes, 0, sizeof(osd_rmw_stripe_t)*pg_size); memset(brute_stripes, 0, sizeof(osd_rmw_stripe_t)*pg_size);
for (int i = 0; i < pg_size; i++) for (int i = 0; i < pg_size; i++)
{ {
auto & bs = brute_stripes[i]; auto & bs = brute_stripes[i];
bs.req_end = bs.read_end = chunk_size; bs.read_end = chunk_size;
if (bitmap_size)
bs.bmp_buf = tmp_buf.data() + pg_size*chunk_size + i*bitmap_size;
} }
for (int i = 0; i < pg_minsize; i++) for (int i = 0; i < pg_minsize; i++)
{ {
auto & src = stripes[subset[i]]; auto & src = stripes[subset[i]];
auto & bs = brute_stripes[src.role]; auto & bs = brute_stripes[src.role];
bs.bmp_buf = src.bmp_buf; if (bitmap_size)
memcpy(bs.bmp_buf, src.bmp_buf, bitmap_size);
bs.write_buf = bs.read_buf = src.read_buf; bs.write_buf = bs.read_buf = src.read_buf;
bs.role = subset[i]; bs.role = subset[i];
} }
@@ -1205,34 +1209,23 @@ 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); assert(tmp_buf.size() >= (i+1)*chunk_size);
bs.read_buf = bs.write_buf = tmp_buf.data() + i*chunk_size; bs.read_buf = bs.write_buf = tmp_buf.data() + i*chunk_size;
if (bitmap_size)
{
assert(tmp_buf.size() >= pg_size*chunk_size + (i+1)*bitmap_size);
bs.bmp_buf = tmp_buf.data() + pg_size*chunk_size + i*bitmap_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); assert(tmp_buf.size() >= (i+1)*chunk_size);
bs.write_buf = tmp_buf.data() + i*chunk_size; bs.write_buf = tmp_buf.data() + i*chunk_size;
if (bitmap_size)
{
assert(tmp_buf.size() >= pg_size*chunk_size + (i+1)*bitmap_size);
bs.bmp_buf = tmp_buf.data() + pg_size*chunk_size + i*bitmap_size;
memcpy(bs.bmp_buf, stripes[i].bmp_buf, bitmap_size);
}
} }
} }
if (is_xor) if (is_xor)
{ {
assert(pg_size == pg_minsize+1); assert(pg_size == pg_minsize+1);
reconstruct_stripes_xor(brute_stripes, pg_size, bitmap_size); calc_rmw_parity_xor(brute_stripes, pg_size, fake_osd_set, fake_osd_set_mod, chunk_size, bitmap_size);
} }
else else
{ {
reconstruct_stripes_ec(brute_stripes, pg_size, pg_minsize, bitmap_size); // Mimic changed osd_set to force parity calculation
calc_rmw_parity_ec(brute_stripes, pg_size, pg_minsize, fake_osd_set, fake_osd_set, chunk_size, bitmap_size); calc_rmw_parity_ec(brute_stripes, pg_size, pg_minsize, fake_osd_set, fake_osd_set_mod, chunk_size, bitmap_size);
} }
bool matched_other = false; bool matched_other = false;
std::vector<int> good_set; std::vector<int> good_set;
@@ -1366,6 +1359,7 @@ std::vector<int> ec_find_good(osd_rmw_stripe_t *stripes, int stripe_count, int p
auto valid_chunks = ec_check_combination(stripes, stripe_count, subset, pg_size, pg_minsize, is_xor, chunk_size, bitmap_size, tmp_buf); auto valid_chunks = ec_check_combination(stripes, stripe_count, subset, pg_size, pg_minsize, is_xor, chunk_size, bitmap_size, tmp_buf);
// The same set may be found from different points of view, // The same set may be found from different points of view,
// like 1 2 3 -> valid 4 5 and 1 3 4 -> valid 2 5 // like 1 2 3 -> valid 4 5 and 1 3 4 -> valid 2 5
// However, a set should never be a subset of another one
if (valid_chunks.size() > 0) if (valid_chunks.size() > 0)
{ {
int valid_roles = count_roles(stripes, valid_chunks, pg_size); int valid_roles = count_roles(stripes, valid_chunks, pg_size);