[U-Boot] [PATCH] JFFS2: bug fix for summary support.

Leo Liu liucai.lfn at gmail.com
Mon Apr 11 15:34:20 CEST 2011


This patch fixes some issues with JFFS2 summary support in U-Boot.
1/ Bug fix for summary support: we need to get the latest DIRENT.
2/ Avoid allocate too big memory if the biggest file in JFFS2 is too
long. We only allocate one node size for pL->readbuf.
3/ Free memory space if we fail to scan the JFFS2.

Signed-off-by: Leo Liu <liucai.lfn at gmail.com>
---
 fs/jffs2/jffs2_1pass.c      |   53 +++++++++++++++++++++++++-----------------
 fs/jffs2/jffs2_nand_1pass.c |   24 ++++++++++++++-----
 include/jffs2/jffs2.h       |   11 +++++++++
 3 files changed, 60 insertions(+), 28 deletions(-)

diff --git a/fs/jffs2/jffs2_1pass.c b/fs/jffs2/jffs2_1pass.c
index c4f7445..dfb1745 100644
--- a/fs/jffs2/jffs2_1pass.c
+++ b/fs/jffs2/jffs2_1pass.c
@@ -662,7 +662,8 @@ jffs2_free_cache(struct part_info *part)
 		pL = (struct b_lists *)part->jffs2_priv;
 		free_nodes(&pL->frag);
 		free_nodes(&pL->dir);
-		free(pL->readbuf);
+		if(pL->readbuf)		
+			free(pL->readbuf);
 		free(pL);
 	}
 }
@@ -676,14 +677,19 @@ jffs_init_1pass_list(struct part_info *part)
 
 	if (NULL != (part->jffs2_priv = malloc(sizeof(struct b_lists)))) {
 		pL = (struct b_lists *)part->jffs2_priv;
-
 		memset(pL, 0, sizeof(*pL));
+		
+		pL->readbuf = malloc(sizeof(union jffs2_node_union));
+		if(!pL->readbuf) {
+			printf("jffs_init_1pass_list: malloc failed\n");
+			return 0;
+		}
 #ifdef CONFIG_SYS_JFFS2_SORT_FRAGMENTS
 		pL->dir.listCompare = compare_dirents;
 		pL->frag.listCompare = compare_inodes;
 #endif
 	}
-	return 0;
+	return 1;
 }
 
 /* find the inode from the slashless name given a parent */
@@ -748,8 +754,8 @@ jffs2_1pass_read_inode(struct b_lists *pL, u32 inode, char *dest)
 
 			if(dest) {
 				src = ((uchar *) jNode) + sizeof(struct jffs2_raw_inode);
-				/* ignore data behind latest known EOF */
-				if (jNode->offset > totalSize) {
+				/* ignore data which exceed file length */
+				if (jNode->offset + jNode->dsize > totalSize) {
 					put_fl_mem(jNode, pL->readbuf);
 					continue;
 				}
@@ -835,10 +841,10 @@ jffs2_1pass_find_inode(struct b_lists * pL, const char *name, u32 pino)
 	for(b = pL->dir.listHead; b; b = b->next, counter++) {
 		jDir = (struct jffs2_raw_dirent *) get_node_mem(b->offset,
 								pL->readbuf);
-		if ((pino == jDir->pino) && (len == jDir->nsize) &&
-		    (jDir->ino) &&	/* 0 for unlink */
+		if ((pino == jDir->pino) && 
+			(len == jDir->nsize) &&
 		    (!strncmp((char *)jDir->name, name, len))) {	/* a match */
-			if (jDir->version < version) {
+			if (jDir->version < version) {  /*ignore the old DIRENT*/
 				put_fl_mem(jDir, pL->readbuf);
 				continue;
 			}
@@ -963,6 +969,13 @@ jffs2_1pass_list_inodes(struct b_lists * pL, u32 pino)
 			struct jffs2_raw_inode *jNode, *i = NULL;
 			struct b_node *b2 = pL->frag.listHead;
 
+			/*
+			we compare the DIRENT's ino with the latest DIRENT's ino t determine whether this DIRENT
+			is the latest. If the DIRENT is not the latest,ignore it.
+			*/
+			if(jDir->ino != jffs2_1pass_find_inode(pL, jDir->name, pino))  
+				continue;
+			
 			while (b2) {
 				jNode = (struct jffs2_raw_inode *)
 					get_fl_mem(b2->offset, sizeof(ojNode), &ojNode);
@@ -1448,7 +1461,6 @@ jffs2_1pass_build_lists(struct part_info * part)
 	u32 counter4 = 0;
 	u32 counterF = 0;
 	u32 counterN = 0;
-	u32 max_totlen = 0;
 	u32 buf_size = DEFAULT_EMPTY_SCAN_SIZE;
 	char *buf;
 
@@ -1458,9 +1470,16 @@ jffs2_1pass_build_lists(struct part_info * part)
 	/* lcd_off(); */
 
 	/* if we are building a list we need to refresh the cache. */
-	jffs_init_1pass_list(part);
-	pL = (struct b_lists *)part->jffs2_priv;
+	if(! jffs_init_1pass_list(part))
+		return 0;
+	
+	pL = (struct b_lists *)part->jffs2_priv;	
 	buf = malloc(buf_size);
+	if (!buf) {
+		printf("jffs2_1pass_build_lists: malloc failed\n");
+		return 0;
+	}
+	
 	puts ("Scanning JFFS2 FS:   ");
 
 	/* start at the beginning of the partition */
@@ -1520,7 +1539,7 @@ jffs2_1pass_build_lists(struct part_info * part)
 			ret = jffs2_sum_scan_sumnode(part, sector_ofs, sumptr,
 					sumlen, pL);
 
-			if (buf_size && sumlen > buf_size)
+			if (sumlen > buf_size)
 				free(sumptr);
 			if (ret < 0) {
 				free(buf);
@@ -1645,8 +1664,6 @@ jffs2_1pass_build_lists(struct part_info * part)
 					jffs2_free_cache(part);
 					return 0;
 				}
-				if (max_totlen < node->totlen)
-					max_totlen = node->totlen;
 				break;
 			case JFFS2_NODETYPE_DIRENT:
 				if (buf_ofs + buf_len < ofs + sizeof(struct
@@ -1675,8 +1692,6 @@ jffs2_1pass_build_lists(struct part_info * part)
 					jffs2_free_cache(part);
 					return 0;
 				}
-				if (max_totlen < node->totlen)
-					max_totlen = node->totlen;
 				counterN++;
 				break;
 			case JFFS2_NODETYPE_CLEANMARKER:
@@ -1708,12 +1723,6 @@ jffs2_1pass_build_lists(struct part_info * part)
 	free(buf);
 	putstr("\b\b done.\r\n");		/* close off the dots */
 
-	/* We don't care if malloc failed - then each read operation will
-	 * allocate its own buffer as necessary (NAND) or will read directly
-	 * from flash (NOR).
-	 */
-	pL->readbuf = malloc(max_totlen);
-
 	/* turn the lcd back on. */
 	/* splash(); */
 
diff --git a/fs/jffs2/jffs2_nand_1pass.c b/fs/jffs2/jffs2_nand_1pass.c
index 3982003..e3bc536 100644
--- a/fs/jffs2/jffs2_nand_1pass.c
+++ b/fs/jffs2/jffs2_nand_1pass.c
@@ -251,6 +251,7 @@ jffs_init_1pass_list(struct part_info *part)
 		pL->dir.listCompare = compare_dirents;
 		pL->frag.listCompare = compare_inodes;
 #endif
+		return 1;
 	}
 	return 0;
 }
@@ -305,8 +306,8 @@ jffs2_1pass_read_inode(struct b_lists *pL, u32 ino, char *dest,
 			if (dest)
 				len += jNode->csize;
 			nand_read(nand, jNode->offset, &len, inode);
-			/* ignore data behind latest known EOF */
-			if (inode->offset > totalSize)
+			/* ignore data which exceed file length */
+			if (inode->offset + inode->dsize> totalSize)
 				continue;
 
 			if (stat) {
@@ -371,7 +372,7 @@ jffs2_1pass_find_inode(struct b_lists * pL, const char *name, u32 pino)
 
 	/* we need to search all and return the inode with the highest version */
 	for (jDir = (struct b_dirent *)pL->dir.listHead; jDir; jDir = jDir->next) {
-		if ((pino == jDir->pino) && (jDir->ino) &&	/* 0 for unlink */
+		if ((pino == jDir->pino) && 
 		    (len == jDir->nsize) && (nhash == jDir->nhash)) {
 			/* TODO: compare name */
 			if (jDir->version < version)
@@ -483,6 +484,14 @@ jffs2_1pass_list_inodes(struct b_lists * pL, u32 pino)
 			struct b_inode *jNode = (struct b_inode *)pL->frag.listHead;
 			struct b_inode *i = NULL;
 
+			/*
+			if the DIRENT is not the latest,ignore it.
+			we compare the DIRENT's ino with the latest DIRENT's ino to determine whether this DIRENT
+			is the latest.
+			*/
+			if(jDir.ino != jffs2_1pass_find_inode(pL, jDir->name, pino))  
+				continue;
+		
 			while (jNode) {
 				if (jNode->ino == jDir->ino && jNode->version >= i_version) {
 					i_version = jNode->version;
@@ -797,7 +806,9 @@ jffs2_1pass_build_lists(struct part_info * part)
 	nand = nand_info + id->num;
 
 	/* if we are building a list we need to refresh the cache. */
-	jffs_init_1pass_list(part);
+	if(! jffs_init_1pass_list(part))
+		return 0;
+
 	pL = (struct b_lists *)part->jffs2_priv;
 	pL->partOffset = part->offset;
 	puts ("Scanning JFFS2 FS:   ");
@@ -809,6 +820,8 @@ jffs2_1pass_build_lists(struct part_info * part)
 		return 0;
 
 	for (i = 0; i < nr_blocks; i++) {
+		WATCHDOG_RESET();		
+		
 		printf("\b\b%c ", spinner[counter++ % sizeof(spinner)]);
 
 		offset = part->offset + i * sectorsize;
@@ -878,6 +891,7 @@ jffs2_1pass_build_lists(struct part_info * part)
 		}
 	}
 
+	free(buf);
 	putstr("\b\b done.\r\n");		/* close off the dots */
 
 #if 0
@@ -897,8 +911,6 @@ jffs2_1pass_build_lists(struct part_info * part)
 
 	/* give visual feedback that we are done scanning the flash */
 	led_blink(0x0, 0x0, 0x1, 0x1);	/* off, forever, on 100ms, off 100ms */
-	free(buf);
-
 	return 1;
 }
 
diff --git a/include/jffs2/jffs2.h b/include/jffs2/jffs2.h
index 651f94c..c01a76e 100644
--- a/include/jffs2/jffs2.h
+++ b/include/jffs2/jffs2.h
@@ -41,6 +41,17 @@
 #include <asm/types.h>
 #include <jffs2/load_kernel.h>
 
+#ifdef CONFIG_JFFS2_SUMMARY
+#ifndef CONFIG_SYS_JFFS2_SORT_FRAGMENTS
+/*
+ *	if we define summary in jffs2, we also need to define 
+ *	CONFIG_SYS_JFFS2_SORT_FRAGMENTS. If not, the data in latest inode may be 
+ *  overwritten by the old one.
+*/
+#error "need to define CONFIG_SYS_JFFS2_SORT_FRAGMENTS,if summary is enabled"
+#endif
+#endif
+
 #define JFFS2_SUPER_MAGIC 0x72b6
 
 /* Values we may expect to find in the 'magic' field */
-- 
1.7.3.1.msysgit.0



More information about the U-Boot mailing list