From: David Zafman Date: Sat, 26 Jan 2019 00:04:11 +0000 (-0800) Subject: osd AsyncReserver: Update priority in AsyncReserver for force and cancel-force X-Git-Tag: v14.1.0~182^2~2 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=11097f1235265a3eb753adc7e6d2818e5902e39e;p=ceph-ci.git osd AsyncReserver: Update priority in AsyncReserver for force and cancel-force Fixes: http://tracker.ceph.com/issues/38041 Signed-off-by: David Zafman --- diff --git a/src/common/AsyncReserver.h b/src/common/AsyncReserver.h index c955584b7c0..8632a5f0857 100644 --- a/src/common/AsyncReserver.h +++ b/src/common/AsyncReserver.h @@ -142,6 +142,78 @@ public: do_queues(); } + /** + * Update the priority of a reservation + * + * Note, on_reserved may be called following update_priority. Thus, + * the callback must be safe in that case. Callback will be called + * with no locks held. cancel_reservation must be called to release the + * reservation slot. + * + * Cases + * 1. Item is queued, re-queue with new priority + * 2. Item is queued, re-queue and preempt if new priority higher than an in progress item + * 3. Item is in progress, just adjust priority if no higher priority waiting + * 4. Item is in progress, adjust priority if higher priority items waiting preempt item + * + */ + void update_priority(T item, unsigned newprio) { + std::lock_guard l(lock); + auto i = queue_pointers.find(item); + if (i != queue_pointers.end()) { + unsigned prio = i->second.first; + if (newprio == prio) + return; + Reservation r = *i->second.second; + rdout(10) << __func__ << " update " << r << " (was queued)" << dendl; + // Like cancel_reservation() without preempting + queues[prio].erase(i->second.second); + if (queues[prio].empty()) { + queues.erase(prio); + } + queue_pointers.erase(i); + + // Like request_reservation() to re-queue it but with new priority + ceph_assert(!queue_pointers.count(item) && + !in_progress.count(item)); + r.prio = newprio; + queues[newprio].push_back(r); + queue_pointers.insert(make_pair(item, + make_pair(newprio,--(queues[newprio]).end()))); + } else { + auto p = in_progress.find(item); + if (p != in_progress.end()) { + if (p->second.prio == newprio) + return; + rdout(10) << __func__ << " update " << p->second + << " (in progress)" << dendl; + // We want to preempt if priority goes down + // and smaller then highest priority waiting + if (p->second.preempt) { + if (newprio < p->second.prio && !queues.empty()) { + // choose highest priority queue + auto it = queues.end(); + --it; + ceph_assert(!it->second.empty()); + if (it->first > newprio) { + rdout(10) << __func__ << " update " << p->second + << " lowered priority let do_queues() preempt it" << dendl; + } + } + preempt_by_prio.erase(make_pair(p->second.prio, p->second.item)); + p->second.prio = newprio; + preempt_by_prio.insert(make_pair(p->second.prio, p->second.item)); + } else { + p->second.prio = newprio; + } + } else { + rdout(10) << __func__ << " update " << item << " (not found)" << dendl; + } + } + do_queues(); + return; + } + void dump(Formatter *f) { std::lock_guard l(lock); _dump(f); diff --git a/src/osd/PG.cc b/src/osd/PG.cc index 9a75aab9f6a..170d772ce28 100644 --- a/src/osd/PG.cc +++ b/src/osd/PG.cc @@ -2399,6 +2399,10 @@ bool PG::set_force_recovery(bool b) publish_stats_to_osd(); did = true; } + if (did) { + dout(20) << __func__ << " state " << pgstate_history.get_current_state() << dendl; + osd->local_reserver.update_priority(info.pgid, get_recovery_priority()); + } return did; } @@ -2421,6 +2425,10 @@ bool PG::set_force_backfill(bool b) publish_stats_to_osd(); did = true; } + if (did) { + dout(20) << __func__ << " state " << pgstate_history.get_current_state() << dendl; + osd->local_reserver.update_priority(info.pgid, get_backfill_priority()); + } return did; } diff --git a/src/osd/PG.h b/src/osd/PG.h index 2af6332091f..d5dcf43ef85 100644 --- a/src/osd/PG.h +++ b/src/osd/PG.h @@ -121,6 +121,11 @@ public: void dump(Formatter* f) const; + string get_current_state() { + if (pi == nullptr) return "unknown"; + return std::get<1>(pi->embedded_states.top()); + } + private: bool pg_in_destructor = false; PG* thispg = nullptr;