bcachefs: Fix a write buffer flush deadlock
authorKent Overstreet <kent.overstreet@linux.dev>
Mon, 10 Jul 2023 15:17:56 +0000 (11:17 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:10:06 +0000 (17:10 -0400)
We're not supposed to block if BTREE_INSERT_JOURNAL_RECLAIM && watermark
!= BCH_WATERMARK_reclaim.

This should really be a separate BTREE_INSERT_NONBLOCK flag - add some
comments to that effect, it's not important for this patch.

btree write buffer flush depends on this behaviour though - the first
loop tries to flush sequentially, which doesn't free up space in the
journal optimally. If that can't proceed we bail out and flush in
journal order - that won't work if we're blocked instead of returning an
error.

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

index 5592feff79d17760dc504155b7ca39c111c5fd39..3659b2c08109b71bb09e5d7fc166b6f049e92ab2 100644 (file)
@@ -1158,6 +1158,17 @@ bch2_btree_update_start(struct btree_trans *trans, struct btree_path *path,
            bch2_err_matches(ret, ENOMEM)) {
                struct closure cl;
 
+               /*
+                * XXX: this should probably be a separate BTREE_INSERT_NONBLOCK
+                * flag
+                */
+               if (bch2_err_matches(ret, ENOSPC) &&
+                   (flags & BTREE_INSERT_JOURNAL_RECLAIM) &&
+                   watermark != BCH_WATERMARK_reclaim) {
+                       ret = -BCH_ERR_journal_reclaim_would_deadlock;
+                       goto err;
+               }
+
                closure_init_stack(&cl);
 
                do {
index 6e12e8e7c301b045f1d47877a2123e70f690b21b..53219fdcff667b29cf86baeacc19e8fa499b4291 100644 (file)
@@ -958,6 +958,10 @@ int bch2_trans_commit_error(struct btree_trans *trans, unsigned flags,
                        bch2_replicas_delta_list_mark(c, trans->fs_usage_deltas));
                break;
        case -BCH_ERR_journal_res_get_blocked:
+               /*
+                * XXX: this should probably be a separate BTREE_INSERT_NONBLOCK
+                * flag
+                */
                if ((flags & BTREE_INSERT_JOURNAL_RECLAIM) &&
                    (flags & BCH_WATERMARK_MASK) != BCH_WATERMARK_reclaim) {
                        ret = -BCH_ERR_journal_reclaim_would_deadlock;