]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
osd: eval access mode before try_*
authorSage Weil <sage@newdream.net>
Wed, 18 Nov 2009 00:26:33 +0000 (16:26 -0800)
committerSage Weil <sage@newdream.net>
Wed, 18 Nov 2009 00:30:39 +0000 (16:30 -0800)
The problem is the try_* functions may change the mode, but a start_write
may not follow if the op doesn't execute (for any number of reasons).  So
the next time we come around, we may need to reset back to IDLE if
num_wr == 0.  Be careful about the wake flag.

This fixes osd op hangs (particularly after mds restart, and lots of
failed stats on objects during file size/mtime recovery).

src/osd/ReplicatedPG.cc
src/osd/ReplicatedPG.h

index ea88fab7a57833e9ce5c975c18eb6dcbc2206503..0c1db3dc6a4f8f9f4cfa7c8c68c8af1fd96e3598 100644 (file)
@@ -487,6 +487,7 @@ void ReplicatedPG::do_op(MOSDOp *op)
   
   bool ok;
   dout(10) << "do_op mode is " << mode << dendl;
+  assert(!mode.wake);   // we should never have woken waiters here.
   if (op->may_read() && op->may_write())
     ok = mode.try_rmw(client);
   else if (op->may_write())
index 0ca4051182dbdba1cecaa3644c741c839760403d..cdfd023a355e279f407b3e3632956b229845ec61 100644 (file)
@@ -102,7 +102,13 @@ public:
     AccessMode() : state(IDLE),
                   num_wr(0), wake(false) {}
 
+    void check_mode() {
+      if (num_wr == 0)
+       state = IDLE;
+    }
+
     bool try_read(entity_inst_t& c) {
+      check_mode();
       switch (state) {
       case IDLE:
       case DELAYED:
@@ -120,6 +126,7 @@ public:
       }
     }
     bool try_write(entity_inst_t& c) {
+      check_mode();
       switch (state) {
       case IDLE:
        state = DELAYED;
@@ -138,6 +145,7 @@ public:
       }
     }
     bool try_rmw(entity_inst_t& c) {
+      check_mode();
       switch (state) {
       case IDLE:
        state = RMW;
@@ -173,21 +181,10 @@ public:
     void finish_write() {
       assert(num_wr > 0);
       --num_wr;
-      if (num_wr == 0)
-       switch (state) {
-       case DELAYED:
-         state = IDLE;
-         wake = true;
-         break;
-       case RMW:
-       case DELAYED_FLUSHING:
-       case RMW_FLUSHING:
-         state = IDLE;
-         wake = true;
-         break;
-       default:
-         assert(0);
-       }
+      if (num_wr == 0) {
+       state = IDLE;
+       wake = true;
+      }
     }
   };
 
@@ -491,7 +488,11 @@ inline ostream& operator<<(ostream& out, ReplicatedPG::RepGather& repop)
 
 inline ostream& operator<<(ostream& out, ReplicatedPG::AccessMode& mode)
 {
-  return out << mode.get_state_name(mode.state) << "(wr=" << mode.num_wr << ")";    
+  out << mode.get_state_name(mode.state) << "(wr=" << mode.num_wr;
+  if (mode.wake)
+    out << " WAKE";
+  out << ")";
+  return out;
 }
 
 #endif