]> git.proxmox.com Git - ceph.git/blame - ceph/src/osd/SnapMapper.h
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / osd / SnapMapper.h
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) 2013 Inktank Storage, Inc.
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#ifndef SNAPMAPPER_H
16#define SNAPMAPPER_H
17
1e59de90 18#include <cstring>
7c673cae 19#include <set>
1e59de90 20#include <string>
7c673cae 21#include <utility>
7c673cae 22
7c673cae 23#include "common/hobject.h"
1e59de90
TL
24#include "common/map_cacher.hpp"
25#ifdef WITH_SEASTAR
26# include "crimson/os/futurized_store.h"
27# include "crimson/os/futurized_collection.h"
28#endif
7c673cae
FG
29#include "include/buffer.h"
30#include "include/encoding.h"
31#include "include/object.h"
32#include "os/ObjectStore.h"
9f95a23c 33#include "osd/OSDMap.h"
1e59de90 34#include "osd/SnapMapReaderI.h"
7c673cae 35
f67539c2 36class OSDriver : public MapCacher::StoreDriver<std::string, ceph::buffer::list> {
1e59de90
TL
37#ifdef WITH_SEASTAR
38 using ObjectStoreT = crimson::os::FuturizedStore::Shard;
39 using CollectionHandleT = ObjectStoreT::CollectionRef;
40#else
41 using ObjectStoreT = ObjectStore;
42 using CollectionHandleT = ObjectStoreT::CollectionHandle;
43#endif
44
45 ObjectStoreT *os;
46 CollectionHandleT ch;
7c673cae
FG
47 ghobject_t hoid;
48
49public:
f67539c2 50 class OSTransaction : public MapCacher::Transaction<std::string, ceph::buffer::list> {
7c673cae
FG
51 friend class OSDriver;
52 coll_t cid;
53 ghobject_t hoid;
1e59de90 54 ceph::os::Transaction *t;
7c673cae 55 OSTransaction(
11fdf7f2 56 const coll_t &cid,
7c673cae 57 const ghobject_t &hoid,
1e59de90 58 ceph::os::Transaction *t)
7c673cae
FG
59 : cid(cid), hoid(hoid), t(t) {}
60 public:
61 void set_keys(
f67539c2 62 const std::map<std::string, ceph::buffer::list> &to_set) override {
7c673cae
FG
63 t->omap_setkeys(cid, hoid, to_set);
64 }
65 void remove_keys(
66 const std::set<std::string> &to_remove) override {
67 t->omap_rmkeys(cid, hoid, to_remove);
68 }
69 void add_callback(
70 Context *c) override {
71 t->register_on_applied(c);
72 }
73 };
74
75 OSTransaction get_transaction(
1e59de90
TL
76 ceph::os::Transaction *t) const {
77 return OSTransaction(ch->get_cid(), hoid, t);
7c673cae
FG
78 }
79
1e59de90
TL
80#ifndef WITH_SEASTAR
81 OSDriver(ObjectStoreT *os, const coll_t& cid, const ghobject_t &hoid) :
82 OSDriver(os, os->open_collection(cid), hoid) {}
83#endif
84 OSDriver(ObjectStoreT *os, CollectionHandleT ch, const ghobject_t &hoid) :
11fdf7f2 85 os(os),
1e59de90
TL
86 ch(ch),
87 hoid(hoid) {}
88
7c673cae
FG
89 int get_keys(
90 const std::set<std::string> &keys,
f67539c2 91 std::map<std::string, ceph::buffer::list> *out) override;
7c673cae
FG
92 int get_next(
93 const std::string &key,
f67539c2 94 std::pair<std::string, ceph::buffer::list> *next) override;
1e59de90
TL
95 int get_next_or_current(
96 const std::string &key,
97 std::pair<std::string, ceph::buffer::list> *next_or_current) override;
7c673cae
FG
98};
99
100/**
101 * SnapMapper
102 *
103 * Manages two mappings:
104 * 1) hobject_t -> {snapid}
105 * 2) snapid -> {hobject_t}
106 *
107 * We accomplish this using two sets of keys:
108 * 1) OBJECT_PREFIX + obj.str() -> encoding of object_snaps
f67539c2 109 * 2) MAPPING_PREFIX + poolid + snapid_t + obj.str() -> encoding of std::pair<snapid_t, obj>
7c673cae
FG
110 *
111 * The on disk strings and encodings are implemented in to_raw, to_raw_key,
112 * from_raw, to_object_key.
113 *
114 * The object -> {snapid} mapping is primarily included so that the
115 * SnapMapper state can be verified against the external PG state during
116 * scrub etc.
117 *
118 * The 2) mapping is arranged such that all objects in a particular
119 * snap will sort together, and so that all objects in a pg for a
120 * particular snap will group under up to 8 prefixes.
121 */
1e59de90
TL
122class SnapMapper : public Scrub::SnapMapReaderI {
123 friend class MapperVerifier; // unit-test support
124 friend class DirectMapper; // unit-test support
7c673cae
FG
125public:
126 CephContext* cct;
127 struct object_snaps {
128 hobject_t oid;
129 std::set<snapid_t> snaps;
130 object_snaps(hobject_t oid, const std::set<snapid_t> &snaps)
131 : oid(oid), snaps(snaps) {}
132 object_snaps() {}
f67539c2
TL
133 void encode(ceph::buffer::list &bl) const;
134 void decode(ceph::buffer::list::const_iterator &bp);
7c673cae
FG
135 };
136
9f95a23c
TL
137 struct Mapping {
138 snapid_t snap;
139 hobject_t hoid;
f67539c2 140 explicit Mapping(const std::pair<snapid_t, hobject_t> &in)
9f95a23c
TL
141 : snap(in.first), hoid(in.second) {}
142 Mapping() : snap(0) {}
f67539c2 143 void encode(ceph::buffer::list &bl) const {
9f95a23c
TL
144 ENCODE_START(1, 1, bl);
145 encode(snap, bl);
146 encode(hoid, bl);
147 ENCODE_FINISH(bl);
148 }
f67539c2 149 void decode(ceph::buffer::list::const_iterator &bl) {
9f95a23c
TL
150 DECODE_START(1, bl);
151 decode(snap, bl);
152 decode(hoid, bl);
153 DECODE_FINISH(bl);
154 }
155 };
7c673cae 156
9f95a23c 157 static const std::string LEGACY_MAPPING_PREFIX;
7c673cae
FG
158 static const std::string MAPPING_PREFIX;
159 static const std::string OBJECT_PREFIX;
9f95a23c
TL
160 static const char *PURGED_SNAP_EPOCH_PREFIX;
161 static const char *PURGED_SNAP_PREFIX;
162
1e59de90 163#ifndef WITH_SEASTAR
9f95a23c
TL
164 struct Scrubber {
165 CephContext *cct;
166 ObjectStore *store;
167 ObjectStore::CollectionHandle ch;
168 ghobject_t mapping_hoid;
169 ghobject_t purged_snaps_hoid;
170
171 ObjectMap::ObjectMapIterator psit;
172 int64_t pool;
173 snapid_t begin, end;
174
175 bool _parse_p(); ///< advance the purged_snaps pointer
176
177 ObjectMap::ObjectMapIterator mapit;
178 Mapping mapping;
179 shard_id_t shard;
180
181 bool _parse_m(); ///< advance the (object) mapper pointer
182
f67539c2 183 std::vector<std::tuple<int64_t, snapid_t, uint32_t, shard_id_t>> stray;
7c673cae 184
9f95a23c
TL
185 Scrubber(
186 CephContext *cct,
187 ObjectStore *store,
188 ObjectStore::CollectionHandle& ch,
189 ghobject_t mapping_hoid,
190 ghobject_t purged_snaps_hoid)
191 : cct(cct),
192 store(store),
193 ch(ch),
194 mapping_hoid(mapping_hoid),
195 purged_snaps_hoid(purged_snaps_hoid) {}
196
197 void run();
198 };
199
2a845540
TL
200 static std::string convert_legacy_key(
201 const std::string& old_key,
202 const bufferlist& value);
203
9f95a23c
TL
204 static int convert_legacy(
205 CephContext *cct,
206 ObjectStore *store,
207 ObjectStore::CollectionHandle& ch,
208 ghobject_t hoid,
209 unsigned max);
1e59de90 210#endif
9f95a23c
TL
211
212 static void record_purged_snaps(
213 CephContext *cct,
1e59de90
TL
214 OSDriver& backend,
215 OSDriver::OSTransaction&& txn,
f67539c2 216 std::map<epoch_t,mempool::osdmap::map<int64_t,snap_interval_set_t>> purged_snaps);
9f95a23c
TL
217
218private:
219 static int _lookup_purged_snap(
220 CephContext *cct,
1e59de90 221 OSDriver& backend,
9f95a23c
TL
222 int64_t pool, snapid_t snap,
223 snapid_t *begin, snapid_t *end);
224 static void make_purged_snap_key_value(
225 int64_t pool, snapid_t begin,
f67539c2
TL
226 snapid_t end, std::map<std::string,ceph::buffer::list> *m);
227 static std::string make_purged_snap_key(int64_t pool, snapid_t last);
9f95a23c 228
1e59de90
TL
229 // note: marked 'mutable', as functions as a cache and used in some 'const'
230 // functions.
231 mutable MapCacher::MapCacher<std::string, ceph::buffer::list> backend;
9f95a23c
TL
232
233 static std::string get_legacy_prefix(snapid_t snap);
234 std::string to_legacy_raw_key(
235 const std::pair<snapid_t, hobject_t> &to_map);
236 static bool is_legacy_mapping(const std::string &to_test);
7c673cae 237
9f95a23c 238 static std::string get_prefix(int64_t pool, snapid_t snap);
7c673cae 239 std::string to_raw_key(
1e59de90
TL
240 const std::pair<snapid_t, hobject_t> &to_map) const;
241
242 std::string to_raw_key(snapid_t snap, const hobject_t& clone) const;
7c673cae 243
f67539c2 244 std::pair<std::string, ceph::buffer::list> to_raw(
1e59de90 245 const std::pair<snapid_t, hobject_t> &to_map) const;
7c673cae
FG
246
247 static bool is_mapping(const std::string &to_test);
248
9f95a23c 249 static std::pair<snapid_t, hobject_t> from_raw(
f67539c2 250 const std::pair<std::string, ceph::buffer::list> &image);
7c673cae 251
1e59de90
TL
252 static std::pair<snapid_t, hobject_t> from_raw(
253 const ceph::buffer::list& image);
254
255 std::string to_object_key(const hobject_t &hoid) const;
7c673cae 256
1e59de90
TL
257 int get_snaps(const hobject_t &oid, object_snaps *out) const;
258
259 std::set<std::string> to_raw_keys(
260 const hobject_t &clone,
261 const std::set<snapid_t> &snaps) const;
7c673cae
FG
262
263 void set_snaps(
264 const hobject_t &oid,
265 const object_snaps &out,
f67539c2 266 MapCacher::Transaction<std::string, ceph::buffer::list> *t);
7c673cae
FG
267
268 void clear_snaps(
269 const hobject_t &oid,
f67539c2 270 MapCacher::Transaction<std::string, ceph::buffer::list> *t);
7c673cae
FG
271
272 // True if hoid belongs in this mapping based on mask_bits and match
11fdf7f2 273 bool check(const hobject_t &hoid) const;
7c673cae
FG
274
275 int _remove_oid(
276 const hobject_t &oid, ///< [in] oid to remove
f67539c2 277 MapCacher::Transaction<std::string, ceph::buffer::list> *t ///< [out] transaction
7c673cae
FG
278 );
279
1e59de90
TL
280 /// Get snaps (as an 'object_snaps' object) for oid
281 tl::expected<object_snaps, SnapMapReaderI::result_t> get_snaps_common(
282 const hobject_t &hoid) const;
283
284 public:
f67539c2 285 static std::string make_shard_prefix(shard_id_t shard) {
7c673cae 286 if (shard == shard_id_t::NO_SHARD)
f67539c2 287 return std::string();
7c673cae
FG
288 char buf[20];
289 int r = snprintf(buf, sizeof(buf), ".%x", (int)shard);
11fdf7f2 290 ceph_assert(r < (int)sizeof(buf));
f67539c2 291 return std::string(buf, r) + '_';
7c673cae
FG
292 }
293 uint32_t mask_bits;
294 const uint32_t match;
f67539c2 295 std::string last_key_checked;
7c673cae
FG
296 const int64_t pool;
297 const shard_id_t shard;
f67539c2 298 const std::string shard_prefix;
7c673cae
FG
299 SnapMapper(
300 CephContext* cct,
f67539c2 301 MapCacher::StoreDriver<std::string, ceph::buffer::list> *driver,
7c673cae
FG
302 uint32_t match, ///< [in] pgid
303 uint32_t bits, ///< [in] current split bits
304 int64_t pool, ///< [in] pool
305 shard_id_t shard ///< [in] shard
306 )
307 : cct(cct), backend(driver), mask_bits(bits), match(match), pool(pool),
308 shard(shard), shard_prefix(make_shard_prefix(shard)) {
309 update_bits(mask_bits);
310 }
311
f67539c2 312 std::set<std::string> prefixes;
11fdf7f2 313 /// Update bits in case of pg split or merge
7c673cae
FG
314 void update_bits(
315 uint32_t new_bits ///< [in] new split bits
316 ) {
7c673cae 317 mask_bits = new_bits;
f67539c2 318 std::set<std::string> _prefixes = hobject_t::get_prefixes(
7c673cae
FG
319 mask_bits,
320 match,
321 pool);
322 prefixes.clear();
f67539c2 323 for (auto i = _prefixes.begin(); i != _prefixes.end(); ++i) {
7c673cae
FG
324 prefixes.insert(shard_prefix + *i);
325 }
326 }
327
328 /// Update snaps for oid, empty new_snaps removes the mapping
329 int update_snaps(
330 const hobject_t &oid, ///< [in] oid to update
f67539c2 331 const std::set<snapid_t> &new_snaps, ///< [in] new snap std::set
7c673cae 332 const std::set<snapid_t> *old_snaps, ///< [in] old snaps (for debugging)
f67539c2 333 MapCacher::Transaction<std::string, ceph::buffer::list> *t ///< [out] transaction
7c673cae
FG
334 ); ///@ return error, 0 on success
335
336 /// Add mapping for oid, must not already be mapped
337 void add_oid(
338 const hobject_t &oid, ///< [in] oid to add
339 const std::set<snapid_t>& new_snaps, ///< [in] snaps
f67539c2 340 MapCacher::Transaction<std::string, ceph::buffer::list> *t ///< [out] transaction
7c673cae
FG
341 );
342
343 /// Returns first object with snap as a snap
344 int get_next_objects_to_trim(
345 snapid_t snap, ///< [in] snap to check
346 unsigned max, ///< [in] max to get
f67539c2 347 std::vector<hobject_t> *out ///< [out] next objects to trim (must be empty)
7c673cae
FG
348 ); ///< @return error, -ENOENT if no more objects
349
350 /// Remove mapping for oid
351 int remove_oid(
352 const hobject_t &oid, ///< [in] oid to remove
f67539c2 353 MapCacher::Transaction<std::string, ceph::buffer::list> *t ///< [out] transaction
7c673cae
FG
354 ); ///< @return error, -ENOENT if the object is not mapped
355
356 /// Get snaps for oid
357 int get_snaps(
358 const hobject_t &oid, ///< [in] oid to get snaps for
359 std::set<snapid_t> *snaps ///< [out] snaps
1e59de90
TL
360 ) const; ///< @return error, -ENOENT if oid is not recorded
361
362 /// Get snaps for oid - alternative interface
363 tl::expected<std::set<snapid_t>, SnapMapReaderI::result_t> get_snaps(
364 const hobject_t &hoid) const final;
365
366 /**
367 * get_snaps_check_consistency
368 *
369 * Returns snaps for hoid as in get_snaps(), but additionally validates the
370 * snap->hobject_t mappings ('SNA_' entries).
371 */
372 tl::expected<std::set<snapid_t>, SnapMapReaderI::result_t>
373 get_snaps_check_consistency(const hobject_t &hoid) const final;
7c673cae
FG
374};
375WRITE_CLASS_ENCODER(SnapMapper::object_snaps)
9f95a23c 376WRITE_CLASS_ENCODER(SnapMapper::Mapping)
7c673cae
FG
377
378#endif