]>
Commit | Line | Data |
---|---|---|
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 | |
24 | namespace rbd { | |
25 | namespace mirror { | |
26 | namespace image_replayer { | |
9f95a23c | 27 | namespace journal { |
7c673cae FG |
28 | |
29 | using librbd::util::create_context_callback; | |
30 | ||
31 | template <typename I> | |
32 | EventPreprocessor<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 | ||
42 | template <typename I> | |
43 | EventPreprocessor<I>::~EventPreprocessor() { | |
11fdf7f2 | 44 | ceph_assert(!m_in_progress); |
7c673cae FG |
45 | } |
46 | ||
47 | template <typename I> | |
48 | bool 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 | ||
55 | template <typename I> | |
56 | void 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 | ||
66 | template <typename I> | |
67 | void 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 | ||
75 | template <typename I> | |
76 | void 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 | ||
89 | template <typename I> | |
90 | void 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 | ||
106 | template <typename I> | |
107 | int 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 | ||
138 | template <typename I> | |
139 | void 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 | ||
159 | template <typename I> | |
160 | void 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 | ||
174 | template <typename I> | |
175 | bool 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 | ||
189 | template <typename I> | |
190 | void 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 | 206 | template class rbd::mirror::image_replayer::journal::EventPreprocessor<librbd::ImageCtx>; |