44#pragma once
55
66#include < boost/intrusive/set.hpp>
7+ #include < seastar/core/metrics_types.hh>
78
89#include " common/ceph_time.h"
910
@@ -255,6 +256,16 @@ class segment_info_set_t {
255256 device_segment_id_t get_journal_segments () const {
256257 return journal_segments;
257258 }
259+ device_segment_id_t num_segments () const {
260+ device_segment_id_t num = 0 ;
261+ for (auto & sm_info : sm_infos) {
262+ if (!sm_info) {
263+ continue ;
264+ }
265+ num += sm_info->num_segments ;
266+ }
267+ return num;
268+ }
258269private:
259270 std::vector<std::optional<segment_manager_info_t >> sm_infos;
260271 segment_map_t <segment_info_t > segments;
@@ -309,20 +320,26 @@ class SpaceTrackerI {
309320
310321 virtual void dump_usage (segment_id_t ) const = 0;
311322
323+ virtual double calc_utilization (segment_id_t segment) const = 0;
324+
312325 virtual void reset () = 0;
313326
314327 virtual ~SpaceTrackerI () = default ;
315328};
316329using SpaceTrackerIRef = std::unique_ptr<SpaceTrackerI>;
317330
318331class SpaceTrackerSimple : public SpaceTrackerI {
332+ struct segment_bytes_t {
333+ int64_t live_bytes = 0 ;
334+ seastore_off_t total_bytes = 0 ;
335+ };
319336 // Tracks live space for each segment
320- segment_map_t <int64_t > live_bytes_by_segment;
337+ segment_map_t <segment_bytes_t > live_bytes_by_segment;
321338
322339 int64_t update_usage (segment_id_t segment, int64_t delta) {
323- live_bytes_by_segment[segment] += delta;
324- assert (live_bytes_by_segment[segment] >= 0 );
325- return live_bytes_by_segment[segment];
340+ live_bytes_by_segment[segment]. live_bytes += delta;
341+ assert (live_bytes_by_segment[segment]. live_bytes >= 0 );
342+ return live_bytes_by_segment[segment]. live_bytes ;
326343 }
327344public:
328345 SpaceTrackerSimple (const SpaceTrackerSimple &) = default ;
@@ -337,7 +354,7 @@ class SpaceTrackerSimple : public SpaceTrackerI {
337354 live_bytes_by_segment.add_device (
338355 sm->get_device_id (),
339356 sm->get_num_segments (),
340- 0 );
357+ { 0 , sm-> get_segment_size ()} );
341358 }
342359 }
343360
@@ -356,14 +373,19 @@ class SpaceTrackerSimple : public SpaceTrackerI {
356373 }
357374
358375 int64_t get_usage (segment_id_t segment) const final {
359- return live_bytes_by_segment[segment];
376+ return live_bytes_by_segment[segment].live_bytes ;
377+ }
378+
379+ double calc_utilization (segment_id_t segment) const final {
380+ auto & seg_bytes = live_bytes_by_segment[segment];
381+ return (double )seg_bytes.live_bytes / (double )seg_bytes.total_bytes ;
360382 }
361383
362384 void dump_usage (segment_id_t ) const final {}
363385
364386 void reset () final {
365387 for (auto &i : live_bytes_by_segment) {
366- i.second = 0 ;
388+ i.second = { 0 , 0 } ;
367389 }
368390 }
369391
@@ -379,10 +401,15 @@ class SpaceTrackerSimple : public SpaceTrackerI {
379401class SpaceTrackerDetailed : public SpaceTrackerI {
380402 class SegmentMap {
381403 int64_t used = 0 ;
404+ seastore_off_t total_bytes = 0 ;
382405 std::vector<bool > bitmap;
383406
384407 public:
385- SegmentMap (size_t blocks) : bitmap(blocks, false ) {}
408+ SegmentMap (
409+ size_t blocks,
410+ seastore_off_t total_bytes)
411+ : total_bytes(total_bytes),
412+ bitmap (blocks, false ) {}
386413
387414 int64_t update_usage (int64_t delta) {
388415 used += delta;
@@ -407,6 +434,10 @@ class SpaceTrackerDetailed : public SpaceTrackerI {
407434
408435 void dump_usage (extent_len_t block_size) const ;
409436
437+ double calc_utilization () const {
438+ return (double )used / (double )total_bytes;
439+ }
440+
410441 void reset () {
411442 used = 0 ;
412443 for (auto &&i: bitmap) {
@@ -435,7 +466,8 @@ class SpaceTrackerDetailed : public SpaceTrackerI {
435466 sm->get_device_id (),
436467 sm->get_num_segments (),
437468 SegmentMap (
438- sm->get_segment_size () / sm->get_block_size ()));
469+ sm->get_segment_size () / sm->get_block_size (),
470+ sm->get_segment_size ()));
439471 block_size_by_segment_manager[sm->get_device_id ()] = sm->get_block_size ();
440472 }
441473 }
@@ -466,6 +498,10 @@ class SpaceTrackerDetailed : public SpaceTrackerI {
466498 return segment_usage[segment].get_usage ();
467499 }
468500
501+ double calc_utilization (segment_id_t segment) const final {
502+ return segment_usage[segment].calc_utilization ();
503+ }
504+
469505 void dump_usage (segment_id_t seg) const final ;
470506
471507 void reset () final {
@@ -647,6 +683,7 @@ class SegmentCleaner : public SegmentProvider {
647683 uint64_t accumulated_blocked_ios = 0 ;
648684 uint64_t empty_segments = 0 ;
649685 int64_t ios_blocking = 0 ;
686+ seastar::metrics::histogram segment_util;
650687 } stats;
651688 seastar::metrics::metric_group metrics;
652689 void register_metrics ();
@@ -717,6 +754,12 @@ class SegmentCleaner : public SegmentProvider {
717754 return mark_empty (segment);
718755 }
719756
757+ void adjust_segment_util (double old_usage, double new_usage) {
758+ assert (stats.segment_util .buckets [std::floor (old_usage * 10 )].count > 0 );
759+ stats.segment_util .buckets [std::floor (old_usage * 10 )].count --;
760+ stats.segment_util .buckets [std::floor (new_usage * 10 )].count ++;
761+ }
762+
720763 void mark_space_used (
721764 paddr_t addr,
722765 extent_len_t len,
@@ -731,10 +774,14 @@ class SegmentCleaner : public SegmentProvider {
731774 return ;
732775
733776 stats.used_bytes += len;
777+ auto old_usage = space_tracker->calc_utilization (seg_addr.get_segment_id ());
734778 [[maybe_unused]] auto ret = space_tracker->allocate (
735779 seg_addr.get_segment_id (),
736780 seg_addr.get_segment_off (),
737781 len);
782+ auto new_usage = space_tracker->calc_utilization (seg_addr.get_segment_id ());
783+ adjust_segment_util (old_usage, new_usage);
784+
738785 gc_process.maybe_wake_on_space_used ();
739786 assert (ret > 0 );
740787 }
@@ -748,15 +795,18 @@ class SegmentCleaner : public SegmentProvider {
748795 ceph_assert (stats.used_bytes >= len);
749796 stats.used_bytes -= len;
750797 auto & seg_addr = addr.as_seg_paddr ();
751- assert (addr. get_device_id () ==
798+ assert (seg_addr. get_segment_id (). device_id () ==
752799 segments[seg_addr.get_segment_id ().device_id ()]->device_id );
753800 assert (seg_addr.get_segment_id ().device_segment_id () <
754801 segments[seg_addr.get_segment_id ().device_id ()]->num_segments );
755802
803+ auto old_usage = space_tracker->calc_utilization (seg_addr.get_segment_id ());
756804 [[maybe_unused]] auto ret = space_tracker->release (
757805 seg_addr.get_segment_id (),
758806 seg_addr.get_segment_off (),
759807 len);
808+ auto new_usage = space_tracker->calc_utilization (seg_addr.get_segment_id ());
809+ adjust_segment_util (old_usage, new_usage);
760810 maybe_wake_gc_blocked_io ();
761811 assert (ret >= 0 );
762812 }
0 commit comments