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