]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
osd: requeue pg waiters at the front of the finished queue
authorSage Weil <sage@inktank.com>
Mon, 18 Feb 2013 06:35:50 +0000 (22:35 -0800)
committerSage Weil <sage@inktank.com>
Mon, 25 Feb 2013 23:29:31 +0000 (15:29 -0800)
We could have a sequence like:

- op1
- notify
- op2

in the finished queue.  Op1 gets put on waiting_for_pg, the notify
creates the pg and requeues op1 (and the end), op2 is handled, and
finally op1 is handled.  That breaks ordering; see #2947.

Instead, when we wake up a pg, queue the waiting messages at the front
of the dispatch queue.

Signed-off-by: Sage Weil <sage@inktank.com>
Reviewed-by: Samuel Just <sam.just@inktank.com>
(cherry picked from commit 56c5a07708d52de1699585c9560cff8b4e993d0a)

src/osd/OSD.h

index c3bc0b96839edb2c49b255906baf173c1a6c05a9..3a4e5117af5559a79c4096db65a3f958a60f9124 100644 (file)
@@ -617,6 +617,11 @@ private:
     finished.splice(finished.end(), ls);
     finished_lock.Unlock();
   }
+  void take_waiters_front(list<OpRequestRef>& ls) {
+    finished_lock.Lock();
+    finished.splice(finished.begin(), ls);
+    finished_lock.Unlock();
+  }
   void take_waiter(OpRequestRef op) {
     finished_lock.Lock();
     finished.push_back(op);
@@ -880,7 +885,7 @@ protected:
 
   void wake_pg_waiters(pg_t pgid) {
     if (waiting_for_pg.count(pgid)) {
-      take_waiters(waiting_for_pg[pgid]);
+      take_waiters_front(waiting_for_pg[pgid]);
       waiting_for_pg.erase(pgid);
     }
   }
@@ -888,7 +893,7 @@ protected:
     for (map<pg_t, list<OpRequestRef> >::iterator p = waiting_for_pg.begin();
         p != waiting_for_pg.end();
         p++)
-      take_waiters(p->second);
+      take_waiters_front(p->second);
     waiting_for_pg.clear();
   }