]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
osd AsyncReserver: Update priority in AsyncReserver for force and cancel-force
authorDavid Zafman <dzafman@redhat.com>
Sat, 26 Jan 2019 00:04:11 +0000 (16:04 -0800)
committerDavid Zafman <dzafman@redhat.com>
Thu, 7 Feb 2019 23:46:23 +0000 (15:46 -0800)
Fixes: http://tracker.ceph.com/issues/38041
Signed-off-by: David Zafman <dzafman@redhat.com>
src/common/AsyncReserver.h
src/osd/PG.cc
src/osd/PG.h

index c955584b7c051e5f1737a4a53affcc9a27f8e18a..8632a5f0857b41ebe35d9fe5fe8e52b04ab12168 100644 (file)
@@ -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);
index 9a75aab9f6a4a686aecc14eb2926be2282802215..170d772ce285af6071d85311814088586be0bc26 100644 (file)
@@ -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;
 }
 
index 2af6332091fe1af4462b8150dae5dd06c5a0a4a5..d5dcf43ef852eedf79fc95186b5564b29e978979 100644 (file)
@@ -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;