Skip to content

Commit 0130e64

Browse files
authored
Merge pull request ceph#65151 from ronen-fr/wip-rf-eccalc
osd/scrub: calculate EC digest map size only once Reviewed-by: Jon Bailey <[email protected]>
2 parents 87f5603 + cbdd07a commit 0130e64

File tree

3 files changed

+81
-50
lines changed

3 files changed

+81
-50
lines changed

src/osd/scrubber/scrub_backend.cc

Lines changed: 40 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,15 @@ std::ostream& ScrubBackend::logger_prefix(std::ostream* out,
4141
return t->m_scrubber.gen_prefix(*out) << " b.e.: ";
4242
}
4343

44+
45+
// //////////////////// scrub_chunk_t ///////////////////////////////////// //
46+
47+
scrub_chunk_t::scrub_chunk_t(pg_shard_t i_am, uint32_t ec_digest_sz)
48+
: m_ec_digest_map{ec_digest_sz}
49+
{
50+
received_maps[i_am] = ScrubMap{};
51+
}
52+
4453
// ////////////////////////////////////////////////////////////////////////// //
4554

4655
// for a Primary
@@ -71,6 +80,12 @@ ScrubBackend::ScrubBackend(ScrubBeListener& scrubber,
7180

7281
m_is_replicated = m_pool.info.is_replicated();
7382
m_is_optimized_ec = m_pool.info.allows_ecoptimizations();
83+
84+
// EC-related:
85+
if (!m_is_replicated && m_pg.get_ec_supports_crc_encode_decode()) {
86+
m_ec_digest_map_size = m_pg.get_ec_sinfo().get_k_plus_m();
87+
}
88+
7489
m_mode_desc =
7590
(m_repair ? "repair"sv
7691
: (m_depth == scrub_level_t::deep ? "deep-scrub"sv : "scrub"sv));
@@ -133,7 +148,7 @@ void ScrubBackend::update_repair_status(bool should_repair)
133148
void ScrubBackend::new_chunk()
134149
{
135150
dout(15) << __func__ << dendl;
136-
this_chunk.emplace(m_pg_whoami);
151+
this_chunk.emplace(m_pg_whoami, m_ec_digest_map_size);
137152
}
138153

139154
ScrubMap& ScrubBackend::get_primary_scrubmap()
@@ -436,11 +451,6 @@ auth_selection_t ScrubBackend::select_auth_object(const hobject_t& ho,
436451
/// This creates an issue with 'digest_match' that should be handled.
437452
std::list<pg_shard_t> shards;
438453
shard_id_set available_shards;
439-
uint32_t digest_map_size = 0;
440-
if (!m_is_replicated && m_pg.get_ec_supports_crc_encode_decode()) {
441-
digest_map_size = m_pg.get_ec_sinfo().get_k_plus_m();
442-
}
443-
shard_id_map<bufferlist> digest_map{digest_map_size};
444454

445455
for (const auto& [srd, smap] : this_chunk->received_maps) {
446456
if (srd != m_pg_whoami) {
@@ -461,8 +471,8 @@ auth_selection_t ScrubBackend::select_auth_object(const hobject_t& ho,
461471
m_pg.get_ec_sinfo().get_chunk_size());
462472
b.copy_in(0, length, crc_bytes);
463473

464-
digest_map[srd.shard] = bufferlist{};
465-
digest_map[srd.shard].append(b);
474+
this_chunk->m_ec_digest_map[srd.shard] = bufferlist{};
475+
this_chunk->m_ec_digest_map[srd.shard].append(b);
466476
}
467477
}
468478
shards.push_front(m_pg_whoami);
@@ -572,8 +582,8 @@ auth_selection_t ScrubBackend::select_auth_object(const hobject_t& ho,
572582
"as only received shards were ({}).",
573583
__func__, missing_shards, m_pg_whoami, available_shards)
574584
<< dendl;
575-
digest_map = m_pg.ec_decode_acting_set(
576-
digest_map, m_pg.get_ec_sinfo().get_chunk_size());
585+
this_chunk->m_ec_digest_map = m_pg.ec_decode_acting_set(
586+
this_chunk->m_ec_digest_map, m_pg.get_ec_sinfo().get_chunk_size());
577587
} else if (missing_shards != 0) {
578588
dout(5) << fmt::format(
579589
"{}: Cannot decode {} shards from pg {} "
@@ -593,17 +603,17 @@ auth_selection_t ScrubBackend::select_auth_object(const hobject_t& ho,
593603
uint32_t zero_data_crc = generate_zero_buffer_crc(
594604
shard_id, logical_to_ondisk_size(ret_auth.auth_oi.size, shard_id));
595605
for (std::size_t i = 0; i < sizeof(zero_data_crc); i++) {
596-
digest_map[shard_id].c_str()[i] =
597-
digest_map[shard_id][i] ^ ((zero_data_crc >> (8 * i)) & 0xff);
606+
this_chunk->m_ec_digest_map[shard_id].c_str()[i] =
607+
this_chunk->m_ec_digest_map[shard_id][i] ^ ((zero_data_crc >> (8 * i)) & 0xff);
598608
}
599609

600-
crc_bl.append(digest_map[shard_id]);
610+
crc_bl.append(this_chunk->m_ec_digest_map[shard_id]);
601611
}
602612

603613
shard_id_map<bufferlist> encoded_crcs = m_pg.ec_encode_acting_set(crc_bl);
604614

605615
if (encoded_crcs[shard_id_t(m_pg.get_ec_sinfo().get_k())] !=
606-
digest_map[shard_id_t(m_pg.get_ec_sinfo().get_k())]) {
616+
this_chunk->m_ec_digest_map[shard_id_t(m_pg.get_ec_sinfo().get_k())]) {
607617
ret_auth.digest_match = false;
608618
}
609619
} else {
@@ -885,9 +895,7 @@ std::optional<std::string> ScrubBackend::compare_obj_in_maps(
885895
const hobject_t& ho)
886896
{
887897
// clear per-object data:
888-
this_chunk->cur_inconsistent.clear();
889-
this_chunk->cur_missing.clear();
890-
this_chunk->fix_digest = false;
898+
m_current_obj = object_scrub_data_t{};
891899

892900
stringstream candidates_errors;
893901
auto auth_res = select_auth_object(ho, candidates_errors);
@@ -927,7 +935,7 @@ std::optional<std::string> ScrubBackend::compare_obj_in_maps(
927935

928936
object_error.set_version(auth_res.auth_oi.user_version);
929937
ScrubMap::object& auth_object = auth->second.objects[ho];
930-
ceph_assert(!this_chunk->fix_digest);
938+
ceph_assert(!m_current_obj.fix_digest);
931939

932940
auto [auths, objerrs] =
933941
match_in_shards(ho, auth_res, object_error, errstream);
@@ -1014,7 +1022,7 @@ void ScrubBackend::inconsistents(const hobject_t& ho,
10141022
auto& object_errors = auth_n_errs.object_errors;
10151023
auto& auth_list = auth_n_errs.auth_list;
10161024

1017-
this_chunk->cur_inconsistent.insert(object_errors.begin(),
1025+
m_current_obj.cur_inconsistent.insert(object_errors.begin(),
10181026
object_errors.end()); // merge?
10191027

10201028
dout(15) << fmt::format(
@@ -1023,19 +1031,19 @@ void ScrubBackend::inconsistents(const hobject_t& ho,
10231031
__func__,
10241032
object_errors.size(),
10251033
auth_list.size(),
1026-
this_chunk->cur_missing.size(),
1027-
this_chunk->cur_inconsistent.size())
1034+
m_current_obj.cur_missing.size(),
1035+
m_current_obj.cur_inconsistent.size())
10281036
<< dendl;
10291037

10301038

1031-
if (!this_chunk->cur_missing.empty()) {
1032-
m_missing[ho] = this_chunk->cur_missing;
1039+
if (!m_current_obj.cur_missing.empty()) {
1040+
m_missing[ho] = m_current_obj.cur_missing;
10331041
}
1034-
if (!this_chunk->cur_inconsistent.empty()) {
1035-
m_inconsistent[ho] = this_chunk->cur_inconsistent;
1042+
if (!m_current_obj.cur_inconsistent.empty()) {
1043+
m_inconsistent[ho] = m_current_obj.cur_inconsistent;
10361044
}
10371045

1038-
if (this_chunk->fix_digest) {
1046+
if (m_current_obj.fix_digest) {
10391047

10401048
ceph_assert(auth_object.digest_present);
10411049
std::optional<uint32_t> data_digest{auth_object.digest};
@@ -1048,12 +1056,12 @@ void ScrubBackend::inconsistents(const hobject_t& ho,
10481056
make_pair(ho, make_pair(data_digest, omap_digest)));
10491057
}
10501058

1051-
if (!this_chunk->cur_inconsistent.empty() ||
1052-
!this_chunk->cur_missing.empty()) {
1059+
if (!m_current_obj.cur_inconsistent.empty() ||
1060+
!m_current_obj.cur_missing.empty()) {
10531061

10541062
this_chunk->authoritative[ho] = auth_list;
10551063

1056-
} else if (!this_chunk->fix_digest && m_is_replicated) {
1064+
} else if (!m_current_obj.fix_digest && m_is_replicated) {
10571065

10581066
auto is_to_fix =
10591067
should_fix_digest(ho, auth_object, auth_oi, m_repair, errstream);
@@ -1227,7 +1235,7 @@ ScrubBackend::auth_and_obj_errs_t ScrubBackend::match_in_shards(
12271235
auth_sel.shard_map[srd].only_data_digest_mismatch_info() &&
12281236
auth_object.digest_present) {
12291237
// Set in missing_digests
1230-
this_chunk->fix_digest = true;
1238+
m_current_obj.fix_digest = true;
12311239
// Clear the error
12321240
auth_sel.shard_map[srd].clear_data_digest_mismatch_info();
12331241
errstream << m_pg_id << " soid " << ho
@@ -1238,7 +1246,7 @@ ScrubBackend::auth_and_obj_errs_t ScrubBackend::match_in_shards(
12381246
// Some errors might have already been set in select_auth_object()
12391247
if (auth_sel.shard_map[srd].errors != 0) {
12401248

1241-
this_chunk->cur_inconsistent.insert(srd);
1249+
m_current_obj.cur_inconsistent.insert(srd);
12421250
if (auth_sel.shard_map[srd].has_deep_errors()) {
12431251
this_chunk->m_error_counts.deep_errors++;
12441252
} else {
@@ -1269,7 +1277,7 @@ ScrubBackend::auth_and_obj_errs_t ScrubBackend::match_in_shards(
12691277

12701278
} else {
12711279

1272-
this_chunk->cur_missing.insert(srd);
1280+
m_current_obj.cur_missing.insert(srd);
12731281
auth_sel.shard_map[srd].set_missing();
12741282
auth_sel.shard_map[srd].primary = (srd == m_pg_whoami);
12751283

src/osd/scrubber/scrub_backend.h

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,6 @@ struct shard_as_auth_t {
162162
object_info_t oi;
163163
shard_to_scrubmap_t::iterator auth_iter;
164164
std::optional<uint32_t> digest;
165-
// when used for Crimson, we'll probably want to return 'digest_match' (and
166-
// other in/out arguments) via this struct
167165
};
168166

169167
namespace fmt {
@@ -227,10 +225,12 @@ struct auth_selection_t {
227225
bool digest_match{true}; ///< do all (existing) digests match?
228226
};
229227

228+
namespace fmt {
229+
230230
// note: some scrub tests are sensitive to the specific format of
231231
// auth_selection_t listing in the logs
232232
template <>
233-
struct fmt::formatter<auth_selection_t> {
233+
struct formatter<auth_selection_t> {
234234
template <typename ParseContext>
235235
constexpr auto parse(ParseContext& ctx)
236236
{
@@ -250,6 +250,19 @@ struct fmt::formatter<auth_selection_t> {
250250
aus.digest_match);
251251
}
252252
};
253+
} // namespace fmt
254+
255+
256+
/**
257+
* the back-end data that is per-object
258+
*/
259+
struct object_scrub_data_t {
260+
std::set<pg_shard_t> cur_missing;
261+
std::set<pg_shard_t> cur_inconsistent;
262+
bool fix_digest{false};
263+
};
264+
265+
253266

254267
/**
255268
* the back-end data that is per-chunk
@@ -258,7 +271,7 @@ struct fmt::formatter<auth_selection_t> {
258271
*/
259272
struct scrub_chunk_t {
260273

261-
explicit scrub_chunk_t(pg_shard_t i_am) { received_maps[i_am] = ScrubMap{}; }
274+
explicit scrub_chunk_t(pg_shard_t i_am, uint32_t ec_digest_sz);
262275

263276
/// the working set of scrub maps: the received maps, plus
264277
/// Primary's own map.
@@ -279,11 +292,8 @@ struct scrub_chunk_t {
279292
/// shallow/deep error counters
280293
error_counters_t m_error_counts;
281294

282-
// these must be reset for each element:
283-
284-
std::set<pg_shard_t> cur_missing;
285-
std::set<pg_shard_t> cur_inconsistent;
286-
bool fix_digest{false};
295+
// EC-related:
296+
shard_id_map<bufferlist> m_ec_digest_map;
287297
};
288298

289299

@@ -377,19 +387,24 @@ class ScrubBackend {
377387
/// Mapping from object with errors to good peers
378388
std::map<hobject_t, auth_peers_t> m_auth_peers;
379389

390+
// EC related:
391+
/// size of the EC digest map, calculated based on the EC configuration
392+
uint32_t m_ec_digest_map_size{0};
393+
380394
// shorthands:
381395
ConfigProxy& m_conf;
382396
LoggerSinkSet& clog;
383397

384-
private:
385-
386398
struct auth_and_obj_errs_t {
387399
std::list<pg_shard_t> auth_list;
388400
std::set<pg_shard_t> object_errors;
389401
};
390402

391403
std::optional<scrub_chunk_t> this_chunk;
392404

405+
/// the data collected/processed re the specific object being scrubbed
406+
object_scrub_data_t m_current_obj;
407+
393408
/// Maps from objects with errors to missing peers
394409
HobjToShardSetMapping m_missing; // used by scrub_process_inconsistent()
395410

src/test/osd/test_scrubber_be.cc

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,12 @@ class TestTScrubberBe : public ::testing::Test {
413413
* \returns the PG info
414414
*/
415415
pg_info_t setup_pg_in_map();
416+
417+
/**
418+
* EC requires that set_stripe_data() is called before the
419+
* ScrubBackend object is constructed
420+
*/
421+
virtual void ec_set_stripe_info() {}
416422
};
417423

418424

@@ -466,6 +472,9 @@ void TestTScrubberBe::SetUp()
466472
test_pg = std::make_unique<TestPg>(pool, info, i_am);
467473
std::cout << fmt::format("{}: acting: {}", __func__, acting_shards)
468474
<< std::endl;
475+
476+
// an EC-only hook to allocate & init the 'stripe conf' structure
477+
ec_set_stripe_info();
469478
sbe = std::make_unique<TestScrubBackend>(*test_scrubber,
470479
*test_pg,
471480
i_am,
@@ -772,7 +781,7 @@ class TestTScrubberBe_data_2 : public TestTScrubberBe {
772781
TestTScrubberBe_data_2() : TestTScrubberBe() {}
773782

774783
// basic test configuration - 3 OSDs, all involved in the pool
775-
pool_conf_t pl{3, 3, 3, 3, "rep_pool", pg_pool_t::TYPE_REPLICATED,
784+
pool_conf_t pl{3, 3, 3, 3, "rep_pool", pg_pool_t::TYPE_REPLICATED,
776785
std::nullopt};
777786

778787
TestTScrubberBeParams inject_params() override
@@ -853,6 +862,11 @@ class TestTScrubberBeECCorruptShards : public TestTScrubberBe {
853862

854863
return params;
855864
}
865+
866+
void ec_set_stripe_info() override
867+
{
868+
test_pg->set_stripe_info(k, m, k * m_chunk_size, &test_pg->m_pool->info);
869+
}
856870
};
857871

858872
class TestTScrubberBeECNoCorruptShards : public TestTScrubberBeECCorruptShards {
@@ -861,8 +875,6 @@ class TestTScrubberBeECNoCorruptShards : public TestTScrubberBeECCorruptShards {
861875
};
862876

863877
TEST_F(TestTScrubberBeECNoCorruptShards, ec_parity_inconsistency) {
864-
test_pg->set_stripe_info(k, m, k * m_chunk_size, &test_pg->m_pool->info);
865-
866878
ASSERT_TRUE(sbe); // Assert we have a scrubber backend
867879
logger.set_expected_err_count(
868880
0); // Set the number of errors we expect to see
@@ -891,8 +903,6 @@ class TestTScrubberBeECSingleCorruptDataShard
891903
};
892904

893905
TEST_F(TestTScrubberBeECSingleCorruptDataShard, ec_parity_inconsistency) {
894-
test_pg->set_stripe_info(k, m, k * m_chunk_size, &test_pg->m_pool->info);
895-
896906
ASSERT_TRUE(sbe); // Assert we have a scrubber backend
897907
logger.set_expected_err_count(
898908
1); // Set the number of errors we expect to see
@@ -920,8 +930,6 @@ class TestTScrubberBeECCorruptParityShard
920930
};
921931

922932
TEST_F(TestTScrubberBeECCorruptParityShard, ec_parity_inconsistency) {
923-
test_pg->set_stripe_info(k, m, k * m_chunk_size, &test_pg->m_pool->info);
924-
925933
ASSERT_TRUE(sbe); // Assert we have a scrubber backend
926934
logger.set_expected_err_count(
927935
1); // Set the number of errors we expect to see

0 commit comments

Comments
 (0)