bcachefs: allocate_dropping_locks()
authorKent Overstreet <kent.overstreet@linux.dev>
Sun, 28 May 2023 07:44:38 +0000 (03:44 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:10:03 +0000 (17:10 -0400)
Add two new helpers for allocating memory with btree locks held: The
idea is to first try the allocation with GFP_NOWAIT|__GFP_NOWARN, then
if that fails - unlock, retry with GFP_KERNEL, and then call
trans_relock().

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

index 9676aa335b8932fa879e718d5ef6167ab53f1d00..d2af3f38e6f524f66bfd0dc109dc10c41145191b 100644 (file)
@@ -859,6 +859,32 @@ __bch2_btree_iter_peek_upto_and_restart(struct btree_trans *trans,
        bch2_trans_unlock(_trans);                                      \
        _do ?: bch2_trans_relock(_trans);                               \
 })
+
+#define allocate_dropping_locks_errcode(_trans, _do)                   \
+({                                                                     \
+       gfp_t _gfp = GFP_NOWAIT|__GFP_NOWARN;                           \
+       int _ret = _do;                                                 \
+                                                                       \
+       if (bch2_err_matches(_ret, ENOMEM)) {                           \
+               _gfp = GFP_KERNEL;                                      \
+               _ret = drop_locks_do(trans, _do);                       \
+       }                                                               \
+       _ret;                                                           \
+})
+
+#define allocate_dropping_locks(_trans, _ret, _do)                     \
+({                                                                     \
+       gfp_t _gfp = GFP_NOWAIT|__GFP_NOWARN;                           \
+       typeof(_do) _p = _do;                                           \
+                                                                       \
+       _ret = 0;                                                       \
+       if (unlikely(!_p)) {                                            \
+               _gfp = GFP_KERNEL;                                      \
+               _ret = drop_locks_do(trans, ((_p = _do), 0));           \
+       }                                                               \
+       _p;                                                             \
+})
+
 /* new multiple iterator interface: */
 
 void bch2_trans_updates_to_text(struct printbuf *, struct btree_trans *);
index 37977b774d616e110743c09f39e419e651eb0ccb..37beb75e25715a41c12e4b19942b3b0005e4240c 100644 (file)
@@ -264,15 +264,8 @@ bkey_cached_alloc(struct btree_trans *trans, struct btree_path *path,
                return ck;
        }
 
-       ck = kmem_cache_zalloc(bch2_key_cache, GFP_NOWAIT|__GFP_NOWARN);
-       if (likely(ck))
-               goto init;
-
-       bch2_trans_unlock(trans);
-
-       ck = kmem_cache_zalloc(bch2_key_cache, GFP_KERNEL);
-
-       ret = bch2_trans_relock(trans);
+       ck = allocate_dropping_locks(trans, ret,
+                       kmem_cache_zalloc(bch2_key_cache, _gfp));
        if (ret) {
                kmem_cache_free(bch2_key_cache, ck);
                return ERR_PTR(ret);
@@ -280,7 +273,7 @@ bkey_cached_alloc(struct btree_trans *trans, struct btree_path *path,
 
        if (!ck)
                return NULL;
-init:
+
        INIT_LIST_HEAD(&ck->list);
        bch2_btree_lock_init(&ck->c, pcpu_readers ? SIX_LOCK_INIT_PCPU : 0);
 
index 1c35fa1fedd3fdf48a0df4221f0db69a6e466857..dfc0a61afa511d4f8d27ef9b3c46bd2f6ae14dfe 100644 (file)
@@ -578,15 +578,8 @@ static int __ec_stripe_mem_alloc(struct bch_fs *c, size_t idx, gfp_t gfp)
 static int ec_stripe_mem_alloc(struct btree_trans *trans,
                               struct btree_iter *iter)
 {
-       size_t idx = iter->pos.offset;
-
-       if (!__ec_stripe_mem_alloc(trans->c, idx, GFP_NOWAIT|__GFP_NOWARN))
-               return 0;
-
-       bch2_trans_unlock(trans);
-
-       return   __ec_stripe_mem_alloc(trans->c, idx, GFP_KERNEL) ?:
-               bch2_trans_relock(trans);
+       return allocate_dropping_locks_errcode(trans,
+                       __ec_stripe_mem_alloc(trans->c, iter->pos.offset, _gfp));
 }
 
 /*