]> git.proxmox.com Git - ceph.git/blame - ceph/src/librbd/object_map/SnapshotRemoveRequest.cc
update sources to v12.2.3
[ceph.git] / ceph / src / librbd / object_map / SnapshotRemoveRequest.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 "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"
11
12#define dout_subsys ceph_subsys_rbd
13#undef dout_prefix
14#define dout_prefix *_dout << "librbd::object_map::SnapshotRemoveRequest: "
15
16namespace librbd {
17namespace object_map {
18
19namespace {
20
21std::ostream& operator<<(std::ostream& os,
22 const SnapshotRemoveRequest::State& state) {
23 switch(state) {
24 case SnapshotRemoveRequest::STATE_LOAD_MAP:
25 os << "LOAD_MAP";
26 break;
27 case SnapshotRemoveRequest::STATE_REMOVE_SNAPSHOT:
28 os << "REMOVE_SNAPSHOT";
29 break;
30 case SnapshotRemoveRequest::STATE_INVALIDATE_NEXT_MAP:
31 os << "INVALIDATE_NEXT_MAP";
32 break;
33 case SnapshotRemoveRequest::STATE_REMOVE_MAP:
34 os << "REMOVE_MAP";
35 break;
36 default:
37 os << "UNKNOWN (" << static_cast<uint32_t>(state) << ")";
38 break;
39 }
40 return os;
41}
42
43} // anonymous namespace
44
45void SnapshotRemoveRequest::send() {
46 assert(m_image_ctx.owner_lock.is_locked());
47 assert(m_image_ctx.snap_lock.is_wlocked());
48
49 if ((m_image_ctx.features & RBD_FEATURE_FAST_DIFF) != 0) {
50 compute_next_snap_id();
51
52 uint64_t flags;
53 int r = m_image_ctx.get_flags(m_snap_id, &flags);
54 assert(r == 0);
55
56 if ((flags & RBD_FLAG_OBJECT_MAP_INVALID) != 0) {
57 send_invalidate_next_map();
58 } else {
59 send_load_map();
60 }
61 } else {
62 send_remove_map();
63 }
64}
65
66bool SnapshotRemoveRequest::should_complete(int r) {
67 CephContext *cct = m_image_ctx.cct;
68 ldout(cct, 5) << this << " " << __func__ << ": state=" << m_state << ", "
69 << "r=" << r << dendl;
70
71 RWLock::RLocker owner_locker(m_image_ctx.owner_lock);
72 bool finished = false;
73 switch (m_state) {
74 case STATE_LOAD_MAP:
75 if (r == -ENOENT) {
76 finished = true;
77 break;
78 }
79
80 if (r == 0) {
81 bufferlist::iterator it = m_out_bl.begin();
82 r = cls_client::object_map_load_finish(&it, &m_snap_object_map);
83 }
84 if (r < 0) {
85 RWLock::WLocker snap_locker(m_image_ctx.snap_lock);
86 send_invalidate_next_map();
87 } else {
88 send_remove_snapshot();
89 }
90 break;
91 case STATE_REMOVE_SNAPSHOT:
92 if (r < 0 && r != -ENOENT) {
93 RWLock::WLocker snap_locker(m_image_ctx.snap_lock);
94 send_invalidate_next_map();
95 } else {
96 update_object_map();
97 send_remove_map();
98 }
99 break;
100 case STATE_INVALIDATE_NEXT_MAP:
101 send_remove_map();
102 break;
103 case STATE_REMOVE_MAP:
104 finished = true;
105 break;
106 default:
107 assert(false);
108 break;
109 }
110 return finished;
111}
112
113void SnapshotRemoveRequest::send_load_map() {
114 CephContext *cct = m_image_ctx.cct;
115 std::string snap_oid(ObjectMap<>::object_map_name(m_image_ctx.id, m_snap_id));
116 ldout(cct, 5) << this << " " << __func__ << ": snap_oid=" << snap_oid
117 << dendl;
118 m_state = STATE_LOAD_MAP;
119
120 librados::ObjectReadOperation op;
121 cls_client::object_map_load_start(&op);
122
123 librados::AioCompletion *rados_completion = create_callback_completion();
124 int r = m_image_ctx.md_ctx.aio_operate(snap_oid, rados_completion, &op,
125 &m_out_bl);
126 assert(r == 0);
127 rados_completion->release();
128}
129
130void SnapshotRemoveRequest::send_remove_snapshot() {
131 CephContext *cct = m_image_ctx.cct;
132 std::string oid(ObjectMap<>::object_map_name(m_image_ctx.id, m_next_snap_id));
133 ldout(cct, 5) << this << " " << __func__ << ": oid=" << oid << dendl;
134 m_state = STATE_REMOVE_SNAPSHOT;
135
136 librados::ObjectWriteOperation op;
137 if (m_next_snap_id == CEPH_NOSNAP) {
138 rados::cls::lock::assert_locked(&op, RBD_LOCK_NAME, LOCK_EXCLUSIVE, "", "");
139 }
140 cls_client::object_map_snap_remove(&op, m_snap_object_map);
141
142 librados::AioCompletion *rados_completion = create_callback_completion();
143 int r = m_image_ctx.md_ctx.aio_operate(oid, rados_completion, &op);
144 assert(r == 0);
145 rados_completion->release();
146}
147
148void SnapshotRemoveRequest::send_invalidate_next_map() {
149 assert(m_image_ctx.owner_lock.is_locked());
150 assert(m_image_ctx.snap_lock.is_wlocked());
151
152 CephContext *cct = m_image_ctx.cct;
153 ldout(cct, 5) << this << " " << __func__ << dendl;
154 m_state = STATE_INVALIDATE_NEXT_MAP;
155
156 InvalidateRequest<> *req = new InvalidateRequest<>(m_image_ctx,
157 m_next_snap_id, true,
158 create_callback_context());
159 req->send();
160}
161
162void SnapshotRemoveRequest::send_remove_map() {
163 CephContext *cct = m_image_ctx.cct;
164 std::string oid(ObjectMap<>::object_map_name(m_image_ctx.id, m_snap_id));
165 ldout(cct, 5) << this << " " << __func__ << ": oid=" << oid << dendl;
166 m_state = STATE_REMOVE_MAP;
167
168 librados::ObjectWriteOperation op;
169 op.remove();
170
171 librados::AioCompletion *rados_completion = create_callback_completion();
172 int r = m_image_ctx.md_ctx.aio_operate(oid, rados_completion, &op);
173 assert(r == 0);
174 rados_completion->release();
175}
176
177void SnapshotRemoveRequest::compute_next_snap_id() {
178 assert(m_image_ctx.snap_lock.is_locked());
179
180 m_next_snap_id = CEPH_NOSNAP;
181 std::map<librados::snap_t, SnapInfo>::const_iterator it =
182 m_image_ctx.snap_info.find(m_snap_id);
183 assert(it != m_image_ctx.snap_info.end());
184
185 ++it;
186 if (it != m_image_ctx.snap_info.end()) {
187 m_next_snap_id = it->first;
188 }
189}
190
191void SnapshotRemoveRequest::update_object_map() {
192 RWLock::RLocker snap_locker(m_image_ctx.snap_lock);
193 RWLock::WLocker object_map_locker(m_image_ctx.object_map_lock);
194 if (m_next_snap_id == m_image_ctx.snap_id && m_next_snap_id == CEPH_NOSNAP) {
195 CephContext *cct = m_image_ctx.cct;
196 ldout(cct, 5) << this << " " << __func__ << dendl;
b32b8144
FG
197
198 auto it = m_object_map.begin();
199 auto end_it = m_object_map.end();
200 auto snap_it = m_snap_object_map.begin();
201 uint64_t i = 0;
202 for (; it != end_it; ++it) {
203 if (*it == OBJECT_EXISTS_CLEAN &&
7c673cae 204 (i >= m_snap_object_map.size() ||
b32b8144
FG
205 *snap_it == OBJECT_EXISTS)) {
206 *it = OBJECT_EXISTS;
207 }
208 if (i < m_snap_object_map.size()) {
209 ++snap_it;
7c673cae 210 }
b32b8144 211 ++i;
7c673cae
FG
212 }
213 }
214}
215
216} // namespace object_map
217} // namespace librbd