watch_lock("OSD::watch_lock"),
watch_timer(osd->client_messenger->cct, watch_lock),
watch(NULL),
+ backfill_request_lock("OSD::backfill_request_lock"),
+ backfill_request_timer(g_ceph_context, backfill_request_lock, false),
last_tid(0),
tid_lock("OSDService::tid_lock"),
reserver_finisher(g_ceph_context),
Mutex::Locker lock(osd_lock);
timer.init();
+ service.backfill_request_timer.init();
// mount.
dout(2) << "mounting " << dev_path << " "
timer.shutdown();
+ service.backfill_request_lock.Lock();
+ service.backfill_request_timer.shutdown();
+ service.backfill_request_lock.Unlock();
+
heartbeat_lock.Lock();
heartbeat_stop = true;
heartbeat_cond.Signal();
m->query_epoch,
m->query_epoch,
PG::RemoteBackfillReserved())));
+ } else if (m->type == MBackfillReserve::REJECT) {
+ pg->queue_peering_event(
+ PG::CephPeeringEvtRef(
+ new PG::CephPeeringEvt(
+ m->query_epoch,
+ m->query_epoch,
+ PG::RemoteReservationRejected())));
} else {
assert(0);
}
// make sure CLEAN is marked if we've been clean in this interval
if (info.last_complete == info.last_update &&
+ !state_test(PG_STATE_BACKFILL_TOOFULL) &&
!state_test(PG_STATE_BACKFILL_WAIT) &&
!state_test(PG_STATE_RECOVERING)) {
mark_clean();
dout(10) << "finish_recovery" << dendl;
assert(info.last_complete == info.last_update);
+ state_clear(PG_STATE_BACKFILL_TOOFULL);
state_clear(PG_STATE_BACKFILL_WAIT);
state_clear(PG_STATE_RECOVERING);
pg->state_clear(PG_STATE_BACKFILL);
}
+template <class EVT>
+struct QueuePeeringEvt : Context {
+ boost::intrusive_ptr<PG> pg;
+ epoch_t epoch;
+ EVT evt;
+ QueuePeeringEvt(PG *pg, epoch_t epoch, EVT evt) :
+ pg(pg), epoch(epoch), evt(evt) {}
+ void finish(int r) {
+ pg->lock();
+ pg->queue_peering_event(PG::CephPeeringEvtRef(
+ new PG::CephPeeringEvt(
+ epoch,
+ epoch,
+ evt)));
+ pg->unlock();
+ }
+};
+
/*--WaitRemoteBackfillReserved--*/
PG::RecoveryState::WaitRemoteBackfillReserved::WaitRemoteBackfillReserved(my_context ctx)
context< RecoveryMachine >().log_exit(state_name, enter_time);
}
+boost::statechart::result
+PG::RecoveryState::WaitRemoteBackfillReserved::react(const RemoteBackfillReserved &evt)
+{
+ PG *pg = context< RecoveryMachine >().pg;
+ pg->state_clear(PG_STATE_BACKFILL_TOOFULL);
+ return transit<Backfilling>();
+}
-/*--WaitLocalBackfillReserved--*/
-template <class EVT>
-struct C_QueuePeeringEvt : Context {
- boost::intrusive_ptr<PG> pg;
- epoch_t epoch;
- EVT evt;
- C_QueuePeeringEvt(PG *pg, epoch_t epoch, EVT evt) :
- pg(pg), epoch(epoch), evt(evt) {}
- void finish(int r) {
- pg->lock();
- pg->queue_peering_event(PG::CephPeeringEvtRef(
- new PG::CephPeeringEvt(
- epoch,
- epoch,
- evt)));
- pg->unlock();
- }
-};
+boost::statechart::result
+PG::RecoveryState::WaitRemoteBackfillReserved::react(const RemoteReservationRejected &evt)
+{
+ PG *pg = context< RecoveryMachine >().pg;
+ pg->osd->local_reserver.cancel_reservation(pg->info.pgid);
+ pg->state_clear(PG_STATE_BACKFILL_WAIT);
+ pg->state_set(PG_STATE_BACKFILL_TOOFULL);
+
+ Mutex::Locker lock(pg->osd->backfill_request_lock);
+ pg->osd->backfill_request_timer.add_event_after(
+ g_conf->osd_backfill_retry_interval,
+ new QueuePeeringEvt<RequestBackfill>(
+ pg, pg->get_osdmap()->get_epoch(),
+ RequestBackfill()));
+ return transit<NotBackfilling>();
+}
+
+/*--WaitLocalBackfillReserved--*/
PG::RecoveryState::WaitLocalBackfillReserved::WaitLocalBackfillReserved(my_context ctx)
: my_base(ctx)
{
PG *pg = context< RecoveryMachine >().pg;
pg->osd->local_reserver.request_reservation(
pg->info.pgid,
- new C_QueuePeeringEvt<LocalBackfillReserved>(
+ new QueuePeeringEvt<LocalBackfillReserved>(
pg, pg->get_osdmap()->get_epoch(),
LocalBackfillReserved()));
}
state_name = "Started/Primary/Active/RepWaitBackfillReserved";
context< RecoveryMachine >().log_enter(state_name);
PG *pg = context< RecoveryMachine >().pg;
- pg->osd->remote_reserver.request_reservation(
- pg->info.pgid,
- new C_QueuePeeringEvt<RemoteBackfillReserved>(
- pg, pg->get_osdmap()->get_epoch(),
- RemoteBackfillReserved()));
+
+ int64_t kb = pg->osd->osd->osd_stat.kb,
+ kb_used = pg->osd->osd->osd_stat.kb_used;
+ int64_t max = kb * g_conf->osd_backfill_full_ratio;
+ if (kb_used >= max) {
+ dout(10) << "backfill reservation rejected: kb used >= max: "
+ << kb_used << " >= " << max << dendl;
+ post_event(RemoteReservationRejected());
+ } else {
+ pg->osd->remote_reserver.request_reservation(
+ pg->info.pgid,
+ new QueuePeeringEvt<RemoteBackfillReserved>(
+ pg, pg->get_osdmap()->get_epoch(),
+ RemoteBackfillReserved()));
+ }
}
void PG::RecoveryState::RepWaitBackfillReserved::exit()
return transit<RepBackfilling>();
}
+boost::statechart::result
+PG::RecoveryState::RepWaitBackfillReserved::react(const RemoteReservationRejected &evt)
+{
+ PG *pg = context< RecoveryMachine >().pg;
+ pg->osd->cluster_messenger->send_message(
+ new MBackfillReserve(
+ MBackfillReserve::REJECT,
+ pg->info.pgid,
+ pg->get_osdmap()->get_epoch()),
+ pg->get_osdmap()->get_cluster_inst(pg->acting[0]));
+ return transit<RepNotBackfilling>();
+}
+
/*---RepBackfilling-------*/
PG::RecoveryState::RepBackfilling::RepBackfilling(my_context ctx)
: my_base(ctx)
int newest_update_osd;
+ pg->state_clear(PG_STATE_BACKFILL_TOOFULL);
pg->state_clear(PG_STATE_BACKFILL_WAIT);
pg->state_clear(PG_STATE_RECOVERING);
pg->backfill_reserved = false;
pg->backfill_reserving = false;
pg->state_clear(PG_STATE_DEGRADED);
+ pg->state_clear(PG_STATE_BACKFILL_TOOFULL);
pg->state_clear(PG_STATE_BACKFILL_WAIT);
pg->state_clear(PG_STATE_REPLAY);
}
TrivialEvent(Backfilled)
TrivialEvent(LocalBackfillReserved)
TrivialEvent(RemoteBackfillReserved)
+ TrivialEvent(RemoteReservationRejected)
TrivialEvent(RequestBackfill)
/* Encapsulates PG recovery process */
struct WaitRemoteBackfillReserved : boost::statechart::state< WaitRemoteBackfillReserved, Active >, NamedState {
typedef boost::mpl::list<
- boost::statechart::transition< RemoteBackfillReserved, Backfilling >
+ boost::statechart::custom_reaction< RemoteBackfillReserved >,
+ boost::statechart::custom_reaction< RemoteReservationRejected >
> reactions;
WaitRemoteBackfillReserved(my_context ctx);
void exit();
+ boost::statechart::result react(const RemoteBackfillReserved& evt);
+ boost::statechart::result react(const RemoteReservationRejected& evt);
};
struct WaitLocalBackfillReserved : boost::statechart::state< WaitLocalBackfillReserved, Active >, NamedState {
struct RepWaitBackfillReserved : boost::statechart::state< RepWaitBackfillReserved, ReplicaActive >, NamedState {
typedef boost::mpl::list<
- boost::statechart::custom_reaction< RemoteBackfillReserved >
+ boost::statechart::custom_reaction< RemoteBackfillReserved >,
+ boost::statechart::custom_reaction< RemoteReservationRejected >
> reactions;
RepWaitBackfillReserved(my_context ctx);
void exit();
boost::statechart::result react(const RemoteBackfillReserved &evt);
+ boost::statechart::result react(const RemoteReservationRejected &evt);
};
struct RepNotBackfilling : boost::statechart::state< RepNotBackfilling, ReplicaActive>, NamedState {