1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #ifndef CEPH_LIBRBD_MANAGED_LOCK_H
5 #define CEPH_LIBRBD_MANAGED_LOCK_H
7 #include "include/int_types.h"
8 #include "include/Context.h"
9 #include "include/rados/librados.hpp"
10 #include "common/AsyncOpTracker.h"
11 #include "common/Mutex.h"
12 #include "cls/lock/cls_lock_types.h"
13 #include "librbd/watcher/Types.h"
14 #include "librbd/managed_lock/Types.h"
25 namespace managed_lock { struct Locker; }
27 template <typename ImageCtxT = librbd::ImageCtx>
30 typedef watcher::Traits<ImageCtxT> TypeTraits;
31 typedef typename TypeTraits::Watcher Watcher;
34 static ManagedLock *create(librados::IoCtx& ioctx, ContextWQ *work_queue,
35 const std::string& oid, Watcher *watcher,
36 managed_lock::Mode mode,
37 bool blacklist_on_break_lock,
38 uint32_t blacklist_expire_seconds) {
39 return new ManagedLock(ioctx, work_queue, oid, watcher, mode,
40 blacklist_on_break_lock, blacklist_expire_seconds);
46 ManagedLock(librados::IoCtx& ioctx, ContextWQ *work_queue,
47 const std::string& oid, Watcher *watcher,
48 managed_lock::Mode mode, bool blacklist_on_break_lock,
49 uint32_t blacklist_expire_seconds);
50 virtual ~ManagedLock();
52 bool is_lock_owner() const;
54 void shut_down(Context *on_shutdown);
55 void acquire_lock(Context *on_acquired);
56 void try_acquire_lock(Context *on_acquired);
57 void release_lock(Context *on_released);
58 void reacquire_lock(Context *on_reacquired = nullptr);
59 void get_locker(managed_lock::Locker *locker, Context *on_finish);
60 void break_lock(const managed_lock::Locker &locker, bool force_break_lock,
63 int assert_header_locked();
65 bool is_shutdown() const {
66 Mutex::Locker l(m_lock);
67 return is_state_shutdown();
73 inline void set_state_uninitialized() {
74 assert(m_lock.is_locked());
75 assert(m_state == STATE_UNLOCKED);
76 m_state = STATE_UNINITIALIZED;
78 inline void set_state_initializing() {
79 assert(m_lock.is_locked());
80 assert(m_state == STATE_UNINITIALIZED);
81 m_state = STATE_INITIALIZING;
83 inline void set_state_unlocked() {
84 assert(m_lock.is_locked());
85 assert(m_state == STATE_INITIALIZING || m_state == STATE_RELEASING);
86 m_state = STATE_UNLOCKED;
88 inline void set_state_waiting_for_lock() {
89 assert(m_lock.is_locked());
90 assert(m_state == STATE_ACQUIRING);
91 m_state = STATE_WAITING_FOR_LOCK;
93 inline void set_state_post_acquiring() {
94 assert(m_lock.is_locked());
95 assert(m_state == STATE_ACQUIRING);
96 m_state = STATE_POST_ACQUIRING;
99 bool is_state_shutdown() const;
100 inline bool is_state_acquiring() const {
101 assert(m_lock.is_locked());
102 return m_state == STATE_ACQUIRING;
104 inline bool is_state_post_acquiring() const {
105 assert(m_lock.is_locked());
106 return m_state == STATE_POST_ACQUIRING;
108 inline bool is_state_releasing() const {
109 assert(m_lock.is_locked());
110 return m_state == STATE_RELEASING;
112 inline bool is_state_pre_releasing() const {
113 assert(m_lock.is_locked());
114 return m_state == STATE_PRE_RELEASING;
116 inline bool is_state_locked() const {
117 assert(m_lock.is_locked());
118 return m_state == STATE_LOCKED;
120 inline bool is_state_waiting_for_lock() const {
121 assert(m_lock.is_locked());
122 return m_state == STATE_WAITING_FOR_LOCK;
125 inline bool is_action_acquire_lock() const {
126 assert(m_lock.is_locked());
127 return get_active_action() == ACTION_ACQUIRE_LOCK;
130 virtual void shutdown_handler(int r, Context *on_finish);
131 virtual void pre_acquire_lock_handler(Context *on_finish);
132 virtual void post_acquire_lock_handler(int r, Context *on_finish);
133 virtual void pre_release_lock_handler(bool shutting_down,
135 virtual void post_release_lock_handler(bool shutting_down, int r,
137 virtual void post_reacquire_lock_handler(int r, Context *on_finish);
139 void execute_next_action();
149 * UNLOCKED -----------------------------------------> ACQUIRING
156 * PRE_RELEASING <----------------------------------------- LOCKED
161 * REACQUIRING -------------------------------------> <finish>
164 * . . . > <RELEASE action> ---> <ACQUIRE action> ---/
166 * <UNLOCKED/LOCKED states>
170 * PRE_SHUTTING_DOWN ---> SHUTTING_DOWN ---> SHUTDOWN ---> <finish>
180 STATE_POST_ACQUIRING,
181 STATE_WAITING_FOR_REGISTER,
182 STATE_WAITING_FOR_LOCK,
186 STATE_PRE_SHUTTING_DOWN,
194 ACTION_REACQUIRE_LOCK,
199 typedef std::list<Context *> Contexts;
200 typedef std::pair<Action, Contexts> ActionContexts;
201 typedef std::list<ActionContexts> ActionsContexts;
203 struct C_ShutDownRelease : public Context {
205 C_ShutDownRelease(ManagedLock *lock)
208 void finish(int r) override {
209 lock->send_shutdown_release();
213 librados::IoCtx& m_ioctx;
215 ContextWQ *m_work_queue;
218 managed_lock::Mode m_mode;
219 bool m_blacklist_on_break_lock;
220 uint32_t m_blacklist_expire_seconds;
222 std::string m_cookie;
223 std::string m_new_cookie;
226 State m_post_next_state;
228 ActionsContexts m_actions_contexts;
229 AsyncOpTracker m_async_op_tracker;
231 bool is_lock_owner(Mutex &lock) const;
232 bool is_transition_state() const;
234 void append_context(Action action, Context *ctx);
235 void execute_action(Action action, Context *ctx);
237 Action get_active_action() const;
238 void complete_active_action(State next_state, int r);
240 void send_acquire_lock();
241 void handle_pre_acquire_lock(int r);
242 void handle_acquire_lock(int r);
243 void handle_post_acquire_lock(int r);
244 void revert_to_unlock_state(int r);
246 void send_reacquire_lock();
247 void handle_reacquire_lock(int r);
249 void send_release_lock();
250 void handle_pre_release_lock(int r);
251 void handle_release_lock(int r);
252 void handle_post_release_lock(int r);
254 void send_shutdown();
255 void handle_shutdown(int r);
256 void send_shutdown_release();
257 void handle_shutdown_pre_release(int r);
258 void handle_shutdown_post_release(int r);
259 void wait_for_tracked_ops(int r);
260 void complete_shutdown(int r);
263 } // namespace librbd
265 extern template class librbd::ManagedLock<librbd::ImageCtx>;
267 #endif // CEPH_LIBRBD_MANAGED_LOCK_H