diff options
Diffstat (limited to 'fs/bcachefs/move.c')
-rw-r--r-- | fs/bcachefs/move.c | 34 |
1 files changed, 26 insertions, 8 deletions
diff --git a/fs/bcachefs/move.c b/fs/bcachefs/move.c index 4a5e435bfe4b..65188f1aa966 100644 --- a/fs/bcachefs/move.c +++ b/fs/bcachefs/move.c @@ -471,7 +471,7 @@ int bch2_move_data(struct bch_fs *c, struct bkey_s_c_extent e; struct data_opts data_opts; enum data_cmd data_cmd; - u64 cur_inum = U64_MAX; + u64 delay, cur_inum = U64_MAX; int ret = 0, ret2; closure_init_stack(&ctxt.cl); @@ -485,12 +485,30 @@ int bch2_move_data(struct bch_fs *c, if (rate) bch2_ratelimit_reset(rate); - while (!kthread || !(ret = kthread_should_stop())) { - if (rate && - bch2_ratelimit_delay(rate) && - (bch2_btree_iter_unlock(&stats->iter), - (ret = bch2_ratelimit_wait_freezable_stoppable(rate)))) - break; + while (1) { + do { + delay = rate ? bch2_ratelimit_delay(rate) : 0; + + if (delay) { + bch2_btree_iter_unlock(&stats->iter); + set_current_state(TASK_INTERRUPTIBLE); + } + + if (kthread && (ret = kthread_should_stop())) { + __set_current_state(TASK_RUNNING); + goto out; + } + + if (delay) + schedule_timeout(delay); + + if (unlikely(freezing(current))) { + bch2_btree_iter_unlock(&stats->iter); + move_ctxt_wait_event(&ctxt, list_empty(&ctxt.reads)); + closure_sync(&ctxt.cl); + try_to_freeze(); + } + } while (delay); peek: k = bch2_btree_iter_peek(&stats->iter); if (!k.k) @@ -561,7 +579,7 @@ next_nondata: bch2_btree_iter_next(&stats->iter); bch2_btree_iter_cond_resched(&stats->iter); } - +out: bch2_btree_iter_unlock(&stats->iter); move_ctxt_wait_event(&ctxt, list_empty(&ctxt.reads)); |