mark_closed(segment);
}
-SegmentCleaner::do_immediate_work_ret SegmentCleaner::do_immediate_work(
- Transaction &t)
-{
- auto next_target = get_dirty_tail_limit();
- logger().debug(
- "{}: journal_tail_target={} get_dirty_tail_limit()={}",
- __func__,
- journal_tail_target,
- next_target);
-
- logger().debug(
- "SegmentCleaner::do_immediate_work gc total {}, available {}, unavailable {}, used {} available_ratio {}, reclaim_ratio {}, bytes_to_gc_for_available {}, bytes_to_gc_for_reclaim {}",
- get_total_bytes(),
- get_available_bytes(),
- get_unavailable_bytes(),
- get_used_bytes(),
- get_available_ratio(),
- get_reclaim_ratio(),
- get_immediate_bytes_to_gc_for_available(),
- get_immediate_bytes_to_gc_for_reclaim());
-
- auto dirty_fut = do_immediate_work_ertr::now();
- if (journal_tail_target < next_target) {
- dirty_fut = rewrite_dirty(t, next_target);
- }
- return dirty_fut.safe_then([=, &t] {
- return do_gc(t, get_immediate_bytes_to_gc());
- }).handle_error(
- do_immediate_work_ertr::pass_further{},
- crimson::ct_error::assert_all{
- "Invalid error in SegmentCleaner::do_immediate_work"
- }
- );
-}
-
-SegmentCleaner::do_deferred_work_ret SegmentCleaner::do_deferred_work(
- Transaction &t)
-{
- return do_deferred_work_ret(
- do_deferred_work_ertr::ready_future_marker{},
- ceph::timespan());
-}
-
SegmentCleaner::rewrite_dirty_ret SegmentCleaner::rewrite_dirty(
Transaction &t,
journal_seq_t limit)
});
}
-SegmentCleaner::do_gc_ret SegmentCleaner::do_gc(
- Transaction &t,
- size_t bytes)
-{
- if (bytes == 0) {
- return do_gc_ertr::now();
- }
-
- if (!scan_cursor) {
- paddr_t next = P_ADDR_NULL;
- next.segment = get_next_gc_target();
- if (next == P_ADDR_NULL) {
- logger().debug(
- "SegmentCleaner::do_gc: no segments to gc");
- return do_gc_ertr::now();
- }
- next.offset = 0;
- scan_cursor =
- std::make_unique<ExtentCallbackInterface::scan_extents_cursor>(
- next);
- logger().debug(
- "SegmentCleaner::do_gc: starting gc on segment {}",
- scan_cursor->get_offset().segment);
- }
-
- return ecb->scan_extents(
- *scan_cursor,
- bytes
- ).safe_then([=, &t](auto addrs) {
- return seastar::do_with(
- std::move(addrs),
- [=, &t](auto &addr_list) {
- return crimson::do_for_each(
- addr_list,
- [=, &t](auto &addr_pair) {
- auto &[addr, info] = addr_pair;
- logger().debug(
- "SegmentCleaner::do_gc: checking addr {}",
- addr);
- return ecb->get_extent_if_live(
- t,
- info.type,
- addr,
- info.addr,
- info.len
- ).safe_then([addr=addr, &t, this](CachedExtentRef ext) {
- if (!ext) {
- logger().debug(
- "SegmentCleaner::do_gc: addr {} dead, skipping",
- addr);
- return ExtentCallbackInterface::rewrite_extent_ertr::now();
- } else {
- logger().debug(
- "SegmentCleaner::do_gc: addr {} alive, gc'ing {}",
- addr,
- *ext);
- }
- return ecb->rewrite_extent(
- t,
- ext);
- });
- }).safe_then([&t, this] {
- if (scan_cursor->is_complete()) {
- t.mark_segment_to_release(scan_cursor->get_offset().segment);
- scan_cursor.reset();
- }
- return ExtentCallbackInterface::release_segment_ertr::now();
- });
- });
- });
-}
-
}
double reclaim_ratio_hard_limit = 0;
double reclaim_ratio_gc_threshhold = 0;
- // don't apply reclaim ratio with available space below this (TODO remove)
- double reclaim_ratio_usage_min = 0;
-
double available_ratio_hard_limit = 0;
size_t reclaim_bytes_stride = 0; // Number of bytes to reclaim on each cycle
.9, // available_ratio_gc_max
.6, // reclaim_ratio_hard_limit
.3, // reclaim_ratio_gc_threshhold
- .95, // reclaim_ratio_usage_min
.1, // available_ratio_hard_limit
1<<20 // reclaim 1MB per gc cycle
};
using work_ertr = ExtentCallbackInterface::extent_mapping_ertr;
- /**
- * do_immediate_work
- *
- * Should be invoked prior to submission of any transaction,
- * will piggy-back work required to maintain deferred work
- * constraints.
- */
- using do_immediate_work_ertr = work_ertr;
- using do_immediate_work_ret = do_immediate_work_ertr::future<>;
- do_immediate_work_ret do_immediate_work(
- Transaction &t);
-
-
- /**
- * do_deferred_work
- *
- * Should be called at idle times -- will perform background
- * operations based on deferred work constraints.
- *
- * If returned timespan is non-zero, caller should pause calling
- * back into do_deferred_work before returned timespan has elapsed,
- * or a foreground operation occurs.
- */
- using do_deferred_work_ertr = work_ertr;
- using do_deferred_work_ret = do_deferred_work_ertr::future<
- ceph::timespan
- >;
- do_deferred_work_ret do_deferred_work(
- Transaction &t);
-
private:
// journal status helpers
using gc_reclaim_space_ret = gc_reclaim_space_ertr::future<>;
gc_reclaim_space_ret gc_reclaim_space();
-
- /**
- * do_gc
- *
- * Performs bytes worth of gc work on t.
- */
- using do_gc_ertr = ExtentCallbackInterface::extent_mapping_ertr::extend_ertr<
- ExtentCallbackInterface::scan_extents_ertr>;
- using do_gc_ret = do_gc_ertr::future<>;
- do_gc_ret do_gc(
- Transaction &t,
- size_t bytes);
-
size_t get_bytes_used_current_segment() const {
assert(journal_head != journal_seq_t());
return journal_head.offset.offset;
return gc_should_reclaim_space() || gc_should_trim_journal();
}
- /**
- * get_immediate_bytes_to_gc_for_reclaim
- *
- * Returns the number of bytes to gc in order to bring the
- * reclaim ratio below reclaim_ratio_hard_limit.
- */
- size_t get_immediate_bytes_to_gc_for_reclaim() const {
- if (get_reclaim_ratio() < config.reclaim_ratio_hard_limit)
- return 0;
-
- const size_t unavailable_target = std::max(
- get_used_bytes() / (1.0 - config.reclaim_ratio_hard_limit),
- (1 - config.reclaim_ratio_usage_min) * get_total_bytes());
-
- if (unavailable_target > get_unavailable_bytes())
- return 0;
-
- return (get_unavailable_bytes() - unavailable_target) / get_reclaim_ratio();
- }
-
- /**
- * get_immediate_bytes_to_gc_for_available
- *
- * Returns the number of bytes to gc in order to bring the
- * the ratio of available disk space to total disk space above
- * available_ratio_hard_limit.
- */
- size_t get_immediate_bytes_to_gc_for_available() const {
- if (get_available_ratio() > config.available_ratio_hard_limit) {
- return 0;
- }
-
- const double ratio_to_make_available = config.available_ratio_hard_limit -
- get_available_ratio();
- return ratio_to_make_available * (double)get_total_bytes()
- / get_reclaim_ratio();
- }
-
- /**
- * get_immediate_bytes_to_gc
- *
- * Returns number of bytes to gc in order to restore any strict
- * limits.
- */
- size_t get_immediate_bytes_to_gc() const {
- // number of bytes to gc in order to correct reclaim ratio
- size_t for_reclaim = get_immediate_bytes_to_gc_for_reclaim();
-
- // number of bytes to gc in order to correct available_ratio
- size_t for_available = get_immediate_bytes_to_gc_for_available();
-
- return std::max(for_reclaim, for_available);
- }
-
void mark_closed(segment_id_t segment) {
assert(segments.size() > segment);
if (init_complete) {