add generic 2.6.29 patches and config (squashfs still untested, user space mkfs still...
[openwrt/svn-archive/archive.git] / target / linux / generic-2.6 / patches-2.6.29 / 511-yaffs-cvs-2009-01-23.patch
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,
5 int blockNo);
6 int yaffs_TagsCompatabilityQueryNANDBlock(struct yaffs_DeviceStruct *dev,
7 - int blockNo, yaffs_BlockState *
8 - state, int *sequenceNumber);
9 + int blockNo,
10 + yaffs_BlockState *state,
11 + __u32 *sequenceNumber);
12
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
23 + in yaffs_mtdif1.c.
24
25 If unsure, say N.
26
27 @@ -109,26 +110,6 @@ config YAFFS_DISABLE_LAZY_LOAD
28
29 If unsure, say N.
30
31 -config YAFFS_CHECKPOINT_RESERVED_BLOCKS
32 - int "Reserved blocks for checkpointing"
33 - depends on YAFFS_YAFFS2
34 - default 10
35 - help
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
45 - checkpointing.
46 -
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.
51
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
56 @@ -18,6 +18,11 @@
57
58 #include "yaffs_guts.h"
59
60 +#if (MTD_VERSION_CODE < MTD_VERSION(2,6,18))
61 +extern struct nand_oobinfo yaffs_oobinfo;
62 +extern struct nand_oobinfo yaffs_noeccinfo;
63 +#endif
64 +
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
70 @@ -1,5 +1,5 @@
71 /*
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.
74 *
75 * Copyright (C) 2002-2007 Aleph One Ltd.
76 * for Toby Churchill Ltd and Brightstar Engineering
77 @@ -14,203 +14,145 @@
78 */
79
80 /*
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
83 - * applications.
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.
87 *
88 */
89
90 #ifndef __EXTRAS_H__
91 #define __EXTRAS_H__
92
93 -#if defined WIN32
94 -#define __inline__ __inline
95 -#define new newHack
96 -#endif
97 -
98 -#if !(defined __KERNEL__) || (defined WIN32)
99
100 -/* User space defines */
101 +#if !(defined __KERNEL__)
102
103 +/* Definition of types */
104 typedef unsigned char __u8;
105 typedef unsigned short __u16;
106 typedef unsigned __u32;
107
108 +#endif
109 +
110 /*
111 - * Simple doubly linked list implementation.
112 - *
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.
120 */
121
122 -#define prefetch(x) 1
123 -
124 -struct list_head {
125 - struct list_head *next, *prev;
126 +struct ylist_head {
127 + struct ylist_head *next; /* next in chain */
128 + struct ylist_head *prev; /* previous in chain */
129 };
130
131 -#define LIST_HEAD_INIT(name) { &(name), &(name) }
132
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)}
138
139 -#define INIT_LIST_HEAD(ptr) do { \
140 - (ptr)->next = (ptr); (ptr)->prev = (ptr); \
141 -} while (0)
142
143 -/*
144 - * Insert a new entry between two known consecutive entries.
145 - *
146 - * This is only for internal list manipulation where we know
147 - * the prev/next entries already!
148 - */
149 -static __inline__ void __list_add(struct list_head *new,
150 - struct list_head *prev,
151 - struct list_head *next)
152 -{
153 - next->prev = new;
154 - new->next = next;
155 - new->prev = prev;
156 - prev->next = new;
157 -}
158
159 -/**
160 - * list_add - add a new entry
161 - * @new: new entry to be added
162 - * @head: list head to add it after
163 - *
164 - * Insert a new entry after the specified head.
165 - * This is good for implementing stacks.
166 - */
167 -static __inline__ void list_add(struct list_head *new, struct list_head *head)
168 -{
169 - __list_add(new, head, head->next);
170 -}
171 +/* Initialise a list head to an empty list */
172 +#define YINIT_LIST_HEAD(p) \
173 +do { \
174 + (p)->next = (p);\
175 + (p)->prev = (p); \
176 +} while(0)
177
178 -/**
179 - * list_add_tail - add a new entry
180 - * @new: new entry to be added
181 - * @head: list head to add it before
182 - *
183 - * Insert a new entry before the specified head.
184 - * This is useful for implementing queues.
185 - */
186 -static __inline__ void list_add_tail(struct list_head *new,
187 - struct list_head *head)
188 +
189 +/* Add an element to a list */
190 +static __inline__ void ylist_add(struct ylist_head *newEntry,
191 + struct ylist_head *list)
192 {
193 - __list_add(new, head->prev, head);
194 + struct ylist_head *listNext = list->next;
195 +
196 + list->next = newEntry;
197 + newEntry->prev = list;
198 + newEntry->next = listNext;
199 + listNext->prev = newEntry;
200 +
201 }
202
203 -/*
204 - * Delete a list entry by making the prev/next entries
205 - * point to each other.
206 - *
207 - * This is only for internal list manipulation where we know
208 - * the prev/next entries already!
209 - */
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)
214 {
215 - next->prev = prev;
216 - prev->next = next;
217 + struct ylist_head *listPrev = list->prev;
218 +
219 + list->prev = newEntry;
220 + newEntry->next = list;
221 + newEntry->prev = listPrev;
222 + listPrev->next = newEntry;
223 +
224 }
225
226 -/**
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.
231 - */
232 -static __inline__ void list_del(struct list_head *entry)
233 +
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)
237 {
238 - __list_del(entry->prev, entry->next);
239 + struct ylist_head *listNext = entry->next;
240 + struct ylist_head *listPrev = entry->prev;
241 +
242 + listNext->prev = listPrev;
243 + listPrev->next = listNext;
244 +
245 }
246
247 -/**
248 - * list_del_init - deletes entry from list and reinitialize it.
249 - * @entry: the element to delete from the list.
250 - */
251 -static __inline__ void list_del_init(struct list_head *entry)
252 +static __inline__ void ylist_del_init(struct ylist_head *entry)
253 {
254 - __list_del(entry->prev, entry->next);
255 - INIT_LIST_HEAD(entry);
256 + ylist_del(entry);
257 + entry->next = entry->prev = entry;
258 }
259
260 -/**
261 - * list_empty - tests whether a list is empty
262 - * @head: the list to test.
263 - */
264 -static __inline__ int list_empty(struct list_head *head)
265 +
266 +/* Test if the list is empty */
267 +static __inline__ int ylist_empty(struct ylist_head *entry)
268 {
269 - return head->next == head;
270 + return (entry->next == entry);
271 }
272
273 -/**
274 - * list_splice - join two lists
275 - * @list: the new list to add.
276 - * @head: the place to add it in the first list.
277 +
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.
280 */
281 -static __inline__ void list_splice(struct list_head *list,
282 - struct list_head *head)
283 -{
284 - struct list_head *first = list->next;
285 +
286 +
287 +#define ylist_entry(entry, type, member) \
288 + ((type *)((char *)(entry)-(unsigned long)(&((type *)NULL)->member)))
289
290 - if (first != list) {
291 - struct list_head *last = list->prev;
292 - struct list_head *at = head->next;
293 -
294 - first->prev = head;
295 - head->next = first;
296 -
297 - last->next = at;
298 - at->prev = last;
299 - }
300 -}
301
302 -/**
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
309 */
310 -#define list_entry(ptr, type, member) \
311 - ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
312
313 -/**
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.
317 - */
318 -#define list_for_each(pos, head) \
319 - for (pos = (head)->next, prefetch(pos->next); pos != (head); \
320 - pos = pos->next, prefetch(pos->next))
321 -
322 -/**
323 - * list_for_each_safe - iterate over a list safe against removal
324 - * of list entry
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.
328 - */
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 )
334
335 -/*
336 - * File types
337 - */
338 -#define DT_UNKNOWN 0
339 -#define DT_FIFO 1
340 -#define DT_CHR 2
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)
344 +
345 +
346 +#if !(defined __KERNEL__)
347 +
348 +
349 +#ifndef WIN32
350 +#include <sys/stat.h>
351 +#endif
352 +
353 +
354 +#ifdef CONFIG_YAFFS_PROVIDE_DEFS
355 +/* File types */
356 +
357 +
358 +#define DT_UNKNOWN 0
359 +#define DT_FIFO 1
360 +#define DT_CHR 2
361 #define DT_DIR 4
362 #define DT_BLK 6
363 -#define DT_REG 8
364 -#define DT_LNK 10
365 -#define DT_SOCK 12
366 -#define DT_WHT 14
367 +#define DT_REG 8
368 +#define DT_LNK 10
369 +#define DT_SOCK 12
370 +#define DT_WHT 14
371 +
372
373 #ifndef WIN32
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
377 * has been changed!
378 */
379 -#define ATTR_MODE 1
380 -#define ATTR_UID 2
381 +#define ATTR_MODE 1
382 +#define ATTR_UID 2
383 #define ATTR_GID 4
384 #define ATTR_SIZE 8
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
392
393 struct iattr {
394 unsigned int ia_valid;
395 @@ -241,24 +179,21 @@ struct iattr {
396 unsigned ia_atime;
397 unsigned ia_mtime;
398 unsigned ia_ctime;
399 - unsigned int ia_attr_flags;
400 + unsigned int ia_attr_flags;
401 };
402
403 +#endif
404 +
405 +
406 #define KERN_DEBUG
407
408 #else
409
410 -#ifndef WIN32
411 #include <linux/types.h>
412 -#include <linux/list.h>
413 #include <linux/fs.h>
414 #include <linux/stat.h>
415 -#endif
416
417 #endif
418
419 -#if defined WIN32
420 -#undef new
421 -#endif
422
423 #endif
424 --- a/fs/yaffs2/yaffs_packedtags2.c
425 +++ b/fs/yaffs2/yaffs_packedtags2.c
426 @@ -37,60 +37,70 @@
427 #define EXTRA_OBJECT_TYPE_SHIFT (28)
428 #define EXTRA_OBJECT_TYPE_MASK ((0x0F) << EXTRA_OBJECT_TYPE_SHIFT)
429
430 -static void yaffs_DumpPackedTags2(const yaffs_PackedTags2 * pt)
431 +
432 +static void yaffs_DumpPackedTags2TagsPart(const yaffs_PackedTags2TagsPart * ptt)
433 {
434 T(YAFFS_TRACE_MTD,
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));
440 +}
441 +static void yaffs_DumpPackedTags2(const yaffs_PackedTags2 * pt)
442 +{
443 + yaffs_DumpPackedTags2TagsPart(&pt->t);
444 }
445
446 static void yaffs_DumpTags2(const yaffs_ExtendedTags * t)
447 {
448 T(YAFFS_TRACE_MTD,
449 (TSTR
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,
455 t->sequenceNumber));
456
457 }
458
459 -void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags * t)
460 +void yaffs_PackTags2TagsPart(yaffs_PackedTags2TagsPart * ptt, const yaffs_ExtendedTags * t)
461 {
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;
470
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;
480 }
481 if (t->extraShadows) {
482 - pt->t.chunkId |= EXTRA_SHADOWS_FLAG;
483 + ptt->chunkId |= EXTRA_SHADOWS_FLAG;
484 }
485
486 - pt->t.objectId &= ~EXTRA_OBJECT_TYPE_MASK;
487 - pt->t.objectId |=
488 + ptt->objectId &= ~EXTRA_OBJECT_TYPE_MASK;
489 + ptt->objectId |=
490 (t->extraObjectType << EXTRA_OBJECT_TYPE_SHIFT);
491
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;
498 } else {
499 - pt->t.byteCount = 0;
500 + ptt->byteCount = 0;
501 }
502 }
503
504 - yaffs_DumpPackedTags2(pt);
505 + yaffs_DumpPackedTags2TagsPart(ptt);
506 yaffs_DumpTags2(t);
507 +}
508 +
509 +
510 +void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags * t)
511 +{
512 + yaffs_PackTags2TagsPart(&pt->t,t);
513
514 #ifndef YAFFS_IGNORE_TAGS_ECC
515 {
516 @@ -101,20 +111,63 @@ void yaffs_PackTags2(yaffs_PackedTags2 *
517 #endif
518 }
519
520 -void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt)
521 +
522 +void yaffs_UnpackTags2TagsPart(yaffs_ExtendedTags * t, yaffs_PackedTags2TagsPart * ptt)
523 {
524
525 memset(t, 0, sizeof(yaffs_ExtendedTags));
526
527 yaffs_InitialiseTags(t);
528
529 + if (ptt->sequenceNumber != 0xFFFFFFFF) {
530 + t->blockBad = 0;
531 + t->chunkUsed = 1;
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;
538 +
539 + /* Do extra header info stuff */
540 +
541 + if (ptt->chunkId & EXTRA_HEADER_INFO_FLAG) {
542 + t->chunkId = 0;
543 + t->byteCount = 0;
544 +
545 + t->extraHeaderInfoAvailable = 1;
546 + t->extraParentObjectId =
547 + ptt->chunkId & (~(ALL_EXTRA_FLAGS));
548 + t->extraIsShrinkHeader =
549 + (ptt->chunkId & EXTRA_SHRINK_FLAG) ? 1 : 0;
550 + t->extraShadows =
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;
555 +
556 + if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) {
557 + t->extraEquivalentObjectId = ptt->byteCount;
558 + } else {
559 + t->extraFileLength = ptt->byteCount;
560 + }
561 + }
562 + }
563 +
564 + yaffs_DumpPackedTags2TagsPart(ptt);
565 + yaffs_DumpTags2(t);
566 +
567 +}
568 +
569 +
570 +void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt)
571 +{
572 +
573 + yaffs_ECCResult eccResult = YAFFS_ECC_RESULT_NO_ERROR;
574 +
575 if (pt->t.sequenceNumber != 0xFFFFFFFF) {
576 /* Page is in use */
577 -#ifdef YAFFS_IGNORE_TAGS_ECC
578 - {
579 - t->eccResult = YAFFS_ECC_RESULT_NO_ERROR;
580 - }
581 -#else
582 +#ifndef YAFFS_IGNORE_TAGS_ECC
583 {
584 yaffs_ECCOther ecc;
585 int result;
586 @@ -129,54 +182,27 @@ void yaffs_UnpackTags2(yaffs_ExtendedTag
587 &pt->ecc, &ecc);
588 switch(result){
589 case 0:
590 - t->eccResult = YAFFS_ECC_RESULT_NO_ERROR;
591 + eccResult = YAFFS_ECC_RESULT_NO_ERROR;
592 break;
593 case 1:
594 - t->eccResult = YAFFS_ECC_RESULT_FIXED;
595 + eccResult = YAFFS_ECC_RESULT_FIXED;
596 break;
597 case -1:
598 - t->eccResult = YAFFS_ECC_RESULT_UNFIXED;
599 + eccResult = YAFFS_ECC_RESULT_UNFIXED;
600 break;
601 default:
602 - t->eccResult = YAFFS_ECC_RESULT_UNKNOWN;
603 + eccResult = YAFFS_ECC_RESULT_UNKNOWN;
604 }
605 }
606 #endif
607 - t->blockBad = 0;
608 - t->chunkUsed = 1;
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;
615 -
616 - /* Do extra header info stuff */
617 -
618 - if (pt->t.chunkId & EXTRA_HEADER_INFO_FLAG) {
619 - t->chunkId = 0;
620 - t->byteCount = 0;
621 -
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;
627 - t->extraShadows =
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;
632 -
633 - if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) {
634 - t->extraEquivalentObjectId = pt->t.byteCount;
635 - } else {
636 - t->extraFileLength = pt->t.byteCount;
637 - }
638 - }
639 }
640
641 + yaffs_UnpackTags2TagsPart(t,&pt->t);
642 +
643 + t->eccResult = eccResult;
644 +
645 yaffs_DumpPackedTags2(pt);
646 yaffs_DumpTags2(t);
647
648 }
649 +
650 --- a/fs/yaffs2/yaffs_ecc.c
651 +++ b/fs/yaffs2/yaffs_ecc.c
652 @@ -29,7 +29,7 @@
653 */
654
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 $";
658
659 #include "yportenv.h"
660
661 --- a/fs/yaffs2/yaffs_packedtags2.h
662 +++ b/fs/yaffs2/yaffs_packedtags2.h
663 @@ -33,6 +33,11 @@ typedef struct {
664 yaffs_ECCOther ecc;
665 } yaffs_PackedTags2;
666
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);
670 +
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);
674 #endif
675 --- a/fs/yaffs2/yportenv.h
676 +++ b/fs/yaffs2/yportenv.h
677 @@ -17,6 +17,14 @@
678 #ifndef __YPORTENV_H__
679 #define __YPORTENV_H__
680
681 +/*
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.
685 + */
686 +
687 +#define MTD_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
688 +
689 #if defined CONFIG_YAFFS_WINCE
690
691 #include "ywinceenv.h"
692 @@ -26,7 +34,10 @@
693 #include "moduleconfig.h"
694
695 /* Linux kernel */
696 +
697 #include <linux/version.h>
698 +#define MTD_VERSION_CODE LINUX_VERSION_CODE
699 +
700 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
701 #include <linux/config.h>
702 #endif
703 @@ -40,6 +51,7 @@
704 #define YCHAR char
705 #define YUCHAR unsigned char
706 #define _Y(x) x
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)
711 @@ -90,6 +102,8 @@
712
713 #elif defined CONFIG_YAFFS_DIRECT
714
715 +#define MTD_VERSION_CODE MTD_VERSION(2,6,22)
716 +
717 /* Direct interface */
718 #include "ydirectenv.h"
719
720 @@ -111,6 +125,7 @@
721 #define YCHAR char
722 #define YUCHAR unsigned char
723 #define _Y(x) x
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;
729
730 #define T(mask,p) do{ if((mask) & (yaffs_traceMask | YAFFS_TRACE_ALWAYS)) TOUT(p);} while(0)
731
732 -#ifndef CONFIG_YAFFS_WINCE
733 -#define YBUG() T(YAFFS_TRACE_BUG,(TSTR("==>> yaffs bug: " __FILE__ " %d" TENDSTR),__LINE__))
734 +#ifndef YBUG
735 +#define YBUG() do {T(YAFFS_TRACE_BUG,(TSTR("==>> yaffs bug: " __FILE__ " %d" TENDSTR),__LINE__));} while(0)
736 #endif
737
738 #endif
739 --- a/fs/yaffs2/Makefile
740 +++ b/fs/yaffs2/Makefile
741 @@ -5,7 +5,6 @@
742 obj-$(CONFIG_YAFFS_FS) += yaffs.o
743
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
753 @@ -32,7 +32,7 @@
754 */
755
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;
760
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>
773
774 +#include "asm/div64.h"
775 +
776 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
777
778 #include <linux/statfs.h> /* Added NCB 15-8-2003 */
779 @@ -76,6 +77,12 @@ extern const char *yaffs_guts_c_version;
780
781 #endif
782
783 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26))
784 +#define YPROC_ROOT &proc_root
785 +#else
786 +#define YPROC_ROOT NULL
787 +#endif
788 +
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
794 #endif
795
796 +#if(LINUX_VERSION_CODE > KERNEL_VERSION(2,6,27))
797 +#define YAFFS_USE_WRITE_BEGIN_END 1
798 +#else
799 +#define YAFFS_USE_WRITE_BEGIN_END 0
800 +#endif
801 +
802 +
803 #include <asm/uaccess.h>
804
805 #include "yportenv.h"
806 @@ -96,14 +110,30 @@ extern const char *yaffs_guts_c_version;
807
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;
811
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);
817 #else
818 MODULE_PARM(yaffs_traceMask,"i");
819 MODULE_PARM(yaffs_wr_attempts,"i");
820 +MODULE_PARM(yaffs_auto_checkpoint,"i");
821 +#endif
822 +
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);
827 +
828 +#else
829 +/* Call local equivalent */
830 +#define YAFFS_USE_OWN_IGET
831 +#define Y_IGET(sb,inum) yaffs_iget((sb),(inum))
832 +
833 +static struct inode * yaffs_iget(struct super_block *sb, unsigned long ino);
834 #endif
835
836 /*#define T(x) printk x */
837 @@ -127,6 +157,8 @@ static void yaffs_put_super(struct super
838
839 static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n,
840 loff_t * pos);
841 +static ssize_t yaffs_hold_space(struct file *f);
842 +static void yaffs_release_space(struct file *f);
843
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
847 #else
848 static int yaffs_statfs(struct super_block *sb, struct statfs *buf);
849 #endif
850 -static void yaffs_read_inode(struct inode *inode);
851
852 +#ifdef YAFFS_HAS_PUT_INODE
853 static void yaffs_put_inode(struct inode *inode);
854 +#endif
855 +
856 static void yaffs_delete_inode(struct inode *);
857 static void yaffs_clear_inode(struct inode *);
858
859 @@ -193,10 +227,22 @@ static int yaffs_writepage(struct page *
860 #else
861 static int yaffs_writepage(struct page *page);
862 #endif
863 +
864 +
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);
872 +#else
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,
876 unsigned to);
877 +
878 +#endif
879
880 static int yaffs_readlink(struct dentry *dentry, char __user * buffer,
881 int buflen);
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,
889 +#else
890 .prepare_write = yaffs_prepare_write,
891 .commit_write = yaffs_commit_write,
892 +#endif
893 };
894
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,
901 };
902
903 #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18))
904 @@ -284,8 +336,13 @@ static struct file_operations yaffs_dir_
905
906 static struct super_operations yaffs_super_ops = {
907 .statfs = yaffs_statfs,
908 +
909 +#ifndef YAFFS_USE_OWN_IGET
910 .read_inode = yaffs_read_inode,
911 +#endif
912 +#ifdef YAFFS_HAS_PUT_INODE
913 .put_inode = yaffs_put_inode,
914 +#endif
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
919
920 }
921
922 +
923 +#ifdef YAFFS_HAS_PUT_INODE
924 +
925 /* For now put inode is just for debugging
926 * Put inode is called when the inode **structure** is put.
927 */
928 @@ -439,6 +499,7 @@ static void yaffs_put_inode(struct inode
929 atomic_read(&inode->i_count)));
930
931 }
932 +#endif
933
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;
938 }
939
940 +
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)
945 +
946 +{
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;
951 +
952 + int ret = 0;
953 + int space_held = 0;
954 +
955 + T(YAFFS_TRACE_OS, (KERN_DEBUG "start yaffs_write_begin\n"));
956 + /* Get a page */
957 + pg = __grab_cache_page(mapping,index);
958 + *pagep = pg;
959 + if(!pg){
960 + ret = -ENOMEM;
961 + goto out;
962 + }
963 + /* Get fs space */
964 + space_held = yaffs_hold_space(filp);
965 +
966 + if(!space_held){
967 + ret = -ENOSPC;
968 + goto out;
969 + }
970 +
971 + /* Update page if required */
972 +
973 + if (!Page_Uptodate(pg) && (offset || to < PAGE_CACHE_SIZE))
974 + ret = yaffs_readpage_nolock(filp, pg);
975 +
976 + if(ret)
977 + goto out;
978 +
979 + /* Happy path return */
980 + T(YAFFS_TRACE_OS, (KERN_DEBUG "end yaffs_write_begin - ok\n"));
981 +
982 + return 0;
983 +
984 +out:
985 + T(YAFFS_TRACE_OS, (KERN_DEBUG "end yaffs_write_begin fail returning %d\n",ret));
986 + if(space_held){
987 + yaffs_release_space(filp);
988 + }
989 + if(pg) {
990 + unlock_page(pg);
991 + page_cache_release(pg);
992 + }
993 + return ret;
994 +}
995 +
996 +#else
997 +
998 static int yaffs_prepare_write(struct file *f, struct page *pg,
999 unsigned offset, unsigned to)
1000 {
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);
1005 -
1006 return 0;
1007
1008 }
1009 +#endif
1010 +
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)
1015 +{
1016 + int ret = 0;
1017 + void *addr, *kva;
1018 + pgoff_t index = pos >> PAGE_CACHE_SHIFT;
1019 + uint32_t offset_into_page = pos & (PAGE_CACHE_SIZE -1);
1020 +
1021 +
1022 +
1023 + kva=kmap(pg);
1024 + addr = kva + offset_into_page;
1025 +
1026 + T(YAFFS_TRACE_OS,
1027 + (KERN_DEBUG "yaffs_write_end addr %x pos %x nBytes %d\n", (unsigned) addr,
1028 + (int)pos, copied));
1029 +
1030 + ret = yaffs_file_write(filp, addr, copied, &pos);
1031 +
1032 + if (ret != copied) {
1033 + T(YAFFS_TRACE_OS,
1034 + (KERN_DEBUG
1035 + "yaffs_write_end not same size ret %d copied %d\n",
1036 + ret, copied ));
1037 + SetPageError(pg);
1038 + ClearPageUptodate(pg);
1039 + } else {
1040 + SetPageUptodate(pg);
1041 + }
1042 +
1043 + kunmap(pg);
1044 +
1045 + yaffs_release_space(filp);
1046 + unlock_page(pg);
1047 + page_cache_release(pg);
1048 + return ret;
1049 +}
1050 +#else
1051
1052 static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset,
1053 unsigned to)
1054 {
1055
1056 - void *addr = page_address(pg) + offset;
1057 + void *addr, *kva;
1058 +
1059 loff_t pos = (((loff_t) pg->index) << PAGE_CACHE_SHIFT) + offset;
1060 int nBytes = to - offset;
1061 int nWritten;
1062
1063 unsigned spos = pos;
1064 - unsigned saddr = (unsigned)addr;
1065 + unsigned saddr;
1066 +
1067 + kva=kmap(pg);
1068 + addr = kva + offset;
1069 +
1070 + saddr = (unsigned) addr;
1071
1072 T(YAFFS_TRACE_OS,
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);
1076 }
1077
1078 + kunmap(pg);
1079 +
1080 T(YAFFS_TRACE_OS,
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;
1085
1086 }
1087 +#endif
1088 +
1089
1090 static void yaffs_FillInodeFromObject(struct inode *inode, yaffs_Object * obj)
1091 {
1092 @@ -753,6 +923,8 @@ static void yaffs_FillInodeFromObject(st
1093 break;
1094 }
1095
1096 + inode->i_flags |= S_NOATIME;
1097 +
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
1102 T(YAFFS_TRACE_OS,
1103 (KERN_DEBUG "yaffs_get_inode for object %d\n", obj->objectId));
1104
1105 - inode = iget(sb, obj->objectId);
1106 + inode = Y_IGET(sb, obj->objectId);
1107 + if(IS_ERR(inode))
1108 + return NULL;
1109
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;
1114 }
1115
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 */
1119 +
1120 +static ssize_t yaffs_hold_space(struct file *f)
1121 +{
1122 + yaffs_Object *obj;
1123 + yaffs_Device *dev;
1124 +
1125 + int nFreeChunks;
1126 +
1127 +
1128 + obj = yaffs_DentryToObject(f->f_dentry);
1129 +
1130 + dev = obj->myDev;
1131 +
1132 + yaffs_GrossLock(dev);
1133 +
1134 + nFreeChunks = yaffs_GetNumberOfFreeChunks(dev);
1135 +
1136 + yaffs_GrossUnlock(dev);
1137 +
1138 + return (nFreeChunks > 20) ? 1 : 0;
1139 +}
1140 +
1141 +static void yaffs_release_space(struct file *f)
1142 +{
1143 + yaffs_Object *obj;
1144 + yaffs_Device *dev;
1145 +
1146 +
1147 + obj = yaffs_DentryToObject(f->f_dentry);
1148 +
1149 + dev = obj->myDev;
1150 +
1151 + yaffs_GrossLock(dev);
1152 +
1153 +
1154 + yaffs_GrossUnlock(dev);
1155 +
1156 +}
1157 +
1158 static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir)
1159 {
1160 yaffs_Object *obj;
1161 yaffs_Device *dev;
1162 struct inode *inode = f->f_dentry->d_inode;
1163 unsigned long offset, curoffs;
1164 - struct list_head *i;
1165 + struct ylist_head *i;
1166 yaffs_Object *l;
1167
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;
1171 }
1172
1173 - list_for_each(i, &obj->variant.directoryVariant.children) {
1174 + ylist_for_each(i, &obj->variant.directoryVariant.children) {
1175 curoffs++;
1176 if (curoffs >= offset) {
1177 - l = list_entry(i, yaffs_Object, siblings);
1178 + l = ylist_entry(i, yaffs_Object, siblings);
1179
1180 yaffs_GetObjectName(l, name,
1181 YAFFS_MAX_NAME_LENGTH + 1);
1182 @@ -1269,7 +1485,7 @@ static int yaffs_rename(struct inode *ol
1183
1184 if (target &&
1185 target->variantType == YAFFS_OBJECT_TYPE_DIRECTORY &&
1186 - !list_empty(&target->variant.directoryVariant.children)) {
1187 + !ylist_empty(&target->variant.directoryVariant.children)) {
1188
1189 T(YAFFS_TRACE_OS, (KERN_DEBUG "target is non-empty dir\n"));
1190
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) {
1196 -
1197 +
1198 + if(dev->nDataBytesPerChunk & (dev->nDataBytesPerChunk - 1)){
1199 + /* Do this if chunk size is not a power of 2 */
1200 +
1201 + uint64_t bytesInDev;
1202 + uint64_t bytesFree;
1203 +
1204 + bytesInDev = ((uint64_t)((dev->endBlock - dev->startBlock +1))) *
1205 + ((uint64_t)(dev->nChunksPerBlock * dev->nDataBytesPerChunk));
1206 +
1207 + do_div(bytesInDev,sb->s_blocksize); /* bytesInDev becomes the number of blocks */
1208 + buf->f_blocks = bytesInDev;
1209 +
1210 + bytesFree = ((uint64_t)(yaffs_GetNumberOfFreeChunks(dev))) *
1211 + ((uint64_t)(dev->nDataBytesPerChunk));
1212 +
1213 + do_div(bytesFree,sb->s_blocksize);
1214 +
1215 + buf->f_bfree = bytesFree;
1216 +
1217 + } else if (sb->s_blocksize > dev->nDataBytesPerChunk) {
1218 +
1219 buf->f_blocks =
1220 - (dev->endBlock - dev->startBlock +
1221 - 1) * dev->nChunksPerBlock / (sb->s_blocksize /
1222 - dev->nDataBytesPerChunk);
1223 - buf->f_bfree =
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);
1229 + buf->f_bfree =
1230 + yaffs_GetNumberOfFreeChunks(dev) /
1231 + (sb->s_blocksize / dev->nDataBytesPerChunk);
1232 } else {
1233 -
1234 - buf->f_blocks =
1235 - (dev->endBlock - dev->startBlock +
1236 - 1) * dev->nChunksPerBlock * (dev->nDataBytesPerChunk /
1237 - sb->s_blocksize);
1238 - buf->f_bfree =
1239 - yaffs_GetNumberOfFreeChunks(dev) * (dev->nDataBytesPerChunk /
1240 - sb->s_blocksize);
1241 + buf->f_blocks =
1242 + (dev->endBlock - dev->startBlock + 1) *
1243 + dev->nChunksPerBlock *
1244 + (dev->nDataBytesPerChunk / sb->s_blocksize);
1245 +
1246 + buf->f_bfree =
1247 + yaffs_GetNumberOfFreeChunks(dev) *
1248 + (dev->nDataBytesPerChunk / sb->s_blocksize);
1249 }
1250 +
1251 +
1252 buf->f_files = 0;
1253 buf->f_ffree = 0;
1254 buf->f_bavail = buf->f_bfree;
1255 @@ -1378,7 +1616,6 @@ static int yaffs_statfs(struct super_blo
1256 }
1257
1258
1259 -/**
1260 static int yaffs_do_sync_fs(struct super_block *sb)
1261 {
1262
1263 @@ -1388,8 +1625,10 @@ static int yaffs_do_sync_fs(struct super
1264 if(sb->s_dirt) {
1265 yaffs_GrossLock(dev);
1266
1267 - if(dev)
1268 + if(dev){
1269 + yaffs_FlushEntireDeviceCache(dev);
1270 yaffs_CheckpointSave(dev);
1271 + }
1272
1273 yaffs_GrossUnlock(dev);
1274
1275 @@ -1397,7 +1636,7 @@ static int yaffs_do_sync_fs(struct super
1276 }
1277 return 0;
1278 }
1279 -**/
1280 +
1281
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
1285 {
1286
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);*/
1292 + return 0;
1293 #endif
1294 }
1295
1296 @@ -1422,10 +1663,48 @@ static int yaffs_sync_fs(struct super_bl
1297
1298 T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_sync_fs\n"));
1299
1300 - return 0; /* yaffs_do_sync_fs(sb);*/
1301 + if (yaffs_auto_checkpoint >= 1)
1302 + yaffs_do_sync_fs(sb);
1303 +
1304 + return 0;
1305
1306 }
1307
1308 +#ifdef YAFFS_USE_OWN_IGET
1309 +
1310 +static struct inode * yaffs_iget(struct super_block *sb, unsigned long ino)
1311 +{
1312 + struct inode *inode;
1313 + yaffs_Object *obj;
1314 + yaffs_Device *dev = yaffs_SuperToDevice(sb);
1315 +
1316 + T(YAFFS_TRACE_OS,
1317 + (KERN_DEBUG "yaffs_iget for %lu\n", ino));
1318 +
1319 + inode = iget_locked(sb, ino);
1320 + if (!inode)
1321 + return ERR_PTR(-ENOMEM);
1322 + if (!(inode->i_state & I_NEW))
1323 + return inode;
1324 +
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.
1328 + */
1329 +
1330 + yaffs_GrossLock(dev);
1331 +
1332 + obj = yaffs_FindObjectByNumber(dev, inode->i_ino);
1333 +
1334 + yaffs_FillInodeFromObject(inode, obj);
1335 +
1336 + yaffs_GrossUnlock(dev);
1337 +
1338 + unlock_new_inode(inode);
1339 + return inode;
1340 +}
1341 +
1342 +#else
1343
1344 static void yaffs_read_inode(struct inode *inode)
1345 {
1346 @@ -1449,7 +1728,9 @@ static void yaffs_read_inode(struct inod
1347 yaffs_GrossUnlock(dev);
1348 }
1349
1350 -static LIST_HEAD(yaffs_dev_list);
1351 +#endif
1352 +
1353 +static YLIST_HEAD(yaffs_dev_list);
1354
1355 #if 0 // not used
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);
1359
1360 /* we assume this is protected by lock_kernel() in mount/umount */
1361 - list_del(&dev->devList);
1362 + ylist_del(&dev->devList);
1363
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;
1368
1369 T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_MarkSuperBlockDirty() sb = %p\n",sb));
1370 -// if(sb)
1371 -// sb->s_dirt = 1;
1372 + if(sb)
1373 + sb->s_dirt = 1;
1374 }
1375
1376 typedef struct {
1377 @@ -1602,6 +1883,7 @@ static struct super_block *yaffs_interna
1378
1379 sb->s_magic = YAFFS_MAGIC;
1380 sb->s_op = &yaffs_super_ops;
1381 + sb->s_flags |= MS_NOATIME;
1382
1383 if (!sb)
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
1387
1388 if (yaffsVersion == 1 &&
1389 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1390 - mtd->writesize >= 2048) {
1391 -#else
1392 - mtd->oobblock >= 2048) {
1393 -#endif
1394 + WRITE_SIZE(mtd) >= 2048) {
1395 T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs2\n"));
1396 yaffsVersion = 2;
1397 }
1398
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) {
1403 -#else
1404 - mtd->oobblock == 512) {
1405 -#endif
1406 + if (yaffsVersion == 2 &&
1407 + !options.inband_tags &&
1408 + WRITE_SIZE(mtd) == 512){
1409 T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs1\n"));
1410 yaffsVersion = 1;
1411 }
1412 @@ -1719,12 +1994,9 @@ static struct super_block *yaffs_interna
1413 return NULL;
1414 }
1415
1416 -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
1417 - if (mtd->writesize < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
1418 -#else
1419 - if (mtd->oobblock < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
1420 -#endif
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;
1437
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);
1442 dev->isYaffs2 = 1;
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;
1447 #else
1448 - dev->nDataBytesPerChunk = mtd->oobblock;
1449 + dev->totalBytesPerChunk = mtd->oobblock;
1450 dev->nChunksPerBlock = mtd->erasesize / mtd->oobblock;
1451 #endif
1452 nBlocks = mtd->size / mtd->erasesize;
1453
1454 - dev->nCheckpointReservedBlocks = CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS;
1455 dev->startBlock = 0;
1456 dev->endBlock = nBlocks - 1;
1457 } else {
1458 @@ -1847,7 +2119,7 @@ static struct super_block *yaffs_interna
1459 dev->skipCheckpointWrite = options.skip_checkpoint_write;
1460
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);
1464
1465 init_MUTEX(&dev->grossLock);
1466
1467 @@ -1884,6 +2156,9 @@ static struct super_block *yaffs_interna
1468 return NULL;
1469 }
1470 sb->s_root = root;
1471 + sb->s_dirt = !dev->isCheckpointed;
1472 + T(YAFFS_TRACE_ALWAYS,
1473 + ("yaffs_read_super: isCheckpointed %d\n", dev->isCheckpointed));
1474
1475 T(YAFFS_TRACE_OS, ("yaffs_read_super: done\n"));
1476 return sb;
1477 @@ -1990,12 +2265,12 @@ static char *yaffs_dump_dev(char *buf, y
1478 {
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);
1495 - buf +=
1496 - sprintf(buf, "garbageCollections. %d\n", dev->garbageCollections);
1497 - buf +=
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);
1509
1510 return buf;
1511 }
1512 @@ -2033,7 +2307,7 @@ static int yaffs_proc_read(char *page,
1513 char **start,
1514 off_t offset, int count, int *eof, void *data)
1515 {
1516 - struct list_head *item;
1517 + struct ylist_head *item;
1518 char *buf = page;
1519 int step = offset;
1520 int n = 0;
1521 @@ -2057,8 +2331,8 @@ static int yaffs_proc_read(char *page,
1522 lock_kernel();
1523
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);
1529 if (n < step) {
1530 n++;
1531 continue;
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",
1535 S_IRUGO | S_IFREG,
1536 - &proc_root);
1537 + YPROC_ROOT);
1538
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__
1543 " removing. \n"));
1544
1545 - remove_proc_entry("yaffs", &proc_root);
1546 + remove_proc_entry("yaffs", YPROC_ROOT);
1547
1548 fsinst = fs_to_install;
1549
1550 --- /dev/null
1551 +++ b/fs/yaffs2/yaffs_getblockinfo.h
1552 @@ -0,0 +1,34 @@
1553 +/*
1554 + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
1555 + *
1556 + * Copyright (C) 2002-2007 Aleph One Ltd.
1557 + * for Toby Churchill Ltd and Brightstar Engineering
1558 + *
1559 + * Created by Charles Manning <charles@aleph1.co.uk>
1560 + *
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.
1564 + *
1565 + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
1566 + */
1567 +
1568 +#ifndef __YAFFS_GETBLOCKINFO_H__
1569 +#define __YAFFS_GETBLOCKINFO_H__
1570 +
1571 +#include "yaffs_guts.h"
1572 +
1573 +/* Function to manipulate block info */
1574 +static Y_INLINE yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device * dev, int blk)
1575 +{
1576 + if (blk < dev->internalStartBlock || blk > dev->internalEndBlock) {
1577 + T(YAFFS_TRACE_ERROR,
1578 + (TSTR
1579 + ("**>> yaffs: getBlockInfo block %d is not valid" TENDSTR),
1580 + blk));
1581 + YBUG();
1582 + }
1583 + return &dev->blockInfo[blk - dev->internalStartBlock];
1584 +}
1585 +
1586 +#endif
1587 --- a/fs/yaffs2/yaffs_nand.c
1588 +++ b/fs/yaffs2/yaffs_nand.c
1589 @@ -12,12 +12,13 @@
1590 */
1591
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 $";
1595
1596 #include "yaffs_nand.h"
1597 #include "yaffs_tagscompat.h"
1598 #include "yaffs_tagsvalidity.h"
1599
1600 +#include "yaffs_getblockinfo.h"
1601
1602 int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,
1603 __u8 * buffer,
1604 @@ -98,7 +99,7 @@ int yaffs_MarkBlockBad(yaffs_Device * de
1605 int yaffs_QueryInitialBlockState(yaffs_Device * dev,
1606 int blockNo,
1607 yaffs_BlockState * state,
1608 - unsigned *sequenceNumber)
1609 + __u32 *sequenceNumber)
1610 {
1611 blockNo -= dev->blockOffset;
1612
1613 --- a/fs/yaffs2/yaffs_guts.c
1614 +++ b/fs/yaffs2/yaffs_guts.c
1615 @@ -11,14 +11,16 @@
1616 * published by the Free Software Foundation.
1617 */
1618
1619 +
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 $";
1623
1624 #include "yportenv.h"
1625
1626 #include "yaffsinterface.h"
1627 #include "yaffs_guts.h"
1628 #include "yaffs_tagsvalidity.h"
1629 +#include "yaffs_getblockinfo.h"
1630
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"
1635
1636
1637 -#ifdef CONFIG_YAFFS_WINCE
1638 -void yfsd_LockYAFFS(BOOL fsLockOnly);
1639 -void yfsd_UnlockYAFFS(BOOL fsLockOnly);
1640 -#endif
1641 -
1642 #define YAFFS_PASSIVE_GC_CHUNKS 2
1643
1644 #include "yaffs_ecc.h"
1645 @@ -78,9 +75,6 @@ static int yaffs_DoGenericObjectDeletion
1646
1647 static yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device * dev, int blockNo);
1648
1649 -static __u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo);
1650 -static void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer,
1651 - int lineNo);
1652
1653 static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,
1654 int chunkInNAND);
1655 @@ -99,6 +93,7 @@ static void yaffs_VerifyFreeChunks(yaffs
1656
1657 static void yaffs_CheckObjectDetailsLoaded(yaffs_Object *in);
1658
1659 +static void yaffs_VerifyDirectory(yaffs_Object *directory);
1660 #ifdef YAFFS_PARANOID
1661 static int yaffs_CheckFileSanity(yaffs_Object * in);
1662 #else
1663 @@ -121,95 +116,109 @@ static yaffs_Tnode *yaffs_FindLevel0Tnod
1664
1665 /* Function to calculate chunk and offset */
1666
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)
1669 {
1670 - if(dev->chunkShift){
1671 - /* Easy-peasy power of 2 case */
1672 - *chunk = (__u32)(addr >> dev->chunkShift);
1673 - *offset = (__u32)(addr & dev->chunkMask);
1674 - }
1675 - else if(dev->crumbsPerChunk)
1676 + int chunk;
1677 + __u32 offset;
1678 +
1679 + chunk = (__u32)(addr >> dev->chunkShift);
1680 +
1681 + if(dev->chunkDiv == 1)
1682 {
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);
1690 }
1691 else
1692 - YBUG();
1693 + {
1694 + /* Non power-of-2 case */
1695 +
1696 + loff_t chunkBase;
1697 +
1698 + chunk /= dev->chunkDiv;
1699 +
1700 + chunkBase = ((loff_t)chunk) * dev->nDataBytesPerChunk;
1701 + offset = (__u32)(addr - chunkBase);
1702 + }
1703 +
1704 + *chunkOut = chunk;
1705 + *offsetOut = offset;
1706 }
1707
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.
1713 */
1714 -
1715 +
1716 static __u32 ShiftsGE(__u32 x)
1717 {
1718 int extraBits;
1719 int nShifts;
1720 -
1721 +
1722 nShifts = extraBits = 0;
1723 -
1724 +
1725 while(x>1){
1726 if(x & 1) extraBits++;
1727 x>>=1;
1728 nShifts++;
1729 }
1730
1731 - if(extraBits)
1732 + if(extraBits)
1733 nShifts++;
1734 -
1735 +
1736 return nShifts;
1737 }
1738
1739 /* Function to return the number of shifts to get a 1 in bit 0
1740 */
1741 -
1742 -static __u32 ShiftDiv(__u32 x)
1743 +
1744 +static __u32 Shifts(__u32 x)
1745 {
1746 int nShifts;
1747 -
1748 +
1749 nShifts = 0;
1750 -
1751 +
1752 if(!x) return 0;
1753 -
1754 +
1755 while( !(x&1)){
1756 x>>=1;
1757 nShifts++;
1758 }
1759 -
1760 +
1761 return nShifts;
1762 }
1763
1764
1765
1766 -/*
1767 +/*
1768 * Temporary buffer manipulations.
1769 */
1770
1771 -static int yaffs_InitialiseTempBuffers(yaffs_Device *dev)
1772 +static int yaffs_InitialiseTempBuffers(yaffs_Device *dev)
1773 {
1774 int i;
1775 __u8 *buf = (__u8 *)1;
1776 -
1777 +
1778 memset(dev->tempBuffer,0,sizeof(dev->tempBuffer));
1779 -
1780 +
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);
1786 }
1787 -
1788 +
1789 return buf ? YAFFS_OK : YAFFS_FAIL;
1790 -
1791 +
1792 }
1793
1794 -static __u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo)
1795 +__u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo)
1796 {
1797 int i, j;
1798 +
1799 + dev->tempInUse++;
1800 + if(dev->tempInUse > dev->maxTemp)
1801 + dev->maxTemp = dev->tempInUse;
1802 +
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
1807
1808 }
1809
1810 -static void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer,
1811 +void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer,
1812 int lineNo)
1813 {
1814 int i;
1815 +
1816 + dev->tempInUse--;
1817 +
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)
1823 {
1824 __u8 *blkBits = yaffs_BlockBits(dev, blk);
1825 -
1826 +
1827 yaffs_VerifyChunkBitId(dev,blk,chunk);
1828
1829 blkBits[chunk / 8] |= (1 << (chunk & 7));
1830 @@ -375,16 +387,16 @@ static int yaffs_CountChunkBits(yaffs_De
1831 n++;
1832 x >>=1;
1833 }
1834 -
1835 +
1836 blkBits++;
1837 }
1838 return n;
1839 }
1840
1841 -/*
1842 +/*
1843 * Verification code
1844 */
1845 -
1846 +
1847 static int yaffs_SkipVerification(yaffs_Device *dev)
1848 {
1849 return !(yaffs_traceMask & (YAFFS_TRACE_VERIFY | YAFFS_TRACE_VERIFY_FULL));
1850 @@ -417,14 +429,14 @@ static void yaffs_VerifyBlock(yaffs_Devi
1851 {
1852 int actuallyUsed;
1853 int inUse;
1854 -
1855 +
1856 if(yaffs_SkipVerification(dev))
1857 return;
1858 -
1859 +
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));
1864 -
1865 +
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]));
1872 }
1873 -
1874 +
1875 /* Check pages in use and soft deletions are legal */
1876 -
1877 +
1878 actuallyUsed = bi->pagesInUse - bi->softDeletions;
1879 -
1880 +
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));
1886 -
1887 -
1888 +
1889 +
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));
1895 -
1896 +
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
1900 */
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));
1907 -
1908 +
1909 }
1910
1911 static void yaffs_VerifyCollectedBlock(yaffs_Device *dev,yaffs_BlockInfo *bi,int n)
1912 {
1913 yaffs_VerifyBlock(dev,bi,n);
1914 -
1915 +
1916 /* After collection the block should be in the erased state */
1917 - /* TODO: This will need to change if we do partial gc */
1918 -
1919 - if(bi->blockState != YAFFS_BLOCK_STATE_EMPTY){
1920 + /* This will need to change if we do partial gc */
1921 +
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),
1925 n,bi->blockState));
1926 }
1927 @@ -479,28 +492,28 @@ static void yaffs_VerifyBlocks(yaffs_Dev
1928 int i;
1929 int nBlocksPerState[YAFFS_NUMBER_OF_BLOCK_STATES];
1930 int nIllegalBlockStates = 0;
1931 -
1932 +
1933
1934 if(yaffs_SkipVerification(dev))
1935 return;
1936
1937 memset(nBlocksPerState,0,sizeof(nBlocksPerState));
1938
1939 -
1940 +
1941 for(i = dev->internalStartBlock; i <= dev->internalEndBlock; i++){
1942 yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,i);
1943 yaffs_VerifyBlock(dev,bi,i);
1944
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]++;
1948 else
1949 nIllegalBlockStates++;
1950 -
1951 +
1952 }
1953 -
1954 +
1955 T(YAFFS_TRACE_VERIFY,(TSTR(""TENDSTR)));
1956 T(YAFFS_TRACE_VERIFY,(TSTR("Block summary"TENDSTR)));
1957 -
1958 +
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]));
1966 -
1967 +
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]));
1972 -
1973 +
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]));
1978 -
1979 +
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
1984 */
1985 static void yaffs_VerifyObjectHeader(yaffs_Object *obj, yaffs_ObjectHeader *oh, yaffs_ExtendedTags *tags, int parentCheck)
1986 {
1987 - if(yaffs_SkipVerification(obj->myDev))
1988 + if(obj && yaffs_SkipVerification(obj->myDev))
1989 return;
1990 -
1991 +
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));
1996 return;
1997 }
1998 -
1999 +
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
2004
2005 /*
2006 * Check that the object's parent ids match if parentCheck requested.
2007 - *
2008 + *
2009 * Tests do not apply to the root object.
2010 */
2011 -
2012 +
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));
2017 -
2018 -
2019 +
2020 +
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));
2029 -
2030 -
2031 +
2032 +
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
2037 int i;
2038 yaffs_Device *dev = obj->myDev;
2039 int ok = 1;
2040 - int nTnodeBytes = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
2041
2042 if (tn) {
2043 if (level > 0) {
2044 @@ -611,15 +623,14 @@ static int yaffs_VerifyTnodeWorker(yaffs
2045 }
2046 }
2047 } else if (level == 0) {
2048 - int i;
2049 yaffs_ExtendedTags tags;
2050 __u32 objectId = obj->objectId;
2051 -
2052 +
2053 chunkOffset <<= YAFFS_TNODES_LEVEL0_BITS;
2054 -
2055 +
2056 for(i = 0; i < YAFFS_NTNODES_LEVEL0; i++){
2057 __u32 theChunk = yaffs_GetChunkGroupBase(dev,tn,i);
2058 -
2059 +
2060 if(theChunk > 0){
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
2064 __u32 lastChunk;
2065 __u32 x;
2066 __u32 i;
2067 - int ok;
2068 yaffs_Device *dev;
2069 yaffs_ExtendedTags tags;
2070 yaffs_Tnode *tn;
2071 __u32 objectId;
2072 -
2073 - if(obj && yaffs_SkipVerification(obj->myDev))
2074 +
2075 + if(!obj)
2076 return;
2077
2078 + if(yaffs_SkipVerification(obj->myDev))
2079 + return;
2080 +
2081 dev = obj->myDev;
2082 objectId = obj->objectId;
2083 -
2084 +
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;
2090 requiredTallness++;
2091 }
2092 -
2093 +
2094 actualTallness = obj->variant.fileVariant.topLevel;
2095 -
2096 +
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));
2101 -
2102 -
2103 - /* Check that the chunks in the tnode tree are all correct.
2104 +
2105 +
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.
2109 */
2110
2111 if(yaffs_SkipNANDVerification(dev))
2112 return;
2113 -
2114 +
2115 for(i = 1; i <= lastChunk; i++){
2116 tn = yaffs_FindLevel0Tnode(dev, &obj->variant.fileVariant,i);
2117
2118 @@ -703,18 +716,12 @@ static void yaffs_VerifyFile(yaffs_Objec
2119
2120 }
2121
2122 -static void yaffs_VerifyDirectory(yaffs_Object *obj)
2123 -{
2124 - if(obj && yaffs_SkipVerification(obj->myDev))
2125 - return;
2126 -
2127 -}
2128
2129 static void yaffs_VerifyHardLink(yaffs_Object *obj)
2130 {
2131 if(obj && yaffs_SkipVerification(obj->myDev))
2132 return;
2133 -
2134 +
2135 /* Verify sane equivalent object */
2136 }
2137
2138 @@ -722,7 +729,7 @@ static void yaffs_VerifySymlink(yaffs_Ob
2139 {
2140 if(obj && yaffs_SkipVerification(obj->myDev))
2141 return;
2142 -
2143 +
2144 /* Verify symlink string */
2145 }
2146
2147 @@ -735,69 +742,77 @@ static void yaffs_VerifySpecial(yaffs_Ob
2148 static void yaffs_VerifyObject(yaffs_Object *obj)
2149 {
2150 yaffs_Device *dev;
2151 -
2152 +
2153 __u32 chunkMin;
2154 __u32 chunkMax;
2155 -
2156 +
2157 __u32 chunkIdOk;
2158 - __u32 chunkIsLive;
2159 -
2160 + __u32 chunkInRange;
2161 + __u32 chunkShouldNotBeDeleted;
2162 + __u32 chunkValid;
2163 +
2164 if(!obj)
2165 return;
2166 -
2167 +
2168 + if(obj->beingCreated)
2169 + return;
2170 +
2171 dev = obj->myDev;
2172 -
2173 +
2174 if(yaffs_SkipVerification(dev))
2175 return;
2176 -
2177 +
2178 /* Check sane object header chunk */
2179
2180 chunkMin = dev->internalStartBlock * dev->nChunksPerBlock;
2181 chunkMax = (dev->internalEndBlock+1) * dev->nChunksPerBlock - 1;
2182
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;
2194 +
2195 if(!obj->fake &&
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" : ""));
2205 }
2206 -
2207 - if(chunkIdOk && chunkIsLive &&!yaffs_SkipNANDVerification(dev)) {
2208 +
2209 + if(chunkValid &&!yaffs_SkipNANDVerification(dev)) {
2210 yaffs_ExtendedTags tags;
2211 yaffs_ObjectHeader *oh;
2212 __u8 *buffer = yaffs_GetTempBuffer(dev,__LINE__);
2213 -
2214 +
2215 oh = (yaffs_ObjectHeader *)buffer;
2216
2217 - yaffs_ReadChunkWithTagsFromNAND(dev, obj->chunkId,buffer, &tags);
2218 + yaffs_ReadChunkWithTagsFromNAND(dev, obj->hdrChunk,buffer, &tags);
2219
2220 yaffs_VerifyObjectHeader(obj,oh,&tags,1);
2221 -
2222 +
2223 yaffs_ReleaseTempBuffer(dev,buffer,__LINE__);
2224 }
2225 -
2226 +
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));
2234 }
2235 -
2236 +
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));
2243 }
2244 -
2245 +
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
2250 default:
2251 T(YAFFS_TRACE_VERIFY,
2252 (TSTR("Obj %d has illegaltype %d"TENDSTR),
2253 - obj->objectId,obj->variantType));
2254 + obj->objectId,obj->variantType));
2255 break;
2256 }
2257 -
2258 -
2259 +
2260 +
2261 }
2262
2263 static void yaffs_VerifyObjects(yaffs_Device *dev)
2264 {
2265 - yaffs_Object *obj;
2266 - int i;
2267 - struct list_head *lh;
2268 -
2269 - if(yaffs_SkipVerification(dev))
2270 - return;
2271 -
2272 - /* Iterate through the objects in each hash entry */
2273 -
2274 - for(i = 0; i < YAFFS_NOBJECT_BUCKETS; i++){
2275 - list_for_each(lh, &dev->objectBucket[i].list) {
2276 - if (lh) {
2277 - obj = list_entry(lh, yaffs_Object, hashLink);
2278 - yaffs_VerifyObject(obj);
2279 - }
2280 - }
2281 + yaffs_Object *obj;
2282 + int i;
2283 + struct ylist_head *lh;
2284 +
2285 + if(yaffs_SkipVerification(dev))
2286 + return;
2287 +
2288 + /* Iterate through the objects in each hash entry */
2289 +
2290 + for(i = 0; i < YAFFS_NOBJECT_BUCKETS; i++){
2291 + ylist_for_each(lh, &dev->objectBucket[i].list) {
2292 + if (lh) {
2293 + obj = ylist_entry(lh, yaffs_Object, hashLink);
2294 + yaffs_VerifyObject(obj);
2295 + }
2296 + }
2297 }
2298
2299 }
2300 @@ -851,7 +866,7 @@ static void yaffs_VerifyObjects(yaffs_De
2301 /*
2302 * Simple hash function. Needs to have a reasonable spread
2303 */
2304 -
2305 +
2306 static Y_INLINE int yaffs_HashFunction(int n)
2307 {
2308 n = abs(n);
2309 @@ -859,9 +874,10 @@ static Y_INLINE int yaffs_HashFunction(i
2310 }
2311
2312 /*
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.
2316 */
2317 -
2318 +
2319 yaffs_Object *yaffs_Root(yaffs_Device * dev)
2320 {
2321 return dev->rootDir;
2322 @@ -876,7 +892,7 @@ yaffs_Object *yaffs_LostNFound(yaffs_Dev
2323 /*
2324 * Erased NAND checking functions
2325 */
2326 -
2327 +
2328 int yaffs_CheckFF(__u8 * buffer, int nBytes)
2329 {
2330 /* Horrible, slow implementation */
2331 @@ -898,10 +914,10 @@ static int yaffs_CheckChunkErased(struct
2332 int result;
2333
2334 result = yaffs_ReadChunkWithTagsFromNAND(dev, chunkInNAND, data, &tags);
2335 -
2336 +
2337 if(tags.eccResult > YAFFS_ECC_RESULT_NO_ERROR)
2338 retval = YAFFS_FAIL;
2339 -
2340 +
2341
2342 if (!yaffs_CheckFF(data, dev->nDataBytesPerChunk) || tags.chunkUsed) {
2343 T(YAFFS_TRACE_NANDACCESS,
2344 @@ -915,7 +931,6 @@ static int yaffs_CheckChunkErased(struct
2345
2346 }
2347
2348 -
2349 static int yaffs_WriteNewChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev,
2350 const __u8 * data,
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);
2355
2356 - } while (writeOk != YAFFS_OK && attempts < yaffs_wr_attempts);
2357 + } while (writeOk != YAFFS_OK &&
2358 + (yaffs_wr_attempts <= 0 || attempts <= yaffs_wr_attempts));
2359 +
2360 + if(!writeOk)
2361 + chunk = -1;
2362
2363 if (attempts > 1) {
2364 T(YAFFS_TRACE_ERROR,
2365 @@ -1008,13 +1027,13 @@ static int yaffs_WriteNewChunkWithTagsTo
2366 /*
2367 * Block retiring for handling a broken block.
2368 */
2369 -
2370 +
2371 static void yaffs_RetireBlock(yaffs_Device * dev, int blockInNAND)
2372 {
2373 yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, blockInNAND);
2374
2375 yaffs_InvalidateCheckpoint(dev);
2376 -
2377 +
2378 yaffs_MarkBlockBad(dev, blockInNAND);
2379
2380 bi->blockState = YAFFS_BLOCK_STATE_DEAD;
2381 @@ -1028,7 +1047,7 @@ static void yaffs_RetireBlock(yaffs_Devi
2382 * Functions for robustisizing TODO
2383 *
2384 */
2385 -
2386 +
2387 static void yaffs_HandleWriteChunkOk(yaffs_Device * dev, int chunkInNAND,
2388 const __u8 * data,
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 ++;
2394 -
2395 +
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)));
2399
2400 }
2401 -
2402 +
2403 }
2404 }
2405
2406 @@ -1063,30 +1082,30 @@ static void yaffs_HandleWriteChunkError(
2407 yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, blockInNAND);
2408
2409 yaffs_HandleChunkError(dev,bi);
2410 -
2411 -
2412 +
2413 +
2414 if(erasedOk ) {
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));
2419
2420 -
2421 +
2422 }
2423 -
2424 +
2425 /* Delete the chunk */
2426 yaffs_DeleteChunk(dev, chunkInNAND, 1, __LINE__);
2427 }
2428
2429
2430 -/*---------------- Name handling functions ------------*/
2431 +/*---------------- Name handling functions ------------*/
2432
2433 static __u16 yaffs_CalcNameSum(const YCHAR * name)
2434 {
2435 __u16 sum = 0;
2436 __u16 i = 1;
2437
2438 - YUCHAR *bname = (YUCHAR *) name;
2439 + const YUCHAR *bname = (const YUCHAR *) name;
2440 if (bname) {
2441 while ((*bname) && (i < (YAFFS_MAX_NAME_LENGTH/2))) {
2442
2443 @@ -1099,12 +1118,14 @@ static __u16 yaffs_CalcNameSum(const YCH
2444 bname++;
2445 }
2446 }
2447 +
2448 return sum;
2449 }
2450
2451 static void yaffs_SetObjectName(yaffs_Object * obj, const YCHAR * name)
2452 {
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);
2457 } else {
2458 @@ -1120,7 +1141,7 @@ static void yaffs_SetObjectName(yaffs_Ob
2459 * The list is hooked together using the first pointer
2460 * in the tnode.
2461 */
2462 -
2463 +
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
2468
2469 if (nTnodes < 1)
2470 return YAFFS_OK;
2471 -
2472 +
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;
2476
2477 + if(tnodeSize < sizeof(yaffs_Tnode))
2478 + tnodeSize = sizeof(yaffs_Tnode);
2479 +
2480 +
2481 /* make these things */
2482
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;
2487 }
2488 -
2489 +
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.
2496 */
2497 -
2498 +
2499 tnl = YMALLOC(sizeof(yaffs_TnodeList));
2500 if (!tnl) {
2501 T(YAFFS_TRACE_ERROR,
2502 @@ -1233,17 +1258,23 @@ static yaffs_Tnode *yaffs_GetTnodeRaw(ya
2503 dev->nFreeTnodes--;
2504 }
2505
2506 + dev->nCheckpointBlocksRequired = 0; /* force recalculation*/
2507 +
2508 return tn;
2509 }
2510
2511 static yaffs_Tnode *yaffs_GetTnode(yaffs_Device * dev)
2512 {
2513 yaffs_Tnode *tn = yaffs_GetTnodeRaw(dev);
2514 + int tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
2515
2516 + if(tnodeSize < sizeof(yaffs_Tnode))
2517 + tnodeSize = sizeof(yaffs_Tnode);
2518 +
2519 if(tn)
2520 - memset(tn, 0, (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8);
2521 + memset(tn, 0, tnodeSize);
2522
2523 - return tn;
2524 + return tn;
2525 }
2526
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;
2530 dev->nFreeTnodes++;
2531 }
2532 + dev->nCheckpointBlocksRequired = 0; /* force recalculation*/
2533 +
2534 }
2535
2536 static void yaffs_DeinitialiseTnodes(yaffs_Device * dev)
2537 @@ -1299,19 +1332,19 @@ void yaffs_PutLevel0Tnode(yaffs_Device *
2538 __u32 bitInWord;
2539 __u32 wordInMap;
2540 __u32 mask;
2541 -
2542 +
2543 pos &= YAFFS_TNODES_LEVEL0_MASK;
2544 val >>= dev->chunkGroupBits;
2545 -
2546 +
2547 bitInMap = pos * dev->tnodeWidth;
2548 wordInMap = bitInMap /32;
2549 bitInWord = bitInMap & (32 -1);
2550 -
2551 +
2552 mask = dev->tnodeMask << bitInWord;
2553 -
2554 +
2555 map[wordInMap] &= ~mask;
2556 map[wordInMap] |= (mask & (val << bitInWord));
2557 -
2558 +
2559 if(dev->tnodeWidth > (32-bitInWord)) {
2560 bitInWord = (32 - bitInWord);
2561 wordInMap++;;
2562 @@ -1328,24 +1361,24 @@ static __u32 yaffs_GetChunkGroupBase(yaf
2563 __u32 bitInWord;
2564 __u32 wordInMap;
2565 __u32 val;
2566 -
2567 +
2568 pos &= YAFFS_TNODES_LEVEL0_MASK;
2569 -
2570 +
2571 bitInMap = pos * dev->tnodeWidth;
2572 wordInMap = bitInMap /32;
2573 bitInWord = bitInMap & (32 -1);
2574 -
2575 +
2576 val = map[wordInMap] >> bitInWord;
2577 -
2578 +
2579 if(dev->tnodeWidth > (32-bitInWord)) {
2580 bitInWord = (32 - bitInWord);
2581 wordInMap++;;
2582 val |= (map[wordInMap] << bitInWord);
2583 }
2584 -
2585 +
2586 val &= dev->tnodeMask;
2587 val <<= dev->chunkGroupBits;
2588 -
2589 +
2590 return val;
2591 }
2592
2593 @@ -1394,7 +1427,7 @@ static yaffs_Tnode *yaffs_FindLevel0Tnod
2594 while (level > 0 && tn) {
2595 tn = tn->
2596 internal[(chunkId >>
2597 - ( YAFFS_TNODES_LEVEL0_BITS +
2598 + ( YAFFS_TNODES_LEVEL0_BITS +
2599 (level - 1) *
2600 YAFFS_TNODES_INTERNAL_BITS)
2601 ) &
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.
2605 */
2606 -
2607 +
2608 static yaffs_Tnode *yaffs_AddOrFindLevel0Tnode(yaffs_Device * dev,
2609 yaffs_FileStructure * fStruct,
2610 __u32 chunkId,
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++) {
2615 -
2616 +
2617 tn = yaffs_GetTnode(dev);
2618
2619 if (tn) {
2620 @@ -1472,7 +1505,7 @@ static yaffs_Tnode *yaffs_AddOrFindLevel
2621
2622 l = fStruct->topLevel;
2623 tn = fStruct->top;
2624 -
2625 +
2626 if(l > 0) {
2627 while (l > 0 && tn) {
2628 x = (chunkId >>
2629 @@ -1492,13 +1525,13 @@ static yaffs_Tnode *yaffs_AddOrFindLevel
2630 if(tn->internal[x])
2631 yaffs_FreeTnode(dev,tn->internal[x]);
2632 tn->internal[x] = passedTn;
2633 -
2634 +
2635 } else if(!tn->internal[x]) {
2636 /* Don't have one, none passed in */
2637 tn->internal[x] = yaffs_GetTnode(dev);
2638 }
2639 }
2640 -
2641 +
2642 tn = tn->internal[x];
2643 l--;
2644 }
2645 @@ -1539,7 +1572,7 @@ static int yaffs_FindChunkInGroup(yaffs_
2646
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.
2652 */
2653
2654 @@ -1653,7 +1686,7 @@ static void yaffs_SoftDeleteChunk(yaffs_
2655 * of the tnode.
2656 * Thus, essentially this is the same as DeleteWorker except that the chunks are soft deleted.
2657 */
2658 -
2659 +
2660 static int yaffs_SoftDeleteWorker(yaffs_Object * in, yaffs_Tnode * tn,
2661 __u32 level, int chunkOffset)
2662 {
2663 @@ -1694,7 +1727,7 @@ static int yaffs_SoftDeleteWorker(yaffs_
2664 theChunk = yaffs_GetChunkGroupBase(dev,tn,i);
2665 if (theChunk) {
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
2669 * a block.
2670 */
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)
2679 */
2680
2681 @@ -1850,14 +1883,14 @@ static int yaffs_CreateFreeObjects(yaffs
2682 (TSTR("yaffs: Could not allocate more objects" TENDSTR)));
2683 return YAFFS_FAIL;
2684 }
2685 +
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]);
2690 + }
2691
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]);
2696 - }
2697 -
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
2704 {
2705 yaffs_Object *tn = NULL;
2706
2707 +#ifdef VALGRIND_TEST
2708 + tn = YMALLOC(sizeof(yaffs_Object));
2709 +#else
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
2714 dev->freeObjects =
2715 (yaffs_Object *) (dev->freeObjects->siblings.next);
2716 dev->nFreeObjects--;
2717 -
2718 + }
2719 +#endif
2720 + if(tn){
2721 /* Now sweeten it up... */
2722
2723 memset(tn, 0, sizeof(yaffs_Object));
2724 + tn->beingCreated = 1;
2725 +
2726 tn->myDev = dev;
2727 - tn->chunkId = -1;
2728 + tn->hdrChunk = 0;
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);
2736 +
2737 +
2738 + /* Now make the directory sane */
2739 + if(dev->rootDir){
2740 + tn->parent = dev->rootDir;
2741 + ylist_add(&(tn->siblings),&dev->rootDir->variant.directoryVariant.children);
2742 + }
2743
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
2749 */
2750 if (dev->lostNFoundDir) {
2751 yaffs_AddObjectToDirectory(dev->lostNFoundDir, tn);
2752 }
2753 +
2754 + tn->beingCreated = 0;
2755 }
2756 +
2757 + dev->nCheckpointBlocksRequired = 0; /* force recalculation*/
2758
2759 return tn;
2760 }
2761 @@ -1917,14 +1968,14 @@ static yaffs_Object *yaffs_CreateFakeDir
2762 yaffs_Object *obj =
2763 yaffs_CreateNewObject(dev, number, YAFFS_OBJECT_TYPE_DIRECTORY);
2764 if (obj) {
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 */
2769 obj->deleted = 0;
2770 obj->unlinked = 0;
2771 obj->yst_mode = mode;
2772 obj->myDev = dev;
2773 - obj->chunkId = 0; /* Not a valid chunk. */
2774 + obj->hdrChunk = 0; /* Not a valid chunk. */
2775 }
2776
2777 return obj;
2778 @@ -1934,14 +1985,14 @@ static yaffs_Object *yaffs_CreateFakeDir
2779 static void yaffs_UnhashObject(yaffs_Object * tn)
2780 {
2781 int bucket;
2782 - yaffs_Device *dev = tn->myDev;
2783 + yaffs_Device *dev = tn->myDev;
2784
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--;
2790 - }
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--;
2796 + }
2797
2798 }
2799
2800 @@ -1951,6 +2002,13 @@ static void yaffs_FreeObject(yaffs_Objec
2801
2802 yaffs_Device *dev = tn->myDev;
2803
2804 +
2805 + if(tn->parent)
2806 + YBUG();
2807 + if(!ylist_empty(&tn->siblings))
2808 + YBUG();
2809 +
2810 +
2811 #ifdef __KERNEL__
2812 if (tn->myInode) {
2813 /* We're still hooked up to a cached inode.
2814 @@ -1961,12 +2019,18 @@ static void yaffs_FreeObject(yaffs_Objec
2815 }
2816 #endif
2817
2818 - yaffs_UnhashObject(tn);
2819 + yaffs_UnhashObject(tn);
2820 +
2821 +#ifdef VALGRIND_TEST
2822 + YFREE(tn);
2823 +#else
2824 + /* Link into the free list. */
2825 + tn->siblings.next = (struct ylist_head *)(dev->freeObjects);
2826 + dev->freeObjects = tn;
2827 + dev->nFreeObjects++;
2828 +#endif
2829 + dev->nCheckpointBlocksRequired = 0; /* force recalculation*/
2830
2831 - /* Link into the free list. */
2832 - tn->siblings.next = (struct list_head *)(dev->freeObjects);
2833 - dev->freeObjects = tn;
2834 - dev->nFreeObjects++;
2835 }
2836
2837 #ifdef __KERNEL__
2838 @@ -2004,12 +2068,12 @@ static void yaffs_InitialiseObjects(yaff
2839
2840 dev->allocatedObjectList = NULL;
2841 dev->freeObjects = NULL;
2842 - dev->nFreeObjects = 0;
2843 + dev->nFreeObjects = 0;
2844
2845 - for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) {
2846 - INIT_LIST_HEAD(&dev->objectBucket[i].list);
2847 - dev->objectBucket[i].count = 0;
2848 - }
2849 + for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) {
2850 + YINIT_LIST_HEAD(&dev->objectBucket[i].list);
2851 + dev->objectBucket[i].count = 0;
2852 + }
2853
2854 }
2855
2856 @@ -2055,26 +2119,26 @@ static int yaffs_CreateNewObjectNumber(y
2857
2858 /* Now find an object value that has not already been taken
2859 * by scanning the list.
2860 - */
2861 + */
2862
2863 - int found = 0;
2864 - struct list_head *i;
2865 + int found = 0;
2866 + struct ylist_head *i;
2867
2868 - __u32 n = (__u32) bucket;
2869 + __u32 n = (__u32) bucket;
2870
2871 /* yaffs_CheckObjectHashSanity(); */
2872
2873 while (!found) {
2874 - found = 1;
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 */
2879 - if (i
2880 - && list_entry(i, yaffs_Object,
2881 - hashLink)->objectId == n) {
2882 - found = 0;
2883 - }
2884 + found = 1;
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 */
2889 + if (i
2890 + && ylist_entry(i, yaffs_Object,
2891 + hashLink)->objectId == n) {
2892 + found = 0;
2893 + }
2894 }
2895 }
2896 }
2897 @@ -2085,27 +2149,27 @@ static int yaffs_CreateNewObjectNumber(y
2898
2899 static void yaffs_HashObject(yaffs_Object * in)
2900 {
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;
2905
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++;
2910
2911 }
2912
2913 yaffs_Object *yaffs_FindObjectByNumber(yaffs_Device * dev, __u32 number)
2914 {
2915 - int bucket = yaffs_HashFunction(number);
2916 - struct list_head *i;
2917 - yaffs_Object *in;
2918 -
2919 - list_for_each(i, &dev->objectBucket[bucket].list) {
2920 - /* Look if it is in the list */
2921 - if (i) {
2922 - in = list_entry(i, yaffs_Object, hashLink);
2923 - if (in->objectId == number) {
2924 + int bucket = yaffs_HashFunction(number);
2925 + struct ylist_head *i;
2926 + yaffs_Object *in;
2927 +
2928 + ylist_for_each(i, &dev->objectBucket[bucket].list) {
2929 + /* Look if it is in the list */
2930 + if (i) {
2931 + in = ylist_entry(i, yaffs_Object, hashLink);
2932 + if (in->objectId == number) {
2933 #ifdef __KERNEL__
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)
2937 return NULL;
2938 #endif
2939 @@ -2123,7 +2187,7 @@ yaffs_Object *yaffs_CreateNewObject(yaff
2940 {
2941
2942 yaffs_Object *theObject;
2943 - yaffs_Tnode *tn;
2944 + yaffs_Tnode *tn = NULL;
2945
2946 if (number < 0) {
2947 number = yaffs_CreateNewObjectNumber(dev);
2948 @@ -2132,7 +2196,7 @@ yaffs_Object *yaffs_CreateNewObject(yaff
2949 theObject = yaffs_AllocateEmptyObject(dev);
2950 if(!theObject)
2951 return NULL;
2952 -
2953 +
2954 if(type == YAFFS_OBJECT_TYPE_FILE){
2955 tn = yaffs_GetTnode(dev);
2956 if(!tn){
2957 @@ -2140,8 +2204,8 @@ yaffs_Object *yaffs_CreateNewObject(yaff
2958 return NULL;
2959 }
2960 }
2961 -
2962 -
2963 +
2964 +
2965
2966 if (theObject) {
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;
2971 #endif
2972 +
2973 +#if 0
2974 + theObject->sum_prev = 12345;
2975 + theObject->sum_trailer = 6789;
2976 +#endif
2977 +
2978 switch (type) {
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;
2985 - break;
2986 - case YAFFS_OBJECT_TYPE_DIRECTORY:
2987 - INIT_LIST_HEAD(&theObject->variant.directoryVariant.
2988 - children);
2989 - break;
2990 - case YAFFS_OBJECT_TYPE_SYMLINK:
2991 + theObject->variant.fileVariant.top = tn;
2992 + break;
2993 + case YAFFS_OBJECT_TYPE_DIRECTORY:
2994 + YINIT_LIST_HEAD(&theObject->variant.directoryVariant.
2995 + children);
2996 + break;
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
3002 return theObject;
3003
3004 }
3005 -
3006 +
3007
3008 static YCHAR *yaffs_CloneString(const YCHAR * str)
3009 {
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)
3013 */
3014 -
3015 +
3016 static yaffs_Object *yaffs_MknodObject(yaffs_ObjectType type,
3017 yaffs_Object * parent,
3018 const YCHAR * name,
3019 @@ -2238,7 +2308,7 @@ static yaffs_Object *yaffs_MknodObject(y
3020 const YCHAR * aliasString, __u32 rdev)
3021 {
3022 yaffs_Object *in;
3023 - YCHAR *str;
3024 + YCHAR *str = NULL;
3025
3026 yaffs_Device *dev = parent->myDev;
3027
3028 @@ -2249,6 +2319,9 @@ static yaffs_Object *yaffs_MknodObject(y
3029
3030 in = yaffs_CreateNewObject(dev, -1, type);
3031
3032 + if(!in)
3033 + return YAFFS_FAIL;
3034 +
3035 if(type == YAFFS_OBJECT_TYPE_SYMLINK){
3036 str = yaffs_CloneString(aliasString);
3037 if(!str){
3038 @@ -2256,11 +2329,11 @@ static yaffs_Object *yaffs_MknodObject(y
3039 return NULL;
3040 }
3041 }
3042 -
3043 -
3044 +
3045 +
3046
3047 if (in) {
3048 - in->chunkId = -1;
3049 + in->hdrChunk = 0;
3050 in->valid = 1;
3051 in->variantType = type;
3052
3053 @@ -2293,13 +2366,13 @@ static yaffs_Object *yaffs_MknodObject(y
3054 break;
3055 case YAFFS_OBJECT_TYPE_HARDLINK:
3056 in->variant.hardLinkVariant.equivalentObject =
3057 - equivalentObject;
3058 - in->variant.hardLinkVariant.equivalentObjectId =
3059 - equivalentObject->objectId;
3060 - list_add(&in->hardLinks, &equivalentObject->hardLinks);
3061 - break;
3062 - case YAFFS_OBJECT_TYPE_FILE:
3063 - case YAFFS_OBJECT_TYPE_DIRECTORY:
3064 + equivalentObject;
3065 + in->variant.hardLinkVariant.equivalentObjectId =
3066 + equivalentObject->objectId;
3067 + ylist_add(&in->hardLinks, &equivalentObject->hardLinks);
3068 + break;
3069 + case YAFFS_OBJECT_TYPE_FILE:
3070 + case YAFFS_OBJECT_TYPE_DIRECTORY:
3071 case YAFFS_OBJECT_TYPE_SPECIAL:
3072 case YAFFS_OBJECT_TYPE_UNKNOWN:
3073 /* do nothing */
3074 @@ -2378,11 +2451,11 @@ static int yaffs_ChangeObjectName(yaffs_
3075 if (newDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) {
3076 T(YAFFS_TRACE_ALWAYS,
3077 (TSTR
3078 - ("tragendy: yaffs_ChangeObjectName: newDir is not a directory"
3079 + ("tragedy: yaffs_ChangeObjectName: newDir is not a directory"
3080 TENDSTR)));
3081 YBUG();
3082 }
3083 -
3084 +
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_
3089
3090 existingTarget = yaffs_FindObjectByName(newDir, newName);
3091
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.
3098 */
3099 if ((unlinkOp ||
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)
3103 {
3104 - yaffs_Object *obj;
3105 - yaffs_Object *existingTarget;
3106 + yaffs_Object *obj=NULL;
3107 + yaffs_Object *existingTarget=NULL;
3108 int force = 0;
3109 +
3110 +
3111 + if(!oldDir || oldDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY)
3112 + YBUG();
3113 + if(!newDir || newDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY)
3114 + YBUG();
3115
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
3119 }
3120 #endif
3121
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)
3131 /* ENAMETOOLONG */
3132 return YAFFS_FAIL;
3133
3134 + obj = yaffs_FindObjectByName(oldDir, oldName);
3135 +
3136 if (obj && obj->renameAllowed) {
3137
3138 /* Now do the handling for an existing target, if there is one */
3139
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
3157 */
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)
3161 {
3162 int nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1;
3163 -
3164 +
3165 dev->blockInfo = NULL;
3166 dev->chunkBits = NULL;
3167 -
3168 +
3169 dev->allocationBlock = -1; /* force it to get a new one */
3170
3171 /* If the first allocation strategy fails, thry the alternate one */
3172 @@ -2493,9 +2567,9 @@ static int yaffs_InitialiseBlocks(yaffs_
3173 }
3174 else
3175 dev->blockInfoAlt = 0;
3176 -
3177 +
3178 if(dev->blockInfo){
3179 -
3180 +
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_
3185 else
3186 dev->chunkBitsAlt = 0;
3187 }
3188 -
3189 +
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;
3195
3196 dev->blockInfo = NULL;
3197 -
3198 +
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
3203 int prioritised=0;
3204 yaffs_BlockInfo *bi;
3205 int pendingPrioritisedExist = 0;
3206 -
3207 +
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++){
3211
3212 bi = yaffs_GetBlockInfo(dev, i);
3213 //yaffs_VerifyBlock(dev,bi,i);
3214 -
3215 +
3216 if(bi->gcPrioritise) {
3217 pendingPrioritisedExist = 1;
3218 if(bi->blockState == YAFFS_BLOCK_STATE_FULL &&
3219 @@ -2610,7 +2684,7 @@ static int yaffs_FindBlockForGarbageColl
3220 }
3221 }
3222 }
3223 -
3224 +
3225 if(!pendingPrioritisedExist) /* None found, so we can clear this */
3226 dev->hasPendingPrioritisedGCs = 0;
3227 }
3228 @@ -2662,7 +2736,7 @@ static int yaffs_FindBlockForGarbageColl
3229 dirtiest = b;
3230 pagesInUse = 0;
3231 }
3232 - else
3233 + else
3234 #endif
3235
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.
3240 */
3241 -
3242 +
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" : ""));
3246 -
3247 +
3248 bi->blockState = YAFFS_BLOCK_STATE_DIRTY;
3249
3250 if (!bi->needsRetiring) {
3251 @@ -2716,7 +2790,7 @@ static void yaffs_BlockBecameDirty(yaffs
3252 }
3253 }
3254
3255 - if (erasedOk &&
3256 + if (erasedOk &&
3257 ((yaffs_traceMask & YAFFS_TRACE_ERASE) || !yaffs_SkipVerification(dev))) {
3258 int i;
3259 for (i = 0; i < dev->nChunksPerBlock; i++) {
3260 @@ -2763,11 +2837,11 @@ static int yaffs_FindBlockForAllocation(
3261 * Can't get space to gc
3262 */
3263 T(YAFFS_TRACE_ERROR,
3264 - (TSTR("yaffs tragedy: no more eraased blocks" TENDSTR)));
3265 + (TSTR("yaffs tragedy: no more erased blocks" TENDSTR)));
3266
3267 return -1;
3268 }
3269 -
3270 +
3271 /* Find an empty block. */
3272
3273 for (i = dev->internalStartBlock; i <= dev->internalEndBlock; i++) {
3274 @@ -2794,13 +2868,48 @@ static int yaffs_FindBlockForAllocation(
3275
3276 T(YAFFS_TRACE_ALWAYS,
3277 (TSTR
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));
3281
3282 return -1;
3283 }
3284
3285
3286 +
3287 +static int yaffs_CalcCheckpointBlocksRequired(yaffs_Device *dev)
3288 +{
3289 + if(!dev->nCheckpointBlocksRequired &&
3290 + dev->isYaffs2){
3291 + /* Not a valid value so recalculate */
3292 + int nBytes = 0;
3293 + int nBlocks;
3294 + int devBlocks = (dev->endBlock - dev->startBlock + 1);
3295 + int tnodeSize;
3296 +
3297 + tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
3298 +
3299 + if(tnodeSize < sizeof(yaffs_Tnode))
3300 + tnodeSize = sizeof(yaffs_Tnode);
3301 +
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*/
3310 +
3311 + /* Round up and add 2 blocks to allow for some bad blocks, so add 3 */
3312 +
3313 + nBlocks = (nBytes/(dev->nDataBytesPerChunk * dev->nChunksPerBlock)) + 3;
3314 +
3315 + dev->nCheckpointBlocksRequired = nBlocks;
3316 + }
3317 +
3318 + return dev->nCheckpointBlocksRequired;
3319 +}
3320 +
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
3325 int reservedChunks;
3326 int reservedBlocks = dev->nReservedBlocks;
3327 int checkpointBlocks;
3328 -
3329 - checkpointBlocks = dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint;
3330 - if(checkpointBlocks < 0)
3331 - checkpointBlocks = 0;
3332 -
3333 +
3334 + if(dev->isYaffs2){
3335 + checkpointBlocks = yaffs_CalcCheckpointBlocksRequired(dev) -
3336 + dev->blocksInCheckpoint;
3337 + if(checkpointBlocks < 0)
3338 + checkpointBlocks = 0;
3339 + } else {
3340 + checkpointBlocks =0;
3341 + }
3342 +
3343 reservedChunks = ((reservedBlocks + checkpointBlocks) * dev->nChunksPerBlock);
3344 -