PGs with degraded objects should be higher priority.
Signed-off-by: Samuel Just <sjust@redhat.com>
void OSDService::queue_recovery_context(
PG *pg,
GenContext<ThreadPool::TPHandle&> *c,
- uint64_t cost)
+ uint64_t cost,
+ int priority)
{
epoch_t e = get_osdmap_epoch();
enqueue_back(
OpSchedulerItem(
unique_ptr<OpSchedulerItem::OpQueueable>(
- new PGRecoveryContext(pg->get_pgid(), c, e)),
+ new PGRecoveryContext(pg->get_pgid(), c, e, priority)),
cost_for_queue,
cct->_conf->osd_recovery_priority,
ceph_clock_now(),
new PGRecovery(
p.pg->get_pgid(),
p.epoch_queued,
- reserved_pushes)),
+ reserved_pushes,
+ p.priority)),
cost_for_queue,
cct->_conf->osd_recovery_priority,
ceph_clock_now(),
}
void OSD::do_recovery(
- PG *pg, epoch_t queued, uint64_t reserved_pushes,
+ PG *pg, epoch_t queued, uint64_t reserved_pushes, int priority,
ThreadPool::TPHandle &handle)
{
uint64_t started = 0;
std::lock_guard l(service.sleep_lock);
if (recovery_sleep > 0 && service.recovery_needs_sleep) {
PGRef pgref(pg);
- auto recovery_requeue_callback = new LambdaContext([this, pgref, queued, reserved_pushes](int r) {
+ auto recovery_requeue_callback = new LambdaContext(
+ [this, pgref, queued, reserved_pushes, priority](int r) {
dout(20) << "do_recovery wake up at "
<< ceph_clock_now()
<< ", re-queuing recovery" << dendl;
std::lock_guard l(service.sleep_lock);
service.recovery_needs_sleep = false;
- service.queue_recovery_after_sleep(pgref.get(), queued, reserved_pushes);
+ service.queue_recovery_after_sleep(pgref.get(), queued, reserved_pushes, priority);
});
// This is true for the first recovery op and when the previous recovery op
AsyncReserver<spg_t, Finisher> snap_reserver;
void queue_recovery_context(PG *pg,
GenContext<ThreadPool::TPHandle&> *c,
- uint64_t cost);
+ uint64_t cost,
+ int priority);
void queue_for_snap_trim(PG *pg);
void queue_for_scrub(PG* pg, Scrub::scrub_prio_t with_priority);
const epoch_t epoch_queued;
PGRef pg;
const uint64_t cost_per_object;
+ const int priority;
};
std::list<pg_awaiting_throttle_t> awaiting_throttle;
unsigned get_target_pg_log_entries() const;
// delayed pg activation
- void queue_for_recovery(PG *pg, uint64_t cost_per_object) {
+ void queue_for_recovery(
+ PG *pg, uint64_t cost_per_object,
+ int priority) {
std::lock_guard l(recovery_lock);
if (pg->is_forced_recovery_or_backfill()) {
awaiting_throttle.emplace_front(
pg_awaiting_throttle_t{
- pg->get_osdmap()->get_epoch(), pg, cost_per_object});
+ pg->get_osdmap()->get_epoch(), pg, cost_per_object, priority});
} else {
awaiting_throttle.emplace_back(
pg_awaiting_throttle_t{
- pg->get_osdmap()->get_epoch(), pg, cost_per_object});
+ pg->get_osdmap()->get_epoch(), pg, cost_per_object, priority});
}
_maybe_queue_recovery();
}
- void queue_recovery_after_sleep(PG *pg, epoch_t queued, uint64_t reserved_pushes) {
+ void queue_recovery_after_sleep(
+ PG *pg, epoch_t queued, uint64_t reserved_pushes,
+ int priority) {
std::lock_guard l(recovery_lock);
// Send cost as 1 in pg_awaiting_throttle_t below. The cost is ignored
// as this path is only applicable for WeightedPriorityQueue scheduler.
- _queue_for_recovery(pg_awaiting_throttle_t{queued, pg, 1}, reserved_pushes);
+ _queue_for_recovery(
+ pg_awaiting_throttle_t{queued, pg, 1, priority},
+ reserved_pushes);
}
void queue_check_readable(spg_t spgid,
// -- pg recovery --
void do_recovery(PG *pg, epoch_t epoch_queued, uint64_t pushes_reserved,
+ int priority,
ThreadPool::TPHandle &handle);
1, // ensure objects is non-negative and non-zero
info.stats.stats.sum.num_objects));
uint64_t cost_per_object = std::max<uint64_t>(num_bytes / num_objects, 1);
- osd->queue_for_recovery(this, cost_per_object);
+ osd->queue_for_recovery(
+ this, cost_per_object, recovery_state.get_recovery_op_priority()
+ );
}
}
GenContext<ThreadPool::TPHandle&> *c,
uint64_t cost)
{
- osd->queue_recovery_context(this, c, cost);
+ osd->queue_recovery_context(
+ this, c, cost,
+ recovery_state.get_recovery_op_priority());
}
void PrimaryLogPG::replica_clear_repop_obc(
PGRef& pg,
ThreadPool::TPHandle &handle)
{
- osd->do_recovery(pg.get(), epoch_queued, reserved_pushes, handle);
+ osd->do_recovery(pg.get(), epoch_queued, reserved_pushes, priority, handle);
pg->unlock();
}
class PGRecovery : public PGOpQueueable {
epoch_t epoch_queued;
uint64_t reserved_pushes;
+ int priority;
public:
PGRecovery(
spg_t pg,
epoch_t epoch_queued,
- uint64_t reserved_pushes)
+ uint64_t reserved_pushes,
+ int priority)
: PGOpQueueable(pg),
epoch_queued(epoch_queued),
- reserved_pushes(reserved_pushes) {}
+ reserved_pushes(reserved_pushes),
+ priority(priority) {}
std::ostream &print(std::ostream &rhs) const final {
return rhs << "PGRecovery(pgid=" << get_pgid()
<< " epoch_queued=" << epoch_queued
void run(
OSD *osd, OSDShard *sdata, PGRef& pg, ThreadPool::TPHandle &handle) final;
op_scheduler_class get_scheduler_class() const final {
- return op_scheduler_class::background_recovery;
+ return priority_to_scheduler_class(priority);
}
};
class PGRecoveryContext : public PGOpQueueable {
std::unique_ptr<GenContext<ThreadPool::TPHandle&>> c;
epoch_t epoch;
+ int priority;
public:
PGRecoveryContext(spg_t pgid,
- GenContext<ThreadPool::TPHandle&> *c, epoch_t epoch)
+ GenContext<ThreadPool::TPHandle&> *c, epoch_t epoch,
+ int priority)
: PGOpQueueable(pgid),
- c(c), epoch(epoch) {}
+ c(c), epoch(epoch), priority(priority) {}
std::ostream &print(std::ostream &rhs) const final {
return rhs << "PGRecoveryContext(pgid=" << get_pgid()
<< " c=" << c.get() << " epoch=" << epoch
void run(
OSD *osd, OSDShard *sdata, PGRef& pg, ThreadPool::TPHandle &handle) final;
op_scheduler_class get_scheduler_class() const final {
- return op_scheduler_class::background_recovery;
+ return priority_to_scheduler_class(priority);
}
};