yaffs: moved to newest official xyaffs driver
This commit is contained in:
		| @@ -102,22 +102,6 @@ config YAFFS_DISABLE_TAGS_ECC | ||||
|  | ||||
| 	  If unsure, say N. | ||||
|  | ||||
|  | ||||
| config YAFFS_DISABLE_WIDE_TNODES | ||||
| 	bool "Turn off wide tnodes" | ||||
| 	depends on YAFFS_FS | ||||
| 	default n | ||||
| 	help | ||||
| 	  Wide tnodes are only used for NAND arrays >=32MB for 512-byte | ||||
| 	  page devices and >=128MB for 2k page devices. They use slightly | ||||
| 	  more RAM but are faster since they eliminate chunk group | ||||
| 	  searching. | ||||
|  | ||||
| 	  Setting this to 'y' will force tnode width to 16 bits and save | ||||
| 	  memory but make large arrays slower. | ||||
|  | ||||
| 	  If unsure, say N. | ||||
|  | ||||
| config YAFFS_ALWAYS_CHECK_CHUNK_ERASED | ||||
| 	bool "Force chunk erase check" | ||||
| 	depends on YAFFS_FS | ||||
| @@ -136,17 +120,6 @@ config YAFFS_ALWAYS_CHECK_CHUNK_ERASED | ||||
|  | ||||
| 	  If unsure, say Y. | ||||
|  | ||||
| config YAFFS_SHORT_NAMES_IN_RAM | ||||
| 	bool "Cache short names in RAM" | ||||
| 	depends on YAFFS_FS | ||||
| 	default y | ||||
| 	help | ||||
| 	  If this config is set, then short names are stored with the | ||||
| 	  yaffs_Object.  This costs an extra 16 bytes of RAM per object, | ||||
| 	  but makes look-ups faster. | ||||
|  | ||||
| 	  If unsure, say Y. | ||||
|  | ||||
| config YAFFS_EMPTY_LOST_AND_FOUND | ||||
| 	bool "Empty lost and found on boot" | ||||
| 	depends on YAFFS_FS | ||||
| @@ -177,7 +150,7 @@ config YAFFS_DISABLE_BACKGROUND | ||||
| 	 If this is set, then background processing is disabled. | ||||
| 	 Background processing makes many foreground activities faster. | ||||
|  | ||||
| 	  If unsure, say N. | ||||
| 	 If unsure, say N. | ||||
|  | ||||
| config YAFFS_XATTR | ||||
| 	bool "Enable yaffs2 xattr support" | ||||
| @@ -186,5 +159,3 @@ config YAFFS_XATTR | ||||
| 	help | ||||
| 	 If this is set then yaffs2 will provide xattr support. | ||||
| 	 If unsure, say Y. | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -16,7 +16,8 @@ | ||||
| #include "yaffs_trace.h" | ||||
| #include "yportenv.h" | ||||
|  | ||||
| #ifdef CONFIG_YAFFS_YMALLOC_ALLOCATOR | ||||
| #ifdef CONFIG_YAFFS_KMALLOC_ALLOCATOR | ||||
| /* This is an alternative debug allocator. Don't use for production code. */ | ||||
|  | ||||
| void yaffs_deinit_raw_tnodes_and_objs(struct yaffs_dev *dev) | ||||
| { | ||||
| @@ -30,13 +31,13 @@ void yaffs_init_raw_tnodes_and_objs(struct yaffs_dev *dev) | ||||
|  | ||||
| struct yaffs_tnode *yaffs_alloc_raw_tnode(struct yaffs_dev *dev) | ||||
| { | ||||
| 	return (struct yaffs_tnode *)YMALLOC(dev->tnode_size); | ||||
| 	return kmalloc(dev->tnode_size, GFP_NOFS); | ||||
| } | ||||
|  | ||||
| void yaffs_free_raw_tnode(struct yaffs_dev *dev, struct yaffs_tnode *tn) | ||||
| { | ||||
| 	dev = dev; | ||||
| 	YFREE(tn); | ||||
| 	kfree(tn); | ||||
| } | ||||
|  | ||||
| void yaffs_init_raw_objs(struct yaffs_dev *dev) | ||||
| @@ -52,14 +53,14 @@ void yaffs_deinit_raw_objs(struct yaffs_dev *dev) | ||||
| struct yaffs_obj *yaffs_alloc_raw_obj(struct yaffs_dev *dev) | ||||
| { | ||||
| 	dev = dev; | ||||
| 	return (struct yaffs_obj *)YMALLOC(sizeof(struct yaffs_obj)); | ||||
| 	return kmalloc(sizeof(struct yaffs_obj)); | ||||
| } | ||||
|  | ||||
| void yaffs_free_raw_obj(struct yaffs_dev *dev, struct yaffs_obj *obj) | ||||
| { | ||||
|  | ||||
| 	dev = dev; | ||||
| 	YFREE(obj); | ||||
| 	kfree(obj); | ||||
| } | ||||
|  | ||||
| #else | ||||
| @@ -89,10 +90,8 @@ struct yaffs_allocator { | ||||
|  | ||||
| static void yaffs_deinit_raw_tnodes(struct yaffs_dev *dev) | ||||
| { | ||||
|  | ||||
| 	struct yaffs_allocator *allocator = | ||||
| 	    (struct yaffs_allocator *)dev->allocator; | ||||
|  | ||||
| 	struct yaffs_tnode_list *tmp; | ||||
|  | ||||
| 	if (!allocator) { | ||||
| @@ -103,10 +102,9 @@ static void yaffs_deinit_raw_tnodes(struct yaffs_dev *dev) | ||||
| 	while (allocator->alloc_tnode_list) { | ||||
| 		tmp = allocator->alloc_tnode_list->next; | ||||
|  | ||||
| 		YFREE(allocator->alloc_tnode_list->tnodes); | ||||
| 		YFREE(allocator->alloc_tnode_list); | ||||
| 		kfree(allocator->alloc_tnode_list->tnodes); | ||||
| 		kfree(allocator->alloc_tnode_list); | ||||
| 		allocator->alloc_tnode_list = tmp; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	allocator->free_tnodes = NULL; | ||||
| @@ -123,8 +121,9 @@ static void yaffs_init_raw_tnodes(struct yaffs_dev *dev) | ||||
| 		allocator->free_tnodes = NULL; | ||||
| 		allocator->n_free_tnodes = 0; | ||||
| 		allocator->n_tnodes_created = 0; | ||||
| 	} else | ||||
| 	} else { | ||||
| 		YBUG(); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static int yaffs_create_tnodes(struct yaffs_dev *dev, int n_tnodes) | ||||
| @@ -147,13 +146,12 @@ static int yaffs_create_tnodes(struct yaffs_dev *dev, int n_tnodes) | ||||
| 		return YAFFS_OK; | ||||
|  | ||||
| 	/* make these things */ | ||||
|  | ||||
| 	new_tnodes = YMALLOC(n_tnodes * dev->tnode_size); | ||||
| 	new_tnodes = kmalloc(n_tnodes * dev->tnode_size, GFP_NOFS); | ||||
| 	mem = (u8 *) new_tnodes; | ||||
|  | ||||
| 	if (!new_tnodes) { | ||||
| 		T(YAFFS_TRACE_ERROR, | ||||
| 		  (TSTR("yaffs: Could not allocate Tnodes" TENDSTR))); | ||||
| 		yaffs_trace(YAFFS_TRACE_ERROR, | ||||
| 			"yaffs: Could not allocate Tnodes"); | ||||
| 		return YAFFS_FAIL; | ||||
| 	} | ||||
|  | ||||
| @@ -175,12 +173,10 @@ static int yaffs_create_tnodes(struct yaffs_dev *dev, int n_tnodes) | ||||
| 	 * NB If we can't add this to the management list it isn't fatal | ||||
| 	 * but it just means we can't free this bunch of tnodes later. | ||||
| 	 */ | ||||
|  | ||||
| 	tnl = YMALLOC(sizeof(struct yaffs_tnode_list)); | ||||
| 	tnl = kmalloc(sizeof(struct yaffs_tnode_list), GFP_NOFS); | ||||
| 	if (!tnl) { | ||||
| 		T(YAFFS_TRACE_ERROR, | ||||
| 		  (TSTR | ||||
| 		   ("yaffs: Could not add tnodes to management list" TENDSTR))); | ||||
| 		yaffs_trace(YAFFS_TRACE_ERROR, | ||||
| 			"Could not add tnodes to management list"); | ||||
| 		return YAFFS_FAIL; | ||||
| 	} else { | ||||
| 		tnl->tnodes = new_tnodes; | ||||
| @@ -188,7 +184,7 @@ static int yaffs_create_tnodes(struct yaffs_dev *dev, int n_tnodes) | ||||
| 		allocator->alloc_tnode_list = tnl; | ||||
| 	} | ||||
|  | ||||
| 	T(YAFFS_TRACE_ALLOCATE, (TSTR("yaffs: Tnodes added" TENDSTR))); | ||||
| 	yaffs_trace(YAFFS_TRACE_ALLOCATE, "Tnodes added"); | ||||
|  | ||||
| 	return YAFFS_OK; | ||||
| } | ||||
| @@ -243,8 +239,9 @@ static void yaffs_init_raw_objs(struct yaffs_dev *dev) | ||||
| 		allocator->allocated_obj_list = NULL; | ||||
| 		allocator->free_objs = NULL; | ||||
| 		allocator->n_free_objects = 0; | ||||
| 	} else | ||||
| 	} else { | ||||
| 		YBUG(); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static void yaffs_deinit_raw_objs(struct yaffs_dev *dev) | ||||
| @@ -259,8 +256,8 @@ static void yaffs_deinit_raw_objs(struct yaffs_dev *dev) | ||||
|  | ||||
| 	while (allocator->allocated_obj_list) { | ||||
| 		tmp = allocator->allocated_obj_list->next; | ||||
| 		YFREE(allocator->allocated_obj_list->objects); | ||||
| 		YFREE(allocator->allocated_obj_list); | ||||
| 		kfree(allocator->allocated_obj_list->objects); | ||||
| 		kfree(allocator->allocated_obj_list); | ||||
|  | ||||
| 		allocator->allocated_obj_list = tmp; | ||||
| 	} | ||||
| @@ -273,7 +270,6 @@ static void yaffs_deinit_raw_objs(struct yaffs_dev *dev) | ||||
| static int yaffs_create_free_objs(struct yaffs_dev *dev, int n_obj) | ||||
| { | ||||
| 	struct yaffs_allocator *allocator = dev->allocator; | ||||
|  | ||||
| 	int i; | ||||
| 	struct yaffs_obj *new_objs; | ||||
| 	struct yaffs_obj_list *list; | ||||
| @@ -287,20 +283,16 @@ static int yaffs_create_free_objs(struct yaffs_dev *dev, int n_obj) | ||||
| 		return YAFFS_OK; | ||||
|  | ||||
| 	/* make these things */ | ||||
| 	new_objs = YMALLOC(n_obj * sizeof(struct yaffs_obj)); | ||||
| 	list = YMALLOC(sizeof(struct yaffs_obj_list)); | ||||
| 	new_objs = kmalloc(n_obj * sizeof(struct yaffs_obj), GFP_NOFS); | ||||
| 	list = kmalloc(sizeof(struct yaffs_obj_list), GFP_NOFS); | ||||
|  | ||||
| 	if (!new_objs || !list) { | ||||
| 		if (new_objs) { | ||||
| 			YFREE(new_objs); | ||||
| 			new_objs = NULL; | ||||
| 		} | ||||
| 		if (list) { | ||||
| 			YFREE(list); | ||||
| 			list = NULL; | ||||
| 		} | ||||
| 		T(YAFFS_TRACE_ALLOCATE, | ||||
| 		  (TSTR("yaffs: Could not allocate more objects" TENDSTR))); | ||||
| 		kfree(new_objs); | ||||
| 		new_objs = NULL; | ||||
| 		kfree(list); | ||||
| 		list = NULL; | ||||
| 		yaffs_trace(YAFFS_TRACE_ALLOCATE, | ||||
| 			"Could not allocate more objects"); | ||||
| 		return YAFFS_FAIL; | ||||
| 	} | ||||
|  | ||||
| @@ -369,10 +361,11 @@ void yaffs_deinit_raw_tnodes_and_objs(struct yaffs_dev *dev) | ||||
| 		yaffs_deinit_raw_tnodes(dev); | ||||
| 		yaffs_deinit_raw_objs(dev); | ||||
|  | ||||
| 		YFREE(dev->allocator); | ||||
| 		kfree(dev->allocator); | ||||
| 		dev->allocator = NULL; | ||||
| 	} else | ||||
| 	} else { | ||||
| 		YBUG(); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void yaffs_init_raw_tnodes_and_objs(struct yaffs_dev *dev) | ||||
| @@ -380,14 +373,15 @@ void yaffs_init_raw_tnodes_and_objs(struct yaffs_dev *dev) | ||||
| 	struct yaffs_allocator *allocator; | ||||
|  | ||||
| 	if (!dev->allocator) { | ||||
| 		allocator = YMALLOC(sizeof(struct yaffs_allocator)); | ||||
| 		allocator = kmalloc(sizeof(struct yaffs_allocator), GFP_NOFS); | ||||
| 		if (allocator) { | ||||
| 			dev->allocator = allocator; | ||||
| 			yaffs_init_raw_tnodes(dev); | ||||
| 			yaffs_init_raw_objs(dev); | ||||
| 		} | ||||
| 	} else | ||||
| 	} else { | ||||
| 		YBUG(); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -39,9 +39,9 @@ void yaffs_load_current_time(struct yaffs_obj *obj, int do_a, int do_c) | ||||
| { | ||||
| 	obj->yst_mtime = Y_CURRENT_TIME; | ||||
| 	if (do_a) | ||||
| 		obj->yst_atime = obj->yst_atime; | ||||
| 		obj->yst_atime = obj->yst_mtime; | ||||
| 	if (do_c) | ||||
| 		obj->yst_ctime = obj->yst_atime; | ||||
| 		obj->yst_ctime = obj->yst_mtime; | ||||
| } | ||||
|  | ||||
| void yaffs_attribs_init(struct yaffs_obj *obj, u32 gid, u32 uid, u32 rdev) | ||||
| @@ -64,7 +64,7 @@ loff_t yaffs_get_file_size(struct yaffs_obj *obj) | ||||
| 		alias = obj->variant.symlink_variant.alias; | ||||
| 		if (!alias) | ||||
| 			return 0; | ||||
| 		return yaffs_strnlen(alias, YAFFS_MAX_ALIAS_LENGTH); | ||||
| 		return strnlen(alias, YAFFS_MAX_ALIAS_LENGTH); | ||||
| 	default: | ||||
| 		return 0; | ||||
| 	} | ||||
|   | ||||
| @@ -17,12 +17,12 @@ | ||||
|  * Chunk bitmap manipulations | ||||
|  */ | ||||
|  | ||||
| static Y_INLINE u8 *yaffs_block_bits(struct yaffs_dev *dev, int blk) | ||||
| static inline u8 *yaffs_block_bits(struct yaffs_dev *dev, int blk) | ||||
| { | ||||
| 	if (blk < dev->internal_start_block || blk > dev->internal_end_block) { | ||||
| 		T(YAFFS_TRACE_ERROR, | ||||
| 		  (TSTR("**>> yaffs: BlockBits block %d is not valid" TENDSTR), | ||||
| 		   blk)); | ||||
| 		yaffs_trace(YAFFS_TRACE_ERROR, | ||||
| 			"BlockBits block %d is not valid", | ||||
| 			blk); | ||||
| 		YBUG(); | ||||
| 	} | ||||
| 	return dev->chunk_bits + | ||||
| @@ -33,9 +33,9 @@ void yaffs_verify_chunk_bit_id(struct yaffs_dev *dev, int blk, int chunk) | ||||
| { | ||||
| 	if (blk < dev->internal_start_block || blk > dev->internal_end_block || | ||||
| 	    chunk < 0 || chunk >= dev->param.chunks_per_block) { | ||||
| 		T(YAFFS_TRACE_ERROR, | ||||
| 		  (TSTR("**>> yaffs: Chunk Id (%d:%d) invalid" TENDSTR), | ||||
| 		   blk, chunk)); | ||||
| 		yaffs_trace(YAFFS_TRACE_ERROR, | ||||
| 			"Chunk Id (%d:%d) invalid", | ||||
| 			blk, chunk); | ||||
| 		YBUG(); | ||||
| 	} | ||||
| } | ||||
| @@ -52,7 +52,6 @@ void yaffs_clear_chunk_bit(struct yaffs_dev *dev, int blk, int chunk) | ||||
| 	u8 *blk_bits = yaffs_block_bits(dev, blk); | ||||
|  | ||||
| 	yaffs_verify_chunk_bit_id(dev, blk, chunk); | ||||
|  | ||||
| 	blk_bits[chunk / 8] &= ~(1 << (chunk & 7)); | ||||
| } | ||||
|  | ||||
| @@ -61,15 +60,14 @@ void yaffs_set_chunk_bit(struct yaffs_dev *dev, int blk, int chunk) | ||||
| 	u8 *blk_bits = yaffs_block_bits(dev, blk); | ||||
|  | ||||
| 	yaffs_verify_chunk_bit_id(dev, blk, chunk); | ||||
|  | ||||
| 	blk_bits[chunk / 8] |= (1 << (chunk & 7)); | ||||
| } | ||||
|  | ||||
| int yaffs_check_chunk_bit(struct yaffs_dev *dev, int blk, int chunk) | ||||
| { | ||||
| 	u8 *blk_bits = yaffs_block_bits(dev, blk); | ||||
| 	yaffs_verify_chunk_bit_id(dev, blk, chunk); | ||||
|  | ||||
| 	yaffs_verify_chunk_bit_id(dev, blk, chunk); | ||||
| 	return (blk_bits[chunk / 8] & (1 << (chunk & 7))) ? 1 : 0; | ||||
| } | ||||
|  | ||||
| @@ -77,6 +75,7 @@ int yaffs_still_some_chunks(struct yaffs_dev *dev, int blk) | ||||
| { | ||||
| 	u8 *blk_bits = yaffs_block_bits(dev, blk); | ||||
| 	int i; | ||||
|  | ||||
| 	for (i = 0; i < dev->chunk_bit_stride; i++) { | ||||
| 		if (*blk_bits) | ||||
| 			return 1; | ||||
| @@ -90,15 +89,9 @@ int yaffs_count_chunk_bits(struct yaffs_dev *dev, int blk) | ||||
| 	u8 *blk_bits = yaffs_block_bits(dev, blk); | ||||
| 	int i; | ||||
| 	int n = 0; | ||||
| 	for (i = 0; i < dev->chunk_bit_stride; i++) { | ||||
| 		u8 x = *blk_bits; | ||||
| 		while (x) { | ||||
| 			if (x & 1) | ||||
| 				n++; | ||||
| 			x >>= 1; | ||||
| 		} | ||||
|  | ||||
| 		blk_bits++; | ||||
| 	} | ||||
| 	for (i = 0; i < dev->chunk_bit_stride; i++, blk_bits++) | ||||
| 		n += hweight8(*blk_bits); | ||||
|  | ||||
| 	return n; | ||||
| } | ||||
|   | ||||
| @@ -18,8 +18,8 @@ static int yaffs2_checkpt_space_ok(struct yaffs_dev *dev) | ||||
| { | ||||
| 	int blocks_avail = dev->n_erased_blocks - dev->param.n_reserved_blocks; | ||||
|  | ||||
| 	T(YAFFS_TRACE_CHECKPOINT, | ||||
| 	  (TSTR("checkpt blocks available = %d" TENDSTR), blocks_avail)); | ||||
| 	yaffs_trace(YAFFS_TRACE_CHECKPOINT, | ||||
| 		"checkpt blocks_avail = %d", blocks_avail); | ||||
|  | ||||
| 	return (blocks_avail <= 0) ? 0 : 1; | ||||
| } | ||||
| @@ -30,21 +30,21 @@ static int yaffs_checkpt_erase(struct yaffs_dev *dev) | ||||
|  | ||||
| 	if (!dev->param.erase_fn) | ||||
| 		return 0; | ||||
| 	T(YAFFS_TRACE_CHECKPOINT, (TSTR("checking blocks %d to %d" TENDSTR), | ||||
| 				   dev->internal_start_block, | ||||
| 				   dev->internal_end_block)); | ||||
| 	yaffs_trace(YAFFS_TRACE_CHECKPOINT, | ||||
| 		"checking blocks %d to %d", | ||||
| 		dev->internal_start_block, dev->internal_end_block); | ||||
|  | ||||
| 	for (i = dev->internal_start_block; i <= dev->internal_end_block; i++) { | ||||
| 		struct yaffs_block_info *bi = yaffs_get_block_info(dev, i); | ||||
| 		if (bi->block_state == YAFFS_BLOCK_STATE_CHECKPOINT) { | ||||
| 			T(YAFFS_TRACE_CHECKPOINT, | ||||
| 			  (TSTR("erasing checkpt block %d" TENDSTR), i)); | ||||
| 			yaffs_trace(YAFFS_TRACE_CHECKPOINT, | ||||
| 			"erasing checkpt block %d", i); | ||||
|  | ||||
| 			dev->n_erasures++; | ||||
|  | ||||
| 			if (dev->param. | ||||
| 			    erase_fn(dev, | ||||
| 				     i - dev->block_offset /* realign */ )) { | ||||
| 				     i - dev->block_offset /* realign */)) { | ||||
| 				bi->block_state = YAFFS_BLOCK_STATE_EMPTY; | ||||
| 				dev->n_erased_blocks++; | ||||
| 				dev->n_free_chunks += | ||||
| @@ -65,11 +65,11 @@ static void yaffs2_checkpt_find_erased_block(struct yaffs_dev *dev) | ||||
| { | ||||
| 	int i; | ||||
| 	int blocks_avail = dev->n_erased_blocks - dev->param.n_reserved_blocks; | ||||
| 	T(YAFFS_TRACE_CHECKPOINT, | ||||
| 	  (TSTR | ||||
| 	   ("allocating checkpt block: erased %d reserved %d avail %d next %d " | ||||
| 	    TENDSTR), dev->n_erased_blocks, dev->param.n_reserved_blocks, | ||||
| 	   blocks_avail, dev->checkpt_next_block)); | ||||
|  | ||||
| 	yaffs_trace(YAFFS_TRACE_CHECKPOINT, | ||||
| 		"allocating checkpt block: erased %d reserved %d avail %d next %d ", | ||||
| 		dev->n_erased_blocks, dev->param.n_reserved_blocks, | ||||
| 		blocks_avail, dev->checkpt_next_block); | ||||
|  | ||||
| 	if (dev->checkpt_next_block >= 0 && | ||||
| 	    dev->checkpt_next_block <= dev->internal_end_block && | ||||
| @@ -82,14 +82,13 @@ static void yaffs2_checkpt_find_erased_block(struct yaffs_dev *dev) | ||||
| 			if (bi->block_state == YAFFS_BLOCK_STATE_EMPTY) { | ||||
| 				dev->checkpt_next_block = i + 1; | ||||
| 				dev->checkpt_cur_block = i; | ||||
| 				T(YAFFS_TRACE_CHECKPOINT, | ||||
| 				  (TSTR("allocating checkpt block %d" TENDSTR), | ||||
| 				   i)); | ||||
| 				yaffs_trace(YAFFS_TRACE_CHECKPOINT, | ||||
| 					"allocating checkpt block %d", i); | ||||
| 				return; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	T(YAFFS_TRACE_CHECKPOINT, (TSTR("out of checkpt blocks" TENDSTR))); | ||||
| 	yaffs_trace(YAFFS_TRACE_CHECKPOINT, "out of checkpt blocks"); | ||||
|  | ||||
| 	dev->checkpt_next_block = -1; | ||||
| 	dev->checkpt_cur_block = -1; | ||||
| @@ -100,9 +99,9 @@ static void yaffs2_checkpt_find_block(struct yaffs_dev *dev) | ||||
| 	int i; | ||||
| 	struct yaffs_ext_tags tags; | ||||
|  | ||||
| 	T(YAFFS_TRACE_CHECKPOINT, | ||||
| 	  (TSTR("find next checkpt block: start:  blocks %d next %d" TENDSTR), | ||||
| 	   dev->blocks_in_checkpt, dev->checkpt_next_block)); | ||||
| 	yaffs_trace(YAFFS_TRACE_CHECKPOINT, | ||||
| 		"find next checkpt block: start:  blocks %d next %d", | ||||
| 		dev->blocks_in_checkpt, dev->checkpt_next_block); | ||||
|  | ||||
| 	if (dev->blocks_in_checkpt < dev->checkpt_max_blocks) | ||||
| 		for (i = dev->checkpt_next_block; i <= dev->internal_end_block; | ||||
| @@ -112,11 +111,10 @@ static void yaffs2_checkpt_find_block(struct yaffs_dev *dev) | ||||
|  | ||||
| 			dev->param.read_chunk_tags_fn(dev, realigned_chunk, | ||||
| 						      NULL, &tags); | ||||
| 			T(YAFFS_TRACE_CHECKPOINT, | ||||
| 			  (TSTR | ||||
| 			   ("find next checkpt block: search: block %d oid %d seq %d eccr %d" | ||||
| 			    TENDSTR), i, tags.obj_id, tags.seq_number, | ||||
| 			   tags.ecc_result)); | ||||
| 			yaffs_trace(YAFFS_TRACE_CHECKPOINT, | ||||
| 				"find next checkpt block: search: block %d oid %d seq %d eccr %d", | ||||
| 				i, tags.obj_id, tags.seq_number, | ||||
| 				tags.ecc_result); | ||||
|  | ||||
| 			if (tags.seq_number == YAFFS_SEQUENCE_CHECKPOINT_DATA) { | ||||
| 				/* Right kind of block */ | ||||
| @@ -125,14 +123,13 @@ static void yaffs2_checkpt_find_block(struct yaffs_dev *dev) | ||||
| 				dev->checkpt_block_list[dev-> | ||||
| 							blocks_in_checkpt] = i; | ||||
| 				dev->blocks_in_checkpt++; | ||||
| 				T(YAFFS_TRACE_CHECKPOINT, | ||||
| 				  (TSTR("found checkpt block %d" TENDSTR), i)); | ||||
| 				yaffs_trace(YAFFS_TRACE_CHECKPOINT, | ||||
| 					"found checkpt block %d", i); | ||||
| 				return; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 	T(YAFFS_TRACE_CHECKPOINT, | ||||
| 	  (TSTR("found no more checkpt blocks" TENDSTR))); | ||||
| 	yaffs_trace(YAFFS_TRACE_CHECKPOINT, "found no more checkpt blocks"); | ||||
|  | ||||
| 	dev->checkpt_next_block = -1; | ||||
| 	dev->checkpt_cur_block = -1; | ||||
| @@ -140,7 +137,6 @@ static void yaffs2_checkpt_find_block(struct yaffs_dev *dev) | ||||
|  | ||||
| int yaffs2_checkpt_open(struct yaffs_dev *dev, int writing) | ||||
| { | ||||
|  | ||||
| 	dev->checkpt_open_write = writing; | ||||
|  | ||||
| 	/* Got the functions we need? */ | ||||
| @@ -154,7 +150,7 @@ int yaffs2_checkpt_open(struct yaffs_dev *dev, int writing) | ||||
|  | ||||
| 	if (!dev->checkpt_buffer) | ||||
| 		dev->checkpt_buffer = | ||||
| 		    YMALLOC_DMA(dev->param.total_bytes_per_chunk); | ||||
| 		    kmalloc(dev->param.total_bytes_per_chunk, GFP_NOFS); | ||||
| 	if (!dev->checkpt_buffer) | ||||
| 		return 0; | ||||
|  | ||||
| @@ -175,14 +171,14 @@ int yaffs2_checkpt_open(struct yaffs_dev *dev, int writing) | ||||
| 		int i; | ||||
| 		/* Set to a value that will kick off a read */ | ||||
| 		dev->checkpt_byte_offs = dev->data_bytes_per_chunk; | ||||
| 		/* A checkpoint block list of 1 checkpoint block per 16 block is (hopefully) | ||||
| 		 * going to be way more than we need */ | ||||
| 		/* A checkpoint block list of 1 checkpoint block per 16 block is | ||||
| 		 * (hopefully) going to be way more than we need */ | ||||
| 		dev->blocks_in_checkpt = 0; | ||||
| 		dev->checkpt_max_blocks = | ||||
| 		    (dev->internal_end_block - dev->internal_start_block) / 16 + | ||||
| 		    2; | ||||
| 		dev->checkpt_block_list = | ||||
| 		    YMALLOC(sizeof(int) * dev->checkpt_max_blocks); | ||||
| 		    kmalloc(sizeof(int) * dev->checkpt_max_blocks, GFP_NOFS); | ||||
| 		if (!dev->checkpt_block_list) | ||||
| 			return 0; | ||||
|  | ||||
| @@ -196,6 +192,7 @@ int yaffs2_checkpt_open(struct yaffs_dev *dev, int writing) | ||||
| int yaffs2_get_checkpt_sum(struct yaffs_dev *dev, u32 * sum) | ||||
| { | ||||
| 	u32 composite_sum; | ||||
|  | ||||
| 	composite_sum = (dev->checkpt_sum << 8) | (dev->checkpt_xor & 0xFF); | ||||
| 	*sum = composite_sum; | ||||
| 	return 1; | ||||
| @@ -205,7 +202,6 @@ static int yaffs2_checkpt_flush_buffer(struct yaffs_dev *dev) | ||||
| { | ||||
| 	int chunk; | ||||
| 	int realigned_chunk; | ||||
|  | ||||
| 	struct yaffs_ext_tags tags; | ||||
|  | ||||
| 	if (dev->checkpt_cur_block < 0) { | ||||
| @@ -234,11 +230,10 @@ static int yaffs2_checkpt_flush_buffer(struct yaffs_dev *dev) | ||||
| 	    dev->checkpt_cur_block * dev->param.chunks_per_block + | ||||
| 	    dev->checkpt_cur_chunk; | ||||
|  | ||||
| 	T(YAFFS_TRACE_CHECKPOINT, | ||||
| 	  (TSTR | ||||
| 	   ("checkpoint wite buffer nand %d(%d:%d) objid %d chId %d" TENDSTR), | ||||
| 	   chunk, dev->checkpt_cur_block, dev->checkpt_cur_chunk, tags.obj_id, | ||||
| 	   tags.chunk_id)); | ||||
| 	yaffs_trace(YAFFS_TRACE_CHECKPOINT, | ||||
| 		"checkpoint wite buffer nand %d(%d:%d) objid %d chId %d", | ||||
| 		chunk, dev->checkpt_cur_block, dev->checkpt_cur_chunk, | ||||
| 		tags.obj_id, tags.chunk_id); | ||||
|  | ||||
| 	realigned_chunk = chunk - dev->chunk_offset; | ||||
|  | ||||
| @@ -262,7 +257,6 @@ int yaffs2_checkpt_wr(struct yaffs_dev *dev, const void *data, int n_bytes) | ||||
| { | ||||
| 	int i = 0; | ||||
| 	int ok = 1; | ||||
|  | ||||
| 	u8 *data_bytes = (u8 *) data; | ||||
|  | ||||
| 	if (!dev->checkpt_buffer) | ||||
| @@ -294,10 +288,8 @@ int yaffs2_checkpt_rd(struct yaffs_dev *dev, void *data, int n_bytes) | ||||
| 	int i = 0; | ||||
| 	int ok = 1; | ||||
| 	struct yaffs_ext_tags tags; | ||||
|  | ||||
| 	int chunk; | ||||
| 	int realigned_chunk; | ||||
|  | ||||
| 	u8 *data_bytes = (u8 *) data; | ||||
|  | ||||
| 	if (!dev->checkpt_buffer) | ||||
| @@ -329,10 +321,9 @@ int yaffs2_checkpt_rd(struct yaffs_dev *dev, void *data, int n_bytes) | ||||
|  | ||||
| 				/* read in the next chunk */ | ||||
| 				dev->param.read_chunk_tags_fn(dev, | ||||
| 							      realigned_chunk, | ||||
| 							      dev-> | ||||
| 							      checkpt_buffer, | ||||
| 							      &tags); | ||||
| 							realigned_chunk, | ||||
| 							dev->checkpt_buffer, | ||||
| 							&tags); | ||||
|  | ||||
| 				if (tags.chunk_id != (dev->checkpt_page_seq + 1) | ||||
| 				    || tags.ecc_result > YAFFS_ECC_RESULT_FIXED | ||||
| @@ -367,7 +358,6 @@ int yaffs2_checkpt_rd(struct yaffs_dev *dev, void *data, int n_bytes) | ||||
|  | ||||
| int yaffs_checkpt_close(struct yaffs_dev *dev) | ||||
| { | ||||
|  | ||||
| 	if (dev->checkpt_open_write) { | ||||
| 		if (dev->checkpt_byte_offs != 0) | ||||
| 			yaffs2_checkpt_flush_buffer(dev); | ||||
| @@ -383,11 +373,8 @@ int yaffs_checkpt_close(struct yaffs_dev *dev) | ||||
| 				bi = yaffs_get_block_info(dev, blk); | ||||
| 			if (bi && bi->block_state == YAFFS_BLOCK_STATE_EMPTY) | ||||
| 				bi->block_state = YAFFS_BLOCK_STATE_CHECKPOINT; | ||||
| 			else { | ||||
| 				/* Todo this looks odd... */ | ||||
| 			} | ||||
| 		} | ||||
| 		YFREE(dev->checkpt_block_list); | ||||
| 		kfree(dev->checkpt_block_list); | ||||
| 		dev->checkpt_block_list = NULL; | ||||
| 	} | ||||
|  | ||||
| @@ -395,25 +382,26 @@ int yaffs_checkpt_close(struct yaffs_dev *dev) | ||||
| 	    dev->blocks_in_checkpt * dev->param.chunks_per_block; | ||||
| 	dev->n_erased_blocks -= dev->blocks_in_checkpt; | ||||
|  | ||||
| 	T(YAFFS_TRACE_CHECKPOINT, (TSTR("checkpoint byte count %d" TENDSTR), | ||||
| 				   dev->checkpt_byte_count)); | ||||
| 	yaffs_trace(YAFFS_TRACE_CHECKPOINT, "checkpoint byte count %d", | ||||
| 		dev->checkpt_byte_count); | ||||
|  | ||||
| 	if (dev->checkpt_buffer) { | ||||
| 		/* free the buffer */ | ||||
| 		YFREE(dev->checkpt_buffer); | ||||
| 		kfree(dev->checkpt_buffer); | ||||
| 		dev->checkpt_buffer = NULL; | ||||
| 		return 1; | ||||
| 	} else | ||||
| 	} else { | ||||
| 		return 0; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| int yaffs2_checkpt_invalidate_stream(struct yaffs_dev *dev) | ||||
| { | ||||
| 	/* Erase the checkpoint data */ | ||||
|  | ||||
| 	T(YAFFS_TRACE_CHECKPOINT, | ||||
| 	  (TSTR("checkpoint invalidate of %d blocks" TENDSTR), | ||||
| 	   dev->blocks_in_checkpt)); | ||||
| 	yaffs_trace(YAFFS_TRACE_CHECKPOINT, | ||||
| 		"checkpoint invalidate of %d blocks", | ||||
| 		dev->blocks_in_checkpt); | ||||
|  | ||||
| 	return yaffs_checkpt_erase(dev); | ||||
| } | ||||
|   | ||||
| @@ -16,16 +16,16 @@ | ||||
|  * | ||||
|  * 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. | ||||
|  * 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. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| /* Table generated by gen-ecc.c | ||||
|  * Using a table means we do not have to calculate p1..p4 and p1'..p4' | ||||
|  * for each byte of data. These are instead provided in a table in bits7..2. | ||||
|  * Bit 0 of each entry indicates whether the entry has an odd or even parity, and therefore | ||||
|  * this bytes influence on the line parity. | ||||
|  * Bit 0 of each entry indicates whether the entry has an odd or even parity, | ||||
|  * and therefore this bytes influence on the line parity. | ||||
|  */ | ||||
|  | ||||
| #include "yportenv.h" | ||||
| @@ -67,35 +67,11 @@ static const unsigned char column_parity_table[] = { | ||||
| 	0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00, | ||||
| }; | ||||
|  | ||||
| /* Count the bits in an unsigned char or a U32 */ | ||||
|  | ||||
| static int yaffs_count_bits(unsigned char x) | ||||
| { | ||||
| 	int r = 0; | ||||
| 	while (x) { | ||||
| 		if (x & 1) | ||||
| 			r++; | ||||
| 		x >>= 1; | ||||
| 	} | ||||
| 	return r; | ||||
| } | ||||
|  | ||||
| static int yaffs_count_bits32(unsigned x) | ||||
| { | ||||
| 	int r = 0; | ||||
| 	while (x) { | ||||
| 		if (x & 1) | ||||
| 			r++; | ||||
| 		x >>= 1; | ||||
| 	} | ||||
| 	return r; | ||||
| } | ||||
|  | ||||
| /* Calculate the ECC for a 256-byte block of data */ | ||||
| void yaffs_ecc_cacl(const unsigned char *data, unsigned char *ecc) | ||||
| { | ||||
| 	unsigned int i; | ||||
|  | ||||
| 	unsigned char col_parity = 0; | ||||
| 	unsigned char line_parity = 0; | ||||
| 	unsigned char line_parity_prime = 0; | ||||
| @@ -222,8 +198,7 @@ int yaffs_ecc_correct(unsigned char *data, unsigned char *read_ecc, | ||||
| 		return 1;	/* Corrected the error */ | ||||
| 	} | ||||
|  | ||||
| 	if ((yaffs_count_bits(d0) + | ||||
| 	     yaffs_count_bits(d1) + yaffs_count_bits(d2)) == 1) { | ||||
| 	if ((hweight8(d0) + hweight8(d1) + hweight8(d2)) == 1) { | ||||
| 		/* Reccoverable error in ecc */ | ||||
|  | ||||
| 		read_ecc[0] = test_ecc[0]; | ||||
| @@ -246,7 +221,6 @@ void yaffs_ecc_calc_other(const unsigned char *data, unsigned n_bytes, | ||||
| 			  struct yaffs_ecc_other *ecc_other) | ||||
| { | ||||
| 	unsigned int i; | ||||
|  | ||||
| 	unsigned char col_parity = 0; | ||||
| 	unsigned line_parity = 0; | ||||
| 	unsigned line_parity_prime = 0; | ||||
| @@ -307,9 +281,9 @@ int yaffs_ecc_correct_other(unsigned char *data, unsigned n_bytes, | ||||
| 		return 1;	/* corrected */ | ||||
| 	} | ||||
|  | ||||
| 	if ((yaffs_count_bits32(delta_line) + | ||||
| 	     yaffs_count_bits32(delta_line_prime) + | ||||
| 	     yaffs_count_bits(delta_col)) == 1) { | ||||
| 	if ((hweight32(delta_line) + | ||||
| 	     hweight32(delta_line_prime) + | ||||
| 	     hweight8(delta_col)) == 1) { | ||||
| 		/* Reccoverable error in ecc */ | ||||
|  | ||||
| 		*read_ecc = *test_ecc; | ||||
|   | ||||
| @@ -18,8 +18,8 @@ | ||||
|  * | ||||
|  * 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. | ||||
|  * 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. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
|   | ||||
| @@ -20,14 +20,13 @@ | ||||
| #include "yaffs_trace.h" | ||||
|  | ||||
| /* Function to manipulate block info */ | ||||
| static Y_INLINE struct yaffs_block_info *yaffs_get_block_info(struct yaffs_dev | ||||
| static inline struct yaffs_block_info *yaffs_get_block_info(struct yaffs_dev | ||||
| 							      *dev, int blk) | ||||
| { | ||||
| 	if (blk < dev->internal_start_block || blk > dev->internal_end_block) { | ||||
| 		T(YAFFS_TRACE_ERROR, | ||||
| 		  (TSTR | ||||
| 		   ("**>> yaffs: get_block_info block %d is not valid" TENDSTR), | ||||
| 		   blk)); | ||||
| 		yaffs_trace(YAFFS_TRACE_ERROR, | ||||
| 			"**>> yaffs: get_block_info block %d is not valid", | ||||
| 			blk); | ||||
| 		YBUG(); | ||||
| 	} | ||||
| 	return &dev->block_info[blk - dev->internal_start_block]; | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -29,12 +29,12 @@ | ||||
|  */ | ||||
| #define YAFFS_MAGIC			0x5941FF53 | ||||
|  | ||||
| #define YAFFS_NTNODES_LEVEL0	  	16 | ||||
| #define YAFFS_NTNODES_LEVEL0		16 | ||||
| #define YAFFS_TNODES_LEVEL0_BITS	4 | ||||
| #define YAFFS_TNODES_LEVEL0_MASK	0xf | ||||
|  | ||||
| #define YAFFS_NTNODES_INTERNAL 		(YAFFS_NTNODES_LEVEL0 / 2) | ||||
| #define YAFFS_TNODES_INTERNAL_BITS 	(YAFFS_TNODES_LEVEL0_BITS - 1) | ||||
| #define YAFFS_NTNODES_INTERNAL		(YAFFS_NTNODES_LEVEL0 / 2) | ||||
| #define YAFFS_TNODES_INTERNAL_BITS	(YAFFS_TNODES_LEVEL0_BITS - 1) | ||||
| #define YAFFS_TNODES_INTERNAL_MASK	0x7 | ||||
| #define YAFFS_TNODES_MAX_LEVEL		6 | ||||
|  | ||||
| @@ -43,10 +43,10 @@ | ||||
| #define YAFFS_BYTES_PER_CHUNK		512 | ||||
| #define YAFFS_CHUNK_SIZE_SHIFT		9 | ||||
| #define YAFFS_CHUNKS_PER_BLOCK		32 | ||||
| #define YAFFS_BYTES_PER_BLOCK		(YAFFS_CHUNKS_PER_BLOCK*YAFFS_BYTES_PER_CHUNK) | ||||
| #define YAFFS_BYTES_PER_BLOCK	(YAFFS_CHUNKS_PER_BLOCK*YAFFS_BYTES_PER_CHUNK) | ||||
| #endif | ||||
|  | ||||
| #define YAFFS_MIN_YAFFS2_CHUNK_SIZE 	1024 | ||||
| #define YAFFS_MIN_YAFFS2_CHUNK_SIZE	1024 | ||||
| #define YAFFS_MIN_YAFFS2_SPARE_SIZE	32 | ||||
|  | ||||
| #define YAFFS_MAX_CHUNK_ID		0x000FFFFF | ||||
| @@ -58,9 +58,9 @@ | ||||
| #define YAFFS_NOBJECT_BUCKETS		256 | ||||
|  | ||||
| #define YAFFS_OBJECT_SPACE		0x40000 | ||||
| #define YAFFS_MAX_OBJECT_ID		(YAFFS_OBJECT_SPACE -1) | ||||
| #define YAFFS_MAX_OBJECT_ID		(YAFFS_OBJECT_SPACE - 1) | ||||
|  | ||||
| #define YAFFS_CHECKPOINT_VERSION 	4 | ||||
| #define YAFFS_CHECKPOINT_VERSION	4 | ||||
|  | ||||
| #ifdef CONFIG_YAFFS_UNICODE | ||||
| #define YAFFS_MAX_NAME_LENGTH		127 | ||||
| @@ -97,7 +97,7 @@ | ||||
|  * The range is limited slightly to help distinguish bad numbers from good. | ||||
|  * This also allows us to perhaps in the future use special numbers for | ||||
|  * special purposes. | ||||
|  * EFFFFF00 allows the allocation of 8 blocks per second (~1Mbytes) for 15 years, | ||||
|  * EFFFFF00 allows the allocation of 8 blocks/second (~1Mbytes) for 15 years, | ||||
|  * and is a larger number than the lifetime of a 2GB device. | ||||
|  */ | ||||
| #define YAFFS_LOWEST_SEQUENCE_NUMBER	0x00001000 | ||||
| @@ -118,8 +118,8 @@ struct yaffs_cache { | ||||
| }; | ||||
|  | ||||
| /* Tags structures in RAM | ||||
|  * NB This uses bitfield. Bitfields should not straddle a u32 boundary otherwise | ||||
|  * the structure size will get blown out. | ||||
|  * NB This uses bitfield. Bitfields should not straddle a u32 boundary | ||||
|  * otherwise the structure size will get blown out. | ||||
|  */ | ||||
|  | ||||
| #ifndef CONFIG_YAFFS_NO_YAFFS1 | ||||
| @@ -163,8 +163,8 @@ struct yaffs_ext_tags { | ||||
|  | ||||
| 	unsigned validity0; | ||||
| 	unsigned chunk_used;	/*  Status of the chunk: used or unused */ | ||||
| 	unsigned obj_id;	/* If 0 then this is not part of an object (unused) */ | ||||
| 	unsigned chunk_id;	/* If 0 then this is a header, else a data chunk */ | ||||
| 	unsigned obj_id;	/* If 0 this is not used */ | ||||
| 	unsigned chunk_id;	/* If 0 this is a header, else a data chunk */ | ||||
| 	unsigned n_bytes;	/* Only valid for data chunks */ | ||||
|  | ||||
| 	/* The following stuff only has meaning when we read */ | ||||
| @@ -180,7 +180,7 @@ struct yaffs_ext_tags { | ||||
|  | ||||
| 	/* Extra info if this is an object header (YAFFS2 only) */ | ||||
|  | ||||
| 	unsigned extra_available;	/* There is extra info available if this is not zero */ | ||||
| 	unsigned extra_available;	/* Extra info available if not zero */ | ||||
| 	unsigned extra_parent_id;	/* The parent object */ | ||||
| 	unsigned extra_is_shrink;	/* Is it a shrink header? */ | ||||
| 	unsigned extra_shadows;	/* Does this shadow another object? */ | ||||
| @@ -188,7 +188,7 @@ struct yaffs_ext_tags { | ||||
| 	enum yaffs_obj_type extra_obj_type;	/* What object type? */ | ||||
|  | ||||
| 	unsigned extra_length;	/* Length if it is a file */ | ||||
| 	unsigned extra_equiv_id;	/* Equivalent object Id if it is a hard link */ | ||||
| 	unsigned extra_equiv_id;	/* Equivalent object for a hard link */ | ||||
|  | ||||
| 	unsigned validity1; | ||||
|  | ||||
| @@ -226,11 +226,14 @@ enum yaffs_block_state { | ||||
| 	/* Being scanned */ | ||||
|  | ||||
| 	YAFFS_BLOCK_STATE_NEEDS_SCANNING, | ||||
| 	/* The block might have something on it (ie it is allocating or full, perhaps empty) | ||||
| 	 * but it needs to be scanned to determine its true state. | ||||
| 	/* The block might have something on it (ie it is allocating or full, | ||||
| 	 * perhaps empty) but it needs to be scanned to determine its true | ||||
| 	 * state. | ||||
| 	 * This state is only valid during scanning. | ||||
| 	 * NB We tolerate empty because the pre-scanner might be incapable of deciding | ||||
| 	 * However, if this state is returned on a YAFFS2 device, then we expect a sequence number | ||||
| 	 * NB We tolerate empty because the pre-scanner might be incapable of | ||||
| 	 * deciding | ||||
| 	 * However, if this state is returned on a YAFFS2 device, | ||||
| 	 * then we expect a sequence number | ||||
| 	 */ | ||||
|  | ||||
| 	YAFFS_BLOCK_STATE_EMPTY, | ||||
| @@ -241,7 +244,8 @@ enum yaffs_block_state { | ||||
| 	 * At least one page holds valid data. | ||||
| 	 * This is the one currently being used for page | ||||
| 	 * allocation. Should never be more than one of these. | ||||
| 	 * If a block is only partially allocated at mount it is treated as full. | ||||
| 	 * If a block is only partially allocated at mount it is treated as | ||||
| 	 * full. | ||||
| 	 */ | ||||
|  | ||||
| 	YAFFS_BLOCK_STATE_FULL, | ||||
| @@ -271,16 +275,19 @@ struct yaffs_block_info { | ||||
|  | ||||
| 	int soft_del_pages:10;	/* number of soft deleted pages */ | ||||
| 	int pages_in_use:10;	/* number of pages in use */ | ||||
| 	unsigned block_state:4;	/* One of the above block states. NB use unsigned because enum is sometimes an int */ | ||||
| 	u32 needs_retiring:1;	/* Data has failed on this block, need to get valid data off */ | ||||
| 	/* and retire the block. */ | ||||
| 	u32 skip_erased_check:1;	/* If this is set we can skip the erased check on this block */ | ||||
| 	u32 gc_prioritise:1;	/* An ECC check or blank check has failed on this block. | ||||
| 				   It should be prioritised for GC */ | ||||
| 	u32 chunk_error_strikes:3;	/* How many times we've had ecc etc failures on this block and tried to reuse it */ | ||||
| 	unsigned block_state:4;	/* One of the above block states. */ | ||||
| 				/* NB use unsigned because enum is sometimes | ||||
| 				 * an int */ | ||||
| 	u32 needs_retiring:1;	/* Data has failed on this block, */ | ||||
| 				/*need to get valid data off and retire*/ | ||||
| 	u32 skip_erased_check:1;/* Skip the erased check on this block */ | ||||
| 	u32 gc_prioritise:1;	/* An ECC check or blank check has failed. | ||||
| 				   Block should be prioritised for GC */ | ||||
| 	u32 chunk_error_strikes:3;	/* How many times we've had ecc etc | ||||
| 				failures on this block and tried to reuse it */ | ||||
|  | ||||
| #ifdef CONFIG_YAFFS_YAFFS2 | ||||
| 	u32 has_shrink_hdr:1;	/* This block has at least one shrink object header */ | ||||
| 	u32 has_shrink_hdr:1;	/* This block has at least one shrink header */ | ||||
| 	u32 seq_number;		/* block sequence number for yaffs2 */ | ||||
| #endif | ||||
|  | ||||
| @@ -297,7 +304,7 @@ struct yaffs_obj_hdr { | ||||
| 	u16 sum_no_longer_used;	/* checksum of name. No longer used */ | ||||
| 	YCHAR name[YAFFS_MAX_NAME_LENGTH + 1]; | ||||
|  | ||||
| 	/* The following apply to directories, files, symlinks - not hard links */ | ||||
| 	/* The following apply to all object types except for hard links */ | ||||
| 	u32 yst_mode;		/* protection */ | ||||
|  | ||||
| 	u32 yst_uid; | ||||
| @@ -315,7 +322,7 @@ struct yaffs_obj_hdr { | ||||
| 	/* Alias is for symlinks only. */ | ||||
| 	YCHAR alias[YAFFS_MAX_ALIAS_LENGTH + 1]; | ||||
|  | ||||
| 	u32 yst_rdev;		/* device stuff for block and char devices (major/min) */ | ||||
| 	u32 yst_rdev;	/* stuff for block and char devices (major/min) */ | ||||
|  | ||||
| 	u32 win_ctime[2]; | ||||
| 	u32 win_atime[2]; | ||||
| @@ -325,9 +332,10 @@ struct yaffs_obj_hdr { | ||||
| 	u32 inband_is_shrink; | ||||
|  | ||||
| 	u32 reserved[2]; | ||||
| 	int shadows_obj;	/* This object header shadows the specified object if > 0 */ | ||||
| 	int shadows_obj;	/* This object header shadows the | ||||
| 				specified object if > 0 */ | ||||
|  | ||||
| 	/* is_shrink applies to object headers written when we shrink the file (ie resize) */ | ||||
| 	/* is_shrink applies to object headers written when wemake a hole. */ | ||||
| 	u32 is_shrink; | ||||
|  | ||||
| }; | ||||
| @@ -378,35 +386,43 @@ union yaffs_obj_var { | ||||
| struct yaffs_obj { | ||||
| 	u8 deleted:1;		/* This should only apply to unlinked files. */ | ||||
| 	u8 soft_del:1;		/* it has also been soft deleted */ | ||||
| 	u8 unlinked:1;		/* An unlinked file. The file should be in the unlinked directory. */ | ||||
| 	u8 unlinked:1;		/* An unlinked file.*/ | ||||
| 	u8 fake:1;		/* A fake object has no presence on NAND. */ | ||||
| 	u8 rename_allowed:1;	/* Some objects are not allowed to be renamed. */ | ||||
| 	u8 rename_allowed:1;	/* Some objects cannot be renamed. */ | ||||
| 	u8 unlink_allowed:1; | ||||
| 	u8 dirty:1;		/* the object needs to be written to flash */ | ||||
| 	u8 valid:1;		/* When the file system is being loaded up, this | ||||
| 				 * object might be created before the data | ||||
| 				 * is available (ie. file data records appear before the header). | ||||
| 				 * is available | ||||
| 				 * ie. file data chunks encountered before | ||||
| 				* the header. | ||||
| 				 */ | ||||
| 	u8 lazy_loaded:1;	/* This object has been lazy loaded and is missing some detail */ | ||||
| 	u8 lazy_loaded:1;	/* This object has been lazy loaded and | ||||
| 				 * is missing some detail */ | ||||
|  | ||||
| 	u8 defered_free:1;	/* For Linux kernel. Object is removed from NAND, but is | ||||
| 				 * still in the inode cache. Free of object is defered. | ||||
| 	u8 defered_free:1;	/* Object is removed from NAND, but is | ||||
| 				 * still in the inode cache. | ||||
| 				 * Free of object is defered. | ||||
| 				 * until the inode is released. | ||||
| 				 */ | ||||
| 	u8 being_created:1;	/* This object is still being created so skip some checks. */ | ||||
| 	u8 is_shadowed:1;	/* This object is shadowed on the way to being renamed. */ | ||||
| 	u8 being_created:1;	/* This object is still being created | ||||
| 				 * so skip some verification checks. */ | ||||
| 	u8 is_shadowed:1;	/* This object is shadowed on the way | ||||
| 				 * to being renamed. */ | ||||
|  | ||||
| 	u8 xattr_known:1;	/* We know if this has object has xattribs or not. */ | ||||
| 	u8 has_xattr:1;		/* This object has xattribs. Valid if xattr_known. */ | ||||
| 	u8 xattr_known:1;	/* We know if this has object has xattribs | ||||
| 				 * or not. */ | ||||
| 	u8 has_xattr:1;		/* This object has xattribs. | ||||
| 				 * Only valid if xattr_known. */ | ||||
|  | ||||
| 	u8 serial;		/* serial number of chunk in NAND. Cached here */ | ||||
| 	u8 serial;		/* serial number of chunk in NAND.*/ | ||||
| 	u16 sum;		/* sum of the name to speed searching */ | ||||
|  | ||||
| 	struct yaffs_dev *my_dev;	/* The device I'm on */ | ||||
|  | ||||
| 	struct list_head hash_link;	/* list of objects in this hash bucket */ | ||||
| 	struct list_head hash_link;	/* list of objects in hash bucket */ | ||||
|  | ||||
| 	struct list_head hard_links;	/* all the equivalent hard linked objects */ | ||||
| 	struct list_head hard_links;	/* hard linked object chain*/ | ||||
|  | ||||
| 	/* directory structure stuff */ | ||||
| 	/* also used for linking up the free list */ | ||||
| @@ -416,13 +432,13 @@ struct yaffs_obj { | ||||
| 	/* Where's my object header in NAND? */ | ||||
| 	int hdr_chunk; | ||||
|  | ||||
| 	int n_data_chunks;	/* Number of data chunks attached to the file. */ | ||||
| 	int n_data_chunks;	/* Number of data chunks for this file. */ | ||||
|  | ||||
| 	u32 obj_id;		/* the object id value */ | ||||
|  | ||||
| 	u32 yst_mode; | ||||
|  | ||||
| #ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM | ||||
| #ifndef CONFIG_YAFFS_NO_SHORT_NAMES | ||||
| 	YCHAR short_name[YAFFS_SHORT_NAME_LENGTH + 1]; | ||||
| #endif | ||||
|  | ||||
| @@ -481,7 +497,7 @@ struct yaffs_checkpt_obj { | ||||
|  | ||||
| struct yaffs_buffer { | ||||
| 	u8 *buffer; | ||||
| 	int line;		/* track from whence this buffer was allocated */ | ||||
| 	int line;	/* track from whence this buffer was allocated */ | ||||
| 	int max_line; | ||||
| }; | ||||
|  | ||||
| @@ -497,26 +513,28 @@ struct yaffs_param { | ||||
| 	 */ | ||||
|  | ||||
| 	int inband_tags;	/* Use unband tags */ | ||||
| 	u32 total_bytes_per_chunk;	/* Should be >= 512, does not need to be a power of 2 */ | ||||
| 	u32 total_bytes_per_chunk;	/* Should be >= 512, does not need to | ||||
| 					 be a power of 2 */ | ||||
| 	int chunks_per_block;	/* does not need to be a power of 2 */ | ||||
| 	int spare_bytes_per_chunk;	/* spare area size */ | ||||
| 	int start_block;	/* Start block we're allowed to use */ | ||||
| 	int end_block;		/* End block we're allowed to use */ | ||||
| 	int n_reserved_blocks;	/* We want this tuneable so that we can reduce */ | ||||
| 	/* reserved blocks on NOR and RAM. */ | ||||
| 	int n_reserved_blocks;	/* Tuneable so that we can reduce | ||||
| 				 * reserved blocks on NOR and RAM. */ | ||||
|  | ||||
| 	int n_caches;		/* If <= 0, then short op caching is disabled, else | ||||
| 				 * the number of short op caches (don't use too many). | ||||
| 				 * 10 to 20 is a good bet. | ||||
| 	int n_caches;		/* If <= 0, then short op caching is disabled, | ||||
| 				 * else the number of short op caches. | ||||
| 				 */ | ||||
| 	int use_nand_ecc;	/* Flag to decide whether or not to use NANDECC on data (yaffs1) */ | ||||
| 	int no_tags_ecc;	/* Flag to decide whether or not to do ECC on packed tags (yaffs2) */ | ||||
| 	int use_nand_ecc;	/* Flag to decide whether or not to use | ||||
| 				 * NAND driver ECC on data (yaffs1) */ | ||||
| 	int no_tags_ecc;	/* Flag to decide whether or not to do ECC | ||||
| 				 * on packed tags (yaffs2) */ | ||||
|  | ||||
| 	int is_yaffs2;		/* Use yaffs2 mode on this device */ | ||||
|  | ||||
| 	int empty_lost_n_found;	/* Auto-empty lost+found directory on mount */ | ||||
|  | ||||
| 	int refresh_period;	/* How often we should check to do a block refresh */ | ||||
| 	int refresh_period;	/* How often to check for a block refresh */ | ||||
|  | ||||
| 	/* Checkpoint control. Can be set before or after initialisation */ | ||||
| 	u8 skip_checkpt_rd; | ||||
| @@ -526,27 +544,27 @@ struct yaffs_param { | ||||
|  | ||||
| 	/* NAND access functions (Must be set before calling YAFFS) */ | ||||
|  | ||||
| 	int (*write_chunk_fn) (struct yaffs_dev * dev, | ||||
| 			       int nand_chunk, const u8 * data, | ||||
| 			       const struct yaffs_spare * spare); | ||||
| 	int (*read_chunk_fn) (struct yaffs_dev * dev, | ||||
| 			      int nand_chunk, u8 * data, | ||||
| 			      struct yaffs_spare * spare); | ||||
| 	int (*erase_fn) (struct yaffs_dev * dev, int flash_block); | ||||
| 	int (*initialise_flash_fn) (struct yaffs_dev * dev); | ||||
| 	int (*deinitialise_flash_fn) (struct yaffs_dev * dev); | ||||
| 	int (*write_chunk_fn) (struct yaffs_dev *dev, | ||||
| 			       int nand_chunk, const u8 *data, | ||||
| 			       const struct yaffs_spare *spare); | ||||
| 	int (*read_chunk_fn) (struct yaffs_dev *dev, | ||||
| 			      int nand_chunk, u8 *data, | ||||
| 			      struct yaffs_spare *spare); | ||||
| 	int (*erase_fn) (struct yaffs_dev *dev, int flash_block); | ||||
| 	int (*initialise_flash_fn) (struct yaffs_dev *dev); | ||||
| 	int (*deinitialise_flash_fn) (struct yaffs_dev *dev); | ||||
|  | ||||
| #ifdef CONFIG_YAFFS_YAFFS2 | ||||
| 	int (*write_chunk_tags_fn) (struct yaffs_dev * dev, | ||||
| 				    int nand_chunk, const u8 * data, | ||||
| 				    const struct yaffs_ext_tags * tags); | ||||
| 	int (*read_chunk_tags_fn) (struct yaffs_dev * dev, | ||||
| 				   int nand_chunk, u8 * data, | ||||
| 				   struct yaffs_ext_tags * tags); | ||||
| 	int (*bad_block_fn) (struct yaffs_dev * dev, int block_no); | ||||
| 	int (*query_block_fn) (struct yaffs_dev * dev, int block_no, | ||||
| 			       enum yaffs_block_state * state, | ||||
| 			       u32 * seq_number); | ||||
| 	int (*write_chunk_tags_fn) (struct yaffs_dev *dev, | ||||
| 				    int nand_chunk, const u8 *data, | ||||
| 				    const struct yaffs_ext_tags *tags); | ||||
| 	int (*read_chunk_tags_fn) (struct yaffs_dev *dev, | ||||
| 				   int nand_chunk, u8 *data, | ||||
| 				   struct yaffs_ext_tags *tags); | ||||
| 	int (*bad_block_fn) (struct yaffs_dev *dev, int block_no); | ||||
| 	int (*query_block_fn) (struct yaffs_dev *dev, int block_no, | ||||
| 			       enum yaffs_block_state *state, | ||||
| 			       u32 *seq_number); | ||||
| #endif | ||||
|  | ||||
| 	/* The remove_obj_fn function must be supplied by OS flavours that | ||||
| @@ -554,19 +572,21 @@ struct yaffs_param { | ||||
| 	 * yaffs direct uses it to implement the faster readdir. | ||||
| 	 * Linux uses it to protect the directory during unlocking. | ||||
| 	 */ | ||||
| 	void (*remove_obj_fn) (struct yaffs_obj * obj); | ||||
| 	void (*remove_obj_fn) (struct yaffs_obj *obj); | ||||
|  | ||||
| 	/* Callback to mark the superblock dirty */ | ||||
| 	void (*sb_dirty_fn) (struct yaffs_dev * dev); | ||||
| 	void (*sb_dirty_fn) (struct yaffs_dev *dev); | ||||
|  | ||||
| 	/*  Callback to control garbage collection. */ | ||||
| 	unsigned (*gc_control) (struct yaffs_dev * dev); | ||||
| 	unsigned (*gc_control) (struct yaffs_dev *dev); | ||||
|  | ||||
| 	/* Debug control flags. Don't use unless you know what you're doing */ | ||||
| 	int use_header_file_size;	/* Flag to determine if we should use file sizes from the header */ | ||||
| 	int use_header_file_size;	/* Flag to determine if we should use | ||||
| 					 * file sizes from the header */ | ||||
| 	int disable_lazy_load;	/* Disable lazy loading on this device */ | ||||
| 	int wide_tnodes_disabled;	/* Set to disable wide tnodes */ | ||||
| 	int disable_soft_del;	/* yaffs 1 only: Set to disable the use of softdeletion. */ | ||||
| 	int disable_soft_del;	/* yaffs 1 only: Set to disable the use of | ||||
| 				 * softdeletion. */ | ||||
|  | ||||
| 	int defered_dir_update;	/* Set to defer directory updates */ | ||||
|  | ||||
| @@ -602,7 +622,7 @@ struct yaffs_dev { | ||||
|  | ||||
| 	/* Stuff for figuring out file offset to chunk conversions */ | ||||
| 	u32 chunk_shift;	/* Shift value */ | ||||
| 	u32 chunk_div;		/* Divisor after shifting: 1 for power-of-2 sizes */ | ||||
| 	u32 chunk_div;		/* Divisor after shifting: 1 for 2^n sizes */ | ||||
| 	u32 chunk_mask;		/* Mask to use for power-of-2 case */ | ||||
|  | ||||
| 	int is_mounted; | ||||
| @@ -616,7 +636,7 @@ struct yaffs_dev { | ||||
| 	int chunk_offset; | ||||
|  | ||||
| 	/* Runtime checkpointing stuff */ | ||||
| 	int checkpt_page_seq;	/* running sequence number of checkpoint pages */ | ||||
| 	int checkpt_page_seq;	/* running sequence number of checkpt pages */ | ||||
| 	int checkpt_byte_count; | ||||
| 	int checkpt_byte_offs; | ||||
| 	u8 *checkpt_buffer; | ||||
| @@ -630,13 +650,14 @@ struct yaffs_dev { | ||||
| 	u32 checkpt_sum; | ||||
| 	u32 checkpt_xor; | ||||
|  | ||||
| 	int checkpoint_blocks_required;	/* Number of blocks needed to store current checkpoint set */ | ||||
| 	int checkpoint_blocks_required;	/* Number of blocks needed to store | ||||
| 					 * current checkpoint set */ | ||||
|  | ||||
| 	/* Block Info */ | ||||
| 	struct yaffs_block_info *block_info; | ||||
| 	u8 *chunk_bits;		/* bitmap of chunks in use */ | ||||
| 	unsigned block_info_alt:1;	/* was allocated using alternative strategy */ | ||||
| 	unsigned chunk_bits_alt:1;	/* was allocated using alternative strategy */ | ||||
| 	unsigned block_info_alt:1;	/* allocated using alternative alloc */ | ||||
| 	unsigned chunk_bits_alt:1;	/* allocated using alternative alloc */ | ||||
| 	int chunk_bit_stride;	/* Number of bytes of chunk_bits per block. | ||||
| 				 * Must be consistent with chunks_per_block. | ||||
| 				 */ | ||||
| @@ -662,7 +683,8 @@ struct yaffs_dev { | ||||
| 	u32 *gc_cleanup_list;	/* objects to delete at the end of a GC. */ | ||||
| 	u32 n_clean_ups; | ||||
|  | ||||
| 	unsigned has_pending_prioritised_gc;	/* We think this device might have pending prioritised gcs */ | ||||
| 	unsigned has_pending_prioritised_gc;	/* We think this device might | ||||
| 						have pending prioritised gcs */ | ||||
| 	unsigned gc_disable; | ||||
| 	unsigned gc_block_finder; | ||||
| 	unsigned gc_dirtiest; | ||||
| @@ -676,11 +698,6 @@ struct yaffs_dev { | ||||
| 	struct yaffs_obj *root_dir; | ||||
| 	struct yaffs_obj *lost_n_found; | ||||
|  | ||||
| 	/* Buffer areas for storing data to recover from write failures TODO | ||||
| 	 *      u8            buffered_data[YAFFS_CHUNKS_PER_BLOCK][YAFFS_BYTES_PER_CHUNK]; | ||||
| 	 *      struct yaffs_spare buffered_spare[YAFFS_CHUNKS_PER_BLOCK]; | ||||
| 	 */ | ||||
|  | ||||
| 	int buffered_block;	/* Which block is buffered here? */ | ||||
| 	int doing_buffered_block_rewrite; | ||||
|  | ||||
| @@ -688,9 +705,12 @@ struct yaffs_dev { | ||||
| 	int cache_last_use; | ||||
|  | ||||
| 	/* Stuff for background deletion and unlinked files. */ | ||||
| 	struct yaffs_obj *unlinked_dir;	/* Directory where unlinked and deleted files live. */ | ||||
| 	struct yaffs_obj *del_dir;	/* Directory where deleted objects are sent to disappear. */ | ||||
| 	struct yaffs_obj *unlinked_deletion;	/* Current file being background deleted. */ | ||||
| 	struct yaffs_obj *unlinked_dir;	/* Directory where unlinked and deleted | ||||
| 					 files live. */ | ||||
| 	struct yaffs_obj *del_dir;	/* Directory where deleted objects are | ||||
| 					sent to disappear. */ | ||||
| 	struct yaffs_obj *unlinked_deletion;	/* Current file being | ||||
| 							background deleted. */ | ||||
| 	int n_deleted_files;	/* Count of files awaiting deletion; */ | ||||
| 	int n_unlinked_files;	/* Count of unlinked files. */ | ||||
| 	int n_bg_deletions;	/* Count of background deletions. */ | ||||
| @@ -703,12 +723,14 @@ struct yaffs_dev { | ||||
| 	int unmanaged_buffer_deallocs; | ||||
|  | ||||
| 	/* yaffs2 runtime stuff */ | ||||
| 	unsigned seq_number;	/* Sequence number of currently allocating block */ | ||||
| 	unsigned seq_number;	/* Sequence number of currently | ||||
| 					allocating block */ | ||||
| 	unsigned oldest_dirty_seq; | ||||
| 	unsigned oldest_dirty_block; | ||||
|  | ||||
| 	/* Block refreshing */ | ||||
| 	int refresh_skip;	/* A skip down counter. Refresh happens when this gets to zero. */ | ||||
| 	int refresh_skip;	/* A skip down counter. | ||||
| 				 * Refresh happens when this gets to zero. */ | ||||
|  | ||||
| 	/* Dirty directory handling */ | ||||
| 	struct list_head dirty_dirs;	/* List of dirty directories */ | ||||
| @@ -737,8 +759,8 @@ struct yaffs_dev { | ||||
|  | ||||
| }; | ||||
|  | ||||
| /* The CheckpointDevice structure holds the device information that changes at runtime and | ||||
|  * must be preserved over unmount/mount cycles. | ||||
| /* The CheckpointDevice structure holds the device information that changes | ||||
|  *at runtime and must be preserved over unmount/mount cycles. | ||||
|  */ | ||||
| struct yaffs_checkpt_dev { | ||||
| 	int struct_type; | ||||
| @@ -752,7 +774,8 @@ struct yaffs_checkpt_dev { | ||||
| 	int n_bg_deletions;	/* Count of background deletions. */ | ||||
|  | ||||
| 	/* yaffs2 runtime stuff */ | ||||
| 	unsigned seq_number;	/* Sequence number of currently allocating block */ | ||||
| 	unsigned seq_number;	/* Sequence number of currently | ||||
| 				 * allocating block */ | ||||
|  | ||||
| }; | ||||
|  | ||||
| @@ -806,7 +829,7 @@ int yaffs_wr_file(struct yaffs_obj *obj, const u8 * buffer, loff_t offset, | ||||
| int yaffs_resize_file(struct yaffs_obj *obj, loff_t new_size); | ||||
|  | ||||
| struct yaffs_obj *yaffs_create_file(struct yaffs_obj *parent, | ||||
| 				    const YCHAR * name, u32 mode, u32 uid, | ||||
| 				    const YCHAR *name, u32 mode, u32 uid, | ||||
| 				    u32 gid); | ||||
|  | ||||
| int yaffs_flush_file(struct yaffs_obj *obj, int update_time, int data_sync); | ||||
| @@ -818,35 +841,35 @@ int yaffs_checkpoint_save(struct yaffs_dev *dev); | ||||
| int yaffs_checkpoint_restore(struct yaffs_dev *dev); | ||||
|  | ||||
| /* Directory operations */ | ||||
| struct yaffs_obj *yaffs_create_dir(struct yaffs_obj *parent, const YCHAR * name, | ||||
| struct yaffs_obj *yaffs_create_dir(struct yaffs_obj *parent, const YCHAR *name, | ||||
| 				   u32 mode, u32 uid, u32 gid); | ||||
| struct yaffs_obj *yaffs_find_by_name(struct yaffs_obj *the_dir, | ||||
| 				     const YCHAR * name); | ||||
| 				     const YCHAR *name); | ||||
| struct yaffs_obj *yaffs_find_by_number(struct yaffs_dev *dev, u32 number); | ||||
|  | ||||
| /* Link operations */ | ||||
| struct yaffs_obj *yaffs_link_obj(struct yaffs_obj *parent, const YCHAR * name, | ||||
| struct yaffs_obj *yaffs_link_obj(struct yaffs_obj *parent, const YCHAR *name, | ||||
| 				 struct yaffs_obj *equiv_obj); | ||||
|  | ||||
| struct yaffs_obj *yaffs_get_equivalent_obj(struct yaffs_obj *obj); | ||||
|  | ||||
| /* Symlink operations */ | ||||
| struct yaffs_obj *yaffs_create_symlink(struct yaffs_obj *parent, | ||||
| 				       const YCHAR * name, u32 mode, u32 uid, | ||||
| 				       u32 gid, const YCHAR * alias); | ||||
| 				       const YCHAR *name, u32 mode, u32 uid, | ||||
| 				       u32 gid, const YCHAR *alias); | ||||
| YCHAR *yaffs_get_symlink_alias(struct yaffs_obj *obj); | ||||
|  | ||||
| /* Special inodes (fifos, sockets and devices) */ | ||||
| struct yaffs_obj *yaffs_create_special(struct yaffs_obj *parent, | ||||
| 				       const YCHAR * name, u32 mode, u32 uid, | ||||
| 				       const YCHAR *name, u32 mode, u32 uid, | ||||
| 				       u32 gid, u32 rdev); | ||||
|  | ||||
| int yaffs_set_xattrib(struct yaffs_obj *obj, const YCHAR * name, | ||||
| int yaffs_set_xattrib(struct yaffs_obj *obj, const YCHAR *name, | ||||
| 		      const void *value, int size, int flags); | ||||
| int yaffs_get_xattrib(struct yaffs_obj *obj, const YCHAR * name, void *value, | ||||
| int yaffs_get_xattrib(struct yaffs_obj *obj, const YCHAR *name, void *value, | ||||
| 		      int size); | ||||
| int yaffs_list_xattrib(struct yaffs_obj *obj, char *buffer, int size); | ||||
| int yaffs_remove_xattrib(struct yaffs_obj *obj, const YCHAR * name); | ||||
| int yaffs_remove_xattrib(struct yaffs_obj *obj, const YCHAR *name); | ||||
|  | ||||
| /* Special directories */ | ||||
| struct yaffs_obj *yaffs_root(struct yaffs_dev *dev); | ||||
| @@ -866,26 +889,26 @@ void yaffs_guts_test(struct yaffs_dev *dev); | ||||
| /* A few useful functions to be used within the core files*/ | ||||
| void yaffs_chunk_del(struct yaffs_dev *dev, int chunk_id, int mark_flash, | ||||
| 		     int lyn); | ||||
| int yaffs_check_ff(u8 * buffer, int n_bytes); | ||||
| int yaffs_check_ff(u8 *buffer, int n_bytes); | ||||
| void yaffs_handle_chunk_error(struct yaffs_dev *dev, | ||||
| 			      struct yaffs_block_info *bi); | ||||
|  | ||||
| u8 *yaffs_get_temp_buffer(struct yaffs_dev *dev, int line_no); | ||||
| void yaffs_release_temp_buffer(struct yaffs_dev *dev, u8 * buffer, int line_no); | ||||
| void yaffs_release_temp_buffer(struct yaffs_dev *dev, u8 *buffer, int line_no); | ||||
|  | ||||
| struct yaffs_obj *yaffs_find_or_create_by_number(struct yaffs_dev *dev, | ||||
| 						 int number, | ||||
| 						 enum yaffs_obj_type type); | ||||
| int yaffs_put_chunk_in_file(struct yaffs_obj *in, int inode_chunk, | ||||
| 			    int nand_chunk, int in_scan); | ||||
| void yaffs_set_obj_name(struct yaffs_obj *obj, const YCHAR * name); | ||||
| void yaffs_set_obj_name(struct yaffs_obj *obj, const YCHAR *name); | ||||
| void yaffs_set_obj_name_from_oh(struct yaffs_obj *obj, | ||||
| 				const struct yaffs_obj_hdr *oh); | ||||
| void yaffs_add_obj_to_dir(struct yaffs_obj *directory, struct yaffs_obj *obj); | ||||
| YCHAR *yaffs_clone_str(const YCHAR * str); | ||||
| YCHAR *yaffs_clone_str(const YCHAR *str); | ||||
| void yaffs_link_fixup(struct yaffs_dev *dev, struct yaffs_obj *hard_list); | ||||
| void yaffs_block_became_dirty(struct yaffs_dev *dev, int block_no); | ||||
| int yaffs_update_oh(struct yaffs_obj *in, const YCHAR * name, | ||||
| int yaffs_update_oh(struct yaffs_obj *in, const YCHAR *name, | ||||
| 		    int force, int is_shrink, int shadows, | ||||
| 		    struct yaffs_xattr_mod *xop); | ||||
| void yaffs_handle_shadowed_obj(struct yaffs_dev *dev, int obj_id, | ||||
| @@ -897,7 +920,7 @@ struct yaffs_tnode *yaffs_add_find_tnode_0(struct yaffs_dev *dev, | ||||
| 					   u32 chunk_id, | ||||
| 					   struct yaffs_tnode *passed_tn); | ||||
|  | ||||
| int yaffs_do_file_wr(struct yaffs_obj *in, const u8 * buffer, loff_t offset, | ||||
| int yaffs_do_file_wr(struct yaffs_obj *in, const u8 *buffer, loff_t offset, | ||||
| 		     int n_bytes, int write_trhrough); | ||||
| void yaffs_resize_file_down(struct yaffs_obj *obj, loff_t new_size); | ||||
| void yaffs_skip_rest_of_block(struct yaffs_dev *dev); | ||||
| @@ -911,4 +934,5 @@ struct yaffs_tnode *yaffs_find_tnode_0(struct yaffs_dev *dev, | ||||
| u32 yaffs_get_group_base(struct yaffs_dev *dev, struct yaffs_tnode *tn, | ||||
| 			 unsigned pos); | ||||
|  | ||||
| int yaffs_is_non_empty_dir(struct yaffs_obj *obj); | ||||
| #endif | ||||
|   | ||||
| @@ -25,11 +25,11 @@ struct yaffs_linux_context { | ||||
| 	struct task_struct *bg_thread;	/* Background thread for this device */ | ||||
| 	int bg_running; | ||||
| 	struct mutex gross_lock;	/* Gross locking mutex*/ | ||||
| 	u8 *spare_buffer;	/* For mtdif2 use. Don't know the size of the buffer | ||||
| 	u8 *spare_buffer;	/* For mtdif2 use. Don't know the buffer size | ||||
| 				 * at compile time so we have to allocate it. | ||||
| 				 */ | ||||
| 	struct list_head search_contexts; | ||||
| 	void (*put_super_fn) (struct super_block * sb); | ||||
| 	void (*put_super_fn) (struct super_block *sb); | ||||
|  | ||||
| 	struct task_struct *readdir_process; | ||||
| 	unsigned mount_id; | ||||
|   | ||||
| @@ -29,7 +29,6 @@ int nandmtd_erase_block(struct yaffs_dev *dev, int block_no) | ||||
| 	    ((loff_t) block_no) * dev->param.total_bytes_per_chunk | ||||
| 	    * dev->param.chunks_per_block; | ||||
| 	struct erase_info ei; | ||||
|  | ||||
| 	int retval = 0; | ||||
|  | ||||
| 	ei.mtd = mtd; | ||||
|   | ||||
| @@ -64,7 +64,7 @@ static struct nand_ecclayout nand_oob_16 = { | ||||
| 	.eccbytes = 6, | ||||
| 	.eccpos = {8, 9, 10, 13, 14, 15}, | ||||
| 	.oobavail = 9, | ||||
| 	.oobfree = {{0, 4}, {6, 2}, {11, 2}, {4, 1}} | ||||
| 	.oobfree = {{0, 4}, {6, 2}, {11, 2}, {4, 1} } | ||||
| }; | ||||
| #endif | ||||
|  | ||||
| @@ -90,7 +90,7 @@ static struct nand_ecclayout nand_oob_16 = { | ||||
|  * Returns YAFFS_OK or YAFFS_FAIL. | ||||
|  */ | ||||
| int nandmtd1_write_chunk_tags(struct yaffs_dev *dev, | ||||
| 			      int nand_chunk, const u8 * data, | ||||
| 			      int nand_chunk, const u8 *data, | ||||
| 			      const struct yaffs_ext_tags *etags) | ||||
| { | ||||
| 	struct mtd_info *mtd = yaffs_dev_to_mtd(dev); | ||||
| @@ -120,11 +120,11 @@ int nandmtd1_write_chunk_tags(struct yaffs_dev *dev, | ||||
| 		pt1.deleted = 0; | ||||
| 	} | ||||
| #else | ||||
| 	((u8 *) & pt1)[8] = 0xff; | ||||
| 	((u8 *) &pt1)[8] = 0xff; | ||||
| 	if (etags->is_deleted) { | ||||
| 		memset(&pt1, 0xff, 8); | ||||
| 		/* zero page_status byte to indicate deleted */ | ||||
| 		((u8 *) & pt1)[8] = 0; | ||||
| 		((u8 *) &pt1)[8] = 0; | ||||
| 	} | ||||
| #endif | ||||
|  | ||||
| @@ -133,13 +133,13 @@ int nandmtd1_write_chunk_tags(struct yaffs_dev *dev, | ||||
| 	ops.len = (data) ? chunk_bytes : 0; | ||||
| 	ops.ooblen = YTAG1_SIZE; | ||||
| 	ops.datbuf = (u8 *) data; | ||||
| 	ops.oobbuf = (u8 *) & pt1; | ||||
| 	ops.oobbuf = (u8 *) &pt1; | ||||
|  | ||||
| 	retval = mtd->write_oob(mtd, addr, &ops); | ||||
| 	if (retval) { | ||||
| 		T(YAFFS_TRACE_MTD, | ||||
| 		  (TSTR("write_oob failed, chunk %d, mtd error %d" TENDSTR), | ||||
| 		   nand_chunk, retval)); | ||||
| 		yaffs_trace(YAFFS_TRACE_MTD, | ||||
| 			"write_oob failed, chunk %d, mtd error %d", | ||||
| 			nand_chunk, retval); | ||||
| 	} | ||||
| 	return retval ? YAFFS_FAIL : YAFFS_OK; | ||||
| } | ||||
| @@ -169,7 +169,7 @@ static int rettags(struct yaffs_ext_tags *etags, int ecc_result, int retval) | ||||
|  * Returns YAFFS_OK or YAFFS_FAIL. | ||||
|  */ | ||||
| int nandmtd1_read_chunk_tags(struct yaffs_dev *dev, | ||||
| 			     int nand_chunk, u8 * data, | ||||
| 			     int nand_chunk, u8 *data, | ||||
| 			     struct yaffs_ext_tags *etags) | ||||
| { | ||||
| 	struct mtd_info *mtd = yaffs_dev_to_mtd(dev); | ||||
| @@ -186,7 +186,7 @@ int nandmtd1_read_chunk_tags(struct yaffs_dev *dev, | ||||
| 	ops.len = (data) ? chunk_bytes : 0; | ||||
| 	ops.ooblen = YTAG1_SIZE; | ||||
| 	ops.datbuf = data; | ||||
| 	ops.oobbuf = (u8 *) & pt1; | ||||
| 	ops.oobbuf = (u8 *) &pt1; | ||||
|  | ||||
| #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; | ||||
| @@ -198,11 +198,10 @@ int nandmtd1_read_chunk_tags(struct yaffs_dev *dev, | ||||
| 	 * Check status and determine ECC result. | ||||
| 	 */ | ||||
| 	retval = mtd->read_oob(mtd, addr, &ops); | ||||
| 	if (retval) { | ||||
| 		T(YAFFS_TRACE_MTD, | ||||
| 		  (TSTR("read_oob failed, chunk %d, mtd error %d" TENDSTR), | ||||
| 		   nand_chunk, retval)); | ||||
| 	} | ||||
| 	if (retval) | ||||
| 		yaffs_trace(YAFFS_TRACE_MTD, | ||||
| 			"read_oob failed, chunk %d, mtd error %d", | ||||
| 			nand_chunk, retval); | ||||
|  | ||||
| 	switch (retval) { | ||||
| 	case 0: | ||||
| @@ -227,7 +226,7 @@ int nandmtd1_read_chunk_tags(struct yaffs_dev *dev, | ||||
|  | ||||
| 	/* Check for a blank/erased chunk. | ||||
| 	 */ | ||||
| 	if (yaffs_check_ff((u8 *) & pt1, 8)) { | ||||
| 	if (yaffs_check_ff((u8 *) &pt1, 8)) { | ||||
| 		/* when blank, upper layers want ecc_result to be <= NO_ERROR */ | ||||
| 		return rettags(etags, YAFFS_ECC_RESULT_NO_ERROR, YAFFS_OK); | ||||
| 	} | ||||
| @@ -239,7 +238,7 @@ int nandmtd1_read_chunk_tags(struct yaffs_dev *dev, | ||||
| 	deleted = !pt1.deleted; | ||||
| 	pt1.deleted = 1; | ||||
| #else | ||||
| 	deleted = (yaffs_count_bits(((u8 *) & pt1)[8]) < 7); | ||||
| 	deleted = (hweight8(((u8 *) &pt1)[8]) < 7); | ||||
| #endif | ||||
|  | ||||
| 	/* Check the packed tags mini-ECC and correct if necessary/possible. | ||||
| @@ -286,8 +285,7 @@ int nandmtd1_mark_block_bad(struct yaffs_dev *dev, int block_no) | ||||
| 	int blocksize = dev->param.chunks_per_block * dev->data_bytes_per_chunk; | ||||
| 	int retval; | ||||
|  | ||||
| 	T(YAFFS_TRACE_BAD_BLOCKS, | ||||
| 	  (TSTR("marking block %d bad" TENDSTR), block_no)); | ||||
| 	yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, "marking block %d bad", block_no); | ||||
|  | ||||
| 	retval = mtd->block_markbad(mtd, (loff_t) blocksize * block_no); | ||||
| 	return (retval) ? YAFFS_FAIL : YAFFS_OK; | ||||
| @@ -304,10 +302,9 @@ static int nandmtd1_test_prerequists(struct mtd_info *mtd) | ||||
| 	int oobavail = mtd->ecclayout->oobavail; | ||||
|  | ||||
| 	if (oobavail < YTAG1_SIZE) { | ||||
| 		T(YAFFS_TRACE_ERROR, | ||||
| 		  (TSTR | ||||
| 		   ("mtd device has only %d bytes for tags, need %d" TENDSTR), | ||||
| 		   oobavail, YTAG1_SIZE)); | ||||
| 		yaffs_trace(YAFFS_TRACE_ERROR, | ||||
| 			"mtd device has only %d bytes for tags, need %d", | ||||
| 			oobavail, YTAG1_SIZE); | ||||
| 		return YAFFS_FAIL; | ||||
| 	} | ||||
| 	return YAFFS_OK; | ||||
| @@ -342,8 +339,9 @@ int nandmtd1_query_block(struct yaffs_dev *dev, int block_no, | ||||
| 	retval = nandmtd1_read_chunk_tags(dev, chunk_num, NULL, &etags); | ||||
| 	etags.block_bad = (mtd->block_isbad) (mtd, addr); | ||||
| 	if (etags.block_bad) { | ||||
| 		T(YAFFS_TRACE_BAD_BLOCKS, | ||||
| 		  (TSTR("block %d is marked bad" TENDSTR), block_no)); | ||||
| 		yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, | ||||
| 			"block %d is marked bad", | ||||
| 			block_no); | ||||
| 		state = YAFFS_BLOCK_STATE_DEAD; | ||||
| 	} else if (etags.ecc_result != YAFFS_ECC_RESULT_NO_ERROR) { | ||||
| 		/* bad tags, need to look more closely */ | ||||
|   | ||||
| @@ -15,15 +15,15 @@ | ||||
| #define __YAFFS_MTDIF1_H__ | ||||
|  | ||||
| int nandmtd1_write_chunk_tags(struct yaffs_dev *dev, int nand_chunk, | ||||
| 			      const u8 * data, | ||||
| 			      const u8 *data, | ||||
| 			      const struct yaffs_ext_tags *tags); | ||||
|  | ||||
| int nandmtd1_read_chunk_tags(struct yaffs_dev *dev, int nand_chunk, | ||||
| 			     u8 * data, struct yaffs_ext_tags *tags); | ||||
| 			     u8 *data, struct yaffs_ext_tags *tags); | ||||
|  | ||||
| int nandmtd1_mark_block_bad(struct yaffs_dev *dev, int block_no); | ||||
|  | ||||
| int nandmtd1_query_block(struct yaffs_dev *dev, int block_no, | ||||
| 			 enum yaffs_block_state *state, u32 * seq_number); | ||||
| 			 enum yaffs_block_state *state, u32 *seq_number); | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -27,11 +27,11 @@ | ||||
| #include "yaffs_linux.h" | ||||
|  | ||||
| /* NB For use with inband tags.... | ||||
|  * We assume that the data buffer is of size total_bytes_per_chunk so that we can also | ||||
|  * use it to load the tags. | ||||
|  * We assume that the data buffer is of size total_bytes_per_chunk so | ||||
|  * that we can also use it to load the tags. | ||||
|  */ | ||||
| int nandmtd2_write_chunk_tags(struct yaffs_dev *dev, int nand_chunk, | ||||
| 			      const u8 * data, | ||||
| 			      const u8 *data, | ||||
| 			      const struct yaffs_ext_tags *tags) | ||||
| { | ||||
| 	struct mtd_info *mtd = yaffs_dev_to_mtd(dev); | ||||
| @@ -51,10 +51,9 @@ int nandmtd2_write_chunk_tags(struct yaffs_dev *dev, int nand_chunk, | ||||
| 	void *packed_tags_ptr = | ||||
| 	    dev->param.no_tags_ecc ? (void *)&pt.t : (void *)&pt; | ||||
|  | ||||
| 	T(YAFFS_TRACE_MTD, | ||||
| 	  (TSTR | ||||
| 	   ("nandmtd2_write_chunk_tags chunk %d data %p tags %p" | ||||
| 	    TENDSTR), nand_chunk, data, tags)); | ||||
| 	yaffs_trace(YAFFS_TRACE_MTD, | ||||
| 		"nandmtd2_write_chunk_tags chunk %d data %p tags %p", | ||||
| 		nand_chunk, data, tags); | ||||
|  | ||||
| 	addr = ((loff_t) nand_chunk) * dev->param.total_bytes_per_chunk; | ||||
|  | ||||
| @@ -68,11 +67,12 @@ int nandmtd2_write_chunk_tags(struct yaffs_dev *dev, int nand_chunk, | ||||
| 		struct yaffs_packed_tags2_tags_only *pt2tp; | ||||
| 		pt2tp = | ||||
| 		    (struct yaffs_packed_tags2_tags_only *)(data + | ||||
| 							    dev-> | ||||
| 							    data_bytes_per_chunk); | ||||
| 							dev-> | ||||
| 							data_bytes_per_chunk); | ||||
| 		yaffs_pack_tags2_tags_only(pt2tp, tags); | ||||
| 	} else | ||||
| 	} else { | ||||
| 		yaffs_pack_tags2(&pt, tags, !dev->param.no_tags_ecc); | ||||
| 	} | ||||
|  | ||||
| #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) | ||||
| 	ops.mode = MTD_OOB_AUTO; | ||||
| @@ -102,7 +102,7 @@ int nandmtd2_write_chunk_tags(struct yaffs_dev *dev, int nand_chunk, | ||||
| } | ||||
|  | ||||
| int nandmtd2_read_chunk_tags(struct yaffs_dev *dev, int nand_chunk, | ||||
| 			     u8 * data, struct yaffs_ext_tags *tags) | ||||
| 			     u8 *data, struct yaffs_ext_tags *tags) | ||||
| { | ||||
| 	struct mtd_info *mtd = yaffs_dev_to_mtd(dev); | ||||
| #if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17)) | ||||
| @@ -121,10 +121,9 @@ int nandmtd2_read_chunk_tags(struct yaffs_dev *dev, int nand_chunk, | ||||
| 	void *packed_tags_ptr = | ||||
| 	    dev->param.no_tags_ecc ? (void *)&pt.t : (void *)&pt; | ||||
|  | ||||
| 	T(YAFFS_TRACE_MTD, | ||||
| 	  (TSTR | ||||
| 	   ("nandmtd2_read_chunk_tags chunk %d data %p tags %p" | ||||
| 	    TENDSTR), nand_chunk, data, tags)); | ||||
| 	yaffs_trace(YAFFS_TRACE_MTD, | ||||
| 		"nandmtd2_read_chunk_tags chunk %d data %p tags %p", | ||||
| 		nand_chunk, data, tags); | ||||
|  | ||||
| 	if (dev->param.inband_tags) { | ||||
|  | ||||
| @@ -169,8 +168,8 @@ int nandmtd2_read_chunk_tags(struct yaffs_dev *dev, int nand_chunk, | ||||
| 		if (tags) { | ||||
| 			struct yaffs_packed_tags2_tags_only *pt2tp; | ||||
| 			pt2tp = | ||||
| 			    (struct yaffs_packed_tags2_tags_only *)&data[dev-> | ||||
| 									 data_bytes_per_chunk]; | ||||
| 				(struct yaffs_packed_tags2_tags_only *) | ||||
| 				&data[dev->data_bytes_per_chunk]; | ||||
| 			yaffs_unpack_tags2_tags_only(tags, pt2tp); | ||||
| 		} | ||||
| 	} else { | ||||
| @@ -205,8 +204,9 @@ int nandmtd2_mark_block_bad(struct yaffs_dev *dev, int block_no) | ||||
| { | ||||
| 	struct mtd_info *mtd = yaffs_dev_to_mtd(dev); | ||||
| 	int retval; | ||||
| 	T(YAFFS_TRACE_MTD, | ||||
| 	  (TSTR("nandmtd2_mark_block_bad %d" TENDSTR), block_no)); | ||||
| 	yaffs_trace(YAFFS_TRACE_MTD, | ||||
| 		"nandmtd2_mark_block_bad %d", | ||||
| 		block_no); | ||||
|  | ||||
| 	retval = | ||||
| 	    mtd->block_markbad(mtd, | ||||
| @@ -221,19 +221,19 @@ int nandmtd2_mark_block_bad(struct yaffs_dev *dev, int block_no) | ||||
| } | ||||
|  | ||||
| int nandmtd2_query_block(struct yaffs_dev *dev, int block_no, | ||||
| 			 enum yaffs_block_state *state, u32 * seq_number) | ||||
| 			 enum yaffs_block_state *state, u32 *seq_number) | ||||
| { | ||||
| 	struct mtd_info *mtd = yaffs_dev_to_mtd(dev); | ||||
| 	int retval; | ||||
|  | ||||
| 	T(YAFFS_TRACE_MTD, (TSTR("nandmtd2_query_block %d" TENDSTR), block_no)); | ||||
| 	yaffs_trace(YAFFS_TRACE_MTD, "nandmtd2_query_block %d", block_no); | ||||
| 	retval = | ||||
| 	    mtd->block_isbad(mtd, | ||||
| 			     block_no * dev->param.chunks_per_block * | ||||
| 			     dev->param.total_bytes_per_chunk); | ||||
|  | ||||
| 	if (retval) { | ||||
| 		T(YAFFS_TRACE_MTD, (TSTR("block is bad" TENDSTR))); | ||||
| 		yaffs_trace(YAFFS_TRACE_MTD, "block is bad"); | ||||
|  | ||||
| 		*state = YAFFS_BLOCK_STATE_DEAD; | ||||
| 		*seq_number = 0; | ||||
| @@ -250,11 +250,13 @@ int nandmtd2_query_block(struct yaffs_dev *dev, int block_no, | ||||
| 			*state = YAFFS_BLOCK_STATE_EMPTY; | ||||
| 		} | ||||
| 	} | ||||
| 	T(YAFFS_TRACE_MTD, | ||||
| 	  (TSTR("block is bad seq %d state %d" TENDSTR), *seq_number, *state)); | ||||
| 	yaffs_trace(YAFFS_TRACE_MTD, | ||||
| 		"block is bad seq %d state %d", | ||||
| 		*seq_number, *state); | ||||
|  | ||||
| 	if (retval == 0) | ||||
| 		return YAFFS_OK; | ||||
| 	else | ||||
| 		return YAFFS_FAIL; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -18,12 +18,12 @@ | ||||
|  | ||||
| #include "yaffs_guts.h" | ||||
| int nandmtd2_write_chunk_tags(struct yaffs_dev *dev, int nand_chunk, | ||||
| 			      const u8 * data, | ||||
| 			      const u8 *data, | ||||
| 			      const struct yaffs_ext_tags *tags); | ||||
| int nandmtd2_read_chunk_tags(struct yaffs_dev *dev, int nand_chunk, | ||||
| 			     u8 * data, struct yaffs_ext_tags *tags); | ||||
| 			     u8 *data, struct yaffs_ext_tags *tags); | ||||
| int nandmtd2_mark_block_bad(struct yaffs_dev *dev, int block_no); | ||||
| int nandmtd2_query_block(struct yaffs_dev *dev, int block_no, | ||||
| 			 enum yaffs_block_state *state, u32 * seq_number); | ||||
| 			 enum yaffs_block_state *state, u32 *seq_number); | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -12,15 +12,15 @@ | ||||
|  */ | ||||
|  | ||||
| /* | ||||
|  * This simple implementation of a name-value store assumes a small number of values and fits | ||||
|  * into a small finite buffer. | ||||
|  * This simple implementation of a name-value store assumes a small number of | ||||
| * values and fits into a small finite buffer. | ||||
|  * | ||||
|  * Each attribute is stored as a record: | ||||
|  *  sizeof(int) bytes   record size. | ||||
|  *  strnlen+1 bytes name null terminated. | ||||
|  *  nbytes    value. | ||||
|  *  ---------- | ||||
|  *  total size  stored in record size  | ||||
|  *  total size  stored in record size | ||||
|  * | ||||
|  * This code has not been tested with unicode yet. | ||||
|  */ | ||||
| @@ -29,7 +29,7 @@ | ||||
|  | ||||
| #include "yportenv.h" | ||||
|  | ||||
| static int nval_find(const char *xb, int xb_size, const YCHAR * name, | ||||
| static int nval_find(const char *xb, int xb_size, const YCHAR *name, | ||||
| 		     int *exist_size) | ||||
| { | ||||
| 	int pos = 0; | ||||
| @@ -37,7 +37,7 @@ static int nval_find(const char *xb, int xb_size, const YCHAR * name, | ||||
|  | ||||
| 	memcpy(&size, xb, sizeof(int)); | ||||
| 	while (size > 0 && (size < xb_size) && (pos + size < xb_size)) { | ||||
| 		if (yaffs_strncmp | ||||
| 		if (strncmp | ||||
| 		    ((YCHAR *) (xb + pos + sizeof(int)), name, size) == 0) { | ||||
| 			if (exist_size) | ||||
| 				*exist_size = size; | ||||
| @@ -70,26 +70,28 @@ static int nval_used(const char *xb, int xb_size) | ||||
| 	return pos; | ||||
| } | ||||
|  | ||||
| int nval_del(char *xb, int xb_size, const YCHAR * name) | ||||
| int nval_del(char *xb, int xb_size, const YCHAR *name) | ||||
| { | ||||
| 	int pos = nval_find(xb, xb_size, name, NULL); | ||||
| 	int size; | ||||
|  | ||||
| 	if (pos >= 0 && pos < xb_size) { | ||||
| 		/* Find size, shift rest over this record, then zero out the rest of buffer */ | ||||
| 		/* Find size, shift rest over this record, | ||||
| 		 * then zero out the rest of buffer */ | ||||
| 		memcpy(&size, xb + pos, sizeof(int)); | ||||
| 		memcpy(xb + pos, xb + pos + size, xb_size - (pos + size)); | ||||
| 		memset(xb + (xb_size - size), 0, size); | ||||
| 		return 0; | ||||
| 	} else | ||||
| 	} else { | ||||
| 		return -ENODATA; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| int nval_set(char *xb, int xb_size, const YCHAR * name, const char *buf, | ||||
| 	     int bsize, int flags) | ||||
| int nval_set(char *xb, int xb_size, const YCHAR *name, const char *buf, | ||||
| 		int bsize, int flags) | ||||
| { | ||||
| 	int pos; | ||||
| 	int namelen = yaffs_strnlen(name, xb_size); | ||||
| 	int namelen = strnlen(name, xb_size); | ||||
| 	int reclen; | ||||
| 	int size_exist = 0; | ||||
| 	int space; | ||||
| @@ -119,7 +121,7 @@ int nval_set(char *xb, int xb_size, const YCHAR * name, const char *buf, | ||||
|  | ||||
| 	memcpy(xb + pos, &reclen, sizeof(int)); | ||||
| 	pos += sizeof(int); | ||||
| 	yaffs_strncpy((YCHAR *) (xb + pos), name, reclen); | ||||
| 	strncpy((YCHAR *) (xb + pos), name, reclen); | ||||
| 	pos += (namelen + 1); | ||||
| 	memcpy(xb + pos, buf, bsize); | ||||
| 	return 0; | ||||
| @@ -167,11 +169,13 @@ int nval_list(const char *xb, int xb_size, char *buf, int bsize) | ||||
| 	int filled = 0; | ||||
|  | ||||
| 	memcpy(&size, xb + pos, sizeof(int)); | ||||
| 	while (size > sizeof(int) && size <= xb_size && (pos + size) < xb_size | ||||
| 	       && !filled) { | ||||
| 	while (size > sizeof(int) && | ||||
| 		size <= xb_size && | ||||
| 		(pos + size) < xb_size && | ||||
| 		!filled) { | ||||
| 		pos += sizeof(int); | ||||
| 		size -= sizeof(int); | ||||
| 		name_len = yaffs_strnlen((YCHAR *) (xb + pos), size); | ||||
| 		name_len = strnlen((YCHAR *) (xb + pos), size); | ||||
| 		if (ncopied + name_len + 1 < bsize) { | ||||
| 			memcpy(buf, xb + pos, name_len * sizeof(YCHAR)); | ||||
| 			buf += name_len; | ||||
| @@ -182,8 +186,9 @@ int nval_list(const char *xb, int xb_size, char *buf, int bsize) | ||||
| 				buf++; | ||||
| 			} | ||||
| 			ncopied += (name_len + 1); | ||||
| 		} else | ||||
| 		} else { | ||||
| 			filled = 1; | ||||
| 		} | ||||
| 		pos += size; | ||||
| 		if (pos < xb_size - sizeof(int)) | ||||
| 			memcpy(&size, xb + pos, sizeof(int)); | ||||
|   | ||||
| @@ -18,16 +18,15 @@ | ||||
| #include "yaffs_getblockinfo.h" | ||||
|  | ||||
| int yaffs_rd_chunk_tags_nand(struct yaffs_dev *dev, int nand_chunk, | ||||
| 			     u8 * buffer, struct yaffs_ext_tags *tags) | ||||
| 			     u8 *buffer, struct yaffs_ext_tags *tags) | ||||
| { | ||||
| 	int result; | ||||
| 	struct yaffs_ext_tags local_tags; | ||||
|  | ||||
| 	int realigned_chunk = nand_chunk - dev->chunk_offset; | ||||
|  | ||||
| 	dev->n_page_reads++; | ||||
|  | ||||
| 	/* If there are no tags provided, use local tags to get prioritised gc working */ | ||||
| 	/* If there are no tags provided use local tags. */ | ||||
| 	if (!tags) | ||||
| 		tags = &local_tags; | ||||
|  | ||||
| @@ -46,38 +45,36 @@ int yaffs_rd_chunk_tags_nand(struct yaffs_dev *dev, int nand_chunk, | ||||
| 					  dev->param.chunks_per_block); | ||||
| 		yaffs_handle_chunk_error(dev, bi); | ||||
| 	} | ||||
|  | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| int yaffs_wr_chunk_tags_nand(struct yaffs_dev *dev, | ||||
| 			     int nand_chunk, | ||||
| 			     const u8 * buffer, struct yaffs_ext_tags *tags) | ||||
| 				int nand_chunk, | ||||
| 				const u8 *buffer, struct yaffs_ext_tags *tags) | ||||
| { | ||||
|  | ||||
| 	dev->n_page_writes++; | ||||
|  | ||||
| 	nand_chunk -= dev->chunk_offset; | ||||
|  | ||||
| 	if (tags) { | ||||
| 		tags->seq_number = dev->seq_number; | ||||
| 		tags->chunk_used = 1; | ||||
| 		if (!yaffs_validate_tags(tags)) { | ||||
| 			T(YAFFS_TRACE_ERROR, | ||||
| 			  (TSTR("Writing uninitialised tags" TENDSTR))); | ||||
| 			yaffs_trace(YAFFS_TRACE_ERROR, | ||||
| 				"Writing uninitialised tags"); | ||||
| 			YBUG(); | ||||
| 		} | ||||
| 		T(YAFFS_TRACE_WRITE, | ||||
| 		  (TSTR("Writing chunk %d tags %d %d" TENDSTR), nand_chunk, | ||||
| 		   tags->obj_id, tags->chunk_id)); | ||||
| 		yaffs_trace(YAFFS_TRACE_WRITE, | ||||
| 			"Writing chunk %d tags %d %d", | ||||
| 			nand_chunk, tags->obj_id, tags->chunk_id); | ||||
| 	} else { | ||||
| 		T(YAFFS_TRACE_ERROR, (TSTR("Writing with no tags" TENDSTR))); | ||||
| 		yaffs_trace(YAFFS_TRACE_ERROR, "Writing with no tags"); | ||||
| 		YBUG(); | ||||
| 		return YAFFS_FAIL; | ||||
| 	} | ||||
|  | ||||
| 	if (dev->param.write_chunk_tags_fn) | ||||
| 		return dev->param.write_chunk_tags_fn(dev, nand_chunk, buffer, | ||||
| 						      tags); | ||||
| 							tags); | ||||
| 	else | ||||
| 		return yaffs_tags_compat_wr(dev, nand_chunk, buffer, tags); | ||||
| } | ||||
| @@ -85,7 +82,6 @@ int yaffs_wr_chunk_tags_nand(struct yaffs_dev *dev, | ||||
| int yaffs_mark_bad(struct yaffs_dev *dev, int block_no) | ||||
| { | ||||
| 	block_no -= dev->block_offset; | ||||
|  | ||||
| 	if (dev->param.bad_block_fn) | ||||
| 		return dev->param.bad_block_fn(dev, block_no); | ||||
| 	else | ||||
| @@ -95,10 +91,9 @@ int yaffs_mark_bad(struct yaffs_dev *dev, int block_no) | ||||
| int yaffs_query_init_block_state(struct yaffs_dev *dev, | ||||
| 				 int block_no, | ||||
| 				 enum yaffs_block_state *state, | ||||
| 				 u32 * seq_number) | ||||
| 				 u32 *seq_number) | ||||
| { | ||||
| 	block_no -= dev->block_offset; | ||||
|  | ||||
| 	if (dev->param.query_block_fn) | ||||
| 		return dev->param.query_block_fn(dev, block_no, state, | ||||
| 						 seq_number); | ||||
| @@ -112,11 +107,8 @@ int yaffs_erase_block(struct yaffs_dev *dev, int flash_block) | ||||
| 	int result; | ||||
|  | ||||
| 	flash_block -= dev->block_offset; | ||||
|  | ||||
| 	dev->n_erasures++; | ||||
|  | ||||
| 	result = dev->param.erase_fn(dev, flash_block); | ||||
|  | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -18,11 +18,11 @@ | ||||
| #include "yaffs_guts.h" | ||||
|  | ||||
| int yaffs_rd_chunk_tags_nand(struct yaffs_dev *dev, int nand_chunk, | ||||
| 			     u8 * buffer, struct yaffs_ext_tags *tags); | ||||
| 			     u8 *buffer, struct yaffs_ext_tags *tags); | ||||
|  | ||||
| int yaffs_wr_chunk_tags_nand(struct yaffs_dev *dev, | ||||
| 			     int nand_chunk, | ||||
| 			     const u8 * buffer, struct yaffs_ext_tags *tags); | ||||
| 			     const u8 *buffer, struct yaffs_ext_tags *tags); | ||||
|  | ||||
| int yaffs_mark_bad(struct yaffs_dev *dev, int block_no); | ||||
|  | ||||
|   | ||||
| @@ -25,15 +25,15 @@ void yaffs_pack_tags1(struct yaffs_packed_tags1 *pt, | ||||
| 	pt->deleted = (t->is_deleted) ? 0 : 1; | ||||
| 	pt->unused_stuff = 0; | ||||
| 	pt->should_be_ff = 0xFFFFFFFF; | ||||
|  | ||||
| } | ||||
|  | ||||
| void yaffs_unpack_tags1(struct yaffs_ext_tags *t, | ||||
| 			const struct yaffs_packed_tags1 *pt) | ||||
| { | ||||
| 	static const u8 all_ff[] = | ||||
| 	    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||||
| 		0xff | ||||
| 	static const u8 all_ff[12] = { | ||||
| 		0xff, 0xff, 0xff, 0xff, | ||||
| 		0xff, 0xff, 0xff, 0xff, | ||||
| 		0xff, 0xff, 0xff, 0xff | ||||
| 	}; | ||||
|  | ||||
| 	if (memcmp(all_ff, pt, sizeof(struct yaffs_packed_tags1))) { | ||||
|   | ||||
| @@ -38,12 +38,12 @@ | ||||
| #define EXTRA_OBJECT_TYPE_SHIFT (28) | ||||
| #define EXTRA_OBJECT_TYPE_MASK  ((0x0F) << EXTRA_OBJECT_TYPE_SHIFT) | ||||
|  | ||||
| static void yaffs_dump_packed_tags2_tags_only(const struct | ||||
| 					      yaffs_packed_tags2_tags_only *ptt) | ||||
| static void yaffs_dump_packed_tags2_tags_only( | ||||
| 				const struct yaffs_packed_tags2_tags_only *ptt) | ||||
| { | ||||
| 	T(YAFFS_TRACE_MTD, | ||||
| 	  (TSTR("packed tags obj %d chunk %d byte %d seq %d" TENDSTR), | ||||
| 	   ptt->obj_id, ptt->chunk_id, ptt->n_bytes, ptt->seq_number)); | ||||
| 	yaffs_trace(YAFFS_TRACE_MTD, | ||||
| 		"packed tags obj %d chunk %d byte %d seq %d", | ||||
| 		ptt->obj_id, ptt->chunk_id, ptt->n_bytes, ptt->seq_number); | ||||
| } | ||||
|  | ||||
| static void yaffs_dump_packed_tags2(const struct yaffs_packed_tags2 *pt) | ||||
| @@ -53,12 +53,11 @@ static void yaffs_dump_packed_tags2(const struct yaffs_packed_tags2 *pt) | ||||
|  | ||||
| static void yaffs_dump_tags2(const struct yaffs_ext_tags *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" | ||||
| 	    TENDSTR), t->ecc_result, t->block_bad, t->chunk_used, t->obj_id, | ||||
| 	   t->chunk_id, t->n_bytes, t->is_deleted, t->serial_number, | ||||
| 	   t->seq_number)); | ||||
| 	yaffs_trace(YAFFS_TRACE_MTD, | ||||
| 		"ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte %d del %d ser %d seq %d", | ||||
| 		t->ecc_result, t->block_bad, t->chunk_used, t->obj_id, | ||||
| 		t->chunk_id, t->n_bytes, t->is_deleted, t->serial_number, | ||||
| 		t->seq_number); | ||||
|  | ||||
| } | ||||
|  | ||||
| @@ -109,9 +108,7 @@ void yaffs_pack_tags2(struct yaffs_packed_tags2 *pt, | ||||
| void yaffs_unpack_tags2_tags_only(struct yaffs_ext_tags *t, | ||||
| 				  struct yaffs_packed_tags2_tags_only *ptt) | ||||
| { | ||||
|  | ||||
| 	memset(t, 0, sizeof(struct yaffs_ext_tags)); | ||||
|  | ||||
| 	yaffs_init_tags(t); | ||||
|  | ||||
| 	if (ptt->seq_number != 0xFFFFFFFF) { | ||||
| @@ -125,7 +122,6 @@ void yaffs_unpack_tags2_tags_only(struct yaffs_ext_tags *t, | ||||
| 		t->seq_number = ptt->seq_number; | ||||
|  | ||||
| 		/* Do extra header info stuff */ | ||||
|  | ||||
| 		if (ptt->chunk_id & EXTRA_HEADER_INFO_FLAG) { | ||||
| 			t->chunk_id = 0; | ||||
| 			t->n_bytes = 0; | ||||
| @@ -147,16 +143,13 @@ void yaffs_unpack_tags2_tags_only(struct yaffs_ext_tags *t, | ||||
| 				t->extra_length = ptt->n_bytes; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	yaffs_dump_packed_tags2_tags_only(ptt); | ||||
| 	yaffs_dump_tags2(t); | ||||
|  | ||||
| } | ||||
|  | ||||
| void yaffs_unpack_tags2(struct yaffs_ext_tags *t, struct yaffs_packed_tags2 *pt, | ||||
| 			int tags_ecc) | ||||
| { | ||||
|  | ||||
| 	enum yaffs_ecc_result ecc_result = YAFFS_ECC_RESULT_NO_ERROR; | ||||
|  | ||||
| 	if (pt->t.seq_number != 0xFFFFFFFF && tags_ecc) { | ||||
| @@ -165,14 +158,12 @@ void yaffs_unpack_tags2(struct yaffs_ext_tags *t, struct yaffs_packed_tags2 *pt, | ||||
| 		struct yaffs_ecc_other ecc; | ||||
| 		int result; | ||||
| 		yaffs_ecc_calc_other((unsigned char *)&pt->t, | ||||
| 				     sizeof(struct | ||||
| 					    yaffs_packed_tags2_tags_only), | ||||
| 				     &ecc); | ||||
| 				sizeof(struct yaffs_packed_tags2_tags_only), | ||||
| 				&ecc); | ||||
| 		result = | ||||
| 		    yaffs_ecc_correct_other((unsigned char *)&pt->t, | ||||
| 					    sizeof(struct | ||||
| 						   yaffs_packed_tags2_tags_only), | ||||
| 					    &pt->ecc, &ecc); | ||||
| 				sizeof(struct yaffs_packed_tags2_tags_only), | ||||
| 				&pt->ecc, &ecc); | ||||
| 		switch (result) { | ||||
| 		case 0: | ||||
| 			ecc_result = YAFFS_ECC_RESULT_NO_ERROR; | ||||
| @@ -187,7 +178,6 @@ void yaffs_unpack_tags2(struct yaffs_ext_tags *t, struct yaffs_packed_tags2 *pt, | ||||
| 			ecc_result = YAFFS_ECC_RESULT_UNKNOWN; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	yaffs_unpack_tags2_tags_only(t, &pt->t); | ||||
|  | ||||
| 	t->ecc_result = ecc_result; | ||||
|   | ||||
| @@ -19,35 +19,10 @@ | ||||
|  | ||||
| static void yaffs_handle_rd_data_error(struct yaffs_dev *dev, int nand_chunk); | ||||
|  | ||||
| static const char yaffs_count_bits_table[256] = { | ||||
| 	0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, | ||||
| 	1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, | ||||
| 	1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, | ||||
| 	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, | ||||
| 	1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, | ||||
| 	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, | ||||
| 	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, | ||||
| 	3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, | ||||
| 	1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, | ||||
| 	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, | ||||
| 	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, | ||||
| 	3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, | ||||
| 	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, | ||||
| 	3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, | ||||
| 	3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, | ||||
| 	4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 | ||||
| }; | ||||
|  | ||||
| int yaffs_count_bits(u8 x) | ||||
| { | ||||
| 	int ret_val; | ||||
| 	ret_val = yaffs_count_bits_table[x]; | ||||
| 	return ret_val; | ||||
| } | ||||
|  | ||||
| /********** Tags ECC calculations  *********/ | ||||
|  | ||||
| void yaffs_calc_ecc(const u8 * data, struct yaffs_spare *spare) | ||||
| void yaffs_calc_ecc(const u8 *data, struct yaffs_spare *spare) | ||||
| { | ||||
| 	yaffs_ecc_cacl(data, spare->ecc1); | ||||
| 	yaffs_ecc_cacl(&data[256], spare->ecc2); | ||||
| @@ -56,7 +31,6 @@ void yaffs_calc_ecc(const u8 * data, struct yaffs_spare *spare) | ||||
| void yaffs_calc_tags_ecc(struct yaffs_tags *tags) | ||||
| { | ||||
| 	/* Calculate an ecc */ | ||||
|  | ||||
| 	unsigned char *b = ((union yaffs_tags_union *)tags)->as_bytes; | ||||
| 	unsigned i, j; | ||||
| 	unsigned ecc = 0; | ||||
| @@ -71,9 +45,7 @@ void yaffs_calc_tags_ecc(struct yaffs_tags *tags) | ||||
| 				ecc ^= bit; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	tags->ecc = ecc; | ||||
|  | ||||
| } | ||||
|  | ||||
| int yaffs_check_tags_ecc(struct yaffs_tags *tags) | ||||
| @@ -101,7 +73,6 @@ int yaffs_check_tags_ecc(struct yaffs_tags *tags) | ||||
| 		/* TODO Need to do somethiong here */ | ||||
| 		return -1;	/* unrecovered error */ | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @@ -153,13 +124,13 @@ static void yaffs_spare_init(struct yaffs_spare *spare) | ||||
| } | ||||
|  | ||||
| static int yaffs_wr_nand(struct yaffs_dev *dev, | ||||
| 			 int nand_chunk, const u8 * data, | ||||
| 			 int nand_chunk, const u8 *data, | ||||
| 			 struct yaffs_spare *spare) | ||||
| { | ||||
| 	if (nand_chunk < dev->param.start_block * dev->param.chunks_per_block) { | ||||
| 		T(YAFFS_TRACE_ERROR, | ||||
| 		  (TSTR("**>> yaffs chunk %d is not valid" TENDSTR), | ||||
| 		   nand_chunk)); | ||||
| 		yaffs_trace(YAFFS_TRACE_ERROR, | ||||
| 			"**>> yaffs chunk %d is not valid", | ||||
| 			nand_chunk); | ||||
| 		return YAFFS_FAIL; | ||||
| 	} | ||||
|  | ||||
| @@ -168,7 +139,7 @@ static int yaffs_wr_nand(struct yaffs_dev *dev, | ||||
|  | ||||
| static int yaffs_rd_chunk_nand(struct yaffs_dev *dev, | ||||
| 			       int nand_chunk, | ||||
| 			       u8 * data, | ||||
| 			       u8 *data, | ||||
| 			       struct yaffs_spare *spare, | ||||
| 			       enum yaffs_ecc_result *ecc_result, | ||||
| 			       int correct_errors) | ||||
| @@ -176,7 +147,7 @@ static int yaffs_rd_chunk_nand(struct yaffs_dev *dev, | ||||
| 	int ret_val; | ||||
| 	struct yaffs_spare local_spare; | ||||
|  | ||||
| 	if (!spare && data) { | ||||
| 	if (!spare) { | ||||
| 		/* If we don't have a real spare, then we use a local one. */ | ||||
| 		/* Need this for the calculation of the ecc */ | ||||
| 		spare = &local_spare; | ||||
| @@ -200,30 +171,26 @@ static int yaffs_rd_chunk_nand(struct yaffs_dev *dev, | ||||
| 					      calc_ecc); | ||||
|  | ||||
| 			if (ecc_result1 > 0) { | ||||
| 				T(YAFFS_TRACE_ERROR, | ||||
| 				  (TSTR | ||||
| 				   ("**>>yaffs ecc error fix performed on chunk %d:0" | ||||
| 				    TENDSTR), nand_chunk)); | ||||
| 				yaffs_trace(YAFFS_TRACE_ERROR, | ||||
| 					"**>>yaffs ecc error fix performed on chunk %d:0", | ||||
| 					nand_chunk); | ||||
| 				dev->n_ecc_fixed++; | ||||
| 			} else if (ecc_result1 < 0) { | ||||
| 				T(YAFFS_TRACE_ERROR, | ||||
| 				  (TSTR | ||||
| 				   ("**>>yaffs ecc error unfixed on chunk %d:0" | ||||
| 				    TENDSTR), nand_chunk)); | ||||
| 				yaffs_trace(YAFFS_TRACE_ERROR, | ||||
| 					"**>>yaffs ecc error unfixed on chunk %d:0", | ||||
| 					nand_chunk); | ||||
| 				dev->n_ecc_unfixed++; | ||||
| 			} | ||||
|  | ||||
| 			if (ecc_result2 > 0) { | ||||
| 				T(YAFFS_TRACE_ERROR, | ||||
| 				  (TSTR | ||||
| 				   ("**>>yaffs ecc error fix performed on chunk %d:1" | ||||
| 				    TENDSTR), nand_chunk)); | ||||
| 				yaffs_trace(YAFFS_TRACE_ERROR, | ||||
| 					"**>>yaffs ecc error fix performed on chunk %d:1", | ||||
| 					nand_chunk); | ||||
| 				dev->n_ecc_fixed++; | ||||
| 			} else if (ecc_result2 < 0) { | ||||
| 				T(YAFFS_TRACE_ERROR, | ||||
| 				  (TSTR | ||||
| 				   ("**>>yaffs ecc error unfixed on chunk %d:1" | ||||
| 				    TENDSTR), nand_chunk)); | ||||
| 				yaffs_trace(YAFFS_TRACE_ERROR, | ||||
| 					"**>>yaffs ecc error unfixed on chunk %d:1", | ||||
| 					nand_chunk); | ||||
| 				dev->n_ecc_unfixed++; | ||||
| 			} | ||||
|  | ||||
| @@ -252,27 +219,23 @@ static int yaffs_rd_chunk_nand(struct yaffs_dev *dev, | ||||
| 		memcpy(spare, &nspare, sizeof(struct yaffs_spare)); | ||||
| 		if (data && correct_errors) { | ||||
| 			if (nspare.eccres1 > 0) { | ||||
| 				T(YAFFS_TRACE_ERROR, | ||||
| 				  (TSTR | ||||
| 				   ("**>>mtd ecc error fix performed on chunk %d:0" | ||||
| 				    TENDSTR), nand_chunk)); | ||||
| 				yaffs_trace(YAFFS_TRACE_ERROR, | ||||
| 					"**>>mtd ecc error fix performed on chunk %d:0", | ||||
| 					nand_chunk); | ||||
| 			} else if (nspare.eccres1 < 0) { | ||||
| 				T(YAFFS_TRACE_ERROR, | ||||
| 				  (TSTR | ||||
| 				   ("**>>mtd ecc error unfixed on chunk %d:0" | ||||
| 				    TENDSTR), nand_chunk)); | ||||
| 				yaffs_trace(YAFFS_TRACE_ERROR, | ||||
| 					"**>>mtd ecc error unfixed on chunk %d:0", | ||||
| 					nand_chunk); | ||||
| 			} | ||||
|  | ||||
| 			if (nspare.eccres2 > 0) { | ||||
| 				T(YAFFS_TRACE_ERROR, | ||||
| 				  (TSTR | ||||
| 				   ("**>>mtd ecc error fix performed on chunk %d:1" | ||||
| 				    TENDSTR), nand_chunk)); | ||||
| 				yaffs_trace(YAFFS_TRACE_ERROR, | ||||
| 					"**>>mtd ecc error fix performed on chunk %d:1", | ||||
| 					nand_chunk); | ||||
| 			} else if (nspare.eccres2 < 0) { | ||||
| 				T(YAFFS_TRACE_ERROR, | ||||
| 				  (TSTR | ||||
| 				   ("**>>mtd ecc error unfixed on chunk %d:1" | ||||
| 				    TENDSTR), nand_chunk)); | ||||
| 				yaffs_trace(YAFFS_TRACE_ERROR, | ||||
| 					"**>>mtd ecc error unfixed on chunk %d:1", | ||||
| 					nand_chunk); | ||||
| 			} | ||||
|  | ||||
| 			if (nspare.eccres1 || nspare.eccres2) { | ||||
| @@ -301,11 +264,11 @@ static void yaffs_handle_rd_data_error(struct yaffs_dev *dev, int nand_chunk) | ||||
| 	int flash_block = nand_chunk / dev->param.chunks_per_block; | ||||
|  | ||||
| 	/* Mark the block for retirement */ | ||||
| 	yaffs_get_block_info(dev, | ||||
| 			     flash_block + dev->block_offset)->needs_retiring = | ||||
| 	    1; | ||||
| 	T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS, | ||||
| 	  (TSTR("**>>Block %d marked for retirement" TENDSTR), flash_block)); | ||||
| 	yaffs_get_block_info(dev, flash_block + dev->block_offset)-> | ||||
| 		needs_retiring = 1; | ||||
| 	yaffs_trace(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS, | ||||
| 		"**>>Block %d marked for retirement", | ||||
| 		flash_block); | ||||
|  | ||||
| 	/* TODO: | ||||
| 	 * Just do a garbage collection on the affected block | ||||
| @@ -316,7 +279,7 @@ static void yaffs_handle_rd_data_error(struct yaffs_dev *dev, int nand_chunk) | ||||
|  | ||||
| int yaffs_tags_compat_wr(struct yaffs_dev *dev, | ||||
| 			 int nand_chunk, | ||||
| 			 const u8 * data, const struct yaffs_ext_tags *ext_tags) | ||||
| 			 const u8 *data, const struct yaffs_ext_tags *ext_tags) | ||||
| { | ||||
| 	struct yaffs_spare spare; | ||||
| 	struct yaffs_tags tags; | ||||
| @@ -350,13 +313,11 @@ int yaffs_tags_compat_wr(struct yaffs_dev *dev, | ||||
|  | ||||
| int yaffs_tags_compat_rd(struct yaffs_dev *dev, | ||||
| 			 int nand_chunk, | ||||
| 			 u8 * data, struct yaffs_ext_tags *ext_tags) | ||||
| 			 u8 *data, struct yaffs_ext_tags *ext_tags) | ||||
| { | ||||
|  | ||||
| 	struct yaffs_spare spare; | ||||
| 	struct yaffs_tags tags; | ||||
| 	enum yaffs_ecc_result ecc_result = YAFFS_ECC_RESULT_UNKNOWN; | ||||
|  | ||||
| 	static struct yaffs_spare spare_ff; | ||||
| 	static int init; | ||||
|  | ||||
| @@ -365,12 +326,13 @@ int yaffs_tags_compat_rd(struct yaffs_dev *dev, | ||||
| 		init = 1; | ||||
| 	} | ||||
|  | ||||
| 	if (yaffs_rd_chunk_nand(dev, nand_chunk, data, &spare, &ecc_result, 1)) { | ||||
| 	if (yaffs_rd_chunk_nand(dev, nand_chunk, | ||||
| 					data, &spare, &ecc_result, 1)) { | ||||
| 		/* ext_tags may be NULL */ | ||||
| 		if (ext_tags) { | ||||
|  | ||||
| 			int deleted = | ||||
| 			    (yaffs_count_bits(spare.page_status) < 7) ? 1 : 0; | ||||
| 			    (hweight8(spare.page_status) < 7) ? 1 : 0; | ||||
|  | ||||
| 			ext_tags->is_deleted = deleted; | ||||
| 			ext_tags->ecc_result = ecc_result; | ||||
| @@ -404,7 +366,6 @@ int yaffs_tags_compat_rd(struct yaffs_dev *dev, | ||||
|  | ||||
| int yaffs_tags_compat_mark_bad(struct yaffs_dev *dev, int flash_block) | ||||
| { | ||||
|  | ||||
| 	struct yaffs_spare spare; | ||||
|  | ||||
| 	memset(&spare, 0xff, sizeof(struct yaffs_spare)); | ||||
| @@ -417,15 +378,13 @@ int yaffs_tags_compat_mark_bad(struct yaffs_dev *dev, int flash_block) | ||||
| 		      NULL, &spare); | ||||
|  | ||||
| 	return YAFFS_OK; | ||||
|  | ||||
| } | ||||
|  | ||||
| int yaffs_tags_compat_query_block(struct yaffs_dev *dev, | ||||
| 				  int block_no, | ||||
| 				  enum yaffs_block_state *state, | ||||
| 				  u32 * seq_number) | ||||
| 				  u32 *seq_number) | ||||
| { | ||||
|  | ||||
| 	struct yaffs_spare spare0, spare1; | ||||
| 	static struct yaffs_spare spare_ff; | ||||
| 	static int init; | ||||
| @@ -443,7 +402,7 @@ int yaffs_tags_compat_query_block(struct yaffs_dev *dev, | ||||
| 	yaffs_rd_chunk_nand(dev, block_no * dev->param.chunks_per_block + 1, | ||||
| 			    NULL, &spare1, &dummy, 1); | ||||
|  | ||||
| 	if (yaffs_count_bits(spare0.block_status & spare1.block_status) < 7) | ||||
| 	if (hweight8(spare0.block_status & spare1.block_status) < 7) | ||||
| 		*state = YAFFS_BLOCK_STATE_DEAD; | ||||
| 	else if (memcmp(&spare_ff, &spare0, sizeof(spare_ff)) == 0) | ||||
| 		*state = YAFFS_BLOCK_STATE_EMPTY; | ||||
|   | ||||
| @@ -19,15 +19,15 @@ | ||||
| #include "yaffs_guts.h" | ||||
| int yaffs_tags_compat_wr(struct yaffs_dev *dev, | ||||
| 			 int nand_chunk, | ||||
| 			 const u8 * data, const struct yaffs_ext_tags *tags); | ||||
| 			 const u8 *data, const struct yaffs_ext_tags *tags); | ||||
| int yaffs_tags_compat_rd(struct yaffs_dev *dev, | ||||
| 			 int nand_chunk, | ||||
| 			 u8 * data, struct yaffs_ext_tags *tags); | ||||
| 			 u8 *data, struct yaffs_ext_tags *tags); | ||||
| int yaffs_tags_compat_mark_bad(struct yaffs_dev *dev, int block_no); | ||||
| int yaffs_tags_compat_query_block(struct yaffs_dev *dev, | ||||
| 				  int block_no, | ||||
| 				  enum yaffs_block_state *state, | ||||
| 				  u32 * seq_number); | ||||
| 				  u32 *seq_number); | ||||
|  | ||||
| void yaffs_calc_tags_ecc(struct yaffs_tags *tags); | ||||
| int yaffs_check_tags_ecc(struct yaffs_tags *tags); | ||||
|   | ||||
| @@ -23,5 +23,4 @@ void yaffs_init_tags(struct yaffs_ext_tags *tags) | ||||
| int yaffs_validate_tags(struct yaffs_ext_tags *tags) | ||||
| { | ||||
| 	return (tags->validity0 == 0xAAAAAAAA && tags->validity1 == 0x55555555); | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -48,11 +48,10 @@ extern unsigned int yaffs_wr_attempts; | ||||
| #define YAFFS_TRACE_SYNC		0x00100000 | ||||
| #define YAFFS_TRACE_BACKGROUND		0x00200000 | ||||
| #define YAFFS_TRACE_LOCK		0x00400000 | ||||
| #define YAFFS_TRACE_MOUNT		0x00800000 | ||||
|  | ||||
| #define YAFFS_TRACE_ERROR		0x40000000 | ||||
| #define YAFFS_TRACE_BUG			0x80000000 | ||||
| #define YAFFS_TRACE_ALWAYS		0xF0000000 | ||||
|  | ||||
| #define T(mask, p) do { if ((mask) & (yaffs_trace_mask | YAFFS_TRACE_ALWAYS)) TOUT(p); } while (0) | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -36,7 +36,7 @@ static int yaffs_skip_nand_verification(struct yaffs_dev *dev) | ||||
| 	return !(yaffs_trace_mask & (YAFFS_TRACE_VERIFY_NAND)); | ||||
| } | ||||
|  | ||||
| static const char *block_state_name[] = { | ||||
| static const char * const block_state_name[] = { | ||||
| 	"Unknown", | ||||
| 	"Needs scanning", | ||||
| 	"Scanning", | ||||
| @@ -59,17 +59,17 @@ void yaffs_verify_blk(struct yaffs_dev *dev, struct yaffs_block_info *bi, int n) | ||||
|  | ||||
| 	/* Report illegal runtime states */ | ||||
| 	if (bi->block_state >= YAFFS_NUMBER_OF_BLOCK_STATES) | ||||
| 		T(YAFFS_TRACE_VERIFY, | ||||
| 		  (TSTR("Block %d has undefined state %d" TENDSTR), n, | ||||
| 		   bi->block_state)); | ||||
| 		yaffs_trace(YAFFS_TRACE_VERIFY, | ||||
| 			"Block %d has undefined state %d", | ||||
| 			n, bi->block_state); | ||||
|  | ||||
| 	switch (bi->block_state) { | ||||
| 	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, | ||||
| 		   block_state_name[bi->block_state])); | ||||
| 		yaffs_trace(YAFFS_TRACE_VERIFY, | ||||
| 			"Block %d has bad run-state %s", | ||||
| 			n, block_state_name[bi->block_state]); | ||||
| 	} | ||||
|  | ||||
| 	/* Check pages in use and soft deletions are legal */ | ||||
| @@ -81,19 +81,16 @@ void yaffs_verify_blk(struct yaffs_dev *dev, struct yaffs_block_info *bi, int n) | ||||
| 	    || bi->soft_del_pages < 0 | ||||
| 	    || bi->soft_del_pages > dev->param.chunks_per_block | ||||
| 	    || actually_used < 0 || actually_used > dev->param.chunks_per_block) | ||||
| 		T(YAFFS_TRACE_VERIFY, | ||||
| 		  (TSTR | ||||
| 		   ("Block %d has illegal values pages_in_used %d soft_del_pages %d" | ||||
| 		    TENDSTR), n, bi->pages_in_use, bi->soft_del_pages)); | ||||
| 		yaffs_trace(YAFFS_TRACE_VERIFY, | ||||
| 			"Block %d has illegal values pages_in_used %d soft_del_pages %d", | ||||
| 			n, bi->pages_in_use, bi->soft_del_pages); | ||||
|  | ||||
| 	/* Check chunk bitmap legal */ | ||||
| 	in_use = yaffs_count_chunk_bits(dev, n); | ||||
| 	if (in_use != bi->pages_in_use) | ||||
| 		T(YAFFS_TRACE_VERIFY, | ||||
| 		  (TSTR | ||||
| 		   ("Block %d has inconsistent values pages_in_use %d counted chunk bits %d" | ||||
| 		    TENDSTR), n, bi->pages_in_use, in_use)); | ||||
|  | ||||
| 		yaffs_trace(YAFFS_TRACE_VERIFY, | ||||
| 			"Block %d has inconsistent values pages_in_use %d counted chunk bits %d", | ||||
| 			n, bi->pages_in_use, in_use); | ||||
| } | ||||
|  | ||||
| void yaffs_verify_collected_blk(struct yaffs_dev *dev, | ||||
| @@ -105,10 +102,9 @@ void yaffs_verify_collected_blk(struct yaffs_dev *dev, | ||||
|  | ||||
| 	if (bi->block_state != YAFFS_BLOCK_STATE_COLLECTING && | ||||
| 	    bi->block_state != YAFFS_BLOCK_STATE_EMPTY) { | ||||
| 		T(YAFFS_TRACE_ERROR, | ||||
| 		  (TSTR | ||||
| 		   ("Block %d is in state %d after gc, should be erased" | ||||
| 		    TENDSTR), n, bi->block_state)); | ||||
| 		yaffs_trace(YAFFS_TRACE_ERROR, | ||||
| 			"Block %d is in state %d after gc, should be erased", | ||||
| 			n, bi->block_state); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -133,43 +129,41 @@ void yaffs_verify_blocks(struct yaffs_dev *dev) | ||||
| 			illegal_states++; | ||||
| 	} | ||||
|  | ||||
| 	T(YAFFS_TRACE_VERIFY, (TSTR("" TENDSTR))); | ||||
| 	T(YAFFS_TRACE_VERIFY, (TSTR("Block summary" TENDSTR))); | ||||
| 	yaffs_trace(YAFFS_TRACE_VERIFY,	"Block summary"); | ||||
|  | ||||
| 	T(YAFFS_TRACE_VERIFY, | ||||
| 	  (TSTR("%d blocks have illegal states" TENDSTR), illegal_states)); | ||||
| 	yaffs_trace(YAFFS_TRACE_VERIFY, | ||||
| 		"%d blocks have illegal states", | ||||
| 		illegal_states); | ||||
| 	if (state_count[YAFFS_BLOCK_STATE_ALLOCATING] > 1) | ||||
| 		T(YAFFS_TRACE_VERIFY, | ||||
| 		  (TSTR("Too many allocating blocks" TENDSTR))); | ||||
| 		yaffs_trace(YAFFS_TRACE_VERIFY, | ||||
| 			"Too many allocating blocks"); | ||||
|  | ||||
| 	for (i = 0; i < YAFFS_NUMBER_OF_BLOCK_STATES; i++) | ||||
| 		T(YAFFS_TRACE_VERIFY, | ||||
| 		  (TSTR("%s %d blocks" TENDSTR), | ||||
| 		   block_state_name[i], state_count[i])); | ||||
| 		yaffs_trace(YAFFS_TRACE_VERIFY, | ||||
| 			"%s %d blocks", | ||||
| 			block_state_name[i], state_count[i]); | ||||
|  | ||||
| 	if (dev->blocks_in_checkpt != state_count[YAFFS_BLOCK_STATE_CHECKPOINT]) | ||||
| 		T(YAFFS_TRACE_VERIFY, | ||||
| 		  (TSTR("Checkpoint block count wrong dev %d count %d" TENDSTR), | ||||
| 		   dev->blocks_in_checkpt, | ||||
| 		   state_count[YAFFS_BLOCK_STATE_CHECKPOINT])); | ||||
| 		yaffs_trace(YAFFS_TRACE_VERIFY, | ||||
| 			"Checkpoint block count wrong dev %d count %d", | ||||
| 			dev->blocks_in_checkpt, | ||||
| 			state_count[YAFFS_BLOCK_STATE_CHECKPOINT]); | ||||
|  | ||||
| 	if (dev->n_erased_blocks != state_count[YAFFS_BLOCK_STATE_EMPTY]) | ||||
| 		T(YAFFS_TRACE_VERIFY, | ||||
| 		  (TSTR("Erased block count wrong dev %d count %d" TENDSTR), | ||||
| 		   dev->n_erased_blocks, state_count[YAFFS_BLOCK_STATE_EMPTY])); | ||||
| 		yaffs_trace(YAFFS_TRACE_VERIFY, | ||||
| 			"Erased block count wrong dev %d count %d", | ||||
| 			dev->n_erased_blocks, | ||||
| 			state_count[YAFFS_BLOCK_STATE_EMPTY]); | ||||
|  | ||||
| 	if (state_count[YAFFS_BLOCK_STATE_COLLECTING] > 1) | ||||
| 		T(YAFFS_TRACE_VERIFY, | ||||
| 		  (TSTR("Too many collecting blocks %d (max is 1)" TENDSTR), | ||||
| 		   state_count[YAFFS_BLOCK_STATE_COLLECTING])); | ||||
|  | ||||
| 	T(YAFFS_TRACE_VERIFY, (TSTR("" TENDSTR))); | ||||
|  | ||||
| 		yaffs_trace(YAFFS_TRACE_VERIFY, | ||||
| 			"Too many collecting blocks %d (max is 1)", | ||||
| 			state_count[YAFFS_BLOCK_STATE_COLLECTING]); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Verify the object header. oh must be valid, but obj and tags may be NULL in which | ||||
|  * case those tests will not be performed. | ||||
|  * Verify the object header. oh must be valid, but obj and tags may be NULL in | ||||
|  * which case those tests will not be performed. | ||||
|  */ | ||||
| void yaffs_verify_oh(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh, | ||||
| 		     struct yaffs_ext_tags *tags, int parent_check) | ||||
| @@ -178,22 +172,22 @@ void yaffs_verify_oh(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh, | ||||
| 		return; | ||||
|  | ||||
| 	if (!(tags && obj && oh)) { | ||||
| 		T(YAFFS_TRACE_VERIFY, | ||||
| 		  (TSTR("Verifying object header tags %p obj %p oh %p" TENDSTR), | ||||
| 		   tags, obj, oh)); | ||||
| 		yaffs_trace(YAFFS_TRACE_VERIFY, | ||||
| 			"Verifying object header tags %p obj %p oh %p", | ||||
| 			tags, obj, 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->obj_id, oh->type)); | ||||
| 		yaffs_trace(YAFFS_TRACE_VERIFY, | ||||
| 			"Obj %d header type is illegal value 0x%x", | ||||
| 			tags->obj_id, oh->type); | ||||
|  | ||||
| 	if (tags->obj_id != obj->obj_id) | ||||
| 		T(YAFFS_TRACE_VERIFY, | ||||
| 		  (TSTR("Obj %d header mismatch obj_id %d" TENDSTR), | ||||
| 		   tags->obj_id, obj->obj_id)); | ||||
| 		yaffs_trace(YAFFS_TRACE_VERIFY, | ||||
| 			"Obj %d header mismatch obj_id %d", | ||||
| 			tags->obj_id, obj->obj_id); | ||||
|  | ||||
| 	/* | ||||
| 	 * Check that the object's parent ids match if parent_check requested. | ||||
| @@ -202,28 +196,28 @@ void yaffs_verify_oh(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh, | ||||
| 	 */ | ||||
|  | ||||
| 	if (parent_check && tags->obj_id > 1 && !obj->parent) | ||||
| 		T(YAFFS_TRACE_VERIFY, | ||||
| 		  (TSTR | ||||
| 		   ("Obj %d header mismatch parent_id %d obj->parent is NULL" | ||||
| 		    TENDSTR), tags->obj_id, oh->parent_obj_id)); | ||||
| 		yaffs_trace(YAFFS_TRACE_VERIFY, | ||||
| 			"Obj %d header mismatch parent_id %d obj->parent is NULL", | ||||
| 			tags->obj_id, oh->parent_obj_id); | ||||
|  | ||||
| 	if (parent_check && obj->parent && | ||||
| 	    oh->parent_obj_id != obj->parent->obj_id && | ||||
| 	    (oh->parent_obj_id != YAFFS_OBJECTID_UNLINKED || | ||||
| 	     obj->parent->obj_id != YAFFS_OBJECTID_DELETED)) | ||||
| 		T(YAFFS_TRACE_VERIFY, | ||||
| 		  (TSTR | ||||
| 		   ("Obj %d header mismatch parent_id %d parent_obj_id %d" | ||||
| 		    TENDSTR), tags->obj_id, oh->parent_obj_id, | ||||
| 		   obj->parent->obj_id)); | ||||
| 		yaffs_trace(YAFFS_TRACE_VERIFY, | ||||
| 			"Obj %d header mismatch parent_id %d parent_obj_id %d", | ||||
| 			tags->obj_id, oh->parent_obj_id, | ||||
| 			obj->parent->obj_id); | ||||
|  | ||||
| 	if (tags->obj_id > 1 && oh->name[0] == 0)	/* Null name */ | ||||
| 		T(YAFFS_TRACE_VERIFY, | ||||
| 		  (TSTR("Obj %d header name is NULL" TENDSTR), obj->obj_id)); | ||||
| 		yaffs_trace(YAFFS_TRACE_VERIFY, | ||||
| 			"Obj %d header name is NULL", | ||||
| 			obj->obj_id); | ||||
|  | ||||
| 	if (tags->obj_id > 1 && ((u8) (oh->name[0])) == 0xff)	/* Trashed name */ | ||||
| 		T(YAFFS_TRACE_VERIFY, | ||||
| 		  (TSTR("Obj %d header name is 0xFF" TENDSTR), obj->obj_id)); | ||||
| 	if (tags->obj_id > 1 && ((u8) (oh->name[0])) == 0xff)	/* Junk name */ | ||||
| 		yaffs_trace(YAFFS_TRACE_VERIFY, | ||||
| 			"Obj %d header name is 0xFF", | ||||
| 			obj->obj_id); | ||||
| } | ||||
|  | ||||
| void yaffs_verify_file(struct yaffs_obj *obj) | ||||
| @@ -273,16 +267,13 @@ void yaffs_verify_file(struct yaffs_obj *obj) | ||||
| 		if (tn) { | ||||
| 			u32 the_chunk = yaffs_get_group_base(dev, tn, i); | ||||
| 			if (the_chunk > 0) { | ||||
| 				/* T(~0,(TSTR("verifying (%d:%d) %d"TENDSTR),obj_id,i,the_chunk)); */ | ||||
| 				yaffs_rd_chunk_tags_nand(dev, the_chunk, NULL, | ||||
| 							 &tags); | ||||
| 				if (tags.obj_id != obj_id || tags.chunk_id != i) { | ||||
| 					T(~0, | ||||
| 					  (TSTR | ||||
| 					   ("Object %d chunk_id %d NAND mismatch chunk %d tags (%d:%d)" | ||||
| 					    TENDSTR), obj_id, i, the_chunk, | ||||
| 					   tags.obj_id, tags.chunk_id)); | ||||
| 				} | ||||
| 				if (tags.obj_id != obj_id || tags.chunk_id != i) | ||||
| 					yaffs_trace(YAFFS_TRACE_VERIFY, | ||||
| 						"Object %d chunk_id %d NAND mismatch chunk %d tags (%d:%d)", | ||||
| 						obj_id, i, the_chunk, | ||||
| 						tags.obj_id, tags.chunk_id); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| @@ -313,10 +304,8 @@ void yaffs_verify_special(struct yaffs_obj *obj) | ||||
| void yaffs_verify_obj(struct yaffs_obj *obj) | ||||
| { | ||||
| 	struct yaffs_dev *dev; | ||||
|  | ||||
| 	u32 chunk_min; | ||||
| 	u32 chunk_max; | ||||
|  | ||||
| 	u32 chunk_id_ok; | ||||
| 	u32 chunk_in_range; | ||||
| 	u32 chunk_wrongly_deleted; | ||||
| @@ -348,13 +337,12 @@ void yaffs_verify_obj(struct yaffs_obj *obj) | ||||
| 				  obj->hdr_chunk % dev->param.chunks_per_block); | ||||
| 	chunk_wrongly_deleted = chunk_in_range && !chunk_valid; | ||||
|  | ||||
| 	if (!obj->fake && (!chunk_id_ok || chunk_wrongly_deleted)) { | ||||
| 		T(YAFFS_TRACE_VERIFY, | ||||
| 		  (TSTR("Obj %d has chunk_id %d %s %s" TENDSTR), | ||||
| 		   obj->obj_id, obj->hdr_chunk, | ||||
| 		   chunk_id_ok ? "" : ",out of range", | ||||
| 		   chunk_wrongly_deleted ? ",marked as deleted" : "")); | ||||
| 	} | ||||
| 	if (!obj->fake && (!chunk_id_ok || chunk_wrongly_deleted)) | ||||
| 		yaffs_trace(YAFFS_TRACE_VERIFY, | ||||
| 			"Obj %d has chunk_id %d %s %s", | ||||
| 			obj->obj_id, obj->hdr_chunk, | ||||
| 			chunk_id_ok ? "" : ",out of range", | ||||
| 			chunk_wrongly_deleted ? ",marked as deleted" : ""); | ||||
|  | ||||
| 	if (chunk_valid && !yaffs_skip_nand_verification(dev)) { | ||||
| 		struct yaffs_ext_tags tags; | ||||
| @@ -372,18 +360,17 @@ void yaffs_verify_obj(struct yaffs_obj *obj) | ||||
|  | ||||
| 	/* Verify it has a parent */ | ||||
| 	if (obj && !obj->fake && (!obj->parent || obj->parent->my_dev != dev)) { | ||||
| 		T(YAFFS_TRACE_VERIFY, | ||||
| 		  (TSTR | ||||
| 		   ("Obj %d has parent pointer %p which does not look like an object" | ||||
| 		    TENDSTR), obj->obj_id, obj->parent)); | ||||
| 		yaffs_trace(YAFFS_TRACE_VERIFY, | ||||
| 			"Obj %d has parent pointer %p which does not look like an object", | ||||
| 			obj->obj_id, obj->parent); | ||||
| 	} | ||||
|  | ||||
| 	/* Verify parent is a directory */ | ||||
| 	if (obj->parent | ||||
| 	    && obj->parent->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) { | ||||
| 		T(YAFFS_TRACE_VERIFY, | ||||
| 		  (TSTR("Obj %d's parent is not a directory (type %d)" TENDSTR), | ||||
| 		   obj->obj_id, obj->parent->variant_type)); | ||||
| 		yaffs_trace(YAFFS_TRACE_VERIFY, | ||||
| 			"Obj %d's parent is not a directory (type %d)", | ||||
| 			obj->obj_id, obj->parent->variant_type); | ||||
| 	} | ||||
|  | ||||
| 	switch (obj->variant_type) { | ||||
| @@ -404,9 +391,9 @@ void yaffs_verify_obj(struct yaffs_obj *obj) | ||||
| 		break; | ||||
| 	case YAFFS_OBJECT_TYPE_UNKNOWN: | ||||
| 	default: | ||||
| 		T(YAFFS_TRACE_VERIFY, | ||||
| 		  (TSTR("Obj %d has illegaltype %d" TENDSTR), | ||||
| 		   obj->obj_id, obj->variant_type)); | ||||
| 		yaffs_trace(YAFFS_TRACE_VERIFY, | ||||
| 			"Obj %d has illegaltype %d", | ||||
| 		   obj->obj_id, obj->variant_type); | ||||
| 		break; | ||||
| 	} | ||||
| } | ||||
| @@ -424,11 +411,8 @@ void yaffs_verify_objects(struct yaffs_dev *dev) | ||||
|  | ||||
| 	for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) { | ||||
| 		list_for_each(lh, &dev->obj_bucket[i].list) { | ||||
| 			if (lh) { | ||||
| 				obj = | ||||
| 				    list_entry(lh, struct yaffs_obj, hash_link); | ||||
| 				yaffs_verify_obj(obj); | ||||
| 			} | ||||
| 			obj = list_entry(lh, struct yaffs_obj, hash_link); | ||||
| 			yaffs_verify_obj(obj); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -437,11 +421,10 @@ void yaffs_verify_obj_in_dir(struct yaffs_obj *obj) | ||||
| { | ||||
| 	struct list_head *lh; | ||||
| 	struct yaffs_obj *list_obj; | ||||
|  | ||||
| 	int count = 0; | ||||
|  | ||||
| 	if (!obj) { | ||||
| 		T(YAFFS_TRACE_ALWAYS, (TSTR("No object to verify" TENDSTR))); | ||||
| 		yaffs_trace(YAFFS_TRACE_ALWAYS, "No object to verify"); | ||||
| 		YBUG(); | ||||
| 		return; | ||||
| 	} | ||||
| @@ -450,32 +433,29 @@ void yaffs_verify_obj_in_dir(struct yaffs_obj *obj) | ||||
| 		return; | ||||
|  | ||||
| 	if (!obj->parent) { | ||||
| 		T(YAFFS_TRACE_ALWAYS, | ||||
| 		  (TSTR("Object does not have parent" TENDSTR))); | ||||
| 		yaffs_trace(YAFFS_TRACE_ALWAYS, "Object does not have parent"); | ||||
| 		YBUG(); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	if (obj->parent->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) { | ||||
| 		T(YAFFS_TRACE_ALWAYS, | ||||
| 		  (TSTR("Parent is not directory" TENDSTR))); | ||||
| 		yaffs_trace(YAFFS_TRACE_ALWAYS, "Parent is not directory"); | ||||
| 		YBUG(); | ||||
| 	} | ||||
|  | ||||
| 	/* Iterate through the objects in each hash entry */ | ||||
|  | ||||
| 	list_for_each(lh, &obj->parent->variant.dir_variant.children) { | ||||
| 		if (lh) { | ||||
| 			list_obj = list_entry(lh, struct yaffs_obj, siblings); | ||||
| 			yaffs_verify_obj(list_obj); | ||||
| 			if (obj == list_obj) | ||||
| 				count++; | ||||
| 		} | ||||
| 		list_obj = list_entry(lh, struct yaffs_obj, siblings); | ||||
| 		yaffs_verify_obj(list_obj); | ||||
| 		if (obj == list_obj) | ||||
| 			count++; | ||||
| 	} | ||||
|  | ||||
| 	if (count != 1) { | ||||
| 		T(YAFFS_TRACE_ALWAYS, | ||||
| 		  (TSTR("Object in directory %d times" TENDSTR), count)); | ||||
| 		yaffs_trace(YAFFS_TRACE_ALWAYS, | ||||
| 			"Object in directory %d times", | ||||
| 			count); | ||||
| 		YBUG(); | ||||
| 	} | ||||
| } | ||||
| @@ -494,26 +474,23 @@ void yaffs_verify_dir(struct yaffs_obj *directory) | ||||
| 		return; | ||||
|  | ||||
| 	if (directory->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) { | ||||
| 		T(YAFFS_TRACE_ALWAYS, | ||||
| 		  (TSTR("Directory has wrong type: %d" TENDSTR), | ||||
| 		   directory->variant_type)); | ||||
| 		yaffs_trace(YAFFS_TRACE_ALWAYS, | ||||
| 			"Directory has wrong type: %d", | ||||
| 			directory->variant_type); | ||||
| 		YBUG(); | ||||
| 	} | ||||
|  | ||||
| 	/* Iterate through the objects in each hash entry */ | ||||
|  | ||||
| 	list_for_each(lh, &directory->variant.dir_variant.children) { | ||||
| 		if (lh) { | ||||
| 			list_obj = list_entry(lh, struct yaffs_obj, siblings); | ||||
| 			if (list_obj->parent != directory) { | ||||
| 				T(YAFFS_TRACE_ALWAYS, | ||||
| 				  (TSTR | ||||
| 				   ("Object in directory list has wrong parent %p" | ||||
| 				    TENDSTR), list_obj->parent)); | ||||
| 				YBUG(); | ||||
| 			} | ||||
| 			yaffs_verify_obj_in_dir(list_obj); | ||||
| 		list_obj = list_entry(lh, struct yaffs_obj, siblings); | ||||
| 		if (list_obj->parent != directory) { | ||||
| 			yaffs_trace(YAFFS_TRACE_ALWAYS, | ||||
| 				"Object in directory list has wrong parent %p", | ||||
| 				list_obj->parent); | ||||
| 			YBUG(); | ||||
| 		} | ||||
| 		yaffs_verify_obj_in_dir(list_obj); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -532,9 +509,9 @@ void yaffs_verify_free_chunks(struct yaffs_dev *dev) | ||||
| 	difference = dev->n_free_chunks - counted; | ||||
|  | ||||
| 	if (difference) { | ||||
| 		T(YAFFS_TRACE_ALWAYS, | ||||
| 		  (TSTR("Freechunks verification failure %d %d %d" TENDSTR), | ||||
| 		   dev->n_free_chunks, counted, difference)); | ||||
| 		yaffs_trace(YAFFS_TRACE_ALWAYS, | ||||
| 			"Freechunks verification failure %d %d %d", | ||||
| 			dev->n_free_chunks, counted, difference); | ||||
| 		yaffs_free_verification_failures++; | ||||
| 	} | ||||
| } | ||||
| @@ -544,3 +521,4 @@ int yaffs_verify_file_sane(struct yaffs_obj *in) | ||||
| 	in = in; | ||||
| 	return YAFFS_OK; | ||||
| } | ||||
|  | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -24,7 +24,6 @@ int yaffs1_scan(struct yaffs_dev *dev) | ||||
| 	struct yaffs_ext_tags tags; | ||||
| 	int blk; | ||||
| 	int result; | ||||
|  | ||||
| 	int chunk; | ||||
| 	int c; | ||||
| 	int deleted; | ||||
| @@ -35,16 +34,13 @@ int yaffs1_scan(struct yaffs_dev *dev) | ||||
| 	struct yaffs_obj_hdr *oh; | ||||
| 	struct yaffs_obj *in; | ||||
| 	struct yaffs_obj *parent; | ||||
|  | ||||
| 	int alloc_failed = 0; | ||||
|  | ||||
| 	struct yaffs_shadow_fixer *shadow_fixers = NULL; | ||||
|  | ||||
| 	u8 *chunk_data; | ||||
|  | ||||
| 	T(YAFFS_TRACE_SCAN, | ||||
| 	  (TSTR("yaffs1_scan starts  intstartblk %d intendblk %d..." TENDSTR), | ||||
| 	   dev->internal_start_block, dev->internal_end_block)); | ||||
| 	yaffs_trace(YAFFS_TRACE_SCAN, | ||||
| 		"yaffs1_scan starts  intstartblk %d intendblk %d...", | ||||
| 		dev->internal_start_block, dev->internal_end_block); | ||||
|  | ||||
| 	chunk_data = yaffs_get_temp_buffer(dev, __LINE__); | ||||
|  | ||||
| @@ -66,16 +62,15 @@ int yaffs1_scan(struct yaffs_dev *dev) | ||||
| 		if (bi->seq_number == YAFFS_SEQUENCE_BAD_BLOCK) | ||||
| 			bi->block_state = state = YAFFS_BLOCK_STATE_DEAD; | ||||
|  | ||||
| 		T(YAFFS_TRACE_SCAN_DEBUG, | ||||
| 		  (TSTR("Block scanning block %d state %d seq %d" TENDSTR), blk, | ||||
| 		   state, seq_number)); | ||||
| 		yaffs_trace(YAFFS_TRACE_SCAN_DEBUG, | ||||
| 			"Block scanning block %d state %d seq %d", | ||||
| 			blk, state, seq_number); | ||||
|  | ||||
| 		if (state == YAFFS_BLOCK_STATE_DEAD) { | ||||
| 			T(YAFFS_TRACE_BAD_BLOCKS, | ||||
| 			  (TSTR("block %d is bad" TENDSTR), blk)); | ||||
| 			yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, | ||||
| 				"block %d is bad", blk); | ||||
| 		} else if (state == YAFFS_BLOCK_STATE_EMPTY) { | ||||
| 			T(YAFFS_TRACE_SCAN_DEBUG, | ||||
| 			  (TSTR("Block empty " TENDSTR))); | ||||
| 			yaffs_trace(YAFFS_TRACE_SCAN_DEBUG, "Block empty "); | ||||
| 			dev->n_erased_blocks++; | ||||
| 			dev->n_free_chunks += dev->param.chunks_per_block; | ||||
| 		} | ||||
| @@ -86,7 +81,7 @@ int yaffs1_scan(struct yaffs_dev *dev) | ||||
| 	for (blk = dev->internal_start_block; | ||||
| 	     !alloc_failed && blk <= dev->internal_end_block; blk++) { | ||||
|  | ||||
| 		YYIELD(); | ||||
| 		cond_resched(); | ||||
|  | ||||
| 		bi = yaffs_get_block_info(dev, blk); | ||||
| 		state = bi->block_state; | ||||
| @@ -111,7 +106,6 @@ int yaffs1_scan(struct yaffs_dev *dev) | ||||
| 				 */ | ||||
| 				deleted++; | ||||
| 				dev->n_free_chunks++; | ||||
| 				/*T((" %d %d deleted\n",blk,c)); */ | ||||
| 			} else if (!tags.chunk_used) { | ||||
| 				/* An unassigned chunk in the block | ||||
| 				 * This means that either the block is empty or | ||||
| @@ -119,20 +113,19 @@ int yaffs1_scan(struct yaffs_dev *dev) | ||||
| 				 */ | ||||
|  | ||||
| 				if (c == 0) { | ||||
| 					/* We're looking at the first chunk in the block so the block is unused */ | ||||
| 					/* We're looking at the first chunk in | ||||
| 					 *the block so the block is unused */ | ||||
| 					state = YAFFS_BLOCK_STATE_EMPTY; | ||||
| 					dev->n_erased_blocks++; | ||||
| 				} else { | ||||
| 					/* this is the block being allocated from */ | ||||
| 					T(YAFFS_TRACE_SCAN, | ||||
| 					  (TSTR | ||||
| 					   (" Allocating from %d %d" TENDSTR), | ||||
| 					   blk, c)); | ||||
| 					/* this is the block being allocated */ | ||||
| 					yaffs_trace(YAFFS_TRACE_SCAN, | ||||
| 						" Allocating from %d %d", | ||||
| 						blk, c); | ||||
| 					state = YAFFS_BLOCK_STATE_ALLOCATING; | ||||
| 					dev->alloc_block = blk; | ||||
| 					dev->alloc_page = c; | ||||
| 					dev->alloc_block_finder = blk; | ||||
| 					/* Set block finder here to encourage the allocator to go forth from here. */ | ||||
|  | ||||
| 				} | ||||
|  | ||||
| @@ -146,10 +139,10 @@ int yaffs1_scan(struct yaffs_dev *dev) | ||||
| 				bi->pages_in_use++; | ||||
|  | ||||
| 				in = yaffs_find_or_create_by_number(dev, | ||||
| 								    tags.obj_id, | ||||
| 								    YAFFS_OBJECT_TYPE_FILE); | ||||
| 				/* PutChunkIntoFile checks for a clash (two data chunks with | ||||
| 				 * the same chunk_id). | ||||
| 							tags.obj_id, | ||||
| 							YAFFS_OBJECT_TYPE_FILE); | ||||
| 				/* PutChunkIntoFile checks for a clash | ||||
| 				 * (two data chunks with the same chunk_id). | ||||
| 				 */ | ||||
|  | ||||
| 				if (!in) | ||||
| @@ -162,13 +155,13 @@ int yaffs1_scan(struct yaffs_dev *dev) | ||||
| 				} | ||||
|  | ||||
| 				endpos = | ||||
| 				    (tags.chunk_id - | ||||
| 				     1) * dev->data_bytes_per_chunk + | ||||
| 				    (tags.chunk_id - 1) * | ||||
| 				    dev->data_bytes_per_chunk + | ||||
| 				    tags.n_bytes; | ||||
| 				if (in | ||||
| 				    && in->variant_type == | ||||
| 				    YAFFS_OBJECT_TYPE_FILE | ||||
| 				    && in->variant.file_variant.scanned_size < | ||||
| 				if (in && | ||||
| 				    in->variant_type == | ||||
| 				    YAFFS_OBJECT_TYPE_FILE && | ||||
| 				    in->variant.file_variant.scanned_size < | ||||
| 				    endpos) { | ||||
| 					in->variant.file_variant.scanned_size = | ||||
| 					    endpos; | ||||
| @@ -180,10 +173,9 @@ int yaffs1_scan(struct yaffs_dev *dev) | ||||
| 					} | ||||
|  | ||||
| 				} | ||||
| 				/* T((" %d %d data %d %d\n",blk,c,tags.obj_id,tags.chunk_id));   */ | ||||
| 			} else { | ||||
| 				/* chunk_id == 0, so it is an ObjectHeader. | ||||
| 				 * Thus, we read in the object header and make the object | ||||
| 				 * Make the object | ||||
| 				 */ | ||||
| 				yaffs_set_chunk_bit(dev, blk, c); | ||||
| 				bi->pages_in_use++; | ||||
| @@ -197,18 +189,19 @@ int yaffs1_scan(struct yaffs_dev *dev) | ||||
| 				in = yaffs_find_by_number(dev, tags.obj_id); | ||||
| 				if (in && in->variant_type != oh->type) { | ||||
| 					/* This should not happen, but somehow | ||||
| 					 * Wev'e ended up with an obj_id that has been reused but not yet | ||||
| 					 * deleted, and worse still it has changed type. Delete the old object. | ||||
| 					 * Wev'e ended up with an obj_id that | ||||
| 					 * has been reused but not yet deleted, | ||||
| 					 * and worse still it has changed type. | ||||
| 					 * Delete the old object. | ||||
| 					 */ | ||||
|  | ||||
| 					yaffs_del_obj(in); | ||||
|  | ||||
| 					in = 0; | ||||
| 					in = NULL; | ||||
| 				} | ||||
|  | ||||
| 				in = yaffs_find_or_create_by_number(dev, | ||||
| 								    tags.obj_id, | ||||
| 								    oh->type); | ||||
| 								tags.obj_id, | ||||
| 								oh->type); | ||||
|  | ||||
| 				if (!in) | ||||
| 					alloc_failed = 1; | ||||
| @@ -217,27 +210,28 @@ int yaffs1_scan(struct yaffs_dev *dev) | ||||
|  | ||||
| 					struct yaffs_shadow_fixer *fixer; | ||||
| 					fixer = | ||||
| 					    YMALLOC(sizeof | ||||
| 						    (struct | ||||
| 						     yaffs_shadow_fixer)); | ||||
| 						kmalloc(sizeof | ||||
| 						(struct yaffs_shadow_fixer), | ||||
| 						GFP_NOFS); | ||||
| 					if (fixer) { | ||||
| 						fixer->next = shadow_fixers; | ||||
| 						shadow_fixers = fixer; | ||||
| 						fixer->obj_id = tags.obj_id; | ||||
| 						fixer->shadowed_id = | ||||
| 						    oh->shadows_obj; | ||||
| 						T(YAFFS_TRACE_SCAN, | ||||
| 						  (TSTR | ||||
| 						   (" Shadow fixer: %d shadows %d" | ||||
| 						    TENDSTR), fixer->obj_id, | ||||
| 						   fixer->shadowed_id)); | ||||
| 						yaffs_trace(YAFFS_TRACE_SCAN, | ||||
| 							" Shadow fixer: %d shadows %d", | ||||
| 							fixer->obj_id, | ||||
| 							fixer->shadowed_id); | ||||
|  | ||||
| 					} | ||||
|  | ||||
| 				} | ||||
|  | ||||
| 				if (in && in->valid) { | ||||
| 					/* We have already filled this one. We have a duplicate and need to resolve it. */ | ||||
| 					/* We have already filled this one. | ||||
| 					 * We have a duplicate and need to | ||||
| 					 * resolve it. */ | ||||
|  | ||||
| 					unsigned existing_serial = in->serial; | ||||
| 					unsigned new_serial = | ||||
| @@ -245,13 +239,15 @@ int yaffs1_scan(struct yaffs_dev *dev) | ||||
|  | ||||
| 					if (((existing_serial + 1) & 3) == | ||||
| 					    new_serial) { | ||||
| 						/* Use new one - destroy the exisiting one */ | ||||
| 						/* Use new one - destroy the | ||||
| 						 * exisiting one */ | ||||
| 						yaffs_chunk_del(dev, | ||||
| 								in->hdr_chunk, | ||||
| 								1, __LINE__); | ||||
| 						in->valid = 0; | ||||
| 					} else { | ||||
| 						/* Use existing - destroy this one. */ | ||||
| 						/* Use existing - destroy | ||||
| 						 * this one. */ | ||||
| 						yaffs_chunk_del(dev, chunk, 1, | ||||
| 								__LINE__); | ||||
| 					} | ||||
| @@ -261,7 +257,8 @@ int yaffs1_scan(struct yaffs_dev *dev) | ||||
| 				    (tags.obj_id == YAFFS_OBJECTID_ROOT || | ||||
| 				     tags.obj_id == | ||||
| 				     YAFFS_OBJECTID_LOSTNFOUND)) { | ||||
| 					/* We only load some info, don't fiddle with directory structure */ | ||||
| 					/* We only load some info, don't fiddle | ||||
| 					 * with directory structure */ | ||||
| 					in->valid = 1; | ||||
| 					in->variant_type = oh->type; | ||||
|  | ||||
| @@ -300,37 +297,24 @@ int yaffs1_scan(struct yaffs_dev *dev) | ||||
| 						parent->variant_type = | ||||
| 						    YAFFS_OBJECT_TYPE_DIRECTORY; | ||||
| 						INIT_LIST_HEAD(&parent-> | ||||
| 							       variant.dir_variant.children); | ||||
| 					} else if (!parent | ||||
| 						   || parent->variant_type != | ||||
| 						   YAFFS_OBJECT_TYPE_DIRECTORY) | ||||
| 					{ | ||||
| 						/* Hoosterman, another problem.... | ||||
| 						 * We're trying to use a non-directory as a directory | ||||
| 							variant.dir_variant. | ||||
| 							children); | ||||
| 					} else if (!parent || | ||||
| 						parent->variant_type != | ||||
| 						YAFFS_OBJECT_TYPE_DIRECTORY) { | ||||
| 						/* Hoosterman, a 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." | ||||
| 						    TENDSTR))); | ||||
| 						yaffs_trace(YAFFS_TRACE_ERROR, | ||||
| 							"yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found." | ||||
| 							); | ||||
| 						parent = dev->lost_n_found; | ||||
| 					} | ||||
|  | ||||
| 					yaffs_add_obj_to_dir(parent, in); | ||||
|  | ||||
| 					if (0 && (parent == dev->del_dir || | ||||
| 						  parent == | ||||
| 						  dev->unlinked_dir)) { | ||||
| 						in->deleted = 1;	/* If it is unlinked at start up then it wants deleting */ | ||||
| 						dev->n_deleted_files++; | ||||
| 					} | ||||
| 					/* Note re hardlinks. | ||||
| 					 * Since we might scan a hardlink before its equivalent object is scanned | ||||
| 					 * we put them all in a list. | ||||
| 					 * After scanning is complete, we should have all the objects, so we run through this | ||||
| 					 * list and fix up all the chains. | ||||
| 					 */ | ||||
|  | ||||
| 					switch (in->variant_type) { | ||||
| 					case YAFFS_OBJECT_TYPE_UNKNOWN: | ||||
| 						/* Todo got a problem */ | ||||
| @@ -340,7 +324,7 @@ int yaffs1_scan(struct yaffs_dev *dev) | ||||
| 						    use_header_file_size) | ||||
|  | ||||
| 							in->variant. | ||||
| 							    file_variant.file_size | ||||
| 							 file_variant.file_size | ||||
| 							    = oh->file_size; | ||||
|  | ||||
| 						break; | ||||
| @@ -368,18 +352,19 @@ int yaffs1_scan(struct yaffs_dev *dev) | ||||
| 							alloc_failed = 1; | ||||
| 						break; | ||||
| 					} | ||||
|  | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) { | ||||
| 			/* If we got this far while scanning, then the block is fully allocated. */ | ||||
| 			/* If we got this far while scanning, | ||||
| 			 * then the block is fully allocated. */ | ||||
| 			state = YAFFS_BLOCK_STATE_FULL; | ||||
| 		} | ||||
|  | ||||
| 		if (state == YAFFS_BLOCK_STATE_ALLOCATING) { | ||||
| 			/* If the block was partially allocated then treat it as fully allocated. */ | ||||
| 			/* If the block was partially allocated then | ||||
| 			 * treat it as fully allocated. */ | ||||
| 			state = YAFFS_BLOCK_STATE_FULL; | ||||
| 			dev->alloc_block = -1; | ||||
| 		} | ||||
| @@ -392,13 +377,12 @@ int yaffs1_scan(struct yaffs_dev *dev) | ||||
| 		    bi->block_state == YAFFS_BLOCK_STATE_FULL) { | ||||
| 			yaffs_block_became_dirty(dev, blk); | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	/* Ok, we've done all the scanning. | ||||
| 	 * Fix up the hard link chains. | ||||
| 	 * We should now have scanned all the objects, now it's time to add these | ||||
| 	 * hardlinks. | ||||
| 	 * We should now have scanned all the objects, now it's time to add | ||||
| 	 * these hardlinks. | ||||
| 	 */ | ||||
|  | ||||
| 	yaffs_link_fixup(dev, hard_list); | ||||
| @@ -411,8 +395,9 @@ int yaffs1_scan(struct yaffs_dev *dev) | ||||
| 		while (shadow_fixers) { | ||||
| 			fixer = shadow_fixers; | ||||
| 			shadow_fixers = fixer->next; | ||||
| 			/* Complete the rename transaction by deleting the shadowed object | ||||
| 			 * then setting the object header to unshadowed. | ||||
| 			/* Complete the rename transaction by deleting the | ||||
| 			 * shadowed object then setting the object header | ||||
| 			 to unshadowed. | ||||
| 			 */ | ||||
| 			obj = yaffs_find_by_number(dev, fixer->shadowed_id); | ||||
| 			if (obj) | ||||
| @@ -423,7 +408,7 @@ int yaffs1_scan(struct yaffs_dev *dev) | ||||
| 			if (obj) | ||||
| 				yaffs_update_oh(obj, NULL, 1, 0, 0, NULL); | ||||
|  | ||||
| 			YFREE(fixer); | ||||
| 			kfree(fixer); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @@ -432,7 +417,7 @@ int yaffs1_scan(struct yaffs_dev *dev) | ||||
| 	if (alloc_failed) | ||||
| 		return YAFFS_FAIL; | ||||
|  | ||||
| 	T(YAFFS_TRACE_SCAN, (TSTR("yaffs1_scan ends" TENDSTR))); | ||||
| 	yaffs_trace(YAFFS_TRACE_SCAN, "yaffs1_scan ends"); | ||||
|  | ||||
| 	return YAFFS_OK; | ||||
| } | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -24,15 +24,9 @@ | ||||
|  | ||||
| #define MTD_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c)) | ||||
|  | ||||
| #if defined CONFIG_YAFFS_WINCE | ||||
|  | ||||
| #include "ywinceenv.h" | ||||
|  | ||||
| #elif defined __KERNEL__ | ||||
|  | ||||
| #ifdef YAFFS_OUT_OF_TREE | ||||
| #include "moduleconfig.h" | ||||
|  | ||||
| /* Linux kernel */ | ||||
| #endif | ||||
|  | ||||
| #include <linux/version.h> | ||||
| #define MTD_VERSION_CODE LINUX_VERSION_CODE | ||||
| @@ -53,33 +47,15 @@ | ||||
| #include <linux/fs.h> | ||||
| #include <linux/stat.h> | ||||
| #include <linux/sort.h> | ||||
| #include <linux/bitops.h> | ||||
|  | ||||
| #define YCHAR char | ||||
| #define YUCHAR unsigned char | ||||
| #define _Y(x)     x | ||||
| #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_strnlen(s,m)	strnlen(s,m) | ||||
| #define yaffs_sprintf	       sprintf | ||||
| #define yaffs_toupper(a)       toupper(a) | ||||
| #define yaffs_sort(base, n, sz, cmp_fn) sort(base, n, sz, cmp_fn, NULL) | ||||
|  | ||||
| #define Y_INLINE __inline__ | ||||
|  | ||||
| #define YAFFS_LOSTNFOUND_NAME		"lost+found" | ||||
| #define YAFFS_LOSTNFOUND_PREFIX		"obj" | ||||
|  | ||||
| /* #define YPRINTF(x) printk x */ | ||||
| #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) | ||||
|  | ||||
| #define YYIELD() schedule() | ||||
| #define Y_DUMP_STACK() dump_stack() | ||||
|  | ||||
| #define YAFFS_ROOT_MODE			0755 | ||||
| #define YAFFS_LOSTNFOUND_MODE		0700 | ||||
| @@ -92,246 +68,24 @@ | ||||
| #define Y_TIME_CONVERT(x) (x) | ||||
| #endif | ||||
|  | ||||
| #define yaffs_sum_cmp(x, y) ((x) == (y)) | ||||
| #define yaffs_strcmp(a, b) strcmp(a, b) | ||||
|  | ||||
| #define TENDSTR "\n" | ||||
| #define TSTR(x) KERN_DEBUG x | ||||
| #define TCONT(x) x | ||||
| #define TOUT(p) printk p | ||||
|  | ||||
| #define compile_time_assertion(assertion) \ | ||||
| 	({ int x = __builtin_choose_expr(assertion, 0, (void)0); (void) x; }) | ||||
|  | ||||
| #elif defined CONFIG_YAFFS_DIRECT | ||||
|  | ||||
| #define MTD_VERSION_CODE MTD_VERSION(2, 6, 22) | ||||
|  | ||||
| /* Direct interface */ | ||||
| #include "ydirectenv.h" | ||||
|  | ||||
| #elif defined CONFIG_YAFFS_UTIL | ||||
|  | ||||
| /* Stuff for YAFFS utilities */ | ||||
|  | ||||
| #include "stdlib.h" | ||||
| #include "stdio.h" | ||||
| #include "string.h" | ||||
|  | ||||
| #define YMALLOC(x) malloc(x) | ||||
| #define YFREE(x)   free(x) | ||||
| #define YMALLOC_ALT(x) malloc(x) | ||||
| #define YFREE_ALT(x) free(x) | ||||
|  | ||||
| #define YCHAR char | ||||
| #define YUCHAR unsigned char | ||||
| #define _Y(x)     x | ||||
| #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_strnlen(s,m)	       strnlen(s,m) | ||||
| #define yaffs_sprintf	       sprintf | ||||
| #define yaffs_toupper(a)       toupper(a) | ||||
|  | ||||
| #define Y_INLINE inline | ||||
|  | ||||
| /* #define YINFO(s) YPRINTF(( __FILE__ " %d %s\n",__LINE__,s)) */ | ||||
| /* #define YALERT(s) YINFO(s) */ | ||||
|  | ||||
| #define TENDSTR "\n" | ||||
| #define TSTR(x) x | ||||
| #define TOUT(p) printf p | ||||
|  | ||||
| #define YAFFS_LOSTNFOUND_NAME		"lost+found" | ||||
| #define YAFFS_LOSTNFOUND_PREFIX		"obj" | ||||
| /* #define YPRINTF(x) printf x */ | ||||
|  | ||||
| #define YAFFS_ROOT_MODE			0755 | ||||
| #define YAFFS_LOSTNFOUND_MODE		0700 | ||||
|  | ||||
| #define yaffs_sum_cmp(x, y) ((x) == (y)) | ||||
| #define yaffs_strcmp(a, b) strcmp(a, b) | ||||
|  | ||||
| #else | ||||
| /* Should have specified a configuration type */ | ||||
| #error Unknown configuration | ||||
|  | ||||
| #endif | ||||
|  | ||||
| #if defined(CONFIG_YAFFS_DIRECT) || defined(CONFIG_YAFFS_WINCE) | ||||
|  | ||||
| #ifdef CONFIG_YAFFSFS_PROVIDE_VALUES | ||||
|  | ||||
| #ifndef O_RDONLY | ||||
| #define O_RDONLY        00 | ||||
| #endif | ||||
|  | ||||
| #ifndef O_WRONLY | ||||
| #define O_WRONLY	01 | ||||
| #endif | ||||
|  | ||||
| #ifndef O_RDWR | ||||
| #define O_RDWR		02 | ||||
| #endif | ||||
|  | ||||
| #ifndef O_CREAT | ||||
| #define O_CREAT 	0100 | ||||
| #endif | ||||
|  | ||||
| #ifndef O_EXCL | ||||
| #define O_EXCL		0200 | ||||
| #endif | ||||
|  | ||||
| #ifndef O_TRUNC | ||||
| #define O_TRUNC		01000 | ||||
| #endif | ||||
|  | ||||
| #ifndef O_APPEND | ||||
| #define O_APPEND	02000 | ||||
| #endif | ||||
|  | ||||
| #ifndef SEEK_SET | ||||
| #define SEEK_SET	0 | ||||
| #endif | ||||
|  | ||||
| #ifndef SEEK_CUR | ||||
| #define SEEK_CUR	1 | ||||
| #endif | ||||
|  | ||||
| #ifndef SEEK_END | ||||
| #define SEEK_END	2 | ||||
| #endif | ||||
|  | ||||
| #ifndef EBUSY | ||||
| #define EBUSY	16 | ||||
| #endif | ||||
|  | ||||
| #ifndef ENODEV | ||||
| #define ENODEV	19 | ||||
| #endif | ||||
|  | ||||
| #ifndef EINVAL | ||||
| #define EINVAL	22 | ||||
| #endif | ||||
|  | ||||
| #ifndef ENFILE | ||||
| #define ENFILE	23 | ||||
| #endif | ||||
|  | ||||
| #ifndef EBADF | ||||
| #define EBADF	9 | ||||
| #endif | ||||
|  | ||||
| #ifndef EACCES | ||||
| #define EACCES	13 | ||||
| #endif | ||||
|  | ||||
| #ifndef EXDEV | ||||
| #define EXDEV	18 | ||||
| #endif | ||||
|  | ||||
| #ifndef ENOENT | ||||
| #define ENOENT	2 | ||||
| #endif | ||||
|  | ||||
| #ifndef ENOSPC | ||||
| #define ENOSPC	28 | ||||
| #endif | ||||
|  | ||||
| #ifndef ERANGE | ||||
| #define ERANGE 34 | ||||
| #endif | ||||
|  | ||||
| #ifndef ENODATA | ||||
| #define ENODATA 61 | ||||
| #endif | ||||
|  | ||||
| #ifndef ENOTEMPTY | ||||
| #define ENOTEMPTY 39 | ||||
| #endif | ||||
|  | ||||
| #ifndef ENAMETOOLONG | ||||
| #define ENAMETOOLONG 36 | ||||
| #endif | ||||
|  | ||||
| #ifndef ENOMEM | ||||
| #define ENOMEM 12 | ||||
| #endif | ||||
|  | ||||
| #ifndef EEXIST | ||||
| #define EEXIST 17 | ||||
| #endif | ||||
|  | ||||
| #ifndef ENOTDIR | ||||
| #define ENOTDIR 20 | ||||
| #endif | ||||
|  | ||||
| #ifndef EISDIR | ||||
| #define EISDIR 21 | ||||
| #endif | ||||
|  | ||||
| // Mode flags | ||||
|  | ||||
| #ifndef S_IFMT | ||||
| #define S_IFMT		0170000 | ||||
| #endif | ||||
|  | ||||
| #ifndef S_IFLNK | ||||
| #define S_IFLNK		0120000 | ||||
| #endif | ||||
|  | ||||
| #ifndef S_IFDIR | ||||
| #define S_IFDIR		0040000 | ||||
| #endif | ||||
|  | ||||
| #ifndef S_IFREG | ||||
| #define S_IFREG		0100000 | ||||
| #endif | ||||
|  | ||||
| #ifndef S_IREAD | ||||
| #define S_IREAD		0000400 | ||||
| #endif | ||||
|  | ||||
| #ifndef S_IWRITE | ||||
| #define	S_IWRITE	0000200 | ||||
| #endif | ||||
|  | ||||
| #ifndef S_IEXEC | ||||
| #define	S_IEXEC	0000100 | ||||
| #endif | ||||
|  | ||||
| #ifndef XATTR_CREATE | ||||
| #define XATTR_CREATE 1 | ||||
| #endif | ||||
|  | ||||
| #ifndef XATTR_REPLACE | ||||
| #define XATTR_REPLACE 2 | ||||
| #endif | ||||
|  | ||||
| #ifndef R_OK | ||||
| #define R_OK	4 | ||||
| #define W_OK	2 | ||||
| #define X_OK	1 | ||||
| #define F_OK	0 | ||||
| #endif | ||||
|  | ||||
| #else | ||||
| #include <errno.h> | ||||
| #include <sys/stat.h> | ||||
| #include <fcntl.h> | ||||
| #endif | ||||
|  | ||||
| #endif | ||||
|  | ||||
| #ifndef Y_DUMP_STACK | ||||
| #define Y_DUMP_STACK() do { } while (0) | ||||
| #define Y_DUMP_STACK() dump_stack() | ||||
| #endif | ||||
|  | ||||
| #define yaffs_trace(msk, fmt, ...) do { \ | ||||
| 	if (yaffs_trace_mask & (msk)) \ | ||||
| 		printk(KERN_DEBUG "yaffs: " fmt "\n", ##__VA_ARGS__); \ | ||||
| } while (0) | ||||
|  | ||||
| #ifndef YBUG | ||||
| #define YBUG() do {\ | ||||
| 	T(YAFFS_TRACE_BUG,\ | ||||
| 		(TSTR("==>> yaffs bug: " __FILE__ " %d" TENDSTR),\ | ||||
| 		__LINE__));\ | ||||
| 	yaffs_trace(YAFFS_TRACE_BUG,\ | ||||
| 		"bug " __FILE__ " %d",\ | ||||
| 		__LINE__);\ | ||||
| 	Y_DUMP_STACK();\ | ||||
| } while (0) | ||||
| #endif | ||||
|   | ||||
		Reference in New Issue
	
	Block a user