public inbox for linux-mtd@lists.infradead.org
 help / color / mirror / Atom feed
* [PATCH] MTD: Retry Read/Write Transfer Buffer Allocations
@ 2011-04-02  0:44 Grant Erickson
  2011-04-04  7:27 ` Artem Bityutskiy
  2011-04-04 18:19 ` [PATCH v2] " Grant Erickson
  0 siblings, 2 replies; 11+ messages in thread
From: Grant Erickson @ 2011-04-02  0:44 UTC (permalink / raw)
  To: linux-mtd

When handling user space read or write requests via mtd_{read,write},
exponentially back 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>
---
 drivers/mtd/mtdchar.c |   30 ++++++++++++++----------------
 1 files changed, 14 insertions(+), 16 deletions(-)

diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 145b3d0d..d887b91 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -179,6 +179,7 @@ static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t
 	size_t total_retlen=0;
 	int ret=0;
 	int len;
+	size_t size;
 	char *kbuf;
 
 	DEBUG(MTD_DEBUG_LEVEL0,"MTD_read\n");
@@ -192,20 +193,18 @@ static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t
 	/* FIXME: Use kiovec in 2.5 to lock down the user's buffers
 	   and pass them directly to the MTD functions */
 
-	if (count > MAX_KMALLOC_SIZE)
-		kbuf=kmalloc(MAX_KMALLOC_SIZE, GFP_KERNEL);
-	else
-		kbuf=kmalloc(count, GFP_KERNEL);
+	size = min_t(size_t, count, MAX_KMALLOC_SIZE);
+
+	do {
+		kbuf=kmalloc(size, GFP_KERNEL);
+	} while (!kbuf && ((size >>= 1) >= PAGE_SIZE));
 
 	if (!kbuf)
 		return -ENOMEM;
 
 	while (count) {
 
-		if (count > MAX_KMALLOC_SIZE)
-			len = MAX_KMALLOC_SIZE;
-		else
-			len = count;
+		len = min_t(size_t, count, size);
 
 		switch (mfi->mode) {
 		case MTD_MODE_OTP_FACTORY:
@@ -268,6 +267,7 @@ static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count
 {
 	struct mtd_file_info *mfi = file->private_data;
 	struct mtd_info *mtd = mfi->mtd;
+	size_t size;
 	char *kbuf;
 	size_t retlen;
 	size_t total_retlen=0;
@@ -285,20 +285,18 @@ static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count
 	if (!count)
 		return 0;
 
-	if (count > MAX_KMALLOC_SIZE)
-		kbuf=kmalloc(MAX_KMALLOC_SIZE, GFP_KERNEL);
-	else
-		kbuf=kmalloc(count, GFP_KERNEL);
+	size = min_t(size_t, count, MAX_KMALLOC_SIZE);
+
+	do {
+		kbuf=kmalloc(size, GFP_KERNEL);
+	} while (!kbuf && ((size >>= 1) >= PAGE_SIZE));
 
 	if (!kbuf)
 		return -ENOMEM;
 
 	while (count) {
 
-		if (count > MAX_KMALLOC_SIZE)
-			len = MAX_KMALLOC_SIZE;
-		else
-			len = count;
+		len = min_t(size_t, count, size);
 
 		if (copy_from_user(kbuf, buf, len)) {
 			kfree(kbuf);
-- 
1.7.4.2

^ permalink raw reply related	[flat|nested] 11+ messages in thread
* [PATCH] JFFS2: Retry Medium Scan Buffer Allocations
@ 2011-04-02  1:29 Grant Erickson
  2011-04-04 18:39 ` [PATCH] MTD: Retry Read/Write Transfer " Grant Erickson
  0 siblings, 1 reply; 11+ messages in thread
From: Grant Erickson @ 2011-04-02  1:29 UTC (permalink / raw)
  To: linux-mtd

When handling a JFFS2 medium scan request exponentially back off on
the size of the requested scan buffer until it succeeds or until the
requested scan buffer size falls below a page. This helps ensure the
allocation and subsequent scan operation can succeed under low-memory,
highly-fragmented situations albeit somewhat more slowly.

Signed-off-by: Grant Erickson <marathon96@gmail.com>
---
 fs/jffs2/scan.c |   11 +++++++----
 1 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
index b632ddd..4d8746d 100644
--- a/fs/jffs2/scan.c
+++ b/fs/jffs2/scan.c
@@ -118,11 +118,14 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
 			buf_size = PAGE_SIZE;
 
 		/* Respect kmalloc limitations */
-		if (buf_size > 128*1024)
-			buf_size = 128*1024;
+		buf_size = min_t(uint32_t, buf_size, 128*1024);
+
+		do {
+			D1(printk(KERN_DEBUG "Trying to allocate readbuf of %d "
+					  "bytes\n", buf_size));
+			flashbuf = kmalloc(buf_size, GFP_KERNEL);
+		} while (!flashbuf && ((buf_size >>= 1) >= PAGE_SIZE));
 
-		D1(printk(KERN_DEBUG "Allocating readbuf of %d bytes\n", buf_size));
-		flashbuf = kmalloc(buf_size, GFP_KERNEL);
 		if (!flashbuf)
 			return -ENOMEM;
 	}
-- 
1.7.4.2

^ permalink raw reply related	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2011-04-05 16:57 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-04-02  0:44 [PATCH] MTD: Retry Read/Write Transfer Buffer Allocations Grant Erickson
2011-04-04  7:27 ` Artem Bityutskiy
2011-04-04  7:41   ` Artem Bityutskiy
2011-04-04 16:05   ` Grant Erickson
2011-04-05  4:39     ` Artem Bityutskiy
2011-04-04 18:19 ` [PATCH v2] " Grant Erickson
2011-04-05  4:39   ` Artem Bityutskiy
2011-04-05 15:54     ` Grant Erickson
2011-04-05 16:54       ` Artem Bityutskiy
2011-04-05  4:48   ` Artem Bityutskiy
  -- strict thread matches above, loose matches on Subject: below --
2011-04-02  1:29 [PATCH] JFFS2: Retry Medium Scan " Grant Erickson
2011-04-04 18:39 ` [PATCH] MTD: Retry Read/Write Transfer " Grant Erickson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox