From: John Spray Date: Mon, 25 Aug 2014 00:16:39 +0000 (+0100) Subject: osdc/Objecter: fix op_cancel on homeless session X-Git-Tag: v0.86~213^2~2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=10efe17819bdd70b2324e98b075feeb553122441;p=ceph.git osdc/Objecter: fix op_cancel on homeless session 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 --- diff --git a/src/osdc/Objecter.cc b/src/osdc/Objecter.cc index 80bbf8377de42..e77ea89fca873 100644 --- a/src/osdc/Objecter.cc +++ b/src/osdc/Objecter.cc @@ -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(); diff --git a/src/osdc/Objecter.h b/src/osdc/Objecter.h index 752c55b366d56..8594f870b83d5 100644 --- a/src/osdc/Objecter.h +++ b/src/osdc/Objecter.h @@ -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