Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / librbd / journal / DemoteRequest.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/journal/DemoteRequest.h"
5 #include "common/dout.h"
6 #include "common/errno.h"
7 #include "common/WorkQueue.h"
8 #include "journal/Journaler.h"
9 #include "journal/Settings.h"
10 #include "librbd/ImageCtx.h"
11 #include "librbd/Journal.h"
12 #include "librbd/Utils.h"
13 #include "librbd/journal/OpenRequest.h"
14
15 #define dout_subsys ceph_subsys_rbd
16 #undef dout_prefix
17 #define dout_prefix *_dout << "librbd::journal::DemoteRequest: " << this \
18                            << " " << __func__ << ": "
19
20 namespace librbd {
21 namespace journal {
22
23 using librbd::util::create_async_context_callback;
24 using librbd::util::create_context_callback;
25
26 template <typename I>
27 DemoteRequest<I>::DemoteRequest(I &image_ctx, Context *on_finish)
28   : m_image_ctx(image_ctx), m_on_finish(on_finish),
29     m_lock("DemoteRequest::m_lock") {
30 }
31
32 template <typename I>
33 DemoteRequest<I>::~DemoteRequest() {
34   assert(m_journaler == nullptr);
35 }
36
37 template <typename I>
38 void DemoteRequest<I>::send() {
39   open_journaler();
40 }
41
42 template <typename I>
43 void DemoteRequest<I>::open_journaler() {
44   CephContext *cct = m_image_ctx.cct;
45   ldout(cct, 20) << dendl;
46
47   m_journaler = new Journaler(m_image_ctx.md_ctx, m_image_ctx.id,
48                               Journal<>::IMAGE_CLIENT_ID, {});
49   auto ctx = create_async_context_callback(
50     m_image_ctx, create_context_callback<
51       DemoteRequest<I>, &DemoteRequest<I>::handle_open_journaler>(this));
52   auto req = OpenRequest<I>::create(&m_image_ctx, m_journaler, &m_lock,
53                                     &m_client_meta, &m_tag_tid, &m_tag_data,
54                                     ctx);
55   req->send();
56 }
57
58 template <typename I>
59 void DemoteRequest<I>::handle_open_journaler(int r) {
60   CephContext *cct = m_image_ctx.cct;
61   ldout(cct, 20) << "r=" << r << dendl;
62
63   if (r < 0) {
64     m_ret_val = r;
65     lderr(cct) << "failed to open journal: " << cpp_strerror(r) << dendl;
66     shut_down_journaler();
67     return;
68   } else if (m_tag_data.mirror_uuid != Journal<>::LOCAL_MIRROR_UUID) {
69     m_ret_val = -EINVAL;
70     lderr(cct) << "image is not currently the primary" << dendl;
71     shut_down_journaler();
72     return;
73   }
74
75   allocate_tag();
76 }
77
78 template <typename I>
79 void DemoteRequest<I>::allocate_tag() {
80   CephContext *cct = m_image_ctx.cct;
81   ldout(cct, 20) << dendl;
82
83   cls::journal::Client client;
84   int r = m_journaler->get_cached_client(Journal<>::IMAGE_CLIENT_ID, &client);
85   if (r < 0) {
86     m_ret_val = r;
87     lderr(cct) << "failed to retrieve client: " << cpp_strerror(r) << dendl;
88     shut_down_journaler();
89     return;
90   }
91
92   TagPredecessor predecessor;
93   predecessor.mirror_uuid = Journal<>::LOCAL_MIRROR_UUID;
94   if (!client.commit_position.object_positions.empty()) {
95     auto position = client.commit_position.object_positions.front();
96     predecessor.commit_valid = true;
97     predecessor.tag_tid = position.tag_tid;
98     predecessor.entry_tid = position.entry_tid;
99   }
100
101   TagData tag_data;
102   tag_data.mirror_uuid = Journal<>::ORPHAN_MIRROR_UUID;
103   tag_data.predecessor = std::move(predecessor);
104
105   bufferlist tag_bl;
106   ::encode(tag_data, tag_bl);
107
108   auto ctx = create_context_callback<
109     DemoteRequest<I>, &DemoteRequest<I>::handle_allocate_tag>(this);
110   m_journaler->allocate_tag(m_client_meta.tag_class, tag_bl, &m_tag, ctx);
111 }
112
113 template <typename I>
114 void DemoteRequest<I>::handle_allocate_tag(int r) {
115   CephContext *cct = m_image_ctx.cct;
116   ldout(cct, 20) << "r=" << r << dendl;
117
118   if (r < 0) {
119     m_ret_val = r;
120     lderr(cct) << "failed to allocate tag: " << cpp_strerror(r) << dendl;
121     shut_down_journaler();
122     return;
123   }
124
125   m_tag_tid = m_tag.tid;
126   append_event();
127 }
128
129 template <typename I>
130 void DemoteRequest<I>::append_event() {
131   CephContext *cct = m_image_ctx.cct;
132   ldout(cct, 20) << dendl;
133
134   EventEntry event_entry{DemotePromoteEvent{}, {}};
135   bufferlist event_entry_bl;
136   ::encode(event_entry, event_entry_bl);
137
138   m_journaler->start_append(0, 0, 0);
139   m_future = m_journaler->append(m_tag_tid, event_entry_bl);
140
141   auto ctx = create_context_callback<
142     DemoteRequest<I>, &DemoteRequest<I>::handle_append_event>(this);
143   m_future.flush(ctx);
144
145 }
146
147 template <typename I>
148 void DemoteRequest<I>::handle_append_event(int r) {
149   CephContext *cct = m_image_ctx.cct;
150   ldout(cct, 20) << "r=" << r << dendl;
151
152   if (r < 0) {
153     m_ret_val = r;
154     lderr(cct) << "failed to append demotion journal event: " << cpp_strerror(r)
155                << dendl;
156     stop_append();
157     return;
158   }
159
160   commit_event();
161 }
162
163 template <typename I>
164 void DemoteRequest<I>::commit_event() {
165   CephContext *cct = m_image_ctx.cct;
166   ldout(cct, 20) << dendl;
167
168   m_journaler->committed(m_future);
169
170   auto ctx = create_context_callback<
171     DemoteRequest<I>, &DemoteRequest<I>::handle_commit_event>(this);
172   m_journaler->flush_commit_position(ctx);
173 }
174
175 template <typename I>
176 void DemoteRequest<I>::handle_commit_event(int r) {
177   CephContext *cct = m_image_ctx.cct;
178   ldout(cct, 20) << "r=" << r << dendl;
179
180   if (r < 0) {
181     m_ret_val = r;
182     lderr(cct) << "failed to flush demotion commit position: "
183                << cpp_strerror(r) << dendl;
184   }
185
186   stop_append();
187 }
188
189 template <typename I>
190 void DemoteRequest<I>::stop_append() {
191   CephContext *cct = m_image_ctx.cct;
192   ldout(cct, 20) << dendl;
193
194   auto ctx = create_context_callback<
195     DemoteRequest<I>, &DemoteRequest<I>::handle_stop_append>(this);
196   m_journaler->stop_append(ctx);
197 }
198
199 template <typename I>
200 void DemoteRequest<I>::handle_stop_append(int r) {
201   CephContext *cct = m_image_ctx.cct;
202   ldout(cct, 20) << "r=" << r << dendl;
203
204   if (r < 0) {
205     if (m_ret_val == 0) {
206       m_ret_val = r;
207     }
208     lderr(cct) << "failed to stop journal append: " << cpp_strerror(r) << dendl;
209   }
210
211   shut_down_journaler();
212 }
213
214 template <typename I>
215 void DemoteRequest<I>::shut_down_journaler() {
216   CephContext *cct = m_image_ctx.cct;
217   ldout(cct, 20) << dendl;
218
219   Context *ctx = create_async_context_callback(
220     m_image_ctx, create_context_callback<
221       DemoteRequest<I>, &DemoteRequest<I>::handle_shut_down_journaler>(this));
222   m_journaler->shut_down(ctx);
223 }
224
225 template <typename I>
226 void DemoteRequest<I>::handle_shut_down_journaler(int r) {
227   CephContext *cct = m_image_ctx.cct;
228   ldout(cct, 20) << "r=" << r << dendl;
229
230   if (r < 0) {
231     lderr(cct) << "failed to shut down journal: " << cpp_strerror(r) << dendl;
232   }
233
234   delete m_journaler;
235   m_journaler = nullptr;
236   finish(r);
237 }
238
239 template <typename I>
240 void DemoteRequest<I>::finish(int r) {
241   if (m_ret_val < 0) {
242     r = m_ret_val;
243   }
244
245   CephContext *cct = m_image_ctx.cct;
246   ldout(cct, 20) << "r=" << r << dendl;
247
248   m_on_finish->complete(r);
249   delete this;
250 }
251
252 } // namespace journal
253 } // namespace librbd
254
255 template class librbd::journal::DemoteRequest<librbd::ImageCtx>;