@@ -122,7 +122,10 @@ void GCManager::start() {
122122 gc_actor->start ();
123123 LOGINFOMOD (gcmgr, " start gc actor for pdev={}" , pdev_id);
124124 }
125+ start_gc_scan_timer ();
126+ }
125127
128+ void GCManager::start_gc_scan_timer () {
126129 const auto gc_scan_interval_sec = HS_BACKEND_DYNAMIC_CONFIG (gc_scan_interval_sec);
127130
128131 // the initial idea here is that we want gc timer to run in a reactor that not shared with other fibers that
@@ -146,9 +149,7 @@ void GCManager::start() {
146149 LOGINFOMOD (gcmgr, " gc scheduler timer has started, interval is set to {} seconds" , gc_scan_interval_sec);
147150}
148151
149- bool GCManager::is_started () { return m_gc_timer_hdl != iomgr::null_timer_handle; }
150-
151- void GCManager::stop () {
152+ void GCManager::stop_gc_scan_timer () {
152153 if (m_gc_timer_hdl == iomgr::null_timer_handle) {
153154 LOGWARNMOD (gcmgr, " gc scheduler timer is not running, no need to stop it" );
154155 return ;
@@ -162,6 +163,10 @@ void GCManager::stop() {
162163 m_gc_timer_hdl = iomgr::null_timer_handle;
163164 });
164165 m_gc_timer_fiber = nullptr ;
166+ }
167+
168+ void GCManager::stop () {
169+ stop_gc_scan_timer ();
165170
166171 for (const auto & [pdev_id, gc_actor] : m_pdev_gc_actors) {
167172 gc_actor->stop ();
@@ -170,9 +175,20 @@ void GCManager::stop() {
170175}
171176
172177folly::SemiFuture< bool > GCManager::submit_gc_task (task_priority priority, chunk_id_t chunk_id) {
173- if (!is_started ()) return folly::makeFuture< bool >(false );
178+ auto ex_vchunk = m_chunk_selector->get_extend_vchunk (chunk_id);
179+ if (ex_vchunk == nullptr ) {
180+ LOGERRORMOD (gcmgr, " chunk {} not found when submit gc task!" , chunk_id);
181+ return folly::makeFuture< bool >(false );
182+ }
183+
184+ // if the chunk has no garbage to be reclaimed, we don`t need to gc it , return true directly
185+ const auto defrag_blk_num = ex_vchunk->get_defrag_nblks ();
186+ if (!defrag_blk_num && task_priority::normal == priority) {
187+ LOGERRORMOD (gcmgr, " chunk {} has no garbage to be reclaimed, skip gc for this chunk!" , chunk_id);
188+ return folly::makeFuture< bool >(true );
189+ }
174190
175- auto pdev_id = m_chunk_selector-> get_extend_vchunk (chunk_id) ->get_pdev_id ();
191+ auto pdev_id = ex_vchunk ->get_pdev_id ();
176192 auto it = m_pdev_gc_actors.find (pdev_id);
177193 if (it == m_pdev_gc_actors.end ()) {
178194 LOGINFOMOD (gcmgr, " pdev gc actor not found for pdev_id={}, chunk={}" , pdev_id, chunk_id);
@@ -218,7 +234,7 @@ bool GCManager::is_eligible_for_gc(chunk_id_t chunk_id) {
218234
219235 const auto total_blk_num = chunk->get_total_blks ();
220236 const auto gc_garbage_rate_threshold = HS_BACKEND_DYNAMIC_CONFIG (gc_garbage_rate_threshold);
221- bool should_gc = 100 * defrag_blk_num >= total_blk_num * gc_garbage_rate_threshold;
237+ bool should_gc = 100 * defrag_blk_num > total_blk_num * gc_garbage_rate_threshold;
222238
223239 LOGDEBUGMOD (gcmgr,
224240 " gc scan chunk_id={}, use_blks={}, available_blks={}, total_blks={}, defrag_blks={}, should_gc={}" ,
@@ -334,6 +350,11 @@ void GCManager::pdev_gc_actor::add_reserved_chunk(
334350}
335351
336352folly::SemiFuture< bool > GCManager::pdev_gc_actor::add_gc_task (uint8_t priority, chunk_id_t move_from_chunk) {
353+ if (m_is_stopped.load ()) {
354+ LOGWARNMOD (gcmgr, " pdev gc actor for pdev_id={} is not started yet or already stopped, cannot add gc task!" ,
355+ m_pdev_id);
356+ return folly::makeSemiFuture< bool >(false );
357+ }
337358 auto EXvchunk = m_chunk_selector->get_extend_vchunk (move_from_chunk);
338359 // it does not belong to any pg, so we don't need to gc it.
339360 if (!EXvchunk->m_pg_id .has_value ()) {
0 commit comments