]> git.proxmox.com Git - ceph.git/blame - ceph/src/tools/rbd_mirror/image_replayer/journal/EventPreprocessor.cc
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / tools / rbd_mirror / image_replayer / journal / EventPreprocessor.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 "EventPreprocessor.h"
5#include "common/debug.h"
6#include "common/dout.h"
7#include "common/errno.h"
7c673cae
FG
8#include "journal/Journaler.h"
9#include "librbd/ImageCtx.h"
10#include "librbd/ImageState.h"
11#include "librbd/Utils.h"
f67539c2 12#include "librbd/asio/ContextWQ.h"
7c673cae
FG
13#include "librbd/journal/Types.h"
14#include <boost/variant.hpp>
15
16#define dout_context g_ceph_context
17#define dout_subsys ceph_subsys_rbd_mirror
18
19#undef dout_prefix
9f95a23c
TL
20#define dout_prefix *_dout << "rbd::mirror::image_replayer::journal::" \
21 << "EventPreprocessor: " << this << " " << __func__ \
22 << ": "
7c673cae
FG
23
24namespace rbd {
25namespace mirror {
26namespace image_replayer {
9f95a23c 27namespace journal {
7c673cae
FG
28
29using librbd::util::create_context_callback;
30
31template <typename I>
32EventPreprocessor<I>::EventPreprocessor(I &local_image_ctx,
33 Journaler &remote_journaler,
34 const std::string &local_mirror_uuid,
35 MirrorPeerClientMeta *client_meta,
f67539c2 36 librbd::asio::ContextWQ *work_queue)
7c673cae
FG
37 : m_local_image_ctx(local_image_ctx), m_remote_journaler(remote_journaler),
38 m_local_mirror_uuid(local_mirror_uuid), m_client_meta(client_meta),
39 m_work_queue(work_queue) {
40}
41
42template <typename I>
43EventPreprocessor<I>::~EventPreprocessor() {
11fdf7f2 44 ceph_assert(!m_in_progress);
7c673cae
FG
45}
46
47template <typename I>
48bool EventPreprocessor<I>::is_required(const EventEntry &event_entry) {
49 SnapSeqs snap_seqs(m_client_meta->snap_seqs);
50 return (prune_snap_map(&snap_seqs) ||
51 event_entry.get_event_type() ==
52 librbd::journal::EVENT_TYPE_SNAP_RENAME);
53}
54
55template <typename I>
56void EventPreprocessor<I>::preprocess(EventEntry *event_entry,
57 Context *on_finish) {
11fdf7f2 58 ceph_assert(!m_in_progress);
7c673cae
FG
59 m_in_progress = true;
60 m_event_entry = event_entry;
61 m_on_finish = on_finish;
62
63 refresh_image();
64}
65
66template <typename I>
67void EventPreprocessor<I>::refresh_image() {
68 dout(20) << dendl;
69
70 Context *ctx = create_context_callback<
71 EventPreprocessor<I>, &EventPreprocessor<I>::handle_refresh_image>(this);
72 m_local_image_ctx.state->refresh(ctx);
73}
74
75template <typename I>
76void EventPreprocessor<I>::handle_refresh_image(int r) {
9f95a23c 77 dout(20) << "r=" << r << dendl;
7c673cae
FG
78
79 if (r < 0) {
80 derr << "error encountered during image refresh: " << cpp_strerror(r)
81 << dendl;
82 finish(r);
83 return;
84 }
85
86 preprocess_event();
87}
88
89template <typename I>
90void EventPreprocessor<I>::preprocess_event() {
91 dout(20) << dendl;
92
93 m_snap_seqs = m_client_meta->snap_seqs;
94 m_snap_seqs_updated = prune_snap_map(&m_snap_seqs);
95
96 int r = boost::apply_visitor(PreprocessEventVisitor(this),
97 m_event_entry->event);
98 if (r < 0) {
99 finish(r);
100 return;
101 }
102
103 update_client();
104}
105
106template <typename I>
107int EventPreprocessor<I>::preprocess_snap_rename(
108 librbd::journal::SnapRenameEvent &event) {
9f95a23c 109 dout(20) << "remote_snap_id=" << event.snap_id << ", "
7c673cae
FG
110 << "src_snap_name=" << event.src_snap_name << ", "
111 << "dest_snap_name=" << event.dst_snap_name << dendl;
112
113 auto snap_seq_it = m_snap_seqs.find(event.snap_id);
114 if (snap_seq_it != m_snap_seqs.end()) {
9f95a23c 115 dout(20) << "remapping remote snap id " << snap_seq_it->first << " "
7c673cae
FG
116 << "to local snap id " << snap_seq_it->second << dendl;
117 event.snap_id = snap_seq_it->second;
118 return 0;
119 }
120
121 auto snap_id_it = m_local_image_ctx.snap_ids.find({cls::rbd::UserSnapshotNamespace(),
122 event.src_snap_name});
123 if (snap_id_it == m_local_image_ctx.snap_ids.end()) {
9f95a23c 124 dout(20) << "cannot map remote snapshot '" << event.src_snap_name << "' "
7c673cae
FG
125 << "to local snapshot" << dendl;
126 event.snap_id = CEPH_NOSNAP;
127 return -ENOENT;
128 }
129
9f95a23c 130 dout(20) << "mapping remote snap id " << event.snap_id << " "
7c673cae
FG
131 << "to local snap id " << snap_id_it->second << dendl;
132 m_snap_seqs_updated = true;
133 m_snap_seqs[event.snap_id] = snap_id_it->second;
134 event.snap_id = snap_id_it->second;
135 return 0;
136}
137
138template <typename I>
139void EventPreprocessor<I>::update_client() {
140 if (!m_snap_seqs_updated) {
141 finish(0);
142 return;
143 }
144
145 dout(20) << dendl;
146 librbd::journal::MirrorPeerClientMeta client_meta(*m_client_meta);
147 client_meta.snap_seqs = m_snap_seqs;
148
149 librbd::journal::ClientData client_data(client_meta);
150 bufferlist data_bl;
11fdf7f2 151 encode(client_data, data_bl);
7c673cae
FG
152
153 Context *ctx = create_context_callback<
154 EventPreprocessor<I>, &EventPreprocessor<I>::handle_update_client>(
155 this);
156 m_remote_journaler.update_client(data_bl, ctx);
157}
158
159template <typename I>
160void EventPreprocessor<I>::handle_update_client(int r) {
9f95a23c 161 dout(20) << "r=" << r << dendl;
7c673cae
FG
162
163 if (r < 0) {
164 derr << "failed to update mirror peer journal client: "
165 << cpp_strerror(r) << dendl;
166 finish(r);
167 return;
168 }
169
170 m_client_meta->snap_seqs = m_snap_seqs;
171 finish(0);
172}
173
174template <typename I>
175bool EventPreprocessor<I>::prune_snap_map(SnapSeqs *snap_seqs) {
176 bool pruned = false;
177
9f95a23c 178 std::shared_lock image_locker{m_local_image_ctx.image_lock};
7c673cae
FG
179 for (auto it = snap_seqs->begin(); it != snap_seqs->end(); ) {
180 auto current_it(it++);
181 if (m_local_image_ctx.snap_info.count(current_it->second) == 0) {
182 snap_seqs->erase(current_it);
183 pruned = true;
184 }
185 }
186 return pruned;
187}
188
189template <typename I>
190void EventPreprocessor<I>::finish(int r) {
9f95a23c 191 dout(20) << "r=" << r << dendl;
7c673cae
FG
192
193 Context *on_finish = m_on_finish;
194 m_on_finish = nullptr;
195 m_event_entry = nullptr;
196 m_in_progress = false;
197 m_snap_seqs_updated = false;
198 m_work_queue->queue(on_finish, r);
199}
200
9f95a23c 201} // namespace journal
7c673cae
FG
202} // namespace image_replayer
203} // namespace mirror
204} // namespace rbd
205
9f95a23c 206template class rbd::mirror::image_replayer::journal::EventPreprocessor<librbd::ImageCtx>;