1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
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"
15 #define dout_subsys ceph_subsys_rbd
17 #define dout_prefix *_dout << "librbd::journal::PromoteRequest: " << this \
18 << " " << __func__ << ": "
23 using librbd::util::create_async_context_callback;
24 using librbd::util::create_context_callback;
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") {
33 void PromoteRequest<I>::send() {
38 void PromoteRequest<I>::send_open() {
39 CephContext *cct = m_image_ctx->cct;
40 ldout(cct, 20) << dendl;
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);
54 void PromoteRequest<I>::handle_open(int r) {
55 CephContext *cct = m_image_ctx->cct;
56 ldout(cct, 20) << "r=" << r << dendl;
60 lderr(cct) << "failed to open journal: " << cpp_strerror(r) << dendl;
69 void PromoteRequest<I>::allocate_tag() {
70 CephContext *cct = m_image_ctx->cct;
71 ldout(cct, 20) << dendl;
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,
80 // forced promotion -- create an epoch no peers can link against
81 predecessor = TagPredecessor{Journal<>::LOCAL_MIRROR_UUID, true, m_tag_tid,
86 tag_data.mirror_uuid = Journal<>::LOCAL_MIRROR_UUID;
87 tag_data.predecessor = predecessor;
90 ::encode(tag_data, tag_bl);
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);
98 void PromoteRequest<I>::handle_allocate_tag(int r) {
99 CephContext *cct = m_image_ctx->cct;
100 ldout(cct, 20) << "r=" << r << dendl;
104 lderr(cct) << "failed to allocate tag: " << cpp_strerror(r) << dendl;
109 m_tag_tid = m_tag.tid;
113 template <typename I>
114 void PromoteRequest<I>::append_event() {
115 CephContext *cct = m_image_ctx->cct;
116 ldout(cct, 20) << dendl;
118 EventEntry event_entry{DemotePromoteEvent{}, {}};
119 bufferlist event_entry_bl;
120 ::encode(event_entry, event_entry_bl);
122 m_journaler->start_append(0, 0, 0);
123 m_future = m_journaler->append(m_tag_tid, event_entry_bl);
125 auto ctx = create_context_callback<
126 PromoteRequest<I>, &PromoteRequest<I>::handle_append_event>(this);
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;
137 lderr(cct) << "failed to append promotion journal event: "
138 << cpp_strerror(r) << dendl;
146 template <typename I>
147 void PromoteRequest<I>::commit_event() {
148 CephContext *cct = m_image_ctx->cct;
149 ldout(cct, 20) << dendl;
151 m_journaler->committed(m_future);
153 auto ctx = create_context_callback<
154 PromoteRequest<I>, &PromoteRequest<I>::handle_commit_event>(this);
155 m_journaler->flush_commit_position(ctx);
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;
165 lderr(cct) << "failed to flush promote commit position: "
166 << cpp_strerror(r) << dendl;
172 template <typename I>
173 void PromoteRequest<I>::stop_append() {
174 CephContext *cct = m_image_ctx->cct;
175 ldout(cct, 20) << dendl;
177 auto ctx = create_context_callback<
178 PromoteRequest<I>, &PromoteRequest<I>::handle_stop_append>(this);
179 m_journaler->stop_append(ctx);
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;
188 if (m_ret_val == 0) {
191 lderr(cct) << "failed to stop journal append: " << cpp_strerror(r) << dendl;
197 template <typename I>
198 void PromoteRequest<I>::shut_down() {
199 CephContext *cct = m_image_ctx->cct;
200 ldout(cct, 20) << dendl;
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);
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;
214 lderr(cct) << "failed to shut down journal: " << cpp_strerror(r) << dendl;
221 template <typename I>
222 void PromoteRequest<I>::finish(int r) {
227 CephContext *cct = m_image_ctx->cct;
228 ldout(cct, 20) << "r=" << r << dendl;
230 m_on_finish->complete(r);
234 } // namespace journal
235 } // namespace librbd
237 template class librbd::journal::PromoteRequest<librbd::ImageCtx>;