- recovery_wait: waiting for local/remote reservations
- recovering: recovering
+ - recovery_toofull: recovery stopped, OSD(s) above full ratio
- backfill_wait: waiting for remote backfill reservations
- backfilling: backfilling
- backfill_toofull: backfill stopped, OSD(s) above backfillfull ratio
// Seconds to wait before retrying refused backfills
OPTION(osd_backfill_retry_interval, OPT_DOUBLE, 30.0)
+// Seconds to wait before retrying refused recovery
+OPTION(osd_recovery_retry_interval, OPT_DOUBLE, 30.0)
+
// max agent flush ops
OPTION(osd_agent_max_ops, OPT_INT, 4)
OPTION(osd_agent_max_low_ops, OPT_INT, 2)
note["backfilling"] += p->second;
if (p->first & PG_STATE_BACKFILL_TOOFULL)
note["backfill_toofull"] += p->second;
+ if (p->first & PG_STATE_RECOVERY_TOOFULL)
+ note["recovery_toofull"] += p->second;
}
ceph::unordered_map<pg_t, pg_stat_t> stuck_pgs;
PG_STATE_REPAIR |
PG_STATE_RECOVERING |
PG_STATE_RECOVERY_WAIT |
+ PG_STATE_RECOVERY_TOOFULL |
PG_STATE_INCOMPLETE |
PG_STATE_BACKFILL_WAIT |
PG_STATE_BACKFILL |
rs_perf.add_time_avg(rs_down_latency, "down_latency", "Down recovery state latency");
rs_perf.add_time_avg(rs_getmissing_latency, "getmissing_latency", "Getmissing recovery state latency");
rs_perf.add_time_avg(rs_waitupthru_latency, "waitupthru_latency", "Waitupthru recovery state latency");
+ rs_perf.add_time_avg(rs_notrecovering_latency, "notrecovering_latency", "Notrecovering recovery state latency");
recoverystate_perf = rs_perf.create_perf_counters();
cct->get_perfcounters_collection()->add(recoverystate_perf);
rs_down_latency,
rs_getmissing_latency,
rs_waitupthru_latency,
+ rs_notrecovering_latency,
rs_last,
};
RequestBackfill()));
}
+void PG::schedule_recovery_full_retry()
+{
+ Mutex::Locker lock(osd->recovery_request_lock);
+ osd->recovery_request_timer.add_event_after(
+ cct->_conf->osd_recovery_retry_interval,
+ new QueuePeeringEvt<DoRecovery>(
+ this, get_osdmap()->get_epoch(),
+ DoRecovery()));
+}
+
void PG::clear_scrub_reserved()
{
scrubber.reserved_peers.clear();
state_clear(PG_STATE_PEERED);
state_clear(PG_STATE_DOWN);
state_clear(PG_STATE_RECOVERY_WAIT);
+ state_clear(PG_STATE_RECOVERY_TOOFULL);
state_clear(PG_STATE_RECOVERING);
peer_purged.clear();
pg->osd->recoverystate_perf->tinc(rs_notbackfilling_latency, dur);
}
+/*----NotRecovering------*/
+PG::RecoveryState::NotRecovering::NotRecovering(my_context ctx)
+ : my_base(ctx),
+ NamedState(context< RecoveryMachine >().pg->cct, "Started/Primary/Active/NotRecovering")
+{
+ context< RecoveryMachine >().log_enter(state_name);
+ PG *pg = context< RecoveryMachine >().pg;
+ pg->publish_stats_to_osd();
+}
+
+void PG::RecoveryState::NotRecovering::exit()
+{
+ context< RecoveryMachine >().log_exit(state_name, enter_time);
+ PG *pg = context< RecoveryMachine >().pg;
+ utime_t dur = ceph_clock_now() - enter_time;
+ pg->osd->recoverystate_perf->tinc(rs_notrecovering_latency, dur);
+}
+
/*---RepNotRecovering----*/
PG::RecoveryState::RepNotRecovering::RepNotRecovering(my_context ctx)
: my_base(ctx),
PG *pg = context< RecoveryMachine >().pg;
pg->state_clear(PG_STATE_RECOVERY_WAIT);
+ pg->state_clear(PG_STATE_RECOVERY_TOOFULL);
pg->state_set(PG_STATE_RECOVERING);
pg->publish_stats_to_osd();
pg->queue_recovery();
pg->state_clear(PG_STATE_BACKFILL_TOOFULL);
pg->state_clear(PG_STATE_BACKFILL_WAIT);
pg->state_clear(PG_STATE_RECOVERY_WAIT);
+ pg->state_clear(PG_STATE_RECOVERY_TOOFULL);
utime_t dur = ceph_clock_now() - enter_time;
pg->osd->recoverystate_perf->tinc(rs_active_latency, dur);
pg->agent_stop();
void reject_reservation();
void schedule_backfill_full_retry();
+ void schedule_recovery_full_retry();
// -- recovery state --
boost::statechart::result react(const RemoteReservationRejected& evt);
};
+ struct NotRecovering : boost::statechart::state< NotRecovering, Active>, NamedState {
+ typedef boost::mpl::list<
+ boost::statechart::transition< DoRecovery, WaitLocalRecoveryReserved >
+ > reactions;
+ explicit NotRecovering(my_context ctx);
+ void exit();
+ };
+
struct RepNotRecovering;
struct ReplicaActive : boost::statechart::state< ReplicaActive, Started, RepNotRecovering >, NamedState {
explicit ReplicaActive(my_context ctx);
oss << "clean+";
if (state & PG_STATE_RECOVERY_WAIT)
oss << "recovery_wait+";
+ if (state & PG_STATE_RECOVERY_TOOFULL)
+ oss << "recovery_toofull+";
if (state & PG_STATE_RECOVERING)
oss << "recovering+";
if (state & PG_STATE_DOWN)
type = PG_STATE_BACKFILL_TOOFULL;
else if (state == "recovery_wait")
type = PG_STATE_RECOVERY_WAIT;
+ else if (state == "recovery_toofull")
+ type = PG_STATE_RECOVERY_TOOFULL;
else if (state == "undersized")
type = PG_STATE_UNDERSIZED;
else if (state == "activating")
#define PG_STATE_PEERED (1<<25) // peered, cannot go active, can recover
#define PG_STATE_SNAPTRIM (1<<26) // trimming snaps
#define PG_STATE_SNAPTRIM_WAIT (1<<27) // queued to trim snaps
+#define PG_STATE_RECOVERY_TOOFULL (1<<28) // recovery can't proceed: too full
std::string pg_state_string(int state);
std::string pg_vector_string(const vector<int32_t> &a);