]> git.proxmox.com Git - ceph.git/blame - ceph/src/osd/SnapMapper.cc
update sources to 12.2.7
[ceph.git] / ceph / src / osd / SnapMapper.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 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 *
13 */
14
15#include "SnapMapper.h"
16
17#define dout_context cct
18#define dout_subsys ceph_subsys_osd
19#undef dout_prefix
20#define dout_prefix *_dout << "snap_mapper."
21
22using std::string;
23
24const string SnapMapper::MAPPING_PREFIX = "MAP_";
25const string SnapMapper::OBJECT_PREFIX = "OBJ_";
26
27int OSDriver::get_keys(
28 const std::set<std::string> &keys,
29 std::map<std::string, bufferlist> *out)
30{
31 return os->omap_get_values(cid, hoid, keys, out);
32}
33
34int OSDriver::get_next(
35 const std::string &key,
36 pair<std::string, bufferlist> *next)
37{
38 ObjectMap::ObjectMapIterator iter =
39 os->get_omap_iterator(cid, hoid);
40 if (!iter) {
41 ceph_abort();
42 return -EINVAL;
43 }
44 iter->upper_bound(key);
45 if (iter->valid()) {
46 if (next)
47 *next = make_pair(iter->key(), iter->value());
48 return 0;
49 } else {
50 return -ENOENT;
51 }
52}
53
54struct Mapping {
55 snapid_t snap;
56 hobject_t hoid;
57 explicit Mapping(const pair<snapid_t, hobject_t> &in)
58 : snap(in.first), hoid(in.second) {}
59 Mapping() : snap(0) {}
60 void encode(bufferlist &bl) const {
61 ENCODE_START(1, 1, bl);
62 ::encode(snap, bl);
63 ::encode(hoid, bl);
64 ENCODE_FINISH(bl);
65 }
66 void decode(bufferlist::iterator &bl) {
67 DECODE_START(1, bl);
68 ::decode(snap, bl);
69 ::decode(hoid, bl);
70 DECODE_FINISH(bl);
71 }
72};
73WRITE_CLASS_ENCODER(Mapping)
74
75string SnapMapper::get_prefix(snapid_t snap)
76{
77 char buf[100];
78 int len = snprintf(
79 buf, sizeof(buf),
80 "%.*X_", (int)(sizeof(snap)*2),
81 static_cast<unsigned>(snap));
82 return MAPPING_PREFIX + string(buf, len);
83}
84
85string SnapMapper::to_raw_key(
86 const pair<snapid_t, hobject_t> &in)
87{
88 return get_prefix(in.first) + shard_prefix + in.second.to_str();
89}
90
91pair<string, bufferlist> SnapMapper::to_raw(
92 const pair<snapid_t, hobject_t> &in)
93{
94 bufferlist bl;
95 ::encode(Mapping(in), bl);
96 return make_pair(
97 to_raw_key(in),
98 bl);
99}
100
101pair<snapid_t, hobject_t> SnapMapper::from_raw(
102 const pair<std::string, bufferlist> &image)
103{
104 Mapping map;
105 bufferlist bl(image.second);
106 bufferlist::iterator bp(bl.begin());
107 ::decode(map, bp);
108 return make_pair(map.snap, map.hoid);
109}
110
111bool SnapMapper::is_mapping(const string &to_test)
112{
113 return to_test.substr(0, MAPPING_PREFIX.size()) == MAPPING_PREFIX;
114}
115
116string SnapMapper::to_object_key(const hobject_t &hoid)
117{
118 return OBJECT_PREFIX + shard_prefix + hoid.to_str();
119}
120
121void SnapMapper::object_snaps::encode(bufferlist &bl) const
122{
123 ENCODE_START(1, 1, bl);
124 ::encode(oid, bl);
125 ::encode(snaps, bl);
126 ENCODE_FINISH(bl);
127}
128
129void SnapMapper::object_snaps::decode(bufferlist::iterator &bl)
130{
131 DECODE_START(1, bl);
132 ::decode(oid, bl);
133 ::decode(snaps, bl);
134 DECODE_FINISH(bl);
135}
136
137int SnapMapper::get_snaps(
138 const hobject_t &oid,
139 object_snaps *out)
140{
141 assert(check(oid));
142 set<string> keys;
143 map<string, bufferlist> got;
144 keys.insert(to_object_key(oid));
145 int r = backend.get_keys(keys, &got);
146 if (r < 0)
147 return r;
148 if (got.empty())
149 return -ENOENT;
150 if (out) {
151 bufferlist::iterator bp = got.begin()->second.begin();
152 ::decode(*out, bp);
153 dout(20) << __func__ << " " << oid << " " << out->snaps << dendl;
28e407b8
AA
154 if (out->snaps.empty()) {
155 dout(1) << __func__ << " " << oid << " empty snapset" << dendl;
156 assert(!cct->_conf->osd_debug_verify_snaps);
157 }
7c673cae
FG
158 } else {
159 dout(20) << __func__ << " " << oid << " (out == NULL)" << dendl;
160 }
161 return 0;
162}
163
164void SnapMapper::clear_snaps(
165 const hobject_t &oid,
166 MapCacher::Transaction<std::string, bufferlist> *t)
167{
168 dout(20) << __func__ << " " << oid << dendl;
169 assert(check(oid));
170 set<string> to_remove;
171 to_remove.insert(to_object_key(oid));
31f18b77
FG
172 if (g_conf->subsys.should_gather(ceph_subsys_osd, 20)) {
173 for (auto& i : to_remove) {
174 dout(20) << __func__ << " rm " << i << dendl;
175 }
176 }
7c673cae
FG
177 backend.remove_keys(to_remove, t);
178}
179
180void SnapMapper::set_snaps(
181 const hobject_t &oid,
182 const object_snaps &in,
183 MapCacher::Transaction<std::string, bufferlist> *t)
184{
185 assert(check(oid));
186 map<string, bufferlist> to_set;
187 bufferlist bl;
188 ::encode(in, bl);
189 to_set[to_object_key(oid)] = bl;
190 dout(20) << __func__ << " " << oid << " " << in.snaps << dendl;
31f18b77
FG
191 if (g_conf->subsys.should_gather(ceph_subsys_osd, 20)) {
192 for (auto& i : to_set) {
193 dout(20) << __func__ << " set " << i.first << dendl;
194 }
195 }
7c673cae
FG
196 backend.set_keys(to_set, t);
197}
198
199int SnapMapper::update_snaps(
200 const hobject_t &oid,
201 const set<snapid_t> &new_snaps,
202 const set<snapid_t> *old_snaps_check,
203 MapCacher::Transaction<std::string, bufferlist> *t)
204{
205 dout(20) << __func__ << " " << oid << " " << new_snaps
206 << " was " << (old_snaps_check ? *old_snaps_check : set<snapid_t>())
207 << dendl;
208 assert(check(oid));
209 if (new_snaps.empty())
210 return remove_oid(oid, t);
211
212 object_snaps out;
213 int r = get_snaps(oid, &out);
214 if (r < 0)
215 return r;
216 if (old_snaps_check)
217 assert(out.snaps == *old_snaps_check);
218
219 object_snaps in(oid, new_snaps);
220 set_snaps(oid, in, t);
221
222 set<string> to_remove;
223 for (set<snapid_t>::iterator i = out.snaps.begin();
224 i != out.snaps.end();
225 ++i) {
226 if (!new_snaps.count(*i)) {
227 to_remove.insert(to_raw_key(make_pair(*i, oid)));
228 }
229 }
31f18b77
FG
230 if (g_conf->subsys.should_gather(ceph_subsys_osd, 20)) {
231 for (auto& i : to_remove) {
232 dout(20) << __func__ << " rm " << i << dendl;
233 }
234 }
7c673cae
FG
235 backend.remove_keys(to_remove, t);
236 return 0;
237}
238
239void SnapMapper::add_oid(
240 const hobject_t &oid,
241 const set<snapid_t>& snaps,
242 MapCacher::Transaction<std::string, bufferlist> *t)
243{
244 dout(20) << __func__ << " " << oid << " " << snaps << dendl;
94b18763 245 assert(!snaps.empty());
7c673cae
FG
246 assert(check(oid));
247 {
248 object_snaps out;
249 int r = get_snaps(oid, &out);
94b18763
FG
250 if (r != -ENOENT) {
251 derr << __func__ << " found existing snaps mapped on " << oid
252 << ", removing" << dendl;
253 assert(!cct->_conf->osd_debug_verify_snaps);
254 remove_oid(oid, t);
255 }
7c673cae
FG
256 }
257
258 object_snaps _snaps(oid, snaps);
259 set_snaps(oid, _snaps, t);
260
261 map<string, bufferlist> to_add;
262 for (set<snapid_t>::iterator i = snaps.begin();
263 i != snaps.end();
264 ++i) {
265 to_add.insert(to_raw(make_pair(*i, oid)));
266 }
31f18b77
FG
267 if (g_conf->subsys.should_gather(ceph_subsys_osd, 20)) {
268 for (auto& i : to_add) {
269 dout(20) << __func__ << " set " << i.first << dendl;
270 }
271 }
7c673cae
FG
272 backend.set_keys(to_add, t);
273}
274
275int SnapMapper::get_next_objects_to_trim(
276 snapid_t snap,
277 unsigned max,
278 vector<hobject_t> *out)
279{
280 assert(out);
281 assert(out->empty());
282 int r = 0;
283 for (set<string>::iterator i = prefixes.begin();
284 i != prefixes.end() && out->size() < max && r == 0;
285 ++i) {
286 string prefix(get_prefix(snap) + *i);
287 string pos = prefix;
288 while (out->size() < max) {
289 pair<string, bufferlist> next;
290 r = backend.get_next(pos, &next);
31f18b77
FG
291 dout(20) << __func__ << " get_next(" << pos << ") returns " << r
292 << " " << next << dendl;
7c673cae
FG
293 if (r != 0) {
294 break; // Done
295 }
296
297 if (next.first.substr(0, prefix.size()) !=
298 prefix) {
299 break; // Done with this prefix
300 }
301
302 assert(is_mapping(next.first));
303
31f18b77 304 dout(20) << __func__ << " " << next.first << dendl;
7c673cae
FG
305 pair<snapid_t, hobject_t> next_decoded(from_raw(next));
306 assert(next_decoded.first == snap);
307 assert(check(next_decoded.second));
308
309 out->push_back(next_decoded.second);
310 pos = next.first;
311 }
312 }
313 if (out->size() == 0) {
314 return -ENOENT;
315 } else {
316 return 0;
317 }
318}
319
320
321int SnapMapper::remove_oid(
322 const hobject_t &oid,
323 MapCacher::Transaction<std::string, bufferlist> *t)
324{
325 dout(20) << __func__ << " " << oid << dendl;
326 assert(check(oid));
327 return _remove_oid(oid, t);
328}
329
330int SnapMapper::_remove_oid(
331 const hobject_t &oid,
332 MapCacher::Transaction<std::string, bufferlist> *t)
333{
334 dout(20) << __func__ << " " << oid << dendl;
335 object_snaps out;
336 int r = get_snaps(oid, &out);
337 if (r < 0)
338 return r;
339
340 clear_snaps(oid, t);
341
342 set<string> to_remove;
343 for (set<snapid_t>::iterator i = out.snaps.begin();
344 i != out.snaps.end();
345 ++i) {
346 to_remove.insert(to_raw_key(make_pair(*i, oid)));
347 }
31f18b77
FG
348 if (g_conf->subsys.should_gather(ceph_subsys_osd, 20)) {
349 for (auto& i : to_remove) {
350 dout(20) << __func__ << " rm " << i << dendl;
351 }
352 }
7c673cae
FG
353 backend.remove_keys(to_remove, t);
354 return 0;
355}
356
357int SnapMapper::get_snaps(
358 const hobject_t &oid,
359 std::set<snapid_t> *snaps)
360{
361 assert(check(oid));
362 object_snaps out;
363 int r = get_snaps(oid, &out);
364 if (r < 0)
365 return r;
366 if (snaps)
367 snaps->swap(out.snaps);
368 return 0;
369}