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) {
case STATE_CLOSING:
case STATE_REFRESHING:
case STATE_SETTING_SNAP:
+ case STATE_PREPARING_LOCK:
break;
}
return true;
case ACTION_TYPE_SET_SNAP:
send_set_snap_unlock();
return;
+ case ACTION_TYPE_LOCK:
+ send_prepare_lock_unlock();
+ return;
}
assert(false);
}
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>;
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);
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 {
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) {
}
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;
}
void send_set_snap_unlock();
void handle_set_snap(int r);
+ void send_prepare_lock_unlock();
+
};
} // namespace librbd