diff options
author | Kent Overstreet <kent.overstreet@linux.dev> | 2023-11-22 23:44:47 -0500 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-11-24 02:10:28 -0500 |
commit | 261af2f1c6b668586325a37df02f904c1c273a7d (patch) | |
tree | 1aa07653d56d441193b143186bb947c5dce024af /fs/bcachefs | |
parent | 50e029c6390a6795869b742a5fce1e57d6a76c82 (diff) |
bcachefs: Make sure bch2_move_ratelimit() also waits for move_ops
This adds move_ctxt_wait_event_timeout(), which can sleep for a timeout
while also issueing pending moves as reads complete.
Co-developed-by: Daniel Hill <daniel@gluo.nz>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs/bcachefs')
-rw-r--r-- | fs/bcachefs/move.c | 17 | ||||
-rw-r--r-- | fs/bcachefs/move.h | 19 |
2 files changed, 23 insertions, 13 deletions
diff --git a/fs/bcachefs/move.c b/fs/bcachefs/move.c index 7819ed8d9df9..71f865352816 100644 --- a/fs/bcachefs/move.c +++ b/fs/bcachefs/move.c @@ -500,22 +500,13 @@ int bch2_move_ratelimit(struct moving_context *ctxt) do { delay = ctxt->rate ? bch2_ratelimit_delay(ctxt->rate) : 0; - - if (delay) { - if (delay > HZ / 10) - bch2_trans_unlock_long(ctxt->trans); - else - bch2_trans_unlock(ctxt->trans); - set_current_state(TASK_INTERRUPTIBLE); - } - - if ((current->flags & PF_KTHREAD) && kthread_should_stop()) { - __set_current_state(TASK_RUNNING); + if ((current->flags & PF_KTHREAD) && kthread_should_stop()) return 1; - } if (delay) - schedule_timeout(delay); + move_ctxt_wait_event_timeout(ctxt, + freezing(current) || kthread_should_stop(), + delay); if (unlikely(freezing(current))) { bch2_moving_ctxt_flush_all(ctxt); diff --git a/fs/bcachefs/move.h b/fs/bcachefs/move.h index 07cf9d42643b..0906aa2d1de2 100644 --- a/fs/bcachefs/move.h +++ b/fs/bcachefs/move.h @@ -38,6 +38,25 @@ struct moving_context { wait_queue_head_t wait; }; +#define move_ctxt_wait_event_timeout(_ctxt, _cond, _timeout) \ +({ \ + int _ret = 0; \ + while (true) { \ + bool cond_finished = false; \ + bch2_moving_ctxt_do_pending_writes(_ctxt); \ + \ + if (_cond) \ + break; \ + bch2_trans_unlock_long((_ctxt)->trans); \ + _ret = __wait_event_timeout((_ctxt)->wait, \ + bch2_moving_ctxt_next_pending_write(_ctxt) || \ + (cond_finished = (_cond)), _timeout); \ + if (_ret || ( cond_finished)) \ + break; \ + } \ + _ret; \ +}) + #define move_ctxt_wait_event(_ctxt, _cond) \ do { \ bool cond_finished = false; \ |