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....@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 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot