]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | ||
4 | #include "seastore.h" | |
5 | ||
6 | #include <boost/algorithm/string/trim.hpp> | |
7 | #include <fmt/format.h> | |
8 | #include <fmt/ostream.h> | |
9 | ||
10 | #include "common/safe_io.h" | |
11 | #include "os/Transaction.h" | |
12 | ||
13 | #include "crimson/common/buffer_io.h" | |
14 | #include "crimson/common/config_proxy.h" | |
15 | ||
16 | #include "crimson/os/futurized_collection.h" | |
17 | ||
18 | #include "crimson/os/seastore/segment_manager/ephemeral.h" | |
19 | #include "crimson/os/seastore/transaction_manager.h" | |
20 | #include "crimson/os/seastore/onode_manager.h" | |
21 | #include "crimson/os/seastore/cache.h" | |
22 | ||
23 | namespace { | |
24 | seastar::logger& logger() { | |
25 | return crimson::get_logger(ceph_subsys_filestore); | |
26 | } | |
27 | } | |
28 | ||
29 | using crimson::common::local_conf; | |
30 | ||
31 | namespace crimson::os::seastore { | |
32 | ||
33 | struct SeastoreCollection final : public FuturizedCollection { | |
34 | template <typename... T> | |
35 | SeastoreCollection(T&&... args) : | |
36 | FuturizedCollection(std::forward<T>(args)...) {} | |
37 | }; | |
38 | ||
39 | SeaStore::SeaStore(const std::string& path) | |
40 | : segment_manager(segment_manager::create_test_ephemeral() /* TODO */), | |
41 | segment_cleaner( | |
42 | std::make_unique<SegmentCleaner>( | |
43 | SegmentCleaner::config_t::default_from_segment_manager( | |
44 | *segment_manager))), | |
45 | cache(std::make_unique<Cache>(*segment_manager)), | |
46 | journal(new Journal(*segment_manager)), | |
47 | lba_manager( | |
48 | lba_manager::create_lba_manager(*segment_manager, *cache)), | |
49 | transaction_manager( | |
50 | new TransactionManager( | |
51 | *segment_manager, | |
52 | *segment_cleaner, | |
53 | *journal, | |
54 | *cache, | |
55 | *lba_manager)), | |
56 | onode_manager(onode_manager::create_ephemeral()) | |
57 | { | |
58 | journal->set_segment_provider(&*segment_cleaner); | |
59 | segment_cleaner->set_extent_callback(&*transaction_manager); | |
60 | } | |
61 | ||
62 | SeaStore::~SeaStore() = default; | |
63 | ||
64 | seastar::future<> SeaStore::stop() | |
65 | { | |
66 | return seastar::now(); | |
67 | } | |
68 | ||
69 | seastar::future<> SeaStore::mount() | |
70 | { | |
71 | return seastar::now(); | |
72 | } | |
73 | ||
74 | seastar::future<> SeaStore::umount() | |
75 | { | |
76 | return seastar::now(); | |
77 | } | |
78 | ||
79 | seastar::future<> SeaStore::mkfs(uuid_d new_osd_fsid) | |
80 | { | |
81 | return seastar::now(); | |
82 | } | |
83 | ||
84 | seastar::future<store_statfs_t> SeaStore::stat() const | |
85 | { | |
86 | logger().debug("{}", __func__); | |
87 | store_statfs_t st; | |
88 | return seastar::make_ready_future<store_statfs_t>(st); | |
89 | } | |
90 | ||
91 | seastar::future<std::tuple<std::vector<ghobject_t>, ghobject_t>> | |
92 | SeaStore::list_objects(CollectionRef ch, | |
93 | const ghobject_t& start, | |
94 | const ghobject_t& end, | |
95 | uint64_t limit) const | |
96 | { | |
97 | return seastar::make_ready_future<std::tuple<std::vector<ghobject_t>, ghobject_t>>( | |
98 | std::make_tuple(std::vector<ghobject_t>(), end)); | |
99 | } | |
100 | ||
101 | seastar::future<CollectionRef> SeaStore::create_new_collection(const coll_t& cid) | |
102 | { | |
103 | auto c = _get_collection(cid); | |
104 | return seastar::make_ready_future<CollectionRef>(c); | |
105 | } | |
106 | ||
107 | seastar::future<CollectionRef> SeaStore::open_collection(const coll_t& cid) | |
108 | { | |
109 | return seastar::make_ready_future<CollectionRef>(_get_collection(cid)); | |
110 | } | |
111 | ||
112 | seastar::future<std::vector<coll_t>> SeaStore::list_collections() | |
113 | { | |
114 | return seastar::make_ready_future<std::vector<coll_t>>(); | |
115 | } | |
116 | ||
117 | SeaStore::read_errorator::future<ceph::bufferlist> SeaStore::read( | |
118 | CollectionRef ch, | |
119 | const ghobject_t& oid, | |
120 | uint64_t offset, | |
121 | size_t len, | |
122 | uint32_t op_flags) | |
123 | { | |
124 | return read_errorator::make_ready_future<ceph::bufferlist>(); | |
125 | } | |
126 | ||
127 | SeaStore::read_errorator::future<ceph::bufferlist> SeaStore::readv( | |
128 | CollectionRef ch, | |
129 | const ghobject_t& oid, | |
130 | interval_set<uint64_t>& m, | |
131 | uint32_t op_flags) | |
132 | { | |
133 | return read_errorator::make_ready_future<ceph::bufferlist>(); | |
134 | } | |
135 | ||
136 | SeaStore::get_attr_errorator::future<ceph::bufferptr> SeaStore::get_attr( | |
137 | CollectionRef ch, | |
138 | const ghobject_t& oid, | |
139 | std::string_view name) const | |
140 | { | |
141 | auto c = static_cast<SeastoreCollection*>(ch.get()); | |
142 | logger().debug("{} {} {}", | |
143 | __func__, c->get_cid(), oid); | |
144 | return crimson::ct_error::enoent::make(); | |
145 | } | |
146 | ||
147 | SeaStore::get_attrs_ertr::future<SeaStore::attrs_t> SeaStore::get_attrs( | |
148 | CollectionRef ch, | |
149 | const ghobject_t& oid) | |
150 | { | |
151 | auto c = static_cast<SeastoreCollection*>(ch.get()); | |
152 | logger().debug("{} {} {}", | |
153 | __func__, c->get_cid(), oid); | |
154 | return crimson::ct_error::enoent::make(); | |
155 | } | |
156 | ||
157 | seastar::future<struct stat> stat( | |
158 | CollectionRef c, | |
159 | const ghobject_t& oid) | |
160 | { | |
161 | return seastar::make_ready_future<struct stat>(); | |
162 | } | |
163 | ||
164 | ||
165 | seastar::future<struct stat> SeaStore::stat( | |
166 | CollectionRef c, | |
167 | const ghobject_t& oid) | |
168 | { | |
169 | struct stat st; | |
170 | return seastar::make_ready_future<struct stat>(st); | |
171 | } | |
172 | ||
173 | auto | |
174 | SeaStore::omap_get_header( | |
175 | CollectionRef c, | |
176 | const ghobject_t& oid) | |
177 | -> read_errorator::future<bufferlist> | |
178 | { | |
179 | return seastar::make_ready_future<bufferlist>(); | |
180 | } | |
181 | ||
182 | auto | |
183 | SeaStore::omap_get_values( | |
184 | CollectionRef ch, | |
185 | const ghobject_t& oid, | |
186 | const omap_keys_t& keys) | |
187 | -> read_errorator::future<omap_values_t> | |
188 | { | |
189 | auto c = static_cast<SeastoreCollection*>(ch.get()); | |
190 | logger().debug("{} {} {}", | |
191 | __func__, c->get_cid(), oid); | |
192 | return seastar::make_ready_future<omap_values_t>(); | |
193 | } | |
194 | ||
195 | auto | |
196 | SeaStore::omap_get_values( | |
197 | CollectionRef ch, | |
198 | const ghobject_t &oid, | |
199 | const std::optional<string> &start) | |
200 | -> read_errorator::future<std::tuple<bool, SeaStore::omap_values_t>> | |
201 | { | |
202 | auto c = static_cast<SeastoreCollection*>(ch.get()); | |
203 | logger().debug( | |
204 | "{} {} {}", | |
205 | __func__, c->get_cid(), oid); | |
206 | return seastar::make_ready_future<std::tuple<bool, omap_values_t>>( | |
207 | std::make_tuple(false, omap_values_t())); | |
208 | } | |
209 | ||
210 | seastar::future<FuturizedStore::OmapIteratorRef> get_omap_iterator( | |
211 | CollectionRef ch, | |
212 | const ghobject_t& oid) | |
213 | { | |
214 | return seastar::make_ready_future<FuturizedStore::OmapIteratorRef>(); | |
215 | } | |
216 | ||
217 | seastar::future<std::map<uint64_t, uint64_t>> fiemap( | |
218 | CollectionRef ch, | |
219 | const ghobject_t& oid, | |
220 | uint64_t off, | |
221 | uint64_t len) | |
222 | { | |
223 | return seastar::make_ready_future<std::map<uint64_t, uint64_t>>(); | |
224 | } | |
225 | ||
226 | seastar::future<> SeaStore::do_transaction( | |
227 | CollectionRef _ch, | |
228 | ceph::os::Transaction&& _t) | |
229 | { | |
230 | return seastar::do_with( | |
231 | _t.begin(), | |
232 | transaction_manager->create_transaction(), | |
233 | std::vector<OnodeRef>(), | |
234 | std::move(_t), | |
235 | std::move(_ch), | |
236 | [this](auto &iter, auto &trans, auto &onodes, auto &t, auto &ch) { | |
237 | return onode_manager->get_or_create_onodes( | |
238 | *trans, iter.get_objects()).safe_then( | |
239 | [this, &iter, &trans, &onodes, &t, &ch](auto &&read_onodes) { | |
240 | onodes = std::move(read_onodes); | |
241 | return seastar::do_until( | |
242 | [&iter]() { return iter.have_op(); }, | |
243 | [this, &iter, &trans, &onodes, &t, &ch]() { | |
244 | return _do_transaction_step(trans, ch, onodes, iter).safe_then( | |
245 | [this, &trans] { | |
246 | return transaction_manager->submit_transaction(std::move(trans)); | |
247 | }).handle_error( | |
248 | // TODO: add errorator::do_until | |
249 | crimson::ct_error::eagain::handle([]() { | |
250 | // TODO retry | |
251 | }), | |
252 | write_ertr::all_same_way([&t](auto e) { | |
253 | logger().error(" transaction dump:\n"); | |
254 | JSONFormatter f(true); | |
255 | f.open_object_section("transaction"); | |
256 | t.dump(&f); | |
257 | f.close_section(); | |
258 | std::stringstream str; | |
259 | f.flush(str); | |
260 | logger().error("{}", str.str()); | |
261 | abort(); | |
262 | })); | |
263 | }); | |
264 | }).safe_then([this, &trans, &onodes]() { | |
265 | return onode_manager->write_dirty(*trans, onodes); | |
266 | }).safe_then([]() { | |
267 | // TODO: complete transaction! | |
268 | return; | |
269 | }).handle_error( | |
270 | write_ertr::all_same_way([&t](auto e) { | |
271 | logger().error(" transaction dump:\n"); | |
272 | JSONFormatter f(true); | |
273 | f.open_object_section("transaction"); | |
274 | t.dump(&f); | |
275 | f.close_section(); | |
276 | std::stringstream str; | |
277 | f.flush(str); | |
278 | logger().error("{}", str.str()); | |
279 | abort(); | |
280 | })).then([&t]() { | |
281 | for (auto i : { | |
282 | t.get_on_applied(), | |
283 | t.get_on_commit(), | |
284 | t.get_on_applied_sync()}) { | |
285 | if (i) { | |
286 | i->complete(0); | |
287 | } | |
288 | } | |
289 | }); | |
290 | }); | |
291 | } | |
292 | ||
293 | SeaStore::write_ertr::future<> SeaStore::_do_transaction_step( | |
294 | TransactionRef &trans, | |
295 | CollectionRef &col, | |
296 | std::vector<OnodeRef> &onodes, | |
297 | ceph::os::Transaction::iterator &i) | |
298 | { | |
299 | auto get_onode = [&onodes](size_t i) -> OnodeRef& { | |
300 | ceph_assert(i < onodes.size()); | |
301 | return onodes[i]; | |
302 | }; | |
303 | ||
304 | using ceph::os::Transaction; | |
305 | try { | |
306 | switch (auto op = i.decode_op(); op->op) { | |
307 | case Transaction::OP_NOP: | |
308 | return write_ertr::now(); | |
309 | case Transaction::OP_REMOVE: | |
310 | { | |
311 | return _remove(trans, get_onode(op->oid)); | |
312 | } | |
313 | break; | |
314 | case Transaction::OP_TOUCH: | |
315 | { | |
316 | return _touch(trans, get_onode(op->oid)); | |
317 | } | |
318 | break; | |
319 | case Transaction::OP_WRITE: | |
320 | { | |
321 | uint64_t off = op->off; | |
322 | uint64_t len = op->len; | |
323 | uint32_t fadvise_flags = i.get_fadvise_flags(); | |
324 | ceph::bufferlist bl; | |
325 | i.decode_bl(bl); | |
326 | return _write(trans, get_onode(op->oid), off, len, bl, fadvise_flags); | |
327 | } | |
328 | break; | |
329 | case Transaction::OP_TRUNCATE: | |
330 | { | |
331 | uint64_t off = op->off; | |
332 | return _truncate(trans, get_onode(op->oid), off); | |
333 | } | |
334 | break; | |
335 | case Transaction::OP_SETATTR: | |
336 | { | |
337 | std::string name = i.decode_string(); | |
338 | ceph::bufferlist bl; | |
339 | i.decode_bl(bl); | |
340 | std::map<std::string, bufferptr> to_set; | |
341 | to_set[name] = bufferptr(bl.c_str(), bl.length()); | |
342 | return _setattrs(trans, get_onode(op->oid), to_set); | |
343 | } | |
344 | break; | |
345 | case Transaction::OP_MKCOLL: | |
346 | { | |
347 | coll_t cid = i.get_cid(op->cid); | |
348 | return _create_collection(trans, cid, op->split_bits); | |
349 | } | |
350 | break; | |
351 | case Transaction::OP_OMAP_SETKEYS: | |
352 | { | |
353 | std::map<std::string, ceph::bufferlist> aset; | |
354 | i.decode_attrset(aset); | |
355 | return _omap_set_values(trans, get_onode(op->oid), std::move(aset)); | |
356 | } | |
357 | break; | |
358 | case Transaction::OP_OMAP_SETHEADER: | |
359 | { | |
360 | ceph::bufferlist bl; | |
361 | i.decode_bl(bl); | |
362 | return _omap_set_header(trans, get_onode(op->oid), bl); | |
363 | } | |
364 | break; | |
365 | case Transaction::OP_OMAP_RMKEYS: | |
366 | { | |
367 | omap_keys_t keys; | |
368 | i.decode_keyset(keys); | |
369 | return _omap_rmkeys(trans, get_onode(op->oid), keys); | |
370 | } | |
371 | break; | |
372 | case Transaction::OP_OMAP_RMKEYRANGE: | |
373 | { | |
374 | string first, last; | |
375 | first = i.decode_string(); | |
376 | last = i.decode_string(); | |
377 | return _omap_rmkeyrange(trans, get_onode(op->oid), first, last); | |
378 | } | |
379 | break; | |
380 | case Transaction::OP_COLL_HINT: | |
381 | { | |
382 | ceph::bufferlist hint; | |
383 | i.decode_bl(hint); | |
384 | return write_ertr::now(); | |
385 | } | |
386 | default: | |
387 | logger().error("bad op {}", static_cast<unsigned>(op->op)); | |
388 | return crimson::ct_error::input_output_error::make(); | |
389 | } | |
390 | } catch (std::exception &e) { | |
391 | logger().error("{} got exception {}", __func__, e); | |
392 | return crimson::ct_error::input_output_error::make(); | |
393 | } | |
394 | } | |
395 | ||
396 | SeaStore::write_ertr::future<> SeaStore::_remove( | |
397 | TransactionRef &trans, | |
398 | OnodeRef &onode) | |
399 | { | |
400 | logger().debug("{} onode={}", | |
401 | __func__, *onode); | |
402 | return write_ertr::now(); | |
403 | } | |
404 | ||
405 | SeaStore::write_ertr::future<> SeaStore::_touch( | |
406 | TransactionRef &trans, | |
407 | OnodeRef &onode) | |
408 | { | |
409 | logger().debug("{} onode={}", | |
410 | __func__, *onode); | |
411 | return write_ertr::now(); | |
412 | } | |
413 | ||
414 | SeaStore::write_ertr::future<> SeaStore::_write( | |
415 | TransactionRef &trans, | |
416 | OnodeRef &onode, | |
417 | uint64_t offset, size_t len, const ceph::bufferlist& bl, | |
418 | uint32_t fadvise_flags) | |
419 | { | |
420 | logger().debug("{}: {} {} ~ {}", | |
421 | __func__, *onode, offset, len); | |
422 | assert(len == bl.length()); | |
423 | ||
424 | /* | |
425 | return onode_manager->get_or_create_onode(cid, oid).safe_then([=, &bl](auto ref) { | |
426 | return; | |
427 | }).handle_error( | |
428 | crimson::ct_error::enoent::handle([]() { | |
429 | return; | |
430 | }), | |
431 | OnodeManager::open_ertr::pass_further{} | |
432 | ); | |
433 | */ | |
434 | return write_ertr::now(); | |
435 | } | |
436 | ||
437 | SeaStore::write_ertr::future<> SeaStore::_omap_set_values( | |
438 | TransactionRef &trans, | |
439 | OnodeRef &onode, | |
440 | std::map<std::string, ceph::bufferlist> &&aset) | |
441 | { | |
442 | logger().debug( | |
443 | "{}: {} {} keys", | |
444 | __func__, *onode, aset.size()); | |
445 | ||
446 | return write_ertr::now(); | |
447 | } | |
448 | ||
449 | SeaStore::write_ertr::future<> SeaStore::_omap_set_header( | |
450 | TransactionRef &trans, | |
451 | OnodeRef &onode, | |
452 | const ceph::bufferlist &header) | |
453 | { | |
454 | logger().debug( | |
455 | "{}: {} {} bytes", | |
456 | __func__, *onode, header.length()); | |
457 | return write_ertr::now(); | |
458 | } | |
459 | ||
460 | SeaStore::write_ertr::future<> SeaStore::_omap_rmkeys( | |
461 | TransactionRef &trans, | |
462 | OnodeRef &onode, | |
463 | const omap_keys_t& aset) | |
464 | { | |
465 | logger().debug( | |
466 | "{} {} {} keys", | |
467 | __func__, *onode, aset.size()); | |
468 | return write_ertr::now(); | |
469 | } | |
470 | ||
471 | SeaStore::write_ertr::future<> SeaStore::_omap_rmkeyrange( | |
472 | TransactionRef &trans, | |
473 | OnodeRef &onode, | |
474 | const std::string &first, | |
475 | const std::string &last) | |
476 | { | |
477 | logger().debug( | |
478 | "{} {} first={} last={}", | |
479 | __func__, *onode, first, last); | |
480 | return write_ertr::now(); | |
481 | } | |
482 | ||
483 | SeaStore::write_ertr::future<> SeaStore::_truncate( | |
484 | TransactionRef &trans, | |
485 | OnodeRef &onode, | |
486 | uint64_t size) | |
487 | { | |
488 | logger().debug("{} onode={} size={}", | |
489 | __func__, *onode, size); | |
490 | return write_ertr::now(); | |
491 | } | |
492 | ||
493 | SeaStore::write_ertr::future<> SeaStore::_setattrs( | |
494 | TransactionRef &trans, | |
495 | OnodeRef &onode, | |
496 | std::map<std::string,bufferptr>& aset) | |
497 | { | |
498 | logger().debug("{} onode={}", | |
499 | __func__, *onode); | |
500 | return write_ertr::now(); | |
501 | } | |
502 | ||
503 | SeaStore::write_ertr::future<> SeaStore::_create_collection( | |
504 | TransactionRef &trans, | |
505 | const coll_t& cid, int bits) | |
506 | { | |
507 | return write_ertr::now(); | |
508 | } | |
509 | ||
510 | boost::intrusive_ptr<SeastoreCollection> SeaStore::_get_collection(const coll_t& cid) | |
511 | { | |
512 | return new SeastoreCollection{cid}; | |
513 | } | |
514 | ||
515 | seastar::future<> SeaStore::write_meta(const std::string& key, | |
516 | const std::string& value) | |
517 | { | |
518 | return seastar::make_ready_future<>(); | |
519 | } | |
520 | ||
521 | seastar::future<std::tuple<int, std::string>> SeaStore::read_meta(const std::string& key) | |
522 | { | |
523 | return seastar::make_ready_future<std::tuple<int, std::string>>( | |
524 | std::make_tuple(0, ""s)); | |
525 | } | |
526 | ||
527 | uuid_d SeaStore::get_fsid() const | |
528 | { | |
529 | return osd_fsid; | |
530 | } | |
531 | ||
532 | } |