}
Cache::get_next_dirty_extents_ret Cache::get_next_dirty_extents(
+ Transaction &t,
journal_seq_t seq,
size_t max_bytes)
{
LOG_PREFIX(Cache::get_next_dirty_extents);
- std::vector<CachedExtentRef> ret;
+ std::vector<CachedExtentRef> cand;
size_t bytes_so_far = 0;
for (auto i = dirty.begin();
i != dirty.end() && bytes_so_far < max_bytes;
++i) {
- CachedExtentRef cand;
if (i->get_dirty_from() != journal_seq_t() && i->get_dirty_from() < seq) {
- DEBUG("next {}", *i);
- if (!(ret.empty() ||
- ret.back()->get_dirty_from() <= i->get_dirty_from())) {
- DEBUG("last {}, next {}", *ret.back(), *i);
+ DEBUGT("next {}", t, *i);
+ if (!(cand.empty() ||
+ cand.back()->get_dirty_from() <= i->get_dirty_from())) {
+ ERRORT("last {}, next {}", t, *cand.back(), *i);
}
- assert(ret.empty() || ret.back()->get_dirty_from() <= i->get_dirty_from());
+ assert(cand.empty() || cand.back()->get_dirty_from() <= i->get_dirty_from());
bytes_so_far += i->get_length();
- ret.push_back(&*i);
+ cand.push_back(&*i);
+
} else {
break;
}
}
return seastar::do_with(
- std::move(ret),
- [FNAME](auto &ret) {
- return seastar::do_for_each(
- ret,
- [FNAME](auto &ext) {
+ std::move(cand),
+ decltype(cand)(),
+ [FNAME, this, &t](auto &cand, auto &ret) {
+ return trans_intr::do_for_each(
+ cand,
+ [FNAME, this, &t, &ret](auto &ext) {
DEBUG("waiting on {}", *ext);
- return ext->wait_io();
- }).then([&ret]() mutable {
- return seastar::make_ready_future<std::vector<CachedExtentRef>>(
- std::move(ret));
+
+ return trans_intr::make_interruptible(
+ ext->wait_io()
+ ).then_interruptible([FNAME, this, ext, &t, &ret] {
+ if (!ext->is_valid()) {
+ invalidate(t, *ext);
+ return;
+ }
+
+ CachedExtentRef on_transaction;
+ auto result = t.get_extent(ext->get_paddr(), &on_transaction);
+ if (result == Transaction::get_extent_ret::ABSENT) {
+ DEBUGT("{} absent on t", t, *ext);
+ t.add_to_read_set(ext);
+ if (ext->get_type() == extent_types_t::ROOT) {
+ if (t.root) {
+ assert(&*t.root == &*ext);
+ assert(0 == "t.root would have to already be in the read set");
+ } else {
+ assert(&*ext == &*root);
+ t.root = root;
+ }
+ }
+ ret.push_back(ext);
+ } else if (result == Transaction::get_extent_ret::PRESENT) {
+ DEBUGT("{} present on t as {}", t, *ext, *on_transaction);
+ ret.push_back(on_transaction);
+ } else {
+ assert(result == Transaction::get_extent_ret::RETIRED);
+ DEBUGT("{} retired on t", t, *ext);
+ }
+ });
+ }).then_interruptible([&ret] {
+ return std::move(ret);
});
});
}
return t.root;
} else {
t.add_to_read_set(extent);
+ t.root = extent->cast<RootBlock>();
return extent;
}
} else {
return out;
}
- /// returns extents with get_dirty_from() < seq
- using get_next_dirty_extents_ertr = crimson::errorator<>;
- using get_next_dirty_extents_ret = get_next_dirty_extents_ertr::future<
+ /**
+ * get_next_dirty_extents
+ *
+ * Returns extents with get_dirty_from() < seq and adds to read set of
+ * t.
+ */
+ using get_next_dirty_extents_iertr = base_iertr;
+ using get_next_dirty_extents_ret = get_next_dirty_extents_iertr::future<
std::vector<CachedExtentRef>>;
get_next_dirty_extents_ret get_next_dirty_extents(
+ Transaction &t,
journal_seq_t seq,
size_t max_bytes);
// vim: ts=8 sw=2 smarttab
#include "crimson/common/log.h"
+#include "crimson/os/seastore/logging.h"
#include "crimson/os/seastore/segment_cleaner.h"
#include "crimson/os/seastore/transaction_manager.h"
Transaction &t,
journal_seq_t limit)
{
- return trans_intr::make_interruptible(
- ecb->get_next_dirty_extents(
- limit,
- config.journal_rewrite_per_cycle)
- ).then_interruptible([=, &t](auto dirty_list) {
+ LOG_PREFIX(SegmentCleaner::rewrite_dirty);
+ return ecb->get_next_dirty_extents(
+ t,
+ limit,
+ config.journal_rewrite_per_cycle
+ ).si_then([=, &t](auto dirty_list) {
return seastar::do_with(
std::move(dirty_list),
- [this, &t](auto &dirty_list) {
+ [FNAME, this, &t](auto &dirty_list) {
return trans_intr::do_for_each(
dirty_list,
- [this, &t](auto &e) {
- logger().debug(
- "SegmentCleaner::rewrite_dirty cleaning {}",
- *e);
+ [FNAME, this, &t](auto &e) {
+ DEBUGT("cleaning {}", t, *e);
return ecb->rewrite_extent(t, e);
});
});
);
}
- /**
- * get_next_dirty_extent
- *
- * returns all extents with dirty_from < bound
- */
- using get_next_dirty_extents_iertr = crimson::errorator<>;
+ /// See Cache::get_next_dirty_extents
+ using get_next_dirty_extents_iertr = trans_iertr<
+ crimson::errorator<
+ crimson::ct_error::input_output_error>
+ >;
using get_next_dirty_extents_ret = get_next_dirty_extents_iertr::future<
std::vector<CachedExtentRef>>;
virtual get_next_dirty_extents_ret get_next_dirty_extents(
+ Transaction &t, ///< [in] current transaction
journal_seq_t bound,///< [in] return extents with dirty_from < bound
size_t max_bytes ///< [in] return up to max_bytes of extents
) = 0;
-
using extent_mapping_ertr = crimson::errorator<
crimson::ct_error::input_output_error,
crimson::ct_error::eagain>;
TransactionManager::get_next_dirty_extents_ret
TransactionManager::get_next_dirty_extents(
+ Transaction &t,
journal_seq_t seq,
size_t max_bytes)
{
- return cache->get_next_dirty_extents(seq, max_bytes);
+ return cache->get_next_dirty_extents(t, seq, max_bytes);
}
TransactionManager::rewrite_extent_ret TransactionManager::rewrite_extent(
using SegmentCleaner::ExtentCallbackInterface::get_next_dirty_extents_ret;
get_next_dirty_extents_ret get_next_dirty_extents(
+ Transaction &t,
journal_seq_t seq,
size_t max_bytes) final;