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: v12.2.12~40^2~2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=883c09fdcda7db276eb0f487cc6c2249c7df94c0;p=ceph.git osd AsyncReserver: Update priority in AsyncReserver for force and cancel-force Fixes: http://tracker.ceph.com/issues/38041 Signed-off-by: David Zafman (cherry picked from commit 11097f1235265a3eb753adc7e6d2818e5902e39e) Conflicts: src/osd/PG.cc (trivial) src/common/AsyncReserver.h (update_priority() assert, lock for luminous) --- diff --git a/src/common/AsyncReserver.h b/src/common/AsyncReserver.h index d5c7a852ddf..6695b7d2993 100644 --- a/src/common/AsyncReserver.h +++ b/src/common/AsyncReserver.h @@ -143,6 +143,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) { + Mutex::Locker 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 + 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; + 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) { Mutex::Locker l(lock); _dump(f); diff --git a/src/osd/PG.cc b/src/osd/PG.cc index f39e4da44e2..7b0e8061763 100644 --- a/src/osd/PG.cc +++ b/src/osd/PG.cc @@ -2155,6 +2155,10 @@ bool PG::set_force_recovery(bool b) } } unlock(); + if (did) { + dout(20) << __func__ << " state " << pgstate_history.get_current_state() << dendl; + osd->local_reserver.update_priority(info.pgid, get_recovery_priority()); + } return did; } @@ -2181,6 +2185,10 @@ bool PG::set_force_backfill(bool b) } } unlock(); + 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 aa69de91a07..fec290eb88c 100644 --- a/src/osd/PG.h +++ b/src/osd/PG.h @@ -122,6 +122,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;