Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / librbd / exclusive_lock / PostAcquireRequest.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #include "librbd/exclusive_lock/PostAcquireRequest.h"
5 #include "cls/lock/cls_lock_client.h"
6 #include "cls/lock/cls_lock_types.h"
7 #include "common/dout.h"
8 #include "common/errno.h"
9 #include "common/WorkQueue.h"
10 #include "include/stringify.h"
11 #include "librbd/ExclusiveLock.h"
12 #include "librbd/ImageCtx.h"
13 #include "librbd/ImageState.h"
14 #include "librbd/ImageWatcher.h"
15 #include "librbd/Journal.h"
16 #include "librbd/ObjectMap.h"
17 #include "librbd/Utils.h"
18 #include "librbd/image/RefreshRequest.h"
19 #include "librbd/journal/Policy.h"
20
21 #define dout_subsys ceph_subsys_rbd
22 #undef dout_prefix
23 #define dout_prefix *_dout << "librbd::exclusive_lock::PostAcquireRequest: " \
24                            << this << " " << __func__ << ": "
25
26 namespace librbd {
27 namespace exclusive_lock {
28
29 using util::create_async_context_callback;
30 using util::create_context_callback;
31 using util::create_rados_callback;
32
33 template <typename I>
34 PostAcquireRequest<I>* PostAcquireRequest<I>::create(I &image_ctx,
35                                                      Context *on_acquire,
36                                                      Context *on_finish) {
37   return new PostAcquireRequest(image_ctx, on_acquire, on_finish);
38 }
39
40 template <typename I>
41 PostAcquireRequest<I>::PostAcquireRequest(I &image_ctx, Context *on_acquire,
42                                           Context *on_finish)
43   : m_image_ctx(image_ctx),
44     m_on_acquire(on_acquire),
45     m_on_finish(create_async_context_callback(image_ctx, on_finish)),
46     m_object_map(nullptr), m_journal(nullptr), m_error_result(0) {
47 }
48
49 template <typename I>
50 PostAcquireRequest<I>::~PostAcquireRequest() {
51   if (!m_prepare_lock_completed) {
52     m_image_ctx.state->handle_prepare_lock_complete();
53   }
54   delete m_on_acquire;
55 }
56
57 template <typename I>
58 void PostAcquireRequest<I>::send() {
59   send_refresh();
60 }
61
62 template <typename I>
63 void PostAcquireRequest<I>::send_refresh() {
64   if (!m_image_ctx.state->is_refresh_required()) {
65     send_open_object_map();
66     return;
67   }
68
69   CephContext *cct = m_image_ctx.cct;
70   ldout(cct, 10) << dendl;
71
72   using klass = PostAcquireRequest<I>;
73   Context *ctx = create_async_context_callback(
74     m_image_ctx, create_context_callback<klass, &klass::handle_refresh>(this));
75
76   // ImageState is blocked waiting for lock to complete -- safe to directly
77   // refresh
78   image::RefreshRequest<I> *req = image::RefreshRequest<I>::create(
79     m_image_ctx, true, false, ctx);
80   req->send();
81 }
82
83 template <typename I>
84 void PostAcquireRequest<I>::handle_refresh(int r) {
85   CephContext *cct = m_image_ctx.cct;
86   ldout(cct, 10) << "r=" << r << dendl;
87
88   if (r == -ERESTART) {
89     // next issued IO or op will (re)-refresh the image and shut down lock
90     ldout(cct, 5) << "exclusive lock dynamically disabled" << dendl;
91     r = 0;
92   } else if (r < 0) {
93     lderr(cct) << "failed to refresh image: " << cpp_strerror(r) << dendl;
94     save_result(r);
95     revert();
96     finish();
97     return;
98   }
99
100   send_open_object_map();
101 }
102
103 template <typename I>
104 void PostAcquireRequest<I>::send_open_journal() {
105   // alert caller that we now own the exclusive lock
106   m_on_acquire->complete(0);
107   m_on_acquire = nullptr;
108
109   bool journal_enabled;
110   {
111     RWLock::RLocker snap_locker(m_image_ctx.snap_lock);
112     journal_enabled = (m_image_ctx.test_features(RBD_FEATURE_JOURNALING,
113                                                  m_image_ctx.snap_lock) &&
114                        !m_image_ctx.get_journal_policy()->journal_disabled());
115   }
116   if (!journal_enabled) {
117     apply();
118     finish();
119     return;
120   }
121
122   CephContext *cct = m_image_ctx.cct;
123   ldout(cct, 10) << dendl;
124
125   using klass = PostAcquireRequest<I>;
126   Context *ctx = create_context_callback<klass, &klass::handle_open_journal>(
127     this);
128   m_journal = m_image_ctx.create_journal();
129
130   // journal playback requires object map (if enabled) and itself
131   apply();
132
133   m_journal->open(ctx);
134 }
135
136 template <typename I>
137 void PostAcquireRequest<I>::handle_open_journal(int r) {
138   CephContext *cct = m_image_ctx.cct;
139   ldout(cct, 10) << "r=" << r << dendl;
140
141   save_result(r);
142   if (r < 0) {
143     lderr(cct) << "failed to open journal: " << cpp_strerror(r) << dendl;
144     send_close_journal();
145     return;
146   }
147
148   send_allocate_journal_tag();
149 }
150
151 template <typename I>
152 void PostAcquireRequest<I>::send_allocate_journal_tag() {
153   CephContext *cct = m_image_ctx.cct;
154   ldout(cct, 10) << dendl;
155
156   RWLock::RLocker snap_locker(m_image_ctx.snap_lock);
157   using klass = PostAcquireRequest<I>;
158   Context *ctx = create_context_callback<
159     klass, &klass::handle_allocate_journal_tag>(this);
160   m_image_ctx.get_journal_policy()->allocate_tag_on_lock(ctx);
161 }
162
163 template <typename I>
164 void PostAcquireRequest<I>::handle_allocate_journal_tag(int r) {
165   CephContext *cct = m_image_ctx.cct;
166   ldout(cct, 10) << "r=" << r << dendl;
167
168   save_result(r);
169   if (r < 0) {
170     lderr(cct) << "failed to allocate journal tag: " << cpp_strerror(r)
171                << dendl;
172     send_close_journal();
173     return;
174   }
175
176   finish();
177 }
178
179 template <typename I>
180 void PostAcquireRequest<I>::send_close_journal() {
181   CephContext *cct = m_image_ctx.cct;
182   ldout(cct, 10) << dendl;
183
184   using klass = PostAcquireRequest<I>;
185   Context *ctx = create_context_callback<klass, &klass::handle_close_journal>(
186     this);
187   m_journal->close(ctx);
188 }
189
190 template <typename I>
191 void PostAcquireRequest<I>::handle_close_journal(int r) {
192   CephContext *cct = m_image_ctx.cct;
193   ldout(cct, 10) << "r=" << r << dendl;
194
195   save_result(r);
196   if (r < 0) {
197     lderr(cct) << "failed to close journal: " << cpp_strerror(r) << dendl;
198   }
199
200   send_close_object_map();
201 }
202
203 template <typename I>
204 void PostAcquireRequest<I>::send_open_object_map() {
205   if (!m_image_ctx.test_features(RBD_FEATURE_OBJECT_MAP)) {
206     send_open_journal();
207     return;
208   }
209
210   CephContext *cct = m_image_ctx.cct;
211   ldout(cct, 10) << dendl;
212
213   using klass = PostAcquireRequest<I>;
214   Context *ctx = create_context_callback<klass, &klass::handle_open_object_map>(
215     this);
216
217   m_object_map = m_image_ctx.create_object_map(CEPH_NOSNAP);
218   m_object_map->open(ctx);
219 }
220
221 template <typename I>
222 void PostAcquireRequest<I>::handle_open_object_map(int r) {
223   CephContext *cct = m_image_ctx.cct;
224   ldout(cct, 10) << "r=" << r << dendl;
225
226   if (r < 0) {
227     lderr(cct) << "failed to open object map: " << cpp_strerror(r) << dendl;
228
229     r = 0;
230     delete m_object_map;
231     m_object_map = nullptr;
232   }
233
234   send_open_journal();
235 }
236
237 template <typename I>
238 void PostAcquireRequest<I>::send_close_object_map() {
239   if (m_object_map == nullptr) {
240     revert();
241     finish();
242     return;
243   }
244
245   CephContext *cct = m_image_ctx.cct;
246   ldout(cct, 10) << dendl;
247
248   using klass = PostAcquireRequest<I>;
249   Context *ctx = create_context_callback<
250     klass, &klass::handle_close_object_map>(this);
251   m_object_map->close(ctx);
252 }
253
254 template <typename I>
255 void PostAcquireRequest<I>::handle_close_object_map(int r) {
256   CephContext *cct = m_image_ctx.cct;
257   ldout(cct, 10) << "r=" << r << dendl;
258
259   // object map should never result in an error
260   assert(r == 0);
261   revert();
262   finish();
263 }
264
265 template <typename I>
266 void PostAcquireRequest<I>::apply() {
267   {
268     RWLock::WLocker snap_locker(m_image_ctx.snap_lock);
269     assert(m_image_ctx.object_map == nullptr);
270     m_image_ctx.object_map = m_object_map;
271
272     assert(m_image_ctx.journal == nullptr);
273     m_image_ctx.journal = m_journal;
274   }
275
276   m_prepare_lock_completed = true;
277   m_image_ctx.state->handle_prepare_lock_complete();
278 }
279
280 template <typename I>
281 void PostAcquireRequest<I>::revert() {
282   RWLock::WLocker snap_locker(m_image_ctx.snap_lock);
283   m_image_ctx.object_map = nullptr;
284   m_image_ctx.journal = nullptr;
285
286   delete m_object_map;
287   delete m_journal;
288
289   assert(m_error_result < 0);
290 }
291
292 template <typename I>
293 void PostAcquireRequest<I>::finish() {
294   m_on_finish->complete(m_error_result);
295   delete this;
296 }
297
298 } // namespace exclusive_lock
299 } // namespace librbd
300
301 template class librbd::exclusive_lock::PostAcquireRequest<librbd::ImageCtx>;