]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
bcachefs: Always give out journal pre-res if we already have one
authorKent Overstreet <kent.overstreet@gmail.com>
Wed, 10 Jun 2020 00:54:36 +0000 (20:54 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:08:41 +0000 (17:08 -0400)
This is better than skipping the journal pre-reservation if we already
have one - we should still acount for the journal reservation we're
going to have to get.

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

index 8f4087db7b6732f74996664d1c580f87dc2d83a0..bb921852a093213086d946bc1bc3a2dc641677df 100644 (file)
@@ -864,8 +864,11 @@ bch2_btree_update_start(struct btree_trans *trans, enum btree_id id,
 {
        struct bch_fs *c = trans->c;
        struct btree_update *as;
-       int ret, disk_res_flags = (flags & BTREE_INSERT_NOFAIL)
+       int disk_res_flags = (flags & BTREE_INSERT_NOFAIL)
                ? BCH_DISK_RESERVATION_NOFAIL : 0;
+       int journal_flags = (flags & BTREE_INSERT_JOURNAL_RESERVED)
+               ? JOURNAL_RES_GET_RECLAIM : 0;
+       int ret = 0;
 
        /*
         * This check isn't necessary for correctness - it's just to potentially
@@ -888,10 +891,9 @@ bch2_btree_update_start(struct btree_trans *trans, enum btree_id id,
        bch2_keylist_init(&as->new_keys, as->_new_keys);
        bch2_keylist_init(&as->parent_keys, as->inline_keys);
 
-       if (!(flags & BTREE_INSERT_JOURNAL_RESERVED))
-               ret = bch2_journal_preres_get(&c->journal, &as->journal_preres,
-                                             BTREE_UPDATE_JOURNAL_RES,
-                                             JOURNAL_RES_GET_NONBLOCK);
+       ret = bch2_journal_preres_get(&c->journal, &as->journal_preres,
+                                     BTREE_UPDATE_JOURNAL_RES,
+                                     journal_flags|JOURNAL_RES_GET_NONBLOCK);
        if (ret == -EAGAIN) {
                if (flags & BTREE_INSERT_NOUNLOCK)
                        return ERR_PTR(-EINTR);
@@ -899,7 +901,8 @@ bch2_btree_update_start(struct btree_trans *trans, enum btree_id id,
                bch2_trans_unlock(trans);
 
                ret = bch2_journal_preres_get(&c->journal, &as->journal_preres,
-                                             BTREE_UPDATE_JOURNAL_RES, 0);
+                               BTREE_UPDATE_JOURNAL_RES,
+                               journal_flags);
                if (ret)
                        return ERR_PTR(ret);
 
index 48607e01bd22d940faeeef0fa2b8dc208ea7fd0e..767cb6f809e78ace5943373611ad031d543f32ee 100644 (file)
@@ -427,9 +427,10 @@ int bch2_journal_res_get_slowpath(struct journal *j, struct journal_res *res,
 
 static bool journal_preres_available(struct journal *j,
                                     struct journal_preres *res,
-                                    unsigned new_u64s)
+                                    unsigned new_u64s,
+                                    unsigned flags)
 {
-       bool ret = bch2_journal_preres_get_fast(j, res, new_u64s);
+       bool ret = bch2_journal_preres_get_fast(j, res, new_u64s, flags);
 
        if (!ret)
                bch2_journal_reclaim_work(&j->reclaim_work.work);
@@ -439,13 +440,14 @@ static bool journal_preres_available(struct journal *j,
 
 int __bch2_journal_preres_get(struct journal *j,
                              struct journal_preres *res,
-                             unsigned new_u64s)
+                             unsigned new_u64s,
+                             unsigned flags)
 {
        int ret;
 
        closure_wait_event(&j->preres_wait,
                   (ret = bch2_journal_error(j)) ||
-                  journal_preres_available(j, res, new_u64s));
+                  journal_preres_available(j, res, new_u64s, flags));
        return ret;
 }
 
index 2c55f74522e2d948ee5e1f9b19478dc5adcc41ad..f14dfa59e7021e459465ad9786fae4ddc060bdd7 100644 (file)
@@ -301,6 +301,7 @@ int bch2_journal_res_get_slowpath(struct journal *, struct journal_res *,
 #define JOURNAL_RES_GET_NONBLOCK       (1 << 0)
 #define JOURNAL_RES_GET_CHECK          (1 << 1)
 #define JOURNAL_RES_GET_RESERVED       (1 << 2)
+#define JOURNAL_RES_GET_RECLAIM                (1 << 3)
 
 static inline int journal_res_get_fast(struct journal *j,
                                       struct journal_res *res,
@@ -408,11 +409,12 @@ static inline void bch2_journal_preres_put(struct journal *j,
 }
 
 int __bch2_journal_preres_get(struct journal *,
-                       struct journal_preres *, unsigned);
+                       struct journal_preres *, unsigned, unsigned);
 
 static inline int bch2_journal_preres_get_fast(struct journal *j,
                                               struct journal_preres *res,
-                                              unsigned new_u64s)
+                                              unsigned new_u64s,
+                                              unsigned flags)
 {
        int d = new_u64s - res->u64s;
        union journal_preres_state old, new;
@@ -423,7 +425,15 @@ static inline int bch2_journal_preres_get_fast(struct journal *j,
 
                new.reserved += d;
 
-               if (new.reserved > new.remaining)
+               /*
+                * If we're being called from the journal reclaim path, we have
+                * to unconditionally give out the pre-reservation, there's
+                * nothing else sensible we can do - otherwise we'd recurse back
+                * into the reclaim path and deadlock:
+                */
+
+               if (!(flags & JOURNAL_RES_GET_RECLAIM) &&
+                   new.reserved > new.remaining)
                        return 0;
        } while ((v = atomic64_cmpxchg(&j->prereserved.counter,
                                       old.v, new.v)) != old.v);
@@ -440,13 +450,13 @@ static inline int bch2_journal_preres_get(struct journal *j,
        if (new_u64s <= res->u64s)
                return 0;
 
-       if (bch2_journal_preres_get_fast(j, res, new_u64s))
+       if (bch2_journal_preres_get_fast(j, res, new_u64s, flags))
                return 0;
 
        if (flags & JOURNAL_RES_GET_NONBLOCK)
                return -EAGAIN;
 
-       return __bch2_journal_preres_get(j, res, new_u64s);
+       return __bch2_journal_preres_get(j, res, new_u64s, flags);
 }
 
 /* journal_entry_res: */