1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "librbd/object_map/SnapshotRemoveRequest.h"
5 #include "common/dout.h"
6 #include "common/errno.h"
7 #include "librbd/ImageCtx.h"
8 #include "librbd/ObjectMap.h"
9 #include "librbd/object_map/InvalidateRequest.h"
10 #include "cls/lock/cls_lock_client.h"
12 #define dout_subsys ceph_subsys_rbd
14 #define dout_prefix *_dout << "librbd::object_map::SnapshotRemoveRequest: " \
15 << this << " " << __func__ << ": "
18 namespace object_map
{
20 void SnapshotRemoveRequest::send() {
21 assert(m_image_ctx
.owner_lock
.is_locked());
22 assert(m_image_ctx
.snap_lock
.is_wlocked());
24 if ((m_image_ctx
.features
& RBD_FEATURE_FAST_DIFF
) != 0) {
25 int r
= m_image_ctx
.get_flags(m_snap_id
, &m_flags
);
28 compute_next_snap_id();
35 void SnapshotRemoveRequest::load_map() {
36 CephContext
*cct
= m_image_ctx
.cct
;
37 std::string
snap_oid(ObjectMap
<>::object_map_name(m_image_ctx
.id
, m_snap_id
));
38 ldout(cct
, 5) << "snap_oid=" << snap_oid
<< dendl
;
40 librados::ObjectReadOperation op
;
41 cls_client::object_map_load_start(&op
);
43 auto rados_completion
= librbd::util::create_rados_callback
<
44 SnapshotRemoveRequest
, &SnapshotRemoveRequest::handle_load_map
>(this);
45 int r
= m_image_ctx
.md_ctx
.aio_operate(snap_oid
, rados_completion
, &op
,
48 rados_completion
->release();
51 void SnapshotRemoveRequest::handle_load_map(int r
) {
52 CephContext
*cct
= m_image_ctx
.cct
;
53 ldout(cct
, 5) << "r=" << r
<< dendl
;
56 auto it
= m_out_bl
.begin();
57 r
= cls_client::object_map_load_finish(&it
, &m_snap_object_map
);
60 // implies we have already deleted this snapshot and handled the
61 // necessary fast-diff cleanup
65 std::string
oid(ObjectMap
<>::object_map_name(m_image_ctx
.id
, m_snap_id
));
66 lderr(cct
) << "failed to load object map " << oid
<< ": "
67 << cpp_strerror(r
) << dendl
;
69 RWLock::RLocker
owner_locker(m_image_ctx
.owner_lock
);
70 RWLock::WLocker
snap_locker(m_image_ctx
.snap_lock
);
71 invalidate_next_map();
78 void SnapshotRemoveRequest::remove_snapshot() {
79 if ((m_flags
& RBD_FLAG_OBJECT_MAP_INVALID
) != 0) {
80 // snapshot object map exists on disk but is invalid. cannot clean fast-diff
81 // on next snapshot if current snapshot was invalid.
82 RWLock::RLocker
owner_locker(m_image_ctx
.owner_lock
);
83 RWLock::WLocker
snap_locker(m_image_ctx
.snap_lock
);
84 invalidate_next_map();
88 CephContext
*cct
= m_image_ctx
.cct
;
89 std::string
oid(ObjectMap
<>::object_map_name(m_image_ctx
.id
, m_next_snap_id
));
90 ldout(cct
, 5) << "oid=" << oid
<< dendl
;
92 librados::ObjectWriteOperation op
;
93 if (m_next_snap_id
== CEPH_NOSNAP
) {
94 rados::cls::lock::assert_locked(&op
, RBD_LOCK_NAME
, LOCK_EXCLUSIVE
, "", "");
96 cls_client::object_map_snap_remove(&op
, m_snap_object_map
);
98 auto rados_completion
= librbd::util::create_rados_callback
<
99 SnapshotRemoveRequest
,
100 &SnapshotRemoveRequest::handle_remove_snapshot
>(this);
101 int r
= m_image_ctx
.md_ctx
.aio_operate(oid
, rados_completion
, &op
);
103 rados_completion
->release();
106 void SnapshotRemoveRequest::handle_remove_snapshot(int r
) {
107 CephContext
*cct
= m_image_ctx
.cct
;
108 ldout(cct
, 5) << "r=" << r
<< dendl
;
109 if (r
< 0 && r
!= -ENOENT
) {
110 std::string
oid(ObjectMap
<>::object_map_name(m_image_ctx
.id
,
112 lderr(cct
) << "failed to remove object map snapshot " << oid
<< ": "
113 << cpp_strerror(r
) << dendl
;
115 RWLock::RLocker
owner_locker(m_image_ctx
.owner_lock
);
116 RWLock::WLocker
snap_locker(m_image_ctx
.snap_lock
);
117 invalidate_next_map();
121 RWLock::RLocker
snap_locker(m_image_ctx
.snap_lock
);
126 void SnapshotRemoveRequest::invalidate_next_map() {
127 assert(m_image_ctx
.owner_lock
.is_locked());
128 assert(m_image_ctx
.snap_lock
.is_wlocked());
130 CephContext
*cct
= m_image_ctx
.cct
;
131 ldout(cct
, 5) << dendl
;
133 auto ctx
= librbd::util::create_context_callback
<
134 SnapshotRemoveRequest
,
135 &SnapshotRemoveRequest::handle_invalidate_next_map
>(this);
136 InvalidateRequest
<> *req
= new InvalidateRequest
<>(m_image_ctx
,
137 m_next_snap_id
, true, ctx
);
141 void SnapshotRemoveRequest::handle_invalidate_next_map(int r
) {
142 CephContext
*cct
= m_image_ctx
.cct
;
143 ldout(cct
, 5) << "r=" << r
<< dendl
;
149 void SnapshotRemoveRequest::remove_map() {
150 CephContext
*cct
= m_image_ctx
.cct
;
151 std::string
oid(ObjectMap
<>::object_map_name(m_image_ctx
.id
, m_snap_id
));
152 ldout(cct
, 5) << "oid=" << oid
<< dendl
;
154 librados::ObjectWriteOperation op
;
157 auto rados_completion
= librbd::util::create_rados_callback
<
158 SnapshotRemoveRequest
, &SnapshotRemoveRequest::handle_remove_map
>(this);
159 int r
= m_image_ctx
.md_ctx
.aio_operate(oid
, rados_completion
, &op
);
161 rados_completion
->release();
164 void SnapshotRemoveRequest::handle_remove_map(int r
) {
165 CephContext
*cct
= m_image_ctx
.cct
;
166 ldout(cct
, 5) << "r=" << r
<< dendl
;
168 if (r
< 0 && r
!= -ENOENT
) {
169 std::string
oid(ObjectMap
<>::object_map_name(m_image_ctx
.id
, m_snap_id
));
170 lderr(cct
) << "failed to remove object map " << oid
<< ": "
171 << cpp_strerror(r
) << dendl
;
179 void SnapshotRemoveRequest::compute_next_snap_id() {
180 assert(m_image_ctx
.snap_lock
.is_locked());
182 m_next_snap_id
= CEPH_NOSNAP
;
183 std::map
<librados::snap_t
, SnapInfo
>::const_iterator it
=
184 m_image_ctx
.snap_info
.find(m_snap_id
);
185 assert(it
!= m_image_ctx
.snap_info
.end());
188 if (it
!= m_image_ctx
.snap_info
.end()) {
189 m_next_snap_id
= it
->first
;
193 void SnapshotRemoveRequest::update_object_map() {
194 assert(m_image_ctx
.snap_lock
.is_locked());
195 RWLock::WLocker
object_map_locker(m_image_ctx
.object_map_lock
);
196 if (m_next_snap_id
== m_image_ctx
.snap_id
&& m_next_snap_id
== CEPH_NOSNAP
) {
197 CephContext
*cct
= m_image_ctx
.cct
;
198 ldout(cct
, 5) << dendl
;
200 auto it
= m_object_map
.begin();
201 auto end_it
= m_object_map
.end();
202 auto snap_it
= m_snap_object_map
.begin();
204 for (; it
!= end_it
; ++it
) {
205 if (*it
== OBJECT_EXISTS_CLEAN
&&
206 (i
>= m_snap_object_map
.size() ||
207 *snap_it
== OBJECT_EXISTS
)) {
210 if (i
< m_snap_object_map
.size()) {
218 } // namespace object_map
219 } // namespace librbd