]> git-server-git.apps.pok.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>
Wed, 6 Mar 2019 10:21:12 +0000 (10:21 +0000)
Fixes: http://tracker.ceph.com/issues/38041
Signed-off-by: David Zafman <dzafman@redhat.com>
(cherry picked from commit 11097f1235265a3eb753adc7e6d2818e5902e39e)

Conflicts:
src/osd/PG.cc (trivial)
        src/common/AsyncReserver.h (update_priority() assert, lock for luminous)

src/common/AsyncReserver.h
src/osd/PG.cc
src/osd/PG.h

index d5c7a852ddf145f682d92c1ce0a442264e615563..6695b7d2993555407849884df73d06f457dd4415 100644 (file)
@@ -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);
index f39e4da44e270245f9ee4eef132039e7682bd515..7b0e80617631ec176d00feab7e09e47a2d1abbad 100644 (file)
@@ -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;
 }
 
index aa69de91a076393b4fca3141926cec765f4d26f8..fec290eb88c19e428a0ceea55b4f6ebcd66f4e27 100644 (file)
@@ -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;