]> git.proxmox.com Git - ceph.git/blame - ceph/src/librbd/journal/PromoteRequest.cc
import 14.2.4 nautilus point release
[ceph.git] / ceph / src / librbd / journal / PromoteRequest.cc
CommitLineData
7c673cae
FG
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
20namespace librbd {
21namespace journal {
22
23using librbd::util::create_async_context_callback;
24using librbd::util::create_context_callback;
25
26template <typename I>
27PromoteRequest<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
32template <typename I>
33void PromoteRequest<I>::send() {
34 send_open();
35}
36
37template <typename I>
38void 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
53template <typename I>
54void 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
68template <typename I>
69void 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;
11fdf7f2 90 encode(tag_data, tag_bl);
7c673cae
FG
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
97template <typename I>
98void 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
113template <typename I>
114void 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;
11fdf7f2 120 encode(event_entry, event_entry_bl);
7c673cae 121
494da23a 122 m_journaler->start_append(0);
7c673cae
FG
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
130template <typename I>
131void 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
146template <typename I>
147void 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
158template <typename I>
159void 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
172template <typename I>
173void 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
182template <typename I>
183void 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
197template <typename I>
198void 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
208template <typename I>
209void 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
221template <typename I>
222void 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
237template class librbd::journal::PromoteRequest<librbd::ImageCtx>;