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