From: Sultan Alsawaf <sultan@kerneltoast.com>
To: unlisted-recipients:; (no To-header on input)
Cc: Sultan Alsawaf <sultan@kerneltoast.com>,
Jason Gunthorpe <jgg@ziepe.ca>, Ming Lei <ming.lei@redhat.com>,
Palmer Dabbelt <palmer@sifive.com>,
"Martin K. Petersen" <martin.petersen@oracle.com>,
Gal Pressman <galpress@amazon.com>,
Allison Randal <allison@lohutok.net>,
Christophe Leroy <christophe.leroy@c-s.fr>,
Thomas Gleixner <tglx@linutronix.de>,
linux-kernel@vger.kernel.org
Subject: [PATCH] scatterlist: Allocate a contiguous array instead of chaining
Date: Thu, 11 Jul 2019 23:36:56 -0700 [thread overview]
Message-ID: <20190712063657.17088-1-sultan@kerneltoast.com> (raw)
From: Sultan Alsawaf <sultan@kerneltoast.com>
Typically, drivers allocate sg lists of sizes up to a few MiB in size.
The current algorithm deals with large sg lists by splitting them into
several smaller arrays and chaining them together. But if the sg list
allocation is large, and we know the size ahead of time, sg chaining is
both inefficient and unnecessary.
Rather than calling kmalloc hundreds of times in a loop for chaining
tiny arrays, we can simply do it all at once with kvmalloc, which has
the proper tradeoff on when to stop using kmalloc and instead use
vmalloc.
Abusing repeated kmallocs to produce a large allocation puts strain on
the slab allocator, when kvmalloc can be used instead. The single
kvmalloc allocation for all sg lists reduces the burden on the slab and
page allocators, since for large sg list allocations, this commit
replaces numerous kmalloc calls with one kvmalloc call.
The sg chaining is effectively disabled by changing SG_MAX_SINGLE_ALLOC
to UINT_MAX, which causes sg list allocations to never be split into
chains, since no allocation is larger than UINT_MAX. We then plumb
kvmalloc into the allocation functions so that it is used.
Signed-off-by: Sultan Alsawaf <sultan@kerneltoast.com>
---
include/linux/scatterlist.h | 2 +-
lib/scatterlist.c | 23 ++---------------------
2 files changed, 3 insertions(+), 22 deletions(-)
diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h
index 6eec50fb36c8..e2e26c53c441 100644
--- a/include/linux/scatterlist.h
+++ b/include/linux/scatterlist.h
@@ -310,7 +310,7 @@ size_t sg_zero_buffer(struct scatterlist *sgl, unsigned int nents,
* Maximum number of entries that will be allocated in one piece, if
* a list larger than this is required then chaining will be utilized.
*/
-#define SG_MAX_SINGLE_ALLOC (PAGE_SIZE / sizeof(struct scatterlist))
+#define SG_MAX_SINGLE_ALLOC (UINT_MAX)
/*
* The maximum number of SG segments that we will put inside a
diff --git a/lib/scatterlist.c b/lib/scatterlist.c
index c2cf2c311b7d..bf76854a34aa 100644
--- a/lib/scatterlist.c
+++ b/lib/scatterlist.c
@@ -148,31 +148,12 @@ EXPORT_SYMBOL(sg_init_one);
*/
static struct scatterlist *sg_kmalloc(unsigned int nents, gfp_t gfp_mask)
{
- if (nents == SG_MAX_SINGLE_ALLOC) {
- /*
- * Kmemleak doesn't track page allocations as they are not
- * commonly used (in a raw form) for kernel data structures.
- * As we chain together a list of pages and then a normal
- * kmalloc (tracked by kmemleak), in order to for that last
- * allocation not to become decoupled (and thus a
- * false-positive) we need to inform kmemleak of all the
- * intermediate allocations.
- */
- void *ptr = (void *) __get_free_page(gfp_mask);
- kmemleak_alloc(ptr, PAGE_SIZE, 1, gfp_mask);
- return ptr;
- } else
- return kmalloc_array(nents, sizeof(struct scatterlist),
- gfp_mask);
+ return kvmalloc_array(nents, sizeof(struct scatterlist), gfp_mask);
}
static void sg_kfree(struct scatterlist *sg, unsigned int nents)
{
- if (nents == SG_MAX_SINGLE_ALLOC) {
- kmemleak_free(sg);
- free_page((unsigned long) sg);
- } else
- kfree(sg);
+ kvfree(sg);
}
/**
--
2.22.0
next reply other threads:[~2019-07-12 6:37 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-07-12 6:36 Sultan Alsawaf [this message]
2019-07-12 6:56 ` [PATCH] scatterlist: Allocate a contiguous array instead of chaining Ming Lei
2019-07-12 7:06 ` Thomas Gleixner
2019-07-12 7:17 ` Sultan Alsawaf
2019-07-12 17:00 ` Andi Kleen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190712063657.17088-1-sultan@kerneltoast.com \
--to=sultan@kerneltoast.com \
--cc=allison@lohutok.net \
--cc=christophe.leroy@c-s.fr \
--cc=galpress@amazon.com \
--cc=jgg@ziepe.ca \
--cc=linux-kernel@vger.kernel.org \
--cc=martin.petersen@oracle.com \
--cc=ming.lei@redhat.com \
--cc=palmer@sifive.com \
--cc=tglx@linutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox