1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
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"
15 #define dout_context g_ceph_context
16 #define dout_subsys ceph_subsys_rbd_mirror
18 #define dout_prefix *_dout << "rbd::mirror::image_deleter::SnapshotPurgeRequest: " \
19 << this << " " << __func__ << ": "
23 namespace image_deleter
{
25 using librbd::util::create_context_callback
;
28 void SnapshotPurgeRequest
<I
>::send() {
33 void SnapshotPurgeRequest
<I
>::open_image() {
35 m_image_ctx
= I::create("", m_image_id
, nullptr, m_io_ctx
, false);
38 RWLock::WLocker
snap_locker(m_image_ctx
->snap_lock
);
39 m_image_ctx
->set_journal_policy(new JournalPolicy());
42 Context
*ctx
= create_context_callback
<
43 SnapshotPurgeRequest
<I
>, &SnapshotPurgeRequest
<I
>::handle_open_image
>(
45 m_image_ctx
->state
->open(librbd::OPEN_FLAG_SKIP_OPEN_PARENT
, ctx
);
49 void SnapshotPurgeRequest
<I
>::handle_open_image(int r
) {
50 dout(10) << "r=" << r
<< dendl
;
53 derr
<< "failed to open image '" << m_image_id
<< "': " << cpp_strerror(r
)
55 m_image_ctx
->destroy();
56 m_image_ctx
= nullptr;
66 void SnapshotPurgeRequest
<I
>::acquire_lock() {
69 m_image_ctx
->owner_lock
.get_read();
70 if (m_image_ctx
->exclusive_lock
== nullptr) {
71 m_image_ctx
->owner_lock
.put_read();
73 derr
<< "exclusive lock not enabled" << dendl
;
79 m_image_ctx
->exclusive_lock
->acquire_lock(create_context_callback
<
80 SnapshotPurgeRequest
<I
>, &SnapshotPurgeRequest
<I
>::handle_acquire_lock
>(
82 m_image_ctx
->owner_lock
.put_read();
86 void SnapshotPurgeRequest
<I
>::handle_acquire_lock(int r
) {
87 dout(10) << "r=" << r
<< dendl
;
90 derr
<< "failed to acquire exclusive lock: " << cpp_strerror(r
) << dendl
;
97 RWLock::RLocker
snap_locker(m_image_ctx
->snap_lock
);
98 m_snaps
= m_image_ctx
->snaps
;
103 template <typename I
>
104 void SnapshotPurgeRequest
<I
>::snap_unprotect() {
105 if (m_snaps
.empty()) {
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
);
114 m_image_ctx
->snap_lock
.put_read();
116 derr
<< "failed to get snap namespace: " << cpp_strerror(r
) << dendl
;
122 r
= m_image_ctx
->get_snap_name(snap_id
, &m_snap_name
);
124 m_image_ctx
->snap_lock
.put_read();
126 derr
<< "failed to get snap name: " << cpp_strerror(r
) << dendl
;
133 r
= m_image_ctx
->is_snap_protected(snap_id
, &is_protected
);
135 m_image_ctx
->snap_lock
.put_read();
137 derr
<< "failed to get snap protection status: " << cpp_strerror(r
)
143 m_image_ctx
->snap_lock
.put_read();
150 dout(10) << "snap_id=" << snap_id
<< ", "
151 << "snap_namespace=" << m_snap_namespace
<< ", "
152 << "snap_name=" << m_snap_name
<< dendl
;
154 auto finish_op_ctx
= start_lock_op(&r
);
155 if (finish_op_ctx
== nullptr) {
156 derr
<< "lost exclusive lock" << dendl
;
162 auto ctx
= new FunctionContext([this, finish_op_ctx
](int r
) {
163 handle_snap_unprotect(r
);
164 finish_op_ctx
->complete(0);
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
);
171 template <typename I
>
172 void SnapshotPurgeRequest
<I
>::handle_snap_unprotect(int r
) {
173 dout(10) << "r=" << r
<< dendl
;
176 dout(10) << "snapshot in-use" << dendl
;
181 derr
<< "failed to unprotect snapshot: " << cpp_strerror(r
) << dendl
;
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
;
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
;
209 auto finish_op_ctx
= start_lock_op(&r
);
210 if (finish_op_ctx
== nullptr) {
211 derr
<< "lost exclusive lock" << dendl
;
217 auto ctx
= new FunctionContext([this, finish_op_ctx
](int r
) {
218 handle_snap_remove(r
);
219 finish_op_ctx
->complete(0);
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
);
226 template <typename I
>
227 void SnapshotPurgeRequest
<I
>::handle_snap_remove(int r
) {
228 dout(10) << "r=" << r
<< dendl
;
231 dout(10) << "snapshot in-use" << dendl
;
236 derr
<< "failed to remove snapshot: " << cpp_strerror(r
) << dendl
;
246 template <typename I
>
247 void SnapshotPurgeRequest
<I
>::close_image() {
250 m_image_ctx
->state
->close(create_context_callback
<
251 SnapshotPurgeRequest
<I
>,
252 &SnapshotPurgeRequest
<I
>::handle_close_image
>(this));
255 template <typename I
>
256 void SnapshotPurgeRequest
<I
>::handle_close_image(int r
) {
257 dout(10) << "r=" << r
<< dendl
;
259 m_image_ctx
->destroy();
260 m_image_ctx
= nullptr;
263 derr
<< "failed to close: " << cpp_strerror(r
) << dendl
;
270 template <typename I
>
271 void SnapshotPurgeRequest
<I
>::finish(int r
) {
276 m_on_finish
->complete(r
);
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
);
286 } // namespace image_deleter
287 } // namespace mirror
290 template class rbd::mirror::image_deleter::SnapshotPurgeRequest
<librbd::ImageCtx
>;