REJECT = 2, // replica->primary: sorry, try again later (*)
RELEASE = 3, // primary->replcia: release the slot i reserved before
TOOFULL = 4, // replica->primary: too full, stop backfilling
+ REVOKE = 5, // replica->primary: i'm taking back the slot i gave you
// (*) NOTE: prior to luminous, REJECT was overloaded to also mean release
};
uint32_t type;
case TOOFULL:
out << "TOOFULL ";
break;
+ case REVOKE:
+ out << "REVOKE ";
+ break;
}
out << " pgid: " << pgid << ", query_epoch: " << query_epoch;
if (type == REQUEST) out << ", prio: " << priority;
header.compat_version = 3;
::encode(pgid.pgid, payload);
::encode(query_epoch, payload);
- ::encode((type == RELEASE || type == TOOFULL) ?
+ ::encode((type == RELEASE || type == TOOFULL || type == REVOKE) ?
REJECT : type, payload);
::encode(priority, payload);
::encode(pgid.shard, payload);
m->query_epoch,
m->query_epoch,
PG::RemoteReservationRevokedTooFull()));
+ } else if (m->type == MBackfillReserve::REVOKE) {
+ evt = PG::CephPeeringEvtRef(
+ new PG::CephPeeringEvt(
+ m->query_epoch,
+ m->query_epoch,
+ PG::RemoteReservationRevoked()));
} else {
ceph_abort();
}
return transit<NotBackfilling>();
}
+boost::statechart::result
+PG::RecoveryState::Backfilling::react(const RemoteReservationRevoked &)
+{
+ PG *pg = context< RecoveryMachine >().pg;
+ pg->osd->local_reserver.cancel_reservation(pg->info.pgid);
+ pg->state_set(PG_STATE_BACKFILL_WAIT);
+
+ for (set<pg_shard_t>::iterator it = pg->backfill_targets.begin();
+ it != pg->backfill_targets.end();
+ ++it) {
+ assert(*it != pg->pg_whoami);
+ ConnectionRef con = pg->osd->get_con_osd_cluster(
+ it->osd, pg->get_osdmap()->get_epoch());
+ if (con) {
+ pg->osd->send_message_osd_cluster(
+ new MBackfillReserve(
+ MBackfillReserve::RELEASE,
+ spg_t(pg->info.pgid.pgid, it->shard),
+ pg->get_osdmap()->get_epoch()),
+ con.get());
+ }
+ }
+
+ pg->waiting_on_backfill.clear();
+
+ return transit<WaitLocalBackfillReserved>();
+}
+
void PG::RecoveryState::Backfilling::exit()
{
context< RecoveryMachine >().log_exit(state_name, enter_time);
<< ss.str() << dendl;
post_event(RejectRemoteReservation());
} else {
+ Context *preempt = nullptr;
+ if (HAVE_FEATURE(pg->upacting_features, SERVER_MIMIC)) {
+ // older peers will interpret preemption as TOOFULL
+ preempt = new QueuePeeringEvt<RemoteBackfillPreempted>(
+ pg, pg->get_osdmap()->get_epoch(),
+ RemoteBackfillPreempted());
+ }
pg->osd->remote_reserver.request_reservation(
pg->info.pgid,
new QueuePeeringEvt<RemoteBackfillReserved>(
pg, pg->get_osdmap()->get_epoch(),
- RemoteBackfillReserved()), evt.priority);
+ RemoteBackfillReserved()),
+ evt.priority,
+ preempt);
}
return transit<RepWaitBackfillReserved>();
}
return discard_event();
}
+boost::statechart::result
+PG::RecoveryState::RepRecovering::react(const RemoteBackfillPreempted &)
+{
+ PG *pg = context< RecoveryMachine >().pg;
+ pg->osd->send_message_osd_cluster(
+ pg->primary.osd,
+ new MBackfillReserve(
+ MBackfillReserve::REVOKE,
+ spg_t(pg->info.pgid.pgid, pg->primary.shard),
+ pg->get_osdmap()->get_epoch()),
+ pg->get_osdmap()->get_epoch());
+ return discard_event();
+}
+
void PG::RecoveryState::RepRecovering::exit()
{
context< RecoveryMachine >().log_exit(state_name, enter_time);
public:
TrivialEvent(RemoteReservationRejected)
TrivialEvent(RemoteReservationRevokedTooFull)
+ TrivialEvent(RemoteReservationRevoked)
TrivialEvent(RemoteReservationCanceled)
TrivialEvent(RequestBackfill)
TrivialEvent(RecoveryDone)
protected:
+ TrivialEvent(RemoteBackfillPreempted)
TrivialEvent(BackfillTooFull)
TrivialEvent(RecoveryTooFull)
boost::statechart::custom_reaction< DeferBackfill >,
boost::statechart::custom_reaction< UnfoundBackfill >,
boost::statechart::custom_reaction< RemoteReservationRejected >,
- boost::statechart::custom_reaction< RemoteReservationRevokedTooFull>
+ boost::statechart::custom_reaction< RemoteReservationRevokedTooFull>,
+ boost::statechart::custom_reaction< RemoteReservationRevoked>
> reactions;
explicit Backfilling(my_context ctx);
boost::statechart::result react(const RemoteReservationRejected& evt) {
return discard_event();
}
boost::statechart::result react(const RemoteReservationRevokedTooFull& evt);
+ boost::statechart::result react(const RemoteReservationRevoked& evt);
boost::statechart::result react(const DeferBackfill& evt);
boost::statechart::result react(const UnfoundBackfill& evt);
void exit();
// for compat with old peers
boost::statechart::transition< RemoteReservationRejected, RepNotRecovering >,
boost::statechart::transition< RemoteReservationCanceled, RepNotRecovering >,
- boost::statechart::custom_reaction< BackfillTooFull >
+ boost::statechart::custom_reaction< BackfillTooFull >,
+ boost::statechart::custom_reaction< RemoteBackfillPreempted >
> reactions;
explicit RepRecovering(my_context ctx);
boost::statechart::result react(const BackfillTooFull &evt);
+ boost::statechart::result react(const RemoteBackfillPreempted &evt);
void exit();
};