]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rbd: Changed exclusive-lock implementation to use the new managed-lock
authorRicardo Dias <rdias@suse.com>
Fri, 4 Nov 2016 02:34:39 +0000 (02:34 +0000)
committerJason Dillaman <dillaman@redhat.com>
Tue, 3 Jan 2017 14:21:45 +0000 (09:21 -0500)
Fixes: http://tracker.ceph.com/issues/17016
Signed-off-by: Ricardo Dias <rdias@suse.com>
36 files changed:
src/librbd/AioImageRequestWQ.cc
src/librbd/CMakeLists.txt
src/librbd/ExclusiveLock.cc
src/librbd/ExclusiveLock.h
src/librbd/Operations.cc
src/librbd/exclusive_lock/AcquireRequest.cc [deleted file]
src/librbd/exclusive_lock/AcquireRequest.h [deleted file]
src/librbd/exclusive_lock/PostAcquireRequest.cc [new file with mode: 0644]
src/librbd/exclusive_lock/PostAcquireRequest.h [new file with mode: 0644]
src/librbd/exclusive_lock/PreAcquireRequest.cc [new file with mode: 0644]
src/librbd/exclusive_lock/PreAcquireRequest.h [new file with mode: 0644]
src/librbd/exclusive_lock/PreReleaseRequest.cc [new file with mode: 0644]
src/librbd/exclusive_lock/PreReleaseRequest.h [new file with mode: 0644]
src/librbd/exclusive_lock/ReacquireRequest.cc [deleted file]
src/librbd/exclusive_lock/ReacquireRequest.h [deleted file]
src/librbd/exclusive_lock/ReleaseRequest.cc [deleted file]
src/librbd/exclusive_lock/ReleaseRequest.h [deleted file]
src/librbd/internal.cc
src/librbd/managed_lock/AcquireRequest.cc
src/librbd/operation/DisableFeaturesRequest.cc
src/test/librbd/CMakeLists.txt
src/test/librbd/exclusive_lock/test_mock_AcquireRequest.cc [deleted file]
src/test/librbd/exclusive_lock/test_mock_PostAcquireRequest.cc [new file with mode: 0644]
src/test/librbd/exclusive_lock/test_mock_PreAcquireRequest.cc [new file with mode: 0644]
src/test/librbd/exclusive_lock/test_mock_PreReleaseRequest.cc [new file with mode: 0644]
src/test/librbd/exclusive_lock/test_mock_ReacquireRequest.cc [deleted file]
src/test/librbd/exclusive_lock/test_mock_ReleaseRequest.cc [deleted file]
src/test/librbd/journal/test_Replay.cc
src/test/librbd/mock/MockExclusiveLock.h
src/test/librbd/test_ImageWatcher.cc
src/test/librbd/test_ObjectMap.cc
src/test/librbd/test_internal.cc
src/test/librbd/test_mock_ExclusiveLock.cc
src/test/rbd_mirror/test_ImageReplayer.cc
src/test/rbd_mirror/test_ImageSync.cc
src/tools/rbd_mirror/image_replayer/OpenLocalImageRequest.cc

index 8565932924e7f8ad4f686b2e0b48d67a24e27b3f..91b3dc784c8b09a5c0dbd0f7e1147d5e6fe06dbf 100644 (file)
@@ -460,7 +460,7 @@ void AioImageRequestWQ::queue(AioImageRequest<> *req) {
   ThreadPool::PointerWQ<AioImageRequest<> >::queue(req);
 
   if (lock_required) {
-    m_image_ctx.exclusive_lock->request_lock(nullptr);
+    m_image_ctx.exclusive_lock->acquire_lock(nullptr);
   }
 }
 
@@ -487,7 +487,7 @@ void AioImageRequestWQ::handle_refreshed(int r, AioImageRequest<> *req) {
   // we acquire the lock
   RWLock::RLocker owner_locker(m_image_ctx.owner_lock);
   if (is_lock_required() && is_lock_request_needed()) {
-    m_image_ctx.exclusive_lock->request_lock(nullptr);
+    m_image_ctx.exclusive_lock->acquire_lock(nullptr);
   }
 }
 
index ff58d68eb169ba7e36963e701bb6c0430064c6ef..cb72553b2ccd29a19e6d3ddc0681bd56b6fbe6f9 100644 (file)
@@ -35,10 +35,10 @@ set(librbd_internal_srcs
   managed_lock/ReleaseRequest.cc
   managed_lock/ReacquireRequest.cc
   ManagedLock.cc
-  exclusive_lock/AcquireRequest.cc
+  exclusive_lock/PreAcquireRequest.cc
+  exclusive_lock/PostAcquireRequest.cc
+  exclusive_lock/PreReleaseRequest.cc
   exclusive_lock/AutomaticPolicy.cc
-  exclusive_lock/ReacquireRequest.cc
-  exclusive_lock/ReleaseRequest.cc
   exclusive_lock/StandardPolicy.cc
   image/CloseRequest.cc
   image/CreateRequest.cc
index 58fc21e78a0891a014696d49362d1eabe528d803..f0eed9c03ee1e8ab96e67e6401eab987fc17459b 100644 (file)
 // vim: ts=8 sw=2 smarttab
 
 #include "librbd/ExclusiveLock.h"
-#include "cls/lock/cls_lock_client.h"
-#include "common/dout.h"
-#include "common/errno.h"
 #include "librbd/AioImageRequestWQ.h"
-#include "librbd/ImageCtx.h"
-#include "librbd/ImageState.h"
 #include "librbd/ImageWatcher.h"
+#include "librbd/ImageState.h"
+#include "librbd/exclusive_lock/PreAcquireRequest.h"
+#include "librbd/exclusive_lock/PostAcquireRequest.h"
+#include "librbd/exclusive_lock/PreReleaseRequest.h"
 #include "librbd/Utils.h"
-#include "librbd/exclusive_lock/AcquireRequest.h"
-#include "librbd/exclusive_lock/ReacquireRequest.h"
-#include "librbd/exclusive_lock/ReleaseRequest.h"
-#include <sstream>
+#include "common/Mutex.h"
+#include "common/dout.h"
 
 #define dout_subsys ceph_subsys_rbd
 #undef dout_prefix
-#define dout_prefix *_dout << "librbd::ExclusiveLock: "
+#define dout_prefix *_dout << "librbd::ExclusiveLock: " << this << " " <<  __func__
 
 namespace librbd {
 
 using namespace exclusive_lock;
 
-namespace {
-
-const std::string WATCHER_LOCK_COOKIE_PREFIX = "auto";
-
-template <typename R>
-struct C_SendRequest : public Context {
-  R* request;
-  explicit C_SendRequest(R* request) : request(request) {
-  }
-  virtual void finish(int r) override {
-    request->send();
-  }
-};
-
-} // anonymous namespace
-
 template <typename I>
-const std::string ExclusiveLock<I>::WATCHER_LOCK_TAG("internal");
+using ML = ManagedLock<I>;
 
 template <typename I>
 ExclusiveLock<I>::ExclusiveLock(I &image_ctx)
-  : m_image_ctx(image_ctx),
-    m_lock(util::unique_lock_name("librbd::ExclusiveLock::m_lock", this)),
-    m_state(STATE_UNINITIALIZED), m_watch_handle(0) {
-}
-
-template <typename I>
-ExclusiveLock<I>::~ExclusiveLock() {
-  assert(m_state == STATE_UNINITIALIZED || m_state == STATE_SHUTDOWN);
-}
-
-template <typename I>
-bool ExclusiveLock<I>::is_lock_owner() const {
-  Mutex::Locker locker(m_lock);
-
-  bool lock_owner;
-  switch (m_state) {
-  case STATE_LOCKED:
-  case STATE_POST_ACQUIRING:
-  case STATE_REACQUIRING:
-  case STATE_PRE_RELEASING:
-  case STATE_PRE_SHUTTING_DOWN:
-    lock_owner = true;
-    break;
-  default:
-    lock_owner = false;
-    break;
-  }
-
-  ldout(m_image_ctx.cct, 20) << this << " " << __func__ << "=" << lock_owner
-                             << dendl;
-  return lock_owner;
+  : ML<I>(image_ctx.md_ctx, image_ctx.op_work_queue, image_ctx.header_oid,
+          image_ctx.image_watcher),
+    m_image_ctx(image_ctx), m_pre_post_callback(nullptr),
+    m_shutting_down(false)  {
+  ML<I>::m_state = ML<I>::STATE_UNINITIALIZED;
 }
 
 template <typename I>
 bool ExclusiveLock<I>::accept_requests(int *ret_val) const {
-  Mutex::Locker locker(m_lock);
+  Mutex::Locker locker(ML<I>::m_lock);
 
-  bool accept_requests = (!is_shutdown() && m_state == STATE_LOCKED &&
+  bool accept_requests = (!ML<I>::is_shutdown_locked() &&
+                          ML<I>::m_state == ML<I>::STATE_LOCKED &&
                           m_request_blocked_count == 0);
   *ret_val = m_request_blocked_ret_val;
 
-  ldout(m_image_ctx.cct, 20) << this << " " << __func__ << "="
-                             << accept_requests << dendl;
+  ldout(m_image_ctx.cct, 20) << "=" << accept_requests << dendl;
   return accept_requests;
 }
 
 template <typename I>
 void ExclusiveLock<I>::block_requests(int r) {
-  Mutex::Locker locker(m_lock);
+  Mutex::Locker locker(ML<I>::m_lock);
+
   m_request_blocked_count++;
   if (m_request_blocked_ret_val == 0) {
     m_request_blocked_ret_val = r;
   }
 
-  ldout(m_image_ctx.cct, 20) << this << " " << __func__ << dendl;
+  ldout(m_image_ctx.cct, 20) << dendl;
 }
 
 template <typename I>
 void ExclusiveLock<I>::unblock_requests() {
-  Mutex::Locker locker(m_lock);
+  Mutex::Locker locker(ML<I>::m_lock);
+
   assert(m_request_blocked_count > 0);
   m_request_blocked_count--;
   if (m_request_blocked_count == 0) {
     m_request_blocked_ret_val = 0;
   }
 
-  ldout(m_image_ctx.cct, 20) << this << " " << __func__ << dendl;
+  ldout(m_image_ctx.cct, 20) << dendl;
 }
 
 template <typename I>
 void ExclusiveLock<I>::init(uint64_t features, Context *on_init) {
   assert(m_image_ctx.owner_lock.is_locked());
-  ldout(m_image_ctx.cct, 10) << this << " " << __func__ << dendl;
+  ldout(m_image_ctx.cct, 10) << dendl;
 
   {
-    Mutex::Locker locker(m_lock);
-    assert(m_state == STATE_UNINITIALIZED);
-    m_state = STATE_INITIALIZING;
+    Mutex::Locker locker(ML<I>::m_lock);
+    assert(ML<I>::m_state == ML<I>::STATE_UNINITIALIZED);
+    ML<I>::m_state = ML<I>::STATE_INITIALIZING;
   }
 
   m_image_ctx.aio_work_queue->block_writes(new C_InitComplete(this, on_init));
@@ -132,602 +89,210 @@ void ExclusiveLock<I>::init(uint64_t features, Context *on_init) {
 
 template <typename I>
 void ExclusiveLock<I>::shut_down(Context *on_shut_down) {
-  ldout(m_image_ctx.cct, 10) << this << " " << __func__ << dendl;
+  ldout(m_image_ctx.cct, 10) << dendl;
 
-  {
-    Mutex::Locker locker(m_lock);
-    assert(!is_shutdown());
-    execute_action(ACTION_SHUT_DOWN, on_shut_down);
-  }
+  ML<I>::shut_down(on_shut_down);
 
   // if stalled in request state machine -- abort
   handle_peer_notification();
 }
 
-template <typename I>
-void ExclusiveLock<I>::try_lock(Context *on_tried_lock) {
-  int r = 0;
-  {
-    Mutex::Locker locker(m_lock);
-    assert(m_image_ctx.owner_lock.is_locked());
-    if (is_shutdown()) {
-      r = -ESHUTDOWN;
-    } else if (m_state != STATE_LOCKED || !m_actions_contexts.empty()) {
-      ldout(m_image_ctx.cct, 10) << this << " " << __func__ << dendl;
-      execute_action(ACTION_TRY_LOCK, on_tried_lock);
-      return;
-    }
-  }
-
-  on_tried_lock->complete(r);
-}
-
-template <typename I>
-void ExclusiveLock<I>::request_lock(Context *on_locked) {
-  int r = 0;
-  {
-    Mutex::Locker locker(m_lock);
-    assert(m_image_ctx.owner_lock.is_locked());
-    if (is_shutdown()) {
-      r = -ESHUTDOWN;
-    } else if (m_state != STATE_LOCKED || !m_actions_contexts.empty()) {
-      ldout(m_image_ctx.cct, 10) << this << " " << __func__ << dendl;
-      execute_action(ACTION_REQUEST_LOCK, on_locked);
-      return;
-    }
-  }
-
-  if (on_locked != nullptr) {
-    on_locked->complete(r);
-  }
-}
-
-template <typename I>
-void ExclusiveLock<I>::release_lock(Context *on_released) {
-  int r = 0;
-  {
-    Mutex::Locker locker(m_lock);
-    assert(m_image_ctx.owner_lock.is_locked());
-    if (is_shutdown()) {
-      r = -ESHUTDOWN;
-    } else if (m_state != STATE_UNLOCKED || !m_actions_contexts.empty()) {
-      ldout(m_image_ctx.cct, 10) << this << " " << __func__ << dendl;
-      execute_action(ACTION_RELEASE_LOCK, on_released);
-      return;
-    }
-  }
-
-  on_released->complete(r);
-}
-
-template <typename I>
-void ExclusiveLock<I>::reacquire_lock(Context *on_reacquired) {
-  {
-    Mutex::Locker locker(m_lock);
-    assert(m_image_ctx.owner_lock.is_locked());
-
-    if (m_state == STATE_WAITING_FOR_REGISTER) {
-      // restart the acquire lock process now that watch is valid
-      ldout(m_image_ctx.cct, 10) << this << " " << __func__ << ": "
-                                 << "woke up waiting acquire" << dendl;
-      Action active_action = get_active_action();
-      assert(active_action == ACTION_TRY_LOCK ||
-             active_action == ACTION_REQUEST_LOCK);
-      execute_next_action();
-    } else if (!is_shutdown() &&
-               (m_state == STATE_LOCKED ||
-                m_state == STATE_ACQUIRING ||
-                m_state == STATE_POST_ACQUIRING ||
-                m_state == STATE_WAITING_FOR_PEER)) {
-      // interlock the lock operation with other image state ops
-      ldout(m_image_ctx.cct, 10) << this << " " << __func__ << dendl;
-      execute_action(ACTION_REACQUIRE_LOCK, on_reacquired);
-      return;
-    }
-  }
-
-  // ignore request if shutdown or not in a locked-related state
-  if (on_reacquired != nullptr) {
-    on_reacquired->complete(0);
-  }
-}
-
 template <typename I>
 void ExclusiveLock<I>::handle_peer_notification() {
-  Mutex::Locker locker(m_lock);
-  if (m_state != STATE_WAITING_FOR_PEER) {
+  Mutex::Locker locker(ML<I>::m_lock);
+  if (ML<I>::m_state != ML<I>::STATE_WAITING_FOR_LOCK) {
     return;
   }
 
-  ldout(m_image_ctx.cct, 10) << this << " " << __func__ << dendl;
-  assert(get_active_action() == ACTION_REQUEST_LOCK);
-  execute_next_action();
+  ldout(m_image_ctx.cct, 10) << dendl;
+  assert(ML<I>::get_active_action() == ML<I>::ACTION_ACQUIRE_LOCK);
+  ML<I>::execute_next_action();
 }
 
 template <typename I>
-std::string ExclusiveLock<I>::encode_lock_cookie() const {
-  assert(m_lock.is_locked());
-
-  assert(m_watch_handle != 0);
-  std::ostringstream ss;
-  ss << WATCHER_LOCK_COOKIE_PREFIX << " " << m_watch_handle;
-  return ss.str();
-}
-
-template <typename I>
-bool ExclusiveLock<I>::decode_lock_cookie(const std::string &tag,
-                                          uint64_t *handle) {
-  std::string prefix;
-  std::istringstream ss(tag);
-  if (!(ss >> prefix >> *handle) || prefix != WATCHER_LOCK_COOKIE_PREFIX) {
-    return false;
-  }
-  return true;
-}
+void ExclusiveLock<I>::handle_init_complete() {
+  ldout(m_image_ctx.cct, 10) << dendl;
 
-template <typename I>
-bool ExclusiveLock<I>::is_transition_state() const {
-  switch (m_state) {
-  case STATE_INITIALIZING:
-  case STATE_ACQUIRING:
-  case STATE_WAITING_FOR_PEER:
-  case STATE_WAITING_FOR_REGISTER:
-  case STATE_POST_ACQUIRING:
-  case STATE_REACQUIRING:
-  case STATE_PRE_RELEASING:
-  case STATE_RELEASING:
-  case STATE_PRE_SHUTTING_DOWN:
-  case STATE_SHUTTING_DOWN:
-    return true;
-  case STATE_UNINITIALIZED:
-  case STATE_UNLOCKED:
-  case STATE_LOCKED:
-  case STATE_SHUTDOWN:
-    break;
-  }
-  return false;
+  Mutex::Locker locker(ML<I>::m_lock);
+  ML<I>::m_state = ML<I>::STATE_UNLOCKED;
 }
 
 template <typename I>
-void ExclusiveLock<I>::append_context(Action action, Context *ctx) {
-  assert(m_lock.is_locked());
-
-  for (auto &action_ctxs : m_actions_contexts) {
-    if (action == action_ctxs.first) {
-      if (ctx != nullptr) {
-        action_ctxs.second.push_back(ctx);
-      }
-      return;
-    }
-  }
-
-  Contexts contexts;
-  if (ctx != nullptr) {
-    contexts.push_back(ctx);
-  }
-  m_actions_contexts.push_back({action, std::move(contexts)});
-}
+void ExclusiveLock<I>::shutdown_handler(int r, Context *on_finish) {
+  ldout(m_image_ctx.cct, 10) << dendl;
 
-template <typename I>
-void ExclusiveLock<I>::execute_action(Action action, Context *ctx) {
-  assert(m_lock.is_locked());
-
-  append_context(action, ctx);
-  if (!is_transition_state()) {
-    execute_next_action();
+  {
+    RWLock::WLocker owner_locker(m_image_ctx.owner_lock);
+    m_image_ctx.aio_work_queue->clear_require_lock_on_read();
+    m_image_ctx.exclusive_lock = nullptr;
   }
-}
 
-template <typename I>
-void ExclusiveLock<I>::execute_next_action() {
-  assert(m_lock.is_locked());
-  assert(!m_actions_contexts.empty());
-  switch (get_active_action()) {
-  case ACTION_TRY_LOCK:
-  case ACTION_REQUEST_LOCK:
-    send_acquire_lock();
-    break;
-  case ACTION_REACQUIRE_LOCK:
-    send_reacquire_lock();
-    break;
-  case ACTION_RELEASE_LOCK:
-    send_release_lock();
-    break;
-  case ACTION_SHUT_DOWN:
-    send_shutdown();
-    break;
-  default:
-    assert(false);
-    break;
-  }
+  m_image_ctx.aio_work_queue->unblock_writes();
+  m_image_ctx.image_watcher->flush(on_finish);
 }
 
 template <typename I>
-typename ExclusiveLock<I>::Action ExclusiveLock<I>::get_active_action() const {
-  assert(m_lock.is_locked());
-  assert(!m_actions_contexts.empty());
-  return m_actions_contexts.front().first;
+void ExclusiveLock<I>::pre_acquire_lock_handler(Context *on_finish) {
+  PreAcquireRequest<I> *req = PreAcquireRequest<I>::create(m_image_ctx,
+                                                           on_finish);
+  m_image_ctx.op_work_queue->queue(new FunctionContext([req](int r) {
+    req->send();
+  }));
 }
 
 template <typename I>
-void ExclusiveLock<I>::complete_active_action(State next_state, int r) {
-  assert(m_lock.is_locked());
-  assert(!m_actions_contexts.empty());
-
-  ActionContexts action_contexts(std::move(m_actions_contexts.front()));
-  m_actions_contexts.pop_front();
-  m_state = next_state;
-
-  m_lock.Unlock();
-  for (auto ctx : action_contexts.second) {
-    ctx->complete(r);
-  }
-  m_lock.Lock();
+void ExclusiveLock<I>::post_acquire_lock_handler(int r, Context *on_finish) {
+  ldout(m_image_ctx.cct, 10) << ": r=" << r << dendl;
 
-  if (!is_transition_state() && !m_actions_contexts.empty()) {
-    execute_next_action();
-  }
-}
 
-template <typename I>
-bool ExclusiveLock<I>::is_shutdown() const {
-  assert(m_lock.is_locked());
+  if (r < 0) {
+    ML<I>::m_lock.Lock();
+    assert(ML<I>::m_state == ML<I>::STATE_ACQUIRING);
 
-  return ((m_state == STATE_SHUTDOWN) ||
-          (!m_actions_contexts.empty() &&
-           m_actions_contexts.back().first == ACTION_SHUT_DOWN));
-}
+    // PostAcquire state machine will not run, so we need complete prepare
+    m_image_ctx.state->handle_prepare_lock_complete();
 
-template <typename I>
-void ExclusiveLock<I>::handle_init_complete() {
-  ldout(m_image_ctx.cct, 10) << this << " " << __func__ << dendl;
+    typename ML<I>::Action action = ML<I>::get_active_action();
+    if (action == ML<I>::ACTION_ACQUIRE_LOCK && r < 0 && r != -EBLACKLISTED) {
+      ML<I>::m_state = ML<I>::STATE_WAITING_FOR_LOCK;
+      ML<I>::m_lock.Unlock();
 
-  Mutex::Locker locker(m_lock);
-  m_state = STATE_UNLOCKED;
-}
+      // request the lock from a peer
+      m_image_ctx.image_watcher->notify_request_lock();
 
-template <typename I>
-void ExclusiveLock<I>::send_acquire_lock() {
-  assert(m_lock.is_locked());
-  if (m_state == STATE_LOCKED) {
-    complete_active_action(STATE_LOCKED, 0);
-    return;
-  }
+      return;
+    }
 
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << this << " " << __func__ << dendl;
-  m_state = STATE_ACQUIRING;
+    ML<I>::m_lock.Unlock();
+    if (r == -EAGAIN) {
+      r = 0;
+    }
 
-  m_watch_handle = m_image_ctx.image_watcher->get_watch_handle();
-  if (m_watch_handle == 0) {
-    lderr(cct) << "image watcher not registered - delaying request" << dendl;
-    m_state = STATE_WAITING_FOR_REGISTER;
+    on_finish->complete(r);
     return;
   }
 
-  m_cookie = encode_lock_cookie();
+  Mutex::Locker locker(ML<I>::m_lock);
+  m_pre_post_callback = on_finish;
+  using EL = ExclusiveLock<I>;
+  PostAcquireRequest<I> *req = PostAcquireRequest<I>::create(m_image_ctx,
+      util::create_context_callback<EL, &EL::handle_post_acquiring_lock>(this),
+      util::create_context_callback<EL, &EL::handle_post_acquired_lock>(this));
 
-  using el = ExclusiveLock<I>;
-  AcquireRequest<I>* req = AcquireRequest<I>::create(
-    m_image_ctx, m_cookie,
-    util::create_context_callback<el, &el::handle_acquiring_lock>(this),
-    util::create_context_callback<el, &el::handle_acquire_lock>(this));
-  m_image_ctx.op_work_queue->queue(new C_SendRequest<AcquireRequest<I> >(req),
-                                   0);
+  m_image_ctx.op_work_queue->queue(new FunctionContext([req](int r) {
+    req->send();
+  }));
 }
 
 template <typename I>
-void ExclusiveLock<I>::handle_acquiring_lock(int r) {
-  Mutex::Locker locker(m_lock);
-  ldout(m_image_ctx.cct, 10) << this << " " << __func__ << dendl;
+void ExclusiveLock<I>::handle_post_acquiring_lock(int r) {
+  ldout(m_image_ctx.cct, 10) << dendl;
+
+  Mutex::Locker locker(ML<I>::m_lock);
 
   assert(r == 0);
-  assert(m_state == STATE_ACQUIRING);
+  assert(ML<I>::m_state == ML<I>::STATE_ACQUIRING);
 
   // lock is owned at this point
-  m_state = STATE_POST_ACQUIRING;
+  ML<I>::m_state = ML<I>::STATE_POST_ACQUIRING;
 }
 
 template <typename I>
-void ExclusiveLock<I>::handle_acquire_lock(int r) {
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << this << " " << __func__ << ": r=" << r << dendl;
-
-  if (r == -EBUSY || r == -EAGAIN) {
-    ldout(cct, 5) << "unable to acquire exclusive lock" << dendl;
-  } else if (r < 0) {
-    lderr(cct) << "failed to acquire exclusive lock:" << cpp_strerror(r)
-               << dendl;
-  } else {
-    ldout(cct, 5) << "successfully acquired exclusive lock" << dendl;
-  }
+void ExclusiveLock<I>::handle_post_acquired_lock(int r) {
+  ldout(m_image_ctx.cct, 10) << ": r=" << r << dendl;
 
+  Context *on_finish = nullptr;
   {
-    m_lock.Lock();
-    assert(m_state == STATE_ACQUIRING ||
-           m_state == STATE_POST_ACQUIRING);
+    Mutex::Locker locker(ML<I>::m_lock);
+    assert(ML<I>::m_state == ML<I>::STATE_ACQUIRING ||
+           ML<I>::m_state == ML<I>::STATE_POST_ACQUIRING);
 
-    Action action = get_active_action();
-    assert(action == ACTION_TRY_LOCK || action == ACTION_REQUEST_LOCK);
-    if (action == ACTION_REQUEST_LOCK && r < 0 && r != -EBLACKLISTED &&
-        r != -EPERM) {
-      m_state = STATE_WAITING_FOR_PEER;
-      m_lock.Unlock();
-
-      // request the lock from a peer
-      m_image_ctx.image_watcher->notify_request_lock();
-      return;
-    }
-    m_lock.Unlock();
+    assert (m_pre_post_callback != nullptr);
+    std::swap(m_pre_post_callback, on_finish);
   }
 
-  State next_state = (r < 0 ? STATE_UNLOCKED : STATE_LOCKED);
-  if (r == -EAGAIN) {
-    r = 0;
-  }
-
-  if (next_state == STATE_LOCKED) {
+  if (r >= 0) {
     m_image_ctx.image_watcher->notify_acquired_lock();
     m_image_ctx.aio_work_queue->clear_require_lock_on_read();
     m_image_ctx.aio_work_queue->unblock_writes();
   }
 
-  Mutex::Locker locker(m_lock);
-  complete_active_action(next_state, r);
+  on_finish->complete(r);
 }
 
 template <typename I>
-void ExclusiveLock<I>::send_reacquire_lock() {
-  assert(m_lock.is_locked());
-
-  CephContext *cct = m_image_ctx.cct;
-  if (m_state != STATE_LOCKED) {
-    complete_active_action(m_state, 0);
-    return;
-  }
-
-  m_watch_handle = m_image_ctx.image_watcher->get_watch_handle();
-  if (m_watch_handle == 0) {
-    // watch (re)failed while recovering
-    lderr(cct) << this << " " << __func__ << ": "
-               << "aborting reacquire due to invalid watch handle" << dendl;
-    complete_active_action(STATE_LOCKED, 0);
-    return;
-  }
+void ExclusiveLock<I>::pre_release_lock_handler(bool shutting_down,
+                                                Context *on_finish) {
+  ldout(m_image_ctx.cct, 10) << dendl;
+  Mutex::Locker locker(ML<I>::m_lock);
 
-  m_new_cookie = encode_lock_cookie();
-  if (m_cookie == m_new_cookie) {
-    ldout(cct, 10) << this << " " << __func__ << ": "
-                   << "skipping reacquire since cookie still valid" << dendl;
-    complete_active_action(STATE_LOCKED, 0);
-    return;
-  }
+  m_shutting_down = shutting_down;
 
-  ldout(cct, 10) << this << " " << __func__ << dendl;
-  m_state = STATE_REACQUIRING;
+  using EL = ExclusiveLock<I>;
+  PreReleaseRequest<I> *req = PreReleaseRequest<I>::create(m_image_ctx,
+      util::create_context_callback<EL, &EL::handle_pre_releasing_lock>(this),
+      on_finish, shutting_down);
 
-  using el = ExclusiveLock<I>;
-  ReacquireRequest<I>* req = ReacquireRequest<I>::create(
-    m_image_ctx, m_cookie, m_new_cookie,
-    util::create_context_callback<el, &el::handle_reacquire_lock>(this));
-  req->send();
+  m_image_ctx.op_work_queue->queue(new FunctionContext([req](int r) {
+    req->send();
+  }));
 }
 
 template <typename I>
-void ExclusiveLock<I>::handle_reacquire_lock(int r) {
-  Mutex::Locker locker(m_lock);
+void ExclusiveLock<I>::handle_pre_releasing_lock(int r) {
+  ldout(m_image_ctx.cct, 10) << dendl;
 
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << this << " " << __func__ << ": r=" << r << dendl;
+  Mutex::Locker locker(ML<I>::m_lock);
 
-  assert(m_state == STATE_REACQUIRING);
-  if (r < 0) {
-    if (r == -EOPNOTSUPP) {
-      ldout(cct, 10) << this << " " << __func__ << ": "
-                     << "updating lock is not supported" << dendl;
-    } else {
-      lderr(cct) << this << " " << __func__ << ": "
-                 << "failed to update lock cookie: " << cpp_strerror(r)
-                 << dendl;
-    }
+  assert(r == 0);
+  if (!m_shutting_down) {
+    assert(ML<I>::m_state == ML<I>::STATE_PRE_RELEASING);
 
-    if (!is_shutdown()) {
-      // queue a release and re-acquire of the lock since cookie cannot
-      // be updated on older OSDs
-      execute_action(ACTION_RELEASE_LOCK, nullptr);
-
-      assert(!m_actions_contexts.empty());
-      ActionContexts &action_contexts(m_actions_contexts.front());
-
-      // reacquire completes when the request lock completes
-      Contexts contexts;
-      std::swap(contexts, action_contexts.second);
-      if (contexts.empty()) {
-        execute_action(ACTION_REQUEST_LOCK, nullptr);
-      } else {
-        for (auto ctx : contexts) {
-          ctx = new FunctionContext([ctx, r](int acquire_ret_val) {
-              if (acquire_ret_val >= 0) {
-                acquire_ret_val = r;
-              }
-              ctx->complete(acquire_ret_val);
-            });
-          execute_action(ACTION_REQUEST_LOCK, ctx);
-        }
-      }
-    }
+    // all IO and ops should be blocked/canceled by this point
+    ML<I>::m_state = ML<I>::STATE_RELEASING;
   } else {
-    m_cookie = m_new_cookie;
-  }
+    assert(ML<I>::m_state == ML<I>::STATE_PRE_SHUTTING_DOWN);
 
-  complete_active_action(STATE_LOCKED, 0);
-}
-
-template <typename I>
-void ExclusiveLock<I>::send_release_lock() {
-  assert(m_lock.is_locked());
-  if (m_state == STATE_UNLOCKED) {
-    complete_active_action(STATE_UNLOCKED, 0);
-    return;
+    // all IO and ops should be blocked/canceled by this point
+    ML<I>::m_state = ML<I>::STATE_SHUTTING_DOWN;
   }
-
-  ldout(m_image_ctx.cct, 10) << this << " " << __func__ << dendl;
-  m_state = STATE_PRE_RELEASING;
-
-  using el = ExclusiveLock<I>;
-  ReleaseRequest<I>* req = ReleaseRequest<I>::create(
-    m_image_ctx, m_cookie,
-    util::create_context_callback<el, &el::handle_releasing_lock>(this),
-    util::create_context_callback<el, &el::handle_release_lock>(this),
-    false);
-  m_image_ctx.op_work_queue->queue(new C_SendRequest<ReleaseRequest<I> >(req),
-                                   0);
-}
-
-template <typename I>
-void ExclusiveLock<I>::handle_releasing_lock(int r) {
-  Mutex::Locker locker(m_lock);
-  ldout(m_image_ctx.cct, 10) << this << " " << __func__ << dendl;
-
-  assert(r == 0);
-  assert(m_state == STATE_PRE_RELEASING);
-
-  // all IO and ops should be blocked/canceled by this point
-  m_state = STATE_RELEASING;
 }
 
 template <typename I>
-void ExclusiveLock<I>::handle_release_lock(int r) {
-  bool lock_request_needed = false;
-  {
-    Mutex::Locker locker(m_lock);
-    ldout(m_image_ctx.cct, 10) << this << " " << __func__ << ": r=" << r
-                               << dendl;
+void ExclusiveLock<I>::post_release_lock_handler(bool shutting_down, int r,
+                                                   Context *on_finish) {
+  ldout(m_image_ctx.cct, 10) << ": r=" << r << " shutting_down="
+                             << shutting_down << dendl;
+  if (!shutting_down) {
+    {
+      Mutex::Locker locker(ML<I>::m_lock);
+      assert(ML<I>::m_state == ML<I>::STATE_PRE_RELEASING ||
+             ML<I>::m_state == ML<I>::STATE_RELEASING);
+    }
 
-    assert(m_state == STATE_PRE_RELEASING ||
-           m_state == STATE_RELEASING);
     if (r >= 0) {
-      m_lock.Unlock();
       m_image_ctx.image_watcher->notify_released_lock();
-      lock_request_needed = m_image_ctx.aio_work_queue->is_lock_request_needed();
-      m_lock.Lock();
-
-      m_cookie = "";
-      m_watch_handle = 0;
+      if (m_image_ctx.aio_work_queue->is_lock_request_needed()) {
+        // if we have blocked IO -- re-request the lock
+        RWLock::RLocker owner_locker(m_image_ctx.owner_lock);
+        ML<I>::acquire_lock(nullptr);
+      }
     }
-    complete_active_action(r < 0 ? STATE_LOCKED : STATE_UNLOCKED, r);
-  }
-
-  if (r >= 0 && lock_request_needed) {
-    // if we have blocked IO -- re-request the lock
-    RWLock::RLocker owner_locker(m_image_ctx.owner_lock);
-    request_lock(nullptr);
-  }
-}
-
-template <typename I>
-void ExclusiveLock<I>::send_shutdown() {
-  assert(m_lock.is_locked());
-  if (m_state == STATE_UNLOCKED) {
-    m_state = STATE_SHUTTING_DOWN;
-    m_image_ctx.op_work_queue->queue(util::create_context_callback<
-      ExclusiveLock<I>, &ExclusiveLock<I>::handle_shutdown>(this), 0);
-    return;
-  }
-
-  ldout(m_image_ctx.cct, 10) << this << " " << __func__ << dendl;
-  assert(m_state == STATE_LOCKED);
-  m_state = STATE_PRE_SHUTTING_DOWN;
-
-  m_lock.Unlock();
-  m_image_ctx.op_work_queue->queue(new C_ShutDownRelease(this), 0);
-  m_lock.Lock();
-}
-
-template <typename I>
-void ExclusiveLock<I>::send_shutdown_release() {
-  std::string cookie;
-  {
-    Mutex::Locker locker(m_lock);
-    cookie = m_cookie;
-  }
-
-  using el = ExclusiveLock<I>;
-  ReleaseRequest<I>* req = ReleaseRequest<I>::create(
-    m_image_ctx, cookie,
-    util::create_context_callback<el, &el::handle_shutdown_releasing>(this),
-    util::create_context_callback<el, &el::handle_shutdown_released>(this),
-    true);
-  req->send();
-}
-
-template <typename I>
-void ExclusiveLock<I>::handle_shutdown_releasing(int r) {
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << this << " " << __func__ << ": r=" << r << dendl;
-
-  assert(r == 0);
-  assert(m_state == STATE_PRE_SHUTTING_DOWN);
-
-  // all IO and ops should be blocked/canceled by this point
-  m_state = STATE_SHUTTING_DOWN;
-}
-
-template <typename I>
-void ExclusiveLock<I>::handle_shutdown_released(int r) {
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << this << " " << __func__ << ": r=" << r << dendl;
-
-  {
-    RWLock::WLocker owner_locker(m_image_ctx.owner_lock);
-    m_image_ctx.aio_work_queue->clear_require_lock_on_read();
-    m_image_ctx.exclusive_lock = nullptr;
-  }
-
-  if (r < 0) {
-    lderr(cct) << "failed to shut down exclusive lock: " << cpp_strerror(r)
-               << dendl;
   } else {
-    m_image_ctx.aio_work_queue->unblock_writes();
-  }
-
-  m_image_ctx.image_watcher->notify_released_lock();
-  complete_shutdown(r);
-}
-
-template <typename I>
-void ExclusiveLock<I>::handle_shutdown(int r) {
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << this << " " << __func__ << ": r=" << r << dendl;
-
-  {
-    RWLock::WLocker owner_locker(m_image_ctx.owner_lock);
-    m_image_ctx.aio_work_queue->clear_require_lock_on_read();
-    m_image_ctx.exclusive_lock = nullptr;
-  }
-
-  m_image_ctx.aio_work_queue->unblock_writes();
-  m_image_ctx.image_watcher->flush(util::create_context_callback<
-    ExclusiveLock<I>, &ExclusiveLock<I>::complete_shutdown>(this));
-}
+    {
+      RWLock::WLocker owner_locker(m_image_ctx.owner_lock);
+      m_image_ctx.aio_work_queue->clear_require_lock_on_read();
+      m_image_ctx.exclusive_lock = nullptr;
+    }
 
-template <typename I>
-void ExclusiveLock<I>::complete_shutdown(int r) {
-  ActionContexts action_contexts;
-  {
-    Mutex::Locker locker(m_lock);
-    assert(m_lock.is_locked());
-    assert(m_actions_contexts.size() == 1);
+    if (r >= 0) {
+      m_image_ctx.aio_work_queue->unblock_writes();
+    }
 
-    action_contexts = std::move(m_actions_contexts.front());
-    m_actions_contexts.pop_front();
-    m_state = STATE_SHUTDOWN;
+    m_image_ctx.image_watcher->notify_released_lock();
   }
 
-  // expect to be destroyed after firing callback
-  for (auto ctx : action_contexts.second) {
-    ctx->complete(r);
-  }
+  on_finish->complete(r);
 }
 
 } // namespace librbd
index c313a895981936e7cd7051b9bd16980b49b047f9..1d2a59fa1cafb4d50dc621697edb41b701544e5d 100644 (file)
@@ -4,31 +4,20 @@
 #ifndef CEPH_LIBRBD_EXCLUSIVE_LOCK_H
 #define CEPH_LIBRBD_EXCLUSIVE_LOCK_H
 
-#include "include/int_types.h"
-#include "include/Context.h"
-#include "include/rados/librados.hpp"
-#include "common/Mutex.h"
-#include <list>
-#include <string>
-#include <utility>
+#include "librbd/ManagedLock.h"
+#include "librbd/ImageCtx.h"
 
 namespace librbd {
 
-class ImageCtx;
-
 template <typename ImageCtxT = ImageCtx>
-class ExclusiveLock {
+class ExclusiveLock : public ManagedLock<ImageCtxT> {
 public:
-  static const std::string WATCHER_LOCK_TAG;
-
   static ExclusiveLock *create(ImageCtxT &image_ctx) {
     return new ExclusiveLock<ImageCtxT>(image_ctx);
   }
 
   ExclusiveLock(ImageCtxT &image_ctx);
-  ~ExclusiveLock();
 
-  bool is_lock_owner() const;
   bool accept_requests(int *ret_val) const;
 
   void block_requests(int r);
@@ -37,15 +26,16 @@ public:
   void init(uint64_t features, Context *on_init);
   void shut_down(Context *on_shutdown);
 
-  void try_lock(Context *on_tried_lock);
-  void request_lock(Context *on_locked);
-  void release_lock(Context *on_released);
-
-  void reacquire_lock(Context *on_reacquired = nullptr);
-
   void handle_peer_notification();
 
-  static bool decode_lock_cookie(const std::string &cookie, uint64_t *handle);
+protected:
+  virtual void shutdown_handler(int r, Context *on_finish);
+  virtual void pre_acquire_lock_handler(Context *on_finish);
+  virtual void post_acquire_lock_handler(int r, Context *on_finish);
+  virtual void pre_release_lock_handler(bool shutting_down,
+                                        Context *on_finish);
+  virtual void post_release_lock_handler(bool shutting_down, int r,
+                                         Context *on_finish);
 
 private:
 
@@ -86,34 +76,6 @@ private:
    *
    * @endverbatim
    */
-  enum State {
-    STATE_UNINITIALIZED,
-    STATE_UNLOCKED,
-    STATE_LOCKED,
-    STATE_INITIALIZING,
-    STATE_ACQUIRING,
-    STATE_POST_ACQUIRING,
-    STATE_WAITING_FOR_PEER,
-    STATE_WAITING_FOR_REGISTER,
-    STATE_REACQUIRING,
-    STATE_PRE_RELEASING,
-    STATE_RELEASING,
-    STATE_PRE_SHUTTING_DOWN,
-    STATE_SHUTTING_DOWN,
-    STATE_SHUTDOWN
-  };
-
-  enum Action {
-    ACTION_TRY_LOCK,
-    ACTION_REQUEST_LOCK,
-    ACTION_REACQUIRE_LOCK,
-    ACTION_RELEASE_LOCK,
-    ACTION_SHUT_DOWN
-  };
-
-  typedef std::list<Context *> Contexts;
-  typedef std::pair<Action, Contexts> ActionContexts;
-  typedef std::list<ActionContexts> ActionsContexts;
 
   struct C_InitComplete : public Context {
     ExclusiveLock *exclusive_lock;
@@ -129,65 +91,19 @@ private:
     }
   };
 
-  struct C_ShutDownRelease : public Context {
-    ExclusiveLock *exclusive_lock;
-    C_ShutDownRelease(ExclusiveLock *exclusive_lock)
-      : exclusive_lock(exclusive_lock) {
-    }
-    virtual void finish(int r) override {
-      exclusive_lock->send_shutdown_release();
-    }
-  };
-
-  ImageCtxT &m_image_ctx;
-
-  mutable Mutex m_lock;
-  State m_state;
-  std::string m_cookie;
-  std::string m_new_cookie;
-  uint64_t m_watch_handle;
-
-  ActionsContexts m_actions_contexts;
+  ImageCtxT& m_image_ctx;
+  Context *m_pre_post_callback;
+  bool m_shutting_down;
 
   uint32_t m_request_blocked_count = 0;
   int m_request_blocked_ret_val = 0;
 
-  std::string encode_lock_cookie() const;
-
-  bool is_transition_state() const;
-
-  void append_context(Action action, Context *ctx);
-  void execute_action(Action action, Context *ctx);
-  void execute_next_action();
-
-  Action get_active_action() const;
-  void complete_active_action(State next_state, int r);
-
-  bool is_shutdown() const;
-
   void handle_init_complete();
-
-  void send_acquire_lock();
-  void handle_acquiring_lock(int r);
-  void handle_acquire_lock(int r);
-
-  void send_reacquire_lock();
-  void handle_reacquire_lock(int r);
-
-  void send_release_lock();
-  void handle_releasing_lock(int r);
-  void handle_release_lock(int r);
-
-  void send_shutdown();
-  void send_shutdown_release();
-  void handle_shutdown_releasing(int r);
-  void handle_shutdown_released(int r);
-  void handle_shutdown(int r);
-  void complete_shutdown(int r);
+  void handle_post_acquiring_lock(int r);
+  void handle_post_acquired_lock(int r);
+  void handle_pre_releasing_lock(int r);
 };
 
 } // namespace librbd
 
-extern template class librbd::ExclusiveLock<librbd::ImageCtx>;
-
 #endif // CEPH_LIBRBD_EXCLUSIVE_LOCK_H
index b83e1c6f4e58cf51d99f060bfdc97acf72301c48..2297b9f731bac60ab727c98ee91fdaad710e2420 100644 (file)
@@ -212,9 +212,9 @@ struct C_InvokeAsyncRequest : public Context {
       // current lock owner doesn't support op -- try to perform
       // the action locally
       request_lock = false;
-      image_ctx.exclusive_lock->request_lock(ctx);
+      image_ctx.exclusive_lock->acquire_lock(ctx);
     } else {
-      image_ctx.exclusive_lock->try_lock(ctx);
+      image_ctx.exclusive_lock->try_acquire_lock(ctx);
     }
     owner_lock.put_read();
   }
@@ -1212,7 +1212,7 @@ int Operations<I>::snap_set_limit(uint64_t limit) {
        !m_image_ctx.exclusive_lock->is_lock_owner()) {
       C_SaferCond lock_ctx;
 
-      m_image_ctx.exclusive_lock->request_lock(&lock_ctx);
+      m_image_ctx.exclusive_lock->acquire_lock(&lock_ctx);
       r = lock_ctx.wait();
       if (r < 0) {
        return r;
@@ -1369,7 +1369,7 @@ int Operations<I>::metadata_set(const std::string &key,
        !m_image_ctx.exclusive_lock->is_lock_owner()) {
       C_SaferCond lock_ctx;
 
-      m_image_ctx.exclusive_lock->request_lock(&lock_ctx);
+      m_image_ctx.exclusive_lock->acquire_lock(&lock_ctx);
       r = lock_ctx.wait();
       if (r < 0) {
        return r;
@@ -1424,7 +1424,7 @@ int Operations<I>::metadata_remove(const std::string &key) {
         !m_image_ctx.exclusive_lock->is_lock_owner()) {
       C_SaferCond lock_ctx;
 
-      m_image_ctx.exclusive_lock->request_lock(&lock_ctx);
+      m_image_ctx.exclusive_lock->acquire_lock(&lock_ctx);
       r = lock_ctx.wait();
       if (r < 0) {
         return r;
@@ -1469,7 +1469,7 @@ int Operations<I>::prepare_image_update() {
     if (m_image_ctx.exclusive_lock != nullptr &&
         (!m_image_ctx.exclusive_lock->is_lock_owner() ||
          !m_image_ctx.exclusive_lock->accept_requests(&r))) {
-      m_image_ctx.exclusive_lock->try_lock(&ctx);
+      m_image_ctx.exclusive_lock->try_acquire_lock(&ctx);
       trying_lock = true;
     }
   }
diff --git a/src/librbd/exclusive_lock/AcquireRequest.cc b/src/librbd/exclusive_lock/AcquireRequest.cc
deleted file mode 100644 (file)
index 1887e74..0000000
+++ /dev/null
@@ -1,622 +0,0 @@
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-
-#include "librbd/exclusive_lock/AcquireRequest.h"
-#include "cls/lock/cls_lock_client.h"
-#include "cls/lock/cls_lock_types.h"
-#include "common/dout.h"
-#include "common/errno.h"
-#include "common/WorkQueue.h"
-#include "include/stringify.h"
-#include "librbd/ExclusiveLock.h"
-#include "librbd/ImageCtx.h"
-#include "librbd/ImageState.h"
-#include "librbd/ImageWatcher.h"
-#include "librbd/Journal.h"
-#include "librbd/ObjectMap.h"
-#include "librbd/Utils.h"
-#include "librbd/image/RefreshRequest.h"
-#include "librbd/journal/Policy.h"
-
-#define dout_subsys ceph_subsys_rbd
-#undef dout_prefix
-#define dout_prefix *_dout << "librbd::exclusive_lock::AcquireRequest: "
-
-namespace librbd {
-namespace exclusive_lock {
-
-using util::create_async_context_callback;
-using util::create_context_callback;
-using util::create_rados_ack_callback;
-using util::create_rados_safe_callback;
-
-namespace {
-
-template <typename I>
-struct C_BlacklistClient : public Context {
-  I &image_ctx;
-  std::string locker_address;
-  Context *on_finish;
-
-  C_BlacklistClient(I &image_ctx, const std::string &locker_address,
-                    Context *on_finish)
-    : image_ctx(image_ctx), locker_address(locker_address),
-      on_finish(on_finish) {
-  }
-
-  virtual void finish(int r) override {
-    librados::Rados rados(image_ctx.md_ctx);
-    r = rados.blacklist_add(locker_address,
-                            image_ctx.blacklist_expire_seconds);
-    on_finish->complete(r);
-  }
-};
-
-} // anonymous namespace
-
-template <typename I>
-AcquireRequest<I>* AcquireRequest<I>::create(I &image_ctx,
-                                             const std::string &cookie,
-                                             Context *on_acquire,
-                                             Context *on_finish) {
-  return new AcquireRequest(image_ctx, cookie, on_acquire, on_finish);
-}
-
-template <typename I>
-AcquireRequest<I>::AcquireRequest(I &image_ctx, const std::string &cookie,
-                                  Context *on_acquire, Context *on_finish)
-  : m_image_ctx(image_ctx), m_cookie(cookie), m_on_acquire(on_acquire),
-    m_on_finish(create_async_context_callback(image_ctx, on_finish)),
-    m_object_map(nullptr), m_journal(nullptr), m_error_result(0) {
-}
-
-template <typename I>
-AcquireRequest<I>::~AcquireRequest() {
-  if (!m_prepare_lock_completed) {
-    m_image_ctx.state->handle_prepare_lock_complete();
-  }
-  delete m_on_acquire;
-}
-
-template <typename I>
-void AcquireRequest<I>::send() {
-  send_prepare_lock();
-}
-
-template <typename I>
-void AcquireRequest<I>::send_prepare_lock() {
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << dendl;
-
-  // acquire the lock if the image is not busy performing other actions
-  Context *ctx = create_context_callback<
-    AcquireRequest<I>, &AcquireRequest<I>::handle_prepare_lock>(this);
-  m_image_ctx.state->prepare_lock(ctx);
-}
-
-template <typename I>
-Context *AcquireRequest<I>::handle_prepare_lock(int *ret_val) {
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << ": r=" << *ret_val << dendl;
-
-  send_flush_notifies();
-  return nullptr;
-}
-
-template <typename I>
-void AcquireRequest<I>::send_flush_notifies() {
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << dendl;
-
-  using klass = AcquireRequest<I>;
-  Context *ctx = create_context_callback<klass, &klass::handle_flush_notifies>(
-    this);
-  m_image_ctx.image_watcher->flush(ctx);
-}
-
-template <typename I>
-Context *AcquireRequest<I>::handle_flush_notifies(int *ret_val) {
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << dendl;
-
-  assert(*ret_val == 0);
-  send_lock();
-  return nullptr;
-}
-
-template <typename I>
-void AcquireRequest<I>::send_lock() {
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << dendl;
-
-  librados::ObjectWriteOperation op;
-  rados::cls::lock::lock(&op, RBD_LOCK_NAME, LOCK_EXCLUSIVE, m_cookie,
-                         ExclusiveLock<>::WATCHER_LOCK_TAG, "", utime_t(), 0);
-
-  using klass = AcquireRequest<I>;
-  librados::AioCompletion *rados_completion =
-    create_rados_safe_callback<klass, &klass::handle_lock>(this);
-  int r = m_image_ctx.md_ctx.aio_operate(m_image_ctx.header_oid,
-                                         rados_completion, &op);
-  assert(r == 0);
-  rados_completion->release();
-}
-
-template <typename I>
-Context *AcquireRequest<I>::handle_lock(int *ret_val) {
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << ": r=" << *ret_val << dendl;
-
-  if (*ret_val == 0) {
-    return send_refresh();
-  } else if (*ret_val != -EBUSY) {
-    lderr(cct) << "failed to lock: " << cpp_strerror(*ret_val) << dendl;
-    return m_on_finish;
-  }
-
-  send_get_lockers();
-  return nullptr;
-}
-
-template <typename I>
-Context *AcquireRequest<I>::send_refresh() {
-  if (!m_image_ctx.state->is_refresh_required()) {
-    return send_open_object_map();
-  }
-
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << dendl;
-
-  using klass = AcquireRequest<I>;
-  Context *ctx = create_async_context_callback(
-    m_image_ctx, create_context_callback<klass, &klass::handle_refresh>(this));
-
-  // ImageState is blocked waiting for lock to complete -- safe to directly
-  // refresh
-  image::RefreshRequest<I> *req = image::RefreshRequest<I>::create(
-    m_image_ctx, true, ctx);
-  req->send();
-  return nullptr;
-}
-
-template <typename I>
-Context *AcquireRequest<I>::handle_refresh(int *ret_val) {
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << ": r=" << *ret_val << dendl;
-
-  if (*ret_val == -ERESTART) {
-    // next issued IO or op will (re)-refresh the image and shut down lock
-    ldout(cct, 5) << ": exclusive lock dynamically disabled" << dendl;
-    *ret_val = 0;
-  } else if (*ret_val < 0) {
-    lderr(cct) << "failed to refresh image: " << cpp_strerror(*ret_val)
-               << dendl;
-    m_error_result = *ret_val;
-    send_unlock();
-    return nullptr;
-  }
-
-  return send_open_object_map();
-}
-
-template <typename I>
-Context *AcquireRequest<I>::send_open_journal() {
-  // alert caller that we now own the exclusive lock
-  m_on_acquire->complete(0);
-  m_on_acquire = nullptr;
-
-  bool journal_enabled;
-  {
-    RWLock::RLocker snap_locker(m_image_ctx.snap_lock);
-    journal_enabled = (m_image_ctx.test_features(RBD_FEATURE_JOURNALING,
-                                                 m_image_ctx.snap_lock) &&
-                       !m_image_ctx.get_journal_policy()->journal_disabled());
-  }
-  if (!journal_enabled) {
-    apply();
-    return m_on_finish;
-  }
-
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << dendl;
-
-  using klass = AcquireRequest<I>;
-  Context *ctx = create_context_callback<klass, &klass::handle_open_journal>(
-    this);
-  m_journal = m_image_ctx.create_journal();
-
-  // journal playback requires object map (if enabled) and itself
-  apply();
-
-  m_journal->open(ctx);
-  return nullptr;
-}
-
-template <typename I>
-Context *AcquireRequest<I>::handle_open_journal(int *ret_val) {
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << ": r=" << *ret_val << dendl;
-
-  if (*ret_val < 0) {
-    lderr(cct) << "failed to open journal: " << cpp_strerror(*ret_val) << dendl;
-    m_error_result = *ret_val;
-    send_close_journal();
-    return nullptr;
-  }
-
-  send_allocate_journal_tag();
-  return nullptr;
-}
-
-template <typename I>
-void AcquireRequest<I>::send_allocate_journal_tag() {
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << dendl;
-
-  RWLock::RLocker snap_locker(m_image_ctx.snap_lock);
-  using klass = AcquireRequest<I>;
-  Context *ctx = create_context_callback<
-    klass, &klass::handle_allocate_journal_tag>(this);
-  m_image_ctx.get_journal_policy()->allocate_tag_on_lock(ctx);
-}
-
-template <typename I>
-Context *AcquireRequest<I>::handle_allocate_journal_tag(int *ret_val) {
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << ": r=" << *ret_val << dendl;
-
-  if (*ret_val < 0) {
-    lderr(cct) << "failed to allocate journal tag: " << cpp_strerror(*ret_val)
-               << dendl;
-    m_error_result = *ret_val;
-    send_close_journal();
-    return nullptr;
-  }
-  return m_on_finish;
-}
-
-template <typename I>
-void AcquireRequest<I>::send_close_journal() {
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << dendl;
-
-  using klass = AcquireRequest<I>;
-  Context *ctx = create_context_callback<klass, &klass::handle_close_journal>(
-    this);
-  m_journal->close(ctx);
-}
-
-template <typename I>
-Context *AcquireRequest<I>::handle_close_journal(int *ret_val) {
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << ": r=" << *ret_val << dendl;
-
-  if (*ret_val < 0) {
-    lderr(cct) << "failed to close journal: " << cpp_strerror(*ret_val)
-               << dendl;
-  }
-
-  send_close_object_map();
-  return nullptr;
-}
-
-template <typename I>
-Context *AcquireRequest<I>::send_open_object_map() {
-  if (!m_image_ctx.test_features(RBD_FEATURE_OBJECT_MAP)) {
-    return send_open_journal();
-  }
-
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << dendl;
-
-  using klass = AcquireRequest<I>;
-  Context *ctx = create_context_callback<klass, &klass::handle_open_object_map>(
-    this);
-
-  m_object_map = m_image_ctx.create_object_map(CEPH_NOSNAP);
-  m_object_map->open(ctx);
-  return nullptr;
-}
-
-template <typename I>
-Context *AcquireRequest<I>::handle_open_object_map(int *ret_val) {
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << ": r=" << *ret_val << dendl;
-
-  if (*ret_val < 0) {
-    lderr(cct) << "failed to open object map: " << cpp_strerror(*ret_val)
-               << dendl;
-
-    *ret_val = 0;
-    delete m_object_map;
-    m_object_map = nullptr;
-  }
-
-  return send_open_journal();
-}
-
-template <typename I>
-void AcquireRequest<I>::send_close_object_map() {
-  if (m_object_map == nullptr) {
-    send_unlock();
-    return;
-  }
-
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << dendl;
-
-  using klass = AcquireRequest<I>;
-  Context *ctx = create_context_callback<
-    klass, &klass::handle_close_object_map>(this);
-  m_object_map->close(ctx);
-}
-
-template <typename I>
-Context *AcquireRequest<I>::handle_close_object_map(int *ret_val) {
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << ": r=" << *ret_val << dendl;
-
-  // object map should never result in an error
-  assert(*ret_val == 0);
-  send_unlock();
-  return nullptr;
-}
-
-template <typename I>
-void AcquireRequest<I>::send_unlock() {
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << dendl;
-
-  librados::ObjectWriteOperation op;
-  rados::cls::lock::unlock(&op, RBD_LOCK_NAME, m_cookie);
-
-  using klass = AcquireRequest<I>;
-  librados::AioCompletion *rados_completion =
-    create_rados_safe_callback<klass, &klass::handle_unlock>(this);
-  int r = m_image_ctx.md_ctx.aio_operate(m_image_ctx.header_oid,
-                                         rados_completion, &op);
-  assert(r == 0);
-  rados_completion->release();
-}
-
-template <typename I>
-Context *AcquireRequest<I>::handle_unlock(int *ret_val) {
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << ": r=" << *ret_val << dendl;
-
-  if (*ret_val < 0) {
-    lderr(cct) << "failed to unlock image: " << cpp_strerror(*ret_val) << dendl;
-  }
-
-  revert(ret_val);
-  return m_on_finish;
-}
-
-template <typename I>
-void AcquireRequest<I>::send_get_lockers() {
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << dendl;
-
-  librados::ObjectReadOperation op;
-  rados::cls::lock::get_lock_info_start(&op, RBD_LOCK_NAME);
-
-  using klass = AcquireRequest<I>;
-  librados::AioCompletion *rados_completion =
-    create_rados_ack_callback<klass, &klass::handle_get_lockers>(this);
-  m_out_bl.clear();
-  int r = m_image_ctx.md_ctx.aio_operate(m_image_ctx.header_oid,
-                                         rados_completion, &op, &m_out_bl);
-  assert(r == 0);
-  rados_completion->release();
-}
-
-template <typename I>
-Context *AcquireRequest<I>::handle_get_lockers(int *ret_val) {
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << ": r=" << *ret_val << dendl;
-
-  std::map<rados::cls::lock::locker_id_t,
-           rados::cls::lock::locker_info_t> lockers;
-  ClsLockType lock_type = LOCK_NONE;
-  std::string lock_tag;
-  if (*ret_val == 0) {
-    bufferlist::iterator it = m_out_bl.begin();
-    *ret_val = rados::cls::lock::get_lock_info_finish(&it, &lockers,
-                                                      &lock_type, &lock_tag);
-  }
-
-  if (*ret_val < 0) {
-    lderr(cct) << "failed to retrieve lockers: " << cpp_strerror(*ret_val)
-               << dendl;
-    return m_on_finish;
-  }
-
-  if (lockers.empty()) {
-    ldout(cct, 20) << "no lockers detected" << dendl;
-    send_lock();
-    return nullptr;
-  }
-
-  if (lock_tag != ExclusiveLock<>::WATCHER_LOCK_TAG) {
-    ldout(cct, 5) <<"locked by external mechanism: tag=" << lock_tag << dendl;
-    *ret_val = -EBUSY;
-    return m_on_finish;
-  }
-
-  if (lock_type == LOCK_SHARED) {
-    ldout(cct, 5) << "shared lock type detected" << dendl;
-    *ret_val = -EBUSY;
-    return m_on_finish;
-  }
-
-  std::map<rados::cls::lock::locker_id_t,
-           rados::cls::lock::locker_info_t>::iterator iter = lockers.begin();
-  if (!ExclusiveLock<>::decode_lock_cookie(iter->first.cookie,
-                                            &m_locker_handle)) {
-    ldout(cct, 5) << "locked by external mechanism: "
-                  << "cookie=" << iter->first.cookie << dendl;
-    *ret_val = -EBUSY;
-    return m_on_finish;
-  }
-
-  m_locker_entity = iter->first.locker;
-  m_locker_cookie = iter->first.cookie;
-  m_locker_address = stringify(iter->second.addr);
-  if (m_locker_cookie.empty() || m_locker_address.empty()) {
-    ldout(cct, 20) << "no valid lockers detected" << dendl;
-    send_lock();
-    return nullptr;
-  }
-
-  ldout(cct, 10) << "retrieved exclusive locker: "
-                 << m_locker_entity << "@" << m_locker_address << dendl;
-  send_get_watchers();
-  return nullptr;
-}
-
-template <typename I>
-void AcquireRequest<I>::send_get_watchers() {
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << dendl;
-
-  librados::ObjectReadOperation op;
-  op.list_watchers(&m_watchers, &m_watchers_ret_val);
-
-  using klass = AcquireRequest<I>;
-  librados::AioCompletion *rados_completion =
-    create_rados_ack_callback<klass, &klass::handle_get_watchers>(this);
-  m_out_bl.clear();
-  int r = m_image_ctx.md_ctx.aio_operate(m_image_ctx.header_oid,
-                                         rados_completion, &op, &m_out_bl);
-  assert(r == 0);
-  rados_completion->release();
-}
-
-template <typename I>
-Context *AcquireRequest<I>::handle_get_watchers(int *ret_val) {
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << ": r=" << *ret_val << dendl;
-
-  if (*ret_val == 0) {
-    *ret_val = m_watchers_ret_val;
-  }
-  if (*ret_val < 0) {
-    lderr(cct) << "failed to retrieve watchers: " << cpp_strerror(*ret_val)
-               << dendl;
-    return m_on_finish;
-  }
-
-  for (auto &watcher : m_watchers) {
-    if ((strncmp(m_locker_address.c_str(),
-                 watcher.addr, sizeof(watcher.addr)) == 0) &&
-        (m_locker_handle == watcher.cookie)) {
-      ldout(cct, 10) << "lock owner is still alive" << dendl;
-
-      *ret_val = -EAGAIN;
-      return m_on_finish;
-    }
-  }
-
-  send_blacklist();
-  return nullptr;
-}
-
-template <typename I>
-void AcquireRequest<I>::send_blacklist() {
-  if (!m_image_ctx.blacklist_on_break_lock) {
-    send_break_lock();
-    return;
-  }
-
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << dendl;
-
-  // TODO: need async version of RadosClient::blacklist_add
-  using klass = AcquireRequest<I>;
-  Context *ctx = create_context_callback<klass, &klass::handle_blacklist>(
-    this);
-  m_image_ctx.op_work_queue->queue(new C_BlacklistClient<I>(m_image_ctx,
-                                                            m_locker_address,
-                                                            ctx), 0);
-}
-
-template <typename I>
-Context *AcquireRequest<I>::handle_blacklist(int *ret_val) {
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << ": r=" << *ret_val << dendl;
-
-  if (*ret_val < 0) {
-    lderr(cct) << "failed to blacklist lock owner: " << cpp_strerror(*ret_val)
-               << dendl;
-    return m_on_finish;
-  }
-  send_break_lock();
-  return nullptr;
-}
-
-template <typename I>
-void AcquireRequest<I>::send_break_lock() {
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << dendl;
-
-  librados::ObjectWriteOperation op;
-  rados::cls::lock::break_lock(&op, RBD_LOCK_NAME, m_locker_cookie,
-                               m_locker_entity);
-
-  using klass = AcquireRequest<I>;
-  librados::AioCompletion *rados_completion =
-    create_rados_safe_callback<klass, &klass::handle_break_lock>(this);
-  int r = m_image_ctx.md_ctx.aio_operate(m_image_ctx.header_oid,
-                                         rados_completion, &op);
-  assert(r == 0);
-  rados_completion->release();
-}
-
-template <typename I>
-Context *AcquireRequest<I>::handle_break_lock(int *ret_val) {
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << ": r=" << *ret_val << dendl;
-
-  if (*ret_val == -ENOENT) {
-    *ret_val = 0;
-  } else if (*ret_val < 0) {
-    lderr(cct) << "failed to break lock: " << cpp_strerror(*ret_val) << dendl;
-    return m_on_finish;
-  }
-
-  send_lock();
-  return nullptr;
-}
-
-template <typename I>
-void AcquireRequest<I>::apply() {
-  {
-    RWLock::WLocker snap_locker(m_image_ctx.snap_lock);
-    assert(m_image_ctx.object_map == nullptr);
-    m_image_ctx.object_map = m_object_map;
-
-    assert(m_image_ctx.journal == nullptr);
-    m_image_ctx.journal = m_journal;
-  }
-
-  m_prepare_lock_completed = true;
-  m_image_ctx.state->handle_prepare_lock_complete();
-}
-
-template <typename I>
-void AcquireRequest<I>::revert(int *ret_val) {
-  RWLock::WLocker snap_locker(m_image_ctx.snap_lock);
-  m_image_ctx.object_map = nullptr;
-  m_image_ctx.journal = nullptr;
-
-  delete m_object_map;
-  delete m_journal;
-
-  assert(m_error_result < 0);
-  *ret_val = m_error_result;
-}
-
-} // namespace exclusive_lock
-} // namespace librbd
-
-template class librbd::exclusive_lock::AcquireRequest<librbd::ImageCtx>;
diff --git a/src/librbd/exclusive_lock/AcquireRequest.h b/src/librbd/exclusive_lock/AcquireRequest.h
deleted file mode 100644 (file)
index 64f078b..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-
-#ifndef CEPH_LIBRBD_EXCLUSIVE_LOCK_ACQUIRE_REQUEST_H
-#define CEPH_LIBRBD_EXCLUSIVE_LOCK_ACQUIRE_REQUEST_H
-
-#include "include/int_types.h"
-#include "include/buffer.h"
-#include "librbd/ImageCtx.h"
-#include "msg/msg_types.h"
-#include <string>
-
-class Context;
-
-namespace librbd {
-
-template <typename> class Journal;
-
-namespace exclusive_lock {
-
-template <typename ImageCtxT = ImageCtx>
-class AcquireRequest {
-public:
-  static AcquireRequest* create(ImageCtxT &image_ctx, const std::string &cookie,
-                                Context *on_acquire, Context *on_finish);
-
-  ~AcquireRequest();
-  void send();
-
-private:
-
-  /**
-   * @verbatim
-   *
-   * <start>
-   *    |
-   *    v
-   * PREPARE_LOCK
-   *    |
-   *    v
-   * FLUSH_NOTIFIES
-   *    |
-   *    |     /-----------------------------------------------------------\
-   *    |     |                                                           |
-   *    |     |             (no lockers)                                  |
-   *    |     |   . . . . . . . . . . . . . . . . . . . . . .             |
-   *    |     |   .                                         .             |
-   *    |     v   v      (EBUSY)                            .             |
-   *    \--> LOCK_IMAGE * * * * * * * * > GET_LOCKERS . . . .             |
-   *              |                         |                             |
-   *              v                         v                             |
-   *         REFRESH (skip if not         GET_WATCHERS                    |
-   *              |   needed)               |                             |
-   *              v                         v                             |
-   *         OPEN_OBJECT_MAP (skip if     BLACKLIST (skip if blacklist    |
-   *              |           disabled)     |        disabled)            |
-   *              v                         v                             |
-   *         OPEN_JOURNAL (skip if        BREAK_LOCK                      |
-   *              |   *     disabled)       |                             |
-   *              |   *                     \-----------------------------/
-   *              |   * * * * * * * *
-   *              v                 *
-   *          ALLOCATE_JOURNAL_TAG  *
-   *              |            *    *
-   *              |            *    *
-   *              |            v    v
-   *              |         CLOSE_JOURNAL
-   *              |               |
-   *              |               v
-   *              |         CLOSE_OBJECT_MAP
-   *              |               |
-   *              |               v
-   *              |         UNLOCK_IMAGE
-   *              |               |
-   *              v               |
-   *          <finish> <----------/
-   *
-   * @endverbatim
-   */
-
-  AcquireRequest(ImageCtxT &image_ctx, const std::string &cookie,
-                 Context *on_acquire, Context *on_finish);
-
-  ImageCtxT &m_image_ctx;
-  std::string m_cookie;
-  Context *m_on_acquire;
-  Context *m_on_finish;
-
-  bufferlist m_out_bl;
-
-  std::list<obj_watch_t> m_watchers;
-  int m_watchers_ret_val;
-
-  decltype(m_image_ctx.object_map) m_object_map;
-  decltype(m_image_ctx.journal) m_journal;
-
-  entity_name_t m_locker_entity;
-  std::string m_locker_cookie;
-  std::string m_locker_address;
-  uint64_t m_locker_handle;
-
-  int m_error_result;
-  bool m_prepare_lock_completed = false;
-
-  void send_prepare_lock();
-  Context *handle_prepare_lock(int *ret_val);
-
-  void send_flush_notifies();
-  Context *handle_flush_notifies(int *ret_val);
-
-  void send_lock();
-  Context *handle_lock(int *ret_val);
-
-  Context *send_refresh();
-  Context *handle_refresh(int *ret_val);
-
-  Context *send_open_journal();
-  Context *handle_open_journal(int *ret_val);
-
-  void send_allocate_journal_tag();
-  Context *handle_allocate_journal_tag(int *ret_val);
-
-  Context *send_open_object_map();
-  Context *handle_open_object_map(int *ret_val);
-
-  void send_close_journal();
-  Context *handle_close_journal(int *ret_val);
-
-  void send_close_object_map();
-  Context *handle_close_object_map(int *ret_val);
-
-  void send_unlock();
-  Context *handle_unlock(int *ret_val);
-
-  void send_get_lockers();
-  Context *handle_get_lockers(int *ret_val);
-
-  void send_get_watchers();
-  Context *handle_get_watchers(int *ret_val);
-
-  void send_blacklist();
-  Context *handle_blacklist(int *ret_val);
-
-  void send_break_lock();
-  Context *handle_break_lock(int *ret_val);
-
-  void apply();
-  void revert(int *ret_val);
-};
-
-} // namespace exclusive_lock
-} // namespace librbd
-
-extern template class librbd::exclusive_lock::AcquireRequest<librbd::ImageCtx>;
-
-#endif // CEPH_LIBRBD_EXCLUSIVE_LOCK_ACQUIRE_REQUEST_H
diff --git a/src/librbd/exclusive_lock/PostAcquireRequest.cc b/src/librbd/exclusive_lock/PostAcquireRequest.cc
new file mode 100644 (file)
index 0000000..ed5c466
--- /dev/null
@@ -0,0 +1,303 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "librbd/exclusive_lock/PostAcquireRequest.h"
+#include "cls/lock/cls_lock_client.h"
+#include "cls/lock/cls_lock_types.h"
+#include "common/dout.h"
+#include "common/errno.h"
+#include "common/WorkQueue.h"
+#include "include/stringify.h"
+#include "librbd/ExclusiveLock.h"
+#include "librbd/ManagedLock.h"
+#include "librbd/ImageCtx.h"
+#include "librbd/ImageState.h"
+#include "librbd/ImageWatcher.h"
+#include "librbd/Journal.h"
+#include "librbd/ObjectMap.h"
+#include "librbd/Utils.h"
+#include "librbd/image/RefreshRequest.h"
+#include "librbd/journal/Policy.h"
+
+#define dout_subsys ceph_subsys_rbd
+#undef dout_prefix
+#define dout_prefix *_dout << "librbd::exclusive_lock::PostAcquireRequest: "
+
+namespace librbd {
+namespace exclusive_lock {
+
+using util::create_async_context_callback;
+using util::create_context_callback;
+using util::create_rados_ack_callback;
+using util::create_rados_safe_callback;
+
+
+template <typename I>
+PostAcquireRequest<I>* PostAcquireRequest<I>::create(I &image_ctx,
+                                                     Context *on_acquire,
+                                                     Context *on_finish) {
+  return new PostAcquireRequest(image_ctx, on_acquire, on_finish);
+}
+
+template <typename I>
+PostAcquireRequest<I>::PostAcquireRequest(I &image_ctx, Context *on_acquire,
+                                          Context *on_finish)
+  : m_image_ctx(image_ctx),
+    m_on_acquire(on_acquire),
+    m_on_finish(create_async_context_callback(image_ctx, on_finish)),
+    m_object_map(nullptr), m_journal(nullptr), m_error_result(0) {
+}
+
+template <typename I>
+PostAcquireRequest<I>::~PostAcquireRequest() {
+  if (!m_prepare_lock_completed) {
+    m_image_ctx.state->handle_prepare_lock_complete();
+  }
+  delete m_on_acquire;
+}
+
+template <typename I>
+void PostAcquireRequest<I>::send() {
+  send_refresh();
+}
+
+template <typename I>
+void PostAcquireRequest<I>::send_refresh() {
+  if (!m_image_ctx.state->is_refresh_required()) {
+    send_open_object_map();
+    return;
+  }
+
+  CephContext *cct = m_image_ctx.cct;
+  ldout(cct, 10) << __func__ << dendl;
+
+  using klass = PostAcquireRequest<I>;
+  Context *ctx = create_async_context_callback(
+    m_image_ctx, create_context_callback<klass, &klass::handle_refresh>(this));
+
+  // ImageState is blocked waiting for lock to complete -- safe to directly
+  // refresh
+  image::RefreshRequest<I> *req = image::RefreshRequest<I>::create(
+    m_image_ctx, true, ctx);
+  req->send();
+}
+
+template <typename I>
+void PostAcquireRequest<I>::handle_refresh(int r) {
+  CephContext *cct = m_image_ctx.cct;
+  ldout(cct, 10) << __func__ << ": r=" << r << dendl;
+
+  if (r == -ERESTART) {
+    // next issued IO or op will (re)-refresh the image and shut down lock
+    ldout(cct, 5) << ": exclusive lock dynamically disabled" << dendl;
+    r = 0;
+  } else if (r < 0) {
+    lderr(cct) << "failed to refresh image: " << cpp_strerror(r) << dendl;
+    save_result(r);
+    revert();
+    finish();
+    return;
+  }
+
+  send_open_object_map();
+}
+
+template <typename I>
+void PostAcquireRequest<I>::send_open_journal() {
+  // alert caller that we now own the exclusive lock
+  m_on_acquire->complete(0);
+  m_on_acquire = nullptr;
+
+  bool journal_enabled;
+  {
+    RWLock::RLocker snap_locker(m_image_ctx.snap_lock);
+    journal_enabled = (m_image_ctx.test_features(RBD_FEATURE_JOURNALING,
+                                                 m_image_ctx.snap_lock) &&
+                       !m_image_ctx.get_journal_policy()->journal_disabled());
+  }
+  if (!journal_enabled) {
+    apply();
+    finish();
+    return;
+  }
+
+  CephContext *cct = m_image_ctx.cct;
+  ldout(cct, 10) << __func__ << dendl;
+
+  using klass = PostAcquireRequest<I>;
+  Context *ctx = create_context_callback<klass, &klass::handle_open_journal>(
+    this);
+  m_journal = m_image_ctx.create_journal();
+
+  // journal playback requires object map (if enabled) and itself
+  apply();
+
+  m_journal->open(ctx);
+}
+
+template <typename I>
+void PostAcquireRequest<I>::handle_open_journal(int r) {
+  CephContext *cct = m_image_ctx.cct;
+  ldout(cct, 10) << __func__ << ": r=" << r << dendl;
+
+  save_result(r);
+  if (r < 0) {
+    lderr(cct) << "failed to open journal: " << cpp_strerror(r) << dendl;
+    send_close_journal();
+    return;
+  }
+
+  send_allocate_journal_tag();
+}
+
+template <typename I>
+void PostAcquireRequest<I>::send_allocate_journal_tag() {
+  CephContext *cct = m_image_ctx.cct;
+  ldout(cct, 10) << __func__ << dendl;
+
+  RWLock::RLocker snap_locker(m_image_ctx.snap_lock);
+  using klass = PostAcquireRequest<I>;
+  Context *ctx = create_context_callback<
+    klass, &klass::handle_allocate_journal_tag>(this);
+  m_image_ctx.get_journal_policy()->allocate_tag_on_lock(ctx);
+}
+
+template <typename I>
+void PostAcquireRequest<I>::handle_allocate_journal_tag(int r) {
+  CephContext *cct = m_image_ctx.cct;
+  ldout(cct, 10) << __func__ << ": r=" << r << dendl;
+
+  save_result(r);
+  if (r < 0) {
+    lderr(cct) << "failed to allocate journal tag: " << cpp_strerror(r)
+               << dendl;
+    send_close_journal();
+    return;
+  }
+
+  finish();
+}
+
+template <typename I>
+void PostAcquireRequest<I>::send_close_journal() {
+  CephContext *cct = m_image_ctx.cct;
+  ldout(cct, 10) << __func__ << dendl;
+
+  using klass = PostAcquireRequest<I>;
+  Context *ctx = create_context_callback<klass, &klass::handle_close_journal>(
+    this);
+  m_journal->close(ctx);
+}
+
+template <typename I>
+void PostAcquireRequest<I>::handle_close_journal(int r) {
+  CephContext *cct = m_image_ctx.cct;
+  ldout(cct, 10) << __func__ << ": r=" << r << dendl;
+
+  save_result(r);
+  if (r < 0) {
+    lderr(cct) << "failed to close journal: " << cpp_strerror(r) << dendl;
+  }
+
+  send_close_object_map();
+}
+
+template <typename I>
+void PostAcquireRequest<I>::send_open_object_map() {
+  if (!m_image_ctx.test_features(RBD_FEATURE_OBJECT_MAP)) {
+    send_open_journal();
+    return;
+  }
+
+  CephContext *cct = m_image_ctx.cct;
+  ldout(cct, 10) << __func__ << dendl;
+
+  using klass = PostAcquireRequest<I>;
+  Context *ctx = create_context_callback<klass, &klass::handle_open_object_map>(
+    this);
+
+  m_object_map = m_image_ctx.create_object_map(CEPH_NOSNAP);
+  m_object_map->open(ctx);
+}
+
+template <typename I>
+void PostAcquireRequest<I>::handle_open_object_map(int r) {
+  CephContext *cct = m_image_ctx.cct;
+  ldout(cct, 10) << __func__ << ": r=" << r << dendl;
+
+  if (r < 0) {
+    lderr(cct) << "failed to open object map: " << cpp_strerror(r) << dendl;
+
+    r = 0;
+    delete m_object_map;
+    m_object_map = nullptr;
+  }
+
+  send_open_journal();
+}
+
+template <typename I>
+void PostAcquireRequest<I>::send_close_object_map() {
+  if (m_object_map == nullptr) {
+    revert();
+    finish();
+    return;
+  }
+
+  CephContext *cct = m_image_ctx.cct;
+  ldout(cct, 10) << __func__ << dendl;
+
+  using klass = PostAcquireRequest<I>;
+  Context *ctx = create_context_callback<
+    klass, &klass::handle_close_object_map>(this);
+  m_object_map->close(ctx);
+}
+
+template <typename I>
+void PostAcquireRequest<I>::handle_close_object_map(int r) {
+  CephContext *cct = m_image_ctx.cct;
+  ldout(cct, 10) << __func__ << ": r=" << r << dendl;
+
+  // object map should never result in an error
+  assert(r == 0);
+  revert();
+  finish();
+}
+
+template <typename I>
+void PostAcquireRequest<I>::apply() {
+  {
+    RWLock::WLocker snap_locker(m_image_ctx.snap_lock);
+    assert(m_image_ctx.object_map == nullptr);
+    m_image_ctx.object_map = m_object_map;
+
+    assert(m_image_ctx.journal == nullptr);
+    m_image_ctx.journal = m_journal;
+  }
+
+  m_prepare_lock_completed = true;
+  m_image_ctx.state->handle_prepare_lock_complete();
+}
+
+template <typename I>
+void PostAcquireRequest<I>::revert() {
+  RWLock::WLocker snap_locker(m_image_ctx.snap_lock);
+  m_image_ctx.object_map = nullptr;
+  m_image_ctx.journal = nullptr;
+
+  delete m_object_map;
+  delete m_journal;
+
+  assert(m_error_result < 0);
+}
+
+template <typename I>
+void PostAcquireRequest<I>::finish() {
+  m_on_finish->complete(m_error_result);
+  delete this;
+}
+
+} // namespace exclusive_lock
+} // namespace librbd
+
+template class librbd::exclusive_lock::PostAcquireRequest<librbd::ImageCtx>;
diff --git a/src/librbd/exclusive_lock/PostAcquireRequest.h b/src/librbd/exclusive_lock/PostAcquireRequest.h
new file mode 100644 (file)
index 0000000..92d2da9
--- /dev/null
@@ -0,0 +1,114 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#ifndef CEPH_LIBRBD_EXCLUSIVE_LOCK_POST_ACQUIRE_REQUEST_H
+#define CEPH_LIBRBD_EXCLUSIVE_LOCK_POST_ACQUIRE_REQUEST_H
+
+#include "include/int_types.h"
+#include "include/buffer.h"
+#include "librbd/ImageCtx.h"
+#include "msg/msg_types.h"
+#include <string>
+
+class Context;
+
+namespace librbd {
+
+template <typename> class Journal;
+template <typename> class ManagedLock;
+
+namespace exclusive_lock {
+
+template <typename ImageCtxT = ImageCtx>
+class PostAcquireRequest {
+public:
+  static PostAcquireRequest* create(ImageCtxT &image_ctx, Context *on_acquire,
+                                    Context *on_finish);
+
+  ~PostAcquireRequest();
+  void send();
+
+private:
+
+  /**
+   * @verbatim
+   *
+   *    <start>
+   *      |
+   *      |
+   *      v
+   * REFRESH (skip if not
+   *      |   needed)
+   *      v
+   * OPEN_OBJECT_MAP (skip if
+   *      |           disabled)
+   *      v
+   * OPEN_JOURNAL (skip if
+   *      |   *     disabled)
+   *      |   *
+   *      |   * * * * * * * *
+   *      v                 *
+   *  ALLOCATE_JOURNAL_TAG  *
+   *      |            *    *
+   *      |            *    *
+   *      |            v    v
+   *      |         CLOSE_JOURNAL
+   *      |               |
+   *      |               v
+   *      |         CLOSE_OBJECT_MAP
+   *      |               |
+   *      v               |
+   *  <finish> <----------/
+   *
+   * @endverbatim
+   */
+
+  PostAcquireRequest(ImageCtxT &image_ctx, Context *on_acquire,
+                     Context *on_finish);
+
+  ImageCtxT &m_image_ctx;
+  Context *m_on_acquire;
+  Context *m_on_finish;
+
+  decltype(m_image_ctx.object_map) m_object_map;
+  decltype(m_image_ctx.journal) m_journal;
+
+  bool m_prepare_lock_completed = false;
+  int m_error_result;
+
+  void send_refresh();
+  void handle_refresh(int r);
+
+  void send_open_journal();
+  void handle_open_journal(int r);
+
+  void send_allocate_journal_tag();
+  void handle_allocate_journal_tag(int r);
+
+  void send_open_object_map();
+  void handle_open_object_map(int r);
+
+  void send_close_journal();
+  void handle_close_journal(int r);
+
+  void send_close_object_map();
+  void handle_close_object_map(int r);
+
+  void apply();
+  void revert();
+
+  void finish();
+
+  void save_result(int result) {
+    if (m_error_result == 0 && result < 0) {
+      m_error_result = result;
+    }
+  }
+};
+
+} // namespace exclusive_lock
+} // namespace librbd
+
+extern template class librbd::exclusive_lock::PostAcquireRequest<librbd::ImageCtx>;
+
+#endif // CEPH_LIBRBD_EXCLUSIVE_LOCK_POST_ACQUIRE_REQUEST_H
diff --git a/src/librbd/exclusive_lock/PreAcquireRequest.cc b/src/librbd/exclusive_lock/PreAcquireRequest.cc
new file mode 100644 (file)
index 0000000..25ef480
--- /dev/null
@@ -0,0 +1,95 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "librbd/exclusive_lock/PreAcquireRequest.h"
+#include "librbd/Utils.h"
+#include "common/dout.h"
+#include "common/errno.h"
+#include "librbd/ImageCtx.h"
+#include "librbd/ImageWatcher.h"
+#include "librbd/ImageState.h"
+
+#define dout_subsys ceph_subsys_rbd
+#undef dout_prefix
+#define dout_prefix *_dout << "librbd::exclusive_lock::PreAcquireRequest: "
+
+namespace librbd {
+namespace exclusive_lock {
+
+using util::create_async_context_callback;
+using util::create_context_callback;
+using util::create_rados_ack_callback;
+using util::create_rados_safe_callback;
+
+
+template <typename I>
+PreAcquireRequest<I>* PreAcquireRequest<I>::create(I &image_ctx,
+                                                   Context *on_finish) {
+  return new PreAcquireRequest(image_ctx, on_finish);
+}
+
+template <typename I>
+PreAcquireRequest<I>::PreAcquireRequest(I &image_ctx, Context *on_finish)
+  : m_image_ctx(image_ctx),
+    m_on_finish(create_async_context_callback(image_ctx, on_finish)),
+    m_error_result(0) {
+}
+
+template <typename I>
+PreAcquireRequest<I>::~PreAcquireRequest() {
+}
+
+template <typename I>
+void PreAcquireRequest<I>::send() {
+  send_prepare_lock();
+}
+
+template <typename I>
+void PreAcquireRequest<I>::send_prepare_lock() {
+  CephContext *cct = m_image_ctx.cct;
+  ldout(cct, 10) << __func__ << dendl;
+
+  // acquire the lock if the image is not busy performing other actions
+  Context *ctx = create_context_callback<
+    PreAcquireRequest<I>, &PreAcquireRequest<I>::handle_prepare_lock>(this);
+  m_image_ctx.state->prepare_lock(ctx);
+}
+
+template <typename I>
+void PreAcquireRequest<I>::handle_prepare_lock(int r) {
+  CephContext *cct = m_image_ctx.cct;
+  ldout(cct, 10) << __func__ << ": r=" << r << dendl;
+
+  send_flush_notifies();
+}
+
+template <typename I>
+void PreAcquireRequest<I>::send_flush_notifies() {
+  CephContext *cct = m_image_ctx.cct;
+  ldout(cct, 10) << __func__ << dendl;
+
+  using klass = PreAcquireRequest<I>;
+  Context *ctx = create_context_callback<klass, &klass::handle_flush_notifies>(
+    this);
+  m_image_ctx.image_watcher->flush(ctx);
+}
+
+template <typename I>
+void PreAcquireRequest<I>::handle_flush_notifies(int r) {
+  CephContext *cct = m_image_ctx.cct;
+  ldout(cct, 10) << __func__ << dendl;
+
+  assert(r == 0);
+  finish();
+}
+
+template <typename I>
+void PreAcquireRequest<I>::finish() {
+  m_on_finish->complete(m_error_result);
+  delete this;
+}
+
+} // namespace exclusive_lock
+} // namespace librbd
+
+template class librbd::exclusive_lock::PreAcquireRequest<librbd::ImageCtx>;
diff --git a/src/librbd/exclusive_lock/PreAcquireRequest.h b/src/librbd/exclusive_lock/PreAcquireRequest.h
new file mode 100644 (file)
index 0000000..15d4b2c
--- /dev/null
@@ -0,0 +1,75 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#ifndef CEPH_LIBRBD_EXCLUSIVE_LOCK_PRE_ACQUIRE_REQUEST_H
+#define CEPH_LIBRBD_EXCLUSIVE_LOCK_PRE_ACQUIRE_REQUEST_H
+
+#include "include/int_types.h"
+#include "include/buffer.h"
+#include "librbd/ImageCtx.h"
+#include "msg/msg_types.h"
+#include <string>
+
+class Context;
+
+namespace librbd {
+
+namespace exclusive_lock {
+
+template <typename ImageCtxT = ImageCtx>
+class PreAcquireRequest {
+public:
+  static PreAcquireRequest* create(ImageCtxT &image_ctx, Context *on_finish);
+
+  ~PreAcquireRequest();
+  void send();
+
+private:
+
+  /**
+   * @verbatim
+   *
+   * <start>
+   *    |
+   *    v
+   * PREPARE_LOCK
+   *    |
+   *    v
+   * FLUSH_NOTIFIES
+   *    |
+   *    |
+   *    |
+        v
+   * <finish>
+   *
+   * @endverbatim
+   */
+
+  PreAcquireRequest(ImageCtxT &image_ctx, Context *on_finish);
+
+  ImageCtxT &m_image_ctx;
+  Context *m_on_finish;
+
+  int m_error_result;
+
+  void send_prepare_lock();
+  void handle_prepare_lock(int r);
+
+  void send_flush_notifies();
+  void handle_flush_notifies(int r);
+
+  void finish();
+
+  void save_result(int result) {
+    if (m_error_result == 0 && result < 0) {
+      m_error_result = result;
+    }
+  }
+};
+
+} // namespace exclusive_lock
+} // namespace librbd
+
+extern template class librbd::exclusive_lock::PreAcquireRequest<librbd::ImageCtx>;
+
+#endif // CEPH_LIBRBD_EXCLUSIVE_LOCK_ACQUIRE_REQUEST_H
diff --git a/src/librbd/exclusive_lock/PreReleaseRequest.cc b/src/librbd/exclusive_lock/PreReleaseRequest.cc
new file mode 100644 (file)
index 0000000..c03838f
--- /dev/null
@@ -0,0 +1,247 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "librbd/exclusive_lock/PreReleaseRequest.h"
+#include "common/dout.h"
+#include "common/errno.h"
+#include "librbd/AioImageRequestWQ.h"
+#include "librbd/ExclusiveLock.h"
+#include "librbd/ManagedLock.h"
+#include "librbd/ImageState.h"
+#include "librbd/ImageWatcher.h"
+#include "librbd/Journal.h"
+#include "librbd/ObjectMap.h"
+#include "librbd/Utils.h"
+
+#define dout_subsys ceph_subsys_rbd
+#undef dout_prefix
+#define dout_prefix *_dout << "librbd::exclusive_lock::PreReleaseRequest: "
+
+namespace librbd {
+namespace exclusive_lock {
+
+using util::create_async_context_callback;
+using util::create_context_callback;
+
+template <typename I>
+PreReleaseRequest<I>* PreReleaseRequest<I>::create(I &image_ctx,
+                                                   Context *on_releasing,
+                                                   Context *on_finish,
+                                                   bool shutting_down) {
+  return new PreReleaseRequest(image_ctx, on_releasing, on_finish,
+                               shutting_down);
+}
+
+template <typename I>
+PreReleaseRequest<I>::PreReleaseRequest(I &image_ctx, Context *on_releasing,
+                                        Context *on_finish, bool shutting_down)
+  : m_image_ctx(image_ctx), m_on_releasing(on_releasing),
+    m_on_finish(create_async_context_callback(image_ctx, on_finish)),
+    m_shutting_down(shutting_down), m_error_result(0), m_object_map(nullptr),
+    m_journal(nullptr) {
+}
+
+template <typename I>
+PreReleaseRequest<I>::~PreReleaseRequest() {
+  if (!m_shutting_down) {
+    m_image_ctx.state->handle_prepare_lock_complete();
+  }
+  delete m_on_releasing;
+}
+
+template <typename I>
+void PreReleaseRequest<I>::send() {
+  send_prepare_lock();
+}
+
+template <typename I>
+void PreReleaseRequest<I>::send_prepare_lock() {
+  if (m_shutting_down) {
+    send_cancel_op_requests();
+    return;
+  }
+
+  CephContext *cct = m_image_ctx.cct;
+  ldout(cct, 10) << __func__ << dendl;
+
+  // release the lock if the image is not busy performing other actions
+  Context *ctx = create_context_callback<
+    PreReleaseRequest<I>, &PreReleaseRequest<I>::handle_prepare_lock>(this);
+  m_image_ctx.state->prepare_lock(ctx);
+}
+
+template <typename I>
+void PreReleaseRequest<I>::handle_prepare_lock(int r) {
+  CephContext *cct = m_image_ctx.cct;
+  ldout(cct, 10) << __func__ << ": r=" << r << dendl;
+
+  send_cancel_op_requests();
+}
+
+template <typename I>
+void PreReleaseRequest<I>::send_cancel_op_requests() {
+  CephContext *cct = m_image_ctx.cct;
+  ldout(cct, 10) << __func__ << dendl;
+
+  using klass = PreReleaseRequest<I>;
+  Context *ctx = create_context_callback<
+    klass, &klass::handle_cancel_op_requests>(this);
+  m_image_ctx.cancel_async_requests(ctx);
+}
+
+template <typename I>
+void PreReleaseRequest<I>::handle_cancel_op_requests(int r) {
+  CephContext *cct = m_image_ctx.cct;
+  ldout(cct, 10) << __func__ << ": r=" << r << dendl;
+
+  assert(r == 0);
+
+  send_block_writes();
+}
+
+template <typename I>
+void PreReleaseRequest<I>::send_block_writes() {
+  CephContext *cct = m_image_ctx.cct;
+  ldout(cct, 10) << __func__ << dendl;
+
+  using klass = PreReleaseRequest<I>;
+  Context *ctx = create_context_callback<
+    klass, &klass::handle_block_writes>(this);
+
+  {
+    RWLock::RLocker owner_locker(m_image_ctx.owner_lock);
+    if (m_image_ctx.test_features(RBD_FEATURE_JOURNALING)) {
+      m_image_ctx.aio_work_queue->set_require_lock_on_read();
+    }
+    m_image_ctx.aio_work_queue->block_writes(ctx);
+  }
+}
+
+template <typename I>
+void PreReleaseRequest<I>::handle_block_writes(int r) {
+  CephContext *cct = m_image_ctx.cct;
+  ldout(cct, 10) << __func__ << ": r=" << r << dendl;
+
+  save_result(r);
+  if (r < 0) {
+    m_image_ctx.aio_work_queue->unblock_writes();
+    finish();
+    return;
+  }
+
+  send_image_flush_notifies();
+}
+
+template <typename I>
+void PreReleaseRequest<I>::send_image_flush_notifies() {
+  CephContext *cct = m_image_ctx.cct;
+  ldout(cct, 10) << __func__ << dendl;
+
+  using klass = PreReleaseRequest<I>;
+  Context *ctx =
+    create_context_callback<klass, &klass::handle_image_flush_notifies>(this);
+  m_image_ctx.image_watcher->flush(ctx);
+}
+
+template <typename I>
+void PreReleaseRequest<I>::handle_image_flush_notifies(int r) {
+  CephContext *cct = m_image_ctx.cct;
+  ldout(cct, 10) << __func__ << dendl;
+
+  assert(r == 0);
+  send_close_journal();
+}
+
+template <typename I>
+void PreReleaseRequest<I>::send_close_journal() {
+  {
+    RWLock::WLocker snap_locker(m_image_ctx.snap_lock);
+    std::swap(m_journal, m_image_ctx.journal);
+  }
+
+  if (m_journal == nullptr) {
+    send_close_object_map();
+    return;
+  }
+
+  CephContext *cct = m_image_ctx.cct;
+  ldout(cct, 10) << __func__ << dendl;
+
+  using klass = PreReleaseRequest<I>;
+  Context *ctx = create_context_callback<klass, &klass::handle_close_journal>(
+    this);
+  m_journal->close(ctx);
+}
+
+template <typename I>
+void PreReleaseRequest<I>::handle_close_journal(int r) {
+  CephContext *cct = m_image_ctx.cct;
+  ldout(cct, 10) << __func__ << ": r=" << r << dendl;
+
+  if (r < 0) {
+    // error implies some journal events were not flushed -- continue
+    lderr(cct) << "failed to close journal: " << cpp_strerror(r) << dendl;
+  }
+
+  delete m_journal;
+
+  send_close_object_map();
+}
+
+template <typename I>
+void PreReleaseRequest<I>::send_close_object_map() {
+  {
+    RWLock::WLocker snap_locker(m_image_ctx.snap_lock);
+    std::swap(m_object_map, m_image_ctx.object_map);
+  }
+
+  if (m_object_map == nullptr) {
+    send_unlock();
+    return;
+  }
+
+  CephContext *cct = m_image_ctx.cct;
+  ldout(cct, 10) << __func__ << dendl;
+
+  using klass = PreReleaseRequest<I>;
+  Context *ctx = create_context_callback<
+    klass, &klass::handle_close_object_map>(this);
+  m_object_map->close(ctx);
+}
+
+template <typename I>
+void PreReleaseRequest<I>::handle_close_object_map(int r) {
+  CephContext *cct = m_image_ctx.cct;
+  ldout(cct, 10) << __func__ << ": r=" << r << dendl;
+
+  // object map shouldn't return errors
+  assert(r == 0);
+  delete m_object_map;
+
+  send_unlock();
+}
+
+template <typename I>
+void PreReleaseRequest<I>::send_unlock() {
+  CephContext *cct = m_image_ctx.cct;
+  ldout(cct, 10) << __func__ << dendl;
+
+  if (m_on_releasing != nullptr) {
+    // alert caller that we no longer own the exclusive lock
+    m_on_releasing->complete(0);
+    m_on_releasing = nullptr;
+  }
+
+  finish();
+}
+
+template <typename I>
+void PreReleaseRequest<I>::finish() {
+  m_on_finish->complete(m_error_result);
+  delete this;
+}
+
+} // namespace exclusive_lock
+} // namespace librbd
+
+template class librbd::exclusive_lock::PreReleaseRequest<librbd::ImageCtx>;
diff --git a/src/librbd/exclusive_lock/PreReleaseRequest.h b/src/librbd/exclusive_lock/PreReleaseRequest.h
new file mode 100644 (file)
index 0000000..b51a5b7
--- /dev/null
@@ -0,0 +1,105 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#ifndef CEPH_LIBRBD_EXCLUSIVE_LOCK_PRE_RELEASE_REQUEST_H
+#define CEPH_LIBRBD_EXCLUSIVE_LOCK_PRE_RELEASE_REQUEST_H
+
+#include "librbd/ImageCtx.h"
+#include <string>
+
+class Context;
+
+namespace librbd {
+
+struct ImageCtx;
+template <typename> class ManagedLock;
+template <typename> class Journal;
+
+namespace exclusive_lock {
+
+template <typename ImageCtxT = ImageCtx>
+class PreReleaseRequest {
+public:
+  static PreReleaseRequest* create(ImageCtxT &image_ctx, Context *on_releasing,
+                                   Context *on_finish, bool shutting_down);
+
+  ~PreReleaseRequest();
+  void send();
+
+private:
+  /**
+   * @verbatim
+   *
+   * <start>
+   *    |
+   *    v
+   * PREPARE_LOCK
+   *    |
+   *    v
+   * CANCEL_OP_REQUESTS
+   *    |
+   *    v
+   * BLOCK_WRITES
+   *    |
+   *    v
+   * FLUSH_NOTIFIES . . . . . . . . . . . . . .
+   *    |                                     .
+   *    v                                     .
+   * CLOSE_JOURNAL                            .
+   *    |                (journal disabled,   .
+   *    v                 object map enabled) .
+   * CLOSE_OBJECT_MAP < . . . . . . . . . . . .
+   *    |                                     .
+   *    v               (object map disabled) .
+   * <finish> < . . . . . . . . . . . . . . . . .
+   *
+   * @endverbatim
+   */
+
+  PreReleaseRequest(ImageCtxT &image_ctx, Context *on_releasing,
+                    Context *on_finish, bool shutting_down);
+
+  ImageCtxT &m_image_ctx;
+  Context *m_on_releasing;
+  Context *m_on_finish;
+  bool m_shutting_down;
+
+  int m_error_result;
+
+  decltype(m_image_ctx.object_map) m_object_map;
+  decltype(m_image_ctx.journal) m_journal;
+
+  void send_prepare_lock();
+  void handle_prepare_lock(int r);
+
+  void send_cancel_op_requests();
+  void handle_cancel_op_requests(int r);
+
+  void send_block_writes();
+  void handle_block_writes(int r);
+
+  void send_image_flush_notifies();
+  void handle_image_flush_notifies(int r);
+
+  void send_close_journal();
+  void handle_close_journal(int r);
+
+  void send_close_object_map();
+  void handle_close_object_map(int r);
+
+  void send_unlock();
+
+  void finish();
+
+  void save_result(int result) {
+    if (m_error_result == 0 && result < 0) {
+      m_error_result = result;
+    }
+  }
+
+};
+
+} // namespace exclusive_lock
+} // namespace librbd
+
+#endif // CEPH_LIBRBD_EXCLUSIVE_LOCK_PRE_RELEASE_REQUEST_H
diff --git a/src/librbd/exclusive_lock/ReacquireRequest.cc b/src/librbd/exclusive_lock/ReacquireRequest.cc
deleted file mode 100644 (file)
index e847f65..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-
-#include "librbd/exclusive_lock/ReacquireRequest.h"
-#include "cls/lock/cls_lock_client.h"
-#include "cls/lock/cls_lock_types.h"
-#include "common/dout.h"
-#include "common/errno.h"
-#include "librbd/ExclusiveLock.h"
-#include "librbd/ImageCtx.h"
-#include "librbd/Utils.h"
-
-#define dout_subsys ceph_subsys_rbd
-#undef dout_prefix
-#define dout_prefix *_dout << "librbd::exclusive_lock::ReacquireRequest: " \
-                           << this << ": " << __func__
-
-namespace librbd {
-namespace exclusive_lock {
-
-using librbd::util::create_rados_safe_callback;
-
-template <typename I>
-ReacquireRequest<I>::ReacquireRequest(I &image_ctx,
-                                      const std::string &old_cookie,
-                                      const std::string &new_cookie,
-                                      Context *on_finish)
-  : m_image_ctx(image_ctx), m_old_cookie(old_cookie), m_new_cookie(new_cookie),
-    m_on_finish(on_finish) {
-}
-
-template <typename I>
-void ReacquireRequest<I>::send() {
-  set_cookie();
-}
-
-template <typename I>
-void ReacquireRequest<I>::set_cookie() {
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << dendl;
-
-  librados::ObjectWriteOperation op;
-  rados::cls::lock::set_cookie(&op, RBD_LOCK_NAME, LOCK_EXCLUSIVE, m_old_cookie,
-                               ExclusiveLock<>::WATCHER_LOCK_TAG, m_new_cookie);
-
-  librados::AioCompletion *rados_completion = create_rados_safe_callback<
-    ReacquireRequest<I>, &ReacquireRequest<I>::handle_set_cookie>(this);
-  int r = m_image_ctx.md_ctx.aio_operate(m_image_ctx.header_oid,
-                                         rados_completion, &op);
-  assert(r == 0);
-  rados_completion->release();
-}
-
-template <typename I>
-void ReacquireRequest<I>::handle_set_cookie(int r) {
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << ": r=" << r << dendl;
-
-  if (r == -EOPNOTSUPP) {
-    ldout(cct, 10) << ": OSD doesn't support updating lock" << dendl;
-  } else if (r < 0) {
-    lderr(cct) << ": failed to update lock: " << cpp_strerror(r) << dendl;
-  }
-
-  m_on_finish->complete(r);
-  delete this;
-}
-
-} // namespace exclusive_lock
-} // namespace librbd
-
-template class librbd::exclusive_lock::ReacquireRequest<librbd::ImageCtx>;
diff --git a/src/librbd/exclusive_lock/ReacquireRequest.h b/src/librbd/exclusive_lock/ReacquireRequest.h
deleted file mode 100644 (file)
index 2718bef..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-
-#ifndef CEPH_LIBRBD_EXCLUSIVE_LOCK_REACQUIRE_REQUEST_H
-#define CEPH_LIBRBD_EXCLUSIVE_LOCK_REACQUIRE_REQUEST_H
-
-#include "include/int_types.h"
-#include <string>
-
-class Context;
-
-namespace librbd {
-
-class ImageCtx;
-
-namespace exclusive_lock {
-
-template <typename ImageCtxT = ImageCtx>
-class ReacquireRequest {
-public:
-
-  static ReacquireRequest *create(ImageCtxT &image_ctx,
-                                  const std::string &old_cookie,
-                                  const std::string &new_cookie,
-                                  Context *on_finish) {
-    return new ReacquireRequest(image_ctx, old_cookie, new_cookie, on_finish);
-  }
-
-  ReacquireRequest(ImageCtxT &image_ctx, const std::string &old_cookie,
-                   const std::string &new_cookie, Context *on_finish);
-
-  void send();
-
-private:
-  /**
-   * @verbatim
-   *
-   * <start>
-   *    |
-   *    v
-   * SET_COOKIE
-   *    |
-   *    v
-   * <finish>
-   *
-   * @endverbatim
-   */
-  ImageCtxT &m_image_ctx;
-  std::string m_old_cookie;
-  std::string m_new_cookie;
-  Context *m_on_finish;
-
-  void set_cookie();
-  void handle_set_cookie(int r);
-
-};
-
-} // namespace exclusive_lock
-} // namespace librbd
-
-extern template class librbd::exclusive_lock::ReacquireRequest<librbd::ImageCtx>;
-
-#endif // CEPH_LIBRBD_EXCLUSIVE_LOCK_REACQUIRE_REQUEST_H
diff --git a/src/librbd/exclusive_lock/ReleaseRequest.cc b/src/librbd/exclusive_lock/ReleaseRequest.cc
deleted file mode 100644 (file)
index 52343f8..0000000
+++ /dev/null
@@ -1,272 +0,0 @@
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-
-#include "librbd/exclusive_lock/ReleaseRequest.h"
-#include "cls/lock/cls_lock_client.h"
-#include "cls/lock/cls_lock_types.h"
-#include "common/dout.h"
-#include "common/errno.h"
-#include "librbd/AioImageRequestWQ.h"
-#include "librbd/ExclusiveLock.h"
-#include "librbd/ImageState.h"
-#include "librbd/ImageWatcher.h"
-#include "librbd/Journal.h"
-#include "librbd/ObjectMap.h"
-#include "librbd/Utils.h"
-
-#define dout_subsys ceph_subsys_rbd
-#undef dout_prefix
-#define dout_prefix *_dout << "librbd::exclusive_lock::ReleaseRequest: "
-
-namespace librbd {
-namespace exclusive_lock {
-
-using util::create_async_context_callback;
-using util::create_context_callback;
-using util::create_rados_safe_callback;
-
-template <typename I>
-ReleaseRequest<I>* ReleaseRequest<I>::create(I &image_ctx,
-                                             const std::string &cookie,
-                                             Context *on_releasing,
-                                             Context *on_finish,
-                                             bool shutting_down) {
-  return new ReleaseRequest(image_ctx, cookie, on_releasing, on_finish,
-                            shutting_down);
-}
-
-template <typename I>
-ReleaseRequest<I>::ReleaseRequest(I &image_ctx, const std::string &cookie,
-                                  Context *on_releasing, Context *on_finish,
-                                  bool shutting_down)
-  : m_image_ctx(image_ctx), m_cookie(cookie), m_on_releasing(on_releasing),
-    m_on_finish(create_async_context_callback(image_ctx, on_finish)),
-    m_shutting_down(shutting_down), m_object_map(nullptr), m_journal(nullptr) {
-}
-
-template <typename I>
-ReleaseRequest<I>::~ReleaseRequest() {
-  if (!m_shutting_down) {
-    m_image_ctx.state->handle_prepare_lock_complete();
-  }
-  delete m_on_releasing;
-}
-
-template <typename I>
-void ReleaseRequest<I>::send() {
-  send_prepare_lock();
-}
-
-template <typename I>
-void ReleaseRequest<I>::send_prepare_lock() {
-  if (m_shutting_down) {
-    send_cancel_op_requests();
-    return;
-  }
-
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << dendl;
-
-  // release the lock if the image is not busy performing other actions
-  Context *ctx = create_context_callback<
-    ReleaseRequest<I>, &ReleaseRequest<I>::handle_prepare_lock>(this);
-  m_image_ctx.state->prepare_lock(ctx);
-}
-
-template <typename I>
-Context *ReleaseRequest<I>::handle_prepare_lock(int *ret_val) {
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << ": r=" << *ret_val << dendl;
-
-  send_cancel_op_requests();
-  return nullptr;
-}
-
-template <typename I>
-void ReleaseRequest<I>::send_cancel_op_requests() {
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << dendl;
-
-  using klass = ReleaseRequest<I>;
-  Context *ctx = create_context_callback<
-    klass, &klass::handle_cancel_op_requests>(this);
-  m_image_ctx.cancel_async_requests(ctx);
-}
-
-template <typename I>
-Context *ReleaseRequest<I>::handle_cancel_op_requests(int *ret_val) {
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << ": r=" << *ret_val << dendl;
-
-  assert(*ret_val == 0);
-
-  send_block_writes();
-  return nullptr;
-}
-
-template <typename I>
-void ReleaseRequest<I>::send_block_writes() {
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << dendl;
-
-  using klass = ReleaseRequest<I>;
-  Context *ctx = create_context_callback<
-    klass, &klass::handle_block_writes>(this);
-
-  {
-    RWLock::RLocker owner_locker(m_image_ctx.owner_lock);
-    if (m_image_ctx.test_features(RBD_FEATURE_JOURNALING)) {
-      m_image_ctx.aio_work_queue->set_require_lock_on_read();
-    }
-    m_image_ctx.aio_work_queue->block_writes(ctx);
-  }
-}
-
-template <typename I>
-Context *ReleaseRequest<I>::handle_block_writes(int *ret_val) {
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << ": r=" << *ret_val << dendl;
-
-  if (*ret_val < 0) {
-    m_image_ctx.aio_work_queue->unblock_writes();
-    return m_on_finish;
-  }
-
-  send_flush_notifies();
-  return nullptr;
-}
-
-template <typename I>
-void ReleaseRequest<I>::send_flush_notifies() {
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << dendl;
-
-  using klass = ReleaseRequest<I>;
-  Context *ctx = create_context_callback<
-    klass, &klass::handle_flush_notifies>(this);
-  m_image_ctx.image_watcher->flush(ctx);
-}
-
-template <typename I>
-Context *ReleaseRequest<I>::handle_flush_notifies(int *ret_val) {
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << dendl;
-
-  assert(*ret_val == 0);
-  send_close_journal();
-  return nullptr;
-}
-
-template <typename I>
-void ReleaseRequest<I>::send_close_journal() {
-  {
-    RWLock::WLocker snap_locker(m_image_ctx.snap_lock);
-    std::swap(m_journal, m_image_ctx.journal);
-  }
-
-  if (m_journal == nullptr) {
-    send_close_object_map();
-    return;
-  }
-
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << dendl;
-
-  using klass = ReleaseRequest<I>;
-  Context *ctx = create_context_callback<klass, &klass::handle_close_journal>(
-    this);
-  m_journal->close(ctx);
-}
-
-template <typename I>
-Context *ReleaseRequest<I>::handle_close_journal(int *ret_val) {
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << ": r=" << *ret_val << dendl;
-
-  if (*ret_val < 0) {
-    // error implies some journal events were not flushed -- continue
-    lderr(cct) << "failed to close journal: " << cpp_strerror(*ret_val)
-               << dendl;
-  }
-
-  delete m_journal;
-
-  send_close_object_map();
-  return nullptr;
-}
-
-template <typename I>
-void ReleaseRequest<I>::send_close_object_map() {
-  {
-    RWLock::WLocker snap_locker(m_image_ctx.snap_lock);
-    std::swap(m_object_map, m_image_ctx.object_map);
-  }
-
-  if (m_object_map == nullptr) {
-    send_unlock();
-    return;
-  }
-
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << dendl;
-
-  using klass = ReleaseRequest<I>;
-  Context *ctx = create_context_callback<
-    klass, &klass::handle_close_object_map>(this);
-  m_object_map->close(ctx);
-}
-
-template <typename I>
-Context *ReleaseRequest<I>::handle_close_object_map(int *ret_val) {
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << ": r=" << *ret_val << dendl;
-
-  // object map shouldn't return errors
-  assert(*ret_val == 0);
-  delete m_object_map;
-
-  send_unlock();
-  return nullptr;
-}
-
-template <typename I>
-void ReleaseRequest<I>::send_unlock() {
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << dendl;
-
-  if (m_on_releasing != nullptr) {
-    // alert caller that we no longer own the exclusive lock
-    m_on_releasing->complete(0);
-    m_on_releasing = nullptr;
-  }
-
-  librados::ObjectWriteOperation op;
-  rados::cls::lock::unlock(&op, RBD_LOCK_NAME, m_cookie);
-
-  using klass = ReleaseRequest<I>;
-  librados::AioCompletion *rados_completion =
-    create_rados_safe_callback<klass, &klass::handle_unlock>(this);
-  int r = m_image_ctx.md_ctx.aio_operate(m_image_ctx.header_oid,
-                                         rados_completion, &op);
-  assert(r == 0);
-  rados_completion->release();
-}
-
-template <typename I>
-Context *ReleaseRequest<I>::handle_unlock(int *ret_val) {
-  CephContext *cct = m_image_ctx.cct;
-  ldout(cct, 10) << __func__ << ": r=" << *ret_val << dendl;
-
-  if (*ret_val < 0 && *ret_val != -ENOENT) {
-    lderr(cct) << "failed to unlock: " << cpp_strerror(*ret_val) << dendl;
-  }
-
-  // treat errors as the image is unlocked
-  *ret_val = 0;
-  return m_on_finish;
-}
-
-} // namespace exclusive_lock
-} // namespace librbd
-
-template class librbd::exclusive_lock::ReleaseRequest<librbd::ImageCtx>;
diff --git a/src/librbd/exclusive_lock/ReleaseRequest.h b/src/librbd/exclusive_lock/ReleaseRequest.h
deleted file mode 100644 (file)
index 7c070ef..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-
-#ifndef CEPH_LIBRBD_EXCLUSIVE_LOCK_RELEASE_REQUEST_H
-#define CEPH_LIBRBD_EXCLUSIVE_LOCK_RELEASE_REQUEST_H
-
-#include "librbd/ImageCtx.h"
-#include <string>
-
-class Context;
-
-namespace librbd {
-
-class ImageCtx;
-template <typename> class Journal;
-
-namespace exclusive_lock {
-
-template <typename ImageCtxT = ImageCtx>
-class ReleaseRequest {
-public:
-  static ReleaseRequest* create(ImageCtxT &image_ctx, const std::string &cookie,
-                                Context *on_releasing, Context *on_finish,
-                                bool shutting_down);
-
-  ~ReleaseRequest();
-  void send();
-
-private:
-  /**
-   * @verbatim
-   *
-   * <start>
-   *    |
-   *    v
-   * PREPARE_LOCK
-   *    |
-   *    v
-   * CANCEL_OP_REQUESTS
-   *    |
-   *    v
-   * BLOCK_WRITES
-   *    |
-   *    v
-   * FLUSH_NOTIFIES . . . . . . . . . . . . . .
-   *    |                                     .
-   *    v                                     .
-   * CLOSE_JOURNAL                            .
-   *    |                (journal disabled,   .
-   *    v                 object map enabled) .
-   * CLOSE_OBJECT_MAP < . . . . . . . . . . . .
-   *    |                                     .
-   *    v               (object map disabled) .
-   * UNLOCK < . . . . . . . . . . . . . . . . .
-   *    |
-   *    v
-   * <finish>
-   *
-   * @endverbatim
-   */
-
-  ReleaseRequest(ImageCtxT &image_ctx, const std::string &cookie,
-                 Context *on_releasing, Context *on_finish,
-                 bool shutting_down);
-
-  ImageCtxT &m_image_ctx;
-  std::string m_cookie;
-  Context *m_on_releasing;
-  Context *m_on_finish;
-  bool m_shutting_down;
-
-  decltype(m_image_ctx.object_map) m_object_map;
-  decltype(m_image_ctx.journal) m_journal;
-
-  void send_prepare_lock();
-  Context *handle_prepare_lock(int *ret_val);
-
-  void send_cancel_op_requests();
-  Context *handle_cancel_op_requests(int *ret_val);
-
-  void send_block_writes();
-  Context *handle_block_writes(int *ret_val);
-
-  void send_flush_notifies();
-  Context *handle_flush_notifies(int *ret_val);
-
-  void send_close_journal();
-  Context *handle_close_journal(int *ret_val);
-
-  void send_close_object_map();
-  Context *handle_close_object_map(int *ret_val);
-
-  void send_unlock();
-  Context *handle_unlock(int *ret_val);
-
-};
-
-} // namespace exclusive_lock
-} // namespace librbd
-
-extern template class librbd::exclusive_lock::ReleaseRequest<librbd::ImageCtx>;
-
-#endif // CEPH_LIBRBD_EXCLUSIVE_LOCK_RELEASE_REQUEST_H
index 7815bc09ce3e6b07120f31c2f8d0a94e86f4a871..bfe226bdb326b298048d61dc76cc01bbd09a5e6c 100644 (file)
@@ -1438,7 +1438,7 @@ int mirror_image_disable_internal(ImageCtx *ictx, bool force,
        return 0;
       }
 
-      ictx->exclusive_lock->request_lock(&lock_ctx);
+      ictx->exclusive_lock->acquire_lock(&lock_ctx);
     }
 
     int r = lock_ctx.wait();
@@ -2580,7 +2580,7 @@ int mirror_image_disable_internal(ImageCtx *ictx, bool force,
     };
 
     C_SaferCond lock_ctx;
-    ictx->exclusive_lock->request_lock(&lock_ctx);
+    ictx->exclusive_lock->acquire_lock(&lock_ctx);
 
     // don't block holding lock since refresh might be required
     ictx->owner_lock.put_read();
index 591f8201be18cb2c7fabbc69284073d2b5a28dbb..5084180a517f4cec42820a217eea1ea3392c3be2 100644 (file)
@@ -139,7 +139,7 @@ void AcquireRequest<I>::handle_get_lockers(int r) {
 
   std::map<rados::cls::lock::locker_id_t,
            rados::cls::lock::locker_info_t> lockers;
-  ClsLockType lock_type;
+  ClsLockType lock_type = LOCK_NONE;
   std::string lock_tag;
 
   if (r == 0) {
index bd9edf6edcc9b5117bd5d17528be2361292a09a3..b7e9bc473c4c7bc307c2709db47c4e70869bef2c 100644 (file)
@@ -144,7 +144,7 @@ void DisableFeaturesRequest<I>::send_acquire_exclusive_lock() {
        !image_ctx.exclusive_lock->is_lock_owner()) {
       m_acquired_lock = true;
 
-      image_ctx.exclusive_lock->request_lock(ctx);
+      image_ctx.exclusive_lock->acquire_lock(ctx);
       return;
     }
   }
index e3d6dbbb6ee0aabc4c56ecdbb5c62f9366adc681..b84abaf68105abdaab363393bd33b5215f495616 100644 (file)
@@ -31,9 +31,9 @@ set(unittest_librbd_srcs
   test_mock_ExclusiveLock.cc
   test_mock_Journal.cc
   test_mock_ObjectMap.cc
-  exclusive_lock/test_mock_AcquireRequest.cc
-  exclusive_lock/test_mock_ReacquireRequest.cc
-  exclusive_lock/test_mock_ReleaseRequest.cc
+  exclusive_lock/test_mock_PreAcquireRequest.cc
+  exclusive_lock/test_mock_PostAcquireRequest.cc
+  exclusive_lock/test_mock_PreReleaseRequest.cc
   image/test_mock_RefreshRequest.cc
   journal/test_mock_OpenRequest.cc
   journal/test_mock_PromoteRequest.cc
diff --git a/src/test/librbd/exclusive_lock/test_mock_AcquireRequest.cc b/src/test/librbd/exclusive_lock/test_mock_AcquireRequest.cc
deleted file mode 100644 (file)
index ee45488..0000000
+++ /dev/null
@@ -1,924 +0,0 @@
-// -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-
-#include "test/librbd/test_mock_fixture.h"
-#include "test/librbd/test_support.h"
-#include "test/librbd/mock/MockImageCtx.h"
-#include "test/librbd/mock/MockImageState.h"
-#include "test/librbd/mock/MockJournal.h"
-#include "test/librbd/mock/MockJournalPolicy.h"
-#include "test/librbd/mock/MockObjectMap.h"
-#include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
-#include "test/librados_test_stub/MockTestMemRadosClient.h"
-#include "cls/lock/cls_lock_ops.h"
-#include "librbd/ExclusiveLock.h"
-#include "librbd/exclusive_lock/AcquireRequest.h"
-#include "librbd/image/RefreshRequest.h"
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include <arpa/inet.h>
-#include <list>
-
-namespace librbd {
-namespace {
-
-struct MockTestImageCtx : public librbd::MockImageCtx {
-  MockTestImageCtx(librbd::ImageCtx &image_ctx)
-    : librbd::MockImageCtx(image_ctx) {
-  }
-};
-
-} // anonymous namespace
-
-namespace image {
-
-template<>
-struct RefreshRequest<librbd::MockTestImageCtx> {
-  static RefreshRequest *s_instance;
-  Context *on_finish;
-
-  static RefreshRequest *create(librbd::MockTestImageCtx &image_ctx,
-                                bool acquire_lock_refresh,
-                                Context *on_finish) {
-    EXPECT_TRUE(acquire_lock_refresh);
-    assert(s_instance != nullptr);
-    s_instance->on_finish = on_finish;
-    return s_instance;
-  }
-
-  RefreshRequest() {
-    s_instance = this;
-  }
-  MOCK_METHOD0(send, void());
-};
-
-RefreshRequest<librbd::MockTestImageCtx> *RefreshRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
-
-} // namespace image
-} // namespace librbd
-
-// template definitions
-#include "librbd/Journal.cc"
-#include "librbd/exclusive_lock/AcquireRequest.cc"
-template class librbd::exclusive_lock::AcquireRequest<librbd::MockTestImageCtx>;
-
-namespace librbd {
-namespace exclusive_lock {
-
-using ::testing::_;
-using ::testing::DoAll;
-using ::testing::InSequence;
-using ::testing::Invoke;
-using ::testing::Return;
-using ::testing::SetArgPointee;
-using ::testing::StrEq;
-using ::testing::WithArg;
-
-static const std::string TEST_COOKIE("auto 123");
-
-class TestMockExclusiveLockAcquireRequest : public TestMockFixture {
-public:
-  typedef AcquireRequest<MockTestImageCtx> MockAcquireRequest;
-  typedef ExclusiveLock<MockTestImageCtx> MockExclusiveLock;
-  typedef librbd::image::RefreshRequest<MockTestImageCtx> MockRefreshRequest;
-
-  void expect_test_features(MockTestImageCtx &mock_image_ctx, uint64_t features,
-                            bool enabled) {
-    EXPECT_CALL(mock_image_ctx, test_features(features))
-                  .WillOnce(Return(enabled));
-  }
-
-  void expect_test_features(MockTestImageCtx &mock_image_ctx, uint64_t features,
-                            RWLock &lock, bool enabled) {
-    EXPECT_CALL(mock_image_ctx, test_features(features, _))
-                  .WillOnce(Return(enabled));
-  }
-
-  void expect_lock(MockTestImageCtx &mock_image_ctx, int r) {
-    EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
-                exec(mock_image_ctx.header_oid, _, StrEq("lock"), StrEq("lock"), _, _, _))
-                  .WillOnce(Return(r));
-  }
-
-  void expect_unlock(MockTestImageCtx &mock_image_ctx, int r) {
-    EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
-                exec(mock_image_ctx.header_oid, _, StrEq("lock"), StrEq("unlock"), _, _, _))
-                  .WillOnce(Return(r));
-  }
-
-  void expect_is_refresh_required(MockTestImageCtx &mock_image_ctx, bool required) {
-    EXPECT_CALL(*mock_image_ctx.state, is_refresh_required())
-      .WillOnce(Return(required));
-  }
-
-  void expect_refresh(MockTestImageCtx &mock_image_ctx,
-                      MockRefreshRequest &mock_refresh_request, int r) {
-    EXPECT_CALL(mock_refresh_request, send())
-                  .WillOnce(FinishRequest(&mock_refresh_request, r,
-                                          &mock_image_ctx));
-  }
-
-  void expect_create_object_map(MockTestImageCtx &mock_image_ctx,
-                                MockObjectMap *mock_object_map) {
-    EXPECT_CALL(mock_image_ctx, create_object_map(_))
-                  .WillOnce(Return(mock_object_map));
-  }
-
-  void expect_open_object_map(MockTestImageCtx &mock_image_ctx,
-                              MockObjectMap &mock_object_map, int r) {
-    EXPECT_CALL(mock_object_map, open(_))
-                  .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
-  }
-
-  void expect_close_object_map(MockTestImageCtx &mock_image_ctx,
-                              MockObjectMap &mock_object_map) {
-    EXPECT_CALL(mock_object_map, close(_))
-                  .WillOnce(CompleteContext(0, mock_image_ctx.image_ctx->op_work_queue));
-  }
-
-  void expect_create_journal(MockTestImageCtx &mock_image_ctx,
-                             MockJournal *mock_journal) {
-    EXPECT_CALL(mock_image_ctx, create_journal())
-                  .WillOnce(Return(mock_journal));
-  }
-
-  void expect_open_journal(MockTestImageCtx &mock_image_ctx,
-                           MockJournal &mock_journal, int r) {
-    EXPECT_CALL(mock_journal, open(_))
-                  .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
-  }
-
-  void expect_close_journal(MockTestImageCtx &mock_image_ctx,
-                            MockJournal &mock_journal) {
-    EXPECT_CALL(mock_journal, close(_))
-                  .WillOnce(CompleteContext(0, mock_image_ctx.image_ctx->op_work_queue));
-  }
-
-  void expect_get_journal_policy(MockTestImageCtx &mock_image_ctx,
-                                 MockJournalPolicy &mock_journal_policy) {
-    EXPECT_CALL(mock_image_ctx, get_journal_policy())
-                  .WillOnce(Return(&mock_journal_policy));
-  }
-
-  void expect_journal_disabled(MockJournalPolicy &mock_journal_policy,
-                               bool disabled) {
-    EXPECT_CALL(mock_journal_policy, journal_disabled())
-      .WillOnce(Return(disabled));
-  }
-
-  void expect_allocate_journal_tag(MockTestImageCtx &mock_image_ctx,
-                                   MockJournalPolicy &mock_journal_policy,
-                                   int r) {
-    EXPECT_CALL(mock_journal_policy, allocate_tag_on_lock(_))
-                  .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
-  }
-
-  void expect_get_lock_info(MockTestImageCtx &mock_image_ctx, int r,
-                            const entity_name_t &locker_entity,
-                            const std::string &locker_address,
-                            const std::string &locker_cookie,
-                            const std::string &lock_tag,
-                            ClsLockType lock_type) {
-    auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
-                               exec(mock_image_ctx.header_oid, _, StrEq("lock"),
-                               StrEq("get_info"), _, _, _));
-    if (r < 0 && r != -ENOENT) {
-      expect.WillOnce(Return(r));
-    } else {
-      entity_name_t entity(locker_entity);
-      entity_addr_t entity_addr;
-      entity_addr.parse(locker_address.c_str(), NULL);
-
-      cls_lock_get_info_reply reply;
-      if (r != -ENOENT) {
-        reply.lockers = decltype(reply.lockers){
-          {rados::cls::lock::locker_id_t(entity, locker_cookie),
-           rados::cls::lock::locker_info_t(utime_t(), entity_addr, "")}};
-        reply.tag = lock_tag;
-        reply.lock_type = lock_type;
-      }
-
-      bufferlist bl;
-      ::encode(reply, bl, CEPH_FEATURES_SUPPORTED_DEFAULT);
-
-      std::string str(bl.c_str(), bl.length());
-      expect.WillOnce(DoAll(WithArg<5>(CopyInBufferlist(str)), Return(0)));
-    }
-  }
-
-  void expect_list_watchers(MockTestImageCtx &mock_image_ctx, int r,
-                            const std::string &address, uint64_t watch_handle) {
-    auto &expect = EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
-                               list_watchers(mock_image_ctx.header_oid, _));
-    if (r < 0) {
-      expect.WillOnce(Return(r));
-    } else {
-      obj_watch_t watcher;
-      strcpy(watcher.addr, (address + ":0/0").c_str());
-      watcher.cookie = watch_handle;
-
-      std::list<obj_watch_t> watchers;
-      watchers.push_back(watcher);
-
-      expect.WillOnce(DoAll(SetArgPointee<1>(watchers), Return(0)));
-    }
-  }
-
-  void expect_blacklist_add(MockTestImageCtx &mock_image_ctx, int r) {
-    EXPECT_CALL(get_mock_rados_client(), blacklist_add(_, _))
-                  .WillOnce(Return(r));
-  }
-
-  void expect_break_lock(MockTestImageCtx &mock_image_ctx, int r) {
-    EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
-                exec(mock_image_ctx.header_oid, _, StrEq("lock"), StrEq("break_lock"), _, _, _))
-                  .WillOnce(Return(r));
-  }
-
-  void expect_flush_notifies(MockTestImageCtx &mock_image_ctx) {
-    EXPECT_CALL(*mock_image_ctx.image_watcher, flush(_))
-                  .WillOnce(CompleteContext(0, mock_image_ctx.image_ctx->op_work_queue));
-  }
-
-  void expect_prepare_lock(MockTestImageCtx &mock_image_ctx) {
-    EXPECT_CALL(*mock_image_ctx.state, prepare_lock(_))
-      .WillOnce(Invoke([](Context *on_ready) {
-                  on_ready->complete(0);
-                }));
-  }
-
-  void expect_handle_prepare_lock_complete(MockTestImageCtx &mock_image_ctx) {
-    EXPECT_CALL(*mock_image_ctx.state, handle_prepare_lock_complete());
-  }
-
-};
-
-TEST_F(TestMockExclusiveLockAcquireRequest, Success) {
-  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
-
-  librbd::ImageCtx *ictx;
-  ASSERT_EQ(0, open_image(m_image_name, &ictx));
-
-  MockTestImageCtx mock_image_ctx(*ictx);
-  expect_op_work_queue(mock_image_ctx);
-
-  InSequence seq;
-  expect_prepare_lock(mock_image_ctx);
-  expect_flush_notifies(mock_image_ctx);
-  expect_lock(mock_image_ctx, 0);
-  expect_is_refresh_required(mock_image_ctx, false);
-
-  MockObjectMap mock_object_map;
-  expect_test_features(mock_image_ctx, RBD_FEATURE_OBJECT_MAP, true);
-  expect_create_object_map(mock_image_ctx, &mock_object_map);
-  expect_open_object_map(mock_image_ctx, mock_object_map, 0);
-
-  MockJournal mock_journal;
-  MockJournalPolicy mock_journal_policy;
-  expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING,
-                       mock_image_ctx.snap_lock, true);
-  expect_get_journal_policy(mock_image_ctx, mock_journal_policy);
-  expect_journal_disabled(mock_journal_policy, false);
-  expect_create_journal(mock_image_ctx, &mock_journal);
-  expect_handle_prepare_lock_complete(mock_image_ctx);
-  expect_open_journal(mock_image_ctx, mock_journal, 0);
-  expect_get_journal_policy(mock_image_ctx, mock_journal_policy);
-  expect_allocate_journal_tag(mock_image_ctx, mock_journal_policy, 0);
-
-  C_SaferCond acquire_ctx;
-  C_SaferCond ctx;
-  MockAcquireRequest *req = MockAcquireRequest::create(mock_image_ctx,
-                                                       TEST_COOKIE,
-                                                       &acquire_ctx, &ctx);
-  req->send();
-  ASSERT_EQ(0, acquire_ctx.wait());
-  ASSERT_EQ(0, ctx.wait());
-}
-
-TEST_F(TestMockExclusiveLockAcquireRequest, SuccessRefresh) {
-  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
-
-  librbd::ImageCtx *ictx;
-  ASSERT_EQ(0, open_image(m_image_name, &ictx));
-
-  MockTestImageCtx mock_image_ctx(*ictx);
-  MockRefreshRequest mock_refresh_request;
-  expect_op_work_queue(mock_image_ctx);
-
-  InSequence seq;
-  expect_prepare_lock(mock_image_ctx);
-  expect_flush_notifies(mock_image_ctx);
-  expect_lock(mock_image_ctx, 0);
-  expect_is_refresh_required(mock_image_ctx, true);
-  expect_refresh(mock_image_ctx, mock_refresh_request, 0);
-
-  MockObjectMap mock_object_map;
-  expect_test_features(mock_image_ctx, RBD_FEATURE_OBJECT_MAP, false);
-  expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING,
-                       mock_image_ctx.snap_lock, false);
-  expect_handle_prepare_lock_complete(mock_image_ctx);
-
-  C_SaferCond acquire_ctx;
-  C_SaferCond ctx;
-  MockAcquireRequest *req = MockAcquireRequest::create(mock_image_ctx,
-                                                       TEST_COOKIE,
-                                                       &acquire_ctx, &ctx);
-  req->send();
-  ASSERT_EQ(0, acquire_ctx.wait());
-  ASSERT_EQ(0, ctx.wait());
-}
-
-TEST_F(TestMockExclusiveLockAcquireRequest, SuccessJournalDisabled) {
-  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
-
-  librbd::ImageCtx *ictx;
-  ASSERT_EQ(0, open_image(m_image_name, &ictx));
-
-  MockTestImageCtx mock_image_ctx(*ictx);
-  expect_op_work_queue(mock_image_ctx);
-
-  InSequence seq;
-  expect_prepare_lock(mock_image_ctx);
-  expect_flush_notifies(mock_image_ctx);
-  expect_lock(mock_image_ctx, 0);
-  expect_is_refresh_required(mock_image_ctx, false);
-
-  MockObjectMap mock_object_map;
-  expect_test_features(mock_image_ctx, RBD_FEATURE_OBJECT_MAP, true);
-  expect_create_object_map(mock_image_ctx, &mock_object_map);
-  expect_open_object_map(mock_image_ctx, mock_object_map, 0);
-
-  expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING,
-                       mock_image_ctx.snap_lock, false);
-  expect_handle_prepare_lock_complete(mock_image_ctx);
-
-  C_SaferCond acquire_ctx;
-  C_SaferCond ctx;
-  MockAcquireRequest *req = MockAcquireRequest::create(mock_image_ctx,
-                                                       TEST_COOKIE,
-                                                       &acquire_ctx, &ctx);
-  req->send();
-  ASSERT_EQ(0, acquire_ctx.wait());
-  ASSERT_EQ(0, ctx.wait());
-}
-
-TEST_F(TestMockExclusiveLockAcquireRequest, SuccessObjectMapDisabled) {
-  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
-
-  librbd::ImageCtx *ictx;
-  ASSERT_EQ(0, open_image(m_image_name, &ictx));
-
-  MockTestImageCtx mock_image_ctx(*ictx);
-  expect_op_work_queue(mock_image_ctx);
-
-  InSequence seq;
-  expect_prepare_lock(mock_image_ctx);
-  expect_flush_notifies(mock_image_ctx);
-  expect_lock(mock_image_ctx, 0);
-  expect_is_refresh_required(mock_image_ctx, false);
-
-  expect_test_features(mock_image_ctx, RBD_FEATURE_OBJECT_MAP, false);
-
-  MockJournal mock_journal;
-  MockJournalPolicy mock_journal_policy;
-  expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING,
-                       mock_image_ctx.snap_lock, true);
-  expect_get_journal_policy(mock_image_ctx, mock_journal_policy);
-  expect_journal_disabled(mock_journal_policy, false);
-  expect_create_journal(mock_image_ctx, &mock_journal);
-  expect_handle_prepare_lock_complete(mock_image_ctx);
-  expect_open_journal(mock_image_ctx, mock_journal, 0);
-  expect_get_journal_policy(mock_image_ctx, mock_journal_policy);
-  expect_allocate_journal_tag(mock_image_ctx, mock_journal_policy, 0);
-
-  C_SaferCond acquire_ctx;
-  C_SaferCond ctx;
-  MockAcquireRequest *req = MockAcquireRequest::create(mock_image_ctx,
-                                                       TEST_COOKIE,
-                                                       &acquire_ctx, &ctx);
-  req->send();
-  ASSERT_EQ(0, acquire_ctx.wait());
-  ASSERT_EQ(0, ctx.wait());
-}
-
-TEST_F(TestMockExclusiveLockAcquireRequest, RefreshError) {
-  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
-
-  librbd::ImageCtx *ictx;
-  ASSERT_EQ(0, open_image(m_image_name, &ictx));
-
-  MockTestImageCtx mock_image_ctx(*ictx);
-  MockRefreshRequest mock_refresh_request;
-  expect_op_work_queue(mock_image_ctx);
-
-  InSequence seq;
-  expect_prepare_lock(mock_image_ctx);
-  expect_flush_notifies(mock_image_ctx);
-  expect_lock(mock_image_ctx, 0);
-  expect_is_refresh_required(mock_image_ctx, true);
-  expect_refresh(mock_image_ctx, mock_refresh_request, -EINVAL);
-  expect_unlock(mock_image_ctx, 0);
-  expect_handle_prepare_lock_complete(mock_image_ctx);
-
-  C_SaferCond *acquire_ctx = new C_SaferCond();
-  C_SaferCond ctx;
-  MockAcquireRequest *req = MockAcquireRequest::create(mock_image_ctx,
-                                                       TEST_COOKIE,
-                                                       acquire_ctx, &ctx);
-  req->send();
-  ASSERT_EQ(-EINVAL, ctx.wait());
-}
-
-TEST_F(TestMockExclusiveLockAcquireRequest, RefreshLockDisabled) {
-  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
-
-  librbd::ImageCtx *ictx;
-  ASSERT_EQ(0, open_image(m_image_name, &ictx));
-
-  MockTestImageCtx mock_image_ctx(*ictx);
-  MockRefreshRequest mock_refresh_request;
-  expect_op_work_queue(mock_image_ctx);
-
-  InSequence seq;
-  expect_prepare_lock(mock_image_ctx);
-  expect_flush_notifies(mock_image_ctx);
-  expect_lock(mock_image_ctx, 0);
-  expect_is_refresh_required(mock_image_ctx, true);
-  expect_refresh(mock_image_ctx, mock_refresh_request, -ERESTART);
-
-  MockObjectMap mock_object_map;
-  expect_test_features(mock_image_ctx, RBD_FEATURE_OBJECT_MAP, false);
-  expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING,
-                       mock_image_ctx.snap_lock, false);
-  expect_handle_prepare_lock_complete(mock_image_ctx);
-
-  C_SaferCond acquire_ctx;
-  C_SaferCond ctx;
-  MockAcquireRequest *req = MockAcquireRequest::create(mock_image_ctx,
-                                                       TEST_COOKIE,
-                                                       &acquire_ctx, &ctx);
-  req->send();
-  ASSERT_EQ(0, acquire_ctx.wait());
-  ASSERT_EQ(0, ctx.wait());
-}
-
-TEST_F(TestMockExclusiveLockAcquireRequest, JournalError) {
-  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
-
-  librbd::ImageCtx *ictx;
-  ASSERT_EQ(0, open_image(m_image_name, &ictx));
-
-  MockTestImageCtx mock_image_ctx(*ictx);
-  expect_op_work_queue(mock_image_ctx);
-
-  InSequence seq;
-  expect_prepare_lock(mock_image_ctx);
-  expect_flush_notifies(mock_image_ctx);
-  expect_lock(mock_image_ctx, 0);
-  expect_is_refresh_required(mock_image_ctx, false);
-
-  MockObjectMap *mock_object_map = new MockObjectMap();
-  expect_test_features(mock_image_ctx, RBD_FEATURE_OBJECT_MAP, true);
-  expect_create_object_map(mock_image_ctx, mock_object_map);
-  expect_open_object_map(mock_image_ctx, *mock_object_map, 0);
-
-  MockJournal *mock_journal = new MockJournal();
-  MockJournalPolicy mock_journal_policy;
-  expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING,
-                       mock_image_ctx.snap_lock, true);
-  expect_get_journal_policy(mock_image_ctx, mock_journal_policy);
-  expect_journal_disabled(mock_journal_policy, false);
-  expect_create_journal(mock_image_ctx, mock_journal);
-  expect_handle_prepare_lock_complete(mock_image_ctx);
-  expect_open_journal(mock_image_ctx, *mock_journal, -EINVAL);
-  expect_close_journal(mock_image_ctx, *mock_journal);
-  expect_close_object_map(mock_image_ctx, *mock_object_map);
-  expect_unlock(mock_image_ctx, 0);
-
-  C_SaferCond acquire_ctx;
-  C_SaferCond ctx;
-  MockAcquireRequest *req = MockAcquireRequest::create(mock_image_ctx,
-                                                       TEST_COOKIE,
-                                                       &acquire_ctx, &ctx);
-  req->send();
-  ASSERT_EQ(-EINVAL, ctx.wait());
-}
-
-TEST_F(TestMockExclusiveLockAcquireRequest, AllocateJournalTagError) {
-  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
-
-  librbd::ImageCtx *ictx;
-  ASSERT_EQ(0, open_image(m_image_name, &ictx));
-
-  MockTestImageCtx mock_image_ctx(*ictx);
-  expect_op_work_queue(mock_image_ctx);
-
-  InSequence seq;
-  expect_prepare_lock(mock_image_ctx);
-  expect_flush_notifies(mock_image_ctx);
-  expect_lock(mock_image_ctx, 0);
-  expect_is_refresh_required(mock_image_ctx, false);
-
-  MockObjectMap *mock_object_map = new MockObjectMap();
-  expect_test_features(mock_image_ctx, RBD_FEATURE_OBJECT_MAP, true);
-  expect_create_object_map(mock_image_ctx, mock_object_map);
-  expect_open_object_map(mock_image_ctx, *mock_object_map, 0);
-
-  MockJournal *mock_journal = new MockJournal();
-  MockJournalPolicy mock_journal_policy;
-  expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING,
-                       mock_image_ctx.snap_lock, true);
-  expect_get_journal_policy(mock_image_ctx, mock_journal_policy);
-  expect_journal_disabled(mock_journal_policy, false);
-  expect_create_journal(mock_image_ctx, mock_journal);
-  expect_handle_prepare_lock_complete(mock_image_ctx);
-  expect_open_journal(mock_image_ctx, *mock_journal, 0);
-  expect_get_journal_policy(mock_image_ctx, mock_journal_policy);
-  expect_allocate_journal_tag(mock_image_ctx, mock_journal_policy, -EPERM);
-  expect_close_journal(mock_image_ctx, *mock_journal);
-  expect_close_object_map(mock_image_ctx, *mock_object_map);
-  expect_unlock(mock_image_ctx, 0);
-
-  C_SaferCond acquire_ctx;
-  C_SaferCond ctx;
-  MockAcquireRequest *req = MockAcquireRequest::create(mock_image_ctx,
-                                                       TEST_COOKIE,
-                                                       &acquire_ctx, &ctx);
-  req->send();
-  ASSERT_EQ(-EPERM, ctx.wait());
-}
-
-TEST_F(TestMockExclusiveLockAcquireRequest, LockBusy) {
-  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
-
-  librbd::ImageCtx *ictx;
-  ASSERT_EQ(0, open_image(m_image_name, &ictx));
-
-  MockTestImageCtx mock_image_ctx(*ictx);
-  expect_op_work_queue(mock_image_ctx);
-
-  InSequence seq;
-  expect_prepare_lock(mock_image_ctx);
-  expect_flush_notifies(mock_image_ctx);
-  expect_lock(mock_image_ctx, -EBUSY);
-  expect_get_lock_info(mock_image_ctx, 0, entity_name_t::CLIENT(1), "1.2.3.4",
-                       "auto 123", ExclusiveLock<>::WATCHER_LOCK_TAG,
-                       LOCK_EXCLUSIVE);
-  expect_list_watchers(mock_image_ctx, 0, "dead client", 123);
-  expect_blacklist_add(mock_image_ctx, 0);
-  expect_break_lock(mock_image_ctx, 0);
-  expect_lock(mock_image_ctx, -ENOENT);
-  expect_handle_prepare_lock_complete(mock_image_ctx);
-
-  C_SaferCond ctx;
-  MockAcquireRequest *req = MockAcquireRequest::create(mock_image_ctx,
-                                                       TEST_COOKIE,
-                                                       nullptr, &ctx);
-  req->send();
-  ASSERT_EQ(-ENOENT, ctx.wait());
-}
-
-TEST_F(TestMockExclusiveLockAcquireRequest, GetLockInfoError) {
-  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
-
-  librbd::ImageCtx *ictx;
-  ASSERT_EQ(0, open_image(m_image_name, &ictx));
-
-  MockTestImageCtx mock_image_ctx(*ictx);
-  expect_op_work_queue(mock_image_ctx);
-
-  InSequence seq;
-  expect_prepare_lock(mock_image_ctx);
-  expect_flush_notifies(mock_image_ctx);
-  expect_lock(mock_image_ctx, -EBUSY);
-  expect_get_lock_info(mock_image_ctx, -EINVAL, entity_name_t::CLIENT(1), "",
-                       "", "", LOCK_EXCLUSIVE);
-  expect_handle_prepare_lock_complete(mock_image_ctx);
-
-  C_SaferCond ctx;
-  MockAcquireRequest *req = MockAcquireRequest::create(mock_image_ctx,
-                                                       TEST_COOKIE,
-                                                       nullptr, &ctx);
-  req->send();
-  ASSERT_EQ(-EINVAL, ctx.wait());
-}
-
-TEST_F(TestMockExclusiveLockAcquireRequest, GetLockInfoEmpty) {
-  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
-
-  librbd::ImageCtx *ictx;
-  ASSERT_EQ(0, open_image(m_image_name, &ictx));
-
-  MockTestImageCtx mock_image_ctx(*ictx);
-  expect_op_work_queue(mock_image_ctx);
-
-  InSequence seq;
-  expect_prepare_lock(mock_image_ctx);
-  expect_flush_notifies(mock_image_ctx);
-  expect_lock(mock_image_ctx, -EBUSY);
-  expect_get_lock_info(mock_image_ctx, -ENOENT, entity_name_t::CLIENT(1), "",
-                       "", "", LOCK_EXCLUSIVE);
-  expect_lock(mock_image_ctx, -EINVAL);
-  expect_handle_prepare_lock_complete(mock_image_ctx);
-
-  C_SaferCond ctx;
-  MockAcquireRequest *req = MockAcquireRequest::create(mock_image_ctx,
-                                                       TEST_COOKIE,
-                                                       nullptr, &ctx);
-  req->send();
-  ASSERT_EQ(-EINVAL, ctx.wait());
-}
-
-TEST_F(TestMockExclusiveLockAcquireRequest, GetLockInfoExternalTag) {
-  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
-
-  librbd::ImageCtx *ictx;
-  ASSERT_EQ(0, open_image(m_image_name, &ictx));
-
-  MockTestImageCtx mock_image_ctx(*ictx);
-  expect_op_work_queue(mock_image_ctx);
-
-  InSequence seq;
-  expect_prepare_lock(mock_image_ctx);
-  expect_flush_notifies(mock_image_ctx);
-  expect_lock(mock_image_ctx, -EBUSY);
-  expect_get_lock_info(mock_image_ctx, 0, entity_name_t::CLIENT(1), "1.2.3.4",
-                       "auto 123", "external tag", LOCK_EXCLUSIVE);
-  expect_handle_prepare_lock_complete(mock_image_ctx);
-
-  C_SaferCond ctx;
-  MockAcquireRequest *req = MockAcquireRequest::create(mock_image_ctx,
-                                                       TEST_COOKIE,
-                                                       nullptr, &ctx);
-  req->send();
-  ASSERT_EQ(-EBUSY, ctx.wait());
-}
-
-TEST_F(TestMockExclusiveLockAcquireRequest, GetLockInfoShared) {
-  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
-
-  librbd::ImageCtx *ictx;
-  ASSERT_EQ(0, open_image(m_image_name, &ictx));
-
-  MockTestImageCtx mock_image_ctx(*ictx);
-  expect_op_work_queue(mock_image_ctx);
-
-  InSequence seq;
-  expect_prepare_lock(mock_image_ctx);
-  expect_flush_notifies(mock_image_ctx);
-  expect_lock(mock_image_ctx, -EBUSY);
-  expect_get_lock_info(mock_image_ctx, 0, entity_name_t::CLIENT(1), "1.2.3.4",
-                       "auto 123", ExclusiveLock<>::WATCHER_LOCK_TAG,
-                       LOCK_SHARED);
-  expect_handle_prepare_lock_complete(mock_image_ctx);
-
-  C_SaferCond ctx;
-  MockAcquireRequest *req = MockAcquireRequest::create(mock_image_ctx,
-                                                       TEST_COOKIE,
-                                                       nullptr, &ctx);
-  req->send();
-  ASSERT_EQ(-EBUSY, ctx.wait());
-}
-
-TEST_F(TestMockExclusiveLockAcquireRequest, GetLockInfoExternalCookie) {
-  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
-
-  librbd::ImageCtx *ictx;
-  ASSERT_EQ(0, open_image(m_image_name, &ictx));
-
-  MockTestImageCtx mock_image_ctx(*ictx);
-  expect_op_work_queue(mock_image_ctx);
-
-  InSequence seq;
-  expect_prepare_lock(mock_image_ctx);
-  expect_flush_notifies(mock_image_ctx);
-  expect_lock(mock_image_ctx, -EBUSY);
-  expect_get_lock_info(mock_image_ctx, 0, entity_name_t::CLIENT(1), "1.2.3.4",
-                       "external cookie", ExclusiveLock<>::WATCHER_LOCK_TAG,
-                       LOCK_EXCLUSIVE);
-  expect_handle_prepare_lock_complete(mock_image_ctx);
-
-  C_SaferCond ctx;
-  MockAcquireRequest *req = MockAcquireRequest::create(mock_image_ctx,
-                                                       TEST_COOKIE,
-                                                       nullptr, &ctx);
-  req->send();
-  ASSERT_EQ(-EBUSY, ctx.wait());
-}
-
-TEST_F(TestMockExclusiveLockAcquireRequest, GetWatchersError) {
-  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
-
-  librbd::ImageCtx *ictx;
-  ASSERT_EQ(0, open_image(m_image_name, &ictx));
-
-  MockTestImageCtx mock_image_ctx(*ictx);
-  expect_op_work_queue(mock_image_ctx);
-
-  InSequence seq;
-  expect_prepare_lock(mock_image_ctx);
-  expect_flush_notifies(mock_image_ctx);
-  expect_lock(mock_image_ctx, -EBUSY);
-  expect_get_lock_info(mock_image_ctx, 0, entity_name_t::CLIENT(1), "1.2.3.4",
-                       "auto 123", ExclusiveLock<>::WATCHER_LOCK_TAG,
-                       LOCK_EXCLUSIVE);
-  expect_list_watchers(mock_image_ctx, -EINVAL, "dead client", 123);
-  expect_handle_prepare_lock_complete(mock_image_ctx);
-
-  C_SaferCond ctx;
-  MockAcquireRequest *req = MockAcquireRequest::create(mock_image_ctx,
-                                                       TEST_COOKIE,
-                                                       nullptr, &ctx);
-  req->send();
-  ASSERT_EQ(-EINVAL, ctx.wait());
-}
-
-TEST_F(TestMockExclusiveLockAcquireRequest, GetWatchersAlive) {
-  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
-
-  librbd::ImageCtx *ictx;
-  ASSERT_EQ(0, open_image(m_image_name, &ictx));
-
-  MockTestImageCtx mock_image_ctx(*ictx);
-  expect_op_work_queue(mock_image_ctx);
-
-  InSequence seq;
-  expect_prepare_lock(mock_image_ctx);
-  expect_flush_notifies(mock_image_ctx);
-  expect_lock(mock_image_ctx, -EBUSY);
-  expect_get_lock_info(mock_image_ctx, 0, entity_name_t::CLIENT(1), "1.2.3.4",
-                       "auto 123", ExclusiveLock<>::WATCHER_LOCK_TAG,
-                       LOCK_EXCLUSIVE);
-  expect_list_watchers(mock_image_ctx, 0, "1.2.3.4", 123);
-  expect_handle_prepare_lock_complete(mock_image_ctx);
-
-  C_SaferCond ctx;
-  MockAcquireRequest *req = MockAcquireRequest::create(mock_image_ctx,
-                                                       TEST_COOKIE,
-                                                       nullptr, &ctx);
-  req->send();
-  ASSERT_EQ(-EAGAIN, ctx.wait());
-}
-
-TEST_F(TestMockExclusiveLockAcquireRequest, BlacklistDisabled) {
-  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
-
-  librbd::ImageCtx *ictx;
-  ASSERT_EQ(0, open_image(m_image_name, &ictx));
-
-  MockTestImageCtx mock_image_ctx(*ictx);
-  expect_op_work_queue(mock_image_ctx);
-  mock_image_ctx.blacklist_on_break_lock = false;
-
-  InSequence seq;
-  expect_prepare_lock(mock_image_ctx);
-  expect_flush_notifies(mock_image_ctx);
-  expect_lock(mock_image_ctx, -EBUSY);
-  expect_get_lock_info(mock_image_ctx, 0, entity_name_t::CLIENT(1), "1.2.3.4",
-                       "auto 123", ExclusiveLock<>::WATCHER_LOCK_TAG,
-                       LOCK_EXCLUSIVE);
-  expect_list_watchers(mock_image_ctx, 0, "dead client", 123);
-  expect_break_lock(mock_image_ctx, 0);
-  expect_lock(mock_image_ctx, -ENOENT);
-  expect_handle_prepare_lock_complete(mock_image_ctx);
-
-  C_SaferCond ctx;
-  MockAcquireRequest *req = MockAcquireRequest::create(mock_image_ctx,
-                                                       TEST_COOKIE,
-                                                       nullptr, &ctx);
-  req->send();
-  ASSERT_EQ(-ENOENT, ctx.wait());
-}
-
-TEST_F(TestMockExclusiveLockAcquireRequest, BlacklistError) {
-  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
-
-  librbd::ImageCtx *ictx;
-  ASSERT_EQ(0, open_image(m_image_name, &ictx));
-
-  MockTestImageCtx mock_image_ctx(*ictx);
-  expect_op_work_queue(mock_image_ctx);
-
-  InSequence seq;
-  expect_prepare_lock(mock_image_ctx);
-  expect_flush_notifies(mock_image_ctx);
-  expect_lock(mock_image_ctx, -EBUSY);
-  expect_get_lock_info(mock_image_ctx, 0, entity_name_t::CLIENT(1), "1.2.3.4",
-                       "auto 123", ExclusiveLock<>::WATCHER_LOCK_TAG,
-                       LOCK_EXCLUSIVE);
-  expect_list_watchers(mock_image_ctx, 0, "dead client", 123);
-  expect_blacklist_add(mock_image_ctx, -EINVAL);
-  expect_handle_prepare_lock_complete(mock_image_ctx);
-
-  C_SaferCond ctx;
-  MockAcquireRequest *req = MockAcquireRequest::create(mock_image_ctx,
-                                                       TEST_COOKIE,
-                                                       nullptr, &ctx);
-  req->send();
-  ASSERT_EQ(-EINVAL, ctx.wait());
-}
-
-TEST_F(TestMockExclusiveLockAcquireRequest, BreakLockMissing) {
-  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
-
-  librbd::ImageCtx *ictx;
-  ASSERT_EQ(0, open_image(m_image_name, &ictx));
-
-  MockTestImageCtx mock_image_ctx(*ictx);
-  expect_op_work_queue(mock_image_ctx);
-
-  InSequence seq;
-  expect_prepare_lock(mock_image_ctx);
-  expect_flush_notifies(mock_image_ctx);
-  expect_lock(mock_image_ctx, -EBUSY);
-  expect_get_lock_info(mock_image_ctx, 0, entity_name_t::CLIENT(1), "1.2.3.4",
-                       "auto 123", ExclusiveLock<>::WATCHER_LOCK_TAG,
-                       LOCK_EXCLUSIVE);
-  expect_list_watchers(mock_image_ctx, 0, "dead client", 123);
-  expect_blacklist_add(mock_image_ctx, 0);
-  expect_break_lock(mock_image_ctx, -ENOENT);
-  expect_lock(mock_image_ctx, -EINVAL);
-  expect_handle_prepare_lock_complete(mock_image_ctx);
-
-  C_SaferCond ctx;
-  MockAcquireRequest *req = MockAcquireRequest::create(mock_image_ctx,
-                                                       TEST_COOKIE,
-                                                       nullptr, &ctx);
-  req->send();
-  ASSERT_EQ(-EINVAL, ctx.wait());
-}
-
-TEST_F(TestMockExclusiveLockAcquireRequest, BreakLockError) {
-  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
-
-  librbd::ImageCtx *ictx;
-  ASSERT_EQ(0, open_image(m_image_name, &ictx));
-
-  MockTestImageCtx mock_image_ctx(*ictx);
-  expect_op_work_queue(mock_image_ctx);
-
-  InSequence seq;
-  expect_prepare_lock(mock_image_ctx);
-  expect_flush_notifies(mock_image_ctx);
-  expect_lock(mock_image_ctx, -EBUSY);
-  expect_get_lock_info(mock_image_ctx, 0, entity_name_t::CLIENT(1), "1.2.3.4",
-                       "auto 123", ExclusiveLock<>::WATCHER_LOCK_TAG,
-                       LOCK_EXCLUSIVE);
-  expect_list_watchers(mock_image_ctx, 0, "dead client", 123);
-  expect_blacklist_add(mock_image_ctx, 0);
-  expect_break_lock(mock_image_ctx, -EINVAL);
-  expect_handle_prepare_lock_complete(mock_image_ctx);
-
-  C_SaferCond ctx;
-  MockAcquireRequest *req = MockAcquireRequest::create(mock_image_ctx,
-                                                       TEST_COOKIE,
-                                                       nullptr, &ctx);
-  req->send();
-  ASSERT_EQ(-EINVAL, ctx.wait());
-}
-
-TEST_F(TestMockExclusiveLockAcquireRequest, OpenObjectMapError) {
-  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
-
-  librbd::ImageCtx *ictx;
-  ASSERT_EQ(0, open_image(m_image_name, &ictx));
-
-  MockTestImageCtx mock_image_ctx(*ictx);
-  expect_op_work_queue(mock_image_ctx);
-
-  InSequence seq;
-  expect_prepare_lock(mock_image_ctx);
-  expect_flush_notifies(mock_image_ctx);
-  expect_lock(mock_image_ctx, 0);
-  expect_is_refresh_required(mock_image_ctx, false);
-
-  MockObjectMap *mock_object_map = new MockObjectMap();
-  expect_test_features(mock_image_ctx, RBD_FEATURE_OBJECT_MAP, true);
-  expect_create_object_map(mock_image_ctx, mock_object_map);
-  expect_open_object_map(mock_image_ctx, *mock_object_map, -EFBIG);
-
-  MockJournal mock_journal;
-  MockJournalPolicy mock_journal_policy;
-  expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING,
-                       mock_image_ctx.snap_lock, true);
-  expect_get_journal_policy(mock_image_ctx, mock_journal_policy);
-  expect_journal_disabled(mock_journal_policy, false);
-  expect_create_journal(mock_image_ctx, &mock_journal);
-  expect_handle_prepare_lock_complete(mock_image_ctx);
-  expect_open_journal(mock_image_ctx, mock_journal, 0);
-  expect_get_journal_policy(mock_image_ctx, mock_journal_policy);
-  expect_allocate_journal_tag(mock_image_ctx, mock_journal_policy, 0);
-
-  C_SaferCond acquire_ctx;
-  C_SaferCond ctx;
-  MockAcquireRequest *req = MockAcquireRequest::create(mock_image_ctx,
-                                                       TEST_COOKIE,
-                                                       &acquire_ctx, &ctx);
-  req->send();
-  ASSERT_EQ(0, acquire_ctx.wait());
-  ASSERT_EQ(0, ctx.wait());
-  ASSERT_EQ(nullptr, mock_image_ctx.object_map);
-}
-
-} // namespace exclusive_lock
-} // namespace librbd
diff --git a/src/test/librbd/exclusive_lock/test_mock_PostAcquireRequest.cc b/src/test/librbd/exclusive_lock/test_mock_PostAcquireRequest.cc
new file mode 100644 (file)
index 0000000..26b20e0
--- /dev/null
@@ -0,0 +1,486 @@
+// -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "test/librbd/test_mock_fixture.h"
+#include "test/librbd/test_support.h"
+#include "test/librbd/mock/MockImageCtx.h"
+#include "test/librbd/mock/MockImageState.h"
+#include "test/librbd/mock/MockJournal.h"
+#include "test/librbd/mock/MockJournalPolicy.h"
+#include "test/librbd/mock/MockObjectMap.h"
+#include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
+#include "test/librados_test_stub/MockTestMemRadosClient.h"
+#include "librbd/exclusive_lock/PostAcquireRequest.h"
+#include "librbd/image/RefreshRequest.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include <arpa/inet.h>
+#include <list>
+
+namespace librbd {
+namespace {
+
+struct MockTestImageCtx : public librbd::MockImageCtx {
+  MockTestImageCtx(librbd::ImageCtx &image_ctx)
+    : librbd::MockImageCtx(image_ctx) {
+  }
+};
+
+inline ImageCtx &get_image_ctx(MockTestImageCtx &image_ctx) {
+  return *(image_ctx.image_ctx);
+}
+
+} // anonymous namespace
+
+namespace image {
+
+template<>
+struct RefreshRequest<librbd::MockTestImageCtx> {
+  static RefreshRequest *s_instance;
+  Context *on_finish;
+
+  static RefreshRequest *create(librbd::MockTestImageCtx &image_ctx,
+                                bool acquire_lock_refresh,
+                                Context *on_finish) {
+    EXPECT_TRUE(acquire_lock_refresh);
+    assert(s_instance != nullptr);
+    s_instance->on_finish = on_finish;
+    return s_instance;
+  }
+
+  RefreshRequest() {
+    s_instance = this;
+  }
+  MOCK_METHOD0(send, void());
+};
+
+RefreshRequest<librbd::MockTestImageCtx> *RefreshRequest<librbd::MockTestImageCtx>::s_instance = nullptr;
+
+} // namespace image
+} // namespace librbd
+
+// template definitions
+#include "librbd/Journal.cc"
+
+#include "librbd/exclusive_lock/PostAcquireRequest.cc"
+template class librbd::exclusive_lock::PostAcquireRequest<librbd::MockTestImageCtx>;
+
+ACTION_P3(FinishRequest2, request, r, mock) {
+  mock->image_ctx->op_work_queue->queue(request->on_finish, r);
+}
+
+
+namespace librbd {
+namespace exclusive_lock {
+
+using ::testing::_;
+using ::testing::DoAll;
+using ::testing::InSequence;
+using ::testing::Invoke;
+using ::testing::Return;
+using ::testing::SetArgPointee;
+using ::testing::StrEq;
+using ::testing::WithArg;
+
+static const std::string TEST_COOKIE("auto 123");
+
+class TestMockExclusiveLockPostAcquireRequest : public TestMockFixture {
+public:
+  typedef PostAcquireRequest<MockTestImageCtx> MockPostAcquireRequest;
+  typedef librbd::image::RefreshRequest<MockTestImageCtx> MockRefreshRequest;
+
+  void expect_test_features(MockTestImageCtx &mock_image_ctx, uint64_t features,
+                            bool enabled) {
+    EXPECT_CALL(mock_image_ctx, test_features(features))
+                  .WillOnce(Return(enabled));
+  }
+
+  void expect_test_features(MockTestImageCtx &mock_image_ctx, uint64_t features,
+                            RWLock &lock, bool enabled) {
+    EXPECT_CALL(mock_image_ctx, test_features(features, _))
+                  .WillOnce(Return(enabled));
+  }
+
+  void expect_is_refresh_required(MockTestImageCtx &mock_image_ctx, bool required) {
+    EXPECT_CALL(*mock_image_ctx.state, is_refresh_required())
+      .WillOnce(Return(required));
+  }
+
+  void expect_refresh(MockTestImageCtx &mock_image_ctx,
+                      MockRefreshRequest &mock_refresh_request, int r) {
+    EXPECT_CALL(mock_refresh_request, send())
+                  .WillOnce(FinishRequest2(&mock_refresh_request, r,
+                                           &mock_image_ctx));
+  }
+
+  void expect_create_object_map(MockTestImageCtx &mock_image_ctx,
+                                MockObjectMap *mock_object_map) {
+    EXPECT_CALL(mock_image_ctx, create_object_map(_))
+                  .WillOnce(Return(mock_object_map));
+  }
+
+  void expect_open_object_map(MockTestImageCtx &mock_image_ctx,
+                              MockObjectMap &mock_object_map, int r) {
+    EXPECT_CALL(mock_object_map, open(_))
+                  .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
+  }
+
+  void expect_close_object_map(MockTestImageCtx &mock_image_ctx,
+                              MockObjectMap &mock_object_map) {
+    EXPECT_CALL(mock_object_map, close(_))
+                  .WillOnce(CompleteContext(0, mock_image_ctx.image_ctx->op_work_queue));
+  }
+
+  void expect_create_journal(MockTestImageCtx &mock_image_ctx,
+                             MockJournal *mock_journal) {
+    EXPECT_CALL(mock_image_ctx, create_journal())
+                  .WillOnce(Return(mock_journal));
+  }
+
+  void expect_open_journal(MockTestImageCtx &mock_image_ctx,
+                           MockJournal &mock_journal, int r) {
+    EXPECT_CALL(mock_journal, open(_))
+                  .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
+  }
+
+  void expect_close_journal(MockTestImageCtx &mock_image_ctx,
+                            MockJournal &mock_journal) {
+    EXPECT_CALL(mock_journal, close(_))
+                  .WillOnce(CompleteContext(0, mock_image_ctx.image_ctx->op_work_queue));
+  }
+
+  void expect_get_journal_policy(MockTestImageCtx &mock_image_ctx,
+                                 MockJournalPolicy &mock_journal_policy) {
+    EXPECT_CALL(mock_image_ctx, get_journal_policy())
+                  .WillOnce(Return(&mock_journal_policy));
+  }
+
+  void expect_journal_disabled(MockJournalPolicy &mock_journal_policy,
+                               bool disabled) {
+    EXPECT_CALL(mock_journal_policy, journal_disabled())
+      .WillOnce(Return(disabled));
+  }
+
+  void expect_allocate_journal_tag(MockTestImageCtx &mock_image_ctx,
+                                   MockJournalPolicy &mock_journal_policy,
+                                   int r) {
+    EXPECT_CALL(mock_journal_policy, allocate_tag_on_lock(_))
+                  .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
+  }
+
+  void expect_handle_prepare_lock_complete(MockTestImageCtx &mock_image_ctx) {
+    EXPECT_CALL(*mock_image_ctx.state, handle_prepare_lock_complete());
+  }
+
+};
+
+TEST_F(TestMockExclusiveLockPostAcquireRequest, Success) {
+  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
+
+  librbd::ImageCtx *ictx;
+  ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+  MockTestImageCtx mock_image_ctx(*ictx);
+  expect_op_work_queue(mock_image_ctx);
+
+  InSequence seq;
+  expect_is_refresh_required(mock_image_ctx, false);
+
+  MockObjectMap mock_object_map;
+  expect_test_features(mock_image_ctx, RBD_FEATURE_OBJECT_MAP, true);
+  expect_create_object_map(mock_image_ctx, &mock_object_map);
+  expect_open_object_map(mock_image_ctx, mock_object_map, 0);
+
+  MockJournal mock_journal;
+  MockJournalPolicy mock_journal_policy;
+  expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING,
+                       mock_image_ctx.snap_lock, true);
+  expect_get_journal_policy(mock_image_ctx, mock_journal_policy);
+  expect_journal_disabled(mock_journal_policy, false);
+  expect_create_journal(mock_image_ctx, &mock_journal);
+  expect_handle_prepare_lock_complete(mock_image_ctx);
+  expect_open_journal(mock_image_ctx, mock_journal, 0);
+  expect_get_journal_policy(mock_image_ctx, mock_journal_policy);
+  expect_allocate_journal_tag(mock_image_ctx, mock_journal_policy, 0);
+
+  C_SaferCond acquire_ctx;
+  C_SaferCond ctx;
+  MockPostAcquireRequest *req = MockPostAcquireRequest::create(mock_image_ctx,
+                                                               &acquire_ctx,
+                                                               &ctx);
+  req->send();
+  ASSERT_EQ(0, acquire_ctx.wait());
+  ASSERT_EQ(0, ctx.wait());
+ }
+
+TEST_F(TestMockExclusiveLockPostAcquireRequest, SuccessRefresh) {
+  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
+
+  librbd::ImageCtx *ictx;
+  ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+  MockTestImageCtx mock_image_ctx(*ictx);
+  MockRefreshRequest mock_refresh_request;
+  expect_op_work_queue(mock_image_ctx);
+
+  InSequence seq;
+  expect_is_refresh_required(mock_image_ctx, true);
+  expect_refresh(mock_image_ctx, mock_refresh_request, 0);
+
+  MockObjectMap mock_object_map;
+  expect_test_features(mock_image_ctx, RBD_FEATURE_OBJECT_MAP, false);
+  expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING,
+                       mock_image_ctx.snap_lock, false);
+  expect_handle_prepare_lock_complete(mock_image_ctx);
+
+  C_SaferCond acquire_ctx;
+  C_SaferCond ctx;
+  MockPostAcquireRequest *req = MockPostAcquireRequest::create(mock_image_ctx,
+                                                               &acquire_ctx,
+                                                               &ctx);
+  req->send();
+  ASSERT_EQ(0, acquire_ctx.wait());
+  ASSERT_EQ(0, ctx.wait());
+}
+
+TEST_F(TestMockExclusiveLockPostAcquireRequest, SuccessJournalDisabled) {
+  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
+
+  librbd::ImageCtx *ictx;
+  ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+  MockTestImageCtx mock_image_ctx(*ictx);
+  expect_op_work_queue(mock_image_ctx);
+
+  InSequence seq;
+  expect_is_refresh_required(mock_image_ctx, false);
+
+  MockObjectMap mock_object_map;
+  expect_test_features(mock_image_ctx, RBD_FEATURE_OBJECT_MAP, true);
+  expect_create_object_map(mock_image_ctx, &mock_object_map);
+  expect_open_object_map(mock_image_ctx, mock_object_map, 0);
+
+  expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING,
+                       mock_image_ctx.snap_lock, false);
+  expect_handle_prepare_lock_complete(mock_image_ctx);
+
+  C_SaferCond acquire_ctx;
+  C_SaferCond ctx;
+  MockPostAcquireRequest *req = MockPostAcquireRequest::create(mock_image_ctx,
+                                                               &acquire_ctx,
+                                                               &ctx);
+  req->send();
+  ASSERT_EQ(0, acquire_ctx.wait());
+  ASSERT_EQ(0, ctx.wait());
+}
+
+TEST_F(TestMockExclusiveLockPostAcquireRequest, SuccessObjectMapDisabled) {
+  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
+
+  librbd::ImageCtx *ictx;
+  ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+  MockTestImageCtx mock_image_ctx(*ictx);
+  expect_op_work_queue(mock_image_ctx);
+
+  InSequence seq;
+  expect_is_refresh_required(mock_image_ctx, false);
+
+  expect_test_features(mock_image_ctx, RBD_FEATURE_OBJECT_MAP, false);
+
+  MockJournal mock_journal;
+  MockJournalPolicy mock_journal_policy;
+  expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING,
+                       mock_image_ctx.snap_lock, true);
+  expect_get_journal_policy(mock_image_ctx, mock_journal_policy);
+  expect_journal_disabled(mock_journal_policy, false);
+  expect_create_journal(mock_image_ctx, &mock_journal);
+  expect_handle_prepare_lock_complete(mock_image_ctx);
+  expect_open_journal(mock_image_ctx, mock_journal, 0);
+  expect_get_journal_policy(mock_image_ctx, mock_journal_policy);
+  expect_allocate_journal_tag(mock_image_ctx, mock_journal_policy, 0);
+
+  C_SaferCond acquire_ctx;
+  C_SaferCond ctx;
+  MockPostAcquireRequest *req = MockPostAcquireRequest::create(mock_image_ctx,
+                                                               &acquire_ctx,
+                                                               &ctx);
+  req->send();
+  ASSERT_EQ(0, acquire_ctx.wait());
+  ASSERT_EQ(0, ctx.wait());
+}
+
+TEST_F(TestMockExclusiveLockPostAcquireRequest, RefreshError) {
+  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
+
+  librbd::ImageCtx *ictx;
+  ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+  MockTestImageCtx mock_image_ctx(*ictx);
+  MockRefreshRequest mock_refresh_request;
+  expect_op_work_queue(mock_image_ctx);
+
+  InSequence seq;
+  expect_is_refresh_required(mock_image_ctx, true);
+  expect_refresh(mock_image_ctx, mock_refresh_request, -EINVAL);
+  expect_handle_prepare_lock_complete(mock_image_ctx);
+
+  C_SaferCond *acquire_ctx = new C_SaferCond();
+  C_SaferCond ctx;
+  MockPostAcquireRequest *req = MockPostAcquireRequest::create(mock_image_ctx,
+                                                               acquire_ctx,
+                                                               &ctx);
+  req->send();
+  ASSERT_EQ(-EINVAL, ctx.wait());
+}
+
+TEST_F(TestMockExclusiveLockPostAcquireRequest, RefreshLockDisabled) {
+  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
+
+  librbd::ImageCtx *ictx;
+  ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+  MockTestImageCtx mock_image_ctx(*ictx);
+  MockRefreshRequest mock_refresh_request;
+  expect_op_work_queue(mock_image_ctx);
+
+  InSequence seq;
+  expect_is_refresh_required(mock_image_ctx, true);
+  expect_refresh(mock_image_ctx, mock_refresh_request, -ERESTART);
+
+  MockObjectMap mock_object_map;
+  expect_test_features(mock_image_ctx, RBD_FEATURE_OBJECT_MAP, false);
+  expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING,
+                       mock_image_ctx.snap_lock, false);
+  expect_handle_prepare_lock_complete(mock_image_ctx);
+
+  C_SaferCond acquire_ctx;
+  C_SaferCond ctx;
+  MockPostAcquireRequest *req = MockPostAcquireRequest::create(mock_image_ctx,
+                                                               &acquire_ctx,
+                                                               &ctx);
+  req->send();
+  ASSERT_EQ(0, acquire_ctx.wait());
+  ASSERT_EQ(0, ctx.wait());
+}
+
+TEST_F(TestMockExclusiveLockPostAcquireRequest, JournalError) {
+  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
+
+  librbd::ImageCtx *ictx;
+  ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+  MockTestImageCtx mock_image_ctx(*ictx);
+  expect_op_work_queue(mock_image_ctx);
+
+  InSequence seq;
+  expect_is_refresh_required(mock_image_ctx, false);
+
+  MockObjectMap *mock_object_map = new MockObjectMap();
+  expect_test_features(mock_image_ctx, RBD_FEATURE_OBJECT_MAP, true);
+  expect_create_object_map(mock_image_ctx, mock_object_map);
+  expect_open_object_map(mock_image_ctx, *mock_object_map, 0);
+
+  MockJournal *mock_journal = new MockJournal();
+  MockJournalPolicy mock_journal_policy;
+  expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING,
+                       mock_image_ctx.snap_lock, true);
+  expect_get_journal_policy(mock_image_ctx, mock_journal_policy);
+  expect_journal_disabled(mock_journal_policy, false);
+  expect_create_journal(mock_image_ctx, mock_journal);
+  expect_handle_prepare_lock_complete(mock_image_ctx);
+  expect_open_journal(mock_image_ctx, *mock_journal, -EINVAL);
+  expect_close_journal(mock_image_ctx, *mock_journal);
+  expect_close_object_map(mock_image_ctx, *mock_object_map);
+
+  C_SaferCond acquire_ctx;
+  C_SaferCond ctx;
+  MockPostAcquireRequest *req = MockPostAcquireRequest::create(mock_image_ctx,
+                                                               &acquire_ctx,
+                                                               &ctx);
+  req->send();
+  ASSERT_EQ(-EINVAL, ctx.wait());
+}
+
+TEST_F(TestMockExclusiveLockPostAcquireRequest, AllocateJournalTagError) {
+  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
+
+  librbd::ImageCtx *ictx;
+  ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+  MockTestImageCtx mock_image_ctx(*ictx);
+  expect_op_work_queue(mock_image_ctx);
+
+  InSequence seq;
+  expect_is_refresh_required(mock_image_ctx, false);
+
+  MockObjectMap *mock_object_map = new MockObjectMap();
+  expect_test_features(mock_image_ctx, RBD_FEATURE_OBJECT_MAP, true);
+  expect_create_object_map(mock_image_ctx, mock_object_map);
+  expect_open_object_map(mock_image_ctx, *mock_object_map, 0);
+
+  MockJournal *mock_journal = new MockJournal();
+  MockJournalPolicy mock_journal_policy;
+  expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING,
+                       mock_image_ctx.snap_lock, true);
+  expect_get_journal_policy(mock_image_ctx, mock_journal_policy);
+  expect_journal_disabled(mock_journal_policy, false);
+  expect_create_journal(mock_image_ctx, mock_journal);
+  expect_handle_prepare_lock_complete(mock_image_ctx);
+  expect_open_journal(mock_image_ctx, *mock_journal, 0);
+  expect_get_journal_policy(mock_image_ctx, mock_journal_policy);
+  expect_allocate_journal_tag(mock_image_ctx, mock_journal_policy, -EPERM);
+  expect_close_journal(mock_image_ctx, *mock_journal);
+  expect_close_object_map(mock_image_ctx, *mock_object_map);
+
+  C_SaferCond acquire_ctx;
+  C_SaferCond ctx;
+  MockPostAcquireRequest *req = MockPostAcquireRequest::create(mock_image_ctx,
+                                                               &acquire_ctx,
+                                                               &ctx);
+  req->send();
+  ASSERT_EQ(-EPERM, ctx.wait());
+}
+
+TEST_F(TestMockExclusiveLockPostAcquireRequest, OpenObjectMapError) {
+  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
+
+  librbd::ImageCtx *ictx;
+  ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+  MockTestImageCtx mock_image_ctx(*ictx);
+  expect_op_work_queue(mock_image_ctx);
+
+  InSequence seq;
+  expect_is_refresh_required(mock_image_ctx, false);
+
+  MockObjectMap *mock_object_map = new MockObjectMap();
+  expect_test_features(mock_image_ctx, RBD_FEATURE_OBJECT_MAP, true);
+  expect_create_object_map(mock_image_ctx, mock_object_map);
+  expect_open_object_map(mock_image_ctx, *mock_object_map, -EFBIG);
+
+  MockJournal mock_journal;
+  MockJournalPolicy mock_journal_policy;
+  expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING,
+                       mock_image_ctx.snap_lock, true);
+  expect_get_journal_policy(mock_image_ctx, mock_journal_policy);
+  expect_journal_disabled(mock_journal_policy, false);
+  expect_create_journal(mock_image_ctx, &mock_journal);
+  expect_handle_prepare_lock_complete(mock_image_ctx);
+  expect_open_journal(mock_image_ctx, mock_journal, 0);
+  expect_get_journal_policy(mock_image_ctx, mock_journal_policy);
+  expect_allocate_journal_tag(mock_image_ctx, mock_journal_policy, 0);
+
+  C_SaferCond acquire_ctx;
+  C_SaferCond ctx;
+  MockPostAcquireRequest *req = MockPostAcquireRequest::create(mock_image_ctx,
+                                                               &acquire_ctx,
+                                                               &ctx);
+  req->send();
+  ASSERT_EQ(0, acquire_ctx.wait());
+  ASSERT_EQ(0, ctx.wait());
+  ASSERT_EQ(nullptr, mock_image_ctx.object_map);
+}
+
+} // namespace exclusive_lock
+} // namespace librbd
diff --git a/src/test/librbd/exclusive_lock/test_mock_PreAcquireRequest.cc b/src/test/librbd/exclusive_lock/test_mock_PreAcquireRequest.cc
new file mode 100644 (file)
index 0000000..9a01123
--- /dev/null
@@ -0,0 +1,92 @@
+// -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "test/librbd/test_mock_fixture.h"
+#include "test/librbd/test_support.h"
+#include "test/librbd/mock/MockImageCtx.h"
+#include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
+#include "test/librados_test_stub/MockTestMemRadosClient.h"
+#include "librbd/exclusive_lock/PreAcquireRequest.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include <arpa/inet.h>
+#include <list>
+
+namespace librbd {
+namespace {
+
+struct MockTestImageCtx : public librbd::MockImageCtx {
+  MockTestImageCtx(librbd::ImageCtx &image_ctx)
+    : librbd::MockImageCtx(image_ctx) {
+  }
+};
+
+inline ImageCtx &get_image_ctx(MockTestImageCtx &image_ctx) {
+  return *(image_ctx.image_ctx);
+}
+
+} // anonymous namespace
+} // namespace librbd
+
+// template definitions
+#include "librbd/exclusive_lock/PreAcquireRequest.cc"
+template class librbd::exclusive_lock::PreAcquireRequest<librbd::MockTestImageCtx>;
+
+namespace librbd {
+namespace exclusive_lock {
+
+using ::testing::_;
+using ::testing::DoAll;
+using ::testing::InSequence;
+using ::testing::Invoke;
+using ::testing::Return;
+using ::testing::SetArgPointee;
+using ::testing::StrEq;
+using ::testing::WithArg;
+
+static const std::string TEST_COOKIE("auto 123");
+
+class TestMockExclusiveLockPreAcquireRequest : public TestMockFixture {
+public:
+  typedef PreAcquireRequest<MockTestImageCtx> MockPreAcquireRequest;
+
+  void expect_flush_notifies(MockTestImageCtx &mock_image_ctx) {
+    EXPECT_CALL(*mock_image_ctx.image_watcher, flush(_))
+                  .WillOnce(CompleteContext(0, mock_image_ctx.image_ctx->op_work_queue));
+  }
+
+  void expect_prepare_lock(MockTestImageCtx &mock_image_ctx) {
+    EXPECT_CALL(*mock_image_ctx.state, prepare_lock(_))
+      .WillOnce(Invoke([](Context *on_ready) {
+                  on_ready->complete(0);
+                }));
+  }
+
+  void expect_handle_prepare_lock_complete(MockTestImageCtx &mock_image_ctx) {
+    EXPECT_CALL(*mock_image_ctx.state, handle_prepare_lock_complete());
+  }
+
+};
+
+TEST_F(TestMockExclusiveLockPreAcquireRequest, Success) {
+  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
+
+  librbd::ImageCtx *ictx;
+  ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+  MockTestImageCtx mock_image_ctx(*ictx);
+  expect_op_work_queue(mock_image_ctx);
+
+  InSequence seq;
+  expect_prepare_lock(mock_image_ctx);
+  expect_flush_notifies(mock_image_ctx);
+
+  C_SaferCond ctx;
+  MockPreAcquireRequest *req = MockPreAcquireRequest::create(mock_image_ctx,
+                                                             &ctx);
+  req->send();
+  ASSERT_EQ(0, ctx.wait());
+ }
+
+} // namespace exclusive_lock
+} // namespace librbd
diff --git a/src/test/librbd/exclusive_lock/test_mock_PreReleaseRequest.cc b/src/test/librbd/exclusive_lock/test_mock_PreReleaseRequest.cc
new file mode 100644 (file)
index 0000000..3c5e8c8
--- /dev/null
@@ -0,0 +1,249 @@
+// -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "test/librbd/test_mock_fixture.h"
+#include "test/librbd/test_support.h"
+#include "test/librbd/mock/MockImageCtx.h"
+#include "test/librbd/mock/MockJournal.h"
+#include "test/librbd/mock/MockObjectMap.h"
+#include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
+#include "librbd/exclusive_lock/PreReleaseRequest.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include <list>
+
+// template definitions
+#include "librbd/exclusive_lock/PreReleaseRequest.cc"
+template class librbd::exclusive_lock::PreReleaseRequest<librbd::MockImageCtx>;
+
+namespace librbd {
+
+using librbd::ManagedLock;
+
+namespace exclusive_lock {
+
+namespace {
+
+struct MockContext : public Context {
+  MOCK_METHOD1(complete, void(int));
+  MOCK_METHOD1(finish, void(int));
+};
+
+} // anonymous namespace
+
+using ::testing::_;
+using ::testing::InSequence;
+using ::testing::Invoke;
+using ::testing::Return;
+using ::testing::StrEq;
+
+static const std::string TEST_COOKIE("auto 123");
+
+class TestMockExclusiveLockPreReleaseRequest : public TestMockFixture {
+public:
+  typedef PreReleaseRequest<MockImageCtx> MockPreReleaseRequest;
+
+  void expect_complete_context(MockContext &mock_context, int r) {
+    EXPECT_CALL(mock_context, complete(r));
+  }
+
+  void expect_test_features(MockImageCtx &mock_image_ctx, uint64_t features,
+                            bool enabled) {
+    EXPECT_CALL(mock_image_ctx, test_features(features))
+                  .WillOnce(Return(enabled));
+  }
+
+  void expect_set_require_lock_on_read(MockImageCtx &mock_image_ctx) {
+    EXPECT_CALL(*mock_image_ctx.aio_work_queue, set_require_lock_on_read());
+  }
+
+  void expect_block_writes(MockImageCtx &mock_image_ctx, int r) {
+    expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING,
+                         ((mock_image_ctx.features & RBD_FEATURE_JOURNALING) != 0));
+    if ((mock_image_ctx.features & RBD_FEATURE_JOURNALING) != 0) {
+      expect_set_require_lock_on_read(mock_image_ctx);
+    }
+    EXPECT_CALL(*mock_image_ctx.aio_work_queue, block_writes(_))
+                  .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
+  }
+
+  void expect_unblock_writes(MockImageCtx &mock_image_ctx) {
+    EXPECT_CALL(*mock_image_ctx.aio_work_queue, unblock_writes());
+  }
+
+  void expect_cancel_op_requests(MockImageCtx &mock_image_ctx, int r) {
+    EXPECT_CALL(mock_image_ctx, cancel_async_requests(_))
+                  .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
+  }
+
+  void expect_close_journal(MockImageCtx &mock_image_ctx,
+                           MockJournal &mock_journal, int r) {
+    EXPECT_CALL(mock_journal, close(_))
+                  .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
+  }
+
+  void expect_close_object_map(MockImageCtx &mock_image_ctx,
+                               MockObjectMap &mock_object_map) {
+    EXPECT_CALL(mock_object_map, close(_))
+                  .WillOnce(CompleteContext(0, mock_image_ctx.image_ctx->op_work_queue));
+  }
+
+  void expect_flush_notifies(MockImageCtx &mock_image_ctx) {
+    EXPECT_CALL(*mock_image_ctx.image_watcher, flush(_))
+                  .WillOnce(CompleteContext(0, mock_image_ctx.image_ctx->op_work_queue));
+  }
+
+  void expect_prepare_lock(MockImageCtx &mock_image_ctx) {
+    EXPECT_CALL(*mock_image_ctx.state, prepare_lock(_))
+      .WillOnce(Invoke([](Context *on_ready) {
+                  on_ready->complete(0);
+                }));
+  }
+
+  void expect_handle_prepare_lock_complete(MockImageCtx &mock_image_ctx) {
+    EXPECT_CALL(*mock_image_ctx.state, handle_prepare_lock_complete());
+  }
+
+};
+
+TEST_F(TestMockExclusiveLockPreReleaseRequest, Success) {
+  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
+
+  librbd::ImageCtx *ictx;
+  ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+  MockImageCtx mock_image_ctx(*ictx);
+  expect_op_work_queue(mock_image_ctx);
+
+  InSequence seq;
+
+  expect_prepare_lock(mock_image_ctx);
+  expect_cancel_op_requests(mock_image_ctx, 0);
+  expect_block_writes(mock_image_ctx, 0);
+  expect_flush_notifies(mock_image_ctx);
+
+  MockJournal *mock_journal = new MockJournal();
+  mock_image_ctx.journal = mock_journal;
+  expect_close_journal(mock_image_ctx, *mock_journal, -EINVAL);
+
+  MockObjectMap *mock_object_map = new MockObjectMap();
+  mock_image_ctx.object_map = mock_object_map;
+  expect_close_object_map(mock_image_ctx, *mock_object_map);
+
+  MockContext mock_releasing_ctx;
+  expect_complete_context(mock_releasing_ctx, 0);
+  expect_handle_prepare_lock_complete(mock_image_ctx);
+
+  C_SaferCond ctx;
+  MockPreReleaseRequest *req = MockPreReleaseRequest::create(mock_image_ctx,
+                                                       &mock_releasing_ctx,
+                                                       &ctx, false);
+  req->send();
+  ASSERT_EQ(0, ctx.wait());
+}
+
+TEST_F(TestMockExclusiveLockPreReleaseRequest, SuccessJournalDisabled) {
+  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
+
+  librbd::ImageCtx *ictx;
+  ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+  MockImageCtx mock_image_ctx(*ictx);
+
+  expect_block_writes(mock_image_ctx, 0);
+  expect_op_work_queue(mock_image_ctx);
+
+  InSequence seq;
+  expect_prepare_lock(mock_image_ctx);
+  expect_cancel_op_requests(mock_image_ctx, 0);
+  expect_flush_notifies(mock_image_ctx);
+
+  MockObjectMap *mock_object_map = new MockObjectMap();
+  mock_image_ctx.object_map = mock_object_map;
+  expect_close_object_map(mock_image_ctx, *mock_object_map);
+
+  expect_handle_prepare_lock_complete(mock_image_ctx);
+
+  C_SaferCond release_ctx;
+  C_SaferCond ctx;
+  MockPreReleaseRequest *req = MockPreReleaseRequest::create(mock_image_ctx,
+                                                       &release_ctx, &ctx,
+                                                       false);
+  req->send();
+  ASSERT_EQ(0, release_ctx.wait());
+  ASSERT_EQ(0, ctx.wait());
+}
+
+TEST_F(TestMockExclusiveLockPreReleaseRequest, SuccessObjectMapDisabled) {
+  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
+
+  librbd::ImageCtx *ictx;
+  ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+  MockImageCtx mock_image_ctx(*ictx);
+
+  expect_block_writes(mock_image_ctx, 0);
+  expect_op_work_queue(mock_image_ctx);
+
+  InSequence seq;
+  expect_cancel_op_requests(mock_image_ctx, 0);
+  expect_flush_notifies(mock_image_ctx);
+
+  C_SaferCond release_ctx;
+  C_SaferCond ctx;
+  MockPreReleaseRequest *req = MockPreReleaseRequest::create(mock_image_ctx,
+                                                       &release_ctx, &ctx,
+                                                       true);
+  req->send();
+  ASSERT_EQ(0, release_ctx.wait());
+  ASSERT_EQ(0, ctx.wait());
+}
+
+TEST_F(TestMockExclusiveLockPreReleaseRequest, BlockWritesError) {
+  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
+
+  librbd::ImageCtx *ictx;
+  ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+  MockImageCtx mock_image_ctx(*ictx);
+
+  expect_op_work_queue(mock_image_ctx);
+
+  InSequence seq;
+  expect_cancel_op_requests(mock_image_ctx, 0);
+  expect_block_writes(mock_image_ctx, -EINVAL);
+  expect_unblock_writes(mock_image_ctx);
+
+  C_SaferCond ctx;
+  MockPreReleaseRequest *req = MockPreReleaseRequest::create(mock_image_ctx,
+                                                       nullptr, &ctx,
+                                                       true);
+  req->send();
+  ASSERT_EQ(-EINVAL, ctx.wait());
+}
+
+TEST_F(TestMockExclusiveLockPreReleaseRequest, UnlockError) {
+  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
+
+  librbd::ImageCtx *ictx;
+  ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+  MockImageCtx mock_image_ctx(*ictx);
+
+  expect_op_work_queue(mock_image_ctx);
+
+  InSequence seq;
+  expect_cancel_op_requests(mock_image_ctx, 0);
+  expect_block_writes(mock_image_ctx, 0);
+  expect_flush_notifies(mock_image_ctx);
+
+  C_SaferCond ctx;
+  MockPreReleaseRequest *req = MockPreReleaseRequest::create(mock_image_ctx,
+                                                       nullptr, &ctx,
+                                                       true);
+  req->send();
+  ASSERT_EQ(0, ctx.wait());
+}
+
+} // namespace exclusive_lock
+} // namespace librbd
diff --git a/src/test/librbd/exclusive_lock/test_mock_ReacquireRequest.cc b/src/test/librbd/exclusive_lock/test_mock_ReacquireRequest.cc
deleted file mode 100644 (file)
index 1ca9f78..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-// -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-
-#include "test/librbd/test_mock_fixture.h"
-#include "test/librbd/test_support.h"
-#include "test/librbd/mock/MockImageCtx.h"
-#include "test/librbd/mock/MockImageState.h"
-#include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
-#include "test/librados_test_stub/MockTestMemRadosClient.h"
-#include "cls/lock/cls_lock_ops.h"
-#include "librbd/ExclusiveLock.h"
-#include "librbd/exclusive_lock/ReacquireRequest.h"
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include <arpa/inet.h>
-#include <list>
-
-// template definitions
-#include "librbd/exclusive_lock/ReacquireRequest.cc"
-template class librbd::exclusive_lock::ReacquireRequest<librbd::MockImageCtx>;
-
-namespace librbd {
-namespace exclusive_lock {
-
-using ::testing::_;
-using ::testing::InSequence;
-using ::testing::Return;
-using ::testing::StrEq;
-
-class TestMockExclusiveLockReacquireRequest : public TestMockFixture {
-public:
-  typedef ReacquireRequest<MockImageCtx> MockReacquireRequest;
-  typedef ExclusiveLock<MockImageCtx> MockExclusiveLock;
-
-  void expect_set_cookie(MockImageCtx &mock_image_ctx, int r) {
-    EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
-                exec(mock_image_ctx.header_oid, _, StrEq("lock"),
-                     StrEq("set_cookie"), _, _, _))
-                  .WillOnce(Return(r));
-  }
-};
-
-TEST_F(TestMockExclusiveLockReacquireRequest, Success) {
-  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
-
-  librbd::ImageCtx *ictx;
-  ASSERT_EQ(0, open_image(m_image_name, &ictx));
-
-  MockImageCtx mock_image_ctx(*ictx);
-
-  InSequence seq;
-  expect_set_cookie(mock_image_ctx, 0);
-
-  C_SaferCond ctx;
-  MockReacquireRequest *req = MockReacquireRequest::create(mock_image_ctx,
-                                                           "old cookie",
-                                                           "new cookie", &ctx);
-  req->send();
-  ASSERT_EQ(0, ctx.wait());
-}
-
-TEST_F(TestMockExclusiveLockReacquireRequest, NotSupported) {
-  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
-
-  librbd::ImageCtx *ictx;
-  ASSERT_EQ(0, open_image(m_image_name, &ictx));
-
-  MockImageCtx mock_image_ctx(*ictx);
-
-  InSequence seq;
-  expect_set_cookie(mock_image_ctx, -EOPNOTSUPP);
-
-  C_SaferCond ctx;
-  MockReacquireRequest *req = MockReacquireRequest::create(mock_image_ctx,
-                                                           "old cookie",
-                                                           "new cookie", &ctx);
-  req->send();
-  ASSERT_EQ(-EOPNOTSUPP, ctx.wait());
-}
-
-TEST_F(TestMockExclusiveLockReacquireRequest, Error) {
-  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
-
-  librbd::ImageCtx *ictx;
-  ASSERT_EQ(0, open_image(m_image_name, &ictx));
-
-  MockImageCtx mock_image_ctx(*ictx);
-
-  InSequence seq;
-  expect_set_cookie(mock_image_ctx, -EBUSY);
-
-  C_SaferCond ctx;
-  MockReacquireRequest *req = MockReacquireRequest::create(mock_image_ctx,
-                                                           "old cookie",
-                                                           "new cookie", &ctx);
-  req->send();
-  ASSERT_EQ(-EBUSY, ctx.wait());
-}
-
-} // namespace exclusive_lock
-} // namespace librbd
diff --git a/src/test/librbd/exclusive_lock/test_mock_ReleaseRequest.cc b/src/test/librbd/exclusive_lock/test_mock_ReleaseRequest.cc
deleted file mode 100644 (file)
index e2fb842..0000000
+++ /dev/null
@@ -1,258 +0,0 @@
-// -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-
-#include "test/librbd/test_mock_fixture.h"
-#include "test/librbd/test_support.h"
-#include "test/librbd/mock/MockImageCtx.h"
-#include "test/librbd/mock/MockJournal.h"
-#include "test/librbd/mock/MockObjectMap.h"
-#include "test/librados_test_stub/MockTestMemIoCtxImpl.h"
-#include "librbd/exclusive_lock/ReleaseRequest.h"
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include <list>
-
-// template definitions
-#include "librbd/exclusive_lock/ReleaseRequest.cc"
-template class librbd::exclusive_lock::ReleaseRequest<librbd::MockImageCtx>;
-
-namespace librbd {
-namespace exclusive_lock {
-
-namespace {
-
-struct MockContext : public Context {
-  MOCK_METHOD1(complete, void(int));
-  MOCK_METHOD1(finish, void(int));
-};
-
-} // anonymous namespace
-
-using ::testing::_;
-using ::testing::InSequence;
-using ::testing::Invoke;
-using ::testing::Return;
-using ::testing::StrEq;
-
-static const std::string TEST_COOKIE("auto 123");
-
-class TestMockExclusiveLockReleaseRequest : public TestMockFixture {
-public:
-  typedef ReleaseRequest<MockImageCtx> MockReleaseRequest;
-
-  void expect_complete_context(MockContext &mock_context, int r) {
-    EXPECT_CALL(mock_context, complete(r));
-  }
-
-  void expect_test_features(MockImageCtx &mock_image_ctx, uint64_t features,
-                            bool enabled) {
-    EXPECT_CALL(mock_image_ctx, test_features(features))
-                  .WillOnce(Return(enabled));
-  }
-
-  void expect_set_require_lock_on_read(MockImageCtx &mock_image_ctx) {
-    EXPECT_CALL(*mock_image_ctx.aio_work_queue, set_require_lock_on_read());
-  }
-
-  void expect_block_writes(MockImageCtx &mock_image_ctx, int r) {
-    expect_test_features(mock_image_ctx, RBD_FEATURE_JOURNALING,
-                         ((mock_image_ctx.features & RBD_FEATURE_JOURNALING) != 0));
-    if ((mock_image_ctx.features & RBD_FEATURE_JOURNALING) != 0) {
-      expect_set_require_lock_on_read(mock_image_ctx);
-    }
-    EXPECT_CALL(*mock_image_ctx.aio_work_queue, block_writes(_))
-                  .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
-  }
-
-  void expect_unblock_writes(MockImageCtx &mock_image_ctx) {
-    EXPECT_CALL(*mock_image_ctx.aio_work_queue, unblock_writes());
-  }
-
-  void expect_cancel_op_requests(MockImageCtx &mock_image_ctx, int r) {
-    EXPECT_CALL(mock_image_ctx, cancel_async_requests(_))
-                  .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
-  }
-
-  void expect_unlock(MockImageCtx &mock_image_ctx, int r) {
-    EXPECT_CALL(get_mock_io_ctx(mock_image_ctx.md_ctx),
-                exec(mock_image_ctx.header_oid, _, StrEq("lock"), StrEq("unlock"), _, _, _))
-                  .WillOnce(Return(r));
-  }
-
-  void expect_close_journal(MockImageCtx &mock_image_ctx,
-                           MockJournal &mock_journal, int r) {
-    EXPECT_CALL(mock_journal, close(_))
-                  .WillOnce(CompleteContext(r, mock_image_ctx.image_ctx->op_work_queue));
-  }
-
-  void expect_close_object_map(MockImageCtx &mock_image_ctx,
-                               MockObjectMap &mock_object_map) {
-    EXPECT_CALL(mock_object_map, close(_))
-                  .WillOnce(CompleteContext(0, mock_image_ctx.image_ctx->op_work_queue));
-  }
-
-  void expect_flush_notifies(MockImageCtx &mock_image_ctx) {
-    EXPECT_CALL(*mock_image_ctx.image_watcher, flush(_))
-                  .WillOnce(CompleteContext(0, mock_image_ctx.image_ctx->op_work_queue));
-  }
-
-  void expect_prepare_lock(MockImageCtx &mock_image_ctx) {
-    EXPECT_CALL(*mock_image_ctx.state, prepare_lock(_))
-      .WillOnce(Invoke([](Context *on_ready) {
-                  on_ready->complete(0);
-                }));
-  }
-
-  void expect_handle_prepare_lock_complete(MockImageCtx &mock_image_ctx) {
-    EXPECT_CALL(*mock_image_ctx.state, handle_prepare_lock_complete());
-  }
-
-};
-
-TEST_F(TestMockExclusiveLockReleaseRequest, Success) {
-  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
-
-  librbd::ImageCtx *ictx;
-  ASSERT_EQ(0, open_image(m_image_name, &ictx));
-
-  MockImageCtx mock_image_ctx(*ictx);
-  expect_op_work_queue(mock_image_ctx);
-
-  InSequence seq;
-  expect_prepare_lock(mock_image_ctx);
-  expect_cancel_op_requests(mock_image_ctx, 0);
-  expect_block_writes(mock_image_ctx, 0);
-  expect_flush_notifies(mock_image_ctx);
-
-  MockJournal *mock_journal = new MockJournal();
-  mock_image_ctx.journal = mock_journal;
-  expect_close_journal(mock_image_ctx, *mock_journal, -EINVAL);
-
-  MockObjectMap *mock_object_map = new MockObjectMap();
-  mock_image_ctx.object_map = mock_object_map;
-  expect_close_object_map(mock_image_ctx, *mock_object_map);
-
-  MockContext mock_releasing_ctx;
-  expect_complete_context(mock_releasing_ctx, 0);
-  expect_unlock(mock_image_ctx, 0);
-  expect_handle_prepare_lock_complete(mock_image_ctx);
-
-  C_SaferCond ctx;
-  MockReleaseRequest *req = MockReleaseRequest::create(mock_image_ctx,
-                                                       TEST_COOKIE,
-                                                       &mock_releasing_ctx,
-                                                       &ctx, false);
-  req->send();
-  ASSERT_EQ(0, ctx.wait());
-}
-
-TEST_F(TestMockExclusiveLockReleaseRequest, SuccessJournalDisabled) {
-  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
-
-  librbd::ImageCtx *ictx;
-  ASSERT_EQ(0, open_image(m_image_name, &ictx));
-
-  MockImageCtx mock_image_ctx(*ictx);
-  expect_block_writes(mock_image_ctx, 0);
-  expect_op_work_queue(mock_image_ctx);
-
-  InSequence seq;
-  expect_prepare_lock(mock_image_ctx);
-  expect_cancel_op_requests(mock_image_ctx, 0);
-  expect_flush_notifies(mock_image_ctx);
-
-  MockObjectMap *mock_object_map = new MockObjectMap();
-  mock_image_ctx.object_map = mock_object_map;
-  expect_close_object_map(mock_image_ctx, *mock_object_map);
-
-  expect_unlock(mock_image_ctx, 0);
-  expect_handle_prepare_lock_complete(mock_image_ctx);
-
-  C_SaferCond release_ctx;
-  C_SaferCond ctx;
-  MockReleaseRequest *req = MockReleaseRequest::create(mock_image_ctx,
-                                                       TEST_COOKIE,
-                                                       &release_ctx, &ctx,
-                                                       false);
-  req->send();
-  ASSERT_EQ(0, release_ctx.wait());
-  ASSERT_EQ(0, ctx.wait());
-}
-
-TEST_F(TestMockExclusiveLockReleaseRequest, SuccessObjectMapDisabled) {
-  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
-
-  librbd::ImageCtx *ictx;
-  ASSERT_EQ(0, open_image(m_image_name, &ictx));
-
-  MockImageCtx mock_image_ctx(*ictx);
-  expect_block_writes(mock_image_ctx, 0);
-  expect_op_work_queue(mock_image_ctx);
-
-  InSequence seq;
-  expect_cancel_op_requests(mock_image_ctx, 0);
-  expect_flush_notifies(mock_image_ctx);
-
-  expect_unlock(mock_image_ctx, 0);
-
-  C_SaferCond release_ctx;
-  C_SaferCond ctx;
-  MockReleaseRequest *req = MockReleaseRequest::create(mock_image_ctx,
-                                                       TEST_COOKIE,
-                                                       &release_ctx, &ctx,
-                                                       true);
-  req->send();
-  ASSERT_EQ(0, release_ctx.wait());
-  ASSERT_EQ(0, ctx.wait());
-}
-
-TEST_F(TestMockExclusiveLockReleaseRequest, BlockWritesError) {
-  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
-
-  librbd::ImageCtx *ictx;
-  ASSERT_EQ(0, open_image(m_image_name, &ictx));
-
-  MockImageCtx mock_image_ctx(*ictx);
-  expect_op_work_queue(mock_image_ctx);
-
-  InSequence seq;
-  expect_cancel_op_requests(mock_image_ctx, 0);
-  expect_block_writes(mock_image_ctx, -EINVAL);
-  expect_unblock_writes(mock_image_ctx);
-
-  C_SaferCond ctx;
-  MockReleaseRequest *req = MockReleaseRequest::create(mock_image_ctx,
-                                                       TEST_COOKIE,
-                                                       nullptr, &ctx,
-                                                       true);
-  req->send();
-  ASSERT_EQ(-EINVAL, ctx.wait());
-}
-
-TEST_F(TestMockExclusiveLockReleaseRequest, UnlockError) {
-  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
-
-  librbd::ImageCtx *ictx;
-  ASSERT_EQ(0, open_image(m_image_name, &ictx));
-
-  MockImageCtx mock_image_ctx(*ictx);
-  expect_op_work_queue(mock_image_ctx);
-
-  InSequence seq;
-  expect_cancel_op_requests(mock_image_ctx, 0);
-  expect_block_writes(mock_image_ctx, 0);
-  expect_flush_notifies(mock_image_ctx);
-
-  expect_unlock(mock_image_ctx, -EINVAL);
-
-  C_SaferCond ctx;
-  MockReleaseRequest *req = MockReleaseRequest::create(mock_image_ctx,
-                                                       TEST_COOKIE,
-                                                       nullptr, &ctx,
-                                                       true);
-  req->send();
-  ASSERT_EQ(0, ctx.wait());
-}
-
-} // namespace exclusive_lock
-} // namespace librbd
index d27b7274eb42fa7ce5ddfe9b1ff0e6a61057aa5b..23a99ef07b3a0f682bd2dedf29c649a56d30ce77 100644 (file)
@@ -30,7 +30,7 @@ public:
     C_SaferCond lock_ctx;
     {
       RWLock::WLocker owner_locker(ictx->owner_lock);
-      ictx->exclusive_lock->request_lock(&lock_ctx);
+      ictx->exclusive_lock->acquire_lock(&lock_ctx);
     }
     int r = lock_ctx.wait();
     if (r < 0) {
index 6e3621ad82bd29cf5fc469ef16e3a2e1cfc380f3..c6ae51cdffecfce258943044383c71100a2b7ab7 100644 (file)
@@ -23,7 +23,7 @@ struct MockExclusiveLock {
   MOCK_METHOD1(block_requests, void(int));
   MOCK_METHOD0(unblock_requests, void());
 
-  MOCK_METHOD1(request_lock, void(Context *));
+  MOCK_METHOD1(acquire_lock, void(Context *));
   MOCK_METHOD1(release_lock, void(Context *));
 };
 
index c2f7d8f12cf9128e203fde0f8be9410d0b2d9d43..a0bf3ea85bc50cce618ed9757374285677628490 100644 (file)
@@ -295,64 +295,6 @@ struct RebuildObjectMapTask {
   }
 };
 
-TEST_F(TestImageWatcher, NotifyRequestLock) {
-  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
-
-  librbd::ImageCtx *ictx;
-  ASSERT_EQ(0, open_image(m_image_name, &ictx));
-
-  ASSERT_EQ(0, register_image_watch(*ictx));
-
-  m_notify_acks = {{NOTIFY_OP_REQUEST_LOCK, {}}};
-  ictx->image_watcher->notify_request_lock();
-
-  C_SaferCond ctx;
-  ictx->image_watcher->flush(&ctx);
-  ctx.wait();
-
-  ASSERT_TRUE(wait_for_notifies(*ictx));
-
-  NotifyOps expected_notify_ops;
-  expected_notify_ops += NOTIFY_OP_REQUEST_LOCK;
-  ASSERT_EQ(expected_notify_ops, m_notifies);
-}
-
-TEST_F(TestImageWatcher, NotifyReleasedLock) {
-  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
-
-  librbd::ImageCtx *ictx;
-  ASSERT_EQ(0, open_image(m_image_name, &ictx));
-
-  ASSERT_EQ(0, register_image_watch(*ictx));
-
-  m_notify_acks = {{NOTIFY_OP_RELEASED_LOCK, {}}};
-  ictx->image_watcher->notify_released_lock();
-
-  ASSERT_TRUE(wait_for_notifies(*ictx));
-
-  NotifyOps expected_notify_ops;
-  expected_notify_ops += NOTIFY_OP_RELEASED_LOCK;
-  ASSERT_EQ(expected_notify_ops, m_notifies);
-}
-
-TEST_F(TestImageWatcher, NotifyAcquiredLock) {
-  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
-
-  librbd::ImageCtx *ictx;
-  ASSERT_EQ(0, open_image(m_image_name, &ictx));
-
-  ASSERT_EQ(0, register_image_watch(*ictx));
-
-  m_notify_acks = {{NOTIFY_OP_ACQUIRED_LOCK, {}}};
-  ictx->image_watcher->notify_acquired_lock();
-
-  ASSERT_TRUE(wait_for_notifies(*ictx));
-
-  NotifyOps expected_notify_ops;
-  expected_notify_ops += NOTIFY_OP_ACQUIRED_LOCK;
-  ASSERT_EQ(expected_notify_ops, m_notifies);
-}
-
 TEST_F(TestImageWatcher, NotifyHeaderUpdate) {
   REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
 
index 65d59ffb954b948039e2b8e178eb1d4d11e9a00a..ac933e52129723ab445ce1bc872a4728f8267f27 100644 (file)
@@ -34,7 +34,7 @@ TEST_F(TestObjectMap, RefreshInvalidatesWhenCorrupt) {
   C_SaferCond lock_ctx;
   {
     RWLock::WLocker owner_locker(ictx->owner_lock);
-    ictx->exclusive_lock->try_lock(&lock_ctx);
+    ictx->exclusive_lock->try_acquire_lock(&lock_ctx);
   }
   ASSERT_EQ(0, lock_ctx.wait());
 
@@ -57,7 +57,7 @@ TEST_F(TestObjectMap, RefreshInvalidatesWhenTooSmall) {
   C_SaferCond lock_ctx;
   {
     RWLock::WLocker owner_locker(ictx->owner_lock);
-    ictx->exclusive_lock->try_lock(&lock_ctx);
+    ictx->exclusive_lock->try_acquire_lock(&lock_ctx);
   }
   ASSERT_EQ(0, lock_ctx.wait());
 
@@ -81,7 +81,7 @@ TEST_F(TestObjectMap, InvalidateFlagOnDisk) {
   C_SaferCond lock_ctx;
   {
     RWLock::WLocker owner_locker(ictx->owner_lock);
-    ictx->exclusive_lock->try_lock(&lock_ctx);
+    ictx->exclusive_lock->try_acquire_lock(&lock_ctx);
   }
   ASSERT_EQ(0, lock_ctx.wait());
 
index a540ba6b917a9f1aa8adcb1d862ee6c1164a92de..d97cda99b8901259705f3b76550121384b770744 100644 (file)
@@ -100,7 +100,7 @@ TEST_F(TestInternal, IsExclusiveLockOwner) {
   C_SaferCond ctx;
   {
     RWLock::WLocker l(ictx->owner_lock);
-    ictx->exclusive_lock->try_lock(&ctx);
+    ictx->exclusive_lock->try_acquire_lock(&ctx);
   }
   ASSERT_EQ(0, ctx.wait());
   ASSERT_EQ(0, librbd::is_exclusive_lock_owner(ictx, &is_owner));
@@ -317,7 +317,7 @@ TEST_F(TestInternal, CancelAsyncResize) {
   C_SaferCond ctx;
   {
     RWLock::WLocker l(ictx->owner_lock);
-    ictx->exclusive_lock->try_lock(&ctx);
+    ictx->exclusive_lock->try_acquire_lock(&ctx);
   }
 
   ASSERT_EQ(0, ctx.wait());
@@ -360,7 +360,7 @@ TEST_F(TestInternal, MultipleResize) {
     C_SaferCond ctx;
     {
       RWLock::WLocker l(ictx->owner_lock);
-      ictx->exclusive_lock->try_lock(&ctx);
+      ictx->exclusive_lock->try_acquire_lock(&ctx);
     }
 
     RWLock::RLocker owner_locker(ictx->owner_lock);
index 5d6eb17458eda2bba1b156ea4704b7cea6f88045..5b7ec332d51066a7b24b09468c940f8ab120085d 100644 (file)
@@ -5,9 +5,13 @@
 #include "test/librbd/test_support.h"
 #include "test/librbd/mock/MockImageCtx.h"
 #include "librbd/ExclusiveLock.h"
-#include "librbd/exclusive_lock/AcquireRequest.h"
-#include "librbd/exclusive_lock/ReacquireRequest.h"
-#include "librbd/exclusive_lock/ReleaseRequest.h"
+#include "librbd/ManagedLock.h"
+#include "librbd/exclusive_lock/PreAcquireRequest.h"
+#include "librbd/exclusive_lock/PostAcquireRequest.h"
+#include "librbd/exclusive_lock/PreReleaseRequest.h"
+#include "librbd/managed_lock/AcquireRequest.h"
+#include "librbd/managed_lock/ReacquireRequest.h"
+#include "librbd/managed_lock/ReleaseRequest.h"
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 #include <list>
@@ -17,21 +21,33 @@ namespace librbd {
 namespace {
 
 struct MockExclusiveLockImageCtx : public MockImageCtx {
+  ContextWQ *op_work_queue;
+
   MockExclusiveLockImageCtx(ImageCtx &image_ctx) : MockImageCtx(image_ctx) {
+    op_work_queue = image_ctx.op_work_queue;
   }
 };
 
 } // anonymous namespace
 
+namespace watcher {
+template <>
+struct Traits<MockExclusiveLockImageCtx> {
+  typedef librbd::MockImageWatcher Watcher;
+};
+}
+
 namespace exclusive_lock {
 
+using librbd::ImageWatcher;
+
 template<typename T>
 struct BaseRequest {
   static std::list<T *> s_requests;
   Context *on_lock_unlock = nullptr;
   Context *on_finish = nullptr;
 
-  static T* create(MockExclusiveLockImageCtx &image_ctx, const std::string &cookie,
+  static T* create(MockExclusiveLockImageCtx &image_ctx,
                    Context *on_lock_unlock, Context *on_finish,
                    bool shutting_down = false) {
     assert(!s_requests.empty());
@@ -50,6 +66,52 @@ struct BaseRequest {
 template<typename T>
 std::list<T *> BaseRequest<T>::s_requests;
 
+template <>
+struct PreAcquireRequest<MockExclusiveLockImageCtx> : public BaseRequest<PreAcquireRequest<MockExclusiveLockImageCtx> > {
+  static PreAcquireRequest<MockExclusiveLockImageCtx> *create(
+      MockExclusiveLockImageCtx &image_ctx, Context *on_finish) {
+    return BaseRequest::create(image_ctx, nullptr, on_finish);
+  }
+  MOCK_METHOD0(send, void());
+};
+
+template <>
+struct PostAcquireRequest<MockExclusiveLockImageCtx> : public BaseRequest<PostAcquireRequest<MockExclusiveLockImageCtx> > {
+  MOCK_METHOD0(send, void());
+};
+
+template <>
+struct PreReleaseRequest<MockExclusiveLockImageCtx> : public BaseRequest<PreReleaseRequest<MockExclusiveLockImageCtx> > {
+  MOCK_METHOD0(send, void());
+};
+
+} // namespace exclusive_lock
+
+namespace managed_lock {
+
+template<typename T>
+struct BaseRequest {
+  static std::list<T *> s_requests;
+  Context *on_finish = nullptr;
+
+  static T* create(librados::IoCtx& ioctx, MockImageWatcher *watcher,
+                   ContextWQ *work_queue, const std::string& oid,
+                   const std::string& cookie, Context *on_finish) {
+    assert(!s_requests.empty());
+    T* req = s_requests.front();
+    req->on_finish = on_finish;
+    s_requests.pop_front();
+    return req;
+  }
+
+  BaseRequest() {
+    s_requests.push_back(reinterpret_cast<T*>(this));
+  }
+};
+
+template<typename T>
+std::list<T *> BaseRequest<T>::s_requests;
+
 template <>
 struct AcquireRequest<MockExclusiveLockImageCtx> : public BaseRequest<AcquireRequest<MockExclusiveLockImageCtx> > {
   MOCK_METHOD0(send, void());
@@ -57,11 +119,10 @@ struct AcquireRequest<MockExclusiveLockImageCtx> : public BaseRequest<AcquireReq
 
 template <>
 struct ReacquireRequest<MockExclusiveLockImageCtx> : public BaseRequest<ReacquireRequest<MockExclusiveLockImageCtx> > {
-  static ReacquireRequest* create(MockExclusiveLockImageCtx &image_ctx,
-                                  const std::string &cookie,
-                                  const std::string &new_cookie,
-                                  Context *on_finish) {
-    return BaseRequest::create(image_ctx, cookie, nullptr, on_finish);
+  static ReacquireRequest* create(librados::IoCtx &ioctx, const std::string& oid,
+                                const string& old_cookie, const std::string& new_cookie,
+                                Context *on_finish) {
+    return BaseRequest::create(ioctx, nullptr, nullptr, oid, new_cookie, on_finish);
   }
 
   MOCK_METHOD0(send, void());
@@ -72,19 +133,27 @@ struct ReleaseRequest<MockExclusiveLockImageCtx> : public BaseRequest<ReleaseReq
   MOCK_METHOD0(send, void());
 };
 
-} // namespace exclusive_lock
+
+} // namespace managed_lock
 } // namespace librbd
 
 // template definitions
 #include "librbd/ExclusiveLock.cc"
 template class librbd::ExclusiveLock<librbd::MockExclusiveLockImageCtx>;
 
+#include "librbd/ManagedLock.cc"
+template class librbd::ManagedLock<librbd::MockExclusiveLockImageCtx>;
+
 ACTION_P(FinishLockUnlock, request) {
   if (request->on_lock_unlock != nullptr) {
     request->on_lock_unlock->complete(0);
   }
 }
 
+ACTION_P2(CompleteRequest, request, ret) {
+  request->on_finish->complete(ret);
+}
+
 namespace librbd {
 
 using ::testing::_;
@@ -96,14 +165,17 @@ using ::testing::Return;
 class TestMockExclusiveLock : public TestMockFixture {
 public:
   typedef ExclusiveLock<MockExclusiveLockImageCtx> MockExclusiveLock;
-  typedef exclusive_lock::AcquireRequest<MockExclusiveLockImageCtx> MockAcquireRequest;
-  typedef exclusive_lock::ReacquireRequest<MockExclusiveLockImageCtx> MockReacquireRequest;
-  typedef exclusive_lock::ReleaseRequest<MockExclusiveLockImageCtx> MockReleaseRequest;
+  typedef exclusive_lock::PreAcquireRequest<MockExclusiveLockImageCtx> MockPreAcquireRequest;
+  typedef exclusive_lock::PostAcquireRequest<MockExclusiveLockImageCtx> MockPostAcquireRequest;
+  typedef exclusive_lock::PreReleaseRequest<MockExclusiveLockImageCtx> MockPreReleaseRequest;
+  typedef managed_lock::AcquireRequest<MockExclusiveLockImageCtx> MockManagedAcquireRequest;
+  typedef managed_lock::ReacquireRequest<MockExclusiveLockImageCtx> MockManagedReacquireRequest;
+  typedef managed_lock::ReleaseRequest<MockExclusiveLockImageCtx> MockManagedReleaseRequest;
 
   void expect_get_watch_handle(MockExclusiveLockImageCtx &mock_image_ctx,
                                uint64_t watch_handle = 1234567890) {
     EXPECT_CALL(*mock_image_ctx.image_watcher, get_watch_handle())
-                  .WillRepeatedly(Return(watch_handle));
+                  .WillOnce(Return(watch_handle));
   }
 
   void expect_set_require_lock_on_read(MockExclusiveLockImageCtx &mock_image_ctx) {
@@ -128,24 +200,41 @@ public:
   }
 
   void expect_acquire_lock(MockExclusiveLockImageCtx &mock_image_ctx,
-                           MockAcquireRequest &acquire_request, int r) {
+                           MockPreAcquireRequest &pre_acquire_request,
+                           MockManagedAcquireRequest &managed_acquire_request,
+                           MockPostAcquireRequest *post_acquire_request,
+                           int pre_r, int managed_r, int post_r) {
+
     expect_get_watch_handle(mock_image_ctx);
-    EXPECT_CALL(acquire_request, send())
-                  .WillOnce(DoAll(FinishLockUnlock(&acquire_request),
-                                  FinishRequest(&acquire_request, r, &mock_image_ctx)));
-    if (r == 0) {
+
+    EXPECT_CALL(pre_acquire_request, send())
+                .WillOnce(CompleteRequest(&pre_acquire_request, pre_r));
+    EXPECT_CALL(managed_acquire_request, send())
+                .WillOnce(CompleteRequest(&managed_acquire_request, managed_r));
+    if (managed_r == 0) {
+      assert(post_acquire_request != nullptr);
+      EXPECT_CALL(*post_acquire_request, send())
+          .WillOnce(DoAll(FinishLockUnlock(post_acquire_request),
+                          CompleteRequest(post_acquire_request, post_r)));
+    }
+
+    if (pre_r == 0 && managed_r == 0 && post_r == 0) {
       expect_notify_acquired_lock(mock_image_ctx);
       expect_unblock_writes(mock_image_ctx);
     }
   }
 
   void expect_release_lock(MockExclusiveLockImageCtx &mock_image_ctx,
-                           MockReleaseRequest &release_request, int r,
-                           bool shutting_down = false) {
-    EXPECT_CALL(release_request, send())
-                  .WillOnce(DoAll(FinishLockUnlock(&release_request),
-                                  FinishRequest(&release_request, r, &mock_image_ctx)));
-    if (r == 0) {
+                           MockPreReleaseRequest &pre_release_request,
+                           MockManagedReleaseRequest &managed_release_request,
+                           int pre_r, int managed_r, bool shutting_down = false) {
+    EXPECT_CALL(pre_release_request, send())
+        .WillOnce(DoAll(FinishLockUnlock(&pre_release_request),
+                        CompleteRequest(&pre_release_request, pre_r)));
+    EXPECT_CALL(managed_release_request, send())
+        .WillOnce(CompleteRequest(&managed_release_request, managed_r));
+
+    if (pre_r == 0 && managed_r == 0) {
       if (shutting_down) {
         expect_unblock_writes(mock_image_ctx);
       }
@@ -155,11 +244,12 @@ public:
   }
 
   void expect_reacquire_lock(MockExclusiveLockImageCtx &mock_image_ctx,
-                             MockReacquireRequest &mock_reacquire_request,
+                             MockManagedReacquireRequest &mock_reacquire_request,
                              int r) {
-    expect_get_watch_handle(mock_image_ctx, 98765);
+    EXPECT_CALL(*mock_image_ctx.image_watcher, get_watch_handle())
+                  .WillOnce(Return(98765));
     EXPECT_CALL(mock_reacquire_request, send())
-                  .WillOnce(FinishRequest(&mock_reacquire_request, r, &mock_image_ctx));
+                  .WillOnce(CompleteRequest(&mock_reacquire_request, r));
   }
 
   void expect_notify_request_lock(MockExclusiveLockImageCtx &mock_image_ctx,
@@ -171,12 +261,12 @@ public:
 
   void expect_notify_acquired_lock(MockExclusiveLockImageCtx &mock_image_ctx) {
     EXPECT_CALL(*mock_image_ctx.image_watcher, notify_acquired_lock())
-                  .Times(1);
+      .Times(1);
   }
 
   void expect_notify_released_lock(MockExclusiveLockImageCtx &mock_image_ctx) {
     EXPECT_CALL(*mock_image_ctx.image_watcher, notify_released_lock())
-                  .Times(1);
+      .Times(1);
   }
 
   void expect_is_lock_request_needed(MockExclusiveLockImageCtx &mock_image_ctx, bool ret) {
@@ -204,7 +294,7 @@ public:
     C_SaferCond ctx;
     {
       RWLock::WLocker owner_locker(mock_image_ctx.owner_lock);
-      exclusive_lock.try_lock(&ctx);
+      exclusive_lock.try_acquire_lock(&ctx);
     }
     return ctx.wait();
   }
@@ -213,7 +303,7 @@ public:
     C_SaferCond ctx;
     {
       RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
-      exclusive_lock.request_lock(&ctx);
+      exclusive_lock.acquire_lock(&ctx);
     }
     return ctx.wait();
   }
@@ -257,23 +347,34 @@ TEST_F(TestMockExclusiveLock, StateTransitions) {
   expect_block_writes(mock_image_ctx);
   ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
 
-  MockAcquireRequest try_lock_acquire;
-  expect_acquire_lock(mock_image_ctx, try_lock_acquire, 0);
+  MockPreAcquireRequest try_lock_pre_acquire;
+  MockManagedAcquireRequest try_lock_managed_acquire;
+  MockPostAcquireRequest try_lock_post_acquire;
+  expect_acquire_lock(mock_image_ctx, try_lock_pre_acquire,
+                      try_lock_managed_acquire, &try_lock_post_acquire, 0, 0, 0);
   ASSERT_EQ(0, when_try_lock(mock_image_ctx, exclusive_lock));
   ASSERT_TRUE(is_lock_owner(mock_image_ctx, exclusive_lock));
 
-  MockReleaseRequest request_release;
-  expect_release_lock(mock_image_ctx, request_release, 0);
+  MockPreReleaseRequest pre_request_release;
+  MockManagedReleaseRequest managed_request_release;
+  expect_release_lock(mock_image_ctx, pre_request_release,
+                      managed_request_release, 0, 0);
   ASSERT_EQ(0, when_release_lock(mock_image_ctx, exclusive_lock));
   ASSERT_FALSE(is_lock_owner(mock_image_ctx, exclusive_lock));
 
-  MockAcquireRequest request_lock_acquire;
-  expect_acquire_lock(mock_image_ctx, request_lock_acquire, 0);
+  MockPreAcquireRequest request_lock_pre_acquire;
+  MockManagedAcquireRequest request_lock_managed_acquire;
+  MockPostAcquireRequest request_lock_post_acquire;
+  expect_acquire_lock(mock_image_ctx, request_lock_pre_acquire,
+                      request_lock_managed_acquire, &request_lock_post_acquire,
+                      0, 0, 0);
   ASSERT_EQ(0, when_request_lock(mock_image_ctx, exclusive_lock));
   ASSERT_TRUE(is_lock_owner(mock_image_ctx, exclusive_lock));
 
-  MockReleaseRequest shutdown_release;
-  expect_release_lock(mock_image_ctx, shutdown_release, 0, true);
+  MockPreReleaseRequest shutdown_pre_release;
+  MockManagedReleaseRequest shutdown_managed_release;
+  expect_release_lock(mock_image_ctx, shutdown_pre_release,
+                      shutdown_managed_release, 0, 0, true);
   ASSERT_EQ(0, when_shut_down(mock_image_ctx, exclusive_lock));
   ASSERT_FALSE(is_lock_owner(mock_image_ctx, exclusive_lock));
 }
@@ -292,13 +393,18 @@ TEST_F(TestMockExclusiveLock, TryLockLockedState) {
   expect_block_writes(mock_image_ctx);
   ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
 
-  MockAcquireRequest try_lock_acquire;
-  expect_acquire_lock(mock_image_ctx, try_lock_acquire, 0);
+  MockPreAcquireRequest try_lock_pre_acquire;
+  MockManagedAcquireRequest try_lock_managed_acquire;
+  MockPostAcquireRequest try_lock_post_acquire;
+  expect_acquire_lock(mock_image_ctx, try_lock_pre_acquire,
+                      try_lock_managed_acquire, &try_lock_post_acquire, 0, 0, 0);
   ASSERT_EQ(0, when_try_lock(mock_image_ctx, exclusive_lock));
   ASSERT_EQ(0, when_try_lock(mock_image_ctx, exclusive_lock));
 
-  MockReleaseRequest shutdown_release;
-  expect_release_lock(mock_image_ctx, shutdown_release, 0, true);
+  MockPreReleaseRequest shutdown_pre_release;
+  MockManagedReleaseRequest shutdown_managed_release;
+  expect_release_lock(mock_image_ctx, shutdown_pre_release,
+                      shutdown_managed_release, 0, 0, true);
   ASSERT_EQ(0, when_shut_down(mock_image_ctx, exclusive_lock));
 }
 
@@ -316,8 +422,10 @@ TEST_F(TestMockExclusiveLock, TryLockAlreadyLocked) {
   expect_block_writes(mock_image_ctx);
   ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
 
-  MockAcquireRequest try_lock_acquire;
-  expect_acquire_lock(mock_image_ctx, try_lock_acquire, -EAGAIN);
+  MockPreAcquireRequest try_lock_pre_acquire;
+  MockManagedAcquireRequest try_lock_managed_acquire;
+  expect_acquire_lock(mock_image_ctx, try_lock_pre_acquire,
+                      try_lock_managed_acquire, nullptr, 0, -EAGAIN, 0);
   ASSERT_EQ(0, when_try_lock(mock_image_ctx, exclusive_lock));
   ASSERT_FALSE(is_lock_owner(mock_image_ctx, exclusive_lock));
 
@@ -340,8 +448,10 @@ TEST_F(TestMockExclusiveLock, TryLockBusy) {
   expect_block_writes(mock_image_ctx);
   ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
 
-  MockAcquireRequest try_lock_acquire;
-  expect_acquire_lock(mock_image_ctx, try_lock_acquire, -EBUSY);
+  MockPreAcquireRequest try_lock_pre_acquire;
+  MockManagedAcquireRequest try_lock_managed_acquire;
+  expect_acquire_lock(mock_image_ctx, try_lock_pre_acquire,
+                      try_lock_managed_acquire, nullptr, 0, -EBUSY, 0);
   ASSERT_EQ(-EBUSY, when_try_lock(mock_image_ctx, exclusive_lock));
   ASSERT_FALSE(is_lock_owner(mock_image_ctx, exclusive_lock));
 
@@ -362,11 +472,12 @@ TEST_F(TestMockExclusiveLock, TryLockError) {
 
   InSequence seq;
   expect_block_writes(mock_image_ctx);
-
-  MockAcquireRequest try_lock_acquire;
-  expect_acquire_lock(mock_image_ctx, try_lock_acquire, -EINVAL);
-
   ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
+
+  MockPreAcquireRequest try_lock_pre_acquire;
+  MockManagedAcquireRequest try_lock_managed_acquire;
+  expect_acquire_lock(mock_image_ctx, try_lock_pre_acquire,
+                      try_lock_managed_acquire, nullptr, 0, -EINVAL, 0);
   ASSERT_EQ(-EINVAL, when_try_lock(mock_image_ctx, exclusive_lock));
   ASSERT_FALSE(is_lock_owner(mock_image_ctx, exclusive_lock));
 
@@ -389,14 +500,19 @@ TEST_F(TestMockExclusiveLock, RequestLockLockedState) {
   expect_block_writes(mock_image_ctx);
   ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
 
-  MockAcquireRequest try_lock_acquire;
-  expect_acquire_lock(mock_image_ctx, try_lock_acquire, 0);
+  MockPreAcquireRequest try_lock_pre_acquire;
+  MockManagedAcquireRequest try_lock_managed_acquire;
+  MockPostAcquireRequest try_lock_post_acquire;
+  expect_acquire_lock(mock_image_ctx, try_lock_pre_acquire,
+                      try_lock_managed_acquire, &try_lock_post_acquire, 0, 0, 0);
   ASSERT_EQ(0, when_try_lock(mock_image_ctx, exclusive_lock));
-
-  MockReleaseRequest shutdown_release;
-  expect_release_lock(mock_image_ctx, shutdown_release, 0, true);
+  ASSERT_TRUE(is_lock_owner(mock_image_ctx, exclusive_lock));
   ASSERT_EQ(0, when_request_lock(mock_image_ctx, exclusive_lock));
 
+  MockPreReleaseRequest shutdown_pre_release;
+  MockManagedReleaseRequest shutdown_managed_release;
+  expect_release_lock(mock_image_ctx, shutdown_pre_release,
+                      shutdown_managed_release, 0, 0, true);
   ASSERT_EQ(0, when_shut_down(mock_image_ctx, exclusive_lock));
 }
 
@@ -415,9 +531,10 @@ TEST_F(TestMockExclusiveLock, RequestLockBlacklist) {
   ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
 
   // will abort after seeing blacklist error (avoid infinite request loop)
-  MockAcquireRequest request_lock_acquire;
-  expect_acquire_lock(mock_image_ctx, request_lock_acquire, -EBLACKLISTED);
-  expect_notify_request_lock(mock_image_ctx, exclusive_lock);
+  MockPreAcquireRequest request_pre_acquire;
+  MockManagedAcquireRequest request_managed_acquire;
+  expect_acquire_lock(mock_image_ctx, request_pre_acquire,
+                      request_managed_acquire, nullptr, 0, -EBLACKLISTED, 0);
   ASSERT_EQ(-EBLACKLISTED, when_request_lock(mock_image_ctx, exclusive_lock));
   ASSERT_FALSE(is_lock_owner(mock_image_ctx, exclusive_lock));
 
@@ -441,17 +558,25 @@ TEST_F(TestMockExclusiveLock, RequestLockBusy) {
   ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
 
   // will repeat until successfully acquires the lock
-  MockAcquireRequest request_lock_acquire1;
-  expect_acquire_lock(mock_image_ctx, request_lock_acquire1, -EBUSY);
+  MockPreAcquireRequest request_lock_pre_acquire1;
+  MockManagedAcquireRequest request_lock_managed_acquire1;
+  expect_acquire_lock(mock_image_ctx, request_lock_pre_acquire1,
+                      request_lock_managed_acquire1, nullptr, 0, -EBUSY, 0);
   expect_notify_request_lock(mock_image_ctx, exclusive_lock);
 
-  MockAcquireRequest request_lock_acquire2;
-  expect_acquire_lock(mock_image_ctx, request_lock_acquire2, 0);
+  MockPreAcquireRequest request_lock_pre_acquire2;
+  MockManagedAcquireRequest request_lock_managed_acquire2;
+  MockPostAcquireRequest request_lock_post_acquire2;
+  expect_acquire_lock(mock_image_ctx, request_lock_pre_acquire2,
+                      request_lock_managed_acquire2,
+                      &request_lock_post_acquire2, 0, 0, 0);
   ASSERT_EQ(0, when_request_lock(mock_image_ctx, exclusive_lock));
   ASSERT_TRUE(is_lock_owner(mock_image_ctx, exclusive_lock));
 
-  MockReleaseRequest shutdown_release;
-  expect_release_lock(mock_image_ctx, shutdown_release, 0, true);
+  MockPreReleaseRequest shutdown_pre_release;
+  MockManagedReleaseRequest shutdown_managed_release;
+  expect_release_lock(mock_image_ctx, shutdown_pre_release,
+                      shutdown_managed_release, 0, 0, true);
   ASSERT_EQ(0, when_shut_down(mock_image_ctx, exclusive_lock));
 }
 
@@ -470,17 +595,57 @@ TEST_F(TestMockExclusiveLock, RequestLockError) {
   ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
 
   // will repeat until successfully acquires the lock
-  MockAcquireRequest request_lock_acquire1;
-  expect_acquire_lock(mock_image_ctx, request_lock_acquire1, -EINVAL);
+  MockPreAcquireRequest request_lock_pre_acquire1;
+  MockManagedAcquireRequest request_lock_managed_acquire1;
+  expect_acquire_lock(mock_image_ctx, request_lock_pre_acquire1,
+                      request_lock_managed_acquire1, nullptr, 0, -EINVAL, 0);
   expect_notify_request_lock(mock_image_ctx, exclusive_lock);
 
-  MockAcquireRequest request_lock_acquire2;
-  expect_acquire_lock(mock_image_ctx, request_lock_acquire2, 0);
+  MockPreAcquireRequest request_lock_pre_acquire2;
+  MockManagedAcquireRequest request_lock_managed_acquire2;
+  MockPostAcquireRequest request_lock_post_acquire2;
+  expect_acquire_lock(mock_image_ctx, request_lock_pre_acquire2,
+                      request_lock_managed_acquire2,
+                      &request_lock_post_acquire2, 0, 0, 0);
   ASSERT_EQ(0, when_request_lock(mock_image_ctx, exclusive_lock));
   ASSERT_TRUE(is_lock_owner(mock_image_ctx, exclusive_lock));
 
-  MockReleaseRequest shutdown_release;
-  expect_release_lock(mock_image_ctx, shutdown_release, 0, true);
+  MockPreReleaseRequest shutdown_pre_release;
+  MockManagedReleaseRequest shutdown_managed_release;
+  expect_release_lock(mock_image_ctx, shutdown_pre_release,
+                      shutdown_managed_release, 0, 0, true);
+  ASSERT_EQ(0, when_shut_down(mock_image_ctx, exclusive_lock));
+}
+
+TEST_F(TestMockExclusiveLock, RequestLockJournalEPERM) {
+  REQUIRE_FEATURE(RBD_FEATURE_EXCLUSIVE_LOCK);
+
+  librbd::ImageCtx *ictx;
+  ASSERT_EQ(0, open_image(m_image_name, &ictx));
+
+  MockExclusiveLockImageCtx mock_image_ctx(*ictx);
+  MockExclusiveLock exclusive_lock(mock_image_ctx);
+  expect_op_work_queue(mock_image_ctx);
+
+  InSequence seq;
+  expect_block_writes(mock_image_ctx);
+  ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
+
+  // will abort after seeing perm error (avoid infinite request loop)
+  MockPreAcquireRequest request_lock_pre_acquire;
+  MockManagedAcquireRequest request_lock_managed_acquire;
+  MockPostAcquireRequest request_lock_post_acquire;
+  expect_acquire_lock(mock_image_ctx, request_lock_pre_acquire,
+                      request_lock_managed_acquire,
+                      &request_lock_post_acquire, 0, 0, -EPERM);
+  MockManagedReleaseRequest release_on_error;
+  EXPECT_CALL(release_on_error, send())
+    .WillOnce(CompleteRequest(&release_on_error, 0));
+  ASSERT_EQ(-EPERM, when_request_lock(mock_image_ctx, exclusive_lock));
+  ASSERT_FALSE(is_lock_owner(mock_image_ctx, exclusive_lock));
+
+  expect_unblock_writes(mock_image_ctx);
+  expect_flush_notifies(mock_image_ctx);
   ASSERT_EQ(0, when_shut_down(mock_image_ctx, exclusive_lock));
 }
 
@@ -519,18 +684,24 @@ TEST_F(TestMockExclusiveLock, ReleaseLockError) {
   expect_block_writes(mock_image_ctx);
   ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
 
-  MockAcquireRequest try_lock_acquire;
-  expect_acquire_lock(mock_image_ctx, try_lock_acquire, 0);
+  MockPreAcquireRequest try_lock_pre_acquire;
+  MockManagedAcquireRequest try_lock_managed_acquire;
+  MockPostAcquireRequest try_lock_post_acquire;
+  expect_acquire_lock(mock_image_ctx, try_lock_pre_acquire,
+                      try_lock_managed_acquire, &try_lock_post_acquire, 0, 0, 0);
   ASSERT_EQ(0, when_try_lock(mock_image_ctx, exclusive_lock));
 
-  MockReleaseRequest release;
-  expect_release_lock(mock_image_ctx, release, -EINVAL);
-
+  MockPreReleaseRequest request_pre_release;
+  MockManagedReleaseRequest request_managed_release;
+  expect_release_lock(mock_image_ctx, request_pre_release,
+                      request_managed_release, 0, -EINVAL, false);
   ASSERT_EQ(-EINVAL, when_release_lock(mock_image_ctx, exclusive_lock));
   ASSERT_TRUE(is_lock_owner(mock_image_ctx, exclusive_lock));
 
-  MockReleaseRequest shutdown_release;
-  expect_release_lock(mock_image_ctx, shutdown_release, 0, true);
+  MockPreReleaseRequest shutdown_pre_release;
+  MockManagedReleaseRequest shutdown_managed_release;
+  expect_release_lock(mock_image_ctx, shutdown_pre_release,
+                      shutdown_managed_release, 0, 0, true);
   ASSERT_EQ(0, when_shut_down(mock_image_ctx, exclusive_lock));
   ASSERT_FALSE(is_lock_owner(mock_image_ctx, exclusive_lock));
 }
@@ -549,34 +720,49 @@ TEST_F(TestMockExclusiveLock, ConcurrentRequests) {
   expect_block_writes(mock_image_ctx);
   ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
 
-  MockAcquireRequest try_lock_acquire;
+  MockPreAcquireRequest try_lock_pre_acquire;
+  MockManagedAcquireRequest try_lock_managed_acquire;
+  MockPostAcquireRequest try_lock_post_acquire;
   C_SaferCond wait_for_send_ctx1;
   expect_get_watch_handle(mock_image_ctx);
-  EXPECT_CALL(try_lock_acquire, send())
+  EXPECT_CALL(try_lock_pre_acquire, send())
+                .WillOnce(CompleteRequest(&try_lock_pre_acquire, 0));
+  EXPECT_CALL(try_lock_managed_acquire, send())
+                .WillOnce(CompleteRequest(&try_lock_managed_acquire, 0));
+  EXPECT_CALL(try_lock_post_acquire, send())
                 .WillOnce(Notify(&wait_for_send_ctx1));
 
-  MockAcquireRequest request_acquire;
-  expect_acquire_lock(mock_image_ctx, request_acquire, 0);
+  MockManagedReleaseRequest managed_release_on_error;
+  EXPECT_CALL(managed_release_on_error, send())
+                .WillOnce(CompleteRequest(&managed_release_on_error, 0));
+
+  MockPreAcquireRequest request_pre_acquire;
+  MockManagedAcquireRequest request_managed_acquire;
+  MockPostAcquireRequest request_post_acquire;
+  expect_acquire_lock(mock_image_ctx, request_pre_acquire,
+                      request_managed_acquire, &request_post_acquire, 0, 0, 0);
 
-  MockReleaseRequest release;
+  MockPreReleaseRequest pre_release;
+  MockManagedReleaseRequest managed_release;
   C_SaferCond wait_for_send_ctx2;
-  EXPECT_CALL(release, send())
-                .WillOnce(Notify(&wait_for_send_ctx2));
+  EXPECT_CALL(pre_release, send()).WillOnce(Notify(&wait_for_send_ctx2));
+  EXPECT_CALL(managed_release, send())
+        .WillOnce(CompleteRequest(&managed_release, 0));
   expect_notify_released_lock(mock_image_ctx);
   expect_is_lock_request_needed(mock_image_ctx, false);
 
   C_SaferCond try_request_ctx1;
   {
     RWLock::WLocker owner_locker(mock_image_ctx.owner_lock);
-    exclusive_lock.try_lock(&try_request_ctx1);
+    exclusive_lock.try_acquire_lock(&try_request_ctx1);
   }
 
   C_SaferCond request_lock_ctx1;
   C_SaferCond request_lock_ctx2;
   {
     RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
-    exclusive_lock.request_lock(&request_lock_ctx1);
-    exclusive_lock.request_lock(&request_lock_ctx2);
+    exclusive_lock.acquire_lock(&request_lock_ctx1);
+    exclusive_lock.acquire_lock(&request_lock_ctx2);
   }
 
   C_SaferCond release_lock_ctx1;
@@ -588,13 +774,13 @@ TEST_F(TestMockExclusiveLock, ConcurrentRequests) {
   C_SaferCond request_lock_ctx3;
   {
     RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
-    exclusive_lock.request_lock(&request_lock_ctx3);
+    exclusive_lock.acquire_lock(&request_lock_ctx3);
   }
 
   // fail the try_lock
   ASSERT_EQ(0, wait_for_send_ctx1.wait());
-  try_lock_acquire.on_lock_unlock->complete(0);
-  try_lock_acquire.on_finish->complete(-EINVAL);
+  try_lock_post_acquire.on_lock_unlock->complete(0);
+  try_lock_post_acquire.on_finish->complete(-EINVAL);
   ASSERT_EQ(-EINVAL, try_request_ctx1.wait());
 
   // all three pending request locks should complete
@@ -604,8 +790,8 @@ TEST_F(TestMockExclusiveLock, ConcurrentRequests) {
 
   // proceed with the release
   ASSERT_EQ(0, wait_for_send_ctx2.wait());
-  release.on_lock_unlock->complete(0);
-  release.on_finish->complete(0);
+  pre_release.on_lock_unlock->complete(0);
+  pre_release.on_finish->complete(0);
   ASSERT_EQ(0, release_lock_ctx1.wait());
 
   expect_unblock_writes(mock_image_ctx);
@@ -628,8 +814,11 @@ TEST_F(TestMockExclusiveLock, BlockRequests) {
   expect_block_writes(mock_image_ctx);
   ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
 
-  MockAcquireRequest try_lock_acquire;
-  expect_acquire_lock(mock_image_ctx, try_lock_acquire, 0);
+  MockPreAcquireRequest try_lock_pre_acquire;
+  MockManagedAcquireRequest try_lock_managed_acquire;
+  MockPostAcquireRequest try_lock_post_acquire;
+  expect_acquire_lock(mock_image_ctx, try_lock_pre_acquire,
+                      try_lock_managed_acquire, &try_lock_post_acquire, 0, 0, 0);
   ASSERT_EQ(0, when_try_lock(mock_image_ctx, exclusive_lock));
   ASSERT_TRUE(is_lock_owner(mock_image_ctx, exclusive_lock));
 
@@ -645,8 +834,10 @@ TEST_F(TestMockExclusiveLock, BlockRequests) {
   ASSERT_TRUE(exclusive_lock.accept_requests(&ret_val));
   ASSERT_EQ(0, ret_val);
 
-  MockReleaseRequest shutdown_release;
-  expect_release_lock(mock_image_ctx, shutdown_release, 0, true);
+  MockPreReleaseRequest shutdown_pre_release;
+  MockManagedReleaseRequest shutdown_managed_release;
+  expect_release_lock(mock_image_ctx, shutdown_pre_release,
+                      shutdown_managed_release, 0, 0, true);
   ASSERT_EQ(0, when_shut_down(mock_image_ctx, exclusive_lock));
   ASSERT_FALSE(is_lock_owner(mock_image_ctx, exclusive_lock));
 }
@@ -675,13 +866,19 @@ TEST_F(TestMockExclusiveLock, RequestLockWatchNotRegistered) {
                     }),
                     Return(0)));
 
-  MockAcquireRequest request_lock_acquire;
-  expect_acquire_lock(mock_image_ctx, request_lock_acquire, 0);
+  MockPreAcquireRequest request_lock_pre_acquire;
+  MockManagedAcquireRequest request_lock_managed_acquire;
+  MockPostAcquireRequest request_lock_post_acquire;
+  expect_acquire_lock(mock_image_ctx, request_lock_pre_acquire,
+                      request_lock_managed_acquire,
+                      &request_lock_post_acquire, 0, 0, 0);
   ASSERT_EQ(0, when_request_lock(mock_image_ctx, exclusive_lock));
   ASSERT_TRUE(is_lock_owner(mock_image_ctx, exclusive_lock));
 
-  MockReleaseRequest shutdown_release;
-  expect_release_lock(mock_image_ctx, shutdown_release, 0, true);
+  MockPreReleaseRequest shutdown_pre_release;
+  MockManagedReleaseRequest shutdown_managed_release;
+  expect_release_lock(mock_image_ctx, shutdown_pre_release,
+                      shutdown_managed_release, 0, 0, true);
   ASSERT_EQ(0, when_shut_down(mock_image_ctx, exclusive_lock));
   ASSERT_FALSE(is_lock_owner(mock_image_ctx, exclusive_lock));
 }
@@ -700,22 +897,29 @@ TEST_F(TestMockExclusiveLock, ReacquireLock) {
   expect_block_writes(mock_image_ctx);
   ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
 
-  MockAcquireRequest request_lock_acquire;
-  expect_acquire_lock(mock_image_ctx, request_lock_acquire, 0);
+  MockPreAcquireRequest request_lock_pre_acquire;
+  MockManagedAcquireRequest request_lock_managed_acquire;
+  MockPostAcquireRequest request_lock_post_acquire;
+  expect_acquire_lock(mock_image_ctx, request_lock_pre_acquire,
+                      request_lock_managed_acquire,
+                      &request_lock_post_acquire, 0, 0, 0);
   ASSERT_EQ(0, when_request_lock(mock_image_ctx, exclusive_lock));
   ASSERT_TRUE(is_lock_owner(mock_image_ctx, exclusive_lock));
 
-  MockReacquireRequest mock_reacquire_request;
+  EXPECT_CALL(*mock_image_ctx.image_watcher, get_watch_handle())
+                 .WillOnce(Return(1234567890));
+
   C_SaferCond reacquire_ctx;
-  expect_reacquire_lock(mock_image_ctx, mock_reacquire_request, 0);
   {
     RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
     exclusive_lock.reacquire_lock(&reacquire_ctx);
   }
   ASSERT_EQ(0, reacquire_ctx.wait());
 
-  MockReleaseRequest shutdown_release;
-  expect_release_lock(mock_image_ctx, shutdown_release, 0, true);
+  MockPreReleaseRequest shutdown_pre_release;
+  MockManagedReleaseRequest shutdown_managed_release;
+  expect_release_lock(mock_image_ctx, shutdown_pre_release,
+                      shutdown_managed_release, 0, 0, true);
   ASSERT_EQ(0, when_shut_down(mock_image_ctx, exclusive_lock));
   ASSERT_FALSE(is_lock_owner(mock_image_ctx, exclusive_lock));
 }
@@ -734,20 +938,30 @@ TEST_F(TestMockExclusiveLock, ReacquireLockError) {
   expect_block_writes(mock_image_ctx);
   ASSERT_EQ(0, when_init(mock_image_ctx, exclusive_lock));
 
-  MockAcquireRequest request_lock_acquire;
-  expect_acquire_lock(mock_image_ctx, request_lock_acquire, 0);
+  MockPreAcquireRequest request_lock_pre_acquire;
+  MockManagedAcquireRequest request_lock_managed_acquire;
+  MockPostAcquireRequest request_lock_post_acquire;
+  expect_acquire_lock(mock_image_ctx, request_lock_pre_acquire,
+                      request_lock_managed_acquire,
+                      &request_lock_post_acquire, 0, 0, 0);
   ASSERT_EQ(0, when_request_lock(mock_image_ctx, exclusive_lock));
   ASSERT_TRUE(is_lock_owner(mock_image_ctx, exclusive_lock));
 
-  MockReacquireRequest mock_reacquire_request;
+  MockManagedReacquireRequest mock_reacquire_request;
   C_SaferCond reacquire_ctx;
   expect_reacquire_lock(mock_image_ctx, mock_reacquire_request, -EOPNOTSUPP);
 
-  MockReleaseRequest reacquire_lock_release;
-  expect_release_lock(mock_image_ctx, reacquire_lock_release, 0, false);
+  MockPreReleaseRequest reacquire_lock_pre_release;
+  MockManagedReleaseRequest reacquire_lock_managed_release;
+  expect_release_lock(mock_image_ctx, reacquire_lock_pre_release,
+                      reacquire_lock_managed_release, 0, 0, false);
 
-  MockAcquireRequest reacquire_lock_acquire;
-  expect_acquire_lock(mock_image_ctx, reacquire_lock_acquire, 0);
+  MockPreAcquireRequest reacquire_lock_pre_acquire;
+  MockManagedAcquireRequest reacquire_lock_managed_acquire;
+  MockPostAcquireRequest reacquire_lock_post_acquire;
+  expect_acquire_lock(mock_image_ctx, reacquire_lock_pre_acquire,
+                      reacquire_lock_managed_acquire,
+                      &reacquire_lock_post_acquire, 0, 0, 0);
 
   {
     RWLock::RLocker owner_locker(mock_image_ctx.owner_lock);
@@ -755,8 +969,10 @@ TEST_F(TestMockExclusiveLock, ReacquireLockError) {
   }
   ASSERT_EQ(-EOPNOTSUPP, reacquire_ctx.wait());
 
-  MockReleaseRequest shutdown_release;
-  expect_release_lock(mock_image_ctx, shutdown_release, 0, true);
+  MockPreReleaseRequest shutdown_pre_release;
+  MockManagedReleaseRequest shutdown_managed_release;
+  expect_release_lock(mock_image_ctx, shutdown_pre_release,
+                      shutdown_managed_release, 0, 0, true);
   ASSERT_EQ(0, when_shut_down(mock_image_ctx, exclusive_lock));
   ASSERT_FALSE(is_lock_owner(mock_image_ctx, exclusive_lock));
 }
index 58f8deefe0dff212d102d996cb06a08cdce97211..ac97ea2e9bf9460c7baf69c0b6cb09b760d77b2f 100644 (file)
@@ -753,7 +753,7 @@ TEST_F(TestImageReplayer, MultipleReplayFailures_SingleEpoch) {
   for (uint64_t i = 0; i < 10; ++i) {
     RWLock::RLocker owner_locker(ictx->owner_lock);
     C_SaferCond request_lock;
-    ictx->exclusive_lock->request_lock(&request_lock);
+    ictx->exclusive_lock->acquire_lock(&request_lock);
     ASSERT_EQ(0, request_lock.wait());
 
     C_SaferCond append_ctx;
@@ -801,7 +801,7 @@ TEST_F(TestImageReplayer, MultipleReplayFailures_MultiEpoch) {
   {
     RWLock::RLocker owner_locker(ictx->owner_lock);
     C_SaferCond request_lock;
-    ictx->exclusive_lock->request_lock(&request_lock);
+    ictx->exclusive_lock->acquire_lock(&request_lock);
     ASSERT_EQ(0, request_lock.wait());
 
     C_SaferCond append_ctx;
index 51305755b80c53a22bf26533e3f20a0dcf5f1e78..e5de1065270f002ad1effd562d217d2072660a74 100644 (file)
@@ -79,7 +79,7 @@ public:
     C_SaferCond ctx;
     {
       RWLock::RLocker owner_locker((*image_ctx)->owner_lock);
-      (*image_ctx)->exclusive_lock->try_lock(&ctx);
+      (*image_ctx)->exclusive_lock->try_acquire_lock(&ctx);
     }
     ASSERT_EQ(0, ctx.wait());
     ASSERT_TRUE((*image_ctx)->exclusive_lock->is_lock_owner());
index ff1493ddfd42d02f489db000eff571a84d7b7048..fbfdbd951b5eeaf04d4ad9855405b436052304df 100644 (file)
@@ -158,7 +158,7 @@ void OpenLocalImageRequest<I>::send_lock_image() {
     OpenLocalImageRequest<I>, &OpenLocalImageRequest<I>::handle_lock_image>(
       this);
 
-  (*m_local_image_ctx)->exclusive_lock->request_lock(ctx);
+  (*m_local_image_ctx)->exclusive_lock->acquire_lock(ctx);
 }
 
 template <typename I>