From: Grant Erickson <marathon96@gmail.com>
To: linux-mtd@lists.infradead.org
Cc: Jarkko Lavinen <jarkko.lavinen@nokia.com>,
Artem Bityutskiy <dedekind1@gmail.com>
Subject: [PATCH v5 1/3] MTD: Create Function to Perform Large Allocations
Date: Fri, 8 Apr 2011 08:51:32 -0700 [thread overview]
Message-ID: <1302277894-26132-2-git-send-email-marathon96@gmail.com> (raw)
In-Reply-To: <1302277894-26132-1-git-send-email-marathon96@gmail.com>
Introduce a common function to handle large, contiguous kmalloc buffer
allocations by exponentially backing off on the size of the requested
kernel transfer buffer until it succeeds or until the requested
transfer buffer size falls below the page size.
This helps ensure the operation can succeed under low-memory, highly-
fragmented situations albeit somewhat more slowly.
Signed-off-by: Grant Erickson <marathon96@gmail.com>
Tested-by: Ben Gardiner <bengardiner at nanometrics.ca>
---
drivers/mtd/mtdcore.c | 41 +++++++++++++++++++++++++++++++++++++++++
include/linux/mtd/mtd.h | 2 ++
2 files changed, 43 insertions(+), 0 deletions(-)
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index da69bc8..6f720cc 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -638,6 +638,46 @@ int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs,
return ret;
}
+/**
+ * mtd_kmalloc_up_to - allocate a contiguous buffer up to the specified size
+ * @size: A pointer to the ideal or maximum size of the allocation. Points
+ * to the actual allocation size on success.
+ *
+ * This routine attempts to allocate a contiguous kernel buffer up to
+ * the specified size, backing off the size of the request exponentially
+ * until the request succeeds or until the allocation size falls below
+ * the system page size. This attempts to make sure it does not adversely
+ * impact system performance, so when allocating more than one page, we
+ * ask the memory allocator to avoid re-trying, swapping, writing back
+ * or performing I/O.
+ *
+ * This is called, for example by mtd_{read,write} and jffs2_scan_medium,
+ * to handle smaller (i.e. degraded) buffer allocations under low- or
+ * fragmented-memory situations where such reduced allocations, from a
+ * requested ideal, are allowed.
+ *
+ * Returns a pointer to the allocated buffer on success; otherwise, NULL.
+ */
+void *mtd_kmalloc_up_to(size_t *size)
+{
+ gfp_t flags = __GFP_NOWARN | __GFP_WAIT |
+ __GFP_NORETRY | __GFP_NO_KSWAPD;
+ size_t try;
+ void *kbuf;
+
+ try = min_t(size_t, *size, KMALLOC_MAX_SIZE);
+
+ do {
+ if (try <= PAGE_SIZE)
+ flags = GFP_KERNEL;
+
+ kbuf = kmalloc(try, flags);
+ } while (!kbuf && ((try >>= 1) >= PAGE_SIZE));
+
+ *size = try;
+ return kbuf;
+}
+
EXPORT_SYMBOL_GPL(add_mtd_device);
EXPORT_SYMBOL_GPL(del_mtd_device);
EXPORT_SYMBOL_GPL(get_mtd_device);
@@ -648,6 +688,7 @@ EXPORT_SYMBOL_GPL(__put_mtd_device);
EXPORT_SYMBOL_GPL(register_mtd_user);
EXPORT_SYMBOL_GPL(unregister_mtd_user);
EXPORT_SYMBOL_GPL(default_mtd_writev);
+EXPORT_SYMBOL_GPL(mtd_kmalloc_up_to);
#ifdef CONFIG_PROC_FS
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 9d5306b..a5d31ba 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -348,7 +348,8 @@ int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs,
int default_mtd_readv(struct mtd_info *mtd, struct kvec *vecs,
unsigned long count, loff_t from, size_t *retlen);
+void *mtd_kmalloc_up_to(size_t *size);
+
#ifdef CONFIG_MTD_PARTITIONS
void mtd_erase_callback(struct erase_info *instr);
#else
--
1.7.4.2
next prev parent reply other threads:[~2011-04-08 15:52 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-04-08 15:51 [PATCH v5 0/3] Retry Large Buffer Allocations Grant Erickson
2011-04-08 15:51 ` Grant Erickson [this message]
2011-04-08 15:51 ` [PATCH v5 2/3] MTD: " Grant Erickson
2011-04-08 15:51 ` [PATCH v5 3/3] JFFS2: " Grant Erickson
2011-04-09 14:38 ` Artem Bityutskiy
2011-04-09 14:28 ` [PATCH v5 0/3] " Artem Bityutskiy
2011-04-11 12:40 ` Ben Gardiner
2011-04-13 4:05 ` Artem Bityutskiy
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=1302277894-26132-2-git-send-email-marathon96@gmail.com \
--to=marathon96@gmail.com \
--cc=dedekind1@gmail.com \
--cc=jarkko.lavinen@nokia.com \
--cc=linux-mtd@lists.infradead.org \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.