aboutsummaryrefslogtreecommitdiffstats
path: root/module/os/linux/spl
diff options
context:
space:
mode:
authorBrian Behlendorf <[email protected]>2023-06-07 10:43:43 -0700
committerGitHub <[email protected]>2023-06-07 10:43:43 -0700
commit93f8abeff08e9c4363ec4d53d501cf21830c95e1 (patch)
tree638be48d4991e995d9bcbd6716be1fa544496b99 /module/os/linux/spl
parentbcd5321039c3de29c14eac1068d392c15ad7fe2c (diff)
Linux: Never sleep in kmem_cache_alloc(..., KM_NOSLEEP) (#14926)
When a kmem cache is exhausted and needs to be expanded a new slab is allocated. KM_SLEEP callers can block and wait for the allocation, but KM_NOSLEEP callers were incorrectly allowed to block as well. Resolve this by attempting an emergency allocation as a best effort. This may fail but that's fine since any KM_NOSLEEP consumer is required to handle an allocation failure. Signed-off-by: Brian Behlendorf <[email protected]> Reviewed-by: Adam Moss <[email protected]> Reviewed-by: Brian Atkinson <[email protected]> Reviewed-by: Richard Yao <[email protected]> Reviewed-by: Tony Hutter <[email protected]>
Diffstat (limited to 'module/os/linux/spl')
-rw-r--r--module/os/linux/spl/spl-kmem-cache.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/module/os/linux/spl/spl-kmem-cache.c b/module/os/linux/spl/spl-kmem-cache.c
index 745d03012..3c30dfc57 100644
--- a/module/os/linux/spl/spl-kmem-cache.c
+++ b/module/os/linux/spl/spl-kmem-cache.c
@@ -1015,10 +1015,20 @@ spl_cache_grow(spl_kmem_cache_t *skc, int flags, void **obj)
ASSERT0(flags & ~KM_PUBLIC_MASK);
ASSERT(skc->skc_magic == SKC_MAGIC);
ASSERT((skc->skc_flags & KMC_SLAB) == 0);
- might_sleep();
+
*obj = NULL;
/*
+ * Since we can't sleep attempt an emergency allocation to satisfy
+ * the request. The only alterative is to fail the allocation but
+ * it's preferable try. The use of KM_NOSLEEP is expected to be rare.
+ */
+ if (flags & KM_NOSLEEP)
+ return (spl_emergency_alloc(skc, flags, obj));
+
+ might_sleep();
+
+ /*
* Before allocating a new slab wait for any reaping to complete and
* then return so the local magazine can be rechecked for new objects.
*/