Skip to content

Commit 571e2f3

Browse files
committed
osd/scrub: directly create or reinit the ScrubStore
The ScrubStore is now directly created or reinitialized by the Scrubber. Note that the store object is not identical to the errors DB: the errors DB is an entity in the OSD store (a collection of OMap entries in a uniquely-named object(s)), while the ScrubSTore object is a cacher and accessor for that entity. That one can be recreated or disposed of at will. We now do not recreate the ScrubStore object for every scrub. Signed-off-by: Ronen Friedman <[email protected]>
1 parent 38d9cf4 commit 571e2f3

File tree

4 files changed

+104
-32
lines changed

4 files changed

+104
-32
lines changed

src/osd/scrubber/ScrubStore.cc

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -99,20 +99,6 @@ string last_snap_key(int64_t pool)
9999

100100
namespace Scrub {
101101

102-
Store*
103-
Store::create(ObjectStore* store,
104-
ObjectStore::Transaction* t,
105-
const spg_t& pgid,
106-
const coll_t& coll)
107-
{
108-
ceph_assert(store);
109-
ceph_assert(t);
110-
ghobject_t oid = make_scrub_object(pgid);
111-
t->touch(coll, oid);
112-
return new Store{*store, t, pgid, coll};
113-
}
114-
115-
116102
Store::Store(
117103
ObjectStore& osd_store,
118104
ObjectStore::Transaction* t,
@@ -174,6 +160,33 @@ void Store::flush(ObjectStore::Transaction* t)
174160
errors_db->results.clear();
175161
}
176162

163+
164+
void Store::clear_level_db(
165+
ObjectStore::Transaction* t,
166+
at_level_t& db)
167+
{
168+
// easiest way to guarantee that the object representing the DB exists
169+
t->touch(coll, db.errors_hoid);
170+
171+
// remove all the keys in the DB
172+
t->omap_clear(coll, db.errors_hoid);
173+
174+
// restart the 'in progress' part of the MapCacher
175+
db.backend.reset();
176+
}
177+
178+
179+
void Store::reinit(ObjectStore::Transaction* t, [[maybe_unused]] scrub_level_t level)
180+
{
181+
// Note: only one caller, and it creates the transaction passed to reinit().
182+
// No need to assert on 't'
183+
184+
if (errors_db) {
185+
clear_level_db(t, *errors_db);
186+
}
187+
}
188+
189+
177190
void Store::cleanup(ObjectStore::Transaction* t)
178191
{
179192
ceph_assert(t);

src/osd/scrubber/ScrubStore.h

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,16 @@ namespace Scrub {
2020
class Store {
2121
public:
2222
~Store();
23-
static Store* create(ObjectStore* store,
24-
ObjectStore::Transaction* t,
25-
const spg_t& pgid,
26-
const coll_t& coll);
23+
24+
Store(ObjectStore& osd_store,
25+
ObjectStore::Transaction* t,
26+
const spg_t& pgid,
27+
const coll_t& coll);
28+
29+
30+
/// mark down detected errors, either shallow or deep
2731
void add_object_error(int64_t pool, const inconsistent_obj_wrapper& e);
32+
2833
void add_snap_error(int64_t pool, const inconsistent_snapset_wrapper& e);
2934

3035
// and a variant-friendly interface:
@@ -33,8 +38,22 @@ class Store {
3338

3439
bool empty() const;
3540
void flush(ObjectStore::Transaction*);
41+
42+
/// remove both shallow and deep errors DBs. Called on interval.
3643
void cleanup(ObjectStore::Transaction*);
3744

45+
/**
46+
* prepare the Store object for a new scrub session.
47+
* This involves clearing one or both of the errors DBs, and resetting
48+
* the cache.
49+
*
50+
* @param level: the scrub level to prepare for. Whenever a deep scrub
51+
* is requested, both the shallow and deep errors DBs are cleared.
52+
* If, on the other hand, a shallow scrub is requested, only the shallow
53+
* errors DB is cleared.
54+
*/
55+
void reinit(ObjectStore::Transaction* t, scrub_level_t level);
56+
3857
std::vector<ceph::buffer::list> get_snap_errors(
3958
int64_t pool,
4059
const librados::object_id_t& start,
@@ -73,15 +92,9 @@ class Store {
7392
std::map<std::string, ceph::buffer::list> results;
7493
};
7594

76-
Store(ObjectStore& osd_store,
77-
ObjectStore::Transaction* t,
78-
const spg_t& pgid,
79-
const coll_t& coll);
80-
8195
std::vector<ceph::buffer::list> get_errors(const std::string& start,
8296
const std::string& end,
8397
uint64_t max_return) const;
84-
private:
8598
/// the OSD's storage backend
8699
ObjectStore& object_store;
87100

@@ -96,6 +109,15 @@ class Store {
96109
*/
97110
mutable std::optional<at_level_t> errors_db;
98111
// not yet: mutable std::optional<at_level_t> deep_db;
112+
113+
/**
114+
* Clear the DB of errors at a specific scrub level by performing an
115+
* omap_clear() on the DB object, and resetting the MapCacher.
116+
*/
117+
void clear_level_db(
118+
ObjectStore::Transaction* t,
119+
at_level_t& db);
120+
99121
};
100122
} // namespace Scrub
101123

src/osd/scrubber/pg_scrubber.cc

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1183,6 +1183,7 @@ void PgScrubber::_request_scrub_map(pg_shard_t replica,
11831183
m_osds->send_message_osd_cluster(replica.osd, repscrubop, get_osdmap_epoch());
11841184
}
11851185

1186+
// only called on interval change. Both DBs are to be removed.
11861187
void PgScrubber::cleanup_store(ObjectStore::Transaction* t)
11871188
{
11881189
if (!m_store)
@@ -1200,6 +1201,38 @@ void PgScrubber::cleanup_store(ObjectStore::Transaction* t)
12001201
ceph_assert(!m_store);
12011202
}
12021203

1204+
1205+
void PgScrubber::reinit_scrub_store()
1206+
{
1207+
// Entering, 0 to 3 of the following objects(*) may exist:
1208+
// ((*)'objects' here: both code objects (the ScrubStore object) and
1209+
// actual Object Store objects).
1210+
// 1. The ScrubStore object itself.
1211+
// 2,3. The two special hobjects in the coll (the PG data) holding the last
1212+
// scrub's results. <<note: only one DB in this commit>>
1213+
//
1214+
// The Store object can be deleted and recreated, as a way to guarantee
1215+
// no junk is left. We won't do it here, but we will clear the at_level_t
1216+
// structures.
1217+
// The hobjects: possibly. The shallow DB object is always cleared. The
1218+
// deep one - only if running a deep scrub.
1219+
ObjectStore::Transaction t;
1220+
if (m_store) {
1221+
dout(10) << __func__ << " reusing existing store" << dendl;
1222+
m_store->flush(&t);
1223+
} else {
1224+
dout(10) << __func__ << " creating new store" << dendl;
1225+
m_store = std::make_unique<Scrub::Store>(
1226+
*m_pg->osd->store, &t, m_pg->info.pgid, m_pg->coll);
1227+
}
1228+
1229+
// regardless of whether the ScrubStore object was recreated or reused, we need to
1230+
// (possibly) clear the actual DB objects in the Object Store.
1231+
m_store->reinit(&t, m_active_target->level());
1232+
m_pg->osd->store->queue_transaction(m_pg->ch, std::move(t), nullptr);
1233+
}
1234+
1235+
12031236
void PgScrubber::on_init()
12041237
{
12051238
// going upwards from 'inactive'
@@ -1217,14 +1250,8 @@ void PgScrubber::on_init()
12171250
m_is_deep ? scrub_level_t::deep : scrub_level_t::shallow,
12181251
m_pg->get_actingset());
12191252

1220-
// create a new store
1221-
{
1222-
ObjectStore::Transaction t;
1223-
cleanup_store(&t);
1224-
m_store.reset(
1225-
Scrub::Store::create(m_pg->osd->store, &t, m_pg->info.pgid, m_pg->coll));
1226-
m_pg->osd->store->queue_transaction(m_pg->ch, std::move(t), nullptr);
1227-
}
1253+
// create or reuse the 'known errors' store
1254+
reinit_scrub_store();
12281255

12291256
m_start = m_pg->info.pgid.pgid.get_hobj_start();
12301257
m_active = true;

src/osd/scrubber/pg_scrubber.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -771,6 +771,16 @@ class PgScrubber : public ScrubPgIF,
771771

772772
std::unique_ptr<Scrub::Store> m_store;
773773

774+
/**
775+
* the ScrubStore sub-object caches and manages the database of known
776+
* scrub errors. reinit_scrub_store() clears the database and re-initializes
777+
* the ScrubStore object.
778+
*
779+
* in the next iteration - reinit_..() potentially deletes only the
780+
* shallow errors part of the database.
781+
*/
782+
void reinit_scrub_store();
783+
774784
int num_digest_updates_pending{0};
775785
hobject_t m_start, m_end; ///< note: half-closed: [start,end)
776786

0 commit comments

Comments
 (0)