bcachefs: Fix a bug with spinning on the journal
authorKent Overstreet <kent.overstreet@gmail.com>
Wed, 15 May 2019 13:49:46 +0000 (09:49 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:08:22 +0000 (17:08 -0400)
Transactional triggers meant that when we failed to get a journal
reservation, then bailed out into the error path to block on a journal
reservation, the second blocking call into the journal code was asking
for less space, which is not what we want.

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

index d88f1c911d047e3f514625951a043eb9a72df0d0..9bab213fd65b8319fa51b60073c888b6656e50db 100644 (file)
@@ -301,6 +301,7 @@ struct btree_trans {
        u64                     *journal_seq;
        struct disk_reservation *disk_res;
        unsigned                flags;
+       unsigned                journal_u64s;
 
        struct btree_iter       iters_onstack[2];
        struct btree_insert_entry updates_onstack[6];
index 7286a5b45481083f0264b121e2c1e5d2f132c5f9..88e038c1cceff154ed56d5f4fd37adc2e80323bb 100644 (file)
@@ -451,21 +451,13 @@ static int bch2_trans_journal_res_get(struct btree_trans *trans,
                                      unsigned flags)
 {
        struct bch_fs *c = trans->c;
-       struct btree_insert_entry *i;
-       unsigned u64s = 0;
        int ret;
 
-       if (unlikely(trans->flags & BTREE_INSERT_JOURNAL_REPLAY))
-               return 0;
-
        if (trans->flags & BTREE_INSERT_JOURNAL_RESERVED)
                flags |= JOURNAL_RES_GET_RESERVED;
 
-       trans_for_each_update(trans, i)
-               u64s += jset_u64s(i->k->k.u64s);
-
        ret = bch2_journal_res_get(&c->journal, &trans->journal_res,
-                                  u64s, flags);
+                                  trans->journal_u64s, flags);
 
        return ret == -EAGAIN ? BTREE_INSERT_NEED_JOURNAL_RES : ret;
 }
@@ -612,9 +604,16 @@ static inline int do_btree_insert_at(struct btree_trans *trans,
         * Don't get journal reservation until after we know insert will
         * succeed:
         */
-       ret = bch2_trans_journal_res_get(trans, JOURNAL_RES_GET_NONBLOCK);
-       if (ret)
-               goto out;
+       if (likely(!(trans->flags & BTREE_INSERT_JOURNAL_REPLAY))) {
+               trans->journal_u64s = 0;
+
+               trans_for_each_update(trans, i)
+                       trans->journal_u64s += jset_u64s(i->k->k.u64s);
+
+               ret = bch2_trans_journal_res_get(trans, JOURNAL_RES_GET_NONBLOCK);
+               if (ret)
+                       goto out;
+       }
 
        if (!(trans->flags & BTREE_INSERT_JOURNAL_REPLAY)) {
                if (journal_seq_verify(c))