Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / librbd / journal / PromoteRequest.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/PromoteRequest.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::PromoteRequest: " << 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 PromoteRequest<I>::PromoteRequest(I *image_ctx, bool force, Context *on_finish)
28   : m_image_ctx(image_ctx), m_force(force), m_on_finish(on_finish),
29     m_lock("PromoteRequest::m_lock") {
30 }
31
32 template <typename I>
33 void PromoteRequest<I>::send() {
34   send_open();
35 }
36
37 template <typename I>
38 void PromoteRequest<I>::send_open() {
39   CephContext *cct = m_image_ctx->cct;
40   ldout(cct, 20) << dendl;
41
42   m_journaler = new Journaler(m_image_ctx->md_ctx, m_image_ctx->id,
43                               Journal<>::IMAGE_CLIENT_ID, {});
44   Context *ctx = create_async_context_callback(
45     *m_image_ctx, create_context_callback<
46       PromoteRequest<I>, &PromoteRequest<I>::handle_open>(this));
47   auto open_req = OpenRequest<I>::create(m_image_ctx, m_journaler,
48                                          &m_lock, &m_client_meta,
49                                          &m_tag_tid, &m_tag_data, ctx);
50   open_req->send();
51 }
52
53 template <typename I>
54 void PromoteRequest<I>::handle_open(int r) {
55   CephContext *cct = m_image_ctx->cct;
56   ldout(cct, 20) << "r=" << r << dendl;
57
58   if (r < 0) {
59     m_ret_val = r;
60     lderr(cct) << "failed to open journal: " << cpp_strerror(r) << dendl;
61     shut_down();
62     return;
63   }
64
65   allocate_tag();
66 }
67
68 template <typename I>
69 void PromoteRequest<I>::allocate_tag() {
70   CephContext *cct = m_image_ctx->cct;
71   ldout(cct, 20) << dendl;
72
73   journal::TagPredecessor predecessor;
74   if (!m_force && m_tag_data.mirror_uuid == Journal<>::ORPHAN_MIRROR_UUID) {
75     // orderly promotion -- demotion epoch will have a single entry
76     // so link to our predecessor (demotion) epoch
77     predecessor = TagPredecessor{Journal<>::ORPHAN_MIRROR_UUID, true, m_tag_tid,
78                                  1};
79   } else {
80     // forced promotion -- create an epoch no peers can link against
81     predecessor = TagPredecessor{Journal<>::LOCAL_MIRROR_UUID, true, m_tag_tid,
82                                  0};
83   }
84
85   TagData tag_data;
86   tag_data.mirror_uuid = Journal<>::LOCAL_MIRROR_UUID;
87   tag_data.predecessor = predecessor;
88
89   bufferlist tag_bl;
90   ::encode(tag_data, tag_bl);
91
92   Context *ctx = create_context_callback<
93     PromoteRequest<I>, &PromoteRequest<I>::handle_allocate_tag>(this);
94   m_journaler->allocate_tag(m_client_meta.tag_class, tag_bl, &m_tag, ctx);
95 }
96
97 template <typename I>
98 void PromoteRequest<I>::handle_allocate_tag(int r) {
99   CephContext *cct = m_image_ctx->cct;
100   ldout(cct, 20) << "r=" << r << dendl;
101
102   if (r < 0) {
103     m_ret_val = r;
104     lderr(cct) << "failed to allocate tag: " << cpp_strerror(r) << dendl;
105     shut_down();
106     return;
107   }
108
109   m_tag_tid = m_tag.tid;
110   append_event();
111 }
112
113 template <typename I>
114 void PromoteRequest<I>::append_event() {
115   CephContext *cct = m_image_ctx->cct;
116   ldout(cct, 20) << dendl;
117
118   EventEntry event_entry{DemotePromoteEvent{}, {}};
119   bufferlist event_entry_bl;
120   ::encode(event_entry, event_entry_bl);
121
122   m_journaler->start_append(0, 0, 0);
123   m_future = m_journaler->append(m_tag_tid, event_entry_bl);
124
125   auto ctx = create_context_callback<
126     PromoteRequest<I>, &PromoteRequest<I>::handle_append_event>(this);
127   m_future.flush(ctx);
128 }
129
130 template <typename I>
131 void PromoteRequest<I>::handle_append_event(int r) {
132   CephContext *cct = m_image_ctx->cct;
133   ldout(cct, 20) << "r=" << r << dendl;
134
135   if (r < 0) {
136     m_ret_val = r;
137     lderr(cct) << "failed to append promotion journal event: "
138                << cpp_strerror(r) << dendl;
139     stop_append();
140     return;
141   }
142
143   commit_event();
144 }
145
146 template <typename I>
147 void PromoteRequest<I>::commit_event() {
148   CephContext *cct = m_image_ctx->cct;
149   ldout(cct, 20) << dendl;
150
151   m_journaler->committed(m_future);
152
153   auto ctx = create_context_callback<
154     PromoteRequest<I>, &PromoteRequest<I>::handle_commit_event>(this);
155   m_journaler->flush_commit_position(ctx);
156 }
157
158 template <typename I>
159 void PromoteRequest<I>::handle_commit_event(int r) {
160   CephContext *cct = m_image_ctx->cct;
161   ldout(cct, 20) << "r=" << r << dendl;
162
163   if (r < 0) {
164     m_ret_val = r;
165     lderr(cct) << "failed to flush promote commit position: "
166                << cpp_strerror(r) << dendl;
167   }
168
169   stop_append();
170 }
171
172 template <typename I>
173 void PromoteRequest<I>::stop_append() {
174   CephContext *cct = m_image_ctx->cct;
175   ldout(cct, 20) << dendl;
176
177   auto ctx = create_context_callback<
178     PromoteRequest<I>, &PromoteRequest<I>::handle_stop_append>(this);
179   m_journaler->stop_append(ctx);
180 }
181
182 template <typename I>
183 void PromoteRequest<I>::handle_stop_append(int r) {
184   CephContext *cct = m_image_ctx->cct;
185   ldout(cct, 20) << "r=" << r << dendl;
186
187   if (r < 0) {
188     if (m_ret_val == 0) {
189       m_ret_val = r;
190     }
191     lderr(cct) << "failed to stop journal append: " << cpp_strerror(r) << dendl;
192   }
193
194   shut_down();
195 }
196
197 template <typename I>
198 void PromoteRequest<I>::shut_down() {
199   CephContext *cct = m_image_ctx->cct;
200   ldout(cct, 20) << dendl;
201
202   Context *ctx = create_async_context_callback(
203     *m_image_ctx, create_context_callback<
204       PromoteRequest<I>, &PromoteRequest<I>::handle_shut_down>(this));
205   m_journaler->shut_down(ctx);
206 }
207
208 template <typename I>
209 void PromoteRequest<I>::handle_shut_down(int r) {
210   CephContext *cct = m_image_ctx->cct;
211   ldout(cct, 20) << "r=" << r << dendl;
212
213   if (r < 0) {
214     lderr(cct) << "failed to shut down journal: " << cpp_strerror(r) << dendl;
215   }
216
217   delete m_journaler;
218   finish(r);
219 }
220
221 template <typename I>
222 void PromoteRequest<I>::finish(int r) {
223   if (m_ret_val < 0) {
224     r = m_ret_val;
225   }
226
227   CephContext *cct = m_image_ctx->cct;
228   ldout(cct, 20) << "r=" << r << dendl;
229
230   m_on_finish->complete(r);
231   delete this;
232 }
233
234 } // namespace journal
235 } // namespace librbd
236
237 template class librbd::journal::PromoteRequest<librbd::ImageCtx>;