]> git.proxmox.com Git - ceph.git/blame - ceph/src/librbd/operation/SnapshotCreateRequest.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / librbd / operation / SnapshotCreateRequest.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 "cls/rbd/cls_rbd_types.h"
5#include "librbd/operation/SnapshotCreateRequest.h"
6#include "common/dout.h"
7#include "common/errno.h"
8#include "librbd/ExclusiveLock.h"
9#include "librbd/ImageCtx.h"
f67539c2 10#include "librbd/ImageWatcher.h"
7c673cae
FG
11#include "librbd/ObjectMap.h"
12#include "librbd/Utils.h"
f67539c2 13#include "librbd/io/ImageDispatcherInterface.h"
9f95a23c 14#include "librbd/mirror/snapshot/SetImageStateRequest.h"
7c673cae
FG
15
16#define dout_subsys ceph_subsys_rbd
17#undef dout_prefix
18#define dout_prefix *_dout << "librbd::SnapshotCreateRequest: "
19
20namespace librbd {
21namespace operation {
22
23using util::create_async_context_callback;
24using util::create_context_callback;
25using util::create_rados_callback;
26
27template <typename I>
28SnapshotCreateRequest<I>::SnapshotCreateRequest(I &image_ctx,
29 Context *on_finish,
30 const cls::rbd::SnapshotNamespace &snap_namespace,
31 const std::string &snap_name,
32 uint64_t journal_op_tid,
f67539c2
TL
33 uint64_t flags,
34 ProgressContext &prog_ctx)
7c673cae
FG
35 : Request<I>(image_ctx, on_finish, journal_op_tid),
36 m_snap_namespace(snap_namespace), m_snap_name(snap_name),
f67539c2
TL
37 m_skip_object_map(flags & SNAP_CREATE_FLAG_SKIP_OBJECT_MAP),
38 m_skip_notify_quiesce(flags & SNAP_CREATE_FLAG_SKIP_NOTIFY_QUIESCE),
39 m_ignore_notify_quiesce_error(flags & SNAP_CREATE_FLAG_IGNORE_NOTIFY_QUIESCE_ERROR),
40 m_prog_ctx(prog_ctx) {
7c673cae
FG
41}
42
43template <typename I>
44void SnapshotCreateRequest<I>::send_op() {
eafe8130
TL
45 I &image_ctx = this->m_image_ctx;
46 CephContext *cct = image_ctx.cct;
47
48 if (!image_ctx.data_ctx.is_valid()) {
49 lderr(cct) << "missing data pool" << dendl;
50 this->async_complete(-ENODEV);
51 return;
52 }
53
f67539c2
TL
54 send_notify_quiesce();
55}
56
57template <typename I>
58void SnapshotCreateRequest<I>::send_notify_quiesce() {
59 if (m_skip_notify_quiesce) {
60 send_suspend_requests();
61 return;
62 }
63
64 I &image_ctx = this->m_image_ctx;
65 CephContext *cct = image_ctx.cct;
66 ldout(cct, 5) << this << " " << __func__ << dendl;
67
68 image_ctx.image_watcher->notify_quiesce(
69 &m_request_id, m_prog_ctx, create_async_context_callback(
70 image_ctx, create_context_callback<SnapshotCreateRequest<I>,
71 &SnapshotCreateRequest<I>::handle_notify_quiesce>(this)));
72}
73
74template <typename I>
75Context *SnapshotCreateRequest<I>::handle_notify_quiesce(int *result) {
76 I &image_ctx = this->m_image_ctx;
77 CephContext *cct = image_ctx.cct;
78 ldout(cct, 5) << this << " " << __func__ << ": r=" << *result << dendl;
79
80 if (*result < 0 && !m_ignore_notify_quiesce_error) {
81 lderr(cct) << "failed to notify quiesce: " << cpp_strerror(*result)
82 << dendl;
83 save_result(result);
84 send_notify_unquiesce();
85 return nullptr;
86 }
87
88 std::shared_lock owner_locker{image_ctx.owner_lock};
7c673cae 89 send_suspend_requests();
f67539c2 90 return nullptr;
7c673cae
FG
91}
92
93template <typename I>
94void SnapshotCreateRequest<I>::send_suspend_requests() {
95 I &image_ctx = this->m_image_ctx;
96 CephContext *cct = image_ctx.cct;
97 ldout(cct, 5) << this << " " << __func__ << dendl;
98
99 // TODO suspend (shrink) resize to ensure consistent RBD mirror
100 send_suspend_aio();
101}
102
103template <typename I>
104Context *SnapshotCreateRequest<I>::handle_suspend_requests(int *result) {
105 I &image_ctx = this->m_image_ctx;
106 CephContext *cct = image_ctx.cct;
107 ldout(cct, 5) << this << " " << __func__ << ": r=" << *result << dendl;
108
109 // TODO
110 send_suspend_aio();
111 return nullptr;
112}
113
114template <typename I>
115void SnapshotCreateRequest<I>::send_suspend_aio() {
116 I &image_ctx = this->m_image_ctx;
9f95a23c 117 ceph_assert(ceph_mutex_is_locked(image_ctx.owner_lock));
7c673cae
FG
118
119 CephContext *cct = image_ctx.cct;
120 ldout(cct, 5) << this << " " << __func__ << dendl;
121
f67539c2 122 image_ctx.io_image_dispatcher->block_writes(create_context_callback<
7c673cae
FG
123 SnapshotCreateRequest<I>,
124 &SnapshotCreateRequest<I>::handle_suspend_aio>(this));
125}
126
127template <typename I>
128Context *SnapshotCreateRequest<I>::handle_suspend_aio(int *result) {
129 I &image_ctx = this->m_image_ctx;
130 CephContext *cct = image_ctx.cct;
131 ldout(cct, 5) << this << " " << __func__ << ": r=" << *result << dendl;
132
133 if (*result < 0) {
134 lderr(cct) << "failed to block writes: " << cpp_strerror(*result) << dendl;
f67539c2
TL
135 save_result(result);
136 return send_notify_unquiesce();
7c673cae
FG
137 }
138
f67539c2
TL
139 m_writes_blocked = true;
140
7c673cae
FG
141 send_append_op_event();
142 return nullptr;
143}
144
145template <typename I>
146void SnapshotCreateRequest<I>::send_append_op_event() {
147 I &image_ctx = this->m_image_ctx;
148 if (!this->template append_op_event<
149 SnapshotCreateRequest<I>,
150 &SnapshotCreateRequest<I>::handle_append_op_event>(this)) {
151 send_allocate_snap_id();
152 return;
153 }
154
155 CephContext *cct = image_ctx.cct;
156 ldout(cct, 5) << this << " " << __func__ << dendl;
157}
158
159template <typename I>
160Context *SnapshotCreateRequest<I>::handle_append_op_event(int *result) {
161 I &image_ctx = this->m_image_ctx;
162 CephContext *cct = image_ctx.cct;
163 ldout(cct, 5) << this << " " << __func__ << ": r=" << *result << dendl;
164
165 if (*result < 0) {
7c673cae
FG
166 lderr(cct) << "failed to commit journal entry: " << cpp_strerror(*result)
167 << dendl;
f67539c2
TL
168 save_result(result);
169 return send_notify_unquiesce();
7c673cae
FG
170 }
171
172 send_allocate_snap_id();
173 return nullptr;
174}
175
176template <typename I>
177void SnapshotCreateRequest<I>::send_allocate_snap_id() {
178 I &image_ctx = this->m_image_ctx;
179 CephContext *cct = image_ctx.cct;
180 ldout(cct, 5) << this << " " << __func__ << dendl;
181
182 librados::AioCompletion *rados_completion = create_rados_callback<
183 SnapshotCreateRequest<I>,
184 &SnapshotCreateRequest<I>::handle_allocate_snap_id>(this);
3efd9988 185 image_ctx.data_ctx.aio_selfmanaged_snap_create(&m_snap_id, rados_completion);
7c673cae
FG
186 rados_completion->release();
187}
188
189template <typename I>
190Context *SnapshotCreateRequest<I>::handle_allocate_snap_id(int *result) {
191 I &image_ctx = this->m_image_ctx;
192 CephContext *cct = image_ctx.cct;
193 ldout(cct, 5) << this << " " << __func__ << ": r=" << *result << ", "
194 << "snap_id=" << m_snap_id << dendl;
195
196 if (*result < 0) {
7c673cae
FG
197 lderr(cct) << "failed to allocate snapshot id: " << cpp_strerror(*result)
198 << dendl;
f67539c2
TL
199 save_result(result);
200 return send_notify_unquiesce();
7c673cae
FG
201 }
202
203 send_create_snap();
204 return nullptr;
205}
206
207template <typename I>
208void SnapshotCreateRequest<I>::send_create_snap() {
209 I &image_ctx = this->m_image_ctx;
210 CephContext *cct = image_ctx.cct;
211 ldout(cct, 5) << this << " " << __func__ << dendl;
212
9f95a23c
TL
213 std::shared_lock owner_locker{image_ctx.owner_lock};
214 std::shared_lock image_locker{image_ctx.image_lock};
7c673cae
FG
215
216 // should have been canceled prior to releasing lock
11fdf7f2
TL
217 ceph_assert(image_ctx.exclusive_lock == nullptr ||
218 image_ctx.exclusive_lock->is_lock_owner());
7c673cae
FG
219
220 // save current size / parent info for creating snapshot record in ImageCtx
221 m_size = image_ctx.size;
222 m_parent_info = image_ctx.parent_md;
223
224 librados::ObjectWriteOperation op;
225 if (image_ctx.old_format) {
226 cls_client::old_snapshot_add(&op, m_snap_id, m_snap_name);
227 } else {
228 cls_client::snapshot_add(&op, m_snap_id, m_snap_name, m_snap_namespace);
229 }
230
231 librados::AioCompletion *rados_completion = create_rados_callback<
232 SnapshotCreateRequest<I>,
233 &SnapshotCreateRequest<I>::handle_create_snap>(this);
234 int r = image_ctx.md_ctx.aio_operate(image_ctx.header_oid,
235 rados_completion, &op);
11fdf7f2 236 ceph_assert(r == 0);
7c673cae
FG
237 rados_completion->release();
238}
239
240template <typename I>
241Context *SnapshotCreateRequest<I>::handle_create_snap(int *result) {
242 I &image_ctx = this->m_image_ctx;
243 CephContext *cct = image_ctx.cct;
244 ldout(cct, 5) << this << " " << __func__ << ": r=" << *result << dendl;
245
246 if (*result == -ESTALE) {
247 send_allocate_snap_id();
248 return nullptr;
249 } else if (*result < 0) {
250 save_result(result);
251 send_release_snap_id();
252 return nullptr;
253 }
254
255 return send_create_object_map();
256}
257
258template <typename I>
259Context *SnapshotCreateRequest<I>::send_create_object_map() {
260 I &image_ctx = this->m_image_ctx;
261
9f95a23c 262 image_ctx.image_lock.lock_shared();
7c673cae 263 if (image_ctx.object_map == nullptr || m_skip_object_map) {
9f95a23c
TL
264 image_ctx.image_lock.unlock_shared();
265
266 return send_create_image_state();
267 }
268
269 CephContext *cct = image_ctx.cct;
270 ldout(cct, 5) << this << " " << __func__ << dendl;
271
272 image_ctx.object_map->snapshot_add(
273 m_snap_id, create_context_callback<
274 SnapshotCreateRequest<I>,
275 &SnapshotCreateRequest<I>::handle_create_object_map>(this));
276 image_ctx.image_lock.unlock_shared();
277 return nullptr;
278}
279
280template <typename I>
281Context *SnapshotCreateRequest<I>::handle_create_object_map(int *result) {
282 I &image_ctx = this->m_image_ctx;
283 CephContext *cct = image_ctx.cct;
284 ldout(cct, 5) << this << " " << __func__ << ": r=" << *result << dendl;
285
286 if (*result < 0) {
287 lderr(cct) << this << " " << __func__ << ": failed to snapshot object map: "
288 << cpp_strerror(*result) << dendl;
7c673cae 289
f67539c2 290 save_result(result);
9f95a23c 291 update_snap_context();
f67539c2 292 return send_notify_unquiesce();
9f95a23c
TL
293 }
294
295 return send_create_image_state();
296}
297
298template <typename I>
299Context *SnapshotCreateRequest<I>::send_create_image_state() {
300 I &image_ctx = this->m_image_ctx;
1e59de90 301 auto mirror_ns = std::get_if<cls::rbd::MirrorSnapshotNamespace>(
9f95a23c
TL
302 &m_snap_namespace);
303 if (mirror_ns == nullptr || !mirror_ns->is_primary()) {
91327a77 304 update_snap_context();
f67539c2 305 return send_notify_unquiesce();
7c673cae
FG
306 }
307
308 CephContext *cct = image_ctx.cct;
309 ldout(cct, 5) << this << " " << __func__ << dendl;
310
9f95a23c
TL
311 auto req = mirror::snapshot::SetImageStateRequest<I>::create(
312 &image_ctx, m_snap_id, create_context_callback<
313 SnapshotCreateRequest<I>,
314 &SnapshotCreateRequest<I>::handle_create_image_state>(this));
315 req->send();
7c673cae
FG
316 return nullptr;
317}
318
319template <typename I>
9f95a23c 320Context *SnapshotCreateRequest<I>::handle_create_image_state(int *result) {
7c673cae
FG
321 I &image_ctx = this->m_image_ctx;
322 CephContext *cct = image_ctx.cct;
323 ldout(cct, 5) << this << " " << __func__ << ": r=" << *result << dendl;
324
91327a77 325 update_snap_context();
91327a77 326 if (*result < 0) {
f67539c2 327 lderr(cct) << this << " " << __func__ << ": failed to create image state: "
91327a77 328 << cpp_strerror(*result) << dendl;
f67539c2 329 save_result(result);
91327a77
AA
330 }
331
f67539c2 332 return send_notify_unquiesce();
7c673cae
FG
333}
334
335template <typename I>
336void SnapshotCreateRequest<I>::send_release_snap_id() {
337 I &image_ctx = this->m_image_ctx;
338 CephContext *cct = image_ctx.cct;
339 ldout(cct, 5) << this << " " << __func__ << dendl;
340
11fdf7f2 341 ceph_assert(m_snap_id != CEPH_NOSNAP);
7c673cae
FG
342
343 librados::AioCompletion *rados_completion = create_rados_callback<
344 SnapshotCreateRequest<I>,
345 &SnapshotCreateRequest<I>::handle_release_snap_id>(this);
3efd9988 346 image_ctx.data_ctx.aio_selfmanaged_snap_remove(m_snap_id, rados_completion);
7c673cae
FG
347 rados_completion->release();
348}
349
350template <typename I>
351Context *SnapshotCreateRequest<I>::handle_release_snap_id(int *result) {
352 I &image_ctx = this->m_image_ctx;
353 CephContext *cct = image_ctx.cct;
354 ldout(cct, 5) << this << " " << __func__ << ": r=" << *result << dendl;
355
f67539c2
TL
356 return send_notify_unquiesce();
357}
358
359template <typename I>
360Context *SnapshotCreateRequest<I>::send_notify_unquiesce() {
361 I &image_ctx = this->m_image_ctx;
362 CephContext *cct = image_ctx.cct;
363
364 if (m_writes_blocked) {
365 image_ctx.io_image_dispatcher->unblock_writes();
366 }
7c673cae 367
f67539c2
TL
368 if (m_skip_notify_quiesce) {
369 return this->create_context_finisher(m_ret_val);
370 }
371
372 ldout(cct, 5) << this << " " << __func__ << dendl;
373
374 image_ctx.image_watcher->notify_unquiesce(
375 m_request_id, create_context_callback<
376 SnapshotCreateRequest<I>,
377 &SnapshotCreateRequest<I>::handle_notify_unquiesce>(this));
378
379 return nullptr;
380}
381
382template <typename I>
383Context *SnapshotCreateRequest<I>::handle_notify_unquiesce(int *result) {
384 I &image_ctx = this->m_image_ctx;
385 CephContext *cct = image_ctx.cct;
386 ldout(cct, 5) << this << " " << __func__ << ": r=" << *result << dendl;
387
388 if (*result < 0) {
389 lderr(cct) << "failed to notify unquiesce: " << cpp_strerror(*result)
390 << dendl;
391 // ignore error
392 }
393
394 *result = m_ret_val;
7c673cae
FG
395 return this->create_context_finisher(m_ret_val);
396}
397
398template <typename I>
399void SnapshotCreateRequest<I>::update_snap_context() {
400 I &image_ctx = this->m_image_ctx;
401
9f95a23c
TL
402 std::shared_lock owner_locker{image_ctx.owner_lock};
403 std::unique_lock image_locker{image_ctx.image_lock};
7c673cae
FG
404 if (image_ctx.get_snap_info(m_snap_id) != NULL) {
405 return;
406 }
407
408 CephContext *cct = image_ctx.cct;
409 ldout(cct, 5) << this << " " << __func__ << dendl;
410
411 // should have been canceled prior to releasing lock
11fdf7f2
TL
412 ceph_assert(image_ctx.exclusive_lock == nullptr ||
413 image_ctx.exclusive_lock->is_lock_owner());
7c673cae
FG
414
415 // immediately add a reference to the new snapshot
416 utime_t snap_time = ceph_clock_now();
417 image_ctx.add_snap(m_snap_namespace, m_snap_name, m_snap_id, m_size,
418 m_parent_info, RBD_PROTECTION_STATUS_UNPROTECTED,
419 0, snap_time);
420
421 // immediately start using the new snap context if we
422 // own the exclusive lock
423 std::vector<snapid_t> snaps;
424 snaps.push_back(m_snap_id);
425 snaps.insert(snaps.end(), image_ctx.snapc.snaps.begin(),
426 image_ctx.snapc.snaps.end());
427
428 image_ctx.snapc.seq = m_snap_id;
429 image_ctx.snapc.snaps.swap(snaps);
430 image_ctx.data_ctx.selfmanaged_snap_set_write_ctx(
431 image_ctx.snapc.seq, image_ctx.snaps);
f67539c2 432 image_ctx.rebuild_data_io_context();
11fdf7f2
TL
433
434 if (!image_ctx.migration_info.empty()) {
435 auto it = image_ctx.migration_info.snap_map.find(CEPH_NOSNAP);
436 ceph_assert(it != image_ctx.migration_info.snap_map.end());
437 ceph_assert(!it->second.empty());
438 if (it->second[0] == CEPH_NOSNAP) {
439 ldout(cct, 5) << this << " " << __func__
440 << ": updating migration snap_map" << dendl;
441 it->second[0] = m_snap_id;
442 }
443 }
7c673cae
FG
444}
445
446} // namespace operation
447} // namespace librbd
448
449template class librbd::operation::SnapshotCreateRequest<librbd::ImageCtx>;