]> git.proxmox.com Git - ceph.git/blob - ceph/src/tools/rbd_mirror/image_deleter/SnapshotPurgeRequest.cc
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / tools / rbd_mirror / image_deleter / SnapshotPurgeRequest.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 "tools/rbd_mirror/image_deleter/SnapshotPurgeRequest.h"
5 #include "common/debug.h"
6 #include "common/errno.h"
7 #include "librbd/ExclusiveLock.h"
8 #include "librbd/ImageCtx.h"
9 #include "librbd/ImageState.h"
10 #include "librbd/Operations.h"
11 #include "librbd/Utils.h"
12 #include "librbd/journal/Policy.h"
13 #include "tools/rbd_mirror/image_deleter/Types.h"
14
15 #define dout_context g_ceph_context
16 #define dout_subsys ceph_subsys_rbd_mirror
17 #undef dout_prefix
18 #define dout_prefix *_dout << "rbd::mirror::image_deleter::SnapshotPurgeRequest: " \
19 << this << " " << __func__ << ": "
20
21 namespace rbd {
22 namespace mirror {
23 namespace image_deleter {
24
25 using librbd::util::create_context_callback;
26
27 template <typename I>
28 void SnapshotPurgeRequest<I>::send() {
29 open_image();
30 }
31
32 template <typename I>
33 void SnapshotPurgeRequest<I>::open_image() {
34 dout(10) << dendl;
35 m_image_ctx = I::create("", m_image_id, nullptr, m_io_ctx, false);
36
37 {
38 RWLock::WLocker snap_locker(m_image_ctx->snap_lock);
39 m_image_ctx->set_journal_policy(new JournalPolicy());
40 }
41
42 Context *ctx = create_context_callback<
43 SnapshotPurgeRequest<I>, &SnapshotPurgeRequest<I>::handle_open_image>(
44 this);
45 m_image_ctx->state->open(librbd::OPEN_FLAG_SKIP_OPEN_PARENT, ctx);
46 }
47
48 template <typename I>
49 void SnapshotPurgeRequest<I>::handle_open_image(int r) {
50 dout(10) << "r=" << r << dendl;
51
52 if (r < 0) {
53 derr << "failed to open image '" << m_image_id << "': " << cpp_strerror(r)
54 << dendl;
55 m_image_ctx->destroy();
56 m_image_ctx = nullptr;
57
58 finish(r);
59 return;
60 }
61
62 acquire_lock();
63 }
64
65 template <typename I>
66 void SnapshotPurgeRequest<I>::acquire_lock() {
67 dout(10) << dendl;
68
69 m_image_ctx->owner_lock.get_read();
70 if (m_image_ctx->exclusive_lock == nullptr) {
71 m_image_ctx->owner_lock.put_read();
72
73 derr << "exclusive lock not enabled" << dendl;
74 m_ret_val = -EINVAL;
75 close_image();
76 return;
77 }
78
79 m_image_ctx->exclusive_lock->acquire_lock(create_context_callback<
80 SnapshotPurgeRequest<I>, &SnapshotPurgeRequest<I>::handle_acquire_lock>(
81 this));
82 m_image_ctx->owner_lock.put_read();
83 }
84
85 template <typename I>
86 void SnapshotPurgeRequest<I>::handle_acquire_lock(int r) {
87 dout(10) << "r=" << r << dendl;
88
89 if (r < 0) {
90 derr << "failed to acquire exclusive lock: " << cpp_strerror(r) << dendl;
91 m_ret_val = r;
92 close_image();
93 return;
94 }
95
96 {
97 RWLock::RLocker snap_locker(m_image_ctx->snap_lock);
98 m_snaps = m_image_ctx->snaps;
99 }
100 snap_unprotect();
101 }
102
103 template <typename I>
104 void SnapshotPurgeRequest<I>::snap_unprotect() {
105 if (m_snaps.empty()) {
106 close_image();
107 return;
108 }
109
110 librados::snap_t snap_id = m_snaps.back();
111 m_image_ctx->snap_lock.get_read();
112 int r = m_image_ctx->get_snap_namespace(snap_id, &m_snap_namespace);
113 if (r < 0) {
114 m_image_ctx->snap_lock.put_read();
115
116 derr << "failed to get snap namespace: " << cpp_strerror(r) << dendl;
117 m_ret_val = r;
118 close_image();
119 return;
120 }
121
122 r = m_image_ctx->get_snap_name(snap_id, &m_snap_name);
123 if (r < 0) {
124 m_image_ctx->snap_lock.put_read();
125
126 derr << "failed to get snap name: " << cpp_strerror(r) << dendl;
127 m_ret_val = r;
128 close_image();
129 return;
130 }
131
132 bool is_protected;
133 r = m_image_ctx->is_snap_protected(snap_id, &is_protected);
134 if (r < 0) {
135 m_image_ctx->snap_lock.put_read();
136
137 derr << "failed to get snap protection status: " << cpp_strerror(r)
138 << dendl;
139 m_ret_val = r;
140 close_image();
141 return;
142 }
143 m_image_ctx->snap_lock.put_read();
144
145 if (!is_protected) {
146 snap_remove();
147 return;
148 }
149
150 dout(10) << "snap_id=" << snap_id << ", "
151 << "snap_namespace=" << m_snap_namespace << ", "
152 << "snap_name=" << m_snap_name << dendl;
153
154 auto finish_op_ctx = start_lock_op(&r);
155 if (finish_op_ctx == nullptr) {
156 derr << "lost exclusive lock" << dendl;
157 m_ret_val = r;
158 close_image();
159 return;
160 }
161
162 auto ctx = new FunctionContext([this, finish_op_ctx](int r) {
163 handle_snap_unprotect(r);
164 finish_op_ctx->complete(0);
165 });
166 RWLock::RLocker owner_locker(m_image_ctx->owner_lock);
167 m_image_ctx->operations->execute_snap_unprotect(
168 m_snap_namespace, m_snap_name.c_str(), ctx);
169 }
170
171 template <typename I>
172 void SnapshotPurgeRequest<I>::handle_snap_unprotect(int r) {
173 dout(10) << "r=" << r << dendl;
174
175 if (r == -EBUSY) {
176 dout(10) << "snapshot in-use" << dendl;
177 m_ret_val = r;
178 close_image();
179 return;
180 } else if (r < 0) {
181 derr << "failed to unprotect snapshot: " << cpp_strerror(r) << dendl;
182 m_ret_val = r;
183 close_image();
184 return;
185 }
186
187 {
188 // avoid the need to refresh to delete the newly unprotected snapshot
189 RWLock::RLocker snap_locker(m_image_ctx->snap_lock);
190 librados::snap_t snap_id = m_snaps.back();
191 auto snap_info_it = m_image_ctx->snap_info.find(snap_id);
192 if (snap_info_it != m_image_ctx->snap_info.end()) {
193 snap_info_it->second.protection_status =
194 RBD_PROTECTION_STATUS_UNPROTECTED;
195 }
196 }
197
198 snap_remove();
199 }
200
201 template <typename I>
202 void SnapshotPurgeRequest<I>::snap_remove() {
203 librados::snap_t snap_id = m_snaps.back();
204 dout(10) << "snap_id=" << snap_id << ", "
205 << "snap_namespace=" << m_snap_namespace << ", "
206 << "snap_name=" << m_snap_name << dendl;
207
208 int r;
209 auto finish_op_ctx = start_lock_op(&r);
210 if (finish_op_ctx == nullptr) {
211 derr << "lost exclusive lock" << dendl;
212 m_ret_val = r;
213 close_image();
214 return;
215 }
216
217 auto ctx = new FunctionContext([this, finish_op_ctx](int r) {
218 handle_snap_remove(r);
219 finish_op_ctx->complete(0);
220 });
221 RWLock::RLocker owner_locker(m_image_ctx->owner_lock);
222 m_image_ctx->operations->execute_snap_remove(
223 m_snap_namespace, m_snap_name.c_str(), ctx);
224 }
225
226 template <typename I>
227 void SnapshotPurgeRequest<I>::handle_snap_remove(int r) {
228 dout(10) << "r=" << r << dendl;
229
230 if (r == -EBUSY) {
231 dout(10) << "snapshot in-use" << dendl;
232 m_ret_val = r;
233 close_image();
234 return;
235 } else if (r < 0) {
236 derr << "failed to remove snapshot: " << cpp_strerror(r) << dendl;
237 m_ret_val = r;
238 close_image();
239 return;
240 }
241
242 m_snaps.pop_back();
243 snap_unprotect();
244 }
245
246 template <typename I>
247 void SnapshotPurgeRequest<I>::close_image() {
248 dout(10) << dendl;
249
250 m_image_ctx->state->close(create_context_callback<
251 SnapshotPurgeRequest<I>,
252 &SnapshotPurgeRequest<I>::handle_close_image>(this));
253 }
254
255 template <typename I>
256 void SnapshotPurgeRequest<I>::handle_close_image(int r) {
257 dout(10) << "r=" << r << dendl;
258
259 m_image_ctx->destroy();
260 m_image_ctx = nullptr;
261
262 if (r < 0) {
263 derr << "failed to close: " << cpp_strerror(r) << dendl;
264 finish(r);
265 return;
266 }
267 finish(0);
268 }
269
270 template <typename I>
271 void SnapshotPurgeRequest<I>::finish(int r) {
272 if (m_ret_val < 0) {
273 r = m_ret_val;
274 }
275
276 m_on_finish->complete(r);
277 delete this;
278 }
279
280 template <typename I>
281 Context *SnapshotPurgeRequest<I>::start_lock_op(int* r) {
282 RWLock::RLocker owner_locker(m_image_ctx->owner_lock);
283 return m_image_ctx->exclusive_lock->start_op(r);
284 }
285
286 } // namespace image_deleter
287 } // namespace mirror
288 } // namespace rbd
289
290 template class rbd::mirror::image_deleter::SnapshotPurgeRequest<librbd::ImageCtx>;