]> git.proxmox.com Git - ceph.git/blob - ceph/src/librbd/ManagedLock.h
update sources to v12.1.0
[ceph.git] / ceph / src / librbd / ManagedLock.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #ifndef CEPH_LIBRBD_MANAGED_LOCK_H
5 #define CEPH_LIBRBD_MANAGED_LOCK_H
6
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"
15 #include <list>
16 #include <string>
17 #include <utility>
18
19 class ContextWQ;
20
21 namespace librbd {
22
23 struct ImageCtx;
24
25 namespace managed_lock { struct Locker; }
26
27 template <typename ImageCtxT = librbd::ImageCtx>
28 class ManagedLock {
29 private:
30 typedef watcher::Traits<ImageCtxT> TypeTraits;
31 typedef typename TypeTraits::Watcher Watcher;
32
33 public:
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);
41 }
42 void destroy() {
43 delete this;
44 }
45
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();
51
52 bool is_lock_owner() const;
53
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,
61 Context *on_finish);
62
63 int assert_header_locked();
64
65 bool is_shutdown() const {
66 Mutex::Locker l(m_lock);
67 return is_state_shutdown();
68 }
69
70 protected:
71 mutable Mutex m_lock;
72
73 inline void set_state_uninitialized() {
74 assert(m_lock.is_locked());
75 assert(m_state == STATE_UNLOCKED);
76 m_state = STATE_UNINITIALIZED;
77 }
78 inline void set_state_initializing() {
79 assert(m_lock.is_locked());
80 assert(m_state == STATE_UNINITIALIZED);
81 m_state = STATE_INITIALIZING;
82 }
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;
87 }
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;
92 }
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;
97 }
98
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;
103 }
104 inline bool is_state_post_acquiring() const {
105 assert(m_lock.is_locked());
106 return m_state == STATE_POST_ACQUIRING;
107 }
108 inline bool is_state_releasing() const {
109 assert(m_lock.is_locked());
110 return m_state == STATE_RELEASING;
111 }
112 inline bool is_state_pre_releasing() const {
113 assert(m_lock.is_locked());
114 return m_state == STATE_PRE_RELEASING;
115 }
116 inline bool is_state_locked() const {
117 assert(m_lock.is_locked());
118 return m_state == STATE_LOCKED;
119 }
120 inline bool is_state_waiting_for_lock() const {
121 assert(m_lock.is_locked());
122 return m_state == STATE_WAITING_FOR_LOCK;
123 }
124
125 inline bool is_action_acquire_lock() const {
126 assert(m_lock.is_locked());
127 return get_active_action() == ACTION_ACQUIRE_LOCK;
128 }
129
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,
134 Context *on_finish);
135 virtual void post_release_lock_handler(bool shutting_down, int r,
136 Context *on_finish);
137 virtual void post_reacquire_lock_handler(int r, Context *on_finish);
138
139 void execute_next_action();
140
141 private:
142 /**
143 * @verbatim
144 *
145 * <start>
146 * |
147 * |
148 * v (acquire_lock)
149 * UNLOCKED -----------------------------------------> ACQUIRING
150 * ^ |
151 * | |
152 * RELEASING |
153 * | |
154 * | |
155 * | (release_lock) v
156 * PRE_RELEASING <----------------------------------------- LOCKED
157 *
158 * <LOCKED state>
159 * |
160 * v
161 * REACQUIRING -------------------------------------> <finish>
162 * . ^
163 * . |
164 * . . . > <RELEASE action> ---> <ACQUIRE action> ---/
165 *
166 * <UNLOCKED/LOCKED states>
167 * |
168 * |
169 * v
170 * PRE_SHUTTING_DOWN ---> SHUTTING_DOWN ---> SHUTDOWN ---> <finish>
171 *
172 * @endverbatim
173 */
174 enum State {
175 STATE_UNINITIALIZED,
176 STATE_INITIALIZING,
177 STATE_UNLOCKED,
178 STATE_LOCKED,
179 STATE_ACQUIRING,
180 STATE_POST_ACQUIRING,
181 STATE_WAITING_FOR_REGISTER,
182 STATE_WAITING_FOR_LOCK,
183 STATE_REACQUIRING,
184 STATE_PRE_RELEASING,
185 STATE_RELEASING,
186 STATE_PRE_SHUTTING_DOWN,
187 STATE_SHUTTING_DOWN,
188 STATE_SHUTDOWN,
189 };
190
191 enum Action {
192 ACTION_TRY_LOCK,
193 ACTION_ACQUIRE_LOCK,
194 ACTION_REACQUIRE_LOCK,
195 ACTION_RELEASE_LOCK,
196 ACTION_SHUT_DOWN
197 };
198
199 typedef std::list<Context *> Contexts;
200 typedef std::pair<Action, Contexts> ActionContexts;
201 typedef std::list<ActionContexts> ActionsContexts;
202
203 struct C_ShutDownRelease : public Context {
204 ManagedLock *lock;
205 C_ShutDownRelease(ManagedLock *lock)
206 : lock(lock) {
207 }
208 void finish(int r) override {
209 lock->send_shutdown_release();
210 }
211 };
212
213 librados::IoCtx& m_ioctx;
214 CephContext *m_cct;
215 ContextWQ *m_work_queue;
216 std::string m_oid;
217 Watcher *m_watcher;
218 managed_lock::Mode m_mode;
219 bool m_blacklist_on_break_lock;
220 uint32_t m_blacklist_expire_seconds;
221
222 std::string m_cookie;
223 std::string m_new_cookie;
224
225 State m_state;
226 State m_post_next_state;
227
228 ActionsContexts m_actions_contexts;
229 AsyncOpTracker m_async_op_tracker;
230
231 bool is_lock_owner(Mutex &lock) const;
232 bool is_transition_state() const;
233
234 void append_context(Action action, Context *ctx);
235 void execute_action(Action action, Context *ctx);
236
237 Action get_active_action() const;
238 void complete_active_action(State next_state, int r);
239
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);
245
246 void send_reacquire_lock();
247 void handle_reacquire_lock(int r);
248
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);
253
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);
261 };
262
263 } // namespace librbd
264
265 extern template class librbd::ManagedLock<librbd::ImageCtx>;
266
267 #endif // CEPH_LIBRBD_MANAGED_LOCK_H