]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: image state machine now has hooks for lock requests
authorJason Dillaman <dillaman@redhat.com>
Wed, 17 Aug 2016 18:02:32 +0000 (14:02 -0400)
committerJason Dillaman <dillaman@redhat.com>
Mon, 30 Jan 2017 14:20:36 +0000 (09:20 -0500)
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
(cherry picked from commit a5b8c9c1d81ed609e71a5a8abe4d0e90194408cc)

src/librbd/ImageState.cc
src/librbd/ImageState.h
src/test/librbd/mock/MockImageState.h

index 5b450b0671e570030f170480431837f2d5e53ad0..3e0a3853f066d6e79728bde656b4a26c27cbcdcd 100644 (file)
@@ -377,6 +377,37 @@ void ImageState<I>::snap_set(const std::string &snap_name, Context *on_finish) {
   execute_action_unlock(action, on_finish);
 }
 
+template <typename I>
+void ImageState<I>::prepare_lock(Context *on_ready) {
+  CephContext *cct = m_image_ctx->cct;
+  ldout(cct, 10) << __func__ << dendl;
+
+  m_lock.Lock();
+  if (is_closed()) {
+    m_lock.Unlock();
+    on_ready->complete(-ESHUTDOWN);
+    return;
+  }
+
+  Action action(ACTION_TYPE_LOCK);
+  action.on_ready = on_ready;
+  execute_action_unlock(action, nullptr);
+}
+
+template <typename I>
+void ImageState<I>::handle_prepare_lock_complete() {
+  CephContext *cct = m_image_ctx->cct;
+  ldout(cct, 10) << __func__ << dendl;
+
+  m_lock.Lock();
+  if (m_state != STATE_PREPARING_LOCK) {
+    m_lock.Unlock();
+    return;
+  }
+
+  complete_action_unlock(STATE_OPEN, 0);
+}
+
 template <typename I>
 int ImageState<I>::register_update_watcher(UpdateWatchCtx *watcher,
                                         uint64_t *handle) {
@@ -426,6 +457,7 @@ bool ImageState<I>::is_transition_state() const {
   case STATE_CLOSING:
   case STATE_REFRESHING:
   case STATE_SETTING_SNAP:
+  case STATE_PREPARING_LOCK:
     break;
   }
   return true;
@@ -479,6 +511,9 @@ void ImageState<I>::execute_next_action_unlock() {
   case ACTION_TYPE_SET_SNAP:
     send_set_snap_unlock();
     return;
+  case ACTION_TYPE_LOCK:
+    send_prepare_lock_unlock();
+    return;
   }
   assert(false);
 }
@@ -663,6 +698,30 @@ void ImageState<I>::handle_set_snap(int r) {
   complete_action_unlock(STATE_OPEN, r);
 }
 
+template <typename I>
+void ImageState<I>::send_prepare_lock_unlock() {
+  CephContext *cct = m_image_ctx->cct;
+  ldout(cct, 10) << this << " " << __func__ << dendl;
+
+  assert(m_lock.is_locked());
+  m_state = STATE_PREPARING_LOCK;
+
+  assert(!m_actions_contexts.empty());
+  ActionContexts &action_contexts(m_actions_contexts.front());
+  assert(action_contexts.first.action_type == ACTION_TYPE_LOCK);
+
+  Context *on_ready = action_contexts.first.on_ready;
+  m_lock.Unlock();
+
+  if (on_ready == nullptr) {
+    complete_action_unlock(STATE_OPEN, 0);
+    return;
+  }
+
+  // wake up the lock handler now that its safe to proceed
+  on_ready->complete(0);
+}
+
 } // namespace librbd
 
 template class librbd::ImageState<librbd::ImageCtx>;
index bad42775d393f85cb4e4dc1bb52f0c8fd0b6638c..2e0fb63fbde48534757c907202c1178cb4a7be70 100644 (file)
@@ -42,6 +42,9 @@ public:
 
   void snap_set(const std::string &snap_name, Context *on_finish);
 
+  void prepare_lock(Context *on_ready);
+  void handle_prepare_lock_complete();
+
   int register_update_watcher(UpdateWatchCtx *watcher, uint64_t *handle);
   int unregister_update_watcher(uint64_t handle);
   void flush_update_watchers(Context *on_finish);
@@ -55,14 +58,16 @@ private:
     STATE_OPENING,
     STATE_CLOSING,
     STATE_REFRESHING,
-    STATE_SETTING_SNAP
+    STATE_SETTING_SNAP,
+    STATE_PREPARING_LOCK
   };
 
   enum ActionType {
     ACTION_TYPE_OPEN,
     ACTION_TYPE_CLOSE,
     ACTION_TYPE_REFRESH,
-    ACTION_TYPE_SET_SNAP
+    ACTION_TYPE_SET_SNAP,
+    ACTION_TYPE_LOCK
   };
 
   struct Action {
@@ -70,6 +75,7 @@ private:
     uint64_t refresh_seq = 0;
     bool refresh_acquiring_lock = false;
     std::string snap_name;
+    Context *on_ready = nullptr;
 
     Action(ActionType action_type) : action_type(action_type) {
     }
@@ -83,6 +89,8 @@ private:
                 refresh_acquiring_lock == action.refresh_acquiring_lock);
       case ACTION_TYPE_SET_SNAP:
         return snap_name == action.snap_name;
+      case ACTION_TYPE_LOCK:
+        return false;
       default:
         return true;
       }
@@ -126,6 +134,8 @@ private:
   void send_set_snap_unlock();
   void handle_set_snap(int r);
 
+  void send_prepare_lock_unlock();
+
 };
 
 } // namespace librbd
index 3ba1ee5d7dd0eb191b74845fbe9bbfc8c5a28b53..603871b5b46e0cf969792343a07a4bd7019bc04b 100644 (file)
@@ -21,6 +21,9 @@ struct MockImageState {
   MOCK_METHOD1(close, void(Context*));
 
   MOCK_METHOD2(snap_set, void(const std::string &, Context*));
+
+  MOCK_METHOD1(prepare_lock, void(Context*));
+  MOCK_METHOD0(handle_prepare_lock_complete, void());
 };
 
 } // namespace librbd