mtd/fs/jffs2 scan.c,1.85,1.86
David Woodhouse
dwmw2 at infradead.org
Thu Sep 5 12:40:26 EDT 2002
Update of /home/cvs/mtd/fs/jffs2
In directory phoenix.infradead.org:/tmp/cvs-serv7778
Modified Files:
scan.c
Log Message:
Remember to unpoint or kfree our read buffer. Use a whole sector read buffer for NAND.
Index: scan.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/scan.c,v
retrieving revision 1.85
retrieving revision 1.86
diff -u -r1.85 -r1.86
--- scan.c 5 Sep 2002 13:16:14 -0000 1.85
+++ scan.c 5 Sep 2002 16:40:23 -0000 1.86
@@ -17,7 +17,7 @@
#include <linux/crc32.h>
#include "nodelist.h"
-#define SCAN_READ_SIZE PAGE_SIZE
+#define EMPTY_SCAN_SIZE 4096
#define DIRTY_SPACE(x) do { typeof(x) _x = (x); \
c->free_size -= _x; c->dirty_size += _x; \
@@ -41,7 +41,7 @@
static uint32_t pseudo_random;
static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
- unsigned char *buf, int pointed);
+ unsigned char *buf, uint32_t buf_size);
/* These helper functions _must_ increase ofs and also do the dirty/used space accounting.
* Returning an error will abort the mount - bad checksums etc. should just mark the space
@@ -63,8 +63,8 @@
{
int i, ret;
uint32_t empty_blocks = 0, bad_blocks = 0;
- unsigned char *pointbuf = NULL;
- unsigned char *readbuf = NULL;
+ unsigned char *flashbuf = NULL;
+ uint32_t buf_size = 0;
size_t pointlen;
if (!c->blocks) {
@@ -72,30 +72,34 @@
return -EINVAL;
}
if (c->mtd->point) {
- ret = c->mtd->point (c->mtd, 0, c->mtd->size, &pointlen, &pointbuf);
+ ret = c->mtd->point (c->mtd, 0, c->mtd->size, &pointlen, &flashbuf);
if (!ret && pointlen < c->mtd->size) {
/* Don't muck about if it won't let us point to the whole flash */
D1(printk(KERN_DEBUG "MTD point returned len too short: 0x%x\n", pointlen));
- c->mtd->unpoint(c->mtd, pointbuf);
- pointbuf = NULL;
+ c->mtd->unpoint(c->mtd, flashbuf);
+ flashbuf = NULL;
}
if (ret)
D1(printk(KERN_DEBUG "MTD point failed %d\n", ret));
}
- if (!pointbuf) {
- D1(printk(KERN_DEBUG "Allocating readbuf\n"));
- readbuf = kmalloc(SCAN_READ_SIZE, GFP_KERNEL);
- if (!readbuf)
+ if (!flashbuf) {
+ /* For NAND it's quicker to read a whole eraseblock at a time,
+ apparently */
+ if (jffs2_cleanmarker_oob(c))
+ buf_size = c->sector_size;
+ else
+ buf_size = PAGE_SIZE;
+
+ D1(printk(KERN_DEBUG "Allocating readbuf of %d bytes\n", buf_size));
+ flashbuf = kmalloc(buf_size, GFP_KERNEL);
+ if (!flashbuf)
return -ENOMEM;
}
for (i=0; i<c->nr_blocks; i++) {
struct jffs2_eraseblock *jeb = &c->blocks[i];
- if (pointbuf)
- ret = jffs2_scan_eraseblock(c, jeb, pointbuf + jeb->offset, 1);
- else
- ret = jffs2_scan_eraseblock(c, jeb, readbuf, 0);
+ ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset), buf_size);
if (ret < 0)
return ret;
@@ -226,6 +230,11 @@
}
jffs2_erase_pending_trigger(c);
}
+ if (buf_size)
+ kfree(flashbuf);
+ else
+ c->mtd->unpoint(c->mtd, flashbuf);
+
return 0;
}
@@ -251,7 +260,7 @@
}
static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
- unsigned char *buf, int pointed) {
+ unsigned char *buf, uint32_t buf_size) {
struct jffs2_unknown_node *node;
struct jffs2_unknown_node crcnode;
uint32_t ofs, prevofs;
@@ -287,10 +296,10 @@
#endif
buf_ofs = jeb->offset;
- if (pointed) {
+ if (!buf_size) {
buf_len = c->sector_size;
} else {
- buf_len = SCAN_READ_SIZE;
+ buf_len = buf_size;
err = jffs2_fill_scan_buf(c, buf, buf_ofs, buf_len);
if (err)
return err;
@@ -298,10 +307,12 @@
/* We temporarily use 'ofs' as a pointer into the buffer/jeb */
ofs = 0;
- while(ofs < SCAN_READ_SIZE && *(uint32_t *)(&buf[ofs]) == 0xFFFFFFFF)
+
+ /* Scan only 4KiB of 0xFF before declaring it's empty */
+ while(ofs < EMPTY_SCAN_SIZE && *(uint32_t *)(&buf[ofs]) == 0xFFFFFFFF)
ofs += 4;
- if (ofs == SCAN_READ_SIZE) {
+ if (ofs == EMPTY_SCAN_SIZE) {
#ifdef CONFIG_JFFS2_FS_NAND
if (jffs2_cleanmarker_oob(c)) {
/* scan oob, take care of cleanmarker */
@@ -349,7 +360,6 @@
}
prevofs = ofs;
- /* FIXME: Maybe in a separate function or macro 'check_read_buf'... */
if (jeb->offset + c->sector_size < ofs + sizeof(*node)) {
D1(printk(KERN_DEBUG "Fewer than %d bytes left to end of block. (%x+%x<%x+%x) Not reading\n", sizeof(struct jffs2_unknown_node),
jeb->offset, c->sector_size, ofs, sizeof(*node)));
@@ -358,7 +368,7 @@
}
if (buf_ofs + buf_len < ofs + sizeof(*node)) {
- buf_len = min_t(uint32_t, SCAN_READ_SIZE, jeb->offset + c->sector_size - ofs);
+ buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);
D1(printk(KERN_DEBUG "Fewer than %d bytes (node header) left to end of buf. Reading 0x%x at 0x%08x\n",
sizeof(struct jffs2_unknown_node), buf_len, ofs));
err = jffs2_fill_scan_buf(c, buf, ofs, buf_len);
@@ -366,16 +376,26 @@
return err;
buf_ofs = ofs;
}
- /* ... to here */
+
node = (struct jffs2_unknown_node *)&buf[ofs-buf_ofs];
if (*(uint32_t *)(&buf[ofs-buf_ofs]) == 0xffffffff) {
uint32_t inbuf_ofs = ofs - buf_ofs + 4;
+ uint32_t scanend;
+
empty_start = ofs;
ofs += 4;
+ /* If scanning empty space after only a cleanmarker, don't
+ bother scanning the whole block */
+ if (unlikely(empty_start == jeb->offset + c->cleanmarker_size &&
+ jeb->offset + EMPTY_SCAN_SIZE < buf_ofs + buf_len))
+ scanend = jeb->offset + EMPTY_SCAN_SIZE - buf_ofs;
+ else
+ scanend = buf_len;
+
D1(printk(KERN_DEBUG "Found empty flash at 0x%08x\n", ofs));
- while (inbuf_ofs < buf_len) {
+ while (inbuf_ofs < scanend) {
if (*(uint32_t *)(&buf[inbuf_ofs]) != 0xffffffff)
goto emptyends;
@@ -466,7 +486,7 @@
switch(je16_to_cpu(node->nodetype)) {
case JFFS2_NODETYPE_INODE:
if (buf_ofs + buf_len < ofs + sizeof(struct jffs2_raw_inode)) {
- buf_len = min_t(uint32_t, SCAN_READ_SIZE, jeb->offset + c->sector_size - ofs);
+ buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);
D1(printk(KERN_DEBUG "Fewer than %d bytes (inode node) left to end of buf. Reading 0x%x at 0x%08x\n",
sizeof(struct jffs2_raw_inode), buf_len, ofs));
err = jffs2_fill_scan_buf(c, buf, ofs, buf_len);
@@ -482,7 +502,7 @@
case JFFS2_NODETYPE_DIRENT:
if (buf_ofs + buf_len < ofs + je32_to_cpu(node->totlen)) {
- buf_len = min_t(uint32_t, SCAN_READ_SIZE, jeb->offset + c->sector_size - ofs);
+ buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);
D1(printk(KERN_DEBUG "Fewer than %d bytes (dirent node) left to end of buf. Reading 0x%x at 0x%08x\n",
je32_to_cpu(node->totlen), buf_len, ofs));
err = jffs2_fill_scan_buf(c, buf, ofs, buf_len);
More information about the linux-mtd-cvs
mailing list