]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
osdc/Objecter: fix op_cancel on homeless session
authorJohn Spray <john.spray@redhat.com>
Mon, 25 Aug 2014 00:16:39 +0000 (01:16 +0100)
committerJohn Spray <john.spray@redhat.com>
Mon, 25 Aug 2014 00:34:20 +0000 (01:34 +0100)
Wrote this block without realizing that op_cancel
takes write lock on session lock, and that operation
is undefined when you already hold the read lock.

Fixes: #9214
Signed-off-by: John Spray <john.spray@redhat.com>
src/osdc/Objecter.cc
src/osdc/Objecter.h

index 80bbf8377de42d07976a10dad92e09a4ee952e3e..e77ea89fca873fe8f0db098cfd1b461f2ab2cd8d 100644 (file)
@@ -1898,11 +1898,19 @@ start:
   }
 
   // Handle case where the op is in homeless session
-  {
-    RWLock::RLocker hs_lc(homeless_session->lock);
-    if (homeless_session->ops.find(tid) != homeless_session->ops.end()) {
-      ret = op_cancel(homeless_session, tid, r);
+  homeless_session->lock.get_read();
+  if (homeless_session->ops.find(tid) != homeless_session->ops.end()) {
+    homeless_session->lock.unlock();
+    ret = op_cancel(homeless_session, tid, r);
+    if (ret == -ENOENT) {
+      /* oh no! raced, maybe tid moved to another session, restarting */
+      goto start;
+    } else {
+      rwlock.unlock();
+      return ret;
     }
+  } else {
+    homeless_session->lock.unlock();
   }
 
   rwlock.unlock();
index 752c55b366d56f53da31f24a9211b82d1401d854..8594f870b83d5766bbbc6eea00575807affe448d 100644 (file)
@@ -1724,7 +1724,10 @@ public:
   void clear_global_op_flag(int flags) { global_op_flags.set(global_op_flags.read() & ~flags); }
 
   /// cancel an in-progress request with the given return code
+private:
   int op_cancel(OSDSession *s, ceph_tid_t tid, int r);
+  friend class C_CancelOp;
+public:
   int op_cancel(ceph_tid_t tid, int r);
 
   // commands