CephContext *cct;
OSDriver osdriver;
SnapMapper snap_mapper;
+ bool eio_errors_to_process = false;
virtual PGBackend *get_pgbackend() = 0;
public:
*v = i->second.need;
return true;
}
+ bool is_deleted(const hobject_t &hoid) const {
+ auto i = needs_recovery_map.find(hoid);
+ if (i == needs_recovery_map.end())
+ return false;
+ return i->second.is_delete();
+ }
bool is_unfound(const hobject_t &hoid) const {
- return needs_recovery(hoid) && (
+ return needs_recovery(hoid) && !is_deleted(hoid) && (
!missing_loc.count(hoid) ||
!(*is_recoverable)(missing_loc.find(hoid)->second));
}
if (j == needs_recovery_map.end()) {
needs_recovery_map.insert(*i);
} else {
+ lgeneric_dout(pg->cct, 0) << this << " " << pg->info.pgid << " unexpected need for "
+ << i->first << " have " << j->second
+ << " tried to add " << i->second << dendl;
assert(i->second.need == j->second.need);
}
}
return; // recovered!
needs_recovery_map[hoid] = *item;
+ if (item->is_delete())
+ return;
auto mliter =
missing_loc.insert(make_pair(hoid, set<pg_shard_t>())).first;
assert(info.last_backfill.is_max());
list<OpRequestRef> waiting_for_scrub;
list<OpRequestRef> waiting_for_cache_not_full;
- list<OpRequestRef> waiting_for_all_missing;
+ list<OpRequestRef> waiting_for_clean_to_primary_repair;
map<hobject_t, list<OpRequestRef>> waiting_for_unreadable_object,
waiting_for_degraded_object,
waiting_for_blocked_object;
bool needs_recovery() const;
bool needs_backfill() const;
+ /// clip calculated priority to reasonable range
+ inline int clamp_recovery_priority(int priority);
/// get log recovery reservation priority
unsigned get_recovery_priority();
/// get backfill reservation priority
unsigned get_backfill_priority();
void mark_clean(); ///< mark an active pg clean
+ void _change_recovery_force_mode(int new_mode, bool clear);
/// return [start,end) bounds for required past_intervals
static pair<epoch_t, epoch_t> get_required_past_interval_bounds(
// common to both scrubs
bool active;
- bool queue_snap_trim;
int waiting_on;
set<pg_shard_t> waiting_on_whom;
int shallow_errors;
// clear all state
void reset() {
active = false;
- queue_snap_trim = false;
waiting_on = 0;
waiting_on_whom.clear();
if (active_rep_scrub) {
void scrub_finish();
void scrub_clear_state();
void _scan_snaps(ScrubMap &map);
+ void _repair_oinfo_oid(ScrubMap &map);
void _scan_rollback_obs(
const vector<ghobject_t> &rollback_obs,
ThreadPool::TPHandle &handle);
void handle_scrub_reserve_release(OpRequestRef op);
void reject_reservation();
- void schedule_backfill_full_retry();
- void schedule_recovery_full_retry();
+ void schedule_backfill_retry(float retry);
+ void schedule_recovery_retry(float retry);
// -- recovery state --
*out << #T; \
} \
};
+ struct DeferBackfill : boost::statechart::event<DeferBackfill> {
+ float delay;
+ explicit DeferBackfill(float delay) : delay(delay) {}
+ void print(std::ostream *out) const {
+ *out << "DeferBackfill: delay " << delay;
+ }
+ };
+ struct DeferRecovery : boost::statechart::event<DeferRecovery> {
+ float delay;
+ explicit DeferRecovery(float delay) : delay(delay) {}
+ void print(std::ostream *out) const {
+ *out << "DeferRecovery: delay " << delay;
+ }
+ };
+
TrivialEvent(Initialize)
TrivialEvent(Load)
TrivialEvent(GotInfo)
TrivialEvent(Backfilled)
TrivialEvent(LocalBackfillReserved)
TrivialEvent(RemoteBackfillReserved)
+ TrivialEvent(RejectRemoteReservation)
TrivialEvent(RemoteReservationRejected)
+ TrivialEvent(RemoteReservationCanceled)
TrivialEvent(RequestBackfill)
TrivialEvent(RequestRecovery)
TrivialEvent(RecoveryDone)
TrivialEvent(BackfillTooFull)
TrivialEvent(RecoveryTooFull)
+ TrivialEvent(MakePrimary)
+ TrivialEvent(MakeStray)
+ TrivialEvent(NeedActingChange)
+ TrivialEvent(IsIncomplete)
+ TrivialEvent(IsDown)
+
TrivialEvent(AllReplicasRecovered)
TrivialEvent(DoRecovery)
TrivialEvent(LocalRecoveryReserved)
}
};
- struct MakePrimary : boost::statechart::event< MakePrimary > {
- MakePrimary() : boost::statechart::event< MakePrimary >() {}
- };
- struct MakeStray : boost::statechart::event< MakeStray > {
- MakeStray() : boost::statechart::event< MakeStray >() {}
- };
struct Primary;
struct Stray;
struct Peering;
struct WaitActingChange;
- struct NeedActingChange : boost::statechart::event< NeedActingChange > {
- NeedActingChange() : boost::statechart::event< NeedActingChange >() {}
- };
struct Incomplete;
- struct IsIncomplete : boost::statechart::event< IsIncomplete > {
- IsIncomplete() : boost::statechart::event< IsIncomplete >() {}
- };
struct Down;
- struct IsDown : boost::statechart::event< IsDown > {
- IsDown() : boost::statechart::event< IsDown >() {}
- };
struct Primary : boost::statechart::state< Primary, Started, Peering >, NamedState {
explicit Primary(my_context ctx);
boost::statechart::custom_reaction< MNotifyRec >,
boost::statechart::custom_reaction< MLogRec >,
boost::statechart::custom_reaction< Backfilled >,
- boost::statechart::custom_reaction< AllReplicasActivated >
+ boost::statechart::custom_reaction< AllReplicasActivated >,
+ boost::statechart::custom_reaction< DeferRecovery >,
+ boost::statechart::custom_reaction< DeferBackfill >
> reactions;
boost::statechart::result react(const QueryState& q);
boost::statechart::result react(const ActMap&);
return discard_event();
}
boost::statechart::result react(const AllReplicasActivated&);
+ boost::statechart::result react(const DeferRecovery& evt) {
+ return discard_event();
+ }
+ boost::statechart::result react(const DeferBackfill& evt) {
+ return discard_event();
+ }
};
struct Clean : boost::statechart::state< Clean, Active >, NamedState {
struct Recovered : boost::statechart::state< Recovered, Active >, NamedState {
typedef boost::mpl::list<
boost::statechart::transition< GoClean, Clean >,
+ boost::statechart::transition< DoRecovery, WaitLocalRecoveryReserved >,
boost::statechart::custom_reaction< AllReplicasActivated >
> reactions;
explicit Recovered(my_context ctx);
struct Backfilling : boost::statechart::state< Backfilling, Active >, NamedState {
typedef boost::mpl::list<
boost::statechart::transition< Backfilled, Recovered >,
+ boost::statechart::custom_reaction< DeferBackfill >,
boost::statechart::custom_reaction< RemoteReservationRejected >
> reactions;
explicit Backfilling(my_context ctx);
boost::statechart::result react(const RemoteReservationRejected& evt);
+ boost::statechart::result react(const DeferBackfill& evt);
void exit();
};
struct NotRecovering : boost::statechart::state< NotRecovering, Active>, NamedState {
typedef boost::mpl::list<
- boost::statechart::transition< DoRecovery, WaitLocalRecoveryReserved >
+ boost::statechart::transition< DoRecovery, WaitLocalRecoveryReserved >,
+ boost::statechart::custom_reaction< DeferRecovery >
> reactions;
explicit NotRecovering(my_context ctx);
+ boost::statechart::result react(const DeferRecovery& evt) {
+ /* no-op */
+ return discard_event();
+ }
void exit();
};
boost::statechart::custom_reaction< MQuery >,
boost::statechart::custom_reaction< MInfoRec >,
boost::statechart::custom_reaction< MLogRec >,
- boost::statechart::custom_reaction< Activate >
+ boost::statechart::custom_reaction< Activate >,
+ boost::statechart::custom_reaction< DeferRecovery >,
+ boost::statechart::custom_reaction< DeferBackfill >
> reactions;
boost::statechart::result react(const QueryState& q);
boost::statechart::result react(const MInfoRec& infoevt);
boost::statechart::result react(const ActMap&);
boost::statechart::result react(const MQuery&);
boost::statechart::result react(const Activate&);
+ boost::statechart::result react(const DeferRecovery& evt) {
+ return discard_event();
+ }
+ boost::statechart::result react(const DeferBackfill& evt) {
+ return discard_event();
+ }
};
struct RepRecovering : boost::statechart::state< RepRecovering, ReplicaActive >, NamedState {
typedef boost::mpl::list<
boost::statechart::transition< RecoveryDone, RepNotRecovering >,
+ // for compat with old peers
boost::statechart::transition< RemoteReservationRejected, RepNotRecovering >,
+ boost::statechart::transition< RemoteReservationCanceled, RepNotRecovering >,
boost::statechart::custom_reaction< BackfillTooFull >
> reactions;
explicit RepRecovering(my_context ctx);
struct RepWaitBackfillReserved : boost::statechart::state< RepWaitBackfillReserved, ReplicaActive >, NamedState {
typedef boost::mpl::list<
boost::statechart::custom_reaction< RemoteBackfillReserved >,
- boost::statechart::custom_reaction< RemoteReservationRejected >
+ boost::statechart::custom_reaction< RejectRemoteReservation >,
+ boost::statechart::custom_reaction< RemoteReservationRejected >,
+ boost::statechart::custom_reaction< RemoteReservationCanceled >
> reactions;
explicit RepWaitBackfillReserved(my_context ctx);
void exit();
boost::statechart::result react(const RemoteBackfillReserved &evt);
+ boost::statechart::result react(const RejectRemoteReservation &evt);
boost::statechart::result react(const RemoteReservationRejected &evt);
+ boost::statechart::result react(const RemoteReservationCanceled &evt);
};
struct RepWaitRecoveryReserved : boost::statechart::state< RepWaitRecoveryReserved, ReplicaActive >, NamedState {
typedef boost::mpl::list<
- boost::statechart::custom_reaction< RemoteRecoveryReserved >
+ boost::statechart::custom_reaction< RemoteRecoveryReserved >,
+ // for compat with old peers
+ boost::statechart::custom_reaction< RemoteReservationRejected >,
+ boost::statechart::custom_reaction< RemoteReservationCanceled >
> reactions;
explicit RepWaitRecoveryReserved(my_context ctx);
void exit();
boost::statechart::result react(const RemoteRecoveryReserved &evt);
+ boost::statechart::result react(const RemoteReservationRejected &evt) {
+ // for compat with old peers
+ post_event(RemoteReservationCanceled());
+ return discard_event();
+ }
+ boost::statechart::result react(const RemoteReservationCanceled &evt);
};
struct RepNotRecovering : boost::statechart::state< RepNotRecovering, ReplicaActive>, NamedState {
typedef boost::mpl::list<
boost::statechart::custom_reaction< RequestBackfillPrio >,
boost::statechart::transition< RequestRecovery, RepWaitRecoveryReserved >,
+ boost::statechart::custom_reaction< RejectRemoteReservation >,
+ boost::statechart::transition< RemoteReservationRejected, RepNotRecovering >,
+ boost::statechart::transition< RemoteReservationCanceled, RepNotRecovering >,
boost::statechart::transition< RecoveryDone, RepNotRecovering > // for compat with pre-reservation peers
> reactions;
explicit RepNotRecovering(my_context ctx);
boost::statechart::result react(const RequestBackfillPrio &evt);
+ boost::statechart::result react(const RejectRemoteReservation &evt);
void exit();
};
struct Recovering : boost::statechart::state< Recovering, Active >, NamedState {
typedef boost::mpl::list <
boost::statechart::custom_reaction< AllReplicasRecovered >,
+ boost::statechart::custom_reaction< DeferRecovery >,
boost::statechart::custom_reaction< RequestBackfill >
> reactions;
explicit Recovering(my_context ctx);
void exit();
- void release_reservations();
+ void release_reservations(bool cancel = false);
boost::statechart::result react(const AllReplicasRecovered &evt);
+ boost::statechart::result react(const DeferRecovery& evt);
boost::statechart::result react(const RequestBackfill &evt);
};
uint64_t get_min_acting_features() const { return acting_features; }
uint64_t get_min_upacting_features() const { return upacting_features; }
+ bool perform_deletes_during_peering() const {
+ return !(get_osdmap()->test_flag(CEPH_OSDMAP_RECOVERY_DELETES));
+ }
void init_primary_up_acting(
const vector<int> &newup,
virtual void kick_snap_trim() = 0;
virtual void snap_trimmer_scrub_complete() = 0;
bool requeue_scrub(bool high_priority = false);
- void queue_recovery(bool front = false);
+ void queue_recovery();
bool queue_scrub();
unsigned get_scrub_priority();