}
/******* PG ***********/
-bool PG::needs_recovery() const
-{
- ceph_assert(is_primary());
-
- auto &missing = pg_log.get_missing();
-
- if (missing.num_missing()) {
- dout(10) << __func__ << " primary has " << missing.num_missing()
- << " missing" << dendl;
- return true;
- }
-
- ceph_assert(!acting_recovery_backfill.empty());
- set<pg_shard_t>::const_iterator end = acting_recovery_backfill.end();
- set<pg_shard_t>::const_iterator a = acting_recovery_backfill.begin();
- for (; a != end; ++a) {
- if (*a == get_primary()) continue;
- pg_shard_t peer = *a;
- map<pg_shard_t, pg_missing_t>::const_iterator pm = peer_missing.find(peer);
- if (pm == peer_missing.end()) {
- dout(10) << __func__ << " osd." << peer << " doesn't have missing set"
- << dendl;
- continue;
- }
- if (pm->second.num_missing()) {
- dout(10) << __func__ << " osd." << peer << " has "
- << pm->second.num_missing() << " missing" << dendl;
- return true;
- }
- }
-
- dout(10) << __func__ << " is recovered" << dendl;
- return false;
-}
-
-bool PG::needs_backfill() const
-{
- ceph_assert(is_primary());
-
- // We can assume that only possible osds that need backfill
- // are on the backfill_targets vector nodes.
- set<pg_shard_t>::const_iterator end = backfill_targets.end();
- set<pg_shard_t>::const_iterator a = backfill_targets.begin();
- for (; a != end; ++a) {
- pg_shard_t peer = *a;
- map<pg_shard_t, pg_info_t>::const_iterator pi = peer_info.find(peer);
- if (!pi->second.last_backfill.is_max()) {
- dout(10) << __func__ << " osd." << peer << " has last_backfill " << pi->second.last_backfill << dendl;
- return true;
- }
- }
-
- dout(10) << __func__ << " does not need backfill" << dendl;
- return false;
-}
-
-/*
- * Returns true unless there is a non-lost OSD in might_have_unfound.
- */
-bool PG::all_unfound_are_queried_or_lost(const OSDMapRef osdmap) const
-{
- ceph_assert(is_primary());
-
- set<pg_shard_t>::const_iterator peer = might_have_unfound.begin();
- set<pg_shard_t>::const_iterator mend = might_have_unfound.end();
- for (; peer != mend; ++peer) {
- if (peer_missing.count(*peer))
- continue;
- map<pg_shard_t, pg_info_t>::const_iterator iter = peer_info.find(*peer);
- if (iter != peer_info.end() &&
- (iter->second.is_empty() || iter->second.dne()))
- continue;
- if (!osdmap->exists(peer->osd))
- continue;
- const osd_info_t &osd_info(osdmap->get_info(peer->osd));
- if (osd_info.lost_at <= osd_info.up_from) {
- // If there is even one OSD in might_have_unfound that isn't lost, we
- // still might retrieve our unfound.
- return false;
- }
- }
- dout(10) << "all_unfound_are_queried_or_lost all of might_have_unfound " << might_have_unfound
- << " have been queried or are marked lost" << dendl;
- return true;
-}
-
void PG::clear_primary_state()
{
last_update_ondisk = eversion_t();
friend class TestOpsSocketHook;
void publish_stats_to_osd() override;
- bool needs_recovery() const;
- bool needs_backfill() const;
-
void try_mark_clean(); ///< mark an active pg clean
+ bool needs_recovery() const {
+ return recovery_state.needs_recovery();
+ }
+ bool needs_backfill() const {
+ return recovery_state.needs_backfill();
+ }
+
bool all_unfound_are_queried_or_lost(const OSDMapRef osdmap) const;
virtual void dump_recovery_info(Formatter *f) const = 0;
uint64_t get_num_unfound() const {
return missing_loc.num_unfound();
}
- bool all_missing_unfound() const {
- const auto& missing = pg_log.get_missing();
- if (!missing.have_missing())
- return false;
- for (auto& m : missing.get_items()) {
- if (!missing_loc.is_unfound(m.first))
- return false;
- }
- return true;
- }
virtual void check_local() = 0;
return prior;
}
+bool PeeringState::needs_recovery() const
+{
+ ceph_assert(is_primary());
+
+ auto &missing = pg_log.get_missing();
+
+ if (missing.num_missing()) {
+ dout(10) << __func__ << " primary has " << missing.num_missing()
+ << " missing" << dendl;
+ return true;
+ }
+
+ ceph_assert(!acting_recovery_backfill.empty());
+ set<pg_shard_t>::const_iterator end = acting_recovery_backfill.end();
+ set<pg_shard_t>::const_iterator a = acting_recovery_backfill.begin();
+ for (; a != end; ++a) {
+ if (*a == get_primary()) continue;
+ pg_shard_t peer = *a;
+ map<pg_shard_t, pg_missing_t>::const_iterator pm = peer_missing.find(peer);
+ if (pm == peer_missing.end()) {
+ psdout(10) << __func__ << " osd." << peer << " doesn't have missing set"
+ << dendl;
+ continue;
+ }
+ if (pm->second.num_missing()) {
+ psdout(10) << __func__ << " osd." << peer << " has "
+ << pm->second.num_missing() << " missing" << dendl;
+ return true;
+ }
+ }
+
+ psdout(10) << __func__ << " is recovered" << dendl;
+ return false;
+}
+
+bool PeeringState::needs_backfill() const
+{
+ ceph_assert(is_primary());
+
+ // We can assume that only possible osds that need backfill
+ // are on the backfill_targets vector nodes.
+ set<pg_shard_t>::const_iterator end = backfill_targets.end();
+ set<pg_shard_t>::const_iterator a = backfill_targets.begin();
+ for (; a != end; ++a) {
+ pg_shard_t peer = *a;
+ map<pg_shard_t, pg_info_t>::const_iterator pi = peer_info.find(peer);
+ if (!pi->second.last_backfill.is_max()) {
+ psdout(10) << __func__ << " osd." << peer
+ << " has last_backfill " << pi->second.last_backfill << dendl;
+ return true;
+ }
+ }
+
+ dout(10) << __func__ << " does not need backfill" << dendl;
+ return false;
+}
+
+/*
+ * Returns true unless there is a non-lost OSD in might_have_unfound.
+ */
+bool PeeringState::all_unfound_are_queried_or_lost(
+ const OSDMapRef osdmap) const
+{
+ ceph_assert(is_primary());
+
+ set<pg_shard_t>::const_iterator peer = might_have_unfound.begin();
+ set<pg_shard_t>::const_iterator mend = might_have_unfound.end();
+ for (; peer != mend; ++peer) {
+ if (peer_missing.count(*peer))
+ continue;
+ map<pg_shard_t, pg_info_t>::const_iterator iter = peer_info.find(*peer);
+ if (iter != peer_info.end() &&
+ (iter->second.is_empty() || iter->second.dne()))
+ continue;
+ if (!osdmap->exists(peer->osd))
+ continue;
+ const osd_info_t &osd_info(osdmap->get_info(peer->osd));
+ if (osd_info.lost_at <= osd_info.up_from) {
+ // If there is even one OSD in might_have_unfound that isn't lost, we
+ // still might retrieve our unfound.
+ return false;
+ }
+ }
+ psdout(10) << "all_unfound_are_queried_or_lost all of might_have_unfound "
+ << might_have_unfound
+ << " have been queried or are marked lost" << dendl;
+ return true;
+}
+
/*------------ Peering State Machine----------------*/
#undef dout_prefix
DECLARE_LOCALS
ps->state_set(PG_STATE_BACKFILL_WAIT);
cancel_backfill();
- if (pg->needs_backfill()) {
+ if (ps->needs_backfill()) {
return transit<WaitLocalBackfillReserved>();
} else {
// raced with MOSDPGBackfill::OP_BACKFILL_FINISH, ignore
DECLARE_LOCALS
- ceph_assert(!pg->needs_recovery());
+ ceph_assert(!ps->needs_recovery());
// if we finished backfill, all acting are active; recheck if
// DEGRADED | UNDERSIZED is appropriate.
uint64_t unfound = ps->missing_loc.num_unfound();
if (unfound > 0 &&
- pg->all_unfound_are_queried_or_lost(ps->get_osdmap())) {
+ ps->all_unfound_are_queried_or_lost(ps->get_osdmap())) {
if (ps->cct->_conf->osd_auto_mark_unfound_lost) {
pl->get_clog().error() << context< PeeringMachine >().spgid.pgid << " has " << unfound
<< " objects unfound and apparently lost, would automatically "
return info;
}
+ bool needs_recovery() const;
+ bool needs_backfill() const;
+ bool all_unfound_are_queried_or_lost(const OSDMapRef osdmap) const;
+ bool all_missing_unfound() const {
+ const auto& missing = pg_log.get_missing();
+ if (!missing.have_missing())
+ return false;
+ for (auto& m : missing.get_items()) {
+ if (!missing_loc.is_unfound(m.first))
+ return false;
+ }
+ return true;
+ }
+
// Flush control interface
private:
void start_flush(ObjectStore::Transaction *t) {
return 0; // make command idempotent
}
- if (!all_unfound_are_queried_or_lost(get_osdmap())) {
+ if (!recovery_state.all_unfound_are_queried_or_lost(get_osdmap())) {
ss << "pg has " << unfound
<< " unfound objects but we haven't probed all sources, not marking lost";
return -EINVAL;
}
if (!missing.have_missing() || // Primary does not have missing
- all_missing_unfound()) { // or all of the missing objects are unfound.
+ // or all of the missing objects are unfound.
+ recovery_state.all_missing_unfound()) {
// Recover the replicas.
started = recover_replicas(max, handle, &recovery_started);
}