]>
Commit | Line | Data |
---|---|---|
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 | |
91327a77 AA |
14 | #define dout_prefix *_dout << "librbd::object_map::SnapshotRemoveRequest: " \ |
15 | << this << " " << __func__ << ": " | |
7c673cae FG |
16 | |
17 | namespace librbd { | |
18 | namespace object_map { | |
19 | ||
7c673cae | 20 | void SnapshotRemoveRequest::send() { |
9f95a23c TL |
21 | ceph_assert(ceph_mutex_is_locked(m_image_ctx.owner_lock)); |
22 | ceph_assert(ceph_mutex_is_wlocked(m_image_ctx.image_lock)); | |
7c673cae FG |
23 | |
24 | if ((m_image_ctx.features & RBD_FEATURE_FAST_DIFF) != 0) { | |
91327a77 | 25 | int r = m_image_ctx.get_flags(m_snap_id, &m_flags); |
11fdf7f2 | 26 | ceph_assert(r == 0); |
7c673cae | 27 | |
91327a77 AA |
28 | compute_next_snap_id(); |
29 | load_map(); | |
7c673cae | 30 | } else { |
91327a77 | 31 | remove_map(); |
7c673cae FG |
32 | } |
33 | } | |
34 | ||
91327a77 | 35 | void SnapshotRemoveRequest::load_map() { |
7c673cae FG |
36 | CephContext *cct = m_image_ctx.cct; |
37 | std::string snap_oid(ObjectMap<>::object_map_name(m_image_ctx.id, m_snap_id)); | |
91327a77 | 38 | ldout(cct, 5) << "snap_oid=" << snap_oid << dendl; |
7c673cae FG |
39 | |
40 | librados::ObjectReadOperation op; | |
41 | cls_client::object_map_load_start(&op); | |
42 | ||
91327a77 AA |
43 | auto rados_completion = librbd::util::create_rados_callback< |
44 | SnapshotRemoveRequest, &SnapshotRemoveRequest::handle_load_map>(this); | |
7c673cae FG |
45 | int r = m_image_ctx.md_ctx.aio_operate(snap_oid, rados_completion, &op, |
46 | &m_out_bl); | |
11fdf7f2 | 47 | ceph_assert(r == 0); |
7c673cae FG |
48 | rados_completion->release(); |
49 | } | |
50 | ||
91327a77 AA |
51 | void SnapshotRemoveRequest::handle_load_map(int r) { |
52 | CephContext *cct = m_image_ctx.cct; | |
53 | ldout(cct, 5) << "r=" << r << dendl; | |
54 | ||
55 | if (r == 0) { | |
11fdf7f2 | 56 | auto it = m_out_bl.cbegin(); |
91327a77 AA |
57 | r = cls_client::object_map_load_finish(&it, &m_snap_object_map); |
58 | } | |
59 | if (r == -ENOENT) { | |
60 | // implies we have already deleted this snapshot and handled the | |
61 | // necessary fast-diff cleanup | |
62 | complete(0); | |
63 | return; | |
64 | } else if (r < 0) { | |
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; | |
68 | ||
9f95a23c TL |
69 | std::shared_lock owner_locker{m_image_ctx.owner_lock}; |
70 | std::unique_lock image_locker{m_image_ctx.image_lock}; | |
91327a77 AA |
71 | invalidate_next_map(); |
72 | return; | |
73 | } | |
74 | ||
75 | remove_snapshot(); | |
76 | } | |
77 | ||
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. | |
9f95a23c TL |
82 | std::shared_lock owner_locker{m_image_ctx.owner_lock}; |
83 | std::unique_lock image_locker{m_image_ctx.image_lock}; | |
91327a77 AA |
84 | invalidate_next_map(); |
85 | return; | |
86 | } | |
87 | ||
7c673cae FG |
88 | CephContext *cct = m_image_ctx.cct; |
89 | std::string oid(ObjectMap<>::object_map_name(m_image_ctx.id, m_next_snap_id)); | |
91327a77 | 90 | ldout(cct, 5) << "oid=" << oid << dendl; |
7c673cae FG |
91 | |
92 | librados::ObjectWriteOperation op; | |
93 | if (m_next_snap_id == CEPH_NOSNAP) { | |
f67539c2 | 94 | rados::cls::lock::assert_locked(&op, RBD_LOCK_NAME, ClsLockType::EXCLUSIVE, "", ""); |
7c673cae FG |
95 | } |
96 | cls_client::object_map_snap_remove(&op, m_snap_object_map); | |
97 | ||
91327a77 AA |
98 | auto rados_completion = librbd::util::create_rados_callback< |
99 | SnapshotRemoveRequest, | |
100 | &SnapshotRemoveRequest::handle_remove_snapshot>(this); | |
7c673cae | 101 | int r = m_image_ctx.md_ctx.aio_operate(oid, rados_completion, &op); |
11fdf7f2 | 102 | ceph_assert(r == 0); |
7c673cae FG |
103 | rados_completion->release(); |
104 | } | |
105 | ||
91327a77 AA |
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, | |
111 | m_next_snap_id)); | |
112 | lderr(cct) << "failed to remove object map snapshot " << oid << ": " | |
113 | << cpp_strerror(r) << dendl; | |
114 | ||
9f95a23c TL |
115 | std::shared_lock owner_locker{m_image_ctx.owner_lock}; |
116 | std::unique_lock image_locker{m_image_ctx.image_lock}; | |
91327a77 AA |
117 | invalidate_next_map(); |
118 | return; | |
119 | } | |
120 | ||
9f95a23c | 121 | std::shared_lock image_locker{m_image_ctx.image_lock}; |
91327a77 AA |
122 | update_object_map(); |
123 | remove_map(); | |
124 | } | |
125 | ||
126 | void SnapshotRemoveRequest::invalidate_next_map() { | |
9f95a23c TL |
127 | ceph_assert(ceph_mutex_is_locked(m_image_ctx.owner_lock)); |
128 | ceph_assert(ceph_mutex_is_wlocked(m_image_ctx.image_lock)); | |
7c673cae FG |
129 | |
130 | CephContext *cct = m_image_ctx.cct; | |
91327a77 | 131 | ldout(cct, 5) << dendl; |
7c673cae | 132 | |
91327a77 AA |
133 | auto ctx = librbd::util::create_context_callback< |
134 | SnapshotRemoveRequest, | |
135 | &SnapshotRemoveRequest::handle_invalidate_next_map>(this); | |
7c673cae | 136 | InvalidateRequest<> *req = new InvalidateRequest<>(m_image_ctx, |
91327a77 | 137 | m_next_snap_id, true, ctx); |
7c673cae FG |
138 | req->send(); |
139 | } | |
140 | ||
91327a77 AA |
141 | void SnapshotRemoveRequest::handle_invalidate_next_map(int r) { |
142 | CephContext *cct = m_image_ctx.cct; | |
143 | ldout(cct, 5) << "r=" << r << dendl; | |
11fdf7f2 TL |
144 | |
145 | if (r < 0) { | |
146 | std::string oid(ObjectMap<>::object_map_name(m_image_ctx.id, | |
147 | m_next_snap_id)); | |
148 | lderr(cct) << "failed to invalidate object map " << oid << ": " | |
149 | << cpp_strerror(r) << dendl; | |
150 | complete(r); | |
151 | return; | |
152 | } | |
91327a77 AA |
153 | |
154 | remove_map(); | |
155 | } | |
156 | ||
157 | void SnapshotRemoveRequest::remove_map() { | |
7c673cae FG |
158 | CephContext *cct = m_image_ctx.cct; |
159 | std::string oid(ObjectMap<>::object_map_name(m_image_ctx.id, m_snap_id)); | |
91327a77 | 160 | ldout(cct, 5) << "oid=" << oid << dendl; |
7c673cae FG |
161 | |
162 | librados::ObjectWriteOperation op; | |
163 | op.remove(); | |
164 | ||
91327a77 AA |
165 | auto rados_completion = librbd::util::create_rados_callback< |
166 | SnapshotRemoveRequest, &SnapshotRemoveRequest::handle_remove_map>(this); | |
7c673cae | 167 | int r = m_image_ctx.md_ctx.aio_operate(oid, rados_completion, &op); |
11fdf7f2 | 168 | ceph_assert(r == 0); |
7c673cae FG |
169 | rados_completion->release(); |
170 | } | |
171 | ||
91327a77 AA |
172 | void SnapshotRemoveRequest::handle_remove_map(int r) { |
173 | CephContext *cct = m_image_ctx.cct; | |
174 | ldout(cct, 5) << "r=" << r << dendl; | |
175 | ||
176 | if (r < 0 && r != -ENOENT) { | |
177 | std::string oid(ObjectMap<>::object_map_name(m_image_ctx.id, m_snap_id)); | |
178 | lderr(cct) << "failed to remove object map " << oid << ": " | |
179 | << cpp_strerror(r) << dendl; | |
180 | complete(r); | |
181 | return; | |
182 | } | |
183 | ||
184 | complete(0); | |
185 | } | |
186 | ||
7c673cae | 187 | void SnapshotRemoveRequest::compute_next_snap_id() { |
9f95a23c | 188 | ceph_assert(ceph_mutex_is_locked(m_image_ctx.image_lock)); |
7c673cae FG |
189 | |
190 | m_next_snap_id = CEPH_NOSNAP; | |
191 | std::map<librados::snap_t, SnapInfo>::const_iterator it = | |
192 | m_image_ctx.snap_info.find(m_snap_id); | |
11fdf7f2 | 193 | ceph_assert(it != m_image_ctx.snap_info.end()); |
7c673cae FG |
194 | |
195 | ++it; | |
196 | if (it != m_image_ctx.snap_info.end()) { | |
197 | m_next_snap_id = it->first; | |
198 | } | |
199 | } | |
200 | ||
201 | void SnapshotRemoveRequest::update_object_map() { | |
9f95a23c TL |
202 | assert(ceph_mutex_is_locked(m_image_ctx.image_lock)); |
203 | std::unique_lock object_map_locker{*m_object_map_lock}; | |
7c673cae FG |
204 | if (m_next_snap_id == m_image_ctx.snap_id && m_next_snap_id == CEPH_NOSNAP) { |
205 | CephContext *cct = m_image_ctx.cct; | |
91327a77 AA |
206 | ldout(cct, 5) << dendl; |
207 | ||
b32b8144 FG |
208 | auto it = m_object_map.begin(); |
209 | auto end_it = m_object_map.end(); | |
210 | auto snap_it = m_snap_object_map.begin(); | |
211 | uint64_t i = 0; | |
212 | for (; it != end_it; ++it) { | |
213 | if (*it == OBJECT_EXISTS_CLEAN && | |
7c673cae | 214 | (i >= m_snap_object_map.size() || |
b32b8144 FG |
215 | *snap_it == OBJECT_EXISTS)) { |
216 | *it = OBJECT_EXISTS; | |
217 | } | |
218 | if (i < m_snap_object_map.size()) { | |
219 | ++snap_it; | |
7c673cae | 220 | } |
b32b8144 | 221 | ++i; |
7c673cae FG |
222 | } |
223 | } | |
224 | } | |
225 | ||
226 | } // namespace object_map | |
227 | } // namespace librbd |