return static_cast<unsigned>(ret);
}
+unsigned PG::get_delete_priority()
+{
+ auto state = get_osdmap()->get_state(osd->whoami);
+ if (state & (CEPH_OSD_NEARFULL |
+ CEPH_OSD_FULL)) {
+ return OSD_DELETE_PRIORITY_FULL;
+ } else if (state & CEPH_OSD_BACKFILLFULL) {
+ return OSD_DELETE_PRIORITY_FULLISH;
+ } else {
+ return OSD_DELETE_PRIORITY_NORMAL;
+ }
+}
+
void PG::finish_recovery(list<Context*>& tfin)
{
dout(10) << "finish_recovery" << dendl;
osd->finish_pg_delete(this);
deleted = true;
+
+ // cancel reserver here, since the PG is about to get deleted and the
+ // exit() methods don't run when that happens.
+ osd->local_reserver.cancel_reservation(info.pgid);
}
}
}
-/*--------Deleting----------*/
+/*--------ToDelete----------*/
+PG::RecoveryState::ToDelete::ToDelete(my_context ctx)
+ : my_base(ctx),
+ NamedState(context< RecoveryMachine >().pg, "Started/ToDelete")
+{
+ context< RecoveryMachine >().log_enter(state_name);
+ PG *pg = context< RecoveryMachine >().pg;
+ pg->osd->logger->inc(l_osd_pg_removing);
+}
+
+void PG::RecoveryState::ToDelete::exit()
+{
+ context< RecoveryMachine >().log_exit(state_name, enter_time);
+ PG *pg = context< RecoveryMachine >().pg;
+ pg->osd->logger->dec(l_osd_pg_removing);
+ pg->osd->local_reserver.cancel_reservation(pg->info.pgid);
+}
+
+/*----WaitDeleteReserved----*/
+PG::RecoveryState::WaitDeleteReserved::WaitDeleteReserved(my_context ctx)
+ : my_base(ctx),
+ NamedState(context< RecoveryMachine >().pg,
+ "Started/ToDelete/WaitDeleteReseved")
+{
+ context< RecoveryMachine >().log_enter(state_name);
+ PG *pg = context< RecoveryMachine >().pg;
+ context<ToDelete>().priority = pg->get_delete_priority();
+ pg->osd->local_reserver.cancel_reservation(pg->info.pgid);
+ pg->osd->local_reserver.request_reservation(
+ pg->info.pgid,
+ new QueuePeeringEvt<DeleteReserved>(
+ pg, pg->get_osdmap()->get_epoch(),
+ DeleteReserved()),
+ context<ToDelete>().priority,
+ new QueuePeeringEvt<DeleteInterrupted>(
+ pg, pg->get_osdmap()->get_epoch(),
+ DeleteInterrupted()));
+}
+
+boost::statechart::result PG::RecoveryState::ToDelete::react(
+ const ActMap& evt)
+{
+ PG *pg = context< RecoveryMachine >().pg;
+ if (pg->get_delete_priority() != priority) {
+ ldout(pg->cct,10) << __func__ << " delete priority changed, resetting"
+ << dendl;
+ return transit<ToDelete>();
+ }
+ return discard_event();
+}
+
+void PG::RecoveryState::WaitDeleteReserved::exit()
+{
+ context< RecoveryMachine >().log_exit(state_name, enter_time);
+}
+
+/*----Deleting-----*/
PG::RecoveryState::Deleting::Deleting(my_context ctx)
: my_base(ctx),
- NamedState(context< RecoveryMachine >().pg, "Started/Deleting")
+ NamedState(context< RecoveryMachine >().pg, "Started/ToDelete/Deleting")
{
context< RecoveryMachine >().log_enter(state_name);
PG *pg = context< RecoveryMachine >().pg;
pg->deleting = true;
ObjectStore::Transaction* t = context<RecoveryMachine>().get_cur_transaction();
pg->on_removal(t);
- pg->osd->logger->inc(l_osd_pg_removing);
RecoveryCtx *rctx = context<RecoveryMachine>().get_recovery_ctx();
Context *fin = new C_DeleteMore(pg, pg->get_osdmap()->get_epoch());
rctx->on_applied->contexts.push_back(fin);
rctx->on_safe->contexts.push_back(fin);
}
-boost::statechart::result PG::RecoveryState::Deleting::react(const DeleteSome& evt)
+boost::statechart::result PG::RecoveryState::Deleting::react(
+ const DeleteSome& evt)
{
PG *pg = context< RecoveryMachine >().pg;
pg->_delete_some();
context< RecoveryMachine >().log_exit(state_name, enter_time);
PG *pg = context< RecoveryMachine >().pg;
pg->deleting = false;
- pg->osd->logger->dec(l_osd_pg_removing);
+ pg->osd->local_reserver.cancel_reservation(pg->info.pgid);
}
/*--------GetInfo---------*/
unsigned get_recovery_priority();
/// get backfill reservation priority
unsigned get_backfill_priority();
+ /// get priority for pg deletion
+ unsigned get_delete_priority();
void mark_clean(); ///< mark an active pg clean
TrivialEvent(DeleteStart)
TrivialEvent(DeleteSome)
+ TrivialEvent(DeleteReserved)
+ TrivialEvent(DeleteInterrupted)
/* Encapsulates PG recovery process */
class RecoveryState {
// RepWaitBackfillReserved
// RepWaitRecoveryReserved
// Stray
- // Deleting
+ // ToDelete
+ // WaitDeleteReserved
+ // Deleting
// Crashed
struct Crashed : boost::statechart::state< Crashed, RecoveryMachine >, NamedState {
void exit();
};
- struct Deleting;
+ struct ToDelete;
struct RepNotRecovering;
struct ReplicaActive : boost::statechart::state< ReplicaActive, Started, RepNotRecovering >, NamedState {
explicit ReplicaActive(my_context ctx);
boost::statechart::custom_reaction< UnfoundBackfill >,
boost::statechart::custom_reaction< RemoteBackfillPreempted >,
boost::statechart::custom_reaction< RemoteRecoveryPreempted >,
- boost::statechart::transition<DeleteStart, Deleting>
+ boost::statechart::transition<DeleteStart, ToDelete>
> reactions;
boost::statechart::result react(const QueryState& q);
boost::statechart::result react(const MInfoRec& infoevt);
boost::statechart::custom_reaction< MInfoRec >,
boost::statechart::custom_reaction< ActMap >,
boost::statechart::custom_reaction< RecoveryDone >,
- boost::statechart::transition<DeleteStart, Deleting>
+ boost::statechart::transition<DeleteStart, ToDelete>
> reactions;
boost::statechart::result react(const MQuery& query);
boost::statechart::result react(const MLogRec& logevt);
}
};
- struct Deleting : boost::statechart::state<Deleting, Started>, NamedState {
+ struct WaitDeleteReserved;
+ struct ToDelete : boost::statechart::state<ToDelete, Started, WaitDeleteReserved>, NamedState {
+ unsigned priority = 0;
typedef boost::mpl::list <
boost::statechart::custom_reaction< ActMap >,
boost::statechart::custom_reaction< DeleteSome >
> reactions;
- explicit Deleting(my_context ctx);
- boost::statechart::result react(const ActMap &evt) {
+ explicit ToDelete(my_context ctx);
+ boost::statechart::result react(const ActMap &evt);
+ boost::statechart::result react(const DeleteSome &evt) {
+ // happens if we drop out of Deleting due to reprioritization etc.
return discard_event();
}
+ void exit();
+ };
+
+ struct Deleting;
+ struct WaitDeleteReserved : boost::statechart::state<WaitDeleteReserved,
+ ToDelete>, NamedState {
+ typedef boost::mpl::list <
+ boost::statechart::transition<DeleteReserved, Deleting>
+ > reactions;
+ explicit WaitDeleteReserved(my_context ctx);
+ void exit();
+ };
+
+ struct Deleting : boost::statechart::state<Deleting,
+ ToDelete>, NamedState {
+ typedef boost::mpl::list <
+ boost::statechart::custom_reaction< DeleteSome >,
+ boost::statechart::transition<DeleteInterrupted, WaitDeleteReserved>
+ > reactions;
+ explicit Deleting(my_context ctx);
boost::statechart::result react(const DeleteSome &evt);
void exit();
};