]> git.proxmox.com Git - ceph.git/blob - ceph/src/osd/ScrubStore.cc
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / osd / ScrubStore.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #include "ScrubStore.h"
5 #include "osd_types.h"
6 #include "common/scrub_types.h"
7 #include "include/rados/rados_types.hpp"
8
9 using std::ostringstream;
10 using std::string;
11 using std::vector;
12
13 using ceph::bufferlist;
14
15 namespace {
16 ghobject_t make_scrub_object(const spg_t& pgid)
17 {
18 ostringstream ss;
19 ss << "scrub_" << pgid;
20 return pgid.make_temp_ghobject(ss.str());
21 }
22
23 string first_object_key(int64_t pool)
24 {
25 auto hoid = hobject_t(object_t(),
26 "",
27 0,
28 0x00000000,
29 pool,
30 "");
31 hoid.build_hash_cache();
32 return "SCRUB_OBJ_" + hoid.to_str();
33 }
34
35 // the object_key should be unique across pools
36 string to_object_key(int64_t pool, const librados::object_id_t& oid)
37 {
38 auto hoid = hobject_t(object_t(oid.name),
39 oid.locator, // key
40 oid.snap,
41 0, // hash
42 pool,
43 oid.nspace);
44 hoid.build_hash_cache();
45 return "SCRUB_OBJ_" + hoid.to_str();
46 }
47
48 string last_object_key(int64_t pool)
49 {
50 auto hoid = hobject_t(object_t(),
51 "",
52 0,
53 0xffffffff,
54 pool,
55 "");
56 hoid.build_hash_cache();
57 return "SCRUB_OBJ_" + hoid.to_str();
58 }
59
60 string first_snap_key(int64_t pool)
61 {
62 // scrub object is per spg_t object, so we can misuse the hash (pg.seed) for
63 // the representing the minimal and maximum keys. and this relies on how
64 // hobject_t::to_str() works: hex(pool).hex(revhash).
65 auto hoid = hobject_t(object_t(),
66 "",
67 0,
68 0x00000000,
69 pool,
70 "");
71 hoid.build_hash_cache();
72 return "SCRUB_SS_" + hoid.to_str();
73 }
74
75 string to_snap_key(int64_t pool, const librados::object_id_t& oid)
76 {
77 auto hoid = hobject_t(object_t(oid.name),
78 oid.locator, // key
79 oid.snap,
80 0x77777777, // hash
81 pool,
82 oid.nspace);
83 hoid.build_hash_cache();
84 return "SCRUB_SS_" + hoid.to_str();
85 }
86
87 string last_snap_key(int64_t pool)
88 {
89 auto hoid = hobject_t(object_t(),
90 "",
91 0,
92 0xffffffff,
93 pool,
94 "");
95 hoid.build_hash_cache();
96 return "SCRUB_SS_" + hoid.to_str();
97 }
98 }
99
100 namespace Scrub {
101
102 Store*
103 Store::create(ObjectStore* store,
104 ObjectStore::Transaction* t,
105 const spg_t& pgid,
106 const coll_t& coll)
107 {
108 ceph_assert(store);
109 ceph_assert(t);
110 ghobject_t oid = make_scrub_object(pgid);
111 t->touch(coll, oid);
112 return new Store{coll, oid, store};
113 }
114
115 Store::Store(const coll_t& coll, const ghobject_t& oid, ObjectStore* store)
116 : coll(coll),
117 hoid(oid),
118 driver(store, coll, hoid),
119 backend(&driver)
120 {}
121
122 Store::~Store()
123 {
124 ceph_assert(results.empty());
125 }
126
127 void Store::add_object_error(int64_t pool, const inconsistent_obj_wrapper& e)
128 {
129 bufferlist bl;
130 e.encode(bl);
131 results[to_object_key(pool, e.object)] = bl;
132 }
133
134 void Store::add_snap_error(int64_t pool, const inconsistent_snapset_wrapper& e)
135 {
136 bufferlist bl;
137 e.encode(bl);
138 results[to_snap_key(pool, e.object)] = bl;
139 }
140
141 bool Store::empty() const
142 {
143 return results.empty();
144 }
145
146 void Store::flush(ObjectStore::Transaction* t)
147 {
148 if (t) {
149 OSDriver::OSTransaction txn = driver.get_transaction(t);
150 backend.set_keys(results, &txn);
151 }
152 results.clear();
153 }
154
155 void Store::cleanup(ObjectStore::Transaction* t)
156 {
157 t->remove(coll, hoid);
158 }
159
160 std::vector<bufferlist>
161 Store::get_snap_errors(int64_t pool,
162 const librados::object_id_t& start,
163 uint64_t max_return) const
164 {
165 const string begin = (start.name.empty() ?
166 first_snap_key(pool) : to_snap_key(pool, start));
167 const string end = last_snap_key(pool);
168 return get_errors(begin, end, max_return);
169 }
170
171 std::vector<bufferlist>
172 Store::get_object_errors(int64_t pool,
173 const librados::object_id_t& start,
174 uint64_t max_return) const
175 {
176 const string begin = (start.name.empty() ?
177 first_object_key(pool) : to_object_key(pool, start));
178 const string end = last_object_key(pool);
179 return get_errors(begin, end, max_return);
180 }
181
182 std::vector<bufferlist>
183 Store::get_errors(const string& begin,
184 const string& end,
185 uint64_t max_return) const
186 {
187 vector<bufferlist> errors;
188 auto next = std::make_pair(begin, bufferlist{});
189 while (max_return && !backend.get_next(next.first, &next)) {
190 if (next.first >= end)
191 break;
192 errors.push_back(next.second);
193 max_return--;
194 }
195 return errors;
196 }
197
198 } // namespace Scrub