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);
37 // ensure non-primary images can be modified
38 m_image_ctx
->read_only_mask
&= ~librbd::IMAGE_READ_ONLY_FLAG_NON_PRIMARY
;
41 std::unique_lock image_locker
{m_image_ctx
->image_lock
};
42 m_image_ctx
->set_journal_policy(new JournalPolicy());
45 Context
*ctx
= create_context_callback
<
46 SnapshotPurgeRequest
<I
>, &SnapshotPurgeRequest
<I
>::handle_open_image
>(
48 m_image_ctx
->state
->open(librbd::OPEN_FLAG_SKIP_OPEN_PARENT
, ctx
);
52 void SnapshotPurgeRequest
<I
>::handle_open_image(int r
) {
53 dout(10) << "r=" << r
<< dendl
;
56 derr
<< "failed to open image '" << m_image_id
<< "': " << cpp_strerror(r
)
58 m_image_ctx
->destroy();
59 m_image_ctx
= nullptr;
69 void SnapshotPurgeRequest
<I
>::acquire_lock() {
72 m_image_ctx
->owner_lock
.lock_shared();
73 if (m_image_ctx
->exclusive_lock
== nullptr) {
74 m_image_ctx
->owner_lock
.unlock_shared();
76 start_snap_unprotect();
80 m_image_ctx
->exclusive_lock
->acquire_lock(create_context_callback
<
81 SnapshotPurgeRequest
<I
>, &SnapshotPurgeRequest
<I
>::handle_acquire_lock
>(
83 m_image_ctx
->owner_lock
.unlock_shared();
87 void SnapshotPurgeRequest
<I
>::handle_acquire_lock(int r
) {
88 dout(10) << "r=" << r
<< dendl
;
91 derr
<< "failed to acquire exclusive lock: " << cpp_strerror(r
) << dendl
;
97 start_snap_unprotect();
100 template <typename I
>
101 void SnapshotPurgeRequest
<I
>::start_snap_unprotect() {
105 std::shared_lock image_locker
{m_image_ctx
->image_lock
};
106 m_snaps
= m_image_ctx
->snaps
;
111 template <typename I
>
112 void SnapshotPurgeRequest
<I
>::snap_unprotect() {
113 if (m_snaps
.empty()) {
118 librados::snap_t snap_id
= m_snaps
.back();
119 m_image_ctx
->image_lock
.lock_shared();
120 int r
= m_image_ctx
->get_snap_namespace(snap_id
, &m_snap_namespace
);
122 m_image_ctx
->image_lock
.unlock_shared();
124 derr
<< "failed to get snap namespace: " << cpp_strerror(r
) << dendl
;
130 r
= m_image_ctx
->get_snap_name(snap_id
, &m_snap_name
);
132 m_image_ctx
->image_lock
.unlock_shared();
134 derr
<< "failed to get snap name: " << cpp_strerror(r
) << dendl
;
141 r
= m_image_ctx
->is_snap_protected(snap_id
, &is_protected
);
143 m_image_ctx
->image_lock
.unlock_shared();
145 derr
<< "failed to get snap protection status: " << cpp_strerror(r
)
151 m_image_ctx
->image_lock
.unlock_shared();
158 dout(10) << "snap_id=" << snap_id
<< ", "
159 << "snap_namespace=" << m_snap_namespace
<< ", "
160 << "snap_name=" << m_snap_name
<< dendl
;
162 auto finish_op_ctx
= start_lock_op(&r
);
163 if (finish_op_ctx
== nullptr) {
164 derr
<< "lost exclusive lock" << dendl
;
170 auto ctx
= new LambdaContext([this, finish_op_ctx
](int r
) {
171 handle_snap_unprotect(r
);
172 finish_op_ctx
->complete(0);
174 std::shared_lock owner_locker
{m_image_ctx
->owner_lock
};
175 m_image_ctx
->operations
->execute_snap_unprotect(
176 m_snap_namespace
, m_snap_name
.c_str(), ctx
);
179 template <typename I
>
180 void SnapshotPurgeRequest
<I
>::handle_snap_unprotect(int r
) {
181 dout(10) << "r=" << r
<< dendl
;
184 dout(10) << "snapshot in-use" << dendl
;
189 derr
<< "failed to unprotect snapshot: " << cpp_strerror(r
) << dendl
;
196 // avoid the need to refresh to delete the newly unprotected snapshot
197 std::shared_lock image_locker
{m_image_ctx
->image_lock
};
198 librados::snap_t snap_id
= m_snaps
.back();
199 auto snap_info_it
= m_image_ctx
->snap_info
.find(snap_id
);
200 if (snap_info_it
!= m_image_ctx
->snap_info
.end()) {
201 snap_info_it
->second
.protection_status
=
202 RBD_PROTECTION_STATUS_UNPROTECTED
;
209 template <typename I
>
210 void SnapshotPurgeRequest
<I
>::snap_remove() {
211 librados::snap_t snap_id
= m_snaps
.back();
212 dout(10) << "snap_id=" << snap_id
<< ", "
213 << "snap_namespace=" << m_snap_namespace
<< ", "
214 << "snap_name=" << m_snap_name
<< dendl
;
217 auto finish_op_ctx
= start_lock_op(&r
);
218 if (finish_op_ctx
== nullptr) {
219 derr
<< "lost exclusive lock" << dendl
;
225 auto ctx
= new LambdaContext([this, finish_op_ctx
](int r
) {
226 handle_snap_remove(r
);
227 finish_op_ctx
->complete(0);
229 std::shared_lock owner_locker
{m_image_ctx
->owner_lock
};
230 m_image_ctx
->operations
->execute_snap_remove(
231 m_snap_namespace
, m_snap_name
.c_str(), ctx
);
234 template <typename I
>
235 void SnapshotPurgeRequest
<I
>::handle_snap_remove(int r
) {
236 dout(10) << "r=" << r
<< dendl
;
239 dout(10) << "snapshot in-use" << dendl
;
244 derr
<< "failed to remove snapshot: " << cpp_strerror(r
) << dendl
;
254 template <typename I
>
255 void SnapshotPurgeRequest
<I
>::close_image() {
258 m_image_ctx
->state
->close(create_context_callback
<
259 SnapshotPurgeRequest
<I
>,
260 &SnapshotPurgeRequest
<I
>::handle_close_image
>(this));
263 template <typename I
>
264 void SnapshotPurgeRequest
<I
>::handle_close_image(int r
) {
265 dout(10) << "r=" << r
<< dendl
;
267 m_image_ctx
->destroy();
268 m_image_ctx
= nullptr;
271 derr
<< "failed to close: " << cpp_strerror(r
) << dendl
;
278 template <typename I
>
279 void SnapshotPurgeRequest
<I
>::finish(int r
) {
284 m_on_finish
->complete(r
);
288 template <typename I
>
289 Context
*SnapshotPurgeRequest
<I
>::start_lock_op(int* r
) {
290 std::shared_lock owner_locker
{m_image_ctx
->owner_lock
};
291 if (m_image_ctx
->exclusive_lock
== nullptr) {
292 return new LambdaContext([](int r
) {});
294 return m_image_ctx
->exclusive_lock
->start_op(r
);
297 } // namespace image_deleter
298 } // namespace mirror
301 template class rbd::mirror::image_deleter::SnapshotPurgeRequest
<librbd::ImageCtx
>;