diff options
| author | wdenk <wdenk> | 2003-09-10 22:30:53 +0000 | 
|---|---|---|
| committer | wdenk <wdenk> | 2003-09-10 22:30:53 +0000 | 
| commit | 7205e4075d8b50e4dd89fe39ed03860b23cbb704 (patch) | |
| tree | 0dfa865e7087ff4ee07967a2531c91ff5645a802 /fs/jffs2/jffs2_1pass.c | |
| parent | 149dded2b178bc0fb62cb6f61b87968d914b580a (diff) | |
| download | olio-uboot-2014.01-7205e4075d8b50e4dd89fe39ed03860b23cbb704.tar.xz olio-uboot-2014.01-7205e4075d8b50e4dd89fe39ed03860b23cbb704.zip | |
* Patches by Denis Peter, 9 Sep 2003:U-Boot-0_4_8
  add FAT support for IDE, SCSI and USB
* Patches by Gleb Natapov, 2 Sep 2003:
  - cleanup of POST code for unsupported architectures
  - MPC824x locks way0 of data cache for use as initial RAM;
    this patch unlocks it after relocation to RAM and invalidates
    the locked entries.
* Patch by Gleb Natapov, 30 Aug 2003:
  new I2C driver for mpc107 bridge. Now works from flash.
* Patch by Dave Ellis, 11 Aug 2003:
  - JFFS2: fix typo in common/cmd_jffs2.c
  - JFFS2: fix CFG_JFFS2_SORT_FRAGMENTS option
  - JFFS2: remove node version 0 warning
  - JFFS2: accept JFFS2 PADDING nodes
  - SXNI855T: add AM29LV800 support
  - SXNI855T: move environment from EEPROM to flash
  - SXNI855T: boot from JFFS2 in NOR or NAND flash
* Patch by Bill Hargen, 11 Aug 2003:
  fixes for I2C on MPC8240
  - fix i2c_write routine
  - fix iprobe command
  - eliminates use of global variables, plus dead code, cleanup.
Diffstat (limited to 'fs/jffs2/jffs2_1pass.c')
| -rw-r--r-- | fs/jffs2/jffs2_1pass.c | 94 | 
1 files changed, 74 insertions, 20 deletions
| diff --git a/fs/jffs2/jffs2_1pass.c b/fs/jffs2/jffs2_1pass.c index 3fd4e52b3..3897ce613 100644 --- a/fs/jffs2/jffs2_1pass.c +++ b/fs/jffs2/jffs2_1pass.c @@ -1,4 +1,3 @@ -/* vi: set sw=4 ts=4: */  /*  -------------------------------------------------------------------------   * Filename:      jffs2.c @@ -265,20 +264,56 @@ insert_node(struct b_list *list, u32 offset)  }  #ifdef CFG_JFFS2_SORT_FRAGMENTS +/* Sort data entries with the latest version last, so that if there + * is overlapping data the latest version will be used. + */  static int compare_inodes(struct b_node *new, struct b_node *old)  {  	struct jffs2_raw_inode *jNew = (struct jffs2_raw_inode *)new->offset;  	struct jffs2_raw_inode *jOld = (struct jffs2_raw_inode *)old->offset; -	return jNew->version < jOld->version; +	return jNew->version > jOld->version;  } +/* Sort directory entries so all entries in the same directory + * with the same name are grouped together, with the latest version + * last. This makes it easy to eliminate all but the latest version + * by marking the previous version dead by setting the inode to 0. + */  static int compare_dirents(struct b_node *new, struct b_node *old)  {  	struct jffs2_raw_dirent *jNew = (struct jffs2_raw_dirent *)new->offset;  	struct jffs2_raw_dirent *jOld = (struct jffs2_raw_dirent *)old->offset; +	int cmp; -	return jNew->version > jOld->version; +	/* ascending sort by pino */ +	if (jNew->pino != jOld->pino) +		return jNew->pino > jOld->pino; + +	/* pino is the same, so use ascending sort by nsize, so +	 * we don't do strncmp unless we really must. +	 */ +	if (jNew->nsize != jOld->nsize) +		return jNew->nsize > jOld->nsize; + +	/* length is also the same, so use ascending sort by name +	 */ +	cmp = strncmp(jNew->name, jOld->name, jNew->nsize); +	if (cmp != 0) +		return cmp > 0; + +	/* we have duplicate names in this directory, so use ascending +	 * sort by version +	 */ +	if (jNew->version > jOld->version) { +		/* since jNew is newer, we know jOld is not valid, so +		 * mark it with inode 0 and it will not be used +		 */ +		jOld->ino = 0; +		return 1; +	} +	 +	return 0;  }  #endif @@ -327,12 +362,31 @@ jffs2_1pass_read_inode(struct b_lists *pL, u32 inode, char *dest)  	struct b_node *b;  	struct jffs2_raw_inode *jNode;  	u32 totalSize = 0; -	u16 latestVersion = 0; +	u32 latestVersion = 0;  	char *lDest;  	char *src;  	long ret;  	int i;  	u32 counter = 0; +#ifdef CFG_JFFS2_SORT_FRAGMENTS +	/* Find file size before loading any data, so fragments that +	 * start past the end of file can be ignored. A fragment +	 * that is partially in the file is loaded, so extra data may +	 * be loaded up to the next 4K boundary above the file size. +	 * This shouldn't cause trouble when loading kernel images, so +	 * we will live with it. +	 */ +	for (b = pL->frag.listHead; b != NULL; b = b->next) { +		jNode = (struct jffs2_raw_inode *) (b->offset); +		if ((inode == jNode->ino)) { +			/* get actual file length from the newest node */ +			if (jNode->version >= latestVersion) { +				totalSize = jNode->isize; +				latestVersion = jNode->version; +			} +		} +	} +#endif  	for (b = pL->frag.listHead; b != NULL; b = b->next) {  		jNode = (struct jffs2_raw_inode *) (b->offset); @@ -349,11 +403,14 @@ jffs2_1pass_read_inode(struct b_lists *pL, u32 inode, char *dest)  			putLabeledWord("read_inode: usercompr = ", jNode->usercompr);  			putLabeledWord("read_inode: flags = ", jNode->flags);  #endif + +#ifndef CFG_JFFS2_SORT_FRAGMENTS  			/* get actual file length from the newest node */  			if (jNode->version >= latestVersion) {  				totalSize = jNode->isize;  				latestVersion = jNode->version;  			} +#endif  			if(dest) {  				src = ((char *) jNode) + sizeof(struct jffs2_raw_inode); @@ -430,15 +487,11 @@ jffs2_1pass_find_inode(struct b_lists * pL, const char *name, u32 pino)  		if ((pino == jDir->pino) && (len == jDir->nsize) &&  		    (jDir->ino) &&	/* 0 for unlink */  		    (!strncmp(jDir->name, name, len))) {	/* a match */ -			if (jDir->version < version) continue; +			if (jDir->version < version) +				continue; -		        if(jDir->version == 0) { -			    	/* Is this legal? */ -				putstr(" ** WARNING ** "); -				putnstr(jDir->name, jDir->nsize); -				putstr(" is version 0 (in find, ignoring)\r\n"); -			} else if(jDir->version == version) { -			    	/* Im pretty sure this isn't ... */ +			if (jDir->version == version && inode != 0) { +			    	/* I'm pretty sure this isn't legal */  				putstr(" ** ERROR ** ");  				putnstr(jDir->name, jDir->nsize);  				putLabeledWord(" has dup version =", version); @@ -643,15 +696,11 @@ jffs2_1pass_resolve_inode(struct b_lists * pL, u32 ino)  	for(b = pL->dir.listHead; b; b = b->next) {  		jDir = (struct jffs2_raw_dirent *) (b->offset);  		if (ino == jDir->ino) { -		    	if(jDir->version < version) continue; +		    	if (jDir->version < version) +				continue; -			if(jDir->version == 0) { -			    	/* Is this legal? */ -				putstr(" ** WARNING ** "); -				putnstr(jDir->name, jDir->nsize); -				putstr(" is version 0 (in resolve, ignoring)\r\n"); -			} else if(jDir->version == version) { -			    	/* Im pretty sure this isn't ... */ +			if (jDir->version == version && jDirFound) { +			    	/* I'm pretty sure this isn't legal */  				putstr(" ** ERROR ** ");  				putnstr(jDir->name, jDir->nsize);  				putLabeledWord(" has dup version (resolve) = ", @@ -891,6 +940,11 @@ jffs2_1pass_build_lists(struct part_info * part)  					printf("OOPS Cleanmarker has bad size "  						"%d != %d\n", node->totlen,  						sizeof(struct jffs2_unknown_node)); +			} else if (node->nodetype == JFFS2_NODETYPE_PADDING) { +				if (node->totlen < sizeof(struct jffs2_unknown_node)) +					printf("OOPS Padding has bad size " +						"%d < %d\n", node->totlen, +						sizeof(struct jffs2_unknown_node));  			} else {  				printf("Unknown node type: %x len %d "  					"offset 0x%x\n", node->nodetype, |