1 --- a/fs/yaffs2/yaffs_tagscompat.h
2 +++ b/fs/yaffs2/yaffs_tagscompat.h
3 @@ -30,8 +30,9 @@ int yaffs_TagsCompatabilityReadChunkWith
4 int yaffs_TagsCompatabilityMarkNANDBlockBad(struct yaffs_DeviceStruct *dev,
6 int yaffs_TagsCompatabilityQueryNANDBlock(struct yaffs_DeviceStruct *dev,
7 - int blockNo, yaffs_BlockState *
8 - state, int *sequenceNumber);
10 + yaffs_BlockState *state,
11 + __u32 *sequenceNumber);
13 void yaffs_CalcTagsECC(yaffs_Tags * tags);
14 int yaffs_CheckECCOnTags(yaffs_Tags * tags);
15 --- a/fs/yaffs2/Kconfig
16 +++ b/fs/yaffs2/Kconfig
17 @@ -43,7 +43,8 @@ config YAFFS_9BYTE_TAGS
18 format that you need to continue to support. New data written
19 also uses the older-style format. Note: Use of this option
20 generally requires that MTD's oob layout be adjusted to use the
21 - older-style format. See notes on tags formats and MTD versions.
22 + older-style format. See notes on tags formats and MTD versions
27 @@ -109,26 +110,6 @@ config YAFFS_DISABLE_LAZY_LOAD
31 -config YAFFS_CHECKPOINT_RESERVED_BLOCKS
32 - int "Reserved blocks for checkpointing"
33 - depends on YAFFS_YAFFS2
36 - Give the number of Blocks to reserve for checkpointing.
37 - Checkpointing saves the state at unmount so that mounting is
38 - much faster as a scan of all the flash to regenerate this state
39 - is not needed. These Blocks are reserved per partition, so if
40 - you have very small partitions the default (10) may be a mess
41 - for you. You can set this value to 0, but that does not mean
42 - checkpointing is disabled at all. There only won't be any
43 - specially reserved blocks for checkpointing, so if there is
44 - enough free space on the filesystem, it will be used for
47 - If unsure, leave at default (10), but don't wonder if there are
48 - always 2MB used on your large page device partition (10 x 2k
49 - pagesize). When using small partitions or when being very small
50 - on space, you probably want to set this to zero.
52 config YAFFS_DISABLE_WIDE_TNODES
53 bool "Turn off wide tnodes"
54 --- a/fs/yaffs2/yaffs_mtdif.h
55 +++ b/fs/yaffs2/yaffs_mtdif.h
58 #include "yaffs_guts.h"
60 +#if (MTD_VERSION_CODE < MTD_VERSION(2,6,18))
61 +extern struct nand_oobinfo yaffs_oobinfo;
62 +extern struct nand_oobinfo yaffs_noeccinfo;
65 int nandmtd_WriteChunkToNAND(yaffs_Device * dev, int chunkInNAND,
66 const __u8 * data, const yaffs_Spare * spare);
67 int nandmtd_ReadChunkFromNAND(yaffs_Device * dev, int chunkInNAND, __u8 * data,
68 --- a/fs/yaffs2/devextras.h
69 +++ b/fs/yaffs2/devextras.h
72 - * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
73 + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
75 * Copyright (C) 2002-2007 Aleph One Ltd.
76 * for Toby Churchill Ltd and Brightstar Engineering
81 - * This file is just holds extra declarations used during development.
82 - * Most of these are from kernel includes placed here so we can use them in
84 + * This file is just holds extra declarations of macros that would normally
85 + * be providesd in the Linux kernel. These macros have been written from
86 + * scratch but are functionally equivalent to the Linux ones.
94 -#define __inline__ __inline
98 -#if !(defined __KERNEL__) || (defined WIN32)
100 -/* User space defines */
101 +#if !(defined __KERNEL__)
103 +/* Definition of types */
104 typedef unsigned char __u8;
105 typedef unsigned short __u16;
106 typedef unsigned __u32;
111 - * Simple doubly linked list implementation.
113 - * Some of the internal functions ("__xxx") are useful when
114 - * manipulating whole lists rather than single entries, as
115 - * sometimes we already know the next/prev entries and we can
116 - * generate better code by using them directly rather than
117 - * using the generic single-entry routines.
118 + * This is a simple doubly linked list implementation that matches the
119 + * way the Linux kernel doubly linked list implementation works.
122 -#define prefetch(x) 1
125 - struct list_head *next, *prev;
127 + struct ylist_head *next; /* next in chain */
128 + struct ylist_head *prev; /* previous in chain */
131 -#define LIST_HEAD_INIT(name) { &(name), &(name) }
133 -#define LIST_HEAD(name) \
134 - struct list_head name = LIST_HEAD_INIT(name)
135 +/* Initialise a static list */
136 +#define YLIST_HEAD(name) \
137 +struct ylist_head name = { &(name),&(name)}
139 -#define INIT_LIST_HEAD(ptr) do { \
140 - (ptr)->next = (ptr); (ptr)->prev = (ptr); \
144 - * Insert a new entry between two known consecutive entries.
146 - * This is only for internal list manipulation where we know
147 - * the prev/next entries already!
149 -static __inline__ void __list_add(struct list_head *new,
150 - struct list_head *prev,
151 - struct list_head *next)
160 - * list_add - add a new entry
161 - * @new: new entry to be added
162 - * @head: list head to add it after
164 - * Insert a new entry after the specified head.
165 - * This is good for implementing stacks.
167 -static __inline__ void list_add(struct list_head *new, struct list_head *head)
169 - __list_add(new, head, head->next);
171 +/* Initialise a list head to an empty list */
172 +#define YINIT_LIST_HEAD(p) \
179 - * list_add_tail - add a new entry
180 - * @new: new entry to be added
181 - * @head: list head to add it before
183 - * Insert a new entry before the specified head.
184 - * This is useful for implementing queues.
186 -static __inline__ void list_add_tail(struct list_head *new,
187 - struct list_head *head)
189 +/* Add an element to a list */
190 +static __inline__ void ylist_add(struct ylist_head *newEntry,
191 + struct ylist_head *list)
193 - __list_add(new, head->prev, head);
194 + struct ylist_head *listNext = list->next;
196 + list->next = newEntry;
197 + newEntry->prev = list;
198 + newEntry->next = listNext;
199 + listNext->prev = newEntry;
204 - * Delete a list entry by making the prev/next entries
205 - * point to each other.
207 - * This is only for internal list manipulation where we know
208 - * the prev/next entries already!
210 -static __inline__ void __list_del(struct list_head *prev,
211 - struct list_head *next)
212 +static __inline__ void ylist_add_tail(struct ylist_head *newEntry,
213 + struct ylist_head *list)
217 + struct ylist_head *listPrev = list->prev;
219 + list->prev = newEntry;
220 + newEntry->next = list;
221 + newEntry->prev = listPrev;
222 + listPrev->next = newEntry;
227 - * list_del - deletes entry from list.
228 - * @entry: the element to delete from the list.
229 - * Note: list_empty on entry does not return true after this, the entry is
230 - * in an undefined state.
232 -static __inline__ void list_del(struct list_head *entry)
234 +/* Take an element out of its current list, with or without
235 + * reinitialising the links.of the entry*/
236 +static __inline__ void ylist_del(struct ylist_head *entry)
238 - __list_del(entry->prev, entry->next);
239 + struct ylist_head *listNext = entry->next;
240 + struct ylist_head *listPrev = entry->prev;
242 + listNext->prev = listPrev;
243 + listPrev->next = listNext;
248 - * list_del_init - deletes entry from list and reinitialize it.
249 - * @entry: the element to delete from the list.
251 -static __inline__ void list_del_init(struct list_head *entry)
252 +static __inline__ void ylist_del_init(struct ylist_head *entry)
254 - __list_del(entry->prev, entry->next);
255 - INIT_LIST_HEAD(entry);
257 + entry->next = entry->prev = entry;
261 - * list_empty - tests whether a list is empty
262 - * @head: the list to test.
264 -static __inline__ int list_empty(struct list_head *head)
266 +/* Test if the list is empty */
267 +static __inline__ int ylist_empty(struct ylist_head *entry)
269 - return head->next == head;
270 + return (entry->next == entry);
274 - * list_splice - join two lists
275 - * @list: the new list to add.
276 - * @head: the place to add it in the first list.
278 +/* ylist_entry takes a pointer to a list entry and offsets it to that
279 + * we can find a pointer to the object it is embedded in.
281 -static __inline__ void list_splice(struct list_head *list,
282 - struct list_head *head)
284 - struct list_head *first = list->next;
287 +#define ylist_entry(entry, type, member) \
288 + ((type *)((char *)(entry)-(unsigned long)(&((type *)NULL)->member)))
290 - if (first != list) {
291 - struct list_head *last = list->prev;
292 - struct list_head *at = head->next;
294 - first->prev = head;
295 - head->next = first;
303 - * list_entry - get the struct for this entry
304 - * @ptr: the &struct list_head pointer.
305 - * @type: the type of the struct this is embedded in.
306 - * @member: the name of the list_struct within the struct.
307 +/* ylist_for_each and list_for_each_safe iterate over lists.
308 + * ylist_for_each_safe uses temporary storage to make the list delete safe
310 -#define list_entry(ptr, type, member) \
311 - ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
314 - * list_for_each - iterate over a list
315 - * @pos: the &struct list_head to use as a loop counter.
316 - * @head: the head for your list.
318 -#define list_for_each(pos, head) \
319 - for (pos = (head)->next, prefetch(pos->next); pos != (head); \
320 - pos = pos->next, prefetch(pos->next))
323 - * list_for_each_safe - iterate over a list safe against removal
325 - * @pos: the &struct list_head to use as a loop counter.
326 - * @n: another &struct list_head to use as temporary storage
327 - * @head: the head for your list.
329 -#define list_for_each_safe(pos, n, head) \
330 - for (pos = (head)->next, n = pos->next; pos != (head); \
331 - pos = n, n = pos->next)
332 +#define ylist_for_each(itervar, list) \
333 + for (itervar = (list)->next; itervar != (list); itervar = itervar->next )
338 -#define DT_UNKNOWN 0
341 +#define ylist_for_each_safe(itervar,saveVar, list) \
342 + for (itervar = (list)->next, saveVar = (list)->next->next; itervar != (list); \
343 + itervar = saveVar, saveVar = saveVar->next)
346 +#if !(defined __KERNEL__)
350 +#include <sys/stat.h>
354 +#ifdef CONFIG_YAFFS_PROVIDE_DEFS
358 +#define DT_UNKNOWN 0
374 #include <sys/stat.h>
375 @@ -220,17 +162,13 @@ static __inline__ void list_splice(struc
376 * Attribute flags. These should be or-ed together to figure out what
385 #define ATTR_ATIME 16
386 #define ATTR_MTIME 32
387 #define ATTR_CTIME 64
388 -#define ATTR_ATIME_SET 128
389 -#define ATTR_MTIME_SET 256
390 -#define ATTR_FORCE 512 /* Not a change, but a change it */
391 -#define ATTR_ATTR_FLAG 1024
394 unsigned int ia_valid;
395 @@ -241,24 +179,21 @@ struct iattr {
399 - unsigned int ia_attr_flags;
400 + unsigned int ia_attr_flags;
411 #include <linux/types.h>
412 -#include <linux/list.h>
413 #include <linux/fs.h>
414 #include <linux/stat.h>
424 --- a/fs/yaffs2/yaffs_packedtags2.c
425 +++ b/fs/yaffs2/yaffs_packedtags2.c
427 #define EXTRA_OBJECT_TYPE_SHIFT (28)
428 #define EXTRA_OBJECT_TYPE_MASK ((0x0F) << EXTRA_OBJECT_TYPE_SHIFT)
430 -static void yaffs_DumpPackedTags2(const yaffs_PackedTags2 * pt)
432 +static void yaffs_DumpPackedTags2TagsPart(const yaffs_PackedTags2TagsPart * ptt)
435 (TSTR("packed tags obj %d chunk %d byte %d seq %d" TENDSTR),
436 - pt->t.objectId, pt->t.chunkId, pt->t.byteCount,
437 - pt->t.sequenceNumber));
438 + ptt->objectId, ptt->chunkId, ptt->byteCount,
439 + ptt->sequenceNumber));
441 +static void yaffs_DumpPackedTags2(const yaffs_PackedTags2 * pt)
443 + yaffs_DumpPackedTags2TagsPart(&pt->t);
446 static void yaffs_DumpTags2(const yaffs_ExtendedTags * t)
450 - ("ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte "
451 - "%d del %d ser %d seq %d"
452 + ("ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte %d del %d ser %d seq %d"
453 TENDSTR), t->eccResult, t->blockBad, t->chunkUsed, t->objectId,
454 t->chunkId, t->byteCount, t->chunkDeleted, t->serialNumber,
459 -void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags * t)
460 +void yaffs_PackTags2TagsPart(yaffs_PackedTags2TagsPart * ptt, const yaffs_ExtendedTags * t)
462 - pt->t.chunkId = t->chunkId;
463 - pt->t.sequenceNumber = t->sequenceNumber;
464 - pt->t.byteCount = t->byteCount;
465 - pt->t.objectId = t->objectId;
466 + ptt->chunkId = t->chunkId;
467 + ptt->sequenceNumber = t->sequenceNumber;
468 + ptt->byteCount = t->byteCount;
469 + ptt->objectId = t->objectId;
471 if (t->chunkId == 0 && t->extraHeaderInfoAvailable) {
472 /* Store the extra header info instead */
473 /* We save the parent object in the chunkId */
474 - pt->t.chunkId = EXTRA_HEADER_INFO_FLAG
475 + ptt->chunkId = EXTRA_HEADER_INFO_FLAG
476 | t->extraParentObjectId;
477 if (t->extraIsShrinkHeader) {
478 - pt->t.chunkId |= EXTRA_SHRINK_FLAG;
479 + ptt->chunkId |= EXTRA_SHRINK_FLAG;
481 if (t->extraShadows) {
482 - pt->t.chunkId |= EXTRA_SHADOWS_FLAG;
483 + ptt->chunkId |= EXTRA_SHADOWS_FLAG;
486 - pt->t.objectId &= ~EXTRA_OBJECT_TYPE_MASK;
488 + ptt->objectId &= ~EXTRA_OBJECT_TYPE_MASK;
490 (t->extraObjectType << EXTRA_OBJECT_TYPE_SHIFT);
492 if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) {
493 - pt->t.byteCount = t->extraEquivalentObjectId;
494 + ptt->byteCount = t->extraEquivalentObjectId;
495 } else if (t->extraObjectType == YAFFS_OBJECT_TYPE_FILE) {
496 - pt->t.byteCount = t->extraFileLength;
497 + ptt->byteCount = t->extraFileLength;
499 - pt->t.byteCount = 0;
500 + ptt->byteCount = 0;
504 - yaffs_DumpPackedTags2(pt);
505 + yaffs_DumpPackedTags2TagsPart(ptt);
510 +void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags * t)
512 + yaffs_PackTags2TagsPart(&pt->t,t);
514 #ifndef YAFFS_IGNORE_TAGS_ECC
516 @@ -101,20 +111,63 @@ void yaffs_PackTags2(yaffs_PackedTags2 *
520 -void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt)
522 +void yaffs_UnpackTags2TagsPart(yaffs_ExtendedTags * t, yaffs_PackedTags2TagsPart * ptt)
525 memset(t, 0, sizeof(yaffs_ExtendedTags));
527 yaffs_InitialiseTags(t);
529 + if (ptt->sequenceNumber != 0xFFFFFFFF) {
532 + t->objectId = ptt->objectId;
533 + t->chunkId = ptt->chunkId;
534 + t->byteCount = ptt->byteCount;
535 + t->chunkDeleted = 0;
536 + t->serialNumber = 0;
537 + t->sequenceNumber = ptt->sequenceNumber;
539 + /* Do extra header info stuff */
541 + if (ptt->chunkId & EXTRA_HEADER_INFO_FLAG) {
545 + t->extraHeaderInfoAvailable = 1;
546 + t->extraParentObjectId =
547 + ptt->chunkId & (~(ALL_EXTRA_FLAGS));
548 + t->extraIsShrinkHeader =
549 + (ptt->chunkId & EXTRA_SHRINK_FLAG) ? 1 : 0;
551 + (ptt->chunkId & EXTRA_SHADOWS_FLAG) ? 1 : 0;
552 + t->extraObjectType =
553 + ptt->objectId >> EXTRA_OBJECT_TYPE_SHIFT;
554 + t->objectId &= ~EXTRA_OBJECT_TYPE_MASK;
556 + if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) {
557 + t->extraEquivalentObjectId = ptt->byteCount;
559 + t->extraFileLength = ptt->byteCount;
564 + yaffs_DumpPackedTags2TagsPart(ptt);
565 + yaffs_DumpTags2(t);
570 +void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt)
573 + yaffs_ECCResult eccResult = YAFFS_ECC_RESULT_NO_ERROR;
575 if (pt->t.sequenceNumber != 0xFFFFFFFF) {
577 -#ifdef YAFFS_IGNORE_TAGS_ECC
579 - t->eccResult = YAFFS_ECC_RESULT_NO_ERROR;
582 +#ifndef YAFFS_IGNORE_TAGS_ECC
586 @@ -129,54 +182,27 @@ void yaffs_UnpackTags2(yaffs_ExtendedTag
590 - t->eccResult = YAFFS_ECC_RESULT_NO_ERROR;
591 + eccResult = YAFFS_ECC_RESULT_NO_ERROR;
594 - t->eccResult = YAFFS_ECC_RESULT_FIXED;
595 + eccResult = YAFFS_ECC_RESULT_FIXED;
598 - t->eccResult = YAFFS_ECC_RESULT_UNFIXED;
599 + eccResult = YAFFS_ECC_RESULT_UNFIXED;
602 - t->eccResult = YAFFS_ECC_RESULT_UNKNOWN;
603 + eccResult = YAFFS_ECC_RESULT_UNKNOWN;
609 - t->objectId = pt->t.objectId;
610 - t->chunkId = pt->t.chunkId;
611 - t->byteCount = pt->t.byteCount;
612 - t->chunkDeleted = 0;
613 - t->serialNumber = 0;
614 - t->sequenceNumber = pt->t.sequenceNumber;
616 - /* Do extra header info stuff */
618 - if (pt->t.chunkId & EXTRA_HEADER_INFO_FLAG) {
622 - t->extraHeaderInfoAvailable = 1;
623 - t->extraParentObjectId =
624 - pt->t.chunkId & (~(ALL_EXTRA_FLAGS));
625 - t->extraIsShrinkHeader =
626 - (pt->t.chunkId & EXTRA_SHRINK_FLAG) ? 1 : 0;
628 - (pt->t.chunkId & EXTRA_SHADOWS_FLAG) ? 1 : 0;
629 - t->extraObjectType =
630 - pt->t.objectId >> EXTRA_OBJECT_TYPE_SHIFT;
631 - t->objectId &= ~EXTRA_OBJECT_TYPE_MASK;
633 - if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) {
634 - t->extraEquivalentObjectId = pt->t.byteCount;
636 - t->extraFileLength = pt->t.byteCount;
641 + yaffs_UnpackTags2TagsPart(t,&pt->t);
643 + t->eccResult = eccResult;
645 yaffs_DumpPackedTags2(pt);
650 --- a/fs/yaffs2/yaffs_ecc.c
651 +++ b/fs/yaffs2/yaffs_ecc.c
655 const char *yaffs_ecc_c_version =
656 - "$Id: yaffs_ecc.c,v 1.9 2007-02-14 01:09:06 wookey Exp $";
657 + "$Id: yaffs_ecc.c,v 1.10 2007-12-13 15:35:17 wookey Exp $";
659 #include "yportenv.h"
661 --- a/fs/yaffs2/yaffs_packedtags2.h
662 +++ b/fs/yaffs2/yaffs_packedtags2.h
663 @@ -33,6 +33,11 @@ typedef struct {
667 +/* Full packed tags with ECC, used for oob tags */
668 void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags * t);
669 void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt);
671 +/* Only the tags part (no ECC for use with inband tags */
672 +void yaffs_PackTags2TagsPart(yaffs_PackedTags2TagsPart * pt, const yaffs_ExtendedTags * t);
673 +void yaffs_UnpackTags2TagsPart(yaffs_ExtendedTags * t, yaffs_PackedTags2TagsPart * pt);
675 --- a/fs/yaffs2/yportenv.h
676 +++ b/fs/yaffs2/yportenv.h
678 #ifndef __YPORTENV_H__
679 #define __YPORTENV_H__
682 + * Define the MTD version in terms of Linux Kernel versions
683 + * This allows yaffs to be used independantly of the kernel
684 + * as well as with it.
687 +#define MTD_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
689 #if defined CONFIG_YAFFS_WINCE
691 #include "ywinceenv.h"
693 #include "moduleconfig.h"
697 #include <linux/version.h>
698 +#define MTD_VERSION_CODE LINUX_VERSION_CODE
700 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
701 #include <linux/config.h>
705 #define YUCHAR unsigned char
707 +#define yaffs_strcat(a,b) strcat(a,b)
708 #define yaffs_strcpy(a,b) strcpy(a,b)
709 #define yaffs_strncpy(a,b,c) strncpy(a,b,c)
710 #define yaffs_strncmp(a,b,c) strncmp(a,b,c)
713 #elif defined CONFIG_YAFFS_DIRECT
715 +#define MTD_VERSION_CODE MTD_VERSION(2,6,22)
717 /* Direct interface */
718 #include "ydirectenv.h"
722 #define YUCHAR unsigned char
724 +#define yaffs_strcat(a,b) strcat(a,b)
725 #define yaffs_strcpy(a,b) strcpy(a,b)
726 #define yaffs_strncpy(a,b,c) strncpy(a,b,c)
727 #define yaffs_strlen(s) strlen(s)
728 @@ -180,8 +195,8 @@ extern unsigned int yaffs_wr_attempts;
730 #define T(mask,p) do{ if((mask) & (yaffs_traceMask | YAFFS_TRACE_ALWAYS)) TOUT(p);} while(0)
732 -#ifndef CONFIG_YAFFS_WINCE
733 -#define YBUG() T(YAFFS_TRACE_BUG,(TSTR("==>> yaffs bug: " __FILE__ " %d" TENDSTR),__LINE__))
735 +#define YBUG() do {T(YAFFS_TRACE_BUG,(TSTR("==>> yaffs bug: " __FILE__ " %d" TENDSTR),__LINE__));} while(0)
739 --- a/fs/yaffs2/Makefile
740 +++ b/fs/yaffs2/Makefile
742 obj-$(CONFIG_YAFFS_FS) += yaffs.o
744 yaffs-y := yaffs_ecc.o yaffs_fs.o yaffs_guts.o yaffs_checkptrw.o
745 -yaffs-y += yaffs_packedtags2.o yaffs_nand.o yaffs_qsort.o
746 +yaffs-y += yaffs_packedtags1.o yaffs_packedtags2.o yaffs_nand.o yaffs_qsort.o
747 yaffs-y += yaffs_tagscompat.o yaffs_tagsvalidity.o
748 -yaffs-y += yaffs_mtdif1.o yaffs_packedtags1.o
749 -yaffs-y += yaffs_mtdif.o yaffs_mtdif2.o
750 +yaffs-y += yaffs_mtdif.o yaffs_mtdif1.o yaffs_mtdif2.o
751 --- a/fs/yaffs2/yaffs_fs.c
752 +++ b/fs/yaffs2/yaffs_fs.c
756 const char *yaffs_fs_c_version =
757 - "$Id: yaffs_fs.c,v 1.63 2007-09-19 20:35:40 imcd Exp $";
758 + "$Id: yaffs_fs.c,v 1.71 2009-01-22 00:45:54 charles Exp $";
759 extern const char *yaffs_guts_c_version;
761 #include <linux/version.h>
762 @@ -43,7 +43,6 @@ extern const char *yaffs_guts_c_version;
763 #include <linux/module.h>
764 #include <linux/slab.h>
765 #include <linux/init.h>
766 -#include <linux/list.h>
767 #include <linux/fs.h>
768 #include <linux/proc_fs.h>
769 #include <linux/smp_lock.h>
770 @@ -53,6 +52,8 @@ extern const char *yaffs_guts_c_version;
771 #include <linux/string.h>
772 #include <linux/ctype.h>
774 +#include "asm/div64.h"
776 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
778 #include <linux/statfs.h> /* Added NCB 15-8-2003 */
779 @@ -76,6 +77,12 @@ extern const char *yaffs_guts_c_version;
783 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26))
784 +#define YPROC_ROOT &proc_root
786 +#define YPROC_ROOT NULL
789 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
790 #define WRITE_SIZE_STR "writesize"
791 #define WRITE_SIZE(mtd) (mtd)->writesize
792 @@ -84,6 +91,13 @@ extern const char *yaffs_guts_c_version;
793 #define WRITE_SIZE(mtd) (mtd)->oobblock
796 +#if(LINUX_VERSION_CODE > KERNEL_VERSION(2,6,27))
797 +#define YAFFS_USE_WRITE_BEGIN_END 1
799 +#define YAFFS_USE_WRITE_BEGIN_END 0
803 #include <asm/uaccess.h>
805 #include "yportenv.h"
806 @@ -96,14 +110,30 @@ extern const char *yaffs_guts_c_version;
808 unsigned int yaffs_traceMask = YAFFS_TRACE_BAD_BLOCKS;
809 unsigned int yaffs_wr_attempts = YAFFS_WR_ATTEMPTS;
810 +unsigned int yaffs_auto_checkpoint = 1;
812 /* Module Parameters */
813 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
814 module_param(yaffs_traceMask,uint,0644);
815 module_param(yaffs_wr_attempts,uint,0644);
816 +module_param(yaffs_auto_checkpoint,uint,0644);
818 MODULE_PARM(yaffs_traceMask,"i");
819 MODULE_PARM(yaffs_wr_attempts,"i");
820 +MODULE_PARM(yaffs_auto_checkpoint,"i");
823 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25))
824 +/* use iget and read_inode */
825 +#define Y_IGET(sb,inum) iget((sb),(inum))
826 +static void yaffs_read_inode(struct inode *inode);
829 +/* Call local equivalent */
830 +#define YAFFS_USE_OWN_IGET
831 +#define Y_IGET(sb,inum) yaffs_iget((sb),(inum))
833 +static struct inode * yaffs_iget(struct super_block *sb, unsigned long ino);
836 /*#define T(x) printk x */
837 @@ -127,6 +157,8 @@ static void yaffs_put_super(struct super
839 static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n,
841 +static ssize_t yaffs_hold_space(struct file *f);
842 +static void yaffs_release_space(struct file *f);
844 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
845 static int yaffs_file_flush(struct file *file, fl_owner_t id);
846 @@ -181,9 +213,11 @@ static int yaffs_statfs(struct super_blo
848 static int yaffs_statfs(struct super_block *sb, struct statfs *buf);
850 -static void yaffs_read_inode(struct inode *inode);
852 +#ifdef YAFFS_HAS_PUT_INODE
853 static void yaffs_put_inode(struct inode *inode);
856 static void yaffs_delete_inode(struct inode *);
857 static void yaffs_clear_inode(struct inode *);
859 @@ -193,10 +227,22 @@ static int yaffs_writepage(struct page *
861 static int yaffs_writepage(struct page *page);
865 +#if (YAFFS_USE_WRITE_BEGIN_END != 0)
866 +static int yaffs_write_begin(struct file *filp, struct address_space *mapping,
867 + loff_t pos, unsigned len, unsigned flags,
868 + struct page **pagep, void **fsdata);
869 +static int yaffs_write_end(struct file *filp, struct address_space *mapping,
870 + loff_t pos, unsigned len, unsigned copied,
871 + struct page *pg, void *fsdadata);
873 static int yaffs_prepare_write(struct file *f, struct page *pg,
874 unsigned offset, unsigned to);
875 static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset,
880 static int yaffs_readlink(struct dentry *dentry, char __user * buffer,
882 @@ -209,8 +255,13 @@ static int yaffs_follow_link(struct dent
883 static struct address_space_operations yaffs_file_address_operations = {
884 .readpage = yaffs_readpage,
885 .writepage = yaffs_writepage,
886 +#if (YAFFS_USE_WRITE_BEGIN_END > 0)
887 + .write_begin = yaffs_write_begin,
888 + .write_end = yaffs_write_end,
890 .prepare_write = yaffs_prepare_write,
891 .commit_write = yaffs_commit_write,
895 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22))
896 @@ -224,6 +275,7 @@ static struct file_operations yaffs_file
897 .fsync = yaffs_sync_object,
898 .splice_read = generic_file_splice_read,
899 .splice_write = generic_file_splice_write,
900 + .llseek = generic_file_llseek,
903 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18))
904 @@ -284,8 +336,13 @@ static struct file_operations yaffs_dir_
906 static struct super_operations yaffs_super_ops = {
907 .statfs = yaffs_statfs,
909 +#ifndef YAFFS_USE_OWN_IGET
910 .read_inode = yaffs_read_inode,
912 +#ifdef YAFFS_HAS_PUT_INODE
913 .put_inode = yaffs_put_inode,
915 .put_super = yaffs_put_super,
916 .delete_inode = yaffs_delete_inode,
917 .clear_inode = yaffs_clear_inode,
918 @@ -429,6 +486,9 @@ static struct dentry *yaffs_lookup(struc
923 +#ifdef YAFFS_HAS_PUT_INODE
925 /* For now put inode is just for debugging
926 * Put inode is called when the inode **structure** is put.
928 @@ -439,6 +499,7 @@ static void yaffs_put_inode(struct inode
929 atomic_read(&inode->i_count)));
934 /* clear is called to tell the fs to release any per-inode data it holds */
935 static void yaffs_clear_inode(struct inode *inode)
936 @@ -667,6 +728,64 @@ static int yaffs_writepage(struct page *
937 return (nWritten == nBytes) ? 0 : -ENOSPC;
941 +#if (YAFFS_USE_WRITE_BEGIN_END > 0)
942 +static int yaffs_write_begin(struct file *filp, struct address_space *mapping,
943 + loff_t pos, unsigned len, unsigned flags,
944 + struct page **pagep, void **fsdata)
947 + struct page *pg = NULL;
948 + pgoff_t index = pos >> PAGE_CACHE_SHIFT;
949 + uint32_t offset = pos & (PAGE_CACHE_SIZE - 1);
950 + uint32_t to = offset + len;
953 + int space_held = 0;
955 + T(YAFFS_TRACE_OS, (KERN_DEBUG "start yaffs_write_begin\n"));
957 + pg = __grab_cache_page(mapping,index);
964 + space_held = yaffs_hold_space(filp);
971 + /* Update page if required */
973 + if (!Page_Uptodate(pg) && (offset || to < PAGE_CACHE_SIZE))
974 + ret = yaffs_readpage_nolock(filp, pg);
979 + /* Happy path return */
980 + T(YAFFS_TRACE_OS, (KERN_DEBUG "end yaffs_write_begin - ok\n"));
985 + T(YAFFS_TRACE_OS, (KERN_DEBUG "end yaffs_write_begin fail returning %d\n",ret));
987 + yaffs_release_space(filp);
991 + page_cache_release(pg);
998 static int yaffs_prepare_write(struct file *f, struct page *pg,
999 unsigned offset, unsigned to)
1001 @@ -674,22 +793,69 @@ static int yaffs_prepare_write(struct fi
1002 T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_prepair_write\n"));
1003 if (!Page_Uptodate(pg) && (offset || to < PAGE_CACHE_SIZE))
1004 return yaffs_readpage_nolock(f, pg);
1011 +#if (YAFFS_USE_WRITE_BEGIN_END > 0)
1012 +static int yaffs_write_end(struct file *filp, struct address_space *mapping,
1013 + loff_t pos, unsigned len, unsigned copied,
1014 + struct page *pg, void *fsdadata)
1018 + pgoff_t index = pos >> PAGE_CACHE_SHIFT;
1019 + uint32_t offset_into_page = pos & (PAGE_CACHE_SIZE -1);
1024 + addr = kva + offset_into_page;
1027 + (KERN_DEBUG "yaffs_write_end addr %x pos %x nBytes %d\n", (unsigned) addr,
1028 + (int)pos, copied));
1030 + ret = yaffs_file_write(filp, addr, copied, &pos);
1032 + if (ret != copied) {
1035 + "yaffs_write_end not same size ret %d copied %d\n",
1038 + ClearPageUptodate(pg);
1040 + SetPageUptodate(pg);
1045 + yaffs_release_space(filp);
1047 + page_cache_release(pg);
1052 static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset,
1056 - void *addr = page_address(pg) + offset;
1059 loff_t pos = (((loff_t) pg->index) << PAGE_CACHE_SHIFT) + offset;
1060 int nBytes = to - offset;
1063 unsigned spos = pos;
1064 - unsigned saddr = (unsigned)addr;
1068 + addr = kva + offset;
1070 + saddr = (unsigned) addr;
1073 (KERN_DEBUG "yaffs_commit_write addr %x pos %x nBytes %d\n", saddr,
1074 @@ -708,6 +874,8 @@ static int yaffs_commit_write(struct fil
1075 SetPageUptodate(pg);
1081 (KERN_DEBUG "yaffs_commit_write returning %d\n",
1082 nWritten == nBytes ? 0 : nWritten));
1083 @@ -715,6 +883,8 @@ static int yaffs_commit_write(struct fil
1084 return nWritten == nBytes ? 0 : nWritten;
1090 static void yaffs_FillInodeFromObject(struct inode *inode, yaffs_Object * obj)
1092 @@ -753,6 +923,8 @@ static void yaffs_FillInodeFromObject(st
1096 + inode->i_flags |= S_NOATIME;
1098 inode->i_ino = obj->objectId;
1099 inode->i_mode = obj->yst_mode;
1100 inode->i_uid = obj->yst_uid;
1101 @@ -844,7 +1016,9 @@ struct inode *yaffs_get_inode(struct sup
1103 (KERN_DEBUG "yaffs_get_inode for object %d\n", obj->objectId));
1105 - inode = iget(sb, obj->objectId);
1106 + inode = Y_IGET(sb, obj->objectId);
1110 /* NB Side effect: iget calls back to yaffs_read_inode(). */
1111 /* iget also increments the inode's i_count */
1112 @@ -910,13 +1084,55 @@ static ssize_t yaffs_file_write(struct f
1113 return nWritten == 0 ? -ENOSPC : nWritten;
1116 +/* Space holding and freeing is done to ensure we have space available for write_begin/end */
1117 +/* For now we just assume few parallel writes and check against a small number. */
1118 +/* Todo: need to do this with a counter to handle parallel reads better */
1120 +static ssize_t yaffs_hold_space(struct file *f)
1122 + yaffs_Object *obj;
1123 + yaffs_Device *dev;
1128 + obj = yaffs_DentryToObject(f->f_dentry);
1132 + yaffs_GrossLock(dev);
1134 + nFreeChunks = yaffs_GetNumberOfFreeChunks(dev);
1136 + yaffs_GrossUnlock(dev);
1138 + return (nFreeChunks > 20) ? 1 : 0;
1141 +static void yaffs_release_space(struct file *f)
1143 + yaffs_Object *obj;
1144 + yaffs_Device *dev;
1147 + obj = yaffs_DentryToObject(f->f_dentry);
1151 + yaffs_GrossLock(dev);
1154 + yaffs_GrossUnlock(dev);
1158 static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir)
1162 struct inode *inode = f->f_dentry->d_inode;
1163 unsigned long offset, curoffs;
1164 - struct list_head *i;
1165 + struct ylist_head *i;
1168 char name[YAFFS_MAX_NAME_LENGTH + 1];
1169 @@ -965,10 +1181,10 @@ static int yaffs_readdir(struct file *f,
1170 f->f_version = inode->i_version;
1173 - list_for_each(i, &obj->variant.directoryVariant.children) {
1174 + ylist_for_each(i, &obj->variant.directoryVariant.children) {
1176 if (curoffs >= offset) {
1177 - l = list_entry(i, yaffs_Object, siblings);
1178 + l = ylist_entry(i, yaffs_Object, siblings);
1180 yaffs_GetObjectName(l, name,
1181 YAFFS_MAX_NAME_LENGTH + 1);
1182 @@ -1269,7 +1485,7 @@ static int yaffs_rename(struct inode *ol
1185 target->variantType == YAFFS_OBJECT_TYPE_DIRECTORY &&
1186 - !list_empty(&target->variant.directoryVariant.children)) {
1187 + !ylist_empty(&target->variant.directoryVariant.children)) {
1189 T(YAFFS_TRACE_OS, (KERN_DEBUG "target is non-empty dir\n"));
1191 @@ -1350,25 +1566,47 @@ static int yaffs_statfs(struct super_blo
1192 buf->f_type = YAFFS_MAGIC;
1193 buf->f_bsize = sb->s_blocksize;
1194 buf->f_namelen = 255;
1195 - if (sb->s_blocksize > dev->nDataBytesPerChunk) {
1198 + if(dev->nDataBytesPerChunk & (dev->nDataBytesPerChunk - 1)){
1199 + /* Do this if chunk size is not a power of 2 */
1201 + uint64_t bytesInDev;
1202 + uint64_t bytesFree;
1204 + bytesInDev = ((uint64_t)((dev->endBlock - dev->startBlock +1))) *
1205 + ((uint64_t)(dev->nChunksPerBlock * dev->nDataBytesPerChunk));
1207 + do_div(bytesInDev,sb->s_blocksize); /* bytesInDev becomes the number of blocks */
1208 + buf->f_blocks = bytesInDev;
1210 + bytesFree = ((uint64_t)(yaffs_GetNumberOfFreeChunks(dev))) *
1211 + ((uint64_t)(dev->nDataBytesPerChunk));
1213 + do_div(bytesFree,sb->s_blocksize);
1215 + buf->f_bfree = bytesFree;
1217 + } else if (sb->s_blocksize > dev->nDataBytesPerChunk) {
1220 - (dev->endBlock - dev->startBlock +
1221 - 1) * dev->nChunksPerBlock / (sb->s_blocksize /
1222 - dev->nDataBytesPerChunk);
1224 - yaffs_GetNumberOfFreeChunks(dev) / (sb->s_blocksize /
1225 - dev->nDataBytesPerChunk);
1226 + (dev->endBlock - dev->startBlock + 1) *
1227 + dev->nChunksPerBlock /
1228 + (sb->s_blocksize / dev->nDataBytesPerChunk);
1230 + yaffs_GetNumberOfFreeChunks(dev) /
1231 + (sb->s_blocksize / dev->nDataBytesPerChunk);
1235 - (dev->endBlock - dev->startBlock +
1236 - 1) * dev->nChunksPerBlock * (dev->nDataBytesPerChunk /
1239 - yaffs_GetNumberOfFreeChunks(dev) * (dev->nDataBytesPerChunk /
1242 + (dev->endBlock - dev->startBlock + 1) *
1243 + dev->nChunksPerBlock *
1244 + (dev->nDataBytesPerChunk / sb->s_blocksize);
1247 + yaffs_GetNumberOfFreeChunks(dev) *
1248 + (dev->nDataBytesPerChunk / sb->s_blocksize);
1254 buf->f_bavail = buf->f_bfree;
1255 @@ -1378,7 +1616,6 @@ static int yaffs_statfs(struct super_blo
1260 static int yaffs_do_sync_fs(struct super_block *sb)
1263 @@ -1388,8 +1625,10 @@ static int yaffs_do_sync_fs(struct super
1265 yaffs_GrossLock(dev);
1269 + yaffs_FlushEntireDeviceCache(dev);
1270 yaffs_CheckpointSave(dev);
1273 yaffs_GrossUnlock(dev);
1275 @@ -1397,7 +1636,7 @@ static int yaffs_do_sync_fs(struct super
1282 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1283 static void yaffs_write_super(struct super_block *sb)
1284 @@ -1407,8 +1646,10 @@ static int yaffs_write_super(struct supe
1287 T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_write_super\n"));
1288 + if (yaffs_auto_checkpoint >= 2)
1289 + yaffs_do_sync_fs(sb);
1290 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18))
1291 - return 0; /* yaffs_do_sync_fs(sb);*/
1296 @@ -1422,10 +1663,48 @@ static int yaffs_sync_fs(struct super_bl
1298 T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_sync_fs\n"));
1300 - return 0; /* yaffs_do_sync_fs(sb);*/
1301 + if (yaffs_auto_checkpoint >= 1)
1302 + yaffs_do_sync_fs(sb);
1308 +#ifdef YAFFS_USE_OWN_IGET
1310 +static struct inode * yaffs_iget(struct super_block *sb, unsigned long ino)
1312 + struct inode *inode;
1313 + yaffs_Object *obj;
1314 + yaffs_Device *dev = yaffs_SuperToDevice(sb);
1317 + (KERN_DEBUG "yaffs_iget for %lu\n", ino));
1319 + inode = iget_locked(sb, ino);
1321 + return ERR_PTR(-ENOMEM);
1322 + if (!(inode->i_state & I_NEW))
1325 + /* NB This is called as a side effect of other functions, but
1326 + * we had to release the lock to prevent deadlocks, so
1327 + * need to lock again.
1330 + yaffs_GrossLock(dev);
1332 + obj = yaffs_FindObjectByNumber(dev, inode->i_ino);
1334 + yaffs_FillInodeFromObject(inode, obj);
1336 + yaffs_GrossUnlock(dev);
1338 + unlock_new_inode(inode);
1344 static void yaffs_read_inode(struct inode *inode)
1346 @@ -1449,7 +1728,9 @@ static void yaffs_read_inode(struct inod
1347 yaffs_GrossUnlock(dev);
1350 -static LIST_HEAD(yaffs_dev_list);
1353 +static YLIST_HEAD(yaffs_dev_list);
1356 static int yaffs_remount_fs(struct super_block *sb, int *flags, char *data)
1357 @@ -1503,7 +1784,7 @@ static void yaffs_put_super(struct super
1358 yaffs_GrossUnlock(dev);
1360 /* we assume this is protected by lock_kernel() in mount/umount */
1361 - list_del(&dev->devList);
1362 + ylist_del(&dev->devList);
1364 if(dev->spareBuffer){
1365 YFREE(dev->spareBuffer);
1366 @@ -1532,8 +1813,8 @@ static void yaffs_MarkSuperBlockDirty(vo
1367 struct super_block *sb = (struct super_block *)vsb;
1369 T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_MarkSuperBlockDirty() sb = %p\n",sb));
1377 @@ -1602,6 +1883,7 @@ static struct super_block *yaffs_interna
1379 sb->s_magic = YAFFS_MAGIC;
1380 sb->s_op = &yaffs_super_ops;
1381 + sb->s_flags |= MS_NOATIME;
1384 printk(KERN_INFO "yaffs: sb is NULL\n");
1385 @@ -1678,22 +1960,15 @@ static struct super_block *yaffs_interna
1386 #ifdef CONFIG_YAFFS_AUTO_YAFFS2
1388 if (yaffsVersion == 1 &&
1389 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1390 - mtd->writesize >= 2048) {
1392 - mtd->oobblock >= 2048) {
1394 + WRITE_SIZE(mtd) >= 2048) {
1395 T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs2\n"));
1399 /* Added NCB 26/5/2006 for completeness */
1400 - if (yaffsVersion == 2 &&
1401 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1402 - mtd->writesize == 512) {
1404 - mtd->oobblock == 512) {
1406 + if (yaffsVersion == 2 &&
1407 + !options.inband_tags &&
1408 + WRITE_SIZE(mtd) == 512){
1409 T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs1\n"));
1412 @@ -1719,12 +1994,9 @@ static struct super_block *yaffs_interna
1416 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1417 - if (mtd->writesize < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
1419 - if (mtd->oobblock < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
1421 - mtd->oobsize < YAFFS_MIN_YAFFS2_SPARE_SIZE) {
1422 + if ((WRITE_SIZE(mtd) < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
1423 + mtd->oobsize < YAFFS_MIN_YAFFS2_SPARE_SIZE) &&
1424 + !options.inband_tags) {
1425 T(YAFFS_TRACE_ALWAYS,
1426 ("yaffs: MTD device does not have the "
1427 "right page sizes\n"));
1428 @@ -1784,9 +2056,10 @@ static struct super_block *yaffs_interna
1429 dev->startBlock = 0;
1430 dev->endBlock = nBlocks - 1;
1431 dev->nChunksPerBlock = YAFFS_CHUNKS_PER_BLOCK;
1432 - dev->nDataBytesPerChunk = YAFFS_BYTES_PER_CHUNK;
1433 + dev->totalBytesPerChunk = YAFFS_BYTES_PER_CHUNK;
1434 dev->nReservedBlocks = 5;
1435 dev->nShortOpCaches = (options.no_cache) ? 0 : 10;
1436 + dev->inbandTags = options.inband_tags;
1438 /* ... and the functions. */
1439 if (yaffsVersion == 2) {
1440 @@ -1799,15 +2072,14 @@ static struct super_block *yaffs_interna
1441 dev->spareBuffer = YMALLOC(mtd->oobsize);
1443 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1444 - dev->nDataBytesPerChunk = mtd->writesize;
1445 + dev->totalBytesPerChunk = mtd->writesize;
1446 dev->nChunksPerBlock = mtd->erasesize / mtd->writesize;
1448 - dev->nDataBytesPerChunk = mtd->oobblock;
1449 + dev->totalBytesPerChunk = mtd->oobblock;
1450 dev->nChunksPerBlock = mtd->erasesize / mtd->oobblock;
1452 nBlocks = mtd->size / mtd->erasesize;
1454 - dev->nCheckpointReservedBlocks = CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS;
1455 dev->startBlock = 0;
1456 dev->endBlock = nBlocks - 1;
1458 @@ -1847,7 +2119,7 @@ static struct super_block *yaffs_interna
1459 dev->skipCheckpointWrite = options.skip_checkpoint_write;
1461 /* we assume this is protected by lock_kernel() in mount/umount */
1462 - list_add_tail(&dev->devList, &yaffs_dev_list);
1463 + ylist_add_tail(&dev->devList, &yaffs_dev_list);
1465 init_MUTEX(&dev->grossLock);
1467 @@ -1884,6 +2156,9 @@ static struct super_block *yaffs_interna
1471 + sb->s_dirt = !dev->isCheckpointed;
1472 + T(YAFFS_TRACE_ALWAYS,
1473 + ("yaffs_read_super: isCheckpointed %d\n", dev->isCheckpointed));
1475 T(YAFFS_TRACE_OS, ("yaffs_read_super: done\n"));
1477 @@ -1990,12 +2265,12 @@ static char *yaffs_dump_dev(char *buf, y
1479 buf += sprintf(buf, "startBlock......... %d\n", dev->startBlock);
1480 buf += sprintf(buf, "endBlock........... %d\n", dev->endBlock);
1481 + buf += sprintf(buf, "totalBytesPerChunk. %d\n", dev->totalBytesPerChunk);
1482 buf += sprintf(buf, "nDataBytesPerChunk. %d\n", dev->nDataBytesPerChunk);
1483 buf += sprintf(buf, "chunkGroupBits..... %d\n", dev->chunkGroupBits);
1484 buf += sprintf(buf, "chunkGroupSize..... %d\n", dev->chunkGroupSize);
1485 buf += sprintf(buf, "nErasedBlocks...... %d\n", dev->nErasedBlocks);
1486 buf += sprintf(buf, "nReservedBlocks.... %d\n", dev->nReservedBlocks);
1487 - buf += sprintf(buf, "nCheckptResBlocks.. %d\n", dev->nCheckpointReservedBlocks);
1488 buf += sprintf(buf, "blocksInCheckpoint. %d\n", dev->blocksInCheckpoint);
1489 buf += sprintf(buf, "nTnodesCreated..... %d\n", dev->nTnodesCreated);
1490 buf += sprintf(buf, "nFreeTnodes........ %d\n", dev->nFreeTnodes);
1491 @@ -2006,10 +2281,8 @@ static char *yaffs_dump_dev(char *buf, y
1492 buf += sprintf(buf, "nPageReads......... %d\n", dev->nPageReads);
1493 buf += sprintf(buf, "nBlockErasures..... %d\n", dev->nBlockErasures);
1494 buf += sprintf(buf, "nGCCopies.......... %d\n", dev->nGCCopies);
1496 - sprintf(buf, "garbageCollections. %d\n", dev->garbageCollections);
1498 - sprintf(buf, "passiveGCs......... %d\n",
1499 + buf += sprintf(buf, "garbageCollections. %d\n", dev->garbageCollections);
1500 + buf += sprintf(buf, "passiveGCs......... %d\n",
1501 dev->passiveGarbageCollections);
1502 buf += sprintf(buf, "nRetriedWrites..... %d\n", dev->nRetriedWrites);
1503 buf += sprintf(buf, "nShortOpCaches..... %d\n", dev->nShortOpCaches);
1504 @@ -2025,6 +2298,7 @@ static char *yaffs_dump_dev(char *buf, y
1505 sprintf(buf, "nBackgroudDeletions %d\n", dev->nBackgroundDeletions);
1506 buf += sprintf(buf, "useNANDECC......... %d\n", dev->useNANDECC);
1507 buf += sprintf(buf, "isYaffs2........... %d\n", dev->isYaffs2);
1508 + buf += sprintf(buf, "inbandTags......... %d\n", dev->inbandTags);
1512 @@ -2033,7 +2307,7 @@ static int yaffs_proc_read(char *page,
1514 off_t offset, int count, int *eof, void *data)
1516 - struct list_head *item;
1517 + struct ylist_head *item;
1521 @@ -2057,8 +2331,8 @@ static int yaffs_proc_read(char *page,
1524 /* Locate and print the Nth entry. Order N-squared but N is small. */
1525 - list_for_each(item, &yaffs_dev_list) {
1526 - yaffs_Device *dev = list_entry(item, yaffs_Device, devList);
1527 + ylist_for_each(item, &yaffs_dev_list) {
1528 + yaffs_Device *dev = ylist_entry(item, yaffs_Device, devList);
1532 @@ -2231,7 +2505,7 @@ static int __init init_yaffs_fs(void)
1533 /* Install the proc_fs entry */
1534 my_proc_entry = create_proc_entry("yaffs",
1539 if (my_proc_entry) {
1540 my_proc_entry->write_proc = yaffs_proc_write;
1541 @@ -2277,7 +2551,7 @@ static void __exit exit_yaffs_fs(void)
1542 T(YAFFS_TRACE_ALWAYS, ("yaffs " __DATE__ " " __TIME__
1545 - remove_proc_entry("yaffs", &proc_root);
1546 + remove_proc_entry("yaffs", YPROC_ROOT);
1548 fsinst = fs_to_install;
1551 +++ b/fs/yaffs2/yaffs_getblockinfo.h
1554 + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
1556 + * Copyright (C) 2002-2007 Aleph One Ltd.
1557 + * for Toby Churchill Ltd and Brightstar Engineering
1559 + * Created by Charles Manning <charles@aleph1.co.uk>
1561 + * This program is free software; you can redistribute it and/or modify
1562 + * it under the terms of the GNU Lesser General Public License version 2.1 as
1563 + * published by the Free Software Foundation.
1565 + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
1568 +#ifndef __YAFFS_GETBLOCKINFO_H__
1569 +#define __YAFFS_GETBLOCKINFO_H__
1571 +#include "yaffs_guts.h"
1573 +/* Function to manipulate block info */
1574 +static Y_INLINE yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device * dev, int blk)
1576 + if (blk < dev->internalStartBlock || blk > dev->internalEndBlock) {
1577 + T(YAFFS_TRACE_ERROR,
1579 + ("**>> yaffs: getBlockInfo block %d is not valid" TENDSTR),
1583 + return &dev->blockInfo[blk - dev->internalStartBlock];
1587 --- a/fs/yaffs2/yaffs_nand.c
1588 +++ b/fs/yaffs2/yaffs_nand.c
1592 const char *yaffs_nand_c_version =
1593 - "$Id: yaffs_nand.c,v 1.7 2007-02-14 01:09:06 wookey Exp $";
1594 + "$Id: yaffs_nand.c,v 1.9 2008-05-05 07:58:58 charles Exp $";
1596 #include "yaffs_nand.h"
1597 #include "yaffs_tagscompat.h"
1598 #include "yaffs_tagsvalidity.h"
1600 +#include "yaffs_getblockinfo.h"
1602 int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,
1604 @@ -98,7 +99,7 @@ int yaffs_MarkBlockBad(yaffs_Device * de
1605 int yaffs_QueryInitialBlockState(yaffs_Device * dev,
1607 yaffs_BlockState * state,
1608 - unsigned *sequenceNumber)
1609 + __u32 *sequenceNumber)
1611 blockNo -= dev->blockOffset;
1613 --- a/fs/yaffs2/yaffs_guts.c
1614 +++ b/fs/yaffs2/yaffs_guts.c
1616 * published by the Free Software Foundation.
1620 const char *yaffs_guts_c_version =
1621 - "$Id: yaffs_guts.c,v 1.49 2007-05-15 20:07:40 charles Exp $";
1622 + "$Id: yaffs_guts.c,v 1.76 2009-01-23 06:36:49 charles Exp $";
1624 #include "yportenv.h"
1626 #include "yaffsinterface.h"
1627 #include "yaffs_guts.h"
1628 #include "yaffs_tagsvalidity.h"
1629 +#include "yaffs_getblockinfo.h"
1631 #include "yaffs_tagscompat.h"
1632 #ifndef CONFIG_YAFFS_USE_OWN_SORT
1633 @@ -32,11 +34,6 @@ const char *yaffs_guts_c_version =
1634 #include "yaffs_packedtags2.h"
1637 -#ifdef CONFIG_YAFFS_WINCE
1638 -void yfsd_LockYAFFS(BOOL fsLockOnly);
1639 -void yfsd_UnlockYAFFS(BOOL fsLockOnly);
1642 #define YAFFS_PASSIVE_GC_CHUNKS 2
1644 #include "yaffs_ecc.h"
1645 @@ -78,9 +75,6 @@ static int yaffs_DoGenericObjectDeletion
1647 static yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device * dev, int blockNo);
1649 -static __u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo);
1650 -static void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer,
1653 static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,
1655 @@ -99,6 +93,7 @@ static void yaffs_VerifyFreeChunks(yaffs
1657 static void yaffs_CheckObjectDetailsLoaded(yaffs_Object *in);
1659 +static void yaffs_VerifyDirectory(yaffs_Object *directory);
1660 #ifdef YAFFS_PARANOID
1661 static int yaffs_CheckFileSanity(yaffs_Object * in);
1663 @@ -121,95 +116,109 @@ static yaffs_Tnode *yaffs_FindLevel0Tnod
1665 /* Function to calculate chunk and offset */
1667 -static void yaffs_AddrToChunk(yaffs_Device *dev, loff_t addr, __u32 *chunk, __u32 *offset)
1668 +static void yaffs_AddrToChunk(yaffs_Device *dev, loff_t addr, int *chunkOut, __u32 *offsetOut)
1670 - if(dev->chunkShift){
1671 - /* Easy-peasy power of 2 case */
1672 - *chunk = (__u32)(addr >> dev->chunkShift);
1673 - *offset = (__u32)(addr & dev->chunkMask);
1675 - else if(dev->crumbsPerChunk)
1679 + chunk = (__u32)(addr >> dev->chunkShift);
1681 + if(dev->chunkDiv == 1)
1683 - /* Case where we're using "crumbs" */
1684 - *offset = (__u32)(addr & dev->crumbMask);
1685 - addr >>= dev->crumbShift;
1686 - *chunk = ((__u32)addr)/dev->crumbsPerChunk;
1687 - *offset += ((addr - (*chunk * dev->crumbsPerChunk)) << dev->crumbShift);
1688 + /* easy power of 2 case */
1689 + offset = (__u32)(addr & dev->chunkMask);
1694 + /* Non power-of-2 case */
1698 + chunk /= dev->chunkDiv;
1700 + chunkBase = ((loff_t)chunk) * dev->nDataBytesPerChunk;
1701 + offset = (__u32)(addr - chunkBase);
1704 + *chunkOut = chunk;
1705 + *offsetOut = offset;
1708 -/* Function to return the number of shifts for a power of 2 greater than or equal
1709 +/* Function to return the number of shifts for a power of 2 greater than or equal
1710 * to the given number
1711 * Note we don't try to cater for all possible numbers and this does not have to
1712 * be hellishly efficient.
1716 static __u32 ShiftsGE(__u32 x)
1722 nShifts = extraBits = 0;
1726 if(x & 1) extraBits++;
1739 /* Function to return the number of shifts to get a 1 in bit 0
1742 -static __u32 ShiftDiv(__u32 x)
1744 +static __u32 Shifts(__u32 x)
1768 * Temporary buffer manipulations.
1771 -static int yaffs_InitialiseTempBuffers(yaffs_Device *dev)
1772 +static int yaffs_InitialiseTempBuffers(yaffs_Device *dev)
1775 __u8 *buf = (__u8 *)1;
1778 memset(dev->tempBuffer,0,sizeof(dev->tempBuffer));
1781 for (i = 0; buf && i < YAFFS_N_TEMP_BUFFERS; i++) {
1782 dev->tempBuffer[i].line = 0; /* not in use */
1783 dev->tempBuffer[i].buffer = buf =
1784 - YMALLOC_DMA(dev->nDataBytesPerChunk);
1785 + YMALLOC_DMA(dev->totalBytesPerChunk);
1789 return buf ? YAFFS_OK : YAFFS_FAIL;
1794 -static __u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo)
1795 +__u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo)
1800 + if(dev->tempInUse > dev->maxTemp)
1801 + dev->maxTemp = dev->tempInUse;
1803 for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
1804 if (dev->tempBuffer[i].line == 0) {
1805 dev->tempBuffer[i].line = lineNo;
1806 @@ -242,10 +251,13 @@ static __u8 *yaffs_GetTempBuffer(yaffs_D
1810 -static void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer,
1811 +void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer,
1818 for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
1819 if (dev->tempBuffer[i].buffer == buffer) {
1820 dev->tempBuffer[i].line = 0;
1821 @@ -337,7 +349,7 @@ static Y_INLINE void yaffs_ClearChunkBit
1822 static Y_INLINE void yaffs_SetChunkBit(yaffs_Device * dev, int blk, int chunk)
1824 __u8 *blkBits = yaffs_BlockBits(dev, blk);
1827 yaffs_VerifyChunkBitId(dev,blk,chunk);
1829 blkBits[chunk / 8] |= (1 << (chunk & 7));
1830 @@ -375,16 +387,16 @@ static int yaffs_CountChunkBits(yaffs_De
1847 static int yaffs_SkipVerification(yaffs_Device *dev)
1849 return !(yaffs_traceMask & (YAFFS_TRACE_VERIFY | YAFFS_TRACE_VERIFY_FULL));
1850 @@ -417,14 +429,14 @@ static void yaffs_VerifyBlock(yaffs_Devi
1856 if(yaffs_SkipVerification(dev))
1860 /* Report illegal runtime states */
1861 - if(bi->blockState <0 || bi->blockState >= YAFFS_NUMBER_OF_BLOCK_STATES)
1862 + if(bi->blockState >= YAFFS_NUMBER_OF_BLOCK_STATES)
1863 T(YAFFS_TRACE_VERIFY,(TSTR("Block %d has undefined state %d"TENDSTR),n,bi->blockState));
1866 switch(bi->blockState){
1867 case YAFFS_BLOCK_STATE_UNKNOWN:
1868 case YAFFS_BLOCK_STATE_SCANNING:
1869 @@ -432,43 +444,44 @@ static void yaffs_VerifyBlock(yaffs_Devi
1870 T(YAFFS_TRACE_VERIFY,(TSTR("Block %d has bad run-state %s"TENDSTR),
1871 n,blockStateName[bi->blockState]));
1875 /* Check pages in use and soft deletions are legal */
1878 actuallyUsed = bi->pagesInUse - bi->softDeletions;
1881 if(bi->pagesInUse < 0 || bi->pagesInUse > dev->nChunksPerBlock ||
1882 bi->softDeletions < 0 || bi->softDeletions > dev->nChunksPerBlock ||
1883 actuallyUsed < 0 || actuallyUsed > dev->nChunksPerBlock)
1884 T(YAFFS_TRACE_VERIFY,(TSTR("Block %d has illegal values pagesInUsed %d softDeletions %d"TENDSTR),
1885 n,bi->pagesInUse,bi->softDeletions));
1890 /* Check chunk bitmap legal */
1891 inUse = yaffs_CountChunkBits(dev,n);
1892 if(inUse != bi->pagesInUse)
1893 T(YAFFS_TRACE_VERIFY,(TSTR("Block %d has inconsistent values pagesInUse %d counted chunk bits %d"TENDSTR),
1894 n,bi->pagesInUse,inUse));
1897 /* Check that the sequence number is valid.
1898 - * Ten million is legal, but is very unlikely
1899 + * Ten million is legal, but is very unlikely
1901 - if(dev->isYaffs2 &&
1902 + if(dev->isYaffs2 &&
1903 (bi->blockState == YAFFS_BLOCK_STATE_ALLOCATING || bi->blockState == YAFFS_BLOCK_STATE_FULL) &&
1904 (bi->sequenceNumber < YAFFS_LOWEST_SEQUENCE_NUMBER || bi->sequenceNumber > 10000000 ))
1905 T(YAFFS_TRACE_VERIFY,(TSTR("Block %d has suspect sequence number of %d"TENDSTR),
1906 n,bi->sequenceNumber));
1911 static void yaffs_VerifyCollectedBlock(yaffs_Device *dev,yaffs_BlockInfo *bi,int n)
1913 yaffs_VerifyBlock(dev,bi,n);
1916 /* After collection the block should be in the erased state */
1917 - /* TODO: This will need to change if we do partial gc */
1919 - if(bi->blockState != YAFFS_BLOCK_STATE_EMPTY){
1920 + /* This will need to change if we do partial gc */
1922 + if(bi->blockState != YAFFS_BLOCK_STATE_COLLECTING &&
1923 + bi->blockState != YAFFS_BLOCK_STATE_EMPTY){
1924 T(YAFFS_TRACE_ERROR,(TSTR("Block %d is in state %d after gc, should be erased"TENDSTR),
1927 @@ -479,28 +492,28 @@ static void yaffs_VerifyBlocks(yaffs_Dev
1929 int nBlocksPerState[YAFFS_NUMBER_OF_BLOCK_STATES];
1930 int nIllegalBlockStates = 0;
1934 if(yaffs_SkipVerification(dev))
1937 memset(nBlocksPerState,0,sizeof(nBlocksPerState));
1941 for(i = dev->internalStartBlock; i <= dev->internalEndBlock; i++){
1942 yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,i);
1943 yaffs_VerifyBlock(dev,bi,i);
1945 - if(bi->blockState >=0 && bi->blockState < YAFFS_NUMBER_OF_BLOCK_STATES)
1946 + if(bi->blockState < YAFFS_NUMBER_OF_BLOCK_STATES)
1947 nBlocksPerState[bi->blockState]++;
1949 nIllegalBlockStates++;
1955 T(YAFFS_TRACE_VERIFY,(TSTR(""TENDSTR)));
1956 T(YAFFS_TRACE_VERIFY,(TSTR("Block summary"TENDSTR)));
1959 T(YAFFS_TRACE_VERIFY,(TSTR("%d blocks have illegal states"TENDSTR),nIllegalBlockStates));
1960 if(nBlocksPerState[YAFFS_BLOCK_STATE_ALLOCATING] > 1)
1961 T(YAFFS_TRACE_VERIFY,(TSTR("Too many allocating blocks"TENDSTR)));
1962 @@ -509,17 +522,17 @@ static void yaffs_VerifyBlocks(yaffs_Dev
1963 T(YAFFS_TRACE_VERIFY,
1964 (TSTR("%s %d blocks"TENDSTR),
1965 blockStateName[i],nBlocksPerState[i]));
1968 if(dev->blocksInCheckpoint != nBlocksPerState[YAFFS_BLOCK_STATE_CHECKPOINT])
1969 T(YAFFS_TRACE_VERIFY,
1970 (TSTR("Checkpoint block count wrong dev %d count %d"TENDSTR),
1971 dev->blocksInCheckpoint, nBlocksPerState[YAFFS_BLOCK_STATE_CHECKPOINT]));
1974 if(dev->nErasedBlocks != nBlocksPerState[YAFFS_BLOCK_STATE_EMPTY])
1975 T(YAFFS_TRACE_VERIFY,
1976 (TSTR("Erased block count wrong dev %d count %d"TENDSTR),
1977 dev->nErasedBlocks, nBlocksPerState[YAFFS_BLOCK_STATE_EMPTY]));
1980 if(nBlocksPerState[YAFFS_BLOCK_STATE_COLLECTING] > 1)
1981 T(YAFFS_TRACE_VERIFY,
1982 (TSTR("Too many collecting blocks %d (max is 1)"TENDSTR),
1983 @@ -535,16 +548,16 @@ static void yaffs_VerifyBlocks(yaffs_Dev
1985 static void yaffs_VerifyObjectHeader(yaffs_Object *obj, yaffs_ObjectHeader *oh, yaffs_ExtendedTags *tags, int parentCheck)
1987 - if(yaffs_SkipVerification(obj->myDev))
1988 + if(obj && yaffs_SkipVerification(obj->myDev))
1992 if(!(tags && obj && oh)){
1993 T(YAFFS_TRACE_VERIFY,
1994 (TSTR("Verifying object header tags %x obj %x oh %x"TENDSTR),
1995 (__u32)tags,(__u32)obj,(__u32)oh));
2000 if(oh->type <= YAFFS_OBJECT_TYPE_UNKNOWN ||
2001 oh->type > YAFFS_OBJECT_TYPE_MAX)
2002 T(YAFFS_TRACE_VERIFY,
2003 @@ -559,25 +572,25 @@ static void yaffs_VerifyObjectHeader(yaf
2006 * Check that the object's parent ids match if parentCheck requested.
2009 * Tests do not apply to the root object.
2013 if(parentCheck && tags->objectId > 1 && !obj->parent)
2014 T(YAFFS_TRACE_VERIFY,
2015 (TSTR("Obj %d header mismatch parentId %d obj->parent is NULL"TENDSTR),
2016 tags->objectId, oh->parentObjectId));
2021 if(parentCheck && obj->parent &&
2022 - oh->parentObjectId != obj->parent->objectId &&
2023 + oh->parentObjectId != obj->parent->objectId &&
2024 (oh->parentObjectId != YAFFS_OBJECTID_UNLINKED ||
2025 obj->parent->objectId != YAFFS_OBJECTID_DELETED))
2026 T(YAFFS_TRACE_VERIFY,
2027 (TSTR("Obj %d header mismatch parentId %d parentObjectId %d"TENDSTR),
2028 tags->objectId, oh->parentObjectId, obj->parent->objectId));
2033 if(tags->objectId > 1 && oh->name[0] == 0) /* Null name */
2034 T(YAFFS_TRACE_VERIFY,
2035 (TSTR("Obj %d header name is NULL"TENDSTR),
2036 @@ -597,7 +610,6 @@ static int yaffs_VerifyTnodeWorker(yaffs
2038 yaffs_Device *dev = obj->myDev;
2040 - int nTnodeBytes = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
2044 @@ -611,15 +623,14 @@ static int yaffs_VerifyTnodeWorker(yaffs
2047 } else if (level == 0) {
2049 yaffs_ExtendedTags tags;
2050 __u32 objectId = obj->objectId;
2053 chunkOffset <<= YAFFS_TNODES_LEVEL0_BITS;
2056 for(i = 0; i < YAFFS_NTNODES_LEVEL0; i++){
2057 __u32 theChunk = yaffs_GetChunkGroupBase(dev,tn,i);
2061 /* T(~0,(TSTR("verifying (%d:%d) %d"TENDSTR),tags.objectId,tags.chunkId,theChunk)); */
2062 yaffs_ReadChunkWithTagsFromNAND(dev,theChunk,NULL, &tags);
2063 @@ -646,18 +657,20 @@ static void yaffs_VerifyFile(yaffs_Objec
2069 yaffs_ExtendedTags tags;
2073 - if(obj && yaffs_SkipVerification(obj->myDev))
2078 + if(yaffs_SkipVerification(obj->myDev))
2082 objectId = obj->objectId;
2085 /* Check file size is consistent with tnode depth */
2086 lastChunk = obj->variant.fileVariant.fileSize / dev->nDataBytesPerChunk + 1;
2087 x = lastChunk >> YAFFS_TNODES_LEVEL0_BITS;
2088 @@ -666,23 +679,23 @@ static void yaffs_VerifyFile(yaffs_Objec
2089 x >>= YAFFS_TNODES_INTERNAL_BITS;
2094 actualTallness = obj->variant.fileVariant.topLevel;
2097 if(requiredTallness > actualTallness )
2098 T(YAFFS_TRACE_VERIFY,
2099 (TSTR("Obj %d had tnode tallness %d, needs to be %d"TENDSTR),
2100 obj->objectId,actualTallness, requiredTallness));
2103 - /* Check that the chunks in the tnode tree are all correct.
2106 + /* Check that the chunks in the tnode tree are all correct.
2107 * We do this by scanning through the tnode tree and
2108 * checking the tags for every chunk match.
2111 if(yaffs_SkipNANDVerification(dev))
2115 for(i = 1; i <= lastChunk; i++){
2116 tn = yaffs_FindLevel0Tnode(dev, &obj->variant.fileVariant,i);
2118 @@ -703,18 +716,12 @@ static void yaffs_VerifyFile(yaffs_Objec
2122 -static void yaffs_VerifyDirectory(yaffs_Object *obj)
2124 - if(obj && yaffs_SkipVerification(obj->myDev))
2129 static void yaffs_VerifyHardLink(yaffs_Object *obj)
2131 if(obj && yaffs_SkipVerification(obj->myDev))
2135 /* Verify sane equivalent object */
2138 @@ -722,7 +729,7 @@ static void yaffs_VerifySymlink(yaffs_Ob
2140 if(obj && yaffs_SkipVerification(obj->myDev))
2144 /* Verify symlink string */
2147 @@ -735,69 +742,77 @@ static void yaffs_VerifySpecial(yaffs_Ob
2148 static void yaffs_VerifyObject(yaffs_Object *obj)
2158 - __u32 chunkIsLive;
2160 + __u32 chunkInRange;
2161 + __u32 chunkShouldNotBeDeleted;
2168 + if(obj->beingCreated)
2174 if(yaffs_SkipVerification(dev))
2178 /* Check sane object header chunk */
2180 chunkMin = dev->internalStartBlock * dev->nChunksPerBlock;
2181 chunkMax = (dev->internalEndBlock+1) * dev->nChunksPerBlock - 1;
2183 - chunkIdOk = (obj->chunkId >= chunkMin && obj->chunkId <= chunkMax);
2184 - chunkIsLive = chunkIdOk &&
2185 + chunkInRange = (((unsigned)(obj->hdrChunk)) >= chunkMin && ((unsigned)(obj->hdrChunk)) <= chunkMax);
2186 + chunkIdOk = chunkInRange || obj->hdrChunk == 0;
2187 + chunkValid = chunkInRange &&
2188 yaffs_CheckChunkBit(dev,
2189 - obj->chunkId / dev->nChunksPerBlock,
2190 - obj->chunkId % dev->nChunksPerBlock);
2191 + obj->hdrChunk / dev->nChunksPerBlock,
2192 + obj->hdrChunk % dev->nChunksPerBlock);
2193 + chunkShouldNotBeDeleted = chunkInRange && !chunkValid;
2196 - (!chunkIdOk || !chunkIsLive)) {
2197 + (!chunkIdOk || chunkShouldNotBeDeleted)) {
2198 T(YAFFS_TRACE_VERIFY,
2199 (TSTR("Obj %d has chunkId %d %s %s"TENDSTR),
2200 - obj->objectId,obj->chunkId,
2201 + obj->objectId,obj->hdrChunk,
2202 chunkIdOk ? "" : ",out of range",
2203 - chunkIsLive || !chunkIdOk ? "" : ",marked as deleted"));
2204 + chunkShouldNotBeDeleted ? ",marked as deleted" : ""));
2207 - if(chunkIdOk && chunkIsLive &&!yaffs_SkipNANDVerification(dev)) {
2209 + if(chunkValid &&!yaffs_SkipNANDVerification(dev)) {
2210 yaffs_ExtendedTags tags;
2211 yaffs_ObjectHeader *oh;
2212 __u8 *buffer = yaffs_GetTempBuffer(dev,__LINE__);
2215 oh = (yaffs_ObjectHeader *)buffer;
2217 - yaffs_ReadChunkWithTagsFromNAND(dev, obj->chunkId,buffer, &tags);
2218 + yaffs_ReadChunkWithTagsFromNAND(dev, obj->hdrChunk,buffer, &tags);
2220 yaffs_VerifyObjectHeader(obj,oh,&tags,1);
2223 yaffs_ReleaseTempBuffer(dev,buffer,__LINE__);
2227 /* Verify it has a parent */
2228 if(obj && !obj->fake &&
2229 (!obj->parent || obj->parent->myDev != dev)){
2230 T(YAFFS_TRACE_VERIFY,
2231 (TSTR("Obj %d has parent pointer %p which does not look like an object"TENDSTR),
2232 - obj->objectId,obj->parent));
2233 + obj->objectId,obj->parent));
2237 /* Verify parent is a directory */
2238 if(obj->parent && obj->parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY){
2239 T(YAFFS_TRACE_VERIFY,
2240 (TSTR("Obj %d's parent is not a directory (type %d)"TENDSTR),
2241 - obj->objectId,obj->parent->variantType));
2242 + obj->objectId,obj->parent->variantType));
2246 switch(obj->variantType){
2247 case YAFFS_OBJECT_TYPE_FILE:
2248 yaffs_VerifyFile(obj);
2249 @@ -818,31 +833,31 @@ static void yaffs_VerifyObject(yaffs_Obj
2251 T(YAFFS_TRACE_VERIFY,
2252 (TSTR("Obj %d has illegaltype %d"TENDSTR),
2253 - obj->objectId,obj->variantType));
2254 + obj->objectId,obj->variantType));
2263 static void yaffs_VerifyObjects(yaffs_Device *dev)
2265 - yaffs_Object *obj;
2267 - struct list_head *lh;
2269 - if(yaffs_SkipVerification(dev))
2272 - /* Iterate through the objects in each hash entry */
2274 - for(i = 0; i < YAFFS_NOBJECT_BUCKETS; i++){
2275 - list_for_each(lh, &dev->objectBucket[i].list) {
2277 - obj = list_entry(lh, yaffs_Object, hashLink);
2278 - yaffs_VerifyObject(obj);
2281 + yaffs_Object *obj;
2283 + struct ylist_head *lh;
2285 + if(yaffs_SkipVerification(dev))
2288 + /* Iterate through the objects in each hash entry */
2290 + for(i = 0; i < YAFFS_NOBJECT_BUCKETS; i++){
2291 + ylist_for_each(lh, &dev->objectBucket[i].list) {
2293 + obj = ylist_entry(lh, yaffs_Object, hashLink);
2294 + yaffs_VerifyObject(obj);
2300 @@ -851,7 +866,7 @@ static void yaffs_VerifyObjects(yaffs_De
2302 * Simple hash function. Needs to have a reasonable spread
2306 static Y_INLINE int yaffs_HashFunction(int n)
2309 @@ -859,9 +874,10 @@ static Y_INLINE int yaffs_HashFunction(i
2313 - * Access functions to useful fake objects
2314 + * Access functions to useful fake objects.
2315 + * Note that root might have a presence in NAND if permissions are set.
2319 yaffs_Object *yaffs_Root(yaffs_Device * dev)
2321 return dev->rootDir;
2322 @@ -876,7 +892,7 @@ yaffs_Object *yaffs_LostNFound(yaffs_Dev
2324 * Erased NAND checking functions
2328 int yaffs_CheckFF(__u8 * buffer, int nBytes)
2330 /* Horrible, slow implementation */
2331 @@ -898,10 +914,10 @@ static int yaffs_CheckChunkErased(struct
2334 result = yaffs_ReadChunkWithTagsFromNAND(dev, chunkInNAND, data, &tags);
2337 if(tags.eccResult > YAFFS_ECC_RESULT_NO_ERROR)
2338 retval = YAFFS_FAIL;
2342 if (!yaffs_CheckFF(data, dev->nDataBytesPerChunk) || tags.chunkUsed) {
2343 T(YAFFS_TRACE_NANDACCESS,
2344 @@ -915,7 +931,6 @@ static int yaffs_CheckChunkErased(struct
2349 static int yaffs_WriteNewChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev,
2351 yaffs_ExtendedTags * tags,
2352 @@ -992,7 +1007,11 @@ static int yaffs_WriteNewChunkWithTagsTo
2353 /* Copy the data into the robustification buffer */
2354 yaffs_HandleWriteChunkOk(dev, chunk, data, tags);
2356 - } while (writeOk != YAFFS_OK && attempts < yaffs_wr_attempts);
2357 + } while (writeOk != YAFFS_OK &&
2358 + (yaffs_wr_attempts <= 0 || attempts <= yaffs_wr_attempts));
2364 T(YAFFS_TRACE_ERROR,
2365 @@ -1008,13 +1027,13 @@ static int yaffs_WriteNewChunkWithTagsTo
2367 * Block retiring for handling a broken block.
2371 static void yaffs_RetireBlock(yaffs_Device * dev, int blockInNAND)
2373 yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, blockInNAND);
2375 yaffs_InvalidateCheckpoint(dev);
2378 yaffs_MarkBlockBad(dev, blockInNAND);
2380 bi->blockState = YAFFS_BLOCK_STATE_DEAD;
2381 @@ -1028,7 +1047,7 @@ static void yaffs_RetireBlock(yaffs_Devi
2382 * Functions for robustisizing TODO
2387 static void yaffs_HandleWriteChunkOk(yaffs_Device * dev, int chunkInNAND,
2389 const yaffs_ExtendedTags * tags)
2390 @@ -1046,13 +1065,13 @@ void yaffs_HandleChunkError(yaffs_Device
2391 bi->gcPrioritise = 1;
2392 dev->hasPendingPrioritisedGCs = 1;
2393 bi->chunkErrorStrikes ++;
2396 if(bi->chunkErrorStrikes > 3){
2397 bi->needsRetiring = 1; /* Too many stikes, so retire this */
2398 T(YAFFS_TRACE_ALWAYS, (TSTR("yaffs: Block struck out" TENDSTR)));
2406 @@ -1063,30 +1082,30 @@ static void yaffs_HandleWriteChunkError(
2407 yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, blockInNAND);
2409 yaffs_HandleChunkError(dev,bi);
2415 /* Was an actual write failure, so mark the block for retirement */
2416 bi->needsRetiring = 1;
2417 T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,
2418 (TSTR("**>> Block %d needs retiring" TENDSTR), blockInNAND));
2425 /* Delete the chunk */
2426 yaffs_DeleteChunk(dev, chunkInNAND, 1, __LINE__);
2430 -/*---------------- Name handling functions ------------*/
2431 +/*---------------- Name handling functions ------------*/
2433 static __u16 yaffs_CalcNameSum(const YCHAR * name)
2438 - YUCHAR *bname = (YUCHAR *) name;
2439 + const YUCHAR *bname = (const YUCHAR *) name;
2441 while ((*bname) && (i < (YAFFS_MAX_NAME_LENGTH/2))) {
2443 @@ -1099,12 +1118,14 @@ static __u16 yaffs_CalcNameSum(const YCH
2451 static void yaffs_SetObjectName(yaffs_Object * obj, const YCHAR * name)
2453 #ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM
2454 + memset(obj->shortName,0,sizeof (YCHAR) * (YAFFS_SHORT_NAME_LENGTH+1));
2455 if (name && yaffs_strlen(name) <= YAFFS_SHORT_NAME_LENGTH) {
2456 yaffs_strcpy(obj->shortName, name);
2458 @@ -1120,7 +1141,7 @@ static void yaffs_SetObjectName(yaffs_Ob
2459 * The list is hooked together using the first pointer
2464 /* yaffs_CreateTnodes creates a bunch more tnodes and
2465 * adds them to the tnode free list.
2466 * Don't use this function directly
2467 @@ -1138,11 +1159,15 @@ static int yaffs_CreateTnodes(yaffs_Devi
2473 /* Calculate the tnode size in bytes for variable width tnode support.
2474 * Must be a multiple of 32-bits */
2475 tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
2477 + if(tnodeSize < sizeof(yaffs_Tnode))
2478 + tnodeSize = sizeof(yaffs_Tnode);
2481 /* make these things */
2483 newTnodes = YMALLOC(nTnodes * tnodeSize);
2484 @@ -1175,7 +1200,7 @@ static int yaffs_CreateTnodes(yaffs_Devi
2485 next = (yaffs_Tnode *) &mem[(i+1) * tnodeSize];
2486 curr->internal[0] = next;
2490 curr = (yaffs_Tnode *) &mem[(nTnodes - 1) * tnodeSize];
2491 curr->internal[0] = dev->freeTnodes;
2492 dev->freeTnodes = (yaffs_Tnode *)mem;
2493 @@ -1190,7 +1215,7 @@ static int yaffs_CreateTnodes(yaffs_Devi
2494 * NB If we can't add this to the management list it isn't fatal
2495 * but it just means we can't free this bunch of tnodes later.
2499 tnl = YMALLOC(sizeof(yaffs_TnodeList));
2501 T(YAFFS_TRACE_ERROR,
2502 @@ -1233,17 +1258,23 @@ static yaffs_Tnode *yaffs_GetTnodeRaw(ya
2506 + dev->nCheckpointBlocksRequired = 0; /* force recalculation*/
2511 static yaffs_Tnode *yaffs_GetTnode(yaffs_Device * dev)
2513 yaffs_Tnode *tn = yaffs_GetTnodeRaw(dev);
2514 + int tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
2516 + if(tnodeSize < sizeof(yaffs_Tnode))
2517 + tnodeSize = sizeof(yaffs_Tnode);
2520 - memset(tn, 0, (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8);
2521 + memset(tn, 0, tnodeSize);
2527 /* FreeTnode frees up a tnode and puts it back on the free list */
2528 @@ -1262,6 +1293,8 @@ static void yaffs_FreeTnode(yaffs_Device
2529 dev->freeTnodes = tn;
2532 + dev->nCheckpointBlocksRequired = 0; /* force recalculation*/
2536 static void yaffs_DeinitialiseTnodes(yaffs_Device * dev)
2537 @@ -1299,19 +1332,19 @@ void yaffs_PutLevel0Tnode(yaffs_Device *
2543 pos &= YAFFS_TNODES_LEVEL0_MASK;
2544 val >>= dev->chunkGroupBits;
2547 bitInMap = pos * dev->tnodeWidth;
2548 wordInMap = bitInMap /32;
2549 bitInWord = bitInMap & (32 -1);
2552 mask = dev->tnodeMask << bitInWord;
2555 map[wordInMap] &= ~mask;
2556 map[wordInMap] |= (mask & (val << bitInWord));
2559 if(dev->tnodeWidth > (32-bitInWord)) {
2560 bitInWord = (32 - bitInWord);
2562 @@ -1328,24 +1361,24 @@ static __u32 yaffs_GetChunkGroupBase(yaf
2568 pos &= YAFFS_TNODES_LEVEL0_MASK;
2571 bitInMap = pos * dev->tnodeWidth;
2572 wordInMap = bitInMap /32;
2573 bitInWord = bitInMap & (32 -1);
2576 val = map[wordInMap] >> bitInWord;
2579 if(dev->tnodeWidth > (32-bitInWord)) {
2580 bitInWord = (32 - bitInWord);
2582 val |= (map[wordInMap] << bitInWord);
2586 val &= dev->tnodeMask;
2587 val <<= dev->chunkGroupBits;
2593 @@ -1394,7 +1427,7 @@ static yaffs_Tnode *yaffs_FindLevel0Tnod
2594 while (level > 0 && tn) {
2596 internal[(chunkId >>
2597 - ( YAFFS_TNODES_LEVEL0_BITS +
2598 + ( YAFFS_TNODES_LEVEL0_BITS +
2600 YAFFS_TNODES_INTERNAL_BITS)
2602 @@ -1416,7 +1449,7 @@ static yaffs_Tnode *yaffs_FindLevel0Tnod
2603 * If the tn argument is NULL, then a fresh tnode will be added otherwise the specified tn will
2604 * be plugged into the ttree.
2608 static yaffs_Tnode *yaffs_AddOrFindLevel0Tnode(yaffs_Device * dev,
2609 yaffs_FileStructure * fStruct,
2611 @@ -1453,7 +1486,7 @@ static yaffs_Tnode *yaffs_AddOrFindLevel
2612 if (requiredTallness > fStruct->topLevel) {
2613 /* Not tall enough,gotta make the tree taller */
2614 for (i = fStruct->topLevel; i < requiredTallness; i++) {
2617 tn = yaffs_GetTnode(dev);
2620 @@ -1472,7 +1505,7 @@ static yaffs_Tnode *yaffs_AddOrFindLevel
2622 l = fStruct->topLevel;
2627 while (l > 0 && tn) {
2629 @@ -1492,13 +1525,13 @@ static yaffs_Tnode *yaffs_AddOrFindLevel
2631 yaffs_FreeTnode(dev,tn->internal[x]);
2632 tn->internal[x] = passedTn;
2635 } else if(!tn->internal[x]) {
2636 /* Don't have one, none passed in */
2637 tn->internal[x] = yaffs_GetTnode(dev);
2642 tn = tn->internal[x];
2645 @@ -1539,7 +1572,7 @@ static int yaffs_FindChunkInGroup(yaffs_
2647 /* DeleteWorker scans backwards through the tnode tree and deletes all the
2648 * chunks and tnodes in the file
2649 - * Returns 1 if the tree was deleted.
2650 + * Returns 1 if the tree was deleted.
2651 * Returns 0 if it stopped early due to hitting the limit and the delete is incomplete.
2654 @@ -1653,7 +1686,7 @@ static void yaffs_SoftDeleteChunk(yaffs_
2656 * Thus, essentially this is the same as DeleteWorker except that the chunks are soft deleted.
2660 static int yaffs_SoftDeleteWorker(yaffs_Object * in, yaffs_Tnode * tn,
2661 __u32 level, int chunkOffset)
2663 @@ -1694,7 +1727,7 @@ static int yaffs_SoftDeleteWorker(yaffs_
2664 theChunk = yaffs_GetChunkGroupBase(dev,tn,i);
2666 /* Note this does not find the real chunk, only the chunk group.
2667 - * We make an assumption that a chunk group is not larger than
2668 + * We make an assumption that a chunk group is not larger than
2671 yaffs_SoftDeleteChunk(dev, theChunk);
2672 @@ -1796,7 +1829,7 @@ static int yaffs_PruneFileStructure(yaff
2673 /* Now we have a tree with all the non-zero branches NULL but the height
2674 * is the same as it was.
2675 * Let's see if we can trim internal tnodes to shorten the tree.
2676 - * We can do this if only the 0th element in the tnode is in use
2677 + * We can do this if only the 0th element in the tnode is in use
2678 * (ie all the non-zero are NULL)
2681 @@ -1850,14 +1883,14 @@ static int yaffs_CreateFreeObjects(yaffs
2682 (TSTR("yaffs: Could not allocate more objects" TENDSTR)));
2686 + /* Hook them into the free list */
2687 + for (i = 0; i < nObjects - 1; i++) {
2688 + newObjects[i].siblings.next =
2689 + (struct ylist_head *)(&newObjects[i + 1]);
2692 - /* Hook them into the free list */
2693 - for (i = 0; i < nObjects - 1; i++) {
2694 - newObjects[i].siblings.next =
2695 - (struct list_head *)(&newObjects[i + 1]);
2698 - newObjects[nObjects - 1].siblings.next = (void *)dev->freeObjects;
2699 + newObjects[nObjects - 1].siblings.next = (void *)dev->freeObjects;
2700 dev->freeObjects = newObjects;
2701 dev->nFreeObjects += nObjects;
2702 dev->nObjectsCreated += nObjects;
2703 @@ -1877,6 +1910,9 @@ static yaffs_Object *yaffs_AllocateEmpty
2705 yaffs_Object *tn = NULL;
2707 +#ifdef VALGRIND_TEST
2708 + tn = YMALLOC(sizeof(yaffs_Object));
2710 /* If there are none left make more */
2711 if (!dev->freeObjects) {
2712 yaffs_CreateFreeObjects(dev, YAFFS_ALLOCATION_NOBJECTS);
2713 @@ -1887,25 +1923,40 @@ static yaffs_Object *yaffs_AllocateEmpty
2715 (yaffs_Object *) (dev->freeObjects->siblings.next);
2716 dev->nFreeObjects--;
2721 /* Now sweeten it up... */
2723 memset(tn, 0, sizeof(yaffs_Object));
2724 + tn->beingCreated = 1;
2729 tn->variantType = YAFFS_OBJECT_TYPE_UNKNOWN;
2730 - INIT_LIST_HEAD(&(tn->hardLinks));
2731 - INIT_LIST_HEAD(&(tn->hashLink));
2732 - INIT_LIST_HEAD(&tn->siblings);
2733 + YINIT_LIST_HEAD(&(tn->hardLinks));
2734 + YINIT_LIST_HEAD(&(tn->hashLink));
2735 + YINIT_LIST_HEAD(&tn->siblings);
2738 + /* Now make the directory sane */
2740 + tn->parent = dev->rootDir;
2741 + ylist_add(&(tn->siblings),&dev->rootDir->variant.directoryVariant.children);
2744 - /* Add it to the lost and found directory.
2745 - * NB Can't put root or lostNFound in lostNFound so
2746 + /* Add it to the lost and found directory.
2747 + * NB Can't put root or lostNFound in lostNFound so
2748 * check if lostNFound exists first
2750 if (dev->lostNFoundDir) {
2751 yaffs_AddObjectToDirectory(dev->lostNFoundDir, tn);
2754 + tn->beingCreated = 0;
2757 + dev->nCheckpointBlocksRequired = 0; /* force recalculation*/
2761 @@ -1917,14 +1968,14 @@ static yaffs_Object *yaffs_CreateFakeDir
2763 yaffs_CreateNewObject(dev, number, YAFFS_OBJECT_TYPE_DIRECTORY);
2765 - obj->fake = 1; /* it is fake so it has no NAND presence... */
2766 + obj->fake = 1; /* it is fake so it might have no NAND presence... */
2767 obj->renameAllowed = 0; /* ... and we're not allowed to rename it... */
2768 obj->unlinkAllowed = 0; /* ... or unlink it */
2771 obj->yst_mode = mode;
2773 - obj->chunkId = 0; /* Not a valid chunk. */
2774 + obj->hdrChunk = 0; /* Not a valid chunk. */
2778 @@ -1934,14 +1985,14 @@ static yaffs_Object *yaffs_CreateFakeDir
2779 static void yaffs_UnhashObject(yaffs_Object * tn)
2782 - yaffs_Device *dev = tn->myDev;
2783 + yaffs_Device *dev = tn->myDev;
2785 - /* If it is still linked into the bucket list, free from the list */
2786 - if (!list_empty(&tn->hashLink)) {
2787 - list_del_init(&tn->hashLink);
2788 - bucket = yaffs_HashFunction(tn->objectId);
2789 - dev->objectBucket[bucket].count--;
2791 + /* If it is still linked into the bucket list, free from the list */
2792 + if (!ylist_empty(&tn->hashLink)) {
2793 + ylist_del_init(&tn->hashLink);
2794 + bucket = yaffs_HashFunction(tn->objectId);
2795 + dev->objectBucket[bucket].count--;
2800 @@ -1951,6 +2002,13 @@ static void yaffs_FreeObject(yaffs_Objec
2802 yaffs_Device *dev = tn->myDev;
2807 + if(!ylist_empty(&tn->siblings))
2813 /* We're still hooked up to a cached inode.
2814 @@ -1961,12 +2019,18 @@ static void yaffs_FreeObject(yaffs_Objec
2818 - yaffs_UnhashObject(tn);
2819 + yaffs_UnhashObject(tn);
2821 +#ifdef VALGRIND_TEST
2824 + /* Link into the free list. */
2825 + tn->siblings.next = (struct ylist_head *)(dev->freeObjects);
2826 + dev->freeObjects = tn;
2827 + dev->nFreeObjects++;
2829 + dev->nCheckpointBlocksRequired = 0; /* force recalculation*/
2831 - /* Link into the free list. */
2832 - tn->siblings.next = (struct list_head *)(dev->freeObjects);
2833 - dev->freeObjects = tn;
2834 - dev->nFreeObjects++;
2838 @@ -2004,12 +2068,12 @@ static void yaffs_InitialiseObjects(yaff
2840 dev->allocatedObjectList = NULL;
2841 dev->freeObjects = NULL;
2842 - dev->nFreeObjects = 0;
2843 + dev->nFreeObjects = 0;
2845 - for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) {
2846 - INIT_LIST_HEAD(&dev->objectBucket[i].list);
2847 - dev->objectBucket[i].count = 0;
2849 + for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) {
2850 + YINIT_LIST_HEAD(&dev->objectBucket[i].list);
2851 + dev->objectBucket[i].count = 0;
2856 @@ -2055,26 +2119,26 @@ static int yaffs_CreateNewObjectNumber(y
2858 /* Now find an object value that has not already been taken
2859 * by scanning the list.
2864 - struct list_head *i;
2866 + struct ylist_head *i;
2868 - __u32 n = (__u32) bucket;
2869 + __u32 n = (__u32) bucket;
2871 /* yaffs_CheckObjectHashSanity(); */
2875 - n += YAFFS_NOBJECT_BUCKETS;
2876 - if (1 || dev->objectBucket[bucket].count > 0) {
2877 - list_for_each(i, &dev->objectBucket[bucket].list) {
2878 - /* If there is already one in the list */
2880 - && list_entry(i, yaffs_Object,
2881 - hashLink)->objectId == n) {
2885 + n += YAFFS_NOBJECT_BUCKETS;
2886 + if (1 || dev->objectBucket[bucket].count > 0) {
2887 + ylist_for_each(i, &dev->objectBucket[bucket].list) {
2888 + /* If there is already one in the list */
2890 + && ylist_entry(i, yaffs_Object,
2891 + hashLink)->objectId == n) {
2897 @@ -2085,27 +2149,27 @@ static int yaffs_CreateNewObjectNumber(y
2899 static void yaffs_HashObject(yaffs_Object * in)
2901 - int bucket = yaffs_HashFunction(in->objectId);
2902 - yaffs_Device *dev = in->myDev;
2903 + int bucket = yaffs_HashFunction(in->objectId);
2904 + yaffs_Device *dev = in->myDev;
2906 - list_add(&in->hashLink, &dev->objectBucket[bucket].list);
2907 - dev->objectBucket[bucket].count++;
2908 + ylist_add(&in->hashLink, &dev->objectBucket[bucket].list);
2909 + dev->objectBucket[bucket].count++;
2913 yaffs_Object *yaffs_FindObjectByNumber(yaffs_Device * dev, __u32 number)
2915 - int bucket = yaffs_HashFunction(number);
2916 - struct list_head *i;
2919 - list_for_each(i, &dev->objectBucket[bucket].list) {
2920 - /* Look if it is in the list */
2922 - in = list_entry(i, yaffs_Object, hashLink);
2923 - if (in->objectId == number) {
2924 + int bucket = yaffs_HashFunction(number);
2925 + struct ylist_head *i;
2928 + ylist_for_each(i, &dev->objectBucket[bucket].list) {
2929 + /* Look if it is in the list */
2931 + in = ylist_entry(i, yaffs_Object, hashLink);
2932 + if (in->objectId == number) {
2934 - /* Don't tell the VFS about this one if it is defered free */
2935 + /* Don't tell the VFS about this one if it is defered free */
2936 if (in->deferedFree)
2939 @@ -2123,7 +2187,7 @@ yaffs_Object *yaffs_CreateNewObject(yaff
2942 yaffs_Object *theObject;
2944 + yaffs_Tnode *tn = NULL;
2947 number = yaffs_CreateNewObjectNumber(dev);
2948 @@ -2132,7 +2196,7 @@ yaffs_Object *yaffs_CreateNewObject(yaff
2949 theObject = yaffs_AllocateEmptyObject(dev);
2954 if(type == YAFFS_OBJECT_TYPE_FILE){
2955 tn = yaffs_GetTnode(dev);
2957 @@ -2140,8 +2204,8 @@ yaffs_Object *yaffs_CreateNewObject(yaff
2967 theObject->fake = 0;
2968 @@ -2162,19 +2226,25 @@ yaffs_Object *yaffs_CreateNewObject(yaff
2969 theObject->yst_atime = theObject->yst_mtime =
2970 theObject->yst_ctime = Y_CURRENT_TIME;
2974 + theObject->sum_prev = 12345;
2975 + theObject->sum_trailer = 6789;
2979 case YAFFS_OBJECT_TYPE_FILE:
2980 theObject->variant.fileVariant.fileSize = 0;
2981 theObject->variant.fileVariant.scannedFileSize = 0;
2982 theObject->variant.fileVariant.shrinkSize = 0xFFFFFFFF; /* max __u32 */
2983 theObject->variant.fileVariant.topLevel = 0;
2984 - theObject->variant.fileVariant.top = tn;
2986 - case YAFFS_OBJECT_TYPE_DIRECTORY:
2987 - INIT_LIST_HEAD(&theObject->variant.directoryVariant.
2990 - case YAFFS_OBJECT_TYPE_SYMLINK:
2991 + theObject->variant.fileVariant.top = tn;
2993 + case YAFFS_OBJECT_TYPE_DIRECTORY:
2994 + YINIT_LIST_HEAD(&theObject->variant.directoryVariant.
2997 + case YAFFS_OBJECT_TYPE_SYMLINK:
2998 case YAFFS_OBJECT_TYPE_HARDLINK:
2999 case YAFFS_OBJECT_TYPE_SPECIAL:
3000 /* No action required */
3001 @@ -2205,7 +2275,7 @@ static yaffs_Object *yaffs_FindOrCreateO
3008 static YCHAR *yaffs_CloneString(const YCHAR * str)
3010 @@ -2227,7 +2297,7 @@ static YCHAR *yaffs_CloneString(const YC
3011 * aliasString only has meaning for a sumlink.
3012 * rdev only has meaning for devices (a subset of special objects)
3016 static yaffs_Object *yaffs_MknodObject(yaffs_ObjectType type,
3017 yaffs_Object * parent,
3019 @@ -2238,7 +2308,7 @@ static yaffs_Object *yaffs_MknodObject(y
3020 const YCHAR * aliasString, __u32 rdev)
3024 + YCHAR *str = NULL;
3026 yaffs_Device *dev = parent->myDev;
3028 @@ -2249,6 +2319,9 @@ static yaffs_Object *yaffs_MknodObject(y
3030 in = yaffs_CreateNewObject(dev, -1, type);
3033 + return YAFFS_FAIL;
3035 if(type == YAFFS_OBJECT_TYPE_SYMLINK){
3036 str = yaffs_CloneString(aliasString);
3038 @@ -2256,11 +2329,11 @@ static yaffs_Object *yaffs_MknodObject(y
3051 in->variantType = type;
3053 @@ -2293,13 +2366,13 @@ static yaffs_Object *yaffs_MknodObject(y
3055 case YAFFS_OBJECT_TYPE_HARDLINK:
3056 in->variant.hardLinkVariant.equivalentObject =
3058 - in->variant.hardLinkVariant.equivalentObjectId =
3059 - equivalentObject->objectId;
3060 - list_add(&in->hardLinks, &equivalentObject->hardLinks);
3062 - case YAFFS_OBJECT_TYPE_FILE:
3063 - case YAFFS_OBJECT_TYPE_DIRECTORY:
3065 + in->variant.hardLinkVariant.equivalentObjectId =
3066 + equivalentObject->objectId;
3067 + ylist_add(&in->hardLinks, &equivalentObject->hardLinks);
3069 + case YAFFS_OBJECT_TYPE_FILE:
3070 + case YAFFS_OBJECT_TYPE_DIRECTORY:
3071 case YAFFS_OBJECT_TYPE_SPECIAL:
3072 case YAFFS_OBJECT_TYPE_UNKNOWN:
3074 @@ -2378,11 +2451,11 @@ static int yaffs_ChangeObjectName(yaffs_
3075 if (newDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) {
3076 T(YAFFS_TRACE_ALWAYS,
3078 - ("tragendy: yaffs_ChangeObjectName: newDir is not a directory"
3079 + ("tragedy: yaffs_ChangeObjectName: newDir is not a directory"
3085 /* TODO: Do we need this different handling for YAFFS2 and YAFFS1?? */
3086 if (obj->myDev->isYaffs2) {
3087 unlinkOp = (newDir == obj->myDev->unlinkedDir);
3088 @@ -2395,9 +2468,9 @@ static int yaffs_ChangeObjectName(yaffs_
3090 existingTarget = yaffs_FindObjectByName(newDir, newName);
3092 - /* If the object is a file going into the unlinked directory,
3093 + /* If the object is a file going into the unlinked directory,
3094 * then it is OK to just stuff it in since duplicate names are allowed.
3095 - * else only proceed if the new name does not exist and if we're putting
3096 + * else only proceed if the new name does not exist and if we're putting
3097 * it into a directory.
3100 @@ -2425,9 +2498,15 @@ static int yaffs_ChangeObjectName(yaffs_
3101 int yaffs_RenameObject(yaffs_Object * oldDir, const YCHAR * oldName,
3102 yaffs_Object * newDir, const YCHAR * newName)
3104 - yaffs_Object *obj;
3105 - yaffs_Object *existingTarget;
3106 + yaffs_Object *obj=NULL;
3107 + yaffs_Object *existingTarget=NULL;
3111 + if(!oldDir || oldDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY)
3113 + if(!newDir || newDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY)
3116 #ifdef CONFIG_YAFFS_CASE_INSENSITIVE
3117 /* Special case for case insemsitive systems (eg. WinCE).
3118 @@ -2439,29 +2518,24 @@ int yaffs_RenameObject(yaffs_Object * ol
3122 - obj = yaffs_FindObjectByName(oldDir, oldName);
3123 - /* Check new name to long. */
3124 - if (obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK &&
3125 - yaffs_strlen(newName) > YAFFS_MAX_ALIAS_LENGTH)
3126 - /* ENAMETOOLONG */
3127 - return YAFFS_FAIL;
3128 - else if (obj->variantType != YAFFS_OBJECT_TYPE_SYMLINK &&
3129 - yaffs_strlen(newName) > YAFFS_MAX_NAME_LENGTH)
3130 + else if (yaffs_strlen(newName) > YAFFS_MAX_NAME_LENGTH)
3134 + obj = yaffs_FindObjectByName(oldDir, oldName);
3136 if (obj && obj->renameAllowed) {
3138 /* Now do the handling for an existing target, if there is one */
3140 - existingTarget = yaffs_FindObjectByName(newDir, newName);
3141 - if (existingTarget &&
3142 - existingTarget->variantType == YAFFS_OBJECT_TYPE_DIRECTORY &&
3143 - !list_empty(&existingTarget->variant.directoryVariant.children)) {
3144 - /* There is a target that is a non-empty directory, so we fail */
3145 - return YAFFS_FAIL; /* EEXIST or ENOTEMPTY */
3146 - } else if (existingTarget && existingTarget != obj) {
3147 - /* Nuke the target first, using shadowing,
3148 + existingTarget = yaffs_FindObjectByName(newDir, newName);
3149 + if (existingTarget &&
3150 + existingTarget->variantType == YAFFS_OBJECT_TYPE_DIRECTORY &&
3151 + !ylist_empty(&existingTarget->variant.directoryVariant.children)) {
3152 + /* There is a target that is a non-empty directory, so we fail */
3153 + return YAFFS_FAIL; /* EEXIST or ENOTEMPTY */
3154 + } else if (existingTarget && existingTarget != obj) {
3155 + /* Nuke the target first, using shadowing,
3156 * but only if it isn't the same object
3158 yaffs_ChangeObjectName(obj, newDir, newName, force,
3159 @@ -2479,10 +2553,10 @@ int yaffs_RenameObject(yaffs_Object * ol
3160 static int yaffs_InitialiseBlocks(yaffs_Device * dev)
3162 int nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1;
3165 dev->blockInfo = NULL;
3166 dev->chunkBits = NULL;
3169 dev->allocationBlock = -1; /* force it to get a new one */
3171 /* If the first allocation strategy fails, thry the alternate one */
3172 @@ -2493,9 +2567,9 @@ static int yaffs_InitialiseBlocks(yaffs_
3175 dev->blockInfoAlt = 0;
3181 /* Set up dynamic blockinfo stuff. */
3182 dev->chunkBitmapStride = (dev->nChunksPerBlock + 7) / 8; /* round up bytes */
3183 dev->chunkBits = YMALLOC(dev->chunkBitmapStride * nBlocks);
3184 @@ -2506,7 +2580,7 @@ static int yaffs_InitialiseBlocks(yaffs_
3186 dev->chunkBitsAlt = 0;
3190 if (dev->blockInfo && dev->chunkBits) {
3191 memset(dev->blockInfo, 0, nBlocks * sizeof(yaffs_BlockInfo));
3192 memset(dev->chunkBits, 0, dev->chunkBitmapStride * nBlocks);
3193 @@ -2527,7 +2601,7 @@ static void yaffs_DeinitialiseBlocks(yaf
3194 dev->blockInfoAlt = 0;
3196 dev->blockInfo = NULL;
3199 if(dev->chunkBitsAlt && dev->chunkBits)
3200 YFREE_ALT(dev->chunkBits);
3201 else if(dev->chunkBits)
3202 @@ -2591,14 +2665,14 @@ static int yaffs_FindBlockForGarbageColl
3204 yaffs_BlockInfo *bi;
3205 int pendingPrioritisedExist = 0;
3208 /* First let's see if we need to grab a prioritised block */
3209 if(dev->hasPendingPrioritisedGCs){
3210 for(i = dev->internalStartBlock; i < dev->internalEndBlock && !prioritised; i++){
3212 bi = yaffs_GetBlockInfo(dev, i);
3213 //yaffs_VerifyBlock(dev,bi,i);
3216 if(bi->gcPrioritise) {
3217 pendingPrioritisedExist = 1;
3218 if(bi->blockState == YAFFS_BLOCK_STATE_FULL &&
3219 @@ -2610,7 +2684,7 @@ static int yaffs_FindBlockForGarbageColl
3225 if(!pendingPrioritisedExist) /* None found, so we can clear this */
3226 dev->hasPendingPrioritisedGCs = 0;
3228 @@ -2662,7 +2736,7 @@ static int yaffs_FindBlockForGarbageColl
3236 if (bi->blockState == YAFFS_BLOCK_STATE_FULL &&
3237 @@ -2699,11 +2773,11 @@ static void yaffs_BlockBecameDirty(yaffs
3238 /* If the block is still healthy erase it and mark as clean.
3239 * If the block has had a data failure, then retire it.
3243 T(YAFFS_TRACE_GC | YAFFS_TRACE_ERASE,
3244 (TSTR("yaffs_BlockBecameDirty block %d state %d %s"TENDSTR),
3245 blockNo, bi->blockState, (bi->needsRetiring) ? "needs retiring" : ""));
3248 bi->blockState = YAFFS_BLOCK_STATE_DIRTY;
3250 if (!bi->needsRetiring) {
3251 @@ -2716,7 +2790,7 @@ static void yaffs_BlockBecameDirty(yaffs
3257 ((yaffs_traceMask & YAFFS_TRACE_ERASE) || !yaffs_SkipVerification(dev))) {
3259 for (i = 0; i < dev->nChunksPerBlock; i++) {
3260 @@ -2763,11 +2837,11 @@ static int yaffs_FindBlockForAllocation(
3261 * Can't get space to gc
3263 T(YAFFS_TRACE_ERROR,
3264 - (TSTR("yaffs tragedy: no more eraased blocks" TENDSTR)));
3265 + (TSTR("yaffs tragedy: no more erased blocks" TENDSTR)));
3271 /* Find an empty block. */
3273 for (i = dev->internalStartBlock; i <= dev->internalEndBlock; i++) {
3274 @@ -2794,13 +2868,48 @@ static int yaffs_FindBlockForAllocation(
3276 T(YAFFS_TRACE_ALWAYS,
3278 - ("yaffs tragedy: no more eraased blocks, but there should have been %d"
3279 + ("yaffs tragedy: no more erased blocks, but there should have been %d"
3280 TENDSTR), dev->nErasedBlocks));
3287 +static int yaffs_CalcCheckpointBlocksRequired(yaffs_Device *dev)
3289 + if(!dev->nCheckpointBlocksRequired &&
3291 + /* Not a valid value so recalculate */
3294 + int devBlocks = (dev->endBlock - dev->startBlock + 1);
3297 + tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
3299 + if(tnodeSize < sizeof(yaffs_Tnode))
3300 + tnodeSize = sizeof(yaffs_Tnode);
3302 + nBytes += sizeof(yaffs_CheckpointValidity);
3303 + nBytes += sizeof(yaffs_CheckpointDevice);
3304 + nBytes += devBlocks * sizeof(yaffs_BlockInfo);
3305 + nBytes += devBlocks * dev->chunkBitmapStride;
3306 + nBytes += (sizeof(yaffs_CheckpointObject) + sizeof(__u32)) * (dev->nObjectsCreated - dev->nFreeObjects);
3307 + nBytes += (tnodeSize + sizeof(__u32)) * (dev->nTnodesCreated - dev->nFreeTnodes);
3308 + nBytes += sizeof(yaffs_CheckpointValidity);
3309 + nBytes += sizeof(__u32); /* checksum*/
3311 + /* Round up and add 2 blocks to allow for some bad blocks, so add 3 */
3313 + nBlocks = (nBytes/(dev->nDataBytesPerChunk * dev->nChunksPerBlock)) + 3;
3315 + dev->nCheckpointBlocksRequired = nBlocks;
3318 + return dev->nCheckpointBlocksRequired;
3321 // Check if there's space to allocate...
3322 // Thinks.... do we need top make this ths same as yaffs_GetFreeChunks()?
3323 static int yaffs_CheckSpaceForAllocation(yaffs_Device * dev)
3324 @@ -2808,13 +2917,18 @@ static int yaffs_CheckSpaceForAllocation
3326 int reservedBlocks = dev->nReservedBlocks;
3327 int checkpointBlocks;
3329 - checkpointBlocks = dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint;
3330 - if(checkpointBlocks < 0)
3331 - checkpointBlocks = 0;
3334 + if(dev->isYaffs2){
3335 + checkpointBlocks = yaffs_CalcCheckpointBlocksRequired(dev) -
3336 + dev->blocksInCheckpoint;
3337 + if(checkpointBlocks < 0)
3338 + checkpointBlocks = 0;
3340 + checkpointBlocks =0;
3343 reservedChunks = ((reservedBlocks + checkpointBlocks) * dev->nChunksPerBlock);
3346 return (dev->nFreeChunks > reservedChunks);
3349 @@ -2861,10 +2975,10 @@ static int yaffs_AllocateChunk(yaffs_Dev
3359 T(YAFFS_TRACE_ERROR,
3360 (TSTR("!!!!!!!!! Allocator out !!!!!!!!!!!!!!!!!" TENDSTR)));
3362 @@ -2885,17 +2999,17 @@ static int yaffs_GetErasedChunks(yaffs_D
3366 -static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block)
3367 +static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block, int wholeBlock)
3373 int retVal = YAFFS_OK;
3376 int isCheckpointBlock;
3380 int chunksBefore = yaffs_GetErasedChunks(dev);
3382 @@ -2907,12 +3021,15 @@ static int yaffs_GarbageCollectBlock(yaf
3383 yaffs_Object *object;
3385 isCheckpointBlock = (bi->blockState == YAFFS_BLOCK_STATE_CHECKPOINT);
3388 bi->blockState = YAFFS_BLOCK_STATE_COLLECTING;
3390 T(YAFFS_TRACE_TRACING,
3391 - (TSTR("Collecting block %d, in use %d, shrink %d, " TENDSTR), block,
3392 - bi->pagesInUse, bi->hasShrinkHeader));
3393 + (TSTR("Collecting block %d, in use %d, shrink %d, wholeBlock %d" TENDSTR),
3396 + bi->hasShrinkHeader,
3399 /*yaffs_VerifyFreeChunks(dev); */
3401 @@ -2935,16 +3052,23 @@ static int yaffs_GarbageCollectBlock(yaf
3404 __u8 *buffer = yaffs_GetTempBuffer(dev, __LINE__);
3407 yaffs_VerifyBlock(dev,bi,block);
3409 - for (chunkInBlock = 0, oldChunk = block * dev->nChunksPerBlock;
3410 - chunkInBlock < dev->nChunksPerBlock
3411 - && yaffs_StillSomeChunkBits(dev, block);
3412 - chunkInBlock++, oldChunk++) {
3413 - if (yaffs_CheckChunkBit(dev, block, chunkInBlock)) {
3414 + maxCopies = (wholeBlock) ? dev->nChunksPerBlock : 10;
3415 + oldChunk = block * dev->nChunksPerBlock + dev->gcChunk;
3417 + for ( /* init already done */;
3418 + retVal == YAFFS_OK &&
3419 + dev->gcChunk < dev->nChunksPerBlock &&
3420 + (bi->blockState == YAFFS_BLOCK_STATE_COLLECTING)&&
3422 + dev->gcChunk++, oldChunk++) {
3423 + if (yaffs_CheckChunkBit(dev, block, dev->gcChunk)) {
3425 /* This page is in use and might need to be copied off */
3431 @@ -2959,23 +3083,23 @@ static int yaffs_GarbageCollectBlock(yaf
3433 T(YAFFS_TRACE_GC_DETAIL,
3435 - ("Collecting page %d, %d %d %d " TENDSTR),
3436 - chunkInBlock, tags.objectId, tags.chunkId,
3437 + ("Collecting chunk in block %d, %d %d %d " TENDSTR),
3438 + dev->gcChunk, tags.objectId, tags.chunkId,
3442 if(object && !yaffs_SkipVerification(dev)){
3443 if(tags.chunkId == 0)
3444 - matchingChunk = object->chunkId;
3445 + matchingChunk = object->hdrChunk;
3446 else if(object->softDeleted)
3447 matchingChunk = oldChunk; /* Defeat the test */
3449 matchingChunk = yaffs_FindChunkInFile(object,tags.chunkId,NULL);
3452 if(oldChunk != matchingChunk)
3453 T(YAFFS_TRACE_ERROR,
3454 (TSTR("gc: page in gc mismatch: %d %d %d %d"TENDSTR),
3455 oldChunk,matchingChunk,tags.objectId, tags.chunkId));
3461 @@ -2986,11 +3110,13 @@ static int yaffs_GarbageCollectBlock(yaf
3462 tags.objectId, tags.chunkId, tags.byteCount));
3465 - if (object && object->deleted
3466 - && tags.chunkId != 0) {
3467 - /* Data chunk in a deleted file, throw it away
3469 + object->deleted &&
3470 + object->softDeleted &&
3471 + tags.chunkId != 0) {
3472 + /* Data chunk in a soft deleted file, throw it away
3473 * It's a soft deleted data chunk,
3474 - * No need to copy this, just forget about it and
3475 + * No need to copy this, just forget about it and
3476 * fix up the object.
3479 @@ -3009,7 +3135,7 @@ static int yaffs_GarbageCollectBlock(yaf
3480 /* Deleted object header with no data chunks.
3481 * Can be discarded and the file deleted.
3483 - object->chunkId = 0;
3484 + object->hdrChunk = 0;
3485 yaffs_FreeTnode(object->myDev,
3488 @@ -3037,10 +3163,9 @@ static int yaffs_GarbageCollectBlock(yaf
3489 yaffs_ObjectHeader *oh;
3490 oh = (yaffs_ObjectHeader *)buffer;
3492 - oh->shadowsObject = -1;
3493 tags.extraShadows = 0;
3494 tags.extraIsShrinkHeader = 0;
3497 yaffs_VerifyObjectHeader(object,oh,&tags,1);
3500 @@ -3055,7 +3180,7 @@ static int yaffs_GarbageCollectBlock(yaf
3502 if (tags.chunkId == 0) {
3504 - object->chunkId = newChunk;
3505 + object->hdrChunk = newChunk;
3506 object->serial = tags.serialNumber;
3508 /* It's a data chunk */
3509 @@ -3067,12 +3192,14 @@ static int yaffs_GarbageCollectBlock(yaf
3513 - yaffs_DeleteChunk(dev, oldChunk, markNAND, __LINE__);
3514 + if(retVal == YAFFS_OK)
3515 + yaffs_DeleteChunk(dev, oldChunk, markNAND, __LINE__);
3520 yaffs_ReleaseTempBuffer(dev, buffer, __LINE__);
3524 /* Do any required cleanups */
3525 @@ -3099,7 +3226,7 @@ static int yaffs_GarbageCollectBlock(yaf
3528 yaffs_VerifyCollectedBlock(dev,bi,block);
3531 if (chunksBefore >= (chunksAfter = yaffs_GetErasedChunks(dev))) {
3534 @@ -3107,9 +3234,15 @@ static int yaffs_GarbageCollectBlock(yaf
3535 TENDSTR), chunksBefore, chunksAfter));
3538 + /* If the gc completed then clear the current gcBlock so that we find another. */
3539 + if(bi->blockState != YAFFS_BLOCK_STATE_COLLECTING){
3540 + dev->gcBlock = -1;
3550 /* New garbage collector
3551 @@ -3127,22 +3260,22 @@ static int yaffs_CheckGarbageCollection(
3553 int gcOk = YAFFS_OK;
3557 int checkpointBlockAdjust;
3559 if (dev->isDoingGC) {
3560 /* Bail out so we don't get recursive gc */
3565 /* This loop should pass the first time.
3566 * We'll only see looping here if the erase of the collected block fails.
3572 - checkpointBlockAdjust = (dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint);
3574 + checkpointBlockAdjust = yaffs_CalcCheckpointBlocksRequired(dev) - dev->blocksInCheckpoint;
3575 if(checkpointBlockAdjust < 0)
3576 checkpointBlockAdjust = 0;
3578 @@ -3154,7 +3287,12 @@ static int yaffs_CheckGarbageCollection(
3582 - block = yaffs_FindBlockForGarbageCollection(dev, aggressive);
3583 + if(dev->gcBlock <= 0){
3584 + dev->gcBlock = yaffs_FindBlockForGarbageCollection(dev, aggressive);
3588 + block = dev->gcBlock;
3591 dev->garbageCollections++;
3592 @@ -3167,7 +3305,7 @@ static int yaffs_CheckGarbageCollection(
3593 ("yaffs: GC erasedBlocks %d aggressive %d" TENDSTR),
3594 dev->nErasedBlocks, aggressive));
3596 - gcOk = yaffs_GarbageCollectBlock(dev, block);
3597 + gcOk = yaffs_GarbageCollectBlock(dev,block,aggressive);
3600 if (dev->nErasedBlocks < (dev->nReservedBlocks) && block > 0) {
3601 @@ -3176,8 +3314,9 @@ static int yaffs_CheckGarbageCollection(
3602 ("yaffs: GC !!!no reclaim!!! erasedBlocks %d after try %d block %d"
3603 TENDSTR), dev->nErasedBlocks, maxTries, block));
3605 - } while ((dev->nErasedBlocks < dev->nReservedBlocks) && (block > 0)
3606 - && (maxTries < 2));
3607 + } while ((dev->nErasedBlocks < dev->nReservedBlocks) &&
3611 return aggressive ? gcOk : YAFFS_OK;
3613 @@ -3326,11 +3465,11 @@ static int yaffs_CheckFileSanity(yaffs_O
3614 static int yaffs_PutChunkIntoFile(yaffs_Object * in, int chunkInInode,
3615 int chunkInNAND, int inScan)
3617 - /* NB inScan is zero unless scanning.
3618 - * For forward scanning, inScan is > 0;
3619 + /* NB inScan is zero unless scanning.
3620 + * For forward scanning, inScan is > 0;
3621 * for backward scanning inScan is < 0
3626 yaffs_Device *dev = in->myDev;
3628 @@ -3354,7 +3493,7 @@ static int yaffs_PutChunkIntoFile(yaffs_
3632 - tn = yaffs_AddOrFindLevel0Tnode(dev,
3633 + tn = yaffs_AddOrFindLevel0Tnode(dev,
3634 &in->variant.fileVariant,
3637 @@ -3366,7 +3505,7 @@ static int yaffs_PutChunkIntoFile(yaffs_
3640 /* If we're scanning then we need to test for duplicates
3641 - * NB This does not need to be efficient since it should only ever
3642 + * NB This does not need to be efficient since it should only ever
3643 * happen when the power fails during a write, then only one
3644 * chunk should ever be affected.
3646 @@ -3374,7 +3513,7 @@ static int yaffs_PutChunkIntoFile(yaffs_
3647 * Update: For backward scanning we don't need to re-read tags so this is quite cheap.
3650 - if (existingChunk != 0) {
3651 + if (existingChunk > 0) {
3652 /* NB Right now existing chunk will not be real chunkId if the device >= 32MB
3653 * thus we have to do a FindChunkInFile to get the real chunk id.
3655 @@ -3407,18 +3546,20 @@ static int yaffs_PutChunkIntoFile(yaffs_
3659 - /* NB The deleted flags should be false, otherwise the chunks will
3660 + /* NB The deleted flags should be false, otherwise the chunks will
3661 * not be loaded during a scan
3664 - newSerial = newTags.serialNumber;
3665 - existingSerial = existingTags.serialNumber;
3667 + newSerial = newTags.serialNumber;
3668 + existingSerial = existingTags.serialNumber;
3672 (in->myDev->isYaffs2 ||
3673 existingChunk <= 0 ||
3674 ((existingSerial + 1) & 3) == newSerial)) {
3675 - /* Forward scanning.
3676 + /* Forward scanning.
3678 * Delete the old one and drop through to update the tnode
3680 @@ -3459,7 +3600,7 @@ static int yaffs_ReadChunkDataFromObject
3681 (TSTR("Chunk %d not found zero instead" TENDSTR),
3683 /* get sane (zero) data if you read a hole */
3684 - memset(buffer, 0, in->myDev->nDataBytesPerChunk);
3685 + memset(buffer, 0, in->myDev->nDataBytesPerChunk);
3689 @@ -3474,7 +3615,7 @@ void yaffs_DeleteChunk(yaffs_Device * de
3697 block = chunkId / dev->nChunksPerBlock;
3698 @@ -3560,6 +3701,14 @@ static int yaffs_WriteChunkDataToObject(
3699 newTags.serialNumber =
3700 (prevChunkId >= 0) ? prevTags.serialNumber + 1 : 1;
3701 newTags.byteCount = nBytes;
3703 + if(nBytes < 1 || nBytes > dev->totalBytesPerChunk){
3704 + T(YAFFS_TRACE_ERROR,
3705 + (TSTR("Writing %d bytes to chunk!!!!!!!!!" TENDSTR), nBytes));
3712 yaffs_WriteNewChunkWithTagsToNAND(dev, buffer, &newTags,
3713 @@ -3601,11 +3750,14 @@ int yaffs_UpdateObjectHeader(yaffs_Objec
3714 __u8 *buffer = NULL;
3715 YCHAR oldName[YAFFS_MAX_NAME_LENGTH + 1];
3717 - yaffs_ObjectHeader *oh = NULL;
3718 + yaffs_ObjectHeader *oh = NULL;
3720 + yaffs_strcpy(oldName,_Y("silly old name"));
3722 - yaffs_strcpy(oldName,"silly old name");
3724 - if (!in->fake || force) {
3726 + in == dev->rootDir || /* The rootDir should also be saved */
3729 yaffs_CheckGarbageCollection(dev);
3730 yaffs_CheckObjectDetailsLoaded(in);
3731 @@ -3613,14 +3765,14 @@ int yaffs_UpdateObjectHeader(yaffs_Objec
3732 buffer = yaffs_GetTempBuffer(in->myDev, __LINE__);
3733 oh = (yaffs_ObjectHeader *) buffer;
3735 - prevChunkId = in->chunkId;
3736 + prevChunkId = in->hdrChunk;
3738 - if (prevChunkId >= 0) {
3739 + if (prevChunkId > 0) {
3740 result = yaffs_ReadChunkWithTagsFromNAND(dev, prevChunkId,
3744 yaffs_VerifyObjectHeader(in,oh,&oldTags,0);
3747 memcpy(oldName, oh->name, sizeof(oh->name));
3750 @@ -3628,7 +3780,7 @@ int yaffs_UpdateObjectHeader(yaffs_Objec
3752 oh->type = in->variantType;
3753 oh->yst_mode = in->yst_mode;
3754 - oh->shadowsObject = shadows;
3755 + oh->shadowsObject = oh->inbandShadowsObject = shadows;
3757 #ifdef CONFIG_YAFFS_WINCE
3758 oh->win_atime[0] = in->win_atime[0];
3759 @@ -3717,7 +3869,7 @@ int yaffs_UpdateObjectHeader(yaffs_Objec
3761 if (newChunkId >= 0) {
3763 - in->chunkId = newChunkId;
3764 + in->hdrChunk = newChunkId;
3766 if (prevChunkId >= 0) {
3767 yaffs_DeleteChunk(dev, prevChunkId, 1,
3768 @@ -3748,11 +3900,11 @@ int yaffs_UpdateObjectHeader(yaffs_Objec
3770 /*------------------------ Short Operations Cache ----------------------------------------
3771 * In many situations where there is no high level buffering (eg WinCE) a lot of
3772 - * reads might be short sequential reads, and a lot of writes may be short
3773 + * reads might be short sequential reads, and a lot of writes may be short
3774 * sequential writes. eg. scanning/writing a jpeg file.
3775 - * In these cases, a short read/write cache can provide a huge perfomance benefit
3776 + * In these cases, a short read/write cache can provide a huge perfomance benefit
3777 * with dumb-as-a-rock code.
3778 - * In Linux, the page cache provides read buffering aand the short op cache provides write
3779 + * In Linux, the page cache provides read buffering aand the short op cache provides write
3782 * There are a limited number (~10) of cache chunks per device so that we don't
3783 @@ -3765,14 +3917,14 @@ static int yaffs_ObjectHasCachedWriteDat
3785 yaffs_ChunkCache *cache;
3786 int nCaches = obj->myDev->nShortOpCaches;
3789 for(i = 0; i < nCaches; i++){
3790 cache = &dev->srCache[i];
3791 if (cache->object == obj &&
3800 @@ -3838,7 +3990,7 @@ void yaffs_FlushEntireDeviceCache(yaffs_
3802 int nCaches = dev->nShortOpCaches;
3806 /* Find a dirty object in the cache and flush it...
3807 * until there are no further dirty objects.
3809 @@ -3848,53 +4000,33 @@ void yaffs_FlushEntireDeviceCache(yaffs_
3810 if (dev->srCache[i].object &&
3811 dev->srCache[i].dirty)
3812 obj = dev->srCache[i].object;
3817 yaffs_FlushFilesChunkCache(obj);
3826 /* Grab us a cache chunk for use.
3827 - * First look for an empty one.
3828 + * First look for an empty one.
3829 * Then look for the least recently used non-dirty one.
3830 * Then look for the least recently used dirty one...., flush and look again.
3832 static yaffs_ChunkCache *yaffs_GrabChunkCacheWorker(yaffs_Device * dev)
3838 if (dev->nShortOpCaches > 0) {
3839 for (i = 0; i < dev->nShortOpCaches; i++) {
3840 - if (!dev->srCache[i].object)
3841 + if (!dev->srCache[i].object)
3842 return &dev->srCache[i];
3848 - usage = 0; /* just to stop the compiler grizzling */
3850 - for (i = 0; i < dev->nShortOpCaches; i++) {
3851 - if (!dev->srCache[i].dirty &&
3852 - ((dev->srCache[i].lastUse < usage && theOne >= 0) ||
3854 - usage = dev->srCache[i].lastUse;
3860 - return theOne >= 0 ? &dev->srCache[theOne] : NULL;
3868 static yaffs_ChunkCache *yaffs_GrabChunkCache(yaffs_Device * dev)
3869 @@ -4032,14 +4164,14 @@ static void yaffs_InvalidateWholeChunkCa
3870 static int yaffs_WriteCheckpointValidityMarker(yaffs_Device *dev,int head)
3872 yaffs_CheckpointValidity cp;
3875 memset(&cp,0,sizeof(cp));
3878 cp.structType = sizeof(cp);
3879 cp.magic = YAFFS_MAGIC;
3880 cp.version = YAFFS_CHECKPOINT_VERSION;
3881 cp.head = (head) ? 1 : 0;
3884 return (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp))?
3887 @@ -4048,9 +4180,9 @@ static int yaffs_ReadCheckpointValidityM
3889 yaffs_CheckpointValidity cp;
3893 ok = (yaffs_CheckpointRead(dev,&cp,sizeof(cp)) == sizeof(cp));
3897 ok = (cp.structType == sizeof(cp)) &&
3898 (cp.magic == YAFFS_MAGIC) &&
3899 @@ -4059,20 +4191,20 @@ static int yaffs_ReadCheckpointValidityM
3903 -static void yaffs_DeviceToCheckpointDevice(yaffs_CheckpointDevice *cp,
3904 +static void yaffs_DeviceToCheckpointDevice(yaffs_CheckpointDevice *cp,
3907 cp->nErasedBlocks = dev->nErasedBlocks;
3908 cp->allocationBlock = dev->allocationBlock;
3909 cp->allocationPage = dev->allocationPage;
3910 cp->nFreeChunks = dev->nFreeChunks;
3913 cp->nDeletedFiles = dev->nDeletedFiles;
3914 cp->nUnlinkedFiles = dev->nUnlinkedFiles;
3915 cp->nBackgroundDeletions = dev->nBackgroundDeletions;
3916 cp->sequenceNumber = dev->sequenceNumber;
3917 cp->oldestDirtySequence = dev->oldestDirtySequence;
3922 static void yaffs_CheckpointDeviceToDevice(yaffs_Device *dev,
3923 @@ -4082,7 +4214,7 @@ static void yaffs_CheckpointDeviceToDevi
3924 dev->allocationBlock = cp->allocationBlock;
3925 dev->allocationPage = cp->allocationPage;
3926 dev->nFreeChunks = cp->nFreeChunks;
3929 dev->nDeletedFiles = cp->nDeletedFiles;
3930 dev->nUnlinkedFiles = cp->nUnlinkedFiles;
3931 dev->nBackgroundDeletions = cp->nBackgroundDeletions;
3932 @@ -4098,20 +4230,20 @@ static int yaffs_WriteCheckpointDevice(y
3933 __u32 nBlocks = (dev->internalEndBlock - dev->internalStartBlock + 1);
3938 /* Write device runtime values*/
3939 yaffs_DeviceToCheckpointDevice(&cp,dev);
3940 cp.structType = sizeof(cp);
3943 ok = (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp));
3946 /* Write block info */
3948 nBytes = nBlocks * sizeof(yaffs_BlockInfo);
3949 ok = (yaffs_CheckpointWrite(dev,dev->blockInfo,nBytes) == nBytes);
3952 - /* Write chunk bits */
3954 + /* Write chunk bits */
3956 nBytes = nBlocks * dev->chunkBitmapStride;
3957 ok = (yaffs_CheckpointWrite(dev,dev->chunkBits,nBytes) == nBytes);
3958 @@ -4126,28 +4258,28 @@ static int yaffs_ReadCheckpointDevice(ya
3960 __u32 nBlocks = (dev->internalEndBlock - dev->internalStartBlock + 1);
3966 ok = (yaffs_CheckpointRead(dev,&cp,sizeof(cp)) == sizeof(cp));
3971 if(cp.structType != sizeof(cp))
3977 yaffs_CheckpointDeviceToDevice(dev,&cp);
3980 nBytes = nBlocks * sizeof(yaffs_BlockInfo);
3983 ok = (yaffs_CheckpointRead(dev,dev->blockInfo,nBytes) == nBytes);
3988 nBytes = nBlocks * dev->chunkBitmapStride;
3991 ok = (yaffs_CheckpointRead(dev,dev->chunkBits,nBytes) == nBytes);
3997 @@ -4157,7 +4289,7 @@ static void yaffs_ObjectToCheckpointObje
3999 cp->objectId = obj->objectId;
4000 cp->parentId = (obj->parent) ? obj->parent->objectId : 0;
4001 - cp->chunkId = obj->chunkId;
4002 + cp->hdrChunk = obj->hdrChunk;
4003 cp->variantType = obj->variantType;
4004 cp->deleted = obj->deleted;
4005 cp->softDeleted = obj->softDeleted;
4006 @@ -4167,7 +4299,7 @@ static void yaffs_ObjectToCheckpointObje
4007 cp->unlinkAllowed = obj->unlinkAllowed;
4008 cp->serial = obj->serial;
4009 cp->nDataChunks = obj->nDataChunks;
4012 if(obj->variantType == YAFFS_OBJECT_TYPE_FILE)
4013 cp->fileSizeOrEquivalentObjectId = obj->variant.fileVariant.fileSize;
4014 else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK)
4015 @@ -4178,9 +4310,9 @@ static void yaffs_CheckpointObjectToObje
4018 yaffs_Object *parent;
4021 obj->objectId = cp->objectId;
4025 parent = yaffs_FindOrCreateObjectByNumber(
4027 @@ -4188,11 +4320,11 @@ static void yaffs_CheckpointObjectToObje
4028 YAFFS_OBJECT_TYPE_DIRECTORY);
4034 yaffs_AddObjectToDirectory(parent, obj);
4036 - obj->chunkId = cp->chunkId;
4037 + obj->hdrChunk = cp->hdrChunk;
4038 obj->variantType = cp->variantType;
4039 obj->deleted = cp->deleted;
4040 obj->softDeleted = cp->softDeleted;
4041 @@ -4202,13 +4334,13 @@ static void yaffs_CheckpointObjectToObje
4042 obj->unlinkAllowed = cp->unlinkAllowed;
4043 obj->serial = cp->serial;
4044 obj->nDataChunks = cp->nDataChunks;
4047 if(obj->variantType == YAFFS_OBJECT_TYPE_FILE)
4048 obj->variant.fileVariant.fileSize = cp->fileSizeOrEquivalentObjectId;
4049 else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK)
4050 obj->variant.hardLinkVariant.equivalentObjectId = cp->fileSizeOrEquivalentObjectId;
4052 - if(obj->objectId >= YAFFS_NOBJECT_BUCKETS)
4053 + if(obj->hdrChunk > 0)
4054 obj->lazyLoaded = 1;
4057 @@ -4220,7 +4352,11 @@ static int yaffs_CheckpointTnodeWorker(y
4059 yaffs_Device *dev = in->myDev;
4061 - int nTnodeBytes = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
4062 + int tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
4064 + if(tnodeSize < sizeof(yaffs_Tnode))
4065 + tnodeSize = sizeof(yaffs_Tnode);
4070 @@ -4235,10 +4371,9 @@ static int yaffs_CheckpointTnodeWorker(y
4072 } else if (level == 0) {
4073 __u32 baseOffset = chunkOffset << YAFFS_TNODES_LEVEL0_BITS;
4074 - /* printf("write tnode at %d\n",baseOffset); */
4075 ok = (yaffs_CheckpointWrite(dev,&baseOffset,sizeof(baseOffset)) == sizeof(baseOffset));
4077 - ok = (yaffs_CheckpointWrite(dev,tn,nTnodeBytes) == nTnodeBytes);
4078 + ok = (yaffs_CheckpointWrite(dev,tn,tnodeSize) == tnodeSize);
4082 @@ -4250,17 +4385,17 @@ static int yaffs_WriteCheckpointTnodes(y
4084 __u32 endMarker = ~0;
4088 if(obj->variantType == YAFFS_OBJECT_TYPE_FILE){
4089 ok = yaffs_CheckpointTnodeWorker(obj,
4090 obj->variant.fileVariant.top,
4091 obj->variant.fileVariant.topLevel,
4094 - ok = (yaffs_CheckpointWrite(obj->myDev,&endMarker,sizeof(endMarker)) ==
4095 + ok = (yaffs_CheckpointWrite(obj->myDev,&endMarker,sizeof(endMarker)) ==
4103 @@ -4272,70 +4407,72 @@ static int yaffs_ReadCheckpointTnodes(ya
4104 yaffs_FileStructure *fileStructPtr = &obj->variant.fileVariant;
4107 + int tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
4109 - ok = (yaffs_CheckpointRead(dev,&baseChunk,sizeof(baseChunk)) == sizeof(baseChunk));
4110 + if(tnodeSize < sizeof(yaffs_Tnode))
4111 + tnodeSize = sizeof(yaffs_Tnode);
4113 + ok = (yaffs_CheckpointRead(dev,&baseChunk,sizeof(baseChunk)) == sizeof(baseChunk));
4115 while(ok && (~baseChunk)){
4117 /* Read level 0 tnode */
4120 - /* printf("read tnode at %d\n",baseChunk); */
4123 tn = yaffs_GetTnodeRaw(dev);
4125 - ok = (yaffs_CheckpointRead(dev,tn,(dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8) ==
4126 - (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8);
4127 + ok = (yaffs_CheckpointRead(dev,tn,tnodeSize) == tnodeSize);
4133 ok = yaffs_AddOrFindLevel0Tnode(dev,
4143 ok = (yaffs_CheckpointRead(dev,&baseChunk,sizeof(baseChunk)) == sizeof(baseChunk));
4148 T(YAFFS_TRACE_CHECKPOINT,(
4149 TSTR("Checkpoint read tnodes %d records, last %d. ok %d" TENDSTR),
4150 nread,baseChunk,ok));
4152 - return ok ? 1 : 0;
4153 + return ok ? 1 : 0;
4158 static int yaffs_WriteCheckpointObjects(yaffs_Device *dev)
4161 - yaffs_CheckpointObject cp;
4164 - struct list_head *lh;
4165 + yaffs_CheckpointObject cp;
4168 + struct ylist_head *lh;
4171 - /* Iterate through the objects in each hash entry,
4173 + /* Iterate through the objects in each hash entry,
4174 * dumping them to the checkpointing stream.
4177 - for(i = 0; ok && i < YAFFS_NOBJECT_BUCKETS; i++){
4178 - list_for_each(lh, &dev->objectBucket[i].list) {
4180 - obj = list_entry(lh, yaffs_Object, hashLink);
4181 - if (!obj->deferedFree) {
4182 - yaffs_ObjectToCheckpointObject(&cp,obj);
4183 - cp.structType = sizeof(cp);
4186 + for(i = 0; ok && i < YAFFS_NOBJECT_BUCKETS; i++){
4187 + ylist_for_each(lh, &dev->objectBucket[i].list) {
4189 + obj = ylist_entry(lh, yaffs_Object, hashLink);
4190 + if (!obj->deferedFree) {
4191 + yaffs_ObjectToCheckpointObject(&cp,obj);
4192 + cp.structType = sizeof(cp);
4194 T(YAFFS_TRACE_CHECKPOINT,(
4195 TSTR("Checkpoint write object %d parent %d type %d chunk %d obj addr %x" TENDSTR),
4196 - cp.objectId,cp.parentId,cp.variantType,cp.chunkId,(unsigned) obj));
4197 + cp.objectId,cp.parentId,cp.variantType,cp.hdrChunk,(unsigned) obj));
4199 ok = (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp));
4202 if(ok && obj->variantType == YAFFS_OBJECT_TYPE_FILE){
4203 ok = yaffs_WriteCheckpointTnodes(obj);
4205 @@ -4343,14 +4480,14 @@ static int yaffs_WriteCheckpointObjects(
4211 /* Dump end of list */
4212 memset(&cp,0xFF,sizeof(yaffs_CheckpointObject));
4213 cp.structType = sizeof(cp);
4217 ok = (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp));
4223 @@ -4361,7 +4498,7 @@ static int yaffs_ReadCheckpointObjects(y
4226 yaffs_Object *hardList = NULL;
4229 while(ok && !done) {
4230 ok = (yaffs_CheckpointRead(dev,&cp,sizeof(cp)) == sizeof(cp));
4231 if(cp.structType != sizeof(cp)) {
4232 @@ -4369,9 +4506,9 @@ static int yaffs_ReadCheckpointObjects(y
4233 cp.structType,sizeof(cp),ok));
4238 T(YAFFS_TRACE_CHECKPOINT,(TSTR("Checkpoint read object %d parent %d type %d chunk %d " TENDSTR),
4239 - cp.objectId,cp.parentId,cp.variantType,cp.chunkId));
4240 + cp.objectId,cp.parentId,cp.variantType,cp.hdrChunk));
4242 if(ok && cp.objectId == ~0)
4244 @@ -4380,21 +4517,21 @@ static int yaffs_ReadCheckpointObjects(y
4246 yaffs_CheckpointObjectToObject(obj,&cp);
4247 if(obj->variantType == YAFFS_OBJECT_TYPE_FILE) {
4248 - ok = yaffs_ReadCheckpointTnodes(obj);
4249 - } else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) {
4250 - obj->hardLinks.next =
4251 - (struct list_head *)
4256 + ok = yaffs_ReadCheckpointTnodes(obj);
4257 + } else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) {
4258 + obj->hardLinks.next =
4259 + (struct ylist_head *)
4270 yaffs_HardlinkFixup(dev,hardList);
4276 @@ -4402,14 +4539,14 @@ static int yaffs_WriteCheckpointSum(yaff
4278 __u32 checkpointSum;
4282 yaffs_GetCheckpointSum(dev,&checkpointSum);
4285 ok = (yaffs_CheckpointWrite(dev,&checkpointSum,sizeof(checkpointSum)) == sizeof(checkpointSum));
4295 @@ -4418,17 +4555,17 @@ static int yaffs_ReadCheckpointSum(yaffs
4296 __u32 checkpointSum0;
4297 __u32 checkpointSum1;
4301 yaffs_GetCheckpointSum(dev,&checkpointSum0);
4304 ok = (yaffs_CheckpointRead(dev,&checkpointSum1,sizeof(checkpointSum1)) == sizeof(checkpointSum1));
4311 if(checkpointSum0 != checkpointSum1)
4318 @@ -4437,15 +4574,15 @@ static int yaffs_WriteCheckpointData(yaf
4324 if(dev->skipCheckpointWrite || !dev->isYaffs2){
4325 T(YAFFS_TRACE_CHECKPOINT,(TSTR("skipping checkpoint write" TENDSTR)));
4331 ok = yaffs_CheckpointOpen(dev,1);
4335 T(YAFFS_TRACE_CHECKPOINT,(TSTR("write checkpoint validity" TENDSTR)));
4336 ok = yaffs_WriteCheckpointValidityMarker(dev,1);
4337 @@ -4462,18 +4599,18 @@ static int yaffs_WriteCheckpointData(yaf
4338 T(YAFFS_TRACE_CHECKPOINT,(TSTR("write checkpoint validity" TENDSTR)));
4339 ok = yaffs_WriteCheckpointValidityMarker(dev,0);
4344 ok = yaffs_WriteCheckpointSum(dev);
4350 if(!yaffs_CheckpointClose(dev))
4355 dev->isCheckpointed = 1;
4358 dev->isCheckpointed = 0;
4360 return dev->isCheckpointed;
4361 @@ -4482,17 +4619,17 @@ static int yaffs_WriteCheckpointData(yaf
4362 static int yaffs_ReadCheckpointData(yaffs_Device *dev)
4367 if(dev->skipCheckpointRead || !dev->isYaffs2){
4368 T(YAFFS_TRACE_CHECKPOINT,(TSTR("skipping checkpoint read" TENDSTR)));
4374 ok = yaffs_CheckpointOpen(dev,0); /* open for read */
4378 - T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint validity" TENDSTR)));
4379 + T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint validity" TENDSTR)));
4380 ok = yaffs_ReadCheckpointValidityMarker(dev,1);
4383 @@ -4500,14 +4637,14 @@ static int yaffs_ReadCheckpointData(yaff
4384 ok = yaffs_ReadCheckpointDevice(dev);
4387 - T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint objects" TENDSTR)));
4388 + T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint objects" TENDSTR)));
4389 ok = yaffs_ReadCheckpointObjects(dev);
4392 T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint validity" TENDSTR)));
4393 ok = yaffs_ReadCheckpointValidityMarker(dev,0);
4398 ok = yaffs_ReadCheckpointSum(dev);
4399 T(YAFFS_TRACE_CHECKPOINT,(TSTR("read checkpoint checksum %d" TENDSTR),ok));
4400 @@ -4518,7 +4655,7 @@ static int yaffs_ReadCheckpointData(yaff
4403 dev->isCheckpointed = 1;
4406 dev->isCheckpointed = 0;
4409 @@ -4527,7 +4664,7 @@ static int yaffs_ReadCheckpointData(yaff
4411 static void yaffs_InvalidateCheckpoint(yaffs_Device *dev)
4413 - if(dev->isCheckpointed ||
4414 + if(dev->isCheckpointed ||
4415 dev->blocksInCheckpoint > 0){
4416 dev->isCheckpointed = 0;
4417 yaffs_CheckpointInvalidateStream(dev);
4418 @@ -4550,7 +4687,7 @@ int yaffs_CheckpointSave(yaffs_Device *d
4419 yaffs_InvalidateCheckpoint(dev);
4420 yaffs_WriteCheckpointData(dev);
4424 T(YAFFS_TRACE_ALWAYS,(TSTR("save exit: isCheckpointed %d"TENDSTR),dev->isCheckpointed));
4426 return dev->isCheckpointed;
4427 @@ -4560,7 +4697,7 @@ int yaffs_CheckpointRestore(yaffs_Device
4430 T(YAFFS_TRACE_CHECKPOINT,(TSTR("restore entry: isCheckpointed %d"TENDSTR),dev->isCheckpointed));
4433 retval = yaffs_ReadCheckpointData(dev);
4435 if(dev->isCheckpointed){
4436 @@ -4570,7 +4707,7 @@ int yaffs_CheckpointRestore(yaffs_Device
4439 T(YAFFS_TRACE_CHECKPOINT,(TSTR("restore exit: isCheckpointed %d"TENDSTR),dev->isCheckpointed));
4445 @@ -4589,7 +4726,7 @@ int yaffs_ReadDataFromFile(yaffs_Object
4454 @@ -4606,7 +4743,7 @@ int yaffs_ReadDataFromFile(yaffs_Object
4457 /* OK now check for the curveball where the start and end are in
4461 if ((start + n) < dev->nDataBytesPerChunk) {
4463 @@ -4617,10 +4754,10 @@ int yaffs_ReadDataFromFile(yaffs_Object
4464 cache = yaffs_FindChunkCache(in, chunk);
4466 /* If the chunk is already in the cache or it is less than a whole chunk
4467 - * then use the cache (if there is caching)
4468 + * or we're using inband tags then use the cache (if there is caching)
4469 * else bypass the cache.
4471 - if (cache || nToCopy != dev->nDataBytesPerChunk) {
4472 + if (cache || nToCopy != dev->nDataBytesPerChunk || dev->inbandTags) {
4473 if (dev->nShortOpCaches > 0) {
4475 /* If we can't find the data in the cache, then load it up. */
4476 @@ -4641,14 +4778,9 @@ int yaffs_ReadDataFromFile(yaffs_Object
4480 -#ifdef CONFIG_YAFFS_WINCE
4481 - yfsd_UnlockYAFFS(TRUE);
4484 memcpy(buffer, &cache->data[start], nToCopy);
4486 -#ifdef CONFIG_YAFFS_WINCE
4487 - yfsd_LockYAFFS(TRUE);
4491 /* Read into the local buffer then copy..*/
4492 @@ -4657,41 +4789,19 @@ int yaffs_ReadDataFromFile(yaffs_Object
4493 yaffs_GetTempBuffer(dev, __LINE__);
4494 yaffs_ReadChunkDataFromObject(in, chunk,
4496 -#ifdef CONFIG_YAFFS_WINCE
4497 - yfsd_UnlockYAFFS(TRUE);
4500 memcpy(buffer, &localBuffer[start], nToCopy);
4502 -#ifdef CONFIG_YAFFS_WINCE
4503 - yfsd_LockYAFFS(TRUE);
4506 yaffs_ReleaseTempBuffer(dev, localBuffer,
4511 -#ifdef CONFIG_YAFFS_WINCE
4512 - __u8 *localBuffer = yaffs_GetTempBuffer(dev, __LINE__);
4514 - /* Under WinCE can't do direct transfer. Need to use a local buffer.
4515 - * This is because we otherwise screw up WinCE's memory mapper
4517 - yaffs_ReadChunkDataFromObject(in, chunk, localBuffer);
4519 -#ifdef CONFIG_YAFFS_WINCE
4520 - yfsd_UnlockYAFFS(TRUE);
4522 - memcpy(buffer, localBuffer, dev->nDataBytesPerChunk);
4524 -#ifdef CONFIG_YAFFS_WINCE
4525 - yfsd_LockYAFFS(TRUE);
4526 - yaffs_ReleaseTempBuffer(dev, localBuffer, __LINE__);
4530 /* A full chunk. Read directly into the supplied buffer. */
4531 yaffs_ReadChunkDataFromObject(in, chunk, buffer);
4537 @@ -4709,14 +4819,15 @@ int yaffs_WriteDataToFile(yaffs_Object *
4547 - int startOfWrite = offset;
4548 - int chunkWritten = 0;
4553 + int startOfWrite = offset;
4554 + int chunkWritten = 0;
4560 @@ -4726,6 +4837,12 @@ int yaffs_WriteDataToFile(yaffs_Object *
4561 //chunk = offset / dev->nDataBytesPerChunk + 1;
4562 //start = offset % dev->nDataBytesPerChunk;
4563 yaffs_AddrToChunk(dev,offset,&chunk,&start);
4565 + if(chunk * dev->nDataBytesPerChunk + start != offset ||
4566 + start >= dev->nDataBytesPerChunk){
4567 + T(YAFFS_TRACE_ERROR,(TSTR("AddrToChunk of offset %d gives chunk %d start %d"TENDSTR),
4568 + (int)offset, chunk,start));
4572 /* OK now check for the curveball where the start and end are in
4573 @@ -4740,9 +4857,12 @@ int yaffs_WriteDataToFile(yaffs_Object *
4574 * we need to write back as much as was there before.
4578 - in->variant.fileVariant.fileSize -
4579 - ((chunk - 1) * dev->nDataBytesPerChunk);
4580 + chunkStart = ((chunk - 1) * dev->nDataBytesPerChunk);
4582 + if(chunkStart > in->variant.fileVariant.fileSize)
4583 + nBytesRead = 0; /* Past end of file */
4585 + nBytesRead = in->variant.fileVariant.fileSize - chunkStart;
4587 if (nBytesRead > dev->nDataBytesPerChunk) {
4588 nBytesRead = dev->nDataBytesPerChunk;
4589 @@ -4751,19 +4871,24 @@ int yaffs_WriteDataToFile(yaffs_Object *
4592 (start + n)) ? nBytesRead : (start + n);
4594 + if(nToWriteBack < 0 || nToWriteBack > dev->nDataBytesPerChunk)
4598 nToCopy = dev->nDataBytesPerChunk - start;
4599 nToWriteBack = dev->nDataBytesPerChunk;
4602 - if (nToCopy != dev->nDataBytesPerChunk) {
4603 - /* An incomplete start or end chunk (or maybe both start and end chunk) */
4604 + if (nToCopy != dev->nDataBytesPerChunk || dev->inbandTags) {
4605 + /* An incomplete start or end chunk (or maybe both start and end chunk),
4606 + * or we're using inband tags, so we want to use the cache buffers.
4608 if (dev->nShortOpCaches > 0) {
4609 yaffs_ChunkCache *cache;
4610 /* If we can't find the data in the cache, then load the cache */
4611 cache = yaffs_FindChunkCache(in, chunk);
4615 && yaffs_CheckSpaceForAllocation(in->
4617 @@ -4776,28 +4901,24 @@ int yaffs_WriteDataToFile(yaffs_Object *
4624 !yaffs_CheckSpaceForAllocation(in->myDev)){
4625 /* Drop the cache if it was a read cache item and
4626 * no space check has been made for it.
4633 yaffs_UseChunkCache(dev, cache, 1);
4635 -#ifdef CONFIG_YAFFS_WINCE
4636 - yfsd_UnlockYAFFS(TRUE);
4640 memcpy(&cache->data[start], buffer,
4643 -#ifdef CONFIG_YAFFS_WINCE
4644 - yfsd_LockYAFFS(TRUE);
4648 cache->nBytes = nToWriteBack;
4650 @@ -4825,15 +4946,10 @@ int yaffs_WriteDataToFile(yaffs_Object *
4651 yaffs_ReadChunkDataFromObject(in, chunk,
4654 -#ifdef CONFIG_YAFFS_WINCE
4655 - yfsd_UnlockYAFFS(TRUE);
4659 memcpy(&localBuffer[start], buffer, nToCopy);
4661 -#ifdef CONFIG_YAFFS_WINCE
4662 - yfsd_LockYAFFS(TRUE);
4665 yaffs_WriteChunkDataToObject(in, chunk,
4667 @@ -4846,31 +4962,15 @@ int yaffs_WriteDataToFile(yaffs_Object *
4672 -#ifdef CONFIG_YAFFS_WINCE
4673 - /* Under WinCE can't do direct transfer. Need to use a local buffer.
4674 - * This is because we otherwise screw up WinCE's memory mapper
4676 - __u8 *localBuffer = yaffs_GetTempBuffer(dev, __LINE__);
4677 -#ifdef CONFIG_YAFFS_WINCE
4678 - yfsd_UnlockYAFFS(TRUE);
4680 - memcpy(localBuffer, buffer, dev->nDataBytesPerChunk);
4681 -#ifdef CONFIG_YAFFS_WINCE
4682 - yfsd_LockYAFFS(TRUE);
4685 - yaffs_WriteChunkDataToObject(in, chunk, localBuffer,
4686 - dev->nDataBytesPerChunk,
4688 - yaffs_ReleaseTempBuffer(dev, localBuffer, __LINE__);
4690 /* A full chunk. Write directly from the supplied buffer. */
4695 yaffs_WriteChunkDataToObject(in, chunk, buffer,
4696 dev->nDataBytesPerChunk,
4700 /* Since we've overwritten the cached data, we better invalidate it. */
4701 yaffs_InvalidateChunkCache(in, chunk);
4703 @@ -4943,9 +5043,9 @@ int yaffs_ResizeFile(yaffs_Object * in,
4706 int oldFileSize = in->variant.fileVariant.fileSize;
4707 - int newSizeOfPartialChunk;
4708 + __u32 newSizeOfPartialChunk;
4712 yaffs_Device *dev = in->myDev;
4714 yaffs_AddrToChunk(dev, newSize, &newFullChunks, &newSizeOfPartialChunk);
4715 @@ -4953,23 +5053,23 @@ int yaffs_ResizeFile(yaffs_Object * in,
4716 yaffs_FlushFilesChunkCache(in);
4717 yaffs_InvalidateWholeChunkCache(in);
4719 - yaffs_CheckGarbageCollection(dev);
4720 + yaffs_CheckGarbageCollection(dev);
4722 - if (in->variantType != YAFFS_OBJECT_TYPE_FILE) {
4723 - return yaffs_GetFileSize(in);
4725 + if (in->variantType != YAFFS_OBJECT_TYPE_FILE) {
4726 + return YAFFS_FAIL;
4729 - if (newSize == oldFileSize) {
4730 - return oldFileSize;
4732 + if (newSize == oldFileSize) {
4736 - if (newSize < oldFileSize) {
4737 + if (newSize < oldFileSize) {
4739 yaffs_PruneResizedChunks(in, newSize);
4741 if (newSizeOfPartialChunk != 0) {
4742 int lastChunk = 1 + newFullChunks;
4745 __u8 *localBuffer = yaffs_GetTempBuffer(dev, __LINE__);
4747 /* Got to read and rewrite the last chunk with its new size and zero pad */
4748 @@ -4993,19 +5093,20 @@ int yaffs_ResizeFile(yaffs_Object * in,
4749 in->variant.fileVariant.fileSize = newSize;
4756 /* Write a new object header.
4757 * show we've shrunk the file, if need be
4758 * Do this only if the file is not in the deleted directories.
4760 - if (in->parent->objectId != YAFFS_OBJECTID_UNLINKED &&
4762 + in->parent->objectId != YAFFS_OBJECTID_UNLINKED &&
4763 in->parent->objectId != YAFFS_OBJECTID_DELETED) {
4764 yaffs_UpdateObjectHeader(in, NULL, 0,
4765 (newSize < oldFileSize) ? 1 : 0, 0);
4772 loff_t yaffs_GetFileSize(yaffs_Object * obj)
4773 @@ -5058,13 +5159,13 @@ static int yaffs_DoGenericObjectDeletion
4775 if (in->myDev->isYaffs2 && (in->parent != in->myDev->deletedDir)) {
4776 /* Move to the unlinked directory so we have a record that it was deleted. */
4777 - yaffs_ChangeObjectName(in, in->myDev->deletedDir,"deleted", 0, 0);
4778 + yaffs_ChangeObjectName(in, in->myDev->deletedDir,_Y("deleted"), 0, 0);
4782 yaffs_RemoveObjectFromDirectory(in);
4783 - yaffs_DeleteChunk(in->myDev, in->chunkId, 1, __LINE__);
4785 + yaffs_DeleteChunk(in->myDev, in->hdrChunk, 1, __LINE__);
4788 yaffs_FreeObject(in);
4790 @@ -5075,62 +5176,66 @@ static int yaffs_DoGenericObjectDeletion
4791 * and the inode associated with the file.
4792 * It does not delete the links associated with the file.
4795 static int yaffs_UnlinkFile(yaffs_Object * in)
4799 int immediateDeletion = 0;
4803 - if (!in->myInode) {
4804 - immediateDeletion = 1;
4807 + if (!in->myInode) {
4808 + immediateDeletion = 1;
4811 - if (in->inUse <= 0) {
4812 - immediateDeletion = 1;
4815 + if (in->inUse <= 0) {
4816 + immediateDeletion = 1;
4819 - if (immediateDeletion) {
4821 - yaffs_ChangeObjectName(in, in->myDev->deletedDir,
4823 - T(YAFFS_TRACE_TRACING,
4824 - (TSTR("yaffs: immediate deletion of file %d" TENDSTR),
4827 - in->myDev->nDeletedFiles++;
4828 - if (0 && in->myDev->isYaffs2) {
4829 - yaffs_ResizeFile(in, 0);
4831 - yaffs_SoftDeleteFile(in);
4834 - yaffs_ChangeObjectName(in, in->myDev->unlinkedDir,
4835 - "unlinked", 0, 0);
4838 + if (immediateDeletion) {
4840 + yaffs_ChangeObjectName(in, in->myDev->deletedDir,
4841 + _Y("deleted"), 0, 0);
4842 + T(YAFFS_TRACE_TRACING,
4843 + (TSTR("yaffs: immediate deletion of file %d" TENDSTR),
4846 + in->myDev->nDeletedFiles++;
4847 + if (1 || in->myDev->isYaffs2) {
4848 + yaffs_ResizeFile(in, 0);
4850 + yaffs_SoftDeleteFile(in);
4853 + yaffs_ChangeObjectName(in, in->myDev->unlinkedDir,
4854 + _Y("unlinked"), 0, 0);
4861 int yaffs_DeleteFile(yaffs_Object * in)
4863 int retVal = YAFFS_OK;
4864 + int deleted = in->deleted;
4866 + yaffs_ResizeFile(in,0);
4868 if (in->nDataChunks > 0) {
4869 - /* Use soft deletion if there is data in the file */
4870 + /* Use soft deletion if there is data in the file.
4871 + * That won't be the case if it has been resized to zero.
4873 if (!in->unlinked) {
4874 retVal = yaffs_UnlinkFile(in);
4876 if (retVal == YAFFS_OK && in->unlinked && !in->deleted) {
4878 + in->deleted = deleted = 1;
4879 in->myDev->nDeletedFiles++;
4880 yaffs_SoftDeleteFile(in);
4882 - return in->deleted ? YAFFS_OK : YAFFS_FAIL;
4883 + return deleted ? YAFFS_OK : YAFFS_FAIL;
4885 /* The file has no data chunks so we toss it immediately */
4886 yaffs_FreeTnode(in->myDev, in->variant.fileVariant.top);
4887 @@ -5143,10 +5248,10 @@ int yaffs_DeleteFile(yaffs_Object * in)
4889 static int yaffs_DeleteDirectory(yaffs_Object * in)
4891 - /* First check that the directory is empty. */
4892 - if (list_empty(&in->variant.directoryVariant.children)) {
4893 - return yaffs_DoGenericObjectDeletion(in);
4895 + /* First check that the directory is empty. */
4896 + if (ylist_empty(&in->variant.directoryVariant.children)) {
4897 + return yaffs_DoGenericObjectDeletion(in);
4902 @@ -5161,11 +5266,11 @@ static int yaffs_DeleteSymLink(yaffs_Obj
4904 static int yaffs_DeleteHardLink(yaffs_Object * in)
4906 - /* remove this hardlink from the list assocaited with the equivalent
4909 - list_del(&in->hardLinks);
4910 - return yaffs_DoGenericObjectDeletion(in);
4911 + /* remove this hardlink from the list assocaited with the equivalent
4914 + ylist_del_init(&in->hardLinks);
4915 + return yaffs_DoGenericObjectDeletion(in);
4918 static void yaffs_DestroyObject(yaffs_Object * obj)
4919 @@ -5194,12 +5299,12 @@ static void yaffs_DestroyObject(yaffs_Ob
4920 static int yaffs_UnlinkWorker(yaffs_Object * obj)
4923 - if (obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) {
4924 - return yaffs_DeleteHardLink(obj);
4925 - } else if (!list_empty(&obj->hardLinks)) {
4926 - /* Curve ball: We're unlinking an object that has a hardlink.
4928 - * This problem arises because we are not strictly following
4929 + if (obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) {
4930 + return yaffs_DeleteHardLink(obj);
4931 + } else if (!ylist_empty(&obj->hardLinks)) {
4932 + /* Curve ball: We're unlinking an object that has a hardlink.
4934 + * This problem arises because we are not strictly following
4935 * The Linux link/inode model.
4937 * We can't really delete the object.
4938 @@ -5212,15 +5317,15 @@ static int yaffs_UnlinkWorker(yaffs_Obje
4943 - YCHAR name[YAFFS_MAX_NAME_LENGTH + 1];
4945 + YCHAR name[YAFFS_MAX_NAME_LENGTH + 1];
4947 - hl = list_entry(obj->hardLinks.next, yaffs_Object, hardLinks);
4948 + hl = ylist_entry(obj->hardLinks.next, yaffs_Object, hardLinks);
4950 - list_del_init(&hl->hardLinks);
4951 - list_del_init(&hl->siblings);
4952 + ylist_del_init(&hl->hardLinks);
4953 + ylist_del_init(&hl->siblings);
4955 - yaffs_GetObjectName(hl, name, YAFFS_MAX_NAME_LENGTH + 1);
4956 + yaffs_GetObjectName(hl, name, YAFFS_MAX_NAME_LENGTH + 1);
4958 retVal = yaffs_ChangeObjectName(obj, hl->parent, name, 0, 0);
4960 @@ -5313,7 +5418,7 @@ static void yaffs_HardlinkFixup(yaffs_De
4968 hardList = (yaffs_Object *) (hardList->hardLinks.next);
4969 @@ -5322,18 +5427,18 @@ static void yaffs_HardlinkFixup(yaffs_De
4970 hl->variant.hardLinkVariant.
4971 equivalentObjectId);
4974 - /* Add the hardlink pointers */
4975 - hl->variant.hardLinkVariant.equivalentObject = in;
4976 - list_add(&hl->hardLinks, &in->hardLinks);
4978 - /* Todo Need to report/handle this better.
4979 - * Got a problem... hardlink to a non-existant object
4981 - hl->variant.hardLinkVariant.equivalentObject = NULL;
4982 - INIT_LIST_HEAD(&hl->hardLinks);
4984 + /* Add the hardlink pointers */
4985 + hl->variant.hardLinkVariant.equivalentObject = in;
4986 + ylist_add(&hl->hardLinks, &in->hardLinks);
4988 + /* Todo Need to report/handle this better.
4989 + * Got a problem... hardlink to a non-existant object
4991 + hl->variant.hardLinkVariant.equivalentObject = NULL;
4992 + YINIT_LIST_HEAD(&hl->hardLinks);
4999 @@ -5355,6 +5460,42 @@ static int ybicmp(const void *a, const v
5004 +struct yaffs_ShadowFixerStruct {
5007 + struct yaffs_ShadowFixerStruct *next;
5011 +static void yaffs_StripDeletedObjects(yaffs_Device *dev)
5014 + * Sort out state of unlinked and deleted objects after scanning.
5016 + struct ylist_head *i;
5017 + struct ylist_head *n;
5020 + /* Soft delete all the unlinked files */
5021 + ylist_for_each_safe(i, n,
5022 + &dev->unlinkedDir->variant.directoryVariant.children) {
5024 + l = ylist_entry(i, yaffs_Object, siblings);
5025 + yaffs_DestroyObject(l);
5029 + ylist_for_each_safe(i, n,
5030 + &dev->deletedDir->variant.directoryVariant.children) {
5032 + l = ylist_entry(i, yaffs_Object, siblings);
5033 + yaffs_DestroyObject(l);
5039 static int yaffs_Scan(yaffs_Device * dev)
5041 yaffs_ExtendedTags tags;
5042 @@ -5362,7 +5503,6 @@ static int yaffs_Scan(yaffs_Device * dev
5046 - int nBlocksToScan = 0;
5050 @@ -5371,27 +5511,20 @@ static int yaffs_Scan(yaffs_Device * dev
5051 yaffs_BlockState state;
5052 yaffs_Object *hardList = NULL;
5053 yaffs_BlockInfo *bi;
5054 - int sequenceNumber;
5055 + __u32 sequenceNumber;
5056 yaffs_ObjectHeader *oh;
5058 yaffs_Object *parent;
5059 - int nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1;
5062 int alloc_failed = 0;
5065 + struct yaffs_ShadowFixerStruct *shadowFixerList = NULL;
5070 - yaffs_BlockIndex *blockIndex = NULL;
5072 - if (dev->isYaffs2) {
5073 - T(YAFFS_TRACE_SCAN,
5074 - (TSTR("yaffs_Scan is not for YAFFS2!" TENDSTR)));
5075 - return YAFFS_FAIL;
5078 - //TODO Throw all the yaffs2 stuuf out of yaffs_Scan since it is only for yaffs1 format.
5083 (TSTR("yaffs_Scan starts intstartblk %d intendblk %d..." TENDSTR),
5084 dev->internalStartBlock, dev->internalEndBlock));
5085 @@ -5400,12 +5533,6 @@ static int yaffs_Scan(yaffs_Device * dev
5087 dev->sequenceNumber = YAFFS_LOWEST_SEQUENCE_NUMBER;
5089 - if (dev->isYaffs2) {
5090 - blockIndex = YMALLOC(nBlocks * sizeof(yaffs_BlockIndex));
5092 - return YAFFS_FAIL;
5095 /* Scan all the blocks to determine their state */
5096 for (blk = dev->internalStartBlock; blk <= dev->internalEndBlock; blk++) {
5097 bi = yaffs_GetBlockInfo(dev, blk);
5098 @@ -5430,70 +5557,21 @@ static int yaffs_Scan(yaffs_Device * dev
5099 (TSTR("Block empty " TENDSTR)));
5100 dev->nErasedBlocks++;
5101 dev->nFreeChunks += dev->nChunksPerBlock;
5102 - } else if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) {
5104 - /* Determine the highest sequence number */
5105 - if (dev->isYaffs2 &&
5106 - sequenceNumber >= YAFFS_LOWEST_SEQUENCE_NUMBER &&
5107 - sequenceNumber < YAFFS_HIGHEST_SEQUENCE_NUMBER) {
5109 - blockIndex[nBlocksToScan].seq = sequenceNumber;
5110 - blockIndex[nBlocksToScan].block = blk;
5114 - if (sequenceNumber >= dev->sequenceNumber) {
5115 - dev->sequenceNumber = sequenceNumber;
5117 - } else if (dev->isYaffs2) {
5118 - /* TODO: Nasty sequence number! */
5119 - T(YAFFS_TRACE_SCAN,
5121 - ("Block scanning block %d has bad sequence number %d"
5122 - TENDSTR), blk, sequenceNumber));
5129 - /* Sort the blocks
5130 - * Dungy old bubble sort for now...
5132 - if (dev->isYaffs2) {
5133 - yaffs_BlockIndex temp;
5137 - for (i = 0; i < nBlocksToScan; i++)
5138 - for (j = i + 1; j < nBlocksToScan; j++)
5139 - if (blockIndex[i].seq > blockIndex[j].seq) {
5140 - temp = blockIndex[j];
5141 - blockIndex[j] = blockIndex[i];
5142 - blockIndex[i] = temp;
5146 - /* Now scan the blocks looking at the data. */
5147 - if (dev->isYaffs2) {
5148 - startIterator = 0;
5149 - endIterator = nBlocksToScan - 1;
5150 - T(YAFFS_TRACE_SCAN_DEBUG,
5151 - (TSTR("%d blocks to be scanned" TENDSTR), nBlocksToScan));
5153 - startIterator = dev->internalStartBlock;
5154 - endIterator = dev->internalEndBlock;
5156 + startIterator = dev->internalStartBlock;
5157 + endIterator = dev->internalEndBlock;
5159 /* For each block.... */
5160 for (blockIterator = startIterator; !alloc_failed && blockIterator <= endIterator;
5165 - if (dev->isYaffs2) {
5166 - /* get the block to scan in the correct order */
5167 - blk = blockIndex[blockIterator].block;
5169 - blk = blockIterator;
5173 + blk = blockIterator;
5175 bi = yaffs_GetBlockInfo(dev, blk);
5176 state = bi->blockState;
5177 @@ -5511,7 +5589,7 @@ static int yaffs_Scan(yaffs_Device * dev
5179 /* Let's have a good look at this chunk... */
5181 - if (!dev->isYaffs2 && tags.chunkDeleted) {
5182 + if (tags.eccResult == YAFFS_ECC_RESULT_UNFIXED || tags.chunkDeleted) {
5186 @@ -5520,7 +5598,7 @@ static int yaffs_Scan(yaffs_Device * dev
5187 /*T((" %d %d deleted\n",blk,c)); */
5188 } else if (!tags.chunkUsed) {
5189 /* An unassigned chunk in the block
5190 - * This means that either the block is empty or
5191 + * This means that either the block is empty or
5192 * this is the one being allocated from
5195 @@ -5537,21 +5615,9 @@ static int yaffs_Scan(yaffs_Device * dev
5196 state = YAFFS_BLOCK_STATE_ALLOCATING;
5197 dev->allocationBlock = blk;
5198 dev->allocationPage = c;
5199 - dev->allocationBlockFinder = blk;
5200 + dev->allocationBlockFinder = blk;
5201 /* Set it to here to encourage the allocator to go forth from here. */
5203 - /* Yaffs2 sanity check:
5204 - * This should be the one with the highest sequence number
5207 - && (dev->sequenceNumber !=
5208 - bi->sequenceNumber)) {
5209 - T(YAFFS_TRACE_ALWAYS,
5211 - ("yaffs: Allocation block %d was not highest sequence id:"
5212 - " block seq = %d, dev seq = %d"
5213 - TENDSTR), blk,bi->sequenceNumber,dev->sequenceNumber));
5218 dev->nFreeChunks += (dev->nChunksPerBlock - c);
5219 @@ -5569,7 +5635,7 @@ static int yaffs_Scan(yaffs_Device * dev
5220 /* PutChunkIntoFile checks for a clash (two data chunks with
5221 * the same chunkId).
5228 @@ -5577,11 +5643,11 @@ static int yaffs_Scan(yaffs_Device * dev
5229 if(!yaffs_PutChunkIntoFile(in, tags.chunkId, chunk,1))
5235 (tags.chunkId - 1) * dev->nDataBytesPerChunk +
5239 in->variantType == YAFFS_OBJECT_TYPE_FILE
5240 && in->variant.fileVariant.scannedFileSize <
5242 @@ -5613,7 +5679,7 @@ static int yaffs_Scan(yaffs_Device * dev
5244 if (in && in->variantType != oh->type) {
5245 /* This should not happen, but somehow
5246 - * Wev'e ended up with an objectId that has been reused but not yet
5247 + * Wev'e ended up with an objectId that has been reused but not yet
5248 * deleted, and worse still it has changed type. Delete the old object.
5251 @@ -5629,12 +5695,18 @@ static int yaffs_Scan(yaffs_Device * dev
5257 if (in && oh->shadowsObject > 0) {
5258 - yaffs_HandleShadowedObject(dev,
5263 + struct yaffs_ShadowFixerStruct *fixer;
5264 + fixer = YMALLOC(sizeof(struct yaffs_ShadowFixerStruct));
5266 + fixer-> next = shadowFixerList;
5267 + shadowFixerList = fixer;
5268 + fixer->objectId = tags.objectId;
5269 + fixer->shadowedId = oh->shadowsObject;
5274 if (in && in->valid) {
5275 @@ -5643,12 +5715,10 @@ static int yaffs_Scan(yaffs_Device * dev
5276 unsigned existingSerial = in->serial;
5277 unsigned newSerial = tags.serialNumber;
5279 - if (dev->isYaffs2 ||
5280 - ((existingSerial + 1) & 3) ==
5282 + if (((existingSerial + 1) & 3) == newSerial) {
5283 /* Use new one - destroy the exisiting one */
5284 yaffs_DeleteChunk(dev,
5290 @@ -5681,7 +5751,8 @@ static int yaffs_Scan(yaffs_Device * dev
5291 in->yst_ctime = oh->yst_ctime;
5292 in->yst_rdev = oh->yst_rdev;
5294 - in->chunkId = chunk;
5295 + in->hdrChunk = chunk;
5296 + in->serial = tags.serialNumber;
5298 } else if (in && !in->valid) {
5299 /* we need to load this info */
5300 @@ -5705,7 +5776,8 @@ static int yaffs_Scan(yaffs_Device * dev
5301 in->yst_ctime = oh->yst_ctime;
5302 in->yst_rdev = oh->yst_rdev;
5304 - in->chunkId = chunk;
5305 + in->hdrChunk = chunk;
5306 + in->serial = tags.serialNumber;
5308 yaffs_SetObjectName(in, oh->name);
5310 @@ -5720,13 +5792,13 @@ static int yaffs_Scan(yaffs_Device * dev
5311 YAFFS_OBJECT_TYPE_DIRECTORY);
5312 if (parent->variantType ==
5313 YAFFS_OBJECT_TYPE_UNKNOWN) {
5314 - /* Set up as a directory */
5315 - parent->variantType =
5316 - YAFFS_OBJECT_TYPE_DIRECTORY;
5317 - INIT_LIST_HEAD(&parent->variant.
5320 - } else if (parent->variantType !=
5321 + /* Set up as a directory */
5322 + parent->variantType =
5323 + YAFFS_OBJECT_TYPE_DIRECTORY;
5324 + YINIT_LIST_HEAD(&parent->variant.
5327 + } else if (parent->variantType !=
5328 YAFFS_OBJECT_TYPE_DIRECTORY)
5330 /* Hoosterman, another problem....
5331 @@ -5735,8 +5807,7 @@ static int yaffs_Scan(yaffs_Device * dev
5333 T(YAFFS_TRACE_ERROR,
5335 - ("yaffs tragedy: attempting to use non-directory as"
5336 - " a directory in scan. Put in lost+found."
5337 + ("yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found."
5339 parent = dev->lostNFoundDir;
5341 @@ -5752,23 +5823,14 @@ static int yaffs_Scan(yaffs_Device * dev
5342 * Since we might scan a hardlink before its equivalent object is scanned
5343 * we put them all in a list.
5344 * After scanning is complete, we should have all the objects, so we run through this
5345 - * list and fix up all the chains.
5346 + * list and fix up all the chains.
5349 switch (in->variantType) {
5350 - case YAFFS_OBJECT_TYPE_UNKNOWN:
5351 + case YAFFS_OBJECT_TYPE_UNKNOWN:
5352 /* Todo got a problem */
5354 case YAFFS_OBJECT_TYPE_FILE:
5356 - && oh->isShrink) {
5357 - /* Prune back the shrunken chunks */
5358 - yaffs_PruneResizedChunks
5359 - (in, oh->fileSize);
5360 - /* Mark the block as having a shrinkHeader */
5361 - bi->hasShrinkHeader = 1;
5364 if (dev->useHeaderFileSize)
5366 in->variant.fileVariant.
5367 @@ -5778,20 +5840,20 @@ static int yaffs_Scan(yaffs_Device * dev
5369 case YAFFS_OBJECT_TYPE_HARDLINK:
5370 in->variant.hardLinkVariant.
5371 - equivalentObjectId =
5372 - oh->equivalentObjectId;
5373 - in->hardLinks.next =
5374 - (struct list_head *)
5378 + equivalentObjectId =
5379 + oh->equivalentObjectId;
5380 + in->hardLinks.next =
5381 + (struct ylist_head *)
5385 case YAFFS_OBJECT_TYPE_DIRECTORY:
5388 case YAFFS_OBJECT_TYPE_SPECIAL:
5391 - case YAFFS_OBJECT_TYPE_SYMLINK:
5392 + case YAFFS_OBJECT_TYPE_SYMLINK:
5393 in->variant.symLinkVariant.alias =
5394 yaffs_CloneString(oh->alias);
5395 if(!in->variant.symLinkVariant.alias)
5396 @@ -5799,10 +5861,12 @@ static int yaffs_Scan(yaffs_Device * dev
5400 - if (parent == dev->deletedDir) {
5402 + if (parent == dev->deletedDir) {
5403 yaffs_DestroyObject(in);
5404 bi->hasShrinkHeader = 1;
5410 @@ -5823,35 +5887,36 @@ static int yaffs_Scan(yaffs_Device * dev
5415 - YFREE(blockIndex);
5420 /* Ok, we've done all the scanning.
5421 * Fix up the hard link chains.
5422 - * We should now have scanned all the objects, now it's time to add these
5423 + * We should now have scanned all the objects, now it's time to add these
5427 yaffs_HardlinkFixup(dev,hardList);
5429 - /* Handle the unlinked files. Since they were left in an unlinked state we should
5430 - * just delete them.
5433 + /* Fix up any shadowed objects */
5435 - struct list_head *i;
5436 - struct list_head *n;
5439 - /* Soft delete all the unlinked files */
5440 - list_for_each_safe(i, n,
5441 - &dev->unlinkedDir->variant.directoryVariant.
5444 - l = list_entry(i, yaffs_Object, siblings);
5445 - yaffs_DestroyObject(l);
5446 + struct yaffs_ShadowFixerStruct *fixer;
5447 + yaffs_Object *obj;
5449 + while(shadowFixerList){
5450 + fixer = shadowFixerList;
5451 + shadowFixerList = fixer->next;
5452 + /* Complete the rename transaction by deleting the shadowed object
5453 + * then setting the object header to unshadowed.
5455 + obj = yaffs_FindObjectByNumber(dev,fixer->shadowedId);
5457 + yaffs_DestroyObject(obj);
5459 + obj = yaffs_FindObjectByNumber(dev,fixer->objectId);
5461 + yaffs_UpdateObjectHeader(obj,NULL,1,0,0);
5468 @@ -5860,9 +5925,9 @@ static int yaffs_Scan(yaffs_Device * dev
5474 T(YAFFS_TRACE_SCAN, (TSTR("yaffs_Scan ends" TENDSTR)));
5480 @@ -5871,25 +5936,27 @@ static void yaffs_CheckObjectDetailsLoad
5483 yaffs_ObjectHeader *oh;
5484 - yaffs_Device *dev = in->myDev;
5485 + yaffs_Device *dev;
5486 yaffs_ExtendedTags tags;
5488 int alloc_failed = 0;
5497 T(YAFFS_TRACE_SCAN,(TSTR("details for object %d %s loaded" TENDSTR),
5499 in->lazyLoaded ? "not yet" : "already"));
5502 - if(in->lazyLoaded){
5503 + if(in->lazyLoaded && in->hdrChunk > 0){
5505 chunkData = yaffs_GetTempBuffer(dev, __LINE__);
5507 - result = yaffs_ReadChunkWithTagsFromNAND(dev,in->chunkId,chunkData,&tags);
5508 + result = yaffs_ReadChunkWithTagsFromNAND(dev,in->hdrChunk,chunkData,&tags);
5509 oh = (yaffs_ObjectHeader *) chunkData;
5511 in->yst_mode = oh->yst_mode;
5512 @@ -5907,17 +5974,17 @@ static void yaffs_CheckObjectDetailsLoad
5513 in->yst_mtime = oh->yst_mtime;
5514 in->yst_ctime = oh->yst_ctime;
5515 in->yst_rdev = oh->yst_rdev;
5519 yaffs_SetObjectName(in, oh->name);
5522 if(in->variantType == YAFFS_OBJECT_TYPE_SYMLINK){
5523 in->variant.symLinkVariant.alias =
5524 yaffs_CloneString(oh->alias);
5525 if(!in->variant.symLinkVariant.alias)
5526 alloc_failed = 1; /* Not returned to caller */
5530 yaffs_ReleaseTempBuffer(dev,chunkData, __LINE__);
5533 @@ -5938,20 +6005,20 @@ static int yaffs_ScanBackwards(yaffs_Dev
5534 yaffs_BlockState state;
5535 yaffs_Object *hardList = NULL;
5536 yaffs_BlockInfo *bi;
5537 - int sequenceNumber;
5538 + __u32 sequenceNumber;
5539 yaffs_ObjectHeader *oh;
5541 yaffs_Object *parent;
5542 int nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1;
5549 int foundChunksInBlock;
5550 int equivalentObjectId;
5551 int alloc_failed = 0;
5555 yaffs_BlockIndex *blockIndex = NULL;
5556 int altBlockIndex = 0;
5557 @@ -5971,20 +6038,20 @@ static int yaffs_ScanBackwards(yaffs_Dev
5558 dev->sequenceNumber = YAFFS_LOWEST_SEQUENCE_NUMBER;
5560 blockIndex = YMALLOC(nBlocks * sizeof(yaffs_BlockIndex));
5564 blockIndex = YMALLOC_ALT(nBlocks * sizeof(yaffs_BlockIndex));
5571 (TSTR("yaffs_Scan() could not allocate block index!" TENDSTR)));
5576 dev->blocksInCheckpoint = 0;
5579 chunkData = yaffs_GetTempBuffer(dev, __LINE__);
5581 /* Scan all the blocks to determine their state */
5582 @@ -6001,15 +6068,15 @@ static int yaffs_ScanBackwards(yaffs_Dev
5584 if(bi->sequenceNumber == YAFFS_SEQUENCE_CHECKPOINT_DATA)
5585 bi->blockState = state = YAFFS_BLOCK_STATE_CHECKPOINT;
5588 T(YAFFS_TRACE_SCAN_DEBUG,
5589 (TSTR("Block scanning block %d state %d seq %d" TENDSTR), blk,
5590 state, sequenceNumber));
5594 if(state == YAFFS_BLOCK_STATE_CHECKPOINT){
5595 dev->blocksInCheckpoint++;
5598 } else if (state == YAFFS_BLOCK_STATE_DEAD) {
5599 T(YAFFS_TRACE_BAD_BLOCKS,
5600 (TSTR("block %d is bad" TENDSTR), blk));
5601 @@ -6021,8 +6088,7 @@ static int yaffs_ScanBackwards(yaffs_Dev
5602 } else if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) {
5604 /* Determine the highest sequence number */
5605 - if (dev->isYaffs2 &&
5606 - sequenceNumber >= YAFFS_LOWEST_SEQUENCE_NUMBER &&
5607 + if (sequenceNumber >= YAFFS_LOWEST_SEQUENCE_NUMBER &&
5608 sequenceNumber < YAFFS_HIGHEST_SEQUENCE_NUMBER) {
5610 blockIndex[nBlocksToScan].seq = sequenceNumber;
5611 @@ -6033,7 +6099,7 @@ static int yaffs_ScanBackwards(yaffs_Dev
5612 if (sequenceNumber >= dev->sequenceNumber) {
5613 dev->sequenceNumber = sequenceNumber;
5615 - } else if (dev->isYaffs2) {
5617 /* TODO: Nasty sequence number! */
5620 @@ -6053,12 +6119,14 @@ static int yaffs_ScanBackwards(yaffs_Dev
5622 /* Sort the blocks */
5623 #ifndef CONFIG_YAFFS_USE_OWN_SORT
5624 - yaffs_qsort(blockIndex, nBlocksToScan,
5625 - sizeof(yaffs_BlockIndex), ybicmp);
5627 + /* Use qsort now. */
5628 + yaffs_qsort(blockIndex, nBlocksToScan, sizeof(yaffs_BlockIndex), ybicmp);
5632 /* Dungy old bubble sort... */
5635 yaffs_BlockIndex temp;
5638 @@ -6094,22 +6162,22 @@ static int yaffs_ScanBackwards(yaffs_Dev
5639 blk = blockIndex[blockIterator].block;
5641 bi = yaffs_GetBlockInfo(dev, blk);
5646 state = bi->blockState;
5650 /* For each chunk in each block that needs scanning.... */
5651 foundChunksInBlock = 0;
5652 - for (c = dev->nChunksPerBlock - 1;
5653 + for (c = dev->nChunksPerBlock - 1;
5654 !alloc_failed && c >= 0 &&
5655 (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING ||
5656 state == YAFFS_BLOCK_STATE_ALLOCATING); c--) {
5657 - /* Scan backwards...
5658 + /* Scan backwards...
5659 * Read the tags and decide what to do
5663 chunk = blk * dev->nChunksPerBlock + c;
5665 result = yaffs_ReadChunkWithTagsFromNAND(dev, chunk, NULL,
5666 @@ -6123,14 +6191,14 @@ static int yaffs_ScanBackwards(yaffs_Dev
5667 * it is a chunk that was skipped due to failing the erased
5668 * check. Just skip it so that it can be deleted.
5669 * But, more typically, We get here when this is an unallocated
5670 - * chunk and his means that either the block is empty or
5671 + * chunk and his means that either the block is empty or
5672 * this is the one being allocated from
5675 if(foundChunksInBlock)
5677 /* This is a chunk that was skipped due to failing the erased check */
5680 } else if (c == 0) {
5681 /* We're looking at the first chunk in the block so the block is unused */
5682 state = YAFFS_BLOCK_STATE_EMPTY;
5683 @@ -6140,7 +6208,7 @@ static int yaffs_ScanBackwards(yaffs_Dev
5684 state == YAFFS_BLOCK_STATE_ALLOCATING) {
5685 if(dev->sequenceNumber == bi->sequenceNumber) {
5686 /* this is the block being allocated from */
5691 (" Allocating from %d %d"
5692 @@ -6149,34 +6217,41 @@ static int yaffs_ScanBackwards(yaffs_Dev
5693 state = YAFFS_BLOCK_STATE_ALLOCATING;
5694 dev->allocationBlock = blk;
5695 dev->allocationPage = c;
5696 - dev->allocationBlockFinder = blk;
5697 + dev->allocationBlockFinder = blk;
5700 /* This is a partially written block that is not
5701 * the current allocation block. This block must have
5702 * had a write failure, so set up for retirement.
5705 - bi->needsRetiring = 1;
5707 + /* bi->needsRetiring = 1; ??? TODO */
5708 bi->gcPrioritise = 1;
5711 T(YAFFS_TRACE_ALWAYS,
5712 - (TSTR("Partially written block %d being set for retirement" TENDSTR),
5713 + (TSTR("Partially written block %d detected" TENDSTR),
5724 + } else if (tags.eccResult == YAFFS_ECC_RESULT_UNFIXED){
5725 + T(YAFFS_TRACE_SCAN,
5726 + (TSTR(" Unfixed ECC in chunk(%d:%d), chunk ignored"TENDSTR),
5729 - } else if (tags.chunkId > 0) {
5730 + dev->nFreeChunks++;
5732 + }else if (tags.chunkId > 0) {
5733 /* chunkId > 0 so it is a data chunk... */
5734 unsigned int endpos;
5736 (tags.chunkId - 1) * dev->nDataBytesPerChunk;
5739 foundChunksInBlock = 1;
5742 @@ -6191,7 +6266,7 @@ static int yaffs_ScanBackwards(yaffs_Dev
5749 in->variantType == YAFFS_OBJECT_TYPE_FILE
5751 @@ -6202,14 +6277,14 @@ static int yaffs_ScanBackwards(yaffs_Dev
5755 - /* File size is calculated by looking at the data chunks if we have not
5756 + /* File size is calculated by looking at the data chunks if we have not
5757 * seen an object header yet. Stop this practice once we find an object header.
5761 1) * dev->nDataBytesPerChunk +
5765 if (!in->valid && /* have not got an object header yet */
5766 in->variant.fileVariant.
5767 scannedFileSize < endpos) {
5768 @@ -6255,7 +6330,7 @@ static int yaffs_ScanBackwards(yaffs_Dev
5771 /* If we don't have valid info then we need to read the chunk
5772 - * TODO In future we can probably defer reading the chunk and
5773 + * TODO In future we can probably defer reading the chunk and
5774 * living with invalid data until needed.
5777 @@ -6265,6 +6340,12 @@ static int yaffs_ScanBackwards(yaffs_Dev
5780 oh = (yaffs_ObjectHeader *) chunkData;
5782 + if(dev->inbandTags){
5783 + /* Fix up the header if they got corrupted by inband tags */
5784 + oh->shadowsObject = oh->inbandShadowsObject;
5785 + oh->isShrink = oh->inbandIsShrink;
5789 in = yaffs_FindOrCreateObjectByNumber(dev, tags.objectId, oh->type);
5790 @@ -6275,20 +6356,19 @@ static int yaffs_ScanBackwards(yaffs_Dev
5791 /* TODO Hoosterman we have a problem! */
5792 T(YAFFS_TRACE_ERROR,
5794 - ("yaffs tragedy: Could not make object for object %d "
5795 - "at chunk %d during scan"
5796 + ("yaffs tragedy: Could not make object for object %d at chunk %d during scan"
5797 TENDSTR), tags.objectId, chunk));
5802 /* We have already filled this one.
5803 - * We have a duplicate that will be discarded, but
5804 + * We have a duplicate that will be discarded, but
5805 * we first have to suck out resize info if it is a file.
5808 - if ((in->variantType == YAFFS_OBJECT_TYPE_FILE) &&
5810 + if ((in->variantType == YAFFS_OBJECT_TYPE_FILE) &&
5812 oh-> type == YAFFS_OBJECT_TYPE_FILE)||
5813 (tags.extraHeaderInfoAvailable &&
5814 tags.extraObjectType == YAFFS_OBJECT_TYPE_FILE))
5815 @@ -6300,7 +6380,9 @@ static int yaffs_ScanBackwards(yaffs_Dev
5817 parentObjectId : tags.
5818 extraParentObjectId;
5819 - unsigned isShrink =
5823 (oh) ? oh->isShrink : tags.
5824 extraIsShrinkHeader;
5826 @@ -6339,7 +6421,7 @@ static int yaffs_ScanBackwards(yaffs_Dev
5827 YAFFS_OBJECTID_LOSTNFOUND)) {
5828 /* We only load some info, don't fiddle with directory structure */
5833 in->variantType = oh->type;
5835 @@ -6358,20 +6440,20 @@ static int yaffs_ScanBackwards(yaffs_Dev
5836 in->yst_mtime = oh->yst_mtime;
5837 in->yst_ctime = oh->yst_ctime;
5838 in->yst_rdev = oh->yst_rdev;
5843 in->variantType = tags.extraObjectType;
5847 - in->chunkId = chunk;
5848 + in->hdrChunk = chunk;
5850 } else if (!in->valid) {
5851 /* we need to load this info */
5854 - in->chunkId = chunk;
5855 + in->hdrChunk = chunk;
5858 in->variantType = oh->type;
5859 @@ -6393,12 +6475,12 @@ static int yaffs_ScanBackwards(yaffs_Dev
5860 in->yst_rdev = oh->yst_rdev;
5863 - if (oh->shadowsObject > 0)
5864 + if (oh->shadowsObject > 0)
5865 yaffs_HandleShadowedObject(dev,
5872 yaffs_SetObjectName(in, oh->name);
5874 @@ -6431,13 +6513,13 @@ static int yaffs_ScanBackwards(yaffs_Dev
5876 if (parent->variantType ==
5877 YAFFS_OBJECT_TYPE_UNKNOWN) {
5878 - /* Set up as a directory */
5879 - parent->variantType =
5880 - YAFFS_OBJECT_TYPE_DIRECTORY;
5881 - INIT_LIST_HEAD(&parent->variant.
5884 - } else if (parent->variantType !=
5885 + /* Set up as a directory */
5886 + parent->variantType =
5887 + YAFFS_OBJECT_TYPE_DIRECTORY;
5888 + YINIT_LIST_HEAD(&parent->variant.
5891 + } else if (parent->variantType !=
5892 YAFFS_OBJECT_TYPE_DIRECTORY)
5894 /* Hoosterman, another problem....
5895 @@ -6446,8 +6528,7 @@ static int yaffs_ScanBackwards(yaffs_Dev
5897 T(YAFFS_TRACE_ERROR,
5899 - ("yaffs tragedy: attempting to use non-directory as"
5900 - " a directory in scan. Put in lost+found."
5901 + ("yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found."
5903 parent = dev->lostNFoundDir;
5905 @@ -6466,11 +6547,11 @@ static int yaffs_ScanBackwards(yaffs_Dev
5906 * Since we might scan a hardlink before its equivalent object is scanned
5907 * we put them all in a list.
5908 * After scanning is complete, we should have all the objects, so we run
5909 - * through this list and fix up all the chains.
5910 + * through this list and fix up all the chains.
5913 switch (in->variantType) {
5914 - case YAFFS_OBJECT_TYPE_UNKNOWN:
5915 + case YAFFS_OBJECT_TYPE_UNKNOWN:
5916 /* Todo got a problem */
5918 case YAFFS_OBJECT_TYPE_FILE:
5919 @@ -6479,7 +6560,7 @@ static int yaffs_ScanBackwards(yaffs_Dev
5920 scannedFileSize < fileSize) {
5921 /* This covers the case where the file size is greater
5922 * than where the data is
5923 - * This will happen if the file is resized to be larger
5924 + * This will happen if the file is resized to be larger
5925 * than its current data extents.
5927 in->variant.fileVariant.fileSize = fileSize;
5928 @@ -6495,13 +6576,13 @@ static int yaffs_ScanBackwards(yaffs_Dev
5930 case YAFFS_OBJECT_TYPE_HARDLINK:
5932 - in->variant.hardLinkVariant.equivalentObjectId =
5933 - equivalentObjectId;
5934 - in->hardLinks.next =
5935 - (struct list_head *) hardList;
5939 + in->variant.hardLinkVariant.equivalentObjectId =
5940 + equivalentObjectId;
5941 + in->hardLinks.next =
5942 + (struct ylist_head *) hardList;
5946 case YAFFS_OBJECT_TYPE_DIRECTORY:
5949 @@ -6520,7 +6601,7 @@ static int yaffs_ScanBackwards(yaffs_Dev
5957 } /* End of scanning for each chunk */
5958 @@ -6541,72 +6622,128 @@ static int yaffs_ScanBackwards(yaffs_Dev
5962 - if (altBlockIndex)
5963 + if (altBlockIndex)
5964 YFREE_ALT(blockIndex);
5969 /* Ok, we've done all the scanning.
5970 * Fix up the hard link chains.
5971 - * We should now have scanned all the objects, now it's time to add these
5972 + * We should now have scanned all the objects, now it's time to add these
5975 yaffs_HardlinkFixup(dev,hardList);
5978 + yaffs_ReleaseTempBuffer(dev, chunkData, __LINE__);
5981 + return YAFFS_FAIL;
5985 - * Sort out state of unlinked and deleted objects.
5988 - struct list_head *i;
5989 - struct list_head *n;
5990 + T(YAFFS_TRACE_SCAN, (TSTR("yaffs_ScanBackwards ends" TENDSTR)));
5996 - /* Soft delete all the unlinked files */
5997 - list_for_each_safe(i, n,
5998 - &dev->unlinkedDir->variant.directoryVariant.
6001 - l = list_entry(i, yaffs_Object, siblings);
6002 - yaffs_DestroyObject(l);
6005 +/*------------------------------ Directory Functions ----------------------------- */
6007 - /* Soft delete all the deletedDir files */
6008 - list_for_each_safe(i, n,
6009 - &dev->deletedDir->variant.directoryVariant.
6012 - l = list_entry(i, yaffs_Object, siblings);
6013 - yaffs_DestroyObject(l);
6014 +static void yaffs_VerifyObjectInDirectory(yaffs_Object *obj)
6016 + struct ylist_head *lh;
6017 + yaffs_Object *listObj;
6024 + T(YAFFS_TRACE_ALWAYS, (TSTR("No object to verify" TENDSTR)));
6028 - yaffs_ReleaseTempBuffer(dev, chunkData, __LINE__);
6029 + if(yaffs_SkipVerification(obj->myDev))
6033 - return YAFFS_FAIL;
6035 + T(YAFFS_TRACE_ALWAYS, (TSTR("Object does not have parent" TENDSTR)));
6039 + if(obj->parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY){
6040 + T(YAFFS_TRACE_ALWAYS, (TSTR("Parent is not directory" TENDSTR)));
6044 + /* Iterate through the objects in each hash entry */
6046 + ylist_for_each(lh, &obj->parent->variant.directoryVariant.children) {
6048 + listObj = ylist_entry(lh, yaffs_Object, siblings);
6049 + yaffs_VerifyObject(listObj);
6050 + if(obj == listObj)
6056 + T(YAFFS_TRACE_ALWAYS, (TSTR("Object in directory %d times" TENDSTR),count));
6060 - T(YAFFS_TRACE_SCAN, (TSTR("yaffs_ScanBackwards ends" TENDSTR)));
6064 +static void yaffs_VerifyDirectory(yaffs_Object *directory)
6067 + struct ylist_head *lh;
6068 + yaffs_Object *listObj;
6073 + if(yaffs_SkipFullVerification(directory->myDev))
6077 + if(directory->variantType != YAFFS_OBJECT_TYPE_DIRECTORY){
6078 + T(YAFFS_TRACE_ALWAYS, (TSTR("Directory has wrong type: %d" TENDSTR),directory->variantType));
6082 + /* Iterate through the objects in each hash entry */
6084 + ylist_for_each(lh, &directory->variant.directoryVariant.children) {
6086 + listObj = ylist_entry(lh, yaffs_Object, siblings);
6087 + if(listObj->parent != directory){
6088 + T(YAFFS_TRACE_ALWAYS, (TSTR("Object in directory list has wrong parent %p" TENDSTR),listObj->parent));
6091 + yaffs_VerifyObjectInDirectory(listObj);
6097 -/*------------------------------ Directory Functions ----------------------------- */
6099 static void yaffs_RemoveObjectFromDirectory(yaffs_Object * obj)
6101 yaffs_Device *dev = obj->myDev;
6102 + yaffs_Object *parent;
6104 + yaffs_VerifyObjectInDirectory(obj);
6105 + parent = obj->parent;
6107 + yaffs_VerifyDirectory(parent);
6109 + if(dev && dev->removeObjectCallback)
6110 + dev->removeObjectCallback(obj);
6113 + ylist_del_init(&obj->siblings);
6114 + obj->parent = NULL;
6116 - if(dev && dev->removeObjectCallback)
6117 - dev->removeObjectCallback(obj);
6118 + yaffs_VerifyDirectory(parent);
6120 - list_del_init(&obj->siblings);
6121 - obj->parent = NULL;
6125 @@ -6629,35 +6766,46 @@ static void yaffs_AddObjectToDirectory(y
6129 - if (obj->siblings.prev == NULL) {
6130 - /* Not initialised */
6131 - INIT_LIST_HEAD(&obj->siblings);
6133 - } else if (!list_empty(&obj->siblings)) {
6134 - /* If it is holed up somewhere else, un hook it */
6135 - yaffs_RemoveObjectFromDirectory(obj);
6138 - list_add(&obj->siblings, &directory->variant.directoryVariant.children);
6139 - obj->parent = directory;
6140 + if (obj->siblings.prev == NULL) {
6141 + /* Not initialised */
6144 + } else if (ylist_empty(&obj->siblings)) {
6149 - if (directory == obj->myDev->unlinkedDir
6150 + yaffs_VerifyDirectory(directory);
6152 + yaffs_RemoveObjectFromDirectory(obj);
6156 + ylist_add(&obj->siblings, &directory->variant.directoryVariant.children);
6157 + obj->parent = directory;
6159 + if (directory == obj->myDev->unlinkedDir
6160 || directory == obj->myDev->deletedDir) {
6162 obj->myDev->nUnlinkedFiles++;
6163 obj->renameAllowed = 0;
6166 + yaffs_VerifyDirectory(directory);
6167 + yaffs_VerifyObjectInDirectory(obj);
6172 yaffs_Object *yaffs_FindObjectByName(yaffs_Object * directory,
6178 - struct list_head *i;
6179 - YCHAR buffer[YAFFS_MAX_NAME_LENGTH + 1];
6180 + struct ylist_head *i;
6181 + YCHAR buffer[YAFFS_MAX_NAME_LENGTH + 1];
6188 @@ -6677,22 +6825,24 @@ yaffs_Object *yaffs_FindObjectByName(yaf
6192 - sum = yaffs_CalcNameSum(name);
6193 + sum = yaffs_CalcNameSum(name);
6195 - list_for_each(i, &directory->variant.directoryVariant.children) {
6197 - l = list_entry(i, yaffs_Object, siblings);
6199 - yaffs_CheckObjectDetailsLoaded(l);
6200 + ylist_for_each(i, &directory->variant.directoryVariant.children) {
6202 + l = ylist_entry(i, yaffs_Object, siblings);
6204 + if(l->parent != directory)
6207 + yaffs_CheckObjectDetailsLoaded(l);
6209 /* Special case for lost-n-found */
6210 if (l->objectId == YAFFS_OBJECTID_LOSTNFOUND) {
6211 if (yaffs_strcmp(name, YAFFS_LOSTNFOUND_NAME) == 0) {
6214 - } else if (yaffs_SumCompare(l->sum, sum) || l->chunkId <= 0)
6216 - /* LostnFound cunk called Objxxx
6217 + } else if (yaffs_SumCompare(l->sum, sum) || l->hdrChunk <= 0){
6218 + /* LostnFound chunk called Objxxx
6221 yaffs_GetObjectName(l, buffer,
6222 @@ -6711,12 +6861,12 @@ yaffs_Object *yaffs_FindObjectByName(yaf
6225 int yaffs_ApplyToDirectoryChildren(yaffs_Object * theDir,
6226 - int (*fn) (yaffs_Object *))
6227 + int (*fn) (yaffs_Object *))
6229 - struct list_head *i;
6231 + struct ylist_head *i;
6236 T(YAFFS_TRACE_ALWAYS,
6238 ("tragedy: yaffs_FindObjectByName: null pointer directory"
6239 @@ -6727,15 +6877,15 @@ int yaffs_ApplyToDirectoryChildren(yaffs
6240 T(YAFFS_TRACE_ALWAYS,
6242 ("tragedy: yaffs_FindObjectByName: non-directory" TENDSTR)));
6248 - list_for_each(i, &theDir->variant.directoryVariant.children) {
6250 - l = list_entry(i, yaffs_Object, siblings);
6251 - if (l && !fn(l)) {
6252 - return YAFFS_FAIL;
6254 + ylist_for_each(i, &theDir->variant.directoryVariant.children) {
6256 + l = ylist_entry(i, yaffs_Object, siblings);
6257 + if (l && !fn(l)) {
6258 + return YAFFS_FAIL;
6263 @@ -6762,16 +6912,25 @@ yaffs_Object *yaffs_GetEquivalentObject(
6264 int yaffs_GetObjectName(yaffs_Object * obj, YCHAR * name, int buffSize)
6266 memset(name, 0, buffSize * sizeof(YCHAR));
6269 yaffs_CheckObjectDetailsLoaded(obj);
6271 if (obj->objectId == YAFFS_OBJECTID_LOSTNFOUND) {
6272 yaffs_strncpy(name, YAFFS_LOSTNFOUND_NAME, buffSize - 1);
6273 - } else if (obj->chunkId <= 0) {
6274 + } else if (obj->hdrChunk <= 0) {
6276 + YCHAR numString[20];
6277 + YCHAR *x = &numString[19];
6278 + unsigned v = obj->objectId;
6279 + numString[19] = 0;
6282 + *x = '0' + (v % 10);
6285 /* make up a name */
6286 - yaffs_sprintf(locName, _Y("%s%d"), YAFFS_LOSTNFOUND_PREFIX,
6288 + yaffs_strcpy(locName, YAFFS_LOSTNFOUND_PREFIX);
6289 + yaffs_strcat(locName,x);
6290 yaffs_strncpy(name, locName, buffSize - 1);
6293 @@ -6788,9 +6947,9 @@ int yaffs_GetObjectName(yaffs_Object * o
6295 memset(buffer, 0, obj->myDev->nDataBytesPerChunk);
6297 - if (obj->chunkId >= 0) {
6298 + if (obj->hdrChunk > 0) {
6299 result = yaffs_ReadChunkWithTagsFromNAND(obj->myDev,
6300 - obj->chunkId, buffer,
6301 + obj->hdrChunk, buffer,
6304 yaffs_strncpy(name, oh->name, buffSize - 1);
6305 @@ -6820,16 +6979,16 @@ int yaffs_GetObjectFileLength(yaffs_Obje
6307 int yaffs_GetObjectLinkCount(yaffs_Object * obj)
6310 - struct list_head *i;
6312 + struct ylist_head *i;
6314 - if (!obj->unlinked) {
6315 - count++; /* the object itself */
6317 - list_for_each(i, &obj->hardLinks) {
6318 - count++; /* add the hard links; */
6321 + if (!obj->unlinked) {
6322 + count++; /* the object itself */
6324 + ylist_for_each(i, &obj->hardLinks) {
6325 + count++; /* add the hard links; */
6331 @@ -6951,7 +7110,7 @@ int yaffs_DumpObject(yaffs_Object * obj)
6332 ("Object %d, inode %d \"%s\"\n dirty %d valid %d serial %d sum %d"
6333 " chunk %d type %d size %d\n"
6334 TENDSTR), obj->objectId, yaffs_GetObjectInode(obj), name,
6335 - obj->dirty, obj->valid, obj->serial, obj->sum, obj->chunkId,
6336 + obj->dirty, obj->valid, obj->serial, obj->sum, obj->hdrChunk,
6337 yaffs_GetObjectType(obj), yaffs_GetObjectFileLength(obj)));
6340 @@ -6994,13 +7153,13 @@ static int yaffs_CheckDevFunctions(const
6341 static int yaffs_CreateInitialDirectories(yaffs_Device *dev)
6343 /* Initialise the unlinked, deleted, root and lost and found directories */
6346 dev->lostNFoundDir = dev->rootDir = NULL;
6347 dev->unlinkedDir = dev->deletedDir = NULL;
6350 yaffs_CreateFakeDirectory(dev, YAFFS_OBJECTID_UNLINKED, S_IFDIR);
6354 yaffs_CreateFakeDirectory(dev, YAFFS_OBJECTID_DELETED, S_IFDIR);
6356 @@ -7010,12 +7169,12 @@ static int yaffs_CreateInitialDirectorie
6357 dev->lostNFoundDir =
6358 yaffs_CreateFakeDirectory(dev, YAFFS_OBJECTID_LOSTNFOUND,
6359 YAFFS_LOSTNFOUND_MODE | S_IFDIR);
6362 if(dev->lostNFoundDir && dev->rootDir && dev->unlinkedDir && dev->deletedDir){
6363 yaffs_AddObjectToDirectory(dev->rootDir, dev->lostNFoundDir);
6371 @@ -7039,6 +7198,8 @@ int yaffs_GutsInitialise(yaffs_Device *
6372 dev->blockOffset = 0;
6373 dev->chunkOffset = 0;
6374 dev->nFreeChunks = 0;
6376 + dev->gcBlock = -1;
6378 if (dev->startBlock == 0) {
6379 dev->internalStartBlock = dev->startBlock + 1;
6380 @@ -7049,18 +7210,19 @@ int yaffs_GutsInitialise(yaffs_Device *
6382 /* Check geometry parameters. */
6384 - if ((dev->isYaffs2 && dev->nDataBytesPerChunk < 1024) ||
6385 - (!dev->isYaffs2 && dev->nDataBytesPerChunk != 512) ||
6386 - dev->nChunksPerBlock < 2 ||
6387 - dev->nReservedBlocks < 2 ||
6388 - dev->internalStartBlock <= 0 ||
6389 - dev->internalEndBlock <= 0 ||
6390 + if ((!dev->inbandTags && dev->isYaffs2 && dev->totalBytesPerChunk < 1024) ||
6391 + (!dev->isYaffs2 && dev->totalBytesPerChunk < 512) ||
6392 + (dev->inbandTags && !dev->isYaffs2 ) ||
6393 + dev->nChunksPerBlock < 2 ||
6394 + dev->nReservedBlocks < 2 ||
6395 + dev->internalStartBlock <= 0 ||
6396 + dev->internalEndBlock <= 0 ||
6397 dev->internalEndBlock <= (dev->internalStartBlock + dev->nReservedBlocks + 2) // otherwise it is too small
6399 T(YAFFS_TRACE_ALWAYS,
6401 - ("yaffs: NAND geometry problems: chunk size %d, type is yaffs%s "
6402 - TENDSTR), dev->nDataBytesPerChunk, dev->isYaffs2 ? "2" : ""));
6403 + ("yaffs: NAND geometry problems: chunk size %d, type is yaffs%s, inbandTags %d "
6404 + TENDSTR), dev->totalBytesPerChunk, dev->isYaffs2 ? "2" : "", dev->inbandTags));
6408 @@ -7069,6 +7231,12 @@ int yaffs_GutsInitialise(yaffs_Device *
6409 (TSTR("yaffs: InitialiseNAND failed" TENDSTR)));
6413 + /* Sort out space for inband tags, if required */
6414 + if(dev->inbandTags)
6415 + dev->nDataBytesPerChunk = dev->totalBytesPerChunk - sizeof(yaffs_PackedTags2TagsPart);
6417 + dev->nDataBytesPerChunk = dev->totalBytesPerChunk;
6419 /* Got the right mix of functions? */
6420 if (!yaffs_CheckDevFunctions(dev)) {
6421 @@ -7097,41 +7265,28 @@ int yaffs_GutsInitialise(yaffs_Device *
6427 /* OK now calculate a few things for the device */
6431 - * Calculate all the chunk size manipulation numbers:
6432 + * Calculate all the chunk size manipulation numbers:
6434 - /* Start off assuming it is a power of 2 */
6435 - dev->chunkShift = ShiftDiv(dev->nDataBytesPerChunk);
6436 - dev->chunkMask = (1<<dev->chunkShift) - 1;
6438 - if(dev->nDataBytesPerChunk == (dev->chunkMask + 1)){
6439 - /* Yes it is a power of 2, disable crumbs */
6440 - dev->crumbMask = 0;
6441 - dev->crumbShift = 0;
6442 - dev->crumbsPerChunk = 0;
6444 - /* Not a power of 2, use crumbs instead */
6445 - dev->crumbShift = ShiftDiv(sizeof(yaffs_PackedTags2TagsPart));
6446 - dev->crumbMask = (1<<dev->crumbShift)-1;
6447 - dev->crumbsPerChunk = dev->nDataBytesPerChunk/(1 << dev->crumbShift);
6448 - dev->chunkShift = 0;
6449 - dev->chunkMask = 0;
6453 + x = dev->nDataBytesPerChunk;
6454 + /* We always use dev->chunkShift and dev->chunkDiv */
6455 + dev->chunkShift = Shifts(x);
6456 + x >>= dev->chunkShift;
6457 + dev->chunkDiv = x;
6458 + /* We only use chunk mask if chunkDiv is 1 */
6459 + dev->chunkMask = (1<<dev->chunkShift) - 1;
6462 * Calculate chunkGroupBits.
6463 * We need to find the next power of 2 > than internalEndBlock
6466 x = dev->nChunksPerBlock * (dev->internalEndBlock + 1);
6472 /* Set up tnode width if wide tnodes are enabled. */
6473 if(!dev->wideTnodesDisabled){
6474 /* bits must be even so that we end up with 32-bit words */
6475 @@ -7144,20 +7299,20 @@ int yaffs_GutsInitialise(yaffs_Device *
6478 dev->tnodeWidth = 16;
6481 dev->tnodeMask = (1<<dev->tnodeWidth)-1;
6484 /* Level0 Tnodes are 16 bits or wider (if wide tnodes are enabled),
6485 * so if the bitwidth of the
6486 * chunk range we're using is greater than 16 we need
6487 * to figure out chunk shift and chunkGroupSize
6491 if (bits <= dev->tnodeWidth)
6492 dev->chunkGroupBits = 0;
6494 dev->chunkGroupBits = bits - dev->tnodeWidth;
6498 dev->chunkGroupSize = 1 << dev->chunkGroupBits;
6500 @@ -7195,40 +7350,42 @@ int yaffs_GutsInitialise(yaffs_Device *
6501 /* Initialise temporary buffers and caches. */
6502 if(!yaffs_InitialiseTempBuffers(dev))
6506 dev->srCache = NULL;
6507 dev->gcCleanupList = NULL;
6513 dev->nShortOpCaches > 0) {
6517 int srCacheBytes = dev->nShortOpCaches * sizeof(yaffs_ChunkCache);
6519 if (dev->nShortOpCaches > YAFFS_MAX_SHORT_OP_CACHES) {
6520 dev->nShortOpCaches = YAFFS_MAX_SHORT_OP_CACHES;
6523 - buf = dev->srCache = YMALLOC(srCacheBytes);
6525 + dev->srCache = YMALLOC(srCacheBytes);
6527 + buf = (__u8 *) dev->srCache;
6530 memset(dev->srCache,0,srCacheBytes);
6533 for (i = 0; i < dev->nShortOpCaches && buf; i++) {
6534 dev->srCache[i].object = NULL;
6535 dev->srCache[i].lastUse = 0;
6536 dev->srCache[i].dirty = 0;
6537 - dev->srCache[i].data = buf = YMALLOC_DMA(dev->nDataBytesPerChunk);
6538 + dev->srCache[i].data = buf = YMALLOC_DMA(dev->totalBytesPerChunk);
6551 dev->gcCleanupList = YMALLOC(dev->nChunksPerBlock * sizeof(__u32));
6552 if(!dev->gcCleanupList)
6553 @@ -7240,7 +7397,7 @@ int yaffs_GutsInitialise(yaffs_Device *
6555 if(!init_failed && !yaffs_InitialiseBlocks(dev))
6559 yaffs_InitialiseTnodes(dev);
6560 yaffs_InitialiseObjects(dev);
6562 @@ -7252,18 +7409,19 @@ int yaffs_GutsInitialise(yaffs_Device *
6563 /* Now scan the flash. */
6564 if (dev->isYaffs2) {
6565 if(yaffs_CheckpointRestore(dev)) {
6566 + yaffs_CheckObjectDetailsLoaded(dev->rootDir);
6567 T(YAFFS_TRACE_ALWAYS,
6568 (TSTR("yaffs: restored from checkpoint" TENDSTR)));
6571 - /* Clean up the mess caused by an aborted checkpoint load
6572 - * and scan backwards.
6573 + /* Clean up the mess caused by an aborted checkpoint load
6574 + * and scan backwards.
6576 yaffs_DeinitialiseBlocks(dev);
6577 yaffs_DeinitialiseTnodes(dev);
6578 yaffs_DeinitialiseObjects(dev);
6583 dev->nErasedBlocks = 0;
6584 dev->nFreeChunks = 0;
6585 dev->allocationBlock = -1;
6586 @@ -7275,7 +7433,7 @@ int yaffs_GutsInitialise(yaffs_Device *
6588 if(!init_failed && !yaffs_InitialiseBlocks(dev))
6592 yaffs_InitialiseTnodes(dev);
6593 yaffs_InitialiseObjects(dev);
6595 @@ -7288,8 +7446,10 @@ int yaffs_GutsInitialise(yaffs_Device *
6597 if(!yaffs_Scan(dev))
6601 + yaffs_StripDeletedObjects(dev);
6605 /* Clean up the mess */
6606 T(YAFFS_TRACE_TRACING,
6607 @@ -7310,7 +7470,7 @@ int yaffs_GutsInitialise(yaffs_Device *
6609 yaffs_VerifyFreeChunks(dev);
6610 yaffs_VerifyBlocks(dev);
6614 T(YAFFS_TRACE_TRACING,
6615 (TSTR("yaffs: yaffs_GutsInitialise() done.\n" TENDSTR)));
6616 @@ -7345,7 +7505,11 @@ void yaffs_Deinitialise(yaffs_Device * d
6617 YFREE(dev->tempBuffer[i].buffer);
6623 + if(dev->deinitialiseNAND)
6624 + dev->deinitialiseNAND(dev);
6628 @@ -7394,7 +7558,7 @@ int yaffs_GetNumberOfFreeChunks(yaffs_De
6631 nFree += dev->nDeletedFiles;
6634 /* Now count the number of dirty chunks in the cache and subtract those */
6637 @@ -7408,12 +7572,12 @@ int yaffs_GetNumberOfFreeChunks(yaffs_De
6638 nFree -= nDirtyCacheChunks;
6640 nFree -= ((dev->nReservedBlocks + 1) * dev->nChunksPerBlock);
6643 /* Now we figure out how much to reserve for the checkpoint and report that... */
6644 - blocksForCheckpoint = dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint;
6645 + blocksForCheckpoint = yaffs_CalcCheckpointBlocksRequired(dev) - dev->blocksInCheckpoint;
6646 if(blocksForCheckpoint < 0)
6647 blocksForCheckpoint = 0;
6650 nFree -= (blocksForCheckpoint * dev->nChunksPerBlock);
6653 @@ -7429,10 +7593,10 @@ static void yaffs_VerifyFreeChunks(yaffs
6659 if(yaffs_SkipVerification(dev))
6663 counted = yaffs_CountFreeChunks(dev);
6665 difference = dev->nFreeChunks - counted;
6666 @@ -7448,22 +7612,25 @@ static void yaffs_VerifyFreeChunks(yaffs
6667 /*---------------------------------------- YAFFS test code ----------------------*/
6669 #define yaffs_CheckStruct(structure,syze, name) \
6671 if(sizeof(structure) != syze) \
6673 T(YAFFS_TRACE_ALWAYS,(TSTR("%s should be %d but is %d\n" TENDSTR),\
6674 name,syze,sizeof(structure))); \
6675 return YAFFS_FAIL; \
6680 static int yaffs_CheckStructures(void)
6682 -/* yaffs_CheckStruct(yaffs_Tags,8,"yaffs_Tags") */
6683 -/* yaffs_CheckStruct(yaffs_TagsUnion,8,"yaffs_TagsUnion") */
6684 -/* yaffs_CheckStruct(yaffs_Spare,16,"yaffs_Spare") */
6685 +/* yaffs_CheckStruct(yaffs_Tags,8,"yaffs_Tags"); */
6686 +/* yaffs_CheckStruct(yaffs_TagsUnion,8,"yaffs_TagsUnion"); */
6687 +/* yaffs_CheckStruct(yaffs_Spare,16,"yaffs_Spare"); */
6688 #ifndef CONFIG_YAFFS_TNODE_LIST_DEBUG
6689 - yaffs_CheckStruct(yaffs_Tnode, 2 * YAFFS_NTNODES_LEVEL0, "yaffs_Tnode")
6690 + yaffs_CheckStruct(yaffs_Tnode, 2 * YAFFS_NTNODES_LEVEL0, "yaffs_Tnode");
6692 +#ifndef CONFIG_YAFFS_WINCE
6693 + yaffs_CheckStruct(yaffs_ObjectHeader, 512, "yaffs_ObjectHeader");
6695 - yaffs_CheckStruct(yaffs_ObjectHeader, 512, "yaffs_ObjectHeader")
6699 --- a/fs/yaffs2/yaffs_mtdif1.c
6700 +++ b/fs/yaffs2/yaffs_mtdif1.c
6702 #include "linux/mtd/mtd.h"
6704 /* Don't compile this module if we don't have MTD's mtd_oob_ops interface */
6705 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
6706 +#if (MTD_VERSION_CODE > MTD_VERSION(2,6,17))
6708 -const char *yaffs_mtdif1_c_version = "$Id: yaffs_mtdif1.c,v 1.3 2007/05/15 20:16:11 ian Exp $";
6709 +const char *yaffs_mtdif1_c_version = "$Id: yaffs_mtdif1.c,v 1.8 2008-07-23 03:35:12 charles Exp $";
6711 #ifndef CONFIG_YAFFS_9BYTE_TAGS
6712 # define YTAG1_SIZE 8
6713 @@ -189,7 +189,7 @@ int nandmtd1_ReadChunkWithTagsFromNAND(y
6715 ops.oobbuf = (__u8 *)&pt1;
6717 -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
6718 +#if (MTD_VERSION_CODE < MTD_VERSION(2,6,20))
6719 /* In MTD 2.6.18 to 2.6.19 nand_base.c:nand_do_read_oob() has a bug;
6720 * help it out with ops.len = ops.ooblen when ops.datbuf == NULL.
6722 @@ -288,7 +288,7 @@ int nandmtd1_MarkNANDBlockBad(struct yaf
6723 int blocksize = dev->nChunksPerBlock * dev->nDataBytesPerChunk;
6726 - yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, "marking block %d bad", blockNo);
6727 + yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, "marking block %d bad\n", blockNo);
6729 retval = mtd->block_markbad(mtd, (loff_t)blocksize * blockNo);
6730 return (retval) ? YAFFS_FAIL : YAFFS_OK;
6731 @@ -323,10 +323,11 @@ static int nandmtd1_TestPrerequists(stru
6732 * Always returns YAFFS_OK.
6734 int nandmtd1_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
6735 - yaffs_BlockState * pState, int *pSequenceNumber)
6736 + yaffs_BlockState * pState, __u32 *pSequenceNumber)
6738 struct mtd_info * mtd = dev->genericDevice;
6739 int chunkNo = blockNo * dev->nChunksPerBlock;
6740 + loff_t addr = (loff_t)chunkNo * dev->nDataBytesPerChunk;
6741 yaffs_ExtendedTags etags;
6742 int state = YAFFS_BLOCK_STATE_DEAD;
6744 @@ -340,11 +341,16 @@ int nandmtd1_QueryNANDBlock(struct yaffs
6747 retval = nandmtd1_ReadChunkWithTagsFromNAND(dev, chunkNo, NULL, &etags);
6748 + etags.blockBad = (mtd->block_isbad)(mtd, addr);
6749 if (etags.blockBad) {
6750 yaffs_trace(YAFFS_TRACE_BAD_BLOCKS,
6751 - "block %d is marked bad", blockNo);
6752 + "block %d is marked bad\n", blockNo);
6753 state = YAFFS_BLOCK_STATE_DEAD;
6755 + else if (etags.eccResult != YAFFS_ECC_RESULT_NO_ERROR) {
6756 + /* bad tags, need to look more closely */
6757 + state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
6759 else if (etags.chunkUsed) {
6760 state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
6761 seqnum = etags.sequenceNumber;
6762 @@ -360,4 +366,4 @@ int nandmtd1_QueryNANDBlock(struct yaffs
6766 -#endif /*KERNEL_VERSION*/
6767 +#endif /*MTD_VERSION*/
6768 --- a/fs/yaffs2/yaffs_mtdif2.c
6769 +++ b/fs/yaffs2/yaffs_mtdif2.c
6771 /* mtd interface for YAFFS2 */
6773 const char *yaffs_mtdif2_c_version =
6774 - "$Id: yaffs_mtdif2.c,v 1.17 2007-02-14 01:09:06 wookey Exp $";
6775 + "$Id: yaffs_mtdif2.c,v 1.22 2008-11-02 22:47:13 charles Exp $";
6777 #include "yportenv.h"
6779 @@ -27,19 +27,23 @@ const char *yaffs_mtdif2_c_version =
6781 #include "yaffs_packedtags2.h"
6783 +/* NB For use with inband tags....
6784 + * We assume that the data buffer is of size totalBytersPerChunk so that we can also
6785 + * use it to load the tags.
6787 int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND,
6789 const yaffs_ExtendedTags * tags)
6791 struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
6792 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
6793 +#if (MTD_VERSION_CODE > MTD_VERSION(2,6,17))
6794 struct mtd_oob_ops ops;
6800 - loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
6803 yaffs_PackedTags2 pt;
6805 @@ -47,47 +51,42 @@ int nandmtd2_WriteChunkWithTagsToNAND(ya
6807 ("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p"
6808 TENDSTR), chunkInNAND, data, tags));
6811 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
6813 - yaffs_PackTags2(&pt, tags);
6814 + addr = ((loff_t) chunkInNAND) * dev->totalBytesPerChunk;
6816 + /* For yaffs2 writing there must be both data and tags.
6817 + * If we're using inband tags, then the tags are stuffed into
6818 + * the end of the data buffer.
6820 + if(!data || !tags)
6822 + else if(dev->inbandTags){
6823 + yaffs_PackedTags2TagsPart *pt2tp;
6824 + pt2tp = (yaffs_PackedTags2TagsPart *)(data + dev->nDataBytesPerChunk);
6825 + yaffs_PackTags2TagsPart(pt2tp,tags);
6828 - BUG(); /* both tags and data should always be present */
6831 - ops.mode = MTD_OOB_AUTO;
6832 - ops.ooblen = sizeof(pt);
6833 - ops.len = dev->nDataBytesPerChunk;
6835 - ops.datbuf = (__u8 *)data;
6836 - ops.oobbuf = (void *)&pt;
6837 - retval = mtd->write_oob(mtd, addr, &ops);
6839 - BUG(); /* both tags and data should always be present */
6842 yaffs_PackTags2(&pt, tags);
6845 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
6846 + ops.mode = MTD_OOB_AUTO;
6847 + ops.ooblen = (dev->inbandTags) ? 0 : sizeof(pt);
6848 + ops.len = dev->totalBytesPerChunk;
6850 + ops.datbuf = (__u8 *)data;
6851 + ops.oobbuf = (dev->inbandTags) ? NULL : (void *)&pt;
6852 + retval = mtd->write_oob(mtd, addr, &ops);
6854 - if (data && tags) {
6855 - if (dev->useNANDECC)
6857 - mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
6858 - &dummy, data, (__u8 *) & pt, NULL);
6861 - mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
6862 - &dummy, data, (__u8 *) & pt, NULL);
6864 + if (!dev->inbandTags) {
6866 + mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
6867 + &dummy, data, (__u8 *) & pt, NULL);
6871 - mtd->write(mtd, addr, dev->nDataBytesPerChunk, &dummy,
6875 - mtd->write_oob(mtd, addr, mtd->oobsize, &dummy,
6879 + mtd->write(mtd, addr, dev->totalBytesPerChunk, &dummy,
6884 @@ -101,13 +100,14 @@ int nandmtd2_ReadChunkWithTagsFromNAND(y
6885 __u8 * data, yaffs_ExtendedTags * tags)
6887 struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
6888 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
6889 +#if (MTD_VERSION_CODE > MTD_VERSION(2,6,17))
6890 struct mtd_oob_ops ops;
6894 + int localData = 0;
6896 - loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
6897 + loff_t addr = ((loff_t) chunkInNAND) * dev->totalBytesPerChunk;
6899 yaffs_PackedTags2 pt;
6901 @@ -115,10 +115,21 @@ int nandmtd2_ReadChunkWithTagsFromNAND(y
6903 ("nandmtd2_ReadChunkWithTagsFromNAND chunk %d data %p tags %p"
6904 TENDSTR), chunkInNAND, data, tags));
6906 + if(dev->inbandTags){
6910 + data = yaffs_GetTempBuffer(dev,__LINE__);
6917 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
6918 - if (data && !tags)
6919 - retval = mtd->read(mtd, addr, dev->nDataBytesPerChunk,
6920 + if (dev->inbandTags || (data && !tags))
6921 + retval = mtd->read(mtd, addr, dev->totalBytesPerChunk,
6924 ops.mode = MTD_OOB_AUTO;
6925 @@ -130,38 +141,43 @@ int nandmtd2_ReadChunkWithTagsFromNAND(y
6926 retval = mtd->read_oob(mtd, addr, &ops);
6929 - if (data && tags) {
6930 - if (dev->useNANDECC) {
6932 - mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,
6933 - &dummy, data, dev->spareBuffer,
6937 - mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,
6938 + if (!dev->inbandTags && data && tags) {
6940 + retval = mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,
6941 &dummy, data, dev->spareBuffer,
6947 mtd->read(mtd, addr, dev->nDataBytesPerChunk, &dummy,
6950 + if (!dev->inbandTags && tags)
6952 mtd->read_oob(mtd, addr, mtd->oobsize, &dummy,
6957 - memcpy(&pt, dev->spareBuffer, sizeof(pt));
6960 - yaffs_UnpackTags2(tags, &pt);
6961 + if(dev->inbandTags){
6963 + yaffs_PackedTags2TagsPart * pt2tp;
6964 + pt2tp = (yaffs_PackedTags2TagsPart *)&data[dev->nDataBytesPerChunk];
6965 + yaffs_UnpackTags2TagsPart(tags,pt2tp);
6970 + memcpy(&pt, dev->spareBuffer, sizeof(pt));
6971 + yaffs_UnpackTags2(tags, &pt);
6976 + yaffs_ReleaseTempBuffer(dev,data,__LINE__);
6978 if(tags && retval == -EBADMSG && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR)
6979 - tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;
6981 + tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;
6985 @@ -178,7 +194,7 @@ int nandmtd2_MarkNANDBlockBad(struct yaf
6987 mtd->block_markbad(mtd,
6988 blockNo * dev->nChunksPerBlock *
6989 - dev->nDataBytesPerChunk);
6990 + dev->totalBytesPerChunk);
6994 @@ -188,7 +204,7 @@ int nandmtd2_MarkNANDBlockBad(struct yaf
6997 int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
6998 - yaffs_BlockState * state, int *sequenceNumber)
6999 + yaffs_BlockState * state, __u32 *sequenceNumber)
7001 struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
7003 @@ -198,7 +214,7 @@ int nandmtd2_QueryNANDBlock(struct yaffs
7005 mtd->block_isbad(mtd,
7006 blockNo * dev->nChunksPerBlock *
7007 - dev->nDataBytesPerChunk);
7008 + dev->totalBytesPerChunk);
7011 T(YAFFS_TRACE_MTD, (TSTR("block is bad" TENDSTR)));
7012 --- a/fs/yaffs2/yaffs_guts.h
7013 +++ b/fs/yaffs2/yaffs_guts.h
7016 - * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
7017 + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
7019 * Copyright (C) 2002-2007 Aleph One Ltd.
7020 * for Toby Churchill Ltd and Brightstar Engineering
7023 #define YAFFS_FAIL 0
7025 -/* Give us a Y=0x59,
7026 - * Give us an A=0x41,
7027 - * Give us an FF=0xFF
7028 +/* Give us a Y=0x59,
7029 + * Give us an A=0x41,
7030 + * Give us an FF=0xFF
7032 - * And what have we got...
7033 + * And what have we got...
7035 #define YAFFS_MAGIC 0x5941FF53
7039 #define YAFFS_MAX_SHORT_OP_CACHES 20
7041 -#define YAFFS_N_TEMP_BUFFERS 4
7042 +#define YAFFS_N_TEMP_BUFFERS 6
7044 /* We limit the number attempts at sucessfully saving a chunk of data.
7045 * Small-page devices have 32 pages per block; large-page devices have 64.
7047 * The range is limited slightly to help distinguish bad numbers from good.
7048 * This also allows us to perhaps in the future use special numbers for
7050 - * EFFFFF00 allows the allocation of 8 blocks per second (~1Mbytes) for 15 years,
7051 + * EFFFFF00 allows the allocation of 8 blocks per second (~1Mbytes) for 15 years,
7052 * and is a larger number than the lifetime of a 2GB device.
7054 #define YAFFS_LOWEST_SEQUENCE_NUMBER 0x00001000
7055 @@ -132,12 +132,12 @@ typedef struct {
7057 #ifndef CONFIG_YAFFS_NO_YAFFS1
7059 - unsigned chunkId:20;
7060 - unsigned serialNumber:2;
7061 - unsigned byteCount:10;
7062 - unsigned objectId:18;
7064 - unsigned unusedStuff:2;
7065 + unsigned chunkId:20;
7066 + unsigned serialNumber:2;
7067 + unsigned byteCountLSB:10;
7068 + unsigned objectId:18;
7070 + unsigned byteCountMSB:2;
7074 @@ -178,7 +178,7 @@ typedef struct {
7076 /* The following stuff only has meaning when we read */
7077 yaffs_ECCResult eccResult;
7078 - unsigned blockBad;
7079 + unsigned blockBad;
7082 unsigned chunkDeleted; /* The chunk is marked deleted */
7083 @@ -244,29 +244,29 @@ typedef enum {
7084 /* This block is empty */
7086 YAFFS_BLOCK_STATE_ALLOCATING,
7087 - /* This block is partially allocated.
7088 + /* This block is partially allocated.
7089 * At least one page holds valid data.
7090 * This is the one currently being used for page
7091 * allocation. Should never be more than one of these
7094 - YAFFS_BLOCK_STATE_FULL,
7095 + YAFFS_BLOCK_STATE_FULL,
7096 /* All the pages in this block have been allocated.
7099 YAFFS_BLOCK_STATE_DIRTY,
7100 - /* All pages have been allocated and deleted.
7101 + /* All pages have been allocated and deleted.
7102 * Erase me, reuse me.
7105 - YAFFS_BLOCK_STATE_CHECKPOINT,
7106 + YAFFS_BLOCK_STATE_CHECKPOINT,
7107 /* This block is assigned to holding checkpoint data.
7110 - YAFFS_BLOCK_STATE_COLLECTING,
7111 + YAFFS_BLOCK_STATE_COLLECTING,
7112 /* This block is being garbage collected */
7114 - YAFFS_BLOCK_STATE_DEAD
7115 + YAFFS_BLOCK_STATE_DEAD
7116 /* This block has failed and is not in use */
7119 @@ -277,11 +277,11 @@ typedef struct {
7121 int softDeletions:10; /* number of soft deleted pages */
7122 int pagesInUse:10; /* number of pages in use */
7123 - yaffs_BlockState blockState:4; /* One of the above block states */
7124 + unsigned blockState:4; /* One of the above block states. NB use unsigned because enum is sometimes an int */
7125 __u32 needsRetiring:1; /* Data has failed on this block, need to get valid data off */
7126 /* and retire the block. */
7127 __u32 skipErasedCheck: 1; /* If this is set we can skip the erased check on this block */
7128 - __u32 gcPrioritise: 1; /* An ECC check or blank check has failed on this block.
7129 + __u32 gcPrioritise: 1; /* An ECC check or blank check has failed on this block.
7130 It should be prioritised for GC */
7131 __u32 chunkErrorStrikes:3; /* How many times we've had ecc etc failures on this block and tried to reuse it */
7133 @@ -300,11 +300,11 @@ typedef struct {
7135 /* Apply to everything */
7137 - __u16 sum__NoLongerUsed; /* checksum of name. No longer used */
7138 - YCHAR name[YAFFS_MAX_NAME_LENGTH + 1];
7139 + __u16 sum__NoLongerUsed; /* checksum of name. No longer used */
7140 + YCHAR name[YAFFS_MAX_NAME_LENGTH + 1];
7142 - /* Thes following apply to directories, files, symlinks - not hard links */
7143 - __u32 yst_mode; /* protection */
7144 + /* The following apply to directories, files, symlinks - not hard links */
7145 + __u32 yst_mode; /* protection */
7147 #ifdef CONFIG_YAFFS_WINCE
7148 __u32 notForWinCE[5];
7149 @@ -331,11 +331,14 @@ typedef struct {
7153 - __u32 roomToGrow[4];
7155 - __u32 roomToGrow[10];
7156 + __u32 roomToGrow[6];
7159 + __u32 inbandShadowsObject;
7160 + __u32 inbandIsShrink;
7162 + __u32 reservedSpace[2];
7163 int shadowsObject; /* This object header shadows the specified object if > 0 */
7165 /* isShrink applies to object headers written when we shrink the file (ie resize) */
7166 @@ -381,7 +384,7 @@ typedef struct {
7167 } yaffs_FileStructure;
7170 - struct list_head children; /* list of child links */
7171 + struct ylist_head children; /* list of child links */
7172 } yaffs_DirectoryStructure;
7175 @@ -408,7 +411,7 @@ struct yaffs_ObjectStruct {
7176 __u8 renameAllowed:1; /* Some objects are not allowed to be renamed. */
7177 __u8 unlinkAllowed:1;
7178 __u8 dirty:1; /* the object needs to be written to flash */
7179 - __u8 valid:1; /* When the file system is being loaded up, this
7180 + __u8 valid:1; /* When the file system is being loaded up, this
7181 * object might be created before the data
7182 * is available (ie. file data records appear before the header).
7184 @@ -417,33 +420,36 @@ struct yaffs_ObjectStruct {
7185 __u8 deferedFree:1; /* For Linux kernel. Object is removed from NAND, but is
7186 * still in the inode cache. Free of object is defered.
7187 * until the inode is released.
7190 + __u8 beingCreated:1; /* This object is still being created so skip some checks. */
7192 - __u8 serial; /* serial number of chunk in NAND. Cached here */
7193 - __u16 sum; /* sum of the name to speed searching */
7194 + __u8 serial; /* serial number of chunk in NAND. Cached here */
7195 +/* __u16 sum_prev; */
7196 + __u16 sum; /* sum of the name to speed searching */
7197 +/* __u16 sum_trailer; */
7199 - struct yaffs_DeviceStruct *myDev; /* The device I'm on */
7200 + struct yaffs_DeviceStruct *myDev; /* The device I'm on */
7202 - struct list_head hashLink; /* list of objects in this hash bucket */
7203 + struct ylist_head hashLink; /* list of objects in this hash bucket */
7205 - struct list_head hardLinks; /* all the equivalent hard linked objects */
7206 + struct ylist_head hardLinks; /* all the equivalent hard linked objects */
7208 - /* directory structure stuff */
7209 - /* also used for linking up the free list */
7210 - struct yaffs_ObjectStruct *parent;
7211 - struct list_head siblings;
7212 + /* directory structure stuff */
7213 + /* also used for linking up the free list */
7214 + struct yaffs_ObjectStruct *parent;
7215 + struct ylist_head siblings;
7217 /* Where's my object header in NAND? */
7221 int nDataChunks; /* Number of data chunks attached to the file. */
7223 __u32 objectId; /* the object id value */
7228 #ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM
7229 - YCHAR shortName[YAFFS_SHORT_NAME_LENGTH + 1];
7230 + YCHAR shortName[YAFFS_SHORT_NAME_LENGTH + 1];
7234 @@ -485,31 +491,30 @@ struct yaffs_ObjectList_struct {
7235 typedef struct yaffs_ObjectList_struct yaffs_ObjectList;
7238 - struct list_head list;
7240 + struct ylist_head list;
7242 } yaffs_ObjectBucket;
7245 -/* yaffs_CheckpointObject holds the definition of an object as dumped
7246 +/* yaffs_CheckpointObject holds the definition of an object as dumped
7258 yaffs_ObjectType variantType:3;
7260 - __u8 softDeleted:1;
7264 + __u8 softDeleted:1;
7267 __u8 renameAllowed:1;
7268 __u8 unlinkAllowed:1;
7275 __u32 fileSizeOrEquivalentObjectId;
7277 }yaffs_CheckpointObject;
7278 @@ -528,25 +533,25 @@ typedef struct {
7279 /*----------------- Device ---------------------------------*/
7281 struct yaffs_DeviceStruct {
7282 - struct list_head devList;
7284 + struct ylist_head devList;
7287 - /* Entry parameters set up way early. Yaffs sets up the rest.*/
7288 - int nDataBytesPerChunk; /* Should be a power of 2 >= 512 */
7289 - int nChunksPerBlock; /* does not need to be a power of 2 */
7290 - int nBytesPerSpare; /* spare area size */
7291 - int startBlock; /* Start block we're allowed to use */
7292 - int endBlock; /* End block we're allowed to use */
7293 - int nReservedBlocks; /* We want this tuneable so that we can reduce */
7294 + /* Entry parameters set up way early. Yaffs sets up the rest.*/
7295 + int nDataBytesPerChunk; /* Should be a power of 2 >= 512 */
7296 + int nChunksPerBlock; /* does not need to be a power of 2 */
7297 + int spareBytesPerChunk;/* spare area size */
7298 + int startBlock; /* Start block we're allowed to use */
7299 + int endBlock; /* End block we're allowed to use */
7300 + int nReservedBlocks; /* We want this tuneable so that we can reduce */
7301 /* reserved blocks on NOR and RAM. */
7306 /* Stuff used by the shared space checkpointing mechanism */
7307 /* If this value is zero, then this mechanism is disabled */
7309 +// int nCheckpointReservedBlocks; /* Blocks to reserve for checkpoint data */
7311 - int nCheckpointReservedBlocks; /* Blocks to reserve for checkpoint data */
7317 int nShortOpCaches; /* If <= 0, then short op caching is disabled, else
7318 @@ -561,7 +566,7 @@ struct yaffs_DeviceStruct {
7319 * On an mtd this holds the mtd pointer.
7324 /* NAND access functions (Must be set before calling YAFFS)*/
7326 int (*writeChunkToNAND) (struct yaffs_DeviceStruct * dev,
7327 @@ -570,12 +575,13 @@ struct yaffs_DeviceStruct {
7328 int (*readChunkFromNAND) (struct yaffs_DeviceStruct * dev,
7329 int chunkInNAND, __u8 * data,
7330 yaffs_Spare * spare);
7331 - int (*eraseBlockInNAND) (struct yaffs_DeviceStruct * dev,
7333 - int (*initialiseNAND) (struct yaffs_DeviceStruct * dev);
7334 + int (*eraseBlockInNAND) (struct yaffs_DeviceStruct * dev,
7336 + int (*initialiseNAND) (struct yaffs_DeviceStruct * dev);
7337 + int (*deinitialiseNAND) (struct yaffs_DeviceStruct * dev);
7339 #ifdef CONFIG_YAFFS_YAFFS2
7340 - int (*writeChunkWithTagsToNAND) (struct yaffs_DeviceStruct * dev,
7341 + int (*writeChunkWithTagsToNAND) (struct yaffs_DeviceStruct * dev,
7342 int chunkInNAND, const __u8 * data,
7343 const yaffs_ExtendedTags * tags);
7344 int (*readChunkWithTagsFromNAND) (struct yaffs_DeviceStruct * dev,
7345 @@ -583,25 +589,27 @@ struct yaffs_DeviceStruct {
7346 yaffs_ExtendedTags * tags);
7347 int (*markNANDBlockBad) (struct yaffs_DeviceStruct * dev, int blockNo);
7348 int (*queryNANDBlock) (struct yaffs_DeviceStruct * dev, int blockNo,
7349 - yaffs_BlockState * state, int *sequenceNumber);
7350 + yaffs_BlockState * state, __u32 *sequenceNumber);
7355 - /* The removeObjectCallback function must be supplied by OS flavours that
7357 + /* The removeObjectCallback function must be supplied by OS flavours that
7358 * need it. The Linux kernel does not use this, but yaffs direct does use
7359 * it to implement the faster readdir
7361 void (*removeObjectCallback)(struct yaffs_ObjectStruct *obj);
7364 /* Callback to mark the superblock dirsty */
7365 void (*markSuperBlockDirty)(void * superblock);
7368 int wideTnodesDisabled; /* Set to disable wide tnodes */
7371 + YCHAR *pathDividers; /* String of legal path dividers */
7374 /* End of stuff that must be set before initialisation. */
7377 /* Checkpoint control. Can be set before or after initialisation */
7378 __u8 skipCheckpointRead;
7379 __u8 skipCheckpointWrite;
7380 @@ -610,34 +618,32 @@ struct yaffs_DeviceStruct {
7382 __u16 chunkGroupBits; /* 0 for devices <= 32MB. else log2(nchunks) - 16 */
7383 __u16 chunkGroupSize; /* == 2^^chunkGroupBits */
7386 /* Stuff to support wide tnodes */
7390 - /* Stuff to support various file offses to chunk/offset translations */
7391 - /* "Crumbs" for nDataBytesPerChunk not being a power of 2 */
7394 - __u32 crumbsPerChunk;
7396 - /* Straight shifting for nDataBytesPerChunk being a power of 2 */
7401 + /* Stuff for figuring out file offset to chunk conversions */
7402 + __u32 chunkShift; /* Shift value */
7403 + __u32 chunkDiv; /* Divisor after shifting: 1 for power-of-2 sizes */
7404 + __u32 chunkMask; /* Mask to use for power-of-2 case */
7406 + /* Stuff to handle inband tags */
7408 + __u32 totalBytesPerChunk;
7412 struct semaphore sem; /* Semaphore for waiting on erasure.*/
7413 struct semaphore grossLock; /* Gross locking semaphore */
7414 - __u8 *spareBuffer; /* For mtdif2 use. Don't know the size of the buffer
7415 + __u8 *spareBuffer; /* For mtdif2 use. Don't know the size of the buffer
7416 * at compile time so we have to allocate it.
7418 void (*putSuperFunc) (struct super_block * sb);
7427 @@ -646,7 +652,7 @@ struct yaffs_DeviceStruct {
7428 int internalEndBlock;
7434 /* Runtime checkpointing stuff */
7435 int checkpointPageSequence; /* running sequence number of checkpoint pages */
7436 @@ -662,13 +668,15 @@ struct yaffs_DeviceStruct {
7437 int checkpointMaxBlocks;
7438 __u32 checkpointSum;
7439 __u32 checkpointXor;
7442 + int nCheckpointBlocksRequired; /* Number of blocks needed to store current checkpoint set */
7445 yaffs_BlockInfo *blockInfo;
7446 __u8 *chunkBits; /* bitmap of chunks in use */
7447 unsigned blockInfoAlt:1; /* was allocated using alternative strategy */
7448 unsigned chunkBitsAlt:1; /* was allocated using alternative strategy */
7449 - int chunkBitmapStride; /* Number of bytes of chunkBits per block.
7450 + int chunkBitmapStride; /* Number of bytes of chunkBits per block.
7451 * Must be consistent with nChunksPerBlock.
7454 @@ -684,10 +692,14 @@ struct yaffs_DeviceStruct {
7455 yaffs_TnodeList *allocatedTnodeList;
7461 int nObjectsCreated;
7462 yaffs_Object *freeObjects;
7467 yaffs_ObjectList *allocatedObjectList;
7469 @@ -716,7 +728,7 @@ struct yaffs_DeviceStruct {
7472 int nUnmarkedDeletions;
7475 int hasPendingPrioritisedGCs; /* We think this device might have pending prioritised gcs */
7477 /* Special directories */
7478 @@ -727,7 +739,7 @@ struct yaffs_DeviceStruct {
7479 * __u8 bufferedData[YAFFS_CHUNKS_PER_BLOCK][YAFFS_BYTES_PER_CHUNK];
7480 * yaffs_Spare bufferedSpare[YAFFS_CHUNKS_PER_BLOCK];
7484 int bufferedBlock; /* Which block is buffered here? */
7485 int doingBufferedBlockRewrite;
7487 @@ -744,9 +756,11 @@ struct yaffs_DeviceStruct {
7488 int nUnlinkedFiles; /* Count of unlinked files. */
7489 int nBackgroundDeletions; /* Count of background deletions. */
7493 + /* Temporary buffer management */
7494 yaffs_TempBuffer tempBuffer[YAFFS_N_TEMP_BUFFERS];
7497 int unmanagedTempAllocations;
7498 int unmanagedTempDeallocations;
7500 @@ -758,17 +772,17 @@ struct yaffs_DeviceStruct {
7502 typedef struct yaffs_DeviceStruct yaffs_Device;
7504 -/* The static layout of bllock usage etc is stored in the super block header */
7505 +/* The static layout of block usage etc is stored in the super block header */
7510 int checkpointStartBlock;
7511 int checkpointEndBlock;
7515 } yaffs_SuperBlockHeader;
7518 /* The CheckpointDevice structure holds the device information that changes at runtime and
7519 * must be preserved over unmount/mount cycles.
7521 @@ -797,18 +811,6 @@ typedef struct {
7523 } yaffs_CheckpointValidity;
7525 -/* Function to manipulate block info */
7526 -static Y_INLINE yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device * dev, int blk)
7528 - if (blk < dev->internalStartBlock || blk > dev->internalEndBlock) {
7529 - T(YAFFS_TRACE_ERROR,
7531 - ("**>> yaffs: getBlockInfo block %d is not valid" TENDSTR),
7535 - return &dev->blockInfo[blk - dev->internalStartBlock];
7538 /*----------------------- YAFFS Functions -----------------------*/
7540 @@ -834,13 +836,13 @@ int yaffs_GetAttributes(yaffs_Object * o
7542 /* File operations */
7543 int yaffs_ReadDataFromFile(yaffs_Object * obj, __u8 * buffer, loff_t offset,
7546 int yaffs_WriteDataToFile(yaffs_Object * obj, const __u8 * buffer, loff_t offset,
7547 - int nBytes, int writeThrough);
7548 + int nBytes, int writeThrough);
7549 int yaffs_ResizeFile(yaffs_Object * obj, loff_t newSize);
7551 yaffs_Object *yaffs_MknodFile(yaffs_Object * parent, const YCHAR * name,
7552 - __u32 mode, __u32 uid, __u32 gid);
7553 + __u32 mode, __u32 uid, __u32 gid);
7554 int yaffs_FlushFile(yaffs_Object * obj, int updateTime);
7556 /* Flushing and checkpointing */
7557 @@ -899,4 +901,7 @@ void yaffs_DeleteChunk(yaffs_Device * de
7558 int yaffs_CheckFF(__u8 * buffer, int nBytes);
7559 void yaffs_HandleChunkError(yaffs_Device *dev, yaffs_BlockInfo *bi);
7561 +__u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo);
7562 +void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer, int lineNo);
7565 --- a/fs/yaffs2/moduleconfig.h
7566 +++ b/fs/yaffs2/moduleconfig.h
7567 @@ -54,11 +54,11 @@ that you need to continue to support. N
7569 Note: Use of this option generally requires that MTD's oob layout be
7570 adjusted to use the older-style format. See notes on tags formats and
7572 +MTD versions in yaffs_mtdif1.c.
7574 /* Default: Not selected */
7575 /* Meaning: Use older-style on-NAND data format with pageStatus byte */
7576 -#define CONFIG_YAFFS_9BYTE_TAGS
7577 +//#define CONFIG_YAFFS_9BYTE_TAGS
7579 #endif /* YAFFS_OUT_OF_TREE */
7581 --- a/fs/yaffs2/yaffs_mtdif1.h
7582 +++ b/fs/yaffs2/yaffs_mtdif1.h
7583 @@ -23,6 +23,6 @@ int nandmtd1_ReadChunkWithTagsFromNAND(y
7584 int nandmtd1_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo);
7586 int nandmtd1_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
7587 - yaffs_BlockState * state, int *sequenceNumber);
7588 + yaffs_BlockState * state, __u32 *sequenceNumber);
7591 --- a/fs/yaffs2/yaffs_mtdif2.h
7592 +++ b/fs/yaffs2/yaffs_mtdif2.h
7593 @@ -24,6 +24,6 @@ int nandmtd2_ReadChunkWithTagsFromNAND(y
7594 __u8 * data, yaffs_ExtendedTags * tags);
7595 int nandmtd2_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo);
7596 int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
7597 - yaffs_BlockState * state, int *sequenceNumber);
7598 + yaffs_BlockState * state, __u32 *sequenceNumber);
7601 --- a/fs/yaffs2/yaffs_checkptrw.c
7602 +++ b/fs/yaffs2/yaffs_checkptrw.c
7606 const char *yaffs_checkptrw_c_version =
7607 - "$Id: yaffs_checkptrw.c,v 1.14 2007-05-15 20:07:40 charles Exp $";
7608 + "$Id: yaffs_checkptrw.c,v 1.17 2008-08-12 22:51:57 charles Exp $";
7611 #include "yaffs_checkptrw.h"
7613 +#include "yaffs_getblockinfo.h"
7615 static int yaffs_CheckpointSpaceOk(yaffs_Device *dev)
7617 @@ -142,7 +142,7 @@ int yaffs_CheckpointOpen(yaffs_Device *d
7620 if(!dev->checkpointBuffer)
7621 - dev->checkpointBuffer = YMALLOC_DMA(dev->nDataBytesPerChunk);
7622 + dev->checkpointBuffer = YMALLOC_DMA(dev->totalBytesPerChunk);
7623 if(!dev->checkpointBuffer)
7626 @@ -324,6 +324,7 @@ int yaffs_CheckpointRead(yaffs_Device *d
7629 if(tags.chunkId != (dev->checkpointPageSequence + 1) ||
7630 + tags.eccResult > YAFFS_ECC_RESULT_FIXED ||
7631 tags.sequenceNumber != YAFFS_SEQUENCE_CHECKPOINT_DATA)
7634 --- a/fs/yaffs2/yaffs_tagscompat.c
7635 +++ b/fs/yaffs2/yaffs_tagscompat.c
7637 #include "yaffs_guts.h"
7638 #include "yaffs_tagscompat.h"
7639 #include "yaffs_ecc.h"
7640 +#include "yaffs_getblockinfo.h"
7642 static void yaffs_HandleReadDataError(yaffs_Device * dev, int chunkInNAND);
7644 @@ -252,6 +253,9 @@ static int yaffs_ReadChunkFromNAND(struc
7645 /* Must allocate enough memory for spare+2*sizeof(int) */
7646 /* for ecc results from device. */
7647 struct yaffs_NANDSpare nspare;
7649 + memset(&nspare,0,sizeof(nspare));
7652 dev->readChunkFromNAND(dev, chunkInNAND, data,
7653 (yaffs_Spare *) & nspare);
7654 @@ -336,7 +340,7 @@ static void yaffs_HandleReadDataError(ya
7655 int blockInNAND = chunkInNAND / dev->nChunksPerBlock;
7657 /* Mark the block for retirement */
7658 - yaffs_GetBlockInfo(dev, blockInNAND)->needsRetiring = 1;
7659 + yaffs_GetBlockInfo(dev, blockInNAND + dev->blockOffset)->needsRetiring = 1;
7660 T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,
7661 (TSTR("**>>Block %d marked for retirement" TENDSTR), blockInNAND));
7663 @@ -414,7 +418,16 @@ int yaffs_TagsCompatabilityWriteChunkWit
7665 tags.objectId = eTags->objectId;
7666 tags.chunkId = eTags->chunkId;
7667 - tags.byteCount = eTags->byteCount;
7669 + tags.byteCountLSB = eTags->byteCount & 0x3ff;
7671 + if(dev->nDataBytesPerChunk >= 1024){
7672 + tags.byteCountMSB = (eTags->byteCount >> 10) & 3;
7674 + tags.byteCountMSB = 3;
7678 tags.serialNumber = eTags->serialNumber;
7680 if (!dev->useNANDECC && data) {
7681 @@ -435,10 +448,10 @@ int yaffs_TagsCompatabilityReadChunkWith
7685 - yaffs_ECCResult eccResult;
7686 + yaffs_ECCResult eccResult = YAFFS_ECC_RESULT_UNKNOWN;
7688 static yaffs_Spare spareFF;
7690 + static int init = 0;
7693 memset(&spareFF, 0xFF, sizeof(spareFF));
7694 @@ -466,7 +479,11 @@ int yaffs_TagsCompatabilityReadChunkWith
7696 eTags->objectId = tags.objectId;
7697 eTags->chunkId = tags.chunkId;
7698 - eTags->byteCount = tags.byteCount;
7699 + eTags->byteCount = tags.byteCountLSB;
7701 + if(dev->nDataBytesPerChunk >= 1024)
7702 + eTags->byteCount |= (((unsigned) tags.byteCountMSB) << 10);
7704 eTags->serialNumber = tags.serialNumber;
7707 @@ -497,9 +514,9 @@ int yaffs_TagsCompatabilityMarkNANDBlock
7710 int yaffs_TagsCompatabilityQueryNANDBlock(struct yaffs_DeviceStruct *dev,
7711 - int blockNo, yaffs_BlockState *
7713 - int *sequenceNumber)
7715 + yaffs_BlockState *state,
7716 + __u32 *sequenceNumber)
7719 yaffs_Spare spare0, spare1;
7720 --- a/fs/yaffs2/yaffs_mtdif.c
7721 +++ b/fs/yaffs2/yaffs_mtdif.c
7725 const char *yaffs_mtdif_c_version =
7726 - "$Id: yaffs_mtdif.c,v 1.19 2007-02-14 01:09:06 wookey Exp $";
7727 + "$Id: yaffs_mtdif.c,v 1.21 2007-12-13 15:35:18 wookey Exp $";
7729 #include "yportenv.h"
7731 @@ -24,7 +24,7 @@ const char *yaffs_mtdif_c_version =
7732 #include "linux/time.h"
7733 #include "linux/mtd/nand.h"
7735 -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18))
7736 +#if (MTD_VERSION_CODE < MTD_VERSION(2,6,18))
7737 static struct nand_oobinfo yaffs_oobinfo = {
7740 @@ -36,7 +36,7 @@ static struct nand_oobinfo yaffs_noeccin
7744 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
7745 +#if (MTD_VERSION_CODE > MTD_VERSION(2,6,17))
7746 static inline void translate_spare2oob(const yaffs_Spare *spare, __u8 *oob)
7748 oob[0] = spare->tagByte0;
7749 @@ -75,14 +75,14 @@ int nandmtd_WriteChunkToNAND(yaffs_Devic
7750 const __u8 * data, const yaffs_Spare * spare)
7752 struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
7753 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
7754 +#if (MTD_VERSION_CODE > MTD_VERSION(2,6,17))
7755 struct mtd_oob_ops ops;
7760 loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
7761 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
7762 +#if (MTD_VERSION_CODE > MTD_VERSION(2,6,17))
7763 __u8 spareAsBytes[8]; /* OOB */
7766 @@ -139,14 +139,14 @@ int nandmtd_ReadChunkFromNAND(yaffs_Devi
7767 yaffs_Spare * spare)
7769 struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
7770 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
7771 +#if (MTD_VERSION_CODE > MTD_VERSION(2,6,17))
7772 struct mtd_oob_ops ops;
7777 loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
7778 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
7779 +#if (MTD_VERSION_CODE > MTD_VERSION(2,6,17))
7780 __u8 spareAsBytes[8]; /* OOB */
7783 --- a/fs/yaffs2/yaffs_nandemul2k.h
7784 +++ b/fs/yaffs2/yaffs_nandemul2k.h
7787 int nandemul2k_WriteChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev,
7788 int chunkInNAND, const __u8 * data,
7789 - yaffs_ExtendedTags * tags);
7790 + const yaffs_ExtendedTags * tags);
7791 int nandemul2k_ReadChunkWithTagsFromNAND(struct yaffs_DeviceStruct *dev,
7792 int chunkInNAND, __u8 * data,
7793 yaffs_ExtendedTags * tags);
7794 int nandemul2k_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo);
7795 int nandemul2k_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
7796 - yaffs_BlockState * state, int *sequenceNumber);
7797 + yaffs_BlockState * state, __u32 *sequenceNumber);
7798 int nandemul2k_EraseBlockInNAND(struct yaffs_DeviceStruct *dev,
7800 int nandemul2k_InitialiseNAND(struct yaffs_DeviceStruct *dev);