diff options
Diffstat (limited to 'target/linux/generic/files/fs')
33 files changed, 3152 insertions, 2824 deletions
diff --git a/target/linux/generic/files/fs/yaffs2/Kconfig b/target/linux/generic/files/fs/yaffs2/Kconfig index 7b6f836cd..c0e545b64 100644 --- a/target/linux/generic/files/fs/yaffs2/Kconfig +++ b/target/linux/generic/files/fs/yaffs2/Kconfig @@ -5,7 +5,7 @@  config YAFFS_FS  	tristate "YAFFS2 file system support"  	default n -	depends on MTD +	depends on MTD_BLOCK  	select YAFFS_YAFFS1  	select YAFFS_YAFFS2  	help @@ -43,7 +43,8 @@ config YAFFS_9BYTE_TAGS  	  format that you need to continue to support.  New data written  	  also uses the older-style format.  Note: Use of this option  	  generally requires that MTD's oob layout be adjusted to use the -	  older-style format.  See notes on tags formats and MTD versions. +	  older-style format.  See notes on tags formats and MTD versions +	  in yaffs_mtdif1.c.  	  If unsure, say N. @@ -109,26 +110,6 @@ config YAFFS_DISABLE_LAZY_LOAD  	  If unsure, say N. -config YAFFS_CHECKPOINT_RESERVED_BLOCKS -	int "Reserved blocks for checkpointing" -	depends on YAFFS_YAFFS2 -	default 10 -	help -          Give the number of Blocks to reserve for checkpointing. -	  Checkpointing saves the state at unmount so that mounting is -	  much faster as a scan of all the flash to regenerate this state -	  is not needed.  These Blocks are reserved per partition, so if -	  you have very small partitions the default (10) may be a mess -	  for you.  You can set this value to 0, but that does not mean -	  checkpointing is disabled at all. There only won't be any -	  specially reserved blocks for checkpointing, so if there is -	  enough free space on the filesystem, it will be used for -	  checkpointing. - -	  If unsure, leave at default (10), but don't wonder if there are -	  always 2MB used on your large page device partition (10 x 2k -	  pagesize). When using small partitions or when being very small -	  on space, you probably want to set this to zero.  config YAFFS_DISABLE_WIDE_TNODES  	bool "Turn off wide tnodes" diff --git a/target/linux/generic/files/fs/yaffs2/Makefile b/target/linux/generic/files/fs/yaffs2/Makefile index 73f46583f..382ee6142 100644 --- a/target/linux/generic/files/fs/yaffs2/Makefile +++ b/target/linux/generic/files/fs/yaffs2/Makefile @@ -5,7 +5,6 @@  obj-$(CONFIG_YAFFS_FS) += yaffs.o  yaffs-y := yaffs_ecc.o yaffs_fs.o yaffs_guts.o yaffs_checkptrw.o -yaffs-y += yaffs_packedtags2.o yaffs_nand.o yaffs_qsort.o +yaffs-y += yaffs_packedtags1.o yaffs_packedtags2.o yaffs_nand.o yaffs_qsort.o  yaffs-y += yaffs_tagscompat.o yaffs_tagsvalidity.o -yaffs-y += yaffs_mtdif1.o yaffs_packedtags1.o -yaffs-y += yaffs_mtdif.o yaffs_mtdif2.o +yaffs-y += yaffs_mtdif.o yaffs_mtdif1.o yaffs_mtdif2.o diff --git a/target/linux/generic/files/fs/yaffs2/NOTE.openwrt b/target/linux/generic/files/fs/yaffs2/NOTE.openwrt new file mode 100644 index 000000000..fe1049d8a --- /dev/null +++ b/target/linux/generic/files/fs/yaffs2/NOTE.openwrt @@ -0,0 +1,4 @@ +The yaffs2 source has been fetched from the yaffs2 CVS tree. + +URL: cvs.aleph1.co.uk +Version: 2009-09-24 diff --git a/target/linux/generic/files/fs/yaffs2/devextras.h b/target/linux/generic/files/fs/yaffs2/devextras.h index fcf2690a5..7df46dc29 100644 --- a/target/linux/generic/files/fs/yaffs2/devextras.h +++ b/target/linux/generic/files/fs/yaffs2/devextras.h @@ -14,194 +14,135 @@   */  /* - * This file is just holds extra declarations used during development. - * Most of these are from kernel includes placed here so we can use them in - * applications. + * This file is just holds extra declarations of macros that would normally + * be providesd in the Linux kernel. These macros have been written from + * scratch but are functionally equivalent to the Linux ones.   *   */  #ifndef __EXTRAS_H__  #define __EXTRAS_H__ -#if defined WIN32 -#define __inline__ __inline -#define new newHack -#endif - -#if !(defined __KERNEL__) || (defined WIN32) -/* User space defines */ +#if !(defined __KERNEL__) +/* Definition of types */  typedef unsigned char __u8;  typedef unsigned short __u16;  typedef unsigned __u32; +#endif +  /* - * Simple doubly linked list implementation. - * - * Some of the internal functions ("__xxx") are useful when - * manipulating whole lists rather than single entries, as - * sometimes we already know the next/prev entries and we can - * generate better code by using them directly rather than - * using the generic single-entry routines. + * This is a simple doubly linked list implementation that matches the + * way the Linux kernel doubly linked list implementation works.   */ -#define prefetch(x) 1 - -struct list_head { -	struct list_head *next, *prev; +struct ylist_head { +	struct ylist_head *next; /* next in chain */ +	struct ylist_head *prev; /* previous in chain */  }; -#define LIST_HEAD_INIT(name) { &(name), &(name) } -#define LIST_HEAD(name) \ -	struct list_head name = LIST_HEAD_INIT(name) +/* Initialise a static list */ +#define YLIST_HEAD(name) \ +struct ylist_head name = { &(name), &(name)} + -#define INIT_LIST_HEAD(ptr) do { \ -	(ptr)->next = (ptr); (ptr)->prev = (ptr); \ + +/* Initialise a list head to an empty list */ +#define YINIT_LIST_HEAD(p) \ +do { \ +	(p)->next = (p);\ +	(p)->prev = (p); \  } while (0) -/* - * Insert a new entry between two known consecutive entries. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static __inline__ void __list_add(struct list_head *new, -				  struct list_head *prev, -				  struct list_head *next) -{ -	next->prev = new; -	new->next = next; -	new->prev = prev; -	prev->next = new; -} -/** - * list_add - add a new entry - * @new: new entry to be added - * @head: list head to add it after - * - * Insert a new entry after the specified head. - * This is good for implementing stacks. - */ -static __inline__ void list_add(struct list_head *new, struct list_head *head) +/* Add an element to a list */ +static __inline__ void ylist_add(struct ylist_head *newEntry, +				struct ylist_head *list)  { -	__list_add(new, head, head->next); -} +	struct ylist_head *listNext = list->next; + +	list->next = newEntry; +	newEntry->prev = list; +	newEntry->next = listNext; +	listNext->prev = newEntry; -/** - * list_add_tail - add a new entry - * @new: new entry to be added - * @head: list head to add it before - * - * Insert a new entry before the specified head. - * This is useful for implementing queues. - */ -static __inline__ void list_add_tail(struct list_head *new, -				     struct list_head *head) -{ -	__list_add(new, head->prev, head);  } -/* - * Delete a list entry by making the prev/next entries - * point to each other. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static __inline__ void __list_del(struct list_head *prev, -				  struct list_head *next) +static __inline__ void ylist_add_tail(struct ylist_head *newEntry, +				 struct ylist_head *list)  { -	next->prev = prev; -	prev->next = next; +	struct ylist_head *listPrev = list->prev; + +	list->prev = newEntry; +	newEntry->next = list; +	newEntry->prev = listPrev; +	listPrev->next = newEntry; +  } -/** - * list_del - deletes entry from list. - * @entry: the element to delete from the list. - * Note: list_empty on entry does not return true after this, the entry is - * in an undefined state. - */ -static __inline__ void list_del(struct list_head *entry) + +/* Take an element out of its current list, with or without + * reinitialising the links.of the entry*/ +static __inline__ void ylist_del(struct ylist_head *entry)  { -	__list_del(entry->prev, entry->next); +	struct ylist_head *listNext = entry->next; +	struct ylist_head *listPrev = entry->prev; + +	listNext->prev = listPrev; +	listPrev->next = listNext; +  } -/** - * list_del_init - deletes entry from list and reinitialize it. - * @entry: the element to delete from the list. - */ -static __inline__ void list_del_init(struct list_head *entry) +static __inline__ void ylist_del_init(struct ylist_head *entry)  { -	__list_del(entry->prev, entry->next); -	INIT_LIST_HEAD(entry); +	ylist_del(entry); +	entry->next = entry->prev = entry;  } -/** - * list_empty - tests whether a list is empty - * @head: the list to test. - */ -static __inline__ int list_empty(struct list_head *head) + +/* Test if the list is empty */ +static __inline__ int ylist_empty(struct ylist_head *entry)  { -	return head->next == head; +	return (entry->next == entry);  } -/** - * list_splice - join two lists - * @list: the new list to add. - * @head: the place to add it in the first list. + +/* ylist_entry takes a pointer to a list entry and offsets it to that + * we can find a pointer to the object it is embedded in.   */ -static __inline__ void list_splice(struct list_head *list, -				   struct list_head *head) -{ -	struct list_head *first = list->next; -	if (first != list) { -		struct list_head *last = list->prev; -		struct list_head *at = head->next; -		first->prev = head; -		head->next = first; +#define ylist_entry(entry, type, member) \ +	((type *)((char *)(entry)-(unsigned long)(&((type *)NULL)->member))) -		last->next = at; -		at->prev = last; -	} -} -/** - * list_entry - get the struct for this entry - * @ptr:	the &struct list_head pointer. - * @type:	the type of the struct this is embedded in. - * @member:	the name of the list_struct within the struct. +/* ylist_for_each and list_for_each_safe  iterate over lists. + * ylist_for_each_safe uses temporary storage to make the list delete safe   */ -#define list_entry(ptr, type, member) \ -	((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) -/** - * list_for_each	-	iterate over a list - * @pos:	the &struct list_head to use as a loop counter. - * @head:	the head for your list. - */ -#define list_for_each(pos, head) \ -	for (pos = (head)->next, prefetch(pos->next); pos != (head); \ -        	pos = pos->next, prefetch(pos->next)) - -/** - * list_for_each_safe	-	iterate over a list safe against removal - *                              of list entry - * @pos:	the &struct list_head to use as a loop counter. - * @n:		another &struct list_head to use as temporary storage - * @head:	the head for your list. - */ -#define list_for_each_safe(pos, n, head) \ -	for (pos = (head)->next, n = pos->next; pos != (head); \ -		pos = n, n = pos->next) +#define ylist_for_each(itervar, list) \ +	for (itervar = (list)->next; itervar != (list); itervar = itervar->next) + +#define ylist_for_each_safe(itervar, saveVar, list) \ +	for (itervar = (list)->next, saveVar = (list)->next->next; \ +		itervar != (list); itervar = saveVar, saveVar = saveVar->next) + + +#if !(defined __KERNEL__) + + +#ifndef WIN32 +#include <sys/stat.h> +#endif + + +#ifdef CONFIG_YAFFS_PROVIDE_DEFS +/* File types */ + -/* - * File types - */  #define DT_UNKNOWN	0  #define DT_FIFO		1  #define DT_CHR		2 @@ -212,6 +153,7 @@ static __inline__ void list_splice(struct list_head *list,  #define DT_SOCK		12  #define DT_WHT		14 +  #ifndef WIN32  #include <sys/stat.h>  #endif @@ -227,10 +169,6 @@ static __inline__ void list_splice(struct list_head *list,  #define ATTR_ATIME	16  #define ATTR_MTIME	32  #define ATTR_CTIME	64 -#define ATTR_ATIME_SET	128 -#define ATTR_MTIME_SET	256 -#define ATTR_FORCE	512	/* Not a change, but a change it */ -#define ATTR_ATTR_FLAG	1024  struct iattr {  	unsigned int ia_valid; @@ -244,21 +182,15 @@ struct iattr {  	unsigned int ia_attr_flags;  }; -#define KERN_DEBUG +#endif  #else -#ifndef WIN32  #include <linux/types.h> -#include <linux/list.h>  #include <linux/fs.h>  #include <linux/stat.h> -#endif  #endif -#if defined WIN32 -#undef new -#endif  #endif diff --git a/target/linux/generic/files/fs/yaffs2/moduleconfig.h b/target/linux/generic/files/fs/yaffs2/moduleconfig.h index 016391ca5..a344baf37 100644 --- a/target/linux/generic/files/fs/yaffs2/moduleconfig.h +++ b/target/linux/generic/files/fs/yaffs2/moduleconfig.h @@ -27,12 +27,12 @@  /* Default: Not selected */  /* Meaning: Yaffs does its own ECC, rather than using MTD ECC */ -//#define CONFIG_YAFFS_DOES_ECC +/* #define CONFIG_YAFFS_DOES_ECC */  /* Default: Not selected */  /* Meaning: ECC byte order is 'wrong'.  Only meaningful if */  /*          CONFIG_YAFFS_DOES_ECC is set */ -//#define CONFIG_YAFFS_ECC_WRONG_ORDER +/* #define CONFIG_YAFFS_ECC_WRONG_ORDER */  /* Default: Selected */  /* Meaning: Disables testing whether chunks are erased before writing to them*/ @@ -54,11 +54,11 @@ that you need to continue to support.  New data written also uses the  older-style format.  Note: Use of this option generally requires that MTD's oob layout be  adjusted to use the older-style format.  See notes on tags formats and -MTD versions. +MTD versions in yaffs_mtdif1.c.  */  /* Default: Not selected */  /* Meaning: Use older-style on-NAND data format with pageStatus byte */ -#define CONFIG_YAFFS_9BYTE_TAGS +/* #define CONFIG_YAFFS_9BYTE_TAGS */  #endif /* YAFFS_OUT_OF_TREE */ diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_checkptrw.c b/target/linux/generic/files/fs/yaffs2/yaffs_checkptrw.c index 933a33fb8..40d792366 100644 --- a/target/linux/generic/files/fs/yaffs2/yaffs_checkptrw.c +++ b/target/linux/generic/files/fs/yaffs2/yaffs_checkptrw.c @@ -12,48 +12,43 @@   */  const char *yaffs_checkptrw_c_version = -    "$Id: yaffs_checkptrw.c,v 1.14 2007-05-15 20:07:40 charles Exp $"; +	"$Id: yaffs_checkptrw.c,v 1.18 2009-03-06 17:20:49 wookey Exp $";  #include "yaffs_checkptrw.h" - +#include "yaffs_getblockinfo.h"  static int yaffs_CheckpointSpaceOk(yaffs_Device *dev)  { -  	int blocksAvailable = dev->nErasedBlocks - dev->nReservedBlocks;  	T(YAFFS_TRACE_CHECKPOINT,  		(TSTR("checkpt blocks available = %d" TENDSTR),  		blocksAvailable)); -  	return (blocksAvailable <= 0) ? 0 : 1;  }  static int yaffs_CheckpointErase(yaffs_Device *dev)  { -  	int i; - -	if(!dev->eraseBlockInNAND) +	if (!dev->eraseBlockInNAND)  		return 0; -	T(YAFFS_TRACE_CHECKPOINT,(TSTR("checking blocks %d to %d"TENDSTR), -		dev->internalStartBlock,dev->internalEndBlock)); - -	for(i = dev->internalStartBlock; i <= dev->internalEndBlock; i++) { -		yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,i); -		if(bi->blockState == YAFFS_BLOCK_STATE_CHECKPOINT){ -			T(YAFFS_TRACE_CHECKPOINT,(TSTR("erasing checkpt block %d"TENDSTR),i)); -			if(dev->eraseBlockInNAND(dev,i- dev->blockOffset /* realign */)){ +	T(YAFFS_TRACE_CHECKPOINT, (TSTR("checking blocks %d to %d"TENDSTR), +		dev->internalStartBlock, dev->internalEndBlock)); + +	for (i = dev->internalStartBlock; i <= dev->internalEndBlock; i++) { +		yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, i); +		if (bi->blockState == YAFFS_BLOCK_STATE_CHECKPOINT) { +			T(YAFFS_TRACE_CHECKPOINT, (TSTR("erasing checkpt block %d"TENDSTR), i)); +			if (dev->eraseBlockInNAND(dev, i - dev->blockOffset /* realign */)) {  				bi->blockState = YAFFS_BLOCK_STATE_EMPTY;  				dev->nErasedBlocks++;  				dev->nFreeChunks += dev->nChunksPerBlock; -			} -			else { -				dev->markNANDBlockBad(dev,i); +			} else { +				dev->markNANDBlockBad(dev, i);  				bi->blockState = YAFFS_BLOCK_STATE_DEAD;  			}  		} @@ -71,23 +66,23 @@ static void yaffs_CheckpointFindNextErasedBlock(yaffs_Device *dev)  	int blocksAvailable = dev->nErasedBlocks - dev->nReservedBlocks;  	T(YAFFS_TRACE_CHECKPOINT,  		(TSTR("allocating checkpt block: erased %d reserved %d avail %d next %d "TENDSTR), -		dev->nErasedBlocks,dev->nReservedBlocks,blocksAvailable,dev->checkpointNextBlock)); +		dev->nErasedBlocks, dev->nReservedBlocks, blocksAvailable, dev->checkpointNextBlock)); -	if(dev->checkpointNextBlock >= 0 && -	   dev->checkpointNextBlock <= dev->internalEndBlock && -	   blocksAvailable > 0){ +	if (dev->checkpointNextBlock >= 0 && +			dev->checkpointNextBlock <= dev->internalEndBlock && +			blocksAvailable > 0) { -		for(i = dev->checkpointNextBlock; i <= dev->internalEndBlock; i++){ -			yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,i); -			if(bi->blockState == YAFFS_BLOCK_STATE_EMPTY){ +		for (i = dev->checkpointNextBlock; i <= dev->internalEndBlock; i++) { +			yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, i); +			if (bi->blockState == YAFFS_BLOCK_STATE_EMPTY) {  				dev->checkpointNextBlock = i + 1;  				dev->checkpointCurrentBlock = i; -				T(YAFFS_TRACE_CHECKPOINT,(TSTR("allocating checkpt block %d"TENDSTR),i)); +				T(YAFFS_TRACE_CHECKPOINT, (TSTR("allocating checkpt block %d"TENDSTR), i));  				return;  			}  		}  	} -	T(YAFFS_TRACE_CHECKPOINT,(TSTR("out of checkpt blocks"TENDSTR))); +	T(YAFFS_TRACE_CHECKPOINT, (TSTR("out of checkpt blocks"TENDSTR)));  	dev->checkpointNextBlock = -1;  	dev->checkpointCurrentBlock = -1; @@ -98,30 +93,31 @@ static void yaffs_CheckpointFindNextCheckpointBlock(yaffs_Device *dev)  	int  i;  	yaffs_ExtendedTags tags; -	T(YAFFS_TRACE_CHECKPOINT,(TSTR("find next checkpt block: start:  blocks %d next %d" TENDSTR), +	T(YAFFS_TRACE_CHECKPOINT, (TSTR("find next checkpt block: start:  blocks %d next %d" TENDSTR),  		dev->blocksInCheckpoint, dev->checkpointNextBlock)); -	if(dev->blocksInCheckpoint < dev->checkpointMaxBlocks) -		for(i = dev->checkpointNextBlock; i <= dev->internalEndBlock; i++){ +	if (dev->blocksInCheckpoint < dev->checkpointMaxBlocks) +		for (i = dev->checkpointNextBlock; i <= dev->internalEndBlock; i++) {  			int chunk = i * dev->nChunksPerBlock;  			int realignedChunk = chunk - dev->chunkOffset; -			dev->readChunkWithTagsFromNAND(dev,realignedChunk,NULL,&tags); -			T(YAFFS_TRACE_CHECKPOINT,(TSTR("find next checkpt block: search: block %d oid %d seq %d eccr %d" TENDSTR), -				i, tags.objectId,tags.sequenceNumber,tags.eccResult)); +			dev->readChunkWithTagsFromNAND(dev, realignedChunk, +					NULL, &tags); +			T(YAFFS_TRACE_CHECKPOINT, (TSTR("find next checkpt block: search: block %d oid %d seq %d eccr %d" TENDSTR), +				i, tags.objectId, tags.sequenceNumber, tags.eccResult)); -			if(tags.sequenceNumber == YAFFS_SEQUENCE_CHECKPOINT_DATA){ +			if (tags.sequenceNumber == YAFFS_SEQUENCE_CHECKPOINT_DATA) {  				/* Right kind of block */  				dev->checkpointNextBlock = tags.objectId;  				dev->checkpointCurrentBlock = i;  				dev->checkpointBlockList[dev->blocksInCheckpoint] = i;  				dev->blocksInCheckpoint++; -				T(YAFFS_TRACE_CHECKPOINT,(TSTR("found checkpt block %d"TENDSTR),i)); +				T(YAFFS_TRACE_CHECKPOINT, (TSTR("found checkpt block %d"TENDSTR), i));  				return;  			}  		} -	T(YAFFS_TRACE_CHECKPOINT,(TSTR("found no more checkpt blocks"TENDSTR))); +	T(YAFFS_TRACE_CHECKPOINT, (TSTR("found no more checkpt blocks"TENDSTR)));  	dev->checkpointNextBlock = -1;  	dev->checkpointCurrentBlock = -1; @@ -133,17 +129,17 @@ int yaffs_CheckpointOpen(yaffs_Device *dev, int forWriting)  	/* Got the functions we need? */  	if (!dev->writeChunkWithTagsToNAND || -	    !dev->readChunkWithTagsFromNAND || -	    !dev->eraseBlockInNAND || -	    !dev->markNANDBlockBad) +			!dev->readChunkWithTagsFromNAND || +			!dev->eraseBlockInNAND || +			!dev->markNANDBlockBad)  		return 0; -	if(forWriting && !yaffs_CheckpointSpaceOk(dev)) +	if (forWriting && !yaffs_CheckpointSpaceOk(dev))  		return 0; -	if(!dev->checkpointBuffer) -		dev->checkpointBuffer = YMALLOC_DMA(dev->nDataBytesPerChunk); -	if(!dev->checkpointBuffer) +	if (!dev->checkpointBuffer) +		dev->checkpointBuffer = YMALLOC_DMA(dev->totalBytesPerChunk); +	if (!dev->checkpointBuffer)  		return 0; @@ -159,12 +155,10 @@ int yaffs_CheckpointOpen(yaffs_Device *dev, int forWriting)  	dev->checkpointNextBlock = dev->internalStartBlock;  	/* Erase all the blocks in the checkpoint area */ -	if(forWriting){ -		memset(dev->checkpointBuffer,0,dev->nDataBytesPerChunk); +	if (forWriting) { +		memset(dev->checkpointBuffer, 0, dev->nDataBytesPerChunk);  		dev->checkpointByteOffset = 0;  		return yaffs_CheckpointErase(dev); - -  	} else {  		int i;  		/* Set to a value that will kick off a read */ @@ -174,7 +168,7 @@ int yaffs_CheckpointOpen(yaffs_Device *dev, int forWriting)  		dev->blocksInCheckpoint = 0;  		dev->checkpointMaxBlocks = (dev->internalEndBlock - dev->internalStartBlock)/16 + 2;  		dev->checkpointBlockList = YMALLOC(sizeof(int) * dev->checkpointMaxBlocks); -		for(i = 0; i < dev->checkpointMaxBlocks; i++) +		for (i = 0; i < dev->checkpointMaxBlocks; i++)  			dev->checkpointBlockList[i] = -1;  	} @@ -191,18 +185,17 @@ int yaffs_GetCheckpointSum(yaffs_Device *dev, __u32 *sum)  static int yaffs_CheckpointFlushBuffer(yaffs_Device *dev)  { -  	int chunk;  	int realignedChunk;  	yaffs_ExtendedTags tags; -	if(dev->checkpointCurrentBlock < 0){ +	if (dev->checkpointCurrentBlock < 0) {  		yaffs_CheckpointFindNextErasedBlock(dev);  		dev->checkpointCurrentChunk = 0;  	} -	if(dev->checkpointCurrentBlock < 0) +	if (dev->checkpointCurrentBlock < 0)  		return 0;  	tags.chunkDeleted = 0; @@ -210,10 +203,10 @@ static int yaffs_CheckpointFlushBuffer(yaffs_Device *dev)  	tags.chunkId = dev->checkpointPageSequence + 1;  	tags.sequenceNumber =  YAFFS_SEQUENCE_CHECKPOINT_DATA;  	tags.byteCount = dev->nDataBytesPerChunk; -	if(dev->checkpointCurrentChunk == 0){ +	if (dev->checkpointCurrentChunk == 0) {  		/* First chunk we write for the block? Set block state to  		   checkpoint */ -		yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,dev->checkpointCurrentBlock); +		yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, dev->checkpointCurrentBlock);  		bi->blockState = YAFFS_BLOCK_STATE_CHECKPOINT;  		dev->blocksInCheckpoint++;  	} @@ -221,28 +214,29 @@ static int yaffs_CheckpointFlushBuffer(yaffs_Device *dev)  	chunk = dev->checkpointCurrentBlock * dev->nChunksPerBlock + dev->checkpointCurrentChunk; -	T(YAFFS_TRACE_CHECKPOINT,(TSTR("checkpoint wite buffer nand %d(%d:%d) objid %d chId %d" TENDSTR), -		chunk, dev->checkpointCurrentBlock, dev->checkpointCurrentChunk,tags.objectId,tags.chunkId)); +	T(YAFFS_TRACE_CHECKPOINT, (TSTR("checkpoint wite buffer nand %d(%d:%d) objid %d chId %d" TENDSTR), +		chunk, dev->checkpointCurrentBlock, dev->checkpointCurrentChunk, tags.objectId, tags.chunkId));  	realignedChunk = chunk - dev->chunkOffset; -	dev->writeChunkWithTagsToNAND(dev,realignedChunk,dev->checkpointBuffer,&tags); +	dev->writeChunkWithTagsToNAND(dev, realignedChunk, +			dev->checkpointBuffer, &tags);  	dev->checkpointByteOffset = 0;  	dev->checkpointPageSequence++;  	dev->checkpointCurrentChunk++; -	if(dev->checkpointCurrentChunk >= dev->nChunksPerBlock){ +	if (dev->checkpointCurrentChunk >= dev->nChunksPerBlock) {  		dev->checkpointCurrentChunk = 0;  		dev->checkpointCurrentBlock = -1;  	} -	memset(dev->checkpointBuffer,0,dev->nDataBytesPerChunk); +	memset(dev->checkpointBuffer, 0, dev->nDataBytesPerChunk);  	return 1;  } -int yaffs_CheckpointWrite(yaffs_Device *dev,const void *data, int nBytes) +int yaffs_CheckpointWrite(yaffs_Device *dev, const void *data, int nBytes)  { -	int i=0; +	int i = 0;  	int ok = 1; @@ -250,17 +244,14 @@ int yaffs_CheckpointWrite(yaffs_Device *dev,const void *data, int nBytes) -	if(!dev->checkpointBuffer) +	if (!dev->checkpointBuffer)  		return 0; -	if(!dev->checkpointOpenForWrite) +	if (!dev->checkpointOpenForWrite)  		return -1; -	while(i < nBytes && ok) { - - - -		dev->checkpointBuffer[dev->checkpointByteOffset] = *dataBytes ; +	while (i < nBytes && ok) { +		dev->checkpointBuffer[dev->checkpointByteOffset] = *dataBytes;  		dev->checkpointSum += *dataBytes;  		dev->checkpointXor ^= *dataBytes; @@ -270,18 +261,17 @@ int yaffs_CheckpointWrite(yaffs_Device *dev,const void *data, int nBytes)  		dev->checkpointByteCount++; -		if(dev->checkpointByteOffset < 0 || +		if (dev->checkpointByteOffset < 0 ||  		   dev->checkpointByteOffset >= dev->nDataBytesPerChunk)  			ok = yaffs_CheckpointFlushBuffer(dev); -  	} -	return 	i; +	return i;  }  int yaffs_CheckpointRead(yaffs_Device *dev, void *data, int nBytes)  { -	int i=0; +	int i = 0;  	int ok = 1;  	yaffs_ExtendedTags tags; @@ -291,52 +281,54 @@ int yaffs_CheckpointRead(yaffs_Device *dev, void *data, int nBytes)  	__u8 *dataBytes = (__u8 *)data; -	if(!dev->checkpointBuffer) +	if (!dev->checkpointBuffer)  		return 0; -	if(dev->checkpointOpenForWrite) +	if (dev->checkpointOpenForWrite)  		return -1; -	while(i < nBytes && ok) { +	while (i < nBytes && ok) { -		if(dev->checkpointByteOffset < 0 || -		   dev->checkpointByteOffset >= dev->nDataBytesPerChunk) { +		if (dev->checkpointByteOffset < 0 || +			dev->checkpointByteOffset >= dev->nDataBytesPerChunk) { -		   	if(dev->checkpointCurrentBlock < 0){ +			if (dev->checkpointCurrentBlock < 0) {  				yaffs_CheckpointFindNextCheckpointBlock(dev);  				dev->checkpointCurrentChunk = 0;  			} -			if(dev->checkpointCurrentBlock < 0) +			if (dev->checkpointCurrentBlock < 0)  				ok = 0;  			else { - -				chunk = dev->checkpointCurrentBlock * dev->nChunksPerBlock + -				          dev->checkpointCurrentChunk; +				chunk = dev->checkpointCurrentBlock * +					dev->nChunksPerBlock + +					dev->checkpointCurrentChunk;  				realignedChunk = chunk - dev->chunkOffset; -	   			/* read in the next chunk */ -	   			/* printf("read checkpoint page %d\n",dev->checkpointPage); */ -				dev->readChunkWithTagsFromNAND(dev, realignedChunk, -							       dev->checkpointBuffer, -							      &tags); +				/* read in the next chunk */ +				/* printf("read checkpoint page %d\n",dev->checkpointPage); */ +				dev->readChunkWithTagsFromNAND(dev, +						realignedChunk, +						dev->checkpointBuffer, +						&tags); -				if(tags.chunkId != (dev->checkpointPageSequence + 1) || -				   tags.sequenceNumber != YAFFS_SEQUENCE_CHECKPOINT_DATA) -				   ok = 0; +				if (tags.chunkId != (dev->checkpointPageSequence + 1) || +					tags.eccResult > YAFFS_ECC_RESULT_FIXED || +					tags.sequenceNumber != YAFFS_SEQUENCE_CHECKPOINT_DATA) +					ok = 0;  				dev->checkpointByteOffset = 0;  				dev->checkpointPageSequence++;  				dev->checkpointCurrentChunk++; -				if(dev->checkpointCurrentChunk >= dev->nChunksPerBlock) +				if (dev->checkpointCurrentChunk >= dev->nChunksPerBlock)  					dev->checkpointCurrentBlock = -1;  			}  		} -		if(ok){ +		if (ok) {  			*dataBytes = dev->checkpointBuffer[dev->checkpointByteOffset];  			dev->checkpointSum += *dataBytes;  			dev->checkpointXor ^= *dataBytes; @@ -353,17 +345,17 @@ int yaffs_CheckpointRead(yaffs_Device *dev, void *data, int nBytes)  int yaffs_CheckpointClose(yaffs_Device *dev)  { -	if(dev->checkpointOpenForWrite){ -		if(dev->checkpointByteOffset != 0) +	if (dev->checkpointOpenForWrite) { +		if (dev->checkpointByteOffset != 0)  			yaffs_CheckpointFlushBuffer(dev);  	} else {  		int i; -		for(i = 0; i < dev->blocksInCheckpoint && dev->checkpointBlockList[i] >= 0; i++){ -			yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,dev->checkpointBlockList[i]); -			if(bi->blockState == YAFFS_BLOCK_STATE_EMPTY) +		for (i = 0; i < dev->blocksInCheckpoint && dev->checkpointBlockList[i] >= 0; i++) { +			yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, dev->checkpointBlockList[i]); +			if (bi->blockState == YAFFS_BLOCK_STATE_EMPTY)  				bi->blockState = YAFFS_BLOCK_STATE_CHECKPOINT;  			else { -				// Todo this looks odd... +				/* Todo this looks odd... */  			}  		}  		YFREE(dev->checkpointBlockList); @@ -374,27 +366,25 @@ int yaffs_CheckpointClose(yaffs_Device *dev)  	dev->nErasedBlocks -= dev->blocksInCheckpoint; -	T(YAFFS_TRACE_CHECKPOINT,(TSTR("checkpoint byte count %d" TENDSTR), +	T(YAFFS_TRACE_CHECKPOINT, (TSTR("checkpoint byte count %d" TENDSTR),  			dev->checkpointByteCount)); -	if(dev->checkpointBuffer){ +	if (dev->checkpointBuffer) {  		/* free the buffer */  		YFREE(dev->checkpointBuffer);  		dev->checkpointBuffer = NULL;  		return 1; -	} -	else +	} else  		return 0; -  }  int yaffs_CheckpointInvalidateStream(yaffs_Device *dev)  {  	/* Erase the first checksum block */ -	T(YAFFS_TRACE_CHECKPOINT,(TSTR("checkpoint invalidate"TENDSTR))); +	T(YAFFS_TRACE_CHECKPOINT, (TSTR("checkpoint invalidate"TENDSTR))); -	if(!yaffs_CheckpointSpaceOk(dev)) +	if (!yaffs_CheckpointSpaceOk(dev))  		return 0;  	return yaffs_CheckpointErase(dev); diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_checkptrw.h b/target/linux/generic/files/fs/yaffs2/yaffs_checkptrw.h index d3ff17405..5d426ea8d 100644 --- a/target/linux/generic/files/fs/yaffs2/yaffs_checkptrw.h +++ b/target/linux/generic/files/fs/yaffs2/yaffs_checkptrw.h @@ -20,9 +20,9 @@  int yaffs_CheckpointOpen(yaffs_Device *dev, int forWriting); -int yaffs_CheckpointWrite(yaffs_Device *dev,const void *data, int nBytes); +int yaffs_CheckpointWrite(yaffs_Device *dev, const void *data, int nBytes); -int yaffs_CheckpointRead(yaffs_Device *dev,void *data, int nBytes); +int yaffs_CheckpointRead(yaffs_Device *dev, void *data, int nBytes);  int yaffs_GetCheckpointSum(yaffs_Device *dev, __u32 *sum); diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_ecc.c b/target/linux/generic/files/fs/yaffs2/yaffs_ecc.c index e2860393d..d037e90a2 100644 --- a/target/linux/generic/files/fs/yaffs2/yaffs_ecc.c +++ b/target/linux/generic/files/fs/yaffs2/yaffs_ecc.c @@ -29,7 +29,7 @@   */  const char *yaffs_ecc_c_version = -    "$Id: yaffs_ecc.c,v 1.9 2007-02-14 01:09:06 wookey Exp $"; +	"$Id: yaffs_ecc.c,v 1.11 2009-03-06 17:20:50 wookey Exp $";  #include "yportenv.h" @@ -109,12 +109,10 @@ void yaffs_ECCCalculate(const unsigned char *data, unsigned char *ecc)  		b = column_parity_table[*data++];  		col_parity ^= b; -		if (b & 0x01)	// odd number of bits in the byte -		{ +		if (b & 0x01) {		/* odd number of bits in the byte */  			line_parity ^= i;  			line_parity_prime ^= ~i;  		} -  	}  	ecc[2] = (~col_parity) | 0x03; @@ -158,7 +156,7 @@ void yaffs_ECCCalculate(const unsigned char *data, unsigned char *ecc)  	ecc[0] = ~t;  #ifdef CONFIG_YAFFS_ECC_WRONG_ORDER -	// Swap the bytes into the wrong order +	/* Swap the bytes into the wrong order */  	t = ecc[0];  	ecc[0] = ecc[1];  	ecc[1] = t; @@ -189,7 +187,7 @@ int yaffs_ECCCorrect(unsigned char *data, unsigned char *read_ecc,  		unsigned bit;  #ifdef CONFIG_YAFFS_ECC_WRONG_ORDER -		// swap the bytes to correct for the wrong order +		/* swap the bytes to correct for the wrong order */  		unsigned char t;  		t = d0; @@ -251,7 +249,7 @@ int yaffs_ECCCorrect(unsigned char *data, unsigned char *read_ecc,   * ECCxxxOther does ECC calcs on arbitrary n bytes of data   */  void yaffs_ECCCalculateOther(const unsigned char *data, unsigned nBytes, -			     yaffs_ECCOther * eccOther) +				yaffs_ECCOther *eccOther)  {  	unsigned int i; @@ -278,8 +276,8 @@ void yaffs_ECCCalculateOther(const unsigned char *data, unsigned nBytes,  }  int yaffs_ECCCorrectOther(unsigned char *data, unsigned nBytes, -			  yaffs_ECCOther * read_ecc, -			  const yaffs_ECCOther * test_ecc) +			yaffs_ECCOther *read_ecc, +			const yaffs_ECCOther *test_ecc)  {  	unsigned char cDelta;	/* column parity delta */  	unsigned lDelta;	/* line parity delta */ @@ -294,8 +292,7 @@ int yaffs_ECCCorrectOther(unsigned char *data, unsigned nBytes,  		return 0; /* no error */  	if (lDelta == ~lDeltaPrime && -	    (((cDelta ^ (cDelta >> 1)) & 0x15) == 0x15)) -	{ +	    (((cDelta ^ (cDelta >> 1)) & 0x15) == 0x15)) {  		/* Single bit (recoverable) error in data */  		bit = 0; @@ -307,7 +304,7 @@ int yaffs_ECCCorrectOther(unsigned char *data, unsigned nBytes,  		if (cDelta & 0x02)  			bit |= 0x01; -		if(lDelta >= nBytes) +		if (lDelta >= nBytes)  			return -1;  		data[lDelta] ^= (1 << bit); @@ -316,7 +313,7 @@ int yaffs_ECCCorrectOther(unsigned char *data, unsigned nBytes,  	}  	if ((yaffs_CountBits32(lDelta) + yaffs_CountBits32(lDeltaPrime) + -	     yaffs_CountBits(cDelta)) == 1) { +			yaffs_CountBits(cDelta)) == 1) {  		/* Reccoverable error in ecc */  		*read_ecc = *test_ecc; @@ -326,6 +323,4 @@ int yaffs_ECCCorrectOther(unsigned char *data, unsigned nBytes,  	/* Unrecoverable error */  	return -1; -  } - diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_ecc.h b/target/linux/generic/files/fs/yaffs2/yaffs_ecc.h index 79bc3d117..60765176e 100644 --- a/target/linux/generic/files/fs/yaffs2/yaffs_ecc.h +++ b/target/linux/generic/files/fs/yaffs2/yaffs_ecc.h @@ -13,15 +13,15 @@   * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.   */ - /* -  * This code implements the ECC algorithm used in SmartMedia. -  * -  * The ECC comprises 22 bits of parity information and is stuffed into 3 bytes. -  * The two unused bit are set to 1. -  * The ECC can correct single bit errors in a 256-byte page of data. Thus, two such ECC -  * blocks are used on a 512-byte NAND page. -  * -  */ +/* + * This code implements the ECC algorithm used in SmartMedia. + * + * The ECC comprises 22 bits of parity information and is stuffed into 3 bytes. + * The two unused bit are set to 1. + * The ECC can correct single bit errors in a 256-byte page of data. Thus, two such ECC + * blocks are used on a 512-byte NAND page. + * + */  #ifndef __YAFFS_ECC_H__  #define __YAFFS_ECC_H__ @@ -34,11 +34,11 @@ typedef struct {  void yaffs_ECCCalculate(const unsigned char *data, unsigned char *ecc);  int yaffs_ECCCorrect(unsigned char *data, unsigned char *read_ecc, -		     const unsigned char *test_ecc); +		const unsigned char *test_ecc);  void yaffs_ECCCalculateOther(const unsigned char *data, unsigned nBytes, -			     yaffs_ECCOther * ecc); +			yaffs_ECCOther *ecc);  int yaffs_ECCCorrectOther(unsigned char *data, unsigned nBytes, -			  yaffs_ECCOther * read_ecc, -			  const yaffs_ECCOther * test_ecc); +			yaffs_ECCOther *read_ecc, +			const yaffs_ECCOther *test_ecc);  #endif diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_fs.c b/target/linux/generic/files/fs/yaffs2/yaffs_fs.c index 67001b10e..7c04ed3a3 100644 --- a/target/linux/generic/files/fs/yaffs2/yaffs_fs.c +++ b/target/linux/generic/files/fs/yaffs2/yaffs_fs.c @@ -1,7 +1,7 @@  /*   * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.   * - * Copyright (C) 2002-2007 Aleph One Ltd. + * Copyright (C) 2002-2009 Aleph One Ltd.   *   for Toby Churchill Ltd and Brightstar Engineering   *   * Created by Charles Manning <charles@aleph1.co.uk> @@ -32,18 +32,17 @@   */  const char *yaffs_fs_c_version = -    "$Id: yaffs_fs.c,v 1.63 2007-09-19 20:35:40 imcd Exp $"; +    "$Id: yaffs_fs.c,v 1.79 2009-03-17 01:12:00 wookey Exp $";  extern const char *yaffs_guts_c_version;  #include <linux/version.h> -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)) +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))  #include <linux/config.h>  #endif  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/slab.h>  #include <linux/init.h> -#include <linux/list.h>  #include <linux/fs.h>  #include <linux/proc_fs.h>  #include <linux/smp_lock.h> @@ -53,10 +52,12 @@ extern const char *yaffs_guts_c_version;  #include <linux/string.h>  #include <linux/ctype.h> -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) +#include "asm/div64.h" + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))  #include <linux/statfs.h>	/* Added NCB 15-8-2003 */ -#include <asm/statfs.h> +#include <linux/statfs.h>  #define UnlockPage(p) unlock_page(p)  #define Page_Uptodate(page)	test_bit(PG_uptodate, &(page)->flags) @@ -69,22 +70,45 @@ extern const char *yaffs_guts_c_version;  #define	BDEVNAME_SIZE		0  #define	yaffs_devname(sb, buf)	kdevname(sb->s_dev) -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0))  /* added NCB 26/5/2006 for 2.4.25-vrs2-tcl1 kernel */  #define __user  #endif  #endif -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)) +#define YPROC_ROOT  (&proc_root) +#else +#define YPROC_ROOT  NULL +#endif + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))  #define WRITE_SIZE_STR "writesize" -#define WRITE_SIZE(mtd) (mtd)->writesize +#define WRITE_SIZE(mtd) ((mtd)->writesize)  #else  #define WRITE_SIZE_STR "oobblock" -#define WRITE_SIZE(mtd) (mtd)->oobblock +#define WRITE_SIZE(mtd) ((mtd)->oobblock) +#endif + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 27)) +#define YAFFS_USE_WRITE_BEGIN_END 1 +#else +#define YAFFS_USE_WRITE_BEGIN_END 0 +#endif + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 28)) +static uint32_t YCALCBLOCKS(uint64_t partition_size, uint32_t block_size) +{ +	uint64_t result = partition_size; +	do_div(result, block_size); +	return (uint32_t)result; +} +#else +#define YCALCBLOCKS(s, b) ((s)/(b))  #endif -#include <asm/uaccess.h> +#include <linux/uaccess.h>  #include "yportenv.h"  #include "yaffs_guts.h" @@ -96,28 +120,44 @@ extern const char *yaffs_guts_c_version;  unsigned int yaffs_traceMask = YAFFS_TRACE_BAD_BLOCKS;  unsigned int yaffs_wr_attempts = YAFFS_WR_ATTEMPTS; +unsigned int yaffs_auto_checkpoint = 1;  /* Module Parameters */ -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -module_param(yaffs_traceMask,uint,0644); -module_param(yaffs_wr_attempts,uint,0644); +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) +module_param(yaffs_traceMask, uint, 0644); +module_param(yaffs_wr_attempts, uint, 0644); +module_param(yaffs_auto_checkpoint, uint, 0644);  #else -MODULE_PARM(yaffs_traceMask,"i"); -MODULE_PARM(yaffs_wr_attempts,"i"); +MODULE_PARM(yaffs_traceMask, "i"); +MODULE_PARM(yaffs_wr_attempts, "i"); +MODULE_PARM(yaffs_auto_checkpoint, "i"); +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)) +/* use iget and read_inode */ +#define Y_IGET(sb, inum) iget((sb), (inum)) +static void yaffs_read_inode(struct inode *inode); + +#else +/* Call local equivalent */ +#define YAFFS_USE_OWN_IGET +#define Y_IGET(sb, inum) yaffs_iget((sb), (inum)) + +static struct inode *yaffs_iget(struct super_block *sb, unsigned long ino);  #endif  /*#define T(x) printk x */ -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)) -#define yaffs_InodeToObjectLV(iptr) (iptr)->i_private +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18)) +#define yaffs_InodeToObjectLV(iptr) ((iptr)->i_private)  #else -#define yaffs_InodeToObjectLV(iptr) (iptr)->u.generic_ip +#define yaffs_InodeToObjectLV(iptr) ((iptr)->u.generic_ip)  #endif  #define yaffs_InodeToObject(iptr) ((yaffs_Object *)(yaffs_InodeToObjectLV(iptr)))  #define yaffs_DentryToObject(dptr) yaffs_InodeToObject((dptr)->d_inode) -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))  #define yaffs_SuperToDevice(sb)	((yaffs_Device *)sb->s_fs_info)  #else  #define yaffs_SuperToDevice(sb)	((yaffs_Device *)sb->u.generic_sbp) @@ -126,47 +166,49 @@ MODULE_PARM(yaffs_wr_attempts,"i");  static void yaffs_put_super(struct super_block *sb);  static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n, -				loff_t * pos); +				loff_t *pos); +static ssize_t yaffs_hold_space(struct file *f); +static void yaffs_release_space(struct file *f); -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))  static int yaffs_file_flush(struct file *file, fl_owner_t id);  #else  static int yaffs_file_flush(struct file *file);  #endif  static int yaffs_sync_object(struct file *file, struct dentry *dentry, -			     int datasync); +				int datasync);  static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir); -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))  static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode,  			struct nameidata *n);  static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry, -				   struct nameidata *n); +					struct nameidata *n);  #else  static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode);  static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry);  #endif  static int yaffs_link(struct dentry *old_dentry, struct inode *dir, -		      struct dentry *dentry); +			struct dentry *dentry);  static int yaffs_unlink(struct inode *dir, struct dentry *dentry);  static int yaffs_symlink(struct inode *dir, struct dentry *dentry, -			 const char *symname); +			const char *symname);  static int yaffs_mkdir(struct inode *dir, struct dentry *dentry, int mode); -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))  static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, -		       dev_t dev); +			dev_t dev);  #else  static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, -		       int dev); +			int dev);  #endif  static int yaffs_rename(struct inode *old_dir, struct dentry *old_dentry,  			struct inode *new_dir, struct dentry *new_dentry);  static int yaffs_setattr(struct dentry *dentry, struct iattr *attr); -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))  static int yaffs_sync_fs(struct super_block *sb, int wait);  static void yaffs_write_super(struct super_block *sb);  #else @@ -174,33 +216,47 @@ static int yaffs_sync_fs(struct super_block *sb);  static int yaffs_write_super(struct super_block *sb);  #endif -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))  static int yaffs_statfs(struct dentry *dentry, struct kstatfs *buf); -#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) +#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))  static int yaffs_statfs(struct super_block *sb, struct kstatfs *buf);  #else  static int yaffs_statfs(struct super_block *sb, struct statfs *buf);  #endif -static void yaffs_read_inode(struct inode *inode); +#ifdef YAFFS_HAS_PUT_INODE  static void yaffs_put_inode(struct inode *inode); +#endif +  static void yaffs_delete_inode(struct inode *);  static void yaffs_clear_inode(struct inode *);  static int yaffs_readpage(struct file *file, struct page *page); -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))  static int yaffs_writepage(struct page *page, struct writeback_control *wbc);  #else  static int yaffs_writepage(struct page *page);  #endif + + +#if (YAFFS_USE_WRITE_BEGIN_END != 0) +static int yaffs_write_begin(struct file *filp, struct address_space *mapping, +				loff_t pos, unsigned len, unsigned flags, +				struct page **pagep, void **fsdata); +static int yaffs_write_end(struct file *filp, struct address_space *mapping, +				loff_t pos, unsigned len, unsigned copied, +				struct page *pg, void *fsdadata); +#else  static int yaffs_prepare_write(struct file *f, struct page *pg, -			       unsigned offset, unsigned to); +				unsigned offset, unsigned to);  static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset, -			      unsigned to); +				unsigned to); -static int yaffs_readlink(struct dentry *dentry, char __user * buffer, -			  int buflen); -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13)) +#endif + +static int yaffs_readlink(struct dentry *dentry, char __user *buffer, +				int buflen); +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13))  static void *yaffs_follow_link(struct dentry *dentry, struct nameidata *nd);  #else  static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd); @@ -209,12 +265,17 @@ static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd);  static struct address_space_operations yaffs_file_address_operations = {  	.readpage = yaffs_readpage,  	.writepage = yaffs_writepage, +#if (YAFFS_USE_WRITE_BEGIN_END > 0) +	.write_begin = yaffs_write_begin, +	.write_end = yaffs_write_end, +#else  	.prepare_write = yaffs_prepare_write,  	.commit_write = yaffs_commit_write, +#endif  }; -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)) -static struct file_operations yaffs_file_operations = { +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22)) +static const struct file_operations yaffs_file_operations = {  	.read = do_sync_read,  	.write = do_sync_write,  	.aio_read = generic_file_aio_read, @@ -224,11 +285,12 @@ static struct file_operations yaffs_file_operations = {  	.fsync = yaffs_sync_object,  	.splice_read = generic_file_splice_read,  	.splice_write = generic_file_splice_write, +	.llseek = generic_file_llseek,  }; -#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)) +#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18)) -static struct file_operations yaffs_file_operations = { +static const struct file_operations yaffs_file_operations = {  	.read = do_sync_read,  	.write = do_sync_write,  	.aio_read = generic_file_aio_read, @@ -241,29 +303,29 @@ static struct file_operations yaffs_file_operations = {  #else -static struct file_operations yaffs_file_operations = { +static const struct file_operations yaffs_file_operations = {  	.read = generic_file_read,  	.write = generic_file_write,  	.mmap = generic_file_mmap,  	.flush = yaffs_file_flush,  	.fsync = yaffs_sync_object, -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))  	.sendfile = generic_file_sendfile,  #endif  };  #endif -static struct inode_operations yaffs_file_inode_operations = { +static const struct inode_operations yaffs_file_inode_operations = {  	.setattr = yaffs_setattr,  }; -static struct inode_operations yaffs_symlink_inode_operations = { +static const struct inode_operations yaffs_symlink_inode_operations = {  	.readlink = yaffs_readlink,  	.follow_link = yaffs_follow_link,  	.setattr = yaffs_setattr,  }; -static struct inode_operations yaffs_dir_inode_operations = { +static const struct inode_operations yaffs_dir_inode_operations = {  	.create = yaffs_create,  	.lookup = yaffs_lookup,  	.link = yaffs_link, @@ -276,16 +338,21 @@ static struct inode_operations yaffs_dir_inode_operations = {  	.setattr = yaffs_setattr,  }; -static struct file_operations yaffs_dir_operations = { +static const struct file_operations yaffs_dir_operations = {  	.read = generic_read_dir,  	.readdir = yaffs_readdir,  	.fsync = yaffs_sync_object,  }; -static struct super_operations yaffs_super_ops = { +static const struct super_operations yaffs_super_ops = {  	.statfs = yaffs_statfs, + +#ifndef YAFFS_USE_OWN_IGET  	.read_inode = yaffs_read_inode, +#endif +#ifdef YAFFS_HAS_PUT_INODE  	.put_inode = yaffs_put_inode, +#endif  	.put_super = yaffs_put_super,  	.delete_inode = yaffs_delete_inode,  	.clear_inode = yaffs_clear_inode, @@ -293,22 +360,21 @@ static struct super_operations yaffs_super_ops = {  	.write_super = yaffs_write_super,  }; -static void yaffs_GrossLock(yaffs_Device * dev) +static void yaffs_GrossLock(yaffs_Device *dev)  { -	T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs locking\n")); - +	T(YAFFS_TRACE_OS, ("yaffs locking %p\n", current));  	down(&dev->grossLock); +	T(YAFFS_TRACE_OS, ("yaffs locked %p\n", current));  } -static void yaffs_GrossUnlock(yaffs_Device * dev) +static void yaffs_GrossUnlock(yaffs_Device *dev)  { -	T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs unlocking\n")); +	T(YAFFS_TRACE_OS, ("yaffs unlocking %p\n", current));  	up(&dev->grossLock); -  } -static int yaffs_readlink(struct dentry *dentry, char __user * buffer, -			  int buflen) +static int yaffs_readlink(struct dentry *dentry, char __user *buffer, +			int buflen)  {  	unsigned char *alias;  	int ret; @@ -329,7 +395,7 @@ static int yaffs_readlink(struct dentry *dentry, char __user * buffer,  	return ret;  } -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13)) +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13))  static void *yaffs_follow_link(struct dentry *dentry, struct nameidata *nd)  #else  static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd) @@ -345,32 +411,31 @@ static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd)  	yaffs_GrossUnlock(dev); -	if (!alias) -        { +	if (!alias) {  		ret = -ENOMEM;  		goto out; -        } +	}  	ret = vfs_follow_link(nd, alias);  	kfree(alias);  out: -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13)) -	return ERR_PTR (ret); +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13)) +	return ERR_PTR(ret);  #else  	return ret;  #endif  }  struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev, -			      yaffs_Object * obj); +				yaffs_Object *obj);  /*   * Lookup is used to find objects in the fs   */ -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))  static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry, -				   struct nameidata *n) +				struct nameidata *n)  #else  static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry)  #endif @@ -383,12 +448,11 @@ static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry)  	yaffs_GrossLock(dev);  	T(YAFFS_TRACE_OS, -	  (KERN_DEBUG "yaffs_lookup for %d:%s\n", -	   yaffs_InodeToObject(dir)->objectId, dentry->d_name.name)); +		("yaffs_lookup for %d:%s\n", +		yaffs_InodeToObject(dir)->objectId, dentry->d_name.name)); -	obj = -	    yaffs_FindObjectByName(yaffs_InodeToObject(dir), -				   dentry->d_name.name); +	obj = yaffs_FindObjectByName(yaffs_InodeToObject(dir), +					dentry->d_name.name);  	obj = yaffs_GetEquivalentObject(obj);	/* in case it was a hardlink */ @@ -397,13 +461,13 @@ static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry)  	if (obj) {  		T(YAFFS_TRACE_OS, -		  (KERN_DEBUG "yaffs_lookup found %d\n", obj->objectId)); +			("yaffs_lookup found %d\n", obj->objectId));  		inode = yaffs_get_inode(dir->i_sb, obj->yst_mode, 0, obj);  		if (inode) {  			T(YAFFS_TRACE_OS, -			  (KERN_DEBUG "yaffs_loookup dentry \n")); +				("yaffs_loookup dentry \n"));  /* #if 0 asserted by NCB for 2.5/6 compatability - falls through to   * d_add even if NULL inode */  #if 0 @@ -416,7 +480,7 @@ static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry)  		}  	} else { -		T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_lookup not found\n")); +		T(YAFFS_TRACE_OS, ("yaffs_lookup not found\n"));  	} @@ -425,20 +489,22 @@ static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry)  	d_add(dentry, inode);  	return NULL; -	/*      return (ERR_PTR(-EIO)); */ -  } + +#ifdef YAFFS_HAS_PUT_INODE +  /* For now put inode is just for debugging   * Put inode is called when the inode **structure** is put.   */  static void yaffs_put_inode(struct inode *inode)  {  	T(YAFFS_TRACE_OS, -	  ("yaffs_put_inode: ino %d, count %d\n", (int)inode->i_ino, -	   atomic_read(&inode->i_count))); +		("yaffs_put_inode: ino %d, count %d\n", (int)inode->i_ino, +		atomic_read(&inode->i_count)));  } +#endif  /* clear is called to tell the fs to release any per-inode data it holds */  static void yaffs_clear_inode(struct inode *inode) @@ -449,9 +515,9 @@ static void yaffs_clear_inode(struct inode *inode)  	obj = yaffs_InodeToObject(inode);  	T(YAFFS_TRACE_OS, -	  ("yaffs_clear_inode: ino %d, count %d %s\n", (int)inode->i_ino, -	   atomic_read(&inode->i_count), -	   obj ? "object exists" : "null object")); +		("yaffs_clear_inode: ino %d, count %d %s\n", (int)inode->i_ino, +		atomic_read(&inode->i_count), +		obj ? "object exists" : "null object"));  	if (obj) {  		dev = obj->myDev; @@ -486,23 +552,23 @@ static void yaffs_delete_inode(struct inode *inode)  	yaffs_Device *dev;  	T(YAFFS_TRACE_OS, -	  ("yaffs_delete_inode: ino %d, count %d %s\n", (int)inode->i_ino, -	   atomic_read(&inode->i_count), -	   obj ? "object exists" : "null object")); +		("yaffs_delete_inode: ino %d, count %d %s\n", (int)inode->i_ino, +		atomic_read(&inode->i_count), +		obj ? "object exists" : "null object"));  	if (obj) {  		dev = obj->myDev;  		yaffs_GrossLock(dev); -		yaffs_DeleteFile(obj); +		yaffs_DeleteObject(obj);  		yaffs_GrossUnlock(dev);  	} -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13)) -        truncate_inode_pages (&inode->i_data, 0); +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13)) +	truncate_inode_pages(&inode->i_data, 0);  #endif  	clear_inode(inode);  } -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))  static int yaffs_file_flush(struct file *file, fl_owner_t id)  #else  static int yaffs_file_flush(struct file *file) @@ -513,8 +579,8 @@ static int yaffs_file_flush(struct file *file)  	yaffs_Device *dev = obj->myDev;  	T(YAFFS_TRACE_OS, -	  (KERN_DEBUG "yaffs_file_flush object %d (%s)\n", obj->objectId, -	   obj->dirty ? "dirty" : "clean")); +		("yaffs_file_flush object %d (%s)\n", obj->objectId, +		obj->dirty ? "dirty" : "clean"));  	yaffs_GrossLock(dev); @@ -535,15 +601,15 @@ static int yaffs_readpage_nolock(struct file *f, struct page *pg)  	yaffs_Device *dev; -	T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_readpage at %08x, size %08x\n", -			   (unsigned)(pg->index << PAGE_CACHE_SHIFT), -			   (unsigned)PAGE_CACHE_SIZE)); +	T(YAFFS_TRACE_OS, ("yaffs_readpage at %08x, size %08x\n", +			(unsigned)(pg->index << PAGE_CACHE_SHIFT), +			(unsigned)PAGE_CACHE_SIZE));  	obj = yaffs_DentryToObject(f->f_dentry);  	dev = obj->myDev; -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))  	BUG_ON(!PageLocked(pg));  #else  	if (!PageLocked(pg)) @@ -555,9 +621,9 @@ static int yaffs_readpage_nolock(struct file *f, struct page *pg)  	yaffs_GrossLock(dev); -	ret = -	    yaffs_ReadDataFromFile(obj, pg_buf, pg->index << PAGE_CACHE_SHIFT, -				   PAGE_CACHE_SIZE); +	ret = yaffs_ReadDataFromFile(obj, pg_buf, +				pg->index << PAGE_CACHE_SHIFT, +				PAGE_CACHE_SIZE);  	yaffs_GrossUnlock(dev); @@ -575,7 +641,7 @@ static int yaffs_readpage_nolock(struct file *f, struct page *pg)  	flush_dcache_page(pg);  	kunmap(pg); -	T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_readpage done\n")); +	T(YAFFS_TRACE_OS, ("yaffs_readpage done\n"));  	return ret;  } @@ -593,7 +659,7 @@ static int yaffs_readpage(struct file *f, struct page *pg)  /* writepage inspired by/stolen from smbfs */ -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))  static int yaffs_writepage(struct page *page, struct writeback_control *wbc)  #else  static int yaffs_writepage(struct page *page) @@ -616,12 +682,11 @@ static int yaffs_writepage(struct page *page)  	if (offset > inode->i_size) {  		T(YAFFS_TRACE_OS, -		  (KERN_DEBUG -		   "yaffs_writepage at %08x, inode size = %08x!!!\n", -		   (unsigned)(page->index << PAGE_CACHE_SHIFT), -		   (unsigned)inode->i_size)); +			("yaffs_writepage at %08x, inode size = %08x!!!\n", +			(unsigned)(page->index << PAGE_CACHE_SHIFT), +			(unsigned)inode->i_size));  		T(YAFFS_TRACE_OS, -		  (KERN_DEBUG "                -> don't care!!\n")); +			("                -> don't care!!\n"));  		unlock_page(page);  		return 0;  	} @@ -629,11 +694,10 @@ static int yaffs_writepage(struct page *page)  	end_index = inode->i_size >> PAGE_CACHE_SHIFT;  	/* easy case */ -	if (page->index < end_index) { +	if (page->index < end_index)  		nBytes = PAGE_CACHE_SIZE; -	} else { +	else  		nBytes = inode->i_size & (PAGE_CACHE_SIZE - 1); -	}  	get_page(page); @@ -643,19 +707,18 @@ static int yaffs_writepage(struct page *page)  	yaffs_GrossLock(obj->myDev);  	T(YAFFS_TRACE_OS, -	  (KERN_DEBUG "yaffs_writepage at %08x, size %08x\n", -	   (unsigned)(page->index << PAGE_CACHE_SHIFT), nBytes)); +		("yaffs_writepage at %08x, size %08x\n", +		(unsigned)(page->index << PAGE_CACHE_SHIFT), nBytes));  	T(YAFFS_TRACE_OS, -	  (KERN_DEBUG "writepag0: obj = %05x, ino = %05x\n", -	   (int)obj->variant.fileVariant.fileSize, (int)inode->i_size)); +		("writepag0: obj = %05x, ino = %05x\n", +		(int)obj->variant.fileVariant.fileSize, (int)inode->i_size)); -	nWritten = -	    yaffs_WriteDataToFile(obj, buffer, page->index << PAGE_CACHE_SHIFT, -				  nBytes, 0); +	nWritten = yaffs_WriteDataToFile(obj, buffer, +			page->index << PAGE_CACHE_SHIFT, nBytes, 0);  	T(YAFFS_TRACE_OS, -	  (KERN_DEBUG "writepag1: obj = %05x, ino = %05x\n", -	   (int)obj->variant.fileVariant.fileSize, (int)inode->i_size)); +		("writepag1: obj = %05x, ino = %05x\n", +		(int)obj->variant.fileVariant.fileSize, (int)inode->i_size));  	yaffs_GrossUnlock(obj->myDev); @@ -667,100 +730,207 @@ static int yaffs_writepage(struct page *page)  	return (nWritten == nBytes) ? 0 : -ENOSPC;  } + +#if (YAFFS_USE_WRITE_BEGIN_END > 0) +static int yaffs_write_begin(struct file *filp, struct address_space *mapping, +				loff_t pos, unsigned len, unsigned flags, +				struct page **pagep, void **fsdata) +{ +	struct page *pg = NULL; +	pgoff_t index = pos >> PAGE_CACHE_SHIFT; +	uint32_t offset = pos & (PAGE_CACHE_SIZE - 1); +	uint32_t to = offset + len; + +	int ret = 0; +	int space_held = 0; + +	T(YAFFS_TRACE_OS, ("start yaffs_write_begin\n")); +	/* Get a page */ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 28) +	pg = grab_cache_page_write_begin(mapping, index, flags); +#else +	pg = __grab_cache_page(mapping, index); +#endif + +	*pagep = pg; +	if (!pg) { +		ret =  -ENOMEM; +		goto out; +	} +	/* Get fs space */ +	space_held = yaffs_hold_space(filp); + +	if (!space_held) { +		ret = -ENOSPC; +		goto out; +	} + +	/* Update page if required */ + +	if (!Page_Uptodate(pg) && (offset || to < PAGE_CACHE_SIZE)) +		ret = yaffs_readpage_nolock(filp, pg); + +	if (ret) +		goto out; + +	/* Happy path return */ +	T(YAFFS_TRACE_OS, ("end yaffs_write_begin - ok\n")); + +	return 0; + +out: +	T(YAFFS_TRACE_OS, ("end yaffs_write_begin fail returning %d\n", ret)); +	if (space_held) +		yaffs_release_space(filp); +	if (pg) { +		unlock_page(pg); +		page_cache_release(pg); +	} +	return ret; +} + +#else +  static int yaffs_prepare_write(struct file *f, struct page *pg, -			       unsigned offset, unsigned to) +				unsigned offset, unsigned to)  { +	T(YAFFS_TRACE_OS, ("yaffs_prepair_write\n")); -	T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_prepair_write\n"));  	if (!Page_Uptodate(pg) && (offset || to < PAGE_CACHE_SIZE))  		return yaffs_readpage_nolock(f, pg); -  	return 0; +} +#endif + +#if (YAFFS_USE_WRITE_BEGIN_END > 0) +static int yaffs_write_end(struct file *filp, struct address_space *mapping, +				loff_t pos, unsigned len, unsigned copied, +				struct page *pg, void *fsdadata) +{ +	int ret = 0; +	void *addr, *kva; +	uint32_t offset_into_page = pos & (PAGE_CACHE_SIZE - 1); + +	kva = kmap(pg); +	addr = kva + offset_into_page; + +	T(YAFFS_TRACE_OS, +		("yaffs_write_end addr %x pos %x nBytes %d\n", +		(unsigned) addr, +		(int)pos, copied)); + +	ret = yaffs_file_write(filp, addr, copied, &pos); +	if (ret != copied) { +		T(YAFFS_TRACE_OS, +			("yaffs_write_end not same size ret %d  copied %d\n", +			ret, copied)); +		SetPageError(pg); +		ClearPageUptodate(pg); +	} else { +		SetPageUptodate(pg); +	} + +	kunmap(pg); + +	yaffs_release_space(filp); +	unlock_page(pg); +	page_cache_release(pg); +	return ret;  } +#else  static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset, -			      unsigned to) +				unsigned to)  { +	void *addr, *kva; -	void *addr = page_address(pg) + offset;  	loff_t pos = (((loff_t) pg->index) << PAGE_CACHE_SHIFT) + offset;  	int nBytes = to - offset;  	int nWritten;  	unsigned spos = pos; -	unsigned saddr = (unsigned)addr; +	unsigned saddr; + +	kva = kmap(pg); +	addr = kva + offset; + +	saddr = (unsigned) addr;  	T(YAFFS_TRACE_OS, -	  (KERN_DEBUG "yaffs_commit_write addr %x pos %x nBytes %d\n", saddr, -	   spos, nBytes)); +		("yaffs_commit_write addr %x pos %x nBytes %d\n", +		saddr, spos, nBytes));  	nWritten = yaffs_file_write(f, addr, nBytes, &pos);  	if (nWritten != nBytes) {  		T(YAFFS_TRACE_OS, -		  (KERN_DEBUG -		   "yaffs_commit_write not same size nWritten %d  nBytes %d\n", -		   nWritten, nBytes)); +			("yaffs_commit_write not same size nWritten %d  nBytes %d\n", +			nWritten, nBytes));  		SetPageError(pg);  		ClearPageUptodate(pg);  	} else {  		SetPageUptodate(pg);  	} +	kunmap(pg); +  	T(YAFFS_TRACE_OS, -	  (KERN_DEBUG "yaffs_commit_write returning %d\n", -	   nWritten == nBytes ? 0 : nWritten)); +		("yaffs_commit_write returning %d\n", +		nWritten == nBytes ? 0 : nWritten));  	return nWritten == nBytes ? 0 : nWritten; -  } +#endif -static void yaffs_FillInodeFromObject(struct inode *inode, yaffs_Object * obj) + +static void yaffs_FillInodeFromObject(struct inode *inode, yaffs_Object *obj)  {  	if (inode && obj) {  		/* Check mode against the variant type and attempt to repair if broken. */ - 		__u32 mode = obj->yst_mode; - 		switch( obj->variantType ){ - 		case YAFFS_OBJECT_TYPE_FILE : - 		        if( ! S_ISREG(mode) ){ - 			        obj->yst_mode &= ~S_IFMT; - 			        obj->yst_mode |= S_IFREG; - 			} - - 			break; - 		case YAFFS_OBJECT_TYPE_SYMLINK : - 		        if( ! S_ISLNK(mode) ){ - 			        obj->yst_mode &= ~S_IFMT; - 				obj->yst_mode |= S_IFLNK; - 			} - - 			break; - 		case YAFFS_OBJECT_TYPE_DIRECTORY : - 		        if( ! S_ISDIR(mode) ){ - 			        obj->yst_mode &= ~S_IFMT; - 			        obj->yst_mode |= S_IFDIR; - 			} - - 			break; - 		case YAFFS_OBJECT_TYPE_UNKNOWN : - 		case YAFFS_OBJECT_TYPE_HARDLINK : - 		case YAFFS_OBJECT_TYPE_SPECIAL : - 		default: - 		        /* TODO? */ - 		        break; - 		} +		__u32 mode = obj->yst_mode; +		switch (obj->variantType) { +		case YAFFS_OBJECT_TYPE_FILE: +			if (!S_ISREG(mode)) { +				obj->yst_mode &= ~S_IFMT; +				obj->yst_mode |= S_IFREG; +			} + +			break; +		case YAFFS_OBJECT_TYPE_SYMLINK: +			if (!S_ISLNK(mode)) { +				obj->yst_mode &= ~S_IFMT; +				obj->yst_mode |= S_IFLNK; +			} + +			break; +		case YAFFS_OBJECT_TYPE_DIRECTORY: +			if (!S_ISDIR(mode)) { +				obj->yst_mode &= ~S_IFMT; +				obj->yst_mode |= S_IFDIR; +			} + +			break; +		case YAFFS_OBJECT_TYPE_UNKNOWN: +		case YAFFS_OBJECT_TYPE_HARDLINK: +		case YAFFS_OBJECT_TYPE_SPECIAL: +		default: +			/* TODO? */ +			break; +		} + +		inode->i_flags |= S_NOATIME;  		inode->i_ino = obj->objectId;  		inode->i_mode = obj->yst_mode;  		inode->i_uid = obj->yst_uid;  		inode->i_gid = obj->yst_gid; -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)) +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))  		inode->i_blksize = inode->i_sb->s_blocksize;  #endif -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))  		inode->i_rdev = old_decode_dev(obj->yst_rdev);  		inode->i_atime.tv_sec = (time_t) (obj->yst_atime); @@ -781,26 +951,25 @@ static void yaffs_FillInodeFromObject(struct inode *inode, yaffs_Object * obj)  		inode->i_nlink = yaffs_GetObjectLinkCount(obj);  		T(YAFFS_TRACE_OS, -		  (KERN_DEBUG -		   "yaffs_FillInode mode %x uid %d gid %d size %d count %d\n", -		   inode->i_mode, inode->i_uid, inode->i_gid, -		   (int)inode->i_size, atomic_read(&inode->i_count))); +			("yaffs_FillInode mode %x uid %d gid %d size %d count %d\n", +			inode->i_mode, inode->i_uid, inode->i_gid, +			(int)inode->i_size, atomic_read(&inode->i_count)));  		switch (obj->yst_mode & S_IFMT) {  		default:	/* fifo, device or socket */ -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))  			init_special_inode(inode, obj->yst_mode, -					   old_decode_dev(obj->yst_rdev)); +					old_decode_dev(obj->yst_rdev));  #else  			init_special_inode(inode, obj->yst_mode, -					   (dev_t) (obj->yst_rdev)); +					(dev_t) (obj->yst_rdev));  #endif  			break;  		case S_IFREG:	/* file */  			inode->i_op = &yaffs_file_inode_operations;  			inode->i_fop = &yaffs_file_operations;  			inode->i_mapping->a_ops = -			    &yaffs_file_address_operations; +				&yaffs_file_address_operations;  			break;  		case S_IFDIR:	/* directory */  			inode->i_op = &yaffs_dir_inode_operations; @@ -817,34 +986,36 @@ static void yaffs_FillInodeFromObject(struct inode *inode, yaffs_Object * obj)  	} else {  		T(YAFFS_TRACE_OS, -		  (KERN_DEBUG "yaffs_FileInode invalid parameters\n")); +			("yaffs_FileInode invalid parameters\n"));  	}  }  struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev, -			      yaffs_Object * obj) +				yaffs_Object *obj)  {  	struct inode *inode;  	if (!sb) {  		T(YAFFS_TRACE_OS, -		  (KERN_DEBUG "yaffs_get_inode for NULL super_block!!\n")); +			("yaffs_get_inode for NULL super_block!!\n"));  		return NULL;  	}  	if (!obj) {  		T(YAFFS_TRACE_OS, -		  (KERN_DEBUG "yaffs_get_inode for NULL object!!\n")); +			("yaffs_get_inode for NULL object!!\n"));  		return NULL;  	}  	T(YAFFS_TRACE_OS, -	  (KERN_DEBUG "yaffs_get_inode for object %d\n", obj->objectId)); +		("yaffs_get_inode for object %d\n", obj->objectId)); -	inode = iget(sb, obj->objectId); +	inode = Y_IGET(sb, obj->objectId); +	if (IS_ERR(inode)) +		return NULL;  	/* NB Side effect: iget calls back to yaffs_read_inode(). */  	/* iget also increments the inode's i_count */ @@ -854,7 +1025,7 @@ struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev,  }  static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n, -				loff_t * pos) +				loff_t *pos)  {  	yaffs_Object *obj;  	int nWritten, ipos; @@ -869,28 +1040,26 @@ static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n,  	inode = f->f_dentry->d_inode; -	if (!S_ISBLK(inode->i_mode) && f->f_flags & O_APPEND) { +	if (!S_ISBLK(inode->i_mode) && f->f_flags & O_APPEND)  		ipos = inode->i_size; -	} else { +	else  		ipos = *pos; -	} -	if (!obj) { +	if (!obj)  		T(YAFFS_TRACE_OS, -		  (KERN_DEBUG "yaffs_file_write: hey obj is null!\n")); -	} else { +			("yaffs_file_write: hey obj is null!\n")); +	else  		T(YAFFS_TRACE_OS, -		  (KERN_DEBUG -		   "yaffs_file_write about to write writing %d bytes" -		   "to object %d at %d\n", -		   n, obj->objectId, ipos)); -	} +			("yaffs_file_write about to write writing %zu bytes" +			"to object %d at %d\n", +			n, obj->objectId, ipos));  	nWritten = yaffs_WriteDataToFile(obj, buf, ipos, n, 0);  	T(YAFFS_TRACE_OS, -	  (KERN_DEBUG "yaffs_file_write writing %d bytes, %d written at %d\n", -	   n, nWritten, ipos)); +		("yaffs_file_write writing %zu bytes, %d written at %d\n", +		n, nWritten, ipos)); +  	if (nWritten > 0) {  		ipos += nWritten;  		*pos = ipos; @@ -899,10 +1068,9 @@ static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n,  			inode->i_blocks = (ipos + 511) >> 9;  			T(YAFFS_TRACE_OS, -			  (KERN_DEBUG -			   "yaffs_file_write size updated to %d bytes, " -			   "%d blocks\n", -			   ipos, (int)(inode->i_blocks))); +				("yaffs_file_write size updated to %d bytes, " +				"%d blocks\n", +				ipos, (int)(inode->i_blocks)));  		}  	} @@ -910,13 +1078,54 @@ static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n,  	return nWritten == 0 ? -ENOSPC : nWritten;  } +/* Space holding and freeing is done to ensure we have space available for write_begin/end */ +/* For now we just assume few parallel writes and check against a small number. */ +/* Todo: need to do this with a counter to handle parallel reads better */ + +static ssize_t yaffs_hold_space(struct file *f) +{ +	yaffs_Object *obj; +	yaffs_Device *dev; + +	int nFreeChunks; + + +	obj = yaffs_DentryToObject(f->f_dentry); + +	dev = obj->myDev; + +	yaffs_GrossLock(dev); + +	nFreeChunks = yaffs_GetNumberOfFreeChunks(dev); + +	yaffs_GrossUnlock(dev); + +	return (nFreeChunks > 20) ? 1 : 0; +} + +static void yaffs_release_space(struct file *f) +{ +	yaffs_Object *obj; +	yaffs_Device *dev; + + +	obj = yaffs_DentryToObject(f->f_dentry); + +	dev = obj->myDev; + +	yaffs_GrossLock(dev); + + +	yaffs_GrossUnlock(dev); +} +  static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir)  {  	yaffs_Object *obj;  	yaffs_Device *dev;  	struct inode *inode = f->f_dentry->d_inode;  	unsigned long offset, curoffs; -	struct list_head *i; +	struct ylist_head *i;  	yaffs_Object *l;  	char name[YAFFS_MAX_NAME_LENGTH + 1]; @@ -932,24 +1141,20 @@ static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir)  	if (offset == 0) {  		T(YAFFS_TRACE_OS, -		  (KERN_DEBUG "yaffs_readdir: entry . ino %d \n", -		   (int)inode->i_ino)); -		if (filldir(dirent, ".", 1, offset, inode->i_ino, DT_DIR) -		    < 0) { +			("yaffs_readdir: entry . ino %d \n", +			(int)inode->i_ino)); +		if (filldir(dirent, ".", 1, offset, inode->i_ino, DT_DIR) < 0)  			goto out; -		}  		offset++;  		f->f_pos++;  	}  	if (offset == 1) {  		T(YAFFS_TRACE_OS, -		  (KERN_DEBUG "yaffs_readdir: entry .. ino %d \n", -		   (int)f->f_dentry->d_parent->d_inode->i_ino)); -		if (filldir -		    (dirent, "..", 2, offset, -		     f->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) { +			("yaffs_readdir: entry .. ino %d \n", +			(int)f->f_dentry->d_parent->d_inode->i_ino)); +		if (filldir(dirent, "..", 2, offset, +			f->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0)  			goto out; -		}  		offset++;  		f->f_pos++;  	} @@ -965,35 +1170,32 @@ static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir)  		f->f_version = inode->i_version;  	} -	list_for_each(i, &obj->variant.directoryVariant.children) { +	ylist_for_each(i, &obj->variant.directoryVariant.children) {  		curoffs++;  		if (curoffs >= offset) { -			l = list_entry(i, yaffs_Object, siblings); +			l = ylist_entry(i, yaffs_Object, siblings);  			yaffs_GetObjectName(l, name,  					    YAFFS_MAX_NAME_LENGTH + 1);  			T(YAFFS_TRACE_OS, -			  (KERN_DEBUG "yaffs_readdir: %s inode %d\n", name, +			  ("yaffs_readdir: %s inode %d\n", name,  			   yaffs_GetObjectInode(l)));  			if (filldir(dirent, -				    name, -				    strlen(name), -				    offset, -				    yaffs_GetObjectInode(l), -				    yaffs_GetObjectType(l)) -			    < 0) { +					name, +					strlen(name), +					offset, +					yaffs_GetObjectInode(l), +					yaffs_GetObjectType(l)) < 0)  				goto up_and_out; -			}  			offset++;  			f->f_pos++;  		}  	} -      up_and_out: -      out: - +up_and_out: +out:  	yaffs_GrossUnlock(dev);  	return 0; @@ -1002,12 +1204,19 @@ static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir)  /*   * File creation. Allocate an inode, and we're done..   */ -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29) +#define YCRED(x) x +#else +#define YCRED(x) (x->cred) +#endif + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))  static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, -		       dev_t rdev) +			dev_t rdev)  #else  static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, -		       int rdev) +			int rdev)  #endif  {  	struct inode *inode; @@ -1018,25 +1227,25 @@ static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,  	yaffs_Object *parent = yaffs_InodeToObject(dir);  	int error = -ENOSPC; -	uid_t uid = current->fsuid; -	gid_t gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid; +	uid_t uid = YCRED(current)->fsuid; +	gid_t gid = (dir->i_mode & S_ISGID) ? dir->i_gid : YCRED(current)->fsgid; -	if((dir->i_mode & S_ISGID) && S_ISDIR(mode)) +	if ((dir->i_mode & S_ISGID) && S_ISDIR(mode))  		mode |= S_ISGID;  	if (parent) {  		T(YAFFS_TRACE_OS, -		  (KERN_DEBUG "yaffs_mknod: parent object %d type %d\n", -		   parent->objectId, parent->variantType)); +			("yaffs_mknod: parent object %d type %d\n", +			parent->objectId, parent->variantType));  	} else {  		T(YAFFS_TRACE_OS, -		  (KERN_DEBUG "yaffs_mknod: could not get parent object\n")); +			("yaffs_mknod: could not get parent object\n"));  		return -EPERM;  	}  	T(YAFFS_TRACE_OS, ("yaffs_mknod: making oject for %s, " -			   "mode %x dev %x\n", -			   dentry->d_name.name, mode, rdev)); +			"mode %x dev %x\n", +			dentry->d_name.name, mode, rdev));  	dev = parent->myDev; @@ -1045,33 +1254,28 @@ static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,  	switch (mode & S_IFMT) {  	default:  		/* Special (socket, fifo, device...) */ -		T(YAFFS_TRACE_OS, (KERN_DEBUG -				   "yaffs_mknod: making special\n")); -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -		obj = -		    yaffs_MknodSpecial(parent, dentry->d_name.name, mode, uid, -				       gid, old_encode_dev(rdev)); +		T(YAFFS_TRACE_OS, ("yaffs_mknod: making special\n")); +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) +		obj = yaffs_MknodSpecial(parent, dentry->d_name.name, mode, uid, +				gid, old_encode_dev(rdev));  #else -		obj = -		    yaffs_MknodSpecial(parent, dentry->d_name.name, mode, uid, -				       gid, rdev); +		obj = yaffs_MknodSpecial(parent, dentry->d_name.name, mode, uid, +				gid, rdev);  #endif  		break;  	case S_IFREG:		/* file          */ -		T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_mknod: making file\n")); -		obj = -		    yaffs_MknodFile(parent, dentry->d_name.name, mode, uid, -				    gid); +		T(YAFFS_TRACE_OS, ("yaffs_mknod: making file\n")); +		obj = yaffs_MknodFile(parent, dentry->d_name.name, mode, uid, +				gid);  		break;  	case S_IFDIR:		/* directory */  		T(YAFFS_TRACE_OS, -		  (KERN_DEBUG "yaffs_mknod: making directory\n")); -		obj = -		    yaffs_MknodDirectory(parent, dentry->d_name.name, mode, -					 uid, gid); +			("yaffs_mknod: making directory\n")); +		obj = yaffs_MknodDirectory(parent, dentry->d_name.name, mode, +					uid, gid);  		break;  	case S_IFLNK:		/* symlink */ -		T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_mknod: making file\n")); +		T(YAFFS_TRACE_OS, ("yaffs_mknod: making symlink\n"));  		obj = NULL;	/* Do we ever get here? */  		break;  	} @@ -1083,12 +1287,12 @@ static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,  		inode = yaffs_get_inode(dir->i_sb, mode, rdev, obj);  		d_instantiate(dentry, inode);  		T(YAFFS_TRACE_OS, -		  (KERN_DEBUG "yaffs_mknod created object %d count = %d\n", -		   obj->objectId, atomic_read(&inode->i_count))); +			("yaffs_mknod created object %d count = %d\n", +			obj->objectId, atomic_read(&inode->i_count)));  		error = 0;  	} else {  		T(YAFFS_TRACE_OS, -		  (KERN_DEBUG "yaffs_mknod failed making object\n")); +			("yaffs_mknod failed making object\n"));  		error = -ENOMEM;  	} @@ -1098,25 +1302,19 @@ static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,  static int yaffs_mkdir(struct inode *dir, struct dentry *dentry, int mode)  {  	int retVal; -	T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_mkdir\n")); +	T(YAFFS_TRACE_OS, ("yaffs_mkdir\n"));  	retVal = yaffs_mknod(dir, dentry, mode | S_IFDIR, 0); -#if 0 -	/* attempt to fix dir bug - didn't work */ -	if (!retVal) { -		dget(dentry); -	} -#endif  	return retVal;  } -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))  static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode,  			struct nameidata *n)  #else  static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode)  #endif  { -	T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_create\n")); +	T(YAFFS_TRACE_OS, ("yaffs_create\n"));  	return yaffs_mknod(dir, dentry, mode | S_IFREG, 0);  } @@ -1127,8 +1325,8 @@ static int yaffs_unlink(struct inode *dir, struct dentry *dentry)  	yaffs_Device *dev;  	T(YAFFS_TRACE_OS, -	  (KERN_DEBUG "yaffs_unlink %d:%s\n", (int)(dir->i_ino), -	   dentry->d_name.name)); +		("yaffs_unlink %d:%s\n", (int)(dir->i_ino), +		dentry->d_name.name));  	dev = yaffs_InodeToObject(dir)->myDev; @@ -1151,82 +1349,74 @@ static int yaffs_unlink(struct inode *dir, struct dentry *dentry)   * Create a link...   */  static int yaffs_link(struct dentry *old_dentry, struct inode *dir, -		      struct dentry *dentry) +			struct dentry *dentry)  {  	struct inode *inode = old_dentry->d_inode;  	yaffs_Object *obj = NULL;  	yaffs_Object *link = NULL;  	yaffs_Device *dev; -	T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_link\n")); +	T(YAFFS_TRACE_OS, ("yaffs_link\n"));  	obj = yaffs_InodeToObject(inode);  	dev = obj->myDev;  	yaffs_GrossLock(dev); -	if (!S_ISDIR(inode->i_mode))	/* Don't link directories */ -	{ -		link = -		    yaffs_Link(yaffs_InodeToObject(dir), dentry->d_name.name, -			       obj); -	} +	if (!S_ISDIR(inode->i_mode))		/* Don't link directories */ +		link = yaffs_Link(yaffs_InodeToObject(dir), dentry->d_name.name, +			obj);  	if (link) {  		old_dentry->d_inode->i_nlink = yaffs_GetObjectLinkCount(obj);  		d_instantiate(dentry, old_dentry->d_inode);  		atomic_inc(&old_dentry->d_inode->i_count);  		T(YAFFS_TRACE_OS, -		  (KERN_DEBUG "yaffs_link link count %d i_count %d\n", -		   old_dentry->d_inode->i_nlink, -		   atomic_read(&old_dentry->d_inode->i_count))); - +			("yaffs_link link count %d i_count %d\n", +			old_dentry->d_inode->i_nlink, +			atomic_read(&old_dentry->d_inode->i_count)));  	}  	yaffs_GrossUnlock(dev); -	if (link) { - +	if (link)  		return 0; -	}  	return -EPERM;  }  static int yaffs_symlink(struct inode *dir, struct dentry *dentry, -			 const char *symname) +				const char *symname)  {  	yaffs_Object *obj;  	yaffs_Device *dev; -	uid_t uid = current->fsuid; -	gid_t gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid; +	uid_t uid = YCRED(current)->fsuid; +	gid_t gid = (dir->i_mode & S_ISGID) ? dir->i_gid : YCRED(current)->fsgid; -	T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_symlink\n")); +	T(YAFFS_TRACE_OS, ("yaffs_symlink\n"));  	dev = yaffs_InodeToObject(dir)->myDev;  	yaffs_GrossLock(dev);  	obj = yaffs_MknodSymLink(yaffs_InodeToObject(dir), dentry->d_name.name, -				 S_IFLNK | S_IRWXUGO, uid, gid, symname); +				S_IFLNK | S_IRWXUGO, uid, gid, symname);  	yaffs_GrossUnlock(dev);  	if (obj) { -  		struct inode *inode;  		inode = yaffs_get_inode(dir->i_sb, obj->yst_mode, 0, obj);  		d_instantiate(dentry, inode); -		T(YAFFS_TRACE_OS, (KERN_DEBUG "symlink created OK\n")); +		T(YAFFS_TRACE_OS, ("symlink created OK\n"));  		return 0;  	} else { -		T(YAFFS_TRACE_OS, (KERN_DEBUG "symlink not created\n")); - +		T(YAFFS_TRACE_OS, ("symlink not created\n"));  	}  	return -ENOMEM;  }  static int yaffs_sync_object(struct file *file, struct dentry *dentry, -			     int datasync) +				int datasync)  {  	yaffs_Object *obj; @@ -1236,7 +1426,7 @@ static int yaffs_sync_object(struct file *file, struct dentry *dentry,  	dev = obj->myDev; -	T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_sync_object\n")); +	T(YAFFS_TRACE_OS, ("yaffs_sync_object\n"));  	yaffs_GrossLock(dev);  	yaffs_FlushFile(obj, 1);  	yaffs_GrossUnlock(dev); @@ -1255,41 +1445,36 @@ static int yaffs_rename(struct inode *old_dir, struct dentry *old_dentry,  	int retVal = YAFFS_FAIL;  	yaffs_Object *target; -        T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_rename\n")); +	T(YAFFS_TRACE_OS, ("yaffs_rename\n"));  	dev = yaffs_InodeToObject(old_dir)->myDev;  	yaffs_GrossLock(dev);  	/* Check if the target is an existing directory that is not empty. */ -	target = -	    yaffs_FindObjectByName(yaffs_InodeToObject(new_dir), -				   new_dentry->d_name.name); +	target = yaffs_FindObjectByName(yaffs_InodeToObject(new_dir), +				new_dentry->d_name.name); -	if (target && -	    target->variantType == YAFFS_OBJECT_TYPE_DIRECTORY && -	    !list_empty(&target->variant.directoryVariant.children)) { +	if (target && target->variantType == YAFFS_OBJECT_TYPE_DIRECTORY && +		!ylist_empty(&target->variant.directoryVariant.children)) { -	        T(YAFFS_TRACE_OS, (KERN_DEBUG "target is non-empty dir\n")); +		T(YAFFS_TRACE_OS, ("target is non-empty dir\n"));  		retVal = YAFFS_FAIL;  	} else { -  		/* Now does unlinking internally using shadowing mechanism */ -	        T(YAFFS_TRACE_OS, (KERN_DEBUG "calling yaffs_RenameObject\n")); - -		retVal = -		    yaffs_RenameObject(yaffs_InodeToObject(old_dir), -				       old_dentry->d_name.name, -				       yaffs_InodeToObject(new_dir), -				       new_dentry->d_name.name); +		T(YAFFS_TRACE_OS, ("calling yaffs_RenameObject\n")); +		retVal = yaffs_RenameObject(yaffs_InodeToObject(old_dir), +				old_dentry->d_name.name, +				yaffs_InodeToObject(new_dir), +				new_dentry->d_name.name);  	}  	yaffs_GrossUnlock(dev);  	if (retVal == YAFFS_OK) { -		if(target) { +		if (target) {  			new_dentry->d_inode->i_nlink--;  			mark_inode_dirty(new_dentry->d_inode);  		} @@ -1298,7 +1483,6 @@ static int yaffs_rename(struct inode *old_dir, struct dentry *old_dentry,  	} else {  		return -ENOTEMPTY;  	} -  }  static int yaffs_setattr(struct dentry *dentry, struct iattr *attr) @@ -1308,15 +1492,15 @@ static int yaffs_setattr(struct dentry *dentry, struct iattr *attr)  	yaffs_Device *dev;  	T(YAFFS_TRACE_OS, -	  (KERN_DEBUG "yaffs_setattr of object %d\n", -	   yaffs_InodeToObject(inode)->objectId)); - -	if ((error = inode_change_ok(inode, attr)) == 0) { +		("yaffs_setattr of object %d\n", +		yaffs_InodeToObject(inode)->objectId)); +	error = inode_change_ok(inode, attr); +	if (error == 0) {  		dev = yaffs_InodeToObject(inode)->myDev;  		yaffs_GrossLock(dev);  		if (yaffs_SetAttributes(yaffs_InodeToObject(inode), attr) == -		    YAFFS_OK) { +				YAFFS_OK) {  			error = 0;  		} else {  			error = -EPERM; @@ -1328,12 +1512,12 @@ static int yaffs_setattr(struct dentry *dentry, struct iattr *attr)  	return error;  } -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))  static int yaffs_statfs(struct dentry *dentry, struct kstatfs *buf)  {  	yaffs_Device *dev = yaffs_DentryToObject(dentry)->myDev;  	struct super_block *sb = dentry->d_sb; -#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) +#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))  static int yaffs_statfs(struct super_block *sb, struct kstatfs *buf)  {  	yaffs_Device *dev = yaffs_SuperToDevice(sb); @@ -1343,32 +1527,53 @@ static int yaffs_statfs(struct super_block *sb, struct statfs *buf)  	yaffs_Device *dev = yaffs_SuperToDevice(sb);  #endif -	T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_statfs\n")); +	T(YAFFS_TRACE_OS, ("yaffs_statfs\n"));  	yaffs_GrossLock(dev);  	buf->f_type = YAFFS_MAGIC;  	buf->f_bsize = sb->s_blocksize;  	buf->f_namelen = 255; -	if (sb->s_blocksize > dev->nDataBytesPerChunk) { + +	if (dev->nDataBytesPerChunk & (dev->nDataBytesPerChunk - 1)) { +		/* Do this if chunk size is not a power of 2 */ + +		uint64_t bytesInDev; +		uint64_t bytesFree; + +		bytesInDev = ((uint64_t)((dev->endBlock - dev->startBlock + 1))) * +			((uint64_t)(dev->nChunksPerBlock * dev->nDataBytesPerChunk)); + +		do_div(bytesInDev, sb->s_blocksize); /* bytesInDev becomes the number of blocks */ +		buf->f_blocks = bytesInDev; + +		bytesFree  = ((uint64_t)(yaffs_GetNumberOfFreeChunks(dev))) * +			((uint64_t)(dev->nDataBytesPerChunk)); + +		do_div(bytesFree, sb->s_blocksize); + +		buf->f_bfree = bytesFree; + +	} else if (sb->s_blocksize > dev->nDataBytesPerChunk) {  		buf->f_blocks = -		    (dev->endBlock - dev->startBlock + -		     1) * dev->nChunksPerBlock / (sb->s_blocksize / -						  dev->nDataBytesPerChunk); +			(dev->endBlock - dev->startBlock + 1) * +			dev->nChunksPerBlock / +			(sb->s_blocksize / dev->nDataBytesPerChunk);  		buf->f_bfree = -		    yaffs_GetNumberOfFreeChunks(dev) / (sb->s_blocksize / -							dev->nDataBytesPerChunk); +			yaffs_GetNumberOfFreeChunks(dev) / +			(sb->s_blocksize / dev->nDataBytesPerChunk);  	} else { -  		buf->f_blocks = -		    (dev->endBlock - dev->startBlock + -		     1) * dev->nChunksPerBlock * (dev->nDataBytesPerChunk / -						  sb->s_blocksize); +			(dev->endBlock - dev->startBlock + 1) * +			dev->nChunksPerBlock * +			(dev->nDataBytesPerChunk / sb->s_blocksize); +  		buf->f_bfree = -		    yaffs_GetNumberOfFreeChunks(dev) * (dev->nDataBytesPerChunk / -							sb->s_blocksize); +			yaffs_GetNumberOfFreeChunks(dev) * +			(dev->nDataBytesPerChunk / sb->s_blocksize);  	} +  	buf->f_files = 0;  	buf->f_ffree = 0;  	buf->f_bavail = buf->f_bfree; @@ -1378,18 +1583,19 @@ static int yaffs_statfs(struct super_block *sb, struct statfs *buf)  } -/**  static int yaffs_do_sync_fs(struct super_block *sb)  {  	yaffs_Device *dev = yaffs_SuperToDevice(sb); -	T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_do_sync_fs\n")); +	T(YAFFS_TRACE_OS, ("yaffs_do_sync_fs\n")); -	if(sb->s_dirt) { +	if (sb->s_dirt) {  		yaffs_GrossLock(dev); -		if(dev) +		if (dev) { +			yaffs_FlushEntireDeviceCache(dev);  			yaffs_CheckpointSave(dev); +		}  		yaffs_GrossUnlock(dev); @@ -1397,35 +1603,73 @@ static int yaffs_do_sync_fs(struct super_block *sb)  	}  	return 0;  } -**/ -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))  static void yaffs_write_super(struct super_block *sb)  #else  static int yaffs_write_super(struct super_block *sb)  #endif  { -	T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_write_super\n")); -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)) -	return 0; /* yaffs_do_sync_fs(sb);*/ +	T(YAFFS_TRACE_OS, ("yaffs_write_super\n")); +	if (yaffs_auto_checkpoint >= 2) +		yaffs_do_sync_fs(sb); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)) +	return 0;  #endif  } -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))  static int yaffs_sync_fs(struct super_block *sb, int wait)  #else  static int yaffs_sync_fs(struct super_block *sb)  #endif  { +	T(YAFFS_TRACE_OS, ("yaffs_sync_fs\n")); + +	if (yaffs_auto_checkpoint >= 1) +		yaffs_do_sync_fs(sb); + +	return 0; +} + +#ifdef YAFFS_USE_OWN_IGET -	T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_sync_fs\n")); +static struct inode *yaffs_iget(struct super_block *sb, unsigned long ino) +{ +	struct inode *inode; +	yaffs_Object *obj; +	yaffs_Device *dev = yaffs_SuperToDevice(sb); -	return 0; /* yaffs_do_sync_fs(sb);*/ +	T(YAFFS_TRACE_OS, +		("yaffs_iget for %lu\n", ino)); +	inode = iget_locked(sb, ino); +	if (!inode) +		return ERR_PTR(-ENOMEM); +	if (!(inode->i_state & I_NEW)) +		return inode; + +	/* NB This is called as a side effect of other functions, but +	 * we had to release the lock to prevent deadlocks, so +	 * need to lock again. +	 */ + +	yaffs_GrossLock(dev); + +	obj = yaffs_FindObjectByNumber(dev, inode->i_ino); + +	yaffs_FillInodeFromObject(inode, obj); + +	yaffs_GrossUnlock(dev); + +	unlock_new_inode(inode); +	return inode;  } +#else  static void yaffs_read_inode(struct inode *inode)  { @@ -1438,7 +1682,7 @@ static void yaffs_read_inode(struct inode *inode)  	yaffs_Device *dev = yaffs_SuperToDevice(inode->i_sb);  	T(YAFFS_TRACE_OS, -	  (KERN_DEBUG "yaffs_read_inode for %d\n", (int)inode->i_ino)); +		("yaffs_read_inode for %d\n", (int)inode->i_ino));  	yaffs_GrossLock(dev); @@ -1449,18 +1693,20 @@ static void yaffs_read_inode(struct inode *inode)  	yaffs_GrossUnlock(dev);  } -static LIST_HEAD(yaffs_dev_list); +#endif + +static YLIST_HEAD(yaffs_dev_list); -#if 0 // not used +#if 0 /* not used */  static int yaffs_remount_fs(struct super_block *sb, int *flags, char *data)  {  	yaffs_Device    *dev = yaffs_SuperToDevice(sb); -	if( *flags & MS_RDONLY ) { +	if (*flags & MS_RDONLY) {  		struct mtd_info *mtd = yaffs_SuperToDevice(sb)->genericDevice;  		T(YAFFS_TRACE_OS, -			(KERN_DEBUG "yaffs_remount_fs: %s: RO\n", dev->name )); +			("yaffs_remount_fs: %s: RO\n", dev->name));  		yaffs_GrossLock(dev); @@ -1472,10 +1718,9 @@ static int yaffs_remount_fs(struct super_block *sb, int *flags, char *data)  			mtd->sync(mtd);  		yaffs_GrossUnlock(dev); -	} -	else { +	} else {  		T(YAFFS_TRACE_OS, -			(KERN_DEBUG "yaffs_remount_fs: %s: RW\n", dev->name )); +			("yaffs_remount_fs: %s: RW\n", dev->name));  	}  	return 0; @@ -1486,7 +1731,7 @@ static void yaffs_put_super(struct super_block *sb)  {  	yaffs_Device *dev = yaffs_SuperToDevice(sb); -	T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_put_super\n")); +	T(YAFFS_TRACE_OS, ("yaffs_put_super\n"));  	yaffs_GrossLock(dev); @@ -1494,18 +1739,17 @@ static void yaffs_put_super(struct super_block *sb)  	yaffs_CheckpointSave(dev); -	if (dev->putSuperFunc) { +	if (dev->putSuperFunc)  		dev->putSuperFunc(sb); -	}  	yaffs_Deinitialise(dev);  	yaffs_GrossUnlock(dev);  	/* we assume this is protected by lock_kernel() in mount/umount */ -	list_del(&dev->devList); +	ylist_del(&dev->devList); -	if(dev->spareBuffer){ +	if (dev->spareBuffer) {  		YFREE(dev->spareBuffer);  		dev->spareBuffer = NULL;  	} @@ -1516,12 +1760,10 @@ static void yaffs_put_super(struct super_block *sb)  static void yaffs_MTDPutSuper(struct super_block *sb)  { -  	struct mtd_info *mtd = yaffs_SuperToDevice(sb)->genericDevice; -	if (mtd->sync) { +	if (mtd->sync)  		mtd->sync(mtd); -	}  	put_mtd_device(mtd);  } @@ -1531,9 +1773,9 @@ static void yaffs_MarkSuperBlockDirty(void *vsb)  {  	struct super_block *sb = (struct super_block *)vsb; -	T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_MarkSuperBlockDirty() sb = %p\n",sb)); -//	if(sb) -//		sb->s_dirt = 1; +	T(YAFFS_TRACE_OS, ("yaffs_MarkSuperBlockDirty() sb = %p\n", sb)); +	if (sb) +		sb->s_dirt = 1;  }  typedef struct { @@ -1546,48 +1788,48 @@ typedef struct {  #define MAX_OPT_LEN 20  static int yaffs_parse_options(yaffs_options *options, const char *options_str)  { -	char cur_opt[MAX_OPT_LEN+1]; +	char cur_opt[MAX_OPT_LEN + 1];  	int p;  	int error = 0;  	/* Parse through the options which is a comma seperated list */ -	while(options_str && *options_str && !error){ -		memset(cur_opt,0,MAX_OPT_LEN+1); +	while (options_str && *options_str && !error) { +		memset(cur_opt, 0, MAX_OPT_LEN + 1);  		p = 0; -		while(*options_str && *options_str != ','){ -			if(p < MAX_OPT_LEN){ +		while (*options_str && *options_str != ',') { +			if (p < MAX_OPT_LEN) {  				cur_opt[p] = *options_str;  				p++;  			}  			options_str++;  		} -		if(!strcmp(cur_opt,"inband-tags")) +		if (!strcmp(cur_opt, "inband-tags"))  			options->inband_tags = 1; -		else if(!strcmp(cur_opt,"no-cache")) +		else if (!strcmp(cur_opt, "no-cache"))  			options->no_cache = 1; -		else if(!strcmp(cur_opt,"no-checkpoint-read")) +		else if (!strcmp(cur_opt, "no-checkpoint-read"))  			options->skip_checkpoint_read = 1; -		else if(!strcmp(cur_opt,"no-checkpoint-write")) +		else if (!strcmp(cur_opt, "no-checkpoint-write"))  			options->skip_checkpoint_write = 1; -		else if(!strcmp(cur_opt,"no-checkpoint")){ +		else if (!strcmp(cur_opt, "no-checkpoint")) {  			options->skip_checkpoint_read = 1;  			options->skip_checkpoint_write = 1;  		} else { -			printk(KERN_INFO "yaffs: Bad mount option \"%s\"\n",cur_opt); +			printk(KERN_INFO "yaffs: Bad mount option \"%s\"\n", +					cur_opt);  			error = 1;  		} -  	}  	return error;  }  static struct super_block *yaffs_internal_read_super(int yaffsVersion, -						     struct super_block *sb, -						     void *data, int silent) +						struct super_block *sb, +						void *data, int silent)  {  	int nBlocks;  	struct inode *inode = NULL; @@ -1602,6 +1844,7 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion,  	sb->s_magic = YAFFS_MAGIC;  	sb->s_op = &yaffs_super_ops; +	sb->s_flags |= MS_NOATIME;  	if (!sb)  		printk(KERN_INFO "yaffs: sb is NULL\n"); @@ -1614,14 +1857,14 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion,  		       sb->s_dev,  		       yaffs_devname(sb, devname_buf)); -	if(!data_str) +	if (!data_str)  		data_str = ""; -	printk(KERN_INFO "yaffs: passed flags \"%s\"\n",data_str); +	printk(KERN_INFO "yaffs: passed flags \"%s\"\n", data_str); -	memset(&options,0,sizeof(options)); +	memset(&options, 0, sizeof(options)); -	if(yaffs_parse_options(&options,data_str)){ +	if (yaffs_parse_options(&options, data_str)) {  		/* Option parsing failed */  		return NULL;  	} @@ -1645,9 +1888,9 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion,  			       yaffs_devname(sb, devname_buf)));  	/* Check it's an mtd device..... */ -	if (MAJOR(sb->s_dev) != MTD_BLOCK_MAJOR) { +	if (MAJOR(sb->s_dev) != MTD_BLOCK_MAJOR)  		return NULL;	/* This isn't an mtd device */ -	} +  	/* Get the device */  	mtd = get_mtd_device(NULL, MINOR(sb->s_dev));  	if (!mtd) { @@ -1673,29 +1916,23 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion,  	T(YAFFS_TRACE_OS, (" %s %d\n", WRITE_SIZE_STR, WRITE_SIZE(mtd)));  	T(YAFFS_TRACE_OS, (" oobsize %d\n", mtd->oobsize));  	T(YAFFS_TRACE_OS, (" erasesize %d\n", mtd->erasesize)); -	T(YAFFS_TRACE_OS, (" size %d\n", mtd->size)); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29) +	T(YAFFS_TRACE_OS, (" size %u\n", mtd->size)); +#else +	T(YAFFS_TRACE_OS, (" size %lld\n", mtd->size)); +#endif  #ifdef CONFIG_YAFFS_AUTO_YAFFS2 -	if (yaffsVersion == 1 && -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -	    mtd->writesize >= 2048) { -#else -	    mtd->oobblock >= 2048) { -#endif -	    T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs2\n")); -	    yaffsVersion = 2; +	if (yaffsVersion == 1 && WRITE_SIZE(mtd) >= 2048) { +		T(YAFFS_TRACE_ALWAYS, ("yaffs: auto selecting yaffs2\n")); +		yaffsVersion = 2;  	}  	/* Added NCB 26/5/2006 for completeness */ -	if (yaffsVersion == 2 && -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -	    mtd->writesize == 512) { -#else -	    mtd->oobblock == 512) { -#endif -	    T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs1\n")); -	    yaffsVersion = 1; +	if (yaffsVersion == 2 && !options.inband_tags && WRITE_SIZE(mtd) == 512) { +		T(YAFFS_TRACE_ALWAYS, ("yaffs: auto selecting yaffs1\n")); +		yaffsVersion = 1;  	}  #endif @@ -1707,7 +1944,7 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion,  		    !mtd->block_markbad ||  		    !mtd->read ||  		    !mtd->write || -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))  		    !mtd->read_oob || !mtd->write_oob) {  #else  		    !mtd->write_ecc || @@ -1719,12 +1956,9 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion,  			return NULL;  		} -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -		if (mtd->writesize < YAFFS_MIN_YAFFS2_CHUNK_SIZE || -#else -		if (mtd->oobblock < YAFFS_MIN_YAFFS2_CHUNK_SIZE || -#endif -		    mtd->oobsize < YAFFS_MIN_YAFFS2_SPARE_SIZE) { +		if ((WRITE_SIZE(mtd) < YAFFS_MIN_YAFFS2_CHUNK_SIZE || +		    mtd->oobsize < YAFFS_MIN_YAFFS2_SPARE_SIZE) && +		    !options.inband_tags) {  			T(YAFFS_TRACE_ALWAYS,  			  ("yaffs: MTD device does not have the "  			   "right page sizes\n")); @@ -1735,7 +1969,7 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion,  		if (!mtd->erase ||  		    !mtd->read ||  		    !mtd->write || -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))  		    !mtd->read_oob || !mtd->write_oob) {  #else  		    !mtd->write_ecc || @@ -1761,7 +1995,7 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion,  	 * Set the yaffs_Device up for mtd  	 */ -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))  	sb->s_fs_info = dev = kmalloc(sizeof(yaffs_Device), GFP_KERNEL);  #else  	sb->u.generic_sbp = dev = kmalloc(sizeof(yaffs_Device), GFP_KERNEL); @@ -1780,13 +2014,15 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion,  	/* Set up the memory size parameters.... */ -	nBlocks = mtd->size / (YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK); +	nBlocks = YCALCBLOCKS(mtd->size, (YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK)); +  	dev->startBlock = 0;  	dev->endBlock = nBlocks - 1;  	dev->nChunksPerBlock = YAFFS_CHUNKS_PER_BLOCK; -	dev->nDataBytesPerChunk = YAFFS_BYTES_PER_CHUNK; +	dev->totalBytesPerChunk = YAFFS_BYTES_PER_CHUNK;  	dev->nReservedBlocks = 5;  	dev->nShortOpCaches = (options.no_cache) ? 0 : 10; +	dev->inbandTags = options.inband_tags;  	/* ... and the functions. */  	if (yaffsVersion == 2) { @@ -1798,20 +2034,19 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion,  		dev->queryNANDBlock = nandmtd2_QueryNANDBlock;  		dev->spareBuffer = YMALLOC(mtd->oobsize);  		dev->isYaffs2 = 1; -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -		dev->nDataBytesPerChunk = mtd->writesize; +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) +		dev->totalBytesPerChunk = mtd->writesize;  		dev->nChunksPerBlock = mtd->erasesize / mtd->writesize;  #else -		dev->nDataBytesPerChunk = mtd->oobblock; +		dev->totalBytesPerChunk = mtd->oobblock;  		dev->nChunksPerBlock = mtd->erasesize / mtd->oobblock;  #endif -		nBlocks = mtd->size / mtd->erasesize; +		nBlocks = YCALCBLOCKS(mtd->size, mtd->erasesize); -		dev->nCheckpointReservedBlocks = CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS;  		dev->startBlock = 0;  		dev->endBlock = nBlocks - 1;  	} else { -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))  		/* use the MTD interface in yaffs_mtdif1.c */  		dev->writeChunkWithTagsToNAND =  			nandmtd1_WriteChunkWithTagsToNAND; @@ -1847,7 +2082,7 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion,  	dev->skipCheckpointWrite = options.skip_checkpoint_write;  	/* we assume this is protected by lock_kernel() in mount/umount */ -	list_add_tail(&dev->devList, &yaffs_dev_list); +	ylist_add_tail(&dev->devList, &yaffs_dev_list);  	init_MUTEX(&dev->grossLock); @@ -1884,20 +2119,23 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion,  		return NULL;  	}  	sb->s_root = root; +	sb->s_dirt = !dev->isCheckpointed; +	T(YAFFS_TRACE_ALWAYS, +	  ("yaffs_read_super: isCheckpointed %d\n", dev->isCheckpointed));  	T(YAFFS_TRACE_OS, ("yaffs_read_super: done\n"));  	return sb;  } -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))  static int yaffs_internal_read_super_mtd(struct super_block *sb, void *data,  					 int silent)  {  	return yaffs_internal_read_super(1, sb, data, silent) ? 0 : -EINVAL;  } -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))  static int yaffs_read_super(struct file_system_type *fs,  			    int flags, const char *dev_name,  			    void *data, struct vfsmount *mnt) @@ -1938,14 +2176,14 @@ static DECLARE_FSTYPE(yaffs_fs_type, "yaffs", yaffs_read_super,  #ifdef CONFIG_YAFFS_YAFFS2 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))  static int yaffs2_internal_read_super_mtd(struct super_block *sb, void *data,  					  int silent)  {  	return yaffs_internal_read_super(2, sb, data, silent) ? 0 : -EINVAL;  } -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))  static int yaffs2_read_super(struct file_system_type *fs,  			int flags, const char *dev_name, void *data,  			struct vfsmount *mnt) @@ -1990,12 +2228,12 @@ static char *yaffs_dump_dev(char *buf, yaffs_Device * dev)  {  	buf += sprintf(buf, "startBlock......... %d\n", dev->startBlock);  	buf += sprintf(buf, "endBlock........... %d\n", dev->endBlock); +	buf += sprintf(buf, "totalBytesPerChunk. %d\n", dev->totalBytesPerChunk);  	buf += sprintf(buf, "nDataBytesPerChunk. %d\n", dev->nDataBytesPerChunk);  	buf += sprintf(buf, "chunkGroupBits..... %d\n", dev->chunkGroupBits);  	buf += sprintf(buf, "chunkGroupSize..... %d\n", dev->chunkGroupSize);  	buf += sprintf(buf, "nErasedBlocks...... %d\n", dev->nErasedBlocks);  	buf += sprintf(buf, "nReservedBlocks.... %d\n", dev->nReservedBlocks); -	buf += sprintf(buf, "nCheckptResBlocks.. %d\n", dev->nCheckpointReservedBlocks);  	buf += sprintf(buf, "blocksInCheckpoint. %d\n", dev->blocksInCheckpoint);  	buf += sprintf(buf, "nTnodesCreated..... %d\n", dev->nTnodesCreated);  	buf += sprintf(buf, "nFreeTnodes........ %d\n", dev->nFreeTnodes); @@ -2006,10 +2244,8 @@ static char *yaffs_dump_dev(char *buf, yaffs_Device * dev)  	buf += sprintf(buf, "nPageReads......... %d\n", dev->nPageReads);  	buf += sprintf(buf, "nBlockErasures..... %d\n", dev->nBlockErasures);  	buf += sprintf(buf, "nGCCopies.......... %d\n", dev->nGCCopies); -	buf += -	    sprintf(buf, "garbageCollections. %d\n", dev->garbageCollections); -	buf += -	    sprintf(buf, "passiveGCs......... %d\n", +	buf += sprintf(buf, "garbageCollections. %d\n", dev->garbageCollections); +	buf += sprintf(buf, "passiveGCs......... %d\n",  		    dev->passiveGarbageCollections);  	buf += sprintf(buf, "nRetriedWrites..... %d\n", dev->nRetriedWrites);  	buf += sprintf(buf, "nShortOpCaches..... %d\n", dev->nShortOpCaches); @@ -2025,6 +2261,7 @@ static char *yaffs_dump_dev(char *buf, yaffs_Device * dev)  	    sprintf(buf, "nBackgroudDeletions %d\n", dev->nBackgroundDeletions);  	buf += sprintf(buf, "useNANDECC......... %d\n", dev->useNANDECC);  	buf += sprintf(buf, "isYaffs2........... %d\n", dev->isYaffs2); +	buf += sprintf(buf, "inbandTags......... %d\n", dev->inbandTags);  	return buf;  } @@ -2033,7 +2270,7 @@ static int yaffs_proc_read(char *page,  			   char **start,  			   off_t offset, int count, int *eof, void *data)  { -	struct list_head *item; +	struct ylist_head *item;  	char *buf = page;  	int step = offset;  	int n = 0; @@ -2057,8 +2294,8 @@ static int yaffs_proc_read(char *page,  	lock_kernel();  	/* Locate and print the Nth entry.  Order N-squared but N is small. */ -	list_for_each(item, &yaffs_dev_list) { -		yaffs_Device *dev = list_entry(item, yaffs_Device, devList); +	ylist_for_each(item, &yaffs_dev_list) { +		yaffs_Device *dev = ylist_entry(item, yaffs_Device, devList);  		if (n < step) {  			n++;  			continue; @@ -2119,7 +2356,7 @@ static int yaffs_proc_write(struct file *file, const char *buf,  	char *end;  	char *mask_name;  	const char *x; -	char substring[MAX_MASK_NAME_LENGTH+1]; +	char substring[MAX_MASK_NAME_LENGTH + 1];  	int i;  	int done = 0;  	int add, len = 0; @@ -2129,9 +2366,8 @@ static int yaffs_proc_write(struct file *file, const char *buf,  	while (!done && (pos < count)) {  		done = 1; -		while ((pos < count) && isspace(buf[pos])) { +		while ((pos < count) && isspace(buf[pos]))  			pos++; -		}  		switch (buf[pos]) {  		case '+': @@ -2148,20 +2384,21 @@ static int yaffs_proc_write(struct file *file, const char *buf,  		mask_name = NULL;  		mask_bitfield = simple_strtoul(buf + pos, &end, 0); +  		if (end > buf + pos) {  			mask_name = "numeral";  			len = end - (buf + pos);  			pos += len;  			done = 0;  		} else { -			for(x = buf + pos, i = 0; -			    (*x == '_' || (*x >='a' && *x <= 'z')) && -			    i <MAX_MASK_NAME_LENGTH; x++, i++, pos++) -			    substring[i] = *x; +			for (x = buf + pos, i = 0; +			    (*x == '_' || (*x >= 'a' && *x <= 'z')) && +			    i < MAX_MASK_NAME_LENGTH; x++, i++, pos++) +				substring[i] = *x;  			substring[i] = '\0';  			for (i = 0; mask_flags[i].mask_name != NULL; i++) { -				if(strcmp(substring,mask_flags[i].mask_name) == 0){ +				if (strcmp(substring, mask_flags[i].mask_name) == 0) {  					mask_name = mask_flags[i].mask_name;  					mask_bitfield = mask_flags[i].mask_bitfield;  					done = 0; @@ -2172,7 +2409,7 @@ static int yaffs_proc_write(struct file *file, const char *buf,  		if (mask_name != NULL) {  			done = 0; -			switch(add) { +			switch (add) {  			case '-':  				rg &= ~mask_bitfield;  				break; @@ -2191,13 +2428,13 @@ static int yaffs_proc_write(struct file *file, const char *buf,  	yaffs_traceMask = rg | YAFFS_TRACE_ALWAYS; -	printk("new trace = 0x%08X\n",yaffs_traceMask); +	printk(KERN_DEBUG "new trace = 0x%08X\n", yaffs_traceMask);  	if (rg & YAFFS_TRACE_ALWAYS) {  		for (i = 0; mask_flags[i].mask_name != NULL; i++) {  			char flag;  			flag = ((rg & mask_flags[i].mask_bitfield) == mask_flags[i].mask_bitfield) ? '+' : '-'; -			printk("%c%s\n", flag, mask_flags[i].mask_name); +			printk(KERN_DEBUG "%c%s\n", flag, mask_flags[i].mask_name);  		}  	} @@ -2211,12 +2448,8 @@ struct file_system_to_install {  };  static struct file_system_to_install fs_to_install[] = { -//#ifdef CONFIG_YAFFS_YAFFS1  	{&yaffs_fs_type, 0}, -//#endif -//#ifdef CONFIG_YAFFS_YAFFS2  	{&yaffs2_fs_type, 0}, -//#endif  	{NULL, 0}  }; @@ -2231,15 +2464,14 @@ static int __init init_yaffs_fs(void)  	/* Install the proc_fs entry */  	my_proc_entry = create_proc_entry("yaffs",  					       S_IRUGO | S_IFREG, -					       &proc_root); +					       YPROC_ROOT);  	if (my_proc_entry) {  		my_proc_entry->write_proc = yaffs_proc_write;  		my_proc_entry->read_proc = yaffs_proc_read;  		my_proc_entry->data = NULL; -	} else { +	} else  		return -ENOMEM; -	}  	/* Now add the file system entries */ @@ -2247,9 +2479,8 @@ static int __init init_yaffs_fs(void)  	while (fsinst->fst && !error) {  		error = register_filesystem(fsinst->fst); -		if (!error) { +		if (!error)  			fsinst->installed = 1; -		}  		fsinst++;  	} @@ -2277,7 +2508,7 @@ static void __exit exit_yaffs_fs(void)  	T(YAFFS_TRACE_ALWAYS, ("yaffs " __DATE__ " " __TIME__  			       " removing. \n")); -	remove_proc_entry("yaffs", &proc_root); +	remove_proc_entry("yaffs", YPROC_ROOT);  	fsinst = fs_to_install; @@ -2288,7 +2519,6 @@ static void __exit exit_yaffs_fs(void)  		}  		fsinst++;  	} -  }  module_init(init_yaffs_fs) diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_getblockinfo.h b/target/linux/generic/files/fs/yaffs2/yaffs_getblockinfo.h new file mode 100644 index 000000000..5b0a1ac24 --- /dev/null +++ b/target/linux/generic/files/fs/yaffs2/yaffs_getblockinfo.h @@ -0,0 +1,34 @@ +/* + * YAFFS: Yet another Flash File System . A NAND-flash specific file system. + * + * Copyright (C) 2002-2007 Aleph One Ltd. + *   for Toby Churchill Ltd and Brightstar Engineering + * + * Created by Charles Manning <charles@aleph1.co.uk> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 2.1 as + * published by the Free Software Foundation. + * + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL. + */ + +#ifndef __YAFFS_GETBLOCKINFO_H__ +#define __YAFFS_GETBLOCKINFO_H__ + +#include "yaffs_guts.h" + +/* Function to manipulate block info */ +static Y_INLINE yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device * dev, int blk) +{ +	if (blk < dev->internalStartBlock || blk > dev->internalEndBlock) { +		T(YAFFS_TRACE_ERROR, +		  (TSTR +		   ("**>> yaffs: getBlockInfo block %d is not valid" TENDSTR), +		   blk)); +		YBUG(); +	} +	return &dev->blockInfo[blk - dev->internalStartBlock]; +} + +#endif diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_guts.c b/target/linux/generic/files/fs/yaffs2/yaffs_guts.c index 2ab814691..d89b87af4 100644 --- a/target/linux/generic/files/fs/yaffs2/yaffs_guts.c +++ b/target/linux/generic/files/fs/yaffs2/yaffs_guts.c @@ -12,16 +12,17 @@   */  const char *yaffs_guts_c_version = -    "$Id: yaffs_guts.c,v 1.49 2007-05-15 20:07:40 charles Exp $"; +    "$Id: yaffs_guts.c,v 1.82 2009-03-09 04:24:17 charles Exp $";  #include "yportenv.h"  #include "yaffsinterface.h"  #include "yaffs_guts.h"  #include "yaffs_tagsvalidity.h" +#include "yaffs_getblockinfo.h"  #include "yaffs_tagscompat.h" -#ifndef  CONFIG_YAFFS_USE_OWN_SORT +#ifndef CONFIG_YAFFS_USE_OWN_SORT  #include "yaffs_qsort.h"  #endif  #include "yaffs_nand.h" @@ -32,116 +33,116 @@ const char *yaffs_guts_c_version =  #include "yaffs_packedtags2.h" -#ifdef CONFIG_YAFFS_WINCE -void yfsd_LockYAFFS(BOOL fsLockOnly); -void yfsd_UnlockYAFFS(BOOL fsLockOnly); -#endif -  #define YAFFS_PASSIVE_GC_CHUNKS 2  #include "yaffs_ecc.h"  /* Robustification (if it ever comes about...) */ -static void yaffs_RetireBlock(yaffs_Device * dev, int blockInNAND); -static void yaffs_HandleWriteChunkError(yaffs_Device * dev, int chunkInNAND, int erasedOk); -static void yaffs_HandleWriteChunkOk(yaffs_Device * dev, int chunkInNAND, -				     const __u8 * data, -				     const yaffs_ExtendedTags * tags); -static void yaffs_HandleUpdateChunk(yaffs_Device * dev, int chunkInNAND, -				    const yaffs_ExtendedTags * tags); +static void yaffs_RetireBlock(yaffs_Device *dev, int blockInNAND); +static void yaffs_HandleWriteChunkError(yaffs_Device *dev, int chunkInNAND, +		int erasedOk); +static void yaffs_HandleWriteChunkOk(yaffs_Device *dev, int chunkInNAND, +				const __u8 *data, +				const yaffs_ExtendedTags *tags); +static void yaffs_HandleUpdateChunk(yaffs_Device *dev, int chunkInNAND, +				const yaffs_ExtendedTags *tags);  /* Other local prototypes */ -static int yaffs_UnlinkObject( yaffs_Object *obj); +static int yaffs_UnlinkObject(yaffs_Object *obj);  static int yaffs_ObjectHasCachedWriteData(yaffs_Object *obj);  static void yaffs_HardlinkFixup(yaffs_Device *dev, yaffs_Object *hardList); -static int yaffs_WriteNewChunkWithTagsToNAND(yaffs_Device * dev, -					     const __u8 * buffer, -					     yaffs_ExtendedTags * tags, -					     int useReserve); -static int yaffs_PutChunkIntoFile(yaffs_Object * in, int chunkInInode, -				  int chunkInNAND, int inScan); - -static yaffs_Object *yaffs_CreateNewObject(yaffs_Device * dev, int number, -					   yaffs_ObjectType type); -static void yaffs_AddObjectToDirectory(yaffs_Object * directory, -				       yaffs_Object * obj); -static int yaffs_UpdateObjectHeader(yaffs_Object * in, const YCHAR * name, -				    int force, int isShrink, int shadows); -static void yaffs_RemoveObjectFromDirectory(yaffs_Object * obj); +static int yaffs_WriteNewChunkWithTagsToNAND(yaffs_Device *dev, +					const __u8 *buffer, +					yaffs_ExtendedTags *tags, +					int useReserve); +static int yaffs_PutChunkIntoFile(yaffs_Object *in, int chunkInInode, +				int chunkInNAND, int inScan); + +static yaffs_Object *yaffs_CreateNewObject(yaffs_Device *dev, int number, +					yaffs_ObjectType type); +static void yaffs_AddObjectToDirectory(yaffs_Object *directory, +				yaffs_Object *obj); +static int yaffs_UpdateObjectHeader(yaffs_Object *in, const YCHAR *name, +				int force, int isShrink, int shadows); +static void yaffs_RemoveObjectFromDirectory(yaffs_Object *obj);  static int yaffs_CheckStructures(void); -static int yaffs_DeleteWorker(yaffs_Object * in, yaffs_Tnode * tn, __u32 level, -			      int chunkOffset, int *limit); -static int yaffs_DoGenericObjectDeletion(yaffs_Object * in); +static int yaffs_DeleteWorker(yaffs_Object *in, yaffs_Tnode *tn, __u32 level, +			int chunkOffset, int *limit); +static int yaffs_DoGenericObjectDeletion(yaffs_Object *in); -static yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device * dev, int blockNo); +static yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device *dev, int blockNo); -static __u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo); -static void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer, -				    int lineNo);  static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev, -				  int chunkInNAND); - -static int yaffs_UnlinkWorker(yaffs_Object * obj); -static void yaffs_DestroyObject(yaffs_Object * obj); +				int chunkInNAND); -static int yaffs_TagsMatch(const yaffs_ExtendedTags * tags, int objectId, -			   int chunkInObject); +static int yaffs_UnlinkWorker(yaffs_Object *obj); -loff_t yaffs_GetFileSize(yaffs_Object * obj); +static int yaffs_TagsMatch(const yaffs_ExtendedTags *tags, int objectId, +			int chunkInObject); -static int yaffs_AllocateChunk(yaffs_Device * dev, int useReserve, yaffs_BlockInfo **blockUsedPtr); +static int yaffs_AllocateChunk(yaffs_Device *dev, int useReserve, +				yaffs_BlockInfo **blockUsedPtr); -static void yaffs_VerifyFreeChunks(yaffs_Device * dev); +static void yaffs_VerifyFreeChunks(yaffs_Device *dev);  static void yaffs_CheckObjectDetailsLoaded(yaffs_Object *in); +static void yaffs_VerifyDirectory(yaffs_Object *directory);  #ifdef YAFFS_PARANOID -static int yaffs_CheckFileSanity(yaffs_Object * in); +static int yaffs_CheckFileSanity(yaffs_Object *in);  #else  #define yaffs_CheckFileSanity(in)  #endif -static void yaffs_InvalidateWholeChunkCache(yaffs_Object * in); -static void yaffs_InvalidateChunkCache(yaffs_Object * object, int chunkId); +static void yaffs_InvalidateWholeChunkCache(yaffs_Object *in); +static void yaffs_InvalidateChunkCache(yaffs_Object *object, int chunkId);  static void yaffs_InvalidateCheckpoint(yaffs_Device *dev); -static int yaffs_FindChunkInFile(yaffs_Object * in, int chunkInInode, -				 yaffs_ExtendedTags * tags); +static int yaffs_FindChunkInFile(yaffs_Object *in, int chunkInInode, +				yaffs_ExtendedTags *tags); -static __u32 yaffs_GetChunkGroupBase(yaffs_Device *dev, yaffs_Tnode *tn, unsigned pos); -static yaffs_Tnode *yaffs_FindLevel0Tnode(yaffs_Device * dev, -					  yaffs_FileStructure * fStruct, -					  __u32 chunkId); +static __u32 yaffs_GetChunkGroupBase(yaffs_Device *dev, yaffs_Tnode *tn, +		unsigned pos); +static yaffs_Tnode *yaffs_FindLevel0Tnode(yaffs_Device *dev, +					yaffs_FileStructure *fStruct, +					__u32 chunkId);  /* Function to calculate chunk and offset */ -static void yaffs_AddrToChunk(yaffs_Device *dev, loff_t addr, __u32 *chunk, __u32 *offset) +static void yaffs_AddrToChunk(yaffs_Device *dev, loff_t addr, int *chunkOut, +		__u32 *offsetOut)  { -	if(dev->chunkShift){ -		/* Easy-peasy power of 2 case */ -		*chunk  = (__u32)(addr >> dev->chunkShift); -		*offset = (__u32)(addr & dev->chunkMask); -	} -	else if(dev->crumbsPerChunk) -	{ -		/* Case where we're using "crumbs" */ -		*offset = (__u32)(addr & dev->crumbMask); -		addr >>= dev->crumbShift; -		*chunk = ((__u32)addr)/dev->crumbsPerChunk; -		*offset += ((addr - (*chunk * dev->crumbsPerChunk)) << dev->crumbShift); +	int chunk; +	__u32 offset; + +	chunk  = (__u32)(addr >> dev->chunkShift); + +	if (dev->chunkDiv == 1) { +		/* easy power of 2 case */ +		offset = (__u32)(addr & dev->chunkMask); +	} else { +		/* Non power-of-2 case */ + +		loff_t chunkBase; + +		chunk /= dev->chunkDiv; + +		chunkBase = ((loff_t)chunk) * dev->nDataBytesPerChunk; +		offset = (__u32)(addr - chunkBase);  	} -	else -		YBUG(); + +	*chunkOut = chunk; +	*offsetOut = offset;  } -/* Function to return the number of shifts for a power of 2 greater than or equal - * to the given number +/* Function to return the number of shifts for a power of 2 greater than or + * equal to the given number   * Note we don't try to cater for all possible numbers and this does not have to   * be hellishly efficient.   */ @@ -153,13 +154,14 @@ static __u32 ShiftsGE(__u32 x)  	nShifts = extraBits = 0; -	while(x>1){ -		if(x & 1) extraBits++; -		x>>=1; +	while (x > 1) { +		if (x & 1) +			extraBits++; +		x >>= 1;  		nShifts++;  	} -	if(extraBits) +	if (extraBits)  		nShifts++;  	return nShifts; @@ -168,16 +170,17 @@ static __u32 ShiftsGE(__u32 x)  /* Function to return the number of shifts to get a 1 in bit 0   */ -static __u32 ShiftDiv(__u32 x) +static __u32 Shifts(__u32 x)  {  	int nShifts;  	nShifts =  0; -	if(!x) return 0; +	if (!x) +		return 0; -	while( !(x&1)){ -		x>>=1; +	while (!(x&1)) { +		x >>= 1;  		nShifts++;  	} @@ -195,21 +198,25 @@ static int yaffs_InitialiseTempBuffers(yaffs_Device *dev)  	int i;  	__u8 *buf = (__u8 *)1; -	memset(dev->tempBuffer,0,sizeof(dev->tempBuffer)); +	memset(dev->tempBuffer, 0, sizeof(dev->tempBuffer));  	for (i = 0; buf && i < YAFFS_N_TEMP_BUFFERS; i++) {  		dev->tempBuffer[i].line = 0;	/* not in use */  		dev->tempBuffer[i].buffer = buf = -		    YMALLOC_DMA(dev->nDataBytesPerChunk); +		    YMALLOC_DMA(dev->totalBytesPerChunk);  	}  	return buf ? YAFFS_OK : YAFFS_FAIL; -  } -static __u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo) +__u8 *yaffs_GetTempBuffer(yaffs_Device *dev, int lineNo)  {  	int i, j; + +	dev->tempInUse++; +	if (dev->tempInUse > dev->maxTemp) +		dev->maxTemp = dev->tempInUse; +  	for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {  		if (dev->tempBuffer[i].line == 0) {  			dev->tempBuffer[i].line = lineNo; @@ -227,9 +234,9 @@ static __u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo)  	T(YAFFS_TRACE_BUFFERS,  	  (TSTR("Out of temp buffers at line %d, other held by lines:"),  	   lineNo)); -	for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) { +	for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++)  		T(YAFFS_TRACE_BUFFERS, (TSTR(" %d "), dev->tempBuffer[i].line)); -	} +  	T(YAFFS_TRACE_BUFFERS, (TSTR(" " TENDSTR)));  	/* @@ -242,10 +249,13 @@ static __u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo)  } -static void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer, +void yaffs_ReleaseTempBuffer(yaffs_Device *dev, __u8 *buffer,  				    int lineNo)  {  	int i; + +	dev->tempInUse--; +  	for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {  		if (dev->tempBuffer[i].buffer == buffer) {  			dev->tempBuffer[i].line = 0; @@ -267,27 +277,26 @@ static void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer,  /*   * Determine if we have a managed buffer.   */ -int yaffs_IsManagedTempBuffer(yaffs_Device * dev, const __u8 * buffer) +int yaffs_IsManagedTempBuffer(yaffs_Device *dev, const __u8 *buffer)  {  	int i; +  	for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {  		if (dev->tempBuffer[i].buffer == buffer)  			return 1; -  	} -    for (i = 0; i < dev->nShortOpCaches; i++) { -        if( dev->srCache[i].data == buffer ) -            return 1; - -    } +	for (i = 0; i < dev->nShortOpCaches; i++) { +		if (dev->srCache[i].data == buffer) +			return 1; +	} -    if (buffer == dev->checkpointBuffer) -      return 1; +	if (buffer == dev->checkpointBuffer) +		return 1; -    T(YAFFS_TRACE_ALWAYS, -	  (TSTR("yaffs: unmaged buffer detected.\n" TENDSTR))); -    return 0; +	T(YAFFS_TRACE_ALWAYS, +		(TSTR("yaffs: unmaged buffer detected.\n" TENDSTR))); +	return 0;  } @@ -296,62 +305,63 @@ int yaffs_IsManagedTempBuffer(yaffs_Device * dev, const __u8 * buffer)   * Chunk bitmap manipulations   */ -static Y_INLINE __u8 *yaffs_BlockBits(yaffs_Device * dev, int blk) +static Y_INLINE __u8 *yaffs_BlockBits(yaffs_Device *dev, int blk)  {  	if (blk < dev->internalStartBlock || blk > dev->internalEndBlock) {  		T(YAFFS_TRACE_ERROR, -		  (TSTR("**>> yaffs: BlockBits block %d is not valid" TENDSTR), -		   blk)); +			(TSTR("**>> yaffs: BlockBits block %d is not valid" TENDSTR), +			blk));  		YBUG();  	}  	return dev->chunkBits + -	    (dev->chunkBitmapStride * (blk - dev->internalStartBlock)); +		(dev->chunkBitmapStride * (blk - dev->internalStartBlock));  }  static Y_INLINE void yaffs_VerifyChunkBitId(yaffs_Device *dev, int blk, int chunk)  { -	if(blk < dev->internalStartBlock || blk > dev->internalEndBlock || -	   chunk < 0 || chunk >= dev->nChunksPerBlock) { -	   T(YAFFS_TRACE_ERROR, -	    (TSTR("**>> yaffs: Chunk Id (%d:%d) invalid"TENDSTR),blk,chunk)); -	    YBUG(); +	if (blk < dev->internalStartBlock || blk > dev->internalEndBlock || +			chunk < 0 || chunk >= dev->nChunksPerBlock) { +		T(YAFFS_TRACE_ERROR, +		(TSTR("**>> yaffs: Chunk Id (%d:%d) invalid"TENDSTR), +			blk, chunk)); +		YBUG();  	}  } -static Y_INLINE void yaffs_ClearChunkBits(yaffs_Device * dev, int blk) +static Y_INLINE void yaffs_ClearChunkBits(yaffs_Device *dev, int blk)  {  	__u8 *blkBits = yaffs_BlockBits(dev, blk);  	memset(blkBits, 0, dev->chunkBitmapStride);  } -static Y_INLINE void yaffs_ClearChunkBit(yaffs_Device * dev, int blk, int chunk) +static Y_INLINE void yaffs_ClearChunkBit(yaffs_Device *dev, int blk, int chunk)  {  	__u8 *blkBits = yaffs_BlockBits(dev, blk); -	yaffs_VerifyChunkBitId(dev,blk,chunk); +	yaffs_VerifyChunkBitId(dev, blk, chunk);  	blkBits[chunk / 8] &= ~(1 << (chunk & 7));  } -static Y_INLINE void yaffs_SetChunkBit(yaffs_Device * dev, int blk, int chunk) +static Y_INLINE void yaffs_SetChunkBit(yaffs_Device *dev, int blk, int chunk)  {  	__u8 *blkBits = yaffs_BlockBits(dev, blk); -	yaffs_VerifyChunkBitId(dev,blk,chunk); +	yaffs_VerifyChunkBitId(dev, blk, chunk);  	blkBits[chunk / 8] |= (1 << (chunk & 7));  } -static Y_INLINE int yaffs_CheckChunkBit(yaffs_Device * dev, int blk, int chunk) +static Y_INLINE int yaffs_CheckChunkBit(yaffs_Device *dev, int blk, int chunk)  {  	__u8 *blkBits = yaffs_BlockBits(dev, blk); -	yaffs_VerifyChunkBitId(dev,blk,chunk); +	yaffs_VerifyChunkBitId(dev, blk, chunk);  	return (blkBits[chunk / 8] & (1 << (chunk & 7))) ? 1 : 0;  } -static Y_INLINE int yaffs_StillSomeChunkBits(yaffs_Device * dev, int blk) +static Y_INLINE int yaffs_StillSomeChunkBits(yaffs_Device *dev, int blk)  {  	__u8 *blkBits = yaffs_BlockBits(dev, blk);  	int i; @@ -363,17 +373,17 @@ static Y_INLINE int yaffs_StillSomeChunkBits(yaffs_Device * dev, int blk)  	return 0;  } -static int yaffs_CountChunkBits(yaffs_Device * dev, int blk) +static int yaffs_CountChunkBits(yaffs_Device *dev, int blk)  {  	__u8 *blkBits = yaffs_BlockBits(dev, blk);  	int i;  	int n = 0;  	for (i = 0; i < dev->chunkBitmapStride; i++) {  		__u8 x = *blkBits; -		while(x){ -			if(x & 1) +		while (x) { +			if (x & 1)  				n++; -			x >>=1; +			x >>= 1;  		}  		blkBits++; @@ -400,7 +410,7 @@ static int yaffs_SkipNANDVerification(yaffs_Device *dev)  	return !(yaffs_traceMask & (YAFFS_TRACE_VERIFY_NAND));  } -static const char * blockStateName[] = { +static const char *blockStateName[] = {  "Unknown",  "Needs scanning",  "Scanning", @@ -413,64 +423,65 @@ static const char * blockStateName[] = {  "Dead"  }; -static void yaffs_VerifyBlock(yaffs_Device *dev,yaffs_BlockInfo *bi,int n) +static void yaffs_VerifyBlock(yaffs_Device *dev, yaffs_BlockInfo *bi, int n)  {  	int actuallyUsed;  	int inUse; -	if(yaffs_SkipVerification(dev)) +	if (yaffs_SkipVerification(dev))  		return;  	/* Report illegal runtime states */ -	if(bi->blockState <0 || bi->blockState >= YAFFS_NUMBER_OF_BLOCK_STATES) -		T(YAFFS_TRACE_VERIFY,(TSTR("Block %d has undefined state %d"TENDSTR),n,bi->blockState)); +	if (bi->blockState >= YAFFS_NUMBER_OF_BLOCK_STATES) +		T(YAFFS_TRACE_VERIFY, (TSTR("Block %d has undefined state %d"TENDSTR), n, bi->blockState)); -	switch(bi->blockState){ -	 case YAFFS_BLOCK_STATE_UNKNOWN: -	 case YAFFS_BLOCK_STATE_SCANNING: -	 case YAFFS_BLOCK_STATE_NEEDS_SCANNING: -		T(YAFFS_TRACE_VERIFY,(TSTR("Block %d has bad run-state %s"TENDSTR), -		n,blockStateName[bi->blockState])); +	switch (bi->blockState) { +	case YAFFS_BLOCK_STATE_UNKNOWN: +	case YAFFS_BLOCK_STATE_SCANNING: +	case YAFFS_BLOCK_STATE_NEEDS_SCANNING: +		T(YAFFS_TRACE_VERIFY, (TSTR("Block %d has bad run-state %s"TENDSTR), +		n, blockStateName[bi->blockState]));  	}  	/* Check pages in use and soft deletions are legal */  	actuallyUsed = bi->pagesInUse - bi->softDeletions; -	if(bi->pagesInUse < 0 || bi->pagesInUse > dev->nChunksPerBlock || +	if (bi->pagesInUse < 0 || bi->pagesInUse > dev->nChunksPerBlock ||  	   bi->softDeletions < 0 || bi->softDeletions > dev->nChunksPerBlock ||  	   actuallyUsed < 0 || actuallyUsed > dev->nChunksPerBlock) -		T(YAFFS_TRACE_VERIFY,(TSTR("Block %d has illegal values pagesInUsed %d softDeletions %d"TENDSTR), -		n,bi->pagesInUse,bi->softDeletions)); +		T(YAFFS_TRACE_VERIFY, (TSTR("Block %d has illegal values pagesInUsed %d softDeletions %d"TENDSTR), +		n, bi->pagesInUse, bi->softDeletions));  	/* Check chunk bitmap legal */ -	inUse = yaffs_CountChunkBits(dev,n); -	if(inUse != bi->pagesInUse) -		T(YAFFS_TRACE_VERIFY,(TSTR("Block %d has inconsistent values pagesInUse %d counted chunk bits %d"TENDSTR), -			n,bi->pagesInUse,inUse)); +	inUse = yaffs_CountChunkBits(dev, n); +	if (inUse != bi->pagesInUse) +		T(YAFFS_TRACE_VERIFY, (TSTR("Block %d has inconsistent values pagesInUse %d counted chunk bits %d"TENDSTR), +			n, bi->pagesInUse, inUse));  	/* Check that the sequence number is valid.  	 * Ten million is legal, but is very unlikely  	 */ -	if(dev->isYaffs2 && +	if (dev->isYaffs2 &&  	   (bi->blockState == YAFFS_BLOCK_STATE_ALLOCATING || bi->blockState == YAFFS_BLOCK_STATE_FULL) && -	   (bi->sequenceNumber < YAFFS_LOWEST_SEQUENCE_NUMBER || bi->sequenceNumber > 10000000 )) -		T(YAFFS_TRACE_VERIFY,(TSTR("Block %d has suspect sequence number of %d"TENDSTR), -		n,bi->sequenceNumber)); - +	   (bi->sequenceNumber < YAFFS_LOWEST_SEQUENCE_NUMBER || bi->sequenceNumber > 10000000)) +		T(YAFFS_TRACE_VERIFY, (TSTR("Block %d has suspect sequence number of %d"TENDSTR), +		n, bi->sequenceNumber));  } -static void yaffs_VerifyCollectedBlock(yaffs_Device *dev,yaffs_BlockInfo *bi,int n) +static void yaffs_VerifyCollectedBlock(yaffs_Device *dev, yaffs_BlockInfo *bi, +		int n)  { -	yaffs_VerifyBlock(dev,bi,n); +	yaffs_VerifyBlock(dev, bi, n);  	/* After collection the block should be in the erased state */ -	/* TODO: This will need to change if we do partial gc */ +	/* This will need to change if we do partial gc */ -	if(bi->blockState != YAFFS_BLOCK_STATE_EMPTY){ -		T(YAFFS_TRACE_ERROR,(TSTR("Block %d is in state %d after gc, should be erased"TENDSTR), -			n,bi->blockState)); +	if (bi->blockState != YAFFS_BLOCK_STATE_COLLECTING && +			bi->blockState != YAFFS_BLOCK_STATE_EMPTY) { +		T(YAFFS_TRACE_ERROR, (TSTR("Block %d is in state %d after gc, should be erased"TENDSTR), +			n, bi->blockState));  	}  } @@ -480,52 +491,49 @@ static void yaffs_VerifyBlocks(yaffs_Device *dev)  	int nBlocksPerState[YAFFS_NUMBER_OF_BLOCK_STATES];  	int nIllegalBlockStates = 0; - -	if(yaffs_SkipVerification(dev)) +	if (yaffs_SkipVerification(dev))  		return; -	memset(nBlocksPerState,0,sizeof(nBlocksPerState)); - +	memset(nBlocksPerState, 0, sizeof(nBlocksPerState)); -	for(i = dev->internalStartBlock; i <= dev->internalEndBlock; i++){ -		yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,i); -		yaffs_VerifyBlock(dev,bi,i); +	for (i = dev->internalStartBlock; i <= dev->internalEndBlock; i++) { +		yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, i); +		yaffs_VerifyBlock(dev, bi, i); -		if(bi->blockState >=0 && bi->blockState < YAFFS_NUMBER_OF_BLOCK_STATES) +		if (bi->blockState < YAFFS_NUMBER_OF_BLOCK_STATES)  			nBlocksPerState[bi->blockState]++;  		else  			nIllegalBlockStates++; -  	} -	T(YAFFS_TRACE_VERIFY,(TSTR(""TENDSTR))); -	T(YAFFS_TRACE_VERIFY,(TSTR("Block summary"TENDSTR))); +	T(YAFFS_TRACE_VERIFY, (TSTR(""TENDSTR))); +	T(YAFFS_TRACE_VERIFY, (TSTR("Block summary"TENDSTR))); -	T(YAFFS_TRACE_VERIFY,(TSTR("%d blocks have illegal states"TENDSTR),nIllegalBlockStates)); -	if(nBlocksPerState[YAFFS_BLOCK_STATE_ALLOCATING] > 1) -		T(YAFFS_TRACE_VERIFY,(TSTR("Too many allocating blocks"TENDSTR))); +	T(YAFFS_TRACE_VERIFY, (TSTR("%d blocks have illegal states"TENDSTR), nIllegalBlockStates)); +	if (nBlocksPerState[YAFFS_BLOCK_STATE_ALLOCATING] > 1) +		T(YAFFS_TRACE_VERIFY, (TSTR("Too many allocating blocks"TENDSTR))); -	for(i = 0; i < YAFFS_NUMBER_OF_BLOCK_STATES; i++) +	for (i = 0; i < YAFFS_NUMBER_OF_BLOCK_STATES; i++)  		T(YAFFS_TRACE_VERIFY,  		  (TSTR("%s %d blocks"TENDSTR), -		  blockStateName[i],nBlocksPerState[i])); +		  blockStateName[i], nBlocksPerState[i])); -	if(dev->blocksInCheckpoint != nBlocksPerState[YAFFS_BLOCK_STATE_CHECKPOINT]) +	if (dev->blocksInCheckpoint != nBlocksPerState[YAFFS_BLOCK_STATE_CHECKPOINT])  		T(YAFFS_TRACE_VERIFY,  		 (TSTR("Checkpoint block count wrong dev %d count %d"TENDSTR),  		 dev->blocksInCheckpoint, nBlocksPerState[YAFFS_BLOCK_STATE_CHECKPOINT])); -	if(dev->nErasedBlocks != nBlocksPerState[YAFFS_BLOCK_STATE_EMPTY]) +	if (dev->nErasedBlocks != nBlocksPerState[YAFFS_BLOCK_STATE_EMPTY])  		T(YAFFS_TRACE_VERIFY,  		 (TSTR("Erased block count wrong dev %d count %d"TENDSTR),  		 dev->nErasedBlocks, nBlocksPerState[YAFFS_BLOCK_STATE_EMPTY])); -	if(nBlocksPerState[YAFFS_BLOCK_STATE_COLLECTING] > 1) +	if (nBlocksPerState[YAFFS_BLOCK_STATE_COLLECTING] > 1)  		T(YAFFS_TRACE_VERIFY,  		 (TSTR("Too many collecting blocks %d (max is 1)"TENDSTR),  		 nBlocksPerState[YAFFS_BLOCK_STATE_COLLECTING])); -	T(YAFFS_TRACE_VERIFY,(TSTR(""TENDSTR))); +	T(YAFFS_TRACE_VERIFY, (TSTR(""TENDSTR)));  } @@ -535,26 +543,26 @@ static void yaffs_VerifyBlocks(yaffs_Device *dev)   */  static void yaffs_VerifyObjectHeader(yaffs_Object *obj, yaffs_ObjectHeader *oh, yaffs_ExtendedTags *tags, int parentCheck)  { -	if(yaffs_SkipVerification(obj->myDev)) +	if (obj && yaffs_SkipVerification(obj->myDev))  		return; -	if(!(tags && obj && oh)){ -	 	T(YAFFS_TRACE_VERIFY, -		 		(TSTR("Verifying object header tags %x obj %x oh %x"TENDSTR), -		 		(__u32)tags,(__u32)obj,(__u32)oh)); +	if (!(tags && obj && oh)) { +		T(YAFFS_TRACE_VERIFY, +				(TSTR("Verifying object header tags %x obj %x oh %x"TENDSTR), +				(__u32)tags, (__u32)obj, (__u32)oh));  		return;  	} -	if(oh->type <= YAFFS_OBJECT_TYPE_UNKNOWN || -	   oh->type > YAFFS_OBJECT_TYPE_MAX) -	 	T(YAFFS_TRACE_VERIFY, -		 (TSTR("Obj %d header type is illegal value 0x%x"TENDSTR), -		 tags->objectId, oh->type)); +	if (oh->type <= YAFFS_OBJECT_TYPE_UNKNOWN || +			oh->type > YAFFS_OBJECT_TYPE_MAX) +		T(YAFFS_TRACE_VERIFY, +			(TSTR("Obj %d header type is illegal value 0x%x"TENDSTR), +			tags->objectId, oh->type)); -	if(tags->objectId != obj->objectId) -	 	T(YAFFS_TRACE_VERIFY, -		 (TSTR("Obj %d header mismatch objectId %d"TENDSTR), -		 tags->objectId, obj->objectId)); +	if (tags->objectId != obj->objectId) +		T(YAFFS_TRACE_VERIFY, +			(TSTR("Obj %d header mismatch objectId %d"TENDSTR), +			tags->objectId, obj->objectId));  	/* @@ -563,46 +571,43 @@ static void yaffs_VerifyObjectHeader(yaffs_Object *obj, yaffs_ObjectHeader *oh,  	 * Tests do not apply to the root object.  	 */ -	if(parentCheck && tags->objectId > 1 && !obj->parent) -	 	T(YAFFS_TRACE_VERIFY, -		 (TSTR("Obj %d header mismatch parentId %d obj->parent is NULL"TENDSTR), -	 	 tags->objectId, oh->parentObjectId)); - - -	if(parentCheck && obj->parent && -	   oh->parentObjectId != obj->parent->objectId && -	   (oh->parentObjectId != YAFFS_OBJECTID_UNLINKED || -	    obj->parent->objectId != YAFFS_OBJECTID_DELETED)) -	 	T(YAFFS_TRACE_VERIFY, -		 (TSTR("Obj %d header mismatch parentId %d parentObjectId %d"TENDSTR), -	 	 tags->objectId, oh->parentObjectId, obj->parent->objectId)); +	if (parentCheck && tags->objectId > 1 && !obj->parent) +		T(YAFFS_TRACE_VERIFY, +			(TSTR("Obj %d header mismatch parentId %d obj->parent is NULL"TENDSTR), +			tags->objectId, oh->parentObjectId)); +	if (parentCheck && obj->parent && +			oh->parentObjectId != obj->parent->objectId && +			(oh->parentObjectId != YAFFS_OBJECTID_UNLINKED || +			obj->parent->objectId != YAFFS_OBJECTID_DELETED)) +		T(YAFFS_TRACE_VERIFY, +			(TSTR("Obj %d header mismatch parentId %d parentObjectId %d"TENDSTR), +			tags->objectId, oh->parentObjectId, obj->parent->objectId)); -	if(tags->objectId > 1 && oh->name[0] == 0) /* Null name */ +	if (tags->objectId > 1 && oh->name[0] == 0) /* Null name */  		T(YAFFS_TRACE_VERIFY, -		(TSTR("Obj %d header name is NULL"TENDSTR), -		 obj->objectId)); +			(TSTR("Obj %d header name is NULL"TENDSTR), +			obj->objectId)); -	if(tags->objectId > 1 && ((__u8)(oh->name[0])) == 0xff) /* Trashed name */ +	if (tags->objectId > 1 && ((__u8)(oh->name[0])) == 0xff) /* Trashed name */  		T(YAFFS_TRACE_VERIFY, -		(TSTR("Obj %d header name is 0xFF"TENDSTR), -		 obj->objectId)); +			(TSTR("Obj %d header name is 0xFF"TENDSTR), +			obj->objectId));  } -static int yaffs_VerifyTnodeWorker(yaffs_Object * obj, yaffs_Tnode * tn, -				  	__u32 level, int chunkOffset) +static int yaffs_VerifyTnodeWorker(yaffs_Object *obj, yaffs_Tnode *tn, +					__u32 level, int chunkOffset)  {  	int i;  	yaffs_Device *dev = obj->myDev;  	int ok = 1; -	int nTnodeBytes = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;  	if (tn) {  		if (level > 0) { -			for (i = 0; i < YAFFS_NTNODES_INTERNAL && ok; i++){ +			for (i = 0; i < YAFFS_NTNODES_INTERNAL && ok; i++) {  				if (tn->internal[i]) {  					ok = yaffs_VerifyTnodeWorker(obj,  							tn->internal[i], @@ -611,20 +616,19 @@ static int yaffs_VerifyTnodeWorker(yaffs_Object * obj, yaffs_Tnode * tn,  				}  			}  		} else if (level == 0) { -			int i;  			yaffs_ExtendedTags tags;  			__u32 objectId = obj->objectId;  			chunkOffset <<=  YAFFS_TNODES_LEVEL0_BITS; -			for(i = 0; i < YAFFS_NTNODES_LEVEL0; i++){ -				__u32 theChunk = yaffs_GetChunkGroupBase(dev,tn,i); +			for (i = 0; i < YAFFS_NTNODES_LEVEL0; i++) { +				__u32 theChunk = yaffs_GetChunkGroupBase(dev, tn, i); -				if(theChunk > 0){ +				if (theChunk > 0) {  					/* T(~0,(TSTR("verifying (%d:%d) %d"TENDSTR),tags.objectId,tags.chunkId,theChunk)); */ -					yaffs_ReadChunkWithTagsFromNAND(dev,theChunk,NULL, &tags); -					if(tags.objectId != objectId || tags.chunkId != chunkOffset){ -						T(~0,(TSTR("Object %d chunkId %d NAND mismatch chunk %d tags (%d:%d)"TENDSTR), +					yaffs_ReadChunkWithTagsFromNAND(dev, theChunk, NULL, &tags); +					if (tags.objectId != objectId || tags.chunkId != chunkOffset) { +						T(~0, (TSTR("Object %d chunkId %d NAND mismatch chunk %d tags (%d:%d)"TENDSTR),  							objectId, chunkOffset, theChunk,  							tags.objectId, tags.chunkId));  					} @@ -646,13 +650,15 @@ static void yaffs_VerifyFile(yaffs_Object *obj)  	__u32 lastChunk;  	__u32 x;  	__u32 i; -	int ok;  	yaffs_Device *dev;  	yaffs_ExtendedTags tags;  	yaffs_Tnode *tn;  	__u32 objectId; -	if(obj && yaffs_SkipVerification(obj->myDev)) +	if (!obj) +		return; + +	if (yaffs_SkipVerification(obj->myDev))  		return;  	dev = obj->myDev; @@ -662,17 +668,17 @@ static void yaffs_VerifyFile(yaffs_Object *obj)  	lastChunk =  obj->variant.fileVariant.fileSize / dev->nDataBytesPerChunk + 1;  	x = lastChunk >> YAFFS_TNODES_LEVEL0_BITS;  	requiredTallness = 0; -	while (x> 0) { +	while (x > 0) {  		x >>= YAFFS_TNODES_INTERNAL_BITS;  		requiredTallness++;  	}  	actualTallness = obj->variant.fileVariant.topLevel; -	if(requiredTallness > actualTallness ) +	if (requiredTallness > actualTallness)  		T(YAFFS_TRACE_VERIFY,  		(TSTR("Obj %d had tnode tallness %d, needs to be %d"TENDSTR), -		 obj->objectId,actualTallness, requiredTallness)); +		 obj->objectId, actualTallness, requiredTallness));  	/* Check that the chunks in the tnode tree are all correct. @@ -680,39 +686,31 @@ static void yaffs_VerifyFile(yaffs_Object *obj)  	 * checking the tags for every chunk match.  	 */ -	if(yaffs_SkipNANDVerification(dev)) +	if (yaffs_SkipNANDVerification(dev))  		return; -	for(i = 1; i <= lastChunk; i++){ -		tn = yaffs_FindLevel0Tnode(dev, &obj->variant.fileVariant,i); +	for (i = 1; i <= lastChunk; i++) { +		tn = yaffs_FindLevel0Tnode(dev, &obj->variant.fileVariant, i);  		if (tn) { -			__u32 theChunk = yaffs_GetChunkGroupBase(dev,tn,i); -			if(theChunk > 0){ +			__u32 theChunk = yaffs_GetChunkGroupBase(dev, tn, i); +			if (theChunk > 0) {  				/* T(~0,(TSTR("verifying (%d:%d) %d"TENDSTR),objectId,i,theChunk)); */ -				yaffs_ReadChunkWithTagsFromNAND(dev,theChunk,NULL, &tags); -				if(tags.objectId != objectId || tags.chunkId != i){ -					T(~0,(TSTR("Object %d chunkId %d NAND mismatch chunk %d tags (%d:%d)"TENDSTR), +				yaffs_ReadChunkWithTagsFromNAND(dev, theChunk, NULL, &tags); +				if (tags.objectId != objectId || tags.chunkId != i) { +					T(~0, (TSTR("Object %d chunkId %d NAND mismatch chunk %d tags (%d:%d)"TENDSTR),  						objectId, i, theChunk,  						tags.objectId, tags.chunkId));  				}  			}  		} -  	} -  } -static void yaffs_VerifyDirectory(yaffs_Object *obj) -{ -	if(obj && yaffs_SkipVerification(obj->myDev)) -		return; - -}  static void yaffs_VerifyHardLink(yaffs_Object *obj)  { -	if(obj && yaffs_SkipVerification(obj->myDev)) +	if (obj && yaffs_SkipVerification(obj->myDev))  		return;  	/* Verify sane equivalent object */ @@ -720,7 +718,7 @@ static void yaffs_VerifyHardLink(yaffs_Object *obj)  static void yaffs_VerifySymlink(yaffs_Object *obj)  { -	if(obj && yaffs_SkipVerification(obj->myDev)) +	if (obj && yaffs_SkipVerification(obj->myDev))  		return;  	/* Verify symlink string */ @@ -728,7 +726,7 @@ static void yaffs_VerifySymlink(yaffs_Object *obj)  static void yaffs_VerifySpecial(yaffs_Object *obj)  { -	if(obj && yaffs_SkipVerification(obj->myDev)) +	if (obj && yaffs_SkipVerification(obj->myDev))  		return;  } @@ -740,14 +738,19 @@ static void yaffs_VerifyObject(yaffs_Object *obj)  	__u32 chunkMax;  	__u32 chunkIdOk; -	__u32 chunkIsLive; +	__u32 chunkInRange; +	__u32 chunkShouldNotBeDeleted; +	__u32 chunkValid; -	if(!obj) +	if (!obj) +		return; + +	if (obj->beingCreated)  		return;  	dev = obj->myDev; -	if(yaffs_SkipVerification(dev)) +	if (yaffs_SkipVerification(dev))  		return;  	/* Check sane object header chunk */ @@ -755,50 +758,54 @@ static void yaffs_VerifyObject(yaffs_Object *obj)  	chunkMin = dev->internalStartBlock * dev->nChunksPerBlock;  	chunkMax = (dev->internalEndBlock+1) * dev->nChunksPerBlock - 1; -	chunkIdOk = (obj->chunkId >= chunkMin && obj->chunkId <= chunkMax); -	chunkIsLive = chunkIdOk && +	chunkInRange = (((unsigned)(obj->hdrChunk)) >= chunkMin && ((unsigned)(obj->hdrChunk)) <= chunkMax); +	chunkIdOk = chunkInRange || obj->hdrChunk == 0; +	chunkValid = chunkInRange &&  			yaffs_CheckChunkBit(dev, -					    obj->chunkId / dev->nChunksPerBlock, -					    obj->chunkId % dev->nChunksPerBlock); -	if(!obj->fake && -	    (!chunkIdOk || !chunkIsLive)) { -	   T(YAFFS_TRACE_VERIFY, -	   (TSTR("Obj %d has chunkId %d %s %s"TENDSTR), -	   obj->objectId,obj->chunkId, -	   chunkIdOk ? "" : ",out of range", -	   chunkIsLive || !chunkIdOk ? "" : ",marked as deleted")); -	} - -	if(chunkIdOk && chunkIsLive &&!yaffs_SkipNANDVerification(dev)) { +					obj->hdrChunk / dev->nChunksPerBlock, +					obj->hdrChunk % dev->nChunksPerBlock); +	chunkShouldNotBeDeleted = chunkInRange && !chunkValid; + +	if (!obj->fake && +			(!chunkIdOk || chunkShouldNotBeDeleted)) { +		T(YAFFS_TRACE_VERIFY, +			(TSTR("Obj %d has chunkId %d %s %s"TENDSTR), +			obj->objectId, obj->hdrChunk, +			chunkIdOk ? "" : ",out of range", +			chunkShouldNotBeDeleted ? ",marked as deleted" : "")); +	} + +	if (chunkValid && !yaffs_SkipNANDVerification(dev)) {  		yaffs_ExtendedTags tags;  		yaffs_ObjectHeader *oh; -		__u8 *buffer = yaffs_GetTempBuffer(dev,__LINE__); +		__u8 *buffer = yaffs_GetTempBuffer(dev, __LINE__);  		oh = (yaffs_ObjectHeader *)buffer; -		yaffs_ReadChunkWithTagsFromNAND(dev, obj->chunkId,buffer, &tags); +		yaffs_ReadChunkWithTagsFromNAND(dev, obj->hdrChunk, buffer, +				&tags); -		yaffs_VerifyObjectHeader(obj,oh,&tags,1); +		yaffs_VerifyObjectHeader(obj, oh, &tags, 1); -		yaffs_ReleaseTempBuffer(dev,buffer,__LINE__); +		yaffs_ReleaseTempBuffer(dev, buffer, __LINE__);  	}  	/* Verify it has a parent */ -	if(obj && !obj->fake && -	   (!obj->parent || obj->parent->myDev != dev)){ -	   T(YAFFS_TRACE_VERIFY, -	   (TSTR("Obj %d has parent pointer %p which does not look like an object"TENDSTR), -	   obj->objectId,obj->parent)); +	if (obj && !obj->fake && +			(!obj->parent || obj->parent->myDev != dev)) { +		T(YAFFS_TRACE_VERIFY, +			(TSTR("Obj %d has parent pointer %p which does not look like an object"TENDSTR), +			obj->objectId, obj->parent));  	}  	/* Verify parent is a directory */ -	if(obj->parent && obj->parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY){ -	   T(YAFFS_TRACE_VERIFY, -	   (TSTR("Obj %d's parent is not a directory (type %d)"TENDSTR), -	   obj->objectId,obj->parent->variantType)); +	if (obj->parent && obj->parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) { +		T(YAFFS_TRACE_VERIFY, +			(TSTR("Obj %d's parent is not a directory (type %d)"TENDSTR), +			obj->objectId, obj->parent->variantType));  	} -	switch(obj->variantType){ +	switch (obj->variantType) {  	case YAFFS_OBJECT_TYPE_FILE:  		yaffs_VerifyFile(obj);  		break; @@ -818,33 +825,30 @@ static void yaffs_VerifyObject(yaffs_Object *obj)  	default:  		T(YAFFS_TRACE_VERIFY,  		(TSTR("Obj %d has illegaltype %d"TENDSTR), -		obj->objectId,obj->variantType)); +		obj->objectId, obj->variantType));  		break;  	} - -  }  static void yaffs_VerifyObjects(yaffs_Device *dev)  {  	yaffs_Object *obj;  	int i; -	struct list_head *lh; +	struct ylist_head *lh; -	if(yaffs_SkipVerification(dev)) +	if (yaffs_SkipVerification(dev))  		return;  	/* Iterate through the objects in each hash entry */ -	 for(i = 0; i <  YAFFS_NOBJECT_BUCKETS; i++){ -	 	list_for_each(lh, &dev->objectBucket[i].list) { +	for (i = 0; i <  YAFFS_NOBJECT_BUCKETS; i++) { +		ylist_for_each(lh, &dev->objectBucket[i].list) {  			if (lh) { -				obj = list_entry(lh, yaffs_Object, hashLink); +				obj = ylist_entry(lh, yaffs_Object, hashLink);  				yaffs_VerifyObject(obj);  			}  		} -	 } - +	}  } @@ -855,19 +859,20 @@ static void yaffs_VerifyObjects(yaffs_Device *dev)  static Y_INLINE int yaffs_HashFunction(int n)  {  	n = abs(n); -	return (n % YAFFS_NOBJECT_BUCKETS); +	return n % YAFFS_NOBJECT_BUCKETS;  }  /* - * Access functions to useful fake objects + * Access functions to useful fake objects. + * Note that root might have a presence in NAND if permissions are set.   */ -yaffs_Object *yaffs_Root(yaffs_Device * dev) +yaffs_Object *yaffs_Root(yaffs_Device *dev)  {  	return dev->rootDir;  } -yaffs_Object *yaffs_LostNFound(yaffs_Device * dev) +yaffs_Object *yaffs_LostNFound(yaffs_Device *dev)  {  	return dev->lostNFoundDir;  } @@ -877,7 +882,7 @@ yaffs_Object *yaffs_LostNFound(yaffs_Device * dev)   *  Erased NAND checking functions   */ -int yaffs_CheckFF(__u8 * buffer, int nBytes) +int yaffs_CheckFF(__u8 *buffer, int nBytes)  {  	/* Horrible, slow implementation */  	while (nBytes--) { @@ -889,9 +894,8 @@ int yaffs_CheckFF(__u8 * buffer, int nBytes)  }  static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev, -				  int chunkInNAND) +				int chunkInNAND)  { -  	int retval = YAFFS_OK;  	__u8 *data = yaffs_GetTempBuffer(dev, __LINE__);  	yaffs_ExtendedTags tags; @@ -899,10 +903,9 @@ static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,  	result = yaffs_ReadChunkWithTagsFromNAND(dev, chunkInNAND, data, &tags); -	if(tags.eccResult > YAFFS_ECC_RESULT_NO_ERROR) +	if (tags.eccResult > YAFFS_ECC_RESULT_NO_ERROR)  		retval = YAFFS_FAIL; -  	if (!yaffs_CheckFF(data, dev->nDataBytesPerChunk) || tags.chunkUsed) {  		T(YAFFS_TRACE_NANDACCESS,  		  (TSTR("Chunk %d not erased" TENDSTR), chunkInNAND)); @@ -915,11 +918,10 @@ static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,  } -  static int yaffs_WriteNewChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev, -					     const __u8 * data, -					     yaffs_ExtendedTags * tags, -					     int useReserve) +					const __u8 *data, +					yaffs_ExtendedTags *tags, +					int useReserve)  {  	int attempts = 0;  	int writeOk = 0; @@ -972,7 +974,7 @@ static int yaffs_WriteNewChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev,  			erasedOk = yaffs_CheckChunkErased(dev, chunk);  			if (erasedOk != YAFFS_OK) {  				T(YAFFS_TRACE_ERROR, -				(TSTR ("**>> yaffs chunk %d was not erased" +				(TSTR("**>> yaffs chunk %d was not erased"  				TENDSTR), chunk));  				/* try another chunk */ @@ -992,7 +994,11 @@ static int yaffs_WriteNewChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev,  		/* Copy the data into the robustification buffer */  		yaffs_HandleWriteChunkOk(dev, chunk, data, tags); -	} while (writeOk != YAFFS_OK && attempts < yaffs_wr_attempts); +	} while (writeOk != YAFFS_OK && +		(yaffs_wr_attempts <= 0 || attempts <= yaffs_wr_attempts)); + +	if (!writeOk) +		chunk = -1;  	if (attempts > 1) {  		T(YAFFS_TRACE_ERROR, @@ -1009,13 +1015,35 @@ static int yaffs_WriteNewChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev,   * Block retiring for handling a broken block.   */ -static void yaffs_RetireBlock(yaffs_Device * dev, int blockInNAND) +static void yaffs_RetireBlock(yaffs_Device *dev, int blockInNAND)  {  	yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, blockInNAND);  	yaffs_InvalidateCheckpoint(dev); -	yaffs_MarkBlockBad(dev, blockInNAND); +	if (yaffs_MarkBlockBad(dev, blockInNAND) != YAFFS_OK) { +		if (yaffs_EraseBlockInNAND(dev, blockInNAND) != YAFFS_OK) { +			T(YAFFS_TRACE_ALWAYS, (TSTR( +				"yaffs: Failed to mark bad and erase block %d" +				TENDSTR), blockInNAND)); +		} else { +			yaffs_ExtendedTags tags; +			int chunkId = blockInNAND * dev->nChunksPerBlock; + +			__u8 *buffer = yaffs_GetTempBuffer(dev, __LINE__); + +			memset(buffer, 0xff, dev->nDataBytesPerChunk); +			yaffs_InitialiseTags(&tags); +			tags.sequenceNumber = YAFFS_SEQUENCE_BAD_BLOCK; +			if (dev->writeChunkWithTagsToNAND(dev, chunkId - +				dev->chunkOffset, buffer, &tags) != YAFFS_OK) +				T(YAFFS_TRACE_ALWAYS, (TSTR("yaffs: Failed to " +					TCONT("write bad block marker to block %d") +					TENDSTR), blockInNAND)); + +			yaffs_ReleaseTempBuffer(dev, buffer, __LINE__); +		} +	}  	bi->blockState = YAFFS_BLOCK_STATE_DEAD;  	bi->gcPrioritise = 0; @@ -1029,49 +1057,45 @@ static void yaffs_RetireBlock(yaffs_Device * dev, int blockInNAND)   *   */ -static void yaffs_HandleWriteChunkOk(yaffs_Device * dev, int chunkInNAND, -				     const __u8 * data, -				     const yaffs_ExtendedTags * tags) +static void yaffs_HandleWriteChunkOk(yaffs_Device *dev, int chunkInNAND, +				const __u8 *data, +				const yaffs_ExtendedTags *tags)  {  } -static void yaffs_HandleUpdateChunk(yaffs_Device * dev, int chunkInNAND, -				    const yaffs_ExtendedTags * tags) +static void yaffs_HandleUpdateChunk(yaffs_Device *dev, int chunkInNAND, +				const yaffs_ExtendedTags *tags)  {  }  void yaffs_HandleChunkError(yaffs_Device *dev, yaffs_BlockInfo *bi)  { -	if(!bi->gcPrioritise){ +	if (!bi->gcPrioritise) {  		bi->gcPrioritise = 1;  		dev->hasPendingPrioritisedGCs = 1; -		bi->chunkErrorStrikes ++; +		bi->chunkErrorStrikes++; -		if(bi->chunkErrorStrikes > 3){ +		if (bi->chunkErrorStrikes > 3) {  			bi->needsRetiring = 1; /* Too many stikes, so retire this */  			T(YAFFS_TRACE_ALWAYS, (TSTR("yaffs: Block struck out" TENDSTR)));  		} -  	}  } -static void yaffs_HandleWriteChunkError(yaffs_Device * dev, int chunkInNAND, int erasedOk) +static void yaffs_HandleWriteChunkError(yaffs_Device *dev, int chunkInNAND, +		int erasedOk)  { -  	int blockInNAND = chunkInNAND / dev->nChunksPerBlock;  	yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, blockInNAND); -	yaffs_HandleChunkError(dev,bi); - +	yaffs_HandleChunkError(dev, bi); -	if(erasedOk ) { +	if (erasedOk) {  		/* Was an actual write failure, so mark the block for retirement  */  		bi->needsRetiring = 1;  		T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,  		  (TSTR("**>> Block %d needs retiring" TENDSTR), blockInNAND)); - -  	}  	/* Delete the chunk */ @@ -1081,12 +1105,12 @@ static void yaffs_HandleWriteChunkError(yaffs_Device * dev, int chunkInNAND, int  /*---------------- Name handling functions ------------*/ -static __u16 yaffs_CalcNameSum(const YCHAR * name) +static __u16 yaffs_CalcNameSum(const YCHAR *name)  {  	__u16 sum = 0;  	__u16 i = 1; -	YUCHAR *bname = (YUCHAR *) name; +	const YUCHAR *bname = (const YUCHAR *) name;  	if (bname) {  		while ((*bname) && (i < (YAFFS_MAX_NAME_LENGTH/2))) { @@ -1102,14 +1126,14 @@ static __u16 yaffs_CalcNameSum(const YCHAR * name)  	return sum;  } -static void yaffs_SetObjectName(yaffs_Object * obj, const YCHAR * name) +static void yaffs_SetObjectName(yaffs_Object *obj, const YCHAR *name)  {  #ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM -	if (name && yaffs_strlen(name) <= YAFFS_SHORT_NAME_LENGTH) { +	memset(obj->shortName, 0, sizeof(YCHAR) * (YAFFS_SHORT_NAME_LENGTH+1)); +	if (name && yaffs_strlen(name) <= YAFFS_SHORT_NAME_LENGTH)  		yaffs_strcpy(obj->shortName, name); -	} else { +	else  		obj->shortName[0] = _Y('\0'); -	}  #endif  	obj->sum = yaffs_CalcNameSum(name);  } @@ -1126,7 +1150,7 @@ static void yaffs_SetObjectName(yaffs_Object * obj, const YCHAR * name)   * Don't use this function directly   */ -static int yaffs_CreateTnodes(yaffs_Device * dev, int nTnodes) +static int yaffs_CreateTnodes(yaffs_Device *dev, int nTnodes)  {  	int i;  	int tnodeSize; @@ -1143,6 +1167,9 @@ static int yaffs_CreateTnodes(yaffs_Device * dev, int nTnodes)  	 * Must be a multiple of 32-bits  */  	tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8; +	if (tnodeSize < sizeof(yaffs_Tnode)) +		tnodeSize = sizeof(yaffs_Tnode); +  	/* make these things */  	newTnodes = YMALLOC(nTnodes * tnodeSize); @@ -1150,7 +1177,7 @@ static int yaffs_CreateTnodes(yaffs_Device * dev, int nTnodes)  	if (!newTnodes) {  		T(YAFFS_TRACE_ERROR, -		  (TSTR("yaffs: Could not allocate Tnodes" TENDSTR))); +			(TSTR("yaffs: Could not allocate Tnodes" TENDSTR)));  		return YAFFS_FAIL;  	} @@ -1170,7 +1197,7 @@ static int yaffs_CreateTnodes(yaffs_Device * dev, int nTnodes)  	dev->freeTnodes = newTnodes;  #else  	/* New hookup for wide tnodes */ -	for(i = 0; i < nTnodes -1; i++) { +	for (i = 0; i < nTnodes - 1; i++) {  		curr = (yaffs_Tnode *) &mem[i * tnodeSize];  		next = (yaffs_Tnode *) &mem[(i+1) * tnodeSize];  		curr->internal[0] = next; @@ -1197,7 +1224,6 @@ static int yaffs_CreateTnodes(yaffs_Device * dev, int nTnodes)  		  (TSTR  		   ("yaffs: Could not add tnodes to management list" TENDSTR)));  		   return YAFFS_FAIL; -  	} else {  		tnl->tnodes = newTnodes;  		tnl->next = dev->allocatedTnodeList; @@ -1211,14 +1237,13 @@ static int yaffs_CreateTnodes(yaffs_Device * dev, int nTnodes)  /* GetTnode gets us a clean tnode. Tries to make allocate more if we run out */ -static yaffs_Tnode *yaffs_GetTnodeRaw(yaffs_Device * dev) +static yaffs_Tnode *yaffs_GetTnodeRaw(yaffs_Device *dev)  {  	yaffs_Tnode *tn = NULL;  	/* If there are none left make more */ -	if (!dev->freeTnodes) { +	if (!dev->freeTnodes)  		yaffs_CreateTnodes(dev, YAFFS_ALLOCATION_NTNODES); -	}  	if (dev->freeTnodes) {  		tn = dev->freeTnodes; @@ -1233,21 +1258,27 @@ static yaffs_Tnode *yaffs_GetTnodeRaw(yaffs_Device * dev)  		dev->nFreeTnodes--;  	} +	dev->nCheckpointBlocksRequired = 0; /* force recalculation*/ +  	return tn;  } -static yaffs_Tnode *yaffs_GetTnode(yaffs_Device * dev) +static yaffs_Tnode *yaffs_GetTnode(yaffs_Device *dev)  {  	yaffs_Tnode *tn = yaffs_GetTnodeRaw(dev); +	int tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8; -	if(tn) -		memset(tn, 0, (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8); +	if (tnodeSize < sizeof(yaffs_Tnode)) +		tnodeSize = sizeof(yaffs_Tnode); + +	if (tn) +		memset(tn, 0, tnodeSize);  	return tn;  }  /* FreeTnode frees up a tnode and puts it back on the free list */ -static void yaffs_FreeTnode(yaffs_Device * dev, yaffs_Tnode * tn) +static void yaffs_FreeTnode(yaffs_Device *dev, yaffs_Tnode *tn)  {  	if (tn) {  #ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG @@ -1262,9 +1293,10 @@ static void yaffs_FreeTnode(yaffs_Device * dev, yaffs_Tnode * tn)  		dev->freeTnodes = tn;  		dev->nFreeTnodes++;  	} +	dev->nCheckpointBlocksRequired = 0; /* force recalculation*/  } -static void yaffs_DeinitialiseTnodes(yaffs_Device * dev) +static void yaffs_DeinitialiseTnodes(yaffs_Device *dev)  {  	/* Free the list of allocated tnodes */  	yaffs_TnodeList *tmp; @@ -1282,71 +1314,72 @@ static void yaffs_DeinitialiseTnodes(yaffs_Device * dev)  	dev->nFreeTnodes = 0;  } -static void yaffs_InitialiseTnodes(yaffs_Device * dev) +static void yaffs_InitialiseTnodes(yaffs_Device *dev)  {  	dev->allocatedTnodeList = NULL;  	dev->freeTnodes = NULL;  	dev->nFreeTnodes = 0;  	dev->nTnodesCreated = 0; -  } -void yaffs_PutLevel0Tnode(yaffs_Device *dev, yaffs_Tnode *tn, unsigned pos, unsigned val) +void yaffs_PutLevel0Tnode(yaffs_Device *dev, yaffs_Tnode *tn, unsigned pos, +		unsigned val)  { -  __u32 *map = (__u32 *)tn; -  __u32 bitInMap; -  __u32 bitInWord; -  __u32 wordInMap; -  __u32 mask; +	__u32 *map = (__u32 *)tn; +	__u32 bitInMap; +	__u32 bitInWord; +	__u32 wordInMap; +	__u32 mask; -  pos &= YAFFS_TNODES_LEVEL0_MASK; -  val >>= dev->chunkGroupBits; +	pos &= YAFFS_TNODES_LEVEL0_MASK; +	val >>= dev->chunkGroupBits; -  bitInMap = pos * dev->tnodeWidth; -  wordInMap = bitInMap /32; -  bitInWord = bitInMap & (32 -1); +	bitInMap = pos * dev->tnodeWidth; +	wordInMap = bitInMap / 32; +	bitInWord = bitInMap & (32 - 1); -  mask = dev->tnodeMask << bitInWord; +	mask = dev->tnodeMask << bitInWord; -  map[wordInMap] &= ~mask; -  map[wordInMap] |= (mask & (val << bitInWord)); +	map[wordInMap] &= ~mask; +	map[wordInMap] |= (mask & (val << bitInWord)); -  if(dev->tnodeWidth > (32-bitInWord)) { -    bitInWord = (32 - bitInWord); -    wordInMap++;; -    mask = dev->tnodeMask >> (/*dev->tnodeWidth -*/ bitInWord); -    map[wordInMap] &= ~mask; -    map[wordInMap] |= (mask & (val >> bitInWord)); -  } +	if (dev->tnodeWidth > (32 - bitInWord)) { +		bitInWord = (32 - bitInWord); +		wordInMap++;; +		mask = dev->tnodeMask >> (/*dev->tnodeWidth -*/ bitInWord); +		map[wordInMap] &= ~mask; +		map[wordInMap] |= (mask & (val >> bitInWord)); +	}  } -static __u32 yaffs_GetChunkGroupBase(yaffs_Device *dev, yaffs_Tnode *tn, unsigned pos) +static __u32 yaffs_GetChunkGroupBase(yaffs_Device *dev, yaffs_Tnode *tn, +		unsigned pos)  { -  __u32 *map = (__u32 *)tn; -  __u32 bitInMap; -  __u32 bitInWord; -  __u32 wordInMap; -  __u32 val; +	__u32 *map = (__u32 *)tn; +	__u32 bitInMap; +	__u32 bitInWord; +	__u32 wordInMap; +	__u32 val; -  pos &= YAFFS_TNODES_LEVEL0_MASK; +	pos &= YAFFS_TNODES_LEVEL0_MASK; -  bitInMap = pos * dev->tnodeWidth; -  wordInMap = bitInMap /32; -  bitInWord = bitInMap & (32 -1); +	bitInMap = pos * dev->tnodeWidth; +	wordInMap = bitInMap / 32; +	bitInWord = bitInMap & (32 - 1); -  val = map[wordInMap] >> bitInWord; +	val = map[wordInMap] >> bitInWord; -  if(dev->tnodeWidth > (32-bitInWord)) { -    bitInWord = (32 - bitInWord); -    wordInMap++;; -    val |= (map[wordInMap] << bitInWord); -  } +	if	(dev->tnodeWidth > (32 - bitInWord)) { +		bitInWord = (32 - bitInWord); +		wordInMap++;; +		val |= (map[wordInMap] << bitInWord); +	} -  val &= dev->tnodeMask; -  val <<= dev->chunkGroupBits; +	val &= dev->tnodeMask; +	val <<= dev->chunkGroupBits; -  return val; +	return val;  }  /* ------------------- End of individual tnode manipulation -----------------*/ @@ -1357,24 +1390,21 @@ static __u32 yaffs_GetChunkGroupBase(yaffs_Device *dev, yaffs_Tnode *tn, unsigne   */  /* FindLevel0Tnode finds the level 0 tnode, if one exists. */ -static yaffs_Tnode *yaffs_FindLevel0Tnode(yaffs_Device * dev, -					  yaffs_FileStructure * fStruct, -					  __u32 chunkId) +static yaffs_Tnode *yaffs_FindLevel0Tnode(yaffs_Device *dev, +					yaffs_FileStructure *fStruct, +					__u32 chunkId)  { -  	yaffs_Tnode *tn = fStruct->top;  	__u32 i;  	int requiredTallness;  	int level = fStruct->topLevel;  	/* Check sane level and chunk Id */ -	if (level < 0 || level > YAFFS_TNODES_MAX_LEVEL) { +	if (level < 0 || level > YAFFS_TNODES_MAX_LEVEL)  		return NULL; -	} -	if (chunkId > YAFFS_MAX_CHUNK_ID) { +	if (chunkId > YAFFS_MAX_CHUNK_ID)  		return NULL; -	}  	/* First check we're tall enough (ie enough topLevel) */ @@ -1385,22 +1415,17 @@ static yaffs_Tnode *yaffs_FindLevel0Tnode(yaffs_Device * dev,  		requiredTallness++;  	} -	if (requiredTallness > fStruct->topLevel) { -		/* Not tall enough, so we can't find it, return NULL. */ -		return NULL; -	} +	if (requiredTallness > fStruct->topLevel) +		return NULL; /* Not tall enough, so we can't find it */  	/* Traverse down to level 0 */  	while (level > 0 && tn) { -		tn = tn-> -		    internal[(chunkId >> -			       ( YAFFS_TNODES_LEVEL0_BITS + -			         (level - 1) * -			         YAFFS_TNODES_INTERNAL_BITS) -			      ) & -			     YAFFS_TNODES_INTERNAL_MASK]; +		tn = tn->internal[(chunkId >> +			(YAFFS_TNODES_LEVEL0_BITS + +				(level - 1) * +				YAFFS_TNODES_INTERNAL_BITS)) & +			YAFFS_TNODES_INTERNAL_MASK];  		level--; -  	}  	return tn; @@ -1417,12 +1442,11 @@ static yaffs_Tnode *yaffs_FindLevel0Tnode(yaffs_Device * dev,   *  be plugged into the ttree.   */ -static yaffs_Tnode *yaffs_AddOrFindLevel0Tnode(yaffs_Device * dev, -					       yaffs_FileStructure * fStruct, -					       __u32 chunkId, -					       yaffs_Tnode *passedTn) +static yaffs_Tnode *yaffs_AddOrFindLevel0Tnode(yaffs_Device *dev, +					yaffs_FileStructure *fStruct, +					__u32 chunkId, +					yaffs_Tnode *passedTn)  { -  	int requiredTallness;  	int i;  	int l; @@ -1432,13 +1456,11 @@ static yaffs_Tnode *yaffs_AddOrFindLevel0Tnode(yaffs_Device * dev,  	/* Check sane level and page Id */ -	if (fStruct->topLevel < 0 || fStruct->topLevel > YAFFS_TNODES_MAX_LEVEL) { +	if (fStruct->topLevel < 0 || fStruct->topLevel > YAFFS_TNODES_MAX_LEVEL)  		return NULL; -	} -	if (chunkId > YAFFS_MAX_CHUNK_ID) { +	if (chunkId > YAFFS_MAX_CHUNK_ID)  		return NULL; -	}  	/* First check we're tall enough (ie enough topLevel) */ @@ -1451,7 +1473,7 @@ static yaffs_Tnode *yaffs_AddOrFindLevel0Tnode(yaffs_Device * dev,  	if (requiredTallness > fStruct->topLevel) { -		/* Not tall enough,gotta make the tree taller */ +		/* Not tall enough, gotta make the tree taller */  		for (i = fStruct->topLevel; i < requiredTallness; i++) {  			tn = yaffs_GetTnode(dev); @@ -1473,27 +1495,27 @@ static yaffs_Tnode *yaffs_AddOrFindLevel0Tnode(yaffs_Device * dev,  	l = fStruct->topLevel;  	tn = fStruct->top; -	if(l > 0) { +	if (l > 0) {  		while (l > 0 && tn) {  			x = (chunkId >> -			     ( YAFFS_TNODES_LEVEL0_BITS + +			     (YAFFS_TNODES_LEVEL0_BITS +  			      (l - 1) * YAFFS_TNODES_INTERNAL_BITS)) &  			    YAFFS_TNODES_INTERNAL_MASK; -			if((l>1) && !tn->internal[x]){ +			if ((l > 1) && !tn->internal[x]) {  				/* Add missing non-level-zero tnode */  				tn->internal[x] = yaffs_GetTnode(dev); -			} else if(l == 1) { +			} else if (l == 1) {  				/* Looking from level 1 at level 0 */ -			 	if (passedTn) { +				if (passedTn) {  					/* If we already have one, then release it.*/ -					if(tn->internal[x]) -						yaffs_FreeTnode(dev,tn->internal[x]); +					if (tn->internal[x]) +						yaffs_FreeTnode(dev, tn->internal[x]);  					tn->internal[x] = passedTn; -				} else if(!tn->internal[x]) { +				} else if (!tn->internal[x]) {  					/* Don't have one, none passed in */  					tn->internal[x] = yaffs_GetTnode(dev);  				} @@ -1504,31 +1526,29 @@ static yaffs_Tnode *yaffs_AddOrFindLevel0Tnode(yaffs_Device * dev,  		}  	} else {  		/* top is level 0 */ -		if(passedTn) { -			memcpy(tn,passedTn,(dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8); -			yaffs_FreeTnode(dev,passedTn); +		if (passedTn) { +			memcpy(tn, passedTn, (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8); +			yaffs_FreeTnode(dev, passedTn);  		}  	}  	return tn;  } -static int yaffs_FindChunkInGroup(yaffs_Device * dev, int theChunk, -				  yaffs_ExtendedTags * tags, int objectId, -				  int chunkInInode) +static int yaffs_FindChunkInGroup(yaffs_Device *dev, int theChunk, +				yaffs_ExtendedTags *tags, int objectId, +				int chunkInInode)  {  	int j;  	for (j = 0; theChunk && j < dev->chunkGroupSize; j++) { -		if (yaffs_CheckChunkBit -		    (dev, theChunk / dev->nChunksPerBlock, -		     theChunk % dev->nChunksPerBlock)) { +		if (yaffs_CheckChunkBit(dev, theChunk / dev->nChunksPerBlock, +				theChunk % dev->nChunksPerBlock)) {  			yaffs_ReadChunkWithTagsFromNAND(dev, theChunk, NULL,  							tags);  			if (yaffs_TagsMatch(tags, objectId, chunkInInode)) {  				/* found it; */  				return theChunk; -  			}  		}  		theChunk++; @@ -1543,7 +1563,7 @@ static int yaffs_FindChunkInGroup(yaffs_Device * dev, int theChunk,   * Returns 0 if it stopped early due to hitting the limit and the delete is incomplete.   */ -static int yaffs_DeleteWorker(yaffs_Object * in, yaffs_Tnode * tn, __u32 level, +static int yaffs_DeleteWorker(yaffs_Object *in, yaffs_Tnode *tn, __u32 level,  			      int chunkOffset, int *limit)  {  	int i; @@ -1557,7 +1577,6 @@ static int yaffs_DeleteWorker(yaffs_Object * in, yaffs_Tnode * tn, __u32 level,  	if (tn) {  		if (level > 0) { -  			for (i = YAFFS_NTNODES_INTERNAL - 1; allDone && i >= 0;  			     i--) {  				if (tn->internal[i]) { @@ -1565,17 +1584,17 @@ static int yaffs_DeleteWorker(yaffs_Object * in, yaffs_Tnode * tn, __u32 level,  						allDone = 0;  					} else {  						allDone = -						    yaffs_DeleteWorker(in, -								       tn-> -								       internal -								       [i], -								       level - -								       1, -								       (chunkOffset +							yaffs_DeleteWorker(in, +								tn-> +								internal +								[i], +								level - +								1, +								(chunkOffset  									<<  									YAFFS_TNODES_INTERNAL_BITS) -								       + i, -								       limit); +								+ i, +								limit);  					}  					if (allDone) {  						yaffs_FreeTnode(dev, @@ -1584,27 +1603,25 @@ static int yaffs_DeleteWorker(yaffs_Object * in, yaffs_Tnode * tn, __u32 level,  						tn->internal[i] = NULL;  					}  				} -  			}  			return (allDone) ? 1 : 0;  		} else if (level == 0) {  			int hitLimit = 0;  			for (i = YAFFS_NTNODES_LEVEL0 - 1; i >= 0 && !hitLimit; -			     i--) { -			        theChunk = yaffs_GetChunkGroupBase(dev,tn,i); +					i--) { +				theChunk = yaffs_GetChunkGroupBase(dev, tn, i);  				if (theChunk) { -					chunkInInode = -					    (chunkOffset << -					     YAFFS_TNODES_LEVEL0_BITS) + i; +					chunkInInode = (chunkOffset << +						YAFFS_TNODES_LEVEL0_BITS) + i;  					foundChunk = -					    yaffs_FindChunkInGroup(dev, -								   theChunk, -								   &tags, -								   in->objectId, -								   chunkInInode); +						yaffs_FindChunkInGroup(dev, +								theChunk, +								&tags, +								in->objectId, +								chunkInInode);  					if (foundChunk > 0) {  						yaffs_DeleteChunk(dev, @@ -1613,14 +1630,13 @@ static int yaffs_DeleteWorker(yaffs_Object * in, yaffs_Tnode * tn, __u32 level,  						in->nDataChunks--;  						if (limit) {  							*limit = *limit - 1; -							if (*limit <= 0) { +							if (*limit <= 0)  								hitLimit = 1; -							}  						}  					} -					yaffs_PutLevel0Tnode(dev,tn,i,0); +					yaffs_PutLevel0Tnode(dev, tn, i, 0);  				}  			} @@ -1634,9 +1650,8 @@ static int yaffs_DeleteWorker(yaffs_Object * in, yaffs_Tnode * tn, __u32 level,  } -static void yaffs_SoftDeleteChunk(yaffs_Device * dev, int chunk) +static void yaffs_SoftDeleteChunk(yaffs_Device *dev, int chunk)  { -  	yaffs_BlockInfo *theBlock;  	T(YAFFS_TRACE_DELETION, (TSTR("soft delete chunk %d" TENDSTR), chunk)); @@ -1654,7 +1669,7 @@ static void yaffs_SoftDeleteChunk(yaffs_Device * dev, int chunk)   * Thus, essentially this is the same as DeleteWorker except that the chunks are soft deleted.   */ -static int yaffs_SoftDeleteWorker(yaffs_Object * in, yaffs_Tnode * tn, +static int yaffs_SoftDeleteWorker(yaffs_Object *in, yaffs_Tnode *tn,  				  __u32 level, int chunkOffset)  {  	int i; @@ -1691,14 +1706,14 @@ static int yaffs_SoftDeleteWorker(yaffs_Object * in, yaffs_Tnode * tn,  		} else if (level == 0) {  			for (i = YAFFS_NTNODES_LEVEL0 - 1; i >= 0; i--) { -				theChunk = yaffs_GetChunkGroupBase(dev,tn,i); +				theChunk = yaffs_GetChunkGroupBase(dev, tn, i);  				if (theChunk) {  					/* Note this does not find the real chunk, only the chunk group.  					 * We make an assumption that a chunk group is not larger than  					 * a block.  					 */  					yaffs_SoftDeleteChunk(dev, theChunk); -					yaffs_PutLevel0Tnode(dev,tn,i,0); +					yaffs_PutLevel0Tnode(dev, tn, i, 0);  				}  			} @@ -1712,7 +1727,7 @@ static int yaffs_SoftDeleteWorker(yaffs_Object * in, yaffs_Tnode * tn,  } -static void yaffs_SoftDeleteFile(yaffs_Object * obj) +static void yaffs_SoftDeleteFile(yaffs_Object *obj)  {  	if (obj->deleted &&  	    obj->variantType == YAFFS_OBJECT_TYPE_FILE && !obj->softDeleted) { @@ -1746,8 +1761,8 @@ static void yaffs_SoftDeleteFile(yaffs_Object * obj)   * by a special case.   */ -static yaffs_Tnode *yaffs_PruneWorker(yaffs_Device * dev, yaffs_Tnode * tn, -				      __u32 level, int del0) +static yaffs_Tnode *yaffs_PruneWorker(yaffs_Device *dev, yaffs_Tnode *tn, +				__u32 level, int del0)  {  	int i;  	int hasData; @@ -1763,9 +1778,8 @@ static yaffs_Tnode *yaffs_PruneWorker(yaffs_Device * dev, yaffs_Tnode * tn,  						      (i == 0) ? del0 : 1);  			} -			if (tn->internal[i]) { +			if (tn->internal[i])  				hasData++; -			}  		}  		if (hasData == 0 && del0) { @@ -1781,8 +1795,8 @@ static yaffs_Tnode *yaffs_PruneWorker(yaffs_Device * dev, yaffs_Tnode * tn,  } -static int yaffs_PruneFileStructure(yaffs_Device * dev, -				    yaffs_FileStructure * fStruct) +static int yaffs_PruneFileStructure(yaffs_Device *dev, +				yaffs_FileStructure *fStruct)  {  	int i;  	int hasData; @@ -1805,9 +1819,8 @@ static int yaffs_PruneFileStructure(yaffs_Device * dev,  			hasData = 0;  			for (i = 1; i < YAFFS_NTNODES_INTERNAL; i++) { -				if (tn->internal[i]) { +				if (tn->internal[i])  					hasData++; -				}  			}  			if (!hasData) { @@ -1828,7 +1841,7 @@ static int yaffs_PruneFileStructure(yaffs_Device * dev,  /* yaffs_CreateFreeObjects creates a bunch more objects and   * adds them to the object free list.   */ -static int yaffs_CreateFreeObjects(yaffs_Device * dev, int nObjects) +static int yaffs_CreateFreeObjects(yaffs_Device *dev, int nObjects)  {  	int i;  	yaffs_Object *newObjects; @@ -1842,9 +1855,9 @@ static int yaffs_CreateFreeObjects(yaffs_Device * dev, int nObjects)  	list = YMALLOC(sizeof(yaffs_ObjectList));  	if (!newObjects || !list) { -		if(newObjects) +		if (newObjects)  			YFREE(newObjects); -		if(list) +		if (list)  			YFREE(list);  		T(YAFFS_TRACE_ALLOCATE,  		  (TSTR("yaffs: Could not allocate more objects" TENDSTR))); @@ -1854,7 +1867,7 @@ static int yaffs_CreateFreeObjects(yaffs_Device * dev, int nObjects)  	/* Hook them into the free list */  	for (i = 0; i < nObjects - 1; i++) {  		newObjects[i].siblings.next = -		    (struct list_head *)(&newObjects[i + 1]); +				(struct ylist_head *)(&newObjects[i + 1]);  	}  	newObjects[nObjects - 1].siblings.next = (void *)dev->freeObjects; @@ -1873,85 +1886,109 @@ static int yaffs_CreateFreeObjects(yaffs_Device * dev, int nObjects)  /* AllocateEmptyObject gets us a clean Object. Tries to make allocate more if we run out */ -static yaffs_Object *yaffs_AllocateEmptyObject(yaffs_Device * dev) +static yaffs_Object *yaffs_AllocateEmptyObject(yaffs_Device *dev)  {  	yaffs_Object *tn = NULL; +#ifdef VALGRIND_TEST +	tn = YMALLOC(sizeof(yaffs_Object)); +#else  	/* If there are none left make more */ -	if (!dev->freeObjects) { +	if (!dev->freeObjects)  		yaffs_CreateFreeObjects(dev, YAFFS_ALLOCATION_NOBJECTS); -	}  	if (dev->freeObjects) {  		tn = dev->freeObjects;  		dev->freeObjects = -		    (yaffs_Object *) (dev->freeObjects->siblings.next); +			(yaffs_Object *) (dev->freeObjects->siblings.next);  		dev->nFreeObjects--; - +	} +#endif +	if (tn) {  		/* Now sweeten it up... */  		memset(tn, 0, sizeof(yaffs_Object)); +		tn->beingCreated = 1; +  		tn->myDev = dev; -		tn->chunkId = -1; +		tn->hdrChunk = 0;  		tn->variantType = YAFFS_OBJECT_TYPE_UNKNOWN; -		INIT_LIST_HEAD(&(tn->hardLinks)); -		INIT_LIST_HEAD(&(tn->hashLink)); -		INIT_LIST_HEAD(&tn->siblings); +		YINIT_LIST_HEAD(&(tn->hardLinks)); +		YINIT_LIST_HEAD(&(tn->hashLink)); +		YINIT_LIST_HEAD(&tn->siblings); + + +		/* Now make the directory sane */ +		if (dev->rootDir) { +			tn->parent = dev->rootDir; +			ylist_add(&(tn->siblings), &dev->rootDir->variant.directoryVariant.children); +		}  		/* Add it to the lost and found directory.  		 * NB Can't put root or lostNFound in lostNFound so  		 * check if lostNFound exists first  		 */ -		if (dev->lostNFoundDir) { +		if (dev->lostNFoundDir)  			yaffs_AddObjectToDirectory(dev->lostNFoundDir, tn); -		} + +		tn->beingCreated = 0;  	} +	dev->nCheckpointBlocksRequired = 0; /* force recalculation*/ +  	return tn;  } -static yaffs_Object *yaffs_CreateFakeDirectory(yaffs_Device * dev, int number, +static yaffs_Object *yaffs_CreateFakeDirectory(yaffs_Device *dev, int number,  					       __u32 mode)  {  	yaffs_Object *obj =  	    yaffs_CreateNewObject(dev, number, YAFFS_OBJECT_TYPE_DIRECTORY);  	if (obj) { -		obj->fake = 1;		/* it is fake so it has no NAND presence... */ +		obj->fake = 1;		/* it is fake so it might have no NAND presence... */  		obj->renameAllowed = 0;	/* ... and we're not allowed to rename it... */  		obj->unlinkAllowed = 0;	/* ... or unlink it */  		obj->deleted = 0;  		obj->unlinked = 0;  		obj->yst_mode = mode;  		obj->myDev = dev; -		obj->chunkId = 0;	/* Not a valid chunk. */ +		obj->hdrChunk = 0;	/* Not a valid chunk. */  	}  	return obj;  } -static void yaffs_UnhashObject(yaffs_Object * tn) +static void yaffs_UnhashObject(yaffs_Object *tn)  {  	int bucket;  	yaffs_Device *dev = tn->myDev;  	/* If it is still linked into the bucket list, free from the list */ -	if (!list_empty(&tn->hashLink)) { -		list_del_init(&tn->hashLink); +	if (!ylist_empty(&tn->hashLink)) { +		ylist_del_init(&tn->hashLink);  		bucket = yaffs_HashFunction(tn->objectId);  		dev->objectBucket[bucket].count--;  	} -  }  /*  FreeObject frees up a Object and puts it back on the free list */ -static void yaffs_FreeObject(yaffs_Object * tn) +static void yaffs_FreeObject(yaffs_Object *tn)  { -  	yaffs_Device *dev = tn->myDev; -#ifdef  __KERNEL__ +#ifdef __KERNEL__ +	T(YAFFS_TRACE_OS, (TSTR("FreeObject %p inode %p"TENDSTR), tn, tn->myInode)); +#endif + +	if (tn->parent) +		YBUG(); +	if (!ylist_empty(&tn->siblings)) +		YBUG(); + + +#ifdef __KERNEL__  	if (tn->myInode) {  		/* We're still hooked up to a cached inode.  		 * Don't delete now, but mark for later deletion @@ -1963,24 +2000,28 @@ static void yaffs_FreeObject(yaffs_Object * tn)  	yaffs_UnhashObject(tn); +#ifdef VALGRIND_TEST +	YFREE(tn); +#else  	/* Link into the free list. */ -	tn->siblings.next = (struct list_head *)(dev->freeObjects); +	tn->siblings.next = (struct ylist_head *)(dev->freeObjects);  	dev->freeObjects = tn;  	dev->nFreeObjects++; +#endif +	dev->nCheckpointBlocksRequired = 0; /* force recalculation*/  }  #ifdef __KERNEL__ -void yaffs_HandleDeferedFree(yaffs_Object * obj) +void yaffs_HandleDeferedFree(yaffs_Object *obj)  { -	if (obj->deferedFree) { +	if (obj->deferedFree)  		yaffs_FreeObject(obj); -	}  }  #endif -static void yaffs_DeinitialiseObjects(yaffs_Device * dev) +static void yaffs_DeinitialiseObjects(yaffs_Device *dev)  {  	/* Free the list of allocated Objects */ @@ -1998,7 +2039,7 @@ static void yaffs_DeinitialiseObjects(yaffs_Device * dev)  	dev->nFreeObjects = 0;  } -static void yaffs_InitialiseObjects(yaffs_Device * dev) +static void yaffs_InitialiseObjects(yaffs_Device *dev)  {  	int i; @@ -2007,15 +2048,14 @@ static void yaffs_InitialiseObjects(yaffs_Device * dev)  	dev->nFreeObjects = 0;  	for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) { -		INIT_LIST_HEAD(&dev->objectBucket[i].list); +		YINIT_LIST_HEAD(&dev->objectBucket[i].list);  		dev->objectBucket[i].count = 0;  	} -  } -static int yaffs_FindNiceObjectBucket(yaffs_Device * dev) +static int yaffs_FindNiceObjectBucket(yaffs_Device *dev)  { -	static int x = 0; +	static int x;  	int i;  	int l = 999;  	int lowest = 999999; @@ -2049,7 +2089,7 @@ static int yaffs_FindNiceObjectBucket(yaffs_Device * dev)  	return l;  } -static int yaffs_CreateNewObjectNumber(yaffs_Device * dev) +static int yaffs_CreateNewObjectNumber(yaffs_Device *dev)  {  	int bucket = yaffs_FindNiceObjectBucket(dev); @@ -2058,7 +2098,7 @@ static int yaffs_CreateNewObjectNumber(yaffs_Device * dev)  	 */  	int found = 0; -	struct list_head *i; +	struct ylist_head *i;  	__u32 n = (__u32) bucket; @@ -2068,41 +2108,38 @@ static int yaffs_CreateNewObjectNumber(yaffs_Device * dev)  		found = 1;  		n += YAFFS_NOBJECT_BUCKETS;  		if (1 || dev->objectBucket[bucket].count > 0) { -			list_for_each(i, &dev->objectBucket[bucket].list) { +			ylist_for_each(i, &dev->objectBucket[bucket].list) {  				/* If there is already one in the list */ -				if (i -				    && list_entry(i, yaffs_Object, -						  hashLink)->objectId == n) { +				if (i && ylist_entry(i, yaffs_Object, +						hashLink)->objectId == n) {  					found = 0;  				}  			}  		}  	} -  	return n;  } -static void yaffs_HashObject(yaffs_Object * in) +static void yaffs_HashObject(yaffs_Object *in)  {  	int bucket = yaffs_HashFunction(in->objectId);  	yaffs_Device *dev = in->myDev; -	list_add(&in->hashLink, &dev->objectBucket[bucket].list); +	ylist_add(&in->hashLink, &dev->objectBucket[bucket].list);  	dev->objectBucket[bucket].count++; -  } -yaffs_Object *yaffs_FindObjectByNumber(yaffs_Device * dev, __u32 number) +yaffs_Object *yaffs_FindObjectByNumber(yaffs_Device *dev, __u32 number)  {  	int bucket = yaffs_HashFunction(number); -	struct list_head *i; +	struct ylist_head *i;  	yaffs_Object *in; -	list_for_each(i, &dev->objectBucket[bucket].list) { +	ylist_for_each(i, &dev->objectBucket[bucket].list) {  		/* Look if it is in the list */  		if (i) { -			in = list_entry(i, yaffs_Object, hashLink); +			in = ylist_entry(i, yaffs_Object, hashLink);  			if (in->objectId == number) {  #ifdef __KERNEL__  				/* Don't tell the VFS about this one if it is defered free */ @@ -2118,31 +2155,27 @@ yaffs_Object *yaffs_FindObjectByNumber(yaffs_Device * dev, __u32 number)  	return NULL;  } -yaffs_Object *yaffs_CreateNewObject(yaffs_Device * dev, int number, +yaffs_Object *yaffs_CreateNewObject(yaffs_Device *dev, int number,  				    yaffs_ObjectType type)  { -  	yaffs_Object *theObject; -	yaffs_Tnode *tn; +	yaffs_Tnode *tn = NULL; -	if (number < 0) { +	if (number < 0)  		number = yaffs_CreateNewObjectNumber(dev); -	}  	theObject = yaffs_AllocateEmptyObject(dev); -	if(!theObject) +	if (!theObject)  		return NULL; -	if(type == YAFFS_OBJECT_TYPE_FILE){ +	if (type == YAFFS_OBJECT_TYPE_FILE) {  		tn = yaffs_GetTnode(dev); -		if(!tn){ +		if (!tn) {  			yaffs_FreeObject(theObject);  			return NULL;  		}  	} - -  	if (theObject) {  		theObject->fake = 0;  		theObject->renameAllowed = 1; @@ -2171,8 +2204,8 @@ yaffs_Object *yaffs_CreateNewObject(yaffs_Device * dev, int number,  			theObject->variant.fileVariant.top = tn;  			break;  		case YAFFS_OBJECT_TYPE_DIRECTORY: -			INIT_LIST_HEAD(&theObject->variant.directoryVariant. -				       children); +			YINIT_LIST_HEAD(&theObject->variant.directoryVariant. +					children);  			break;  		case YAFFS_OBJECT_TYPE_SYMLINK:  		case YAFFS_OBJECT_TYPE_HARDLINK: @@ -2188,32 +2221,30 @@ yaffs_Object *yaffs_CreateNewObject(yaffs_Device * dev, int number,  	return theObject;  } -static yaffs_Object *yaffs_FindOrCreateObjectByNumber(yaffs_Device * dev, +static yaffs_Object *yaffs_FindOrCreateObjectByNumber(yaffs_Device *dev,  						      int number,  						      yaffs_ObjectType type)  {  	yaffs_Object *theObject = NULL; -	if (number > 0) { +	if (number > 0)  		theObject = yaffs_FindObjectByNumber(dev, number); -	} -	if (!theObject) { +	if (!theObject)  		theObject = yaffs_CreateNewObject(dev, number, type); -	}  	return theObject;  } -static YCHAR *yaffs_CloneString(const YCHAR * str) +static YCHAR *yaffs_CloneString(const YCHAR *str)  {  	YCHAR *newStr = NULL;  	if (str && *str) {  		newStr = YMALLOC((yaffs_strlen(str) + 1) * sizeof(YCHAR)); -		if(newStr) +		if (newStr)  			yaffs_strcpy(newStr, str);  	} @@ -2229,29 +2260,31 @@ static YCHAR *yaffs_CloneString(const YCHAR * str)   */  static yaffs_Object *yaffs_MknodObject(yaffs_ObjectType type, -				       yaffs_Object * parent, -				       const YCHAR * name, +				       yaffs_Object *parent, +				       const YCHAR *name,  				       __u32 mode,  				       __u32 uid,  				       __u32 gid, -				       yaffs_Object * equivalentObject, -				       const YCHAR * aliasString, __u32 rdev) +				       yaffs_Object *equivalentObject, +				       const YCHAR *aliasString, __u32 rdev)  {  	yaffs_Object *in; -	YCHAR *str; +	YCHAR *str = NULL;  	yaffs_Device *dev = parent->myDev;  	/* Check if the entry exists. If it does then fail the call since we don't want a dup.*/ -	if (yaffs_FindObjectByName(parent, name)) { +	if (yaffs_FindObjectByName(parent, name))  		return NULL; -	}  	in = yaffs_CreateNewObject(dev, -1, type); -	if(type == YAFFS_OBJECT_TYPE_SYMLINK){ +	if (!in) +		return YAFFS_FAIL; + +	if (type == YAFFS_OBJECT_TYPE_SYMLINK) {  		str = yaffs_CloneString(aliasString); -		if(!str){ +		if (!str) {  			yaffs_FreeObject(in);  			return NULL;  		} @@ -2260,7 +2293,7 @@ static yaffs_Object *yaffs_MknodObject(yaffs_ObjectType type,  	if (in) { -		in->chunkId = -1; +		in->hdrChunk = 0;  		in->valid = 1;  		in->variantType = type; @@ -2293,10 +2326,10 @@ static yaffs_Object *yaffs_MknodObject(yaffs_ObjectType type,  			break;  		case YAFFS_OBJECT_TYPE_HARDLINK:  			in->variant.hardLinkVariant.equivalentObject = -			    equivalentObject; +				equivalentObject;  			in->variant.hardLinkVariant.equivalentObjectId = -			    equivalentObject->objectId; -			list_add(&in->hardLinks, &equivalentObject->hardLinks); +				equivalentObject->objectId; +			ylist_add(&in->hardLinks, &equivalentObject->hardLinks);  			break;  		case YAFFS_OBJECT_TYPE_FILE:  		case YAFFS_OBJECT_TYPE_DIRECTORY: @@ -2308,7 +2341,7 @@ static yaffs_Object *yaffs_MknodObject(yaffs_ObjectType type,  		if (yaffs_UpdateObjectHeader(in, name, 0, 0, 0) < 0) {  			/* Could not create the object header, fail the creation */ -			yaffs_DestroyObject(in); +			yaffs_DeleteObject(in);  			in = NULL;  		} @@ -2317,38 +2350,38 @@ static yaffs_Object *yaffs_MknodObject(yaffs_ObjectType type,  	return in;  } -yaffs_Object *yaffs_MknodFile(yaffs_Object * parent, const YCHAR * name, -			      __u32 mode, __u32 uid, __u32 gid) +yaffs_Object *yaffs_MknodFile(yaffs_Object *parent, const YCHAR *name, +			__u32 mode, __u32 uid, __u32 gid)  {  	return yaffs_MknodObject(YAFFS_OBJECT_TYPE_FILE, parent, name, mode, -				 uid, gid, NULL, NULL, 0); +				uid, gid, NULL, NULL, 0);  } -yaffs_Object *yaffs_MknodDirectory(yaffs_Object * parent, const YCHAR * name, -				   __u32 mode, __u32 uid, __u32 gid) +yaffs_Object *yaffs_MknodDirectory(yaffs_Object *parent, const YCHAR *name, +				__u32 mode, __u32 uid, __u32 gid)  {  	return yaffs_MknodObject(YAFFS_OBJECT_TYPE_DIRECTORY, parent, name,  				 mode, uid, gid, NULL, NULL, 0);  } -yaffs_Object *yaffs_MknodSpecial(yaffs_Object * parent, const YCHAR * name, -				 __u32 mode, __u32 uid, __u32 gid, __u32 rdev) +yaffs_Object *yaffs_MknodSpecial(yaffs_Object *parent, const YCHAR *name, +				__u32 mode, __u32 uid, __u32 gid, __u32 rdev)  {  	return yaffs_MknodObject(YAFFS_OBJECT_TYPE_SPECIAL, parent, name, mode,  				 uid, gid, NULL, NULL, rdev);  } -yaffs_Object *yaffs_MknodSymLink(yaffs_Object * parent, const YCHAR * name, -				 __u32 mode, __u32 uid, __u32 gid, -				 const YCHAR * alias) +yaffs_Object *yaffs_MknodSymLink(yaffs_Object *parent, const YCHAR *name, +				__u32 mode, __u32 uid, __u32 gid, +				const YCHAR *alias)  {  	return yaffs_MknodObject(YAFFS_OBJECT_TYPE_SYMLINK, parent, name, mode, -				 uid, gid, NULL, alias, 0); +				uid, gid, NULL, alias, 0);  }  /* yaffs_Link returns the object id of the equivalent object.*/ -yaffs_Object *yaffs_Link(yaffs_Object * parent, const YCHAR * name, -			 yaffs_Object * equivalentObject) +yaffs_Object *yaffs_Link(yaffs_Object *parent, const YCHAR *name, +			yaffs_Object *equivalentObject)  {  	/* Get the real object in case we were fed a hard link as an equivalent object */  	equivalentObject = yaffs_GetEquivalentObject(equivalentObject); @@ -2363,33 +2396,31 @@ yaffs_Object *yaffs_Link(yaffs_Object * parent, const YCHAR * name,  } -static int yaffs_ChangeObjectName(yaffs_Object * obj, yaffs_Object * newDir, -				  const YCHAR * newName, int force, int shadows) +static int yaffs_ChangeObjectName(yaffs_Object *obj, yaffs_Object *newDir, +				const YCHAR *newName, int force, int shadows)  {  	int unlinkOp;  	int deleteOp;  	yaffs_Object *existingTarget; -	if (newDir == NULL) { +	if (newDir == NULL)  		newDir = obj->parent;	/* use the old directory */ -	}  	if (newDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) {  		T(YAFFS_TRACE_ALWAYS,  		  (TSTR -		   ("tragendy: yaffs_ChangeObjectName: newDir is not a directory" +		   ("tragedy: yaffs_ChangeObjectName: newDir is not a directory"  		    TENDSTR)));  		YBUG();  	}  	/* TODO: Do we need this different handling for YAFFS2 and YAFFS1?? */ -	if (obj->myDev->isYaffs2) { +	if (obj->myDev->isYaffs2)  		unlinkOp = (newDir == obj->myDev->unlinkedDir); -	} else { +	else  		unlinkOp = (newDir == obj->myDev->unlinkedDir  			    && obj->variantType == YAFFS_OBJECT_TYPE_FILE); -	}  	deleteOp = (newDir == obj->myDev->deletedDir); @@ -2415,40 +2446,40 @@ static int yaffs_ChangeObjectName(yaffs_Object * obj, yaffs_Object * newDir,  			obj->unlinked = 1;  		/* If it is a deletion then we mark it as a shrink for gc purposes. */ -		if (yaffs_UpdateObjectHeader(obj, newName, 0, deleteOp, shadows)>= 0) +		if (yaffs_UpdateObjectHeader(obj, newName, 0, deleteOp, shadows) >= 0)  			return YAFFS_OK;  	}  	return YAFFS_FAIL;  } -int yaffs_RenameObject(yaffs_Object * oldDir, const YCHAR * oldName, -		       yaffs_Object * newDir, const YCHAR * newName) +int yaffs_RenameObject(yaffs_Object *oldDir, const YCHAR *oldName, +		yaffs_Object *newDir, const YCHAR *newName)  { -	yaffs_Object *obj; -	yaffs_Object *existingTarget; +	yaffs_Object *obj = NULL; +	yaffs_Object *existingTarget = NULL;  	int force = 0; + +	if (!oldDir || oldDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) +		YBUG(); +	if (!newDir || newDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) +		YBUG(); +  #ifdef CONFIG_YAFFS_CASE_INSENSITIVE  	/* Special case for case insemsitive systems (eg. WinCE).  	 * While look-up is case insensitive, the name isn't.  	 * Therefore we might want to change x.txt to X.txt  	*/ -	if (oldDir == newDir && yaffs_strcmp(oldName, newName) == 0) { +	if (oldDir == newDir && yaffs_strcmp(oldName, newName) == 0)  		force = 1; -	}  #endif +	else if (yaffs_strlen(newName) > YAFFS_MAX_NAME_LENGTH) +		/* ENAMETOOLONG */ +		return YAFFS_FAIL; +  	obj = yaffs_FindObjectByName(oldDir, oldName); -	/* Check new name to long. */ -	if (obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK && -	    yaffs_strlen(newName) > YAFFS_MAX_ALIAS_LENGTH) -	  /* ENAMETOOLONG */ -	  return YAFFS_FAIL; -	else if (obj->variantType != YAFFS_OBJECT_TYPE_SYMLINK && -		 yaffs_strlen(newName) > YAFFS_MAX_NAME_LENGTH) -	  /* ENAMETOOLONG */ -	  return YAFFS_FAIL;  	if (obj && obj->renameAllowed) { @@ -2456,8 +2487,8 @@ int yaffs_RenameObject(yaffs_Object * oldDir, const YCHAR * oldName,  		existingTarget = yaffs_FindObjectByName(newDir, newName);  		if (existingTarget && -		    existingTarget->variantType == YAFFS_OBJECT_TYPE_DIRECTORY && -		    !list_empty(&existingTarget->variant.directoryVariant.children)) { +			existingTarget->variantType == YAFFS_OBJECT_TYPE_DIRECTORY && +			!ylist_empty(&existingTarget->variant.directoryVariant.children)) {  			/* There is a target that is a non-empty directory, so we fail */  			return YAFFS_FAIL;	/* EEXIST or ENOTEMPTY */  		} else if (existingTarget && existingTarget != obj) { @@ -2465,7 +2496,7 @@ int yaffs_RenameObject(yaffs_Object * oldDir, const YCHAR * oldName,  			 * but only if it isn't the same object  			 */  			yaffs_ChangeObjectName(obj, newDir, newName, force, -					       existingTarget->objectId); +						existingTarget->objectId);  			yaffs_UnlinkObject(existingTarget);  		} @@ -2476,7 +2507,7 @@ int yaffs_RenameObject(yaffs_Object * oldDir, const YCHAR * oldName,  /*------------------------- Block Management and Page Allocation ----------------*/ -static int yaffs_InitialiseBlocks(yaffs_Device * dev) +static int yaffs_InitialiseBlocks(yaffs_Device *dev)  {  	int nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1; @@ -2487,23 +2518,20 @@ static int yaffs_InitialiseBlocks(yaffs_Device * dev)  	/* If the first allocation strategy fails, thry the alternate one */  	dev->blockInfo = YMALLOC(nBlocks * sizeof(yaffs_BlockInfo)); -	if(!dev->blockInfo){ +	if (!dev->blockInfo) {  		dev->blockInfo = YMALLOC_ALT(nBlocks * sizeof(yaffs_BlockInfo));  		dev->blockInfoAlt = 1; -	} -	else +	} else  		dev->blockInfoAlt = 0; -	if(dev->blockInfo){ - +	if (dev->blockInfo) {  		/* Set up dynamic blockinfo stuff. */  		dev->chunkBitmapStride = (dev->nChunksPerBlock + 7) / 8; /* round up bytes */  		dev->chunkBits = YMALLOC(dev->chunkBitmapStride * nBlocks); -		if(!dev->chunkBits){ +		if (!dev->chunkBits) {  			dev->chunkBits = YMALLOC_ALT(dev->chunkBitmapStride * nBlocks);  			dev->chunkBitsAlt = 1; -		} -		else +		} else  			dev->chunkBitsAlt = 0;  	} @@ -2514,30 +2542,29 @@ static int yaffs_InitialiseBlocks(yaffs_Device * dev)  	}  	return YAFFS_FAIL; -  } -static void yaffs_DeinitialiseBlocks(yaffs_Device * dev) +static void yaffs_DeinitialiseBlocks(yaffs_Device *dev)  { -	if(dev->blockInfoAlt && dev->blockInfo) +	if (dev->blockInfoAlt && dev->blockInfo)  		YFREE_ALT(dev->blockInfo); -	else if(dev->blockInfo) +	else if (dev->blockInfo)  		YFREE(dev->blockInfo);  	dev->blockInfoAlt = 0;  	dev->blockInfo = NULL; -	if(dev->chunkBitsAlt && dev->chunkBits) +	if (dev->chunkBitsAlt && dev->chunkBits)  		YFREE_ALT(dev->chunkBits); -	else if(dev->chunkBits) +	else if (dev->chunkBits)  		YFREE(dev->chunkBits);  	dev->chunkBitsAlt = 0;  	dev->chunkBits = NULL;  } -static int yaffs_BlockNotDisqualifiedFromGC(yaffs_Device * dev, -					    yaffs_BlockInfo * bi) +static int yaffs_BlockNotDisqualifiedFromGC(yaffs_Device *dev, +					yaffs_BlockInfo *bi)  {  	int i;  	__u32 seq; @@ -2556,7 +2583,7 @@ static int yaffs_BlockNotDisqualifiedFromGC(yaffs_Device * dev,  		seq = dev->sequenceNumber;  		for (i = dev->internalStartBlock; i <= dev->internalEndBlock; -		     i++) { +				i++) {  			b = yaffs_GetBlockInfo(dev, i);  			if (b->blockState == YAFFS_BLOCK_STATE_FULL &&  			    (b->pagesInUse - b->softDeletions) < @@ -2571,38 +2598,36 @@ static int yaffs_BlockNotDisqualifiedFromGC(yaffs_Device * dev,  	 * discarded pages.  	 */  	return (bi->sequenceNumber <= dev->oldestDirtySequence); -  }  /* FindDiretiestBlock is used to select the dirtiest block (or close enough)   * for garbage collection.   */ -static int yaffs_FindBlockForGarbageCollection(yaffs_Device * dev, -					       int aggressive) +static int yaffs_FindBlockForGarbageCollection(yaffs_Device *dev, +					int aggressive)  { -  	int b = dev->currentDirtyChecker;  	int i;  	int iterations;  	int dirtiest = -1;  	int pagesInUse = 0; -	int prioritised=0; +	int prioritised = 0;  	yaffs_BlockInfo *bi;  	int pendingPrioritisedExist = 0;  	/* First let's see if we need to grab a prioritised block */ -	if(dev->hasPendingPrioritisedGCs){ -		for(i = dev->internalStartBlock; i < dev->internalEndBlock && !prioritised; i++){ +	if (dev->hasPendingPrioritisedGCs) { +		for (i = dev->internalStartBlock; i < dev->internalEndBlock && !prioritised; i++) {  			bi = yaffs_GetBlockInfo(dev, i); -			//yaffs_VerifyBlock(dev,bi,i); +			/* yaffs_VerifyBlock(dev,bi,i); */ -			if(bi->gcPrioritise) { +			if (bi->gcPrioritise) {  				pendingPrioritisedExist = 1; -				if(bi->blockState == YAFFS_BLOCK_STATE_FULL && -				   yaffs_BlockNotDisqualifiedFromGC(dev, bi)){ +				if (bi->blockState == YAFFS_BLOCK_STATE_FULL && +				   yaffs_BlockNotDisqualifiedFromGC(dev, bi)) {  					pagesInUse = (bi->pagesInUse - bi->softDeletions);  					dirtiest = i;  					prioritised = 1; @@ -2611,7 +2636,7 @@ static int yaffs_FindBlockForGarbageCollection(yaffs_Device * dev,  			}  		} -		if(!pendingPrioritisedExist) /* None found, so we can clear this */ +		if (!pendingPrioritisedExist) /* None found, so we can clear this */  			dev->hasPendingPrioritisedGCs = 0;  	} @@ -2623,31 +2648,28 @@ static int yaffs_FindBlockForGarbageCollection(yaffs_Device * dev,  	dev->nonAggressiveSkip--; -	if (!aggressive && (dev->nonAggressiveSkip > 0)) { +	if (!aggressive && (dev->nonAggressiveSkip > 0))  		return -1; -	} -	if(!prioritised) +	if (!prioritised)  		pagesInUse = -	    		(aggressive) ? dev->nChunksPerBlock : YAFFS_PASSIVE_GC_CHUNKS + 1; +			(aggressive) ? dev->nChunksPerBlock : YAFFS_PASSIVE_GC_CHUNKS + 1; -	if (aggressive) { +	if (aggressive)  		iterations =  		    dev->internalEndBlock - dev->internalStartBlock + 1; -	} else { +	else {  		iterations =  		    dev->internalEndBlock - dev->internalStartBlock + 1;  		iterations = iterations / 16; -		if (iterations > 200) { +		if (iterations > 200)  			iterations = 200; -		}  	}  	for (i = 0; i <= iterations && pagesInUse > 0 && !prioritised; i++) {  		b++; -		if (b < dev->internalStartBlock || b > dev->internalEndBlock) { +		if (b < dev->internalStartBlock || b > dev->internalEndBlock)  			b = dev->internalStartBlock; -		}  		if (b < dev->internalStartBlock || b > dev->internalEndBlock) {  			T(YAFFS_TRACE_ERROR, @@ -2657,17 +2679,9 @@ static int yaffs_FindBlockForGarbageCollection(yaffs_Device * dev,  		bi = yaffs_GetBlockInfo(dev, b); -#if 0 -		if (bi->blockState == YAFFS_BLOCK_STATE_CHECKPOINT) { -			dirtiest = b; -			pagesInUse = 0; -		} -		else -#endif -  		if (bi->blockState == YAFFS_BLOCK_STATE_FULL && -		       (bi->pagesInUse - bi->softDeletions) < pagesInUse && -		        yaffs_BlockNotDisqualifiedFromGC(dev, bi)) { +			(bi->pagesInUse - bi->softDeletions) < pagesInUse && +				yaffs_BlockNotDisqualifiedFromGC(dev, bi)) {  			dirtiest = b;  			pagesInUse = (bi->pagesInUse - bi->softDeletions);  		} @@ -2678,19 +2692,18 @@ static int yaffs_FindBlockForGarbageCollection(yaffs_Device * dev,  	if (dirtiest > 0) {  		T(YAFFS_TRACE_GC,  		  (TSTR("GC Selected block %d with %d free, prioritised:%d" TENDSTR), dirtiest, -		   dev->nChunksPerBlock - pagesInUse,prioritised)); +		   dev->nChunksPerBlock - pagesInUse, prioritised));  	}  	dev->oldestDirtySequence = 0; -	if (dirtiest > 0) { +	if (dirtiest > 0)  		dev->nonAggressiveSkip = 4; -	}  	return dirtiest;  } -static void yaffs_BlockBecameDirty(yaffs_Device * dev, int blockNo) +static void yaffs_BlockBecameDirty(yaffs_Device *dev, int blockNo)  {  	yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, blockNo); @@ -2752,7 +2765,7 @@ static void yaffs_BlockBecameDirty(yaffs_Device * dev, int blockNo)  	}  } -static int yaffs_FindBlockForAllocation(yaffs_Device * dev) +static int yaffs_FindBlockForAllocation(yaffs_Device *dev)  {  	int i; @@ -2763,7 +2776,7 @@ static int yaffs_FindBlockForAllocation(yaffs_Device * dev)  		 * Can't get space to gc  		 */  		T(YAFFS_TRACE_ERROR, -		  (TSTR("yaffs tragedy: no more eraased blocks" TENDSTR))); +		  (TSTR("yaffs tragedy: no more erased blocks" TENDSTR)));  		return -1;  	} @@ -2794,31 +2807,74 @@ static int yaffs_FindBlockForAllocation(yaffs_Device * dev)  	T(YAFFS_TRACE_ALWAYS,  	  (TSTR -	   ("yaffs tragedy: no more eraased blocks, but there should have been %d" +	   ("yaffs tragedy: no more erased blocks, but there should have been %d"  	    TENDSTR), dev->nErasedBlocks));  	return -1;  } -// Check if there's space to allocate... -// Thinks.... do we need top make this ths same as yaffs_GetFreeChunks()? -static int yaffs_CheckSpaceForAllocation(yaffs_Device * dev) + +static int yaffs_CalcCheckpointBlocksRequired(yaffs_Device *dev) +{ +	if (!dev->nCheckpointBlocksRequired && +	   dev->isYaffs2) { +		/* Not a valid value so recalculate */ +		int nBytes = 0; +		int nBlocks; +		int devBlocks = (dev->endBlock - dev->startBlock + 1); +		int tnodeSize; + +		tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8; + +		if (tnodeSize < sizeof(yaffs_Tnode)) +			tnodeSize = sizeof(yaffs_Tnode); + +		nBytes += sizeof(yaffs_CheckpointValidity); +		nBytes += sizeof(yaffs_CheckpointDevice); +		nBytes += devBlocks * sizeof(yaffs_BlockInfo); +		nBytes += devBlocks * dev->chunkBitmapStride; +		nBytes += (sizeof(yaffs_CheckpointObject) + sizeof(__u32)) * (dev->nObjectsCreated - dev->nFreeObjects); +		nBytes += (tnodeSize + sizeof(__u32)) * (dev->nTnodesCreated - dev->nFreeTnodes); +		nBytes += sizeof(yaffs_CheckpointValidity); +		nBytes += sizeof(__u32); /* checksum*/ + +		/* Round up and add 2 blocks to allow for some bad blocks, so add 3 */ + +		nBlocks = (nBytes/(dev->nDataBytesPerChunk * dev->nChunksPerBlock)) + 3; + +		dev->nCheckpointBlocksRequired = nBlocks; +	} + +	return dev->nCheckpointBlocksRequired; +} + +/* + * Check if there's space to allocate... + * Thinks.... do we need top make this ths same as yaffs_GetFreeChunks()? + */ +static int yaffs_CheckSpaceForAllocation(yaffs_Device *dev)  {  	int reservedChunks;  	int reservedBlocks = dev->nReservedBlocks;  	int checkpointBlocks; -	checkpointBlocks =  dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint; -	if(checkpointBlocks < 0) +	if (dev->isYaffs2) { +		checkpointBlocks =  yaffs_CalcCheckpointBlocksRequired(dev) - +				    dev->blocksInCheckpoint; +		if (checkpointBlocks < 0) +			checkpointBlocks = 0; +	} else {  		checkpointBlocks = 0; +	}  	reservedChunks = ((reservedBlocks + checkpointBlocks) * dev->nChunksPerBlock);  	return (dev->nFreeChunks > reservedChunks);  } -static int yaffs_AllocateChunk(yaffs_Device * dev, int useReserve, yaffs_BlockInfo **blockUsedPtr) +static int yaffs_AllocateChunk(yaffs_Device *dev, int useReserve, +		yaffs_BlockInfo **blockUsedPtr)  {  	int retVal;  	yaffs_BlockInfo *bi; @@ -2835,7 +2891,7 @@ static int yaffs_AllocateChunk(yaffs_Device * dev, int useReserve, yaffs_BlockIn  	}  	if (dev->nErasedBlocks < dev->nReservedBlocks -	    && dev->allocationPage == 0) { +			&& dev->allocationPage == 0) {  		T(YAFFS_TRACE_ALLOCATE, (TSTR("Allocating reserve" TENDSTR)));  	} @@ -2844,10 +2900,10 @@ static int yaffs_AllocateChunk(yaffs_Device * dev, int useReserve, yaffs_BlockIn  		bi = yaffs_GetBlockInfo(dev, dev->allocationBlock);  		retVal = (dev->allocationBlock * dev->nChunksPerBlock) + -		    dev->allocationPage; +			dev->allocationPage;  		bi->pagesInUse++;  		yaffs_SetChunkBit(dev, dev->allocationBlock, -				  dev->allocationPage); +				dev->allocationPage);  		dev->allocationPage++; @@ -2859,43 +2915,43 @@ static int yaffs_AllocateChunk(yaffs_Device * dev, int useReserve, yaffs_BlockIn  			dev->allocationBlock = -1;  		} -		if(blockUsedPtr) +		if (blockUsedPtr)  			*blockUsedPtr = bi;  		return retVal;  	}  	T(YAFFS_TRACE_ERROR, -	  (TSTR("!!!!!!!!! Allocator out !!!!!!!!!!!!!!!!!" TENDSTR))); +			(TSTR("!!!!!!!!! Allocator out !!!!!!!!!!!!!!!!!" TENDSTR)));  	return -1;  } -static int yaffs_GetErasedChunks(yaffs_Device * dev) +static int yaffs_GetErasedChunks(yaffs_Device *dev)  {  	int n;  	n = dev->nErasedBlocks * dev->nChunksPerBlock; -	if (dev->allocationBlock > 0) { +	if (dev->allocationBlock > 0)  		n += (dev->nChunksPerBlock - dev->allocationPage); -	}  	return n;  } -static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block) +static int yaffs_GarbageCollectBlock(yaffs_Device *dev, int block, +		int wholeBlock)  {  	int oldChunk;  	int newChunk; -	int chunkInBlock;  	int markNAND;  	int retVal = YAFFS_OK;  	int cleanups = 0;  	int i;  	int isCheckpointBlock;  	int matchingChunk; +	int maxCopies;  	int chunksBefore = yaffs_GetErasedChunks(dev);  	int chunksAfter; @@ -2911,8 +2967,11 @@ static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block)  	bi->blockState = YAFFS_BLOCK_STATE_COLLECTING;  	T(YAFFS_TRACE_TRACING, -	  (TSTR("Collecting block %d, in use %d, shrink %d, " TENDSTR), block, -	   bi->pagesInUse, bi->hasShrinkHeader)); +			(TSTR("Collecting block %d, in use %d, shrink %d, wholeBlock %d" TENDSTR), +			 block, +			 bi->pagesInUse, +			 bi->hasShrinkHeader, +			 wholeBlock));  	/*yaffs_VerifyFreeChunks(dev); */ @@ -2926,26 +2985,33 @@ static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block)  	dev->isDoingGC = 1;  	if (isCheckpointBlock || -	    !yaffs_StillSomeChunkBits(dev, block)) { +			!yaffs_StillSomeChunkBits(dev, block)) {  		T(YAFFS_TRACE_TRACING, -		  (TSTR -		   ("Collecting block %d that has no chunks in use" TENDSTR), -		   block)); +				(TSTR +				 ("Collecting block %d that has no chunks in use" TENDSTR), +				 block));  		yaffs_BlockBecameDirty(dev, block);  	} else {  		__u8 *buffer = yaffs_GetTempBuffer(dev, __LINE__); -		yaffs_VerifyBlock(dev,bi,block); +		yaffs_VerifyBlock(dev, bi, block); + +		maxCopies = (wholeBlock) ? dev->nChunksPerBlock : 10; +		oldChunk = block * dev->nChunksPerBlock + dev->gcChunk; -		for (chunkInBlock = 0, oldChunk = block * dev->nChunksPerBlock; -		     chunkInBlock < dev->nChunksPerBlock -		     && yaffs_StillSomeChunkBits(dev, block); -		     chunkInBlock++, oldChunk++) { -			if (yaffs_CheckChunkBit(dev, block, chunkInBlock)) { +		for (/* init already done */; +		     retVal == YAFFS_OK && +		     dev->gcChunk < dev->nChunksPerBlock && +		     (bi->blockState == YAFFS_BLOCK_STATE_COLLECTING) && +		     maxCopies > 0; +		     dev->gcChunk++, oldChunk++) { +			if (yaffs_CheckChunkBit(dev, block, dev->gcChunk)) {  				/* This page is in use and might need to be copied off */ +				maxCopies--; +  				markNAND = 1;  				yaffs_InitialiseTags(&tags); @@ -2959,22 +3025,22 @@ static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block)  				T(YAFFS_TRACE_GC_DETAIL,  				  (TSTR -				   ("Collecting page %d, %d %d %d " TENDSTR), -				   chunkInBlock, tags.objectId, tags.chunkId, +				   ("Collecting chunk in block %d, %d %d %d " TENDSTR), +				   dev->gcChunk, tags.objectId, tags.chunkId,  				   tags.byteCount)); -				if(object && !yaffs_SkipVerification(dev)){ -					if(tags.chunkId == 0) -						matchingChunk = object->chunkId; -					else if(object->softDeleted) +				if (object && !yaffs_SkipVerification(dev)) { +					if (tags.chunkId == 0) +						matchingChunk = object->hdrChunk; +					else if (object->softDeleted)  						matchingChunk = oldChunk; /* Defeat the test */  					else -						matchingChunk = yaffs_FindChunkInFile(object,tags.chunkId,NULL); +						matchingChunk = yaffs_FindChunkInFile(object, tags.chunkId, NULL); -					if(oldChunk != matchingChunk) +					if (oldChunk != matchingChunk)  						T(YAFFS_TRACE_ERROR,  						  (TSTR("gc: page in gc mismatch: %d %d %d %d"TENDSTR), -						  oldChunk,matchingChunk,tags.objectId, tags.chunkId)); +						  oldChunk, matchingChunk, tags.objectId, tags.chunkId));  				} @@ -2986,9 +3052,11 @@ static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block)  					    tags.objectId, tags.chunkId, tags.byteCount));  				} -				if (object && object->deleted -				    && tags.chunkId != 0) { -					/* Data chunk in a deleted file, throw it away +				if (object && +				    object->deleted && +				    object->softDeleted && +				    tags.chunkId != 0) { +					/* Data chunk in a soft deleted file, throw it away  					 * It's a soft deleted data chunk,  					 * No need to copy this, just forget about it and  					 * fix up the object. @@ -3003,13 +3071,12 @@ static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block)  						cleanups++;  					}  					markNAND = 0; -				} else if (0 -					   /* Todo object && object->deleted && object->nDataChunks == 0 */ -					   ) { +				} else if (0) { +					/* Todo object && object->deleted && object->nDataChunks == 0 */  					/* Deleted object header with no data chunks.  					 * Can be discarded and the file deleted.  					 */ -					object->chunkId = 0; +					object->hdrChunk = 0;  					yaffs_FreeTnode(object->myDev,  							object->variant.  							fileVariant.top); @@ -3031,17 +3098,14 @@ static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block)  						 * We need to nuke the shrinkheader flags first  						 * We no longer want the shrinkHeader flag since its work is done  						 * and if it is left in place it will mess up scanning. -						 * Also, clear out any shadowing stuff  						 */  						yaffs_ObjectHeader *oh;  						oh = (yaffs_ObjectHeader *)buffer;  						oh->isShrink = 0; -						oh->shadowsObject = -1; -						tags.extraShadows = 0;  						tags.extraIsShrinkHeader = 0; -						yaffs_VerifyObjectHeader(object,oh,&tags,1); +						yaffs_VerifyObjectHeader(object, oh, &tags, 1);  					}  					newChunk = @@ -3055,7 +3119,7 @@ static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block)  						if (tags.chunkId == 0) {  							/* It's a header */ -							object->chunkId =  newChunk; +							object->hdrChunk =  newChunk;  							object->serial =   tags.serialNumber;  						} else {  							/* It's a data chunk */ @@ -3067,7 +3131,8 @@ static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block)  					}  				} -				yaffs_DeleteChunk(dev, oldChunk, markNAND, __LINE__); +				if (retVal == YAFFS_OK) +					yaffs_DeleteChunk(dev, oldChunk, markNAND, __LINE__);  			}  		} @@ -3098,18 +3163,25 @@ static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block)  	} -	yaffs_VerifyCollectedBlock(dev,bi,block); +	yaffs_VerifyCollectedBlock(dev, bi, block); -	if (chunksBefore >= (chunksAfter = yaffs_GetErasedChunks(dev))) { +	chunksAfter = yaffs_GetErasedChunks(dev); +	if (chunksBefore >= chunksAfter) {  		T(YAFFS_TRACE_GC,  		  (TSTR  		   ("gc did not increase free chunks before %d after %d"  		    TENDSTR), chunksBefore, chunksAfter));  	} +	/* If the gc completed then clear the current gcBlock so that we find another. */ +	if (bi->blockState != YAFFS_BLOCK_STATE_COLLECTING) { +		dev->gcBlock = -1; +		dev->gcChunk = 0; +	} +  	dev->isDoingGC = 0; -	return YAFFS_OK; +	return retVal;  }  /* New garbage collector @@ -3121,7 +3193,7 @@ static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block)   * The idea is to help clear out space in a more spread-out manner.   * Dunno if it really does anything useful.   */ -static int yaffs_CheckGarbageCollection(yaffs_Device * dev) +static int yaffs_CheckGarbageCollection(yaffs_Device *dev)  {  	int block;  	int aggressive; @@ -3142,8 +3214,8 @@ static int yaffs_CheckGarbageCollection(yaffs_Device * dev)  	do {  		maxTries++; -		checkpointBlockAdjust = (dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint); -		if(checkpointBlockAdjust < 0) +		checkpointBlockAdjust = yaffs_CalcCheckpointBlocksRequired(dev) - dev->blocksInCheckpoint; +		if (checkpointBlockAdjust < 0)  			checkpointBlockAdjust = 0;  		if (dev->nErasedBlocks < (dev->nReservedBlocks + checkpointBlockAdjust + 2)) { @@ -3154,20 +3226,24 @@ static int yaffs_CheckGarbageCollection(yaffs_Device * dev)  			aggressive = 0;  		} -		block = yaffs_FindBlockForGarbageCollection(dev, aggressive); +		if (dev->gcBlock <= 0) { +			dev->gcBlock = yaffs_FindBlockForGarbageCollection(dev, aggressive); +			dev->gcChunk = 0; +		} + +		block = dev->gcBlock;  		if (block > 0) {  			dev->garbageCollections++; -			if (!aggressive) { +			if (!aggressive)  				dev->passiveGarbageCollections++; -			}  			T(YAFFS_TRACE_GC,  			  (TSTR  			   ("yaffs: GC erasedBlocks %d aggressive %d" TENDSTR),  			   dev->nErasedBlocks, aggressive)); -			gcOk = yaffs_GarbageCollectBlock(dev, block); +			gcOk = yaffs_GarbageCollectBlock(dev, block, aggressive);  		}  		if (dev->nErasedBlocks < (dev->nReservedBlocks) && block > 0) { @@ -3176,15 +3252,16 @@ static int yaffs_CheckGarbageCollection(yaffs_Device * dev)  			   ("yaffs: GC !!!no reclaim!!! erasedBlocks %d after try %d block %d"  			    TENDSTR), dev->nErasedBlocks, maxTries, block));  		} -	} while ((dev->nErasedBlocks < dev->nReservedBlocks) && (block > 0) -		 && (maxTries < 2)); +	} while ((dev->nErasedBlocks < dev->nReservedBlocks) && +		 (block > 0) && +		 (maxTries < 2));  	return aggressive ? gcOk : YAFFS_OK;  }  /*-------------------------  TAGS --------------------------------*/ -static int yaffs_TagsMatch(const yaffs_ExtendedTags * tags, int objectId, +static int yaffs_TagsMatch(const yaffs_ExtendedTags *tags, int objectId,  			   int chunkInObject)  {  	return (tags->chunkId == chunkInObject && @@ -3195,8 +3272,8 @@ static int yaffs_TagsMatch(const yaffs_ExtendedTags * tags, int objectId,  /*-------------------- Data file manipulation -----------------*/ -static int yaffs_FindChunkInFile(yaffs_Object * in, int chunkInInode, -				 yaffs_ExtendedTags * tags) +static int yaffs_FindChunkInFile(yaffs_Object *in, int chunkInInode, +				 yaffs_ExtendedTags *tags)  {  	/*Get the Tnode, then get the level 0 offset chunk offset */  	yaffs_Tnode *tn; @@ -3214,7 +3291,7 @@ static int yaffs_FindChunkInFile(yaffs_Object * in, int chunkInInode,  	tn = yaffs_FindLevel0Tnode(dev, &in->variant.fileVariant, chunkInInode);  	if (tn) { -		theChunk = yaffs_GetChunkGroupBase(dev,tn,chunkInInode); +		theChunk = yaffs_GetChunkGroupBase(dev, tn, chunkInInode);  		retVal =  		    yaffs_FindChunkInGroup(dev, theChunk, tags, in->objectId, @@ -3223,8 +3300,8 @@ static int yaffs_FindChunkInFile(yaffs_Object * in, int chunkInInode,  	return retVal;  } -static int yaffs_FindAndDeleteChunkInFile(yaffs_Object * in, int chunkInInode, -					  yaffs_ExtendedTags * tags) +static int yaffs_FindAndDeleteChunkInFile(yaffs_Object *in, int chunkInInode, +					  yaffs_ExtendedTags *tags)  {  	/* Get the Tnode, then get the level 0 offset chunk offset */  	yaffs_Tnode *tn; @@ -3243,29 +3320,23 @@ static int yaffs_FindAndDeleteChunkInFile(yaffs_Object * in, int chunkInInode,  	if (tn) { -		theChunk = yaffs_GetChunkGroupBase(dev,tn,chunkInInode); +		theChunk = yaffs_GetChunkGroupBase(dev, tn, chunkInInode);  		retVal =  		    yaffs_FindChunkInGroup(dev, theChunk, tags, in->objectId,  					   chunkInInode);  		/* Delete the entry in the filestructure (if found) */ -		if (retVal != -1) { -			yaffs_PutLevel0Tnode(dev,tn,chunkInInode,0); -		} -	} else { -		/*T(("No level 0 found for %d\n", chunkInInode)); */ +		if (retVal != -1) +			yaffs_PutLevel0Tnode(dev, tn, chunkInInode, 0);  	} -	if (retVal == -1) { -		/* T(("Could not find %d to delete\n",chunkInInode)); */ -	}  	return retVal;  }  #ifdef YAFFS_PARANOID -static int yaffs_CheckFileSanity(yaffs_Object * in) +static int yaffs_CheckFileSanity(yaffs_Object *in)  {  	int chunk;  	int nChunks; @@ -3278,10 +3349,8 @@ static int yaffs_CheckFileSanity(yaffs_Object * in)  	int theChunk;  	int chunkDeleted; -	if (in->variantType != YAFFS_OBJECT_TYPE_FILE) { -		/* T(("Object not a file\n")); */ +	if (in->variantType != YAFFS_OBJECT_TYPE_FILE)  		return YAFFS_FAIL; -	}  	objId = in->objectId;  	fSize = in->variant.fileVariant.fileSize; @@ -3294,7 +3363,7 @@ static int yaffs_CheckFileSanity(yaffs_Object * in)  		if (tn) { -			theChunk = yaffs_GetChunkGroupBase(dev,tn,chunk); +			theChunk = yaffs_GetChunkGroupBase(dev, tn, chunk);  			if (yaffs_CheckChunkBits  			    (dev, theChunk / dev->nChunksPerBlock, @@ -3323,7 +3392,7 @@ static int yaffs_CheckFileSanity(yaffs_Object * in)  #endif -static int yaffs_PutChunkIntoFile(yaffs_Object * in, int chunkInInode, +static int yaffs_PutChunkIntoFile(yaffs_Object *in, int chunkInInode,  				  int chunkInNAND, int inScan)  {  	/* NB inScan is zero unless scanning. @@ -3358,11 +3427,10 @@ static int yaffs_PutChunkIntoFile(yaffs_Object * in, int chunkInInode,  					&in->variant.fileVariant,  					chunkInInode,  					NULL); -	if (!tn) { +	if (!tn)  		return YAFFS_FAIL; -	} -	existingChunk = yaffs_GetChunkGroupBase(dev,tn,chunkInInode); +	existingChunk = yaffs_GetChunkGroupBase(dev, tn, chunkInInode);  	if (inScan != 0) {  		/* If we're scanning then we need to test for duplicates @@ -3374,7 +3442,7 @@ static int yaffs_PutChunkIntoFile(yaffs_Object * in, int chunkInInode,  		 * Update: For backward scanning we don't need to re-read tags so this is quite cheap.  		 */ -		if (existingChunk != 0) { +		if (existingChunk > 0) {  			/* NB Right now existing chunk will not be real chunkId if the device >= 32MB  			 *    thus we have to do a FindChunkInFile to get the real chunk id.  			 * @@ -3411,8 +3479,10 @@ static int yaffs_PutChunkIntoFile(yaffs_Object * in, int chunkInInode,  			 * not be loaded during a scan  			 */ -			newSerial = newTags.serialNumber; -			existingSerial = existingTags.serialNumber; +			if (inScan > 0) { +				newSerial = newTags.serialNumber; +				existingSerial = existingTags.serialNumber; +			}  			if ((inScan > 0) &&  			    (in->myDev->isYaffs2 || @@ -3437,24 +3507,23 @@ static int yaffs_PutChunkIntoFile(yaffs_Object * in, int chunkInInode,  	} -	if (existingChunk == 0) { +	if (existingChunk == 0)  		in->nDataChunks++; -	} -	yaffs_PutLevel0Tnode(dev,tn,chunkInInode,chunkInNAND); +	yaffs_PutLevel0Tnode(dev, tn, chunkInInode, chunkInNAND);  	return YAFFS_OK;  } -static int yaffs_ReadChunkDataFromObject(yaffs_Object * in, int chunkInInode, -					 __u8 * buffer) +static int yaffs_ReadChunkDataFromObject(yaffs_Object *in, int chunkInInode, +					__u8 *buffer)  {  	int chunkInNAND = yaffs_FindChunkInFile(in, chunkInInode, NULL); -	if (chunkInNAND >= 0) { +	if (chunkInNAND >= 0)  		return yaffs_ReadChunkWithTagsFromNAND(in->myDev, chunkInNAND, -						       buffer,NULL); -	} else { +						buffer, NULL); +	else {  		T(YAFFS_TRACE_NANDACCESS,  		  (TSTR("Chunk %d not found zero instead" TENDSTR),  		   chunkInNAND)); @@ -3465,7 +3534,7 @@ static int yaffs_ReadChunkDataFromObject(yaffs_Object * in, int chunkInInode,  } -void yaffs_DeleteChunk(yaffs_Device * dev, int chunkId, int markNAND, int lyn) +void yaffs_DeleteChunk(yaffs_Device *dev, int chunkId, int markNAND, int lyn)  {  	int block;  	int page; @@ -3475,16 +3544,15 @@ void yaffs_DeleteChunk(yaffs_Device * dev, int chunkId, int markNAND, int lyn)  	if (chunkId <= 0)  		return; -  	dev->nDeletions++;  	block = chunkId / dev->nChunksPerBlock;  	page = chunkId % dev->nChunksPerBlock; -	if(!yaffs_CheckChunkBit(dev,block,page)) +	if (!yaffs_CheckChunkBit(dev, block, page))  		T(YAFFS_TRACE_VERIFY, -		 	(TSTR("Deleting invalid chunk %d"TENDSTR), -		 	 chunkId)); +			(TSTR("Deleting invalid chunk %d"TENDSTR), +			 chunkId));  	bi = yaffs_GetBlockInfo(dev, block); @@ -3524,14 +3592,12 @@ void yaffs_DeleteChunk(yaffs_Device * dev, int chunkId, int markNAND, int lyn)  			yaffs_BlockBecameDirty(dev, block);  		} -	} else { -		/* T(("Bad news deleting chunk %d\n",chunkId)); */  	}  } -static int yaffs_WriteChunkDataToObject(yaffs_Object * in, int chunkInInode, -					const __u8 * buffer, int nBytes, +static int yaffs_WriteChunkDataToObject(yaffs_Object *in, int chunkInInode, +					const __u8 *buffer, int nBytes,  					int useReserve)  {  	/* Find old chunk Need to do this to get serial number @@ -3561,6 +3627,12 @@ static int yaffs_WriteChunkDataToObject(yaffs_Object * in, int chunkInInode,  	    (prevChunkId >= 0) ? prevTags.serialNumber + 1 : 1;  	newTags.byteCount = nBytes; +	if (nBytes < 1 || nBytes > dev->totalBytesPerChunk) { +		T(YAFFS_TRACE_ERROR, +		(TSTR("Writing %d bytes to chunk!!!!!!!!!" TENDSTR), nBytes)); +		YBUG(); +	} +  	newChunkId =  	    yaffs_WriteNewChunkWithTagsToNAND(dev, buffer, &newTags,  					      useReserve); @@ -3568,11 +3640,9 @@ static int yaffs_WriteChunkDataToObject(yaffs_Object * in, int chunkInInode,  	if (newChunkId >= 0) {  		yaffs_PutChunkIntoFile(in, chunkInInode, newChunkId, 0); -		if (prevChunkId >= 0) { +		if (prevChunkId >= 0)  			yaffs_DeleteChunk(dev, prevChunkId, 1, __LINE__); -		} -  		yaffs_CheckFileSanity(in);  	}  	return newChunkId; @@ -3582,7 +3652,7 @@ static int yaffs_WriteChunkDataToObject(yaffs_Object * in, int chunkInInode,  /* UpdateObjectHeader updates the header on NAND for an object.   * If name is not NULL, then that new name is used.   */ -int yaffs_UpdateObjectHeader(yaffs_Object * in, const YCHAR * name, int force, +int yaffs_UpdateObjectHeader(yaffs_Object *in, const YCHAR *name, int force,  			     int isShrink, int shadows)  { @@ -3603,9 +3673,12 @@ int yaffs_UpdateObjectHeader(yaffs_Object * in, const YCHAR * name, int force,  	yaffs_ObjectHeader *oh = NULL; -	yaffs_strcpy(oldName,"silly old name"); +	yaffs_strcpy(oldName, _Y("silly old name")); + -	if (!in->fake || force) { +	if (!in->fake || +		in == dev->rootDir || /* The rootDir should also be saved */ +		force) {  		yaffs_CheckGarbageCollection(dev);  		yaffs_CheckObjectDetailsLoaded(in); @@ -3613,13 +3686,13 @@ int yaffs_UpdateObjectHeader(yaffs_Object * in, const YCHAR * name, int force,  		buffer = yaffs_GetTempBuffer(in->myDev, __LINE__);  		oh = (yaffs_ObjectHeader *) buffer; -		prevChunkId = in->chunkId; +		prevChunkId = in->hdrChunk; -		if (prevChunkId >= 0) { +		if (prevChunkId > 0) {  			result = yaffs_ReadChunkWithTagsFromNAND(dev, prevChunkId,  							buffer, &oldTags); -			yaffs_VerifyObjectHeader(in,oh,&oldTags,0); +			yaffs_VerifyObjectHeader(in, oh, &oldTags, 0);  			memcpy(oldName, oh->name, sizeof(oh->name));  		} @@ -3628,7 +3701,7 @@ int yaffs_UpdateObjectHeader(yaffs_Object * in, const YCHAR * name, int force,  		oh->type = in->variantType;  		oh->yst_mode = in->yst_mode; -		oh->shadowsObject = shadows; +		oh->shadowsObject = oh->inbandShadowsObject = shadows;  #ifdef CONFIG_YAFFS_WINCE  		oh->win_atime[0] = in->win_atime[0]; @@ -3645,20 +3718,18 @@ int yaffs_UpdateObjectHeader(yaffs_Object * in, const YCHAR * name, int force,  		oh->yst_ctime = in->yst_ctime;  		oh->yst_rdev = in->yst_rdev;  #endif -		if (in->parent) { +		if (in->parent)  			oh->parentObjectId = in->parent->objectId; -		} else { +		else  			oh->parentObjectId = 0; -		}  		if (name && *name) {  			memset(oh->name, 0, sizeof(oh->name));  			yaffs_strncpy(oh->name, name, YAFFS_MAX_NAME_LENGTH); -		} else if (prevChunkId>=0) { +		} else if (prevChunkId >= 0)  			memcpy(oh->name, oldName, sizeof(oh->name)); -		} else { +		else  			memset(oh->name, 0, sizeof(oh->name)); -		}  		oh->isShrink = isShrink; @@ -3708,7 +3779,7 @@ int yaffs_UpdateObjectHeader(yaffs_Object * in, const YCHAR * name, int force,  		newTags.extraShadows = (oh->shadowsObject > 0) ? 1 : 0;  		newTags.extraObjectType = in->variantType; -		yaffs_VerifyObjectHeader(in,oh,&newTags,1); +		yaffs_VerifyObjectHeader(in, oh, &newTags, 1);  		/* Create new chunk in NAND */  		newChunkId = @@ -3717,20 +3788,20 @@ int yaffs_UpdateObjectHeader(yaffs_Object * in, const YCHAR * name, int force,  		if (newChunkId >= 0) { -			in->chunkId = newChunkId; +			in->hdrChunk = newChunkId;  			if (prevChunkId >= 0) {  				yaffs_DeleteChunk(dev, prevChunkId, 1,  						  __LINE__);  			} -			if(!yaffs_ObjectHasCachedWriteData(in)) +			if (!yaffs_ObjectHasCachedWriteData(in))  				in->dirty = 0;  			/* If this was a shrink, then mark the block that the chunk lives on */  			if (isShrink) {  				bi = yaffs_GetBlockInfo(in->myDev, -							newChunkId /in->myDev->	nChunksPerBlock); +					newChunkId / in->myDev->nChunksPerBlock);  				bi->hasShrinkHeader = 1;  			} @@ -3766,7 +3837,7 @@ static int yaffs_ObjectHasCachedWriteData(yaffs_Object *obj)  	yaffs_ChunkCache *cache;  	int nCaches = obj->myDev->nShortOpCaches; -	for(i = 0; i < nCaches; i++){ +	for (i = 0; i < nCaches; i++) {  		cache = &dev->srCache[i];  		if (cache->object == obj &&  		    cache->dirty) @@ -3777,7 +3848,7 @@ static int yaffs_ObjectHasCachedWriteData(yaffs_Object *obj)  } -static void yaffs_FlushFilesChunkCache(yaffs_Object * obj) +static void yaffs_FlushFilesChunkCache(yaffs_Object *obj)  {  	yaffs_Device *dev = obj->myDev;  	int lowest = -99;	/* Stop compiler whining. */ @@ -3844,16 +3915,16 @@ void yaffs_FlushEntireDeviceCache(yaffs_Device *dev)  	 */  	do {  		obj = NULL; -		for( i = 0; i < nCaches && !obj; i++) { +		for (i = 0; i < nCaches && !obj; i++) {  			if (dev->srCache[i].object &&  			    dev->srCache[i].dirty)  				obj = dev->srCache[i].object;  		} -		if(obj) +		if (obj)  			yaffs_FlushFilesChunkCache(obj); -	} while(obj); +	} while (obj);  } @@ -3863,41 +3934,21 @@ void yaffs_FlushEntireDeviceCache(yaffs_Device *dev)   * Then look for the least recently used non-dirty one.   * Then look for the least recently used dirty one...., flush and look again.   */ -static yaffs_ChunkCache *yaffs_GrabChunkCacheWorker(yaffs_Device * dev) +static yaffs_ChunkCache *yaffs_GrabChunkCacheWorker(yaffs_Device *dev)  {  	int i; -	int usage; -	int theOne;  	if (dev->nShortOpCaches > 0) {  		for (i = 0; i < dev->nShortOpCaches; i++) {  			if (!dev->srCache[i].object)  				return &dev->srCache[i];  		} - -		return NULL; - -		theOne = -1; -		usage = 0;	/* just to stop the compiler grizzling */ - -		for (i = 0; i < dev->nShortOpCaches; i++) { -			if (!dev->srCache[i].dirty && -			    ((dev->srCache[i].lastUse < usage && theOne >= 0) || -			     theOne < 0)) { -				usage = dev->srCache[i].lastUse; -				theOne = i; -			} -		} - - -		return theOne >= 0 ? &dev->srCache[theOne] : NULL; -	} else { -		return NULL;  	} +	return NULL;  } -static yaffs_ChunkCache *yaffs_GrabChunkCache(yaffs_Device * dev) +static yaffs_ChunkCache *yaffs_GrabChunkCache(yaffs_Device *dev)  {  	yaffs_ChunkCache *cache;  	yaffs_Object *theObj; @@ -3927,8 +3978,7 @@ static yaffs_ChunkCache *yaffs_GrabChunkCache(yaffs_Device * dev)  			for (i = 0; i < dev->nShortOpCaches; i++) {  				if (dev->srCache[i].object &&  				    !dev->srCache[i].locked && -				    (dev->srCache[i].lastUse < usage || !cache)) -				{ +				    (dev->srCache[i].lastUse < usage || !cache)) {  					usage = dev->srCache[i].lastUse;  					theObj = dev->srCache[i].object;  					cache = &dev->srCache[i]; @@ -3950,7 +4000,7 @@ static yaffs_ChunkCache *yaffs_GrabChunkCache(yaffs_Device * dev)  }  /* Find a cached chunk */ -static yaffs_ChunkCache *yaffs_FindChunkCache(const yaffs_Object * obj, +static yaffs_ChunkCache *yaffs_FindChunkCache(const yaffs_Object *obj,  					      int chunkId)  {  	yaffs_Device *dev = obj->myDev; @@ -3969,7 +4019,7 @@ static yaffs_ChunkCache *yaffs_FindChunkCache(const yaffs_Object * obj,  }  /* Mark the chunk for the least recently used algorithym */ -static void yaffs_UseChunkCache(yaffs_Device * dev, yaffs_ChunkCache * cache, +static void yaffs_UseChunkCache(yaffs_Device *dev, yaffs_ChunkCache *cache,  				int isAWrite)  { @@ -3977,9 +4027,9 @@ static void yaffs_UseChunkCache(yaffs_Device * dev, yaffs_ChunkCache * cache,  		if (dev->srLastUse < 0 || dev->srLastUse > 100000000) {  			/* Reset the cache usages */  			int i; -			for (i = 1; i < dev->nShortOpCaches; i++) { +			for (i = 1; i < dev->nShortOpCaches; i++)  				dev->srCache[i].lastUse = 0; -			} +  			dev->srLastUse = 0;  		} @@ -3987,9 +4037,8 @@ static void yaffs_UseChunkCache(yaffs_Device * dev, yaffs_ChunkCache * cache,  		cache->lastUse = dev->srLastUse; -		if (isAWrite) { +		if (isAWrite)  			cache->dirty = 1; -		}  	}  } @@ -3997,21 +4046,20 @@ static void yaffs_UseChunkCache(yaffs_Device * dev, yaffs_ChunkCache * cache,   * Do this when a whole page gets written,   * ie the short cache for this page is no longer valid.   */ -static void yaffs_InvalidateChunkCache(yaffs_Object * object, int chunkId) +static void yaffs_InvalidateChunkCache(yaffs_Object *object, int chunkId)  {  	if (object->myDev->nShortOpCaches > 0) {  		yaffs_ChunkCache *cache = yaffs_FindChunkCache(object, chunkId); -		if (cache) { +		if (cache)  			cache->object = NULL; -		}  	}  }  /* Invalidate all the cache pages associated with this object   * Do this whenever ther file is deleted or resized.   */ -static void yaffs_InvalidateWholeChunkCache(yaffs_Object * in) +static void yaffs_InvalidateWholeChunkCache(yaffs_Object *in)  {  	int i;  	yaffs_Device *dev = in->myDev; @@ -4019,9 +4067,8 @@ static void yaffs_InvalidateWholeChunkCache(yaffs_Object * in)  	if (dev->nShortOpCaches > 0) {  		/* Invalidate it. */  		for (i = 0; i < dev->nShortOpCaches; i++) { -			if (dev->srCache[i].object == in) { +			if (dev->srCache[i].object == in)  				dev->srCache[i].object = NULL; -			}  		}  	}  } @@ -4029,18 +4076,18 @@ static void yaffs_InvalidateWholeChunkCache(yaffs_Object * in)  /*--------------------- Checkpointing --------------------*/ -static int yaffs_WriteCheckpointValidityMarker(yaffs_Device *dev,int head) +static int yaffs_WriteCheckpointValidityMarker(yaffs_Device *dev, int head)  {  	yaffs_CheckpointValidity cp; -	memset(&cp,0,sizeof(cp)); +	memset(&cp, 0, sizeof(cp));  	cp.structType = sizeof(cp);  	cp.magic = YAFFS_MAGIC;  	cp.version = YAFFS_CHECKPOINT_VERSION;  	cp.head = (head) ? 1 : 0; -	return (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp))? +	return (yaffs_CheckpointWrite(dev, &cp, sizeof(cp)) == sizeof(cp)) ?  		1 : 0;  } @@ -4049,9 +4096,9 @@ static int yaffs_ReadCheckpointValidityMarker(yaffs_Device *dev, int head)  	yaffs_CheckpointValidity cp;  	int ok; -	ok = (yaffs_CheckpointRead(dev,&cp,sizeof(cp)) == sizeof(cp)); +	ok = (yaffs_CheckpointRead(dev, &cp, sizeof(cp)) == sizeof(cp)); -	if(ok) +	if (ok)  		ok = (cp.structType == sizeof(cp)) &&  		     (cp.magic == YAFFS_MAGIC) &&  		     (cp.version == YAFFS_CHECKPOINT_VERSION) && @@ -4100,21 +4147,21 @@ static int yaffs_WriteCheckpointDevice(yaffs_Device *dev)  	int ok;  	/* Write device runtime values*/ -	yaffs_DeviceToCheckpointDevice(&cp,dev); +	yaffs_DeviceToCheckpointDevice(&cp, dev);  	cp.structType = sizeof(cp); -	ok = (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp)); +	ok = (yaffs_CheckpointWrite(dev, &cp, sizeof(cp)) == sizeof(cp));  	/* Write block info */ -	if(ok) { +	if (ok) {  		nBytes = nBlocks * sizeof(yaffs_BlockInfo); -		ok = (yaffs_CheckpointWrite(dev,dev->blockInfo,nBytes) == nBytes); +		ok = (yaffs_CheckpointWrite(dev, dev->blockInfo, nBytes) == nBytes);  	}  	/* Write chunk bits */ -	if(ok) { +	if (ok) {  		nBytes = nBlocks * dev->chunkBitmapStride; -		ok = (yaffs_CheckpointWrite(dev,dev->chunkBits,nBytes) == nBytes); +		ok = (yaffs_CheckpointWrite(dev, dev->chunkBits, nBytes) == nBytes);  	}  	return	 ok ? 1 : 0; @@ -4128,25 +4175,25 @@ static int yaffs_ReadCheckpointDevice(yaffs_Device *dev)  	int ok; -	ok = (yaffs_CheckpointRead(dev,&cp,sizeof(cp)) == sizeof(cp)); -	if(!ok) +	ok = (yaffs_CheckpointRead(dev, &cp, sizeof(cp)) == sizeof(cp)); +	if (!ok)  		return 0; -	if(cp.structType != sizeof(cp)) +	if (cp.structType != sizeof(cp))  		return 0; -	yaffs_CheckpointDeviceToDevice(dev,&cp); +	yaffs_CheckpointDeviceToDevice(dev, &cp);  	nBytes = nBlocks * sizeof(yaffs_BlockInfo); -	ok = (yaffs_CheckpointRead(dev,dev->blockInfo,nBytes) == nBytes); +	ok = (yaffs_CheckpointRead(dev, dev->blockInfo, nBytes) == nBytes); -	if(!ok) +	if (!ok)  		return 0;  	nBytes = nBlocks * dev->chunkBitmapStride; -	ok = (yaffs_CheckpointRead(dev,dev->chunkBits,nBytes) == nBytes); +	ok = (yaffs_CheckpointRead(dev, dev->chunkBits, nBytes) == nBytes);  	return ok ? 1 : 0;  } @@ -4157,7 +4204,7 @@ static void yaffs_ObjectToCheckpointObject(yaffs_CheckpointObject *cp,  	cp->objectId = obj->objectId;  	cp->parentId = (obj->parent) ? obj->parent->objectId : 0; -	cp->chunkId = obj->chunkId; +	cp->hdrChunk = obj->hdrChunk;  	cp->variantType = obj->variantType;  	cp->deleted = obj->deleted;  	cp->softDeleted = obj->softDeleted; @@ -4168,20 +4215,28 @@ static void yaffs_ObjectToCheckpointObject(yaffs_CheckpointObject *cp,  	cp->serial = obj->serial;  	cp->nDataChunks = obj->nDataChunks; -	if(obj->variantType == YAFFS_OBJECT_TYPE_FILE) +	if (obj->variantType == YAFFS_OBJECT_TYPE_FILE)  		cp->fileSizeOrEquivalentObjectId = obj->variant.fileVariant.fileSize; -	else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) +	else if (obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK)  		cp->fileSizeOrEquivalentObjectId = obj->variant.hardLinkVariant.equivalentObjectId;  } -static void yaffs_CheckpointObjectToObject( yaffs_Object *obj,yaffs_CheckpointObject *cp) +static int yaffs_CheckpointObjectToObject(yaffs_Object *obj, yaffs_CheckpointObject *cp)  {  	yaffs_Object *parent; +	if (obj->variantType != cp->variantType) { +		T(YAFFS_TRACE_ERROR, (TSTR("Checkpoint read object %d type %d " +			TCONT("chunk %d does not match existing object type %d") +			TENDSTR), cp->objectId, cp->variantType, cp->hdrChunk, +			obj->variantType)); +		return 0; +	} +  	obj->objectId = cp->objectId; -	if(cp->parentId) +	if (cp->parentId)  		parent = yaffs_FindOrCreateObjectByNumber(  					obj->myDev,  					cp->parentId, @@ -4189,10 +4244,19 @@ static void yaffs_CheckpointObjectToObject( yaffs_Object *obj,yaffs_CheckpointOb  	else  		parent = NULL; -	if(parent) +	if (parent) { +		if (parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) { +			T(YAFFS_TRACE_ALWAYS, (TSTR("Checkpoint read object %d parent %d type %d" +				TCONT(" chunk %d Parent type, %d, not directory") +				TENDSTR), +				cp->objectId, cp->parentId, cp->variantType, +				cp->hdrChunk, parent->variantType)); +			return 0; +		}  		yaffs_AddObjectToDirectory(parent, obj); +	} -	obj->chunkId = cp->chunkId; +	obj->hdrChunk = cp->hdrChunk;  	obj->variantType = cp->variantType;  	obj->deleted = cp->deleted;  	obj->softDeleted = cp->softDeleted; @@ -4203,29 +4267,34 @@ static void yaffs_CheckpointObjectToObject( yaffs_Object *obj,yaffs_CheckpointOb  	obj->serial = cp->serial;  	obj->nDataChunks = cp->nDataChunks; -	if(obj->variantType == YAFFS_OBJECT_TYPE_FILE) +	if (obj->variantType == YAFFS_OBJECT_TYPE_FILE)  		obj->variant.fileVariant.fileSize = cp->fileSizeOrEquivalentObjectId; -	else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) +	else if (obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK)  		obj->variant.hardLinkVariant.equivalentObjectId = cp->fileSizeOrEquivalentObjectId; -	if(obj->objectId >= YAFFS_NOBJECT_BUCKETS) +	if (obj->hdrChunk > 0)  		obj->lazyLoaded = 1; +	return 1;  } -static int yaffs_CheckpointTnodeWorker(yaffs_Object * in, yaffs_Tnode * tn, -				  	__u32 level, int chunkOffset) +static int yaffs_CheckpointTnodeWorker(yaffs_Object *in, yaffs_Tnode *tn, +					__u32 level, int chunkOffset)  {  	int i;  	yaffs_Device *dev = in->myDev;  	int ok = 1; -	int nTnodeBytes = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8; +	int tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8; + +	if (tnodeSize < sizeof(yaffs_Tnode)) +		tnodeSize = sizeof(yaffs_Tnode); +  	if (tn) {  		if (level > 0) { -			for (i = 0; i < YAFFS_NTNODES_INTERNAL && ok; i++){ +			for (i = 0; i < YAFFS_NTNODES_INTERNAL && ok; i++) {  				if (tn->internal[i]) {  					ok = yaffs_CheckpointTnodeWorker(in,  							tn->internal[i], @@ -4235,10 +4304,9 @@ static int yaffs_CheckpointTnodeWorker(yaffs_Object * in, yaffs_Tnode * tn,  			}  		} else if (level == 0) {  			__u32 baseOffset = chunkOffset <<  YAFFS_TNODES_LEVEL0_BITS; -			/* printf("write tnode at %d\n",baseOffset); */ -			ok = (yaffs_CheckpointWrite(dev,&baseOffset,sizeof(baseOffset)) == sizeof(baseOffset)); -			if(ok) -				ok = (yaffs_CheckpointWrite(dev,tn,nTnodeBytes) == nTnodeBytes); +			ok = (yaffs_CheckpointWrite(dev, &baseOffset, sizeof(baseOffset)) == sizeof(baseOffset)); +			if (ok) +				ok = (yaffs_CheckpointWrite(dev, tn, tnodeSize) == tnodeSize);  		}  	} @@ -4251,13 +4319,13 @@ static int yaffs_WriteCheckpointTnodes(yaffs_Object *obj)  	__u32 endMarker = ~0;  	int ok = 1; -	if(obj->variantType == YAFFS_OBJECT_TYPE_FILE){ +	if (obj->variantType == YAFFS_OBJECT_TYPE_FILE) {  		ok = yaffs_CheckpointTnodeWorker(obj,  					    obj->variant.fileVariant.top,  					    obj->variant.fileVariant.topLevel,  					    0); -		if(ok) -			ok = (yaffs_CheckpointWrite(obj->myDev,&endMarker,sizeof(endMarker)) == +		if (ok) +			ok = (yaffs_CheckpointWrite(obj->myDev, &endMarker, sizeof(endMarker)) ==  				sizeof(endMarker));  	} @@ -4272,38 +4340,38 @@ static int yaffs_ReadCheckpointTnodes(yaffs_Object *obj)  	yaffs_FileStructure *fileStructPtr = &obj->variant.fileVariant;  	yaffs_Tnode *tn;  	int nread = 0; +	int tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8; -	ok = (yaffs_CheckpointRead(dev,&baseChunk,sizeof(baseChunk)) == sizeof(baseChunk)); +	if (tnodeSize < sizeof(yaffs_Tnode)) +		tnodeSize = sizeof(yaffs_Tnode); -	while(ok && (~baseChunk)){ +	ok = (yaffs_CheckpointRead(dev, &baseChunk, sizeof(baseChunk)) == sizeof(baseChunk)); + +	while (ok && (~baseChunk)) {  		nread++;  		/* Read level 0 tnode */ -		/* printf("read  tnode at %d\n",baseChunk); */  		tn = yaffs_GetTnodeRaw(dev); -		if(tn) -			ok = (yaffs_CheckpointRead(dev,tn,(dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8) == -			      (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8); +		if (tn) +			ok = (yaffs_CheckpointRead(dev, tn, tnodeSize) == tnodeSize);  		else  			ok = 0; -		if(tn && ok){ +		if (tn && ok)  			ok = yaffs_AddOrFindLevel0Tnode(dev, -					       		fileStructPtr, -					       		baseChunk, -					       		tn) ? 1 : 0; +							fileStructPtr, +							baseChunk, +							tn) ? 1 : 0; -		} - -		if(ok) -			ok = (yaffs_CheckpointRead(dev,&baseChunk,sizeof(baseChunk)) == sizeof(baseChunk)); +		if (ok) +			ok = (yaffs_CheckpointRead(dev, &baseChunk, sizeof(baseChunk)) == sizeof(baseChunk));  	} -	T(YAFFS_TRACE_CHECKPOINT,( +	T(YAFFS_TRACE_CHECKPOINT, (  		TSTR("Checkpoint read tnodes %d records, last %d. ok %d" TENDSTR), -		nread,baseChunk,ok)); +		nread, baseChunk, ok));  	return ok ? 1 : 0;  } @@ -4315,41 +4383,40 @@ static int yaffs_WriteCheckpointObjects(yaffs_Device *dev)  	yaffs_CheckpointObject cp;  	int i;  	int ok = 1; -	struct list_head *lh; +	struct ylist_head *lh;  	/* Iterate through the objects in each hash entry,  	 * dumping them to the checkpointing stream.  	 */ -	 for(i = 0; ok &&  i <  YAFFS_NOBJECT_BUCKETS; i++){ -	 	list_for_each(lh, &dev->objectBucket[i].list) { +	for (i = 0; ok &&  i <  YAFFS_NOBJECT_BUCKETS; i++) { +		ylist_for_each(lh, &dev->objectBucket[i].list) {  			if (lh) { -				obj = list_entry(lh, yaffs_Object, hashLink); +				obj = ylist_entry(lh, yaffs_Object, hashLink);  				if (!obj->deferedFree) { -					yaffs_ObjectToCheckpointObject(&cp,obj); +					yaffs_ObjectToCheckpointObject(&cp, obj);  					cp.structType = sizeof(cp); -					T(YAFFS_TRACE_CHECKPOINT,( +					T(YAFFS_TRACE_CHECKPOINT, (  						TSTR("Checkpoint write object %d parent %d type %d chunk %d obj addr %x" TENDSTR), -						cp.objectId,cp.parentId,cp.variantType,cp.chunkId,(unsigned) obj)); +						cp.objectId, cp.parentId, cp.variantType, cp.hdrChunk, (unsigned) obj)); -					ok = (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp)); +					ok = (yaffs_CheckpointWrite(dev, &cp, sizeof(cp)) == sizeof(cp)); -					if(ok && obj->variantType == YAFFS_OBJECT_TYPE_FILE){ +					if (ok && obj->variantType == YAFFS_OBJECT_TYPE_FILE)  						ok = yaffs_WriteCheckpointTnodes(obj); -					}  				}  			}  		} -	 } +	} -	 /* Dump end of list */ -	memset(&cp,0xFF,sizeof(yaffs_CheckpointObject)); +	/* Dump end of list */ +	memset(&cp, 0xFF, sizeof(yaffs_CheckpointObject));  	cp.structType = sizeof(cp); -	if(ok) -		ok = (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp)); +	if (ok) +		ok = (yaffs_CheckpointWrite(dev, &cp, sizeof(cp)) == sizeof(cp));  	return ok ? 1 : 0;  } @@ -4362,38 +4429,39 @@ static int yaffs_ReadCheckpointObjects(yaffs_Device *dev)  	int done = 0;  	yaffs_Object *hardList = NULL; -	while(ok && !done) { -		ok = (yaffs_CheckpointRead(dev,&cp,sizeof(cp)) == sizeof(cp)); -		if(cp.structType != sizeof(cp)) { -			T(YAFFS_TRACE_CHECKPOINT,(TSTR("struct size %d instead of %d ok %d"TENDSTR), -				cp.structType,sizeof(cp),ok)); +	while (ok && !done) { +		ok = (yaffs_CheckpointRead(dev, &cp, sizeof(cp)) == sizeof(cp)); +		if (cp.structType != sizeof(cp)) { +			T(YAFFS_TRACE_CHECKPOINT, (TSTR("struct size %d instead of %d ok %d"TENDSTR), +				cp.structType, sizeof(cp), ok));  			ok = 0;  		} -		T(YAFFS_TRACE_CHECKPOINT,(TSTR("Checkpoint read object %d parent %d type %d chunk %d " TENDSTR), -			cp.objectId,cp.parentId,cp.variantType,cp.chunkId)); +		T(YAFFS_TRACE_CHECKPOINT, (TSTR("Checkpoint read object %d parent %d type %d chunk %d " TENDSTR), +			cp.objectId, cp.parentId, cp.variantType, cp.hdrChunk)); -		if(ok && cp.objectId == ~0) +		if (ok && cp.objectId == ~0)  			done = 1; -		else if(ok){ -			obj = yaffs_FindOrCreateObjectByNumber(dev,cp.objectId, cp.variantType); -			if(obj) { -				yaffs_CheckpointObjectToObject(obj,&cp); -				if(obj->variantType == YAFFS_OBJECT_TYPE_FILE) { +		else if (ok) { +			obj = yaffs_FindOrCreateObjectByNumber(dev, cp.objectId, cp.variantType); +			if (obj) { +				ok = yaffs_CheckpointObjectToObject(obj, &cp); +				if (!ok) +					break; +				if (obj->variantType == YAFFS_OBJECT_TYPE_FILE) {  					ok = yaffs_ReadCheckpointTnodes(obj); -				} else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) { +				} else if (obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) {  					obj->hardLinks.next = -						    (struct list_head *) -						    hardList; +						(struct ylist_head *) hardList;  					hardList = obj;  				} - -			} +			} else +				ok = 0;  		}  	} -	if(ok) -		yaffs_HardlinkFixup(dev,hardList); +	if (ok) +		yaffs_HardlinkFixup(dev, hardList);  	return ok ? 1 : 0;  } @@ -4403,11 +4471,11 @@ static int yaffs_WriteCheckpointSum(yaffs_Device *dev)  	__u32 checkpointSum;  	int ok; -	yaffs_GetCheckpointSum(dev,&checkpointSum); +	yaffs_GetCheckpointSum(dev, &checkpointSum); -	ok = (yaffs_CheckpointWrite(dev,&checkpointSum,sizeof(checkpointSum)) == sizeof(checkpointSum)); +	ok = (yaffs_CheckpointWrite(dev, &checkpointSum, sizeof(checkpointSum)) == sizeof(checkpointSum)); -	if(!ok) +	if (!ok)  		return 0;  	return 1; @@ -4419,14 +4487,14 @@ static int yaffs_ReadCheckpointSum(yaffs_Device *dev)  	__u32 checkpointSum1;  	int ok; -	yaffs_GetCheckpointSum(dev,&checkpointSum0); +	yaffs_GetCheckpointSum(dev, &checkpointSum0); -	ok = (yaffs_CheckpointRead(dev,&checkpointSum1,sizeof(checkpointSum1)) == sizeof(checkpointSum1)); +	ok = (yaffs_CheckpointRead(dev, &checkpointSum1, sizeof(checkpointSum1)) == sizeof(checkpointSum1)); -	if(!ok) +	if (!ok)  		return 0; -	if(checkpointSum0 != checkpointSum1) +	if (checkpointSum0 != checkpointSum1)  		return 0;  	return 1; @@ -4435,46 +4503,43 @@ static int yaffs_ReadCheckpointSum(yaffs_Device *dev)  static int yaffs_WriteCheckpointData(yaffs_Device *dev)  { -  	int ok = 1; -	if(dev->skipCheckpointWrite || !dev->isYaffs2){ -		T(YAFFS_TRACE_CHECKPOINT,(TSTR("skipping checkpoint write" TENDSTR))); +	if (dev->skipCheckpointWrite || !dev->isYaffs2) { +		T(YAFFS_TRACE_CHECKPOINT, (TSTR("skipping checkpoint write" TENDSTR)));  		ok = 0;  	} -	if(ok) -		ok = yaffs_CheckpointOpen(dev,1); +	if (ok) +		ok = yaffs_CheckpointOpen(dev, 1); -	if(ok){ -		T(YAFFS_TRACE_CHECKPOINT,(TSTR("write checkpoint validity" TENDSTR))); -		ok = yaffs_WriteCheckpointValidityMarker(dev,1); +	if (ok) { +		T(YAFFS_TRACE_CHECKPOINT, (TSTR("write checkpoint validity" TENDSTR))); +		ok = yaffs_WriteCheckpointValidityMarker(dev, 1);  	} -	if(ok){ -		T(YAFFS_TRACE_CHECKPOINT,(TSTR("write checkpoint device" TENDSTR))); +	if (ok) { +		T(YAFFS_TRACE_CHECKPOINT, (TSTR("write checkpoint device" TENDSTR)));  		ok = yaffs_WriteCheckpointDevice(dev);  	} -	if(ok){ -		T(YAFFS_TRACE_CHECKPOINT,(TSTR("write checkpoint objects" TENDSTR))); +	if (ok) { +		T(YAFFS_TRACE_CHECKPOINT, (TSTR("write checkpoint objects" TENDSTR)));  		ok = yaffs_WriteCheckpointObjects(dev);  	} -	if(ok){ -		T(YAFFS_TRACE_CHECKPOINT,(TSTR("write checkpoint validity" TENDSTR))); -		ok = yaffs_WriteCheckpointValidityMarker(dev,0); +	if (ok) { +		T(YAFFS_TRACE_CHECKPOINT, (TSTR("write checkpoint validity" TENDSTR))); +		ok = yaffs_WriteCheckpointValidityMarker(dev, 0);  	} -	if(ok){ +	if (ok)  		ok = yaffs_WriteCheckpointSum(dev); -	} +	if (!yaffs_CheckpointClose(dev)) +		ok = 0; -	if(!yaffs_CheckpointClose(dev)) -		 ok = 0; - -	if(ok) -	    	dev->isCheckpointed = 1; -	 else -	 	dev->isCheckpointed = 0; +	if (ok) +		dev->isCheckpointed = 1; +	else +		dev->isCheckpointed = 0;  	return dev->isCheckpointed;  } @@ -4483,43 +4548,43 @@ static int yaffs_ReadCheckpointData(yaffs_Device *dev)  {  	int ok = 1; -	if(dev->skipCheckpointRead || !dev->isYaffs2){ -		T(YAFFS_TRACE_CHECKPOINT,(TSTR("skipping checkpoint read" TENDSTR))); +	if (dev->skipCheckpointRead || !dev->isYaffs2) { +		T(YAFFS_TRACE_CHECKPOINT, (TSTR("skipping checkpoint read" TENDSTR)));  		ok = 0;  	} -	if(ok) -		ok = yaffs_CheckpointOpen(dev,0); /* open for read */ +	if (ok) +		ok = yaffs_CheckpointOpen(dev, 0); /* open for read */ -	if(ok){ -		T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint validity" TENDSTR))); -		ok = yaffs_ReadCheckpointValidityMarker(dev,1); +	if (ok) { +		T(YAFFS_TRACE_CHECKPOINT, (TSTR("read checkpoint validity" TENDSTR))); +		ok = yaffs_ReadCheckpointValidityMarker(dev, 1);  	} -	if(ok){ -		T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint device" TENDSTR))); +	if (ok) { +		T(YAFFS_TRACE_CHECKPOINT, (TSTR("read checkpoint device" TENDSTR)));  		ok = yaffs_ReadCheckpointDevice(dev);  	} -	if(ok){ -		T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint objects" TENDSTR))); +	if (ok) { +		T(YAFFS_TRACE_CHECKPOINT, (TSTR("read checkpoint objects" TENDSTR)));  		ok = yaffs_ReadCheckpointObjects(dev);  	} -	if(ok){ -		T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint validity" TENDSTR))); -		ok = yaffs_ReadCheckpointValidityMarker(dev,0); +	if (ok) { +		T(YAFFS_TRACE_CHECKPOINT, (TSTR("read checkpoint validity" TENDSTR))); +		ok = yaffs_ReadCheckpointValidityMarker(dev, 0);  	} -	if(ok){ +	if (ok) {  		ok = yaffs_ReadCheckpointSum(dev); -		T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint checksum %d" TENDSTR),ok)); +		T(YAFFS_TRACE_CHECKPOINT, (TSTR("read checkpoint checksum %d" TENDSTR), ok));  	} -	if(!yaffs_CheckpointClose(dev)) +	if (!yaffs_CheckpointClose(dev))  		ok = 0; -	if(ok) -	    	dev->isCheckpointed = 1; -	 else -	 	dev->isCheckpointed = 0; +	if (ok) +		dev->isCheckpointed = 1; +	else +		dev->isCheckpointed = 0;  	return ok ? 1 : 0; @@ -4527,11 +4592,11 @@ static int yaffs_ReadCheckpointData(yaffs_Device *dev)  static void yaffs_InvalidateCheckpoint(yaffs_Device *dev)  { -	if(dev->isCheckpointed || -	   dev->blocksInCheckpoint > 0){ +	if (dev->isCheckpointed || +			dev->blocksInCheckpoint > 0) {  		dev->isCheckpointed = 0;  		yaffs_CheckpointInvalidateStream(dev); -		if(dev->superBlock && dev->markSuperBlockDirty) +		if (dev->superBlock && dev->markSuperBlockDirty)  			dev->markSuperBlockDirty(dev->superBlock);  	}  } @@ -4540,18 +4605,18 @@ static void yaffs_InvalidateCheckpoint(yaffs_Device *dev)  int yaffs_CheckpointSave(yaffs_Device *dev)  { -	T(YAFFS_TRACE_CHECKPOINT,(TSTR("save entry: isCheckpointed %d"TENDSTR),dev->isCheckpointed)); +	T(YAFFS_TRACE_CHECKPOINT, (TSTR("save entry: isCheckpointed %d"TENDSTR), dev->isCheckpointed));  	yaffs_VerifyObjects(dev);  	yaffs_VerifyBlocks(dev);  	yaffs_VerifyFreeChunks(dev); -	if(!dev->isCheckpointed) { +	if (!dev->isCheckpointed) {  		yaffs_InvalidateCheckpoint(dev);  		yaffs_WriteCheckpointData(dev);  	} -	T(YAFFS_TRACE_ALWAYS,(TSTR("save exit: isCheckpointed %d"TENDSTR),dev->isCheckpointed)); +	T(YAFFS_TRACE_ALWAYS, (TSTR("save exit: isCheckpointed %d"TENDSTR), dev->isCheckpointed));  	return dev->isCheckpointed;  } @@ -4559,17 +4624,17 @@ int yaffs_CheckpointSave(yaffs_Device *dev)  int yaffs_CheckpointRestore(yaffs_Device *dev)  {  	int retval; -	T(YAFFS_TRACE_CHECKPOINT,(TSTR("restore entry: isCheckpointed %d"TENDSTR),dev->isCheckpointed)); +	T(YAFFS_TRACE_CHECKPOINT, (TSTR("restore entry: isCheckpointed %d"TENDSTR), dev->isCheckpointed));  	retval = yaffs_ReadCheckpointData(dev); -	if(dev->isCheckpointed){ +	if (dev->isCheckpointed) {  		yaffs_VerifyObjects(dev);  		yaffs_VerifyBlocks(dev);  		yaffs_VerifyFreeChunks(dev);  	} -	T(YAFFS_TRACE_CHECKPOINT,(TSTR("restore exit: isCheckpointed %d"TENDSTR),dev->isCheckpointed)); +	T(YAFFS_TRACE_CHECKPOINT, (TSTR("restore exit: isCheckpointed %d"TENDSTR), dev->isCheckpointed));  	return retval;  } @@ -4584,12 +4649,12 @@ int yaffs_CheckpointRestore(yaffs_Device *dev)   * Curve-balls: the first chunk might also be the last chunk.   */ -int yaffs_ReadDataFromFile(yaffs_Object * in, __u8 * buffer, loff_t offset, -			   int nBytes) +int yaffs_ReadDataFromFile(yaffs_Object *in, __u8 *buffer, loff_t offset, +			int nBytes)  {  	int chunk; -	int start; +	__u32 start;  	int nToCopy;  	int n = nBytes;  	int nDone = 0; @@ -4600,27 +4665,26 @@ int yaffs_ReadDataFromFile(yaffs_Object * in, __u8 * buffer, loff_t offset,  	dev = in->myDev;  	while (n > 0) { -		//chunk = offset / dev->nDataBytesPerChunk + 1; -		//start = offset % dev->nDataBytesPerChunk; -		yaffs_AddrToChunk(dev,offset,&chunk,&start); +		/* chunk = offset / dev->nDataBytesPerChunk + 1; */ +		/* start = offset % dev->nDataBytesPerChunk; */ +		yaffs_AddrToChunk(dev, offset, &chunk, &start);  		chunk++;  		/* OK now check for the curveball where the start and end are in  		 * the same chunk.  		 */ -		if ((start + n) < dev->nDataBytesPerChunk) { +		if ((start + n) < dev->nDataBytesPerChunk)  			nToCopy = n; -		} else { +		else  			nToCopy = dev->nDataBytesPerChunk - start; -		}  		cache = yaffs_FindChunkCache(in, chunk);  		/* If the chunk is already in the cache or it is less than a whole chunk -		 * then use the cache (if there is caching) +		 * or we're using inband tags then use the cache (if there is caching)  		 * else bypass the cache.  		 */ -		if (cache || nToCopy != dev->nDataBytesPerChunk) { +		if (cache || nToCopy != dev->nDataBytesPerChunk || dev->inbandTags) {  			if (dev->nShortOpCaches > 0) {  				/* If we can't find the data in the cache, then load it up. */ @@ -4641,14 +4705,9 @@ int yaffs_ReadDataFromFile(yaffs_Object * in, __u8 * buffer, loff_t offset,  				cache->locked = 1; -#ifdef CONFIG_YAFFS_WINCE -				yfsd_UnlockYAFFS(TRUE); -#endif +  				memcpy(buffer, &cache->data[start], nToCopy); -#ifdef CONFIG_YAFFS_WINCE -				yfsd_LockYAFFS(TRUE); -#endif  				cache->locked = 0;  			} else {  				/* Read into the local buffer then copy..*/ @@ -4657,41 +4716,19 @@ int yaffs_ReadDataFromFile(yaffs_Object * in, __u8 * buffer, loff_t offset,  				    yaffs_GetTempBuffer(dev, __LINE__);  				yaffs_ReadChunkDataFromObject(in, chunk,  							      localBuffer); -#ifdef CONFIG_YAFFS_WINCE -				yfsd_UnlockYAFFS(TRUE); -#endif +  				memcpy(buffer, &localBuffer[start], nToCopy); -#ifdef CONFIG_YAFFS_WINCE -				yfsd_LockYAFFS(TRUE); -#endif +  				yaffs_ReleaseTempBuffer(dev, localBuffer,  							__LINE__);  			}  		} else { -#ifdef CONFIG_YAFFS_WINCE -			__u8 *localBuffer = yaffs_GetTempBuffer(dev, __LINE__); -			/* Under WinCE can't do direct transfer. Need to use a local buffer. -			 * This is because we otherwise screw up WinCE's memory mapper -			 */ -			yaffs_ReadChunkDataFromObject(in, chunk, localBuffer); - -#ifdef CONFIG_YAFFS_WINCE -			yfsd_UnlockYAFFS(TRUE); -#endif -			memcpy(buffer, localBuffer, dev->nDataBytesPerChunk); - -#ifdef CONFIG_YAFFS_WINCE -			yfsd_LockYAFFS(TRUE); -			yaffs_ReleaseTempBuffer(dev, localBuffer, __LINE__); -#endif - -#else  			/* A full chunk. Read directly into the supplied buffer. */  			yaffs_ReadChunkDataFromObject(in, chunk, buffer); -#endif +  		}  		n -= nToCopy; @@ -4704,28 +4741,37 @@ int yaffs_ReadDataFromFile(yaffs_Object * in, __u8 * buffer, loff_t offset,  	return nDone;  } -int yaffs_WriteDataToFile(yaffs_Object * in, const __u8 * buffer, loff_t offset, -			  int nBytes, int writeThrough) +int yaffs_WriteDataToFile(yaffs_Object *in, const __u8 *buffer, loff_t offset, +			int nBytes, int writeThrough)  {  	int chunk; -	int start; +	__u32 start;  	int nToCopy;  	int n = nBytes;  	int nDone = 0;  	int nToWriteBack;  	int startOfWrite = offset;  	int chunkWritten = 0; -	int nBytesRead; +	__u32 nBytesRead; +	__u32 chunkStart;  	yaffs_Device *dev;  	dev = in->myDev;  	while (n > 0 && chunkWritten >= 0) { -		//chunk = offset / dev->nDataBytesPerChunk + 1; -		//start = offset % dev->nDataBytesPerChunk; -		yaffs_AddrToChunk(dev,offset,&chunk,&start); +		/* chunk = offset / dev->nDataBytesPerChunk + 1; */ +		/* start = offset % dev->nDataBytesPerChunk; */ +		yaffs_AddrToChunk(dev, offset, &chunk, &start); + +		if (chunk * dev->nDataBytesPerChunk + start != offset || +				start >= dev->nDataBytesPerChunk) { +			T(YAFFS_TRACE_ERROR, ( +			   TSTR("AddrToChunk of offset %d gives chunk %d start %d" +			   TENDSTR), +			   (int)offset, chunk, start)); +		}  		chunk++;  		/* OK now check for the curveball where the start and end are in @@ -4740,25 +4786,32 @@ int yaffs_WriteDataToFile(yaffs_Object * in, const __u8 * buffer, loff_t offset,  			 * we need to write back as much as was there before.  			 */ -			nBytesRead = -			    in->variant.fileVariant.fileSize - -			    ((chunk - 1) * dev->nDataBytesPerChunk); +			chunkStart = ((chunk - 1) * dev->nDataBytesPerChunk); -			if (nBytesRead > dev->nDataBytesPerChunk) { +			if (chunkStart > in->variant.fileVariant.fileSize) +				nBytesRead = 0; /* Past end of file */ +			else +				nBytesRead = in->variant.fileVariant.fileSize - chunkStart; + +			if (nBytesRead > dev->nDataBytesPerChunk)  				nBytesRead = dev->nDataBytesPerChunk; -			}  			nToWriteBack =  			    (nBytesRead >  			     (start + n)) ? nBytesRead : (start + n); +			if (nToWriteBack < 0 || nToWriteBack > dev->nDataBytesPerChunk) +				YBUG(); +  		} else {  			nToCopy = dev->nDataBytesPerChunk - start;  			nToWriteBack = dev->nDataBytesPerChunk;  		} -		if (nToCopy != dev->nDataBytesPerChunk) { -			/* An incomplete start or end chunk (or maybe both start and end chunk) */ +		if (nToCopy != dev->nDataBytesPerChunk || dev->inbandTags) { +			/* An incomplete start or end chunk (or maybe both start and end chunk), +			 * or we're using inband tags, so we want to use the cache buffers. +			 */  			if (dev->nShortOpCaches > 0) {  				yaffs_ChunkCache *cache;  				/* If we can't find the data in the cache, then load the cache */ @@ -4775,10 +4828,9 @@ int yaffs_WriteDataToFile(yaffs_Object * in, const __u8 * buffer, loff_t offset,  					yaffs_ReadChunkDataFromObject(in, chunk,  								      cache->  								      data); -				} -				else if(cache && -				        !cache->dirty && -					!yaffs_CheckSpaceForAllocation(in->myDev)){ +				} else if (cache && +					!cache->dirty && +					!yaffs_CheckSpaceForAllocation(in->myDev)) {  					/* Drop the cache if it was a read cache item and  					 * no space check has been made for it.  					 */ @@ -4788,16 +4840,12 @@ int yaffs_WriteDataToFile(yaffs_Object * in, const __u8 * buffer, loff_t offset,  				if (cache) {  					yaffs_UseChunkCache(dev, cache, 1);  					cache->locked = 1; -#ifdef CONFIG_YAFFS_WINCE -					yfsd_UnlockYAFFS(TRUE); -#endif +  					memcpy(&cache->data[start], buffer,  					       nToCopy); -#ifdef CONFIG_YAFFS_WINCE -					yfsd_LockYAFFS(TRUE); -#endif +  					cache->locked = 0;  					cache->nBytes = nToWriteBack; @@ -4825,15 +4873,10 @@ int yaffs_WriteDataToFile(yaffs_Object * in, const __u8 * buffer, loff_t offset,  				yaffs_ReadChunkDataFromObject(in, chunk,  							      localBuffer); -#ifdef CONFIG_YAFFS_WINCE -				yfsd_UnlockYAFFS(TRUE); -#endif +  				memcpy(&localBuffer[start], buffer, nToCopy); -#ifdef CONFIG_YAFFS_WINCE -				yfsd_LockYAFFS(TRUE); -#endif  				chunkWritten =  				    yaffs_WriteChunkDataToObject(in, chunk,  								 localBuffer, @@ -4846,31 +4889,15 @@ int yaffs_WriteDataToFile(yaffs_Object * in, const __u8 * buffer, loff_t offset,  			}  		} else { - -#ifdef CONFIG_YAFFS_WINCE -			/* Under WinCE can't do direct transfer. Need to use a local buffer. -			 * This is because we otherwise screw up WinCE's memory mapper -			 */ -			__u8 *localBuffer = yaffs_GetTempBuffer(dev, __LINE__); -#ifdef CONFIG_YAFFS_WINCE -			yfsd_UnlockYAFFS(TRUE); -#endif -			memcpy(localBuffer, buffer, dev->nDataBytesPerChunk); -#ifdef CONFIG_YAFFS_WINCE -			yfsd_LockYAFFS(TRUE); -#endif -			chunkWritten = -			    yaffs_WriteChunkDataToObject(in, chunk, localBuffer, -							 dev->nDataBytesPerChunk, -							 0); -			yaffs_ReleaseTempBuffer(dev, localBuffer, __LINE__); -#else  			/* A full chunk. Write directly from the supplied buffer. */ + + +  			chunkWritten =  			    yaffs_WriteChunkDataToObject(in, chunk, buffer,  							 dev->nDataBytesPerChunk,  							 0); -#endif +  			/* Since we've overwritten the cached data, we better invalidate it. */  			yaffs_InvalidateChunkCache(in, chunk);  		} @@ -4886,9 +4913,8 @@ int yaffs_WriteDataToFile(yaffs_Object * in, const __u8 * buffer, loff_t offset,  	/* Update file object */ -	if ((startOfWrite + nDone) > in->variant.fileVariant.fileSize) { +	if ((startOfWrite + nDone) > in->variant.fileVariant.fileSize)  		in->variant.fileVariant.fileSize = (startOfWrite + nDone); -	}  	in->dirty = 1; @@ -4898,7 +4924,7 @@ int yaffs_WriteDataToFile(yaffs_Object * in, const __u8 * buffer, loff_t offset,  /* ---------------------- File resizing stuff ------------------ */ -static void yaffs_PruneResizedChunks(yaffs_Object * in, int newSize) +static void yaffs_PruneResizedChunks(yaffs_Object *in, int newSize)  {  	yaffs_Device *dev = in->myDev; @@ -4939,11 +4965,11 @@ static void yaffs_PruneResizedChunks(yaffs_Object * in, int newSize)  } -int yaffs_ResizeFile(yaffs_Object * in, loff_t newSize) +int yaffs_ResizeFile(yaffs_Object *in, loff_t newSize)  {  	int oldFileSize = in->variant.fileVariant.fileSize; -	int newSizeOfPartialChunk; +	__u32 newSizeOfPartialChunk;  	int newFullChunks;  	yaffs_Device *dev = in->myDev; @@ -4955,13 +4981,11 @@ int yaffs_ResizeFile(yaffs_Object * in, loff_t newSize)  	yaffs_CheckGarbageCollection(dev); -	if (in->variantType != YAFFS_OBJECT_TYPE_FILE) { -		return yaffs_GetFileSize(in); -	} +	if (in->variantType != YAFFS_OBJECT_TYPE_FILE) +		return YAFFS_FAIL; -	if (newSize == oldFileSize) { -		return oldFileSize; -	} +	if (newSize == oldFileSize) +		return YAFFS_OK;  	if (newSize < oldFileSize) { @@ -4994,21 +5018,20 @@ int yaffs_ResizeFile(yaffs_Object * in, loff_t newSize)  	} -  	/* Write a new object header.  	 * show we've shrunk the file, if need be  	 * Do this only if the file is not in the deleted directories.  	 */ -	if (in->parent->objectId != YAFFS_OBJECTID_UNLINKED && -	    in->parent->objectId != YAFFS_OBJECTID_DELETED) { +	if (in->parent && +	    in->parent->objectId != YAFFS_OBJECTID_UNLINKED && +	    in->parent->objectId != YAFFS_OBJECTID_DELETED)  		yaffs_UpdateObjectHeader(in, NULL, 0,  					 (newSize < oldFileSize) ? 1 : 0, 0); -	} -	return newSize; +	return YAFFS_OK;  } -loff_t yaffs_GetFileSize(yaffs_Object * obj) +loff_t yaffs_GetFileSize(yaffs_Object *obj)  {  	obj = yaffs_GetEquivalentObject(obj); @@ -5024,7 +5047,7 @@ loff_t yaffs_GetFileSize(yaffs_Object * obj) -int yaffs_FlushFile(yaffs_Object * in, int updateTime) +int yaffs_FlushFile(yaffs_Object *in, int updateTime)  {  	int retVal;  	if (in->dirty) { @@ -5039,9 +5062,8 @@ int yaffs_FlushFile(yaffs_Object * in, int updateTime)  #endif  		} -		retVal = -		    (yaffs_UpdateObjectHeader(in, NULL, 0, 0, 0) >= -		     0) ? YAFFS_OK : YAFFS_FAIL; +		retVal = (yaffs_UpdateObjectHeader(in, NULL, 0, 0, 0) >= +			0) ? YAFFS_OK : YAFFS_FAIL;  	} else {  		retVal = YAFFS_OK;  	} @@ -5050,7 +5072,7 @@ int yaffs_FlushFile(yaffs_Object * in, int updateTime)  } -static int yaffs_DoGenericObjectDeletion(yaffs_Object * in) +static int yaffs_DoGenericObjectDeletion(yaffs_Object *in)  {  	/* First off, invalidate the file's data in the cache, without flushing. */ @@ -5058,13 +5080,13 @@ static int yaffs_DoGenericObjectDeletion(yaffs_Object * in)  	if (in->myDev->isYaffs2 && (in->parent != in->myDev->deletedDir)) {  		/* Move to the unlinked directory so we have a record that it was deleted. */ -		yaffs_ChangeObjectName(in, in->myDev->deletedDir,"deleted", 0, 0); +		yaffs_ChangeObjectName(in, in->myDev->deletedDir, _Y("deleted"), 0, 0);  	}  	yaffs_RemoveObjectFromDirectory(in); -	yaffs_DeleteChunk(in->myDev, in->chunkId, 1, __LINE__); -	in->chunkId = -1; +	yaffs_DeleteChunk(in->myDev, in->hdrChunk, 1, __LINE__); +	in->hdrChunk = 0;  	yaffs_FreeObject(in);  	return YAFFS_OK; @@ -5075,62 +5097,63 @@ static int yaffs_DoGenericObjectDeletion(yaffs_Object * in)   * and the inode associated with the file.   * It does not delete the links associated with the file.   */ -static int yaffs_UnlinkFile(yaffs_Object * in) +static int yaffs_UnlinkFileIfNeeded(yaffs_Object *in)  {  	int retVal;  	int immediateDeletion = 0; -	if (1) {  #ifdef __KERNEL__ -		if (!in->myInode) { -			immediateDeletion = 1; - -		} +	if (!in->myInode) +		immediateDeletion = 1;  #else -		if (in->inUse <= 0) { -			immediateDeletion = 1; - -		} +	if (in->inUse <= 0) +		immediateDeletion = 1;  #endif -		if (immediateDeletion) { -			retVal = -			    yaffs_ChangeObjectName(in, in->myDev->deletedDir, -						   "deleted", 0, 0); -			T(YAFFS_TRACE_TRACING, -			  (TSTR("yaffs: immediate deletion of file %d" TENDSTR), -			   in->objectId)); -			in->deleted = 1; -			in->myDev->nDeletedFiles++; -			if (0 && in->myDev->isYaffs2) { -				yaffs_ResizeFile(in, 0); -			} -			yaffs_SoftDeleteFile(in); -		} else { -			retVal = -			    yaffs_ChangeObjectName(in, in->myDev->unlinkedDir, -						   "unlinked", 0, 0); -		} +	if (immediateDeletion) { +		retVal = +		    yaffs_ChangeObjectName(in, in->myDev->deletedDir, +					   _Y("deleted"), 0, 0); +		T(YAFFS_TRACE_TRACING, +		  (TSTR("yaffs: immediate deletion of file %d" TENDSTR), +		   in->objectId)); +		in->deleted = 1; +		in->myDev->nDeletedFiles++; +		if (1 || in->myDev->isYaffs2) +			yaffs_ResizeFile(in, 0); +		yaffs_SoftDeleteFile(in); +	} else { +		retVal = +		    yaffs_ChangeObjectName(in, in->myDev->unlinkedDir, +					   _Y("unlinked"), 0, 0);  	} + +  	return retVal;  } -int yaffs_DeleteFile(yaffs_Object * in) +int yaffs_DeleteFile(yaffs_Object *in)  {  	int retVal = YAFFS_OK; +	int deleted = in->deleted; + +	yaffs_ResizeFile(in, 0);  	if (in->nDataChunks > 0) { -		/* Use soft deletion if there is data in the file */ -		if (!in->unlinked) { -			retVal = yaffs_UnlinkFile(in); -		} +		/* Use soft deletion if there is data in the file. +		 * That won't be the case if it has been resized to zero. +		 */ +		if (!in->unlinked) +			retVal = yaffs_UnlinkFileIfNeeded(in); +  		if (retVal == YAFFS_OK && in->unlinked && !in->deleted) {  			in->deleted = 1; +			deleted = 1;  			in->myDev->nDeletedFiles++;  			yaffs_SoftDeleteFile(in);  		} -		return in->deleted ? YAFFS_OK : YAFFS_FAIL; +		return deleted ? YAFFS_OK : YAFFS_FAIL;  	} else {  		/* The file has no data chunks so we toss it immediately */  		yaffs_FreeTnode(in->myDev, in->variant.fileVariant.top); @@ -5141,62 +5164,75 @@ int yaffs_DeleteFile(yaffs_Object * in)  	}  } -static int yaffs_DeleteDirectory(yaffs_Object * in) +static int yaffs_DeleteDirectory(yaffs_Object *in)  {  	/* First check that the directory is empty. */ -	if (list_empty(&in->variant.directoryVariant.children)) { +	if (ylist_empty(&in->variant.directoryVariant.children))  		return yaffs_DoGenericObjectDeletion(in); -	}  	return YAFFS_FAIL;  } -static int yaffs_DeleteSymLink(yaffs_Object * in) +static int yaffs_DeleteSymLink(yaffs_Object *in)  {  	YFREE(in->variant.symLinkVariant.alias);  	return yaffs_DoGenericObjectDeletion(in);  } -static int yaffs_DeleteHardLink(yaffs_Object * in) +static int yaffs_DeleteHardLink(yaffs_Object *in)  {  	/* remove this hardlink from the list assocaited with the equivalent  	 * object  	 */ -	list_del(&in->hardLinks); +	ylist_del_init(&in->hardLinks);  	return yaffs_DoGenericObjectDeletion(in);  } -static void yaffs_DestroyObject(yaffs_Object * obj) +int yaffs_DeleteObject(yaffs_Object *obj)  { +int retVal = -1;  	switch (obj->variantType) {  	case YAFFS_OBJECT_TYPE_FILE: -		yaffs_DeleteFile(obj); +		retVal = yaffs_DeleteFile(obj);  		break;  	case YAFFS_OBJECT_TYPE_DIRECTORY: -		yaffs_DeleteDirectory(obj); +		return yaffs_DeleteDirectory(obj);  		break;  	case YAFFS_OBJECT_TYPE_SYMLINK: -		yaffs_DeleteSymLink(obj); +		retVal = yaffs_DeleteSymLink(obj);  		break;  	case YAFFS_OBJECT_TYPE_HARDLINK: -		yaffs_DeleteHardLink(obj); +		retVal = yaffs_DeleteHardLink(obj);  		break;  	case YAFFS_OBJECT_TYPE_SPECIAL: -		yaffs_DoGenericObjectDeletion(obj); +		retVal = yaffs_DoGenericObjectDeletion(obj);  		break;  	case YAFFS_OBJECT_TYPE_UNKNOWN: +		retVal = 0;  		break;		/* should not happen. */  	} + +	return retVal;  } -static int yaffs_UnlinkWorker(yaffs_Object * obj) +static int yaffs_UnlinkWorker(yaffs_Object *obj)  { +	int immediateDeletion = 0; + +#ifdef __KERNEL__ +	if (!obj->myInode) +		immediateDeletion = 1; +#else +	if (obj->inUse <= 0) +		immediateDeletion = 1; +#endif +  	if (obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) {  		return yaffs_DeleteHardLink(obj); -	} else if (!list_empty(&obj->hardLinks)) { +	} else if (!ylist_empty(&obj->hardLinks)) {  		/* Curve ball: We're unlinking an object that has a hardlink.  		 *  		 * This problem arises because we are not strictly following @@ -5215,24 +5251,24 @@ static int yaffs_UnlinkWorker(yaffs_Object * obj)  		int retVal;  		YCHAR name[YAFFS_MAX_NAME_LENGTH + 1]; -		hl = list_entry(obj->hardLinks.next, yaffs_Object, hardLinks); +		hl = ylist_entry(obj->hardLinks.next, yaffs_Object, hardLinks); -		list_del_init(&hl->hardLinks); -		list_del_init(&hl->siblings); +		ylist_del_init(&hl->hardLinks); +		ylist_del_init(&hl->siblings);  		yaffs_GetObjectName(hl, name, YAFFS_MAX_NAME_LENGTH + 1);  		retVal = yaffs_ChangeObjectName(obj, hl->parent, name, 0, 0); -		if (retVal == YAFFS_OK) { +		if (retVal == YAFFS_OK)  			retVal = yaffs_DoGenericObjectDeletion(hl); -		} +  		return retVal; -	} else { +	} else if (immediateDeletion) {  		switch (obj->variantType) {  		case YAFFS_OBJECT_TYPE_FILE: -			return yaffs_UnlinkFile(obj); +			return yaffs_DeleteFile(obj);  			break;  		case YAFFS_OBJECT_TYPE_DIRECTORY:  			return yaffs_DeleteDirectory(obj); @@ -5248,21 +5284,22 @@ static int yaffs_UnlinkWorker(yaffs_Object * obj)  		default:  			return YAFFS_FAIL;  		} -	} +	} else +		return yaffs_ChangeObjectName(obj, obj->myDev->unlinkedDir, +					   _Y("unlinked"), 0, 0);  } -static int yaffs_UnlinkObject( yaffs_Object *obj) +static int yaffs_UnlinkObject(yaffs_Object *obj)  { -	if (obj && obj->unlinkAllowed) { +	if (obj && obj->unlinkAllowed)  		return yaffs_UnlinkWorker(obj); -	}  	return YAFFS_FAIL;  } -int yaffs_Unlink(yaffs_Object * dir, const YCHAR * name) +int yaffs_Unlink(yaffs_Object *dir, const YCHAR *name)  {  	yaffs_Object *obj; @@ -5272,8 +5309,8 @@ int yaffs_Unlink(yaffs_Object * dir, const YCHAR * name)  /*----------------------- Initialisation Scanning ---------------------- */ -static void yaffs_HandleShadowedObject(yaffs_Device * dev, int objId, -				       int backwardScanning) +static void yaffs_HandleShadowedObject(yaffs_Device *dev, int objId, +				int backwardScanning)  {  	yaffs_Object *obj; @@ -5286,9 +5323,8 @@ static void yaffs_HandleShadowedObject(yaffs_Device * dev, int objId,  		/* Handle YAFFS2 case (backward scanning)  		 * If the shadowed object exists then ignore.  		 */ -		if (yaffs_FindObjectByNumber(dev, objId)) { +		if (yaffs_FindObjectByNumber(dev, objId))  			return; -		}  	}  	/* Let's create it (if it does not exist) assuming it is a file so that it can do shrinking etc. @@ -5297,6 +5333,8 @@ static void yaffs_HandleShadowedObject(yaffs_Device * dev, int objId,  	obj =  	    yaffs_FindOrCreateObjectByNumber(dev, objId,  					     YAFFS_OBJECT_TYPE_FILE); +	if (!obj) +		return;  	yaffs_AddObjectToDirectory(dev->unlinkedDir, obj);  	obj->variant.fileVariant.shrinkSize = 0;  	obj->valid = 1;		/* So that we don't read any other info for this file */ @@ -5325,44 +5363,77 @@ static void yaffs_HardlinkFixup(yaffs_Device *dev, yaffs_Object *hardList)  		if (in) {  			/* Add the hardlink pointers */  			hl->variant.hardLinkVariant.equivalentObject = in; -			list_add(&hl->hardLinks, &in->hardLinks); +			ylist_add(&hl->hardLinks, &in->hardLinks);  		} else {  			/* Todo Need to report/handle this better.  			 * Got a problem... hardlink to a non-existant object  			 */  			hl->variant.hardLinkVariant.equivalentObject = NULL; -			INIT_LIST_HEAD(&hl->hardLinks); +			YINIT_LIST_HEAD(&hl->hardLinks);  		} -  	} +} + + + + +static int ybicmp(const void *a, const void *b) +{ +	register int aseq = ((yaffs_BlockIndex *)a)->seq; +	register int bseq = ((yaffs_BlockIndex *)b)->seq; +	register int ablock = ((yaffs_BlockIndex *)a)->block; +	register int bblock = ((yaffs_BlockIndex *)b)->block; +	if (aseq == bseq) +		return ablock - bblock; +	else +		return aseq - bseq;  } +struct yaffs_ShadowFixerStruct { +	int objectId; +	int shadowedId; +	struct yaffs_ShadowFixerStruct *next; +}; + +static void yaffs_StripDeletedObjects(yaffs_Device *dev) +{ +	/* +	*  Sort out state of unlinked and deleted objects after scanning. +	*/ +	struct ylist_head *i; +	struct ylist_head *n; +	yaffs_Object *l; +	/* Soft delete all the unlinked files */ +	ylist_for_each_safe(i, n, +		&dev->unlinkedDir->variant.directoryVariant.children) { +		if (i) { +			l = ylist_entry(i, yaffs_Object, siblings); +			yaffs_DeleteObject(l); +		} +	} -static int ybicmp(const void *a, const void *b){ -    register int aseq = ((yaffs_BlockIndex *)a)->seq; -    register int bseq = ((yaffs_BlockIndex *)b)->seq; -    register int ablock = ((yaffs_BlockIndex *)a)->block; -    register int bblock = ((yaffs_BlockIndex *)b)->block; -    if( aseq == bseq ) -        return ablock - bblock; -    else -        return aseq - bseq; +	ylist_for_each_safe(i, n, +		&dev->deletedDir->variant.directoryVariant.children) { +		if (i) { +			l = ylist_entry(i, yaffs_Object, siblings); +			yaffs_DeleteObject(l); +		} +	}  } -static int yaffs_Scan(yaffs_Device * dev) +static int yaffs_Scan(yaffs_Device *dev)  {  	yaffs_ExtendedTags tags;  	int blk;  	int blockIterator;  	int startIterator;  	int endIterator; -	int nBlocksToScan = 0;  	int result;  	int chunk; @@ -5371,26 +5442,19 @@ static int yaffs_Scan(yaffs_Device * dev)  	yaffs_BlockState state;  	yaffs_Object *hardList = NULL;  	yaffs_BlockInfo *bi; -	int sequenceNumber; +	__u32 sequenceNumber;  	yaffs_ObjectHeader *oh;  	yaffs_Object *in;  	yaffs_Object *parent; -	int nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1;  	int alloc_failed = 0; +	struct yaffs_ShadowFixerStruct *shadowFixerList = NULL; -	__u8 *chunkData; -	yaffs_BlockIndex *blockIndex = NULL; +	__u8 *chunkData; -	if (dev->isYaffs2) { -		T(YAFFS_TRACE_SCAN, -		  (TSTR("yaffs_Scan is not for YAFFS2!" TENDSTR))); -		return YAFFS_FAIL; -	} -	//TODO  Throw all the yaffs2 stuuf out of yaffs_Scan since it is only for yaffs1 format.  	T(YAFFS_TRACE_SCAN,  	  (TSTR("yaffs_Scan starts  intstartblk %d intendblk %d..." TENDSTR), @@ -5400,12 +5464,6 @@ static int yaffs_Scan(yaffs_Device * dev)  	dev->sequenceNumber = YAFFS_LOWEST_SEQUENCE_NUMBER; -	if (dev->isYaffs2) { -		blockIndex = YMALLOC(nBlocks * sizeof(yaffs_BlockIndex)); -		if(!blockIndex) -			return YAFFS_FAIL; -	} -  	/* Scan all the blocks to determine their state */  	for (blk = dev->internalStartBlock; blk <= dev->internalEndBlock; blk++) {  		bi = yaffs_GetBlockInfo(dev, blk); @@ -5418,6 +5476,9 @@ static int yaffs_Scan(yaffs_Device * dev)  		bi->blockState = state;  		bi->sequenceNumber = sequenceNumber; +		if (bi->sequenceNumber == YAFFS_SEQUENCE_BAD_BLOCK) +			bi->blockState = state = YAFFS_BLOCK_STATE_DEAD; +  		T(YAFFS_TRACE_SCAN_DEBUG,  		  (TSTR("Block scanning block %d state %d seq %d" TENDSTR), blk,  		   state, sequenceNumber)); @@ -5430,70 +5491,21 @@ static int yaffs_Scan(yaffs_Device * dev)  			  (TSTR("Block empty " TENDSTR)));  			dev->nErasedBlocks++;  			dev->nFreeChunks += dev->nChunksPerBlock; -		} else if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) { - -			/* Determine the highest sequence number */ -			if (dev->isYaffs2 && -			    sequenceNumber >= YAFFS_LOWEST_SEQUENCE_NUMBER && -			    sequenceNumber < YAFFS_HIGHEST_SEQUENCE_NUMBER) { - -				blockIndex[nBlocksToScan].seq = sequenceNumber; -				blockIndex[nBlocksToScan].block = blk; - -				nBlocksToScan++; - -				if (sequenceNumber >= dev->sequenceNumber) { -					dev->sequenceNumber = sequenceNumber; -				} -			} else if (dev->isYaffs2) { -				/* TODO: Nasty sequence number! */ -				T(YAFFS_TRACE_SCAN, -				  (TSTR -				   ("Block scanning block %d has bad sequence number %d" -				    TENDSTR), blk, sequenceNumber)); - -			}  		}  	} -	/* Sort the blocks -	 * Dungy old bubble sort for now... -	 */ -	if (dev->isYaffs2) { -		yaffs_BlockIndex temp; -		int i; -		int j; - -		for (i = 0; i < nBlocksToScan; i++) -			for (j = i + 1; j < nBlocksToScan; j++) -				if (blockIndex[i].seq > blockIndex[j].seq) { -					temp = blockIndex[j]; -					blockIndex[j] = blockIndex[i]; -					blockIndex[i] = temp; -				} -	} - -	/* Now scan the blocks looking at the data. */ -	if (dev->isYaffs2) { -		startIterator = 0; -		endIterator = nBlocksToScan - 1; -		T(YAFFS_TRACE_SCAN_DEBUG, -		  (TSTR("%d blocks to be scanned" TENDSTR), nBlocksToScan)); -	} else { -		startIterator = dev->internalStartBlock; -		endIterator = dev->internalEndBlock; -	} +	startIterator = dev->internalStartBlock; +	endIterator = dev->internalEndBlock;  	/* For each block.... */  	for (blockIterator = startIterator; !alloc_failed && blockIterator <= endIterator;  	     blockIterator++) { -		if (dev->isYaffs2) { -			/* get the block to scan in the correct order */ -			blk = blockIndex[blockIterator].block; -		} else { -			blk = blockIterator; -		} +		YYIELD(); + +		YYIELD(); + +		blk = blockIterator;  		bi = yaffs_GetBlockInfo(dev, blk);  		state = bi->blockState; @@ -5511,7 +5523,7 @@ static int yaffs_Scan(yaffs_Device * dev)  			/* Let's have a good look at this chunk... */ -			if (!dev->isYaffs2 && tags.chunkDeleted) { +			if (tags.eccResult == YAFFS_ECC_RESULT_UNFIXED || tags.chunkDeleted) {  				/* YAFFS1 only...  				 * A deleted chunk  				 */ @@ -5540,18 +5552,6 @@ static int yaffs_Scan(yaffs_Device * dev)  					dev->allocationBlockFinder = blk;  					/* Set it to here to encourage the allocator to go forth from here. */ -					/* Yaffs2 sanity check: -					 * This should be the one with the highest sequence number -					 */ -					if (dev->isYaffs2 -					    && (dev->sequenceNumber != -						bi->sequenceNumber)) { -						T(YAFFS_TRACE_ALWAYS, -						  (TSTR -						   ("yaffs: Allocation block %d was not highest sequence id:" -						    " block seq = %d, dev seq = %d" -						    TENDSTR), blk,bi->sequenceNumber,dev->sequenceNumber)); -					}  				}  				dev->nFreeChunks += (dev->nChunksPerBlock - c); @@ -5570,11 +5570,11 @@ static int yaffs_Scan(yaffs_Device * dev)  				 * the same chunkId).  				 */ -				if(!in) +				if (!in)  					alloc_failed = 1; -				if(in){ -					if(!yaffs_PutChunkIntoFile(in, tags.chunkId, chunk,1)) +				if (in) { +					if (!yaffs_PutChunkIntoFile(in, tags.chunkId, chunk, 1))  						alloc_failed = 1;  				} @@ -5617,7 +5617,7 @@ static int yaffs_Scan(yaffs_Device * dev)  					 * deleted, and worse still it has changed type. Delete the old object.  					 */ -					yaffs_DestroyObject(in); +					yaffs_DeleteObject(in);  					in = 0;  				} @@ -5627,14 +5627,20 @@ static int yaffs_Scan(yaffs_Device * dev)  								      objectId,  								      oh->type); -				if(!in) +				if (!in)  					alloc_failed = 1;  				if (in && oh->shadowsObject > 0) { -					yaffs_HandleShadowedObject(dev, -								   oh-> -								   shadowsObject, -								   0); + +					struct yaffs_ShadowFixerStruct *fixer; +					fixer = YMALLOC(sizeof(struct yaffs_ShadowFixerStruct)); +					if (fixer) { +						fixer->next = shadowFixerList; +						shadowFixerList = fixer; +						fixer->objectId = tags.objectId; +						fixer->shadowedId = oh->shadowsObject; +					} +  				}  				if (in && in->valid) { @@ -5643,12 +5649,10 @@ static int yaffs_Scan(yaffs_Device * dev)  					unsigned existingSerial = in->serial;  					unsigned newSerial = tags.serialNumber; -					if (dev->isYaffs2 || -					    ((existingSerial + 1) & 3) == -					    newSerial) { +					if (((existingSerial + 1) & 3) == newSerial) {  						/* Use new one - destroy the exisiting one */  						yaffs_DeleteChunk(dev, -								  in->chunkId, +								  in->hdrChunk,  								  1, __LINE__);  						in->valid = 0;  					} else { @@ -5681,7 +5685,8 @@ static int yaffs_Scan(yaffs_Device * dev)  					in->yst_ctime = oh->yst_ctime;  					in->yst_rdev = oh->yst_rdev;  #endif -					in->chunkId = chunk; +					in->hdrChunk = chunk; +					in->serial = tags.serialNumber;  				} else if (in && !in->valid) {  					/* we need to load this info */ @@ -5705,7 +5710,8 @@ static int yaffs_Scan(yaffs_Device * dev)  					in->yst_ctime = oh->yst_ctime;  					in->yst_rdev = oh->yst_rdev;  #endif -					in->chunkId = chunk; +					in->hdrChunk = chunk; +					in->serial = tags.serialNumber;  					yaffs_SetObjectName(in, oh->name);  					in->dirty = 0; @@ -5718,25 +5724,25 @@ static int yaffs_Scan(yaffs_Device * dev)  					    yaffs_FindOrCreateObjectByNumber  					    (dev, oh->parentObjectId,  					     YAFFS_OBJECT_TYPE_DIRECTORY); -					if (parent->variantType == +					if (!parent) +						alloc_failed = 1; +					if (parent && parent->variantType ==  					    YAFFS_OBJECT_TYPE_UNKNOWN) {  						/* Set up as a directory */  						parent->variantType = -						    YAFFS_OBJECT_TYPE_DIRECTORY; -						INIT_LIST_HEAD(&parent->variant. -							       directoryVariant. -							       children); -					} else if (parent->variantType != -						   YAFFS_OBJECT_TYPE_DIRECTORY) -					{ +							YAFFS_OBJECT_TYPE_DIRECTORY; +						YINIT_LIST_HEAD(&parent->variant. +								directoryVariant. +								children); +					} else if (!parent || parent->variantType != +						   YAFFS_OBJECT_TYPE_DIRECTORY) {  						/* Hoosterman, another problem....  						 * We're trying to use a non-directory as a directory  						 */  						T(YAFFS_TRACE_ERROR,  						  (TSTR -						   ("yaffs tragedy: attempting to use non-directory as" -						    " a directory in scan. Put in lost+found." +						   ("yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found."  						    TENDSTR)));  						parent = dev->lostNFoundDir;  					} @@ -5760,15 +5766,6 @@ static int yaffs_Scan(yaffs_Device * dev)  						/* Todo got a problem */  						break;  					case YAFFS_OBJECT_TYPE_FILE: -						if (dev->isYaffs2 -						    && oh->isShrink) { -							/* Prune back the shrunken chunks */ -							yaffs_PruneResizedChunks -							    (in, oh->fileSize); -							/* Mark the block as having a shrinkHeader */ -							bi->hasShrinkHeader = 1; -						} -  						if (dev->useHeaderFileSize)  							in->variant.fileVariant. @@ -5778,11 +5775,11 @@ static int yaffs_Scan(yaffs_Device * dev)  						break;  					case YAFFS_OBJECT_TYPE_HARDLINK:  						in->variant.hardLinkVariant. -						    equivalentObjectId = -						    oh->equivalentObjectId; +							equivalentObjectId = +							oh->equivalentObjectId;  						in->hardLinks.next = -						    (struct list_head *) -						    hardList; +							(struct ylist_head *) +							hardList;  						hardList = in;  						break;  					case YAFFS_OBJECT_TYPE_DIRECTORY: @@ -5794,15 +5791,17 @@ static int yaffs_Scan(yaffs_Device * dev)  					case YAFFS_OBJECT_TYPE_SYMLINK:  						in->variant.symLinkVariant.alias =  						    yaffs_CloneString(oh->alias); -						if(!in->variant.symLinkVariant.alias) +						if (!in->variant.symLinkVariant.alias)  							alloc_failed = 1;  						break;  					} +/*  					if (parent == dev->deletedDir) {  						yaffs_DestroyObject(in);  						bi->hasShrinkHeader = 1;  					} +*/  				}  			}  		} @@ -5823,10 +5822,6 @@ static int yaffs_Scan(yaffs_Device * dev)  	} -	if (blockIndex) { -		YFREE(blockIndex); -	} -  	/* Ok, we've done all the scanning.  	 * Fix up the hard link chains. @@ -5834,32 +5829,36 @@ static int yaffs_Scan(yaffs_Device * dev)  	 * hardlinks.  	 */ -	yaffs_HardlinkFixup(dev,hardList); +	yaffs_HardlinkFixup(dev, hardList); -	/* Handle the unlinked files. Since they were left in an unlinked state we should -	 * just delete them. -	 */ +	/* Fix up any shadowed objects */  	{ -		struct list_head *i; -		struct list_head *n; - -		yaffs_Object *l; -		/* Soft delete all the unlinked files */ -		list_for_each_safe(i, n, -				   &dev->unlinkedDir->variant.directoryVariant. -				   children) { -			if (i) { -				l = list_entry(i, yaffs_Object, siblings); -				yaffs_DestroyObject(l); -			} +		struct yaffs_ShadowFixerStruct *fixer; +		yaffs_Object *obj; + +		while (shadowFixerList) { +			fixer = shadowFixerList; +			shadowFixerList = fixer->next; +			/* Complete the rename transaction by deleting the shadowed object +			 * then setting the object header to unshadowed. +			 */ +			obj = yaffs_FindObjectByNumber(dev, fixer->shadowedId); +			if (obj) +				yaffs_DeleteObject(obj); + +			obj = yaffs_FindObjectByNumber(dev, fixer->objectId); + +			if (obj) +				yaffs_UpdateObjectHeader(obj, NULL, 1, 0, 0); + +			YFREE(fixer);  		}  	}  	yaffs_ReleaseTempBuffer(dev, chunkData, __LINE__); -	if(alloc_failed){ +	if (alloc_failed)  		return YAFFS_FAIL; -	}  	T(YAFFS_TRACE_SCAN, (TSTR("yaffs_Scan ends" TENDSTR))); @@ -5871,25 +5870,27 @@ static void yaffs_CheckObjectDetailsLoaded(yaffs_Object *in)  {  	__u8 *chunkData;  	yaffs_ObjectHeader *oh; -	yaffs_Device *dev = in->myDev; +	yaffs_Device *dev;  	yaffs_ExtendedTags tags;  	int result;  	int alloc_failed = 0; -	if(!in) +	if (!in)  		return; +	dev = in->myDev; +  #if 0 -	T(YAFFS_TRACE_SCAN,(TSTR("details for object %d %s loaded" TENDSTR), +	T(YAFFS_TRACE_SCAN, (TSTR("details for object %d %s loaded" TENDSTR),  		in->objectId,  		in->lazyLoaded ? "not yet" : "already"));  #endif -	if(in->lazyLoaded){ +	if (in->lazyLoaded && in->hdrChunk > 0) {  		in->lazyLoaded = 0;  		chunkData = yaffs_GetTempBuffer(dev, __LINE__); -		result = yaffs_ReadChunkWithTagsFromNAND(dev,in->chunkId,chunkData,&tags); +		result = yaffs_ReadChunkWithTagsFromNAND(dev, in->hdrChunk, chunkData, &tags);  		oh = (yaffs_ObjectHeader *) chunkData;  		in->yst_mode = oh->yst_mode; @@ -5911,18 +5912,18 @@ static void yaffs_CheckObjectDetailsLoaded(yaffs_Object *in)  #endif  		yaffs_SetObjectName(in, oh->name); -		if(in->variantType == YAFFS_OBJECT_TYPE_SYMLINK){ -			 in->variant.symLinkVariant.alias = +		if (in->variantType == YAFFS_OBJECT_TYPE_SYMLINK) { +			in->variant.symLinkVariant.alias =  						    yaffs_CloneString(oh->alias); -			if(!in->variant.symLinkVariant.alias) +			if (!in->variant.symLinkVariant.alias)  				alloc_failed = 1; /* Not returned to caller */  		} -		yaffs_ReleaseTempBuffer(dev,chunkData, __LINE__); +		yaffs_ReleaseTempBuffer(dev, chunkData, __LINE__);  	}  } -static int yaffs_ScanBackwards(yaffs_Device * dev) +static int yaffs_ScanBackwards(yaffs_Device *dev)  {  	yaffs_ExtendedTags tags;  	int blk; @@ -5938,7 +5939,7 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)  	yaffs_BlockState state;  	yaffs_Object *hardList = NULL;  	yaffs_BlockInfo *bi; -	int sequenceNumber; +	__u32 sequenceNumber;  	yaffs_ObjectHeader *oh;  	yaffs_Object *in;  	yaffs_Object *parent; @@ -5972,12 +5973,12 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)  	blockIndex = YMALLOC(nBlocks * sizeof(yaffs_BlockIndex)); -	if(!blockIndex) { +	if (!blockIndex) {  		blockIndex = YMALLOC_ALT(nBlocks * sizeof(yaffs_BlockIndex));  		altBlockIndex = 1;  	} -	if(!blockIndex) { +	if (!blockIndex) {  		T(YAFFS_TRACE_SCAN,  		  (TSTR("yaffs_Scan() could not allocate block index!" TENDSTR)));  		return YAFFS_FAIL; @@ -5999,15 +6000,17 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)  		bi->blockState = state;  		bi->sequenceNumber = sequenceNumber; -		if(bi->sequenceNumber == YAFFS_SEQUENCE_CHECKPOINT_DATA) +		if (bi->sequenceNumber == YAFFS_SEQUENCE_CHECKPOINT_DATA)  			bi->blockState = state = YAFFS_BLOCK_STATE_CHECKPOINT; +		if (bi->sequenceNumber == YAFFS_SEQUENCE_BAD_BLOCK) +			bi->blockState = state = YAFFS_BLOCK_STATE_DEAD;  		T(YAFFS_TRACE_SCAN_DEBUG,  		  (TSTR("Block scanning block %d state %d seq %d" TENDSTR), blk,  		   state, sequenceNumber)); -		if(state == YAFFS_BLOCK_STATE_CHECKPOINT){ +		if (state == YAFFS_BLOCK_STATE_CHECKPOINT) {  			dev->blocksInCheckpoint++;  		} else if (state == YAFFS_BLOCK_STATE_DEAD) { @@ -6021,8 +6024,7 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)  		} else if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) {  			/* Determine the highest sequence number */ -			if (dev->isYaffs2 && -			    sequenceNumber >= YAFFS_LOWEST_SEQUENCE_NUMBER && +			if (sequenceNumber >= YAFFS_LOWEST_SEQUENCE_NUMBER &&  			    sequenceNumber < YAFFS_HIGHEST_SEQUENCE_NUMBER) {  				blockIndex[nBlocksToScan].seq = sequenceNumber; @@ -6030,10 +6032,9 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)  				nBlocksToScan++; -				if (sequenceNumber >= dev->sequenceNumber) { +				if (sequenceNumber >= dev->sequenceNumber)  					dev->sequenceNumber = sequenceNumber; -				} -			} else if (dev->isYaffs2) { +			} else {  				/* TODO: Nasty sequence number! */  				T(YAFFS_TRACE_SCAN,  				  (TSTR @@ -6053,11 +6054,13 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)  	/* Sort the blocks */  #ifndef CONFIG_YAFFS_USE_OWN_SORT -	yaffs_qsort(blockIndex, nBlocksToScan, -		sizeof(yaffs_BlockIndex), ybicmp); +	{ +		/* Use qsort now. */ +		yaffs_qsort(blockIndex, nBlocksToScan, sizeof(yaffs_BlockIndex), ybicmp); +	}  #else  	{ -	 	/* Dungy old bubble sort... */ +		/* Dungy old bubble sort... */  		yaffs_BlockIndex temp;  		int i; @@ -6075,7 +6078,7 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)  	YYIELD(); -    	T(YAFFS_TRACE_SCAN, (TSTR("...done" TENDSTR))); +	T(YAFFS_TRACE_SCAN, (TSTR("...done" TENDSTR)));  	/* Now scan the blocks looking at the data. */  	startIterator = 0; @@ -6085,10 +6088,10 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)  	/* For each block.... backwards */  	for (blockIterator = endIterator; !alloc_failed && blockIterator >= startIterator; -	     blockIterator--) { -	        /* Cooperative multitasking! This loop can run for so +			blockIterator--) { +		/* Cooperative multitasking! This loop can run for so  		   long that watchdog timers expire. */ -	        YYIELD(); +		YYIELD();  		/* get the block to scan in the correct order */  		blk = blockIndex[blockIterator].block; @@ -6127,10 +6130,8 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)  				 * this is the one being allocated from  				 */ -				if(foundChunksInBlock) -				{ +				if (foundChunksInBlock) {  					/* This is a chunk that was skipped due to failing the erased check */ -  				} else if (c == 0) {  					/* We're looking at the first chunk in the block so the block is unused */  					state = YAFFS_BLOCK_STATE_EMPTY; @@ -6138,7 +6139,7 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)  				} else {  					if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING ||  					    state == YAFFS_BLOCK_STATE_ALLOCATING) { -					    	if(dev->sequenceNumber == bi->sequenceNumber) { +						if (dev->sequenceNumber == bi->sequenceNumber) {  							/* this is the block being allocated from */  							T(YAFFS_TRACE_SCAN, @@ -6150,27 +6151,31 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)  							dev->allocationBlock = blk;  							dev->allocationPage = c;  							dev->allocationBlockFinder = blk; -						} -						else { +						} else {  							/* This is a partially written block that is not  							 * the current allocation block. This block must have  							 * had a write failure, so set up for retirement.  							 */ -							 bi->needsRetiring = 1; +							 /* bi->needsRetiring = 1; ??? TODO */  							 bi->gcPrioritise = 1;  							 T(YAFFS_TRACE_ALWAYS, -							 (TSTR("Partially written block %d being set for retirement" TENDSTR), +							 (TSTR("Partially written block %d detected" TENDSTR),  							 blk));  						} -  					} -  				}  				dev->nFreeChunks++; +			} else if (tags.eccResult == YAFFS_ECC_RESULT_UNFIXED) { +				T(YAFFS_TRACE_SCAN, +				  (TSTR(" Unfixed ECC in chunk(%d:%d), chunk ignored"TENDSTR), +				  blk, c)); + +				  dev->nFreeChunks++; +  			} else if (tags.chunkId > 0) {  				/* chunkId > 0 so it is a data chunk... */  				unsigned int endpos; @@ -6187,7 +6192,7 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)  								      tags.  								      objectId,  								      YAFFS_OBJECT_TYPE_FILE); -				if(!in){ +				if (!in) {  					/* Out of memory */  					alloc_failed = 1;  				} @@ -6197,8 +6202,8 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)  				    && chunkBase <  				    in->variant.fileVariant.shrinkSize) {  					/* This has not been invalidated by a resize */ -					if(!yaffs_PutChunkIntoFile(in, tags.chunkId, -							       chunk, -1)){ +					if (!yaffs_PutChunkIntoFile(in, tags.chunkId, +							       chunk, -1)) {  						alloc_failed = 1;  					} @@ -6221,7 +6226,7 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)  						    scannedFileSize;  					} -				} else if(in) { +				} else if (in) {  					/* This chunk has been invalidated by a resize, so delete */  					yaffs_DeleteChunk(dev, chunk, 1, __LINE__); @@ -6242,6 +6247,8 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)  					in = yaffs_FindOrCreateObjectByNumber  					    (dev, tags.objectId,  					     tags.extraObjectType); +					if (!in) +						alloc_failed = 1;  				}  				if (!in || @@ -6251,8 +6258,7 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)  				    tags.extraShadows ||  				    (!in->valid &&  				    (tags.objectId == YAFFS_OBJECTID_ROOT || -				     tags.objectId == YAFFS_OBJECTID_LOSTNFOUND)) -				    ) { +				     tags.objectId == YAFFS_OBJECTID_LOSTNFOUND))) {  					/* If we don't have  valid info then we need to read the chunk  					 * TODO In future we can probably defer reading the chunk and @@ -6266,8 +6272,17 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)  					oh = (yaffs_ObjectHeader *) chunkData; -					if (!in) +					if (dev->inbandTags) { +						/* Fix up the header if they got corrupted by inband tags */ +						oh->shadowsObject = oh->inbandShadowsObject; +						oh->isShrink = oh->inbandIsShrink; +					} + +					if (!in) {  						in = yaffs_FindOrCreateObjectByNumber(dev, tags.objectId, oh->type); +						if (!in) +							alloc_failed = 1; +					}  				} @@ -6275,10 +6290,9 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)  					/* TODO Hoosterman we have a problem! */  					T(YAFFS_TRACE_ERROR,  					  (TSTR -					   ("yaffs tragedy: Could not make object for object  %d  " -					    "at chunk %d during scan" +					   ("yaffs tragedy: Could not make object for object  %d at chunk %d during scan"  					    TENDSTR), tags.objectId, chunk)); - +					continue;  				}  				if (in->valid) { @@ -6289,10 +6303,9 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)  					if ((in->variantType == YAFFS_OBJECT_TYPE_FILE) &&  					     ((oh && -					       oh-> type == YAFFS_OBJECT_TYPE_FILE)|| +					       oh->type == YAFFS_OBJECT_TYPE_FILE) ||  					      (tags.extraHeaderInfoAvailable  && -					       tags.extraObjectType == YAFFS_OBJECT_TYPE_FILE)) -					    ) { +					       tags.extraObjectType == YAFFS_OBJECT_TYPE_FILE))) {  						__u32 thisSize =  						    (oh) ? oh->fileSize : tags.  						    extraFileLength; @@ -6300,7 +6313,9 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)  						    (oh) ? oh->  						    parentObjectId : tags.  						    extraParentObjectId; -						unsigned isShrink = + + +						isShrink =  						    (oh) ? oh->isShrink : tags.  						    extraIsShrinkHeader; @@ -6323,9 +6338,8 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)  							    thisSize;  						} -						if (isShrink) { +						if (isShrink)  							bi->hasShrinkHeader = 1; -						}  					}  					/* Use existing - destroy this one. */ @@ -6333,6 +6347,17 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)  				} +				if (!in->valid && in->variantType != +				    (oh ? oh->type : tags.extraObjectType)) +					T(YAFFS_TRACE_ERROR, ( +						TSTR("yaffs tragedy: Bad object type, " +					    TCONT("%d != %d, for object %d at chunk ") +					    TCONT("%d during scan") +						TENDSTR), oh ? +					    oh->type : tags.extraObjectType, +					    in->variantType, tags.objectId, +					    chunk)); +  				if (!in->valid &&  				    (tags.objectId == YAFFS_OBJECTID_ROOT ||  				     tags.objectId == @@ -6340,7 +6365,7 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)  					/* We only load some info, don't fiddle with directory structure */  					in->valid = 1; -					if(oh) { +					if (oh) {  						in->variantType = oh->type;  						in->yst_mode = oh->yst_mode; @@ -6365,15 +6390,15 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)  						in->lazyLoaded = 1;  					} -					in->chunkId = chunk; +					in->hdrChunk = chunk;  				} else if (!in->valid) {  					/* we need to load this info */  					in->valid = 1; -					in->chunkId = chunk; +					in->hdrChunk = chunk; -					if(oh) { +					if (oh) {  						in->variantType = oh->type;  						in->yst_mode = oh->yst_mode; @@ -6403,20 +6428,19 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)  						yaffs_SetObjectName(in, oh->name);  						parent =  						    yaffs_FindOrCreateObjectByNumber -					    		(dev, oh->parentObjectId, -					     		 YAFFS_OBJECT_TYPE_DIRECTORY); +							(dev, oh->parentObjectId, +							 YAFFS_OBJECT_TYPE_DIRECTORY);  						 fileSize = oh->fileSize; - 						 isShrink = oh->isShrink; +						 isShrink = oh->isShrink;  						 equivalentObjectId = oh->equivalentObjectId; -					} -					else { +					} else {  						in->variantType = tags.extraObjectType;  						parent =  						    yaffs_FindOrCreateObjectByNumber -					    		(dev, tags.extraParentObjectId, -					     		 YAFFS_OBJECT_TYPE_DIRECTORY); +							(dev, tags.extraParentObjectId, +							 YAFFS_OBJECT_TYPE_DIRECTORY);  						 fileSize = tags.extraFileLength;  						 isShrink = tags.extraIsShrinkHeader;  						 equivalentObjectId = tags.extraEquivalentObjectId; @@ -6425,29 +6449,30 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)  					}  					in->dirty = 0; +					if (!parent) +						alloc_failed = 1; +  					/* directory stuff...  					 * hook up to parent  					 */ -					if (parent->variantType == +					if (parent && parent->variantType ==  					    YAFFS_OBJECT_TYPE_UNKNOWN) {  						/* Set up as a directory */  						parent->variantType = -						    YAFFS_OBJECT_TYPE_DIRECTORY; -						INIT_LIST_HEAD(&parent->variant. -							       directoryVariant. -							       children); -					} else if (parent->variantType != -						   YAFFS_OBJECT_TYPE_DIRECTORY) -					{ +							YAFFS_OBJECT_TYPE_DIRECTORY; +						YINIT_LIST_HEAD(&parent->variant. +							directoryVariant. +							children); +					} else if (!parent || parent->variantType != +						   YAFFS_OBJECT_TYPE_DIRECTORY) {  						/* Hoosterman, another problem....  						 * We're trying to use a non-directory as a directory  						 */  						T(YAFFS_TRACE_ERROR,  						  (TSTR -						   ("yaffs tragedy: attempting to use non-directory as" -						    " a directory in scan. Put in lost+found." +						   ("yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found."  						    TENDSTR)));  						parent = dev->lostNFoundDir;  					} @@ -6494,12 +6519,12 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)  						break;  					case YAFFS_OBJECT_TYPE_HARDLINK: -						if(!itsUnlinked) { -						  in->variant.hardLinkVariant.equivalentObjectId = -						    equivalentObjectId; -						  in->hardLinks.next = -						    (struct list_head *) hardList; -						  hardList = in; +						if (!itsUnlinked) { +							in->variant.hardLinkVariant.equivalentObjectId = +								equivalentObjectId; +							in->hardLinks.next = +								(struct ylist_head *) hardList; +							hardList = in;  						}  						break;  					case YAFFS_OBJECT_TYPE_DIRECTORY: @@ -6509,12 +6534,11 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)  						/* Do nothing */  						break;  					case YAFFS_OBJECT_TYPE_SYMLINK: -						if(oh){ -						   in->variant.symLinkVariant.alias = -						    yaffs_CloneString(oh-> -								      alias); -						   if(!in->variant.symLinkVariant.alias) -						   	alloc_failed = 1; +						if (oh) { +							in->variant.symLinkVariant.alias = +								yaffs_CloneString(oh->alias); +							if (!in->variant.symLinkVariant.alias) +								alloc_failed = 1;  						}  						break;  					} @@ -6551,75 +6575,129 @@ static int yaffs_ScanBackwards(yaffs_Device * dev)  	 * We should now have scanned all the objects, now it's time to add these  	 * hardlinks.  	 */ -	yaffs_HardlinkFixup(dev,hardList); +	yaffs_HardlinkFixup(dev, hardList); -	/* -	*  Sort out state of unlinked and deleted objects. -	*/ -	{ -		struct list_head *i; -		struct list_head *n; - -		yaffs_Object *l; - -		/* Soft delete all the unlinked files */ -		list_for_each_safe(i, n, -				   &dev->unlinkedDir->variant.directoryVariant. -				   children) { -			if (i) { -				l = list_entry(i, yaffs_Object, siblings); -				yaffs_DestroyObject(l); -			} -		} +	yaffs_ReleaseTempBuffer(dev, chunkData, __LINE__); -		/* Soft delete all the deletedDir files */ -		list_for_each_safe(i, n, -				   &dev->deletedDir->variant.directoryVariant. -				   children) { -			if (i) { -				l = list_entry(i, yaffs_Object, siblings); -				yaffs_DestroyObject(l); +	if (alloc_failed) +		return YAFFS_FAIL; -			} +	T(YAFFS_TRACE_SCAN, (TSTR("yaffs_ScanBackwards ends" TENDSTR))); + +	return YAFFS_OK; +} + +/*------------------------------  Directory Functions ----------------------------- */ + +static void yaffs_VerifyObjectInDirectory(yaffs_Object *obj) +{ +	struct ylist_head *lh; +	yaffs_Object *listObj; + +	int count = 0; + +	if (!obj) { +		T(YAFFS_TRACE_ALWAYS, (TSTR("No object to verify" TENDSTR))); +		YBUG(); +		return; +	} + +	if (yaffs_SkipVerification(obj->myDev)) +		return; + +	if (!obj->parent) { +		T(YAFFS_TRACE_ALWAYS, (TSTR("Object does not have parent" TENDSTR))); +		YBUG(); +		return; +	} + +	if (obj->parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) { +		T(YAFFS_TRACE_ALWAYS, (TSTR("Parent is not directory" TENDSTR))); +		YBUG(); +	} + +	/* Iterate through the objects in each hash entry */ + +	ylist_for_each(lh, &obj->parent->variant.directoryVariant.children) { +		if (lh) { +			listObj = ylist_entry(lh, yaffs_Object, siblings); +			yaffs_VerifyObject(listObj); +			if (obj == listObj) +				count++;  		} +	 } + +	if (count != 1) { +		T(YAFFS_TRACE_ALWAYS, (TSTR("Object in directory %d times" TENDSTR), count)); +		YBUG();  	} +} -	yaffs_ReleaseTempBuffer(dev, chunkData, __LINE__); +static void yaffs_VerifyDirectory(yaffs_Object *directory) +{ +	struct ylist_head *lh; +	yaffs_Object *listObj; -	if(alloc_failed){ -		return YAFFS_FAIL; +	if (!directory) { +		YBUG(); +		return;  	} -	T(YAFFS_TRACE_SCAN, (TSTR("yaffs_ScanBackwards ends" TENDSTR))); +	if (yaffs_SkipFullVerification(directory->myDev)) +		return; -	return YAFFS_OK; +	if (directory->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) { +		T(YAFFS_TRACE_ALWAYS, (TSTR("Directory has wrong type: %d" TENDSTR), directory->variantType)); +		YBUG(); +	} + +	/* Iterate through the objects in each hash entry */ + +	ylist_for_each(lh, &directory->variant.directoryVariant.children) { +		if (lh) { +			listObj = ylist_entry(lh, yaffs_Object, siblings); +			if (listObj->parent != directory) { +				T(YAFFS_TRACE_ALWAYS, (TSTR("Object in directory list has wrong parent %p" TENDSTR), listObj->parent)); +				YBUG(); +			} +			yaffs_VerifyObjectInDirectory(listObj); +		} +	}  } -/*------------------------------  Directory Functions ----------------------------- */ -static void yaffs_RemoveObjectFromDirectory(yaffs_Object * obj) +static void yaffs_RemoveObjectFromDirectory(yaffs_Object *obj)  {  	yaffs_Device *dev = obj->myDev; +	yaffs_Object *parent; + +	yaffs_VerifyObjectInDirectory(obj); +	parent = obj->parent; -	if(dev && dev->removeObjectCallback) +	yaffs_VerifyDirectory(parent); + +	if (dev && dev->removeObjectCallback)  		dev->removeObjectCallback(obj); -	list_del_init(&obj->siblings); + +	ylist_del_init(&obj->siblings);  	obj->parent = NULL; + +	yaffs_VerifyDirectory(parent);  } -static void yaffs_AddObjectToDirectory(yaffs_Object * directory, -				       yaffs_Object * obj) +static void yaffs_AddObjectToDirectory(yaffs_Object *directory, +					yaffs_Object *obj)  { -  	if (!directory) {  		T(YAFFS_TRACE_ALWAYS,  		  (TSTR  		   ("tragedy: Trying to add an object to a null pointer directory"  		    TENDSTR)));  		YBUG(); +		return;  	}  	if (directory->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) {  		T(YAFFS_TRACE_ALWAYS, @@ -6631,37 +6709,42 @@ static void yaffs_AddObjectToDirectory(yaffs_Object * directory,  	if (obj->siblings.prev == NULL) {  		/* Not initialised */ -		INIT_LIST_HEAD(&obj->siblings); - -	} else if (!list_empty(&obj->siblings)) { -		/* If it is holed up somewhere else, un hook it */ -		yaffs_RemoveObjectFromDirectory(obj); +		YBUG();  	} + + +	yaffs_VerifyDirectory(directory); + +	yaffs_RemoveObjectFromDirectory(obj); + +  	/* Now add it */ -	list_add(&obj->siblings, &directory->variant.directoryVariant.children); +	ylist_add(&obj->siblings, &directory->variant.directoryVariant.children);  	obj->parent = directory;  	if (directory == obj->myDev->unlinkedDir -	    || directory == obj->myDev->deletedDir) { +			|| directory == obj->myDev->deletedDir) {  		obj->unlinked = 1;  		obj->myDev->nUnlinkedFiles++;  		obj->renameAllowed = 0;  	} + +	yaffs_VerifyDirectory(directory); +	yaffs_VerifyObjectInDirectory(obj);  } -yaffs_Object *yaffs_FindObjectByName(yaffs_Object * directory, -				     const YCHAR * name) +yaffs_Object *yaffs_FindObjectByName(yaffs_Object *directory, +				     const YCHAR *name)  {  	int sum; -	struct list_head *i; +	struct ylist_head *i;  	YCHAR buffer[YAFFS_MAX_NAME_LENGTH + 1];  	yaffs_Object *l; -	if (!name) { +	if (!name)  		return NULL; -	}  	if (!directory) {  		T(YAFFS_TRACE_ALWAYS, @@ -6669,6 +6752,7 @@ yaffs_Object *yaffs_FindObjectByName(yaffs_Object * directory,  		   ("tragedy: yaffs_FindObjectByName: null pointer directory"  		    TENDSTR)));  		YBUG(); +		return NULL;  	}  	if (directory->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) {  		T(YAFFS_TRACE_ALWAYS, @@ -6679,28 +6763,27 @@ yaffs_Object *yaffs_FindObjectByName(yaffs_Object * directory,  	sum = yaffs_CalcNameSum(name); -	list_for_each(i, &directory->variant.directoryVariant.children) { +	ylist_for_each(i, &directory->variant.directoryVariant.children) {  		if (i) { -			l = list_entry(i, yaffs_Object, siblings); +			l = ylist_entry(i, yaffs_Object, siblings); + +			if (l->parent != directory) +				YBUG();  			yaffs_CheckObjectDetailsLoaded(l);  			/* Special case for lost-n-found */  			if (l->objectId == YAFFS_OBJECTID_LOSTNFOUND) { -				if (yaffs_strcmp(name, YAFFS_LOSTNFOUND_NAME) == 0) { +				if (yaffs_strcmp(name, YAFFS_LOSTNFOUND_NAME) == 0)  					return l; -				} -			} else if (yaffs_SumCompare(l->sum, sum) || l->chunkId <= 0) -			{ -				/* LostnFound cunk called Objxxx +			} else if (yaffs_SumCompare(l->sum, sum) || l->hdrChunk <= 0) { +				/* LostnFound chunk called Objxxx  				 * Do a real check  				 */  				yaffs_GetObjectName(l, buffer,  						    YAFFS_MAX_NAME_LENGTH); -				if (yaffs_strncmp(name, buffer,YAFFS_MAX_NAME_LENGTH) == 0) { +				if (yaffs_strncmp(name, buffer, YAFFS_MAX_NAME_LENGTH) == 0)  					return l; -				} -  			}  		}  	} @@ -6710,10 +6793,10 @@ yaffs_Object *yaffs_FindObjectByName(yaffs_Object * directory,  #if 0 -int yaffs_ApplyToDirectoryChildren(yaffs_Object * theDir, -				   int (*fn) (yaffs_Object *)) +int yaffs_ApplyToDirectoryChildren(yaffs_Object *theDir, +					int (*fn) (yaffs_Object *))  { -	struct list_head *i; +	struct ylist_head *i;  	yaffs_Object *l;  	if (!theDir) { @@ -6722,20 +6805,21 @@ int yaffs_ApplyToDirectoryChildren(yaffs_Object * theDir,  		   ("tragedy: yaffs_FindObjectByName: null pointer directory"  		    TENDSTR)));  		YBUG(); +		return YAFFS_FAIL;  	}  	if (theDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) {  		T(YAFFS_TRACE_ALWAYS,  		  (TSTR  		   ("tragedy: yaffs_FindObjectByName: non-directory" TENDSTR)));  		YBUG(); +		return YAFFS_FAIL;  	} -	list_for_each(i, &theDir->variant.directoryVariant.children) { +	ylist_for_each(i, &theDir->variant.directoryVariant.children) {  		if (i) { -			l = list_entry(i, yaffs_Object, siblings); -			if (l && !fn(l)) { +			l = ylist_entry(i, yaffs_Object, siblings); +			if (l && !fn(l))  				return YAFFS_FAIL; -			}  		}  	} @@ -6748,7 +6832,7 @@ int yaffs_ApplyToDirectoryChildren(yaffs_Object * theDir,   * actual object.   */ -yaffs_Object *yaffs_GetEquivalentObject(yaffs_Object * obj) +yaffs_Object *yaffs_GetEquivalentObject(yaffs_Object *obj)  {  	if (obj && obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) {  		/* We want the object id of the equivalent object, not this one */ @@ -6756,10 +6840,9 @@ yaffs_Object *yaffs_GetEquivalentObject(yaffs_Object * obj)  		yaffs_CheckObjectDetailsLoaded(obj);  	}  	return obj; -  } -int yaffs_GetObjectName(yaffs_Object * obj, YCHAR * name, int buffSize) +int yaffs_GetObjectName(yaffs_Object *obj, YCHAR *name, int buffSize)  {  	memset(name, 0, buffSize * sizeof(YCHAR)); @@ -6767,18 +6850,26 @@ int yaffs_GetObjectName(yaffs_Object * obj, YCHAR * name, int buffSize)  	if (obj->objectId == YAFFS_OBJECTID_LOSTNFOUND) {  		yaffs_strncpy(name, YAFFS_LOSTNFOUND_NAME, buffSize - 1); -	} else if (obj->chunkId <= 0) { +	} else if (obj->hdrChunk <= 0) {  		YCHAR locName[20]; +		YCHAR numString[20]; +		YCHAR *x = &numString[19]; +		unsigned v = obj->objectId; +		numString[19] = 0; +		while (v > 0) { +			x--; +			*x = '0' + (v % 10); +			v /= 10; +		}  		/* make up a name */ -		yaffs_sprintf(locName, _Y("%s%d"), YAFFS_LOSTNFOUND_PREFIX, -			      obj->objectId); +		yaffs_strcpy(locName, YAFFS_LOSTNFOUND_PREFIX); +		yaffs_strcat(locName, x);  		yaffs_strncpy(name, locName, buffSize - 1);  	}  #ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM -	else if (obj->shortName[0]) { +	else if (obj->shortName[0])  		yaffs_strcpy(name, obj->shortName); -	}  #endif  	else {  		int result; @@ -6788,9 +6879,9 @@ int yaffs_GetObjectName(yaffs_Object * obj, YCHAR * name, int buffSize)  		memset(buffer, 0, obj->myDev->nDataBytesPerChunk); -		if (obj->chunkId >= 0) { +		if (obj->hdrChunk > 0) {  			result = yaffs_ReadChunkWithTagsFromNAND(obj->myDev, -							obj->chunkId, buffer, +							obj->hdrChunk, buffer,  							NULL);  		}  		yaffs_strncpy(name, oh->name, buffSize - 1); @@ -6801,46 +6892,43 @@ int yaffs_GetObjectName(yaffs_Object * obj, YCHAR * name, int buffSize)  	return yaffs_strlen(name);  } -int yaffs_GetObjectFileLength(yaffs_Object * obj) +int yaffs_GetObjectFileLength(yaffs_Object *obj)  { -  	/* Dereference any hard linking */  	obj = yaffs_GetEquivalentObject(obj); -	if (obj->variantType == YAFFS_OBJECT_TYPE_FILE) { +	if (obj->variantType == YAFFS_OBJECT_TYPE_FILE)  		return obj->variant.fileVariant.fileSize; -	} -	if (obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK) { +	if (obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK)  		return yaffs_strlen(obj->variant.symLinkVariant.alias); -	} else { +	else {  		/* Only a directory should drop through to here */  		return obj->myDev->nDataBytesPerChunk;  	}  } -int yaffs_GetObjectLinkCount(yaffs_Object * obj) +int yaffs_GetObjectLinkCount(yaffs_Object *obj)  {  	int count = 0; -	struct list_head *i; +	struct ylist_head *i; -	if (!obj->unlinked) { -		count++;	/* the object itself */ -	} -	list_for_each(i, &obj->hardLinks) { -		count++;	/* add the hard links; */ -	} -	return count; +	if (!obj->unlinked) +		count++;		/* the object itself */ + +	ylist_for_each(i, &obj->hardLinks) +		count++;		/* add the hard links; */ +	return count;  } -int yaffs_GetObjectInode(yaffs_Object * obj) +int yaffs_GetObjectInode(yaffs_Object *obj)  {  	obj = yaffs_GetEquivalentObject(obj);  	return obj->objectId;  } -unsigned yaffs_GetObjectType(yaffs_Object * obj) +unsigned yaffs_GetObjectType(yaffs_Object *obj)  {  	obj = yaffs_GetEquivalentObject(obj); @@ -6872,19 +6960,18 @@ unsigned yaffs_GetObjectType(yaffs_Object * obj)  	}  } -YCHAR *yaffs_GetSymlinkAlias(yaffs_Object * obj) +YCHAR *yaffs_GetSymlinkAlias(yaffs_Object *obj)  {  	obj = yaffs_GetEquivalentObject(obj); -	if (obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK) { +	if (obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK)  		return yaffs_CloneString(obj->variant.symLinkVariant.alias); -	} else { +	else  		return yaffs_CloneString(_Y("")); -	}  }  #ifndef CONFIG_YAFFS_WINCE -int yaffs_SetAttributes(yaffs_Object * obj, struct iattr *attr) +int yaffs_SetAttributes(yaffs_Object *obj, struct iattr *attr)  {  	unsigned int valid = attr->ia_valid; @@ -6910,7 +6997,7 @@ int yaffs_SetAttributes(yaffs_Object * obj, struct iattr *attr)  	return YAFFS_OK;  } -int yaffs_GetAttributes(yaffs_Object * obj, struct iattr *attr) +int yaffs_GetAttributes(yaffs_Object *obj, struct iattr *attr)  {  	unsigned int valid = 0; @@ -6934,13 +7021,12 @@ int yaffs_GetAttributes(yaffs_Object * obj, struct iattr *attr)  	attr->ia_valid = valid;  	return YAFFS_OK; -  }  #endif  #if 0 -int yaffs_DumpObject(yaffs_Object * obj) +int yaffs_DumpObject(yaffs_Object *obj)  {  	YCHAR name[257]; @@ -6951,7 +7037,7 @@ int yaffs_DumpObject(yaffs_Object * obj)  	   ("Object %d, inode %d \"%s\"\n dirty %d valid %d serial %d sum %d"  	    " chunk %d type %d size %d\n"  	    TENDSTR), obj->objectId, yaffs_GetObjectInode(obj), name, -	   obj->dirty, obj->valid, obj->serial, obj->sum, obj->chunkId, +	   obj->dirty, obj->valid, obj->serial, obj->sum, obj->hdrChunk,  	   yaffs_GetObjectType(obj), yaffs_GetObjectFileLength(obj)));  	return YAFFS_OK; @@ -6960,7 +7046,7 @@ int yaffs_DumpObject(yaffs_Object * obj)  /*---------------------------- Initialisation code -------------------------------------- */ -static int yaffs_CheckDevFunctions(const yaffs_Device * dev) +static int yaffs_CheckDevFunctions(const yaffs_Device *dev)  {  	/* Common functions, gotta have */ @@ -7011,7 +7097,7 @@ static int yaffs_CreateInitialDirectories(yaffs_Device *dev)  	    yaffs_CreateFakeDirectory(dev, YAFFS_OBJECTID_LOSTNFOUND,  				      YAFFS_LOSTNFOUND_MODE | S_IFDIR); -	if(dev->lostNFoundDir && dev->rootDir && dev->unlinkedDir && dev->deletedDir){ +	if (dev->lostNFoundDir && dev->rootDir && dev->unlinkedDir && dev->deletedDir) {  		yaffs_AddObjectToDirectory(dev->rootDir, dev->lostNFoundDir);  		return YAFFS_OK;  	} @@ -7019,7 +7105,7 @@ static int yaffs_CreateInitialDirectories(yaffs_Device *dev)  	return YAFFS_FAIL;  } -int yaffs_GutsInitialise(yaffs_Device * dev) +int yaffs_GutsInitialise(yaffs_Device *dev)  {  	int init_failed = 0;  	unsigned x; @@ -7040,6 +7126,8 @@ int yaffs_GutsInitialise(yaffs_Device * dev)  	dev->chunkOffset = 0;  	dev->nFreeChunks = 0; +	dev->gcBlock = -1; +  	if (dev->startBlock == 0) {  		dev->internalStartBlock = dev->startBlock + 1;  		dev->internalEndBlock = dev->endBlock + 1; @@ -7049,18 +7137,18 @@ int yaffs_GutsInitialise(yaffs_Device * dev)  	/* Check geometry parameters. */ -	if ((dev->isYaffs2 && dev->nDataBytesPerChunk < 1024) || -	    (!dev->isYaffs2 && dev->nDataBytesPerChunk != 512) || +	if ((!dev->inbandTags && dev->isYaffs2 && dev->totalBytesPerChunk < 1024) || +	    (!dev->isYaffs2 && dev->totalBytesPerChunk < 512) || +	    (dev->inbandTags && !dev->isYaffs2) ||  	     dev->nChunksPerBlock < 2 ||  	     dev->nReservedBlocks < 2 ||  	     dev->internalStartBlock <= 0 ||  	     dev->internalEndBlock <= 0 || -	     dev->internalEndBlock <= (dev->internalStartBlock + dev->nReservedBlocks + 2)	// otherwise it is too small -	    ) { +	     dev->internalEndBlock <= (dev->internalStartBlock + dev->nReservedBlocks + 2)) {	/* otherwise it is too small */  		T(YAFFS_TRACE_ALWAYS,  		  (TSTR -		   ("yaffs: NAND geometry problems: chunk size %d, type is yaffs%s " -		    TENDSTR), dev->nDataBytesPerChunk, dev->isYaffs2 ? "2" : "")); +		   ("yaffs: NAND geometry problems: chunk size %d, type is yaffs%s, inbandTags %d " +		    TENDSTR), dev->totalBytesPerChunk, dev->isYaffs2 ? "2" : "", dev->inbandTags));  		return YAFFS_FAIL;  	} @@ -7070,6 +7158,12 @@ int yaffs_GutsInitialise(yaffs_Device * dev)  		return YAFFS_FAIL;  	} +	/* Sort out space for inband tags, if required */ +	if (dev->inbandTags) +		dev->nDataBytesPerChunk = dev->totalBytesPerChunk - sizeof(yaffs_PackedTags2TagsPart); +	else +		dev->nDataBytesPerChunk = dev->totalBytesPerChunk; +  	/* Got the right mix of functions? */  	if (!yaffs_CheckDevFunctions(dev)) {  		/* Function missing */ @@ -7097,31 +7191,18 @@ int yaffs_GutsInitialise(yaffs_Device * dev)  	dev->isMounted = 1; - -  	/* OK now calculate a few things for the device */  	/*  	 *  Calculate all the chunk size manipulation numbers:  	 */ -	 /* Start off assuming it is a power of 2 */ -	 dev->chunkShift = ShiftDiv(dev->nDataBytesPerChunk); -	 dev->chunkMask = (1<<dev->chunkShift) - 1; - -	 if(dev->nDataBytesPerChunk == (dev->chunkMask + 1)){ -	 	/* Yes it is a power of 2, disable crumbs */ -		dev->crumbMask = 0; -		dev->crumbShift = 0; -		dev->crumbsPerChunk = 0; -	 } else { -	 	/* Not a power of 2, use crumbs instead */ -		dev->crumbShift = ShiftDiv(sizeof(yaffs_PackedTags2TagsPart)); -		dev->crumbMask = (1<<dev->crumbShift)-1; -		dev->crumbsPerChunk = dev->nDataBytesPerChunk/(1 << dev->crumbShift); -		dev->chunkShift = 0; -		dev->chunkMask = 0; -	} - +	x = dev->nDataBytesPerChunk; +	/* We always use dev->chunkShift and dev->chunkDiv */ +	dev->chunkShift = Shifts(x); +	x >>= dev->chunkShift; +	dev->chunkDiv = x; +	/* We only use chunk mask if chunkDiv is 1 */ +	dev->chunkMask = (1<<dev->chunkShift) - 1;  	/*  	 * Calculate chunkGroupBits. @@ -7133,16 +7214,15 @@ int yaffs_GutsInitialise(yaffs_Device * dev)  	bits = ShiftsGE(x);  	/* Set up tnode width if wide tnodes are enabled. */ -	if(!dev->wideTnodesDisabled){ +	if (!dev->wideTnodesDisabled) {  		/* bits must be even so that we end up with 32-bit words */ -		if(bits & 1) +		if (bits & 1)  			bits++; -		if(bits < 16) +		if (bits < 16)  			dev->tnodeWidth = 16;  		else  			dev->tnodeWidth = bits; -	} -	else +	} else  		dev->tnodeWidth = 16;  	dev->tnodeMask = (1<<dev->tnodeWidth)-1; @@ -7193,7 +7273,7 @@ int yaffs_GutsInitialise(yaffs_Device * dev)  	dev->hasPendingPrioritisedGCs = 1; /* Assume the worst for now, will get fixed on first GC */  	/* Initialise temporary buffers and caches. */ -	if(!yaffs_InitialiseTempBuffers(dev)) +	if (!yaffs_InitialiseTempBuffers(dev))  		init_failed = 1;  	dev->srCache = NULL; @@ -7203,25 +7283,26 @@ int yaffs_GutsInitialise(yaffs_Device * dev)  	if (!init_failed &&  	    dev->nShortOpCaches > 0) {  		int i; -		__u8 *buf; +		void *buf;  		int srCacheBytes = dev->nShortOpCaches * sizeof(yaffs_ChunkCache); -		if (dev->nShortOpCaches > YAFFS_MAX_SHORT_OP_CACHES) { +		if (dev->nShortOpCaches > YAFFS_MAX_SHORT_OP_CACHES)  			dev->nShortOpCaches = YAFFS_MAX_SHORT_OP_CACHES; -		} -		buf = dev->srCache =  YMALLOC(srCacheBytes); +		dev->srCache =  YMALLOC(srCacheBytes); + +		buf = (__u8 *) dev->srCache; -		if(dev->srCache) -			memset(dev->srCache,0,srCacheBytes); +		if (dev->srCache) +			memset(dev->srCache, 0, srCacheBytes);  		for (i = 0; i < dev->nShortOpCaches && buf; i++) {  			dev->srCache[i].object = NULL;  			dev->srCache[i].lastUse = 0;  			dev->srCache[i].dirty = 0; -			dev->srCache[i].data = buf = YMALLOC_DMA(dev->nDataBytesPerChunk); +			dev->srCache[i].data = buf = YMALLOC_DMA(dev->totalBytesPerChunk);  		} -		if(!buf) +		if (!buf)  			init_failed = 1;  		dev->srLastUse = 0; @@ -7229,29 +7310,30 @@ int yaffs_GutsInitialise(yaffs_Device * dev)  	dev->cacheHits = 0; -	if(!init_failed){ +	if (!init_failed) {  		dev->gcCleanupList = YMALLOC(dev->nChunksPerBlock * sizeof(__u32)); -		if(!dev->gcCleanupList) +		if (!dev->gcCleanupList)  			init_failed = 1;  	} -	if (dev->isYaffs2) { +	if (dev->isYaffs2)  		dev->useHeaderFileSize = 1; -	} -	if(!init_failed && !yaffs_InitialiseBlocks(dev)) + +	if (!init_failed && !yaffs_InitialiseBlocks(dev))  		init_failed = 1;  	yaffs_InitialiseTnodes(dev);  	yaffs_InitialiseObjects(dev); -	if(!init_failed && !yaffs_CreateInitialDirectories(dev)) +	if (!init_failed && !yaffs_CreateInitialDirectories(dev))  		init_failed = 1; -	if(!init_failed){ +	if (!init_failed) {  		/* Now scan the flash. */  		if (dev->isYaffs2) { -			if(yaffs_CheckpointRestore(dev)) { +			if (yaffs_CheckpointRestore(dev)) { +				yaffs_CheckObjectDetailsLoaded(dev->rootDir);  				T(YAFFS_TRACE_ALWAYS,  				  (TSTR("yaffs: restored from checkpoint" TENDSTR)));  			} else { @@ -7273,24 +7355,25 @@ int yaffs_GutsInitialise(yaffs_Device * dev)  				dev->nBackgroundDeletions = 0;  				dev->oldestDirtySequence = 0; -				if(!init_failed && !yaffs_InitialiseBlocks(dev)) +				if (!init_failed && !yaffs_InitialiseBlocks(dev))  					init_failed = 1;  				yaffs_InitialiseTnodes(dev);  				yaffs_InitialiseObjects(dev); -				if(!init_failed && !yaffs_CreateInitialDirectories(dev)) +				if (!init_failed && !yaffs_CreateInitialDirectories(dev))  					init_failed = 1; -				if(!init_failed && !yaffs_ScanBackwards(dev)) +				if (!init_failed && !yaffs_ScanBackwards(dev))  					init_failed = 1;  			} -		}else -			if(!yaffs_Scan(dev)) +		} else if (!yaffs_Scan(dev))  				init_failed = 1; + +		yaffs_StripDeletedObjects(dev);  	} -	if(init_failed){ +	if (init_failed) {  		/* Clean up the mess */  		T(YAFFS_TRACE_TRACING,  		  (TSTR("yaffs: yaffs_GutsInitialise() aborted.\n" TENDSTR))); @@ -7318,7 +7401,7 @@ int yaffs_GutsInitialise(yaffs_Device * dev)  } -void yaffs_Deinitialise(yaffs_Device * dev) +void yaffs_Deinitialise(yaffs_Device *dev)  {  	if (dev->isMounted) {  		int i; @@ -7330,7 +7413,7 @@ void yaffs_Deinitialise(yaffs_Device * dev)  		    dev->srCache) {  			for (i = 0; i < dev->nShortOpCaches; i++) { -				if(dev->srCache[i].data) +				if (dev->srCache[i].data)  					YFREE(dev->srCache[i].data);  				dev->srCache[i].data = NULL;  			} @@ -7341,16 +7424,17 @@ void yaffs_Deinitialise(yaffs_Device * dev)  		YFREE(dev->gcCleanupList); -		for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) { +		for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++)  			YFREE(dev->tempBuffer[i].buffer); -		}  		dev->isMounted = 0; -	} +		if (dev->deinitialiseNAND) +			dev->deinitialiseNAND(dev); +	}  } -static int yaffs_CountFreeChunks(yaffs_Device * dev) +static int yaffs_CountFreeChunks(yaffs_Device *dev)  {  	int nFree;  	int b; @@ -7358,7 +7442,7 @@ static int yaffs_CountFreeChunks(yaffs_Device * dev)  	yaffs_BlockInfo *blk;  	for (nFree = 0, b = dev->internalStartBlock; b <= dev->internalEndBlock; -	     b++) { +			b++) {  		blk = yaffs_GetBlockInfo(dev, b);  		switch (blk->blockState) { @@ -7373,19 +7457,19 @@ static int yaffs_CountFreeChunks(yaffs_Device * dev)  		default:  			break;  		} -  	}  	return nFree;  } -int yaffs_GetNumberOfFreeChunks(yaffs_Device * dev) +int yaffs_GetNumberOfFreeChunks(yaffs_Device *dev)  {  	/* This is what we report to the outside world */  	int nFree;  	int nDirtyCacheChunks;  	int blocksForCheckpoint; +	int i;  #if 1  	nFree = dev->nFreeChunks; @@ -7397,12 +7481,9 @@ int yaffs_GetNumberOfFreeChunks(yaffs_Device * dev)  	/* Now count the number of dirty chunks in the cache and subtract those */ -	{ -		int i; -		for (nDirtyCacheChunks = 0, i = 0; i < dev->nShortOpCaches; i++) { -			if (dev->srCache[i].dirty) -				nDirtyCacheChunks++; -		} +	for (nDirtyCacheChunks = 0, i = 0; i < dev->nShortOpCaches; i++) { +		if (dev->srCache[i].dirty) +			nDirtyCacheChunks++;  	}  	nFree -= nDirtyCacheChunks; @@ -7410,8 +7491,8 @@ int yaffs_GetNumberOfFreeChunks(yaffs_Device * dev)  	nFree -= ((dev->nReservedBlocks + 1) * dev->nChunksPerBlock);  	/* Now we figure out how much to reserve for the checkpoint and report that... */ -	blocksForCheckpoint = dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint; -	if(blocksForCheckpoint < 0) +	blocksForCheckpoint = yaffs_CalcCheckpointBlocksRequired(dev) - dev->blocksInCheckpoint; +	if (blocksForCheckpoint < 0)  		blocksForCheckpoint = 0;  	nFree -= (blocksForCheckpoint * dev->nChunksPerBlock); @@ -7425,12 +7506,12 @@ int yaffs_GetNumberOfFreeChunks(yaffs_Device * dev)  static int yaffs_freeVerificationFailures; -static void yaffs_VerifyFreeChunks(yaffs_Device * dev) +static void yaffs_VerifyFreeChunks(yaffs_Device *dev)  {  	int counted;  	int difference; -	if(yaffs_SkipVerification(dev)) +	if (yaffs_SkipVerification(dev))  		return;  	counted = yaffs_CountFreeChunks(dev); @@ -7447,23 +7528,25 @@ static void yaffs_VerifyFreeChunks(yaffs_Device * dev)  /*---------------------------------------- YAFFS test code ----------------------*/ -#define yaffs_CheckStruct(structure,syze, name) \ -           if(sizeof(structure) != syze) \ -	       { \ -	         T(YAFFS_TRACE_ALWAYS,(TSTR("%s should be %d but is %d\n" TENDSTR),\ -		 name,syze,sizeof(structure))); \ -	         return YAFFS_FAIL; \ -		} +#define yaffs_CheckStruct(structure, syze, name) \ +	do { \ +		if (sizeof(structure) != syze) { \ +			T(YAFFS_TRACE_ALWAYS, (TSTR("%s should be %d but is %d\n" TENDSTR),\ +				name, syze, sizeof(structure))); \ +			return YAFFS_FAIL; \ +		} \ +	} while (0)  static int yaffs_CheckStructures(void)  { -/*      yaffs_CheckStruct(yaffs_Tags,8,"yaffs_Tags") */ -/*      yaffs_CheckStruct(yaffs_TagsUnion,8,"yaffs_TagsUnion") */ -/*      yaffs_CheckStruct(yaffs_Spare,16,"yaffs_Spare") */ +/*      yaffs_CheckStruct(yaffs_Tags,8,"yaffs_Tags"); */ +/*      yaffs_CheckStruct(yaffs_TagsUnion,8,"yaffs_TagsUnion"); */ +/*      yaffs_CheckStruct(yaffs_Spare,16,"yaffs_Spare"); */  #ifndef CONFIG_YAFFS_TNODE_LIST_DEBUG -	yaffs_CheckStruct(yaffs_Tnode, 2 * YAFFS_NTNODES_LEVEL0, "yaffs_Tnode") +	yaffs_CheckStruct(yaffs_Tnode, 2 * YAFFS_NTNODES_LEVEL0, "yaffs_Tnode");  #endif -	    yaffs_CheckStruct(yaffs_ObjectHeader, 512, "yaffs_ObjectHeader") - -	    return YAFFS_OK; +#ifndef CONFIG_YAFFS_WINCE +	yaffs_CheckStruct(yaffs_ObjectHeader, 512, "yaffs_ObjectHeader"); +#endif +	return YAFFS_OK;  } diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_guts.h b/target/linux/generic/files/fs/yaffs2/yaffs_guts.h index ea06c1a38..a3b110291 100644 --- a/target/linux/generic/files/fs/yaffs2/yaffs_guts.h +++ b/target/linux/generic/files/fs/yaffs2/yaffs_guts.h @@ -90,7 +90,7 @@  #define YAFFS_MAX_SHORT_OP_CACHES	20 -#define YAFFS_N_TEMP_BUFFERS		4 +#define YAFFS_N_TEMP_BUFFERS		6  /* We limit the number attempts at sucessfully saving a chunk of data.   * Small-page devices have 32 pages per block; large-page devices have 64. @@ -108,6 +108,9 @@  #define YAFFS_LOWEST_SEQUENCE_NUMBER	0x00001000  #define YAFFS_HIGHEST_SEQUENCE_NUMBER	0xEFFFFF00 +/* Special sequence number for bad block that failed to be marked bad */ +#define YAFFS_SEQUENCE_BAD_BLOCK	0xFFFF0000 +  /* ChunkCache is used for short read/write operations.*/  typedef struct {  	struct yaffs_ObjectStruct *object; @@ -134,11 +137,10 @@ typedef struct {  typedef struct {  	unsigned chunkId:20;  	unsigned serialNumber:2; -	unsigned byteCount:10; +	unsigned byteCountLSB:10;  	unsigned objectId:18;  	unsigned ecc:12; -	unsigned unusedStuff:2; - +	unsigned byteCountMSB:2;  } yaffs_Tags;  typedef union { @@ -277,13 +279,13 @@ typedef struct {  	int softDeletions:10;	/* number of soft deleted pages */  	int pagesInUse:10;	/* number of pages in use */ -	yaffs_BlockState blockState:4;	/* One of the above block states */ +	unsigned blockState:4;	/* One of the above block states. NB use unsigned because enum is sometimes an int */  	__u32 needsRetiring:1;	/* Data has failed on this block, need to get valid data off */ -                        	/* and retire the block. */ -	__u32 skipErasedCheck: 1; /* If this is set we can skip the erased check on this block */ -	__u32 gcPrioritise: 1; 	/* An ECC check or blank check has failed on this block. +				/* and retire the block. */ +	__u32 skipErasedCheck:1; /* If this is set we can skip the erased check on this block */ +	__u32 gcPrioritise:1; 	/* An ECC check or blank check has failed on this block.  				   It should be prioritised for GC */ -        __u32 chunkErrorStrikes:3; /* How many times we've had ecc etc failures on this block and tried to reuse it */ +	__u32 chunkErrorStrikes:3; /* How many times we've had ecc etc failures on this block and tried to reuse it */  #ifdef CONFIG_YAFFS_YAFFS2  	__u32 hasShrinkHeader:1; /* This block has at least one shrink object header */ @@ -300,11 +302,11 @@ typedef struct {  	/* Apply to everything  */  	int parentObjectId; -	__u16 sum__NoLongerUsed;	/* checksum of name. No longer used */ +	__u16 sum__NoLongerUsed;        /* checksum of name. No longer used */  	YCHAR name[YAFFS_MAX_NAME_LENGTH + 1]; -	/* Thes following apply to directories, files, symlinks - not hard links */ -	__u32 yst_mode;		/* protection */ +	/* The following apply to directories, files, symlinks - not hard links */ +	__u32 yst_mode;         /* protection */  #ifdef CONFIG_YAFFS_WINCE  	__u32 notForWinCE[5]; @@ -331,11 +333,14 @@ typedef struct {  	__u32 win_ctime[2];  	__u32 win_atime[2];  	__u32 win_mtime[2]; -	__u32 roomToGrow[4];  #else -	__u32 roomToGrow[10]; +	__u32 roomToGrow[6]; +  #endif +	__u32 inbandShadowsObject; +	__u32 inbandIsShrink; +	__u32 reservedSpace[2];  	int shadowsObject;	/* This object header shadows the specified object if > 0 */  	/* isShrink applies to object headers written when we shrink the file (ie resize) */ @@ -381,7 +386,7 @@ typedef struct {  } yaffs_FileStructure;  typedef struct { -	struct list_head children;	/* list of child links */ +	struct ylist_head children;     /* list of child links */  } yaffs_DirectoryStructure;  typedef struct { @@ -418,23 +423,24 @@ struct yaffs_ObjectStruct {  				 * still in the inode cache. Free of object is defered.  				 * until the inode is released.  				 */ +	__u8 beingCreated:1;	/* This object is still being created so skip some checks. */  	__u8 serial;		/* serial number of chunk in NAND. Cached here */  	__u16 sum;		/* sum of the name to speed searching */ -	struct yaffs_DeviceStruct *myDev;	/* The device I'm on */ +	struct yaffs_DeviceStruct *myDev;       /* The device I'm on */ -	struct list_head hashLink;	/* list of objects in this hash bucket */ +	struct ylist_head hashLink;     /* list of objects in this hash bucket */ -	struct list_head hardLinks;	/* all the equivalent hard linked objects */ +	struct ylist_head hardLinks;    /* all the equivalent hard linked objects */  	/* directory structure stuff */  	/* also used for linking up the free list */  	struct yaffs_ObjectStruct *parent; -	struct list_head siblings; +	struct ylist_head siblings;  	/* Where's my object header in NAND? */ -	int chunkId; +	int hdrChunk;  	int nDataChunks;	/* Number of data chunks attached to the file. */ @@ -485,7 +491,7 @@ struct yaffs_ObjectList_struct {  typedef struct yaffs_ObjectList_struct yaffs_ObjectList;  typedef struct { -	struct list_head list; +	struct ylist_head list;  	int count;  } yaffs_ObjectBucket; @@ -495,11 +501,10 @@ typedef struct {   */  typedef struct { -        int structType; +	int structType;  	__u32 objectId;  	__u32 parentId; -	int chunkId; - +	int hdrChunk;  	yaffs_ObjectType variantType:3;  	__u8 deleted:1;  	__u8 softDeleted:1; @@ -511,8 +516,7 @@ typedef struct {  	int nDataChunks;  	__u32 fileSizeOrEquivalentObjectId; - -}yaffs_CheckpointObject; +} yaffs_CheckpointObject;  /*--------------------- Temporary buffers ----------------   * @@ -528,13 +532,13 @@ typedef struct {  /*----------------- Device ---------------------------------*/  struct yaffs_DeviceStruct { -	struct list_head devList; +	struct ylist_head devList;  	const char *name;  	/* Entry parameters set up way early. Yaffs sets up the rest.*/  	int nDataBytesPerChunk;	/* Should be a power of 2 >= 512 */  	int nChunksPerBlock;	/* does not need to be a power of 2 */ -	int nBytesPerSpare;	/* spare area size */ +	int spareBytesPerChunk;	/* spare area size */  	int startBlock;		/* Start block we're allowed to use */  	int endBlock;		/* End block we're allowed to use */  	int nReservedBlocks;	/* We want this tuneable so that we can reduce */ @@ -544,9 +548,7 @@ struct yaffs_DeviceStruct {  	/* Stuff used by the shared space checkpointing mechanism */  	/* If this value is zero, then this mechanism is disabled */ -	int nCheckpointReservedBlocks; /* Blocks to reserve for checkpoint data */ - - +/*	int nCheckpointReservedBlocks; */ /* Blocks to reserve for checkpoint data */  	int nShortOpCaches;	/* If <= 0, then short op caching is disabled, else @@ -560,30 +562,31 @@ struct yaffs_DeviceStruct {  	void *genericDevice;	/* Pointer to device context  				 * On an mtd this holds the mtd pointer.  				 */ -        void *superBlock; +	void *superBlock;  	/* NAND access functions (Must be set before calling YAFFS)*/ -	int (*writeChunkToNAND) (struct yaffs_DeviceStruct * dev, -				 int chunkInNAND, const __u8 * data, -				 const yaffs_Spare * spare); -	int (*readChunkFromNAND) (struct yaffs_DeviceStruct * dev, -				  int chunkInNAND, __u8 * data, -				  yaffs_Spare * spare); -	int (*eraseBlockInNAND) (struct yaffs_DeviceStruct * dev, -				 int blockInNAND); -	int (*initialiseNAND) (struct yaffs_DeviceStruct * dev); +	int (*writeChunkToNAND) (struct yaffs_DeviceStruct *dev, +					int chunkInNAND, const __u8 *data, +					const yaffs_Spare *spare); +	int (*readChunkFromNAND) (struct yaffs_DeviceStruct *dev, +					int chunkInNAND, __u8 *data, +					yaffs_Spare *spare); +	int (*eraseBlockInNAND) (struct yaffs_DeviceStruct *dev, +					int blockInNAND); +	int (*initialiseNAND) (struct yaffs_DeviceStruct *dev); +	int (*deinitialiseNAND) (struct yaffs_DeviceStruct *dev);  #ifdef CONFIG_YAFFS_YAFFS2 -	int (*writeChunkWithTagsToNAND) (struct yaffs_DeviceStruct * dev, -					 int chunkInNAND, const __u8 * data, -					 const yaffs_ExtendedTags * tags); -	int (*readChunkWithTagsFromNAND) (struct yaffs_DeviceStruct * dev, -					  int chunkInNAND, __u8 * data, -					  yaffs_ExtendedTags * tags); -	int (*markNANDBlockBad) (struct yaffs_DeviceStruct * dev, int blockNo); -	int (*queryNANDBlock) (struct yaffs_DeviceStruct * dev, int blockNo, -			       yaffs_BlockState * state, int *sequenceNumber); +	int (*writeChunkWithTagsToNAND) (struct yaffs_DeviceStruct *dev, +					 int chunkInNAND, const __u8 *data, +					 const yaffs_ExtendedTags *tags); +	int (*readChunkWithTagsFromNAND) (struct yaffs_DeviceStruct *dev, +					  int chunkInNAND, __u8 *data, +					  yaffs_ExtendedTags *tags); +	int (*markNANDBlockBad) (struct yaffs_DeviceStruct *dev, int blockNo); +	int (*queryNANDBlock) (struct yaffs_DeviceStruct *dev, int blockNo, +			       yaffs_BlockState *state, __u32 *sequenceNumber);  #endif  	int isYaffs2; @@ -595,10 +598,12 @@ struct yaffs_DeviceStruct {  	void (*removeObjectCallback)(struct yaffs_ObjectStruct *obj);  	/* Callback to mark the superblock dirsty */ -	void (*markSuperBlockDirty)(void * superblock); +	void (*markSuperBlockDirty)(void *superblock);  	int wideTnodesDisabled; /* Set to disable wide tnodes */ +	YCHAR *pathDividers;	/* String of legal path dividers */ +  	/* End of stuff that must be set before initialisation. */ @@ -615,16 +620,14 @@ struct yaffs_DeviceStruct {  	__u32 tnodeWidth;  	__u32 tnodeMask; -	/* Stuff to support various file offses to chunk/offset translations */ -	/* "Crumbs" for nDataBytesPerChunk not being a power of 2 */ -	__u32 crumbMask; -	__u32 crumbShift; -	__u32 crumbsPerChunk; - -	/* Straight shifting for nDataBytesPerChunk being a power of 2 */ -	__u32 chunkShift; -	__u32 chunkMask; +	/* Stuff for figuring out file offset to chunk conversions */ +	__u32 chunkShift; /* Shift value */ +	__u32 chunkDiv;   /* Divisor after shifting: 1 for power-of-2 sizes */ +	__u32 chunkMask;  /* Mask to use for power-of-2 case */ +	/* Stuff to handle inband tags */ +	int inbandTags; +	__u32 totalBytesPerChunk;  #ifdef __KERNEL__ @@ -633,7 +636,7 @@ struct yaffs_DeviceStruct {  	__u8 *spareBuffer;	/* For mtdif2 use. Don't know the size of the buffer  				 * at compile time so we have to allocate it.  				 */ -	void (*putSuperFunc) (struct super_block * sb); +	void (*putSuperFunc) (struct super_block *sb);  #endif  	int isMounted; @@ -663,6 +666,8 @@ struct yaffs_DeviceStruct {  	__u32 checkpointSum;  	__u32 checkpointXor; +	int nCheckpointBlocksRequired; /* Number of blocks needed to store current checkpoint set */ +  	/* Block Info */  	yaffs_BlockInfo *blockInfo;  	__u8 *chunkBits;	/* bitmap of chunks in use */ @@ -684,11 +689,15 @@ struct yaffs_DeviceStruct {  	yaffs_TnodeList *allocatedTnodeList;  	int isDoingGC; +	int gcBlock; +	int gcChunk;  	int nObjectsCreated;  	yaffs_Object *freeObjects;  	int nFreeObjects; +	int nHardLinks; +  	yaffs_ObjectList *allocatedObjectList;  	yaffs_ObjectBucket objectBucket[YAFFS_NOBJECT_BUCKETS]; @@ -745,8 +754,10 @@ struct yaffs_DeviceStruct {  	int nBackgroundDeletions;	/* Count of background deletions. */ +	/* Temporary buffer management */  	yaffs_TempBuffer tempBuffer[YAFFS_N_TEMP_BUFFERS];  	int maxTemp; +	int tempInUse;  	int unmanagedTempAllocations;  	int unmanagedTempDeallocations; @@ -758,9 +769,9 @@ struct yaffs_DeviceStruct {  typedef struct yaffs_DeviceStruct yaffs_Device; -/* The static layout of bllock usage etc is stored in the super block header */ +/* The static layout of block usage etc is stored in the super block header */  typedef struct { -        int StructType; +	int StructType;  	int version;  	int checkpointStartBlock;  	int checkpointEndBlock; @@ -773,7 +784,7 @@ typedef struct {   * must be preserved over unmount/mount cycles.   */  typedef struct { -        int structType; +	int structType;  	int nErasedBlocks;  	int allocationBlock;	/* Current block being allocated off */  	__u32 allocationPage; @@ -791,57 +802,45 @@ typedef struct {  typedef struct { -    int structType; -    __u32 magic; -    __u32 version; -    __u32 head; +	int structType; +	__u32 magic; +	__u32 version; +	__u32 head;  } yaffs_CheckpointValidity; -/* Function to manipulate block info */ -static Y_INLINE yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device * dev, int blk) -{ -	if (blk < dev->internalStartBlock || blk > dev->internalEndBlock) { -		T(YAFFS_TRACE_ERROR, -		  (TSTR -		   ("**>> yaffs: getBlockInfo block %d is not valid" TENDSTR), -		   blk)); -		YBUG(); -	} -	return &dev->blockInfo[blk - dev->internalStartBlock]; -}  /*----------------------- YAFFS Functions -----------------------*/ -int yaffs_GutsInitialise(yaffs_Device * dev); -void yaffs_Deinitialise(yaffs_Device * dev); +int yaffs_GutsInitialise(yaffs_Device *dev); +void yaffs_Deinitialise(yaffs_Device *dev); -int yaffs_GetNumberOfFreeChunks(yaffs_Device * dev); +int yaffs_GetNumberOfFreeChunks(yaffs_Device *dev); -int yaffs_RenameObject(yaffs_Object * oldDir, const YCHAR * oldName, -		       yaffs_Object * newDir, const YCHAR * newName); +int yaffs_RenameObject(yaffs_Object *oldDir, const YCHAR *oldName, +		       yaffs_Object *newDir, const YCHAR *newName); -int yaffs_Unlink(yaffs_Object * dir, const YCHAR * name); -int yaffs_DeleteFile(yaffs_Object * obj); +int yaffs_Unlink(yaffs_Object *dir, const YCHAR *name); +int yaffs_DeleteObject(yaffs_Object *obj); -int yaffs_GetObjectName(yaffs_Object * obj, YCHAR * name, int buffSize); -int yaffs_GetObjectFileLength(yaffs_Object * obj); -int yaffs_GetObjectInode(yaffs_Object * obj); -unsigned yaffs_GetObjectType(yaffs_Object * obj); -int yaffs_GetObjectLinkCount(yaffs_Object * obj); +int yaffs_GetObjectName(yaffs_Object *obj, YCHAR *name, int buffSize); +int yaffs_GetObjectFileLength(yaffs_Object *obj); +int yaffs_GetObjectInode(yaffs_Object *obj); +unsigned yaffs_GetObjectType(yaffs_Object *obj); +int yaffs_GetObjectLinkCount(yaffs_Object *obj); -int yaffs_SetAttributes(yaffs_Object * obj, struct iattr *attr); -int yaffs_GetAttributes(yaffs_Object * obj, struct iattr *attr); +int yaffs_SetAttributes(yaffs_Object *obj, struct iattr *attr); +int yaffs_GetAttributes(yaffs_Object *obj, struct iattr *attr);  /* File operations */ -int yaffs_ReadDataFromFile(yaffs_Object * obj, __u8 * buffer, loff_t offset, -			   int nBytes); -int yaffs_WriteDataToFile(yaffs_Object * obj, const __u8 * buffer, loff_t offset, -			  int nBytes, int writeThrough); -int yaffs_ResizeFile(yaffs_Object * obj, loff_t newSize); +int yaffs_ReadDataFromFile(yaffs_Object *obj, __u8 *buffer, loff_t offset, +				int nBytes); +int yaffs_WriteDataToFile(yaffs_Object *obj, const __u8 *buffer, loff_t offset, +				int nBytes, int writeThrough); +int yaffs_ResizeFile(yaffs_Object *obj, loff_t newSize); -yaffs_Object *yaffs_MknodFile(yaffs_Object * parent, const YCHAR * name, -			      __u32 mode, __u32 uid, __u32 gid); -int yaffs_FlushFile(yaffs_Object * obj, int updateTime); +yaffs_Object *yaffs_MknodFile(yaffs_Object *parent, const YCHAR *name, +				__u32 mode, __u32 uid, __u32 gid); +int yaffs_FlushFile(yaffs_Object *obj, int updateTime);  /* Flushing and checkpointing */  void yaffs_FlushEntireDeviceCache(yaffs_Device *dev); @@ -850,33 +849,33 @@ int yaffs_CheckpointSave(yaffs_Device *dev);  int yaffs_CheckpointRestore(yaffs_Device *dev);  /* Directory operations */ -yaffs_Object *yaffs_MknodDirectory(yaffs_Object * parent, const YCHAR * name, -				   __u32 mode, __u32 uid, __u32 gid); -yaffs_Object *yaffs_FindObjectByName(yaffs_Object * theDir, const YCHAR * name); -int yaffs_ApplyToDirectoryChildren(yaffs_Object * theDir, +yaffs_Object *yaffs_MknodDirectory(yaffs_Object *parent, const YCHAR *name, +				__u32 mode, __u32 uid, __u32 gid); +yaffs_Object *yaffs_FindObjectByName(yaffs_Object *theDir, const YCHAR *name); +int yaffs_ApplyToDirectoryChildren(yaffs_Object *theDir,  				   int (*fn) (yaffs_Object *)); -yaffs_Object *yaffs_FindObjectByNumber(yaffs_Device * dev, __u32 number); +yaffs_Object *yaffs_FindObjectByNumber(yaffs_Device *dev, __u32 number);  /* Link operations */ -yaffs_Object *yaffs_Link(yaffs_Object * parent, const YCHAR * name, -			 yaffs_Object * equivalentObject); +yaffs_Object *yaffs_Link(yaffs_Object *parent, const YCHAR *name, +			 yaffs_Object *equivalentObject); -yaffs_Object *yaffs_GetEquivalentObject(yaffs_Object * obj); +yaffs_Object *yaffs_GetEquivalentObject(yaffs_Object *obj);  /* Symlink operations */ -yaffs_Object *yaffs_MknodSymLink(yaffs_Object * parent, const YCHAR * name, +yaffs_Object *yaffs_MknodSymLink(yaffs_Object *parent, const YCHAR *name,  				 __u32 mode, __u32 uid, __u32 gid, -				 const YCHAR * alias); -YCHAR *yaffs_GetSymlinkAlias(yaffs_Object * obj); +				 const YCHAR *alias); +YCHAR *yaffs_GetSymlinkAlias(yaffs_Object *obj);  /* Special inodes (fifos, sockets and devices) */ -yaffs_Object *yaffs_MknodSpecial(yaffs_Object * parent, const YCHAR * name, +yaffs_Object *yaffs_MknodSpecial(yaffs_Object *parent, const YCHAR *name,  				 __u32 mode, __u32 uid, __u32 gid, __u32 rdev);  /* Special directories */ -yaffs_Object *yaffs_Root(yaffs_Device * dev); -yaffs_Object *yaffs_LostNFound(yaffs_Device * dev); +yaffs_Object *yaffs_Root(yaffs_Device *dev); +yaffs_Object *yaffs_LostNFound(yaffs_Device *dev);  #ifdef CONFIG_YAFFS_WINCE  /* CONFIG_YAFFS_WINCE special stuff */ @@ -885,18 +884,21 @@ void yfsd_WinFileTimeNow(__u32 target[2]);  #ifdef __KERNEL__ -void yaffs_HandleDeferedFree(yaffs_Object * obj); +void yaffs_HandleDeferedFree(yaffs_Object *obj);  #endif  /* Debug dump  */ -int yaffs_DumpObject(yaffs_Object * obj); +int yaffs_DumpObject(yaffs_Object *obj); -void yaffs_GutsTest(yaffs_Device * dev); +void yaffs_GutsTest(yaffs_Device *dev);  /* A few useful functions */ -void yaffs_InitialiseTags(yaffs_ExtendedTags * tags); -void yaffs_DeleteChunk(yaffs_Device * dev, int chunkId, int markNAND, int lyn); -int yaffs_CheckFF(__u8 * buffer, int nBytes); +void yaffs_InitialiseTags(yaffs_ExtendedTags *tags); +void yaffs_DeleteChunk(yaffs_Device *dev, int chunkId, int markNAND, int lyn); +int yaffs_CheckFF(__u8 *buffer, int nBytes);  void yaffs_HandleChunkError(yaffs_Device *dev, yaffs_BlockInfo *bi); +__u8 *yaffs_GetTempBuffer(yaffs_Device *dev, int lineNo); +void yaffs_ReleaseTempBuffer(yaffs_Device *dev, __u8 *buffer, int lineNo); +  #endif diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_mtdif.c b/target/linux/generic/files/fs/yaffs2/yaffs_mtdif.c index 466e5a44c..306e18839 100644 --- a/target/linux/generic/files/fs/yaffs2/yaffs_mtdif.c +++ b/target/linux/generic/files/fs/yaffs2/yaffs_mtdif.c @@ -12,7 +12,7 @@   */  const char *yaffs_mtdif_c_version = -    "$Id: yaffs_mtdif.c,v 1.19 2007-02-14 01:09:06 wookey Exp $"; +	"$Id: yaffs_mtdif.c,v 1.22 2009-03-06 17:20:51 wookey Exp $";  #include "yportenv.h" @@ -24,7 +24,7 @@ const char *yaffs_mtdif_c_version =  #include "linux/time.h"  #include "linux/mtd/nand.h" -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)) +#if (MTD_VERSION_CODE < MTD_VERSION(2, 6, 18))  static struct nand_oobinfo yaffs_oobinfo = {  	.useecc = 1,  	.eccbytes = 6, @@ -36,7 +36,7 @@ static struct nand_oobinfo yaffs_noeccinfo = {  };  #endif -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) +#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17))  static inline void translate_spare2oob(const yaffs_Spare *spare, __u8 *oob)  {  	oob[0] = spare->tagByte0; @@ -45,8 +45,8 @@ static inline void translate_spare2oob(const yaffs_Spare *spare, __u8 *oob)  	oob[3] = spare->tagByte3;  	oob[4] = spare->tagByte4;  	oob[5] = spare->tagByte5 & 0x3f; -	oob[5] |= spare->blockStatus == 'Y' ? 0: 0x80; -	oob[5] |= spare->pageStatus == 0 ? 0: 0x40; +	oob[5] |= spare->blockStatus == 'Y' ? 0 : 0x80; +	oob[5] |= spare->pageStatus == 0 ? 0 : 0x40;  	oob[6] = spare->tagByte6;  	oob[7] = spare->tagByte7;  } @@ -71,18 +71,18 @@ static inline void translate_oob2spare(yaffs_Spare *spare, __u8 *oob)  }  #endif -int nandmtd_WriteChunkToNAND(yaffs_Device * dev, int chunkInNAND, -			     const __u8 * data, const yaffs_Spare * spare) +int nandmtd_WriteChunkToNAND(yaffs_Device *dev, int chunkInNAND, +			     const __u8 *data, const yaffs_Spare *spare)  {  	struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) +#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17))  	struct mtd_oob_ops ops;  #endif  	size_t dummy;  	int retval = 0;  	loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk; -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) +#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17))  	__u8 spareAsBytes[8]; /* OOB */  	if (data && !spare) @@ -135,18 +135,18 @@ int nandmtd_WriteChunkToNAND(yaffs_Device * dev, int chunkInNAND,  		return YAFFS_FAIL;  } -int nandmtd_ReadChunkFromNAND(yaffs_Device * dev, int chunkInNAND, __u8 * data, -			      yaffs_Spare * spare) +int nandmtd_ReadChunkFromNAND(yaffs_Device *dev, int chunkInNAND, __u8 *data, +			      yaffs_Spare *spare)  {  	struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) +#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17))  	struct mtd_oob_ops ops;  #endif  	size_t dummy;  	int retval = 0;  	loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk; -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) +#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17))  	__u8 spareAsBytes[8]; /* OOB */  	if (data && !spare) @@ -205,7 +205,7 @@ int nandmtd_ReadChunkFromNAND(yaffs_Device * dev, int chunkInNAND, __u8 * data,  		return YAFFS_FAIL;  } -int nandmtd_EraseBlockInNAND(yaffs_Device * dev, int blockNumber) +int nandmtd_EraseBlockInNAND(yaffs_Device *dev, int blockNumber)  {  	struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);  	__u32 addr = @@ -234,7 +234,7 @@ int nandmtd_EraseBlockInNAND(yaffs_Device * dev, int blockNumber)  		return YAFFS_FAIL;  } -int nandmtd_InitialiseNAND(yaffs_Device * dev) +int nandmtd_InitialiseNAND(yaffs_Device *dev)  {  	return YAFFS_OK;  } diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_mtdif.h b/target/linux/generic/files/fs/yaffs2/yaffs_mtdif.h index 317600cac..e72cfcddf 100644 --- a/target/linux/generic/files/fs/yaffs2/yaffs_mtdif.h +++ b/target/linux/generic/files/fs/yaffs2/yaffs_mtdif.h @@ -18,10 +18,15 @@  #include "yaffs_guts.h" -int nandmtd_WriteChunkToNAND(yaffs_Device * dev, int chunkInNAND, -			     const __u8 * data, const yaffs_Spare * spare); -int nandmtd_ReadChunkFromNAND(yaffs_Device * dev, int chunkInNAND, __u8 * data, -			      yaffs_Spare * spare); -int nandmtd_EraseBlockInNAND(yaffs_Device * dev, int blockNumber); -int nandmtd_InitialiseNAND(yaffs_Device * dev); +#if (MTD_VERSION_CODE < MTD_VERSION(2, 6, 18)) +extern struct nand_oobinfo yaffs_oobinfo; +extern struct nand_oobinfo yaffs_noeccinfo; +#endif + +int nandmtd_WriteChunkToNAND(yaffs_Device *dev, int chunkInNAND, +			const __u8 *data, const yaffs_Spare *spare); +int nandmtd_ReadChunkFromNAND(yaffs_Device *dev, int chunkInNAND, __u8 *data, +			yaffs_Spare *spare); +int nandmtd_EraseBlockInNAND(yaffs_Device *dev, int blockNumber); +int nandmtd_InitialiseNAND(yaffs_Device *dev);  #endif diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_mtdif1.c b/target/linux/generic/files/fs/yaffs2/yaffs_mtdif1.c index 36d5adec5..c069dfac7 100644 --- a/target/linux/generic/files/fs/yaffs2/yaffs_mtdif1.c +++ b/target/linux/generic/files/fs/yaffs2/yaffs_mtdif1.c @@ -26,7 +26,7 @@  #include "yportenv.h"  #include "yaffs_guts.h"  #include "yaffs_packedtags1.h" -#include "yaffs_tagscompat.h"	// for yaffs_CalcTagsECC +#include "yaffs_tagscompat.h"	/* for yaffs_CalcTagsECC */  #include "linux/kernel.h"  #include "linux/version.h" @@ -34,9 +34,9 @@  #include "linux/mtd/mtd.h"  /* Don't compile this module if we don't have MTD's mtd_oob_ops interface */ -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) +#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17)) -const char *yaffs_mtdif1_c_version = "$Id: yaffs_mtdif1.c,v 1.3 2007/05/15 20:16:11 ian Exp $"; +const char *yaffs_mtdif1_c_version = "$Id: yaffs_mtdif1.c,v 1.10 2009-03-09 07:41:10 charles Exp $";  #ifndef CONFIG_YAFFS_9BYTE_TAGS  # define YTAG1_SIZE 8 @@ -89,9 +89,9 @@ static struct nand_ecclayout nand_oob_16 = {   * Returns YAFFS_OK or YAFFS_FAIL.   */  int nandmtd1_WriteChunkWithTagsToNAND(yaffs_Device *dev, -	int chunkInNAND, const __u8 * data, const yaffs_ExtendedTags * etags) +	int chunkInNAND, const __u8 *data, const yaffs_ExtendedTags *etags)  { -	struct mtd_info * mtd = dev->genericDevice; +	struct mtd_info *mtd = dev->genericDevice;  	int chunkBytes = dev->nDataBytesPerChunk;  	loff_t addr = ((loff_t)chunkInNAND) * chunkBytes;  	struct mtd_oob_ops ops; @@ -146,7 +146,7 @@ int nandmtd1_WriteChunkWithTagsToNAND(yaffs_Device *dev,  /* Return with empty ExtendedTags but add eccResult.   */ -static int rettags(yaffs_ExtendedTags * etags, int eccResult, int retval) +static int rettags(yaffs_ExtendedTags *etags, int eccResult, int retval)  {  	if (etags) {  		memset(etags, 0, sizeof(*etags)); @@ -169,9 +169,9 @@ static int rettags(yaffs_ExtendedTags * etags, int eccResult, int retval)   * Returns YAFFS_OK or YAFFS_FAIL.   */  int nandmtd1_ReadChunkWithTagsFromNAND(yaffs_Device *dev, -	int chunkInNAND, __u8 * data, yaffs_ExtendedTags * etags) +	int chunkInNAND, __u8 *data, yaffs_ExtendedTags *etags)  { -	struct mtd_info * mtd = dev->genericDevice; +	struct mtd_info *mtd = dev->genericDevice;  	int chunkBytes = dev->nDataBytesPerChunk;  	loff_t addr = ((loff_t)chunkInNAND) * chunkBytes;  	int eccres = YAFFS_ECC_RESULT_NO_ERROR; @@ -189,7 +189,7 @@ int nandmtd1_ReadChunkWithTagsFromNAND(yaffs_Device *dev,  	ops.datbuf = data;  	ops.oobbuf = (__u8 *)&pt1; -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)) +#if (MTD_VERSION_CODE < MTD_VERSION(2, 6, 20))  	/* In MTD 2.6.18 to 2.6.19 nand_base.c:nand_do_read_oob() has a bug;  	 * help it out with ops.len = ops.ooblen when ops.datbuf == NULL.  	 */ @@ -284,11 +284,11 @@ int nandmtd1_ReadChunkWithTagsFromNAND(yaffs_Device *dev,   */  int nandmtd1_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo)  { -	struct mtd_info * mtd = dev->genericDevice; +	struct mtd_info *mtd = dev->genericDevice;  	int blocksize = dev->nChunksPerBlock * dev->nDataBytesPerChunk;  	int retval; -	yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, "marking block %d bad", blockNo); +	yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, "marking block %d bad\n", blockNo);  	retval = mtd->block_markbad(mtd, (loff_t)blocksize * blockNo);  	return (retval) ? YAFFS_FAIL : YAFFS_OK; @@ -298,7 +298,7 @@ int nandmtd1_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo)   *   * Returns YAFFS_OK or YAFFS_FAIL.   */ -static int nandmtd1_TestPrerequists(struct mtd_info * mtd) +static int nandmtd1_TestPrerequists(struct mtd_info *mtd)  {  	/* 2.6.18 has mtd->ecclayout->oobavail */  	/* 2.6.21 has mtd->ecclayout->oobavail and mtd->oobavail */ @@ -323,10 +323,11 @@ static int nandmtd1_TestPrerequists(struct mtd_info * mtd)   * Always returns YAFFS_OK.   */  int nandmtd1_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, -	yaffs_BlockState * pState, int *pSequenceNumber) +	yaffs_BlockState *pState, __u32 *pSequenceNumber)  { -	struct mtd_info * mtd = dev->genericDevice; +	struct mtd_info *mtd = dev->genericDevice;  	int chunkNo = blockNo * dev->nChunksPerBlock; +	loff_t addr = (loff_t)chunkNo * dev->nDataBytesPerChunk;  	yaffs_ExtendedTags etags;  	int state = YAFFS_BLOCK_STATE_DEAD;  	int seqnum = 0; @@ -335,21 +336,22 @@ int nandmtd1_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,  	/* We don't yet have a good place to test for MTD config prerequists.  	 * Do it here as we are called during the initial scan.  	 */ -	if (nandmtd1_TestPrerequists(mtd) != YAFFS_OK) { +	if (nandmtd1_TestPrerequists(mtd) != YAFFS_OK)  		return YAFFS_FAIL; -	}  	retval = nandmtd1_ReadChunkWithTagsFromNAND(dev, chunkNo, NULL, &etags); +	etags.blockBad = (mtd->block_isbad)(mtd, addr);  	if (etags.blockBad) {  		yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, -			"block %d is marked bad", blockNo); +			"block %d is marked bad\n", blockNo);  		state = YAFFS_BLOCK_STATE_DEAD; -	} -	else if (etags.chunkUsed) { +	} else if (etags.eccResult != YAFFS_ECC_RESULT_NO_ERROR) { +		/* bad tags, need to look more closely */ +		state = YAFFS_BLOCK_STATE_NEEDS_SCANNING; +	} else if (etags.chunkUsed) {  		state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;  		seqnum = etags.sequenceNumber; -	} -	else { +	} else {  		state = YAFFS_BLOCK_STATE_EMPTY;  	} @@ -360,4 +362,4 @@ int nandmtd1_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,  	return YAFFS_OK;  } -#endif /*KERNEL_VERSION*/ +#endif /*MTD_VERSION*/ diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_mtdif1.h b/target/linux/generic/files/fs/yaffs2/yaffs_mtdif1.h index c4f6197d6..240202cdf 100644 --- a/target/linux/generic/files/fs/yaffs2/yaffs_mtdif1.h +++ b/target/linux/generic/files/fs/yaffs2/yaffs_mtdif1.h @@ -14,15 +14,15 @@  #ifndef __YAFFS_MTDIF1_H__  #define __YAFFS_MTDIF1_H__ -int nandmtd1_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND, -	const __u8 * data, const yaffs_ExtendedTags * tags); +int nandmtd1_WriteChunkWithTagsToNAND(yaffs_Device *dev, int chunkInNAND, +	const __u8 *data, const yaffs_ExtendedTags *tags); -int nandmtd1_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND, -	__u8 * data, yaffs_ExtendedTags * tags); +int nandmtd1_ReadChunkWithTagsFromNAND(yaffs_Device *dev, int chunkInNAND, +	__u8 *data, yaffs_ExtendedTags *tags);  int nandmtd1_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo);  int nandmtd1_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, -	yaffs_BlockState * state, int *sequenceNumber); +	yaffs_BlockState *state, __u32 *sequenceNumber);  #endif diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_mtdif2.c b/target/linux/generic/files/fs/yaffs2/yaffs_mtdif2.c index cdad0734b..77504babb 100644 --- a/target/linux/generic/files/fs/yaffs2/yaffs_mtdif2.c +++ b/target/linux/generic/files/fs/yaffs2/yaffs_mtdif2.c @@ -14,7 +14,7 @@  /* mtd interface for YAFFS2 */  const char *yaffs_mtdif2_c_version = -    "$Id: yaffs_mtdif2.c,v 1.17 2007-02-14 01:09:06 wookey Exp $"; +	"$Id: yaffs_mtdif2.c,v 1.23 2009-03-06 17:20:53 wookey Exp $";  #include "yportenv.h" @@ -27,19 +27,23 @@ const char *yaffs_mtdif2_c_version =  #include "yaffs_packedtags2.h" -int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND, -				      const __u8 * data, -				      const yaffs_ExtendedTags * tags) +/* NB For use with inband tags.... + * We assume that the data buffer is of size totalBytersPerChunk so that we can also + * use it to load the tags. + */ +int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device *dev, int chunkInNAND, +				      const __u8 *data, +				      const yaffs_ExtendedTags *tags)  {  	struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) +#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17))  	struct mtd_oob_ops ops;  #else  	size_t dummy;  #endif  	int retval = 0; -	loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk; +	loff_t addr;  	yaffs_PackedTags2 pt; @@ -48,46 +52,40 @@ int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND,  	   ("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p"  	    TENDSTR), chunkInNAND, data, tags)); -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -	if (tags) -		yaffs_PackTags2(&pt, tags); -	else -		BUG(); /* both tags and data should always be present */ -	if (data) { -		ops.mode = MTD_OOB_AUTO; -		ops.ooblen = sizeof(pt); -		ops.len = dev->nDataBytesPerChunk; -		ops.ooboffs = 0; -		ops.datbuf = (__u8 *)data; -		ops.oobbuf = (void *)&pt; -		retval = mtd->write_oob(mtd, addr, &ops); +	addr  = ((loff_t) chunkInNAND) * dev->totalBytesPerChunk; + +	/* For yaffs2 writing there must be both data and tags. +	 * If we're using inband tags, then the tags are stuffed into +	 * the end of the data buffer. +	 */ +	if (!data || !tags) +		BUG(); +	else if (dev->inbandTags) { +		yaffs_PackedTags2TagsPart *pt2tp; +		pt2tp = (yaffs_PackedTags2TagsPart *)(data + dev->nDataBytesPerChunk); +		yaffs_PackTags2TagsPart(pt2tp, tags);  	} else -		BUG(); /* both tags and data should always be present */ -#else -	if (tags) {  		yaffs_PackTags2(&pt, tags); -	} -	if (data && tags) { -		if (dev->useNANDECC) -			retval = -			    mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk, -					   &dummy, data, (__u8 *) & pt, NULL); -		else -			retval = -			    mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk, -					   &dummy, data, (__u8 *) & pt, NULL); -	} else { -		if (data) -			retval = -			    mtd->write(mtd, addr, dev->nDataBytesPerChunk, &dummy, -				       data); -		if (tags) -			retval = -			    mtd->write_oob(mtd, addr, mtd->oobsize, &dummy, -					   (__u8 *) & pt); +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) +	ops.mode = MTD_OOB_AUTO; +	ops.ooblen = (dev->inbandTags) ? 0 : sizeof(pt); +	ops.len = dev->totalBytesPerChunk; +	ops.ooboffs = 0; +	ops.datbuf = (__u8 *)data; +	ops.oobbuf = (dev->inbandTags) ? NULL : (void *)&pt; +	retval = mtd->write_oob(mtd, addr, &ops); +#else +	if (!dev->inbandTags) { +		retval = +		    mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk, +				   &dummy, data, (__u8 *) &pt, NULL); +	} else { +		retval = +		    mtd->write(mtd, addr, dev->totalBytesPerChunk, &dummy, +			       data);  	}  #endif @@ -97,17 +95,18 @@ int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND,  		return YAFFS_FAIL;  } -int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND, -				       __u8 * data, yaffs_ExtendedTags * tags) +int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device *dev, int chunkInNAND, +				       __u8 *data, yaffs_ExtendedTags *tags)  {  	struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice); -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) +#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17))  	struct mtd_oob_ops ops;  #endif  	size_t dummy;  	int retval = 0; +	int localData = 0; -	loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk; +	loff_t addr = ((loff_t) chunkInNAND) * dev->totalBytesPerChunk;  	yaffs_PackedTags2 pt; @@ -116,9 +115,20 @@ int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,  	   ("nandmtd2_ReadChunkWithTagsFromNAND chunk %d data %p tags %p"  	    TENDSTR), chunkInNAND, data, tags)); -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17)) -	if (data && !tags) -		retval = mtd->read(mtd, addr, dev->nDataBytesPerChunk, +	if (dev->inbandTags) { + +		if (!data) { +			localData = 1; +			data = yaffs_GetTempBuffer(dev, __LINE__); +		} + + +	} + + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) +	if (dev->inbandTags || (data && !tags)) +		retval = mtd->read(mtd, addr, dev->totalBytesPerChunk,  				&dummy, data);  	else if (tags) {  		ops.mode = MTD_OOB_AUTO; @@ -130,38 +140,42 @@ int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,  		retval = mtd->read_oob(mtd, addr, &ops);  	}  #else -	if (data && tags) { -		if (dev->useNANDECC) { -			retval = -			    mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk, -					  &dummy, data, dev->spareBuffer, -					  NULL); -		} else { -			retval = -			    mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk, +	if (!dev->inbandTags && data && tags) { + +		retval = mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,  					  &dummy, data, dev->spareBuffer,  					  NULL); -		}  	} else {  		if (data)  			retval =  			    mtd->read(mtd, addr, dev->nDataBytesPerChunk, &dummy,  				      data); -		if (tags) +		if (!dev->inbandTags && tags)  			retval =  			    mtd->read_oob(mtd, addr, mtd->oobsize, &dummy,  					  dev->spareBuffer);  	}  #endif -	memcpy(&pt, dev->spareBuffer, sizeof(pt)); -	if (tags) -		yaffs_UnpackTags2(tags, &pt); +	if (dev->inbandTags) { +		if (tags) { +			yaffs_PackedTags2TagsPart *pt2tp; +			pt2tp = (yaffs_PackedTags2TagsPart *)&data[dev->nDataBytesPerChunk]; +			yaffs_UnpackTags2TagsPart(tags, pt2tp); +		} +	} else { +		if (tags) { +			memcpy(&pt, dev->spareBuffer, sizeof(pt)); +			yaffs_UnpackTags2(tags, &pt); +		} +	} -	if(tags && retval == -EBADMSG && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR) -		tags->eccResult = YAFFS_ECC_RESULT_UNFIXED; +	if (localData) +		yaffs_ReleaseTempBuffer(dev, data, __LINE__); +	if (tags && retval == -EBADMSG && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR) +		tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;  	if (retval == 0)  		return YAFFS_OK;  	else @@ -178,7 +192,7 @@ int nandmtd2_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo)  	retval =  	    mtd->block_markbad(mtd,  			       blockNo * dev->nChunksPerBlock * -			       dev->nDataBytesPerChunk); +			       dev->totalBytesPerChunk);  	if (retval == 0)  		return YAFFS_OK; @@ -188,7 +202,7 @@ int nandmtd2_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo)  }  int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, -			    yaffs_BlockState * state, int *sequenceNumber) +			    yaffs_BlockState *state, __u32 *sequenceNumber)  {  	struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);  	int retval; @@ -198,7 +212,7 @@ int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,  	retval =  	    mtd->block_isbad(mtd,  			     blockNo * dev->nChunksPerBlock * -			     dev->nDataBytesPerChunk); +			     dev->totalBytesPerChunk);  	if (retval) {  		T(YAFFS_TRACE_MTD, (TSTR("block is bad" TENDSTR))); diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_mtdif2.h b/target/linux/generic/files/fs/yaffs2/yaffs_mtdif2.h index b67ba52aa..b5ff07881 100644 --- a/target/linux/generic/files/fs/yaffs2/yaffs_mtdif2.h +++ b/target/linux/generic/files/fs/yaffs2/yaffs_mtdif2.h @@ -17,13 +17,13 @@  #define __YAFFS_MTDIF2_H__  #include "yaffs_guts.h" -int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND, -				      const __u8 * data, -				      const yaffs_ExtendedTags * tags); -int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND, -				       __u8 * data, yaffs_ExtendedTags * tags); +int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device *dev, int chunkInNAND, +				const __u8 *data, +				const yaffs_ExtendedTags *tags); +int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device *dev, int chunkInNAND, +				__u8 *data, yaffs_ExtendedTags *tags);  int nandmtd2_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo);  int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, -			    yaffs_BlockState * state, int *sequenceNumber); +			yaffs_BlockState *state, __u32 *sequenceNumber);  #endif diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_nand.c b/target/linux/generic/files/fs/yaffs2/yaffs_nand.c index 4e250338d..bd815cb7a 100644 --- a/target/linux/generic/files/fs/yaffs2/yaffs_nand.c +++ b/target/linux/generic/files/fs/yaffs2/yaffs_nand.c @@ -12,16 +12,17 @@   */  const char *yaffs_nand_c_version = -    "$Id: yaffs_nand.c,v 1.7 2007-02-14 01:09:06 wookey Exp $"; +	"$Id: yaffs_nand.c,v 1.10 2009-03-06 17:20:54 wookey Exp $";  #include "yaffs_nand.h"  #include "yaffs_tagscompat.h"  #include "yaffs_tagsvalidity.h" +#include "yaffs_getblockinfo.h" -int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND, -					   __u8 * buffer, -					   yaffs_ExtendedTags * tags) +int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device *dev, int chunkInNAND, +					   __u8 *buffer, +					   yaffs_ExtendedTags *tags)  {  	int result;  	yaffs_ExtendedTags localTags; @@ -29,7 +30,7 @@ int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,  	int realignedChunkInNAND = chunkInNAND - dev->chunkOffset;  	/* If there are no tags provided, use local tags to get prioritised gc working */ -	if(!tags) +	if (!tags)  		tags = &localTags;  	if (dev->readChunkWithTagsFromNAND) @@ -40,20 +41,20 @@ int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,  									realignedChunkInNAND,  									buffer,  									tags); -	if(tags && -	   tags->eccResult > YAFFS_ECC_RESULT_NO_ERROR){ +	if (tags && +	   tags->eccResult > YAFFS_ECC_RESULT_NO_ERROR) {  		yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, chunkInNAND/dev->nChunksPerBlock); -                yaffs_HandleChunkError(dev,bi); +		yaffs_HandleChunkError(dev, bi);  	}  	return result;  } -int yaffs_WriteChunkWithTagsToNAND(yaffs_Device * dev, +int yaffs_WriteChunkWithTagsToNAND(yaffs_Device *dev,  						   int chunkInNAND, -						   const __u8 * buffer, -						   yaffs_ExtendedTags * tags) +						   const __u8 *buffer, +						   yaffs_ExtendedTags *tags)  {  	chunkInNAND -= dev->chunkOffset; @@ -84,7 +85,7 @@ int yaffs_WriteChunkWithTagsToNAND(yaffs_Device * dev,  								       tags);  } -int yaffs_MarkBlockBad(yaffs_Device * dev, int blockNo) +int yaffs_MarkBlockBad(yaffs_Device *dev, int blockNo)  {  	blockNo -= dev->blockOffset; @@ -95,10 +96,10 @@ int yaffs_MarkBlockBad(yaffs_Device * dev, int blockNo)  		return yaffs_TagsCompatabilityMarkNANDBlockBad(dev, blockNo);  } -int yaffs_QueryInitialBlockState(yaffs_Device * dev, +int yaffs_QueryInitialBlockState(yaffs_Device *dev,  						 int blockNo, -						 yaffs_BlockState * state, -						 unsigned *sequenceNumber) +						 yaffs_BlockState *state, +						 __u32 *sequenceNumber)  {  	blockNo -= dev->blockOffset; diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_nand.h b/target/linux/generic/files/fs/yaffs2/yaffs_nand.h index 5fa334bdc..e013cdc2f 100644 --- a/target/linux/generic/files/fs/yaffs2/yaffs_nand.h +++ b/target/linux/generic/files/fs/yaffs2/yaffs_nand.h @@ -19,21 +19,21 @@ -int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND, -					   __u8 * buffer, -					   yaffs_ExtendedTags * tags); +int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device *dev, int chunkInNAND, +					__u8 *buffer, +					yaffs_ExtendedTags *tags); -int yaffs_WriteChunkWithTagsToNAND(yaffs_Device * dev, -						   int chunkInNAND, -						   const __u8 * buffer, -						   yaffs_ExtendedTags * tags); +int yaffs_WriteChunkWithTagsToNAND(yaffs_Device *dev, +						int chunkInNAND, +						const __u8 *buffer, +						yaffs_ExtendedTags *tags); -int yaffs_MarkBlockBad(yaffs_Device * dev, int blockNo); +int yaffs_MarkBlockBad(yaffs_Device *dev, int blockNo); -int yaffs_QueryInitialBlockState(yaffs_Device * dev, -						 int blockNo, -						 yaffs_BlockState * state, -						 unsigned *sequenceNumber); +int yaffs_QueryInitialBlockState(yaffs_Device *dev, +						int blockNo, +						yaffs_BlockState *state, +						unsigned *sequenceNumber);  int yaffs_EraseBlockInNAND(struct yaffs_DeviceStruct *dev,  				  int blockInNAND); diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_nandemul2k.h b/target/linux/generic/files/fs/yaffs2/yaffs_nandemul2k.h index cd2e96f7a..41bc2b5f8 100644 --- a/target/linux/generic/files/fs/yaffs2/yaffs_nandemul2k.h +++ b/target/linux/generic/files/fs/yaffs2/yaffs_nandemul2k.h @@ -21,14 +21,14 @@  #include "yaffs_guts.h"  int nandemul2k_WriteChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev, -					int chunkInNAND, const __u8 * data, -					yaffs_ExtendedTags * tags); +					int chunkInNAND, const __u8 *data, +					const yaffs_ExtendedTags *tags);  int nandemul2k_ReadChunkWithTagsFromNAND(struct yaffs_DeviceStruct *dev, -					 int chunkInNAND, __u8 * data, -					 yaffs_ExtendedTags * tags); +					 int chunkInNAND, __u8 *data, +					 yaffs_ExtendedTags *tags);  int nandemul2k_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo);  int nandemul2k_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, -			      yaffs_BlockState * state, int *sequenceNumber); +			      yaffs_BlockState *state, __u32 *sequenceNumber);  int nandemul2k_EraseBlockInNAND(struct yaffs_DeviceStruct *dev,  				int blockInNAND);  int nandemul2k_InitialiseNAND(struct yaffs_DeviceStruct *dev); diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_packedtags1.c b/target/linux/generic/files/fs/yaffs2/yaffs_packedtags1.c index f480bf1df..3e67e6916 100644 --- a/target/linux/generic/files/fs/yaffs2/yaffs_packedtags1.c +++ b/target/linux/generic/files/fs/yaffs2/yaffs_packedtags1.c @@ -14,7 +14,7 @@  #include "yaffs_packedtags1.h"  #include "yportenv.h" -void yaffs_PackTags1(yaffs_PackedTags1 * pt, const yaffs_ExtendedTags * t) +void yaffs_PackTags1(yaffs_PackedTags1 *pt, const yaffs_ExtendedTags *t)  {  	pt->chunkId = t->chunkId;  	pt->serialNumber = t->serialNumber; @@ -27,7 +27,7 @@ void yaffs_PackTags1(yaffs_PackedTags1 * pt, const yaffs_ExtendedTags * t)  } -void yaffs_UnpackTags1(yaffs_ExtendedTags * t, const yaffs_PackedTags1 * pt) +void yaffs_UnpackTags1(yaffs_ExtendedTags *t, const yaffs_PackedTags1 *pt)  {  	static const __u8 allFF[] =  	    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, @@ -35,9 +35,8 @@ void yaffs_UnpackTags1(yaffs_ExtendedTags * t, const yaffs_PackedTags1 * pt)  	if (memcmp(allFF, pt, sizeof(yaffs_PackedTags1))) {  		t->blockBad = 0; -		if (pt->shouldBeFF != 0xFFFFFFFF) { +		if (pt->shouldBeFF != 0xFFFFFFFF)  			t->blockBad = 1; -		}  		t->chunkUsed = 1;  		t->objectId = pt->objectId;  		t->chunkId = pt->chunkId; @@ -47,6 +46,5 @@ void yaffs_UnpackTags1(yaffs_ExtendedTags * t, const yaffs_PackedTags1 * pt)  		t->serialNumber = pt->serialNumber;  	} else {  		memset(t, 0, sizeof(yaffs_ExtendedTags)); -  	}  } diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_packedtags1.h b/target/linux/generic/files/fs/yaffs2/yaffs_packedtags1.h index 776c5c256..f8c0471d4 100644 --- a/target/linux/generic/files/fs/yaffs2/yaffs_packedtags1.h +++ b/target/linux/generic/files/fs/yaffs2/yaffs_packedtags1.h @@ -32,6 +32,6 @@ typedef struct {  } yaffs_PackedTags1; -void yaffs_PackTags1(yaffs_PackedTags1 * pt, const yaffs_ExtendedTags * t); -void yaffs_UnpackTags1(yaffs_ExtendedTags * t, const yaffs_PackedTags1 * pt); +void yaffs_PackTags1(yaffs_PackedTags1 *pt, const yaffs_ExtendedTags *t); +void yaffs_UnpackTags1(yaffs_ExtendedTags *t, const yaffs_PackedTags1 *pt);  #endif diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_packedtags2.c b/target/linux/generic/files/fs/yaffs2/yaffs_packedtags2.c index e420f95da..a78c03c9d 100644 --- a/target/linux/generic/files/fs/yaffs2/yaffs_packedtags2.c +++ b/target/linux/generic/files/fs/yaffs2/yaffs_packedtags2.c @@ -37,60 +37,68 @@  #define EXTRA_OBJECT_TYPE_SHIFT (28)  #define EXTRA_OBJECT_TYPE_MASK  ((0x0F) << EXTRA_OBJECT_TYPE_SHIFT) -static void yaffs_DumpPackedTags2(const yaffs_PackedTags2 * pt) + +static void yaffs_DumpPackedTags2TagsPart(const yaffs_PackedTags2TagsPart *ptt)  {  	T(YAFFS_TRACE_MTD,  	  (TSTR("packed tags obj %d chunk %d byte %d seq %d" TENDSTR), -	   pt->t.objectId, pt->t.chunkId, pt->t.byteCount, -	   pt->t.sequenceNumber)); +	   ptt->objectId, ptt->chunkId, ptt->byteCount, +	   ptt->sequenceNumber)); +} +static void yaffs_DumpPackedTags2(const yaffs_PackedTags2 *pt) +{ +	yaffs_DumpPackedTags2TagsPart(&pt->t);  } -static void yaffs_DumpTags2(const yaffs_ExtendedTags * t) +static void yaffs_DumpTags2(const yaffs_ExtendedTags *t)  {  	T(YAFFS_TRACE_MTD,  	  (TSTR -	   ("ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte " -	    "%d del %d ser %d seq %d" +	   ("ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte %d del %d ser %d seq %d"  	    TENDSTR), t->eccResult, t->blockBad, t->chunkUsed, t->objectId,  	   t->chunkId, t->byteCount, t->chunkDeleted, t->serialNumber,  	   t->sequenceNumber));  } -void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags * t) +void yaffs_PackTags2TagsPart(yaffs_PackedTags2TagsPart *ptt, +		const yaffs_ExtendedTags *t)  { -	pt->t.chunkId = t->chunkId; -	pt->t.sequenceNumber = t->sequenceNumber; -	pt->t.byteCount = t->byteCount; -	pt->t.objectId = t->objectId; +	ptt->chunkId = t->chunkId; +	ptt->sequenceNumber = t->sequenceNumber; +	ptt->byteCount = t->byteCount; +	ptt->objectId = t->objectId;  	if (t->chunkId == 0 && t->extraHeaderInfoAvailable) {  		/* Store the extra header info instead */  		/* We save the parent object in the chunkId */ -		pt->t.chunkId = EXTRA_HEADER_INFO_FLAG +		ptt->chunkId = EXTRA_HEADER_INFO_FLAG  			| t->extraParentObjectId; -		if (t->extraIsShrinkHeader) { -			pt->t.chunkId |= EXTRA_SHRINK_FLAG; -		} -		if (t->extraShadows) { -			pt->t.chunkId |= EXTRA_SHADOWS_FLAG; -		} +		if (t->extraIsShrinkHeader) +			ptt->chunkId |= EXTRA_SHRINK_FLAG; +		if (t->extraShadows) +			ptt->chunkId |= EXTRA_SHADOWS_FLAG; -		pt->t.objectId &= ~EXTRA_OBJECT_TYPE_MASK; -		pt->t.objectId |= +		ptt->objectId &= ~EXTRA_OBJECT_TYPE_MASK; +		ptt->objectId |=  		    (t->extraObjectType << EXTRA_OBJECT_TYPE_SHIFT); -		if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) { -			pt->t.byteCount = t->extraEquivalentObjectId; -		} else if (t->extraObjectType == YAFFS_OBJECT_TYPE_FILE) { -			pt->t.byteCount = t->extraFileLength; -		} else { -			pt->t.byteCount = 0; -		} +		if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) +			ptt->byteCount = t->extraEquivalentObjectId; +		else if (t->extraObjectType == YAFFS_OBJECT_TYPE_FILE) +			ptt->byteCount = t->extraFileLength; +		else +			ptt->byteCount = 0;  	} -	yaffs_DumpPackedTags2(pt); +	yaffs_DumpPackedTags2TagsPart(ptt);  	yaffs_DumpTags2(t); +} + + +void yaffs_PackTags2(yaffs_PackedTags2 *pt, const yaffs_ExtendedTags *t) +{ +	yaffs_PackTags2TagsPart(&pt->t, t);  #ifndef YAFFS_IGNORE_TAGS_ECC  	{ @@ -101,82 +109,98 @@ void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags * t)  #endif  } -void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt) + +void yaffs_UnpackTags2TagsPart(yaffs_ExtendedTags *t, +		yaffs_PackedTags2TagsPart *ptt)  {  	memset(t, 0, sizeof(yaffs_ExtendedTags));  	yaffs_InitialiseTags(t); -	if (pt->t.sequenceNumber != 0xFFFFFFFF) { -		/* Page is in use */ -#ifdef YAFFS_IGNORE_TAGS_ECC -		{ -			t->eccResult = YAFFS_ECC_RESULT_NO_ERROR; -		} -#else -		{ -			yaffs_ECCOther ecc; -			int result; -			yaffs_ECCCalculateOther((unsigned char *)&pt->t, -						sizeof -						(yaffs_PackedTags2TagsPart), -						&ecc); -			result = -			    yaffs_ECCCorrectOther((unsigned char *)&pt->t, -						  sizeof -						  (yaffs_PackedTags2TagsPart), -						  &pt->ecc, &ecc); -			switch(result){ -				case 0: -					t->eccResult = YAFFS_ECC_RESULT_NO_ERROR; -					break; -				case 1: -					t->eccResult = YAFFS_ECC_RESULT_FIXED; -					break; -				case -1: -					t->eccResult = YAFFS_ECC_RESULT_UNFIXED; -					break; -				default: -					t->eccResult = YAFFS_ECC_RESULT_UNKNOWN; -			} -		} -#endif +	if (ptt->sequenceNumber != 0xFFFFFFFF) {  		t->blockBad = 0;  		t->chunkUsed = 1; -		t->objectId = pt->t.objectId; -		t->chunkId = pt->t.chunkId; -		t->byteCount = pt->t.byteCount; +		t->objectId = ptt->objectId; +		t->chunkId = ptt->chunkId; +		t->byteCount = ptt->byteCount;  		t->chunkDeleted = 0;  		t->serialNumber = 0; -		t->sequenceNumber = pt->t.sequenceNumber; +		t->sequenceNumber = ptt->sequenceNumber;  		/* Do extra header info stuff */ -		if (pt->t.chunkId & EXTRA_HEADER_INFO_FLAG) { +		if (ptt->chunkId & EXTRA_HEADER_INFO_FLAG) {  			t->chunkId = 0;  			t->byteCount = 0;  			t->extraHeaderInfoAvailable = 1;  			t->extraParentObjectId = -			    pt->t.chunkId & (~(ALL_EXTRA_FLAGS)); +			    ptt->chunkId & (~(ALL_EXTRA_FLAGS));  			t->extraIsShrinkHeader = -			    (pt->t.chunkId & EXTRA_SHRINK_FLAG) ? 1 : 0; +			    (ptt->chunkId & EXTRA_SHRINK_FLAG) ? 1 : 0;  			t->extraShadows = -			    (pt->t.chunkId & EXTRA_SHADOWS_FLAG) ? 1 : 0; +			    (ptt->chunkId & EXTRA_SHADOWS_FLAG) ? 1 : 0;  			t->extraObjectType = -			    pt->t.objectId >> EXTRA_OBJECT_TYPE_SHIFT; +			    ptt->objectId >> EXTRA_OBJECT_TYPE_SHIFT;  			t->objectId &= ~EXTRA_OBJECT_TYPE_MASK; -			if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) { -				t->extraEquivalentObjectId = pt->t.byteCount; -			} else { -				t->extraFileLength = pt->t.byteCount; +			if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) +				t->extraEquivalentObjectId = ptt->byteCount; +			else +				t->extraFileLength = ptt->byteCount; +		} +	} + +	yaffs_DumpPackedTags2TagsPart(ptt); +	yaffs_DumpTags2(t); + +} + + +void yaffs_UnpackTags2(yaffs_ExtendedTags *t, yaffs_PackedTags2 *pt) +{ + +	yaffs_ECCResult eccResult = YAFFS_ECC_RESULT_NO_ERROR; + +	if (pt->t.sequenceNumber != 0xFFFFFFFF) { +		/* Page is in use */ +#ifndef YAFFS_IGNORE_TAGS_ECC +		{ +			yaffs_ECCOther ecc; +			int result; +			yaffs_ECCCalculateOther((unsigned char *)&pt->t, +						sizeof +						(yaffs_PackedTags2TagsPart), +						&ecc); +			result = +			    yaffs_ECCCorrectOther((unsigned char *)&pt->t, +						  sizeof +						  (yaffs_PackedTags2TagsPart), +						  &pt->ecc, &ecc); +			switch (result) { +			case 0: +				eccResult = YAFFS_ECC_RESULT_NO_ERROR; +				break; +			case 1: +				eccResult = YAFFS_ECC_RESULT_FIXED; +				break; +			case -1: +				eccResult = YAFFS_ECC_RESULT_UNFIXED; +				break; +			default: +				eccResult = YAFFS_ECC_RESULT_UNKNOWN;  			}  		} +#endif  	} +	yaffs_UnpackTags2TagsPart(t, &pt->t); + +	t->eccResult = eccResult; +  	yaffs_DumpPackedTags2(pt);  	yaffs_DumpTags2(t);  } + diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_packedtags2.h b/target/linux/generic/files/fs/yaffs2/yaffs_packedtags2.h index c2242ffe7..ec30f843b 100644 --- a/target/linux/generic/files/fs/yaffs2/yaffs_packedtags2.h +++ b/target/linux/generic/files/fs/yaffs2/yaffs_packedtags2.h @@ -33,6 +33,11 @@ typedef struct {  	yaffs_ECCOther ecc;  } yaffs_PackedTags2; -void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags * t); -void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt); +/* Full packed tags with ECC, used for oob tags */ +void yaffs_PackTags2(yaffs_PackedTags2 *pt, const yaffs_ExtendedTags *t); +void yaffs_UnpackTags2(yaffs_ExtendedTags *t, yaffs_PackedTags2 *pt); + +/* Only the tags part (no ECC for use with inband tags */ +void yaffs_PackTags2TagsPart(yaffs_PackedTags2TagsPart *pt, const yaffs_ExtendedTags *t); +void yaffs_UnpackTags2TagsPart(yaffs_ExtendedTags *t, yaffs_PackedTags2TagsPart *pt);  #endif diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_qsort.c b/target/linux/generic/files/fs/yaffs2/yaffs_qsort.c index 474be9cea..187519fbd 100644 --- a/target/linux/generic/files/fs/yaffs2/yaffs_qsort.c +++ b/target/linux/generic/files/fs/yaffs2/yaffs_qsort.c @@ -28,12 +28,12 @@   */  #include "yportenv.h" -//#include <linux/string.h> +/* #include <linux/string.h> */  /*   * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".   */ -#define swapcode(TYPE, parmi, parmj, n) { 		\ +#define swapcode(TYPE, parmi, parmj, n) do { 		\  	long i = (n) / sizeof (TYPE); 			\  	register TYPE *pi = (TYPE *) (parmi); 		\  	register TYPE *pj = (TYPE *) (parmj); 		\ @@ -41,28 +41,29 @@  		register TYPE	t = *pi;		\  		*pi++ = *pj;				\  		*pj++ = t;				\ -        } while (--i > 0);				\ -} +	} while (--i > 0);				\ +} while (0)  #define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \ -	es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1; +	es % sizeof(long) ? 2 : es == sizeof(long) ? 0 : 1;  static __inline void  swapfunc(char *a, char *b, int n, int swaptype)  {  	if (swaptype <= 1) -		swapcode(long, a, b, n) +		swapcode(long, a, b, n);  	else -		swapcode(char, a, b, n) +		swapcode(char, a, b, n);  } -#define swap(a, b)					\ +#define yswap(a, b) do {					\  	if (swaptype == 0) {				\  		long t = *(long *)(a);			\  		*(long *)(a) = *(long *)(b);		\  		*(long *)(b) = t;			\  	} else						\ -		swapfunc(a, b, es, swaptype) +		swapfunc(a, b, es, swaptype);		\ +} while (0)  #define vecswap(a, b, n) 	if ((n) > 0) swapfunc(a, b, n, swaptype) @@ -70,12 +71,12 @@ static __inline char *  med3(char *a, char *b, char *c, int (*cmp)(const void *, const void *))  {  	return cmp(a, b) < 0 ? -	       (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a )) -              :(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c )); +		(cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a)) +		: (cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c));  }  #ifndef min -#define min(a,b) (((a) < (b)) ? (a) : (b)) +#define min(a, b) (((a) < (b)) ? (a) : (b))  #endif  void @@ -92,7 +93,7 @@ loop:	SWAPINIT(a, es);  		for (pm = (char *)a + es; pm < (char *) a + n * es; pm += es)  			for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;  			     pl -= es) -				swap(pl, pl - es); +				yswap(pl, pl - es);  		return;  	}  	pm = (char *)a + (n / 2) * es; @@ -107,7 +108,7 @@ loop:	SWAPINIT(a, es);  		}  		pm = med3(pl, pm, pn, cmp);  	} -	swap(a, pm); +	yswap(a, pm);  	pa = pb = (char *)a + es;  	pc = pd = (char *)a + (n - 1) * es; @@ -115,7 +116,7 @@ loop:	SWAPINIT(a, es);  		while (pb <= pc && (r = cmp(pb, a)) <= 0) {  			if (r == 0) {  				swap_cnt = 1; -				swap(pa, pb); +				yswap(pa, pb);  				pa += es;  			}  			pb += es; @@ -123,14 +124,14 @@ loop:	SWAPINIT(a, es);  		while (pb <= pc && (r = cmp(pc, a)) >= 0) {  			if (r == 0) {  				swap_cnt = 1; -				swap(pc, pd); +				yswap(pc, pd);  				pd -= es;  			}  			pc -= es;  		}  		if (pb > pc)  			break; -		swap(pb, pc); +		yswap(pb, pc);  		swap_cnt = 1;  		pb += es;  		pc -= es; @@ -139,7 +140,7 @@ loop:	SWAPINIT(a, es);  		for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)  			for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;  			     pl -= es) -				swap(pl, pl - es); +				yswap(pl, pl - es);  		return;  	} @@ -148,9 +149,11 @@ loop:	SWAPINIT(a, es);  	vecswap(a, pb - r, r);  	r = min((long)(pd - pc), (long)(pn - pd - es));  	vecswap(pb, pn - r, r); -	if ((r = pb - pa) > es) +	r = pb - pa; +	if (r > es)  		yaffs_qsort(a, r / es, es, cmp); -	if ((r = pd - pc) > es) { +	r = pd - pc; +	if (r > es) {  		/* Iterate rather than recurse to save stack space */  		a = pn - r;  		n = r / es; diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_qsort.h b/target/linux/generic/files/fs/yaffs2/yaffs_qsort.h index 610b7ec84..941c7a87c 100644 --- a/target/linux/generic/files/fs/yaffs2/yaffs_qsort.h +++ b/target/linux/generic/files/fs/yaffs2/yaffs_qsort.h @@ -17,7 +17,7 @@  #ifndef __YAFFS_QSORT_H__  #define __YAFFS_QSORT_H__ -extern void yaffs_qsort (void *const base, size_t total_elems, size_t size, -                   int (*cmp)(const void *, const void *)); +extern void yaffs_qsort(void *const base, size_t total_elems, size_t size, +			int (*cmp)(const void *, const void *));  #endif diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_tagscompat.c b/target/linux/generic/files/fs/yaffs2/yaffs_tagscompat.c index 7622b1af7..402537fb4 100644 --- a/target/linux/generic/files/fs/yaffs2/yaffs_tagscompat.c +++ b/target/linux/generic/files/fs/yaffs2/yaffs_tagscompat.c @@ -14,16 +14,17 @@  #include "yaffs_guts.h"  #include "yaffs_tagscompat.h"  #include "yaffs_ecc.h" +#include "yaffs_getblockinfo.h" -static void yaffs_HandleReadDataError(yaffs_Device * dev, int chunkInNAND); +static void yaffs_HandleReadDataError(yaffs_Device *dev, int chunkInNAND);  #ifdef NOTYET -static void yaffs_CheckWrittenBlock(yaffs_Device * dev, int chunkInNAND); -static void yaffs_HandleWriteChunkOk(yaffs_Device * dev, int chunkInNAND, -				     const __u8 * data, -				     const yaffs_Spare * spare); -static void yaffs_HandleUpdateChunk(yaffs_Device * dev, int chunkInNAND, -				    const yaffs_Spare * spare); -static void yaffs_HandleWriteChunkError(yaffs_Device * dev, int chunkInNAND); +static void yaffs_CheckWrittenBlock(yaffs_Device *dev, int chunkInNAND); +static void yaffs_HandleWriteChunkOk(yaffs_Device *dev, int chunkInNAND, +				     const __u8 *data, +				     const yaffs_Spare *spare); +static void yaffs_HandleUpdateChunk(yaffs_Device *dev, int chunkInNAND, +				    const yaffs_Spare *spare); +static void yaffs_HandleWriteChunkError(yaffs_Device *dev, int chunkInNAND);  #endif  static const char yaffs_countBitsTable[256] = { @@ -54,13 +55,13 @@ int yaffs_CountBits(__u8 x)  /********** Tags ECC calculations  *********/ -void yaffs_CalcECC(const __u8 * data, yaffs_Spare * spare) +void yaffs_CalcECC(const __u8 *data, yaffs_Spare *spare)  {  	yaffs_ECCCalculate(data, spare->ecc1);  	yaffs_ECCCalculate(&data[256], spare->ecc2);  } -void yaffs_CalcTagsECC(yaffs_Tags * tags) +void yaffs_CalcTagsECC(yaffs_Tags *tags)  {  	/* Calculate an ecc */ @@ -74,9 +75,8 @@ void yaffs_CalcTagsECC(yaffs_Tags * tags)  	for (i = 0; i < 8; i++) {  		for (j = 1; j & 0xff; j <<= 1) {  			bit++; -			if (b[i] & j) { +			if (b[i] & j)  				ecc ^= bit; -			}  		}  	} @@ -84,7 +84,7 @@ void yaffs_CalcTagsECC(yaffs_Tags * tags)  } -int yaffs_CheckECCOnTags(yaffs_Tags * tags) +int yaffs_CheckECCOnTags(yaffs_Tags *tags)  {  	unsigned ecc = tags->ecc; @@ -115,8 +115,8 @@ int yaffs_CheckECCOnTags(yaffs_Tags * tags)  /********** Tags **********/ -static void yaffs_LoadTagsIntoSpare(yaffs_Spare * sparePtr, -				    yaffs_Tags * tagsPtr) +static void yaffs_LoadTagsIntoSpare(yaffs_Spare *sparePtr, +				yaffs_Tags *tagsPtr)  {  	yaffs_TagsUnion *tu = (yaffs_TagsUnion *) tagsPtr; @@ -132,8 +132,8 @@ static void yaffs_LoadTagsIntoSpare(yaffs_Spare * sparePtr,  	sparePtr->tagByte7 = tu->asBytes[7];  } -static void yaffs_GetTagsFromSpare(yaffs_Device * dev, yaffs_Spare * sparePtr, -				   yaffs_Tags * tagsPtr) +static void yaffs_GetTagsFromSpare(yaffs_Device *dev, yaffs_Spare *sparePtr, +				yaffs_Tags *tagsPtr)  {  	yaffs_TagsUnion *tu = (yaffs_TagsUnion *) tagsPtr;  	int result; @@ -148,21 +148,20 @@ static void yaffs_GetTagsFromSpare(yaffs_Device * dev, yaffs_Spare * sparePtr,  	tu->asBytes[7] = sparePtr->tagByte7;  	result = yaffs_CheckECCOnTags(tagsPtr); -	if (result > 0) { +	if (result > 0)  		dev->tagsEccFixed++; -	} else if (result < 0) { +	else if (result < 0)  		dev->tagsEccUnfixed++; -	}  } -static void yaffs_SpareInitialise(yaffs_Spare * spare) +static void yaffs_SpareInitialise(yaffs_Spare *spare)  {  	memset(spare, 0xFF, sizeof(yaffs_Spare));  }  static int yaffs_WriteChunkToNAND(struct yaffs_DeviceStruct *dev, -				  int chunkInNAND, const __u8 * data, -				  yaffs_Spare * spare) +				int chunkInNAND, const __u8 *data, +				yaffs_Spare *spare)  {  	if (chunkInNAND < dev->startBlock * dev->nChunksPerBlock) {  		T(YAFFS_TRACE_ERROR, @@ -177,9 +176,9 @@ static int yaffs_WriteChunkToNAND(struct yaffs_DeviceStruct *dev,  static int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev,  				   int chunkInNAND, -				   __u8 * data, -				   yaffs_Spare * spare, -				   yaffs_ECCResult * eccResult, +				   __u8 *data, +				   yaffs_Spare *spare, +				   yaffs_ECCResult *eccResult,  				   int doErrorCorrection)  {  	int retVal; @@ -252,9 +251,11 @@ static int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev,  		/* Must allocate enough memory for spare+2*sizeof(int) */  		/* for ecc results from device. */  		struct yaffs_NANDSpare nspare; -		retVal = -		    dev->readChunkFromNAND(dev, chunkInNAND, data, -					   (yaffs_Spare *) & nspare); + +		memset(&nspare, 0, sizeof(nspare)); + +		retVal = dev->readChunkFromNAND(dev, chunkInNAND, data, +					(yaffs_Spare *) &nspare);  		memcpy(spare, &nspare, sizeof(yaffs_Spare));  		if (data && doErrorCorrection) {  			if (nspare.eccres1 > 0) { @@ -302,8 +303,7 @@ static int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev,  static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,  				  int chunkInNAND)  { - -	static int init = 0; +	static int init;  	static __u8 cmpbuf[YAFFS_BYTES_PER_CHUNK];  	static __u8 data[YAFFS_BYTES_PER_CHUNK];  	/* Might as well always allocate the larger size for */ @@ -331,12 +331,12 @@ static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,   * Functions for robustisizing   */ -static void yaffs_HandleReadDataError(yaffs_Device * dev, int chunkInNAND) +static void yaffs_HandleReadDataError(yaffs_Device *dev, int chunkInNAND)  {  	int blockInNAND = chunkInNAND / dev->nChunksPerBlock;  	/* Mark the block for retirement */ -	yaffs_GetBlockInfo(dev, blockInNAND)->needsRetiring = 1; +	yaffs_GetBlockInfo(dev, blockInNAND + dev->blockOffset)->needsRetiring = 1;  	T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,  	  (TSTR("**>>Block %d marked for retirement" TENDSTR), blockInNAND)); @@ -348,22 +348,22 @@ static void yaffs_HandleReadDataError(yaffs_Device * dev, int chunkInNAND)  }  #ifdef NOTYET -static void yaffs_CheckWrittenBlock(yaffs_Device * dev, int chunkInNAND) +static void yaffs_CheckWrittenBlock(yaffs_Device *dev, int chunkInNAND)  {  } -static void yaffs_HandleWriteChunkOk(yaffs_Device * dev, int chunkInNAND, -				     const __u8 * data, -				     const yaffs_Spare * spare) +static void yaffs_HandleWriteChunkOk(yaffs_Device *dev, int chunkInNAND, +				     const __u8 *data, +				     const yaffs_Spare *spare)  {  } -static void yaffs_HandleUpdateChunk(yaffs_Device * dev, int chunkInNAND, -				    const yaffs_Spare * spare) +static void yaffs_HandleUpdateChunk(yaffs_Device *dev, int chunkInNAND, +				    const yaffs_Spare *spare)  {  } -static void yaffs_HandleWriteChunkError(yaffs_Device * dev, int chunkInNAND) +static void yaffs_HandleWriteChunkError(yaffs_Device *dev, int chunkInNAND)  {  	int blockInNAND = chunkInNAND / dev->nChunksPerBlock; @@ -373,8 +373,8 @@ static void yaffs_HandleWriteChunkError(yaffs_Device * dev, int chunkInNAND)  	yaffs_DeleteChunk(dev, chunkInNAND, 1, __LINE__);  } -static int yaffs_VerifyCompare(const __u8 * d0, const __u8 * d1, -			       const yaffs_Spare * s0, const yaffs_Spare * s1) +static int yaffs_VerifyCompare(const __u8 *d0, const __u8 *d1, +			       const yaffs_Spare *s0, const yaffs_Spare *s1)  {  	if (memcmp(d0, d1, YAFFS_BYTES_PER_CHUNK) != 0 || @@ -398,28 +398,35 @@ static int yaffs_VerifyCompare(const __u8 * d0, const __u8 * d1,  }  #endif				/* NOTYET */ -int yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(yaffs_Device * dev, -						    int chunkInNAND, -						    const __u8 * data, -						    const yaffs_ExtendedTags * -						    eTags) +int yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(yaffs_Device *dev, +						int chunkInNAND, +						const __u8 *data, +						const yaffs_ExtendedTags *eTags)  {  	yaffs_Spare spare;  	yaffs_Tags tags;  	yaffs_SpareInitialise(&spare); -	if (eTags->chunkDeleted) { +	if (eTags->chunkDeleted)  		spare.pageStatus = 0; -	} else { +	else {  		tags.objectId = eTags->objectId;  		tags.chunkId = eTags->chunkId; -		tags.byteCount = eTags->byteCount; + +		tags.byteCountLSB = eTags->byteCount & 0x3ff; + +		if (dev->nDataBytesPerChunk >= 1024) +			tags.byteCountMSB = (eTags->byteCount >> 10) & 3; +		else +			tags.byteCountMSB = 3; + +  		tags.serialNumber = eTags->serialNumber; -		if (!dev->useNANDECC && data) { +		if (!dev->useNANDECC && data)  			yaffs_CalcECC(data, &spare); -		} +  		yaffs_LoadTagsIntoSpare(&spare, &tags);  	} @@ -427,15 +434,15 @@ int yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(yaffs_Device * dev,  	return yaffs_WriteChunkToNAND(dev, chunkInNAND, data, &spare);  } -int yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(yaffs_Device * dev, +int yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(yaffs_Device *dev,  						     int chunkInNAND, -						     __u8 * data, -						     yaffs_ExtendedTags * eTags) +						     __u8 *data, +						     yaffs_ExtendedTags *eTags)  {  	yaffs_Spare spare;  	yaffs_Tags tags; -	yaffs_ECCResult eccResult; +	yaffs_ECCResult eccResult = YAFFS_ECC_RESULT_UNKNOWN;  	static yaffs_Spare spareFF;  	static int init; @@ -466,7 +473,11 @@ int yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(yaffs_Device * dev,  				eTags->objectId = tags.objectId;  				eTags->chunkId = tags.chunkId; -				eTags->byteCount = tags.byteCount; +				eTags->byteCount = tags.byteCountLSB; + +				if (dev->nDataBytesPerChunk >= 1024) +					eTags->byteCount |= (((unsigned) tags.byteCountMSB) << 10); +  				eTags->serialNumber = tags.serialNumber;  			}  		} @@ -497,9 +508,9 @@ int yaffs_TagsCompatabilityMarkNANDBlockBad(struct yaffs_DeviceStruct *dev,  }  int yaffs_TagsCompatabilityQueryNANDBlock(struct yaffs_DeviceStruct *dev, -					  int blockNo, yaffs_BlockState * -					  state, -					  int *sequenceNumber) +					  int blockNo, +					  yaffs_BlockState *state, +					  __u32 *sequenceNumber)  {  	yaffs_Spare spare0, spare1; diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_tagscompat.h b/target/linux/generic/files/fs/yaffs2/yaffs_tagscompat.h index a61e3ba14..6f95119e0 100644 --- a/target/linux/generic/files/fs/yaffs2/yaffs_tagscompat.h +++ b/target/linux/generic/files/fs/yaffs2/yaffs_tagscompat.h @@ -17,24 +17,23 @@  #define __YAFFS_TAGSCOMPAT_H__  #include "yaffs_guts.h" -int yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(yaffs_Device * dev, -						    int chunkInNAND, -						    const __u8 * data, -						    const yaffs_ExtendedTags * -						    tags); -int yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(yaffs_Device * dev, -						     int chunkInNAND, -						     __u8 * data, -						     yaffs_ExtendedTags * -						     tags); +int yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(yaffs_Device *dev, +						int chunkInNAND, +						const __u8 *data, +						const yaffs_ExtendedTags *tags); +int yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(yaffs_Device *dev, +						int chunkInNAND, +						__u8 *data, +						yaffs_ExtendedTags *tags);  int yaffs_TagsCompatabilityMarkNANDBlockBad(struct yaffs_DeviceStruct *dev,  					    int blockNo);  int yaffs_TagsCompatabilityQueryNANDBlock(struct yaffs_DeviceStruct *dev, -					  int blockNo, yaffs_BlockState * -					  state, int *sequenceNumber); +					  int blockNo, +					  yaffs_BlockState *state, +					  __u32 *sequenceNumber); -void yaffs_CalcTagsECC(yaffs_Tags * tags); -int yaffs_CheckECCOnTags(yaffs_Tags * tags); +void yaffs_CalcTagsECC(yaffs_Tags *tags); +int yaffs_CheckECCOnTags(yaffs_Tags *tags);  int yaffs_CountBits(__u8 byte);  #endif diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_tagsvalidity.c b/target/linux/generic/files/fs/yaffs2/yaffs_tagsvalidity.c index 9e0bd1cf5..5233bcba8 100644 --- a/target/linux/generic/files/fs/yaffs2/yaffs_tagsvalidity.c +++ b/target/linux/generic/files/fs/yaffs2/yaffs_tagsvalidity.c @@ -13,14 +13,14 @@  #include "yaffs_tagsvalidity.h" -void yaffs_InitialiseTags(yaffs_ExtendedTags * tags) +void yaffs_InitialiseTags(yaffs_ExtendedTags *tags)  {  	memset(tags, 0, sizeof(yaffs_ExtendedTags));  	tags->validMarker0 = 0xAAAAAAAA;  	tags->validMarker1 = 0x55555555;  } -int yaffs_ValidateTags(yaffs_ExtendedTags * tags) +int yaffs_ValidateTags(yaffs_ExtendedTags *tags)  {  	return (tags->validMarker0 == 0xAAAAAAAA &&  		tags->validMarker1 == 0x55555555); diff --git a/target/linux/generic/files/fs/yaffs2/yaffs_tagsvalidity.h b/target/linux/generic/files/fs/yaffs2/yaffs_tagsvalidity.h index 2fd0c24ed..cb11884b2 100644 --- a/target/linux/generic/files/fs/yaffs2/yaffs_tagsvalidity.h +++ b/target/linux/generic/files/fs/yaffs2/yaffs_tagsvalidity.h @@ -19,6 +19,6 @@  #include "yaffs_guts.h" -void yaffs_InitialiseTags(yaffs_ExtendedTags * tags); -int yaffs_ValidateTags(yaffs_ExtendedTags * tags); +void yaffs_InitialiseTags(yaffs_ExtendedTags *tags); +int yaffs_ValidateTags(yaffs_ExtendedTags *tags);  #endif diff --git a/target/linux/generic/files/fs/yaffs2/yportenv.h b/target/linux/generic/files/fs/yaffs2/yportenv.h index 15ac28121..28e205bbd 100644 --- a/target/linux/generic/files/fs/yaffs2/yportenv.h +++ b/target/linux/generic/files/fs/yaffs2/yportenv.h @@ -17,17 +17,28 @@  #ifndef __YPORTENV_H__  #define __YPORTENV_H__ +/* + * Define the MTD version in terms of Linux Kernel versions + * This allows yaffs to be used independantly of the kernel + * as well as with it. + */ + +#define MTD_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c)) +  #if defined CONFIG_YAFFS_WINCE  #include "ywinceenv.h" -#elif  defined __KERNEL__ +#elif defined __KERNEL__  #include "moduleconfig.h"  /* Linux kernel */ +  #include <linux/version.h> -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)) +#define MTD_VERSION_CODE LINUX_VERSION_CODE + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19))  #include <linux/config.h>  #endif  #include <linux/kernel.h> @@ -40,12 +51,13 @@  #define YCHAR char  #define YUCHAR unsigned char  #define _Y(x)     x -#define yaffs_strcpy(a,b)    strcpy(a,b) -#define yaffs_strncpy(a,b,c) strncpy(a,b,c) -#define yaffs_strncmp(a,b,c) strncmp(a,b,c) -#define yaffs_strlen(s)	     strlen(s) -#define yaffs_sprintf	     sprintf -#define yaffs_toupper(a)     toupper(a) +#define yaffs_strcat(a, b)     strcat(a, b) +#define yaffs_strcpy(a, b)     strcpy(a, b) +#define yaffs_strncpy(a, b, c) strncpy(a, b, c) +#define yaffs_strncmp(a, b, c) strncmp(a, b, c) +#define yaffs_strlen(s)	       strlen(s) +#define yaffs_sprintf	       sprintf +#define yaffs_toupper(a)       toupper(a)  #define Y_INLINE inline @@ -53,19 +65,19 @@  #define YAFFS_LOSTNFOUND_PREFIX		"obj"  /* #define YPRINTF(x) printk x */ -#define YMALLOC(x) kmalloc(x,GFP_KERNEL) +#define YMALLOC(x) kmalloc(x, GFP_NOFS)  #define YFREE(x)   kfree(x)  #define YMALLOC_ALT(x) vmalloc(x)  #define YFREE_ALT(x)   vfree(x)  #define YMALLOC_DMA(x) YMALLOC(x) -// KR - added for use in scan so processes aren't blocked indefinitely. +/* KR - added for use in scan so processes aren't blocked indefinitely. */  #define YYIELD() schedule()  #define YAFFS_ROOT_MODE			0666  #define YAFFS_LOSTNFOUND_MODE		0666 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))  #define Y_CURRENT_TIME CURRENT_TIME.tv_sec  #define Y_TIME_CONVERT(x) (x).tv_sec  #else @@ -73,11 +85,12 @@  #define Y_TIME_CONVERT(x) (x)  #endif -#define yaffs_SumCompare(x,y) ((x) == (y)) -#define yaffs_strcmp(a,b) strcmp(a,b) +#define yaffs_SumCompare(x, y) ((x) == (y)) +#define yaffs_strcmp(a, b) strcmp(a, b)  #define TENDSTR "\n"  #define TSTR(x) KERN_WARNING x +#define TCONT(x) x  #define TOUT(p) printk p  #define yaffs_trace(mask, fmt, args...) \ @@ -90,6 +103,8 @@  #elif defined CONFIG_YAFFS_DIRECT +#define MTD_VERSION_CODE MTD_VERSION(2, 6, 22) +  /* Direct interface */  #include "ydirectenv.h" @@ -111,11 +126,12 @@  #define YCHAR char  #define YUCHAR unsigned char  #define _Y(x)     x -#define yaffs_strcpy(a,b)    strcpy(a,b) -#define yaffs_strncpy(a,b,c) strncpy(a,b,c) -#define yaffs_strlen(s)	     strlen(s) -#define yaffs_sprintf	     sprintf -#define yaffs_toupper(a)     toupper(a) +#define yaffs_strcat(a, b)     strcat(a, b) +#define yaffs_strcpy(a, b)     strcpy(a, b) +#define yaffs_strncpy(a, b, c) strncpy(a, b, c) +#define yaffs_strlen(s)	       strlen(s) +#define yaffs_sprintf	       sprintf +#define yaffs_toupper(a)       toupper(a)  #define Y_INLINE inline @@ -133,8 +149,8 @@  #define YAFFS_ROOT_MODE				0666  #define YAFFS_LOSTNFOUND_MODE		0666 -#define yaffs_SumCompare(x,y) ((x) == (y)) -#define yaffs_strcmp(a,b) strcmp(a,b) +#define yaffs_SumCompare(x, y) ((x) == (y)) +#define yaffs_strcmp(a, b) strcmp(a, b)  #else  /* Should have specified a configuration type */ @@ -178,10 +194,10 @@ extern unsigned int yaffs_wr_attempts;  #define YAFFS_TRACE_ALWAYS		0xF0000000 -#define T(mask,p) do{ if((mask) & (yaffs_traceMask | YAFFS_TRACE_ALWAYS)) TOUT(p);} while(0) +#define T(mask, p) do { if ((mask) & (yaffs_traceMask | YAFFS_TRACE_ALWAYS)) TOUT(p); } while (0) -#ifndef CONFIG_YAFFS_WINCE -#define YBUG() T(YAFFS_TRACE_BUG,(TSTR("==>> yaffs bug: " __FILE__ " %d" TENDSTR),__LINE__)) +#ifndef YBUG +#define YBUG() do {T(YAFFS_TRACE_BUG, (TSTR("==>> yaffs bug: " __FILE__ " %d" TENDSTR), __LINE__)); } while (0)  #endif  #endif  | 
