summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Behlendorf <[email protected]>2015-01-29 16:08:25 -0800
committerBrian Behlendorf <[email protected]>2015-02-02 10:57:56 -0800
commitc7db36a3c4ac768a74bd86778cc3535bdcb8d526 (patch)
tree3ba5c7c1d6f8b6f28d9a26e7e373fcf39722ef02
parent54cccfc2e30fa84463c056e8ad04b2be9448999e (diff)
Optimize vmem_alloc() retry path
For performance reasons the reworked kmem code maps vmem_alloc() to kmalloc_node() for allocations less than spa_kmem_alloc_max. This allows for more concurrency in the system and less contention of the virtual address space. Generally, this is a good thing. However, in the case when the kmalloc_node() fails it makes little sense to retry it using kmalloc_node() again. It will likely fail in exactly the same way. A smarter strategy is to abandon this optimization and retry using spl_vmalloc() which is very likely to succeed. Signed-off-by: Brian Behlendorf <[email protected]> Signed-off-by: Ned Bass <[email protected]> Closes #428
-rw-r--r--module/spl/spl-kmem.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/module/spl/spl-kmem.c b/module/spl/spl-kmem.c
index e97d5f255..92263f8f4 100644
--- a/module/spl/spl-kmem.c
+++ b/module/spl/spl-kmem.c
@@ -149,6 +149,7 @@ inline void *
spl_kmem_alloc_impl(size_t size, int flags, int node)
{
gfp_t lflags = kmem_flags_convert(flags);
+ int use_vmem = 0;
void *ptr;
/*
@@ -182,7 +183,7 @@ spl_kmem_alloc_impl(size_t size, int flags, int node)
* impact performance so frequently manipulating the virtual
* address space is strongly discouraged.
*/
- if (unlikely(size > spl_kmem_alloc_max)) {
+ if ((size > spl_kmem_alloc_max) || use_vmem) {
if (flags & KM_VMEM) {
ptr = spl_vmalloc(size, lflags, PAGE_KERNEL);
} else {
@@ -195,6 +196,15 @@ spl_kmem_alloc_impl(size_t size, int flags, int node)
if (likely(ptr) || (flags & KM_NOSLEEP))
return (ptr);
+ /*
+ * For vmem_alloc() and vmem_zalloc() callers retry immediately
+ * using spl_vmalloc() which is unlikely to fail.
+ */
+ if ((flags & KM_VMEM) && (use_vmem == 0)) {
+ use_vmem = 1;
+ continue;
+ }
+
if (unlikely(__ratelimit(&kmem_alloc_ratelimit_state))) {
printk(KERN_WARNING
"Possible memory allocation deadlock: "