bcachefs: bch2_moving_ctxt_flush_all()
authorKent Overstreet <kent.overstreet@linux.dev>
Mon, 20 Nov 2023 22:24:32 +0000 (17:24 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Fri, 24 Nov 2023 07:08:25 +0000 (02:08 -0500)
Introduce a new helper to flush all move IOs, and use it in a few places
where we should have been.

The new helper also drops btree locks before waiting on outstanding move
writes, avoiding potential deadlocks.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/move.c

index ab749bf2fcbc551e68753857efdf008848d140b7..7819ed8d9df97d4f1493d369e0ff157744fa405f 100644 (file)
@@ -163,12 +163,18 @@ void bch2_move_ctxt_wait_for_io(struct moving_context *ctxt)
                atomic_read(&ctxt->write_sectors) != sectors_pending);
 }
 
+static void bch2_moving_ctxt_flush_all(struct moving_context *ctxt)
+{
+       move_ctxt_wait_event(ctxt, list_empty(&ctxt->reads));
+       bch2_trans_unlock_long(ctxt->trans);
+       closure_sync(&ctxt->cl);
+}
+
 void bch2_moving_ctxt_exit(struct moving_context *ctxt)
 {
        struct bch_fs *c = ctxt->trans->c;
 
-       move_ctxt_wait_event(ctxt, list_empty(&ctxt->reads));
-       closure_sync(&ctxt->cl);
+       bch2_moving_ctxt_flush_all(ctxt);
 
        EBUG_ON(atomic_read(&ctxt->write_sectors));
        EBUG_ON(atomic_read(&ctxt->write_ios));
@@ -484,8 +490,8 @@ int bch2_move_ratelimit(struct moving_context *ctxt)
        struct bch_fs *c = ctxt->trans->c;
        u64 delay;
 
-       if (ctxt->wait_on_copygc && !c->copygc_running) {
-               bch2_trans_unlock_long(ctxt->trans);
+       if (ctxt->wait_on_copygc && c->copygc_running) {
+               bch2_moving_ctxt_flush_all(ctxt);
                wait_event_killable(c->copygc_running_wq,
                                    !c->copygc_running ||
                                    kthread_should_stop());
@@ -512,7 +518,7 @@ int bch2_move_ratelimit(struct moving_context *ctxt)
                        schedule_timeout(delay);
 
                if (unlikely(freezing(current))) {
-                       move_ctxt_wait_event(ctxt, list_empty(&ctxt->reads));
+                       bch2_moving_ctxt_flush_all(ctxt);
                        try_to_freeze();
                }
        } while (delay);