Changeset 5591477 in freewrt for target/linux


Ignore:
Timestamp:
Dec 10, 2006, 5:33:25 AM (19 years ago)
Author:
Phil Sutter <n0-1@…>
Children:
29e4d6d
Parents:
8808337
Message:

Major rebuild of YAFFS2 support for linux-2.6.18

Initially I used the current YAFFS2 sources from CVS,
but they included some problems:

  • the filesystem used 2MB for itself on each partition (after formating NAND via RouterBOOT and initially mounting)
  • while using a nfsroot setup for testing, some nfs timeouts occured right after bootup (totally weird)

this patch is based on the one by OpenWrt, and was ported
to linux-2.6.18 (more a hack, but seems to work).

git-svn-id: svn://www.freewrt.org/trunk/freewrt@1283 afb5a338-a214-0410-bd46-81f09a774fd1

File:
1 edited

Legend:

Unmodified
Added
Removed
  • target/linux/rb-2.6/patches/140-yaffs2.patch

    r8808337 r5591477  
    1 diff -NaurB linux-2.6.18.2/fs/Kconfig linux-2.6.18.2.patched/fs/Kconfig
    2 --- linux-2.6.18.2/fs/Kconfig   2006-11-04 02:33:58.000000000 +0100
    3 +++ linux-2.6.18.2.patched/fs/Kconfig   2006-11-25 00:15:31.000000000 +0100
    4 @@ -1045,6 +1045,10 @@
     1diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/Kconfig linux-2.6-rb/linux-2.6.18.2/fs/Kconfig
     2--- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/Kconfig 2006-11-04 02:33:58.000000000 +0100
     3+++ linux-2.6-rb/linux-2.6.18.2/fs/Kconfig      2006-12-10 03:57:50.000000000 +0100
     4@@ -1045,6 +1045,15 @@
    55          To compile the EFS file system support as a module, choose M here: the
    66          module will be called efs.
    77 
    8 +
    9 +# Patched by YAFFS
    10 +source "fs/yaffs2/Kconfig"
     8+config YAFFS_FS
     9+       tristate "Yet Another Flash File System (YAFFS) support"
     10+       depends on MTD
     11+       help
     12+         JFFS is the Journaling Flash File System developed by Axis
     13+         Communications in Sweden, aimed at providing a crash/powerdown-safe
     14+         file system for disk-less embedded devices. Further information is
     15+         available at (<http://developer.axis.com/software/jffs/>).
    1116+
    1217 config JFFS_FS
    1318        tristate "Journalling Flash File System (JFFS) support"
    1419        depends on MTD
    15 diff -NaurB linux-2.6.18.2/fs/Makefile linux-2.6.18.2.patched/fs/Makefile
    16 --- linux-2.6.18.2/fs/Makefile  2006-11-04 02:33:58.000000000 +0100
    17 +++ linux-2.6.18.2.patched/fs/Makefile  2006-11-25 00:15:31.000000000 +0100
    18 @@ -102,3 +102,6 @@
    19  obj-$(CONFIG_HPPFS)            += hppfs/
    20  obj-$(CONFIG_DEBUG_FS)         += debugfs/
    21  obj-$(CONFIG_OCFS2_FS)         += ocfs2/
    22 +
    23 +# Patched by YAFFS
    24 +obj-$(CONFIG_YAFFS_FS)         += yaffs2/
    25 diff -NaurB linux-2.6.18.2/fs/yaffs2/devextras.h linux-2.6.18.2.patched/fs/yaffs2/devextras.h
    26 --- linux-2.6.18.2/fs/yaffs2/devextras.h        1970-01-01 01:00:00.000000000 +0100
    27 +++ linux-2.6.18.2.patched/fs/yaffs2/devextras.h        2006-11-25 00:15:32.000000000 +0100
    28 @@ -0,0 +1,265 @@
     20diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/Makefile linux-2.6-rb/linux-2.6.18.2/fs/Makefile
     21--- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/Makefile        2006-11-04 02:33:58.000000000 +0100
     22+++ linux-2.6-rb/linux-2.6.18.2/fs/Makefile     2006-12-10 03:57:50.000000000 +0100
     23@@ -84,6 +84,7 @@
     24 obj-$(CONFIG_EFS_FS)           += efs/
     25 obj-$(CONFIG_JFFS_FS)          += jffs/
     26 obj-$(CONFIG_JFFS2_FS)         += jffs2/
     27+obj-$(CONFIG_YAFFS_FS)         += yaffs/
     28 obj-$(CONFIG_AFFS_FS)          += affs/
     29 obj-$(CONFIG_ROMFS_FS)         += romfs/
     30 obj-$(CONFIG_QNX4FS_FS)                += qnx4/
     31diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/devextras.h linux-2.6-rb/linux-2.6.18.2/fs/yaffs/devextras.h
     32--- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/devextras.h       1970-01-01 01:00:00.000000000 +0100
     33+++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/devextras.h    2006-12-10 03:57:50.000000000 +0100
     34@@ -0,0 +1,271 @@
    2935+/*
    3036+ * YAFFS: Yet another FFS. A NAND-flash specific file system.
     
    4652+ * applications.
    4753+ *
    48 + * $Id: devextras.h,v 1.2 2005/08/11 02:37:49 marty Exp $
     54+ * $Id: devextras.h,v 1.1 2004/11/03 08:14:07 charles Exp $
    4955+ *
    5056+ */
    51 +
     57+ 
    5258+#ifndef __EXTRAS_H__
    5359+#define __EXTRAS_H__
     
    6066+#if !(defined __KERNEL__) || (defined WIN32)
    6167+
    62 +/* User space defines */
    63 +
    64 +typedef unsigned char __u8;
    65 +typedef unsigned short __u16;
    66 +typedef unsigned __u32;
     68+// User space defines
     69+
     70+typedef unsigned char   __u8;
     71+typedef unsigned short  __u16;
     72+typedef unsigned        __u32;
     73+
    6774+
    6875+/*
     
    7582+ * using the generic single-entry routines.
    7683+ */
    77 +
    78 +#define prefetch(x) 1
     84+
     85+ #define prefetch(x) 1
     86+
    7987+
    8088+struct list_head {
     
    97105+ * the prev/next entries already!
    98106+ */
    99 +static __inline__ void __list_add(struct list_head *new,
    100 +                                 struct list_head *prev,
    101 +                                 struct list_head *next)
     107+static __inline__ void __list_add(struct list_head * new,
     108+       struct list_head * prev,
     109+       struct list_head * next)
    102110+{
    103111+       next->prev = new;
     
    128136+ * This is useful for implementing queues.
    129137+ */
    130 +static __inline__ void list_add_tail(struct list_head *new,
    131 +                                    struct list_head *head)
     138+static __inline__ void list_add_tail(struct list_head *new, struct list_head *head)
    132139+{
    133140+       __list_add(new, head->prev, head);
     
    141148+ * the prev/next entries already!
    142149+ */
    143 +static __inline__ void __list_del(struct list_head *prev,
    144 +                                 struct list_head *next)
     150+static __inline__ void __list_del(struct list_head * prev,
     151+                                 struct list_head * next)
    145152+{
    146153+       next->prev = prev;
     
    151158+ * list_del - deletes entry from list.
    152159+ * @entry: the element to delete from the list.
    153 + * Note: list_empty on entry does not return true after this, the entry is
    154 + * in an undefined state.
     160+ * Note: list_empty on entry does not return true after this, the entry is in an undefined state.
    155161+ */
    156162+static __inline__ void list_del(struct list_head *entry)
     
    183189+ * @head: the place to add it in the first list.
    184190+ */
    185 +static __inline__ void list_splice(struct list_head *list,
    186 +                                  struct list_head *head)
     191+static __inline__ void list_splice(struct list_head *list, struct list_head *head)
    187192+{
    188193+       struct list_head *first = list->next;
     
    219224+
    220225+/**
    221 + * list_for_each_safe  -       iterate over a list safe against removal
    222 + *                              of list entry
     226+ * list_for_each_safe  -       iterate over a list safe against removal of list entry
    223227+ * @pos:       the &struct list_head to use as a loop counter.
    224228+ * @n:         another &struct list_head to use as temporary storage
     
    228232+       for (pos = (head)->next, n = pos->next; pos != (head); \
    229233+               pos = n, n = pos->next)
     234+
     235+
     236+
    230237+
    231238+/*
     
    262269+#define ATTR_ATTR_FLAG 1024
    263270+
     271+
    264272+struct iattr {
    265 +       unsigned int ia_valid;
    266 +       unsigned ia_mode;
    267 +       unsigned ia_uid;
    268 +       unsigned ia_gid;
    269 +       unsigned ia_size;
    270 +       unsigned ia_atime;
    271 +       unsigned ia_mtime;
    272 +       unsigned ia_ctime;
    273 +       unsigned int ia_attr_flags;
     273+       unsigned int    ia_valid;
     274+       unsigned                ia_mode;
     275+       unsigned                ia_uid;
     276+       unsigned                ia_gid;
     277+       unsigned                ia_size;
     278+       unsigned                ia_atime;
     279+       unsigned        ia_mtime;
     280+       unsigned        ia_ctime;
     281+       unsigned int    ia_attr_flags;
    274282+};
    275283+
    276284+#define KERN_DEBUG
     285+
    277286+
    278287+#else
     
    287296+#endif
    288297+
     298+
     299+
    289300+#if defined WIN32
    290301+#undef new
    291 +#endif
    292 +
    293 +#endif
    294 diff -NaurB linux-2.6.18.2/fs/yaffs2/Kconfig linux-2.6.18.2.patched/fs/yaffs2/Kconfig
    295 --- linux-2.6.18.2/fs/yaffs2/Kconfig    1970-01-01 01:00:00.000000000 +0100
    296 +++ linux-2.6.18.2.patched/fs/yaffs2/Kconfig    2006-11-25 00:15:31.000000000 +0100
    297 @@ -0,0 +1,135 @@
     302+#endif
     303+
     304+#endif
     305+
     306diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/Makefile linux-2.6-rb/linux-2.6.18.2/fs/yaffs/Makefile
     307--- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/Makefile  1970-01-01 01:00:00.000000000 +0100
     308+++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/Makefile       2006-12-10 03:57:50.000000000 +0100
     309@@ -0,0 +1,18 @@
    298310+#
    299 +# YAFFS file system configurations
     311+# Makefile for the Linux msdos filesystem routines.
    300312+#
    301 +
    302 +config YAFFS_FS
    303 +       tristate "YAFFS2 file system support"
    304 +       default n
    305 +       depends on MTD
    306 +       select YAFFS_YAFFS1
    307 +       select YAFFS_YAFFS2
    308 +       help
    309 +         YAFFS2, or Yet Another Flash Filing System, is a filing system
    310 +         optimised for NAND Flash chips.
    311 +
    312 +         To compile the YAFFS2 file system support as a module, choose M here:
    313 +         the module will be called yaffs2.
    314 +
    315 +         If unsure, say N.
    316 +
    317 +         Further information on YAFFS2 is available at
    318 +         <http://www.aleph1.co.uk/yaffs/>.
    319 +
    320 +config YAFFS_YAFFS1
    321 +       bool "512 byte / page devices"
    322 +       depends on YAFFS_FS
    323 +       default y
    324 +       help
    325 +         Enable YAFFS1 support -- yaffs for 512 byte / page devices
    326 +
    327 +         If unsure, say Y.
    328 +
    329 +config YAFFS_DOES_ECC
    330 +       bool "Lets Yaffs do its own ECC"
    331 +       depends on YAFFS_FS && YAFFS_YAFFS1
    332 +       default n
    333 +       help
    334 +         This enables Yaffs to use its own ECC functions instead of using
    335 +         the ones from the generic MTD-NAND driver.
    336 +
    337 +         If unsure, say N.
    338 +
    339 +config YAFFS_ECC_WRONG_ORDER
    340 +       bool "Use the same ecc byte order as Steven Hill's nand_ecc.c"
    341 +       depends on YAFFS_FS && YAFFS_DOES_ECC
    342 +       default n
    343 +       help
    344 +         This makes yaffs_ecc.c use the same ecc byte order as
    345 +         Steven Hill's nand_ecc.c. If not set, then you get the
    346 +         same ecc byte order as SmartMedia.
    347 +
    348 +         If unsure, say N.
    349 +
    350 +config YAFFS_YAFFS2
    351 +       bool "2048 byte (or larger) / page devices"
    352 +       depends on YAFFS_FS
    353 +       default y
    354 +       help
    355 +         Enable YAFFS2 support -- yaffs for >= 2048 byte / page larger devices
    356 +
    357 +         If unsure, say Y.
    358 +
    359 +config YAFFS_AUTO_YAFFS2
    360 +       bool "Autoselect yaffs2 format"
    361 +       depends on YAFFS_YAFFS2
    362 +       default y
    363 +       help
    364 +         Without this, you need to explicitely use yaffs2 as the file
    365 +         system type. With this, you can say "yaffs" and yaffs or yaffs2
    366 +          will be used depending on the device page size.
    367 +
    368 +         If unsure, say Y.
    369 +
    370 +config YAFFS_DISABLE_LAZY_LOAD
    371 +       bool "Disable lazy loading"
    372 +       depends on YAFFS_YAFFS2
    373 +       default n
    374 +       help
    375 +         "Lazy loading" defers loading file details until they are
    376 +         required. This saves mount time, but makes the first look-up
    377 +         a bit longer.
    378 +
    379 +         Lazy loading will only happen if enabled by this option being 'n'
    380 +         and if the appropriate tags are available, else yaffs2 will
    381 +         automatically fall back to immediate loading and do the right
    382 +         thing.
    383 +
    384 +         Lazy laoding will be required by checkpointing.
    385 +
    386 +         Setting this to 'y' will disable lazy loading.
    387 +
    388 +         If unsure, say N.
    389 +
    390 +config YAFFS_DISABLE_WIDE_TNODES
    391 +       bool "Turn off wide tnodes"
    392 +       depends on YAFFS_FS
    393 +       default n
    394 +       help
    395 +         Wide tnodes are only used for large NAND arrays (>=32MB for
    396 +         512-byte page devices and >=128MB for 2k page devices). They use
    397 +         slightly more RAM but are faster since they eliminate chunk group
    398 +         searching.
    399 +
    400 +         Setting this to 'y' will force tnode width to 16 bits and make
    401 +         large arrays slower.
    402 +
    403 +         If unsure, say N.
    404 +
    405 +config YAFFS_ALWAYS_CHECK_CHUNK_ERASED
    406 +       bool "Force chunk erase check"
    407 +       depends on YAFFS_FS
    408 +       default n
    409 +       help
    410 +          Normally YAFFS only checks chunks before writing until an erased
    411 +         chunk is found. This helps to detect any partially written chunks
    412 +         that might have happened due to power loss.
    413 +
    414 +         Enabling this forces on the test that chunks are erased in flash
    415 +         before writing to them. This takes more time but is potentially a
    416 +         bit more secure.
    417 +
    418 +         Suggest setting Y during development and ironing out driver issues
    419 +         etc. Suggest setting to N if you want faster writing.                 
    420 +
    421 +         If unsure, say Y.
    422 +
    423 +config YAFFS_SHORT_NAMES_IN_RAM
    424 +       bool "Cache short names in RAM"
    425 +       depends on YAFFS_FS
    426 +       default y
    427 +       help
    428 +         If this config is set, then short names are stored with the
    429 +         yaffs_Object.  This costs an extra 16 bytes of RAM per object,
    430 +         but makes look-ups faster.
    431 +
    432 +         If unsure, say Y.
    433 diff -NaurB linux-2.6.18.2/fs/yaffs2/Makefile linux-2.6.18.2.patched/fs/yaffs2/Makefile
    434 --- linux-2.6.18.2/fs/yaffs2/Makefile   1970-01-01 01:00:00.000000000 +0100
    435 +++ linux-2.6.18.2.patched/fs/yaffs2/Makefile   2006-11-25 00:15:31.000000000 +0100
    436 @@ -0,0 +1,10 @@
     313+# Note! Dependencies are done automagically by 'make dep', which also
     314+# removes any old dependencies. DON'T put your own dependencies here
     315+# unless it's something special (ie not a .c file).
    437316+#
    438 +# Makefile for the linux YAFFS filesystem routines.
    439 +#
     317+# Note 2! The CFLAGS definitions are now in the main makefile.
     318+
     319+
     320+EXTRA_CFLAGS += -DCONFIG_YAFFS_YAFFS1 -DCONFIG_YAFFS_YAFFS2
     321+
    440322+
    441323+obj-$(CONFIG_YAFFS_FS) += yaffs.o
    442324+
    443 +yaffs-y := yaffs_ecc.o yaffs_fs.o yaffs_guts.o yaffs_checkptrw.o
    444 +yaffs-y += yaffs_packedtags2.o yaffs_nand.o yaffs_qsort.o
    445 +yaffs-y += yaffs_tagscompat.o yaffs_tagsvalidity.o
    446 +yaffs-y += yaffs_mtdif.o yaffs_mtdif2.o
    447 diff -NaurB linux-2.6.18.2/fs/yaffs2/moduleconfig.h linux-2.6.18.2.patched/fs/yaffs2/moduleconfig.h
    448 --- linux-2.6.18.2/fs/yaffs2/moduleconfig.h     1970-01-01 01:00:00.000000000 +0100
    449 +++ linux-2.6.18.2.patched/fs/yaffs2/moduleconfig.h     2006-11-25 00:15:32.000000000 +0100
    450 @@ -0,0 +1,32 @@
    451 +#ifndef __YAFFS_CONFIG_H__
    452 +#define __YAFFS_CONFIG_H__
    453 +
    454 +#ifdef YAFFS_OUT_OF_TREE
    455 +
    456 +/* DO NOT UNSET THESE THREE. YAFFS2 will not compile if you do. */
    457 +#define CONFIG_YAFFS_FS
    458 +#define CONFIG_YAFFS_YAFFS1
    459 +#define CONFIG_YAFFS_YAFFS2
    460 +
    461 +/* These options are independent of each other.  Select those that matter. */
    462 +
    463 +/* Default: Not selected */
    464 +/* Meaning: Yaffs does its own ECC, rather than using MTD ECC */
    465 +//#define CONFIG_YAFFS_DOES_ECC
    466 +
    467 +/* Default: Not selected */
    468 +/* Meaning: ECC byte order is 'wrong'.  Only meaningful if */
    469 +/*          CONFIG_YAFFS_DOES_ECC is set */
    470 +//#define CONFIG_YAFFS_ECC_WRONG_ORDER
    471 +
    472 +/* Default: Selected */
    473 +/* Meaning: Disables testing whether chunks are erased before writing to them*/
    474 +#define CONFIG_YAFFS_DISABLE_CHUNK_ERASED_CHECK
    475 +
    476 +/* Default: Selected */
    477 +/* Meaning: Cache short names, taking more RAM, but faster look-ups */
    478 +#define CONFIG_YAFFS_SHORT_NAMES_IN_RAM
    479 +
    480 +#endif /* YAFFS_OUT_OF_TREE */
    481 +
    482 +#endif /* __YAFFS_CONFIG_H__ */
    483 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_checkptrw.c linux-2.6.18.2.patched/fs/yaffs2/yaffs_checkptrw.c
    484 --- linux-2.6.18.2/fs/yaffs2/yaffs_checkptrw.c  1970-01-01 01:00:00.000000000 +0100
    485 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_checkptrw.c  2006-11-25 00:15:31.000000000 +0100
    486 @@ -0,0 +1,384 @@
    487 +/* YAFFS: Yet another FFS. A NAND-flash specific file system.
    488 + *
    489 + * Copyright (C) 2002 Aleph One Ltd.
    490 + *   for Toby Churchill Ltd and Brightstar Engineering
    491 + *
    492 + * Created by Charles Manning <charles@aleph1.co.uk>
    493 + *
    494 + * This program is free software; you can redistribute it and/or modify
    495 + * it under the terms of the GNU General Public License version 2 as
    496 + * published by the Free Software Foundation.
    497 + *
    498 + */
    499 +
    500 +const char *yaffs_checkptrw_c_version =
    501 +    "$Id: yaffs_checkptrw.c,v 1.11 2006/11/11 23:27:04 charles Exp $";
    502 +
    503 +
    504 +#include "yaffs_checkptrw.h"
    505 +
    506 +
    507 +static int yaffs_CheckpointSpaceOk(yaffs_Device *dev)
    508 +{
    509 +
    510 +       int blocksAvailable = dev->nErasedBlocks - dev->nReservedBlocks;
    511 +       
    512 +       T(YAFFS_TRACE_CHECKPOINT,
    513 +               (TSTR("checkpt blocks available = %d" TENDSTR),
    514 +               blocksAvailable));
    515 +               
    516 +       
    517 +       return (blocksAvailable <= 0) ? 0 : 1;
    518 +}
    519 +
    520 +
    521 +
    522 +static int yaffs_CheckpointErase(yaffs_Device *dev)
    523 +{
    524 +       
    525 +       int i;
    526 +       
    527 +
    528 +       if(!dev->eraseBlockInNAND)     
    529 +               return 0;
    530 +       T(YAFFS_TRACE_CHECKPOINT,(TSTR("checking blocks %d to %d"TENDSTR),
    531 +               dev->internalStartBlock,dev->internalEndBlock));
    532 +               
    533 +       for(i = dev->internalStartBlock; i <= dev->internalEndBlock; i++) {
    534 +               yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,i);
    535 +               if(bi->blockState == YAFFS_BLOCK_STATE_CHECKPOINT){
    536 +                       T(YAFFS_TRACE_CHECKPOINT,(TSTR("erasing checkpt block %d"TENDSTR),i));
    537 +                       if(dev->eraseBlockInNAND(dev,i- dev->blockOffset /* realign */)){
    538 +                               bi->blockState = YAFFS_BLOCK_STATE_EMPTY;
    539 +                               dev->nErasedBlocks++;
    540 +                               dev->nFreeChunks += dev->nChunksPerBlock;
    541 +                       }
    542 +                       else {
    543 +                               dev->markNANDBlockBad(dev,i);
    544 +                               bi->blockState = YAFFS_BLOCK_STATE_DEAD;
    545 +                       }
    546 +               }
    547 +       }
    548 +       
    549 +       dev->blocksInCheckpoint = 0;
    550 +       
    551 +       return 1;
    552 +}
    553 +
    554 +
    555 +static void yaffs_CheckpointFindNextErasedBlock(yaffs_Device *dev)
    556 +{
    557 +       int  i;
    558 +       int blocksAvailable = dev->nErasedBlocks - dev->nReservedBlocks;
    559 +       T(YAFFS_TRACE_CHECKPOINT,
    560 +               (TSTR("allocating checkpt block: erased %d reserved %d avail %d next %d "TENDSTR),
    561 +               dev->nErasedBlocks,dev->nReservedBlocks,blocksAvailable,dev->checkpointNextBlock));
    562 +               
    563 +       if(dev->checkpointNextBlock >= 0 &&
    564 +          dev->checkpointNextBlock <= dev->internalEndBlock &&
    565 +          blocksAvailable > 0){
    566 +       
    567 +               for(i = dev->checkpointNextBlock; i <= dev->internalEndBlock; i++){
    568 +                       yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,i);
    569 +                       if(bi->blockState == YAFFS_BLOCK_STATE_EMPTY){
    570 +                               dev->checkpointNextBlock = i + 1;
    571 +                               dev->checkpointCurrentBlock = i;
    572 +                               T(YAFFS_TRACE_CHECKPOINT,(TSTR("allocating checkpt block %d"TENDSTR),i));
    573 +                               return;
    574 +                       }
    575 +               }
    576 +       }
    577 +       T(YAFFS_TRACE_CHECKPOINT,(TSTR("out of checkpt blocks"TENDSTR)));
    578 +       
    579 +       dev->checkpointNextBlock = -1;
    580 +       dev->checkpointCurrentBlock = -1;
    581 +}
    582 +
    583 +static void yaffs_CheckpointFindNextCheckpointBlock(yaffs_Device *dev)
    584 +{
    585 +       int  i;
    586 +       yaffs_ExtendedTags tags;
    587 +       
    588 +       T(YAFFS_TRACE_CHECKPOINT,(TSTR("find next checkpt block: start:  blocks %d next %d" TENDSTR),
    589 +               dev->blocksInCheckpoint, dev->checkpointNextBlock));
    590 +               
    591 +       if(dev->blocksInCheckpoint < dev->checkpointMaxBlocks)
    592 +               for(i = dev->checkpointNextBlock; i <= dev->internalEndBlock; i++){
    593 +                       int chunk = i * dev->nChunksPerBlock;
    594 +                       int realignedChunk = chunk - dev->chunkOffset;
    595 +
    596 +                       dev->readChunkWithTagsFromNAND(dev,realignedChunk,NULL,&tags);
    597 +                       T(YAFFS_TRACE_CHECKPOINT,(TSTR("find next checkpt block: search: block %d oid %d seq %d eccr %d" TENDSTR),
    598 +                               i, tags.objectId,tags.sequenceNumber,tags.eccResult));
    599 +                                                     
    600 +                       if(tags.sequenceNumber == YAFFS_SEQUENCE_CHECKPOINT_DATA){
    601 +                               /* Right kind of block */
    602 +                               dev->checkpointNextBlock = tags.objectId;
    603 +                               dev->checkpointCurrentBlock = i;
    604 +                               dev->checkpointBlockList[dev->blocksInCheckpoint] = i;
    605 +                               dev->blocksInCheckpoint++;
    606 +                               T(YAFFS_TRACE_CHECKPOINT,(TSTR("found checkpt block %d"TENDSTR),i));
    607 +                               return;
    608 +                       }
    609 +               }
    610 +
    611 +       T(YAFFS_TRACE_CHECKPOINT,(TSTR("found no more checkpt blocks"TENDSTR)));
    612 +
    613 +       dev->checkpointNextBlock = -1;
    614 +       dev->checkpointCurrentBlock = -1;
    615 +}
    616 +
    617 +
    618 +int yaffs_CheckpointOpen(yaffs_Device *dev, int forWriting)
    619 +{
    620 +       
    621 +       /* Got the functions we need? */
    622 +       if (!dev->writeChunkWithTagsToNAND ||
    623 +           !dev->readChunkWithTagsFromNAND ||
    624 +           !dev->eraseBlockInNAND ||
    625 +           !dev->markNANDBlockBad)
    626 +               return 0;
    627 +
    628 +       if(forWriting && !yaffs_CheckpointSpaceOk(dev))
    629 +               return 0;
    630 +                       
    631 +       if(!dev->checkpointBuffer)
    632 +               dev->checkpointBuffer = YMALLOC_DMA(dev->nDataBytesPerChunk);
    633 +       if(!dev->checkpointBuffer)
    634 +               return 0;
    635 +
    636 +       
    637 +       dev->checkpointPageSequence = 0;
    638 +       
    639 +       dev->checkpointOpenForWrite = forWriting;
    640 +       
    641 +       dev->checkpointByteCount = 0;
    642 +       dev->checkpointCurrentBlock = -1;
    643 +       dev->checkpointCurrentChunk = -1;
    644 +       dev->checkpointNextBlock = dev->internalStartBlock;
    645 +       
    646 +       /* Erase all the blocks in the checkpoint area */
    647 +       if(forWriting){
    648 +               memset(dev->checkpointBuffer,0,dev->nDataBytesPerChunk);
    649 +               dev->checkpointByteOffset = 0;
    650 +               return yaffs_CheckpointErase(dev);
    651 +               
    652 +               
    653 +       } else {
    654 +               int i;
    655 +               /* Set to a value that will kick off a read */
    656 +               dev->checkpointByteOffset = dev->nDataBytesPerChunk;
    657 +               /* A checkpoint block list of 1 checkpoint block per 16 block is (hopefully)
    658 +                * going to be way more than we need */
    659 +               dev->blocksInCheckpoint = 0;
    660 +               dev->checkpointMaxBlocks = (dev->internalEndBlock - dev->internalStartBlock)/16 + 2;
    661 +               dev->checkpointBlockList = YMALLOC(sizeof(int) * dev->checkpointMaxBlocks);
    662 +               for(i = 0; i < dev->checkpointMaxBlocks; i++)
    663 +                       dev->checkpointBlockList[i] = -1;
    664 +       }
    665 +       
    666 +       return 1;
    667 +}
    668 +
    669 +static int yaffs_CheckpointFlushBuffer(yaffs_Device *dev)
    670 +{
    671 +
    672 +       int chunk;
    673 +       int realignedChunk;
    674 +
    675 +       yaffs_ExtendedTags tags;
    676 +       
    677 +       if(dev->checkpointCurrentBlock < 0){
    678 +               yaffs_CheckpointFindNextErasedBlock(dev);
    679 +               dev->checkpointCurrentChunk = 0;
    680 +       }
    681 +       
    682 +       if(dev->checkpointCurrentBlock < 0)
    683 +               return 0;
    684 +       
    685 +       tags.chunkDeleted = 0;
    686 +       tags.objectId = dev->checkpointNextBlock; /* Hint to next place to look */
    687 +       tags.chunkId = dev->checkpointPageSequence + 1;
    688 +       tags.sequenceNumber =  YAFFS_SEQUENCE_CHECKPOINT_DATA;
    689 +       tags.byteCount = dev->nDataBytesPerChunk;
    690 +       if(dev->checkpointCurrentChunk == 0){
    691 +               /* First chunk we write for the block? Set block state to
    692 +                  checkpoint */
    693 +               yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,dev->checkpointCurrentBlock);
    694 +               bi->blockState = YAFFS_BLOCK_STATE_CHECKPOINT;
    695 +               dev->blocksInCheckpoint++;
    696 +       }
    697 +       
    698 +       chunk = dev->checkpointCurrentBlock * dev->nChunksPerBlock + dev->checkpointCurrentChunk;
    699 +
    700 +       
    701 +       T(YAFFS_TRACE_CHECKPOINT,(TSTR("checkpoint wite buffer nand %d(%d:%d) objid %d chId %d" TENDSTR),
    702 +               chunk, dev->checkpointCurrentBlock, dev->checkpointCurrentChunk,tags.objectId,tags.chunkId));
    703 +       
    704 +       realignedChunk = chunk - dev->chunkOffset;
    705 +       
    706 +       dev->writeChunkWithTagsToNAND(dev,realignedChunk,dev->checkpointBuffer,&tags);
    707 +       dev->checkpointByteOffset = 0;
    708 +       dev->checkpointPageSequence++;     
    709 +       dev->checkpointCurrentChunk++;
    710 +       if(dev->checkpointCurrentChunk >= dev->nChunksPerBlock){
    711 +               dev->checkpointCurrentChunk = 0;
    712 +               dev->checkpointCurrentBlock = -1;
    713 +       }
    714 +       memset(dev->checkpointBuffer,0,dev->nDataBytesPerChunk);
    715 +       
    716 +       return 1;
    717 +}
    718 +
    719 +
    720 +int yaffs_CheckpointWrite(yaffs_Device *dev,const void *data, int nBytes)
    721 +{
    722 +       int i=0;
    723 +       int ok = 1;
    724 +
    725 +       
    726 +       __u8 * dataBytes = (__u8 *)data;
    727 +       
    728 +       
    729 +
    730 +       if(!dev->checkpointBuffer)
    731 +               return 0;
    732 +
    733 +       while(i < nBytes && ok) {
    734 +               
    735 +
    736 +               
    737 +                dev->checkpointBuffer[dev->checkpointByteOffset] = *dataBytes ;
    738 +               dev->checkpointByteOffset++;
    739 +               i++;
    740 +               dataBytes++;
    741 +               dev->checkpointByteCount++;
    742 +               
    743 +               
    744 +               if(dev->checkpointByteOffset < 0 ||
    745 +                  dev->checkpointByteOffset >= dev->nDataBytesPerChunk)
    746 +                       ok = yaffs_CheckpointFlushBuffer(dev);
    747 +
    748 +       }
    749 +       
    750 +       return  i;
    751 +}
    752 +
    753 +int yaffs_CheckpointRead(yaffs_Device *dev, void *data, int nBytes)
    754 +{
    755 +       int i=0;
    756 +       int ok = 1;
    757 +       yaffs_ExtendedTags tags;
    758 +
    759 +       
    760 +       int chunk;
    761 +       int realignedChunk;
    762 +
    763 +       __u8 *dataBytes = (__u8 *)data;
    764 +               
    765 +       if(!dev->checkpointBuffer)
    766 +               return 0;
    767 +
    768 +       while(i < nBytes && ok) {
    769 +       
    770 +       
    771 +               if(dev->checkpointByteOffset < 0 ||
    772 +                  dev->checkpointByteOffset >= dev->nDataBytesPerChunk) {
    773 +                 
    774 +                       if(dev->checkpointCurrentBlock < 0){
    775 +                               yaffs_CheckpointFindNextCheckpointBlock(dev);
    776 +                               dev->checkpointCurrentChunk = 0;
    777 +                       }
    778 +                       
    779 +                       if(dev->checkpointCurrentBlock < 0)
    780 +                               ok = 0;
    781 +                       else {
    782 +                       
    783 +                               chunk = dev->checkpointCurrentBlock * dev->nChunksPerBlock +
    784 +                                         dev->checkpointCurrentChunk;
    785 +
    786 +                               realignedChunk = chunk - dev->chunkOffset;
    787 +
    788 +                               /* read in the next chunk */
    789 +                               /* printf("read checkpoint page %d\n",dev->checkpointPage); */
    790 +                               dev->readChunkWithTagsFromNAND(dev, realignedChunk,
    791 +                                                              dev->checkpointBuffer,
    792 +                                                             &tags);
    793 +                                                     
    794 +                               if(tags.chunkId != (dev->checkpointPageSequence + 1) ||
    795 +                                  tags.sequenceNumber != YAFFS_SEQUENCE_CHECKPOINT_DATA)
    796 +                                  ok = 0;
    797 +
    798 +                               dev->checkpointByteOffset = 0;
    799 +                               dev->checkpointPageSequence++;
    800 +                               dev->checkpointCurrentChunk++;
    801 +                       
    802 +                               if(dev->checkpointCurrentChunk >= dev->nChunksPerBlock)
    803 +                                       dev->checkpointCurrentBlock = -1;
    804 +                       }
    805 +               }
    806 +               
    807 +               if(ok){
    808 +                       *dataBytes = dev->checkpointBuffer[dev->checkpointByteOffset];
    809 +                       dev->checkpointByteOffset++;
    810 +                       i++;
    811 +                       dataBytes++;
    812 +                       dev->checkpointByteCount++;
    813 +               }
    814 +       }
    815 +       
    816 +       return  i;
    817 +}
    818 +
    819 +int yaffs_CheckpointClose(yaffs_Device *dev)
    820 +{
    821 +
    822 +       if(dev->checkpointOpenForWrite){       
    823 +               if(dev->checkpointByteOffset != 0)
    824 +                       yaffs_CheckpointFlushBuffer(dev);
    825 +       } else {
    826 +               int i;
    827 +               for(i = 0; i < dev->blocksInCheckpoint && dev->checkpointBlockList[i] >= 0; i++){
    828 +                       yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,dev->checkpointBlockList[i]);
    829 +                       if(bi->blockState == YAFFS_BLOCK_STATE_EMPTY)
    830 +                               bi->blockState = YAFFS_BLOCK_STATE_CHECKPOINT;
    831 +                       else {
    832 +                               // Todo this looks odd...
    833 +                       }
    834 +               }
    835 +               YFREE(dev->checkpointBlockList);
    836 +               dev->checkpointBlockList = NULL;
    837 +       }
    838 +
    839 +       dev->nFreeChunks -= dev->blocksInCheckpoint * dev->nChunksPerBlock;
    840 +       dev->nErasedBlocks -= dev->blocksInCheckpoint;
    841 +
    842 +               
    843 +       T(YAFFS_TRACE_CHECKPOINT,(TSTR("checkpoint byte count %d" TENDSTR),
    844 +                       dev->checkpointByteCount));
    845 +                       
    846 +       if(dev->checkpointBuffer){
    847 +               /* free the buffer */   
    848 +               YFREE(dev->checkpointBuffer);
    849 +               dev->checkpointBuffer = NULL;
    850 +               return 1;
    851 +       }
    852 +       else
    853 +               return 0;
    854 +       
    855 +}
    856 +
    857 +int yaffs_CheckpointInvalidateStream(yaffs_Device *dev)
    858 +{
    859 +       /* Erase the first checksum block */
    860 +
    861 +       T(YAFFS_TRACE_CHECKPOINT,(TSTR("checkpoint invalidate"TENDSTR)));
    862 +
    863 +       if(!yaffs_CheckpointSpaceOk(dev))
    864 +               return 0;
    865 +
    866 +       return yaffs_CheckpointErase(dev);
    867 +}
    868 +
    869 +
    870 +
    871 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_checkptrw.h linux-2.6.18.2.patched/fs/yaffs2/yaffs_checkptrw.h
    872 --- linux-2.6.18.2/fs/yaffs2/yaffs_checkptrw.h  1970-01-01 01:00:00.000000000 +0100
    873 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_checkptrw.h  2006-11-25 00:15:32.000000000 +0100
    874 @@ -0,0 +1,18 @@
    875 +#ifndef __YAFFS_CHECKPTRW_H__
    876 +#define __YAFFS_CHECKPTRW_H__
    877 +
    878 +#include "yaffs_guts.h"
    879 +
    880 +int yaffs_CheckpointOpen(yaffs_Device *dev, int forWriting);
    881 +
    882 +int yaffs_CheckpointWrite(yaffs_Device *dev,const void *data, int nBytes);
    883 +
    884 +int yaffs_CheckpointRead(yaffs_Device *dev,void *data, int nBytes);
    885 +
    886 +int yaffs_CheckpointClose(yaffs_Device *dev);
    887 +
    888 +int yaffs_CheckpointInvalidateStream(yaffs_Device *dev);
    889 +
    890 +
    891 +#endif
    892 +
    893 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_ecc.c linux-2.6.18.2.patched/fs/yaffs2/yaffs_ecc.c
    894 --- linux-2.6.18.2/fs/yaffs2/yaffs_ecc.c        1970-01-01 01:00:00.000000000 +0100
    895 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_ecc.c        2006-11-25 00:15:31.000000000 +0100
    896 @@ -0,0 +1,333 @@
     325+yaffs-y = yaffs_fs.o yaffs_guts.o yaffs_mtdif.o yaffs_tagscompat.o \
     326+        yaffs_packedtags2.o yaffs_mtdif2.o yaffs_tagsvalidity.o \
     327+       yaffs_ecc.o
     328diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_ecc.c linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_ecc.c
     329--- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_ecc.c       1970-01-01 01:00:00.000000000 +0100
     330+++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_ecc.c    2006-12-10 03:57:50.000000000 +0100
     331@@ -0,0 +1,287 @@
    897332+/*
    898333+ * YAFFS: Yet another FFS. A NAND-flash specific file system.
     
    909344+ * version 2.1 as published by the Free Software Foundation.
    910345+ */
    911 +
     346+ 
    912347+ /*
    913 +  * This code implements the ECC algorithm used in SmartMedia.
    914 +  *
    915 +  * The ECC comprises 22 bits of parity information and is stuffed into 3 bytes.
    916 +  * The two unused bit are set to 1.
    917 +  * The ECC can correct single bit errors in a 256-byte page of data. Thus, two such ECC
    918 +  * blocks are used on a 512-byte NAND page.
    919 +  *
    920 +  */
    921 +
    922 +/* Table generated by gen-ecc.c
    923 + * Using a table means we do not have to calculate p1..p4 and p1'..p4'
    924 + * for each byte of data. These are instead provided in a table in bits7..2.
    925 + * Bit 0 of each entry indicates whether the entry has an odd or even parity, and therefore
    926 + * this bytes influence on the line parity.
     348+ * This code implements the ECC algorithm used in SmartMedia.
     349+ *
     350+ * The ECC comprises 22 bits of parity information and is stuffed into 3 bytes.
     351+ * The two unused bit are set to 1.
     352+ * The ECC can correct single bit errors in a 256-byte page of data. Thus, two such ECC
     353+ * blocks are used on a 512-byte NAND page.
     354+ *
    927355+ */
    928356+
    929 +const char *yaffs_ecc_c_version =
    930 +    "$Id: yaffs_ecc.c,v 1.7 2006/09/14 22:02:46 charles Exp $";
     357+// Table generated by gen-ecc.c
     358+// Using a table means we do not have to calculate p1..p4 and p1'..p4'
     359+// for each byte of data. These are instead provided in a table in bits7..2.
     360+// Bit 0 of each entry indicates whether the entry has an odd or even parity, and therefore
     361+// this bytes influence on the line parity.
     362+
     363+const char *yaffs_ecc_c_version = "$Id: yaffs_ecc.c,v 1.4 2005/07/31 00:28:04 charles Exp $";
    931364+
    932365+#include "yportenv.h"
     
    935368+
    936369+static const unsigned char column_parity_table[] = {
    937 +       0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69,
    938 +       0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00,
    939 +       0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc,
    940 +       0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95,
    941 +       0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0,
    942 +       0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99,
    943 +       0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65,
    944 +       0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c,
    945 +       0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc,
    946 +       0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5,
    947 +       0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59,
    948 +       0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30,
    949 +       0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55,
    950 +       0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c,
    951 +       0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0,
    952 +       0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9,
    953 +       0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0,
    954 +       0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9,
    955 +       0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55,
    956 +       0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c,
    957 +       0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59,
    958 +       0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30,
    959 +       0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc,
    960 +       0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5,
    961 +       0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65,
    962 +       0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c,
    963 +       0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0,
    964 +       0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99,
    965 +       0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc,
    966 +       0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95,
    967 +       0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69,
    968 +       0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00,
     370+0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69, 0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00,
     371+0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc, 0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95,
     372+0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0, 0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99,
     373+0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65, 0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c,
     374+0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc, 0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5,
     375+0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59, 0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30,
     376+0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55, 0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c,
     377+0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0, 0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9,
     378+0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0, 0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9,
     379+0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55, 0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c,
     380+0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59, 0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30,
     381+0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc, 0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5,
     382+0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65, 0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c,
     383+0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0, 0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99,
     384+0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc, 0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95,
     385+0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69, 0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00,
    969386+};
    970387+
    971 +/* Count the bits in an unsigned char or a U32 */
    972388+
    973389+static int yaffs_CountBits(unsigned char x)
    974390+{
    975391+       int r = 0;
    976 +       while (x) {
    977 +               if (x & 1)
    978 +                       r++;
     392+       while(x)
     393+       {
     394+               if(x & 1) r++;
    979395+               x >>= 1;
    980396+       }
     
    982398+}
    983399+
    984 +static int yaffs_CountBits32(unsigned x)
     400+static int yaffs_CountBits32(unsigned  x)
    985401+{
    986402+       int r = 0;
    987 +       while (x) {
    988 +               if (x & 1)
    989 +                       r++;
     403+       while(x)
     404+       {
     405+               if(x & 1) r++;
    990406+               x >>= 1;
    991407+       }
     
    993409+}
    994410+
    995 +/* Calculate the ECC for a 256-byte block of data */
    996 +void yaffs_ECCCalculate(const unsigned char *data, unsigned char *ecc)
     411+
     412+void yaffs_ECCCalculate(const unsigned char *data,unsigned char *ecc)
    997413+{
    998414+       unsigned int i;
    999 +
     415+       
    1000416+       unsigned char col_parity = 0;
    1001417+       unsigned char line_parity = 0;
     
    1003419+       unsigned char t;
    1004420+       unsigned char b;
    1005 +
    1006 +       for (i = 0; i < 256; i++) {
     421+       
     422+       for(i = 0; i < 256; i++)
     423+       {
    1007424+               b = column_parity_table[*data++];
    1008425+               col_parity ^= b;
    1009426+
    1010 +               if (b & 0x01)   // odd number of bits in the byte
     427+               if(b & 0x01) // odd number of bits in the byte
    1011428+               {
    1012429+                       line_parity ^= i;
    1013430+                       line_parity_prime ^= ~i;
    1014431+               }
    1015 +
    1016 +       }
    1017 +
     432+               
     433+       }
     434+       
    1018435+       ecc[2] = (~col_parity) | 0x03;
    1019 +
     436+       
    1020437+       t = 0;
    1021 +       if (line_parity & 0x80)
    1022 +               t |= 0x80;
    1023 +       if (line_parity_prime & 0x80)
    1024 +               t |= 0x40;
    1025 +       if (line_parity & 0x40)
    1026 +               t |= 0x20;
    1027 +       if (line_parity_prime & 0x40)
    1028 +               t |= 0x10;
    1029 +       if (line_parity & 0x20)
    1030 +               t |= 0x08;
    1031 +       if (line_parity_prime & 0x20)
    1032 +               t |= 0x04;
    1033 +       if (line_parity & 0x10)
    1034 +               t |= 0x02;
    1035 +       if (line_parity_prime & 0x10)
    1036 +               t |= 0x01;
     438+       if(line_parity       & 0x80) t |= 0x80;
     439+       if(line_parity_prime & 0x80) t |= 0x40;
     440+       if(line_parity       & 0x40) t |= 0x20;
     441+       if(line_parity_prime & 0x40) t |= 0x10;
     442+       if(line_parity       & 0x20) t |= 0x08;
     443+       if(line_parity_prime & 0x20) t |= 0x04;
     444+       if(line_parity       & 0x10) t |= 0x02;
     445+       if(line_parity_prime & 0x10) t |= 0x01;
    1037446+       ecc[1] = ~t;
    1038 +
     447+       
    1039448+       t = 0;
    1040 +       if (line_parity & 0x08)
    1041 +               t |= 0x80;
    1042 +       if (line_parity_prime & 0x08)
    1043 +               t |= 0x40;
    1044 +       if (line_parity & 0x04)
    1045 +               t |= 0x20;
    1046 +       if (line_parity_prime & 0x04)
    1047 +               t |= 0x10;
    1048 +       if (line_parity & 0x02)
    1049 +               t |= 0x08;
    1050 +       if (line_parity_prime & 0x02)
    1051 +               t |= 0x04;
    1052 +       if (line_parity & 0x01)
    1053 +               t |= 0x02;
    1054 +       if (line_parity_prime & 0x01)
    1055 +               t |= 0x01;
     449+       if(line_parity       & 0x08) t |= 0x80;
     450+       if(line_parity_prime & 0x08) t |= 0x40;
     451+       if(line_parity       & 0x04) t |= 0x20;
     452+       if(line_parity_prime & 0x04) t |= 0x10;
     453+       if(line_parity       & 0x02) t |= 0x08;
     454+       if(line_parity_prime & 0x02) t |= 0x04;
     455+       if(line_parity       & 0x01) t |= 0x02;
     456+       if(line_parity_prime & 0x01) t |= 0x01;
    1056457+       ecc[0] = ~t;
    1057458+
     
    1061462+       ecc[0] = ecc[1];
    1062463+       ecc[1] = t;
    1063 +#endif
    1064 +}
    1065 +
    1066 +
    1067 +/* Correct the ECC on a 256 byte block of data */
    1068 +
    1069 +int yaffs_ECCCorrect(unsigned char *data, unsigned char *read_ecc,
    1070 +                    const unsigned char *test_ecc)
    1071 +{
    1072 +       unsigned char d0, d1, d2;       /* deltas */
     464+#endif
     465+}
     466+
     467+int yaffs_ECCCorrect(unsigned char *data, unsigned char *read_ecc, const unsigned char *test_ecc)
     468+{
     469+       unsigned char d0, d1, d2; // deltas
    1073470+
    1074471+       d0 = read_ecc[0] ^ test_ecc[0];
    1075472+       d1 = read_ecc[1] ^ test_ecc[1];
    1076473+       d2 = read_ecc[2] ^ test_ecc[2];
    1077 +
    1078 +       if ((d0 | d1 | d2) == 0)
    1079 +               return 0; /* no error */
    1080 +
    1081 +       if (((d0 ^ (d0 >> 1)) & 0x55) == 0x55 &&
     474+       
     475+       
     476+       
     477+       if((d0 | d1 | d2) == 0)
     478+       {
     479+               // no error
     480+               return 0;
     481+       }
     482+       
     483+       if( ((d0 ^ (d0 >> 1)) & 0x55) == 0x55 &&
    1082484+           ((d1 ^ (d1 >> 1)) & 0x55) == 0x55 &&
    1083 +           ((d2 ^ (d2 >> 1)) & 0x54) == 0x54) {
    1084 +               /* Single bit (recoverable) error in data */
     485+           ((d2 ^ (d2 >> 1)) & 0x54) == 0x54)
     486+       {
     487+               // Single bit (recoverable) error in data
    1085488+
    1086489+               unsigned byte;
     
    1090493+               // swap the bytes to correct for the wrong order
    1091494+               unsigned char t;
    1092 +
     495+               
    1093496+               t = d0;
    1094497+               d0 = d1;
    1095498+               d1 = t;
    1096499+#endif
    1097 +
     500+               
    1098501+               bit = byte = 0;
    1099 +
    1100 +               if (d1 & 0x80)
    1101 +                       byte |= 0x80;
    1102 +               if (d1 & 0x20)
    1103 +                       byte |= 0x40;
    1104 +               if (d1 & 0x08)
    1105 +                       byte |= 0x20;
    1106 +               if (d1 & 0x02)
    1107 +                       byte |= 0x10;
    1108 +               if (d0 & 0x80)
    1109 +                       byte |= 0x08;
    1110 +               if (d0 & 0x20)
    1111 +                       byte |= 0x04;
    1112 +               if (d0 & 0x08)
    1113 +                       byte |= 0x02;
    1114 +               if (d0 & 0x02)
    1115 +                       byte |= 0x01;
    1116 +
    1117 +               if (d2 & 0x80)
    1118 +                       bit |= 0x04;
    1119 +               if (d2 & 0x20)
    1120 +                       bit |= 0x02;
    1121 +               if (d2 & 0x08)
    1122 +                       bit |= 0x01;
     502+               
     503+               
     504+               if(d1 & 0x80) byte |= 0x80;
     505+               if(d1 & 0x20) byte |= 0x40;
     506+               if(d1 & 0x08) byte |= 0x20;
     507+               if(d1 & 0x02) byte |= 0x10;
     508+               if(d0 & 0x80) byte |= 0x08;
     509+               if(d0 & 0x20) byte |= 0x04;
     510+               if(d0 & 0x08) byte |= 0x02;
     511+               if(d0 & 0x02) byte |= 0x01;
     512+
     513+               if(d2 & 0x80) bit |= 0x04;
     514+               if(d2 & 0x20) bit |= 0x02;
     515+               if(d2 & 0x08) bit |= 0x01;
    1123516+
    1124517+               data[byte] ^= (1 << bit);
    1125 +
    1126 +               return 1; /* Corrected the error */
    1127 +       }
    1128 +
    1129 +       if ((yaffs_CountBits(d0) +
    1130 +            yaffs_CountBits(d1) +
    1131 +            yaffs_CountBits(d2)) ==  1) {
    1132 +               /* Reccoverable error in ecc */
    1133 +
     518+               
     519+               return 1;
     520+       }
     521+       
     522+       if((yaffs_CountBits(d0)+yaffs_CountBits(d1)+yaffs_CountBits(d2)) == 1)
     523+       {
     524+               // Reccoverable error in ecc
     525+               
    1134526+               read_ecc[0] = test_ecc[0];
    1135527+               read_ecc[1] = test_ecc[1];
    1136528+               read_ecc[2] = test_ecc[2];
    1137 +
    1138 +               return 1; /* Corrected the error */
    1139 +       }
    1140 +       
    1141 +       /* Unrecoverable error */
    1142 +
     529+               
     530+               return 1;
     531+       }
     532+       
     533+       // Unrecoverable error
     534+       
    1143535+       return -1;
    1144 +
    1145 +}
    1146 +
    1147 +
    1148 +/*
    1149 + * ECCxxxOther does ECC calcs on arbitrary n bytes of data
    1150 + */
    1151 +void yaffs_ECCCalculateOther(const unsigned char *data, unsigned nBytes,
    1152 +                            yaffs_ECCOther * eccOther)
     536+           
     537+
     538+}
     539+
     540+
     541+
     542+void yaffs_ECCCalculateOther(const unsigned char *data,unsigned nBytes, yaffs_ECCOther *eccOther)
    1153543+{
    1154544+       unsigned int i;
    1155 +
     545+       
    1156546+       unsigned char col_parity = 0;
    1157547+       unsigned line_parity = 0;
    1158548+       unsigned line_parity_prime = 0;
    1159549+       unsigned char b;
    1160 +
    1161 +       for (i = 0; i < nBytes; i++) {
     550+       
     551+       for(i = 0; i < nBytes; i++)
     552+       {
    1162553+               b = column_parity_table[*data++];
    1163554+               col_parity ^= b;
    1164555+
    1165 +               if (b & 0x01)    {
    1166 +                       /* odd number of bits in the byte */
     556+               if(b & 0x01) // odd number of bits in the byte
     557+               {
    1167558+                       line_parity ^= i;
    1168559+                       line_parity_prime ^= ~i;
    1169560+               }
    1170 +
    1171 +       }
    1172 +
     561+               
     562+       }
     563+       
    1173564+       eccOther->colParity = (col_parity >> 2) & 0x3f;
    1174565+       eccOther->lineParity = line_parity;
     
    1176567+}
    1177568+
    1178 +int yaffs_ECCCorrectOther(unsigned char *data, unsigned nBytes,
    1179 +                         yaffs_ECCOther * read_ecc,
    1180 +                         const yaffs_ECCOther * test_ecc)
    1181 +{
    1182 +       unsigned char cDelta;   /* column parity delta */
    1183 +       unsigned lDelta;        /* line parity delta */
    1184 +       unsigned lDeltaPrime;   /* line parity delta */
     569+int yaffs_ECCCorrectOther(unsigned char *data, unsigned nBytes, yaffs_ECCOther *read_ecc, const yaffs_ECCOther  *test_ecc)
     570+{
     571+       unsigned char cDelta; // column parity delta
     572+       unsigned lDelta; // line parity delta
     573+       unsigned lDeltaPrime; // line parity delta
    1185574+       unsigned bit;
    1186575+
    1187576+       cDelta = read_ecc->colParity ^ test_ecc->colParity;
    1188 +       lDelta = read_ecc->lineParity ^ test_ecc->lineParity;
     577+       lDelta = read_ecc->lineParity ^ test_ecc->lineParity;   
    1189578+       lDeltaPrime = read_ecc->lineParityPrime ^ test_ecc->lineParityPrime;
    1190 +
    1191 +       if ((cDelta | lDelta | lDeltaPrime) == 0)
    1192 +               return 0; /* no error */
    1193 +
    1194 +       if (lDelta == ~lDeltaPrime &&
    1195 +           (((cDelta ^ (cDelta >> 1)) & 0x15) == 0x15))
    1196 +       {
    1197 +               /* Single bit (recoverable) error in data */
     579+       
     580+       if((cDelta | lDelta | lDeltaPrime) == 0)
     581+       {
     582+               // no error
     583+               return 0;
     584+       }
     585+       
     586+       if( lDelta == ~lDeltaPrime &&
     587+            (((cDelta ^ (cDelta >> 1)) & 0x15) == 0x15)) // Not correct
     588+       {
     589+               // Single bit (recoverable) error in data
    1198590+
    1199591+               bit = 0;
    1200592+
    1201 +               if (cDelta & 0x20)
    1202 +                       bit |= 0x04;
    1203 +               if (cDelta & 0x08)
    1204 +                       bit |= 0x02;
    1205 +               if (cDelta & 0x02)
    1206 +                       bit |= 0x01;
    1207 +
    1208 +               if(lDelta >= nBytes)
    1209 +                       return -1;
    1210 +                       
     593+               if(cDelta & 0x20) bit |= 0x04;
     594+               if(cDelta & 0x08) bit |= 0x02;
     595+               if(cDelta & 0x02) bit |= 0x01;
     596+
    1211597+               data[lDelta] ^= (1 << bit);
    1212 +
    1213 +               return 1; /* corrected */
    1214 +       }
    1215 +
    1216 +       if ((yaffs_CountBits32(lDelta) + yaffs_CountBits32(lDeltaPrime) +
    1217 +            yaffs_CountBits(cDelta)) == 1) {
    1218 +               /* Reccoverable error in ecc */
    1219 +
    1220 +               *read_ecc = *test_ecc;
    1221 +               return 1; /* corrected */
    1222 +       }
    1223 +
    1224 +       /* Unrecoverable error */
    1225 +
     598+               
     599+               return 1;
     600+       }
     601+       
     602+       if((yaffs_CountBits32(lDelta) + yaffs_CountBits32(lDeltaPrime) + yaffs_CountBits(cDelta)) == 1)
     603+       {
     604+               // Reccoverable error in ecc
     605+               
     606+               *read_ecc  = *test_ecc;         
     607+               return 1;
     608+       }
     609+       
     610+       // Unrecoverable error
     611+       
    1226612+       return -1;
    1227 +
    1228 +}
    1229 +
    1230 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_ecc.h linux-2.6.18.2.patched/fs/yaffs2/yaffs_ecc.h
    1231 --- linux-2.6.18.2/fs/yaffs2/yaffs_ecc.h        1970-01-01 01:00:00.000000000 +0100
    1232 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_ecc.h        2006-11-25 00:15:32.000000000 +0100
    1233 @@ -0,0 +1,44 @@
     613+           
     614+
     615+}
     616+
     617+
     618+
     619diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_ecc.h linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_ecc.h
     620--- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_ecc.h       1970-01-01 01:00:00.000000000 +0100
     621+++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_ecc.h    2006-12-10 03:57:50.000000000 +0100
     622@@ -0,0 +1,41 @@
    1234623+/*
    1235624+ * YAFFS: Yet another FFS. A NAND-flash specific file system.
     
    1246635+ *
    1247636+ */
    1248 +
     637+ 
    1249638+ /*
    1250 +  * This code implements the ECC algorithm used in SmartMedia.
    1251 +  *
    1252 +  * The ECC comprises 22 bits of parity information and is stuffed into 3 bytes.
    1253 +  * The two unused bit are set to 1.
    1254 +  * The ECC can correct single bit errors in a 256-byte page of data. Thus, two such ECC
    1255 +  * blocks are used on a 512-byte NAND page.
    1256 +  *
    1257 +  */
     639+ * This code implements the ECC algorithm used in SmartMedia.
     640+ *
     641+ * The ECC comprises 22 bits of parity information and is stuffed into 3 bytes.
     642+ * The two unused bit are set to 1.
     643+ * The ECC can correct single bit errors in a 256-byte page of data. Thus, two such ECC
     644+ * blocks are used on a 512-byte NAND page.
     645+ *
     646+ */
    1258647+
    1259648+#ifndef __YAFFS_ECC_H__
    1260649+#define __YAFFS_ECC_H__
    1261650+
    1262 +typedef struct {
     651+typedef struct
     652+{
    1263653+       unsigned char colParity;
    1264654+       unsigned lineParity;
     
    1266656+} yaffs_ECCOther;
    1267657+
    1268 +void yaffs_ECCCalculate(const unsigned char *data, unsigned char *ecc);
    1269 +int yaffs_ECCCorrect(unsigned char *data, unsigned char *read_ecc,
    1270 +                    const unsigned char *test_ecc);
    1271 +
    1272 +void yaffs_ECCCalculateOther(const unsigned char *data, unsigned nBytes,
    1273 +                            yaffs_ECCOther * ecc);
    1274 +int yaffs_ECCCorrectOther(unsigned char *data, unsigned nBytes,
    1275 +                         yaffs_ECCOther * read_ecc,
    1276 +                         const yaffs_ECCOther * test_ecc);
    1277 +#endif
    1278 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_fs.c linux-2.6.18.2.patched/fs/yaffs2/yaffs_fs.c
    1279 --- linux-2.6.18.2/fs/yaffs2/yaffs_fs.c 1970-01-01 01:00:00.000000000 +0100
    1280 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_fs.c 2006-11-25 00:15:31.000000000 +0100
    1281 @@ -0,0 +1,2116 @@
     658+void yaffs_ECCCalculate(const unsigned char *data,unsigned char *ecc);
     659+int yaffs_ECCCorrect(unsigned char *data, unsigned char *read_ecc, const unsigned char *test_ecc);
     660+
     661+void yaffs_ECCCalculateOther(const unsigned char *data,unsigned nBytes, yaffs_ECCOther *ecc);
     662+int yaffs_ECCCorrectOther(unsigned char *data, unsigned nBytes, yaffs_ECCOther *read_ecc, const yaffs_ECCOther *test_ecc);
     663+#endif
     664diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_fs.c linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_fs.c
     665--- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_fs.c        1970-01-01 01:00:00.000000000 +0100
     666+++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_fs.c     2006-12-10 04:40:11.000000000 +0100
     667@@ -0,0 +1,1720 @@
    1282668+/*
    1283669+ * YAFFS: Yet another FFS. A NAND-flash specific file system.
     
    1297683+ *
    1298684+ * Special notes:
    1299 + * >> 2.4: sb->u.generic_sbp points to the yaffs_Device associated with
    1300 + *         this superblock
    1301 + * >> 2.6: sb->s_fs_info  points to the yaffs_Device associated with this
    1302 + *         superblock
     685+ * >> 2.4: sb->u.generic_sbp points to the yaffs_Device associated with this superblock
     686+ * >> 2.6: sb->s_fs_info  points to the yaffs_Device associated with this superblock
    1303687+ * >> inode->u.generic_ip points to the associated yaffs_Object.
     688+ *
    1304689+ *
    1305690+ * Acknowledgements:
     
    1312697+ */
    1313698+
    1314 +const char *yaffs_fs_c_version =
    1315 +    "$Id: yaffs_fs.c,v 1.54 2006/10/24 18:09:15 charles Exp $";
     699+
     700+const char *yaffs_fs_c_version = "$Id: yaffs_fs.c,v 1.27 2005/08/04 22:47:36 luc Exp $";
    1316701+extern const char *yaffs_guts_c_version;
     702+
    1317703+
    1318704+#include <linux/config.h>
     
    1330716+#include <linux/interrupt.h>
    1331717+#include <linux/string.h>
    1332 +#include <linux/ctype.h>
     718+
    1333719+
    1334720+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
     
    1338724+#define UnlockPage(p) unlock_page(p)
    1339725+#define Page_Uptodate(page)    test_bit(PG_uptodate, &(page)->flags)
    1340 +
    1341 +/* FIXME: use sb->s_id instead ? */
    1342 +#define yaffs_devname(sb, buf) bdevname(sb->s_bdev, buf)
     726+#define yaffs_devname(sb, buf) bdevname(sb->s_bdev, buf)       // FIXME: use sb->s_id instead ?
    1343727+
    1344728+#else
     
    1348732+#define        yaffs_devname(sb, buf)  kdevname(sb->s_dev)
    1349733+
    1350 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
    1351 +/* added NCB 26/5/2006 for 2.4.25-vrs2-tcl1 kernel */
    1352 +#define __user
    1353 +#endif
    1354 +
    1355734+#endif
    1356735+
     
    1360739+#include "yaffs_guts.h"
    1361740+
    1362 +unsigned yaffs_traceMask = YAFFS_TRACE_ALWAYS |
    1363 +                          YAFFS_TRACE_BAD_BLOCKS |
    1364 +                          YAFFS_TRACE_CHECKPOINT
    1365 +                          /* | 0xFFFFFFFF */;
    1366 +
     741+
     742+
     743+
     744+unsigned yaffs_traceMask = YAFFS_TRACE_ALWAYS | YAFFS_TRACE_BAD_BLOCKS;
     745+//unsigned yaffs_traceMask = 0xFFFFFFFF;
     746+
     747+
     748+#ifdef CONFIG_YAFFS_YAFFS1
    1367749+#include <linux/mtd/mtd.h>
    1368750+#include "yaffs_mtdif.h"
    1369751+#include "yaffs_mtdif2.h"
    1370 +
    1371 +/*#define T(x) printk x */
     752+#endif //CONFIG_YAFFS_YAFFS1
     753+
     754+//#define T(x) printk x
     755+
     756+
    1372757+
    1373758+#define yaffs_InodeToObject(iptr) ((yaffs_Object *)((iptr)->u.generic_ip))
     
    1380765+#endif
    1381766+
     767+
    1382768+static void yaffs_put_super(struct super_block *sb);
    1383769+
    1384 +static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n,
    1385 +                               loff_t * pos);
    1386 +
    1387 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
    1388 +static int yaffs_file_flush(struct file *file, fl_owner_t id);
    1389 +#else
    1390 +static int yaffs_file_flush(struct file *file);
    1391 +#endif
    1392 +
    1393 +static int yaffs_sync_object(struct file *file, struct dentry *dentry,
    1394 +                            int datasync);
     770+static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n, loff_t *pos);
     771+
     772+static int yaffs_file_flush(struct file* file, fl_owner_t id);
     773+
     774+static int yaffs_sync_object(struct file * file, struct dentry *dentry, int datasync);
    1395775+
    1396776+static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir);
    1397777+
    1398778+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
    1399 +static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode,
    1400 +                       struct nameidata *n);
    1401 +static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry,
    1402 +                                  struct nameidata *n);
     779+static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *n);
     780+static struct dentry * yaffs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *n);
    1403781+#else
    1404782+static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode);
    1405 +static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry);
    1406 +#endif
    1407 +static int yaffs_link(struct dentry *old_dentry, struct inode *dir,
    1408 +                     struct dentry *dentry);
    1409 +static int yaffs_unlink(struct inode *dir, struct dentry *dentry);
    1410 +static int yaffs_symlink(struct inode *dir, struct dentry *dentry,
    1411 +                        const char *symname);
    1412 +static int yaffs_mkdir(struct inode *dir, struct dentry *dentry, int mode);
     783+static struct dentry * yaffs_lookup(struct inode *dir, struct dentry *dentry);
     784+#endif
     785+static int yaffs_link(struct dentry *old_dentry, struct inode * dir, struct dentry * dentry);
     786+static int yaffs_unlink(struct inode * dir, struct dentry *dentry);
     787+static int yaffs_symlink(struct inode * dir, struct dentry *dentry, const char * symname);
     788+static int yaffs_mkdir(struct inode * dir, struct dentry * dentry, int mode);
    1413789+
    1414790+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
    1415 +static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,
    1416 +                      dev_t dev);
     791+static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev);
    1417792+#else
    1418 +static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,
    1419 +                      int dev);
    1420 +#endif
    1421 +static int yaffs_rename(struct inode *old_dir, struct dentry *old_dentry,
    1422 +                       struct inode *new_dir, struct dentry *new_dentry);
     793+static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, int dev);
     794+#endif
     795+static int yaffs_rename(struct inode * old_dir, struct dentry *old_dentry, struct inode * new_dir,struct dentry *new_dentry);
    1423796+static int yaffs_setattr(struct dentry *dentry, struct iattr *attr);
    1424797+
    1425 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
    1426 +static int yaffs_sync_fs(struct super_block *sb, int wait);
    1427 +static void yaffs_write_super(struct super_block *sb);
    1428 +#else
    1429 +static int yaffs_sync_fs(struct super_block *sb);
    1430 +static int yaffs_write_super(struct super_block *sb);
    1431 +#endif
    1432 +
    1433 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
    1434798+static int yaffs_statfs(struct dentry *dentry, struct kstatfs *buf);
    1435 +#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
    1436 +static int yaffs_statfs(struct super_block *sb, struct kstatfs *buf);
    1437 +#else
    1438 +static int yaffs_statfs(struct super_block *sb, struct statfs *buf);
    1439 +#endif
    1440 +static void yaffs_read_inode(struct inode *inode);
    1441 +
    1442 +static void yaffs_put_inode(struct inode *inode);
     799+static void yaffs_read_inode (struct inode *inode);
     800+
     801+static void yaffs_put_inode (struct inode *inode);
    1443802+static void yaffs_delete_inode(struct inode *);
    1444803+static void yaffs_clear_inode(struct inode *);
    1445804+
    1446 +static int yaffs_readpage(struct file *file, struct page *page);
     805+static int yaffs_readpage(struct file *file, struct page * page);
    1447806+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
    1448807+static int yaffs_writepage(struct page *page, struct writeback_control *wbc);
     
    1450809+static int yaffs_writepage(struct page *page);
    1451810+#endif
    1452 +static int yaffs_prepare_write(struct file *f, struct page *pg,
    1453 +                              unsigned offset, unsigned to);
    1454 +static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset,
    1455 +                             unsigned to);
    1456 +
    1457 +static int yaffs_readlink(struct dentry *dentry, char __user * buffer,
    1458 +                         int buflen);
    1459 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13))
     811+static int yaffs_prepare_write(struct file *f, struct page *pg, unsigned offset, unsigned to);
     812+static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset, unsigned to);
     813+
     814+static int yaffs_readlink(struct dentry *dentry, char __user *buffer, int buflen);
    1460815+static void *yaffs_follow_link(struct dentry *dentry, struct nameidata *nd);
    1461 +#else
    1462 +static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd);
    1463 +#endif
     816+
     817+
    1464818+
    1465819+static struct address_space_operations yaffs_file_address_operations = {
    1466 +       .readpage = yaffs_readpage,
    1467 +       .writepage = yaffs_writepage,
    1468 +       .prepare_write = yaffs_prepare_write,
    1469 +       .commit_write = yaffs_commit_write,
     820+       .readpage       = yaffs_readpage,
     821+       .writepage      = yaffs_writepage,
     822+       .prepare_write  = yaffs_prepare_write,
     823+       .commit_write   = yaffs_commit_write,
    1470824+};
    1471825+
    1472826+static struct file_operations yaffs_file_operations = {
    1473 +       .read = generic_file_read,
    1474 +       .write = generic_file_write,
    1475 +       .mmap = generic_file_mmap,
    1476 +       .flush = yaffs_file_flush,
    1477 +       .fsync = yaffs_sync_object,
    1478 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
    1479 +       .sendfile = generic_file_sendfile,
    1480 +#endif
    1481 +
     827+       .read           = generic_file_read,
     828+       .write          = generic_file_write,
     829+       .mmap           = generic_file_mmap,
     830+       .flush          = yaffs_file_flush,
     831+       .fsync          = yaffs_sync_object,
    1482832+};
    1483833+
    1484834+static struct inode_operations yaffs_file_inode_operations = {
    1485 +       .setattr = yaffs_setattr,
     835+       .setattr        = yaffs_setattr,
    1486836+};
    1487837+
    1488 +static struct inode_operations yaffs_symlink_inode_operations = {
    1489 +       .readlink = yaffs_readlink,
    1490 +       .follow_link = yaffs_follow_link,
    1491 +       .setattr = yaffs_setattr,
     838+static struct inode_operations yaffs_symlink_inode_operations = {     
     839+       .readlink       = yaffs_readlink,
     840+       .follow_link    = yaffs_follow_link,
     841+       .setattr        = yaffs_setattr,
    1492842+};
    1493843+
    1494844+static struct inode_operations yaffs_dir_inode_operations = {
    1495 +       .create = yaffs_create,
    1496 +       .lookup = yaffs_lookup,
    1497 +       .link = yaffs_link,
    1498 +       .unlink = yaffs_unlink,
    1499 +       .symlink = yaffs_symlink,
    1500 +       .mkdir = yaffs_mkdir,
    1501 +       .rmdir = yaffs_unlink,
    1502 +       .mknod = yaffs_mknod,
    1503 +       .rename = yaffs_rename,
    1504 +       .setattr = yaffs_setattr,
     845+       .create         = yaffs_create,
     846+       .lookup         = yaffs_lookup,
     847+       .link           = yaffs_link,
     848+       .unlink         = yaffs_unlink,
     849+       .symlink        = yaffs_symlink,
     850+       .mkdir          = yaffs_mkdir,
     851+       .rmdir          = yaffs_unlink,
     852+       .mknod          = yaffs_mknod,
     853+       .rename         = yaffs_rename,
     854+       .setattr        = yaffs_setattr,
    1505855+};
    1506856+
    1507857+static struct file_operations yaffs_dir_operations = {
    1508 +       .read = generic_read_dir,
    1509 +       .readdir = yaffs_readdir,
    1510 +       .fsync = yaffs_sync_object,
     858+       .read           = generic_read_dir,
     859+       .readdir        = yaffs_readdir,
     860+       .fsync          = yaffs_sync_object,
    1511861+};
    1512862+
    1513863+static struct super_operations yaffs_super_ops = {
    1514 +       .statfs = yaffs_statfs,
    1515 +       .read_inode = yaffs_read_inode,
    1516 +       .put_inode = yaffs_put_inode,
    1517 +       .put_super = yaffs_put_super,
    1518 +       .delete_inode = yaffs_delete_inode,
    1519 +       .clear_inode = yaffs_clear_inode,
    1520 +       .sync_fs = yaffs_sync_fs,
    1521 +       .write_super = yaffs_write_super,
     864+       .statfs         = yaffs_statfs,
     865+       .read_inode     = yaffs_read_inode,
     866+       .put_inode      = yaffs_put_inode,
     867+       .put_super      = yaffs_put_super,
     868+       .delete_inode   = yaffs_delete_inode,
     869+       .clear_inode    = yaffs_clear_inode,
    1522870+};
    1523871+
    1524 +static void yaffs_GrossLock(yaffs_Device * dev)
    1525 +{
    1526 +       T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs locking\n"));
     872+
     873+
     874+static void yaffs_GrossLock(yaffs_Device *dev)
     875+{
     876+       T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs locking\n"));
    1527877+
    1528878+       down(&dev->grossLock);
    1529879+}
    1530880+
    1531 +static void yaffs_GrossUnlock(yaffs_Device * dev)
    1532 +{
    1533 +       T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs unlocking\n"));
     881+static void yaffs_GrossUnlock(yaffs_Device *dev)
     882+{
     883+       T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs unlocking\n"));
    1534884+       up(&dev->grossLock);
    1535885+
    1536886+}
    1537887+
    1538 +static int yaffs_readlink(struct dentry *dentry, char __user * buffer,
    1539 +                         int buflen)
     888+static int yaffs_readlink(struct dentry *dentry, char __user *buffer, int buflen)
    1540889+{
    1541890+       unsigned char *alias;
     
    1544893+       yaffs_Device *dev = yaffs_DentryToObject(dentry)->myDev;
    1545894+
     895+
    1546896+       yaffs_GrossLock(dev);
    1547 +
     897+       
    1548898+       alias = yaffs_GetSymlinkAlias(yaffs_DentryToObject(dentry));
    1549 +
     899+       
    1550900+       yaffs_GrossUnlock(dev);
    1551 +
    1552 +       if (!alias)
     901+       
     902+       if(!alias)
    1553903+               return -ENOMEM;
    1554904+
     
    1558908+}
    1559909+
    1560 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13))
    1561910+static void *yaffs_follow_link(struct dentry *dentry, struct nameidata *nd)
    1562 +#else
    1563 +static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd)
    1564 +#endif
    1565911+{
    1566912+       unsigned char *alias;
     
    1568914+       yaffs_Device *dev = yaffs_DentryToObject(dentry)->myDev;
    1569915+
     916+
    1570917+       yaffs_GrossLock(dev);
    1571918+
    1572919+       alias = yaffs_GetSymlinkAlias(yaffs_DentryToObject(dentry));
    1573 +
     920+       
    1574921+       yaffs_GrossUnlock(dev);
    1575 +
    1576 +       if (!alias)
    1577 +        {
     922+       
     923+       if(!alias)
    1578924+               ret = -ENOMEM;
    1579 +               goto out;
    1580 +        }
    1581 +
    1582 +       ret = vfs_follow_link(nd, alias);
    1583 +       kfree(alias);
    1584 +out:
    1585 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13))
     925+       else {
     926+               ret = vfs_follow_link(nd,alias);
     927+               kfree(alias);
     928+       }
    1586929+       return ERR_PTR (ret);
    1587 +#else
    1588 +       return ret;
    1589 +#endif
    1590 +}
    1591 +
    1592 +struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev,
    1593 +                             yaffs_Object * obj);
     930+}
     931+
     932+
     933+struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev,yaffs_Object *obj);
    1594934+
    1595935+/*
     
    1598938+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
    1599939+
    1600 +static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry,
    1601 +                                  struct nameidata *n)
     940+static struct dentry * yaffs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *n)
    1602941+#else
    1603 +static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry)
     942+static struct dentry * yaffs_lookup(struct inode *dir, struct dentry *dentry)
    1604943+#endif
    1605944+{
    1606945+       yaffs_Object *obj;
    1607 +       struct inode *inode = NULL;     /* NCB 2.5/2.6 needs NULL here */
    1608 +
     946+       struct inode *inode = NULL; // NCB 2.5/2.6 needs NULL here
     947+       
    1609948+       yaffs_Device *dev = yaffs_InodeToObject(dir)->myDev;
    1610949+
     950+
    1611951+       yaffs_GrossLock(dev);
    1612952+
    1613 +       T(YAFFS_TRACE_OS,
    1614 +         (KERN_DEBUG "yaffs_lookup for %d:%s\n",
    1615 +          yaffs_InodeToObject(dir)->objectId, dentry->d_name.name));
    1616 +
    1617 +       obj =
    1618 +           yaffs_FindObjectByName(yaffs_InodeToObject(dir),
    1619 +                                  dentry->d_name.name);
    1620 +
    1621 +       obj = yaffs_GetEquivalentObject(obj);   /* in case it was a hardlink */
    1622 +       
    1623 +       /* Can't hold gross lock when calling yaffs_get_inode() */
     953+       
     954+       T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_lookup for %d:%s\n",yaffs_InodeToObject(dir)->objectId,dentry->d_name.name));
     955+       
     956+       obj = yaffs_FindObjectByName(yaffs_InodeToObject(dir),dentry->d_name.name);
     957+       
     958+       obj = yaffs_GetEquivalentObject(obj); // in case it was a hardlink
     959+       
     960+
     961+       
     962+       if(obj)
     963+       {
     964+               T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_lookup found %d\n",obj->objectId));
     965+               
     966+               inode = yaffs_get_inode(dir->i_sb, obj->yst_mode,0,obj);
     967+               
     968+               if(inode)
     969+               {
     970+                       T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_loookup dentry \n"));
     971+/* #if 0 asserted by NCB for 2.5/6 compatability - falls through to d_add even if NULL inode */       
     972+#if 0
     973+                       //dget(dentry); // try to solve directory bug
     974+                       d_add(dentry,inode);
     975+                       
     976+                       yaffs_GrossUnlock(dev);
     977+
     978+                       // return dentry;
     979+                       return NULL;
     980+#endif
     981+               }
     982+
     983+       }
     984+       else
     985+       {
     986+               T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_lookup not found\n"));
     987+               
     988+       }
    1624989+       yaffs_GrossUnlock(dev);
    1625990+
    1626 +       if (obj) {
    1627 +               T(YAFFS_TRACE_OS,
    1628 +                 (KERN_DEBUG "yaffs_lookup found %d\n", obj->objectId));
    1629 +
    1630 +               inode = yaffs_get_inode(dir->i_sb, obj->yst_mode, 0, obj);
    1631 +
    1632 +               if (inode) {
    1633 +                       T(YAFFS_TRACE_OS,
    1634 +                         (KERN_DEBUG "yaffs_loookup dentry \n"));
    1635 +/* #if 0 asserted by NCB for 2.5/6 compatability - falls through to
    1636 + * d_add even if NULL inode */
    1637 +#if 0
    1638 +                       /*dget(dentry); // try to solve directory bug */
    1639 +                       d_add(dentry, inode);
    1640 +
    1641 +                       /* return dentry; */
    1642 +                       return NULL;
    1643 +#endif
    1644 +               }
    1645 +
    1646 +       } else {
    1647 +               T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_lookup not found\n"));
    1648 +
    1649 +       }
    1650 +
    1651 +/* added NCB for 2.5/6 compatability - forces add even if inode is
    1652 + * NULL which creates dentry hash */
    1653 +       d_add(dentry, inode);
    1654 +
     991+/* added NCB for 2.5/6 compatability - forces add even if inode is NULL which creates dentry hash*/   
     992+       d_add(dentry,inode);
     993+       
    1655994+       return NULL;
    1656 +       /*      return (ERR_PTR(-EIO)); */
    1657 +
    1658 +}
    1659 +
    1660 +/* For now put inode is just for debugging
    1661 + * Put inode is called when the inode **structure** is put.
    1662 + */
     995+       //      return (ERR_PTR(-EIO));
     996+       
     997+}
     998+
     999+// For now put inode is just for debugging
     1000+// Put inode is called when the inode **structure** is put.
    16631001+static void yaffs_put_inode(struct inode *inode)
    16641002+{
    1665 +       T(YAFFS_TRACE_OS,
    1666 +         ("yaffs_put_inode: ino %d, count %d\n", (int)inode->i_ino,
    1667 +          atomic_read(&inode->i_count)));
    1668 +
    1669 +}
    1670 +
    1671 +/* clear is called to tell the fs to release any per-inode data it holds */
     1003+       T(YAFFS_TRACE_OS,("yaffs_put_inode: ino %d, count %d\n",(int)inode->i_ino, atomic_read(&inode->i_count)));
     1004+       
     1005+}
     1006+
     1007+// clear is called to tell the fs to release any per-inode data it holds
    16721008+static void yaffs_clear_inode(struct inode *inode)
    16731009+{
    16741010+       yaffs_Object *obj;
    16751011+       yaffs_Device *dev;
    1676 +
     1012+       
    16771013+       obj = yaffs_InodeToObject(inode);
    1678 +
    1679 +       T(YAFFS_TRACE_OS,
    1680 +         ("yaffs_clear_inode: ino %d, count %d %s\n", (int)inode->i_ino,
    1681 +          atomic_read(&inode->i_count),
    1682 +          obj ? "object exists" : "null object"));
    1683 +
    1684 +       if (obj) {
     1014+       
     1015+       T(YAFFS_TRACE_OS,("yaffs_clear_inode: ino %d, count %d %s\n",(int)inode->i_ino, atomic_read(&inode->i_count),
     1016+               obj ? "object exists" : "null object"));       
     1017+
     1018+       if(obj)
     1019+       {
    16851020+               dev = obj->myDev;
    16861021+               yaffs_GrossLock(dev);
    1687 +
    1688 +               /* Clear the association between the inode and
    1689 +                * the yaffs_Object.
    1690 +                */
     1022+               
     1023+               // Clear the association between the inode ant the yaffs_Object.
    16911024+               obj->myInode = NULL;
    16921025+               inode->u.generic_ip = NULL;
    1693 +
    1694 +               /* If the object freeing was deferred, then the real
    1695 +                * free happens now.
    1696 +                * This should fix the inode inconsistency problem.
    1697 +                */
    1698 +
     1026+               
     1027+               // If the object freeing was deferred, then the real free happens now.
     1028+               // This should fix the inode inconsistency problem.
     1029+               
    16991030+               yaffs_HandleDeferedFree(obj);
    1700 +
     1031+               
    17011032+               yaffs_GrossUnlock(dev);
    17021033+       }
    1703 +
    1704 +}
    1705 +
    1706 +/* delete is called when the link count is zero and the inode
    1707 + * is put (ie. nobody wants to know about it anymore, time to
    1708 + * delete the file).
    1709 + * NB Must call clear_inode()
    1710 + */
     1034+       
     1035+       
     1036+}
     1037+
     1038+// delete is called when the link count is zero and the inode
     1039+// is put (ie. nobody wants to know about it anymore, time to
     1040+// delete the file).
     1041+// NB Must call clear_inode()
    17111042+static void yaffs_delete_inode(struct inode *inode)
    17121043+{
     
    17141045+       yaffs_Device *dev;
    17151046+
    1716 +       T(YAFFS_TRACE_OS,
    1717 +         ("yaffs_delete_inode: ino %d, count %d %s\n", (int)inode->i_ino,
    1718 +          atomic_read(&inode->i_count),
    1719 +          obj ? "object exists" : "null object"));
    1720 +
    1721 +       if (obj) {
    1722 +               dev = obj->myDev;
     1047+       T(YAFFS_TRACE_OS,("yaffs_delete_inode: ino %d, count %d %s\n",(int)inode->i_ino, atomic_read(&inode->i_count),
     1048+               obj ? "object exists" : "null object"));
     1049+       
     1050+       if(obj)
     1051+       {
     1052+               dev = obj->myDev;
    17231053+               yaffs_GrossLock(dev);
    17241054+               yaffs_DeleteFile(obj);
    17251055+               yaffs_GrossUnlock(dev);
    17261056+       }
    1727 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13))
    1728 +        truncate_inode_pages (&inode->i_data, 0);
    1729 +#endif
    17301057+       clear_inode(inode);
    17311058+}
    17321059+
    1733 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
    1734 +static int yaffs_file_flush(struct file *file, fl_owner_t id)
    1735 +#else
    1736 +static int yaffs_file_flush(struct file *file)
    1737 +#endif
     1060+
     1061+static int yaffs_file_flush(struct file* file, fl_owner_t id)
    17381062+{
    17391063+       yaffs_Object *obj = yaffs_DentryToObject(file->f_dentry);
    1740 +
     1064+       
    17411065+       yaffs_Device *dev = obj->myDev;
    1742 +
    1743 +       T(YAFFS_TRACE_OS,
    1744 +         (KERN_DEBUG "yaffs_file_flush object %d (%s)\n", obj->objectId,
    1745 +          obj->dirty ? "dirty" : "clean"));
     1066+       
     1067+       T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_file_flush object %d (%s)\n",obj->objectId,
     1068+                               obj->dirty ? "dirty" : "clean"));
    17461069+
    17471070+       yaffs_GrossLock(dev);
    1748 +
    1749 +       yaffs_FlushFile(obj, 1);
     1071+       
     1072+    yaffs_FlushFile(obj,1);
    17501073+
    17511074+       yaffs_GrossUnlock(dev);
    17521075+
    1753 +       return 0;
    1754 +}
    1755 +
    1756 +static int yaffs_readpage_nolock(struct file *f, struct page *pg)
    1757 +{
    1758 +       /* Lifted from jffs2 */
    1759 +
     1076+    return 0;
     1077+}
     1078+
     1079+
     1080+
     1081+static int yaffs_readpage_nolock(struct file *f, struct page * pg)
     1082+{
     1083+       // Lifted from jffs2
     1084+       
    17601085+       yaffs_Object *obj;
    17611086+       unsigned char *pg_buf;
     
    17641089+       yaffs_Device *dev;
    17651090+
    1766 +       T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_readpage at %08x, size %08x\n",
    1767 +                          (unsigned)(pg->index << PAGE_CACHE_SHIFT),
    1768 +                          (unsigned)PAGE_CACHE_SIZE));
    1769 +
    1770 +       obj = yaffs_DentryToObject(f->f_dentry);
     1091+       T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_readpage at %08x, size %08x\n",
     1092+                     (unsigned)(pg->index << PAGE_CACHE_SHIFT), (unsigned)PAGE_CACHE_SIZE));
     1093+
     1094+       obj  = yaffs_DentryToObject(f->f_dentry);
    17711095+
    17721096+       dev = obj->myDev;
    1773 +
     1097+       
     1098+       
    17741099+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
    1775 +       BUG_ON(!PageLocked(pg));
     1100+        BUG_ON(!PageLocked(pg));
    17761101+#else
    17771102+       if (!PageLocked(pg))
    1778 +               PAGE_BUG(pg);
     1103+                PAGE_BUG(pg);
    17791104+#endif
    17801105+
     
    17831108+
    17841109+       yaffs_GrossLock(dev);
    1785 +
    1786 +       ret =
    1787 +           yaffs_ReadDataFromFile(obj, pg_buf, pg->index << PAGE_CACHE_SHIFT,
    1788 +                                  PAGE_CACHE_SIZE);
     1110+       
     1111+       ret = yaffs_ReadDataFromFile(obj, pg_buf, pg->index << PAGE_CACHE_SHIFT, PAGE_CACHE_SIZE);
    17891112+
    17901113+       yaffs_GrossUnlock(dev);
    1791 +
    1792 +       if (ret >= 0)
    1793 +               ret = 0;
     1114+       
     1115+       if(ret >= 0) ret = 0;
    17941116+
    17951117+       if (ret) {
     
    18041126+       kunmap(pg);
    18051127+
    1806 +       T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_readpage done\n"));
     1128+
     1129+       T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_readpage done\n"));
    18071130+       return ret;
    18081131+}
     
    18101133+static int yaffs_readpage_unlock(struct file *f, struct page *pg)
    18111134+{
    1812 +       int ret = yaffs_readpage_nolock(f, pg);
     1135+       int ret = yaffs_readpage_nolock(f,pg);
    18131136+       UnlockPage(pg);
    18141137+       return ret;
    18151138+}
    18161139+
    1817 +static int yaffs_readpage(struct file *f, struct page *pg)
    1818 +{
    1819 +       return yaffs_readpage_unlock(f, pg);
    1820 +}
    1821 +
    1822 +/* writepage inspired by/stolen from smbfs */
     1140+static int yaffs_readpage(struct file *f, struct page * pg)
     1141+{
     1142+       return yaffs_readpage_unlock(f,pg);
     1143+}
     1144+
     1145+// writepage inspired by/stolen from smbfs
     1146+//
    18231147+
    18241148+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
     
    18291153+{
    18301154+       struct address_space *mapping = page->mapping;
    1831 +       loff_t offset = (loff_t) page->index << PAGE_CACHE_SHIFT;
     1155+       loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
    18321156+       struct inode *inode;
    18331157+       unsigned long end_index;
     
    18431167+               BUG();
    18441168+
    1845 +       if (offset > inode->i_size) {
    1846 +               T(YAFFS_TRACE_OS,
    1847 +                 (KERN_DEBUG
    1848 +                  "yaffs_writepage at %08x, inode size = %08x!!!\n",
    1849 +                  (unsigned)(page->index << PAGE_CACHE_SHIFT),
    1850 +                  (unsigned)inode->i_size));
    1851 +               T(YAFFS_TRACE_OS,
    1852 +                 (KERN_DEBUG "                -> don't care!!\n"));
     1169+       if (offset > inode->i_size)
     1170+       {
     1171+               T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_writepage at %08x, inode size = %08x!!!\n", (unsigned)(page->index << PAGE_CACHE_SHIFT), (unsigned) inode->i_size));
     1172+               T(YAFFS_TRACE_OS,(KERN_DEBUG"                -> don't care!!\n"));
    18531173+               unlock_page(page);
    18541174+               return 0;
     
    18581178+
    18591179+       /* easy case */
    1860 +       if (page->index < end_index) {
     1180+       if (page->index < end_index)
     1181+       {
    18611182+               nBytes = PAGE_CACHE_SIZE;
    1862 +       } else {
    1863 +               nBytes = inode->i_size & (PAGE_CACHE_SIZE - 1);
    1864 +       }
     1183+       }
     1184+       else
     1185+       {
     1186+               nBytes = inode->i_size & (PAGE_CACHE_SIZE-1);
     1187+       }
     1188+       //  What's happening here?
     1189+       ///* OK, are we completely out? */
     1190+       //if (page->index >= end_index+1 || !offset)
     1191+       //      return -EIO;
    18651192+
    18661193+       get_page(page);
     1194+
    18671195+
    18681196+       buffer = kmap(page);
     
    18711199+       yaffs_GrossLock(obj->myDev);
    18721200+
    1873 +       T(YAFFS_TRACE_OS,
    1874 +         (KERN_DEBUG "yaffs_writepage at %08x, size %08x\n",
    1875 +          (unsigned)(page->index << PAGE_CACHE_SHIFT), nBytes));
    1876 +       T(YAFFS_TRACE_OS,
    1877 +         (KERN_DEBUG "writepag0: obj = %05x, ino = %05x\n",
    1878 +          (int)obj->variant.fileVariant.fileSize, (int)inode->i_size));
    1879 +
    1880 +       nWritten =
    1881 +           yaffs_WriteDataToFile(obj, buffer, page->index << PAGE_CACHE_SHIFT,
    1882 +                                 nBytes, 0);
    1883 +
    1884 +       T(YAFFS_TRACE_OS,
    1885 +         (KERN_DEBUG "writepag1: obj = %05x, ino = %05x\n",
    1886 +          (int)obj->variant.fileVariant.fileSize, (int)inode->i_size));
     1201+       T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_writepage at %08x, size %08x\n", (unsigned)(page->index << PAGE_CACHE_SHIFT), nBytes));
     1202+       T(YAFFS_TRACE_OS,(KERN_DEBUG"writepag0: obj = %05x, ino = %05x\n", (int) obj->variant.fileVariant.fileSize, (int) inode->i_size));
     1203+
     1204+       nWritten = yaffs_WriteDataToFile(obj,buffer,page->index << PAGE_CACHE_SHIFT,nBytes,0);
     1205+
     1206+       T(YAFFS_TRACE_OS,(KERN_DEBUG"writepag1: obj = %05x, ino = %05x\n", (int) obj->variant.fileVariant.fileSize, (int) inode->i_size));
    18871207+
    18881208+       yaffs_GrossUnlock(obj->myDev);
    1889 +
     1209+       
    18901210+       kunmap(page);
    18911211+       SetPageUptodate(page);
     
    18931213+       put_page(page);
    18941214+
    1895 +       return (nWritten == nBytes) ? 0 : -ENOSPC;
    1896 +}
    1897 +
    1898 +static int yaffs_prepare_write(struct file *f, struct page *pg,
    1899 +                              unsigned offset, unsigned to)
    1900 +{
    1901 +
    1902 +       T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_prepair_write\n"));
    1903 +       if (!Page_Uptodate(pg) && (offset || to < PAGE_CACHE_SIZE))
    1904 +               return yaffs_readpage_nolock(f, pg);
     1215+       return (nWritten == nBytes) ? 0  : -ENOSPC;
     1216+}
     1217+
     1218+
     1219+
     1220+static int yaffs_prepare_write(struct file *f, struct page *pg, unsigned offset, unsigned to)
     1221+{
     1222+
     1223+       T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_prepair_write\n"));
     1224+       if(!Page_Uptodate(pg) && (offset || to < PAGE_CACHE_SIZE))
     1225+               return  yaffs_readpage_nolock(f,pg);   
    19051226+
    19061227+       return 0;
    1907 +
    1908 +}
    1909 +
    1910 +static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset,
    1911 +                             unsigned to)
     1228+       
     1229+}
     1230+
     1231+static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset, unsigned to)
    19121232+{
    19131233+
    19141234+       void *addr = page_address(pg) + offset;
    1915 +       loff_t pos = (((loff_t) pg->index) << PAGE_CACHE_SHIFT) + offset;
     1235+       loff_t pos = (((loff_t)pg->index) << PAGE_CACHE_SHIFT) + offset;
    19161236+       int nBytes = to - offset;
    19171237+       int nWritten;
    1918 +
     1238+       
    19191239+       unsigned spos = pos;
    19201240+       unsigned saddr = (unsigned)addr;
    19211241+
    1922 +       T(YAFFS_TRACE_OS,
    1923 +         (KERN_DEBUG "yaffs_commit_write addr %x pos %x nBytes %d\n", saddr,
    1924 +          spos, nBytes));
    1925 +
    1926 +       nWritten = yaffs_file_write(f, addr, nBytes, &pos);
    1927 +
    1928 +       if (nWritten != nBytes) {
    1929 +               T(YAFFS_TRACE_OS,
    1930 +                 (KERN_DEBUG
    1931 +                  "yaffs_commit_write not same size nWritten %d  nBytes %d\n",
    1932 +                  nWritten, nBytes));
     1242+       T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_commit_write addr %x pos %x nBytes %d\n",saddr,spos,nBytes));
     1243+       
     1244+       nWritten = yaffs_file_write(f,addr, nBytes, &pos);
     1245+       
     1246+       if(nWritten != nBytes)
     1247+       {
     1248+               T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_commit_write not same size nWritten %d  nBytes %d\n",nWritten,nBytes));
    19331249+               SetPageError(pg);
    19341250+               ClearPageUptodate(pg);
    1935 +       } else {
     1251+       }
     1252+       else
     1253+       {
    19361254+               SetPageUptodate(pg);
    19371255+       }
    19381256+
    1939 +       T(YAFFS_TRACE_OS,
    1940 +         (KERN_DEBUG "yaffs_commit_write returning %d\n",
    1941 +          nWritten == nBytes ? 0 : nWritten));
    1942 +
    1943 +       return nWritten == nBytes ? 0 : nWritten;
    1944 +
    1945 +}
    1946 +
    1947 +static void yaffs_FillInodeFromObject(struct inode *inode, yaffs_Object * obj)
    1948 +{
    1949 +       if (inode && obj) {
    1950 +
    1951 +
    1952 +               /* Check mode against the variant type and attempt to repair if broken. */
    1953 +               __u32 mode = obj->yst_mode;
    1954 +               switch( obj->variantType ){
    1955 +               case YAFFS_OBJECT_TYPE_FILE :
    1956 +                       if( ! S_ISREG(mode) ){
    1957 +                               obj->yst_mode &= ~S_IFMT;
    1958 +                               obj->yst_mode |= S_IFREG;
    1959 +                       }
    1960 +
    1961 +                       break;
    1962 +               case YAFFS_OBJECT_TYPE_SYMLINK :
    1963 +                       if( ! S_ISLNK(mode) ){
    1964 +                               obj->yst_mode &= ~S_IFMT;
    1965 +                               obj->yst_mode |= S_IFLNK;
    1966 +                       }
    1967 +
    1968 +                       break;
    1969 +               case YAFFS_OBJECT_TYPE_DIRECTORY :
    1970 +                       if( ! S_ISDIR(mode) ){
    1971 +                               obj->yst_mode &= ~S_IFMT;
    1972 +                               obj->yst_mode |= S_IFDIR;
    1973 +                       }
    1974 +
    1975 +                       break;
    1976 +               case YAFFS_OBJECT_TYPE_UNKNOWN :
    1977 +               case YAFFS_OBJECT_TYPE_HARDLINK :
    1978 +               case YAFFS_OBJECT_TYPE_SPECIAL :
    1979 +               default:
    1980 +                       /* TODO? */
    1981 +                       break;
    1982 +               }
    1983 +
     1257+       T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_commit_write returning %d\n",nWritten));
     1258+       
     1259+       return nWritten;
     1260+
     1261+}
     1262+
     1263+
     1264+
     1265+static void yaffs_FillInodeFromObject(struct inode *inode, yaffs_Object *obj)
     1266+{
     1267+       if (inode && obj)
     1268+       {
    19841269+               inode->i_ino = obj->objectId;
    19851270+               inode->i_mode = obj->yst_mode;
     
    19901275+
    19911276+               inode->i_rdev = old_decode_dev(obj->yst_rdev);
    1992 +               inode->i_atime.tv_sec = (time_t) (obj->yst_atime);
     1277+               inode->i_atime.tv_sec = (time_t)(obj->yst_atime);
    19931278+               inode->i_atime.tv_nsec = 0;
    1994 +               inode->i_mtime.tv_sec = (time_t) obj->yst_mtime;
    1995 +               inode->i_mtime.tv_nsec = 0;
    1996 +               inode->i_ctime.tv_sec = (time_t) obj->yst_ctime;
     1279+               inode->i_mtime.tv_sec = (time_t)obj->yst_mtime;
     1280+               inode->i_mtime.tv_nsec =0;
     1281+               inode->i_ctime.tv_sec = (time_t)obj->yst_ctime;
    19971282+               inode->i_ctime.tv_nsec = 0;
    19981283+#else
     
    20061291+
    20071292+               inode->i_nlink = yaffs_GetObjectLinkCount(obj);
    2008 +
    2009 +               T(YAFFS_TRACE_OS,
    2010 +                 (KERN_DEBUG
    2011 +                  "yaffs_FillInode mode %x uid %d gid %d size %d count %d\n",
    2012 +                  inode->i_mode, inode->i_uid, inode->i_gid,
    2013 +                  (int)inode->i_size, atomic_read(&inode->i_count)));
    2014 +
    2015 +               switch (obj->yst_mode & S_IFMT) {
    2016 +               default:        /* fifo, device or socket */
     1293+               
     1294+               T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_FillInode mode %x uid %d gid %d size %d count %d\n",
     1295+                               inode->i_mode, inode->i_uid, inode->i_gid, (int)inode->i_size, atomic_read(&inode->i_count)));
     1296+               
     1297+               switch (obj->yst_mode & S_IFMT)
     1298+               {
     1299+                       default: // fifo, device or socket
    20171300+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
    2018 +                       init_special_inode(inode, obj->yst_mode,
    2019 +                                          old_decode_dev(obj->yst_rdev));
     1301+                               init_special_inode(inode, obj->yst_mode,old_decode_dev(obj->yst_rdev));
    20201302+#else
    2021 +                       init_special_inode(inode, obj->yst_mode,
    2022 +                                          (dev_t) (obj->yst_rdev));
    2023 +#endif
    2024 +                       break;
    2025 +               case S_IFREG:   /* file */
    2026 +                       inode->i_op = &yaffs_file_inode_operations;
    2027 +                       inode->i_fop = &yaffs_file_operations;
    2028 +                       inode->i_mapping->a_ops =
    2029 +                           &yaffs_file_address_operations;
    2030 +                       break;
    2031 +               case S_IFDIR:   /* directory */
    2032 +                       inode->i_op = &yaffs_dir_inode_operations;
    2033 +                       inode->i_fop = &yaffs_dir_operations;
    2034 +                       break;
    2035 +               case S_IFLNK:   /* symlink */
    2036 +                       inode->i_op = &yaffs_symlink_inode_operations;
    2037 +                       break;
    2038 +               }
    2039 +
     1303+                                 init_special_inode(inode, obj->yst_mode,(dev_t)(obj->yst_rdev));
     1304+#endif                         
     1305+                        break;
     1306+                       case S_IFREG:   // file         
     1307+                               inode->i_op = &yaffs_file_inode_operations;
     1308+                               inode->i_fop = &yaffs_file_operations;
     1309+                               inode->i_mapping->a_ops = &yaffs_file_address_operations;
     1310+                               break;
     1311+                       case S_IFDIR:   // directory
     1312+                               inode->i_op = &yaffs_dir_inode_operations;
     1313+                               inode->i_fop = &yaffs_dir_operations;
     1314+                               break;
     1315+                       case S_IFLNK:   // symlink
     1316+                               inode->i_op = &yaffs_symlink_inode_operations;
     1317+                               break;
     1318+               }
     1319+               
     1320+               
    20401321+               inode->u.generic_ip = obj;
    20411322+               obj->myInode = inode;
    2042 +
    2043 +       } else {
    2044 +               T(YAFFS_TRACE_OS,
    2045 +                 (KERN_DEBUG "yaffs_FileInode invalid parameters\n"));
    2046 +       }
    2047 +
    2048 +}
    2049 +
    2050 +struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev,
    2051 +                             yaffs_Object * obj)
    2052 +{
    2053 +       struct inode *inode;
    2054 +
    2055 +       if (!sb) {
    2056 +               T(YAFFS_TRACE_OS,
    2057 +                 (KERN_DEBUG "yaffs_get_inode for NULL super_block!!\n"));
    2058 +               return NULL;
    2059 +
    2060 +       }
    2061 +
    2062 +       if (!obj) {
    2063 +               T(YAFFS_TRACE_OS,
    2064 +                 (KERN_DEBUG "yaffs_get_inode for NULL object!!\n"));
    2065 +               return NULL;
    2066 +
    2067 +       }
    2068 +
    2069 +       T(YAFFS_TRACE_OS,
    2070 +         (KERN_DEBUG "yaffs_get_inode for object %d\n", obj->objectId));
    2071 +
    2072 +       inode = iget(sb, obj->objectId);
    2073 +
    2074 +       /* NB Side effect: iget calls back to yaffs_read_inode(). */
    2075 +       /* iget also increments the inode's i_count */
    2076 +       /* NB You can't be holding grossLock or deadlock will happen! */
    2077 +
     1323+               
     1324+       }
     1325+       else
     1326+       {
     1327+               T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_FileInode invalid parameters\n"));
     1328+       }
     1329+
     1330+}
     1331+
     1332+struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev,yaffs_Object *obj)
     1333+{
     1334+       struct inode * inode;
     1335+       
     1336+       if(!sb)
     1337+       {
     1338+         T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_get_inode for NULL super_block!!\n"));
     1339+         return NULL;
     1340+         
     1341+       }
     1342+       
     1343+       if(!obj)
     1344+       {
     1345+         T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_get_inode for NULL object!!\n"));
     1346+         return NULL;
     1347+         
     1348+       }
     1349+       
     1350+       T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_get_inode for object %d\n",obj->objectId));
     1351+
     1352+       inode = iget(sb,obj->objectId);
     1353+
     1354+       // NB Side effect: iget calls back to yaffs_read_inode().
     1355+       // iget also increments the inode's i_count
     1356+       
    20781357+       return inode;
    20791358+}
    20801359+
    2081 +static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n,
    2082 +                               loff_t * pos)
     1360+static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n, loff_t *pos)
    20831361+{
    20841362+       yaffs_Object *obj;
    2085 +       int nWritten, ipos;
     1363+       int nWritten,ipos;
    20861364+       struct inode *inode;
    20871365+       yaffs_Device *dev;
    2088 +
    2089 +       obj = yaffs_DentryToObject(f->f_dentry);
    2090 +
     1366+       
     1367+       
     1368+       obj  = yaffs_DentryToObject(f->f_dentry);
     1369+       
    20911370+       dev = obj->myDev;
    2092 +
     1371+       
    20931372+       yaffs_GrossLock(dev);
    20941373+
    20951374+       inode = f->f_dentry->d_inode;
    20961375+
    2097 +       if (!S_ISBLK(inode->i_mode) && f->f_flags & O_APPEND) {
     1376+       if(!S_ISBLK(inode->i_mode) && f->f_flags & O_APPEND)
     1377+       {
    20981378+               ipos = inode->i_size;
    2099 +       } else {
     1379+       }
     1380+       else
     1381+       {
    21001382+               ipos = *pos;
    21011383+       }
    2102 +
    2103 +       if (!obj) {
    2104 +               T(YAFFS_TRACE_OS,
    2105 +                 (KERN_DEBUG "yaffs_file_write: hey obj is null!\n"));
    2106 +       } else {
    2107 +               T(YAFFS_TRACE_OS,
    2108 +                 (KERN_DEBUG
    2109 +                  "yaffs_file_write about to write writing %d bytes"
    2110 +                  "to object %d at %d\n",
    2111 +                  n, obj->objectId, ipos));
    2112 +       }
    2113 +
    2114 +       nWritten = yaffs_WriteDataToFile(obj, buf, ipos, n, 0);
    2115 +
    2116 +       T(YAFFS_TRACE_OS,
    2117 +         (KERN_DEBUG "yaffs_file_write writing %d bytes, %d written at %d\n",
    2118 +          n, nWritten, ipos));
    2119 +       if (nWritten > 0) {
     1384+       
     1385+       
     1386+       if(!obj)
     1387+       {
     1388+               T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_file_write: hey obj is null!\n"));
     1389+       }
     1390+       else
     1391+       {
     1392+               T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_file_write about to write writing %d bytes to object %d at %d\n",n,obj->objectId,ipos));
     1393+       }
     1394+
     1395+       nWritten = yaffs_WriteDataToFile(obj,buf,ipos,n,0);
     1396+
     1397+       T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_file_write writing %d bytes, %d written at %d\n",n,nWritten,ipos));
     1398+       if(nWritten > 0)
     1399+       {
    21201400+               ipos += nWritten;
    21211401+               *pos = ipos;
    2122 +               if (ipos > inode->i_size) {
     1402+               if(ipos > inode->i_size)
     1403+               {
    21231404+                       inode->i_size = ipos;
    2124 +                       inode->i_blocks = (ipos + 511) >> 9;
    2125 +
    2126 +                       T(YAFFS_TRACE_OS,
    2127 +                         (KERN_DEBUG
    2128 +                          "yaffs_file_write size updated to %d bytes, "
    2129 +                          "%d blocks\n",
    2130 +                          ipos, (int)(inode->i_blocks)));
    2131 +               }
    2132 +
     1405+                       inode->i_blocks = (ipos + 511)>>9;
     1406+                       
     1407+                       T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_file_write size updated to %d bytes, %d blocks\n",ipos,(int)(inode->i_blocks)));
     1408+               }
     1409+               
    21331410+       }
    21341411+       yaffs_GrossUnlock(dev);
    2135 +       return nWritten == 0 ? -ENOSPC : nWritten;
    2136 +}
     1412+       
     1413+       return nWritten != n ? -ENOSPC : nWritten;
     1414+}
     1415+
     1416+
    21371417+
    21381418+static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir)
     
    21421422+       struct inode *inode = f->f_dentry->d_inode;
    21431423+       unsigned long offset, curoffs;
    2144 +       struct list_head *i;
     1424+       struct list_head *i;   
    21451425+       yaffs_Object *l;
    2146 +
    2147 +       char name[YAFFS_MAX_NAME_LENGTH + 1];
    2148 +
    2149 +       obj = yaffs_DentryToObject(f->f_dentry);
     1426+       
     1427+       char name[YAFFS_MAX_NAME_LENGTH +1];
     1428+               
     1429+       obj =  yaffs_DentryToObject(f->f_dentry);
    21501430+       dev = obj->myDev;
    2151 +
     1431+       
    21521432+       yaffs_GrossLock(dev);
    2153 +
     1433+       
    21541434+       offset = f->f_pos;
    2155 +
    2156 +       T(YAFFS_TRACE_OS, ("yaffs_readdir: starting at %d\n", (int)offset));
    2157 +
    2158 +       if (offset == 0) {
    2159 +               T(YAFFS_TRACE_OS,
    2160 +                 (KERN_DEBUG "yaffs_readdir: entry . ino %d \n",
    2161 +                  (int)inode->i_ino));
    2162 +               if (filldir(dirent, ".", 1, offset, inode->i_ino, DT_DIR)
    2163 +                   < 0) {
     1435+       
     1436+       T(YAFFS_TRACE_OS,("yaffs_readdir: starting at %d\n",(int)offset));
     1437+       
     1438+       if(offset == 0)
     1439+       {
     1440+        T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_readdir: entry . ino %d \n",(int)inode->i_ino));
     1441+               if(filldir(dirent,".",1,offset,inode->i_ino,DT_DIR) < 0)
     1442+               {
    21641443+                       goto out;
    21651444+               }
     
    21671446+               f->f_pos++;
    21681447+       }
    2169 +       if (offset == 1) {
    2170 +               T(YAFFS_TRACE_OS,
    2171 +                 (KERN_DEBUG "yaffs_readdir: entry .. ino %d \n",
    2172 +                  (int)f->f_dentry->d_parent->d_inode->i_ino));
    2173 +               if (filldir
    2174 +                   (dirent, "..", 2, offset,
    2175 +                    f->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {
     1448+       if(offset == 1)
     1449+       {
     1450+               T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_readdir: entry .. ino %d \n",(int)f->f_dentry->d_parent->d_inode->i_ino));
     1451+               if(filldir(dirent,"..",2,offset,f->f_dentry->d_parent->d_inode->i_ino,DT_DIR) < 0)
     1452+               {
    21761453+                       goto out;
    21771454+               }
     
    21791456+               f->f_pos++;
    21801457+       }
    2181 +
     1458+       
    21821459+       curoffs = 1;
    2183 +
    2184 +       /* If the directory has changed since the open or last call to
    2185 +          readdir, rewind to after the 2 canned entries. */
    2186 +
    2187 +       if (f->f_version != inode->i_version) {
    2188 +               offset = 2;
    2189 +               f->f_pos = offset;
    2190 +               f->f_version = inode->i_version;
    2191 +       }
    2192 +
    2193 +       list_for_each(i, &obj->variant.directoryVariant.children) {
     1460+       
     1461+       list_for_each(i,&obj->variant.directoryVariant.children)
     1462+       {
    21941463+               curoffs++;
    2195 +               if (curoffs >= offset) {
    2196 +                       l = list_entry(i, yaffs_Object, siblings);
    2197 +
    2198 +                       yaffs_GetObjectName(l, name,
    2199 +                                           YAFFS_MAX_NAME_LENGTH + 1);
    2200 +                       T(YAFFS_TRACE_OS,
    2201 +                         (KERN_DEBUG "yaffs_readdir: %s inode %d\n", name,
    2202 +                          yaffs_GetObjectInode(l)));
    2203 +
    2204 +                       if (filldir(dirent,
    2205 +                                   name,
    2206 +                                   strlen(name),
    2207 +                                   offset,
    2208 +                                   yaffs_GetObjectInode(l),
    2209 +                                   yaffs_GetObjectType(l))
    2210 +                           < 0) {
     1464+               if(curoffs >= offset)
     1465+               {               
     1466+                       l = list_entry(i, yaffs_Object,siblings);
     1467+                       
     1468+                       yaffs_GetObjectName(l,name,YAFFS_MAX_NAME_LENGTH+1);
     1469+                       T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_readdir: %s inode %d\n",name,yaffs_GetObjectInode(l)));
     1470+                       
     1471+                       if(filldir(dirent,
     1472+                                          name,
     1473+                                          strlen(name),
     1474+                                          offset,
     1475+                                          yaffs_GetObjectInode(l),
     1476+                                          yaffs_GetObjectType(l))
     1477+                                          < 0)
     1478+                       {
    22111479+                               goto up_and_out;
    22121480+                       }
    2213 +
     1481+                       
    22141482+                       offset++;
    2215 +                       f->f_pos++;
    2216 +               }
    2217 +       }
    2218 +
    2219     up_and_out:
    2220     out:
    2221 +
    2222 +       yaffs_GrossUnlock(dev);
    2223 +
     1483+                       f->f_pos++;       
     1484+               }
     1485+       }
     1486+
     1487up_and_out:
     1488out:
     1489+ 
     1490+    yaffs_GrossUnlock(dev);
     1491+   
    22241492+       return 0;
    22251493+}
     1494+
    22261495+
    22271496+/*
     
    22291498+ */
    22301499+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
    2231 +static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,
    2232 +                      dev_t rdev)
     1500+static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
    22331501+#else
    2234 +static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,
    2235 +                      int rdev)
     1502+static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rdev)
    22361503+#endif
    22371504+{
    22381505+       struct inode *inode;
    2239 +
     1506+       
    22401507+       yaffs_Object *obj = NULL;
    22411508+       yaffs_Device *dev;
    2242 +
     1509+       
    22431510+       yaffs_Object *parent = yaffs_InodeToObject(dir);
    2244 +
     1511+       
    22451512+       int error = -ENOSPC;
    22461513+       uid_t uid = current->fsuid;
    22471514+       gid_t gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
    2248 +       
    2249 +       if((dir->i_mode & S_ISGID) && S_ISDIR(mode))
    2250 +               mode |= S_ISGID;
    2251 +
    2252 +       if (parent) {
    2253 +               T(YAFFS_TRACE_OS,
    2254 +                 (KERN_DEBUG "yaffs_mknod: parent object %d type %d\n",
    2255 +                  parent->objectId, parent->variantType));
    2256 +       } else {
    2257 +               T(YAFFS_TRACE_OS,
    2258 +                 (KERN_DEBUG "yaffs_mknod: could not get parent object\n"));
     1515+
     1516+       if(parent)
     1517+       {
     1518+               T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_mknod: parent object %d type %d\n",
     1519+                                        parent->objectId,parent->variantType));
     1520+       }
     1521+       else
     1522+       {
     1523+               T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_mknod: could not get parent object\n"));
    22591524+               return -EPERM;
    22601525+       }
    2261 +
    2262 +       T(YAFFS_TRACE_OS, ("yaffs_mknod: making oject for %s, "
    2263 +                          "mode %x dev %x\n",
    2264 +                          dentry->d_name.name, mode, rdev));
     1526+       
     1527+       T(YAFFS_TRACE_OS,("yaffs_mknod: making oject for %s, mode %x dev %x\n",
     1528+                                       dentry->d_name.name, mode,rdev));
    22651529+
    22661530+       dev = parent->myDev;
    2267 +
     1531+       
    22681532+       yaffs_GrossLock(dev);
    22691533+
    2270 +       switch (mode & S_IFMT) {
    2271 +       default:
    2272 +               /* Special (socket, fifo, device...) */
    2273 +               T(YAFFS_TRACE_OS, (KERN_DEBUG
    2274 +                                  "yaffs_mknod: making special\n"));
     1534+       switch (mode & S_IFMT)
     1535+       {
     1536+               default:
     1537+                       // Special (socket, fifo, device...)
     1538+                       T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_mknod: making special\n"));
    22751539+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
    2276 +               obj =
    2277 +                   yaffs_MknodSpecial(parent, dentry->d_name.name, mode, uid,
    2278 +                                      gid, old_encode_dev(rdev));
     1540+                        obj = yaffs_MknodSpecial(parent,dentry->d_name.name,mode,uid, gid,old_encode_dev(rdev));
    22791541+#else
    2280 +               obj =
    2281 +                   yaffs_MknodSpecial(parent, dentry->d_name.name, mode, uid,
    2282 +                                      gid, rdev);
    2283 +#endif
    2284 +               break;
    2285 +       case S_IFREG:           /* file          */
    2286 +               T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_mknod: making file\n"));
    2287 +               obj =
    2288 +                   yaffs_MknodFile(parent, dentry->d_name.name, mode, uid,
    2289 +                                   gid);
    2290 +               break;
    2291 +       case S_IFDIR:           /* directory */
    2292 +               T(YAFFS_TRACE_OS,
    2293 +                 (KERN_DEBUG "yaffs_mknod: making directory\n"));
    2294 +               obj =
    2295 +                   yaffs_MknodDirectory(parent, dentry->d_name.name, mode,
    2296 +                                        uid, gid);
    2297 +               break;
    2298 +       case S_IFLNK:           /* symlink */
    2299 +               T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_mknod: making file\n"));
    2300 +               obj = NULL;     /* Do we ever get here? */
    2301 +               break;
    2302 +       }
    2303 +       
    2304 +       /* Can not call yaffs_get_inode() with gross lock held */
    2305 +       yaffs_GrossUnlock(dev);
    2306 +
    2307 +       if (obj) {
     1542+                        obj = yaffs_MknodSpecial(parent,dentry->d_name.name,mode,uid, gid,rdev);
     1543+#endif                 
     1544+                break;
     1545+               case S_IFREG:   // file         
     1546+                       T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_mknod: making file\n"));
     1547+                       obj = yaffs_MknodFile(parent,dentry->d_name.name,mode,uid, gid);
     1548+                       break;
     1549+               case S_IFDIR:   // directory
     1550+                       T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_mknod: making directory\n"));
     1551+                       obj = yaffs_MknodDirectory(parent,dentry->d_name.name,mode,uid, gid);
     1552+                       break;
     1553+               case S_IFLNK:   // symlink
     1554+                       T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_mknod: making file\n"));
     1555+                       obj = NULL; // Do we ever get here?
     1556+                       break;
     1557+       }
     1558+       
     1559+       if(obj)
     1560+       {
    23081561+               inode = yaffs_get_inode(dir->i_sb, mode, rdev, obj);
    23091562+               d_instantiate(dentry, inode);
    2310 +               T(YAFFS_TRACE_OS,
    2311 +                 (KERN_DEBUG "yaffs_mknod created object %d count = %d\n",
    2312 +                  obj->objectId, atomic_read(&inode->i_count)));
     1563+               T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_mknod created object %d count = %d\n",obj->objectId,atomic_read(&inode->i_count)));
    23131564+               error = 0;
    2314 +       } else {
    2315 +               T(YAFFS_TRACE_OS,
    2316 +                 (KERN_DEBUG "yaffs_mknod failed making object\n"));
     1565+       }
     1566+       else
     1567+       {
     1568+               T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_mknod failed making object\n"));
    23171569+               error = -ENOMEM;
    23181570+       }
    23191571+
     1572+       yaffs_GrossUnlock(dev);
     1573+
    23201574+       return error;
    23211575+}
    23221576+
    2323 +static int yaffs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
     1577+static int yaffs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
    23241578+{
    23251579+       int retVal;
    2326 +       T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_mkdir\n"));
    2327 +       retVal = yaffs_mknod(dir, dentry, mode | S_IFDIR, 0);
     1580+       T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_mkdir\n"));
     1581+       retVal =  yaffs_mknod(dir, dentry, mode | S_IFDIR, 0);
    23281582+#if 0
    2329 +       /* attempt to fix dir bug - didn't work */
    2330 +       if (!retVal) {
     1583+ // attempt to fix dir bug - didn't work
     1584+       if(!retVal)
     1585+       {
    23311586+               dget(dentry);
    23321587+       }
     
    23361591+
    23371592+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
    2338 +static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode,
    2339 +                       struct nameidata *n)
     1593+static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *n)
    23401594+#else
    23411595+static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode)
    23421596+#endif
    23431597+{
    2344 +       T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_create\n"));
     1598+       T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_create\n"));
    23451599+       return yaffs_mknod(dir, dentry, mode | S_IFREG, 0);
    23461600+}
    23471601+
    2348 +static int yaffs_unlink(struct inode *dir, struct dentry *dentry)
     1602+
     1603+static int yaffs_unlink(struct inode * dir, struct dentry *dentry)
    23491604+{
    23501605+       int retVal;
    2351 +
     1606+       
    23521607+       yaffs_Device *dev;
    2353 +
    2354 +       T(YAFFS_TRACE_OS,
    2355 +         (KERN_DEBUG "yaffs_unlink %d:%s\n", (int)(dir->i_ino),
    2356 +          dentry->d_name.name));
    2357 +
     1608+       
     1609+       
     1610+       T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_unlink %d:%s\n",(int)(dir->i_ino),dentry->d_name.name));
     1611+       
    23581612+       dev = yaffs_InodeToObject(dir)->myDev;
    2359 +
     1613+       
    23601614+       yaffs_GrossLock(dev);
    2361 +
    2362 +       retVal = yaffs_Unlink(yaffs_InodeToObject(dir), dentry->d_name.name);
    2363 +
    2364 +       if (retVal == YAFFS_OK) {
     1615+       
     1616+       
     1617+       retVal = yaffs_Unlink(yaffs_InodeToObject(dir),dentry->d_name.name);
     1618+       
     1619+       
     1620+       yaffs_GrossUnlock(dev);
     1621+       
     1622+       if( retVal == YAFFS_OK)
     1623+       {
    23651624+               dentry->d_inode->i_nlink--;
    2366 +               dir->i_version++;
    2367 +               yaffs_GrossUnlock(dev);
    23681625+               mark_inode_dirty(dentry->d_inode);
    23691626+               return 0;
    23701627+       }
    2371 +       yaffs_GrossUnlock(dev);
    2372 +       return -ENOTEMPTY;
    2373 +}
     1628+       else
     1629+       {
     1630+               return -ENOTEMPTY;
     1631+       }
     1632+}
     1633+
    23741634+
    23751635+/*
    23761636+ * Create a link...
    23771637+ */
    2378 +static int yaffs_link(struct dentry *old_dentry, struct inode *dir,
    2379 +                     struct dentry *dentry)
     1638+static int yaffs_link(struct dentry *old_dentry, struct inode * dir, struct dentry * dentry)
    23801639+{
    23811640+       struct inode *inode = old_dentry->d_inode;
    23821641+       yaffs_Object *obj = NULL;
    2383 +       yaffs_Object *link = NULL;
     1642+       yaffs_Object *link=NULL;
    23841643+       yaffs_Device *dev;
    2385 +
    2386 +       T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_link\n"));
    2387 +
     1644+       
     1645+       T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_link\n"));
     1646+       
    23881647+       obj = yaffs_InodeToObject(inode);
    23891648+       dev = obj->myDev;
    2390 +
     1649+       
    23911650+       yaffs_GrossLock(dev);
    23921651+
    2393 +       if (!S_ISDIR(inode->i_mode))    /* Don't link directories */
    2394 +       {
    2395 +               link =
    2396 +                   yaffs_Link(yaffs_InodeToObject(dir), dentry->d_name.name,
    2397 +                              obj);
    2398 +       }
    2399 +
    2400 +       if (link) {
    2401 +               old_dentry->d_inode->i_nlink = yaffs_GetObjectLinkCount(obj);
     1652+       if (!S_ISDIR(inode->i_mode))    // Don't link directories
     1653+       {
     1654+               link = yaffs_Link(yaffs_InodeToObject(dir),dentry->d_name.name,obj);
     1655+       }
     1656+       
     1657+
     1658+       if(link)
     1659+       {
     1660+               old_dentry->d_inode->i_nlink =  yaffs_GetObjectLinkCount(obj);
    24021661+               d_instantiate(dentry, old_dentry->d_inode);
    24031662+               atomic_inc(&old_dentry->d_inode->i_count);
    2404 +               T(YAFFS_TRACE_OS,
    2405 +                 (KERN_DEBUG "yaffs_link link count %d i_count %d\n",
    2406 +                  old_dentry->d_inode->i_nlink,
    2407 +                  atomic_read(&old_dentry->d_inode->i_count)));
    2408 +
    2409 +       }
    2410 +
     1663+               T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_link link count %d i_count %d\n",   
     1664+                       old_dentry->d_inode->i_nlink,atomic_read(&old_dentry->d_inode->i_count)));
     1665+       
     1666+       }
     1667+       
    24111668+       yaffs_GrossUnlock(dev);
    2412 +
    2413 +       if (link) {
    2414 +
     1669+       
     1670+
     1671+       if(link)
     1672+       {
     1673+       
    24151674+               return 0;
    24161675+       }
    2417 +
    2418 +       return -EPERM;
    2419 +}
    2420 +
    2421 +static int yaffs_symlink(struct inode *dir, struct dentry *dentry,
    2422 +                        const char *symname)
     1676+       
     1677+       
     1678+       return -EPERM;
     1679+}
     1680+
     1681+
     1682+static int yaffs_symlink(struct inode * dir, struct dentry *dentry, const char * symname)
    24231683+{
    24241684+       yaffs_Object *obj;
     
    24261686+       uid_t uid = current->fsuid;
    24271687+       gid_t gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
    2428 +
    2429 +       T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_symlink\n"));
    2430 +
     1688+       
     1689+       T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_symlink\n"));
     1690+       
    24311691+       dev = yaffs_InodeToObject(dir)->myDev;
    24321692+       yaffs_GrossLock(dev);
    2433 +       obj = yaffs_MknodSymLink(yaffs_InodeToObject(dir), dentry->d_name.name,
    2434 +                                S_IFLNK | S_IRWXUGO, uid, gid, symname);
     1693+       obj = yaffs_MknodSymLink(yaffs_InodeToObject(dir), dentry->d_name.name,
     1694+                                                        S_IFLNK | S_IRWXUGO, uid, gid,
     1695+                                                        symname);
    24351696+       yaffs_GrossUnlock(dev);
    24361697+
    2437 +       if (obj) {
    2438 +
    2439 +               struct inode *inode;
    2440 +
     1698+       if(obj)
     1699+       {
     1700+
     1701+               struct inode* inode;
     1702+       
    24411703+               inode = yaffs_get_inode(dir->i_sb, obj->yst_mode, 0, obj);
    24421704+               d_instantiate(dentry, inode);
    2443 +               T(YAFFS_TRACE_OS, (KERN_DEBUG "symlink created OK\n"));
     1705+               T(YAFFS_TRACE_OS,(KERN_DEBUG"symlink created OK\n"));
    24441706+               return 0;
    2445 +       } else {
    2446 +               T(YAFFS_TRACE_OS, (KERN_DEBUG "symlink not created\n"));
    2447 +
    2448 +       }
    2449 +
     1707+       }
     1708+       else
     1709+       {
     1710+               T(YAFFS_TRACE_OS,(KERN_DEBUG"symlink not created\n"));
     1711+
     1712+       }
     1713+       
    24501714+       return -ENOMEM;
    24511715+}
    24521716+
    2453 +static int yaffs_sync_object(struct file *file, struct dentry *dentry,
    2454 +                            int datasync)
     1717+static int yaffs_sync_object(struct file * file, struct dentry *dentry, int datasync)
    24551718+{
    24561719+
    24571720+       yaffs_Object *obj;
    24581721+       yaffs_Device *dev;
    2459 +
     1722+       
    24601723+       obj = yaffs_DentryToObject(dentry);
    24611724+
    24621725+       dev = obj->myDev;
    2463 +
    2464 +       T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_sync_object\n"));
     1726+       
     1727+       T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_sync_object\n"));
    24651728+       yaffs_GrossLock(dev);
    2466 +       yaffs_FlushFile(obj, 1);
     1729+       yaffs_FlushFile(obj,1);
    24671730+       yaffs_GrossUnlock(dev);
    24681731+       return 0;
     
    24741737+ * NB: POSIX says you can rename an object over an old object of the same name
    24751738+ */
    2476 +static int yaffs_rename(struct inode *old_dir, struct dentry *old_dentry,
    2477 +                       struct inode *new_dir, struct dentry *new_dentry)
     1739+static int yaffs_rename(struct inode * old_dir, struct dentry *old_dentry, struct inode * new_dir,struct dentry *new_dentry)
    24781740+{
    24791741+       yaffs_Device *dev;
    24801742+       int retVal = YAFFS_FAIL;
     1743+       int removed = 0;
    24811744+       yaffs_Object *target;
    2482 +
    2483 +        T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_rename\n"));
     1745+       
    24841746+       dev = yaffs_InodeToObject(old_dir)->myDev;
    24851747+
    24861748+       yaffs_GrossLock(dev);
    2487 +
    2488 +       /* Check if the target is an existing directory that is not empty. */
    2489 +       target =
    2490 +           yaffs_FindObjectByName(yaffs_InodeToObject(new_dir),
    2491 +                                  new_dentry->d_name.name);
    2492 +       
    2493 +       
    2494 +
    2495 +       if (target &&
    2496 +           target->variantType == YAFFS_OBJECT_TYPE_DIRECTORY &&
    2497 +           !list_empty(&target->variant.directoryVariant.children)) {
    2498 +           
    2499 +               T(YAFFS_TRACE_OS, (KERN_DEBUG "target is non-empty dir\n"));
    2500 +
     1749+       
     1750+       // Check if the target is an existing directory that is not empty.
     1751+       target = yaffs_FindObjectByName(yaffs_InodeToObject(new_dir),new_dentry->d_name.name);
     1752+       
     1753+       if(target &&
     1754+          target->variantType == YAFFS_OBJECT_TYPE_DIRECTORY &&
     1755+          !list_empty(&target->variant.directoryVariant.children))
     1756+       {
    25011757+               retVal = YAFFS_FAIL;
    2502 +       } else {
    2503 +
    2504 +               /* Now does unlinking internally using shadowing mechanism */
    2505 +               T(YAFFS_TRACE_OS, (KERN_DEBUG "calling yaffs_RenameObject\n"));
    2506 +               
    2507 +               retVal =
    2508 +                   yaffs_RenameObject(yaffs_InodeToObject(old_dir),
    2509 +                                      old_dentry->d_name.name,
    2510 +                                      yaffs_InodeToObject(new_dir),
    2511 +                                      new_dentry->d_name.name);
    2512 +
     1758+       }
     1759+       else
     1760+       {
     1761+         
     1762+               // Unlink the target if it exists
     1763+               removed = yaffs_Unlink(yaffs_InodeToObject(new_dir),new_dentry->d_name.name);
     1764+
     1765+       
     1766+               retVal =  yaffs_RenameObject(yaffs_InodeToObject(old_dir),old_dentry->d_name.name,
     1767+                                                                       yaffs_InodeToObject(new_dir),new_dentry->d_name.name);
     1768+                                                                       
    25131769+       }
    25141770+       yaffs_GrossUnlock(dev);
    2515 +
    2516 +       if (retVal == YAFFS_OK) {
    2517 +               if(target) {
     1771+       
     1772+       if(retVal == YAFFS_OK)
     1773+       {
     1774+               if(removed == YAFFS_OK)
     1775+               {
    25181776+                       new_dentry->d_inode->i_nlink--;
    25191777+                       mark_inode_dirty(new_dentry->d_inode);
    25201778+               }
    2521 +
     1779+               
    25221780+               return 0;
    2523 +       } else {
     1781+       }
     1782+       else
     1783+       {
    25241784+               return -ENOTEMPTY;
    25251785+       }
     1786+       
    25261787+
    25271788+}
     
    25321793+       int error;
    25331794+       yaffs_Device *dev;
    2534 +
    2535 +       T(YAFFS_TRACE_OS,
    2536 +         (KERN_DEBUG "yaffs_setattr of object %d\n",
    2537 +          yaffs_InodeToObject(inode)->objectId));
    2538 +
    2539 +       if ((error = inode_change_ok(inode, attr)) == 0) {
    2540 +
     1795+       
     1796+       T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_setattr of object %d\n",yaffs_InodeToObject(inode)->objectId));
     1797+       
     1798+       if((error = inode_change_ok(inode,attr)) == 0)
     1799+       {
     1800+       
    25411801+               dev = yaffs_InodeToObject(inode)->myDev;
    25421802+               yaffs_GrossLock(dev);
    2543 +               if (yaffs_SetAttributes(yaffs_InodeToObject(inode), attr) ==
    2544 +                   YAFFS_OK) {
     1803+               if(yaffs_SetAttributes(yaffs_InodeToObject(inode),attr) == YAFFS_OK)
     1804+               {
    25451805+                       error = 0;
    2546 +               } else {
     1806+               }
     1807+               else
     1808+               {
    25471809+                       error = -EPERM;
    25481810+               }
    25491811+               yaffs_GrossUnlock(dev);
    25501812+               if (!error)
    2551 +                       error = inode_setattr(inode, attr);
     1813+                       error = inode_setattr(inode,attr);
    25521814+       }
    25531815+       return error;
    25541816+}
    25551817+
    2556 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
    25571818+static int yaffs_statfs(struct dentry *dentry, struct kstatfs *buf)
    25581819+{
     1820+
     1821+       
    25591822+       yaffs_Device *dev = yaffs_DentryToObject(dentry)->myDev;
    25601823+       struct super_block *sb = dentry->d_sb;
    2561 +#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
    2562 +static int yaffs_statfs(struct super_block *sb, struct kstatfs *buf)
    2563 +{
    2564 +       yaffs_Device *dev = yaffs_SuperToDevice(sb);
    2565 +#else
    2566 +static int yaffs_statfs(struct super_block *sb, struct statfs *buf)
    2567 +{
    2568 +       yaffs_Device *dev = yaffs_SuperToDevice(sb);
    2569 +#endif
    2570 +
    2571 +       T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_statfs\n"));
     1824+       T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_statfs\n"));
    25721825+
    25731826+       yaffs_GrossLock(dev);
    2574 +
     1827+       
     1828+       
    25751829+       buf->f_type = YAFFS_MAGIC;
    25761830+       buf->f_bsize = sb->s_blocksize;
    25771831+       buf->f_namelen = 255;
    2578 +       if (sb->s_blocksize > dev->nDataBytesPerChunk) {
    2579 +
    2580 +               buf->f_blocks =
    2581 +                   (dev->endBlock - dev->startBlock +
    2582 +                    1) * dev->nChunksPerBlock / (sb->s_blocksize /
    2583 +                                                 dev->nDataBytesPerChunk);
    2584 +               buf->f_bfree =
    2585 +                   yaffs_GetNumberOfFreeChunks(dev) / (sb->s_blocksize /
    2586 +                                                       dev->nDataBytesPerChunk);
    2587 +       } else {
    2588 +
    2589 +               buf->f_blocks =
    2590 +                   (dev->endBlock - dev->startBlock +
    2591 +                    1) * dev->nChunksPerBlock * (dev->nDataBytesPerChunk /
    2592 +                                                 sb->s_blocksize);
    2593 +               buf->f_bfree =
    2594 +                   yaffs_GetNumberOfFreeChunks(dev) * (dev->nDataBytesPerChunk /
    2595 +                                                       sb->s_blocksize);
     1832+       if(sb->s_blocksize > dev->nBytesPerChunk)
     1833+       {
     1834+               
     1835+               buf->f_blocks = (dev->endBlock - dev->startBlock + 1) * dev->nChunksPerBlock/
     1836+                                               (sb->s_blocksize/dev->nBytesPerChunk);
     1837+               buf->f_bfree = yaffs_GetNumberOfFreeChunks(dev)/
     1838+                                               (sb->s_blocksize/dev->nBytesPerChunk);
     1839+       }
     1840+       else
     1841+       {
     1842+               
     1843+               buf->f_blocks = (dev->endBlock - dev->startBlock + 1) * dev->nChunksPerBlock *
     1844+                                               (dev->nBytesPerChunk/sb->s_blocksize);
     1845+               buf->f_bfree = yaffs_GetNumberOfFreeChunks(dev) *
     1846+                                               (dev->nBytesPerChunk/sb->s_blocksize);
    25961847+       }
    25971848+       buf->f_files = 0;
    25981849+       buf->f_ffree = 0;
    2599 +       buf->f_bavail = buf->f_bfree;
    2600 +
     1850+       buf->f_bavail =  buf->f_bfree;
     1851+       
    26011852+       yaffs_GrossUnlock(dev);
    26021853+       return 0;
    26031854+}
    26041855+
    2605 +
    2606 +
    2607 +static int yaffs_do_sync_fs(struct super_block *sb)
    2608 +{
    2609 +
     1856+static void yaffs_read_inode (struct inode *inode)
     1857+{
     1858+       // NB This is called as a side effect of other functions and
     1859+       // thus gross locking should always be in place already.
     1860+       
     1861+       yaffs_Object *obj ;
     1862+       yaffs_Device *dev = yaffs_SuperToDevice(inode->i_sb);
     1863+       
     1864+       T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_read_inode for %d\n",(int)inode->i_ino));
     1865+
     1866+       obj  = yaffs_FindObjectByNumber(dev,inode->i_ino);
     1867+       
     1868+       yaffs_FillInodeFromObject(inode,obj);
     1869+
     1870+}
     1871+
     1872+static LIST_HEAD(yaffs_dev_list);
     1873+
     1874+static void yaffs_put_super(struct super_block *sb)
     1875+{
    26101876+       yaffs_Device *dev = yaffs_SuperToDevice(sb);
    2611 +       T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_do_sync_fs\n"));
    2612 +
    2613 +       if(sb->s_dirt) {
    2614 +               yaffs_GrossLock(dev);
    2615 +
    2616 +               if(dev)
    2617 +                       yaffs_CheckpointSave(dev);
    2618 +               
    2619 +               yaffs_GrossUnlock(dev);
    2620 +
    2621 +               sb->s_dirt = 0;
    2622 +       }
    2623 +       return 0;
    2624 +}
    2625 +
    2626 +
    2627 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
    2628 +static void yaffs_write_super(struct super_block *sb)
    2629 +#else
    2630 +static int yaffs_write_super(struct super_block *sb)
    2631 +#endif
    2632 +{
    2633 +
    2634 +       T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_write_super\n"));
    2635 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18))
    2636 +       return 0; /* yaffs_do_sync_fs(sb);*/
    2637 +#endif
    2638 +}
    2639 +
    2640 +
    2641 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
    2642 +static int yaffs_sync_fs(struct super_block *sb, int wait)
    2643 +#else
    2644 +static int yaffs_sync_fs(struct super_block *sb)
    2645 +#endif
    2646 +{
    2647 +
    2648 +       T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_sync_fs\n"));
    2649 +       
    2650 +       return 0; /* yaffs_do_sync_fs(sb);*/
    2651 +       
    2652 +}
    2653 +
    2654 +
    2655 +static void yaffs_read_inode(struct inode *inode)
    2656 +{
    2657 +       /* NB This is called as a side effect of other functions, but
    2658 +        * we had to release the lock to prevent deadlocks, so
    2659 +        * need to lock again.
    2660 +        */
    2661 +
    2662 +       yaffs_Object *obj;
    2663 +       yaffs_Device *dev = yaffs_SuperToDevice(inode->i_sb);
    2664 +
    2665 +       T(YAFFS_TRACE_OS,
    2666 +         (KERN_DEBUG "yaffs_read_inode for %d\n", (int)inode->i_ino));
    2667 +
     1877+       
    26681878+       yaffs_GrossLock(dev);
    2669 +       
    2670 +       obj = yaffs_FindObjectByNumber(dev, inode->i_ino);
    2671 +
    2672 +       yaffs_FillInodeFromObject(inode, obj);
    2673 +
    2674 +       yaffs_GrossUnlock(dev);
    2675 +}
    2676 +
    2677 +static LIST_HEAD(yaffs_dev_list);
    2678 +
    2679 +static void yaffs_put_super(struct super_block *sb)
    2680 +{
    2681 +       yaffs_Device *dev = yaffs_SuperToDevice(sb);
    2682 +
    2683 +       T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_put_super\n"));
    2684 +
    2685 +       yaffs_GrossLock(dev);
    2686 +       
    2687 +       yaffs_FlushEntireDeviceCache(dev);
    2688 +       
    2689 +       if (dev->putSuperFunc) {
    2690 +               dev->putSuperFunc(sb);
    2691 +       }
    2692 +       
    2693 +       yaffs_CheckpointSave(dev);
     1879+       if(dev->putSuperFunc)
     1880+       {
     1881+                dev->putSuperFunc(sb);
     1882+       }
    26941883+       yaffs_Deinitialise(dev);
    2695 +       
    26961884+       yaffs_GrossUnlock(dev);
    26971885+
    26981886+       /* we assume this is protected by lock_kernel() in mount/umount */
    26991887+       list_del(&dev->devList);
    2700 +       
    2701 +       if(dev->spareBuffer){
    2702 +               YFREE(dev->spareBuffer);
    2703 +               dev->spareBuffer = NULL;
    2704 +       }
    27051888+
    27061889+       kfree(dev);
     
    27081891+
    27091892+
    2710 +static void yaffs_MTDPutSuper(struct super_block *sb)
    2711 +{
    2712 +
     1893+#ifdef CONFIG_YAFFS_YAFFS1
     1894+
     1895+static void  yaffs_MTDPutSuper(struct super_block *sb)
     1896+{
     1897+       
    27131898+       struct mtd_info *mtd = yaffs_SuperToDevice(sb)->genericDevice;
    2714 +
    2715 +       if (mtd->sync) {
     1899+       
     1900+       if(mtd->sync)
     1901+       {
    27161902+               mtd->sync(mtd);
    27171903+       }
    2718 +
     1904+       
    27191905+       put_mtd_device(mtd);
    27201906+}
    27211907+
    2722 +
    2723 +static void yaffs_MarkSuperBlockDirty(void *vsb)
    2724 +{
    2725 +       struct super_block *sb = (struct super_block *)vsb;
    2726 +       
    2727 +       T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_MarkSuperBlockDirty() sb = %p\n",sb));
    2728 +//     if(sb)
    2729 +//             sb->s_dirt = 1;
    2730 +}
    2731 +
    2732 +static struct super_block *yaffs_internal_read_super(int yaffsVersion,
    2733 +                                                    struct super_block *sb,
    2734 +                                                    void *data, int silent)
     1908+#endif
     1909+
     1910+
     1911+static struct super_block *yaffs_internal_read_super(int yaffsVersion, struct super_block * sb, void * data, int silent)
    27351912+{
    27361913+       int nBlocks;
    2737 +       struct inode *inode = NULL;
    2738 +       struct dentry *root;
     1914+       struct inode * inode = NULL;
     1915+       struct dentry * root;
    27391916+       yaffs_Device *dev = 0;
    2740 +       char devname_buf[BDEVNAME_SIZE + 1];
     1917+       char devname_buf[BDEVNAME_SIZE+1];
    27411918+       struct mtd_info *mtd;
    27421919+       int err;
    2743 +
     1920+       
    27441921+       sb->s_magic = YAFFS_MAGIC;
    27451922+       sb->s_op = &yaffs_super_ops;
    2746 +
    2747 +       if (!sb)
    2748 +               printk(KERN_INFO "yaffs: sb is NULL\n");
    2749 +       else if (!sb->s_dev)
    2750 +               printk(KERN_INFO "yaffs: sb->s_dev is NULL\n");
    2751 +       else if (!yaffs_devname(sb, devname_buf))
    2752 +               printk(KERN_INFO "yaffs: devname is NULL\n");
     1923+       
     1924+       if(!sb)
     1925+               printk(KERN_INFO"yaffs: sb is NULL\n");
     1926+       else if(!sb->s_dev)
     1927+               printk(KERN_INFO"yaffs: sb->s_dev is NULL\n");
     1928+       else if(!yaffs_devname(sb, devname_buf))
     1929+               printk(KERN_INFO"yaffs: devname is NULL\n");
    27531930+       else
    2754 +               printk(KERN_INFO "yaffs: dev is %d name is \"%s\"\n",
    2755 +                      sb->s_dev,
    2756 +                      yaffs_devname(sb, devname_buf));
     1931+               printk(KERN_INFO"yaffs: dev is %d name is \"%s\"\n", sb->s_dev, yaffs_devname(sb, devname_buf));
     1932+
     1933+       
    27571934+
    27581935+       sb->s_blocksize = PAGE_CACHE_SIZE;
    27591936+       sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
    2760 +       T(YAFFS_TRACE_OS, ("yaffs_read_super: Using yaffs%d\n", yaffsVersion));
    2761 +       T(YAFFS_TRACE_OS,
    2762 +         ("yaffs_read_super: block size %d\n", (int)(sb->s_blocksize)));
     1937+       T(YAFFS_TRACE_OS,("yaffs_read_super: Using yaffs%d\n",yaffsVersion));
     1938+       T(YAFFS_TRACE_OS,("yaffs_read_super: block size %d\n", (int)(sb->s_blocksize)));
    27631939+
    27641940+#ifdef CONFIG_YAFFS_DISABLE_WRITE_VERIFY
    2765 +       T(YAFFS_TRACE_OS,
    2766 +         ("yaffs: Write verification disabled. All guarantees "
    2767 +          "null and void\n"));
    2768 +#endif
    2769 +
    2770 +       T(YAFFS_TRACE_ALWAYS, ("yaffs: Attempting MTD mount on %u.%u, "
    2771 +                              "\"%s\"\n",
    2772 +                              MAJOR(sb->s_dev), MINOR(sb->s_dev),
    2773 +                              yaffs_devname(sb, devname_buf)));
    2774 +
    2775 +       /* Check it's an mtd device..... */
    2776 +       if (MAJOR(sb->s_dev) != MTD_BLOCK_MAJOR) {
    2777 +               return NULL;    /* This isn't an mtd device */
    2778 +       }
    2779 +       /* Get the device */
     1941+       T(YAFFS_TRACE_OS,("yaffs: Write verification disabled. All guarantees null and void\n"));
     1942+#endif
     1943+
     1944+
     1945+       T(YAFFS_TRACE_ALWAYS,("yaffs: Attempting MTD mount on %u.%u, \"%s\"\n",
     1946+        MAJOR(sb->s_dev),MINOR(sb->s_dev), yaffs_devname(sb, devname_buf)));
     1947+               
     1948+       // Check it's an mtd device.....
     1949+       if(MAJOR(sb->s_dev) != MTD_BLOCK_MAJOR)
     1950+       {
     1951+               return NULL; // This isn't an mtd device
     1952+       }
     1953+       
     1954+       // Get the device
    27801955+       mtd = get_mtd_device(NULL, MINOR(sb->s_dev));
    2781 +       if (!mtd) {
    2782 +               T(YAFFS_TRACE_ALWAYS,
    2783 +                 ("yaffs: MTD device #%u doesn't appear to exist\n",
    2784 +                  MINOR(sb->s_dev)));
     1956+       if (!mtd)
     1957+       {
     1958+               T(YAFFS_TRACE_ALWAYS,("yaffs: MTD device #%u doesn't appear to exist\n", MINOR(sb->s_dev)));
    27851959+               return NULL;
    27861960+       }
    2787 +       /* Check it's NAND */
    2788 +       if (mtd->type != MTD_NANDFLASH) {
    2789 +               T(YAFFS_TRACE_ALWAYS,
    2790 +                 ("yaffs: MTD device is not NAND it's type %d\n", mtd->type));
     1961+       
     1962+       // Check it's NAND
     1963+       if(mtd->type != MTD_NANDFLASH)
     1964+       {
     1965+               T(YAFFS_TRACE_ALWAYS,("yaffs: MTD device is not NAND it's type %d\n", mtd->type));
    27911966+               return NULL;
    27921967+       }
    27931968+
    2794 +       T(YAFFS_TRACE_OS, (" erase %p\n", mtd->erase));
    2795 +       T(YAFFS_TRACE_OS, (" read %p\n", mtd->read));
    2796 +       T(YAFFS_TRACE_OS, (" write %p\n", mtd->write));
    2797 +       T(YAFFS_TRACE_OS, (" readoob %p\n", mtd->read_oob));
    2798 +       T(YAFFS_TRACE_OS, (" writeoob %p\n", mtd->write_oob));
    2799 +       T(YAFFS_TRACE_OS, (" block_isbad %p\n", mtd->block_isbad));
    2800 +       T(YAFFS_TRACE_OS, (" block_markbad %p\n", mtd->block_markbad));
    2801 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
    2802 +       T(YAFFS_TRACE_OS, (" writesize %d\n", mtd->writesize));
     1969+       T(YAFFS_TRACE_OS,(" erase %p\n",mtd->erase));
     1970+       T(YAFFS_TRACE_OS,(" read %p\n",mtd->read));
     1971+       T(YAFFS_TRACE_OS,(" write %p\n",mtd->write));
     1972+       T(YAFFS_TRACE_OS,(" readoob %p\n",mtd->read_oob));
     1973+       T(YAFFS_TRACE_OS,(" writeoob %p\n",mtd->write_oob));
     1974+//     T(YAFFS_TRACE_OS,(" block_isbad %p\n",mtd->block_isbad));
     1975+//     T(YAFFS_TRACE_OS,(" block_markbad %p\n",mtd->block_markbad));
     1976+       T(YAFFS_TRACE_OS,(" writesize %d\n",mtd->writesize));
     1977+       T(YAFFS_TRACE_OS,(" oobsize %d\n",mtd->oobsize));
     1978+       T(YAFFS_TRACE_OS,(" erasesize %d\n",mtd->erasesize));
     1979+       T(YAFFS_TRACE_OS,(" size %d\n",mtd->size));
     1980+
     1981+       if(yaffsVersion == 2)
     1982+       {
     1983+               // Check for version 2 style functions
     1984+               if(!mtd->erase ||
     1985+//                !mtd->block_isbad ||
     1986+//                !mtd->block_markbad ||
     1987+                  !mtd->read  ||
     1988+                  !mtd->write ||
     1989+//                !mtd->write_ecc ||
     1990+//                !mtd->read_ecc ||
     1991+                  !mtd->read_oob ||
     1992+                  !mtd->write_oob )
     1993+               {
     1994+                       T(YAFFS_TRACE_ALWAYS,("yaffs: MTD device does not support required functions\n"));;
     1995+                       return NULL;
     1996+               }
     1997+       
     1998+               if(mtd->writesize < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
     1999+                  mtd->oobsize < YAFFS_MIN_YAFFS2_SPARE_SIZE)
     2000+               {
     2001+                       T(YAFFS_TRACE_ALWAYS,("yaffs: MTD device does not support have the right page sizes\n"));
     2002+                       return NULL;
     2003+               }               }
     2004+       else
     2005+       {
     2006+               // Check for V1 style functions
     2007+               if(!mtd->erase ||
     2008+                  !mtd->read  ||
     2009+                  !mtd->write ||
     2010+//                !mtd->write_ecc ||
     2011+//                !mtd->read_ecc ||
     2012+                  !mtd->read_oob ||
     2013+                  !mtd->write_oob )
     2014+               {
     2015+                       T(YAFFS_TRACE_ALWAYS,("yaffs: MTD device does not support required functions\n"));;
     2016+                       return NULL;
     2017+               }
     2018+       
     2019+               if(mtd->writesize != YAFFS_BYTES_PER_CHUNK ||
     2020+                  mtd->oobsize != YAFFS_BYTES_PER_SPARE)
     2021+               {
     2022+                       T(YAFFS_TRACE_ALWAYS,("yaffs: MTD device does not support have the right page sizes\n"));
     2023+                       return NULL;
     2024+               }
     2025+       }
     2026+         
     2027+
     2028+               // OK, so if we got here, we have an MTD that's NAND and looks
     2029+               // like it has the right capabilities
     2030+               // Set the yaffs_Device up for mtd
     2031+
     2032+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
     2033+       sb->s_fs_info = dev = kmalloc(sizeof(yaffs_Device),GFP_KERNEL);
    28032034+#else
    2804 +       T(YAFFS_TRACE_OS, (" oobblock %d\n", mtd->oobblock));
    2805 +#endif
    2806 +       T(YAFFS_TRACE_OS, (" oobsize %d\n", mtd->oobsize));
    2807 +       T(YAFFS_TRACE_OS, (" erasesize %d\n", mtd->erasesize));
    2808 +       T(YAFFS_TRACE_OS, (" size %d\n", mtd->size));
    2809 +       
    2810 +#ifdef CONFIG_YAFFS_AUTO_YAFFS2
    2811 +
    2812 +       if (yaffsVersion == 1 &&
    2813 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
    2814 +           mtd->writesize >= 2048) {
    2815 +#else
    2816 +           mtd->oobblock >= 2048) {
    2817 +#endif
    2818 +           T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs2\n"));
    2819 +           yaffsVersion = 2;
    2820 +       }       
    2821 +       
    2822 +       /* Added NCB 26/5/2006 for completeness */
    2823 +       if (yaffsVersion == 2 &&
    2824 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
    2825 +           mtd->writesize == 512) {
    2826 +#else
    2827 +           mtd->oobblock == 512) {
    2828 +#endif
    2829 +           T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs1\n"));
    2830 +           yaffsVersion = 1;
    2831 +       }       
    2832 +
    2833 +#endif
    2834 +
    2835 +       if (yaffsVersion == 2) {
    2836 +               /* Check for version 2 style functions */
    2837 +               if (!mtd->erase ||
    2838 +                   !mtd->block_isbad ||
    2839 +                   !mtd->block_markbad ||
    2840 +                   !mtd->read ||
    2841 +                   !mtd->write ||
    2842 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
    2843 +                   !mtd->read_oob || !mtd->write_oob) {
    2844 +#else
    2845 +                   !mtd->write_ecc ||
    2846 +                   !mtd->read_ecc || !mtd->read_oob || !mtd->write_oob) {
    2847 +#endif
    2848 +                       T(YAFFS_TRACE_ALWAYS,
    2849 +                         ("yaffs: MTD device does not support required "
    2850 +                          "functions\n"));;
    2851 +                       return NULL;
    2852 +               }
    2853 +
    2854 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
    2855 +               if (mtd->writesize < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
    2856 +#else
    2857 +               if (mtd->oobblock < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
    2858 +#endif
    2859 +                   mtd->oobsize < YAFFS_MIN_YAFFS2_SPARE_SIZE) {
    2860 +                       T(YAFFS_TRACE_ALWAYS,
    2861 +                         ("yaffs: MTD device does not have the "
    2862 +                          "right page sizes\n"));
    2863 +                       return NULL;
    2864 +               }
    2865 +       } else {
    2866 +               /* Check for V1 style functions */
    2867 +               if (!mtd->erase ||
    2868 +                   !mtd->read ||
    2869 +                   !mtd->write ||
    2870 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
    2871 +                   !mtd->read_oob || !mtd->write_oob) {
    2872 +#else
    2873 +                   !mtd->write_ecc ||
    2874 +                   !mtd->read_ecc || !mtd->read_oob || !mtd->write_oob) {
    2875 +#endif
    2876 +                       T(YAFFS_TRACE_ALWAYS,
    2877 +                         ("yaffs: MTD device does not support required "
    2878 +                          "functions\n"));;
    2879 +                       return NULL;
    2880 +               }
    2881 +
    2882 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
    2883 +               if (mtd->writesize < YAFFS_BYTES_PER_CHUNK ||
    2884 +#else
    2885 +               if (mtd->oobblock < YAFFS_BYTES_PER_CHUNK ||
    2886 +#endif
    2887 +                   mtd->oobsize != YAFFS_BYTES_PER_SPARE) {
    2888 +                       T(YAFFS_TRACE_ALWAYS,
    2889 +                         ("yaffs: MTD device does not support have the "
    2890 +                          "right page sizes\n"));
    2891 +                       return NULL;
    2892 +               }
    2893 +       }
    2894 +
    2895 +       /* OK, so if we got here, we have an MTD that's NAND and looks
    2896 +        * like it has the right capabilities
    2897 +        * Set the yaffs_Device up for mtd
    2898 +        */
    2899 +
    2900 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
    2901 +       sb->s_fs_info = dev = kmalloc(sizeof(yaffs_Device), GFP_KERNEL);
    2902 +#else
    2903 +       sb->u.generic_sbp = dev = kmalloc(sizeof(yaffs_Device), GFP_KERNEL);
    2904 +#endif
    2905 +       if (!dev) {
    2906 +               /* Deep shit could not allocate device structure */
    2907 +               T(YAFFS_TRACE_ALWAYS,
    2908 +                 ("yaffs_read_super: Failed trying to allocate "
    2909 +                  "yaffs_Device. \n"));
     2035+       sb->u.generic_sbp = dev = kmalloc(sizeof(yaffs_Device),GFP_KERNEL);
     2036+#endif
     2037+       if(!dev)
     2038+       {
     2039+               // Deep shit could not allocate device structure
     2040+               T(YAFFS_TRACE_ALWAYS,("yaffs_read_super: Failed trying to allocate yaffs_Device. \n"));
    29102041+               return NULL;
    29112042+       }
    29122043+
    2913 +       memset(dev, 0, sizeof(yaffs_Device));
    2914 +       dev->genericDevice = mtd;
     2044+       memset(dev,0,sizeof(yaffs_Device));
     2045+       dev->genericDevice = mtd; 
    29152046+       dev->name = mtd->name;
    29162047+
    2917 +       /* Set up the memory size parameters.... */
    2918 +
     2048+       // Set up the memory size parameters....
     2049+       
    29192050+       nBlocks = mtd->size / (YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK);
    29202051+       dev->startBlock = 0;
    29212052+       dev->endBlock = nBlocks - 1;
    29222053+       dev->nChunksPerBlock = YAFFS_CHUNKS_PER_BLOCK;
    2923 +       dev->nDataBytesPerChunk = YAFFS_BYTES_PER_CHUNK;
     2054+       dev->nBytesPerChunk = YAFFS_BYTES_PER_CHUNK;
    29242055+       dev->nReservedBlocks = 5;
    2925 +       dev->nShortOpCaches = 10;       /* Enable short op caching */
    2926 +
    2927 +       /* ... and the functions. */
    2928 +       if (yaffsVersion == 2) {
    2929 +               dev->writeChunkWithTagsToNAND =
    2930 +                   nandmtd2_WriteChunkWithTagsToNAND;
    2931 +               dev->readChunkWithTagsFromNAND =
    2932 +                   nandmtd2_ReadChunkWithTagsFromNAND;
     2056+       dev->nShortOpCaches = 10; // Enable short op caching
     2057+       
     2058+
     2059+       // ... and the functions.
     2060+       if(yaffsVersion == 2)
     2061+       {
     2062+               dev->writeChunkWithTagsToNAND = nandmtd2_WriteChunkWithTagsToNAND;
     2063+               dev->readChunkWithTagsFromNAND = nandmtd2_ReadChunkWithTagsFromNAND;
    29332064+               dev->markNANDBlockBad = nandmtd2_MarkNANDBlockBad;
    29342065+               dev->queryNANDBlock = nandmtd2_QueryNANDBlock;
    29352066+               dev->spareBuffer = YMALLOC(mtd->oobsize);
    29362067+               dev->isYaffs2 = 1;
    2937 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
    2938 +               dev->nDataBytesPerChunk = mtd->writesize;
     2068+               dev->nBytesPerChunk = mtd->writesize;
    29392069+               dev->nChunksPerBlock = mtd->erasesize / mtd->writesize;
    2940 +#else
    2941 +               dev->nDataBytesPerChunk = mtd->oobblock;
    2942 +               dev->nChunksPerBlock = mtd->erasesize / mtd->oobblock;
    2943 +#endif
    29442070+               nBlocks = mtd->size / mtd->erasesize;
    2945 +
    2946 +               dev->nCheckpointReservedBlocks = 10;
    29472071+               dev->startBlock = 0;
    29482072+               dev->endBlock = nBlocks - 1;
    2949 +       } else {
     2073+       }
     2074+       else
     2075+       {
    29502076+               dev->writeChunkToNAND = nandmtd_WriteChunkToNAND;
    29512077+               dev->readChunkFromNAND = nandmtd_ReadChunkFromNAND;
    29522078+               dev->isYaffs2 = 0;
    29532079+       }
    2954 +       /* ... and common functions */
     2080+       // ... and common functions
    29552081+       dev->eraseBlockInNAND = nandmtd_EraseBlockInNAND;
    29562082+       dev->initialiseNAND = nandmtd_InitialiseNAND;
    2957 +
     2083+       
    29582084+       dev->putSuperFunc = yaffs_MTDPutSuper;
    29592085+       
    2960 +       dev->superBlock = (void *)sb;
    2961 +       dev->markSuperBlockDirty = yaffs_MarkSuperBlockDirty;
    2962 +       
    2963 +
    29642086+#ifndef CONFIG_YAFFS_DOES_ECC
    29652087+       dev->useNANDECC = 1;
    29662088+#endif
    29672089+
    2968 +#ifdef CONFIG_YAFFS_DISABLE_WIDE_TNODES
    2969 +       dev->wideTnodesDisabled = 1;
    2970 +#endif
    2971 +
    29722090+       /* we assume this is protected by lock_kernel() in mount/umount */
    29732091+       list_add_tail(&dev->devList, &yaffs_dev_list);
    29742092+
    29752093+       init_MUTEX(&dev->grossLock);
    2976 +
     2094+       
     2095+       
    29772096+       yaffs_GrossLock(dev);
    2978 +
     2097+       
    29792098+       err = yaffs_GutsInitialise(dev);
    29802099+
    2981 +       T(YAFFS_TRACE_OS,
    2982 +         ("yaffs_read_super: guts initialised %s\n",
    2983 +          (err == YAFFS_OK) ? "OK" : "FAILED"));
    2984 +       
    2985 +       /* Release lock before yaffs_get_inode() */
     2100+       T(YAFFS_TRACE_OS,("yaffs_read_super: guts initialised %s\n", (err == YAFFS_OK) ? "OK" : "FAILED"));
     2101+
     2102+       // Create root inode
     2103+       if(err == YAFFS_OK)
     2104+         inode = yaffs_get_inode(sb, S_IFDIR | 0755, 0,yaffs_Root(dev));
     2105+
    29862106+       yaffs_GrossUnlock(dev);
    2987 +
    2988 +       /* Create root inode */
    2989 +       if (err == YAFFS_OK)
    2990 +               inode = yaffs_get_inode(sb, S_IFDIR | 0755, 0,
    2991 +                                       yaffs_Root(dev));
    29922107+
    29932108+       if (!inode)
    29942109+               return NULL;
    2995 +
    2996 +       inode->i_op = &yaffs_dir_inode_operations;
    2997 +       inode->i_fop = &yaffs_dir_operations;
    2998 +
    2999 +       T(YAFFS_TRACE_OS, ("yaffs_read_super: got root inode\n"));
     2110+               
     2111+// added NCB
     2112+       inode->i_op = & yaffs_dir_inode_operations;
     2113+       inode->i_fop = & yaffs_dir_operations;
     2114+
     2115+       T(YAFFS_TRACE_OS,("yaffs_read_super: got root inode\n"));
     2116+               
    30002117+
    30012118+       root = d_alloc_root(inode);
    30022119+
    3003 +       T(YAFFS_TRACE_OS, ("yaffs_read_super: d_alloc_root done\n"));
     2120+       T(YAFFS_TRACE_OS,("yaffs_read_super: d_alloc_root done\n"));
    30042121+
    30052122+       if (!root) {
     
    30092126+       sb->s_root = root;
    30102127+
    3011 +       T(YAFFS_TRACE_OS, ("yaffs_read_super: done\n"));
     2128+       T(YAFFS_TRACE_OS,("yaffs_read_super: done\n"));
    30122129+       return sb;
    30132130+}
    30142131+
    30152132+
     2133+
     2134+#ifdef CONFIG_YAFFS_YAFFS1
     2135+
    30162136+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
    3017 +static int yaffs_internal_read_super_mtd(struct super_block *sb, void *data,
    3018 +                                        int silent)
    3019 +{
    3020 +       return yaffs_internal_read_super(1, sb, data, silent) ? 0 : -EINVAL;
    3021 +}
    3022 +
    3023 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
    3024 +static int yaffs_read_super(struct file_system_type *fs,
    3025 +                           int flags, const char *dev_name,
    3026 +                           void *data, struct vfsmount *mnt)
    3027 +{
    3028 +
    3029 +       return get_sb_bdev(fs, flags, dev_name, data,
    3030 +                          yaffs_internal_read_super_mtd, mnt);
    3031 +}
    3032 +#else
    3033 +static struct super_block *yaffs_read_super(struct file_system_type *fs,
    3034 +                                           int flags, const char *dev_name,
    3035 +                                           void *data)
    3036 +{
    3037 +
    3038 +       return get_sb_bdev(fs, flags, dev_name, data,
    3039 +                          yaffs_internal_read_super_mtd);
    3040 +}
    3041 +#endif
     2137+static int yaffs_internal_read_super_mtd(struct super_block * sb, void * data, int silent)
     2138+{
     2139+        return yaffs_internal_read_super(1,sb,data,silent) ? 0 : -1;
     2140+}
     2141+
     2142+static struct super_block *yaffs_read_super(struct file_system_type * fs, int flags, const char *dev_name, void *data, struct vfsmount *mnt)
     2143+{
     2144+
     2145+    return get_sb_bdev(fs, flags, dev_name, data, yaffs_internal_read_super_mtd, mnt);
     2146+}
    30422147+
    30432148+static struct file_system_type yaffs_fs_type = {
    3044 +       .owner = THIS_MODULE,
    3045 +       .name = "yaffs",
    3046 +       .get_sb = yaffs_read_super,
    3047 +       .kill_sb = kill_block_super,
    3048 +       .fs_flags = FS_REQUIRES_DEV,
     2149+       .owner          = THIS_MODULE,
     2150+       .name           = "yaffs",
     2151+       .get_sb         = yaffs_read_super,
     2152+       .kill_sb        = kill_block_super,
     2153+       .fs_flags       = FS_REQUIRES_DEV,
    30492154+};
    30502155+#else
    3051 +static struct super_block *yaffs_read_super(struct super_block *sb, void *data,
    3052 +                                           int silent)
    3053 +{
    3054 +       return yaffs_internal_read_super(1, sb, data, silent);
    3055 +}
    3056 +
    3057 +static DECLARE_FSTYPE(yaffs_fs_type, "yaffs", yaffs_read_super,
    3058 +                     FS_REQUIRES_DEV);
    3059 +#endif
    3060 +
     2156+static struct super_block *yaffs_read_super(struct super_block * sb, void * data, int silent)
     2157+{
     2158+       return yaffs_internal_read_super(1,sb,data,silent);
     2159+}
     2160+
     2161+static DECLARE_FSTYPE(yaffs_fs_type, "yaffs", yaffs_read_super, FS_REQUIRES_DEV);
     2162+#endif
     2163+
     2164+#endif // CONFIG_YAFFS_YAFFS1
    30612165+
    30622166+#ifdef CONFIG_YAFFS_YAFFS2
    30632167+
    30642168+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
    3065 +static int yaffs2_internal_read_super_mtd(struct super_block *sb, void *data,
    3066 +                                         int silent)
    3067 +{
    3068 +       return yaffs_internal_read_super(2, sb, data, silent) ? 0 : -EINVAL;
    3069 +}
    3070 +
    3071 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
    3072 +static int yaffs2_read_super(struct file_system_type *fs,
    3073 +                       int flags, const char *dev_name, void *data,
    3074 +                       struct vfsmount *mnt)
    3075 +{
    3076 +       return get_sb_bdev(fs, flags, dev_name, data,
    3077 +                       yaffs2_internal_read_super_mtd, mnt);
    3078 +}
    3079 +#else
    3080 +static struct super_block *yaffs2_read_super(struct file_system_type *fs,
    3081 +                                            int flags, const char *dev_name,
    3082 +                                            void *data)
    3083 +{
    3084 +
    3085 +       return get_sb_bdev(fs, flags, dev_name, data,
    3086 +                          yaffs2_internal_read_super_mtd);
    3087 +}
    3088 +#endif
     2169+static int yaffs2_internal_read_super_mtd(struct super_block * sb, void * data, int silent)
     2170+{
     2171+        return yaffs_internal_read_super(2,sb,data,silent) ? 0 : -1;
     2172+}
     2173+
     2174+static struct super_block *yaffs2_read_super(struct file_system_type * fs, int flags, const char *dev_name, void *data, struct vfsmount *mnt)
     2175+{
     2176+
     2177+    return get_sb_bdev(fs, flags, dev_name, data, yaffs2_internal_read_super_mtd, mnt);
     2178+}
    30892179+
    30902180+static struct file_system_type yaffs2_fs_type = {
    3091 +       .owner = THIS_MODULE,
    3092 +       .name = "yaffs2",
    3093 +       .get_sb = yaffs2_read_super,
    3094 +       .kill_sb = kill_block_super,
    3095 +       .fs_flags = FS_REQUIRES_DEV,
     2181+       .owner          = THIS_MODULE,
     2182+       .name           = "yaffs2",
     2183+       .get_sb         = yaffs2_read_super,
     2184+       .kill_sb        = kill_block_super,
     2185+       .fs_flags       = FS_REQUIRES_DEV,
    30962186+};
    30972187+#else
    3098 +static struct super_block *yaffs2_read_super(struct super_block *sb,
    3099 +                                            void *data, int silent)
    3100 +{
    3101 +       return yaffs_internal_read_super(2, sb, data, silent);
    3102 +}
    3103 +
    3104 +static DECLARE_FSTYPE(yaffs2_fs_type, "yaffs2", yaffs2_read_super,
    3105 +                     FS_REQUIRES_DEV);
    3106 +#endif
    3107 +
    3108 +#endif                         /* CONFIG_YAFFS_YAFFS2 */
     2188+static struct super_block *yaffs2_read_super(struct super_block * sb, void * data, int silent)
     2189+{
     2190+       return yaffs_internal_read_super(2,sb,data,silent);
     2191+}
     2192+
     2193+static DECLARE_FSTYPE(yaffs2_fs_type, "yaffs2", yaffs2_read_super, FS_REQUIRES_DEV);
     2194+#endif
     2195+
     2196+#endif // CONFIG_YAFFS_YAFFS2
     2197+
     2198+
     2199+
    31092200+
    31102201+static struct proc_dir_entry *my_proc_entry;
    31112202+
    3112 +static char *yaffs_dump_dev(char *buf, yaffs_Device * dev)
    3113 +{
    3114 +       buf += sprintf(buf, "startBlock......... %d\n", dev->startBlock);
    3115 +       buf += sprintf(buf, "endBlock........... %d\n", dev->endBlock);
    3116 +       buf += sprintf(buf, "chunkGroupBits..... %d\n", dev->chunkGroupBits);
    3117 +       buf += sprintf(buf, "chunkGroupSize..... %d\n", dev->chunkGroupSize);
    3118 +       buf += sprintf(buf, "nErasedBlocks...... %d\n", dev->nErasedBlocks);
    3119 +       buf += sprintf(buf, "nTnodesCreated..... %d\n", dev->nTnodesCreated);
    3120 +       buf += sprintf(buf, "nFreeTnodes........ %d\n", dev->nFreeTnodes);
    3121 +       buf += sprintf(buf, "nObjectsCreated.... %d\n", dev->nObjectsCreated);
    3122 +       buf += sprintf(buf, "nFreeObjects....... %d\n", dev->nFreeObjects);
    3123 +       buf += sprintf(buf, "nFreeChunks........ %d\n", dev->nFreeChunks);
    3124 +       buf += sprintf(buf, "nPageWrites........ %d\n", dev->nPageWrites);
    3125 +       buf += sprintf(buf, "nPageReads......... %d\n", dev->nPageReads);
    3126 +       buf += sprintf(buf, "nBlockErasures..... %d\n", dev->nBlockErasures);
    3127 +       buf += sprintf(buf, "nGCCopies.......... %d\n", dev->nGCCopies);
    3128 +       buf +=
    3129 +           sprintf(buf, "garbageCollections. %d\n", dev->garbageCollections);
    3130 +       buf +=
    3131 +           sprintf(buf, "passiveGCs......... %d\n",
    3132 +                   dev->passiveGarbageCollections);
    3133 +       buf += sprintf(buf, "nRetriedWrites..... %d\n", dev->nRetriedWrites);
    3134 +       buf += sprintf(buf, "nRetireBlocks...... %d\n", dev->nRetiredBlocks);
    3135 +       buf += sprintf(buf, "eccFixed........... %d\n", dev->eccFixed);
    3136 +       buf += sprintf(buf, "eccUnfixed......... %d\n", dev->eccUnfixed);
    3137 +       buf += sprintf(buf, "tagsEccFixed....... %d\n", dev->tagsEccFixed);
    3138 +       buf += sprintf(buf, "tagsEccUnfixed..... %d\n", dev->tagsEccUnfixed);
    3139 +       buf += sprintf(buf, "cacheHits.......... %d\n", dev->cacheHits);
    3140 +       buf += sprintf(buf, "nDeletedFiles...... %d\n", dev->nDeletedFiles);
    3141 +       buf += sprintf(buf, "nUnlinkedFiles..... %d\n", dev->nUnlinkedFiles);
    3142 +       buf +=
    3143 +           sprintf(buf, "nBackgroudDeletions %d\n", dev->nBackgroundDeletions);
    3144 +       buf += sprintf(buf, "useNANDECC......... %d\n", dev->useNANDECC);
    3145 +       buf += sprintf(buf, "isYaffs2........... %d\n", dev->isYaffs2);
    3146 +
    3147 +       return buf;
    3148 +}
    3149 +
    3150 +static int yaffs_proc_read(char *page,
    3151 +                          char **start,
    3152 +                          off_t offset, int count, int *eof, void *data)
     2203+static char * yaffs_dump_dev(char *buf,yaffs_Device *dev)
     2204+{
     2205+       buf +=sprintf(buf,"startBlock......... %d\n",dev->startBlock);
     2206+       buf +=sprintf(buf,"endBlock........... %d\n",dev->endBlock);
     2207+       buf +=sprintf(buf,"chunkGroupBits..... %d\n",dev->chunkGroupBits);
     2208+       buf +=sprintf(buf,"chunkGroupSize..... %d\n",dev->chunkGroupSize);
     2209+       buf +=sprintf(buf,"nErasedBlocks...... %d\n",dev->nErasedBlocks);
     2210+       buf +=sprintf(buf,"nTnodesCreated..... %d\n",dev->nTnodesCreated);
     2211+       buf +=sprintf(buf,"nFreeTnodes........ %d\n",dev->nFreeTnodes);
     2212+       buf +=sprintf(buf,"nObjectsCreated.... %d\n",dev->nObjectsCreated);
     2213+       buf +=sprintf(buf,"nFreeObjects....... %d\n",dev->nFreeObjects);
     2214+       buf +=sprintf(buf,"nFreeChunks........ %d\n",dev->nFreeChunks);
     2215+       buf +=sprintf(buf,"nPageWrites........ %d\n",dev->nPageWrites);
     2216+       buf +=sprintf(buf,"nPageReads......... %d\n",dev->nPageReads);
     2217+       buf +=sprintf(buf,"nBlockErasures..... %d\n",dev->nBlockErasures);
     2218+       buf +=sprintf(buf,"nGCCopies.......... %d\n",dev->nGCCopies);
     2219+       buf +=sprintf(buf,"garbageCollections. %d\n",dev->garbageCollections);
     2220+       buf +=sprintf(buf,"passiveGCs......... %d\n",dev->passiveGarbageCollections);
     2221+       buf +=sprintf(buf,"nRetriedWrites..... %d\n",dev->nRetriedWrites);
     2222+       buf +=sprintf(buf,"nRetireBlocks...... %d\n",dev->nRetiredBlocks);
     2223+       buf +=sprintf(buf,"eccFixed........... %d\n",dev->eccFixed);
     2224+       buf +=sprintf(buf,"eccUnfixed......... %d\n",dev->eccUnfixed);
     2225+       buf +=sprintf(buf,"tagsEccFixed....... %d\n",dev->tagsEccFixed);
     2226+       buf +=sprintf(buf,"tagsEccUnfixed..... %d\n",dev->tagsEccUnfixed);
     2227+       buf +=sprintf(buf,"cacheHits.......... %d\n",dev->cacheHits);
     2228+       buf +=sprintf(buf,"nDeletedFiles...... %d\n",dev->nDeletedFiles);
     2229+       buf +=sprintf(buf,"nUnlinkedFiles..... %d\n",dev->nUnlinkedFiles);
     2230+       buf +=sprintf(buf,"nBackgroudDeletions %d\n",dev->nBackgroundDeletions);
     2231+       buf +=sprintf(buf,"useNANDECC......... %d\n",dev->useNANDECC);
     2232+       buf +=sprintf(buf,"isYaffs2........... %d\n",dev->isYaffs2);
     2233+
     2234+       return buf;     
     2235+}
     2236+
     2237+static int  yaffs_proc_read(
     2238+        char *page,
     2239+       char **start,
     2240+       off_t offset,
     2241+       int count,
     2242+       int *eof,
     2243+       void *data
     2244+       )
    31532245+{
    31542246+       struct list_head *item;
     
    31672259+       /* Print header first */
    31682260+       if (step == 0) {
    3169 +               buf += sprintf(buf, "YAFFS built:" __DATE__ " " __TIME__
    3170 +                              "\n%s\n%s\n", yaffs_fs_c_version,
    3171 +                              yaffs_guts_c_version);
     2261+               buf += sprintf(buf, "YAFFS built:" __DATE__ " "__TIME__
     2262+               "\n%s\n%s\n", yaffs_fs_c_version, yaffs_guts_c_version);
    31722263+       }
    31732264+
     
    31822273+                       continue;
    31832274+               }
    3184 +               buf += sprintf(buf, "\nDevice %d \"%s\"\n", n, dev->name);
     2275+               buf += sprintf(buf,"\nDevice %d \"%s\"\n", n, dev->name);
    31852276+               buf = yaffs_dump_dev(buf, dev);
    31862277+               break;
     
    31882279+       unlock_kernel();
    31892280+
    3190 +       return buf - page < count ? buf - page : count;
    3191 +}
    3192 +
    3193 +/**
    3194 + * Set the verbosity of the warnings and error messages.
    3195 + *
    3196 + */
    3197 +
    3198 +static struct {
    3199 +       char *mask_name;
    3200 +       unsigned mask_bitfield;
    3201 +} mask_flags[] = {
    3202 +       {"allocate", YAFFS_TRACE_ALLOCATE},
    3203 +       {"always", YAFFS_TRACE_ALWAYS},
    3204 +       {"bad_blocks", YAFFS_TRACE_BAD_BLOCKS},
    3205 +       {"buffers", YAFFS_TRACE_BUFFERS},
    3206 +       {"bug", YAFFS_TRACE_BUG},
    3207 +       {"deletion", YAFFS_TRACE_DELETION},
    3208 +       {"erase", YAFFS_TRACE_ERASE},
    3209 +       {"error", YAFFS_TRACE_ERROR},
    3210 +       {"gc_detail", YAFFS_TRACE_GC_DETAIL},
    3211 +       {"gc", YAFFS_TRACE_GC},
    3212 +       {"mtd", YAFFS_TRACE_MTD},
    3213 +       {"nandaccess", YAFFS_TRACE_NANDACCESS},
    3214 +       {"os", YAFFS_TRACE_OS},
    3215 +       {"scan_debug", YAFFS_TRACE_SCAN_DEBUG},
    3216 +       {"scan", YAFFS_TRACE_SCAN},
    3217 +       {"tracing", YAFFS_TRACE_TRACING},
    3218 +       {"write", YAFFS_TRACE_WRITE},
    3219 +       {"all", 0xffffffff},
    3220 +       {"none", 0},
    3221 +       {NULL, 0},
     2281+       return buf-page < count ? buf-page : count;
     2282+}
     2283+
     2284+// Stuff to handle installation of file systems
     2285+struct file_system_to_install
     2286+{
     2287+   struct file_system_type *fst;
     2288+   int installed;
    32222289+};
    32232290+
    3224 +static int yaffs_proc_write(struct file *file, const char *buf,
    3225 +                                        unsigned long count, void *data)
    3226 +{
    3227 +       unsigned rg = 0, mask_bitfield;
    3228 +       char *end, *mask_name;
    3229 +       int i;
    3230 +       int done = 0;
    3231 +       int add, len;
    3232 +       int pos = 0;
    3233 +
    3234 +       rg = yaffs_traceMask;
    3235 +
    3236 +       while (!done && (pos < count)) {
    3237 +               done = 1;
    3238 +               while ((pos < count) && isspace(buf[pos])) {
    3239 +                       pos++;
    3240 +               }
    3241 +
    3242 +               switch (buf[pos]) {
    3243 +               case '+':
    3244 +               case '-':
    3245 +               case '=':
    3246 +                       add = buf[pos];
    3247 +                       pos++;
    3248 +                       break;
    3249 +
    3250 +               default:
    3251 +                       add = ' ';
    3252 +                       break;
    3253 +               }
    3254 +               mask_name = NULL;
    3255 +               mask_bitfield = simple_strtoul(buf + pos, &end, 0);
    3256 +               if (end > buf + pos) {
    3257 +                       mask_name = "numeral";
    3258 +                       len = end - (buf + pos);
    3259 +                       done = 0;
    3260 +               } else {
    3261 +
    3262 +                       for (i = 0; mask_flags[i].mask_name != NULL; i++) {
    3263 +                               len = strlen(mask_flags[i].mask_name);
    3264 +                               if (strncmp(buf + pos, mask_flags[i].mask_name, len) == 0) {
    3265 +                                       mask_name = mask_flags[i].mask_name;
    3266 +                                       mask_bitfield = mask_flags[i].mask_bitfield;
    3267 +                                       done = 0;
    3268 +                                       break;
    3269 +                               }
    3270 +                       }
    3271 +               }
    3272 +
    3273 +               if (mask_name != NULL) {
    3274 +                       pos += len;
    3275 +                       done = 0;
    3276 +                       switch(add) {
    3277 +                       case '-':
    3278 +                               rg &= ~mask_bitfield;
    3279 +                               break;
    3280 +                       case '+':
    3281 +                               rg |= mask_bitfield;
    3282 +                               break;
    3283 +                       case '=':
    3284 +                               rg = mask_bitfield;
    3285 +                               break;
    3286 +                       default:
    3287 +                               rg |= mask_bitfield;
    3288 +                               break;
    3289 +                       }
    3290 +               }
    3291 +       }
    3292 +
    3293 +       yaffs_traceMask = rg;
    3294 +       if (rg & YAFFS_TRACE_ALWAYS) {
    3295 +               for (i = 0; mask_flags[i].mask_name != NULL; i++) {
    3296 +                       char flag;
    3297 +                       flag = ((rg & mask_flags[i].mask_bitfield) == mask_flags[i].mask_bitfield) ? '+' : '-';
    3298 +                       printk("%c%s\n", flag, mask_flags[i].mask_name);
    3299 +               }
    3300 +       }
    3301 +
    3302 +       return count;
    3303 +}
    3304 +
    3305 +/* Stuff to handle installation of file systems */
    3306 +struct file_system_to_install {
    3307 +       struct file_system_type *fst;
    3308 +       int installed;
     2291+static struct file_system_to_install fs_to_install[] =
     2292+{
     2293+#ifdef CONFIG_YAFFS_YAFFS1
     2294+     { &yaffs_fs_type,0},
     2295+#endif
     2296+#ifdef CONFIG_YAFFS_YAFFS2
     2297+     { &yaffs2_fs_type,0},
     2298+#endif
     2299+     { NULL,0}
    33092300+};
    33102301+
    3311 +static struct file_system_to_install fs_to_install[] = {
    3312 +//#ifdef CONFIG_YAFFS_YAFFS1
    3313 +       {&yaffs_fs_type, 0},
    3314 +//#endif
    3315 +//#ifdef CONFIG_YAFFS_YAFFS2
    3316 +       {&yaffs2_fs_type, 0},
    3317 +//#endif
    3318 +       {NULL, 0}
    3319 +};
    3320 +
    33212302+static int __init init_yaffs_fs(void)
    33222303+{
    33232304+       int error = 0;
    3324 +       struct file_system_to_install *fsinst;
    3325 +
    3326 +       T(YAFFS_TRACE_ALWAYS,
    3327 +         ("yaffs " __DATE__ " " __TIME__ " Installing. \n"));
    3328 +
    3329 +       /* Install the proc_fs entry */
    3330 +       my_proc_entry = create_proc_entry("yaffs",
    3331 +                                              S_IRUGO | S_IFREG,
    3332 +                                              &proc_root);
    3333 +
    3334 +       if (my_proc_entry) {
    3335 +               my_proc_entry->write_proc = yaffs_proc_write;
    3336 +               my_proc_entry->read_proc = yaffs_proc_read;
    3337 +               my_proc_entry->data = NULL;
    3338 +       } else {
    3339 +               return -ENOMEM;
    3340 +       }
    3341 +
    3342 +       /* Now add the file system entries */
    3343 +
    3344 +       fsinst = fs_to_install;
    3345 +
    3346 +       while (fsinst->fst && !error) {
    3347 +               error = register_filesystem(fsinst->fst);
    3348 +               if (!error) {
    3349 +                       fsinst->installed = 1;
    3350 +               }
    3351 +               fsinst++;
    3352 +       }
    3353 +
    3354 +       /* Any errors? uninstall  */
    3355 +       if (error) {
    3356 +               fsinst = fs_to_install;
    3357 +
    3358 +               while (fsinst->fst) {
    3359 +                       if (fsinst->installed) {
    3360 +                               unregister_filesystem(fsinst->fst);
    3361 +                               fsinst->installed = 0;
    3362 +                       }
    3363 +                       fsinst++;
    3364 +               }
    3365 +       }
    3366 +
    3367 +       return error;
     2305+       struct file_system_to_install *fsinst; 
     2306+       
     2307+   T(YAFFS_TRACE_ALWAYS,("yaffs " __DATE__ " " __TIME__ " Installing. \n"));
     2308+
     2309+
     2310+
     2311+    /* Install the proc_fs entry */
     2312+    my_proc_entry = create_proc_read_entry("yaffs",
     2313+                                           S_IRUGO | S_IFREG,
     2314+                                          &proc_root,
     2315+                                          yaffs_proc_read,
     2316+                                          NULL);
     2317+    if(!my_proc_entry)
     2318+    {
     2319+       return -ENOMEM;
     2320+    }
     2321+   
     2322+   
     2323+
     2324+    // Now add the file system entries
     2325+   
     2326+    fsinst = fs_to_install;
     2327+   
     2328+    while(fsinst->fst && !error)
     2329+    {
     2330+      error = register_filesystem(fsinst->fst);
     2331+      if(!error)
     2332+      {
     2333+          fsinst->installed = 1;
     2334+      }
     2335+      fsinst++;
     2336+    }
     2337+   
     2338+    // Any errors? uninstall
     2339+    if(error)
     2340+    {
     2341+           fsinst = fs_to_install;
     2342+           
     2343+           while(fsinst->fst)
     2344+           {
     2345+             if(fsinst->installed)
     2346+             {
     2347+               unregister_filesystem(fsinst->fst);
     2348+               fsinst->installed = 0;
     2349+             }
     2350+             fsinst++;
     2351+           }
     2352+    }
     2353+   
     2354+    return error;
    33682355+}
    33692356+
     
    33712358+{
    33722359+
    3373 +       struct file_system_to_install *fsinst;
    3374 +
    3375 +       T(YAFFS_TRACE_ALWAYS, ("yaffs " __DATE__ " " __TIME__
    3376 +                              " removing. \n"));
    3377 +
    3378 +       remove_proc_entry("yaffs", &proc_root);
    3379 +
    3380 +       fsinst = fs_to_install;
    3381 +
    3382 +       while (fsinst->fst) {
    3383 +               if (fsinst->installed) {
    3384 +                       unregister_filesystem(fsinst->fst);
    3385 +                       fsinst->installed = 0;
    3386 +               }
    3387 +               fsinst++;
    3388 +       }
     2360+   struct file_system_to_install *fsinst;
     2361+   
     2362+   T(YAFFS_TRACE_ALWAYS,("yaffs " __DATE__ " " __TIME__ " removing. \n"));
     2363+
     2364+   remove_proc_entry("yaffs",&proc_root);
     2365+   
     2366+    fsinst = fs_to_install;
     2367+   
     2368+    while(fsinst->fst)
     2369+    {
     2370+      if(fsinst->installed)
     2371+      {
     2372+        unregister_filesystem(fsinst->fst);
     2373+        fsinst->installed = 0;
     2374+      }
     2375+      fsinst++;
     2376+    }
    33892377+
    33902378+}
     
    33942382+
    33952383+MODULE_DESCRIPTION("YAFFS2 - a NAND specific flash file system");
    3396 +MODULE_AUTHOR("Charles Manning, Aleph One Ltd., 2002-2006");
     2384+MODULE_AUTHOR("Charles Manning, Aleph One Ltd., 2002,2003,2004");
    33972385+MODULE_LICENSE("GPL");
    3398 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_guts.c linux-2.6.18.2.patched/fs/yaffs2/yaffs_guts.c
    3399 --- linux-2.6.18.2/fs/yaffs2/yaffs_guts.c       1970-01-01 01:00:00.000000000 +0100
    3400 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_guts.c       2006-11-25 00:15:31.000000000 +0100
    3401 @@ -0,0 +1,6675 @@
     2386+
     2387+
     2388diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_guts.c linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_guts.c
     2389--- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_guts.c      1970-01-01 01:00:00.000000000 +0100
     2390+++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_guts.c   2006-12-10 03:57:50.000000000 +0100
     2391@@ -0,0 +1,6346 @@
    34022392+/*
    3403 + * YAFFS: Yet another FFS. A NAND-flash specific file system.
     2393+ * YAFFS: Yet another FFS. A NAND-flash specific file system. 
    34042394+ *
    34052395+ * Copyright (C) 2002 Aleph One Ltd.
     
    34132403+ *
    34142404+ */
    3415 +
    3416 +const char *yaffs_guts_c_version =
    3417 +    "$Id: yaffs_guts.c,v 1.45 2006/11/14 03:07:17 charles Exp $";
     2405+ //yaffs_guts.c
     2406+
     2407+const char *yaffs_guts_c_version="$Id: yaffs_guts.c,v 1.15 2005/08/02 04:24:22 charles Exp $";
    34182408+
    34192409+#include "yportenv.h"
     
    34232413+#include "yaffs_tagsvalidity.h"
    34242414+
     2415+
    34252416+#include "yaffs_tagscompat.h"
    3426 +#ifndef CONFIG_YAFFS_OWN_SORT
    3427 +#include "yaffs_qsort.h"
    3428 +#endif
    3429 +#include "yaffs_nand.h"
    3430 +
    3431 +#include "yaffs_checkptrw.h"
    3432 +
    3433 +#include "yaffs_nand.h"
    3434 +#include "yaffs_packedtags2.h"
    3435 +
    34362417+
    34372418+#ifdef CONFIG_YAFFS_WINCE
     
    34422423+#define YAFFS_PASSIVE_GC_CHUNKS 2
    34432424+
     2425+#if 0
     2426+// Use Steven Hill's ECC struff instead
     2427+// External functions for ECC on data
     2428+void nand_calculate_ecc (const u_char *dat, u_char *ecc_code);
     2429+int nand_correct_data (u_char *dat, u_char *read_ecc, u_char *calc_ecc);
     2430+#define yaffs_ECCCalculate(data,ecc) nand_calculate_ecc(data,ecc)
     2431+#define yaffs_ECCCorrect(data,read_ecc,calc_ecc) nand_correct_ecc(data,read_ecc,calc_ecc)
     2432+#else
    34442433+#include "yaffs_ecc.h"
    3445 +
    3446 +
    3447 +/* Robustification (if it ever comes about...) */
    3448 +static void yaffs_RetireBlock(yaffs_Device * dev, int blockInNAND);
    3449 +static void yaffs_HandleWriteChunkError(yaffs_Device * dev, int chunkInNAND, int erasedOk);
    3450 +static void yaffs_HandleWriteChunkOk(yaffs_Device * dev, int chunkInNAND,
    3451 +                                    const __u8 * data,
    3452 +                                    const yaffs_ExtendedTags * tags);
    3453 +static void yaffs_HandleUpdateChunk(yaffs_Device * dev, int chunkInNAND,
    3454 +                                   const yaffs_ExtendedTags * tags);
    3455 +
    3456 +/* Other local prototypes */
    3457 +static int yaffs_UnlinkObject( yaffs_Object *obj);
    3458 +static int yaffs_ObjectHasCachedWriteData(yaffs_Object *obj);
    3459 +
    3460 +static void yaffs_HardlinkFixup(yaffs_Device *dev, yaffs_Object *hardList);
    3461 +
    3462 +static int yaffs_WriteNewChunkWithTagsToNAND(yaffs_Device * dev,
    3463 +                                            const __u8 * buffer,
    3464 +                                            yaffs_ExtendedTags * tags,
    3465 +                                            int useReserve);
    3466 +static int yaffs_PutChunkIntoFile(yaffs_Object * in, int chunkInInode,
    3467 +                                 int chunkInNAND, int inScan);
    3468 +
    3469 +static yaffs_Object *yaffs_CreateNewObject(yaffs_Device * dev, int number,
    3470 +                                          yaffs_ObjectType type);
    3471 +static void yaffs_AddObjectToDirectory(yaffs_Object * directory,
    3472 +                                      yaffs_Object * obj);
    3473 +static int yaffs_UpdateObjectHeader(yaffs_Object * in, const YCHAR * name,
    3474 +                                   int force, int isShrink, int shadows);
    3475 +static void yaffs_RemoveObjectFromDirectory(yaffs_Object * obj);
     2434+#endif
     2435+
     2436+#if 0
     2437+// countBits is a quick way of counting the number of bits in a byte.
     2438+// ie. countBits[n] holds the number of 1 bits in a byte with the value n.
     2439+
     2440+static const char yaffs_countBitsTable[256] =
     2441+{
     2442+0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,
     2443+1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
     2444+1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
     2445+2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
     2446+1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
     2447+2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
     2448+2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
     2449+3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
     2450+1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
     2451+2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
     2452+2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
     2453+3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
     2454+2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
     2455+3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
     2456+3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
     2457+4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8
     2458+};
     2459+
     2460+static int yaffs_CountBits(__u8 x)
     2461+{
     2462+       int retVal;
     2463+       retVal = yaffs_countBitsTable[x];
     2464+       return retVal;
     2465+}
     2466+
     2467+#endif
     2468+
     2469+
     2470+#if 0
     2471+// Stuff using yea olde tags
     2472+static void yaffs_LoadTagsIntoSpare(yaffs_Spare *sparePtr, yaffs_Tags *tagsPtr);
     2473+static void yaffs_GetTagsFromSpare(yaffs_Device *dev, yaffs_Spare *sparePtr,yaffs_Tags *tagsPtr);
     2474+
     2475+static int yaffs_ReadChunkTagsFromNAND(yaffs_Device *dev,int chunkInNAND, yaffs_Tags *tags, int *chunkDeleted);
     2476+static int yaffs_TagsMatch(const yaffs_Tags *tags, int objectId, int chunkInObject, int chunkDeleted);
     2477+#else
     2478+#endif
     2479+
     2480+// NAND access
     2481+
     2482+
     2483+static Y_INLINE int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *buffer, yaffs_ExtendedTags *tags);
     2484+static Y_INLINE int yaffs_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND, const __u8 *data, yaffs_ExtendedTags *tags);
     2485+static Y_INLINE int yaffs_MarkBlockBad(yaffs_Device *dev, int blockNo);
     2486+static Y_INLINE int yaffs_QueryInitialBlockState(yaffs_Device *dev,int blockNo, yaffs_BlockState *state,unsigned *sequenceNumber);
     2487+// Local prototypes
     2488+static int yaffs_WriteNewChunkWithTagsToNAND(yaffs_Device *dev, const __u8 *buffer, yaffs_ExtendedTags *tags, int useReserve);
     2489+#if 0
     2490+static int yaffs_CheckObjectHashSanity(yaffs_Device *dev);
     2491+#endif
     2492+static int yaffs_PutChunkIntoFile(yaffs_Object *in,int chunkInInode, int chunkInNAND, int inScan);
     2493+
     2494+static yaffs_Object *yaffs_CreateNewObject(yaffs_Device *dev,int number,yaffs_ObjectType type);
     2495+static void yaffs_AddObjectToDirectory(yaffs_Object *directory, yaffs_Object *obj);
     2496+static int yaffs_UpdateObjectHeader(yaffs_Object *in,const YCHAR *name, int force,int isShrink, int shadows);
     2497+static void yaffs_RemoveObjectFromDirectory(yaffs_Object *obj);
    34762498+static int yaffs_CheckStructures(void);
    3477 +static int yaffs_DeleteWorker(yaffs_Object * in, yaffs_Tnode * tn, __u32 level,
    3478 +                             int chunkOffset, int *limit);
    3479 +static int yaffs_DoGenericObjectDeletion(yaffs_Object * in);
    3480 +
    3481 +static yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device * dev, int blockNo);
    3482 +
    3483 +static __u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo);
    3484 +static void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer,
    3485 +                                   int lineNo);
    3486 +
    3487 +static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,
    3488 +                                 int chunkInNAND);
    3489 +
    3490 +static int yaffs_UnlinkWorker(yaffs_Object * obj);
    3491 +static void yaffs_DestroyObject(yaffs_Object * obj);
    3492 +
    3493 +static int yaffs_TagsMatch(const yaffs_ExtendedTags * tags, int objectId,
    3494 +                          int chunkInObject);
    3495 +
    3496 +loff_t yaffs_GetFileSize(yaffs_Object * obj);
    3497 +
    3498 +static int yaffs_AllocateChunk(yaffs_Device * dev, int useReserve, yaffs_BlockInfo **blockUsedPtr);
    3499 +
    3500 +static void yaffs_VerifyFreeChunks(yaffs_Device * dev);
     2499+static int yaffs_DeleteWorker(yaffs_Object *in, yaffs_Tnode *tn, __u32 level, int chunkOffset,int *limit);
     2500+static int yaffs_DoGenericObjectDeletion(yaffs_Object *in);
     2501+
     2502+static yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device *dev,int blockNo);
     2503+
     2504+static __u8 *yaffs_GetTempBuffer(yaffs_Device *dev,int lineNo);
     2505+static void yaffs_ReleaseTempBuffer(yaffs_Device *dev, __u8 *buffer, int lineNo);
     2506+
     2507+
     2508+// Robustification (if it ever comes about...)
     2509+static void yaffs_RetireBlock(yaffs_Device *dev,int blockInNAND);
     2510+#if 0
     2511+static void yaffs_HandleReadDataError(yaffs_Device *dev,int chunkInNAND);
     2512+#endif
     2513+static void yaffs_HandleWriteChunkError(yaffs_Device *dev,int chunkInNAND);
     2514+static void yaffs_HandleWriteChunkOk(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_ExtendedTags *tags);
     2515+static void yaffs_HandleUpdateChunk(yaffs_Device *dev,int chunkInNAND,  const yaffs_ExtendedTags *tags);
     2516+
     2517+static int  yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,int chunkInNAND);
     2518+
     2519+static int yaffs_UnlinkWorker(yaffs_Object *obj);
     2520+static void yaffs_DestroyObject(yaffs_Object *obj);
     2521+
     2522+#if 0
     2523+static int yaffs_VerifyCompare(const __u8 *d0, const __u8 * d1, const yaffs_Spare *s0, const yaffs_Spare *s1,int dataSize);
     2524+#endif
     2525+
     2526+static int yaffs_TagsMatch(const yaffs_ExtendedTags *tags, int objectId, int chunkInObject);
     2527+
     2528+
     2529+loff_t yaffs_GetFileSize(yaffs_Object *obj);
     2530+
     2531+
     2532+static int yaffs_AllocateChunk(yaffs_Device *dev,int useReserve);
     2533+
     2534+static void yaffs_VerifyFreeChunks(yaffs_Device *dev);
    35012535+
    35022536+#ifdef YAFFS_PARANOID
    3503 +static int yaffs_CheckFileSanity(yaffs_Object * in);
     2537+static int yaffs_CheckFileSanity(yaffs_Object *in);
    35042538+#else
    35052539+#define yaffs_CheckFileSanity(in)
    35062540+#endif
    35072541+
    3508 +static void yaffs_InvalidateWholeChunkCache(yaffs_Object * in);
    3509 +static void yaffs_InvalidateChunkCache(yaffs_Object * object, int chunkId);
    3510 +
    3511 +static void yaffs_InvalidateCheckpoint(yaffs_Device *dev);
    3512 +
    3513 +
    3514 +
    3515 +/* Function to calculate chunk and offset */
    3516 +
    3517 +static void yaffs_AddrToChunk(yaffs_Device *dev, loff_t addr, __u32 *chunk, __u32 *offset)
    3518 +{
    3519 +       if(dev->chunkShift){
    3520 +               /* Easy-peasy power of 2 case */
    3521 +               *chunk  = (__u32)(addr >> dev->chunkShift);
    3522 +               *offset = (__u32)(addr & dev->chunkMask);
    3523 +       }
    3524 +       else if(dev->crumbsPerChunk)
    3525 +       {
    3526 +               /* Case where we're using "crumbs" */
    3527 +               *offset = (__u32)(addr & dev->crumbMask);
    3528 +               addr >>= dev->crumbShift;
    3529 +               *chunk = ((__u32)addr)/dev->crumbsPerChunk;
    3530 +               *offset += ((addr - (*chunk * dev->crumbsPerChunk)) << dev->crumbShift);
    3531 +       }
     2542+static void yaffs_InvalidateWholeChunkCache(yaffs_Object *in);
     2543+static void yaffs_InvalidateChunkCache(yaffs_Object *object, int chunkId);
     2544+
     2545+static int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *buffer, yaffs_ExtendedTags *tags)
     2546+{
     2547+       chunkInNAND -= dev->chunkOffset;
     2548+       
     2549+       if(dev->readChunkWithTagsFromNAND)
     2550+               return dev->readChunkWithTagsFromNAND(dev,chunkInNAND,buffer,tags);
    35322551+       else
    3533 +               YBUG();
    3534 +}
    3535 +
    3536 +/* Function to return the number of shifts for a power of 2 greater than or equal
    3537 + * to the given number
    3538 + * Note we don't try to cater for all possible numbers and this does not have to
    3539 + * be hellishly efficient.
    3540 + */
    3541 +
    3542 +static __u32 ShiftsGE(__u32 x)
    3543 +{
    3544 +       int extraBits;
    3545 +       int nShifts;
    3546 +       
    3547 +       nShifts = extraBits = 0;
    3548 +       
    3549 +       while(x>1){
    3550 +               if(x & 1) extraBits++;
    3551 +               x>>=1;
    3552 +               nShifts++;
    3553 +       }
    3554 +
    3555 +       if(extraBits)
    3556 +               nShifts++;
    3557 +               
    3558 +       return nShifts;
    3559 +}
    3560 +
    3561 +/* Function to return the number of shifts to get a 1 in bit 0
    3562 + */
    3563 +
    3564 +static __u32 ShiftDiv(__u32 x)
    3565 +{
    3566 +       int nShifts;
    3567 +       
    3568 +       nShifts =  0;
    3569 +       
    3570 +       if(!x) return 0;
    3571 +       
    3572 +       while( !(x&1)){
    3573 +               x>>=1;
    3574 +               nShifts++;
    3575 +       }
    3576 +               
    3577 +       return nShifts;
    3578 +}
    3579 +
    3580 +
    3581 +
    3582 +/*
    3583 + * Temporary buffer manipulations.
    3584 + */
    3585 +
    3586 +static __u8 *yaffs_GetTempBuffer(yaffs_Device * dev, int lineNo)
    3587 +{
    3588 +       int i, j;
    3589 +       for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
    3590 +               if (dev->tempBuffer[i].line == 0) {
     2552+               return yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(dev,chunkInNAND,buffer,tags);
     2553+}
     2554+
     2555+static Y_INLINE int yaffs_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND, const __u8 *buffer, yaffs_ExtendedTags *tags)
     2556+{
     2557+       chunkInNAND -= dev->chunkOffset;
     2558+       
     2559+       if(tags)
     2560+       {
     2561+               tags->sequenceNumber = dev->sequenceNumber;
     2562+               tags->chunkUsed = 1;
     2563+               if(!yaffs_ValidateTags(tags))
     2564+               {
     2565+                       T(YAFFS_TRACE_ERROR,(TSTR("Writing uninitialised tags" TENDSTR)));
     2566+                       YBUG();
     2567+               }
     2568+               T(YAFFS_TRACE_WRITE,(TSTR("Writing chunk %d tags %d %d"TENDSTR),chunkInNAND,tags->objectId,tags->chunkId));
     2569+       }
     2570+       else
     2571+       {
     2572+                       T(YAFFS_TRACE_ERROR,(TSTR("Writing with no tags" TENDSTR)));
     2573+                       YBUG();
     2574+       }
     2575+
     2576+       if(dev->writeChunkWithTagsToNAND)
     2577+               return dev->writeChunkWithTagsToNAND(dev,chunkInNAND,buffer,tags);
     2578+       else
     2579+               return yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(dev,chunkInNAND,buffer,tags);
     2580+}
     2581+
     2582+static Y_INLINE int yaffs_MarkBlockBad(yaffs_Device *dev, int blockNo)
     2583+{
     2584+       blockNo -= dev->blockOffset;
     2585+       
     2586+       if(dev->markNANDBlockBad)
     2587+               return dev->markNANDBlockBad(dev,blockNo);
     2588+       else
     2589+               return yaffs_TagsCompatabilityMarkNANDBlockBad(dev,blockNo);
     2590+}
     2591+static Y_INLINE int yaffs_QueryInitialBlockState(yaffs_Device *dev,int blockNo, yaffs_BlockState *state, unsigned *sequenceNumber)
     2592+{
     2593+       blockNo -= dev->blockOffset;
     2594+       
     2595+       if(dev->queryNANDBlock)
     2596+               return dev->queryNANDBlock(dev,blockNo,state,sequenceNumber);
     2597+       else
     2598+               return yaffs_TagsCompatabilityQueryNANDBlock(dev,blockNo,state,sequenceNumber);
     2599+}
     2600+
     2601+static int yaffs_EraseBlockInNAND(struct yaffs_DeviceStruct *dev,int blockInNAND)
     2602+{
     2603+       int result;
     2604+       
     2605+       blockInNAND -= dev->blockOffset;
     2606+
     2607+       dev->nBlockErasures++;
     2608+       result = dev->eraseBlockInNAND(dev,blockInNAND);
     2609+
     2610+       if(!result)result = dev->eraseBlockInNAND(dev,blockInNAND); // If at first we don't succeed, try again *once*.
     2611+       return result;
     2612+}
     2613+
     2614+static int yaffs_InitialiseNAND(struct yaffs_DeviceStruct *dev)
     2615+{
     2616+       return dev->initialiseNAND(dev);
     2617+}
     2618+
     2619+
     2620+
     2621+
     2622+// Temporary buffer manipulations
     2623+
     2624+static __u8 *yaffs_GetTempBuffer(yaffs_Device *dev,int lineNo)
     2625+{
     2626+       int i,j;
     2627+       for(i = 0; i < YAFFS_N_TEMP_BUFFERS; i++)
     2628+       {
     2629+               if(dev->tempBuffer[i].line == 0)
     2630+               {
    35912631+                       dev->tempBuffer[i].line = lineNo;
    3592 +                       if ((i + 1) > dev->maxTemp) {
     2632+                       if((i+1) > dev->maxTemp)
     2633+                       {
    35932634+                               dev->maxTemp = i + 1;
    3594 +                               for (j = 0; j <= i; j++)
    3595 +                                       dev->tempBuffer[j].maxLine =
    3596 +                                           dev->tempBuffer[j].line;
    3597 +                       }
    3598 +
     2635+                               for(j = 0; j <= i; j++)
     2636+                                       dev->tempBuffer[j].maxLine = dev->tempBuffer[j].line;
     2637+                       }       
     2638+                       
    35992639+                       return dev->tempBuffer[i].buffer;
    36002640+               }
    36012641+       }
    36022642+
    3603 +       T(YAFFS_TRACE_BUFFERS,
    3604 +         (TSTR("Out of temp buffers at line %d, other held by lines:"),
    3605 +          lineNo));
    3606 +       for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
    3607 +               T(YAFFS_TRACE_BUFFERS, (TSTR(" %d "), dev->tempBuffer[i].line));
    3608 +       }
    3609 +       T(YAFFS_TRACE_BUFFERS, (TSTR(" " TENDSTR)));
    3610 +
    3611 +       /*
    3612 +        * If we got here then we have to allocate an unmanaged one
    3613 +        * This is not good.
    3614 +        */
    3615 +
     2643+       T(YAFFS_TRACE_BUFFERS,(TSTR("Out of temp buffers at line %d, other held by lines:"),lineNo));
     2644+       for(i = 0; i < YAFFS_N_TEMP_BUFFERS; i++)
     2645+       {
     2646+               T(YAFFS_TRACE_BUFFERS,(TSTR(" %d "),dev->tempBuffer[i].line));
     2647+       }
     2648+       T(YAFFS_TRACE_BUFFERS,(TSTR(" "TENDSTR)));
     2649+       
    36162650+       dev->unmanagedTempAllocations++;
    3617 +       return YMALLOC(dev->nDataBytesPerChunk);
    3618 +
    3619 +}
    3620 +
    3621 +static void yaffs_ReleaseTempBuffer(yaffs_Device * dev, __u8 * buffer,
    3622 +                                   int lineNo)
     2651+       // Get an unmanaged one
     2652+       return YMALLOC(dev->nBytesPerChunk);   
     2653+       
     2654+       
     2655+}
     2656+
     2657+static void yaffs_ReleaseTempBuffer(yaffs_Device *dev, __u8 *buffer, int lineNo)
    36232658+{
    36242659+       int i;
    3625 +       for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
    3626 +               if (dev->tempBuffer[i].buffer == buffer) {
     2660+       for(i = 0; i < YAFFS_N_TEMP_BUFFERS; i++)
     2661+       {
     2662+               if(dev->tempBuffer[i].buffer == buffer)
     2663+               {
    36272664+                       dev->tempBuffer[i].line = 0;
    36282665+                       return;
    36292666+               }
    36302667+       }
    3631 +
    3632 +       if (buffer) {
    3633 +               /* assume it is an unmanaged one. */
    3634 +               T(YAFFS_TRACE_BUFFERS,
    3635 +                 (TSTR("Releasing unmanaged temp buffer in line %d" TENDSTR),
    3636 +                  lineNo));
     2668+       
     2669+       if(buffer)
     2670+       {
     2671+               // assume it is an unmanaged one.
     2672+               T(YAFFS_TRACE_BUFFERS,(TSTR("Releasing unmanaged temp buffer in line %d" TENDSTR),lineNo));
    36372673+               YFREE(buffer);
    36382674+               dev->unmanagedTempDeallocations++;
     
    36412677+}
    36422678+
    3643 +/*
    3644 + * Determine if we have a managed buffer.
    3645 + */
    3646 +int yaffs_IsManagedTempBuffer(yaffs_Device * dev, const __u8 * buffer)
    3647 +{
     2679+
     2680+// Chunk bitmap manipulations
     2681+
     2682+static Y_INLINE __u8 *yaffs_BlockBits(yaffs_Device *dev, int blk)
     2683+{
     2684+       if(blk < dev->internalStartBlock || blk > dev->internalEndBlock)
     2685+       {
     2686+               T(YAFFS_TRACE_ERROR,(TSTR("**>> yaffs: BlockBits block %d is not valid" TENDSTR),blk));
     2687+               YBUG();
     2688+       }
     2689+       return dev->chunkBits + (dev->chunkBitmapStride * (blk - dev->internalStartBlock));
     2690+}
     2691+
     2692+static Y_INLINE void yaffs_ClearChunkBits(yaffs_Device *dev,int blk)
     2693+{
     2694+       __u8 *blkBits = yaffs_BlockBits(dev,blk);
     2695+
     2696+        memset(blkBits,0,dev->chunkBitmapStride);
     2697+}
     2698+
     2699+static Y_INLINE void yaffs_ClearChunkBit(yaffs_Device *dev,int blk,int chunk)
     2700+{
     2701+       __u8 *blkBits = yaffs_BlockBits(dev,blk);
     2702+       
     2703+       blkBits[chunk/8] &=  ~ (1<<(chunk & 7));
     2704+}
     2705+
     2706+static Y_INLINE void yaffs_SetChunkBit(yaffs_Device *dev,int blk,int chunk)
     2707+{
     2708+       __u8 *blkBits = yaffs_BlockBits(dev,blk);
     2709+
     2710+       blkBits[chunk/8] |=   (1<<(chunk & 7));
     2711+}
     2712+
     2713+static Y_INLINE int yaffs_CheckChunkBit(yaffs_Device *dev,int blk,int chunk)
     2714+{
     2715+       __u8 *blkBits = yaffs_BlockBits(dev,blk);
     2716+       return (blkBits[chunk/8] &  (1<<(chunk & 7))) ? 1 :0;
     2717+}
     2718+
     2719+static Y_INLINE int yaffs_StillSomeChunkBits(yaffs_Device *dev,int blk)
     2720+{
     2721+       __u8 *blkBits = yaffs_BlockBits(dev,blk);
    36482722+       int i;
    3649 +       for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
    3650 +               if (dev->tempBuffer[i].buffer == buffer)
    3651 +                       return 1;
    3652 +
    3653 +       }
    3654 +
    3655 +    for (i = 0; i < dev->nShortOpCaches; i++) {
    3656 +        if( dev->srCache[i].data == buffer )
    3657 +            return 1;
    3658 +
    3659 +    }
    3660 +
    3661 +    if (buffer == dev->checkpointBuffer)
    3662 +      return 1;
    3663 +
    3664 +    T(YAFFS_TRACE_ALWAYS,
    3665 +         (TSTR("yaffs: unmaged buffer detected.\n" TENDSTR)));
    3666 +    return 0;
    3667 +}
    3668 +
    3669 +/*
    3670 + * Chunk bitmap manipulations
    3671 + */
    3672 +
    3673 +static Y_INLINE __u8 *yaffs_BlockBits(yaffs_Device * dev, int blk)
    3674 +{
    3675 +       if (blk < dev->internalStartBlock || blk > dev->internalEndBlock) {
    3676 +               T(YAFFS_TRACE_ERROR,
    3677 +                 (TSTR("**>> yaffs: BlockBits block %d is not valid" TENDSTR),
    3678 +                  blk));
    3679 +               YBUG();
    3680 +       }
    3681 +       return dev->chunkBits +
    3682 +           (dev->chunkBitmapStride * (blk - dev->internalStartBlock));
    3683 +}
    3684 +
    3685 +static Y_INLINE void yaffs_ClearChunkBits(yaffs_Device * dev, int blk)
    3686 +{
    3687 +       __u8 *blkBits = yaffs_BlockBits(dev, blk);
    3688 +
    3689 +       memset(blkBits, 0, dev->chunkBitmapStride);
    3690 +}
    3691 +
    3692 +static Y_INLINE void yaffs_ClearChunkBit(yaffs_Device * dev, int blk, int chunk)
    3693 +{
    3694 +       __u8 *blkBits = yaffs_BlockBits(dev, blk);
    3695 +
    3696 +       blkBits[chunk / 8] &= ~(1 << (chunk & 7));
    3697 +}
    3698 +
    3699 +static Y_INLINE void yaffs_SetChunkBit(yaffs_Device * dev, int blk, int chunk)
    3700 +{
    3701 +       __u8 *blkBits = yaffs_BlockBits(dev, blk);
    3702 +
    3703 +       blkBits[chunk / 8] |= (1 << (chunk & 7));
    3704 +}
    3705 +
    3706 +static Y_INLINE int yaffs_CheckChunkBit(yaffs_Device * dev, int blk, int chunk)
    3707 +{
    3708 +       __u8 *blkBits = yaffs_BlockBits(dev, blk);
    3709 +       return (blkBits[chunk / 8] & (1 << (chunk & 7))) ? 1 : 0;
    3710 +}
    3711 +
    3712 +static Y_INLINE int yaffs_StillSomeChunkBits(yaffs_Device * dev, int blk)
    3713 +{
    3714 +       __u8 *blkBits = yaffs_BlockBits(dev, blk);
    3715 +       int i;
    3716 +       for (i = 0; i < dev->chunkBitmapStride; i++) {
    3717 +               if (*blkBits)
    3718 +                       return 1;
     2723+       for(i = 0; i < dev->chunkBitmapStride; i++)
     2724+       {
     2725+               if(*blkBits) return 1;
    37192726+               blkBits++;
    37202727+       }
     
    37222729+}
    37232730+
    3724 +/*
    3725 + *  Simple hash function. Needs to have a reasonable spread
    3726 + */
    3727 +
    3728 +static Y_INLINE int yaffs_HashFunction(int n)
    3729 +{
    3730 +       n = abs(n);
     2731+
     2732+static  Y_INLINE int yaffs_HashFunction(int n)
     2733+{
    37312734+       return (n % YAFFS_NOBJECT_BUCKETS);
    37322735+}
    37332736+
    3734 +/*
    3735 + * Access functions to useful fake objects
    3736 + */
    3737 +
    3738 +yaffs_Object *yaffs_Root(yaffs_Device * dev)
     2737+
     2738+yaffs_Object *yaffs_Root(yaffs_Device *dev)
    37392739+{
    37402740+       return dev->rootDir;
    37412741+}
    37422742+
    3743 +yaffs_Object *yaffs_LostNFound(yaffs_Device * dev)
     2743+yaffs_Object *yaffs_LostNFound(yaffs_Device *dev)
    37442744+{
    37452745+       return dev->lostNFoundDir;
     
    37472747+
    37482748+
    3749 +/*
    3750 + *  Erased NAND checking functions
    3751 + */
    3752 +
    3753 +int yaffs_CheckFF(__u8 * buffer, int nBytes)
    3754 +{
    3755 +       /* Horrible, slow implementation */
    3756 +       while (nBytes--) {
    3757 +               if (*buffer != 0xFF)
     2749+
     2750+
     2751+int yaffs_CheckFF(__u8 *buffer,int nBytes)
     2752+{
     2753+       //Horrible, slow implementation
     2754+       while(nBytes--)
     2755+       {
     2756+               if(*buffer != 0xFF) return 0;
     2757+               buffer++;
     2758+       }
     2759+       return 1;
     2760+}
     2761+
     2762+static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,int chunkInNAND)
     2763+{
     2764+
     2765+       int retval = YAFFS_OK;
     2766+       __u8 *data = yaffs_GetTempBuffer(dev,__LINE__);
     2767+       yaffs_ExtendedTags tags;
     2768+
     2769+// NCB         dev->readChunkWithTagsFromNAND(dev,chunkInNAND,data,&tags);
     2770+       yaffs_ReadChunkWithTagsFromNAND(dev,chunkInNAND,data,&tags);
     2771+       
     2772+       if(!yaffs_CheckFF(data,dev->nBytesPerChunk) || tags.chunkUsed)
     2773+       {
     2774+               T(YAFFS_TRACE_NANDACCESS,(TSTR("Chunk %d not erased" TENDSTR),chunkInNAND));
     2775+               retval = YAFFS_FAIL;
     2776+       }
     2777+
     2778+       yaffs_ReleaseTempBuffer(dev,data,__LINE__);
     2779+       
     2780+       return retval;
     2781+       
     2782+}
     2783+
     2784+
     2785+
     2786+#if 1
     2787+static int yaffs_WriteNewChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev, const __u8 *data, yaffs_ExtendedTags *tags,int useReserve)
     2788+{
     2789+       int chunk;
     2790+       
     2791+       int writeOk = 1;
     2792+       int attempts = 0;
     2793+       
     2794+
     2795+       
     2796+       do{
     2797+               chunk = yaffs_AllocateChunk(dev,useReserve);
     2798+       
     2799+               if(chunk >= 0)
     2800+               {
     2801+
     2802+                       // First check this chunk is erased...
     2803+#ifndef CONFIG_YAFFS_DISABLE_CHUNK_ERASED_CHECK
     2804+                       writeOk = yaffs_CheckChunkErased(dev,chunk);
     2805+#endif         
     2806+                       if(!writeOk)
     2807+                       {
     2808+                               T(YAFFS_TRACE_ERROR,(TSTR("**>> yaffs chunk %d was not erased" TENDSTR),chunk));
     2809+                       }
     2810+                       else
     2811+                       {
     2812+                               writeOk =  yaffs_WriteChunkWithTagsToNAND(dev,chunk,data,tags);
     2813+                       }
     2814+                       attempts++;
     2815+
     2816+                       if(writeOk)
     2817+                       {
     2818+                               // Copy the data into the robustification buffer.
     2819+                               // NB We do this at the end to prevent duplicates in the case of a write error.
     2820+                               //Todo
     2821+                               yaffs_HandleWriteChunkOk(dev,chunk,data,tags);
     2822+                       }
     2823+                       else
     2824+                       {
     2825+                               yaffs_HandleWriteChunkError(dev,chunk);
     2826+                       }
     2827+               }
     2828+               
     2829+       } while(chunk >= 0 && ! writeOk);
     2830+       
     2831+       if(attempts > 1)
     2832+       {
     2833+               T(YAFFS_TRACE_ERROR,(TSTR("**>> yaffs write required %d attempts" TENDSTR),attempts));
     2834+               dev->nRetriedWrites+= (attempts - 1);   
     2835+       }
     2836+       
     2837+
     2838+       
     2839+       return chunk;
     2840+}
     2841+#endif
     2842+
     2843+
     2844+///
     2845+// Functions for robustisizing
     2846+//
     2847+//
     2848+
     2849+static void yaffs_RetireBlock(yaffs_Device *dev,int blockInNAND)
     2850+{
     2851+       
     2852+       yaffs_MarkBlockBad(dev,blockInNAND);
     2853+       
     2854+       yaffs_GetBlockInfo(dev,blockInNAND)->blockState = YAFFS_BLOCK_STATE_DEAD;
     2855+
     2856+       dev->nRetiredBlocks++;
     2857+}
     2858+
     2859+
     2860+#if 0
     2861+static int yaffs_RewriteBufferedBlock(yaffs_Device *dev)
     2862+{
     2863+       dev->doingBufferedBlockRewrite = 1;
     2864+       //
     2865+       //      Remove erased chunks
     2866+       //  Rewrite existing chunks to a new block
     2867+       //      Set current write block to the new block
     2868+       
     2869+       dev->doingBufferedBlockRewrite = 0;
     2870+       
     2871+       return 1;
     2872+}
     2873+
     2874+
     2875+static void yaffs_HandleReadDataError(yaffs_Device *dev,int chunkInNAND)
     2876+{
     2877+       int blockInNAND = chunkInNAND/dev->nChunksPerBlock;
     2878+
     2879+       // Mark the block for retirement
     2880+       yaffs_GetBlockInfo(dev,blockInNAND)->needsRetiring = 1;
     2881+       T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,(TSTR("**>>Block %d marked for retirement" TENDSTR),blockInNAND));
     2882+
     2883+
     2884+       //TODO 
     2885+       // Just do a garbage collection on the affected block then retire the block
     2886+       // NB recursion
     2887+}
     2888+
     2889+
     2890+static void yaffs_CheckWrittenBlock(yaffs_Device *dev,int chunkInNAND)
     2891+{
     2892+}
     2893+
     2894+#endif
     2895+
     2896+static void yaffs_HandleWriteChunkOk(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_ExtendedTags *tags)
     2897+{
     2898+}
     2899+
     2900+static void yaffs_HandleUpdateChunk(yaffs_Device *dev,int chunkInNAND, const yaffs_ExtendedTags *tags)
     2901+{
     2902+}
     2903+
     2904+static void yaffs_HandleWriteChunkError(yaffs_Device *dev,int chunkInNAND)
     2905+{
     2906+       int blockInNAND = chunkInNAND/dev->nChunksPerBlock;
     2907+
     2908+       // Mark the block for retirement
     2909+       yaffs_GetBlockInfo(dev,blockInNAND)->needsRetiring = 1;
     2910+       // Delete the chunk
     2911+       yaffs_DeleteChunk(dev,chunkInNAND,1,__LINE__);
     2912+}
     2913+
     2914+
     2915+
     2916+#if 0
     2917+static int yaffs_VerifyCompare(const __u8 *d0, const __u8 * d1, const yaffs_Spare *s0, const yaffs_Spare *s1,int dataSize)
     2918+{
     2919+
     2920+
     2921+       if( memcmp(d0,d1,dataSize) != 0 ||
     2922+               s0->tagByte0 != s1->tagByte0 ||
     2923+               s0->tagByte1 != s1->tagByte1 ||
     2924+               s0->tagByte2 != s1->tagByte2 ||
     2925+               s0->tagByte3 != s1->tagByte3 ||
     2926+               s0->tagByte4 != s1->tagByte4 ||
     2927+               s0->tagByte5 != s1->tagByte5 ||
     2928+               s0->tagByte6 != s1->tagByte6 ||
     2929+               s0->tagByte7 != s1->tagByte7 ||
     2930+               s0->ecc1[0]  != s1->ecc1[0]  ||
     2931+               s0->ecc1[1]  != s1->ecc1[1]  ||
     2932+               s0->ecc1[2]  != s1->ecc1[2]  ||
     2933+               s0->ecc2[0]  != s1->ecc2[0]  ||
     2934+               s0->ecc2[1]  != s1->ecc2[1]  ||
     2935+               s0->ecc2[2]  != s1->ecc2[2] )
     2936+               {
    37582937+                       return 0;
    3759 +               buffer++;
    3760 +       }
     2938+               }
     2939+       
    37612940+       return 1;
    37622941+}
    3763 +
    3764 +static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,
    3765 +                                 int chunkInNAND)
    3766 +{
    3767 +
    3768 +       int retval = YAFFS_OK;
    3769 +       __u8 *data = yaffs_GetTempBuffer(dev, __LINE__);
    3770 +       yaffs_ExtendedTags tags;
    3771 +       int result;
    3772 +
    3773 +       result = yaffs_ReadChunkWithTagsFromNAND(dev, chunkInNAND, data, &tags);
    3774 +       
    3775 +       if(tags.eccResult > YAFFS_ECC_RESULT_NO_ERROR)
    3776 +               retval = YAFFS_FAIL;
    3777 +               
    3778 +
    3779 +       if (!yaffs_CheckFF(data, dev->nDataBytesPerChunk) || tags.chunkUsed) {
    3780 +               T(YAFFS_TRACE_NANDACCESS,
    3781 +                 (TSTR("Chunk %d not erased" TENDSTR), chunkInNAND));
    3782 +               retval = YAFFS_FAIL;
    3783 +       }
    3784 +
    3785 +       yaffs_ReleaseTempBuffer(dev, data, __LINE__);
    3786 +
    3787 +       return retval;
    3788 +
    3789 +}
    3790 +
    3791 +static int yaffs_WriteNewChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev,
    3792 +                                            const __u8 * data,
    3793 +                                            yaffs_ExtendedTags * tags,
    3794 +                                            int useReserve)
    3795 +{
    3796 +       int chunk;
    3797 +
    3798 +       int writeOk = 0;
    3799 +       int erasedOk = 1;
    3800 +       int attempts = 0;
    3801 +       yaffs_BlockInfo *bi;
    3802 +       
    3803 +       yaffs_InvalidateCheckpoint(dev);
    3804 +
    3805 +       do {
    3806 +               chunk = yaffs_AllocateChunk(dev, useReserve,&bi);
    3807 +
    3808 +               if (chunk >= 0) {
    3809 +                       /* First check this chunk is erased, if it needs checking.
    3810 +                        * The checking policy (unless forced always on) is as follows:
    3811 +                        * Check the first page we try to write in a block.
    3812 +                        * - If the check passes then we don't need to check any more.
    3813 +                        * - If the check fails, we check again...
    3814 +                        * If the block has been erased, we don't need to check.
    3815 +                        *
    3816 +                        * However, if the block has been prioritised for gc, then
    3817 +                        * we think there might be something odd about this block
    3818 +                        * and stop using it.
    3819 +                        *
    3820 +                        * Rationale:
    3821 +                        * We should only ever see chunks that have not been erased
    3822 +                        * if there was a partially written chunk due to power loss
    3823 +                        * This checking policy should catch that case with very
    3824 +                        * few checks and thus save a lot of checks that are most likely not
    3825 +                        * needed.
    3826 +                        */
    3827 +                       
    3828 +                        if(bi->gcPrioritise){
    3829 +                                       yaffs_DeleteChunk(dev, chunk, 1, __LINE__);
    3830 +                       } else {
    3831 +#ifdef CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED
    3832 +
    3833 +                               bi->skipErasedCheck = 0;
    3834 +
    3835 +#endif
    3836 +                               if(!bi->skipErasedCheck){
    3837 +                                       erasedOk = yaffs_CheckChunkErased(dev, chunk);
    3838 +                                       if(erasedOk && !bi->gcPrioritise)
    3839 +                                               bi->skipErasedCheck = 1;
    3840 +                               }
    3841 +
    3842 +                               if (!erasedOk) {
    3843 +                                       T(YAFFS_TRACE_ERROR,
    3844 +                                         (TSTR
    3845 +                                          ("**>> yaffs chunk %d was not erased"
    3846 +                                           TENDSTR), chunk));
    3847 +                               } else {
    3848 +                                       writeOk =
    3849 +                                           yaffs_WriteChunkWithTagsToNAND(dev, chunk,
    3850 +                                                                          data, tags);
    3851 +                               }
    3852 +                       
    3853 +                               attempts++;
    3854 +
    3855 +                               if (writeOk) {
    3856 +                                       /*
    3857 +                                        *  Copy the data into the robustification buffer.
    3858 +                                        *  NB We do this at the end to prevent duplicates in the case of a write error.
    3859 +                                        *  Todo
    3860 +                                        */
    3861 +                                       yaffs_HandleWriteChunkOk(dev, chunk, data, tags);
    3862 +                               
    3863 +                               } else {
    3864 +                                       /* The erased check or write failed */
    3865 +                                       yaffs_HandleWriteChunkError(dev, chunk, erasedOk);
    3866 +                               }
    3867 +                       }
    3868 +               }
    3869 +
    3870 +       } while (chunk >= 0 && !writeOk);
    3871 +
    3872 +       if (attempts > 1) {
    3873 +               T(YAFFS_TRACE_ERROR,
    3874 +                 (TSTR("**>> yaffs write required %d attempts" TENDSTR),
    3875 +                  attempts));
    3876 +               dev->nRetriedWrites += (attempts - 1);
    3877 +       }
    3878 +
    3879 +       return chunk;
    3880 +}
    3881 +
    3882 +/*
    3883 + * Block retiring for handling a broken block.
    3884 + */
    3885 +
    3886 +static void yaffs_RetireBlock(yaffs_Device * dev, int blockInNAND)
    3887 +{
    3888 +       yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, blockInNAND);
    3889 +
    3890 +       yaffs_InvalidateCheckpoint(dev);
    3891 +       
    3892 +       yaffs_MarkBlockBad(dev, blockInNAND);
    3893 +
    3894 +       bi->blockState = YAFFS_BLOCK_STATE_DEAD;
    3895 +       bi->gcPrioritise = 0;
    3896 +       bi->needsRetiring = 0;
    3897 +
    3898 +       dev->nRetiredBlocks++;
    3899 +}
    3900 +
    3901 +/*
    3902 + * Functions for robustisizing TODO
    3903 + *
    3904 + */
    3905 +
    3906 +static void yaffs_HandleWriteChunkOk(yaffs_Device * dev, int chunkInNAND,
    3907 +                                    const __u8 * data,
    3908 +                                    const yaffs_ExtendedTags * tags)
    3909 +{
    3910 +}
    3911 +
    3912 +static void yaffs_HandleUpdateChunk(yaffs_Device * dev, int chunkInNAND,
    3913 +                                   const yaffs_ExtendedTags * tags)
    3914 +{
    3915 +}
    3916 +
    3917 +void yaffs_HandleChunkError(yaffs_Device *dev, yaffs_BlockInfo *bi)
    3918 +{
    3919 +       if(!bi->gcPrioritise){
    3920 +               bi->gcPrioritise = 1;
    3921 +               dev->hasPendingPrioritisedGCs = 1;
    3922 +               bi->chunkErrorStrikes ++;
    3923 +               
    3924 +               if(bi->chunkErrorStrikes > 3){
    3925 +                       bi->needsRetiring = 1; /* Too many stikes, so retire this */
    3926 +                       T(YAFFS_TRACE_ALWAYS, (TSTR("yaffs: Block struck out" TENDSTR)));
    3927 +
    3928 +               }
    3929 +               
    3930 +       }
    3931 +}
    3932 +
    3933 +static void yaffs_ReportOddballBlocks(yaffs_Device *dev)
    3934 +{
    3935 +       int i;
    3936 +               
    3937 +       for(i = dev->internalStartBlock; i <= dev->internalEndBlock && (yaffs_traceMask & YAFFS_TRACE_BAD_BLOCKS); i++){
    3938 +               yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,i);
    3939 +               if(bi->needsRetiring || bi->gcPrioritise)
    3940 +                       T(YAFFS_TRACE_BAD_BLOCKS,(TSTR("yaffs block %d%s%s" TENDSTR),
    3941 +                               i,
    3942 +                               bi->needsRetiring ? " needs retiring" : "",
    3943 +                               bi->gcPrioritise ?  " gc prioritised" : ""));
    3944 +               
    3945 +       }
    3946 +}
    3947 +
    3948 +static void yaffs_HandleWriteChunkError(yaffs_Device * dev, int chunkInNAND, int erasedOk)
    3949 +{
    3950 +
    3951 +       int blockInNAND = chunkInNAND / dev->nChunksPerBlock;
    3952 +       yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, blockInNAND);
    3953 +
    3954 +       yaffs_HandleChunkError(dev,bi);
    3955 +               
    3956 +       
    3957 +       if(erasedOk ) {
    3958 +               /* Was an actual write failure, so mark the block for retirement  */
    3959 +               bi->needsRetiring = 1;
    3960 +               T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,
    3961 +                 (TSTR("**>> Block %d needs retiring" TENDSTR), blockInNAND));
    3962 +
    3963 +               
    3964 +       }
    3965 +       
    3966 +       /* Delete the chunk */
    3967 +       yaffs_DeleteChunk(dev, chunkInNAND, 1, __LINE__);
    3968 +}
    3969 +
    3970 +
    3971 +/*---------------- Name handling functions ------------*/
    3972 +
    3973 +static __u16 yaffs_CalcNameSum(const YCHAR * name)
     2942+#endif
     2943+
     2944+
     2945+///////////////////////// Object management //////////////////
     2946+// List of spare objects
     2947+// The list is hooked together using the first pointer
     2948+// in the object
     2949+
     2950+// static yaffs_Object *yaffs_freeObjects = NULL;
     2951+
     2952+// static int yaffs_nFreeObjects;
     2953+
     2954+// static yaffs_ObjectList *yaffs_allocatedObjectList = NULL;
     2955+
     2956+// static yaffs_ObjectBucket yaffs_objectBucket[YAFFS_NOBJECT_BUCKETS];
     2957+
     2958+
     2959+static __u16 yaffs_CalcNameSum(const YCHAR *name)
    39742960+{
    39752961+       __u16 sum = 0;
    39762962+       __u16 i = 1;
    3977 +
    3978 +       YUCHAR *bname = (YUCHAR *) name;
    3979 +       if (bname) {
    3980 +               while ((*bname) && (i <= YAFFS_MAX_NAME_LENGTH)) {
     2963+       
     2964+       YUCHAR *bname = (YUCHAR *)name;
     2965+       if(bname)
     2966+       {
     2967+               while ((*bname) && (i <=YAFFS_MAX_NAME_LENGTH))
     2968+               {
    39812969+
    39822970+#ifdef CONFIG_YAFFS_CASE_INSENSITIVE
     
    39922980+}
    39932981+
    3994 +static void yaffs_SetObjectName(yaffs_Object * obj, const YCHAR * name)
     2982+static void yaffs_SetObjectName(yaffs_Object *obj, const YCHAR *name)
    39952983+{
    39962984+#ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM
    3997 +       if (name && yaffs_strlen(name) <= YAFFS_SHORT_NAME_LENGTH) {
    3998 +               yaffs_strcpy(obj->shortName, name);
    3999 +       } else {
    4000 +               obj->shortName[0] = _Y('\0');
    4001 +       }
    4002 +#endif
    4003 +       obj->sum = yaffs_CalcNameSum(name);
    4004 +}
    4005 +
    4006 +/*-------------------- TNODES -------------------
    4007 +
    4008 + * List of spare tnodes
    4009 + * The list is hooked together using the first pointer
    4010 + * in the tnode.
    4011 + */
    4012 +
    4013 +/* yaffs_CreateTnodes creates a bunch more tnodes and
    4014 + * adds them to the tnode free list.
    4015 + * Don't use this function directly
    4016 + */
    4017 +
    4018 +static int yaffs_CreateTnodes(yaffs_Device * dev, int nTnodes)
    4019 +{
    4020 +       int i;
    4021 +       int tnodeSize;
    4022 +       yaffs_Tnode *newTnodes;
    4023 +       __u8 *mem;
    4024 +       yaffs_Tnode *curr;
    4025 +       yaffs_Tnode *next;
    4026 +       yaffs_TnodeList *tnl;
    4027 +
    4028 +       if (nTnodes < 1)
    4029 +               return YAFFS_OK;
    4030 +               
    4031 +       /* Calculate the tnode size in bytes for variable width tnode support.
    4032 +        * Must be a multiple of 32-bits  */
    4033 +       tnodeSize = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
    4034 +
    4035 +       /* make these things */
    4036 +
    4037 +       newTnodes = YMALLOC(nTnodes * tnodeSize);
    4038 +       mem = (__u8 *)newTnodes;
    4039 +
    4040 +       if (!newTnodes) {
    4041 +               T(YAFFS_TRACE_ERROR,
    4042 +                 (TSTR("yaffs: Could not allocate Tnodes" TENDSTR)));
     2985+                                       if(name && yaffs_strlen(name) <= YAFFS_SHORT_NAME_LENGTH)
     2986+                                       {
     2987+                                               yaffs_strcpy(obj->shortName,name);
     2988+                                       }
     2989+                                       else
     2990+                                       {
     2991+                                               obj->shortName[0]=_Y('\0');
     2992+                                       }
     2993+#endif
     2994+                                       obj->sum = yaffs_CalcNameSum(name);
     2995+}
     2996+
     2997+#if 0
     2998+void yaffs_CalcECC(const __u8 *data, yaffs_Spare *spare)
     2999+{
     3000+       yaffs_ECCCalculate(data , spare->ecc1);
     3001+       yaffs_ECCCalculate(&data[256] , spare->ecc2);
     3002+}
     3003+#endif
     3004+
     3005+
     3006+///////////////////////// TNODES ///////////////////////
     3007+
     3008+// List of spare tnodes
     3009+// The list is hooked together using the first pointer
     3010+// in the tnode.
     3011+
     3012+//static yaffs_Tnode *yaffs_freeTnodes = NULL;
     3013+
     3014+// static int yaffs_nFreeTnodes;
     3015+
     3016+//static yaffs_TnodeList *yaffs_allocatedTnodeList = NULL;
     3017+
     3018+
     3019+
     3020+// yaffs_CreateTnodes creates a bunch more tnodes and
     3021+// adds them to the tnode free list.
     3022+// Don't use this function directly
     3023+
     3024+static int yaffs_CreateTnodes(yaffs_Device *dev,int nTnodes)
     3025+{
     3026+    int i;
     3027+    yaffs_Tnode *newTnodes;
     3028+    yaffs_TnodeList *tnl;
     3029+   
     3030+    if(nTnodes < 1) return YAFFS_OK;
     3031+   
     3032+       // make these things
     3033+       
     3034+    newTnodes = YMALLOC(nTnodes * sizeof(yaffs_Tnode));
     3035+   
     3036+    if (!newTnodes)
     3037+    {
     3038+               T(YAFFS_TRACE_ERROR,(TSTR("yaffs: Could not allocate Tnodes"TENDSTR)));
    40433039+               return YAFFS_FAIL;
    4044 +       }
    4045 +
    4046 +       /* Hook them into the free list */
    4047 +#if 0
    4048 +       for (i = 0; i < nTnodes - 1; i++) {
    4049 +               newTnodes[i].internal[0] = &newTnodes[i + 1];
     3040+    }
     3041+   
     3042+    // Hook them into the free list
     3043+    for(i = 0; i < nTnodes - 1; i++)
     3044+    {
     3045+       newTnodes[i].internal[0] = &newTnodes[i+1];
    40503046+#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG
    4051 +               newTnodes[i].internal[YAFFS_NTNODES_INTERNAL] = (void *)1;
    4052 +#endif
    4053 +       }
    4054 +
     3047+       newTnodes[i].internal[YAFFS_NTNODES_INTERNAL] = (void *)1;
     3048+#endif
     3049+    }
     3050+       
    40553051+       newTnodes[nTnodes - 1].internal[0] = dev->freeTnodes;
    40563052+#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG
    4057 +       newTnodes[nTnodes - 1].internal[YAFFS_NTNODES_INTERNAL] = (void *)1;
     3053+       newTnodes[nTnodes - 1].internal[YAFFS_NTNODES_INTERNAL] = (void *)1;
    40583054+#endif
    40593055+       dev->freeTnodes = newTnodes;
    4060 +#else
    4061 +       /* New hookup for wide tnodes */
    4062 +       for(i = 0; i < nTnodes -1; i++) {
    4063 +               curr = (yaffs_Tnode *) &mem[i * tnodeSize];
    4064 +               next = (yaffs_Tnode *) &mem[(i+1) * tnodeSize];
    4065 +               curr->internal[0] = next;
    4066 +       }
    4067 +       
    4068 +       curr = (yaffs_Tnode *) &mem[(nTnodes - 1) * tnodeSize];
    4069 +       curr->internal[0] = dev->freeTnodes;
    4070 +       dev->freeTnodes = (yaffs_Tnode *)mem;
    4071 +
    4072 +#endif
    4073 +
    4074 +
    4075 +       dev->nFreeTnodes += nTnodes;
     3056+       dev->nFreeTnodes+= nTnodes;
    40763057+       dev->nTnodesCreated += nTnodes;
    40773058+
    4078 +       /* Now add this bunch of tnodes to a list for freeing up.
    4079 +        * NB If we can't add this to the management list it isn't fatal
    4080 +        * but it just means we can't free this bunch of tnodes later.
    4081 +        */
    4082 +       
     3059+       // Now add this bunch of tnodes to a list for freeing up.
     3060+       // NB If we can't add this to the management list it isn't fatal
     3061+       // but it just means we can't free this bunch of tnodes later.
    40833062+       tnl = YMALLOC(sizeof(yaffs_TnodeList));
    4084 +       if (!tnl) {
    4085 +               T(YAFFS_TRACE_ERROR,
    4086 +                 (TSTR
    4087 +                  ("yaffs: Could not add tnodes to management list" TENDSTR)));
    4088 +
    4089 +       } else {
     3063+       if(!tnl)
     3064+       {
     3065+               T(YAFFS_TRACE_ERROR,(TSTR("yaffs: Could not add tnodes to management list" TENDSTR)));
     3066+               
     3067+       }
     3068+       else
     3069+       {
    40903070+               tnl->tnodes = newTnodes;
    40913071+               tnl->next = dev->allocatedTnodeList;
     
    40933073+       }
    40943074+
    4095 +       T(YAFFS_TRACE_ALLOCATE, (TSTR("yaffs: Tnodes added" TENDSTR)));
     3075+
     3076+       T(YAFFS_TRACE_ALLOCATE,(TSTR("yaffs: Tnodes added" TENDSTR)));
     3077+
    40963078+
    40973079+       return YAFFS_OK;
    40983080+}
    40993081+
    4100 +/* GetTnode gets us a clean tnode. Tries to make allocate more if we run out */
    4101 +
    4102 +static yaffs_Tnode *yaffs_GetTnodeRaw(yaffs_Device * dev)
     3082+
     3083+// GetTnode gets us a clean tnode. Tries to make allocate more if we run out
     3084+static yaffs_Tnode *yaffs_GetTnode(yaffs_Device *dev)
    41033085+{
    41043086+       yaffs_Tnode *tn = NULL;
    4105 +
    4106 +       /* If there are none left make more */
    4107 +       if (!dev->freeTnodes) {
    4108 +               yaffs_CreateTnodes(dev, YAFFS_ALLOCATION_NTNODES);
    4109 +       }
    4110 +
    4111 +       if (dev->freeTnodes) {
     3087+       
     3088+       // If there are none left make more
     3089+       if(!dev->freeTnodes)
     3090+       {
     3091+               yaffs_CreateTnodes(dev,YAFFS_ALLOCATION_NTNODES);
     3092+       }
     3093+       
     3094+       if(dev->freeTnodes)
     3095+       {
    41123096+               tn = dev->freeTnodes;
    41133097+#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG
    4114 +               if (tn->internal[YAFFS_NTNODES_INTERNAL] != (void *)1) {
    4115 +                       /* Hoosterman, this thing looks like it isn't in the list */
    4116 +                       T(YAFFS_TRACE_ALWAYS,
    4117 +                         (TSTR("yaffs: Tnode list bug 1" TENDSTR)));
     3098+       if(tn->internal[YAFFS_NTNODES_INTERNAL] != (void *)1)
     3099+               {
     3100+                       // Hoosterman, this thing looks like it isn't in the list
     3101+                               T(YAFFS_TRACE_ALWAYS,(TSTR("yaffs: Tnode list bug 1" TENDSTR)));
    41183102+               }
    41193103+#endif
    41203104+               dev->freeTnodes = dev->freeTnodes->internal[0];
    41213105+               dev->nFreeTnodes--;
    4122 +       }
     3106+               // zero out
     3107+               memset(tn,0,sizeof(yaffs_Tnode));
     3108+       }
     3109+       
    41233110+
    41243111+       return tn;
    41253112+}
    41263113+
    4127 +static yaffs_Tnode *yaffs_GetTnode(yaffs_Device * dev)
    4128 +{
    4129 +       yaffs_Tnode *tn = yaffs_GetTnodeRaw(dev);
    4130 +       
     3114+
     3115+// FreeTnode frees up a tnode and puts it back on the free list
     3116+static void yaffs_FreeTnode(yaffs_Device*dev, yaffs_Tnode *tn)
     3117+{
    41313118+       if(tn)
    4132 +               memset(tn, 0, (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8);
    4133 +
    4134 +       return tn;     
    4135 +}
    4136 +
    4137 +/* FreeTnode frees up a tnode and puts it back on the free list */
    4138 +static void yaffs_FreeTnode(yaffs_Device * dev, yaffs_Tnode * tn)
    4139 +{
    4140 +       if (tn) {
     3119+       {
    41413120+#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG
    4142 +               if (tn->internal[YAFFS_NTNODES_INTERNAL] != 0) {
    4143 +                       /* Hoosterman, this thing looks like it is already in the list */
    4144 +                       T(YAFFS_TRACE_ALWAYS,
    4145 +                         (TSTR("yaffs: Tnode list bug 2" TENDSTR)));
     3121+       if(tn->internal[YAFFS_NTNODES_INTERNAL] != 0)
     3122+               {
     3123+                       // Hoosterman, this thing looks like it is already in the list
     3124+                               T(YAFFS_TRACE_ALWAYS,(TSTR("yaffs: Tnode list bug 2" TENDSTR)));
    41463125+               }
    41473126+               tn->internal[YAFFS_NTNODES_INTERNAL] = (void *)1;
     
    41533132+}
    41543133+
    4155 +static void yaffs_DeinitialiseTnodes(yaffs_Device * dev)
    4156 +{
    4157 +       /* Free the list of allocated tnodes */
     3134+
     3135+static void yaffs_DeinitialiseTnodes(yaffs_Device*dev)
     3136+{
     3137+       // Free the list of allocated tnodes
    41583138+       yaffs_TnodeList *tmp;
    4159 +
    4160 +       while (dev->allocatedTnodeList) {
    4161 +               tmp = dev->allocatedTnodeList->next;
     3139+               
     3140+       while(dev->allocatedTnodeList)
     3141+       {
     3142+               tmp =  dev->allocatedTnodeList->next;
    41623143+
    41633144+               YFREE(dev->allocatedTnodeList->tnodes);
    41643145+               YFREE(dev->allocatedTnodeList);
    4165 +               dev->allocatedTnodeList = tmp;
    4166 +
    4167 +       }
    4168 +
     3146+               dev->allocatedTnodeList = tmp;
     3147+               
     3148+       }
     3149+       
    41693150+       dev->freeTnodes = NULL;
    41703151+       dev->nFreeTnodes = 0;
    41713152+}
    41723153+
    4173 +static void yaffs_InitialiseTnodes(yaffs_Device * dev)
     3154+static void yaffs_InitialiseTnodes(yaffs_Device*dev)
    41743155+{
    41753156+       dev->allocatedTnodeList = NULL;
     
    41803161+}
    41813162+
    4182 +
    4183 +void yaffs_PutLevel0Tnode(yaffs_Device *dev, yaffs_Tnode *tn, unsigned pos, unsigned val)
    4184 +{
    4185 +  __u32 *map = (__u32 *)tn;
    4186 +  __u32 bitInMap;
    4187 +  __u32 bitInWord;
    4188 +  __u32 wordInMap;
    4189 +  __u32 mask;
    4190 
    4191 +  pos &= YAFFS_TNODES_LEVEL0_MASK;
    4192 +  val >>= dev->chunkGroupBits;
    4193 
    4194 +  bitInMap = pos * dev->tnodeWidth;
    4195 +  wordInMap = bitInMap /32;
    4196 +  bitInWord = bitInMap & (32 -1);
    4197 
    4198 +  mask = dev->tnodeMask << bitInWord;
    4199 
    4200 +  map[wordInMap] &= ~mask;
    4201 +  map[wordInMap] |= (mask & (val << bitInWord));
    4202 
    4203 +  if(dev->tnodeWidth > (32-bitInWord)) {
    4204 +    bitInWord = (32 - bitInWord);
    4205 +    wordInMap++;;
    4206 +    mask = dev->tnodeMask >> (/*dev->tnodeWidth -*/ bitInWord);
    4207 +    map[wordInMap] &= ~mask;
    4208 +    map[wordInMap] |= (mask & (val >> bitInWord));
    4209 +  }
    4210 +}
    4211 +
    4212 +__u32 yaffs_GetChunkGroupBase(yaffs_Device *dev, yaffs_Tnode *tn, unsigned pos)
    4213 +{
    4214 +  __u32 *map = (__u32 *)tn;
    4215 +  __u32 bitInMap;
    4216 +  __u32 bitInWord;
    4217 +  __u32 wordInMap;
    4218 +  __u32 val;
    4219 
    4220 +  pos &= YAFFS_TNODES_LEVEL0_MASK;
    4221 
    4222 +  bitInMap = pos * dev->tnodeWidth;
    4223 +  wordInMap = bitInMap /32;
    4224 +  bitInWord = bitInMap & (32 -1);
    4225 
    4226 +  val = map[wordInMap] >> bitInWord;
    4227 
    4228 +  if(dev->tnodeWidth > (32-bitInWord)) {
    4229 +    bitInWord = (32 - bitInWord);
    4230 +    wordInMap++;;
    4231 +    val |= (map[wordInMap] << bitInWord);
    4232 +  }
    4233 
    4234 +  val &= dev->tnodeMask;
    4235 +  val <<= dev->chunkGroupBits;
    4236 
    4237 +  return val;
    4238 +}
    4239 +
    4240 +/* ------------------- End of individual tnode manipulation -----------------*/
    4241 +
    4242 +/* ---------Functions to manipulate the look-up tree (made up of tnodes) ------
    4243 + * The look up tree is represented by the top tnode and the number of topLevel
    4244 + * in the tree. 0 means only the level 0 tnode is in the tree.
    4245 + */
    4246 +
    4247 +/* FindLevel0Tnode finds the level 0 tnode, if one exists. */
    4248 +static yaffs_Tnode *yaffs_FindLevel0Tnode(yaffs_Device * dev,
    4249 +                                         yaffs_FileStructure * fStruct,
    4250 +                                         __u32 chunkId)
    4251 +{
    4252 +
     3163+#if 0
     3164+void yaffs_TnodeTest(yaffs_Device *dev)
     3165+{
     3166+
     3167+       int i;
     3168+       int j;
     3169+       yaffs_Tnode *tn[1000];
     3170+       
     3171+       YINFO("Testing TNodes");
     3172+       
     3173+       for(j = 0; j < 50; j++)
     3174+       {
     3175+               for(i = 0; i < 1000; i++)
     3176+               {
     3177+                       tn[i] = yaffs_GetTnode(dev);
     3178+                       if(!tn[i])
     3179+                       {
     3180+                               YALERT("Getting tnode failed");
     3181+                       }
     3182+               }
     3183+               for(i = 0; i < 1000; i+=3)
     3184+               {
     3185+                       yaffs_FreeTnode(dev,tn[i]);
     3186+                       tn[i] = NULL;
     3187+               }
     3188+               
     3189+       }
     3190+}
     3191+#endif
     3192+
     3193+
     3194+////////////////// END OF TNODE MANIPULATION ///////////////////////////
     3195+
     3196+/////////////// Functions to manipulate the look-up tree (made up of tnodes)
     3197+// The look up tree is represented by the top tnode and the number of topLevel
     3198+// in the tree. 0 means only the level 0 tnode is in the tree.
     3199+
     3200+
     3201+// FindLevel0Tnode finds the level 0 tnode, if one exists.
     3202+// Used when reading.....
     3203+static yaffs_Tnode *yaffs_FindLevel0Tnode(yaffs_Device *dev,yaffs_FileStructure *fStruct, __u32 chunkId)
     3204+{
     3205+       
    42533206+       yaffs_Tnode *tn = fStruct->top;
    42543207+       __u32 i;
    4255 +       int requiredTallness;
     3208+       int requiredTallness;   
    42563209+       int level = fStruct->topLevel;
    4257 +
    4258 +       /* Check sane level and chunk Id */
    4259 +       if (level < 0 || level > YAFFS_TNODES_MAX_LEVEL) {
     3210+       
     3211+       // Check sane level and chunk Id
     3212+       if(level < 0 || level > YAFFS_TNODES_MAX_LEVEL)
     3213+       {
     3214+//             char str[50];
     3215+//             sprintf(str,"Bad level %d",level);
     3216+//             YALERT(str);
    42603217+               return NULL;
    42613218+       }
    4262 +
    4263 +       if (chunkId > YAFFS_MAX_CHUNK_ID) {
     3219+       
     3220+       if(chunkId > YAFFS_MAX_CHUNK_ID)
     3221+       {
     3222+//             char str[50];
     3223+//             sprintf(str,"Bad chunkId %d",chunkId);
     3224+//             YALERT(str);
    42643225+               return NULL;
    42653226+       }
    42663227+
    4267 +       /* First check we're tall enough (ie enough topLevel) */
    4268 +
    4269 +       i = chunkId >> YAFFS_TNODES_LEVEL0_BITS;
     3228+       // First check we're tall enough (ie enough topLevel)
     3229+       
     3230+       i = chunkId >> (/*dev->chunkGroupBits  + */YAFFS_TNODES_LEVEL0_BITS);
    42703231+       requiredTallness = 0;
    4271 +       while (i) {
     3232+       while(i)
     3233+       {
    42723234+               i >>= YAFFS_TNODES_INTERNAL_BITS;
    42733235+               requiredTallness++;
    42743236+       }
    4275 +
    4276 +       if (requiredTallness > fStruct->topLevel) {
    4277 +               /* Not tall enough, so we can't find it, return NULL. */
     3237+       
     3238+       
     3239+       if(requiredTallness > fStruct->topLevel)
     3240+       {
     3241+               // Not tall enough, so we can't find it, return NULL.
    42783242+               return NULL;
    42793243+       }
    4280 +
    4281 +       /* Traverse down to level 0 */
    4282 +       while (level > 0 && tn) {
    4283 +               tn = tn->
    4284 +                   internal[(chunkId >>
    4285 +                              ( YAFFS_TNODES_LEVEL0_BITS +
    4286 +                                (level - 1) *
    4287 +                                YAFFS_TNODES_INTERNAL_BITS)
    4288 +                             ) &
    4289 +                            YAFFS_TNODES_INTERNAL_MASK];
     3244+               
     3245+       
     3246+       // Traverse down to level 0
     3247+       while (level > 0 && tn)
     3248+       {
     3249+           tn = tn->internal[(chunkId >>(/* dev->chunkGroupBits + */ YAFFS_TNODES_LEVEL0_BITS + (level-1) * YAFFS_TNODES_INTERNAL_BITS)) &
     3250+                              YAFFS_TNODES_INTERNAL_MASK];
    42903251+               level--;
    4291 +
    4292 +       }
    4293 +
    4294 +       return tn;
    4295 +}
    4296 +
    4297 +/* AddOrFindLevel0Tnode finds the level 0 tnode if it exists, otherwise first expands the tree.
    4298 + * This happens in two steps:
    4299 + *  1. If the tree isn't tall enough, then make it taller.
    4300 + *  2. Scan down the tree towards the level 0 tnode adding tnodes if required.
    4301 + *
    4302 + * Used when modifying the tree.
    4303 + *
    4304 + *  If the tn argument is NULL, then a fresh tnode will be added otherwise the specified tn will
    4305 + *  be plugged into the ttree.
    4306 + */
    4307 +
    4308 +static yaffs_Tnode *yaffs_AddOrFindLevel0Tnode(yaffs_Device * dev,
    4309 +                                              yaffs_FileStructure * fStruct,
    4310 +                                              __u32 chunkId,
    4311 +                                              yaffs_Tnode *passedTn)
    4312 +{
    4313 +
     3252+       
     3253+       }
     3254+       
     3255+       return tn;             
     3256+}
     3257+
     3258+// AddOrFindLevel0Tnode finds the level 0 tnode if it exists, otherwise first expands the tree.
     3259+// This happens in two steps:
     3260+//  1. If the tree isn't tall enough, then make it taller.
     3261+//  2. Scan down the tree towards the level 0 tnode adding tnodes if required.
     3262+//
     3263+// Used when modifying the tree.
     3264+//
     3265+static yaffs_Tnode *yaffs_AddOrFindLevel0Tnode(yaffs_Device *dev, yaffs_FileStructure *fStruct, __u32 chunkId)
     3266+{
     3267+       
     3268+       yaffs_Tnode *tn;
     3269+       
    43143270+       int requiredTallness;
    43153271+       int i;
    43163272+       int l;
    4317 +       yaffs_Tnode *tn;
    4318 +
     3273+       
    43193274+       __u32 x;
    4320 +
    4321 +
    4322 +       /* Check sane level and page Id */
    4323 +       if (fStruct->topLevel < 0 || fStruct->topLevel > YAFFS_TNODES_MAX_LEVEL) {
     3275+               
     3276+       
     3277+       //T((TSTR("AddOrFind topLevel=%d, chunk=%d"),fStruct->topLevel,chunkId));
     3278+       
     3279+       // Check sane level and page Id
     3280+       if(fStruct->topLevel < 0 || fStruct->topLevel > YAFFS_TNODES_MAX_LEVEL)
     3281+       {
     3282+//             char str[50];
     3283+//             sprintf(str,"Bad level %d",fStruct->topLevel);
     3284+//             YALERT(str);
    43243285+               return NULL;
    43253286+       }
    4326 +
    4327 +       if (chunkId > YAFFS_MAX_CHUNK_ID) {
     3287+       
     3288+       if(chunkId > YAFFS_MAX_CHUNK_ID)
     3289+       {
     3290+//             char str[50];
     3291+//             sprintf(str,"Bad chunkId %d",chunkId);
     3292+//             YALERT(str);
    43283293+               return NULL;
    43293294+       }
    4330 +
    4331 +       /* First check we're tall enough (ie enough topLevel) */
    4332 +
    4333 +       x = chunkId >> YAFFS_TNODES_LEVEL0_BITS;
     3295+       
     3296+       // First check we're tall enough (ie enough topLevel)
     3297+       
     3298+       x = chunkId >> (/*dev->chunkGroupBits + */YAFFS_TNODES_LEVEL0_BITS);
    43343299+       requiredTallness = 0;
    4335 +       while (x) {
     3300+       while(x)
     3301+       {
    43363302+               x >>= YAFFS_TNODES_INTERNAL_BITS;
    43373303+               requiredTallness++;
    43383304+       }
    4339 +
    4340 +
    4341 +       if (requiredTallness > fStruct->topLevel) {
    4342 +               /* Not tall enough,gotta make the tree taller */
    4343 +               for (i = fStruct->topLevel; i < requiredTallness; i++) {
    4344 +               
     3305+       
     3306+       //T((TSTR(" required=%d"),requiredTallness));
     3307+       
     3308+       
     3309+       if(requiredTallness > fStruct->topLevel)
     3310+       {
     3311+               // Not tall enough,gotta make the tree taller
     3312+               for(i = fStruct->topLevel; i < requiredTallness; i++)
     3313+               {
     3314+                       //T((TSTR(" add new top")));
     3315+                       
    43453316+                       tn = yaffs_GetTnode(dev);
    4346 +
    4347 +                       if (tn) {
     3317+                       
     3318+                       if(tn)
     3319+                       {
    43483320+                               tn->internal[0] = fStruct->top;
    43493321+                               fStruct->top = tn;
    4350 +                       } else {
    4351 +                               T(YAFFS_TRACE_ERROR,
    4352 +                                 (TSTR("yaffs: no more tnodes" TENDSTR)));
    43533322+                       }
    4354 +               }
    4355 +
     3323+                       else
     3324+                       {
     3325+                                       T(YAFFS_TRACE_ERROR,(TSTR("yaffs: no more tnodes" TENDSTR)));
     3326+                       }
     3327+               }
     3328+               
    43563329+               fStruct->topLevel = requiredTallness;
    43573330+       }
    4358 +
    4359 +       /* Traverse down to level 0, adding anything we need */
    4360 +
     3331+       
     3332+       
     3333+       // Traverse down to level 0, adding anything we need
     3334+       
    43613335+       l = fStruct->topLevel;
    43623336+       tn = fStruct->top;
    4363 +       
    4364 +       if(l > 0) {
    4365 +               while (l > 0 && tn) {
    4366 +                       x = (chunkId >>
    4367 +                            ( YAFFS_TNODES_LEVEL0_BITS +
    4368 +                             (l - 1) * YAFFS_TNODES_INTERNAL_BITS)) &
    4369 +                           YAFFS_TNODES_INTERNAL_MASK;
    4370 +
    4371 +
    4372 +                       if((l>1) && !tn->internal[x]){
    4373 +                               /* Add missing non-level-zero tnode */
    4374 +                               tn->internal[x] = yaffs_GetTnode(dev);
    4375 +
    4376 +                       } else if(l == 1) {
    4377 +                               /* Looking from level 1 at level 0 */
    4378 +                               if (passedTn) {
    4379 +                                       /* If we already have one, then release it.*/
    4380 +                                       if(tn->internal[x])
    4381 +                                               yaffs_FreeTnode(dev,tn->internal[x]);
    4382 +                                       tn->internal[x] = passedTn;
    4383 +                       
    4384 +                               } else if(!tn->internal[x]) {
    4385 +                                       /* Don't have one, none passed in */
    4386 +                                       tn->internal[x] = yaffs_GetTnode(dev);
    4387 +                               }
     3337+       while (l > 0 && tn)
     3338+       {
     3339+               x = (chunkId >> (/*dev->chunkGroupBits + */YAFFS_TNODES_LEVEL0_BITS + (l-1) * YAFFS_TNODES_INTERNAL_BITS)) &
     3340+                              YAFFS_TNODES_INTERNAL_MASK;
     3341+                             
     3342+               //T((TSTR(" [%d:%d]"),l,i));
     3343+               
     3344+           if(!tn->internal[x])
     3345+           {
     3346+               //T((TSTR(" added")));
     3347+               
     3348+               tn->internal[x] = yaffs_GetTnode(dev);
     3349+           }
     3350+           
     3351+           tn =        tn->internal[x];
     3352+               l--;
     3353+       
     3354+       }
     3355+       
     3356+       //TSTR(TENDSTR)));
     3357+       
     3358+       return tn;             
     3359+}
     3360+
     3361+
     3362+static int yaffs_FindChunkInGroup(yaffs_Device *dev, int theChunk, yaffs_ExtendedTags *tags, int objectId, int chunkInInode)
     3363+{
     3364+       int j;
     3365+       
     3366+                                       
     3367+       for(j = 0; theChunk && j < dev->chunkGroupSize; j++)
     3368+       {
     3369+               if(yaffs_CheckChunkBit(dev,theChunk / dev->nChunksPerBlock,theChunk % dev->nChunksPerBlock))
     3370+               {
     3371+                       yaffs_ReadChunkWithTagsFromNAND(dev,theChunk,NULL,tags);
     3372+                       if(yaffs_TagsMatch(tags,objectId,chunkInInode))
     3373+                       {
     3374+                               // found it;
     3375+                               return theChunk;
     3376+                                       
    43883377+                       }
    4389 +               
    4390 +                       tn = tn->internal[x];
    4391 +                       l--;
    4392 +               }
    4393 +       } else {
    4394 +               /* top is level 0 */
    4395 +               if(passedTn) {
    4396 +                       memcpy(tn,passedTn,(dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8);
    4397 +                       yaffs_FreeTnode(dev,passedTn);
    4398 +               }
    4399 +       }
    4400 +
    4401 +       return tn;
    4402 +}
    4403 +
    4404 +static int yaffs_FindChunkInGroup(yaffs_Device * dev, int theChunk,
    4405 +                                 yaffs_ExtendedTags * tags, int objectId,
    4406 +                                 int chunkInInode)
    4407 +{
    4408 +       int j;
    4409 +
    4410 +       for (j = 0; theChunk && j < dev->chunkGroupSize; j++) {
    4411 +               if (yaffs_CheckChunkBit
    4412 +                   (dev, theChunk / dev->nChunksPerBlock,
    4413 +                    theChunk % dev->nChunksPerBlock)) {
    4414 +                       yaffs_ReadChunkWithTagsFromNAND(dev, theChunk, NULL,
    4415 +                                                       tags);
    4416 +                       if (yaffs_TagsMatch(tags, objectId, chunkInInode)) {
    4417 +                               /* found it; */
    4418 +                               return theChunk;
    4419 +
    4420 +                       }
    44213378+               }
    44223379+               theChunk++;
     
    44253382+}
    44263383+
    4427 +
    4428 +/* DeleteWorker scans backwards through the tnode tree and deletes all the
    4429 + * chunks and tnodes in the file
    4430 + * Returns 1 if the tree was deleted.
    4431 + * Returns 0 if it stopped early due to hitting the limit and the delete is incomplete.
    4432 + */
    4433 +
    4434 +static int yaffs_DeleteWorker(yaffs_Object * in, yaffs_Tnode * tn, __u32 level,
    4435 +                             int chunkOffset, int *limit)
     3384+// DeleteWorker scans backwards through the tnode tree and deletes all the
     3385+// chunks and tnodes in the file
     3386+// Returns 1 if the tree was deleted. Returns 0 if it stopped early due to hitting the limit and the delete is incomplete.
     3387+
     3388+static int yaffs_DeleteWorker(yaffs_Object *in, yaffs_Tnode *tn, __u32 level, int chunkOffset,int *limit)
    44363389+{
    44373390+       int i;
     
    44433396+
    44443397+       int allDone = 1;
    4445 +
    4446 +       if (tn) {
    4447 +               if (level > 0) {
    4448 +
    4449 +                       for (i = YAFFS_NTNODES_INTERNAL - 1; allDone && i >= 0;
    4450 +                            i--) {
    4451 +                               if (tn->internal[i]) {
    4452 +                                       if (limit && (*limit) < 0) {
     3398+       
     3399+       
     3400+       if(tn)
     3401+       {
     3402+               if(level > 0)
     3403+               {
     3404+               
     3405+                       for(i = YAFFS_NTNODES_INTERNAL -1; allDone && i >= 0; i--)
     3406+                       {
     3407+                           if(tn->internal[i])
     3408+                       {
     3409+                                       if(limit && (*limit) < 0)
     3410+                                       {
    44533411+                                               allDone = 0;
    4454 +                                       } else {
    4455 +                                               allDone =
    4456 +                                                   yaffs_DeleteWorker(in,
    4457 +                                                                      tn->
    4458 +                                                                      internal
    4459 +                                                                      [i],
    4460 +                                                                      level -
    4461 +                                                                      1,
    4462 +                                                                      (chunkOffset
    4463 +                                                                       <<
    4464 +                                                                       YAFFS_TNODES_INTERNAL_BITS)
    4465 +                                                                      + i,
    4466 +                                                                      limit);
    44673412+                                       }
    4468 +                                       if (allDone) {
    4469 +                                               yaffs_FreeTnode(dev,
    4470 +                                                               tn->
    4471 +                                                               internal[i]);
    4472 +                                               tn->internal[i] = NULL;
     3413+                                       else
     3414+                                       {
     3415+                                               allDone = yaffs_DeleteWorker(in,tn->internal[i],level - 1,
     3416+                                                                               (chunkOffset << YAFFS_TNODES_INTERNAL_BITS ) + i ,limit);
    44733417+                                       }
    4474 +                               }
    4475 +
     3418+                                       if(allDone)
     3419+                                       {
     3420+                                               yaffs_FreeTnode(dev,tn->internal[i]);
     3421+                                       tn->internal[i] = NULL;
     3422+                                       }
     3423+                           }
     3424+                   
    44763425+                       }
    44773426+                       return (allDone) ? 1 : 0;
    4478 +               } else if (level == 0) {
     3427+               }
     3428+               else if(level == 0)
     3429+               {
    44793430+                       int hitLimit = 0;
    4480 +
    4481 +                       for (i = YAFFS_NTNODES_LEVEL0 - 1; i >= 0 && !hitLimit;
    4482 +                            i--) {
    4483 +                               theChunk = yaffs_GetChunkGroupBase(dev,tn,i);
    4484 +                               if (theChunk) {
    4485 +
    4486 +                                       chunkInInode =
    4487 +                                           (chunkOffset <<
    4488 +                                            YAFFS_TNODES_LEVEL0_BITS) + i;
    4489 +
    4490 +                                       foundChunk =
    4491 +                                           yaffs_FindChunkInGroup(dev,
    4492 +                                                                  theChunk,
    4493 +                                                                  &tags,
    4494 +                                                                  in->objectId,
    4495 +                                                                  chunkInInode);
    4496 +
    4497 +                                       if (foundChunk > 0) {
    4498 +                                               yaffs_DeleteChunk(dev,
    4499 +                                                                 foundChunk, 1,
    4500 +                                                                 __LINE__);
     3431+                       
     3432+                       for(i = YAFFS_NTNODES_LEVEL0 -1; i >= 0 && !hitLimit; i--)
     3433+                       {
     3434+                           if(tn->level0[i])
     3435+                       {
     3436+                                       
     3437+                                       chunkInInode = (chunkOffset << YAFFS_TNODES_LEVEL0_BITS ) + i;
     3438+                                       
     3439+                                       theChunk =  tn->level0[i] << dev->chunkGroupBits;
     3440+                                       
     3441+                                       foundChunk = yaffs_FindChunkInGroup(dev,theChunk,&tags,in->objectId,chunkInInode);
     3442+                                       
     3443+                                       if(foundChunk > 0)
     3444+                                       {
     3445+                                               yaffs_DeleteChunk(dev,foundChunk,1,__LINE__);
    45013446+                                               in->nDataChunks--;
    4502 +                                               if (limit) {
    4503 +                                                       *limit = *limit - 1;
    4504 +                                                       if (*limit <= 0) {
     3447+                                               if(limit)
     3448+                                               {
     3449+                                                       *limit = *limit-1;
     3450+                                                       if(*limit <= 0)
     3451+                                                       {
    45053452+                                                               hitLimit = 1;
    45063453+                                                       }
    45073454+                                               }
    4508 +
     3455+                                       
    45093456+                                       }
    4510 +
    4511 +                                       yaffs_PutLevel0Tnode(dev,tn,i,0);
    4512 +                               }
    4513 +
     3457+                                       
     3458+                               tn->level0[i] = 0;
     3459+                           }
     3460+                   
    45143461+                       }
    45153462+                       return (i < 0) ? 1 : 0;
    45163463+
    4517 +               }
    4518 +
    4519 +       }
    4520 +
     3464+                       
     3465+               }
     3466+               
     3467+       }
     3468+       
    45213469+       return 1;
    4522 +
    4523 +}
    4524 +
    4525 +static void yaffs_SoftDeleteChunk(yaffs_Device * dev, int chunk)
    4526 +{
    4527 +
    4528 +       yaffs_BlockInfo *theBlock;
    4529 +
    4530 +       T(YAFFS_TRACE_DELETION, (TSTR("soft delete chunk %d" TENDSTR), chunk));
    4531 +
    4532 +       theBlock = yaffs_GetBlockInfo(dev, chunk / dev->nChunksPerBlock);
    4533 +       if (theBlock) {
     3470+       
     3471+}
     3472+
     3473+
     3474+static void yaffs_SoftDeleteChunk(yaffs_Device *dev, int chunk)
     3475+{
     3476+
     3477+       yaffs_BlockInfo *theBlock;                                     
     3478+       
     3479+       T(YAFFS_TRACE_DELETION,(TSTR("soft delete chunk %d" TENDSTR),chunk));
     3480+                                               
     3481+       theBlock =      yaffs_GetBlockInfo(dev,  chunk/dev->nChunksPerBlock);
     3482+       if(theBlock)
     3483+       {
    45343484+               theBlock->softDeletions++;
    45353485+               dev->nFreeChunks++;
     
    45373487+}
    45383488+
    4539 +/* SoftDeleteWorker scans backwards through the tnode tree and soft deletes all the chunks in the file.
    4540 + * All soft deleting does is increment the block's softdelete count and pulls the chunk out
    4541 + * of the tnode.
    4542 + * Thus, essentially this is the same as DeleteWorker except that the chunks are soft deleted.
    4543 + */
    4544 +
    4545 +static int yaffs_SoftDeleteWorker(yaffs_Object * in, yaffs_Tnode * tn,
    4546 +                                 __u32 level, int chunkOffset)
     3489+// SoftDeleteWorker scans backwards through the tnode tree and soft deletes all the chunks in the file.
     3490+// All soft deleting does is increment the block's softdelete count and pulls the chunk out
     3491+// of the tnode.
     3492+// THus, essentially this is the same as DeleteWorker except that the chunks are soft deleted.
     3493+//
     3494+static int yaffs_SoftDeleteWorker(yaffs_Object *in, yaffs_Tnode *tn, __u32 level, int chunkOffset)
    45473495+{
    45483496+       int i;
     
    45503498+       int allDone = 1;
    45513499+       yaffs_Device *dev = in->myDev;
    4552 +
    4553 +       if (tn) {
    4554 +               if (level > 0) {
    4555 +
    4556 +                       for (i = YAFFS_NTNODES_INTERNAL - 1; allDone && i >= 0;
    4557 +                            i--) {
    4558 +                               if (tn->internal[i]) {
    4559 +                                       allDone =
    4560 +                                           yaffs_SoftDeleteWorker(in,
    4561 +                                                                  tn->
    4562 +                                                                  internal[i],
    4563 +                                                                  level - 1,
    4564 +                                                                  (chunkOffset
    4565 +                                                                   <<
    4566 +                                                                   YAFFS_TNODES_INTERNAL_BITS)
    4567 +                                                                  + i);
    4568 +                                       if (allDone) {
    4569 +                                               yaffs_FreeTnode(dev,
    4570 +                                                               tn->
    4571 +                                                               internal[i]);
    4572 +                                               tn->internal[i] = NULL;
    4573 +                                       } else {
    4574 +                                               /* Hoosterman... how could this happen? */
     3500+       
     3501+       
     3502+       if(tn)
     3503+       {
     3504+               if(level > 0)
     3505+               {
     3506+               
     3507+                       for(i = YAFFS_NTNODES_INTERNAL -1; allDone && i >= 0; i--)
     3508+                       {
     3509+                           if(tn->internal[i])
     3510+                       {
     3511+                                               allDone = yaffs_SoftDeleteWorker(in,tn->internal[i],level - 1,
     3512+                                                                               (chunkOffset << YAFFS_TNODES_INTERNAL_BITS ) + i);
     3513+                                       if(allDone)
     3514+                                       {
     3515+                                               yaffs_FreeTnode(dev,tn->internal[i]);
     3516+                                       tn->internal[i] = NULL;
    45753517+                                       }
    4576 +                               }
     3518+                                       else
     3519+                                       {
     3520+                                               //Hoosterman... how could this happen.
     3521+                                       }                           
     3522+                               }                   
    45773523+                       }
    45783524+                       return (allDone) ? 1 : 0;
    4579 +               } else if (level == 0) {
    4580 +
    4581 +                       for (i = YAFFS_NTNODES_LEVEL0 - 1; i >= 0; i--) {
    4582 +                               theChunk = yaffs_GetChunkGroupBase(dev,tn,i);
    4583 +                               if (theChunk) {
    4584 +                                       /* Note this does not find the real chunk, only the chunk group.
    4585 +                                        * We make an assumption that a chunk group is not larger than
    4586 +                                        * a block.
    4587 +                                        */
    4588 +                                       yaffs_SoftDeleteChunk(dev, theChunk);
    4589 +                                       yaffs_PutLevel0Tnode(dev,tn,i,0);
    4590 +                               }
    4591 +
     3525+               }
     3526+               else if(level == 0)
     3527+               {
     3528+                       
     3529+                       for(i = YAFFS_NTNODES_LEVEL0 -1; i >=0; i--)
     3530+                       {
     3531+                           if(tn->level0[i])
     3532+                       {
     3533+                                       // Note this does not find the real chunk, only the chunk group.
     3534+                                       // We make an assumption that a chunk group is niot larger than a block.
     3535+                                       theChunk =  (tn->level0[i] << dev->chunkGroupBits);
     3536+                                       
     3537+                                       yaffs_SoftDeleteChunk(dev,theChunk);
     3538+                               tn->level0[i] = 0;
     3539+                           }
     3540+                   
    45923541+                       }
    45933542+                       return 1;
    4594 +
    4595 +               }
    4596 +
    4597 +       }
    4598 +
     3543+                       
     3544+               }
     3545+               
     3546+       }
     3547+       
    45993548+       return 1;
    4600 +
    4601 +}
    4602 +
    4603 +static void yaffs_SoftDeleteFile(yaffs_Object * obj)
    4604 +{
    4605 +       if (obj->deleted &&
    4606 +           obj->variantType == YAFFS_OBJECT_TYPE_FILE && !obj->softDeleted) {
    4607 +               if (obj->nDataChunks <= 0) {
    4608 +                       /* Empty file with no duplicate object headers, just delete it immediately */
    4609 +                       yaffs_FreeTnode(obj->myDev,
    4610 +                                       obj->variant.fileVariant.top);
    4611 +                       obj->variant.fileVariant.top = NULL;
    4612 +                       T(YAFFS_TRACE_TRACING,
    4613 +                         (TSTR("yaffs: Deleting empty file %d" TENDSTR),
    4614 +                          obj->objectId));
    4615 +                       yaffs_DoGenericObjectDeletion(obj);
    4616 +               } else {
    4617 +                       yaffs_SoftDeleteWorker(obj,
    4618 +                                              obj->variant.fileVariant.top,
    4619 +                                              obj->variant.fileVariant.
    4620 +                                              topLevel, 0);
     3549+               
     3550+}
     3551+
     3552+
     3553+
     3554+static void yaffs_SoftDeleteFile(yaffs_Object *obj)
     3555+{
     3556+       if(obj->deleted &&
     3557+          obj->variantType == YAFFS_OBJECT_TYPE_FILE &&
     3558+          !obj->softDeleted)
     3559+       {
     3560+               if(obj->nDataChunks <= 0)
     3561+               {
     3562+                               // Empty file with no duplicate object headers, just delete it immediately
     3563+                               yaffs_FreeTnode(obj->myDev,obj->variant.fileVariant.top);
     3564+                               obj->variant.fileVariant.top = NULL;
     3565+                               T(YAFFS_TRACE_TRACING,(TSTR("yaffs: Deleting empty file %d" TENDSTR),obj->objectId));
     3566+                               yaffs_DoGenericObjectDeletion(obj);     
     3567+               }
     3568+               else
     3569+               {
     3570+                       yaffs_SoftDeleteWorker(obj, obj->variant.fileVariant.top, obj->variant.fileVariant.topLevel, 0);
    46213571+                       obj->softDeleted = 1;
    46223572+               }
     
    46243574+}
    46253575+
    4626 +/* Pruning removes any part of the file structure tree that is beyond the
    4627 + * bounds of the file (ie that does not point to chunks).
    4628 + *
    4629 + * A file should only get pruned when its size is reduced.
    4630 + *
    4631 + * Before pruning, the chunks must be pulled from the tree and the
    4632 + * level 0 tnode entries must be zeroed out.
    4633 + * Could also use this for file deletion, but that's probably better handled
    4634 + * by a special case.
    4635 + */
    4636 +
    4637 +static yaffs_Tnode *yaffs_PruneWorker(yaffs_Device * dev, yaffs_Tnode * tn,
    4638 +                                     __u32 level, int del0)
     3576+
     3577+
     3578+
     3579+
     3580+// Pruning removes any part of the file structure tree that is beyond the
     3581+// bounds of the file (ie that does not point to chunks).
     3582+//
     3583+// A file should only get pruned when its size is reduced.
     3584+//
     3585+// Before pruning, the chunks must be pulled from the tree and the
     3586+// level 0 tnode entries must be zeroed out.
     3587+// Could also use this for file deletion, but that's probably better handled
     3588+// by a special case.
     3589+
     3590+// yaffs_PruneWorker should only be called by yaffs_PruneFileStructure()
     3591+
     3592+static yaffs_Tnode *yaffs_PruneWorker(yaffs_Device *dev, yaffs_Tnode *tn, __u32 level, int del0)
    46393593+{
    46403594+       int i;
    46413595+       int hasData;
    4642 +
    4643 +       if (tn) {
     3596+       
     3597+       if(tn)
     3598+       {
    46443599+               hasData = 0;
    4645 +
    4646 +               for (i = 0; i < YAFFS_NTNODES_INTERNAL; i++) {
    4647 +                       if (tn->internal[i] && level > 0) {
    4648 +                               tn->internal[i] =
    4649 +                                   yaffs_PruneWorker(dev, tn->internal[i],
    4650 +                                                     level - 1,
    4651 +                                                     (i == 0) ? del0 : 1);
     3600+               
     3601+               for(i = 0; i < YAFFS_NTNODES_INTERNAL; i++)
     3602+               {
     3603+                   if(tn->internal[i] && level > 0)
     3604+                   {
     3605+                       tn->internal[i] = yaffs_PruneWorker(dev,tn->internal[i],level - 1, ( i == 0) ? del0 : 1);
     3606+                   }
     3607+                   
     3608+                   if(tn->internal[i])
     3609+                   {
     3610+                       hasData++;
    46523611+                       }
    4653 +
    4654 +                       if (tn->internal[i]) {
    4655 +                               hasData++;
    4656 +                       }
    4657 +               }
    4658 +
    4659 +               if (hasData == 0 && del0) {
    4660 +                       /* Free and return NULL */
    4661 +
    4662 +                       yaffs_FreeTnode(dev, tn);
     3612+               }
     3613+               
     3614+               if(hasData == 0 && del0)
     3615+               {
     3616+                       // Free and return NULL
     3617+                       
     3618+                       yaffs_FreeTnode(dev,tn);
    46633619+                       tn = NULL;
    46643620+               }
    4665 +
     3621+               
    46663622+       }
    46673623+
    46683624+       return tn;
    4669 +
    4670 +}
    4671 +
    4672 +static int yaffs_PruneFileStructure(yaffs_Device * dev,
    4673 +                                   yaffs_FileStructure * fStruct)
     3625+       
     3626+}
     3627+
     3628+static int yaffs_PruneFileStructure(yaffs_Device *dev, yaffs_FileStructure *fStruct)
    46743629+{
    46753630+       int i;
     
    46773632+       int done = 0;
    46783633+       yaffs_Tnode *tn;
    4679 +
    4680 +       if (fStruct->topLevel > 0) {
    4681 +               fStruct->top =
    4682 +                   yaffs_PruneWorker(dev, fStruct->top, fStruct->topLevel, 0);
    4683 +
    4684 +               /* Now we have a tree with all the non-zero branches NULL but the height
    4685 +                * is the same as it was.
    4686 +                * Let's see if we can trim internal tnodes to shorten the tree.
    4687 +                * We can do this if only the 0th element in the tnode is in use
    4688 +                * (ie all the non-zero are NULL)
    4689 +                */
    4690 +
    4691 +               while (fStruct->topLevel && !done) {
     3634+       
     3635+       if(fStruct->topLevel > 0)
     3636+       {
     3637+               fStruct->top = yaffs_PruneWorker(dev,fStruct->top, fStruct->topLevel,0);
     3638+               
     3639+               // Now we have a tree with all the non-zero branches NULL but the height
     3640+               // is the same as it was.
     3641+               // Let's see if we can trim internal tnodes to shorten the tree.
     3642+               // We can do this if only the 0th element in the tnode is in use
     3643+               // (ie all the non-zero are NULL)
     3644+               
     3645+               while(fStruct->topLevel && !done)
     3646+               {
    46923647+                       tn = fStruct->top;
    4693 +
     3648+                       
    46943649+                       hasData = 0;
    4695 +                       for (i = 1; i < YAFFS_NTNODES_INTERNAL; i++) {
    4696 +                               if (tn->internal[i]) {
    4697 +                                       hasData++;
     3650+                       for(i = 1; i <YAFFS_NTNODES_INTERNAL; i++)
     3651+                       {
     3652+                               if(tn->internal[i])
     3653+                       {
     3654+                               hasData++;
    46983655+                               }
    46993656+                       }
    4700 +
    4701 +                       if (!hasData) {
     3657+                       
     3658+                       if(!hasData)
     3659+                       {
    47023660+                               fStruct->top = tn->internal[0];
    47033661+                               fStruct->topLevel--;
    4704 +                               yaffs_FreeTnode(dev, tn);
    4705 +                       } else {
     3662+                               yaffs_FreeTnode(dev,tn);
     3663+                       }
     3664+                       else
     3665+                       {
    47063666+                               done = 1;
    47073667+                       }
    47083668+               }
    47093669+       }
    4710 +
     3670+       
    47113671+       return YAFFS_OK;
    47123672+}
    47133673+
    4714 +/*-------------------- End of File Structure functions.-------------------*/
    4715 +
    4716 +/* yaffs_CreateFreeObjects creates a bunch more objects and
    4717 + * adds them to the object free list.
    4718 + */
    4719 +static int yaffs_CreateFreeObjects(yaffs_Device * dev, int nObjects)
    4720 +{
    4721 +       int i;
    4722 +       yaffs_Object *newObjects;
    4723 +       yaffs_ObjectList *list;
    4724 +
    4725 +       if (nObjects < 1)
    4726 +               return YAFFS_OK;
    4727 +
    4728 +       /* make these things */
    4729 +       newObjects = YMALLOC(nObjects * sizeof(yaffs_Object));
    4730 +
    4731 +       if (!newObjects) {
    4732 +               T(YAFFS_TRACE_ALLOCATE,
    4733 +                 (TSTR("yaffs: Could not allocate more objects" TENDSTR)));
     3674+
     3675+
     3676+
     3677+
     3678+/////////////////////// End of File Structure functions. /////////////////
     3679+
     3680+// yaffs_CreateFreeObjects creates a bunch more objects and
     3681+// adds them to the object free list.
     3682+static int yaffs_CreateFreeObjects(yaffs_Device *dev, int nObjects)
     3683+{
     3684+    int i;
     3685+    yaffs_Object *newObjects;
     3686+    yaffs_ObjectList *list;
     3687+   
     3688+    if(nObjects < 1) return YAFFS_OK;
     3689+   
     3690+       // make these things
     3691+       
     3692+    newObjects = YMALLOC(nObjects * sizeof(yaffs_Object));
     3693+   
     3694+    if (!newObjects)
     3695+    {
     3696+               T(YAFFS_TRACE_ALLOCATE,(TSTR("yaffs: Could not allocate more objects" TENDSTR)));
    47343697+               return YAFFS_FAIL;
    4735 +       }
    4736 +       
    4737 +       /* Hook them into the free list */
    4738 +       for (i = 0; i < nObjects - 1; i++) {
    4739 +               newObjects[i].siblings.next =
    4740 +                   (struct list_head *)(&newObjects[i + 1]);
    4741 +       }
    4742 +
     3698+    }
     3699+   
     3700+    // Hook them into the free list
     3701+    for(i = 0; i < nObjects - 1; i++)
     3702+    {
     3703+       newObjects[i].siblings.next = (struct list_head *)(&newObjects[i+1]);
     3704+    }
     3705+       
    47433706+       newObjects[nObjects - 1].siblings.next = (void *)dev->freeObjects;
    47443707+       dev->freeObjects = newObjects;
    4745 +       dev->nFreeObjects += nObjects;
    4746 +       dev->nObjectsCreated += nObjects;
    4747 +
    4748 +       /* Now add this bunch of Objects to a list for freeing up. */
    4749 +
     3708+       dev->nFreeObjects+= nObjects;
     3709+       dev->nObjectsCreated+= nObjects;
     3710+       
     3711+       // Now add this bunch of Objects to a list for freeing up.
     3712+       
    47503713+       list = YMALLOC(sizeof(yaffs_ObjectList));
    4751 +       if (!list) {
    4752 +               T(YAFFS_TRACE_ALLOCATE,
    4753 +                 (TSTR("Could not add objects to management list" TENDSTR)));
    4754 +       } else {
     3714+       if(!list)
     3715+       {
     3716+               T(YAFFS_TRACE_ALLOCATE,(TSTR("Could not add objects to management list" TENDSTR)));
     3717+       }
     3718+       else
     3719+       {
    47553720+               list->objects = newObjects;
    47563721+               list->next = dev->allocatedObjectList;
    47573722+               dev->allocatedObjectList = list;
    47583723+       }
    4759 +
     3724+       
     3725+       
     3726+       
    47603727+       return YAFFS_OK;
    47613728+}
    47623729+
    47633730+
    4764 +/* AllocateEmptyObject gets us a clean Object. Tries to make allocate more if we run out */
    4765 +static yaffs_Object *yaffs_AllocateEmptyObject(yaffs_Device * dev)
     3731+// AllocateEmptyObject gets us a clean Object. Tries to make allocate more if we run out
     3732+static yaffs_Object *yaffs_AllocateEmptyObject(yaffs_Device *dev)
    47663733+{
    47673734+       yaffs_Object *tn = NULL;
    4768 +
    4769 +       /* If there are none left make more */
    4770 +       if (!dev->freeObjects) {
    4771 +               yaffs_CreateFreeObjects(dev, YAFFS_ALLOCATION_NOBJECTS);
    4772 +       }
    4773 +
    4774 +       if (dev->freeObjects) {
     3735+       
     3736+       // If there are none left make more
     3737+       if(!dev->freeObjects)
     3738+       {
     3739+               yaffs_CreateFreeObjects(dev,YAFFS_ALLOCATION_NOBJECTS);
     3740+       }
     3741+       
     3742+       if(dev->freeObjects)
     3743+       {
    47753744+               tn = dev->freeObjects;
    4776 +               dev->freeObjects =
    4777 +                   (yaffs_Object *) (dev->freeObjects->siblings.next);
     3745+               dev->freeObjects = (yaffs_Object *)(dev->freeObjects->siblings.next);
    47783746+               dev->nFreeObjects--;
    4779 +
    4780 +               /* Now sweeten it up... */
    4781 +
    4782 +               memset(tn, 0, sizeof(yaffs_Object));
     3747+               
     3748+               // Now sweeten it up...
     3749+       
     3750+               memset(tn,0,sizeof(yaffs_Object));
    47833751+               tn->myDev = dev;
    47843752+               tn->chunkId = -1;
     
    47873755+               INIT_LIST_HEAD(&(tn->hashLink));
    47883756+               INIT_LIST_HEAD(&tn->siblings);
    4789 +
    4790 +               /* Add it to the lost and found directory.
    4791 +                * NB Can't put root or lostNFound in lostNFound so
    4792 +                * check if lostNFound exists first
    4793 +                */
    4794 +               if (dev->lostNFoundDir) {
    4795 +                       yaffs_AddObjectToDirectory(dev->lostNFoundDir, tn);
    4796 +               }
    4797 +       }
     3757+               
     3758+               // Add it to the lost and found directory.
     3759+               // NB Can't put root or lostNFound in lostNFound so
     3760+               // check if lostNFound exists first
     3761+               if(dev->lostNFoundDir)
     3762+               {
     3763+                       yaffs_AddObjectToDirectory(dev->lostNFoundDir,tn);     
     3764+               }
     3765+       }
     3766+       
    47983767+
    47993768+       return tn;
    48003769+}
    48013770+
    4802 +static yaffs_Object *yaffs_CreateFakeDirectory(yaffs_Device * dev, int number,
    4803 +                                              __u32 mode)
    4804 +{
    4805 +
    4806 +       yaffs_Object *obj =
    4807 +           yaffs_CreateNewObject(dev, number, YAFFS_OBJECT_TYPE_DIRECTORY);
    4808 +       if (obj) {
    4809 +               obj->fake = 1;          /* it is fake so it has no NAND presence... */
    4810 +               obj->renameAllowed = 0; /* ... and we're not allowed to rename it... */
    4811 +               obj->unlinkAllowed = 0; /* ... or unlink it */
     3771+static yaffs_Object *yaffs_CreateFakeDirectory(yaffs_Device *dev,int number,__u32 mode)
     3772+{
     3773+
     3774+       yaffs_Object *obj = yaffs_CreateNewObject(dev,number,YAFFS_OBJECT_TYPE_DIRECTORY);             
     3775+       if(obj)
     3776+       {
     3777+               obj->fake = 1;                  // it is fake so it has no NAND presence...
     3778+               obj->renameAllowed= 0;  // ... and we're not allowed to rename it...
     3779+               obj->unlinkAllowed= 0;  // ... or unlink it
    48123780+               obj->deleted = 0;
    48133781+               obj->unlinked = 0;
    48143782+               obj->yst_mode = mode;
    48153783+               obj->myDev = dev;
    4816 +               obj->chunkId = 0;       /* Not a valid chunk. */
    4817 +       }
    4818 +
     3784+               obj->chunkId = 0; // Not a valid chunk.
     3785+       }
     3786+       
    48193787+       return obj;
    4820 +
    4821 +}
    4822 +
    4823 +static void yaffs_UnhashObject(yaffs_Object * tn)
     3788+       
     3789+}
     3790+
     3791+
     3792+static void yaffs_UnhashObject(yaffs_Object *tn)
    48243793+{
    48253794+       int bucket;
    48263795+       yaffs_Device *dev = tn->myDev;
    4827 +
    4828 +       /* If it is still linked into the bucket list, free from the list */
    4829 +       if (!list_empty(&tn->hashLink)) {
     3796+       
     3797+       
     3798+       // If it is still linked into the bucket list, free from the list
     3799+       if(!list_empty(&tn->hashLink))
     3800+       {
    48303801+               list_del_init(&tn->hashLink);
    4831 +               bucket = yaffs_HashFunction(tn->objectId);
     3802+               bucket =  yaffs_HashFunction(tn->objectId);
    48323803+               dev->objectBucket[bucket].count--;
    48333804+       }
    4834 +
    4835 +}
    4836 +
    4837 +/*  FreeObject frees up a Object and puts it back on the free list */
    4838 +static void yaffs_FreeObject(yaffs_Object * tn)
     3805+       
     3806+}
     3807+
     3808+
     3809+// FreeObject frees up a Object and puts it back on the free list
     3810+static void yaffs_FreeObject(yaffs_Object *tn)
    48393811+{
    48403812+
    48413813+       yaffs_Device *dev = tn->myDev;
    4842 +
     3814+       
    48433815+#ifdef  __KERNEL__
    4844 +       if (tn->myInode) {
    4845 +               /* We're still hooked up to a cached inode.
    4846 +                * Don't delete now, but mark for later deletion
    4847 +                */
     3816+       if(tn->myInode)
     3817+       {
     3818+               // We're still hooked up to a cached inode.
     3819+               // Don't delete now, but mark for later deletion
    48483820+               tn->deferedFree = 1;
    48493821+               return;
    48503822+       }
    48513823+#endif
    4852 +
     3824+       
    48533825+       yaffs_UnhashObject(tn);
    4854 +
    4855 +       /* Link into the free list. */
     3826+       
     3827+       // Link into the free list.
    48563828+       tn->siblings.next = (struct list_head *)(dev->freeObjects);
    48573829+       dev->freeObjects = tn;
     
    48593831+}
    48603832+
     3833+
     3834+
    48613835+#ifdef __KERNEL__
    48623836+
    4863 +void yaffs_HandleDeferedFree(yaffs_Object * obj)
    4864 +{
    4865 +       if (obj->deferedFree) {
    4866 +               yaffs_FreeObject(obj);
    4867 +       }
    4868 +}
    4869 +
    4870 +#endif
    4871 +
    4872 +static void yaffs_DeinitialiseObjects(yaffs_Device * dev)
    4873 +{
    4874 +       /* Free the list of allocated Objects */
    4875 +
     3837+void yaffs_HandleDeferedFree(yaffs_Object *obj)
     3838+{
     3839+       if(obj->deferedFree)
     3840+       {
     3841+          yaffs_FreeObject(obj);
     3842+       }
     3843+}
     3844+
     3845+#endif
     3846+
     3847+
     3848+
     3849+static void yaffs_DeinitialiseObjects(yaffs_Device *dev)
     3850+{
     3851+       // Free the list of allocated Objects
     3852+       
    48763853+       yaffs_ObjectList *tmp;
    4877 +
    4878 +       while (dev->allocatedObjectList) {
    4879 +               tmp = dev->allocatedObjectList->next;
     3854+       
     3855+       while( dev->allocatedObjectList)
     3856+       {
     3857+               tmp =  dev->allocatedObjectList->next;
    48803858+               YFREE(dev->allocatedObjectList->objects);
    48813859+               YFREE(dev->allocatedObjectList);
    4882 +
    4883 +               dev->allocatedObjectList = tmp;
    4884 +       }
    4885 +
     3860+               
     3861+               dev->allocatedObjectList =  tmp;
     3862+       }
     3863+       
    48863864+       dev->freeObjects = NULL;
    48873865+       dev->nFreeObjects = 0;
    48883866+}
    48893867+
    4890 +static void yaffs_InitialiseObjects(yaffs_Device * dev)
     3868+static void yaffs_InitialiseObjects(yaffs_Device *dev)
    48913869+{
    48923870+       int i;
    4893 +
     3871+       
    48943872+       dev->allocatedObjectList = NULL;
    48953873+       dev->freeObjects = NULL;
    48963874+       dev->nFreeObjects = 0;
    4897 +
    4898 +       for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) {
     3875+       
     3876+       for(i = 0; i < YAFFS_NOBJECT_BUCKETS; i++)
     3877+       {
    48993878+               INIT_LIST_HEAD(&dev->objectBucket[i].list);
    4900 +               dev->objectBucket[i].count = 0;
    4901 +       }
    4902 +
    4903 +}
    4904 +
    4905 +static int yaffs_FindNiceObjectBucket(yaffs_Device * dev)
     3879+               dev->objectBucket[i].count = 0;
     3880+       }
     3881+
     3882+}
     3883+
     3884+
     3885+
     3886+
     3887+
     3888+
     3889+static int yaffs_FindNiceObjectBucket(yaffs_Device *dev)
    49063890+{
    49073891+       static int x = 0;
     
    49103894+       int lowest = 999999;
    49113895+
    4912 +       /* First let's see if we can find one that's empty. */
    4913 +
    4914 +       for (i = 0; i < 10 && lowest > 0; i++) {
     3896+               
     3897+       // First let's see if we can find one that's empty.
     3898+       
     3899+       for(i = 0; i < 10 && lowest > 0; i++)
     3900+        {
    49153901+               x++;
    4916 +               x %= YAFFS_NOBJECT_BUCKETS;
    4917 +               if (dev->objectBucket[x].count < lowest) {
     3902+               x %=  YAFFS_NOBJECT_BUCKETS;
     3903+               if(dev->objectBucket[x].count < lowest)
     3904+               {
    49183905+                       lowest = dev->objectBucket[x].count;
    49193906+                       l = x;
    49203907+               }
    4921 +
    4922 +       }
    4923 +
    4924 +       /* If we didn't find an empty list, then try
    4925 +        * looking a bit further for a short one
    4926 +        */
    4927 +
    4928 +       for (i = 0; i < 10 && lowest > 3; i++) {
     3908+               
     3909+       }
     3910+       
     3911+       // If we didn't find an empty list, then try
     3912+       // looking a bit further for a short one
     3913+       
     3914+       for(i = 0; i < 10 && lowest > 3; i++)
     3915+        {
    49293916+               x++;
    4930 +               x %= YAFFS_NOBJECT_BUCKETS;
    4931 +               if (dev->objectBucket[x].count < lowest) {
     3917+               x %=  YAFFS_NOBJECT_BUCKETS;
     3918+               if(dev->objectBucket[x].count < lowest)
     3919+               {
    49323920+                       lowest = dev->objectBucket[x].count;
    49333921+                       l = x;
    49343922+               }
    4935 +
    4936 +       }
    4937 +
     3923+               
     3924+       }
     3925+       
    49383926+       return l;
    49393927+}
    49403928+
    4941 +static int yaffs_CreateNewObjectNumber(yaffs_Device * dev)
     3929+static int yaffs_CreateNewObjectNumber(yaffs_Device *dev)
    49423930+{
    49433931+       int bucket = yaffs_FindNiceObjectBucket(dev);
    4944 +
    4945 +       /* Now find an object value that has not already been taken
    4946 +        * by scanning the list.
    4947 +        */
    4948 +
     3932+       
     3933+       // Now find an object value that has not already been taken
     3934+       // by scanning the list.
     3935+       
    49493936+       int found = 0;
    49503937+       struct list_head *i;
    4951 +
    4952 +       __u32 n = (__u32) bucket;
    4953 +
    4954 +       /* yaffs_CheckObjectHashSanity();  */
    4955 +
    4956 +       while (!found) {
     3938+       
     3939+       __u32 n = (__u32)bucket;
     3940+
     3941+       //yaffs_CheckObjectHashSanity();       
     3942+       
     3943+       while(!found)
     3944+       {
    49573945+               found = 1;
    4958 +               n += YAFFS_NOBJECT_BUCKETS;
    4959 +               if (1 || dev->objectBucket[bucket].count > 0) {
    4960 +                       list_for_each(i, &dev->objectBucket[bucket].list) {
    4961 +                               /* If there is already one in the list */
    4962 +                               if (i
    4963 +                                   && list_entry(i, yaffs_Object,
    4964 +                                                 hashLink)->objectId == n) {
     3946+               n +=  YAFFS_NOBJECT_BUCKETS;
     3947+               if(1 ||dev->objectBucket[bucket].count > 0)
     3948+               {
     3949+                       list_for_each(i,&dev->objectBucket[bucket].list)
     3950+                       {
     3951+                               // If there is already one in the list
     3952+                               if(i && list_entry(i, yaffs_Object,hashLink)->objectId == n)
     3953+                               {
    49653954+                                       found = 0;
    49663955+                               }
     
    49683957+               }
    49693958+       }
    4970 +
    4971 +
    4972 +       return n;
    4973 +}
    4974 +
    4975 +static void yaffs_HashObject(yaffs_Object * in)
     3959+       
     3960+       //T(("bucket %d count %d inode %d\n",bucket,yaffs_objectBucket[bucket].count,n);
     3961+       
     3962+       return n;       
     3963+}
     3964+
     3965+static void yaffs_HashObject(yaffs_Object *in)
    49763966+{
    49773967+       int bucket = yaffs_HashFunction(in->objectId);
    49783968+       yaffs_Device *dev = in->myDev;
    4979 +
    4980 +       list_add(&in->hashLink, &dev->objectBucket[bucket].list);
     3969+       
     3970+       if(!list_empty(&in->hashLink))
     3971+       {
     3972+               //YINFO("!!!");
     3973+       }
     3974+
     3975+       
     3976+       list_add(&in->hashLink,&dev->objectBucket[bucket].list);
    49813977+       dev->objectBucket[bucket].count++;
    49823978+
    49833979+}
    49843980+
    4985 +yaffs_Object *yaffs_FindObjectByNumber(yaffs_Device * dev, __u32 number)
     3981+yaffs_Object *yaffs_FindObjectByNumber(yaffs_Device *dev,__u32 number)
    49863982+{
    49873983+       int bucket = yaffs_HashFunction(number);
    49883984+       struct list_head *i;
    49893985+       yaffs_Object *in;
    4990 +
    4991 +       list_for_each(i, &dev->objectBucket[bucket].list) {
    4992 +               /* Look if it is in the list */
    4993 +               if (i) {
    4994 +                       in = list_entry(i, yaffs_Object, hashLink);
    4995 +                       if (in->objectId == number) {
     3986+       
     3987+       list_for_each(i,&dev->objectBucket[bucket].list)
     3988+       {
     3989+               // Look if it is in the list
     3990+               if(i)
     3991+               {
     3992+                       in = list_entry(i, yaffs_Object,hashLink);
     3993+                       if(in->objectId == number)
     3994+                       {
    49963995+#ifdef __KERNEL__
    4997 +                               /* Don't tell the VFS about this one if it is defered free */
    4998 +                               if (in->deferedFree)
    4999 +                                       return NULL;
    5000 +#endif
    5001 +
     3996+                               // Don't tell the VFS about this one if it is defered free
     3997+                               if(in->deferedFree)
     3998+                                 return NULL;
     3999+#endif
     4000+                                 
    50024001+                               return in;
    50034002+                       }
    50044003+               }
    50054004+       }
    5006 +
     4005+       
    50074006+       return NULL;
    50084007+}
    50094008+
    5010 +yaffs_Object *yaffs_CreateNewObject(yaffs_Device * dev, int number,
    5011 +                                   yaffs_ObjectType type)
    5012 +{
    5013 +
     4009+
     4010+
     4011+yaffs_Object *yaffs_CreateNewObject(yaffs_Device *dev,int number,yaffs_ObjectType type)
     4012+{
     4013+               
    50144014+       yaffs_Object *theObject;
    50154015+
    5016 +       if (number < 0) {
     4016+       if(number < 0)
     4017+       {
    50174018+               number = yaffs_CreateNewObjectNumber(dev);
    50184019+       }
    5019 +
     4020+       
    50204021+       theObject = yaffs_AllocateEmptyObject(dev);
    5021 +
    5022 +       if (theObject) {
     4022+       
     4023+       if(theObject)
     4024+       {
    50234025+               theObject->fake = 0;
    50244026+               theObject->renameAllowed = 1;
     
    50294031+#ifdef CONFIG_YAFFS_WINCE
    50304032+               yfsd_WinFileTimeNow(theObject->win_atime);
    5031 +               theObject->win_ctime[0] = theObject->win_mtime[0] =
    5032 +                   theObject->win_atime[0];
    5033 +               theObject->win_ctime[1] = theObject->win_mtime[1] =
    5034 +                   theObject->win_atime[1];
     4033+               theObject->win_ctime[0] = theObject->win_mtime[0] = theObject->win_atime[0];
     4034+               theObject->win_ctime[1] = theObject->win_mtime[1] = theObject->win_atime[1];
    50354035+
    50364036+#else
    50374037+
    5038 +               theObject->yst_atime = theObject->yst_mtime =
    5039 +                   theObject->yst_ctime = Y_CURRENT_TIME;
    5040 +#endif
    5041 +               switch (type) {
    5042 +               case YAFFS_OBJECT_TYPE_FILE:
    5043 +                       theObject->variant.fileVariant.fileSize = 0;
    5044 +                       theObject->variant.fileVariant.scannedFileSize = 0;
    5045 +                       theObject->variant.fileVariant.shrinkSize = 0xFFFFFFFF; /* max __u32 */
    5046 +                       theObject->variant.fileVariant.topLevel = 0;
    5047 +                       theObject->variant.fileVariant.top =
    5048 +                           yaffs_GetTnode(dev);
    5049 +                       break;
    5050 +               case YAFFS_OBJECT_TYPE_DIRECTORY:
    5051 +                       INIT_LIST_HEAD(&theObject->variant.directoryVariant.
    5052 +                                      children);
    5053 +                       break;
    5054 +               case YAFFS_OBJECT_TYPE_SYMLINK:
    5055 +               case YAFFS_OBJECT_TYPE_HARDLINK:
    5056 +               case YAFFS_OBJECT_TYPE_SPECIAL:
    5057 +                       /* No action required */
    5058 +                       break;
    5059 +               case YAFFS_OBJECT_TYPE_UNKNOWN:
    5060 +                       /* todo this should not happen */
    5061 +                       break;
    5062 +               }
    5063 +       }
    5064 +
     4038+               theObject->yst_atime = theObject->yst_mtime = theObject->yst_ctime = Y_CURRENT_TIME;           
     4039+#endif
     4040+               switch(type)
     4041+               {
     4042+                       case YAFFS_OBJECT_TYPE_FILE:
     4043+                               theObject->variant.fileVariant.fileSize = 0;
     4044+                               theObject->variant.fileVariant.scannedFileSize = 0;
     4045+                               theObject->variant.fileVariant.shrinkSize = 0xFFFFFFFF; // max __u32
     4046+                               theObject->variant.fileVariant.topLevel = 0;
     4047+                               theObject->variant.fileVariant.top  = yaffs_GetTnode(dev);
     4048+                               break;
     4049+                       case YAFFS_OBJECT_TYPE_DIRECTORY:
     4050+                               INIT_LIST_HEAD(&theObject->variant.directoryVariant.children);
     4051+                               break;
     4052+                       case YAFFS_OBJECT_TYPE_SYMLINK:
     4053+                               // No action required
     4054+                               break;
     4055+                       case YAFFS_OBJECT_TYPE_HARDLINK:
     4056+                               // No action required
     4057+                               break;
     4058+                       case YAFFS_OBJECT_TYPE_SPECIAL:
     4059+                               // No action required
     4060+                               break;
     4061+                       case YAFFS_OBJECT_TYPE_UNKNOWN:
     4062+                               // todo this should not happen
     4063+                               break;
     4064+               }
     4065+       }
     4066+       
    50654067+       return theObject;
    50664068+}
    50674069+
    5068 +static yaffs_Object *yaffs_FindOrCreateObjectByNumber(yaffs_Device * dev,
    5069 +                                                     int number,
    5070 +                                                     yaffs_ObjectType type)
     4070+static yaffs_Object *yaffs_FindOrCreateObjectByNumber(yaffs_Device *dev, int number,yaffs_ObjectType type)
    50714071+{
    50724072+       yaffs_Object *theObject = NULL;
    5073 +
    5074 +       if (number > 0) {
    5075 +               theObject = yaffs_FindObjectByNumber(dev, number);
    5076 +       }
    5077 +
    5078 +       if (!theObject) {
    5079 +               theObject = yaffs_CreateNewObject(dev, number, type);
    5080 +       }
    5081 +
     4073+       
     4074+       if(number > 0)
     4075+       {
     4076+               theObject = yaffs_FindObjectByNumber(dev,number);
     4077+       }
     4078+       
     4079+       if(!theObject)
     4080+       {
     4081+               theObject = yaffs_CreateNewObject(dev,number,type);
     4082+       }
     4083+       
    50824084+       return theObject;
    50834085+
    50844086+}
    5085 +                       
    5086 +
    5087 +static YCHAR *yaffs_CloneString(const YCHAR * str)
     4087+
     4088+static YCHAR *yaffs_CloneString(const YCHAR *str)
    50884089+{
    50894090+       YCHAR *newStr = NULL;
    5090 +
    5091 +       if (str && *str) {
     4091+       
     4092+       if(str && *str)
     4093+       {
    50924094+               newStr = YMALLOC((yaffs_strlen(str) + 1) * sizeof(YCHAR));
    5093 +               yaffs_strcpy(newStr, str);
     4095+               yaffs_strcpy(newStr,str);
    50944096+       }
    50954097+
    50964098+       return newStr;
    5097 +
    5098 +}
    5099 +
    5100 +/*
    5101 + * Mknod (create) a new object.
    5102 + * equivalentObject only has meaning for a hard link;
    5103 + * aliasString only has meaning for a sumlink.
    5104 + * rdev only has meaning for devices (a subset of special objects)
    5105 + */
    5106 +
    5107 +static yaffs_Object *yaffs_MknodObject(yaffs_ObjectType type,
    5108 +                                      yaffs_Object * parent,
    5109 +                                      const YCHAR * name,
    5110 +                                      __u32 mode,
    5111 +                                      __u32 uid,
    5112 +                                      __u32 gid,
    5113 +                                      yaffs_Object * equivalentObject,
    5114 +                                      const YCHAR * aliasString, __u32 rdev)
     4099+       
     4100+}
     4101+
     4102+//
     4103+// Mknod (create) a new object.
     4104+// equivalentObject only has meaning for a hard link;
     4105+// aliasString only has meaning for a sumlink.
     4106+// rdev only has meaning for devices (a subset of special objects)
     4107+static yaffs_Object *yaffs_MknodObject( yaffs_ObjectType type,
     4108+                                                                yaffs_Object *parent,
     4109+                                                                const YCHAR *name,
     4110+                                                                __u32 mode,
     4111+                                                                __u32 uid,
     4112+                                                                __u32 gid,
     4113+                                                                yaffs_Object *equivalentObject,
     4114+                                                                const YCHAR *aliasString,
     4115+                                                                __u32 rdev)
    51154116+{
    51164117+       yaffs_Object *in;
    51174118+
    51184119+       yaffs_Device *dev = parent->myDev;
    5119 +
    5120 +       /* Check if the entry exists. If it does then fail the call since we don't want a dup.*/
    5121 +       if (yaffs_FindObjectByName(parent, name)) {
     4120+       
     4121+       // Check if the entry exists. If it does then fail the call since we don't want a dup.
     4122+       if(yaffs_FindObjectByName(parent,name))
     4123+       {
    51224124+               return NULL;
    51234125+       }
    5124 +
    5125 +       in = yaffs_CreateNewObject(dev, -1, type);
    5126 +
    5127 +       if (in) {
     4126+       
     4127+       in = yaffs_CreateNewObject(dev,-1,type);
     4128+       
     4129+       if(in)
     4130+       {
    51284131+               in->chunkId = -1;
    51294132+               in->valid = 1;
    51304133+               in->variantType = type;
    51314134+
    5132 +               in->yst_mode = mode;
    5133 +
     4135+               in->yst_mode  = mode;
     4136+               
    51344137+#ifdef CONFIG_YAFFS_WINCE
    51354138+               yfsd_WinFileTimeNow(in->win_atime);
    51364139+               in->win_ctime[0] = in->win_mtime[0] = in->win_atime[0];
    51374140+               in->win_ctime[1] = in->win_mtime[1] = in->win_atime[1];
    5138 +
     4141+               
    51394142+#else
    51404143+               in->yst_atime = in->yst_mtime = in->yst_ctime = Y_CURRENT_TIME;
    51414144+
    5142 +               in->yst_rdev = rdev;
    5143 +               in->yst_uid = uid;
    5144 +               in->yst_gid = gid;
    5145 +#endif
     4145+               in->yst_rdev  = rdev;
     4146+               in->yst_uid   = uid;
     4147+               in->yst_gid   = gid;
     4148+#endif         
    51464149+               in->nDataChunks = 0;
    51474150+
    5148 +               yaffs_SetObjectName(in, name);
     4151+               yaffs_SetObjectName(in,name);
    51494152+               in->dirty = 1;
    5150 +
    5151 +               yaffs_AddObjectToDirectory(parent, in);
    5152 +
     4153+               
     4154+               yaffs_AddObjectToDirectory(parent,in);
     4155+               
    51534156+               in->myDev = parent->myDev;
    5154 +
    5155 +               switch (type) {
    5156 +               case YAFFS_OBJECT_TYPE_SYMLINK:
    5157 +                       in->variant.symLinkVariant.alias =
    5158 +                           yaffs_CloneString(aliasString);
    5159 +                       break;
    5160 +               case YAFFS_OBJECT_TYPE_HARDLINK:
    5161 +                       in->variant.hardLinkVariant.equivalentObject =
    5162 +                           equivalentObject;
    5163 +                       in->variant.hardLinkVariant.equivalentObjectId =
    5164 +                           equivalentObject->objectId;
    5165 +                       list_add(&in->hardLinks, &equivalentObject->hardLinks);
    5166 +                       break;
    5167 +               case YAFFS_OBJECT_TYPE_FILE:   
    5168 +               case YAFFS_OBJECT_TYPE_DIRECTORY:
    5169 +               case YAFFS_OBJECT_TYPE_SPECIAL:
    5170 +               case YAFFS_OBJECT_TYPE_UNKNOWN:
    5171 +                       /* do nothing */
    5172 +                       break;
    5173 +               }
    5174 +
    5175 +               if (yaffs_UpdateObjectHeader(in, name, 0, 0, 0) < 0) {
    5176 +                       /* Could not create the object header, fail the creation */
     4157+               
     4158+                              
     4159+               switch(type)
     4160+               {
     4161+                       case YAFFS_OBJECT_TYPE_SYMLINK:
     4162+                               in->variant.symLinkVariant.alias = yaffs_CloneString(aliasString);
     4163+                               break;
     4164+                       case YAFFS_OBJECT_TYPE_HARDLINK:
     4165+                               in->variant.hardLinkVariant.equivalentObject = equivalentObject;
     4166+                               in->variant.hardLinkVariant.equivalentObjectId = equivalentObject->objectId;
     4167+                               list_add(&in->hardLinks,&equivalentObject->hardLinks);
     4168+                               break;
     4169+                       case YAFFS_OBJECT_TYPE_FILE: // do nothing
     4170+                       case YAFFS_OBJECT_TYPE_DIRECTORY: // do nothing
     4171+                       case YAFFS_OBJECT_TYPE_SPECIAL: // do nothing
     4172+                       case YAFFS_OBJECT_TYPE_UNKNOWN:
     4173+                               break;
     4174+               }
     4175+
     4176+               if(/*yaffs_GetNumberOfFreeChunks(dev) <= 0 || */
     4177+                  yaffs_UpdateObjectHeader(in,name,0,0,0) < 0)
     4178+               {
     4179+                       // Could not create the object header, fail the creation
    51774180+                       yaffs_DestroyObject(in);
    51784181+                       in = NULL;
     
    51804183+
    51814184+       }
    5182 +
     4185+       
    51834186+       return in;
    51844187+}
    51854188+
    5186 +yaffs_Object *yaffs_MknodFile(yaffs_Object * parent, const YCHAR * name,
    5187 +                             __u32 mode, __u32 uid, __u32 gid)
    5188 +{
    5189 +       return yaffs_MknodObject(YAFFS_OBJECT_TYPE_FILE, parent, name, mode,
    5190 +                                uid, gid, NULL, NULL, 0);
    5191 +}
    5192 +
    5193 +yaffs_Object *yaffs_MknodDirectory(yaffs_Object * parent, const YCHAR * name,
    5194 +                                  __u32 mode, __u32 uid, __u32 gid)
    5195 +{
    5196 +       return yaffs_MknodObject(YAFFS_OBJECT_TYPE_DIRECTORY, parent, name,
    5197 +                                mode, uid, gid, NULL, NULL, 0);
    5198 +}
    5199 +
    5200 +yaffs_Object *yaffs_MknodSpecial(yaffs_Object * parent, const YCHAR * name,
    5201 +                                __u32 mode, __u32 uid, __u32 gid, __u32 rdev)
    5202 +{
    5203 +       return yaffs_MknodObject(YAFFS_OBJECT_TYPE_SPECIAL, parent, name, mode,
    5204 +                                uid, gid, NULL, NULL, rdev);
    5205 +}
    5206 +
    5207 +yaffs_Object *yaffs_MknodSymLink(yaffs_Object * parent, const YCHAR * name,
    5208 +                                __u32 mode, __u32 uid, __u32 gid,
    5209 +                                const YCHAR * alias)
    5210 +{
    5211 +       return yaffs_MknodObject(YAFFS_OBJECT_TYPE_SYMLINK, parent, name, mode,
    5212 +                                uid, gid, NULL, alias, 0);
    5213 +}
    5214 +
    5215 +/* yaffs_Link returns the object id of the equivalent object.*/
    5216 +yaffs_Object *yaffs_Link(yaffs_Object * parent, const YCHAR * name,
    5217 +                        yaffs_Object * equivalentObject)
    5218 +{
    5219 +       /* Get the real object in case we were fed a hard link as an equivalent object */
     4189+yaffs_Object *yaffs_MknodFile(yaffs_Object *parent,const YCHAR *name, __u32 mode, __u32 uid, __u32 gid)
     4190+{
     4191+       return yaffs_MknodObject(YAFFS_OBJECT_TYPE_FILE,parent,name,mode,uid,gid,NULL,NULL,0);
     4192+}
     4193+
     4194+yaffs_Object *yaffs_MknodDirectory(yaffs_Object *parent,const YCHAR *name, __u32 mode, __u32 uid, __u32 gid)
     4195+{
     4196+       return yaffs_MknodObject(YAFFS_OBJECT_TYPE_DIRECTORY,parent,name,mode,uid,gid,NULL,NULL,0);
     4197+}
     4198+
     4199+yaffs_Object *yaffs_MknodSpecial(yaffs_Object *parent,const YCHAR *name, __u32 mode, __u32 uid, __u32 gid, __u32 rdev)
     4200+{
     4201+       return yaffs_MknodObject(YAFFS_OBJECT_TYPE_SPECIAL,parent,name,mode,uid,gid,NULL,NULL,rdev);
     4202+}
     4203+
     4204+yaffs_Object *yaffs_MknodSymLink(yaffs_Object *parent,const YCHAR *name, __u32 mode, __u32 uid, __u32 gid,const YCHAR *alias)
     4205+{
     4206+       return yaffs_MknodObject(YAFFS_OBJECT_TYPE_SYMLINK,parent,name,mode,uid,gid,NULL,alias,0);
     4207+}
     4208+
     4209+// NB yaffs_Link returns the object id of the equivalent object.
     4210+yaffs_Object *yaffs_Link(yaffs_Object *parent, const YCHAR *name, yaffs_Object *equivalentObject)
     4211+{
     4212+       // Get the real object in case we were fed a hard link as an equivalent object
    52204213+       equivalentObject = yaffs_GetEquivalentObject(equivalentObject);
    5221 +
    5222 +       if (yaffs_MknodObject
    5223 +           (YAFFS_OBJECT_TYPE_HARDLINK, parent, name, 0, 0, 0,
    5224 +            equivalentObject, NULL, 0)) {
     4214+       
     4215+       if(yaffs_MknodObject(YAFFS_OBJECT_TYPE_HARDLINK,parent,name,0,0,0,equivalentObject,NULL,0))
     4216+       {
    52254217+               return equivalentObject;
    5226 +       } else {
     4218+       }
     4219+       else
     4220+       {
    52274221+               return NULL;
    52284222+       }
    5229 +
    5230 +}
    5231 +
    5232 +static int yaffs_ChangeObjectName(yaffs_Object * obj, yaffs_Object * newDir,
    5233 +                                 const YCHAR * newName, int force, int shadows)
     4223+       
     4224+}
     4225+
     4226+
     4227+static int yaffs_ChangeObjectName(yaffs_Object *obj, yaffs_Object *newDir, const YCHAR *newName,int force,int shadows)
    52344228+{
    52354229+       int unlinkOp;
    52364230+       int deleteOp;
    5237 +
    5238 +       yaffs_Object *existingTarget;
    5239 +
    5240 +       if (newDir == NULL) {
    5241 +               newDir = obj->parent;   /* use the old directory */
    5242 +       }
    5243 +
    5244 +       if (newDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) {
    5245 +               T(YAFFS_TRACE_ALWAYS,
    5246 +                 (TSTR
    5247 +                  ("tragendy: yaffs_ChangeObjectName: newDir is not a directory"
    5248 +                   TENDSTR)));
     4231+       
     4232+       yaffs_Object * existingTarget;
     4233+
     4234+       if(newDir == NULL)
     4235+       {
     4236+               newDir = obj->parent; // use the old directory
     4237+       }
     4238+       
     4239+       if(newDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY)
     4240+       {
     4241+               T(YAFFS_TRACE_ALWAYS,(TSTR("tragendy: yaffs_ChangeObjectName: newDir is not a directory"TENDSTR)));
    52494242+               YBUG();
    52504243+       }
    5251 +       
    5252 +       /* TODO: Do we need this different handling for YAFFS2 and YAFFS1?? */
    5253 +       if (obj->myDev->isYaffs2) {
     4244+
     4245+       // TODO: Do we need this different handling for YAFFS2 and YAFFS1??
     4246+       if(obj->myDev->isYaffs2)
     4247+       {
    52544248+               unlinkOp = (newDir == obj->myDev->unlinkedDir);
    5255 +       } else {
    5256 +               unlinkOp = (newDir == obj->myDev->unlinkedDir
    5257 +                           && obj->variantType == YAFFS_OBJECT_TYPE_FILE);
     4249+       }
     4250+       else
     4251+       {
     4252+               unlinkOp = (newDir == obj->myDev->unlinkedDir && obj->variantType == YAFFS_OBJECT_TYPE_FILE);
    52584253+       }
    52594254+
    52604255+       deleteOp = (newDir == obj->myDev->deletedDir);
    5261 +
    5262 +       existingTarget = yaffs_FindObjectByName(newDir, newName);
    5263 +
    5264 +       /* If the object is a file going into the unlinked directory,
    5265 +        *   then it is OK to just stuff it in since duplicate names are allowed.
    5266 +        *   else only proceed if the new name does not exist and if we're putting
    5267 +        *   it into a directory.
    5268 +        */
    5269 +       if ((unlinkOp ||
    5270 +            deleteOp ||
    5271 +            force ||
    5272 +            (shadows > 0) ||
    5273 +            !existingTarget) &&
    5274 +           newDir->variantType == YAFFS_OBJECT_TYPE_DIRECTORY) {
    5275 +               yaffs_SetObjectName(obj, newName);
     4256+       
     4257+       existingTarget = yaffs_FindObjectByName(newDir,newName);
     4258+       
     4259+       // If the object is a file going into the unlinked directory, then it is OK to just stuff it in since
     4260+       // duplicate names are allowed.
     4261+       // Otherwise only proceed if the new name does not exist and if we're putting it into a directory.
     4262+       if( (unlinkOp||
     4263+                deleteOp ||
     4264+                force ||
     4265+                (shadows > 0) ||
     4266+                !existingTarget)  &&
     4267+            newDir->variantType == YAFFS_OBJECT_TYPE_DIRECTORY)
     4268+       {
     4269+               yaffs_SetObjectName(obj,newName);
    52764270+               obj->dirty = 1;
    5277 +
    5278 +               yaffs_AddObjectToDirectory(newDir, obj);
    5279 +
    5280 +               if (unlinkOp)
    5281 +                       obj->unlinked = 1;
    5282 +
    5283 +               /* If it is a deletion then we mark it as a shrink for gc purposes. */
    5284 +               if (yaffs_UpdateObjectHeader(obj, newName, 0, deleteOp, shadows)>= 0)
     4271+               
     4272+               yaffs_AddObjectToDirectory(newDir,obj);
     4273+               
     4274+               if(unlinkOp) obj->unlinked = 1;
     4275+               
     4276+               // If it is a deletion then we mark it as a shrink for gc purposes.
     4277+               if(yaffs_UpdateObjectHeader(obj,newName,0,deleteOp,shadows) >= 0)
     4278+               {
    52854279+                       return YAFFS_OK;
    5286 +       }
    5287 +
     4280+               }
     4281+       }
     4282+       
    52884283+       return YAFFS_FAIL;
    52894284+}
    52904285+
    5291 +int yaffs_RenameObject(yaffs_Object * oldDir, const YCHAR * oldName,
    5292 +                      yaffs_Object * newDir, const YCHAR * newName)
     4286+
     4287+
     4288+int yaffs_RenameObject(yaffs_Object *oldDir, const YCHAR *oldName, yaffs_Object *newDir, const YCHAR *newName)
    52934289+{
    52944290+       yaffs_Object *obj;
    52954291+       yaffs_Object *existingTarget;
    52964292+       int force = 0;
    5297 +
     4293+       
    52984294+#ifdef CONFIG_YAFFS_CASE_INSENSITIVE
    5299 +       /* Special case for case insemsitive systems (eg. WinCE).
    5300 +        * While look-up is case insensitive, the name isn't.
    5301 +        * Therefore we might want to change x.txt to X.txt
    5302 +       */
    5303 +       if (oldDir == newDir && yaffs_strcmp(oldName, newName) == 0) {
     4295+       // Special case for case insemsitive systems (eg. WinCE).
     4296+       // While look-up is case insensitive, the name isn't.
     4297+       // THerefore we might want to change x.txt to X.txt
     4298+       if(oldDir == newDir && yaffs_strcmp(oldName,newName) == 0)
     4299+       {
    53044300+               force = 1;
    5305 +       }
    5306 +#endif
    5307 +
    5308 +       obj = yaffs_FindObjectByName(oldDir, oldName);
    5309 +       /* Check new name to long. */
    5310 +       if (obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK &&
    5311 +           yaffs_strlen(newName) > YAFFS_MAX_ALIAS_LENGTH)
    5312 +         /* ENAMETOOLONG */
    5313 +         return YAFFS_FAIL;
    5314 +       else if (obj->variantType != YAFFS_OBJECT_TYPE_SYMLINK &&
    5315 +                yaffs_strlen(newName) > YAFFS_MAX_NAME_LENGTH)
    5316 +         /* ENAMETOOLONG */
    5317 +         return YAFFS_FAIL;
    5318 +
    5319 +       if (obj && obj->renameAllowed) {
    5320 +
    5321 +               /* Now do the handling for an existing target, if there is one */
    5322 +
    5323 +               existingTarget = yaffs_FindObjectByName(newDir, newName);
    5324 +               if (existingTarget &&
    5325 +                   existingTarget->variantType == YAFFS_OBJECT_TYPE_DIRECTORY &&
    5326 +                   !list_empty(&existingTarget->variant.directoryVariant.children)) {
    5327 +                       /* There is a target that is a non-empty directory, so we fail */
    5328 +                       return YAFFS_FAIL;      /* EEXIST or ENOTEMPTY */
    5329 +               } else if (existingTarget && existingTarget != obj) {
    5330 +                       /* Nuke the target first, using shadowing,
    5331 +                        * but only if it isn't the same object
    5332 +                        */
    5333 +                       yaffs_ChangeObjectName(obj, newDir, newName, force,
    5334 +                                              existingTarget->objectId);
    5335 +                       yaffs_UnlinkObject(existingTarget);
    5336 +               }
    5337 +
    5338 +               return yaffs_ChangeObjectName(obj, newDir, newName, 1, 0);
     4301+       }       
     4302+#endif
     4303+       
     4304+       obj = yaffs_FindObjectByName(oldDir,oldName);
     4305+       
     4306+       if(obj && obj->renameAllowed)
     4307+       {
     4308+       
     4309+               // Now do the handling for an existing target, if there is one
     4310+       
     4311+               existingTarget = yaffs_FindObjectByName(newDir,newName);
     4312+               if(existingTarget &&
     4313+                  existingTarget->variantType == YAFFS_OBJECT_TYPE_DIRECTORY &&
     4314+                  !list_empty(&existingTarget->variant.directoryVariant.children))
     4315+                {
     4316+                       // There is a target that is a non-empty directory, so we have to fail
     4317+                       return YAFFS_FAIL; // EEXIST or ENOTEMPTY
     4318+                }
     4319+                else if(existingTarget)
     4320+                {
     4321+                       // Nuke the target first, using shadowing
     4322+                        yaffs_ChangeObjectName(obj,newDir,newName,force,existingTarget->objectId);
     4323+                        yaffs_Unlink(newDir,newName);
     4324+                }
     4325+               
     4326+               
     4327+               return yaffs_ChangeObjectName(obj,newDir,newName,force,0);
    53394328+       }
    53404329+       return YAFFS_FAIL;
    53414330+}
    53424331+
    5343 +/*------------------------- Block Management and Page Allocation ----------------*/
    5344 +
    5345 +static int yaffs_InitialiseBlocks(yaffs_Device * dev)
    5346 +{
    5347 +       int nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1;
    5348 +       
    5349 +       dev->allocationBlock = -1;      /* force it to get a new one */
    5350 +
    5351 +       /* Todo we're assuming the malloc will pass. */
     4332+
     4333+#if 0
     4334+
     4335+static int yaffs_CheckObjectHashSanity(yaffs_Device *dev)
     4336+{
     4337+       // Scan the buckets and check that the lists
     4338+       // have as many members as the count says there are
     4339+       int bucket;
     4340+       int countEm;
     4341+       struct list_head *j;
     4342+       int ok = YAFFS_OK;
     4343+       
     4344+       for(bucket = 0; bucket < YAFFS_NOBJECT_BUCKETS; bucket++)
     4345+       {
     4346+               countEm = 0;
     4347+               
     4348+               list_for_each(j,&dev->objectBucket[bucket].list)
     4349+               {
     4350+                       countEm++;
     4351+               }
     4352+               
     4353+               if(countEm != dev->objectBucket[bucket].count)
     4354+               {
     4355+                       T(YAFFS_TRACE_ERROR,(TSTR("Inode hash inconsistency" TENDSTR)));
     4356+                       ok = YAFFS_FAIL;
     4357+               }
     4358+       }
     4359+
     4360+       return ok;
     4361+}
     4362+
     4363+
     4364+void yaffs_ObjectTest(yaffs_Device *dev)
     4365+{
     4366+       yaffs_Object *in[1000];
     4367+       int inNo[1000];
     4368+       yaffs_Object *inold[1000];
     4369+       int i;
     4370+       int j;
     4371+       
     4372+       memset(in,0,1000*sizeof(yaffs_Object *));
     4373+       memset(inold,0,1000*sizeof(yaffs_Object *));
     4374+       
     4375+       yaffs_CheckObjectHashSanity(dev);
     4376+       
     4377+       for(j = 0; j < 10; j++)
     4378+       {
     4379+               //T(("%d\n",j));
     4380+               
     4381+               for(i = 0; i < 1000; i++)
     4382+               {
     4383+                       in[i] = yaffs_CreateNewObject(dev,-1,YAFFS_OBJECT_TYPE_FILE);
     4384+                       if(!in[i])
     4385+                       {
     4386+                               YINFO("No more inodes");
     4387+                       }
     4388+                       else
     4389+                       {
     4390+                               inNo[i] = in[i]->objectId;
     4391+                       }
     4392+               }
     4393+               
     4394+               for(i = 0; i < 1000; i++)
     4395+               {
     4396+                       if(yaffs_FindObjectByNumber(dev,inNo[i]) != in[i])
     4397+                       {
     4398+                               //T(("Differnce in look up test\n"));
     4399+                       }
     4400+                       else
     4401+                       {
     4402+                               // T(("Look up ok\n"));
     4403+                       }
     4404+               }
     4405+               
     4406+               yaffs_CheckObjectHashSanity(dev);
     4407+       
     4408+               for(i = 0; i < 1000; i+=3)
     4409+               {
     4410+                       yaffs_FreeObject(in[i]);       
     4411+                       in[i] = NULL;
     4412+               }
     4413+               
     4414+       
     4415+               yaffs_CheckObjectHashSanity(dev);
     4416+       }
     4417+               
     4418+}
     4419+
     4420+#endif
     4421+
     4422+/////////////////////////// Block Management and Page Allocation ///////////////////
     4423+
     4424+
     4425+static int yaffs_InitialiseBlocks(yaffs_Device *dev,int nBlocks)
     4426+{
     4427+       dev->allocationBlock = -1; // force it to get a new one
     4428+       //Todo we're assuming the malloc will pass.
    53524429+       dev->blockInfo = YMALLOC(nBlocks * sizeof(yaffs_BlockInfo));
    5353 +       if(!dev->blockInfo){
    5354 +               dev->blockInfo = YMALLOC_ALT(nBlocks * sizeof(yaffs_BlockInfo));
    5355 +               dev->blockInfoAlt = 1;
    5356 +       }
    5357 +       else
    5358 +               dev->blockInfoAlt = 0;
    5359 +       
    5360 +       /* Set up dynamic blockinfo stuff. */
    5361 +       dev->chunkBitmapStride = (dev->nChunksPerBlock + 7) / 8; /* round up bytes */
     4430+       // Set up dynamic blockinfo stuff.
     4431+       dev->chunkBitmapStride = (dev->nChunksPerBlock+7)/8;
    53624432+       dev->chunkBits = YMALLOC(dev->chunkBitmapStride * nBlocks);
    5363 +       if(!dev->chunkBits){
    5364 +               dev->chunkBits = YMALLOC_ALT(dev->chunkBitmapStride * nBlocks);
    5365 +               dev->chunkBitsAlt = 1;
    5366 +       }
    5367 +       else
    5368 +               dev->chunkBitsAlt = 0;
    5369 +       
    5370 +       if (dev->blockInfo && dev->chunkBits) {
    5371 +               memset(dev->blockInfo, 0, nBlocks * sizeof(yaffs_BlockInfo));
    5372 +               memset(dev->chunkBits, 0, dev->chunkBitmapStride * nBlocks);
     4433+       if(dev->blockInfo && dev->chunkBits)
     4434+       {
     4435+               memset(dev->blockInfo,0,nBlocks * sizeof(yaffs_BlockInfo));
     4436+               memset(dev->chunkBits,0,dev->chunkBitmapStride * nBlocks);
    53734437+               return YAFFS_OK;
    53744438+       }
    5375 +
     4439+       
    53764440+       return YAFFS_FAIL;
    5377 +
    5378 +}
    5379 +
    5380 +static void yaffs_DeinitialiseBlocks(yaffs_Device * dev)
    5381 +{
    5382 +       if(dev->blockInfoAlt)
    5383 +               YFREE_ALT(dev->blockInfo);
    5384 +       else
    5385 +               YFREE(dev->blockInfo);
    5386 +       dev->blockInfoAlt = 0;
    5387 +
     4441+       
     4442+}
     4443+
     4444+static void yaffs_DeinitialiseBlocks(yaffs_Device *dev)
     4445+{
     4446+       YFREE(dev->blockInfo);
    53884447+       dev->blockInfo = NULL;
    5389 +       
    5390 +       if(dev->chunkBitsAlt)
    5391 +               YFREE_ALT(dev->chunkBits);
    5392 +       else
    5393 +               YFREE(dev->chunkBits);
    5394 +       dev->chunkBitsAlt = 0;
     4448+       YFREE(dev->chunkBits);
    53954449+       dev->chunkBits = NULL;
    53964450+}
    53974451+
    5398 +static int yaffs_BlockNotDisqualifiedFromGC(yaffs_Device * dev,
    5399 +                                           yaffs_BlockInfo * bi)
     4452+
     4453+static int yaffs_BlockNotDisqualifiedFromGC(yaffs_Device *dev, yaffs_BlockInfo *bi)
    54004454+{
    54014455+       int i;
    54024456+       __u32 seq;
    54034457+       yaffs_BlockInfo *b;
    5404 +
    5405 +       if (!dev->isYaffs2)
    5406 +               return 1;       /* disqualification only applies to yaffs2. */
    5407 +
    5408 +       if (!bi->hasShrinkHeader)
    5409 +               return 1;       /* can gc */
    5410 +
    5411 +       /* Find the oldest dirty sequence number if we don't know it and save it
    5412 +        * so we don't have to keep recomputing it.
    5413 +        */
    5414 +       if (!dev->oldestDirtySequence) {
     4458+       
     4459+       if(!dev->isYaffs2) return 1; // disqualification only applies to yaffs2.
     4460+       
     4461+       if(!bi->hasShrinkHeader) return 1; // can gc
     4462+
     4463+
     4464+       // Find the oldest dirty sequence number if we don't know it and save it
     4465+       // so we don't have to keep recomputing it.
     4466+       if(!dev->oldestDirtySequence)
     4467+       {
    54154468+               seq = dev->sequenceNumber;
    54164469+
    5417 +               for (i = dev->internalStartBlock; i <= dev->internalEndBlock;
    5418 +                    i++) {
    5419 +                       b = yaffs_GetBlockInfo(dev, i);
    5420 +                       if (b->blockState == YAFFS_BLOCK_STATE_FULL &&
    5421 +                           (b->pagesInUse - b->softDeletions) <
    5422 +                           dev->nChunksPerBlock && b->sequenceNumber < seq) {
    5423 +                               seq = b->sequenceNumber;
     4470+               for(i = dev->internalStartBlock; i <= dev->internalEndBlock; i++)
     4471+               {
     4472+                       b = yaffs_GetBlockInfo(dev,i);
     4473+                       if(b->blockState == YAFFS_BLOCK_STATE_FULL &&
     4474+                       (b->pagesInUse - b->softDeletions )< dev->nChunksPerBlock &&
     4475+                       b->sequenceNumber < seq)
     4476+                       {
     4477+                               seq = b->sequenceNumber;
    54244478+                       }
    54254479+               }
     
    54274481+       }
    54284482+
    5429 +       /* Can't do gc of this block if there are any blocks older than this one that have
    5430 +        * discarded pages.
    5431 +        */
     4483+
     4484+       // Can't do gc of this block if there are any blocks older than this one that have
     4485+       // discarded pages.
    54324486+       return (bi->sequenceNumber <= dev->oldestDirtySequence);
    5433 +
    5434 +}
    5435 +
    5436 +/* FindDiretiestBlock is used to select the dirtiest block (or close enough)
    5437 + * for garbage collection.
    5438 + */
    5439 +
    5440 +static int yaffs_FindBlockForGarbageCollection(yaffs_Device * dev,
    5441 +                                              int aggressive)
     4487+       
     4488+       
     4489+       return 1;
     4490+
     4491+}
     4492+
     4493+// FindDiretiestBlock is used to select the dirtiest block (or close enough)
     4494+// for garbage collection.
     4495+//
     4496+
     4497+
     4498+
     4499+static int yaffs_FindBlockForGarbageCollection(yaffs_Device *dev,int aggressive)
    54424500+{
    54434501+
    54444502+       int b = dev->currentDirtyChecker;
    5445 +
     4503+       
    54464504+       int i;
    54474505+       int iterations;
    54484506+       int dirtiest = -1;
    5449 +       int pagesInUse;
    5450 +       int prioritised=0;
     4507+       int pagesInUse;
    54514508+       yaffs_BlockInfo *bi;
    5452 +       static int nonAggressiveSkip = 0;
    5453 +       int pendingPrioritisedExist = 0;
    5454 +       
    5455 +       /* First let's see if we need to grab a prioritised block */
    5456 +       if(dev->hasPendingPrioritisedGCs){
    5457 +               for(i = dev->internalStartBlock; i < dev->internalEndBlock && !prioritised; i++){
    5458 +
    5459 +                       bi = yaffs_GetBlockInfo(dev, i);
    5460 +                       if(bi->gcPrioritise) {
    5461 +                               pendingPrioritisedExist = 1;
    5462 +                               if(bi->blockState == YAFFS_BLOCK_STATE_FULL &&
    5463 +                                  yaffs_BlockNotDisqualifiedFromGC(dev, bi)){
    5464 +                                       pagesInUse = (bi->pagesInUse - bi->softDeletions);
    5465 +                                       dirtiest = i;
    5466 +                                       prioritised = 1;
    5467 +                                       aggressive = 1; /* Fool the non-aggressive skip logiv below */
    5468 +                               }
    5469 +                       }
    5470 +               }
    5471 +               
    5472 +               if(!pendingPrioritisedExist) /* None found, so we can clear this */
    5473 +                       dev->hasPendingPrioritisedGCs = 0;
    5474 +       }
    5475 +
    5476 +       /* If we're doing aggressive GC then we are happy to take a less-dirty block, and
    5477 +        * search harder.
    5478 +        * else (we're doing a leasurely gc), then we only bother to do this if the
    5479 +        * block has only a few pages in use.
    5480 +        */
     4509+       static int  nonAggressiveSkip = 0;
     4510+
     4511+       // If we're doing aggressive GC then we are happy to take a less-dirty block, and
     4512+       // search harder.
     4513+       // else (we're doing a leasurely gc), then we only bother to do this if the
     4514+       // block has only a few pages in use.
     4515+       
    54814516+
    54824517+       nonAggressiveSkip--;
    54834518+
    5484 +       if (!aggressive && (nonAggressiveSkip > 0)) {
     4519+       if(!aggressive &&(nonAggressiveSkip > 0))
     4520+       {
    54854521+               return -1;
    54864522+       }
    54874523+
    5488 +       if(!prioritised)
    5489 +               pagesInUse =
    5490 +                       (aggressive) ? dev->nChunksPerBlock : YAFFS_PASSIVE_GC_CHUNKS + 1;
    5491 +
    5492 +       if (aggressive) {
    5493 +               iterations =
    5494 +                   dev->internalEndBlock - dev->internalStartBlock + 1;
    5495 +       } else {
    5496 +               iterations =
    5497 +                   dev->internalEndBlock - dev->internalStartBlock + 1;
    5498 +               iterations = iterations / 16;
    5499 +               if (iterations > 200) {
     4524+       pagesInUse = (aggressive)? dev->nChunksPerBlock : YAFFS_PASSIVE_GC_CHUNKS + 1;
     4525+
     4526+       if(aggressive)
     4527+       {
     4528+               iterations = dev->internalEndBlock - dev->internalStartBlock + 1;
     4529+       }
     4530+       else
     4531+       {
     4532+               iterations = dev->internalEndBlock - dev->internalStartBlock + 1;
     4533+               iterations = iterations / 16;
     4534+               if(iterations > 200)
     4535+               {
    55004536+                       iterations = 200;
    55014537+               }
    55024538+       }
    5503 +
    5504 +       for (i = 0; i <= iterations && pagesInUse > 0 && !prioritised; i++) {
     4539+       
     4540+       for(i = 0; i <= iterations && pagesInUse > 0 ; i++)
     4541+       {
    55054542+               b++;
    5506 +               if (b < dev->internalStartBlock || b > dev->internalEndBlock) {
    5507 +                       b = dev->internalStartBlock;
    5508 +               }
    5509 +
    5510 +               if (b < dev->internalStartBlock || b > dev->internalEndBlock) {
    5511 +                       T(YAFFS_TRACE_ERROR,
    5512 +                         (TSTR("**>> Block %d is not valid" TENDSTR), b));
     4543+               if ( b < dev->internalStartBlock || b > dev->internalEndBlock)
     4544+               {
     4545+                       b =  dev->internalStartBlock;
     4546+               }
     4547+
     4548+               if(b < dev->internalStartBlock || b > dev->internalEndBlock)
     4549+               {
     4550+                       T(YAFFS_TRACE_ERROR,(TSTR("**>> Block %d is not valid" TENDSTR),b));
    55134551+                       YBUG();
    55144552+               }
    5515 +
    5516 +               bi = yaffs_GetBlockInfo(dev, b);
    5517 +
    5518 +#if 0
    5519 +               if (bi->blockState == YAFFS_BLOCK_STATE_CHECKPOINT) {
    5520 +                       dirtiest = b;
    5521 +                       pagesInUse = 0;
    5522 +               }
    5523 +               else
    5524 +#endif
    5525 +
    5526 +               if (bi->blockState == YAFFS_BLOCK_STATE_FULL &&
    5527 +                      (bi->pagesInUse - bi->softDeletions) < pagesInUse &&
    5528 +                       yaffs_BlockNotDisqualifiedFromGC(dev, bi)) {
     4553+               
     4554+               bi = yaffs_GetBlockInfo(dev,b);
     4555+               
     4556+               if(bi->blockState == YAFFS_BLOCK_STATE_FULL &&
     4557+                  (bi->pagesInUse - bi->softDeletions )< pagesInUse &&
     4558+                  yaffs_BlockNotDisqualifiedFromGC(dev,bi))
     4559+               {
    55294560+                       dirtiest = b;
    55304561+                       pagesInUse = (bi->pagesInUse - bi->softDeletions);
    55314562+               }
    55324563+       }
    5533 +
     4564+       
    55344565+       dev->currentDirtyChecker = b;
    5535 +
    5536 +       if (dirtiest > 0) {
    5537 +               T(YAFFS_TRACE_GC,
    5538 +                 (TSTR("GC Selected block %d with %d free, prioritised:%d" TENDSTR), dirtiest,
    5539 +                  dev->nChunksPerBlock - pagesInUse,prioritised));
    5540 +       }
    5541 +
    5542 +       dev->oldestDirtySequence = 0;
    5543 +
    5544 +       if (dirtiest > 0) {
     4566+       
     4567+       if(dirtiest > 0)
     4568+       {
     4569+               T(YAFFS_TRACE_GC,(TSTR("GC Selected block %d with %d free" TENDSTR),dirtiest,dev->nChunksPerBlock - pagesInUse));
     4570+       }
     4571+       
     4572+       dev->oldestDirtySequence = 0; // clear this
     4573+       
     4574+       if(dirtiest > 0)
     4575+       {
    55454576+               nonAggressiveSkip = 4;
    55464577+       }
     
    55494580+}
    55504581+
    5551 +static void yaffs_BlockBecameDirty(yaffs_Device * dev, int blockNo)
    5552 +{
    5553 +       yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, blockNo);
    5554 +
     4582+
     4583+static void yaffs_BlockBecameDirty(yaffs_Device *dev,int blockNo)
     4584+{
     4585+       yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,blockNo);
     4586+       
    55554587+       int erasedOk = 0;
    5556 +
    5557 +       /* If the block is still healthy erase it and mark as clean.
    5558 +        * If the block has had a data failure, then retire it.
    5559 +        */
    5560 +       
    5561 +       T(YAFFS_TRACE_GC | YAFFS_TRACE_ERASE,
    5562 +               (TSTR("yaffs_BlockBecameDirty block %d state %d %s"TENDSTR),
    5563 +               blockNo, bi->blockState, (bi->needsRetiring) ? "needs retiring" : ""));
    5564 +               
     4588+       
     4589+       // If the block is still healthy erase it and mark as clean.
     4590+       // If the block has had a data failure, then retire it.
    55654591+       bi->blockState = YAFFS_BLOCK_STATE_DIRTY;
    55664592+
    5567 +       if (!bi->needsRetiring) {
    5568 +               yaffs_InvalidateCheckpoint(dev);
    5569 +               erasedOk = yaffs_EraseBlockInNAND(dev, blockNo);
    5570 +               if (!erasedOk) {
     4593+       if(!bi->needsRetiring)
     4594+       {
     4595+               erasedOk = yaffs_EraseBlockInNAND(dev,blockNo);
     4596+               if(!erasedOk)
     4597+               {
    55714598+                       dev->nErasureFailures++;
    5572 +                       T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,
    5573 +                         (TSTR("**>> Erasure failed %d" TENDSTR), blockNo));
    5574 +               }
    5575 +       }
    5576 +
    5577 +       if (erasedOk && (yaffs_traceMask & YAFFS_TRACE_ERASE)) {
    5578 +               int i;
    5579 +               for (i = 0; i < dev->nChunksPerBlock; i++) {
    5580 +                       if (!yaffs_CheckChunkErased
    5581 +                           (dev, blockNo * dev->nChunksPerBlock + i)) {
    5582 +                               T(YAFFS_TRACE_ERROR,
    5583 +                                 (TSTR
    5584 +                                  (">>Block %d erasure supposedly OK, but chunk %d not erased"
    5585 +                                   TENDSTR), blockNo, i));
     4599+                       T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,(TSTR("**>> Erasure failed %d" TENDSTR),blockNo));
     4600+               }
     4601+       }
     4602+
     4603+       if(erasedOk && (yaffs_traceMask & YAFFS_TRACE_ERASE))
     4604+       {
     4605+                       int i;
     4606+                       for(i = 0; i < dev->nChunksPerBlock; i++)
     4607+                       {
     4608+                                       if(!yaffs_CheckChunkErased(dev,blockNo * dev->nChunksPerBlock + i))
     4609+                                       {
     4610+                                               T(YAFFS_TRACE_ERROR,(TSTR(">>Block %d erasure supposedly OK, but chunk %d not erased" TENDSTR),blockNo,i));
     4611+                                       }
    55864612+                       }
    5587 +               }
    5588 +       }
    5589 +
    5590 +       if (erasedOk) {
    5591 +               /* Clean it up... */
     4613+       }
     4614+       
     4615+       if( erasedOk )
     4616+       {
     4617+               // Clean it up...
    55924618+               bi->blockState = YAFFS_BLOCK_STATE_EMPTY;
    55934619+               dev->nErasedBlocks++;
    55944620+               bi->pagesInUse = 0;
    55954621+               bi->softDeletions = 0;
    5596 +               bi->hasShrinkHeader = 0;
    5597 +               bi->skipErasedCheck = 1;  /* This is clean, so no need to check */
    5598 +               bi->gcPrioritise = 0;
    5599 +               yaffs_ClearChunkBits(dev, blockNo);
    5600 +
    5601 +               T(YAFFS_TRACE_ERASE,
    5602 +                 (TSTR("Erased block %d" TENDSTR), blockNo));
    5603 +       } else {
    5604 +               dev->nFreeChunks -= dev->nChunksPerBlock;       /* We lost a block of free space */
    5605 +
    5606 +               yaffs_RetireBlock(dev, blockNo);
    5607 +               T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,
    5608 +                 (TSTR("**>> Block %d retired" TENDSTR), blockNo));
    5609 +       }
    5610 +}
    5611 +
    5612 +static int yaffs_FindBlockForAllocation(yaffs_Device * dev)
     4622+               bi->hasShrinkHeader=0;
     4623+               yaffs_ClearChunkBits(dev,blockNo);
     4624+       
     4625+               T(YAFFS_TRACE_ERASE,(TSTR("Erased block %d" TENDSTR),blockNo));
     4626+       }
     4627+       else
     4628+       {
     4629+               dev->nFreeChunks -= dev->nChunksPerBlock; // We lost a block of free space
     4630+               
     4631+               yaffs_RetireBlock(dev,blockNo);
     4632+               T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,(TSTR("**>> Block %d retired" TENDSTR),blockNo));
     4633+       }
     4634+}
     4635+
     4636+#if 0
     4637+static void yaffs_DumpBlockStats(yaffs_Device *dev)
     4638+{
     4639+       int i,j;
     4640+       yaffs_BlockInfo *bi;
     4641+       
     4642+       for(i= dev->internalStartBlock; i <=dev->internalEndBlock; i++)
     4643+       {
     4644+               bi = yaffs_GetBlockInfo(dev,i);
     4645+               T(YAFFS_TRACE_ALLOCATE,(TSTR("%3d state %d shrink %d inuse %d/%d seq %d pages"),i,
     4646+               bi->blockState,bi->hasShrinkHeader,bi->pagesInUse,bi->softDeletions,bi->sequenceNumber));       
     4647+               
     4648+               for(j = 0; j < dev->nChunksPerBlock; j++)
     4649+               {
     4650+                       if(yaffs_CheckChunkBit(dev,i,j))
     4651+                       {
     4652+                               T(YAFFS_TRACE_ALLOCATE,(TSTR(" %d"),j));
     4653+
     4654+                       }
     4655+               }
     4656+               T(YAFFS_TRACE_ALLOCATE,(TSTR(" " TENDSTR)));
     4657+
     4658+       }
     4659+}
     4660+#endif
     4661+
     4662+
     4663+static int yaffs_FindBlockForAllocation(yaffs_Device *dev)
    56134664+{
    56144665+       int i;
    5615 +
     4666+       
    56164667+       yaffs_BlockInfo *bi;
    5617 +
    5618 +       if (dev->nErasedBlocks < 1) {
    5619 +               /* Hoosterman we've got a problem.
    5620 +                * Can't get space to gc
    5621 +                */
    5622 +               T(YAFFS_TRACE_ERROR,
    5623 +                 (TSTR("yaffs tragedy: no more eraased blocks" TENDSTR)));
     4668+       
     4669+#if 0
     4670+       static int j = 0;
     4671+       j++;
     4672+       if(j < 0 || j > 100)
     4673+       {
     4674+               j = 0;
     4675+               yaffs_DumpBlockStats(dev);
     4676+       }
     4677+       
     4678+#endif
     4679+       
     4680+       if(dev->nErasedBlocks < 1)
     4681+       {
     4682+               // Hoosterman we've got a problem.
     4683+               // Can't get space to gc
     4684+               T(YAFFS_TRACE_ERROR, (TSTR("yaffs tragedy: no more eraased blocks" TENDSTR)));
    56244685+
    56254686+               return -1;
    56264687+       }
    56274688+       
    5628 +       /* Find an empty block. */
    5629 +
    5630 +       for (i = dev->internalStartBlock; i <= dev->internalEndBlock; i++) {
     4689+       // Find an empty block.
     4690+       
     4691+       for(i = dev->internalStartBlock; i <= dev->internalEndBlock; i++)
     4692+       {
    56314693+               dev->allocationBlockFinder++;
    5632 +               if (dev->allocationBlockFinder < dev->internalStartBlock
    5633 +                   || dev->allocationBlockFinder > dev->internalEndBlock) {
     4694+               if(dev->allocationBlockFinder < dev->internalStartBlock || dev->allocationBlockFinder> dev->internalEndBlock)
     4695+               {
    56344696+                       dev->allocationBlockFinder = dev->internalStartBlock;
    56354697+               }
    5636 +
    5637 +               bi = yaffs_GetBlockInfo(dev, dev->allocationBlockFinder);
    5638 +
    5639 +               if (bi->blockState == YAFFS_BLOCK_STATE_EMPTY) {
     4698+               
     4699+               bi = yaffs_GetBlockInfo(dev,dev->allocationBlockFinder);
     4700+
     4701+               if(bi->blockState == YAFFS_BLOCK_STATE_EMPTY)
     4702+               {
    56404703+                       bi->blockState = YAFFS_BLOCK_STATE_ALLOCATING;
    56414704+                       dev->sequenceNumber++;
    56424705+                       bi->sequenceNumber = dev->sequenceNumber;
    5643 +                       dev->nErasedBlocks--;
    5644 +                       T(YAFFS_TRACE_ALLOCATE,
    5645 +                         (TSTR("Allocated block %d, seq  %d, %d left" TENDSTR),
    5646 +                          dev->allocationBlockFinder, dev->sequenceNumber,
    5647 +                          dev->nErasedBlocks));
     4706+                       dev->nErasedBlocks--;           
     4707+                       T(YAFFS_TRACE_ALLOCATE,(TSTR("Allocated block %d, seq  %d, %d left" TENDSTR),dev->allocationBlockFinder,dev->sequenceNumber, dev->nErasedBlocks));     
    56484708+                       return dev->allocationBlockFinder;
    56494709+               }
    56504710+       }
    5651 +
    5652 +       T(YAFFS_TRACE_ALWAYS,
    5653 +         (TSTR
    5654 +          ("yaffs tragedy: no more eraased blocks, but there should have been %d"
    5655 +           TENDSTR), dev->nErasedBlocks));
    5656 +
    5657 +       return -1;
    5658 +}
    5659 +
    5660 +
    5661 +// Check if there's space to allocate...
    5662 +// Thinks.... do we need top make this ths same as yaffs_GetFreeChunks()?
    5663 +static int yaffs_CheckSpaceForAllocation(yaffs_Device * dev)
    5664 +{
    5665 +       int reservedChunks;
    5666 +       int reservedBlocks = dev->nReservedBlocks;
    5667 +       int checkpointBlocks;
    5668 +       
    5669 +       checkpointBlocks =  dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint;
    5670 +       if(checkpointBlocks < 0)
    5671 +               checkpointBlocks = 0;
    5672 +       
    5673 +       reservedChunks = ((reservedBlocks + checkpointBlocks) * dev->nChunksPerBlock);
    5674 +       
     4711+       
     4712+       
     4713+       T(YAFFS_TRACE_ALWAYS, (TSTR("yaffs tragedy: no more eraased blocks, but there should have been %d" TENDSTR),dev->nErasedBlocks));
     4714+       
     4715+       
     4716+       
     4717+
     4718+       
     4719+       return -1;     
     4720+}
     4721+
     4722+
     4723+// To determine if we have enough space we just look at the
     4724+// number of erased blocks.
     4725+
     4726+static int yaffs_CheckSpaceForAllocation(yaffs_Device *dev)
     4727+{
     4728+       int reservedChunks = (dev->nReservedBlocks * dev->nChunksPerBlock);
    56754729+       return (dev->nFreeChunks > reservedChunks);
    56764730+}
    56774731+
    5678 +static int yaffs_AllocateChunk(yaffs_Device * dev, int useReserve, yaffs_BlockInfo **blockUsedPtr)
     4732+
     4733+static int yaffs_AllocateChunk(yaffs_Device *dev,int useReserve)
    56794734+{
    56804735+       int retVal;
    56814736+       yaffs_BlockInfo *bi;
    5682 +
    5683 +       if (dev->allocationBlock < 0) {
    5684 +               /* Get next block to allocate off */
     4737+       
     4738+       if(dev->allocationBlock < 0)
     4739+       {
     4740+               // Get next block to allocate off
    56854741+               dev->allocationBlock = yaffs_FindBlockForAllocation(dev);
    56864742+               dev->allocationPage = 0;
    56874743+       }
    5688 +
    5689 +       if (!useReserve && !yaffs_CheckSpaceForAllocation(dev)) {
    5690 +               /* Not enough space to allocate unless we're allowed to use the reserve. */
     4744+       
     4745+       if(!useReserve &&  !yaffs_CheckSpaceForAllocation(dev))
     4746+       {
     4747+               // Not enough space to allocate unless we're allowed to use the reserve.
    56914748+               return -1;
    56924749+       }
    56934750+
    5694 +       if (dev->nErasedBlocks < dev->nReservedBlocks
    5695 +           && dev->allocationPage == 0) {
    5696 +               T(YAFFS_TRACE_ALLOCATE, (TSTR("Allocating reserve" TENDSTR)));
    5697 +       }
    5698 +
    5699 +       /* Next page please.... */
    5700 +       if (dev->allocationBlock >= 0) {
    5701 +               bi = yaffs_GetBlockInfo(dev, dev->allocationBlock);
    5702 +
    5703 +               retVal = (dev->allocationBlock * dev->nChunksPerBlock) +
    5704 +                   dev->allocationPage;
     4751+       if(dev->nErasedBlocks < dev->nReservedBlocks && dev->allocationPage == 0)
     4752+       {
     4753+               T(YAFFS_TRACE_ALLOCATE,(TSTR("Allocating reserve" TENDSTR)));   
     4754+       }
     4755+
     4756+       
     4757+       // Next page please....
     4758+       if(dev->allocationBlock >= 0)
     4759+       {
     4760+               bi = yaffs_GetBlockInfo(dev,dev->allocationBlock);
     4761+               
     4762+               retVal = (dev->allocationBlock * dev->nChunksPerBlock) +
     4763+                                 dev->allocationPage;
    57054764+               bi->pagesInUse++;
    5706 +               yaffs_SetChunkBit(dev, dev->allocationBlock,
    5707 +                                 dev->allocationPage);
     4765+               yaffs_SetChunkBit(dev,dev->allocationBlock,dev->allocationPage);
    57084766+
    57094767+               dev->allocationPage++;
    5710 +
     4768+               
    57114769+               dev->nFreeChunks--;
    5712 +
    5713 +               /* If the block is full set the state to full */
    5714 +               if (dev->allocationPage >= dev->nChunksPerBlock) {
     4770+               
     4771+               // If the block is full set the state to full
     4772+               if(dev->allocationPage >= dev->nChunksPerBlock)
     4773+               {
    57154774+                       bi->blockState = YAFFS_BLOCK_STATE_FULL;
    57164775+                       dev->allocationBlock = -1;
    57174776+               }
    57184777+
    5719 +               if(blockUsedPtr)
    5720 +                       *blockUsedPtr = bi;
    5721 +                       
     4778+
    57224779+               return retVal;
    5723 +       }
    5724 +       
    5725 +       T(YAFFS_TRACE_ERROR,
    5726 +         (TSTR("!!!!!!!!! Allocator out !!!!!!!!!!!!!!!!!" TENDSTR)));
    5727 +
    5728 +       return -1;
    5729 +}
    5730 +
    5731 +static int yaffs_GetErasedChunks(yaffs_Device * dev)
    5732 +{
    5733 +       int n;
    5734 +
    5735 +       n = dev->nErasedBlocks * dev->nChunksPerBlock;
    5736 +
    5737 +       if (dev->allocationBlock > 0) {
    5738 +               n += (dev->nChunksPerBlock - dev->allocationPage);
    5739 +       }
    5740 +
    5741 +       return n;
    5742 +
    5743 +}
    5744 +
    5745 +static int yaffs_GarbageCollectBlock(yaffs_Device * dev, int block)
     4780+               
     4781+       }
     4782+       T(YAFFS_TRACE_ERROR,(TSTR("!!!!!!!!! Allocator out !!!!!!!!!!!!!!!!!" TENDSTR)));
     4783+
     4784+       return -1;     
     4785+}
     4786+
     4787+
     4788+
     4789+
     4790+static int yaffs_GetErasedChunks(yaffs_Device *dev)
     4791+{
     4792+               int n;
     4793+
     4794+               n = dev->nErasedBlocks * dev->nChunksPerBlock;
     4795+
     4796+               if(dev->allocationBlock> 0)
     4797+               {
     4798+                       n += (dev->nChunksPerBlock - dev->allocationPage);
     4799+               }
     4800+
     4801+               return n;
     4802+
     4803+}
     4804+
     4805+static int  yaffs_GarbageCollectBlock(yaffs_Device *dev,int block)
    57464806+{
    57474807+       int oldChunk;
     
    57524812+       int cleanups = 0;
    57534813+       int i;
    5754 +       int isCheckpointBlock;
    57554814+
    57564815+       int chunksBefore = yaffs_GetErasedChunks(dev);
    57574816+       int chunksAfter;
    57584817+
    5759 +       yaffs_ExtendedTags tags;
    5760 +
    5761 +       yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, block);
    5762 +
     4818+       yaffs_ExtendedTags  tags;
     4819+       
     4820+       yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev,block);
     4821+       
    57634822+       yaffs_Object *object;
    5764 +
    5765 +       isCheckpointBlock = (bi->blockState == YAFFS_BLOCK_STATE_CHECKPOINT);
    57664823+       
    57674824+       bi->blockState = YAFFS_BLOCK_STATE_COLLECTING;
    57684825+
    5769 +       T(YAFFS_TRACE_TRACING,
    5770 +         (TSTR("Collecting block %d, in use %d, shrink %d, " TENDSTR), block,
    5771 +          bi->pagesInUse, bi->hasShrinkHeader));
    5772 +
    5773 +       /*yaffs_VerifyFreeChunks(dev); */
    5774 +
    5775 +       bi->hasShrinkHeader = 0;        /* clear the flag so that the block can erase */
    5776 +
    5777 +       /* Take off the number of soft deleted entries because
    5778 +        * they're going to get really deleted during GC.
    5779 +        */
    5780 +       dev->nFreeChunks -= bi->softDeletions;
     4826+       T(YAFFS_TRACE_TRACING,(TSTR("Collecting block %d, in use %d, shrink %d, " TENDSTR),block,bi->pagesInUse,bi->hasShrinkHeader));
     4827+       //T(("Collecting block %d n %d bits %x\n",block, bi->pagesInUse, bi->pageBits));       
     4828+       
     4829+       //yaffs_VerifyFreeChunks(dev);
     4830+
     4831+       bi->hasShrinkHeader = 0; // clear the flag so that the block can erase
     4832+       
     4833+       dev->nFreeChunks -= bi->softDeletions;  // Take off the number of soft deleted entries because
     4834+                                               // they're going to get really deleted during GC.
    57814835+
    57824836+       dev->isDoingGC = 1;
    57834837+
    5784 +       if (isCheckpointBlock ||
    5785 +           !yaffs_StillSomeChunkBits(dev, block)) {
    5786 +               T(YAFFS_TRACE_TRACING,
    5787 +                 (TSTR
    5788 +                  ("Collecting block %d that has no chunks in use" TENDSTR),
    5789 +                  block));
    5790 +               yaffs_BlockBecameDirty(dev, block);
    5791 +       } else {
    5792 +
    5793 +               __u8 *buffer = yaffs_GetTempBuffer(dev, __LINE__);
    5794 +
    5795 +               for (chunkInBlock = 0, oldChunk = block * dev->nChunksPerBlock;
    5796 +                    chunkInBlock < dev->nChunksPerBlock
    5797 +                    && yaffs_StillSomeChunkBits(dev, block);
    5798 +                    chunkInBlock++, oldChunk++) {
    5799 +                       if (yaffs_CheckChunkBit(dev, block, chunkInBlock)) {
    5800 +
    5801 +                               /* This page is in use and might need to be copied off */
    5802 +
    5803 +                               markNAND = 1;
    5804 +
    5805 +                               yaffs_InitialiseTags(&tags);
    5806 +
    5807 +                               yaffs_ReadChunkWithTagsFromNAND(dev, oldChunk,
    5808 +                                                               buffer, &tags);
    5809 +
    5810 +                               object =
    5811 +                                   yaffs_FindObjectByNumber(dev,
    5812 +                                                            tags.objectId);
    5813 +
    5814 +                               T(YAFFS_TRACE_GC_DETAIL,
    5815 +                                 (TSTR
    5816 +                                  ("Collecting page %d, %d %d %d " TENDSTR),
    5817 +                                  chunkInBlock, tags.objectId, tags.chunkId,
    5818 +                                  tags.byteCount));
    5819 +
    5820 +                               if (!object) {
    5821 +                                       T(YAFFS_TRACE_ERROR,
    5822 +                                         (TSTR
    5823 +                                          ("page %d in gc has no object "
    5824 +                                           TENDSTR), oldChunk));
     4838+       if(!yaffs_StillSomeChunkBits(dev,block))
     4839+       {
     4840+               T(YAFFS_TRACE_TRACING,(TSTR("Collecting block %d that has no chunks in use" TENDSTR),block));
     4841+               yaffs_BlockBecameDirty(dev,block);
     4842+       }
     4843+       else
     4844+       {
     4845+
     4846+       __u8  *buffer = yaffs_GetTempBuffer(dev,__LINE__);
     4847+
     4848+       for(chunkInBlock = 0,oldChunk = block * dev->nChunksPerBlock;
     4849+           chunkInBlock < dev->nChunksPerBlock && yaffs_StillSomeChunkBits(dev,block);
     4850+           chunkInBlock++, oldChunk++ )
     4851+       {
     4852+               if(yaffs_CheckChunkBit(dev,block,chunkInBlock))
     4853+               {
     4854+                       
     4855+                       // This page is in use and might need to be copied off
     4856+                       
     4857+                       markNAND = 1;
     4858+                       
     4859+                       //T(("copying page %x from %d to %d\n",mask,oldChunk,newChunk));
     4860+                       
     4861+                       yaffs_InitialiseTags(&tags);
     4862+                       
     4863+                       yaffs_ReadChunkWithTagsFromNAND(dev,oldChunk,buffer, &tags);
     4864+
     4865+                       object = yaffs_FindObjectByNumber(dev,tags.objectId);
     4866+                       
     4867+                       T(YAFFS_TRACE_GC_DETAIL,(TSTR("Collecting page %d, %d %d %d " TENDSTR),chunkInBlock,tags.objectId,tags.chunkId,tags.byteCount));
     4868+                       
     4869+                       if(!object)
     4870+                       {
     4871+                               T(YAFFS_TRACE_ERROR,(TSTR("page %d in gc has no object " TENDSTR),oldChunk));
     4872+                       }
     4873+                       
     4874+                       if(object && object->deleted && tags.chunkId != 0)
     4875+                       {
     4876+                               // Data chunk in a deleted file, throw it away
     4877+                               // It's a soft deleted data chunk,
     4878+                               // No need to copy this, just forget about it and fix up the
     4879+                               // object.
     4880+                               
     4881+                               //yaffs_PutChunkIntoFile(object, tags.chunkId, 0,0);
     4882+                               object->nDataChunks--;
     4883+                               
     4884+                               if(object->nDataChunks <= 0)
     4885+                               {
     4886+                                       // remeber to clean up the object
     4887+                                       dev->gcCleanupList[cleanups] = tags.objectId;
     4888+                                       cleanups++;
     4889+                               }
     4890+                               markNAND = 0;
     4891+                       }
     4892+                       else if( 0 /* Todo object && object->deleted && object->nDataChunks == 0 */)
     4893+                       {
     4894+                               // Deleted object header with no data chunks.
     4895+                               // Can be discarded and the file deleted.
     4896+                               object->chunkId = 0;
     4897+                               yaffs_FreeTnode(object->myDev,object->variant.fileVariant.top);
     4898+                               object->variant.fileVariant.top = NULL;
     4899+                               yaffs_DoGenericObjectDeletion(object);
     4900+                               
     4901+                       }
     4902+                       else if(object)
     4903+                       {
     4904+                               // It's either a data chunk in a live file or
     4905+                               // an ObjectHeader, so we're interested in it.
     4906+                               // NB Need to keep the ObjectHeaders of deleted files
     4907+                               // until the whole file has been deleted off
     4908+                               tags.serialNumber++;
     4909+
     4910+                               dev->nGCCopies++;
     4911+                               
     4912+                               if(tags.chunkId == 0)
     4913+                               {
     4914+                                       // It is an object Id,
     4915+                                       // We need to nuke the shrinkheader flags first
     4916+                                       // We no longer want the shrinkHeader flag since its work is done
     4917+                                       // and if it is left in place it will mess up scanning.
     4918+                                       
     4919+                                       yaffs_ObjectHeader *oh = (yaffs_ObjectHeader *)buffer;
     4920+                                       oh->isShrink = 0;
     4921+                                       tags.extraIsShrinkHeader = 0;
    58254922+                               }
    58264923+
    5827 +                               if (object && object->deleted
    5828 +                                   && tags.chunkId != 0) {
    5829 +                                       /* Data chunk in a deleted file, throw it away
    5830 +                                        * It's a soft deleted data chunk,
    5831 +                                        * No need to copy this, just forget about it and
    5832 +                                        * fix up the object.
    5833 +                                        */
    5834 +
    5835 +                                       object->nDataChunks--;
    5836 +
    5837 +                                       if (object->nDataChunks <= 0) {
    5838 +                                               /* remeber to clean up the object */
    5839 +                                               dev->gcCleanupList[cleanups] =
    5840 +                                                   tags.objectId;
    5841 +                                               cleanups++;
     4924+                               newChunk = yaffs_WriteNewChunkWithTagsToNAND(dev, buffer, &tags,1);
     4925+                       
     4926+                               if(newChunk < 0)
     4927+                               {
     4928+                                       retVal =  YAFFS_FAIL;
     4929+                               }
     4930+                               else
     4931+                               {
     4932+                       
     4933+                                       // Ok, now fix up the Tnodes etc.
     4934+                       
     4935+                                       if(tags.chunkId == 0)
     4936+                                       {
     4937+                                               // It's a header
     4938+                                               object->chunkId = newChunk;
     4939+                                               object->serial = tags.serialNumber;
    58424940+                                       }
    5843 +                                       markNAND = 0;
    5844 +                               } else if (0
    5845 +                                          /* Todo object && object->deleted && object->nDataChunks == 0 */
    5846 +                                          ) {
    5847 +                                       /* Deleted object header with no data chunks.
    5848 +                                        * Can be discarded and the file deleted.
    5849 +                                        */
    5850 +                                       object->chunkId = 0;
    5851 +                                       yaffs_FreeTnode(object->myDev,
    5852 +                                                       object->variant.
    5853 +                                                       fileVariant.top);
    5854 +                                       object->variant.fileVariant.top = NULL;
    5855 +                                       yaffs_DoGenericObjectDeletion(object);
    5856 +
    5857 +                               } else if (object) {
    5858 +                                       /* It's either a data chunk in a live file or
    5859 +                                        * an ObjectHeader, so we're interested in it.
    5860 +                                        * NB Need to keep the ObjectHeaders of deleted files
    5861 +                                        * until the whole file has been deleted off
    5862 +                                        */
    5863 +                                       tags.serialNumber++;
    5864 +
    5865 +                                       dev->nGCCopies++;
    5866 +
    5867 +                                       if (tags.chunkId == 0) {
    5868 +                                               /* It is an object Id,
    5869 +                                                * We need to nuke the shrinkheader flags first
    5870 +                                                * We no longer want the shrinkHeader flag since its work is done
    5871 +                                                * and if it is left in place it will mess up scanning.
    5872 +                                                * Also, clear out any shadowing stuff
    5873 +                                                */
    5874 +
    5875 +                                               yaffs_ObjectHeader *oh;
    5876 +                                               oh = (yaffs_ObjectHeader *)buffer;
    5877 +                                               oh->isShrink = 0;
    5878 +                                               oh->shadowsObject = -1;
    5879 +                                               tags.extraShadows = 0;
    5880 +                                               tags.extraIsShrinkHeader = 0;
    5881 +                                       }
    5882 +
    5883 +                                       newChunk =
    5884 +                                           yaffs_WriteNewChunkWithTagsToNAND(dev, buffer, &tags, 1);
    5885 +
    5886 +                                       if (newChunk < 0) {
    5887 +                                               retVal = YAFFS_FAIL;
    5888 +                                       } else {
    5889 +
    5890 +                                               /* Ok, now fix up the Tnodes etc. */
    5891 +
    5892 +                                               if (tags.chunkId == 0) {
    5893 +                                                       /* It's a header */
    5894 +                                                       object->chunkId =  newChunk;
    5895 +                                                       object->serial =   tags.serialNumber;
    5896 +                                               } else {
    5897 +                                                       /* It's a data chunk */
    5898 +                                                       yaffs_PutChunkIntoFile
    5899 +                                                           (object,
    5900 +                                                            tags.chunkId,
    5901 +                                                            newChunk, 0);
    5902 +                                               }
     4941+                                       else
     4942+                                       {
     4943+                                               // It's a data chunk
     4944+                                               yaffs_PutChunkIntoFile(object, tags.chunkId, newChunk,0);
    59034945+                                       }
    59044946+                               }
    5905 +
    5906 +                               yaffs_DeleteChunk(dev, oldChunk, markNAND, __LINE__);
    5907 +
    59084947+                       }
    5909 +               }
    5910 +
    5911 +               yaffs_ReleaseTempBuffer(dev, buffer, __LINE__);
    5912 +
    5913 +
    5914 +               /* Do any required cleanups */
    5915 +               for (i = 0; i < cleanups; i++) {
    5916 +                       /* Time to delete the file too */
    5917 +                       object =
    5918 +                           yaffs_FindObjectByNumber(dev,
    5919 +                                                    dev->gcCleanupList[i]);
    5920 +                       if (object) {
    5921 +                               yaffs_FreeTnode(dev,
    5922 +                                               object->variant.fileVariant.
    5923 +                                               top);
    5924 +                               object->variant.fileVariant.top = NULL;
    5925 +                               T(YAFFS_TRACE_GC,
    5926 +                                 (TSTR
    5927 +                                  ("yaffs: About to finally delete object %d"
    5928 +                                   TENDSTR), object->objectId));
    5929 +                               yaffs_DoGenericObjectDeletion(object);
    5930 +                               object->myDev->nDeletedFiles--;
     4948+                       
     4949+                       yaffs_DeleteChunk(dev,oldChunk,markNAND,__LINE__);                     
     4950+                       
     4951+               }
     4952+       }
     4953+
     4954+       yaffs_ReleaseTempBuffer(dev,buffer,__LINE__);
     4955+
     4956+       //yaffs_VerifyFreeChunks(dev);
     4957+
     4958+       // Do any required cleanups
     4959+       for(i = 0; i < cleanups; i++)
     4960+       {                                               
     4961+               // Time to delete the file too
     4962+               object =  yaffs_FindObjectByNumber(dev,dev->gcCleanupList[i]);
     4963+               if(object)
     4964+               {
     4965+                       yaffs_FreeTnode(dev,object->variant.fileVariant.top);
     4966+                       object->variant.fileVariant.top = NULL;
     4967+                       T(YAFFS_TRACE_GC,(TSTR("yaffs: About to finally delete object %d" TENDSTR),object->objectId));
     4968+                       yaffs_DoGenericObjectDeletion(object);
     4969+               }
     4970+
     4971+       }
     4972+
     4973+       }
     4974+
     4975+       if(chunksBefore >= (chunksAfter = yaffs_GetErasedChunks(dev)))
     4976+       {
     4977+                       T(YAFFS_TRACE_GC,(TSTR("gc did not increase free chunks before %d after %d" TENDSTR),chunksBefore,chunksAfter));
     4978+       }
     4979+       
     4980+       
     4981+       dev->isDoingGC = 0;
     4982+       
     4983+       //yaffs_VerifyFreeChunks(dev);
     4984+                       
     4985+       return YAFFS_OK;
     4986+}
     4987+
     4988+#if 0
     4989+static yaffs_Object *yaffs_FindDeletedUnlinkedFile(yaffs_Device *dev)
     4990+{
     4991+       // find a file to delete
     4992+       struct list_head *i;   
     4993+       yaffs_Object *l;
     4994+
     4995+
     4996+       //Scan the unlinked files looking for one to delete
     4997+       list_for_each(i,&dev->unlinkedDir->variant.directoryVariant.children)
     4998+       {
     4999+               if(i)
     5000+               {
     5001+                       l = list_entry(i, yaffs_Object,siblings);
     5002+                       if(l->deleted)
     5003+                       {
     5004+                               return l;                       
    59315005+                       }
    5932 +
    5933 +               }
    5934 +
    5935 +       }
    5936 +
    5937 +       if (chunksBefore >= (chunksAfter = yaffs_GetErasedChunks(dev))) {
    5938 +               T(YAFFS_TRACE_GC,
    5939 +                 (TSTR
    5940 +                  ("gc did not increase free chunks before %d after %d"
    5941 +                   TENDSTR), chunksBefore, chunksAfter));
    5942 +       }
    5943 +
    5944 +       dev->isDoingGC = 0;
    5945 +
    5946 +       return YAFFS_OK;
    5947 +}
    5948 +
    5949 +/* New garbage collector
    5950 + * If we're very low on erased blocks then we do aggressive garbage collection
    5951 + * otherwise we do "leasurely" garbage collection.
    5952 + * Aggressive gc looks further (whole array) and will accept less dirty blocks.
    5953 + * Passive gc only inspects smaller areas and will only accept more dirty blocks.
    5954 + *
    5955 + * The idea is to help clear out space in a more spread-out manner.
    5956 + * Dunno if it really does anything useful.
    5957 + */
    5958 +static int yaffs_CheckGarbageCollection(yaffs_Device * dev)
     5006+               }
     5007+       }       
     5008+       return NULL;
     5009+}
     5010+
     5011+
     5012+static void yaffs_DoUnlinkedFileDeletion(yaffs_Device *dev)
     5013+{
     5014+       // This does background deletion on unlinked files.. only deleted ones.
     5015+       // If we don't have a file we're working on then find one
     5016+       if(!dev->unlinkedDeletion && dev->nDeletedFiles > 0)
     5017+       {
     5018+               dev->unlinkedDeletion = yaffs_FindDeletedUnlinkedFile(dev);
     5019+       }
     5020+       
     5021+       // OK, we're working on a file...
     5022+       if(dev->unlinkedDeletion)
     5023+       {
     5024+               yaffs_Object *obj = dev->unlinkedDeletion;
     5025+               int delresult;
     5026+               int limit; // Number of chunks to delete in a file.
     5027+                                  // NB this can be exceeded, but not by much.
     5028+                                 
     5029+               limit = -1;
     5030+
     5031+               delresult = yaffs_DeleteWorker(obj, obj->variant.fileVariant.top, obj->variant.fileVariant.topLevel, 0,&limit);
     5032+               
     5033+               if(obj->nDataChunks == 0)
     5034+               {
     5035+                       // Done all the deleting of data chunks.
     5036+                       // Now dump the header and clean up
     5037+                       yaffs_FreeTnode(dev,obj->variant.fileVariant.top);
     5038+                       obj->variant.fileVariant.top = NULL;
     5039+                       yaffs_DoGenericObjectDeletion(obj);
     5040+                       dev->nDeletedFiles--;
     5041+                       dev->nUnlinkedFiles--;
     5042+                       dev->nBackgroundDeletions++;
     5043+                       dev->unlinkedDeletion = NULL;   
     5044+               }
     5045+       }
     5046+}
     5047+
     5048+#endif
     5049+
     5050+
     5051+
     5052+// New garbage collector
     5053+// If we're very low on erased blocks then we do aggressive garbage collection
     5054+// otherwise we do "leasurely" garbage collection.
     5055+// Aggressive gc looks further (whole array) and will accept dirtier blocks.
     5056+// Passive gc only inspects smaller areas and will only accept cleaner blocks.
     5057+//
     5058+// The idea is to help clear out space in a more spread-out manner.
     5059+// Dunno if it really does anything useful.
     5060+//
     5061+static int yaffs_CheckGarbageCollection(yaffs_Device *dev)
    59595062+{
    59605063+       int block;
    5961 +       int aggressive;
     5064+       int aggressive; 
    59625065+       int gcOk = YAFFS_OK;
    59635066+       int maxTries = 0;
    59645067+       
    5965 +       int checkpointBlockAdjust;
    5966 +
    5967 +       if (dev->isDoingGC) {
    5968 +               /* Bail out so we don't get recursive gc */
     5068+       //yaffs_VerifyFreeChunks(dev);
     5069+       
     5070+       if(dev->isDoingGC)
     5071+       {
     5072+               // Bail out so we don't get recursive gc
    59695073+               return YAFFS_OK;
    59705074+       }
    5971 +       
    5972 +       /* This loop should pass the first time.
    5973 +        * We'll only see looping here if the erase of the collected block fails.
    5974 +        */
    5975 +
    5976 +       do {
     5075+
     5076+       // This loop should pass the first time.
     5077+       // We'll only see looping here if the erase of the collected block fails.
     5078+       
     5079+       do{
    59775080+               maxTries++;
    5978 +               
    5979 +               checkpointBlockAdjust = (dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint);
    5980 +               if(checkpointBlockAdjust < 0)
    5981 +                       checkpointBlockAdjust = 0;
    5982 +
    5983 +               if (dev->nErasedBlocks < (dev->nReservedBlocks + checkpointBlockAdjust)) {
    5984 +                       /* We need a block soon...*/
     5081+               if(dev->nErasedBlocks < dev->nReservedBlocks)
     5082+               {
     5083+                       // We need a block soon...
    59855084+                       aggressive = 1;
    5986 +               } else {
    5987 +                       /* We're in no hurry */
     5085+               }
     5086+               else
     5087+               {
     5088+                       // We're in no hurry
    59885089+                       aggressive = 0;
    59895090+               }
    5990 +
    5991 +               block = yaffs_FindBlockForGarbageCollection(dev, aggressive);
    5992 +
    5993 +               if (block > 0) {
     5091+       
     5092+               block = yaffs_FindBlockForGarbageCollection(dev,aggressive);
     5093+       
     5094+               if(block > 0)
     5095+               {
    59945096+                       dev->garbageCollections++;
    5995 +                       if (!aggressive) {
     5097+                       if(!aggressive)
     5098+                       {
    59965099+                               dev->passiveGarbageCollections++;
    59975100+                       }
    59985101+
    5999 +                       T(YAFFS_TRACE_GC,
    6000 +                         (TSTR
    6001 +                          ("yaffs: GC erasedBlocks %d aggressive %d" TENDSTR),
    6002 +                          dev->nErasedBlocks, aggressive));
    6003 +
    6004 +                       gcOk = yaffs_GarbageCollectBlock(dev, block);
    6005 +               }
    6006 +
    6007 +               if (dev->nErasedBlocks < (dev->nReservedBlocks) && block > 0) {
    6008 +                       T(YAFFS_TRACE_GC,
    6009 +                         (TSTR
    6010 +                          ("yaffs: GC !!!no reclaim!!! erasedBlocks %d after try %d block %d"
    6011 +                           TENDSTR), dev->nErasedBlocks, maxTries, block));
    6012 +               }
    6013 +       } while ((dev->nErasedBlocks < dev->nReservedBlocks) && (block > 0)
    6014 +                && (maxTries < 2));
    6015 +
    6016 +       return aggressive ? gcOk : YAFFS_OK;
    6017 +}
    6018 +
    6019 +/*-------------------------  TAGS --------------------------------*/
    6020 +
    6021 +static int yaffs_TagsMatch(const yaffs_ExtendedTags * tags, int objectId,
    6022 +                          int chunkInObject)
    6023 +{
    6024 +       return (tags->chunkId == chunkInObject &&
    6025 +               tags->objectId == objectId && !tags->chunkDeleted) ? 1 : 0;
    6026 +
    6027 +}
    6028 +
    6029 +
    6030 +/*-------------------- Data file manipulation -----------------*/
    6031 +
    6032 +static int yaffs_FindChunkInFile(yaffs_Object * in, int chunkInInode,
    6033 +                                yaffs_ExtendedTags * tags)
    6034 +{
    6035 +       /*Get the Tnode, then get the level 0 offset chunk offset */
    6036 +       yaffs_Tnode *tn;
    6037 +       int theChunk = -1;
    6038 +       yaffs_ExtendedTags localTags;
    6039 +       int retVal = -1;
    6040 +
    6041 +       yaffs_Device *dev = in->myDev;
    6042 +
    6043 +       if (!tags) {
    6044 +               /* Passed a NULL, so use our own tags space */
    6045 +               tags = &localTags;
    6046 +       }
    6047 +
    6048 +       tn = yaffs_FindLevel0Tnode(dev, &in->variant.fileVariant, chunkInInode);
    6049 +
    6050 +       if (tn) {
    6051 +               theChunk = yaffs_GetChunkGroupBase(dev,tn,chunkInInode);
    6052 +
    6053 +               retVal =
    6054 +                   yaffs_FindChunkInGroup(dev, theChunk, tags, in->objectId,
    6055 +                                          chunkInInode);
    6056 +       }
    6057 +       return retVal;
    6058 +}
    6059 +
    6060 +static int yaffs_FindAndDeleteChunkInFile(yaffs_Object * in, int chunkInInode,
    6061 +                                         yaffs_ExtendedTags * tags)
    6062 +{
    6063 +       /* Get the Tnode, then get the level 0 offset chunk offset */
    6064 +       yaffs_Tnode *tn;
    6065 +       int theChunk = -1;
    6066 +       yaffs_ExtendedTags localTags;
    6067 +
    6068 +       yaffs_Device *dev = in->myDev;
    6069 +       int retVal = -1;
    6070 +
    6071 +       if (!tags) {
    6072 +               /* Passed a NULL, so use our own tags space */
    6073 +               tags = &localTags;
    6074 +       }
    6075 +
    6076 +       tn = yaffs_FindLevel0Tnode(dev, &in->variant.fileVariant, chunkInInode);
    6077 +
    6078 +       if (tn) {
    6079 +
    6080 +               theChunk = yaffs_GetChunkGroupBase(dev,tn,chunkInInode);
    6081 +
    6082 +               retVal =
    6083 +                   yaffs_FindChunkInGroup(dev, theChunk, tags, in->objectId,
    6084 +                                          chunkInInode);
    6085 +
    6086 +               /* Delete the entry in the filestructure (if found) */
    6087 +               if (retVal != -1) {
    6088 +                       yaffs_PutLevel0Tnode(dev,tn,chunkInInode,0);
    6089 +               }
    6090 +       } else {
    6091 +               /*T(("No level 0 found for %d\n", chunkInInode)); */
    6092 +       }
    6093 +
    6094 +       if (retVal == -1) {
    6095 +               /* T(("Could not find %d to delete\n",chunkInInode)); */
    6096 +       }
    6097 +       return retVal;
    6098 +}
     5102+                       T(YAFFS_TRACE_GC,(TSTR("yaffs: GC erasedBlocks %d aggressive %d" TENDSTR),dev->nErasedBlocks,aggressive));
     5103+
     5104+                       gcOk =  yaffs_GarbageCollectBlock(dev,block);
     5105+               }
     5106+
     5107+               if(dev->nErasedBlocks < (dev->nReservedBlocks) && block > 0)
     5108+               {
     5109+                       T(YAFFS_TRACE_GC,(TSTR("yaffs: GC !!!no reclaim!!! erasedBlocks %d after try %d block %d" TENDSTR),dev->nErasedBlocks,maxTries,block));
     5110+               }
     5111+       } while((dev->nErasedBlocks < dev->nReservedBlocks) && (block > 0) && (maxTries < 2));
     5112+
     5113+       return aggressive ? gcOk: YAFFS_OK;
     5114+}
     5115+
     5116+
     5117+//////////////////////////// TAGS ///////////////////////////////////////
     5118+
     5119+
     5120+
     5121+#if 0
     5122+
     5123+void yaffs_CalcTagsECC(yaffs_Tags *tags)
     5124+{
     5125+       // Calculate an ecc
     5126+       
     5127+       unsigned char *b = ((yaffs_TagsUnion *)tags)->asBytes;
     5128+       unsigned  i,j;
     5129+       unsigned  ecc = 0;
     5130+       unsigned bit = 0;
     5131+
     5132+       tags->ecc = 0;
     5133+       
     5134+       for(i = 0; i < 8; i++)
     5135+       {
     5136+               for(j = 1; j &0xff; j<<=1)
     5137+               {
     5138+                       bit++;
     5139+                       if(b[i] & j)
     5140+                       {
     5141+                               ecc ^= bit;
     5142+                       }
     5143+               }
     5144+       }
     5145+       
     5146+       tags->ecc = ecc;
     5147+       
     5148+       
     5149+}
     5150+
     5151+int  yaffs_CheckECCOnTags(yaffs_Tags *tags)
     5152+{
     5153+       unsigned ecc = tags->ecc;
     5154+       
     5155+       yaffs_CalcTagsECC(tags);
     5156+       
     5157+       ecc ^= tags->ecc;
     5158+       
     5159+       if(ecc && ecc <= 64)
     5160+       {
     5161+               // TODO: Handle the failure better. Retire?
     5162+               unsigned char *b = ((yaffs_TagsUnion *)tags)->asBytes;
     5163+
     5164+               ecc--;
     5165+                               
     5166+               b[ecc / 8] ^= (1 << (ecc & 7));
     5167+               
     5168+               // Now recvalc the ecc
     5169+               yaffs_CalcTagsECC(tags);
     5170+               
     5171+               return 1; // recovered error
     5172+       }
     5173+       else if(ecc)
     5174+       {
     5175+               // Wierd ecc failure value
     5176+               // TODO Need to do somethiong here
     5177+               return -1; //unrecovered error
     5178+       }
     5179+       
     5180+       return 0;
     5181+}
     5182+
     5183+static void yaffs_LoadTagsIntoSpare(yaffs_Spare *sparePtr, yaffs_Tags *tagsPtr)
     5184+{
     5185+       yaffs_TagsUnion *tu = (yaffs_TagsUnion *)tagsPtr;
     5186+       
     5187+       yaffs_CalcTagsECC(tagsPtr);
     5188+       
     5189+       sparePtr->tagByte0 = tu->asBytes[0];
     5190+       sparePtr->tagByte1 = tu->asBytes[1];
     5191+       sparePtr->tagByte2 = tu->asBytes[2];
     5192+       sparePtr->tagByte3 = tu->asBytes[3];
     5193+       sparePtr->tagByte4 = tu->asBytes[4];
     5194+       sparePtr->tagByte5 = tu->asBytes[5];
     5195+       sparePtr->tagByte6 = tu->asBytes[6];
     5196+       sparePtr->tagByte7 = tu->asBytes[7];
     5197+}
     5198+
     5199+static void yaffs_GetTagsFromSpare(yaffs_Device *dev, yaffs_Spare *sparePtr,yaffs_Tags *tagsPtr)
     5200+{
     5201+       yaffs_TagsUnion *tu = (yaffs_TagsUnion *)tagsPtr;
     5202+       int result;
     5203+
     5204+       tu->asBytes[0]= sparePtr->tagByte0;
     5205+       tu->asBytes[1]= sparePtr->tagByte1;
     5206+       tu->asBytes[2]= sparePtr->tagByte2;
     5207+       tu->asBytes[3]= sparePtr->tagByte3;
     5208+       tu->asBytes[4]= sparePtr->tagByte4;
     5209+       tu->asBytes[5]= sparePtr->tagByte5;
     5210+       tu->asBytes[6]= sparePtr->tagByte6;
     5211+       tu->asBytes[7]= sparePtr->tagByte7;
     5212+       
     5213+       result =  yaffs_CheckECCOnTags(tagsPtr);
     5214+       if(result> 0)
     5215+       {
     5216+               dev->tagsEccFixed++;
     5217+       }
     5218+       else if(result <0)
     5219+       {
     5220+               dev->tagsEccUnfixed++;
     5221+       }
     5222+}
     5223+
     5224+static void yaffs_SpareInitialise(yaffs_Spare *spare)
     5225+{
     5226+       memset(spare,0xFF,sizeof(yaffs_Spare));
     5227+}
     5228+
     5229+#endif
     5230+
     5231+#if 0
     5232+static int yaffs_WriteNewChunkWithTagsToNAND(yaffs_Device *dev, const __u8 *buffer, yaffs_ExtendedTags *tags, int useReserve)
     5233+{
     5234+       // NB There must be tags, data is optional
     5235+       // If there is data, then an ECC is calculated on it.
     5236+       
     5237+       yaffs_Spare spare;
     5238+       
     5239+       if(!tags)
     5240+       {
     5241+               return YAFFS_FAIL;
     5242+       }
     5243+       
     5244+       //yaffs_SpareInitialise(&spare);
     5245+       
     5246+       //if(!dev->useNANDECC && buffer)
     5247+       //{
     5248+       //      yaffs_CalcECC(buffer,&spare);
     5249+       //}
     5250+       
     5251+       //yaffs_LoadTagsIntoSpare(&spare,tags);
     5252+       
     5253+       return yaffs_WriteNewChunkToNAND(dev,buffer,&spare,useReserve);
     5254+       
     5255+}
     5256+#endif
     5257+
     5258+static int yaffs_TagsMatch(const yaffs_ExtendedTags *tags, int objectId, int chunkInObject)
     5259+{
     5260+       return  (  tags->chunkId == chunkInObject &&
     5261+                          tags->objectId == objectId &&
     5262+                          !tags->chunkDeleted) ? 1 : 0;
     5263+       
     5264+}
     5265+
     5266+/////////////////////////////////////////////////////////////////////////////////////////////////////////
     5267+
     5268+
     5269+static int yaffs_FindChunkInFile(yaffs_Object *in,int chunkInInode,yaffs_ExtendedTags *tags)
     5270+{
     5271+       //Get the Tnode, then get the level 0 offset chunk offset
     5272+    yaffs_Tnode *tn;     
     5273+    int theChunk = -1;
     5274+    yaffs_ExtendedTags localTags;
     5275+    int retVal = -1;
     5276+   
     5277+    yaffs_Device *dev = in->myDev;
     5278+   
     5279+   
     5280+    if(!tags)
     5281+    {
     5282+       // Passed a NULL, so use our own tags space
     5283+       tags = &localTags;
     5284+    }
     5285+   
     5286+    tn = yaffs_FindLevel0Tnode(dev,&in->variant.fileVariant, chunkInInode);
     5287+   
     5288+    if(tn)
     5289+    {
     5290+               theChunk = tn->level0[chunkInInode & YAFFS_TNODES_LEVEL0_MASK] << dev->chunkGroupBits;
     5291+               
     5292+               retVal = yaffs_FindChunkInGroup(dev,theChunk,tags,in->objectId,chunkInInode);
     5293+    }
     5294+    return retVal;
     5295+}
     5296+
     5297+static int yaffs_FindAndDeleteChunkInFile(yaffs_Object *in,int chunkInInode,yaffs_ExtendedTags *tags)
     5298+{
     5299+       //Get the Tnode, then get the level 0 offset chunk offset
     5300+    yaffs_Tnode *tn;     
     5301+    int theChunk = -1;
     5302+    yaffs_ExtendedTags localTags;
     5303+
     5304+    yaffs_Device *dev = in->myDev;
     5305+    int retVal = -1;
     5306+   
     5307+    if(!tags)
     5308+    {
     5309+       // Passed a NULL, so use our own tags space
     5310+       tags = &localTags;
     5311+    }
     5312+   
     5313+    tn = yaffs_FindLevel0Tnode(dev,&in->variant.fileVariant, chunkInInode);
     5314+   
     5315+    if(tn)
     5316+    {
     5317+   
     5318+               theChunk = tn->level0[chunkInInode & YAFFS_TNODES_LEVEL0_MASK] << dev->chunkGroupBits;
     5319+               
     5320+               retVal = yaffs_FindChunkInGroup(dev,theChunk,tags,in->objectId,chunkInInode);
     5321+   
     5322+               // Delete the entry in the filestructure (if found)
     5323+               if(retVal != -1)
     5324+               {
     5325+                       tn->level0[chunkInInode & YAFFS_TNODES_LEVEL0_MASK] = 0;
     5326+               }
     5327+    }
     5328+    else
     5329+    {
     5330+       //T(("No level 0 found for %d\n", chunkInInode));
     5331+    }
     5332+   
     5333+    if(retVal == -1)
     5334+    {
     5335+       //T(("Could not find %d to delete\n",chunkInInode));
     5336+    }
     5337+    return retVal;
     5338+}
     5339+
    60995340+
    61005341+#ifdef YAFFS_PARANOID
    61015342+
    6102 +static int yaffs_CheckFileSanity(yaffs_Object * in)
     5343+static int yaffs_CheckFileSanity(yaffs_Object *in)
    61035344+{
    61045345+       int chunk;
     
    61085349+       int objId;
    61095350+       yaffs_Tnode *tn;
    6110 +       yaffs_Tags localTags;
    6111 +       yaffs_Tags *tags = &localTags;
    6112 +       int theChunk;
    6113 +       int chunkDeleted;
    6114 +
    6115 +       if (in->variantType != YAFFS_OBJECT_TYPE_FILE) {
    6116 +               /* T(("Object not a file\n")); */
     5351+    yaffs_Tags localTags;
     5352+    yaffs_Tags *tags = &localTags;
     5353+    int theChunk;
     5354+    int chunkDeleted;
     5355+   
     5356+       
     5357+       if(in->variantType != YAFFS_OBJECT_TYPE_FILE)
     5358+       {
     5359+               //T(("Object not a file\n"));
    61175360+               return YAFFS_FAIL;
    61185361+       }
    6119 +
     5362+       
    61205363+       objId = in->objectId;
    6121 +       fSize = in->variant.fileVariant.fileSize;
    6122 +       nChunks =
    6123 +           (fSize + in->myDev->nDataBytesPerChunk - 1) / in->myDev->nDataBytesPerChunk;
    6124 +
    6125 +       for (chunk = 1; chunk <= nChunks; chunk++) {
    6126 +               tn = yaffs_FindLevel0Tnode(in->myDev, &in->variant.fileVariant,
    6127 +                                          chunk);
    6128 +
    6129 +               if (tn) {
    6130 +
    6131 +                       theChunk = yaffs_GetChunkGroupBase(dev,tn,chunk);
    6132 +
    6133 +                       if (yaffs_CheckChunkBits
    6134 +                           (dev, theChunk / dev->nChunksPerBlock,
    6135 +                            theChunk % dev->nChunksPerBlock)) {
    6136 +
    6137 +                               yaffs_ReadChunkTagsFromNAND(in->myDev, theChunk,
    6138 +                                                           tags,
    6139 +                                                           &chunkDeleted);
    6140 +                               if (yaffs_TagsMatch
    6141 +                                   (tags, in->objectId, chunk, chunkDeleted)) {
    6142 +                                       /* found it; */
    6143 +
     5364+       fSize  = in->variant.fileVariant.fileSize;
     5365+       nChunks = (fSize + in->myDev->nBytesPerChunk -1)/in->myDev->nBytesPerChunk;
     5366+       
     5367+       for(chunk = 1; chunk <= nChunks; chunk++)
     5368+       {
     5369+               tn = yaffs_FindLevel0Tnode(in->myDev,&in->variant.fileVariant, chunk);
     5370+   
     5371+               if(tn)
     5372+               {
     5373+   
     5374+                       theChunk = tn->level0[chunk & YAFFS_TNODES_LEVEL0_MASK] << in->myDev->chunkGroupBits;
     5375+                       
     5376+               if(yaffs_CheckChunkBits(dev,theChunk/dev->nChunksPerBlock,theChunk%dev->nChunksPerBlock))
     5377+                       {
     5378+
     5379+
     5380+                               yaffs_ReadChunkTagsFromNAND(in->myDev,theChunk,tags,&chunkDeleted);
     5381+                               if(yaffs_TagsMatch(tags,in->objectId,chunk,chunkDeleted))
     5382+                               {
     5383+                                       // found it;
     5384+                               
    61445385+                               }
    6145 +                       } else {
    6146 +
     5386+                       }
     5387+                       else
     5388+                       {
     5389+                               //T(("File problem file [%d,%d] NAND %d  tags[%d,%d]\n",
     5390+                               //              objId,chunk,theChunk,tags->chunkId,tags->objectId);
     5391+                                               
    61475392+                               failed = 1;
     5393+                                                       
    61485394+                       }
    6149 +
    6150 +               } else {
    6151 +                       /* T(("No level 0 found for %d\n", chunk)); */
    6152 +               }
    6153 +       }
    6154 +
     5395+   
     5396+               }
     5397+               else
     5398+               {
     5399+                       //T(("No level 0 found for %d\n", chunk));
     5400+               }
     5401+       }
     5402+       
    61555403+       return failed ? YAFFS_FAIL : YAFFS_OK;
    61565404+}
     
    61585406+#endif
    61595407+
    6160 +static int yaffs_PutChunkIntoFile(yaffs_Object * in, int chunkInInode,
    6161 +                                 int chunkInNAND, int inScan)
    6162 +{
    6163 +       /* NB inScan is zero unless scanning.
    6164 +        * For forward scanning, inScan is > 0;
    6165 +        * for backward scanning inScan is < 0
    6166 +        */
    6167 +       
     5408+static int yaffs_PutChunkIntoFile(yaffs_Object *in,int chunkInInode, int chunkInNAND, int inScan)
     5409+{
     5410+       // NB inScan is zero unless scanning. For forward scanning, inScan is > 0; for backward scanning inScan is < 0
    61685411+       yaffs_Tnode *tn;
    61695412+       yaffs_Device *dev = in->myDev;
     
    61725415+       yaffs_ExtendedTags newTags;
    61735416+       unsigned existingSerial, newSerial;
    6174 +
    6175 +       if (in->variantType != YAFFS_OBJECT_TYPE_FILE) {
    6176 +               /* Just ignore an attempt at putting a chunk into a non-file during scanning
    6177 +                * If it is not during Scanning then something went wrong!
    6178 +                */
    6179 +               if (!inScan) {
    6180 +                       T(YAFFS_TRACE_ERROR,
    6181 +                         (TSTR
    6182 +                          ("yaffs tragedy:attempt to put data chunk into a non-file"
    6183 +                           TENDSTR)));
     5417+       
     5418+       if(in->variantType != YAFFS_OBJECT_TYPE_FILE)
     5419+       {
     5420+               // Just ignore an attempt at putting a chunk into a non-file during scanning
     5421+               // If it is not during Scanning then something went wrong!
     5422+               if(!inScan)
     5423+               {
     5424+                       T(YAFFS_TRACE_ERROR, (TSTR("yaffs tragedy:attempt to put data chunk into a non-file" TENDSTR)));
    61845425+                       YBUG();
    61855426+               }
    6186 +
    6187 +               yaffs_DeleteChunk(dev, chunkInNAND, 1, __LINE__);
     5427+               
     5428+               yaffs_DeleteChunk(dev,chunkInNAND,1,__LINE__);
    61885429+               return YAFFS_OK;
    61895430+       }
    6190 +
    6191 +       tn = yaffs_AddOrFindLevel0Tnode(dev,
    6192 +                                       &in->variant.fileVariant,
    6193 +                                       chunkInInode,
    6194 +                                       NULL);
    6195 +       if (!tn) {
     5431+               
     5432+       tn = yaffs_AddOrFindLevel0Tnode(dev,&in->variant.fileVariant, chunkInInode);
     5433+       if(!tn)
     5434+       {
    61965435+               return YAFFS_FAIL;
    61975436+       }
    61985437+
    6199 +       existingChunk = yaffs_GetChunkGroupBase(dev,tn,chunkInInode);
    6200 +
    6201 +       if (inScan != 0) {
    6202 +               /* If we're scanning then we need to test for duplicates
    6203 +                * NB This does not need to be efficient since it should only ever
    6204 +                * happen when the power fails during a write, then only one
    6205 +                * chunk should ever be affected.
    6206 +                *
    6207 +                * Correction for YAFFS2: This could happen quite a lot and we need to think about efficiency! TODO
    6208 +                * Update: For backward scanning we don't need to re-read tags so this is quite cheap.
    6209 +                */
    6210 +
    6211 +               if (existingChunk != 0) {
    6212 +                       /* NB Right now existing chunk will not be real chunkId if the device >= 32MB
    6213 +                        *    thus we have to do a FindChunkInFile to get the real chunk id.
    6214 +                        *
    6215 +                        * We have a duplicate now we need to decide which one to use:
    6216 +                        *
    6217 +                        * Backwards scanning YAFFS2: The old one is what we use, dump the new one.
    6218 +                        * Forward scanning YAFFS2: The new one is what we use, dump the old one.
    6219 +                        * YAFFS1: Get both sets of tags and compare serial numbers.
    6220 +                        */
    6221 +
    6222 +                       if (inScan > 0) {
    6223 +                               /* Only do this for forward scanning */
    6224 +                               yaffs_ReadChunkWithTagsFromNAND(dev,
    6225 +                                                               chunkInNAND,
    6226 +                                                               NULL, &newTags);
    6227 +
    6228 +                               /* Do a proper find */
    6229 +                               existingChunk =
    6230 +                                   yaffs_FindChunkInFile(in, chunkInInode,
    6231 +                                                         &existingTags);
     5438+       existingChunk = tn->level0[chunkInInode & YAFFS_TNODES_LEVEL0_MASK];           
     5439+       
     5440+       if(inScan != 0)
     5441+       {
     5442+               // If we're scanning then we need to test for duplicates
     5443+               // NB This does not need to be efficient since it should only ever
     5444+               // happen when the power fails during a write, then only one
     5445+               // chunk should ever be affected.
     5446+               //
     5447+               // Correction for YAFFS2: This could happen quite a lot and we need to think about efficiency! TODO
     5448+               // Update: For backward scanning we don't need to re-read tags so this is quite cheap.
     5449+               
     5450+       
     5451+               
     5452+               if(existingChunk != 0)
     5453+               {
     5454+                       // NB Right now existing chunk will not be real chunkId if the device >= 32MB
     5455+                       //    thus we have to do a FindChunkInFile to get the real chunk id.
     5456+                       //
     5457+                       // We have a duplicate now we need to decide which one to use:
     5458+                       //
     5459+                       // Backwards scanning YAFFS2: The old one is what we use, dump the new one.
     5460+                       // Forward scanning YAFFS2: The new one is what we use, dump the old one.
     5461+                       // YAFFS1: Get both sets of tags and compare serial numbers.
     5462+                       //
     5463+                       //
     5464+                       
     5465+                       if(inScan > 0)
     5466+                       {
     5467+                               // Only do this for forward scanning
     5468+                               yaffs_ReadChunkWithTagsFromNAND(dev,chunkInNAND, NULL,&newTags);
     5469+                       
     5470+                       
     5471+                               // Do a proper find
     5472+                               existingChunk = yaffs_FindChunkInFile(in,chunkInInode, &existingTags);
    62325473+                       }
    62335474+
    6234 +                       if (existingChunk <= 0) {
    6235 +                               /*Hoosterman - how did this happen? */
    6236 +
    6237 +                               T(YAFFS_TRACE_ERROR,
    6238 +                                 (TSTR
    6239 +                                  ("yaffs tragedy: existing chunk < 0 in scan"
    6240 +                                   TENDSTR)));
     5475+                       if(existingChunk <=0)
     5476+                       {
     5477+                               //Hoosterman - how did this happen?
     5478+                               
     5479+                               T(YAFFS_TRACE_ERROR, (TSTR("yaffs tragedy: existing chunk < 0 in scan" TENDSTR)));
    62415480+
    62425481+                       }
    62435482+
    6244 +                       /* NB The deleted flags should be false, otherwise the chunks will
    6245 +                        * not be loaded during a scan
    6246 +                        */
    6247 +
     5483+                       
     5484+                       // NB The deleted flags should be false, otherwise the chunks will
     5485+                       // not be loaded during a scan
     5486+                       
    62485487+                       newSerial = newTags.serialNumber;
    62495488+                       existingSerial = existingTags.serialNumber;
    6250 +
    6251 +                       if ((inScan > 0) &&
    6252 +                           (in->myDev->isYaffs2 ||
    6253 +                            existingChunk <= 0 ||
    6254 +                            ((existingSerial + 1) & 3) == newSerial)) {
    6255 +                               /* Forward scanning.                           
    6256 +                                * Use new
    6257 +                                * Delete the old one and drop through to update the tnode
    6258 +                                */
    6259 +                               yaffs_DeleteChunk(dev, existingChunk, 1,
    6260 +                                                 __LINE__);
    6261 +                       } else {
    6262 +                               /* Backward scanning or we want to use the existing one
    6263 +                                * Use existing.
    6264 +                                * Delete the new one and return early so that the tnode isn't changed
    6265 +                                */
    6266 +                               yaffs_DeleteChunk(dev, chunkInNAND, 1,
    6267 +                                                 __LINE__);
     5489+                       
     5490+                       if( (inScan > 0) &&
     5491+                           ( in->myDev->isYaffs2  ||
     5492+                             existingChunk <= 0 ||
     5493+                            ((existingSerial+1) & 3) == newSerial))
     5494+                       {
     5495+                               // Forward scanning.                           
     5496+                               // Use new
     5497+                               // Delete the old one and drop through to update the tnode
     5498+                               yaffs_DeleteChunk(dev,existingChunk,1,__LINE__);
     5499+                       }
     5500+                       else
     5501+                       {
     5502+                               // Backward scanning or we want to use the existing one
     5503+                               // Use existing.
     5504+                               // Delete the new one and return early so that the tnode isn't changed
     5505+                               yaffs_DeleteChunk(dev,chunkInNAND,1,__LINE__);
    62685506+                               return YAFFS_OK;
    62695507+                       }
     
    62715509+
    62725510+       }
    6273 +
    6274 +       if (existingChunk == 0) {
     5511+               
     5512+       if(existingChunk == 0)
     5513+       {
    62755514+               in->nDataChunks++;
    62765515+       }
    6277 +
    6278 +       yaffs_PutLevel0Tnode(dev,tn,chunkInInode,chunkInNAND);
    6279 +
     5516+       
     5517+       tn->level0[chunkInInode & YAFFS_TNODES_LEVEL0_MASK] = (chunkInNAND >> dev->chunkGroupBits);
     5518+       
    62805519+       return YAFFS_OK;
    62815520+}
    62825521+
    6283 +static int yaffs_ReadChunkDataFromObject(yaffs_Object * in, int chunkInInode,
    6284 +                                        __u8 * buffer)
    6285 +{
    6286 +       int chunkInNAND = yaffs_FindChunkInFile(in, chunkInInode, NULL);
    6287 +
    6288 +       if (chunkInNAND >= 0) {
    6289 +               return yaffs_ReadChunkWithTagsFromNAND(in->myDev, chunkInNAND,
    6290 +                                                      buffer,NULL);
    6291 +       } else {
    6292 +               T(YAFFS_TRACE_NANDACCESS,
    6293 +                 (TSTR("Chunk %d not found zero instead" TENDSTR),
    6294 +                  chunkInNAND));
    6295 +               /* get sane (zero) data if you read a hole */
    6296 +               memset(buffer, 0, in->myDev->nDataBytesPerChunk);       
     5522+
     5523+
     5524+static int yaffs_ReadChunkDataFromObject(yaffs_Object *in,int chunkInInode, __u8 *buffer)
     5525+{
     5526+    int chunkInNAND = yaffs_FindChunkInFile(in,chunkInInode,NULL);
     5527+   
     5528+    if(chunkInNAND >= 0)
     5529+    {
     5530+               return yaffs_ReadChunkWithTagsFromNAND(in->myDev,chunkInNAND,buffer,NULL);
     5531+       }
     5532+       else
     5533+       {
     5534+               T(YAFFS_TRACE_NANDACCESS,(TSTR("Chunk %d not found zero instead" TENDSTR),chunkInNAND));
     5535+
     5536+               memset(buffer,0,in->myDev->nBytesPerChunk); // get sane data if you read a hole
    62975537+               return 0;
    62985538+       }
     
    63005540+}
    63015541+
    6302 +void yaffs_DeleteChunk(yaffs_Device * dev, int chunkId, int markNAND, int lyn)
     5542+
     5543+void yaffs_DeleteChunk(yaffs_Device *dev,int chunkId,int markNAND,int lyn)
    63035544+{
    63045545+       int block;
     
    63065547+       yaffs_ExtendedTags tags;
    63075548+       yaffs_BlockInfo *bi;
    6308 +
    6309 +       if (chunkId <= 0)
    6310 +               return;
    6311 +
     5549+       
     5550+       if(chunkId <= 0) return;       
     5551+       
    63125552+       dev->nDeletions++;
    63135553+       block = chunkId / dev->nChunksPerBlock;
    63145554+       page = chunkId % dev->nChunksPerBlock;
    6315 +
    6316 +       bi = yaffs_GetBlockInfo(dev, block);
    6317 +
    6318 +       T(YAFFS_TRACE_DELETION,
    6319 +         (TSTR("line %d delete of chunk %d" TENDSTR), lyn, chunkId));
    6320 +
    6321 +       if (markNAND &&
    6322 +           bi->blockState != YAFFS_BLOCK_STATE_COLLECTING && !dev->isYaffs2) {
     5555+       
     5556+       bi = yaffs_GetBlockInfo(dev,block);
     5557+       
     5558+       T(YAFFS_TRACE_DELETION,(TSTR("line %d delete of chunk %d" TENDSTR),lyn,chunkId));
     5559+       
     5560+       if(markNAND &&
     5561+         bi->blockState != YAFFS_BLOCK_STATE_COLLECTING &&
     5562+         !dev->isYaffs2)
     5563+       {
     5564+//             yaffs_SpareInitialise(&spare);
     5565+
     5566+#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
     5567+
     5568+                //read data before write, to ensure correct ecc
     5569+                //if we're using MTD verification under Linux
     5570+//                yaffs_ReadChunkFromNAND(dev,chunkId,NULL,&spare,0);
     5571+#endif
    63235572+
    63245573+               yaffs_InitialiseTags(&tags);
     
    63265575+               tags.chunkDeleted = 1;
    63275576+
    6328 +               yaffs_WriteChunkWithTagsToNAND(dev, chunkId, NULL, &tags);
    6329 +               yaffs_HandleUpdateChunk(dev, chunkId, &tags);
    6330 +       } else {
    6331 +               dev->nUnmarkedDeletions++;
    6332 +       }
    6333 +
    6334 +       /* Pull out of the management area.
    6335 +        * If the whole block became dirty, this will kick off an erasure.
    6336 +        */
    6337 +       if (bi->blockState == YAFFS_BLOCK_STATE_ALLOCATING ||
    6338 +           bi->blockState == YAFFS_BLOCK_STATE_FULL ||
     5577+       
     5578+               yaffs_WriteChunkWithTagsToNAND(dev,chunkId,NULL,&tags);
     5579+               yaffs_HandleUpdateChunk(dev,chunkId,&tags);
     5580+       }
     5581+       else
     5582+       {
     5583+                       dev->nUnmarkedDeletions++;
     5584+       }       
     5585+       
     5586+       
     5587+       // Pull out of the management area.
     5588+       // If the whole block became dirty, this will kick off an erasure.
     5589+       if(     bi->blockState == YAFFS_BLOCK_STATE_ALLOCATING ||
     5590+           bi->blockState == YAFFS_BLOCK_STATE_FULL ||     
    63395591+           bi->blockState == YAFFS_BLOCK_STATE_NEEDS_SCANNING ||
    6340 +           bi->blockState == YAFFS_BLOCK_STATE_COLLECTING) {
    6341 +               dev->nFreeChunks++;
    6342 +
    6343 +               yaffs_ClearChunkBit(dev, block, page);
    6344 +
     5592+           bi->blockState == YAFFS_BLOCK_STATE_COLLECTING)
     5593+       {
     5594+               dev->nFreeChunks++;
     5595+
     5596+               yaffs_ClearChunkBit(dev,block,page);
     5597+               
    63455598+               bi->pagesInUse--;
    6346 +
    6347 +               if (bi->pagesInUse == 0 &&
    6348 +                   !bi->hasShrinkHeader &&
    6349 +                   bi->blockState != YAFFS_BLOCK_STATE_ALLOCATING &&
    6350 +                   bi->blockState != YAFFS_BLOCK_STATE_NEEDS_SCANNING) {
    6351 +                       yaffs_BlockBecameDirty(dev, block);
    6352 +               }
    6353 +
    6354 +       } else {
    6355 +               /* T(("Bad news deleting chunk %d\n",chunkId)); */
    6356 +       }
    6357 +
    6358 +}
    6359 +
    6360 +static int yaffs_WriteChunkDataToObject(yaffs_Object * in, int chunkInInode,
    6361 +                                       const __u8 * buffer, int nBytes,
    6362 +                                       int useReserve)
    6363 +{
    6364 +       /* Find old chunk Need to do this to get serial number
    6365 +        * Write new one and patch into tree.
    6366 +        * Invalidate old tags.
    6367 +        */
    6368 +
    6369 +       int prevChunkId;
    6370 +       yaffs_ExtendedTags prevTags;
    6371 +
    6372 +       int newChunkId;
    6373 +       yaffs_ExtendedTags newTags;
    6374 +
     5599+               
     5600+               if(bi->pagesInUse == 0 &&
     5601+                  !bi->hasShrinkHeader &&
     5602+              bi->blockState != YAFFS_BLOCK_STATE_ALLOCATING &&
     5603+              bi->blockState != YAFFS_BLOCK_STATE_NEEDS_SCANNING)
     5604+           {
     5605+               yaffs_BlockBecameDirty(dev,block);
     5606+           }
     5607+
     5608+       }
     5609+       else
     5610+       {
     5611+               // T(("Bad news deleting chunk %d\n",chunkId));
     5612+       }
     5613+       
     5614+}
     5615+
     5616+
     5617+
     5618+
     5619+static int yaffs_WriteChunkDataToObject(yaffs_Object *in,int chunkInInode, const __u8 *buffer,int nBytes,int useReserve)
     5620+{
     5621+       // Find old chunk Need to do this to get serial number
     5622+       // Write new one and patch into tree.
     5623+       // Invalidate old tags.
     5624+
     5625+    int prevChunkId;
     5626+    yaffs_ExtendedTags prevTags;
     5627+   
     5628+    int newChunkId;
     5629+    yaffs_ExtendedTags newTags;
     5630+
     5631+    yaffs_Device *dev = in->myDev;   
     5632+
     5633+       yaffs_CheckGarbageCollection(dev);
     5634+
     5635+       // Get the previous chunk at this location in the file if it exists
     5636+    prevChunkId  = yaffs_FindChunkInFile(in,chunkInInode,&prevTags);
     5637+   
     5638+    // Set up new tags
     5639+    yaffs_InitialiseTags(&newTags);
     5640+   
     5641+       newTags.chunkId = chunkInInode;
     5642+       newTags.objectId = in->objectId;
     5643+       newTags.serialNumber = (prevChunkId >= 0) ? prevTags.serialNumber + 1 : 1;
     5644+       newTags.byteCount = nBytes;
     5645+               
     5646+//     yaffs_CalcTagsECC(&newTags);
     5647+
     5648+       newChunkId = yaffs_WriteNewChunkWithTagsToNAND(dev,buffer,&newTags,useReserve);
     5649+       
     5650+       if(newChunkId >= 0)
     5651+       {
     5652+               yaffs_PutChunkIntoFile(in,chunkInInode,newChunkId,0);
     5653+               
     5654+               
     5655+               if(prevChunkId >= 0)
     5656+               {
     5657+                       yaffs_DeleteChunk(dev,prevChunkId,1,__LINE__);
     5658+       
     5659+               }
     5660+               
     5661+               yaffs_CheckFileSanity(in);
     5662+       }
     5663+       return newChunkId;
     5664+
     5665+
     5666+
     5667+
     5668+
     5669+}
     5670+
     5671+
     5672+// UpdateObjectHeader updates the header on NAND for an object.
     5673+// If name is not NULL, then that new name is used.
     5674+//
     5675+int yaffs_UpdateObjectHeader(yaffs_Object *in,const YCHAR *name, int force,int isShrink,int shadows)
     5676+{
     5677+
     5678+       yaffs_BlockInfo *bi;
     5679+       
    63755680+       yaffs_Device *dev = in->myDev;
    6376 +
    6377 +       yaffs_CheckGarbageCollection(dev);
    6378 +
    6379 +       /* Get the previous chunk at this location in the file if it exists */
    6380 +       prevChunkId = yaffs_FindChunkInFile(in, chunkInInode, &prevTags);
    6381 +
    6382 +       /* Set up new tags */
    6383 +       yaffs_InitialiseTags(&newTags);
    6384 +
    6385 +       newTags.chunkId = chunkInInode;
    6386 +       newTags.objectId = in->objectId;
    6387 +       newTags.serialNumber =
    6388 +           (prevChunkId >= 0) ? prevTags.serialNumber + 1 : 1;
    6389 +       newTags.byteCount = nBytes;
    6390 +
    6391 +       newChunkId =
    6392 +           yaffs_WriteNewChunkWithTagsToNAND(dev, buffer, &newTags,
    6393 +                                             useReserve);
    6394 +
    6395 +       if (newChunkId >= 0) {
    6396 +               yaffs_PutChunkIntoFile(in, chunkInInode, newChunkId, 0);
    6397 +
    6398 +               if (prevChunkId >= 0) {
    6399 +                       yaffs_DeleteChunk(dev, prevChunkId, 1, __LINE__);
    6400 +
    6401 +               }
    6402 +
    6403 +               yaffs_CheckFileSanity(in);
    6404 +       }
    6405 +       return newChunkId;
    6406 +
    6407 +}
    6408 +
    6409 +/* UpdateObjectHeader updates the header on NAND for an object.
    6410 + * If name is not NULL, then that new name is used.
    6411 + */
    6412 +int yaffs_UpdateObjectHeader(yaffs_Object * in, const YCHAR * name, int force,
    6413 +                            int isShrink, int shadows)
    6414 +{
    6415 +
    6416 +       yaffs_BlockInfo *bi;
    6417 +
    6418 +       yaffs_Device *dev = in->myDev;
    6419 +
    6420 +       int prevChunkId;
    6421 +       int retVal = 0;
    6422 +       int result = 0;
    6423 +
    6424 +       int newChunkId;
    6425 +       yaffs_ExtendedTags newTags;
    6426 +
    6427 +       __u8 *buffer = NULL;
    6428 +       YCHAR oldName[YAFFS_MAX_NAME_LENGTH + 1];
    6429 +
    6430 +       yaffs_ObjectHeader *oh = NULL;
    6431 +
    6432 +       if (!in->fake || force) {
    6433 +
    6434 +               yaffs_CheckGarbageCollection(dev);
    6435 +
    6436 +               buffer = yaffs_GetTempBuffer(in->myDev, __LINE__);
    6437 +               oh = (yaffs_ObjectHeader *) buffer;
    6438 +
     5681+       
     5682+    int prevChunkId;
     5683+    int retVal = 0;
     5684+   
     5685+    int newChunkId;
     5686+    yaffs_ExtendedTags newTags;
     5687+   
     5688+    __u8 *buffer = NULL;
     5689+    YCHAR oldName[YAFFS_MAX_NAME_LENGTH+1];
     5690+   
     5691+   // __u8 bufferOld[YAFFS_BYTES_PER_CHUNK];
     5692+   
     5693+    yaffs_ObjectHeader *oh = NULL;
     5694+    // yaffs_ObjectHeader *ohOld = (yaffs_ObjectHeader *)bufferOld;
     5695+
     5696+   
     5697+    if(!in->fake || force)
     5698+    {
     5699
     5700+               yaffs_CheckGarbageCollection(dev);             
     5701+   
     5702+           buffer = yaffs_GetTempBuffer(in->myDev,__LINE__);
     5703+           oh  = (yaffs_ObjectHeader *)buffer;
     5704+   
    64395705+               prevChunkId = in->chunkId;
    6440 +
    6441 +               if (prevChunkId >= 0) {
    6442 +                       result = yaffs_ReadChunkWithTagsFromNAND(dev, prevChunkId,
    6443 +                                                       buffer, NULL);
    6444 +                       memcpy(oldName, oh->name, sizeof(oh->name));
    6445 +               }
    6446 +
    6447 +               memset(buffer, 0xFF, dev->nDataBytesPerChunk);
    6448 +
     5706+   
     5707+               if(prevChunkId >= 0)
     5708+               {
     5709+                       yaffs_ReadChunkWithTagsFromNAND(dev,prevChunkId,buffer,NULL);
     5710+                       memcpy(oldName,oh->name,sizeof(oh->name));     
     5711+               }
     5712+
     5713+               memset(buffer,0xFF,dev->nBytesPerChunk);
     5714+
     5715+               // Header data
    64495716+               oh->type = in->variantType;
     5717+               
    64505718+               oh->yst_mode = in->yst_mode;
     5719+               
     5720+               // shadowing
    64515721+               oh->shadowsObject = shadows;
    64525722+
     
    64655735+               oh->yst_ctime = in->yst_ctime;
    64665736+               oh->yst_rdev = in->yst_rdev;
    6467 +#endif
    6468 +               if (in->parent) {
     5737+#endif
     5738+               if(in->parent)
     5739+               {
    64695740+                       oh->parentObjectId = in->parent->objectId;
    6470 +               } else {
     5741+               }
     5742+               else
     5743+               {
    64715744+                       oh->parentObjectId = 0;
    64725745+               }
    6473 +
    6474 +               if (name && *name) {
    6475 +                       memset(oh->name, 0, sizeof(oh->name));
    6476 +                       yaffs_strncpy(oh->name, name, YAFFS_MAX_NAME_LENGTH);
    6477 +               } else if (prevChunkId) {
    6478 +                       memcpy(oh->name, oldName, sizeof(oh->name));
    6479 +               } else {
    6480 +                       memset(oh->name, 0, sizeof(oh->name));
    6481 +               }
    6482 +
     5746+               
     5747+               //oh->sum = in->sum;
     5748+               if(name && *name)
     5749+               {
     5750+                       memset(oh->name,0,sizeof(oh->name));
     5751+                       yaffs_strncpy(oh->name,name,YAFFS_MAX_NAME_LENGTH);
     5752+               }
     5753+               else if(prevChunkId)
     5754+               {       
     5755+                       memcpy(oh->name, oldName,sizeof(oh->name));
     5756+               }
     5757+               else
     5758+               {
     5759+                       memset(oh->name,0,sizeof(oh->name));   
     5760+               }
     5761+               
    64835762+               oh->isShrink = isShrink;
    6484 +
    6485 +               switch (in->variantType) {
    6486 +               case YAFFS_OBJECT_TYPE_UNKNOWN:
    6487 +                       /* Should not happen */
    6488 +                       break;
    6489 +               case YAFFS_OBJECT_TYPE_FILE:
    6490 +                       oh->fileSize =
    6491 +                           (oh->parentObjectId == YAFFS_OBJECTID_DELETED
    6492 +                            || oh->parentObjectId ==
    6493 +                            YAFFS_OBJECTID_UNLINKED) ? 0 : in->variant.
    6494 +                           fileVariant.fileSize;
    6495 +                       break;
    6496 +               case YAFFS_OBJECT_TYPE_HARDLINK:
    6497 +                       oh->equivalentObjectId =
    6498 +                           in->variant.hardLinkVariant.equivalentObjectId;
    6499 +                       break;
    6500 +               case YAFFS_OBJECT_TYPE_SPECIAL:
    6501 +                       /* Do nothing */
    6502 +                       break;
    6503 +               case YAFFS_OBJECT_TYPE_DIRECTORY:
    6504 +                       /* Do nothing */
    6505 +                       break;
    6506 +               case YAFFS_OBJECT_TYPE_SYMLINK:
    6507 +                       yaffs_strncpy(oh->alias,
    6508 +                                     in->variant.symLinkVariant.alias,
    6509 +                                     YAFFS_MAX_ALIAS_LENGTH);
    6510 +                       oh->alias[YAFFS_MAX_ALIAS_LENGTH] = 0;
    6511 +                       break;
    6512 +               }
    6513 +
    6514 +               /* Tags */
     5763+       
     5764+               switch(in->variantType)
     5765+               {
     5766+                       case YAFFS_OBJECT_TYPE_UNKNOWN:         
     5767+                               // Should not happen
     5768+                               break;
     5769+                       case YAFFS_OBJECT_TYPE_FILE:
     5770+                               oh->fileSize = (oh->parentObjectId == YAFFS_OBJECTID_DELETED ||
     5771+                                               oh->parentObjectId == YAFFS_OBJECTID_UNLINKED) ? 0 : in->variant.fileVariant.fileSize;
     5772+                               break;
     5773+                       case YAFFS_OBJECT_TYPE_HARDLINK:
     5774+                               oh->equivalentObjectId = in->variant.hardLinkVariant.equivalentObjectId;
     5775+                               break;
     5776+                       case YAFFS_OBJECT_TYPE_SPECIAL:
     5777+                               // Do nothing
     5778+                               break;
     5779+                       case YAFFS_OBJECT_TYPE_DIRECTORY:       
     5780+                               // Do nothing
     5781+                               break;
     5782+                       case YAFFS_OBJECT_TYPE_SYMLINK:
     5783+                               yaffs_strncpy(oh->alias,in->variant.symLinkVariant.alias,YAFFS_MAX_ALIAS_LENGTH);
     5784+                               oh->alias[YAFFS_MAX_ALIAS_LENGTH] = 0;
     5785+                               break;
     5786+               }
     5787+
     5788+               // Tags
    65155789+               yaffs_InitialiseTags(&newTags);
    65165790+               in->serial++;
     
    65185792+               newTags.objectId = in->objectId;
    65195793+               newTags.serialNumber = in->serial;
    6520 +
    6521 +               /* Add extra info for file header */
    6522 +
     5794+               
     5795+               // Add extra info for file header
     5796+               
    65235797+               newTags.extraHeaderInfoAvailable = 1;
    65245798+               newTags.extraParentObjectId = oh->parentObjectId;
     
    65275801+               newTags.extraEquivalentObjectId = oh->equivalentObjectId;
    65285802+               newTags.extraShadows = (oh->shadowsObject > 0) ? 1 : 0;
    6529 +               newTags.extraObjectType = in->variantType;
    6530 +
    6531 +               /* Create new chunk in NAND */
    6532 +               newChunkId =
    6533 +                   yaffs_WriteNewChunkWithTagsToNAND(dev, buffer, &newTags,
    6534 +                                                     (prevChunkId >= 0) ? 1 : 0);
    6535 +
    6536 +               if (newChunkId >= 0) {
    6537 +
    6538 +                       in->chunkId = newChunkId;
    6539 +
    6540 +                       if (prevChunkId >= 0) {
    6541 +                               yaffs_DeleteChunk(dev, prevChunkId, 1,
    6542 +                                                 __LINE__);
     5803+               newTags.extraObjectType  = in->variantType;
     5804+               
     5805+               // Create new chunk in NAND
     5806+               newChunkId = yaffs_WriteNewChunkWithTagsToNAND(dev,buffer,&newTags, (prevChunkId >= 0) ? 1 : 0 );
     5807+   
     5808+               if(newChunkId >= 0)
     5809+               {
     5810+               
     5811+                       in->chunkId = newChunkId;       
     5812+               
     5813+                       if(prevChunkId >= 0)
     5814+                       {
     5815+                               yaffs_DeleteChunk(dev,prevChunkId,1,__LINE__);
    65435816+                       }
    6544 +
    6545 +                       if(!yaffs_ObjectHasCachedWriteData(in))
    6546 +                               in->dirty = 0;
    6547 +
    6548 +                       /* If this was a shrink, then mark the block that the chunk lives on */
    6549 +                       if (isShrink) {
    6550 +                               bi = yaffs_GetBlockInfo(in->myDev,
    6551 +                                                       newChunkId /in->myDev-> nChunksPerBlock);
     5817+               
     5818+                       in->dirty = 0;
     5819+                       
     5820+                       // If this was a shrink, then mark the block that the chunk lives on
     5821+                       if(isShrink)
     5822+                       {
     5823+                               bi = yaffs_GetBlockInfo(in->myDev,newChunkId / in->myDev->nChunksPerBlock);
    65525824+                               bi->hasShrinkHeader = 1;
    65535825+                       }
    6554 +
    6555 +               }
    6556 +
    6557 +               retVal = newChunkId;
    6558 +
    6559 +       }
    6560 +
    6561 +       if (buffer)
    6562 +               yaffs_ReleaseTempBuffer(dev, buffer, __LINE__);
    6563 +
    6564 +       return retVal;
    6565 +}
    6566 +
    6567 +/*------------------------ Short Operations Cache ----------------------------------------
    6568 + *   In many situations where there is no high level buffering (eg WinCE) a lot of
    6569 + *   reads might be short sequential reads, and a lot of writes may be short
    6570 + *   sequential writes. eg. scanning/writing a jpeg file.
    6571 + *   In these cases, a short read/write cache can provide a huge perfomance benefit
    6572 + *   with dumb-as-a-rock code.
    6573 + *   In Linux, the page cache provides read buffering aand the short op cache provides write
    6574 + *   buffering.
    6575 + *
    6576 + *   There are a limited number (~10) of cache chunks per device so that we don't
    6577 + *   need a very intelligent search.
    6578 + */
    6579 +
    6580 +static int yaffs_ObjectHasCachedWriteData(yaffs_Object *obj)
     5826+                       
     5827+               }
     5828+               
     5829+               retVal =  newChunkId;
     5830+
     5831+    }
     5832+   
     5833+       if(buffer)
     5834+               yaffs_ReleaseTempBuffer(dev,buffer,__LINE__);
     5835+       
     5836+    return retVal;
     5837+}
     5838+
     5839+
     5840+/////////////////////// Short Operations Cache ////////////////////////////////
     5841+//     In many siturations where there is no high level buffering (eg WinCE) a lot of
     5842+//     reads might be short sequential reads, and a lot of writes may be short
     5843+//  sequential writes. eg. scanning/writing a jpeg file.
     5844+//     In these cases, a short read/write cache can provide a huge perfomance benefit
     5845+//  with dumb-as-a-rock code.
     5846+//  There are a limited number (~10) of cache chunks per device so that we don't
     5847+//  need a very intelligent search.
     5848+
     5849+
     5850+
     5851+
     5852+
     5853+static void yaffs_FlushFilesChunkCache(yaffs_Object *obj)
    65815854+{
    65825855+       yaffs_Device *dev = obj->myDev;
    6583 +       int i;
    6584 +       yaffs_ChunkCache *cache;
    6585 +       int nCaches = obj->myDev->nShortOpCaches;
    6586 +       
    6587 +       for(i = 0; i < nCaches; i++){
    6588 +               cache = &dev->srCache[i];
    6589 +               if (cache->object == obj &&
    6590 +                   cache->dirty)
    6591 +                       return 1;
    6592 +       }
    6593 +       
    6594 +       return 0;
    6595 +}
    6596 +
    6597 +
    6598 +static void yaffs_FlushFilesChunkCache(yaffs_Object * obj)
    6599 +{
    6600 +       yaffs_Device *dev = obj->myDev;
    6601 +       int lowest = -99;       /* Stop compiler whining. */
     5856+       int lowest = -99; // Stop compiler whining.
    66025857+       int i;
    66035858+       yaffs_ChunkCache *cache;
    66045859+       int chunkWritten = 0;
     5860+       //int nBytes;
    66055861+       int nCaches = obj->myDev->nShortOpCaches;
    6606 +
    6607 +       if (nCaches > 0) {
    6608 +               do {
     5862+       
     5863+       if  (nCaches > 0)
     5864+       {
     5865+               do{
    66095866+                       cache = NULL;
    6610 +
    6611 +                       /* Find the dirty cache for this object with the lowest chunk id. */
    6612 +                       for (i = 0; i < nCaches; i++) {
    6613 +                               if (dev->srCache[i].object == obj &&
    6614 +                                   dev->srCache[i].dirty) {
    6615 +                                       if (!cache
    6616 +                                           || dev->srCache[i].chunkId <
    6617 +                                           lowest) {
     5867+               
     5868+                       // Find the dirty cache for this object with the lowest chunk id.
     5869+                       for(i = 0; i < nCaches; i++)
     5870+                       {
     5871+                               if(dev->srCache[i].object == obj &&
     5872+                                  dev->srCache[i].dirty)
     5873+                               {
     5874+                                       if(!cache ||  dev->srCache[i].chunkId < lowest)
     5875+                                       {
    66185876+                                               cache = &dev->srCache[i];
    66195877+                                               lowest = cache->chunkId;
     
    66215879+                               }
    66225880+                       }
    6623 +
    6624 +                       if (cache && !cache->locked) {
    6625 +                               /* Write it out and free it up */
    6626 +
    6627 +                               chunkWritten =
    6628 +                                   yaffs_WriteChunkDataToObject(cache->object,
    6629 +                                                                cache->chunkId,
    6630 +                                                                cache->data,
    6631 +                                                                cache->nBytes,
    6632 +                                                                1);
     5881+               
     5882+                       if(cache && !cache->locked)
     5883+                       {
     5884+                               //Write it out and free it up
     5885+
     5886+#if 0
     5887+                               nBytes = cache->object->variant.fileVariant.fileSize - ((cache->chunkId -1) * YAFFS_BYTES_PER_CHUNK);
     5888+                       
     5889+                               if(nBytes > YAFFS_BYTES_PER_CHUNK)
     5890+                               {
     5891+                                       nBytes= YAFFS_BYTES_PER_CHUNK;
     5892+                               }
     5893+#endif                 
     5894+                               chunkWritten = yaffs_WriteChunkDataToObject(cache->object,
     5895+                                                                                                                       cache->chunkId,
     5896+                                                                                                                       cache->data,
     5897+                                                                                                                       cache->nBytes,1);
     5898+
    66335899+                               cache->dirty = 0;
    66345900+                               cache->object = NULL;
    66355901+                       }
    6636 +
    6637 +               } while (cache && chunkWritten > 0);
    6638 +
    6639 +               if (cache) {
    6640 +                       /* Hoosterman, disk full while writing cache out. */
    6641 +                       T(YAFFS_TRACE_ERROR,
    6642 +                         (TSTR("yaffs tragedy: no space during cache write" TENDSTR)));
    6643 +
    6644 +               }
    6645 +       }
    6646 +
    6647 +}
    6648 +
    6649 +/*yaffs_FlushEntireDeviceCache(dev)
    6650 + *
    6651 + *
    6652 + */
    6653 +
    6654 +void yaffs_FlushEntireDeviceCache(yaffs_Device *dev)
    6655 +{
    6656 +       yaffs_Object *obj;
    6657 +       int nCaches = dev->nShortOpCaches;
    6658 +       int i;
    6659 +       
    6660 +       /* Find a dirty object in the cache and flush it...
    6661 +        * until there are no further dirty objects.
    6662 +        */
    6663 +       do {
    6664 +               obj = NULL;
    6665 +               for( i = 0; i < nCaches && !obj; i++) {
    6666 +                       if (dev->srCache[i].object &&
    6667 +                           dev->srCache[i].dirty)
    6668 +                               obj = dev->srCache[i].object;
    6669 +                           
    6670 +               }
    6671 +               if(obj)
    6672 +                       yaffs_FlushFilesChunkCache(obj);
    6673 +                       
    6674 +       } while(obj);
    6675 +       
    6676 +}
    6677 +
    6678 +
    6679 +/* Grab us a cache chunk for use.
    6680 + * First look for an empty one.
    6681 + * Then look for the least recently used non-dirty one.
    6682 + * Then look for the least recently used dirty one...., flush and look again.
    6683 + */
    6684 +static yaffs_ChunkCache *yaffs_GrabChunkCacheWorker(yaffs_Device * dev)
     5902+               
     5903+               } while(cache && chunkWritten > 0);
     5904+       
     5905+               if(cache)
     5906+               {
     5907+                       //Hoosterman, disk full while writing cache out.
     5908+                       T(YAFFS_TRACE_ERROR, (TSTR("yaffs tragedy: no space during cache write" TENDSTR)));
     5909+
     5910+               }
     5911+       }       
     5912+               
     5913+}
     5914+
     5915+
     5916+// Grab us a chunk for use.
     5917+// First look for an empty one.
     5918+// Then look for the least recently used non-dirty one.
     5919+// Then look for the least recently used dirty one...., flush and look again.
     5920+static yaffs_ChunkCache *yaffs_GrabChunkCacheWorker(yaffs_Device *dev)
    66855921+{
    66865922+       int i;
    66875923+       int usage;
    66885924+       int theOne;
    6689 +
    6690 +       if (dev->nShortOpCaches > 0) {
    6691 +               for (i = 0; i < dev->nShortOpCaches; i++) {
    6692 +                       if (!dev->srCache[i].object)
     5925+       
     5926+       if(dev->nShortOpCaches > 0)
     5927+       {
     5928+               for(i = 0; i < dev->nShortOpCaches; i++)
     5929+               {
     5930+                       if(!dev->srCache[i].object)
     5931+                       {
     5932+                               //T(("Grabbing empty %d\n",i));
     5933+                               
     5934+                               //printf("Grabbing empty %d\n",i);
     5935+                       
    66935936+                               return &dev->srCache[i];
    6694 +               }
    6695 +
     5937+                       }
     5938+               }
     5939+               
    66965940+               return NULL;
    6697 +
    6698 +               theOne = -1;
    6699 +               usage = 0;      /* just to stop the compiler grizzling */
    6700 +
    6701 +               for (i = 0; i < dev->nShortOpCaches; i++) {
    6702 +                       if (!dev->srCache[i].dirty &&
    6703 +                           ((dev->srCache[i].lastUse < usage && theOne >= 0) ||
    6704 +                            theOne < 0)) {
     5941+       
     5942+               theOne = -1;
     5943+               usage = 0; // just to stop the compiler grizzling
     5944+       
     5945+               for(i = 0; i < dev->nShortOpCaches; i++)
     5946+               {
     5947+                       if(!dev->srCache[i].dirty &&
     5948+                       ((dev->srCache[i].lastUse < usage  && theOne >= 0)||
     5949+                               theOne < 0))
     5950+                       {
    67055951+                               usage = dev->srCache[i].lastUse;
    67065952+                               theOne = i;
    67075953+                       }
    67085954+               }
    6709 +
    6710 +
    6711 +               return theOne >= 0 ? &dev->srCache[theOne] : NULL;
    6712 +       } else {
     5955+       
     5956+               //T(("Grabbing non-empty %d\n",theOne));
     5957+               
     5958+               //if(theOne >= 0) printf("Grabbed non-empty cache %d\n",theOne);
     5959+               
     5960+               return  theOne >= 0 ?  &dev->srCache[theOne] : NULL;
     5961+       }
     5962+       else
     5963+       {
    67135964+               return NULL;
    67145965+       }
    6715 +
    6716 +}
    6717 +
    6718 +static yaffs_ChunkCache *yaffs_GrabChunkCache(yaffs_Device * dev)
     5966+       
     5967+}
     5968+
     5969+
     5970+static yaffs_ChunkCache *yaffs_GrabChunkCache(yaffs_Device *dev)
    67195971+{
    67205972+       yaffs_ChunkCache *cache;
     
    67235975+       int i;
    67245976+       int pushout;
    6725 +
    6726 +       if (dev->nShortOpCaches > 0) {
    6727 +               /* Try find a non-dirty one... */
    6728 +
     5977+       
     5978+       if(dev->nShortOpCaches > 0)
     5979+       {
     5980+               // Try find a non-dirty one...
     5981+       
    67295982+               cache = yaffs_GrabChunkCacheWorker(dev);
    6730 +
    6731 +               if (!cache) {
    6732 +                       /* They were all dirty, find the last recently used object and flush
    6733 +                        * its cache, then  find again.
    6734 +                        * NB what's here is not very accurate, we actually flush the object
    6735 +                        * the last recently used page.
    6736 +                        */
    6737 +
    6738 +                       /* With locking we can't assume we can use entry zero */
    6739 +
     5983+       
     5984+               if(!cache)
     5985+               {
     5986+                       // They were all dirty, find the last recently used object and flush
     5987+                       // its cache, then  find again.
     5988+                       // NB what's here is not very accurate, we actually flush the object
     5989+                       // the last recently used page.
     5990+                       
     5991+                       // With locking we can't assume we can use entry zero
     5992+                       
     5993+               
    67405994+                       theObj = NULL;
    67415995+                       usage = -1;
    67425996+                       cache = NULL;
    67435997+                       pushout = -1;
    6744 +
    6745 +                       for (i = 0; i < dev->nShortOpCaches; i++) {
    6746 +                               if (dev->srCache[i].object &&
    6747 +                                   !dev->srCache[i].locked &&
    6748 +                                   (dev->srCache[i].lastUse < usage || !cache))
     5998+       
     5999+                       for(i = 0; i < dev->nShortOpCaches; i++)
     6000+                       {
     6001+                               if( dev->srCache[i].object &&
     6002+                                       !dev->srCache[i].locked &&
     6003+                                       (dev->srCache[i].lastUse < usage || !cache))
    67496004+                               {
    6750 +                                       usage = dev->srCache[i].lastUse;
     6005+                                       usage  = dev->srCache[i].lastUse;
    67516006+                                       theObj = dev->srCache[i].object;
    67526007+                                       cache = &dev->srCache[i];
     
    67546009+                               }
    67556010+                       }
    6756 +
    6757 +                       if (!cache || cache->dirty) {
    6758 +                               /* Flush and try again */
     6011+               
     6012+                       if(!cache || cache->dirty)
     6013+                       {
     6014+                       
     6015+                               //printf("Dirty ");
    67596016+                               yaffs_FlushFilesChunkCache(theObj);
     6017+               
     6018+                               // Try again
    67606019+                               cache = yaffs_GrabChunkCacheWorker(dev);
    67616020+                       }
    6762 +
     6021+                       else
     6022+                       {
     6023+                               //printf(" pushout %d\n",pushout);
     6024+                       }
     6025+                       
    67636026+               }
    67646027+               return cache;
    6765 +       } else
     6028+       }
     6029+       else
    67666030+               return NULL;
    67676031+
    67686032+}
    67696033+
    6770 +/* Find a cached chunk */
    6771 +static yaffs_ChunkCache *yaffs_FindChunkCache(const yaffs_Object * obj,
    6772 +                                            int chunkId)
     6034+
     6035+// Find a cached chunk
     6036+static yaffs_ChunkCache *yaffs_FindChunkCache(const yaffs_Object *obj, int chunkId)
    67736037+{
    67746038+       yaffs_Device *dev = obj->myDev;
    67756039+       int i;
    6776 +       if (dev->nShortOpCaches > 0) {
    6777 +               for (i = 0; i < dev->nShortOpCaches; i++) {
    6778 +                       if (dev->srCache[i].object == obj &&
    6779 +                           dev->srCache[i].chunkId == chunkId) {
     6040+       if(dev->nShortOpCaches > 0)
     6041+       {
     6042+               for(i = 0; i < dev->nShortOpCaches; i++)
     6043+               {
     6044+                       if(dev->srCache[i].object == obj &&
     6045+                       dev->srCache[i].chunkId == chunkId)
     6046+                       {
    67806047+                               dev->cacheHits++;
    6781 +
     6048+                       
    67826049+                               return &dev->srCache[i];
    67836050+                       }
     
    67876054+}
    67886055+
    6789 +/* Mark the chunk for the least recently used algorithym */
    6790 +static void yaffs_UseChunkCache(yaffs_Device * dev, yaffs_ChunkCache * cache,
    6791 +                               int isAWrite)
    6792 +{
    6793 +
    6794 +       if (dev->nShortOpCaches > 0) {
    6795 +               if (dev->srLastUse < 0 || dev->srLastUse > 100000000) {
    6796 +                       /* Reset the cache usages */
     6056+// Mark the chunk for the least recently used algorithym
     6057+static void yaffs_UseChunkCache(yaffs_Device *dev, yaffs_ChunkCache *cache, int isAWrite)
     6058+{
     6059+
     6060+       if(dev->nShortOpCaches > 0)
     6061+       {
     6062+               if( dev->srLastUse < 0 ||
     6063+                       dev->srLastUse > 100000000)
     6064+               {
     6065+                       // Reset the cache usages
    67976066+                       int i;
    6798 +                       for (i = 1; i < dev->nShortOpCaches; i++) {
     6067+                       for(i = 1; i < dev->nShortOpCaches; i++)
     6068+                       {
    67996069+                               dev->srCache[i].lastUse = 0;
    68006070+                       }
     
    68036073+
    68046074+               dev->srLastUse++;
    6805 +
     6075+       
    68066076+               cache->lastUse = dev->srLastUse;
    68076077+
    6808 +               if (isAWrite) {
     6078+               if(isAWrite)
     6079+               {
    68096080+                       cache->dirty = 1;
    68106081+               }
     
    68126083+}
    68136084+
    6814 +/* Invalidate a single cache page.
    6815 + * Do this when a whole page gets written,
    6816 + * ie the short cache for this page is no longer valid.
    6817 + */
    6818 +static void yaffs_InvalidateChunkCache(yaffs_Object * object, int chunkId)
    6819 +{
    6820 +       if (object->myDev->nShortOpCaches > 0) {
    6821 +               yaffs_ChunkCache *cache = yaffs_FindChunkCache(object, chunkId);
    6822 +
    6823 +               if (cache) {
     6085+// Invalidate a single cache page.
     6086+// Do this when a whole page gets written,
     6087+// ie the short cache for this page is no longer valid.
     6088+static void yaffs_InvalidateChunkCache(yaffs_Object *object, int chunkId)
     6089+{
     6090+       if(object->myDev->nShortOpCaches > 0)
     6091+       {
     6092+               yaffs_ChunkCache *cache = yaffs_FindChunkCache(object,chunkId);
     6093+
     6094+               if(cache)
     6095+               {
    68246096+                       cache->object = NULL;
    68256097+               }
     
    68276099+}
    68286100+
    6829 +/* Invalidate all the cache pages associated with this object
    6830 + * Do this whenever ther file is deleted or resized.
    6831 + */
    6832 +static void yaffs_InvalidateWholeChunkCache(yaffs_Object * in)
     6101+
     6102+// Invalidate all the cache pages associated with this object
     6103+// Do this whenever ther file is deleted or resized.
     6104+static void yaffs_InvalidateWholeChunkCache(yaffs_Object *in)
    68336105+{
    68346106+       int i;
    68356107+       yaffs_Device *dev = in->myDev;
    6836 +
    6837 +       if (dev->nShortOpCaches > 0) {
    6838 +               /* Invalidate it. */
    6839 +               for (i = 0; i < dev->nShortOpCaches; i++) {
    6840 +                       if (dev->srCache[i].object == in) {
     6108+       
     6109+       if(dev->nShortOpCaches > 0)
     6110+       {
     6111+               // Now invalidate it.
     6112+               for(i = 0; i < dev->nShortOpCaches; i++)
     6113+               {
     6114+                       if(dev->srCache[i].object == in)
     6115+                       {
    68416116+                               dev->srCache[i].object = NULL;
    68426117+                       }
     
    68456120+}
    68466121+
    6847 +/*--------------------- Checkpointing --------------------*/
    6848 +
    6849 +
    6850 +static int yaffs_WriteCheckpointValidityMarker(yaffs_Device *dev,int head)
    6851 +{
    6852 +       yaffs_CheckpointValidity cp;
    6853 +       cp.structType = sizeof(cp);
    6854 +       cp.magic = YAFFS_MAGIC;
    6855 +       cp.version = YAFFS_CHECKPOINT_VERSION;
    6856 +       cp.head = (head) ? 1 : 0;
    6857 +       
    6858 +       return (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp))?
    6859 +               1 : 0;
    6860 +}
    6861 +
    6862 +static int yaffs_ReadCheckpointValidityMarker(yaffs_Device *dev, int head)
    6863 +{
    6864 +       yaffs_CheckpointValidity cp;
    6865 +       int ok;
    6866 +       
    6867 +       ok = (yaffs_CheckpointRead(dev,&cp,sizeof(cp)) == sizeof(cp));
    6868 +       
    6869 +       if(ok)
    6870 +               ok = (cp.structType == sizeof(cp)) &&
    6871 +                    (cp.magic == YAFFS_MAGIC) &&
    6872 +                    (cp.version == YAFFS_CHECKPOINT_VERSION) &&
    6873 +                    (cp.head == ((head) ? 1 : 0));
    6874 +       return ok ? 1 : 0;
    6875 +}
    6876 +
    6877 +static void yaffs_DeviceToCheckpointDevice(yaffs_CheckpointDevice *cp,
    6878 +                                          yaffs_Device *dev)
    6879 +{
    6880 +       cp->nErasedBlocks = dev->nErasedBlocks;
    6881 +       cp->allocationBlock = dev->allocationBlock;
    6882 +       cp->allocationPage = dev->allocationPage;
    6883 +       cp->nFreeChunks = dev->nFreeChunks;
    6884 +       
    6885 +       cp->nDeletedFiles = dev->nDeletedFiles;
    6886 +       cp->nUnlinkedFiles = dev->nUnlinkedFiles;
    6887 +       cp->nBackgroundDeletions = dev->nBackgroundDeletions;
    6888 +       cp->sequenceNumber = dev->sequenceNumber;
    6889 +       cp->oldestDirtySequence = dev->oldestDirtySequence;
    6890 +       
    6891 +}
    6892 +
    6893 +static void yaffs_CheckpointDeviceToDevice(yaffs_Device *dev,
    6894 +                                          yaffs_CheckpointDevice *cp)
    6895 +{
    6896 +       dev->nErasedBlocks = cp->nErasedBlocks;
    6897 +       dev->allocationBlock = cp->allocationBlock;
    6898 +       dev->allocationPage = cp->allocationPage;
    6899 +       dev->nFreeChunks = cp->nFreeChunks;
    6900 +       
    6901 +       dev->nDeletedFiles = cp->nDeletedFiles;
    6902 +       dev->nUnlinkedFiles = cp->nUnlinkedFiles;
    6903 +       dev->nBackgroundDeletions = cp->nBackgroundDeletions;
    6904 +       dev->sequenceNumber = cp->sequenceNumber;
    6905 +       dev->oldestDirtySequence = cp->oldestDirtySequence;
    6906 +}
    6907 +
    6908 +
    6909 +static int yaffs_WriteCheckpointDevice(yaffs_Device *dev)
    6910 +{
    6911 +       yaffs_CheckpointDevice cp;
    6912 +       __u32 nBytes;
    6913 +       __u32 nBlocks = (dev->internalEndBlock - dev->internalStartBlock + 1);
    6914 +
    6915 +       int ok;
    6916 +               
    6917 +       /* Write device runtime values*/
    6918 +       yaffs_DeviceToCheckpointDevice(&cp,dev);
    6919 +       cp.structType = sizeof(cp);
    6920 +       
    6921 +       ok = (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp));
    6922 +       
    6923 +       /* Write block info */
    6924 +       if(ok) {
    6925 +               nBytes = nBlocks * sizeof(yaffs_BlockInfo);
    6926 +               ok = (yaffs_CheckpointWrite(dev,dev->blockInfo,nBytes) == nBytes);
    6927 +       }
    6928 +               
    6929 +       /* Write chunk bits */         
    6930 +       if(ok) {
    6931 +               nBytes = nBlocks * dev->chunkBitmapStride;
    6932 +               ok = (yaffs_CheckpointWrite(dev,dev->chunkBits,nBytes) == nBytes);
    6933 +       }
    6934 +       return   ok ? 1 : 0;
    6935 +
    6936 +}
    6937 +
    6938 +static int yaffs_ReadCheckpointDevice(yaffs_Device *dev)
    6939 +{
    6940 +       yaffs_CheckpointDevice cp;
    6941 +       __u32 nBytes;
    6942 +       __u32 nBlocks = (dev->internalEndBlock - dev->internalStartBlock + 1);
    6943 +
    6944 +       int ok;
    6945 +       
    6946 +       ok = (yaffs_CheckpointRead(dev,&cp,sizeof(cp)) == sizeof(cp));
    6947 +       if(!ok)
    6948 +               return 0;
    6949 +               
    6950 +       if(cp.structType != sizeof(cp))
    6951 +               return 0;
    6952 +               
    6953 +       
    6954 +       yaffs_CheckpointDeviceToDevice(dev,&cp);
    6955 +       
    6956 +       nBytes = nBlocks * sizeof(yaffs_BlockInfo);
    6957 +       
    6958 +       ok = (yaffs_CheckpointRead(dev,dev->blockInfo,nBytes) == nBytes);
    6959 +       
    6960 +       if(!ok)
    6961 +               return 0;
    6962 +       nBytes = nBlocks * dev->chunkBitmapStride;
    6963 +       
    6964 +       ok = (yaffs_CheckpointRead(dev,dev->chunkBits,nBytes) == nBytes);
    6965 +       
    6966 +       return ok ? 1 : 0;
    6967 +}
    6968 +
    6969 +static void yaffs_ObjectToCheckpointObject(yaffs_CheckpointObject *cp,
    6970 +                                          yaffs_Object *obj)
    6971 +{
    6972 +
    6973 +       cp->objectId = obj->objectId;
    6974 +       cp->parentId = (obj->parent) ? obj->parent->objectId : 0;
    6975 +       cp->chunkId = obj->chunkId;
    6976 +       cp->variantType = obj->variantType;                     
    6977 +       cp->deleted = obj->deleted;
    6978 +       cp->softDeleted = obj->softDeleted;
    6979 +       cp->unlinked = obj->unlinked;
    6980 +       cp->fake = obj->fake;
    6981 +       cp->renameAllowed = obj->renameAllowed;
    6982 +       cp->unlinkAllowed = obj->unlinkAllowed;
    6983 +       cp->serial = obj->serial;
    6984 +       cp->nDataChunks = obj->nDataChunks;
    6985 +       
    6986 +       if(obj->variantType == YAFFS_OBJECT_TYPE_FILE)
    6987 +               cp->fileSizeOrEquivalentObjectId = obj->variant.fileVariant.fileSize;
    6988 +       else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK)
    6989 +               cp->fileSizeOrEquivalentObjectId = obj->variant.hardLinkVariant.equivalentObjectId;
    6990 +}
    6991 +
    6992 +static void yaffs_CheckpointObjectToObject( yaffs_Object *obj,yaffs_CheckpointObject *cp)
    6993 +{
    6994 +
    6995 +       yaffs_Object *parent;
    6996 +       
    6997 +       obj->objectId = cp->objectId;
    6998 +       
    6999 +       if(cp->parentId)
    7000 +               parent = yaffs_FindOrCreateObjectByNumber(
    7001 +                                       obj->myDev,
    7002 +                                       cp->parentId,
    7003 +                                       YAFFS_OBJECT_TYPE_DIRECTORY);
    7004 +       else
    7005 +               parent = NULL;
    7006 +               
    7007 +       if(parent)
    7008 +               yaffs_AddObjectToDirectory(parent, obj);
    7009 +               
    7010 +       obj->chunkId = cp->chunkId;
    7011 +       obj->variantType = cp->variantType;                     
    7012 +       obj->deleted = cp->deleted;
    7013 +       obj->softDeleted = cp->softDeleted;
    7014 +       obj->unlinked = cp->unlinked;
    7015 +       obj->fake = cp->fake;
    7016 +       obj->renameAllowed = cp->renameAllowed;
    7017 +       obj->unlinkAllowed = cp->unlinkAllowed;
    7018 +       obj->serial = cp->serial;
    7019 +       obj->nDataChunks = cp->nDataChunks;
    7020 +       
    7021 +       if(obj->variantType == YAFFS_OBJECT_TYPE_FILE)
    7022 +               obj->variant.fileVariant.fileSize = cp->fileSizeOrEquivalentObjectId;
    7023 +       else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK)
    7024 +               obj->variant.hardLinkVariant.equivalentObjectId = cp->fileSizeOrEquivalentObjectId;
    7025 +               
    7026 +       if(obj->objectId >= YAFFS_NOBJECT_BUCKETS)
    7027 +               obj->lazyLoaded = 1;
    7028 +}
    7029 +
    7030 +
    7031 +
    7032 +static int yaffs_CheckpointTnodeWorker(yaffs_Object * in, yaffs_Tnode * tn,
    7033 +                                       __u32 level, int chunkOffset)
    7034 +{
    7035 +       int i;
    7036 +       yaffs_Device *dev = in->myDev;
    7037 +       int ok = 1;
    7038 +       int nTnodeBytes = (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8;
    7039 +
    7040 +       if (tn) {
    7041 +               if (level > 0) {
    7042 +
    7043 +                       for (i = 0; i < YAFFS_NTNODES_INTERNAL && ok; i++){
    7044 +                               if (tn->internal[i]) {
    7045 +                                       ok = yaffs_CheckpointTnodeWorker(in,
    7046 +                                                       tn->internal[i],
    7047 +                                                       level - 1,
    7048 +                                                       (chunkOffset<<YAFFS_TNODES_INTERNAL_BITS) + i);
    7049 +                               }
    7050 +                       }
    7051 +               } else if (level == 0) {
    7052 +                       __u32 baseOffset = chunkOffset <<  YAFFS_TNODES_LEVEL0_BITS;
    7053 +                       /* printf("write tnode at %d\n",baseOffset); */
    7054 +                       ok = (yaffs_CheckpointWrite(dev,&baseOffset,sizeof(baseOffset)) == sizeof(baseOffset));
    7055 +                       if(ok)
    7056 +                               ok = (yaffs_CheckpointWrite(dev,tn,nTnodeBytes) == nTnodeBytes);
    7057 +               }
    7058 +       }
    7059 +
    7060 +       return ok;
    7061 +
    7062 +}
    7063 +
    7064 +static int yaffs_WriteCheckpointTnodes(yaffs_Object *obj)
    7065 +{
    7066 +       __u32 endMarker = ~0;
    7067 +       int ok = 1;
    7068 +       
    7069 +       if(obj->variantType == YAFFS_OBJECT_TYPE_FILE){
    7070 +               ok = yaffs_CheckpointTnodeWorker(obj,
    7071 +                                           obj->variant.fileVariant.top,
    7072 +                                           obj->variant.fileVariant.topLevel,
    7073 +                                           0);
    7074 +               if(ok)
    7075 +                       ok = (yaffs_CheckpointWrite(obj->myDev,&endMarker,sizeof(endMarker)) ==
    7076 +                               sizeof(endMarker));
    7077 +       }
    7078 +       
    7079 +       return ok ? 1 : 0;
    7080 +}
    7081 +
    7082 +static int yaffs_ReadCheckpointTnodes(yaffs_Object *obj)
    7083 +{
    7084 +       __u32 baseChunk;
    7085 +       int ok = 1;
    7086 +       yaffs_Device *dev = obj->myDev;
    7087 +       yaffs_FileStructure *fileStructPtr = &obj->variant.fileVariant;
    7088 +       yaffs_Tnode *tn;
    7089 +       
    7090 +       ok = (yaffs_CheckpointRead(dev,&baseChunk,sizeof(baseChunk)) == sizeof(baseChunk));
    7091 +       
    7092 +       while(ok && (~baseChunk)){
    7093 +               /* Read level 0 tnode */
    7094 +               
    7095 +               /* printf("read  tnode at %d\n",baseChunk); */
    7096 +               tn = yaffs_GetTnodeRaw(dev);
    7097 +               if(tn)
    7098 +                       ok = (yaffs_CheckpointRead(dev,tn,(dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8) ==
    7099 +                             (dev->tnodeWidth * YAFFS_NTNODES_LEVEL0)/8);
    7100 +               else
    7101 +                       ok = 0;
    7102 +                       
    7103 +               if(tn && ok){
    7104 +                       ok = yaffs_AddOrFindLevel0Tnode(dev,
    7105 +                                                       fileStructPtr,
    7106 +                                                       baseChunk,
    7107 +                                                       tn) ? 1 : 0;
    7108 +               }
    7109 +                       
    7110 +               if(ok)
    7111 +                       ok = (yaffs_CheckpointRead(dev,&baseChunk,sizeof(baseChunk)) == sizeof(baseChunk));
    7112 +               
    7113 +       }
    7114 +
    7115 +       return ok ? 1 : 0;     
    7116 +}
    7117 +
    7118 +
    7119 +static int yaffs_WriteCheckpointObjects(yaffs_Device *dev)
    7120 +{
    7121 +       yaffs_Object *obj;
    7122 +       yaffs_CheckpointObject cp;
    7123 +       int i;
    7124 +       int ok = 1;
    7125 +       struct list_head *lh;
    7126 +
    7127 +       
    7128 +       /* Iterate through the objects in each hash entry,
    7129 +        * dumping them to the checkpointing stream.
    7130 +        */
    7131 +       
    7132 +        for(i = 0; ok &&  i <  YAFFS_NOBJECT_BUCKETS; i++){
    7133 +               list_for_each(lh, &dev->objectBucket[i].list) {
    7134 +                       if (lh) {
    7135 +                               obj = list_entry(lh, yaffs_Object, hashLink);
    7136 +                               if (!obj->deferedFree) {
    7137 +                                       yaffs_ObjectToCheckpointObject(&cp,obj);
    7138 +                                       cp.structType = sizeof(cp);
    7139 +
    7140 +                                       T(YAFFS_TRACE_CHECKPOINT,(
    7141 +                                               TSTR("Checkpoint write object %d parent %d type %d chunk %d obj addr %x" TENDSTR),
    7142 +                                               cp.objectId,cp.parentId,cp.variantType,cp.chunkId,(unsigned) obj));
    7143 +                                               
    7144 +                                       ok = (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp));
    7145 +                                       
    7146 +                                       if(ok && obj->variantType == YAFFS_OBJECT_TYPE_FILE){
    7147 +                                               ok = yaffs_WriteCheckpointTnodes(obj);
    7148 +                                       }
    7149 +                               }
    7150 +                       }
    7151 +               }
    7152 +        }
    7153 +       
    7154 +        /* Dump end of list */
    7155 +       memset(&cp,0xFF,sizeof(yaffs_CheckpointObject));
    7156 +       cp.structType = sizeof(cp);
    7157 +       
    7158 +       if(ok)
    7159 +               ok = (yaffs_CheckpointWrite(dev,&cp,sizeof(cp)) == sizeof(cp));
    7160 +               
    7161 +       return ok ? 1 : 0;
    7162 +}
    7163 +
    7164 +static int yaffs_ReadCheckpointObjects(yaffs_Device *dev)
    7165 +{
    7166 +       yaffs_Object *obj;
    7167 +       yaffs_CheckpointObject cp;
    7168 +       int ok = 1;
    7169 +       int done = 0;
    7170 +       yaffs_Object *hardList = NULL;
    7171 +       
    7172 +       while(ok && !done) {
    7173 +               ok = (yaffs_CheckpointRead(dev,&cp,sizeof(cp)) == sizeof(cp));
    7174 +               if(cp.structType != sizeof(cp)) {
    7175 +                       /* printf("structure parsing failed\n"); */
    7176 +                       ok = 0;
    7177 +               }
    7178 +                       
    7179 +               if(ok && cp.objectId == ~0)
    7180 +                       done = 1;
    7181 +               else if(ok){
    7182 +                       obj = yaffs_FindOrCreateObjectByNumber(dev,cp.objectId, cp.variantType);
    7183 +                       T(YAFFS_TRACE_CHECKPOINT,(TSTR("Checkpoint read object %d parent %d type %d chunk %d obj addr %x" TENDSTR),
    7184 +                               cp.objectId,cp.parentId,cp.variantType,cp.chunkId,(unsigned) obj));
    7185 +                       if(obj) {
    7186 +                               yaffs_CheckpointObjectToObject(obj,&cp);
    7187 +                               if(obj->variantType == YAFFS_OBJECT_TYPE_FILE) {
    7188 +                                       ok = yaffs_ReadCheckpointTnodes(obj);
    7189 +                               } else if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) {
    7190 +                                       obj->hardLinks.next =
    7191 +                                                   (struct list_head *)
    7192 +                                                   hardList;
    7193 +                                       hardList = obj;
    7194 +                               }
    7195 +                         
    7196 +                       }
    7197 +               }
    7198 +       }
    7199 +       
    7200 +       if(ok)
    7201 +               yaffs_HardlinkFixup(dev,hardList);
    7202 +       
    7203 +       return ok ? 1 : 0;
    7204 +}
    7205 +
    7206 +static int yaffs_WriteCheckpointData(yaffs_Device *dev)
    7207 +{
    7208 +
    7209 +       int ok;
    7210 +       
    7211 +       ok = yaffs_CheckpointOpen(dev,1);
    7212 +       
    7213 +       if(ok)
    7214 +               ok = yaffs_WriteCheckpointValidityMarker(dev,1);
    7215 +       if(ok)
    7216 +               ok = yaffs_WriteCheckpointDevice(dev);
    7217 +       if(ok)
    7218 +               ok = yaffs_WriteCheckpointObjects(dev);
    7219 +       if(ok)
    7220 +               ok = yaffs_WriteCheckpointValidityMarker(dev,0);
    7221 +               
    7222 +       if(!yaffs_CheckpointClose(dev))
    7223 +                ok = 0;
    7224 +               
    7225 +       if(ok)
    7226 +               dev->isCheckpointed = 1;
    7227 +        else
    7228 +               dev->isCheckpointed = 0;
    7229 +
    7230 +       return dev->isCheckpointed;
    7231 +}
    7232 +
    7233 +static int yaffs_ReadCheckpointData(yaffs_Device *dev)
    7234 +{
    7235 +       int ok;
    7236 +       
    7237 +       ok = yaffs_CheckpointOpen(dev,0); /* open for read */
    7238 +       
    7239 +       if(ok)
    7240 +               ok = yaffs_ReadCheckpointValidityMarker(dev,1);
    7241 +       if(ok)
    7242 +               ok = yaffs_ReadCheckpointDevice(dev);
    7243 +       if(ok)
    7244 +               ok = yaffs_ReadCheckpointObjects(dev);
    7245 +       if(ok)
    7246 +               ok = yaffs_ReadCheckpointValidityMarker(dev,0);
    7247 +               
    7248 +
    7249 +
    7250 +       if(!yaffs_CheckpointClose(dev))
    7251 +               ok = 0;
    7252 +
    7253 +       if(ok)
    7254 +               dev->isCheckpointed = 1;
    7255 +        else
    7256 +               dev->isCheckpointed = 0;
    7257 +
    7258 +       return ok ? 1 : 0;
    7259 +
    7260 +}
    7261 +
    7262 +static void yaffs_InvalidateCheckpoint(yaffs_Device *dev)
    7263 +{
    7264 +       if(dev->isCheckpointed ||
    7265 +          dev->blocksInCheckpoint > 0){
    7266 +               dev->isCheckpointed = 0;
    7267 +               yaffs_CheckpointInvalidateStream(dev);
    7268 +               if(dev->superBlock && dev->markSuperBlockDirty)
    7269 +                       dev->markSuperBlockDirty(dev->superBlock);
    7270 +       }
    7271 +}
    7272 +
    7273 +
    7274 +int yaffs_CheckpointSave(yaffs_Device *dev)
    7275 +{
    7276 +       yaffs_ReportOddballBlocks(dev);
    7277 +       T(YAFFS_TRACE_CHECKPOINT,(TSTR("save entry: isCheckpointed %d"TENDSTR),dev->isCheckpointed));
    7278 +
    7279 +       if(!dev->isCheckpointed)
    7280 +               yaffs_WriteCheckpointData(dev);
    7281 +       
    7282 +       T(YAFFS_TRACE_CHECKPOINT,(TSTR("save exit: isCheckpointed %d"TENDSTR),dev->isCheckpointed));
    7283 +
    7284 +       return dev->isCheckpointed;
    7285 +}
    7286 +
    7287 +int yaffs_CheckpointRestore(yaffs_Device *dev)
    7288 +{
    7289 +       int retval;
    7290 +       T(YAFFS_TRACE_CHECKPOINT,(TSTR("restore entry: isCheckpointed %d"TENDSTR),dev->isCheckpointed));
    7291 +       
    7292 +       retval = yaffs_ReadCheckpointData(dev);
    7293 +
    7294 +       T(YAFFS_TRACE_CHECKPOINT,(TSTR("restore exit: isCheckpointed %d"TENDSTR),dev->isCheckpointed));
    7295 +       
    7296 +       yaffs_ReportOddballBlocks(dev);
    7297 +       
    7298 +       return retval;
    7299 +}
    7300 +
    7301 +/*--------------------- File read/write ------------------------
    7302 + * Read and write have very similar structures.
    7303 + * In general the read/write has three parts to it
    7304 + * An incomplete chunk to start with (if the read/write is not chunk-aligned)
    7305 + * Some complete chunks
    7306 + * An incomplete chunk to end off with
    7307 + *
    7308 + * Curve-balls: the first chunk might also be the last chunk.
    7309 + */
    7310 +
    7311 +int yaffs_ReadDataFromFile(yaffs_Object * in, __u8 * buffer, loff_t offset,
    7312 +                          int nBytes)
    7313 +{
    7314 +
     6122+
     6123+
     6124+
     6125+
     6126+///////////////////////// File read/write ///////////////////////////////
     6127+// Read and write have very similar structures.
     6128+// In general the read/write has three parts to it
     6129+// * An incomplete chunk to start with (if the read/write is not chunk-aligned)
     6130+// * Some complete chunks
     6131+// * An incomplete chunk to end off with
     6132+//
     6133+// Curve-balls: the first chunk might also be the last chunk.
     6134+
     6135+int yaffs_ReadDataFromFile(yaffs_Object *in, __u8 * buffer, __u32 offset, int nBytes)
     6136+{
     6137+       
     6138+       
    73156139+       int chunk;
    73166140+       int start;
     
    73196143+       int nDone = 0;
    73206144+       yaffs_ChunkCache *cache;
    7321 +
     6145+       
    73226146+       yaffs_Device *dev;
    7323 +
     6147+       
    73246148+       dev = in->myDev;
    7325 +
    7326 +       while (n > 0) {
    7327 +               //chunk = offset / dev->nDataBytesPerChunk + 1;
    7328 +               //start = offset % dev->nDataBytesPerChunk;
    7329 +               yaffs_AddrToChunk(dev,offset,&chunk,&start);
    7330 +               chunk++;
    7331 +
    7332 +               /* OK now check for the curveball where the start and end are in
    7333 +                * the same chunk.     
    7334 +                */
    7335 +               if ((start + n) < dev->nDataBytesPerChunk) {
     6149+       
     6150+       while(n > 0)
     6151+       {
     6152+               chunk = offset / dev->nBytesPerChunk + 1; // The first chunk is 1
     6153+               start = offset % dev->nBytesPerChunk;
     6154+
     6155+               // OK now check for the curveball where the start and end are in
     6156+               // the same chunk.     
     6157+               if(     (start + n) < dev->nBytesPerChunk)
     6158+               {
    73366159+                       nToCopy = n;
    7337 +               } else {
    7338 +                       nToCopy = dev->nDataBytesPerChunk - start;
    7339 +               }
    7340 +
    7341 +               cache = yaffs_FindChunkCache(in, chunk);
    7342 +
    7343 +               /* If the chunk is already in the cache or it is less than a whole chunk
    7344 +                * then use the cache (if there is caching)
    7345 +                * else bypass the cache.
    7346 +                */
    7347 +               if (cache || nToCopy != dev->nDataBytesPerChunk) {
    7348 +                       if (dev->nShortOpCaches > 0) {
    7349 +
    7350 +                               /* If we can't find the data in the cache, then load it up. */
    7351 +
    7352 +                               if (!cache) {
     6160+               }
     6161+               else
     6162+               {
     6163+                       nToCopy = dev->nBytesPerChunk - start;
     6164+               }
     6165+       
     6166+               cache = yaffs_FindChunkCache(in,chunk);
     6167+               
     6168+               // If the chunk is already in the cache or it is less than a whole chunk
     6169+               // then use the cache (if there is caching)
     6170+               // else bypass the cache.
     6171+               if( cache || nToCopy != dev->nBytesPerChunk)
     6172+               {
     6173+                       if(dev->nShortOpCaches > 0)
     6174+                       {
     6175+                               
     6176+                               // If we can't find the data in the cache, then load it up.
     6177+                               
     6178+                               if(!cache)
     6179+                               {
    73536180+                                       cache = yaffs_GrabChunkCache(in->myDev);
    73546181+                                       cache->object = in;
     
    73566183+                                       cache->dirty = 0;
    73576184+                                       cache->locked = 0;
    7358 +                                       yaffs_ReadChunkDataFromObject(in, chunk,
    7359 +                                                                     cache->
    7360 +                                                                     data);
    7361 +                                       cache->nBytes = 0;
     6185+                                       yaffs_ReadChunkDataFromObject(in,chunk,cache->data);
     6186+                                       cache->nBytes = 0;     
    73626187+                               }
    7363 +
    7364 +                               yaffs_UseChunkCache(dev, cache, 0);
     6188+                       
     6189+                               yaffs_UseChunkCache(dev,cache,0);
    73656190+
    73666191+                               cache->locked = 1;
     
    73696194+                               yfsd_UnlockYAFFS(TRUE);
    73706195+#endif
    7371 +                               memcpy(buffer, &cache->data[start], nToCopy);
     6196+                               memcpy(buffer,&cache->data[start],nToCopy);
    73726197+
    73736198+#ifdef CONFIG_YAFFS_WINCE
     
    73756200+#endif
    73766201+                               cache->locked = 0;
    7377 +                       } else {
    7378 +                               /* Read into the local buffer then copy..*/
    7379 +
    7380 +                               __u8 *localBuffer =
    7381 +                                   yaffs_GetTempBuffer(dev, __LINE__);
    7382 +                               yaffs_ReadChunkDataFromObject(in, chunk,
    7383 +                                                             localBuffer);
     6202+                       }
     6203+                       else
     6204+                       {
     6205+                               // Read into the local buffer then copy...
     6206+                               
     6207+                               __u8 *localBuffer = yaffs_GetTempBuffer(dev,__LINE__);
     6208+                               yaffs_ReadChunkDataFromObject(in,chunk,localBuffer);           
    73846209+#ifdef CONFIG_YAFFS_WINCE
    73856210+                               yfsd_UnlockYAFFS(TRUE);
    73866211+#endif
    7387 +                               memcpy(buffer, &localBuffer[start], nToCopy);
     6212+                               memcpy(buffer,&localBuffer[start],nToCopy);
    73886213+
    73896214+#ifdef CONFIG_YAFFS_WINCE
    73906215+                               yfsd_LockYAFFS(TRUE);
    73916216+#endif
    7392 +                               yaffs_ReleaseTempBuffer(dev, localBuffer,
    7393 +                                                       __LINE__);
     6217+                               yaffs_ReleaseTempBuffer(dev,localBuffer,__LINE__);
    73946218+                       }
    73956219+
    7396 +               } else {
     6220+               }
     6221+               else
     6222+               {
    73976223+#ifdef CONFIG_YAFFS_WINCE
    7398 +                       __u8 *localBuffer = yaffs_GetTempBuffer(dev, __LINE__);
    7399 +
    7400 +                       /* Under WinCE can't do direct transfer. Need to use a local buffer.
    7401 +                        * This is because we otherwise screw up WinCE's memory mapper
    7402 +                        */
    7403 +                       yaffs_ReadChunkDataFromObject(in, chunk, localBuffer);
     6224+                       __u8 *localBuffer = yaffs_GetTempBuffer(dev,__LINE__);
     6225+                       
     6226+                       // Under WinCE can't do direct transfer. Need to use a local buffer.
     6227+                       // This is because we otherwise screw up WinCE's memory mapper
     6228+                       yaffs_ReadChunkDataFromObject(in,chunk,localBuffer);
    74046229+
    74056230+#ifdef CONFIG_YAFFS_WINCE
    7406 +                       yfsd_UnlockYAFFS(TRUE);
    7407 +#endif
    7408 +                       memcpy(buffer, localBuffer, dev->nDataBytesPerChunk);
     6231+                               yfsd_UnlockYAFFS(TRUE);
     6232+#endif
     6233+                       memcpy(buffer,localBuffer,dev->nBytesPerChunk);
    74096234+
    74106235+#ifdef CONFIG_YAFFS_WINCE
    7411 +                       yfsd_LockYAFFS(TRUE);
    7412 +                       yaffs_ReleaseTempBuffer(dev, localBuffer, __LINE__);
     6236+                               yfsd_LockYAFFS(TRUE);
     6237+                               yaffs_ReleaseTempBuffer(dev,localBuffer,__LINE__);
    74136238+#endif
    74146239+
    74156240+#else
    7416 +                       /* A full chunk. Read directly into the supplied buffer. */
    7417 +                       yaffs_ReadChunkDataFromObject(in, chunk, buffer);
    7418 +#endif
    7419 +               }
    7420 +
     6241+                       // A full chunk. Read directly into the supplied buffer.
     6242+                       yaffs_ReadChunkDataFromObject(in,chunk,buffer);
     6243+#endif
     6244+               }
     6245+               
    74216246+               n -= nToCopy;
    74226247+               offset += nToCopy;
    74236248+               buffer += nToCopy;
    74246249+               nDone += nToCopy;
    7425 +
    7426 +       }
    7427 +
     6250+               
     6251+       }
     6252+       
    74286253+       return nDone;
    74296254+}
    74306255+
    7431 +int yaffs_WriteDataToFile(yaffs_Object * in, const __u8 * buffer, loff_t offset,
    7432 +                         int nBytes, int writeThrough)
    7433 +{
    7434 +
     6256+
     6257+
     6258+int yaffs_WriteDataToFile(yaffs_Object *in,const __u8 * buffer, __u32 offset, int nBytes, int writeThrough)
     6259+{     
     6260+       
    74356261+       int chunk;
    74366262+       int start;
     
    74426268+       int chunkWritten = 0;
    74436269+       int nBytesRead;
    7444 +
     6270+       
    74456271+       yaffs_Device *dev;
    7446 +
     6272+       
    74476273+       dev = in->myDev;
    7448 +
    7449 +       while (n > 0 && chunkWritten >= 0) {
    7450 +               //chunk = offset / dev->nDataBytesPerChunk + 1;
    7451 +               //start = offset % dev->nDataBytesPerChunk;
    7452 +               yaffs_AddrToChunk(dev,offset,&chunk,&start);
    7453 +               chunk++;
    7454 +
    7455 +               /* OK now check for the curveball where the start and end are in
    7456 +                * the same chunk.
    7457 +                */
    7458 +
    7459 +               if ((start + n) < dev->nDataBytesPerChunk) {
     6274+       
     6275+       
     6276+       while(n > 0 && chunkWritten >= 0)
     6277+       {
     6278+               chunk = offset / dev->nBytesPerChunk + 1;
     6279+               start = offset % dev->nBytesPerChunk;
     6280+               
     6281+
     6282+               // OK now check for the curveball where the start and end are in
     6283+               // the same chunk.
     6284+               
     6285+               if((start + n) < dev->nBytesPerChunk)
     6286+               {
    74606287+                       nToCopy = n;
    7461 +
    7462 +                       /* Now folks, to calculate how many bytes to write back....
    7463 +                        * If we're overwriting and not writing to then end of file then
    7464 +                        * we need to write back as much as was there before.
    7465 +                        */
    7466 +
    7467 +                       nBytesRead =
    7468 +                           in->variant.fileVariant.fileSize -
    7469 +                           ((chunk - 1) * dev->nDataBytesPerChunk);
    7470 +
    7471 +                       if (nBytesRead > dev->nDataBytesPerChunk) {
    7472 +                               nBytesRead = dev->nDataBytesPerChunk;
     6288+                       
     6289+                       // Now folks, to calculate how many bytes to write back....
     6290+                       // If we're overwriting and not writing to then end of file then
     6291+                       // we need to write back as much as was there before.
     6292+                       
     6293+                       nBytesRead = in->variant.fileVariant.fileSize - ((chunk -1) * dev->nBytesPerChunk);
     6294+                       
     6295+                       if(nBytesRead > dev->nBytesPerChunk)
     6296+                       {
     6297+                               nBytesRead = dev->nBytesPerChunk;
    74736298+                       }
    7474 +
    7475 +                       nToWriteBack =
    7476 +                           (nBytesRead >
    7477 +                            (start + n)) ? nBytesRead : (start + n);
    7478 +
    7479 +               } else {
    7480 +                       nToCopy = dev->nDataBytesPerChunk - start;
    7481 +                       nToWriteBack = dev->nDataBytesPerChunk;
    7482 +               }
    7483 +
    7484 +               if (nToCopy != dev->nDataBytesPerChunk) {
    7485 +                       /* An incomplete start or end chunk (or maybe both start and end chunk) */
    7486 +                       if (dev->nShortOpCaches > 0) {
     6299+                       
     6300+                       nToWriteBack = (nBytesRead > (start + n)) ? nBytesRead : (start +n);
     6301+                       
     6302+               }
     6303+               else
     6304+               {
     6305+                       nToCopy = dev->nBytesPerChunk - start;
     6306+                       nToWriteBack = dev->nBytesPerChunk;
     6307+               }
     6308+       
     6309+               if(nToCopy != dev->nBytesPerChunk)
     6310+               {
     6311+                       // An incomplete start or end chunk (or maybe both start and end chunk)
     6312+                       if(dev->nShortOpCaches > 0)
     6313+                          {
    74876314+                               yaffs_ChunkCache *cache;
    7488 +                               /* If we can't find the data in the cache, then load the cache */
    7489 +                               cache = yaffs_FindChunkCache(in, chunk);
    7490 +                               
    7491 +                               if (!cache
    7492 +                                   && yaffs_CheckSpaceForAllocation(in->
    7493 +                                                                    myDev)) {
     6315+                               // If we can't find the data in the cache, then load it up.
     6316+                               cache = yaffs_FindChunkCache(in,chunk);
     6317+                               if(!cache && yaffs_CheckSpaceForAllocation(in->myDev))
     6318+                               {
    74946319+                                       cache = yaffs_GrabChunkCache(in->myDev);
    74956320+                                       cache->object = in;
     
    74976322+                                       cache->dirty = 0;
    74986323+                                       cache->locked = 0;
    7499 +                                       yaffs_ReadChunkDataFromObject(in, chunk,
    7500 +                                                                     cache->
    7501 +                                                                     data);
     6324+                                       yaffs_ReadChunkDataFromObject(in,chunk,cache->data);           
    75026325+                               }
    7503 +                               else if(cache &&
    7504 +                                       !cache->dirty &&
    7505 +                                       !yaffs_CheckSpaceForAllocation(in->myDev)){
    7506 +                                       /* Drop the cache if it was a read cache item and
    7507 +                                        * no space check has been made for it.
    7508 +                                        */
    7509 +                                        cache = NULL;
    7510 +                               }
    7511 +
    7512 +                               if (cache) {
    7513 +                                       yaffs_UseChunkCache(dev, cache, 1);
     6326+                       
     6327+                               if(cache)
     6328+                               {       
     6329+                                       yaffs_UseChunkCache(dev,cache,1);
    75146330+                                       cache->locked = 1;
    75156331+#ifdef CONFIG_YAFFS_WINCE
    7516 +                                       yfsd_UnlockYAFFS(TRUE);
    7517 +#endif
    7518 +
    7519 +                                       memcpy(&cache->data[start], buffer,
    7520 +                                              nToCopy);
     6332+                               yfsd_UnlockYAFFS(TRUE);
     6333+#endif
     6334+       
     6335+                                       memcpy(&cache->data[start],buffer,nToCopy);
    75216336+
    75226337+#ifdef CONFIG_YAFFS_WINCE
    7523 +                                       yfsd_LockYAFFS(TRUE);
     6338+                               yfsd_LockYAFFS(TRUE);
    75246339+#endif
    75256340+                                       cache->locked = 0;
    75266341+                                       cache->nBytes = nToWriteBack;
    7527 +
    7528 +                                       if (writeThrough) {
    7529 +                                               chunkWritten =
    7530 +                                                   yaffs_WriteChunkDataToObject
    7531 +                                                   (cache->object,
    7532 +                                                    cache->chunkId,
    7533 +                                                    cache->data, cache->nBytes,
    7534 +                                                    1);
     6342+                                       
     6343+                                       if(writeThrough)
     6344+                                       {
     6345+                                               chunkWritten = yaffs_WriteChunkDataToObject(cache->object,
     6346+                                                                                           cache->chunkId,
     6347+                                                                                           cache->data,
     6348+                                                                                           cache->nBytes,1);
    75356349+                                               cache->dirty = 0;
    75366350+                                       }
    75376351+
    7538 +                               } else {
    7539 +                                       chunkWritten = -1;      /* fail the write */
    75406352+                               }
    7541 +                       } else {
    7542 +                               /* An incomplete start or end chunk (or maybe both start and end chunk)
    7543 +                                * Read into the local buffer then copy, then copy over and write back.
    7544 +                                */
    7545 +
    7546 +                               __u8 *localBuffer =
    7547 +                                   yaffs_GetTempBuffer(dev, __LINE__);
    7548 +
    7549 +                               yaffs_ReadChunkDataFromObject(in, chunk,
    7550 +                                                             localBuffer);
    7551 +
     6353+                               else
     6354+                               {
     6355+                                       chunkWritten = -1; // fail the write
     6356+                               }
     6357+                       }
     6358+                       else
     6359+                       {
     6360+                               // An incomplete start or end chunk (or maybe both start and end chunk)
     6361+                               // Read into the local buffer then copy, then copy over and write back.
     6362+                               
     6363+                               __u8 *localBuffer = yaffs_GetTempBuffer(dev,__LINE__);
     6364+               
     6365+                               yaffs_ReadChunkDataFromObject(in,chunk,localBuffer);
     6366+                               
    75526367+#ifdef CONFIG_YAFFS_WINCE
    75536368+                               yfsd_UnlockYAFFS(TRUE);
    75546369+#endif
    7555 +
    7556 +                               memcpy(&localBuffer[start], buffer, nToCopy);
    7557 +
     6370+                                       
     6371+                               memcpy(&localBuffer[start],buffer,nToCopy);
     6372+                       
    75586373+#ifdef CONFIG_YAFFS_WINCE
    75596374+                               yfsd_LockYAFFS(TRUE);
    75606375+#endif
    7561 +                               chunkWritten =
    7562 +                                   yaffs_WriteChunkDataToObject(in, chunk,
    7563 +                                                                localBuffer,
    7564 +                                                                nToWriteBack,
    7565 +                                                                0);
    7566 +
    7567 +                               yaffs_ReleaseTempBuffer(dev, localBuffer,
    7568 +                                                       __LINE__);
    7569 +
     6376+                               chunkWritten = yaffs_WriteChunkDataToObject(in,chunk,localBuffer,nToWriteBack,0);
     6377+                               
     6378+                               yaffs_ReleaseTempBuffer(dev,localBuffer,__LINE__);
     6379+                       
     6380+                               //T(("Write with readback to chunk %d %d  start %d  copied %d wrote back %d\n",chunk,chunkWritten,start, nToCopy, nToWriteBack));
    75706381+                       }
    7571 +
    7572 +               } else {
    7573 +
     6382+                       
     6383+               }
     6384+               else
     6385+               {
     6386+                       
    75746387+#ifdef CONFIG_YAFFS_WINCE
    7575 +                       /* Under WinCE can't do direct transfer. Need to use a local buffer.
    7576 +                        * This is because we otherwise screw up WinCE's memory mapper
    7577 +                        */
    7578 +                       __u8 *localBuffer = yaffs_GetTempBuffer(dev, __LINE__);
     6388+                       // Under WinCE can't do direct transfer. Need to use a local buffer.
     6389+                       // This is because we otherwise screw up WinCE's memory mapper
     6390+                               __u8 *localBuffer = yaffs_GetTempBuffer(dev,__LINE__);
    75796391+#ifdef CONFIG_YAFFS_WINCE
    7580 +                       yfsd_UnlockYAFFS(TRUE);
    7581 +#endif
    7582 +                       memcpy(localBuffer, buffer, dev->nDataBytesPerChunk);
     6392+                               yfsd_UnlockYAFFS(TRUE);
     6393+#endif
     6394+                       memcpy(localBuffer,buffer,dev->nBytesPerChunk);
    75836395+#ifdef CONFIG_YAFFS_WINCE
    7584 +                       yfsd_LockYAFFS(TRUE);
    7585 +#endif
    7586 +                       chunkWritten =
    7587 +                           yaffs_WriteChunkDataToObject(in, chunk, localBuffer,
    7588 +                                                        dev->nDataBytesPerChunk,
    7589 +                                                        0);
    7590 +                       yaffs_ReleaseTempBuffer(dev, localBuffer, __LINE__);
     6396+                               yfsd_LockYAFFS(TRUE);
     6397+#endif
     6398+                       chunkWritten = yaffs_WriteChunkDataToObject(in,chunk,localBuffer,dev->nBytesPerChunk,0);
     6399+                       yaffs_ReleaseTempBuffer(dev,localBuffer,__LINE__);
    75916400+#else
    7592 +                       /* A full chunk. Write directly from the supplied buffer. */
    7593 +                       chunkWritten =
    7594 +                           yaffs_WriteChunkDataToObject(in, chunk, buffer,
    7595 +                                                        dev->nDataBytesPerChunk,
    7596 +                                                        0);
    7597 +#endif
    7598 +                       /* Since we've overwritten the cached data, we better invalidate it. */
    7599 +                       yaffs_InvalidateChunkCache(in, chunk);
    7600 +               }
    7601 +
    7602 +               if (chunkWritten >= 0) {
     6401+                       // A full chunk. Write directly from the supplied buffer.
     6402+                       chunkWritten = yaffs_WriteChunkDataToObject(in,chunk,buffer,dev->nBytesPerChunk,0);
     6403+#endif
     6404+                       // Since we've overwritten the cached data, we better invalidate it.
     6405+                       yaffs_InvalidateChunkCache(in,chunk);
     6406+                       //T(("Write to chunk %d %d\n",chunk,chunkWritten));
     6407+               }
     6408+               
     6409+               if(chunkWritten >= 0)
     6410+               {
    76036411+                       n -= nToCopy;
    76046412+                       offset += nToCopy;
     
    76066414+                       nDone += nToCopy;
    76076415+               }
    7608 +
    7609 +       }
    7610 +
    7611 +       /* Update file object */
    7612 +
    7613 +       if ((startOfWrite + nDone) > in->variant.fileVariant.fileSize) {
     6416+               
     6417+       }
     6418+       
     6419+       // Update file object
     6420+       
     6421+       if((startOfWrite + nDone) > in->variant.fileVariant.fileSize)
     6422+       {
    76146423+               in->variant.fileVariant.fileSize = (startOfWrite + nDone);
    76156424+       }
    7616 +
     6425+       
    76176426+       in->dirty = 1;
    7618 +
     6427+       
    76196428+       return nDone;
    76206429+}
    76216430+
    7622 +
    7623 +/* ---------------------- File resizing stuff ------------------ */
    7624 +
    7625 +static void yaffs_PruneResizedChunks(yaffs_Object * in, int newSize)
     6431+static void yaffs_PruneResizedChunks(yaffs_Object *in, int newSize)
    76266432+{
    76276433+
     
    76296435+       int oldFileSize = in->variant.fileVariant.fileSize;
    76306436+
    7631 +       int lastDel = 1 + (oldFileSize - 1) / dev->nDataBytesPerChunk;
    7632 +
    7633 +       int startDel = 1 + (newSize + dev->nDataBytesPerChunk - 1) /
    7634 +           dev->nDataBytesPerChunk;
     6437+       
     6438+       int lastDel = 1 + (oldFileSize-1)/dev->nBytesPerChunk;
     6439+               
     6440+       int startDel = 1 + (newSize + dev->nBytesPerChunk - 1)/
     6441+                                               dev->nBytesPerChunk;
    76356442+       int i;
    76366443+       int chunkId;
    76376444+
    7638 +       /* Delete backwards so that we don't end up with holes if
    7639 +        * power is lost part-way through the operation.
    7640 +        */
    7641 +       for (i = lastDel; i >= startDel; i--) {
    7642 +               /* NB this could be optimised somewhat,
    7643 +                * eg. could retrieve the tags and write them without
    7644 +                * using yaffs_DeleteChunk
    7645 +                */
    7646 +
    7647 +               chunkId = yaffs_FindAndDeleteChunkInFile(in, i, NULL);
    7648 +               if (chunkId > 0) {
    7649 +                       if (chunkId <
    7650 +                           (dev->internalStartBlock * dev->nChunksPerBlock)
    7651 +                           || chunkId >=
    7652 +                           ((dev->internalEndBlock +
    7653 +                             1) * dev->nChunksPerBlock)) {
    7654 +                               T(YAFFS_TRACE_ALWAYS,
    7655 +                                 (TSTR("Found daft chunkId %d for %d" TENDSTR),
    7656 +                                  chunkId, i));
    7657 +                       } else {
     6445+       // Delete backwards so that we don't end up with holes if
     6446+       // power is lost part-way through the operation.
     6447+       for(i = lastDel; i >= startDel; i--)
     6448+       {
     6449+               // NB this could be optimised somewhat,
     6450+               // eg. could retrieve the tags and write them without
     6451+               // using yaffs_DeleteChunk
     6452+
     6453+               chunkId = yaffs_FindAndDeleteChunkInFile(in,i,NULL);
     6454+               if(chunkId > 0)
     6455+               {
     6456+                       if(chunkId < (dev->internalStartBlock * dev->nChunksPerBlock) ||
     6457+                      chunkId >= ((dev->internalEndBlock+1) * dev->nChunksPerBlock))
     6458+                       {
     6459+                               T(YAFFS_TRACE_ALWAYS,(TSTR("Found daft chunkId %d for %d"TENDSTR),chunkId,i));
     6460+                       }
     6461+                       else
     6462+                       {
    76586463+                               in->nDataChunks--;
    7659 +                               yaffs_DeleteChunk(dev, chunkId, 1, __LINE__);
     6464+                               yaffs_DeleteChunk(dev,chunkId,1,__LINE__);
    76606465+                       }
    76616466+               }
    76626467+       }
    7663 +
    7664 +}
    7665 +
    7666 +int yaffs_ResizeFile(yaffs_Object * in, loff_t newSize)
     6468+               
     6469+}
     6470+
     6471+int yaffs_ResizeFile(yaffs_Object *in, int newSize)
    76676472+{
    76686473+
    76696474+       int oldFileSize = in->variant.fileVariant.fileSize;
    7670 +       int newSizeOfPartialChunk;
    7671 +       int newFullChunks;
    7672 +       
     6475+       int sizeOfPartialChunk;
    76736476+       yaffs_Device *dev = in->myDev;
    76746477+       
    7675 +       yaffs_AddrToChunk(dev, newSize, &newFullChunks, &newSizeOfPartialChunk);
    7676 +
    7677 +       yaffs_FlushFilesChunkCache(in);
     6478+        sizeOfPartialChunk  = newSize % dev->nBytesPerChunk;
     6479+               
     6480+
     6481+       yaffs_FlushFilesChunkCache(in);
    76786482+       yaffs_InvalidateWholeChunkCache(in);
    76796483+
    76806484+       yaffs_CheckGarbageCollection(dev);
    7681 +
    7682 +       if (in->variantType != YAFFS_OBJECT_TYPE_FILE) {
     6485+       
     6486+       if(in->variantType != YAFFS_OBJECT_TYPE_FILE)
     6487+       {
    76836488+               return yaffs_GetFileSize(in);
    76846489+       }
    7685 +
    7686 +       if (newSize == oldFileSize) {
     6490+       
     6491+       if(newSize < oldFileSize)
     6492+       {
     6493+
     6494+               yaffs_PruneResizedChunks(in,newSize);
     6495+               
     6496+               if(sizeOfPartialChunk != 0)
     6497+               {
     6498+                       int lastChunk = 1+ newSize/dev->nBytesPerChunk;
     6499+                       __u8 *localBuffer = yaffs_GetTempBuffer(dev,__LINE__);
     6500+                       
     6501+                       // Got to read and rewrite the last chunk with its new size and zero pad
     6502+                       yaffs_ReadChunkDataFromObject(in,lastChunk,localBuffer);
     6503+                       
     6504+                       memset(localBuffer + sizeOfPartialChunk,0, dev->nBytesPerChunk - sizeOfPartialChunk);
     6505+                       
     6506+                       yaffs_WriteChunkDataToObject(in,lastChunk,localBuffer,sizeOfPartialChunk,1);
     6507+                               
     6508+                       yaffs_ReleaseTempBuffer(dev,localBuffer,__LINE__);
     6509+               }
     6510+               
     6511+               in->variant.fileVariant.fileSize = newSize;
     6512+               
     6513+               yaffs_PruneFileStructure(dev,&in->variant.fileVariant);
     6514+               
     6515+               // Write a new object header to show we've shrunk the file
     6516+               // Do this only if the file is not in the deleted directories.
     6517+               if(in->parent->objectId != YAFFS_OBJECTID_UNLINKED &&
     6518+                  in->parent->objectId != YAFFS_OBJECTID_DELETED
     6519+                 )
     6520+               {
     6521+                       yaffs_UpdateObjectHeader(in,NULL, 0, 1,0);
     6522+               }
     6523+
     6524+               
     6525+               return newSize;
     6526+               
     6527+       }
     6528+       else
     6529+       {
    76876530+               return oldFileSize;
    76886531+       }
    7689 +
    7690 +       if (newSize < oldFileSize) {
    7691 +
    7692 +               yaffs_PruneResizedChunks(in, newSize);
    7693 +
    7694 +               if (newSizeOfPartialChunk != 0) {
    7695 +                       int lastChunk = 1 + newFullChunks;
    7696 +                       
    7697 +                       __u8 *localBuffer = yaffs_GetTempBuffer(dev, __LINE__);
    7698 +
    7699 +                       /* Got to read and rewrite the last chunk with its new size and zero pad */
    7700 +                       yaffs_ReadChunkDataFromObject(in, lastChunk,
    7701 +                                                     localBuffer);
    7702 +
    7703 +                       memset(localBuffer + newSizeOfPartialChunk, 0,
    7704 +                              dev->nDataBytesPerChunk - newSizeOfPartialChunk);
    7705 +
    7706 +                       yaffs_WriteChunkDataToObject(in, lastChunk, localBuffer,
    7707 +                                                    newSizeOfPartialChunk, 1);
    7708 +
    7709 +                       yaffs_ReleaseTempBuffer(dev, localBuffer, __LINE__);
    7710 +               }
    7711 +
    7712 +               in->variant.fileVariant.fileSize = newSize;
    7713 +
    7714 +               yaffs_PruneFileStructure(dev, &in->variant.fileVariant);
    7715 +       }
    7716 +       /* Write a new object header.
    7717 +        * show we've shrunk the file, if need be
    7718 +        * Do this only if the file is not in the deleted directories.
    7719 +        */
    7720 +       if (in->parent->objectId != YAFFS_OBJECTID_UNLINKED &&
    7721 +           in->parent->objectId != YAFFS_OBJECTID_DELETED) {
    7722 +               yaffs_UpdateObjectHeader(in, NULL, 0,
    7723 +                                        (newSize < oldFileSize) ? 1 : 0, 0);
    7724 +       }
    7725 +
    7726 +       return newSize;
    7727 +}
    7728 +
    7729 +loff_t yaffs_GetFileSize(yaffs_Object * obj)
     6532+}
     6533+
     6534+
     6535+loff_t yaffs_GetFileSize(yaffs_Object *obj)
    77306536+{
    77316537+       obj = yaffs_GetEquivalentObject(obj);
    7732 +
    7733 +       switch (obj->variantType) {
    7734 +       case YAFFS_OBJECT_TYPE_FILE:
    7735 +               return obj->variant.fileVariant.fileSize;
    7736 +       case YAFFS_OBJECT_TYPE_SYMLINK:
    7737 +               return yaffs_strlen(obj->variant.symLinkVariant.alias);
    7738 +       default:
    7739 +               return 0;
    7740 +       }
    7741 +}
    7742 +
    7743 +
    7744 +
    7745 +int yaffs_FlushFile(yaffs_Object * in, int updateTime)
     6538+       
     6539+       switch(obj->variantType)
     6540+       {
     6541+               case YAFFS_OBJECT_TYPE_FILE:
     6542+                       return obj->variant.fileVariant.fileSize;
     6543+               case YAFFS_OBJECT_TYPE_SYMLINK:
     6544+                       return yaffs_strlen(obj->variant.symLinkVariant.alias);
     6545+               default:
     6546+                       return 0;
     6547+       }
     6548+}
     6549+
     6550+
     6551+
     6552+// yaffs_FlushFile() updates the file's
     6553+// objectId in NAND
     6554+
     6555+int yaffs_FlushFile(yaffs_Object *in, int updateTime)
    77466556+{
    77476557+       int retVal;
    7748 +       if (in->dirty) {
     6558+       if(in->dirty)
     6559+       {
     6560+               //T(("flushing object header\n"));
     6561+               
    77496562+               yaffs_FlushFilesChunkCache(in);
    7750 +               if (updateTime) {
     6563+               if(updateTime)
     6564+               {
    77516565+#ifdef CONFIG_YAFFS_WINCE
    77526566+                       yfsd_WinFileTimeNow(in->win_mtime);
     
    77586572+               }
    77596573+
    7760 +               retVal =
    7761 +                   (yaffs_UpdateObjectHeader(in, NULL, 0, 0, 0) >=
    7762 +                    0) ? YAFFS_OK : YAFFS_FAIL;
    7763 +       } else {
     6574+               retVal = (yaffs_UpdateObjectHeader(in,NULL,0,0,0) >= 0)? YAFFS_OK : YAFFS_FAIL;
     6575+       }
     6576+       else
     6577+       {
    77646578+               retVal = YAFFS_OK;
    77656579+       }
    7766 +
     6580+       
    77676581+       return retVal;
    7768 +
    7769 +}
    7770 +
    7771 +static int yaffs_DoGenericObjectDeletion(yaffs_Object * in)
    7772 +{
    7773 +
    7774 +       /* First off, invalidate the file's data in the cache, without flushing. */
     6582+       
     6583+}
     6584+
     6585+
     6586+static int yaffs_DoGenericObjectDeletion(yaffs_Object *in)
     6587+{
     6588+
     6589+       // First off, invalidate the file's data in the cache, without flushing.
    77756590+       yaffs_InvalidateWholeChunkCache(in);
    77766591+
    7777 +       if (in->myDev->isYaffs2 && (in->parent != in->myDev->deletedDir)) {
    7778 +               /* Move to the unlinked directory so we have a record that it was deleted. */
    7779 +               yaffs_ChangeObjectName(in, in->myDev->deletedDir, NULL, 0, 0);
    7780 +
    7781 +       }
    7782 +
     6592+       if(in->myDev->isYaffs2 && (in->parent != in->myDev->deletedDir))
     6593+       {
     6594+               // Move to the unlinked directory so we have a record that it was deleted.
     6595+               yaffs_ChangeObjectName(in, in->myDev->deletedDir,NULL,0,0);
     6596+
     6597+       }
     6598+
     6599+       
    77836600+       yaffs_RemoveObjectFromDirectory(in);
    7784 +       yaffs_DeleteChunk(in->myDev, in->chunkId, 1, __LINE__);
     6601+       yaffs_DeleteChunk(in->myDev,in->chunkId,1,__LINE__);
    77856602+       in->chunkId = -1;
     6603+#if 0
     6604+#ifdef __KERNEL__
     6605+       if(in->myInode)
     6606+       {
     6607+               in->myInode->u.generic_ip = NULL;
     6608+               in->myInode = 0;
     6609+       }
     6610+#endif
     6611+#endif
    77866612+
    77876613+       yaffs_FreeObject(in);
     
    77906616+}
    77916617+
    7792 +/* yaffs_DeleteFile deletes the whole file data
    7793 + * and the inode associated with the file.
    7794 + * It does not delete the links associated with the file.
    7795 + */
    7796 +static int yaffs_UnlinkFile(yaffs_Object * in)
    7797 +{
    7798 +
     6618+// yaffs_DeleteFile deletes the whole file data
     6619+// and the inode associated with the file.
     6620+// It does not delete the links associated with the file.
     6621+static int yaffs_UnlinkFile(yaffs_Object *in)
     6622+{
     6623+
     6624+#ifdef CONFIG_YAFFS_DISABLE_BACKGROUND_DELETION
     6625+
     6626+       // Delete the file data & tnodes
     6627+
     6628+        yaffs_DeleteWorker(in, in->variant.fileVariant.top, in->variant.fileVariant.topLevel, 0,NULL);
     6629+       
     6630+
     6631+       yaffs_FreeTnode(in->myDev,in->variant.fileVariant.top);
     6632+       
     6633+       return  yaffs_DoGenericObjectDeletion(in);
     6634+#else
    77996635+       int retVal;
    7800 +       int immediateDeletion = 0;
    7801 +
    7802 +       if (1) {
     6636+       int immediateDeletion=0;
     6637+
     6638+       if(1)
     6639+       {
     6640+               //in->unlinked = 1;
     6641+               //in->myDev->nUnlinkedFiles++;
     6642+               //in->renameAllowed = 0;
    78036643+#ifdef __KERNEL__
    7804 +               if (!in->myInode) {
     6644+               if(!in->myInode)
     6645+               {
    78056646+                       immediateDeletion = 1;
    78066647+
    78076648+               }
    78086649+#else
    7809 +               if (in->inUse <= 0) {
     6650+               if(in->inUse <= 0)
     6651+               {
    78106652+                       immediateDeletion = 1;
    78116653+
    78126654+               }
    78136655+#endif
    7814 +               if (immediateDeletion) {
    7815 +                       retVal =
    7816 +                           yaffs_ChangeObjectName(in, in->myDev->deletedDir,
    7817 +                                                  NULL, 0, 0);
    7818 +                       T(YAFFS_TRACE_TRACING,
    7819 +                         (TSTR("yaffs: immediate deletion of file %d" TENDSTR),
    7820 +                          in->objectId));
    7821 +                       in->deleted = 1;
     6656+               if(immediateDeletion)
     6657+               {
     6658+                       retVal = yaffs_ChangeObjectName(in, in->myDev->deletedDir,NULL,0,0);
     6659+                       T(YAFFS_TRACE_TRACING,(TSTR("yaffs: immediate deletion of file %d" TENDSTR),in->objectId));
     6660+                       in->deleted=1;
    78226661+                       in->myDev->nDeletedFiles++;
    7823 +                       if (0 && in->myDev->isYaffs2) {
    7824 +                               yaffs_ResizeFile(in, 0);
     6662+                       if( 0 && in->myDev->isYaffs2)
     6663+                       {
     6664+                               yaffs_ResizeFile(in,0);
    78256665+                       }
    78266666+                       yaffs_SoftDeleteFile(in);
    7827 +               } else {
    7828 +                       retVal =
    7829 +                           yaffs_ChangeObjectName(in, in->myDev->unlinkedDir,
    7830 +                                                  NULL, 0, 0);
    7831 +               }
    7832 +
     6667+               }
     6668+               else
     6669+               {
     6670+                       retVal = yaffs_ChangeObjectName(in, in->myDev->unlinkedDir,NULL,0,0);
     6671+               }
     6672+       
    78336673+       }
    78346674+       return retVal;
    7835 +}
    7836 +
    7837 +int yaffs_DeleteFile(yaffs_Object * in)
     6675+
     6676+       
     6677+#endif
     6678+}
     6679+
     6680+int yaffs_DeleteFile(yaffs_Object *in)
    78386681+{
    78396682+       int retVal = YAFFS_OK;
    7840 +
    7841 +       if (in->nDataChunks > 0) {
    7842 +               /* Use soft deletion if there is data in the file */
    7843 +               if (!in->unlinked) {
     6683+       
     6684+       if(in->nDataChunks > 0)
     6685+       {
     6686+               // Use soft deletion
     6687+               if(!in->unlinked)
     6688+               {
    78446689+                       retVal = yaffs_UnlinkFile(in);
    78456690+               }
    7846 +               if (retVal == YAFFS_OK && in->unlinked && !in->deleted) {
     6691+               if(retVal == YAFFS_OK &&
     6692+               in->unlinked &&
     6693+               !in->deleted)
     6694+               {
    78476695+                       in->deleted = 1;
    78486696+                       in->myDev->nDeletedFiles++;
    78496697+                       yaffs_SoftDeleteFile(in);
    78506698+               }
    7851 +               return in->deleted ? YAFFS_OK : YAFFS_FAIL;
    7852 +       } else {
    7853 +               /* The file has no data chunks so we toss it immediately */
    7854 +               yaffs_FreeTnode(in->myDev, in->variant.fileVariant.top);
     6699+               return in->deleted ? YAFFS_OK : YAFFS_FAIL;     
     6700+       }
     6701+       else
     6702+       {
     6703+               // The file has no data chunks so we toss it immediately
     6704+               yaffs_FreeTnode(in->myDev,in->variant.fileVariant.top);
    78556705+               in->variant.fileVariant.top = NULL;
    7856 +               yaffs_DoGenericObjectDeletion(in);
    7857 +
    7858 +               return YAFFS_OK;
    7859 +       }
    7860 +}
    7861 +
    7862 +static int yaffs_DeleteDirectory(yaffs_Object * in)
    7863 +{
    7864 +       /* First check that the directory is empty. */
    7865 +       if (list_empty(&in->variant.directoryVariant.children)) {
    7866 +               return yaffs_DoGenericObjectDeletion(in);
    7867 +       }
    7868 +
     6706+               yaffs_DoGenericObjectDeletion(in);     
     6707+               
     6708+               return YAFFS_OK;       
     6709+       }
     6710+}
     6711+
     6712+static int yaffs_DeleteDirectory(yaffs_Object *in)
     6713+{
     6714+       //First check that the directory is empty.
     6715+       if(list_empty(&in->variant.directoryVariant.children))
     6716+       {
     6717+               return  yaffs_DoGenericObjectDeletion(in);
     6718+       }
     6719+       
    78696720+       return YAFFS_FAIL;
    7870 +
    7871 +}
    7872 +
    7873 +static int yaffs_DeleteSymLink(yaffs_Object * in)
     6721+       
     6722+}
     6723+
     6724+static int yaffs_DeleteSymLink(yaffs_Object *in)
    78746725+{
    78756726+       YFREE(in->variant.symLinkVariant.alias);
    78766727+
    7877 +       return yaffs_DoGenericObjectDeletion(in);
    7878 +}
    7879 +
    7880 +static int yaffs_DeleteHardLink(yaffs_Object * in)
    7881 +{
    7882 +       /* remove this hardlink from the list assocaited with the equivalent
    7883 +        * object
    7884 +        */
     6728+       return  yaffs_DoGenericObjectDeletion(in);
     6729+}
     6730+
     6731+static int yaffs_DeleteHardLink(yaffs_Object *in)
     6732+{
     6733+       // remove this hardlink from the list assocaited with the equivalent
     6734+       // object
    78856735+       list_del(&in->hardLinks);
    7886 +       return yaffs_DoGenericObjectDeletion(in);
    7887 +}
    7888 +
    7889 +static void yaffs_DestroyObject(yaffs_Object * obj)
    7890 +{
    7891 +       switch (obj->variantType) {
    7892 +       case YAFFS_OBJECT_TYPE_FILE:
    7893 +               yaffs_DeleteFile(obj);
    7894 +               break;
    7895 +       case YAFFS_OBJECT_TYPE_DIRECTORY:
    7896 +               yaffs_DeleteDirectory(obj);
    7897 +               break;
    7898 +       case YAFFS_OBJECT_TYPE_SYMLINK:
    7899 +               yaffs_DeleteSymLink(obj);
    7900 +               break;
    7901 +       case YAFFS_OBJECT_TYPE_HARDLINK:
    7902 +               yaffs_DeleteHardLink(obj);
    7903 +               break;
    7904 +       case YAFFS_OBJECT_TYPE_SPECIAL:
    7905 +               yaffs_DoGenericObjectDeletion(obj);
    7906 +               break;
    7907 +       case YAFFS_OBJECT_TYPE_UNKNOWN:
    7908 +               break;          /* should not happen. */
    7909 +       }
    7910 +}
    7911 +
    7912 +static int yaffs_UnlinkWorker(yaffs_Object * obj)
    7913 +{
    7914 +
    7915 +       if (obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) {
    7916 +               return yaffs_DeleteHardLink(obj);
    7917 +       } else if (!list_empty(&obj->hardLinks)) {
    7918 +               /* Curve ball: We're unlinking an object that has a hardlink.
    7919 +                *
    7920 +                * This problem arises because we are not strictly following
    7921 +                * The Linux link/inode model.
    7922 +                *
    7923 +                * We can't really delete the object.
    7924 +                * Instead, we do the following:
    7925 +                * - Select a hardlink.
    7926 +                * - Unhook it from the hard links
    7927 +                * - Unhook it from its parent directory (so that the rename can work)
    7928 +                * - Rename the object to the hardlink's name.
    7929 +                * - Delete the hardlink
    7930 +                */
    7931 +
     6736+       return  yaffs_DoGenericObjectDeletion(in);     
     6737+}
     6738+
     6739+
     6740+static void yaffs_DestroyObject(yaffs_Object *obj)
     6741+{
     6742+       switch(obj->variantType)
     6743+       {
     6744+               case YAFFS_OBJECT_TYPE_FILE: yaffs_DeleteFile(obj); break;
     6745+               case YAFFS_OBJECT_TYPE_DIRECTORY: yaffs_DeleteDirectory(obj); break;
     6746+               case YAFFS_OBJECT_TYPE_SYMLINK: yaffs_DeleteSymLink(obj); break;
     6747+               case YAFFS_OBJECT_TYPE_HARDLINK: yaffs_DeleteHardLink(obj); break;
     6748+               case YAFFS_OBJECT_TYPE_SPECIAL: yaffs_DoGenericObjectDeletion(obj); break;
     6749+               case YAFFS_OBJECT_TYPE_UNKNOWN: break; // should not happen.
     6750+       }
     6751+}
     6752+
     6753+
     6754+static int yaffs_UnlinkWorker(yaffs_Object *obj)
     6755+{
     6756+
     6757+       
     6758+       if(obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK)
     6759+       {
     6760+               return  yaffs_DeleteHardLink(obj);
     6761+       }
     6762+       else if(!list_empty(&obj->hardLinks))
     6763+       {       
     6764+               // Curve ball: We're unlinking an object that has a hardlink.
     6765+               //
     6766+               //      This problem arises because we are not strictly following
     6767+               //  The Linux link/inode model.
     6768+               //
     6769+               // We can't really delete the object.
     6770+               // Instead, we do the following:
     6771+               // - Select a hardlink.
     6772+               // - Unhook it from the hard links
     6773+               // - Unhook it from its parent directory (so that the rename can work)
     6774+               // - Rename the object to the hardlink's name.
     6775+               // - Delete the hardlink
     6776+               
     6777+               
    79326778+               yaffs_Object *hl;
    79336779+               int retVal;
    7934 +               YCHAR name[YAFFS_MAX_NAME_LENGTH + 1];
    7935 +
    7936 +               hl = list_entry(obj->hardLinks.next, yaffs_Object, hardLinks);
    7937 +
     6780+               YCHAR name[YAFFS_MAX_NAME_LENGTH+1];
     6781+               
     6782+               hl = list_entry(obj->hardLinks.next,yaffs_Object,hardLinks);
     6783+               
    79386784+               list_del_init(&hl->hardLinks);
    79396785+               list_del_init(&hl->siblings);
    7940 +
    7941 +               yaffs_GetObjectName(hl, name, YAFFS_MAX_NAME_LENGTH + 1);
    7942 +
    7943 +               retVal = yaffs_ChangeObjectName(obj, hl->parent, name, 0, 0);
    7944 +
    7945 +               if (retVal == YAFFS_OK) {
     6786+               
     6787+               yaffs_GetObjectName(hl,name,YAFFS_MAX_NAME_LENGTH+1);
     6788+               
     6789+               retVal = yaffs_ChangeObjectName(obj, hl->parent, name,0,0);
     6790+               
     6791+               if(retVal == YAFFS_OK)
     6792+               {
    79466793+                       retVal = yaffs_DoGenericObjectDeletion(hl);
    79476794+               }
    79486795+               return retVal;
    7949 +
    7950 +       } else {
    7951 +               switch (obj->variantType) {
    7952 +               case YAFFS_OBJECT_TYPE_FILE:
    7953 +                       return yaffs_UnlinkFile(obj);
    7954 +                       break;
    7955 +               case YAFFS_OBJECT_TYPE_DIRECTORY:
    7956 +                       return yaffs_DeleteDirectory(obj);
    7957 +                       break;
    7958 +               case YAFFS_OBJECT_TYPE_SYMLINK:
    7959 +                       return yaffs_DeleteSymLink(obj);
    7960 +                       break;
    7961 +               case YAFFS_OBJECT_TYPE_SPECIAL:
    7962 +                       return yaffs_DoGenericObjectDeletion(obj);
    7963 +                       break;
    7964 +               case YAFFS_OBJECT_TYPE_HARDLINK:
    7965 +               case YAFFS_OBJECT_TYPE_UNKNOWN:
    7966 +               default:
    7967 +                       return YAFFS_FAIL;
    7968 +               }
    7969 +       }
    7970 +}
    7971 +
    7972 +
    7973 +static int yaffs_UnlinkObject( yaffs_Object *obj)
    7974 +{
    7975 +
    7976 +       if (obj && obj->unlinkAllowed) {
    7977 +               return yaffs_UnlinkWorker(obj);
    7978 +       }
    7979 +
    7980 +       return YAFFS_FAIL;
    7981 +
    7982 +}
    7983 +int yaffs_Unlink(yaffs_Object * dir, const YCHAR * name)
     6796+                               
     6797+       }
     6798+       else
     6799+       {
     6800+               switch(obj->variantType)
     6801+               {
     6802+                       case YAFFS_OBJECT_TYPE_FILE:
     6803+                               return yaffs_UnlinkFile(obj);
     6804+                               break;
     6805+                       case YAFFS_OBJECT_TYPE_DIRECTORY:
     6806+                               return yaffs_DeleteDirectory(obj);
     6807+                               break;
     6808+                       case YAFFS_OBJECT_TYPE_SYMLINK:
     6809+                               return yaffs_DeleteSymLink(obj);
     6810+                               break;
     6811+                       case YAFFS_OBJECT_TYPE_SPECIAL:
     6812+                               return yaffs_DoGenericObjectDeletion(obj);
     6813+                               break;
     6814+                       case YAFFS_OBJECT_TYPE_HARDLINK:
     6815+                       case YAFFS_OBJECT_TYPE_UNKNOWN:
     6816+                       default:
     6817+                               return YAFFS_FAIL;
     6818+               }
     6819+       }
     6820+}
     6821+
     6822+int yaffs_Unlink(yaffs_Object *dir, const YCHAR *name)
    79846823+{
    79856824+       yaffs_Object *obj;
    7986 +
    7987 +       obj = yaffs_FindObjectByName(dir, name);
    7988 +       return yaffs_UnlinkObject(obj);
    7989 +}
    7990 +
    7991 +/*----------------------- Initialisation Scanning ---------------------- */
    7992 +
    7993 +static void yaffs_HandleShadowedObject(yaffs_Device * dev, int objId,
    7994 +                                      int backwardScanning)
    7995 +{
    7996 +       yaffs_Object *obj;
    7997 +
    7998 +       if (!backwardScanning) {
    7999 +               /* Handle YAFFS1 forward scanning case
    8000 +                * For YAFFS1 we always do the deletion
    8001 +                */
    8002 +
    8003 +       } else {
    8004 +               /* Handle YAFFS2 case (backward scanning)
    8005 +                * If the shadowed object exists then ignore.
    8006 +                */
    8007 +               if (yaffs_FindObjectByNumber(dev, objId)) {
    8008 +                       return;
    8009 +               }
    8010 +       }
    8011 +
    8012 +       /* Let's create it (if it does not exist) assuming it is a file so that it can do shrinking etc.
    8013 +        * We put it in unlinked dir to be cleaned up after the scanning
    8014 +        */
    8015 +       obj =
    8016 +           yaffs_FindOrCreateObjectByNumber(dev, objId,
    8017 +                                            YAFFS_OBJECT_TYPE_FILE);
    8018 +       yaffs_AddObjectToDirectory(dev->unlinkedDir, obj);
    8019 +       obj->variant.fileVariant.shrinkSize = 0;
    8020 +       obj->valid = 1;         /* So that we don't read any other info for this file */
    8021 +
    8022 +}
    8023 +
    8024 +typedef struct {
     6825+       
     6826+        obj = yaffs_FindObjectByName(dir,name);
     6827+       
     6828+        if(obj && obj->unlinkAllowed)
     6829+        {
     6830+               return yaffs_UnlinkWorker(obj);
     6831+        }
     6832+       
     6833+        return YAFFS_FAIL;
     6834+       
     6835+}
     6836+
     6837+//////////////// Initialisation Scanning /////////////////
     6838+
     6839+
     6840+void yaffs_HandleShadowedObject(yaffs_Device *dev, int objId, int backwardScanning)
     6841+{
     6842+       //Todo
     6843+}
     6844+
     6845+#if 0
     6846+// For now we use the SmartMedia check.
     6847+// We look at the blockStatus byte in the first two chunks
     6848+// These must be 0xFF to pass as OK.
     6849+// todo: this function needs to be modifyable foir different NAND types
     6850+// and different chunk sizes.  Suggest make this into a per-device configurable
     6851+// function.
     6852+static int yaffs_IsBlockBad(yaffs_Device *dev, int blk)
     6853+{
     6854+       yaffsExtendedTags *tags;
     6855+       
     6856+       yaffs_ReadChunkFromNAND(dev,blk * dev->nChunksPerBlock,NULL,&tags,1);
     6857+#if 1
     6858+       if(yaffs_CountBits(spare.blockStatus) < 7)
     6859+       {
     6860+               return 1;
     6861+       }
     6862+#else
     6863+       if(spare.blockStatus != 0xFF)
     6864+       {
     6865+               return 1;
     6866+       }
     6867+#endif
     6868+       yaffs_ReadChunkFromNAND(dev,blk * dev->nChunksPerBlock + 1,NULL,&spare,1);
     6869+
     6870+#if 1
     6871+       if(yaffs_CountBits(spare.blockStatus) < 7)
     6872+       {
     6873+               return 1;
     6874+       }
     6875+#else
     6876+       if(spare.blockStatus != 0xFF)
     6877+       {
     6878+               return 1;
     6879+       }
     6880+#endif
     6881+       
     6882+       return 0;
     6883+       
     6884+}
     6885+
     6886+#endif
     6887+
     6888+
     6889+typedef struct
     6890+{
    80256891+       int seq;
    80266892+       int block;
     
    80286894+
    80296895+
    8030 +static void yaffs_HardlinkFixup(yaffs_Device *dev, yaffs_Object *hardList)
    8031 +{
    8032 +       yaffs_Object *hl;
    8033 +       yaffs_Object *in;
    8034 +       
    8035 +       while (hardList) {
    8036 +               hl = hardList;
    8037 +               hardList = (yaffs_Object *) (hardList->hardLinks.next);
    8038 +
    8039 +               in = yaffs_FindObjectByNumber(dev,
    8040 +                                             hl->variant.hardLinkVariant.
    8041 +                                             equivalentObjectId);
    8042 +
    8043 +               if (in) {
    8044 +                       /* Add the hardlink pointers */
    8045 +                       hl->variant.hardLinkVariant.equivalentObject = in;
    8046 +                       list_add(&hl->hardLinks, &in->hardLinks);
    8047 +               } else {
    8048 +                       /* Todo Need to report/handle this better.
    8049 +                        * Got a problem... hardlink to a non-existant object
    8050 +                        */
    8051 +                       hl->variant.hardLinkVariant.equivalentObject = NULL;
    8052 +                       INIT_LIST_HEAD(&hl->hardLinks);
    8053 +
    8054 +               }
    8055 +
    8056 +       }
    8057 +
    8058 +}
    8059 +
    8060 +
    8061 +
    8062 +
    8063 +
    8064 +static int ybicmp(const void *a, const void *b){
    8065 +    register int aseq = ((yaffs_BlockIndex *)a)->seq;
    8066 +    register int bseq = ((yaffs_BlockIndex *)b)->seq;
    8067 +    register int ablock = ((yaffs_BlockIndex *)a)->block;
    8068 +    register int bblock = ((yaffs_BlockIndex *)b)->block;
    8069 +    if( aseq == bseq )
    8070 +        return ablock - bblock;
    8071 +    else
    8072 +        return aseq - bseq;
    8073 +
    8074 +}
    8075 +
    8076 +static int yaffs_Scan(yaffs_Device * dev)
     6896+
     6897+static int yaffs_Scan(yaffs_Device *dev)
    80776898+{
    80786899+       yaffs_ExtendedTags tags;
     
    80826903+       int endIterator;
    80836904+       int nBlocksToScan = 0;
    8084 +       int result;
    8085 +
     6905+       
    80866906+       int chunk;
    80876907+       int c;
     
    80916911+       yaffs_Object *hl;
    80926912+       yaffs_BlockInfo *bi;
    8093 +       int sequenceNumber;
     6913+       int sequenceNumber;     
    80946914+       yaffs_ObjectHeader *oh;
    80956915+       yaffs_Object *in;
    80966916+       yaffs_Object *parent;
    80976917+       int nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1;
    8098 +
     6918+       
    80996919+       __u8 *chunkData;
    81006920+
    81016921+       yaffs_BlockIndex *blockIndex = NULL;
    81026922+
    8103 +       if (dev->isYaffs2) {
    8104 +               T(YAFFS_TRACE_SCAN,
    8105 +                 (TSTR("yaffs_Scan is not for YAFFS2!" TENDSTR)));
    8106 +               return YAFFS_FAIL;
    8107 +       }
    8108 +       
    8109 +       //TODO  Throw all the yaffs2 stuuf out of yaffs_Scan since it is only for yaffs1 format.
    8110 +       
    8111 +       T(YAFFS_TRACE_SCAN,
    8112 +         (TSTR("yaffs_Scan starts  intstartblk %d intendblk %d..." TENDSTR),
    8113 +          dev->internalStartBlock, dev->internalEndBlock));
    8114 +
    8115 +       chunkData = yaffs_GetTempBuffer(dev, __LINE__);
    8116 +
     6923+       T(YAFFS_TRACE_SCAN,(TSTR("yaffs_Scan starts  intstartblk %d intendblk %d..." TENDSTR),dev->internalStartBlock,dev->internalEndBlock));
     6924+       
     6925+       chunkData = yaffs_GetTempBuffer(dev,__LINE__);
     6926+       
     6927+       
    81176928+       dev->sequenceNumber = YAFFS_LOWEST_SEQUENCE_NUMBER;
    8118 +
    8119 +       if (dev->isYaffs2) {
    8120 +               blockIndex = YMALLOC(nBlocks * sizeof(yaffs_BlockIndex));
    8121 +       }
    8122 +
    8123 +       /* Scan all the blocks to determine their state */
    8124 +       for (blk = dev->internalStartBlock; blk <= dev->internalEndBlock; blk++) {
    8125 +               bi = yaffs_GetBlockInfo(dev, blk);
    8126 +               yaffs_ClearChunkBits(dev, blk);
     6929+       
     6930+       if(dev->isYaffs2)
     6931+       {
     6932+               blockIndex = YMALLOC(nBlocks * sizeof(yaffs_BlockIndex));               
     6933+       }
     6934+       
     6935+       
     6936+       // Scan all the blocks to determine their state
     6937+       for(blk = dev->internalStartBlock; blk <= dev->internalEndBlock; blk++)
     6938+       {
     6939+               bi = yaffs_GetBlockInfo(dev,blk);
     6940+               yaffs_ClearChunkBits(dev,blk);
    81276941+               bi->pagesInUse = 0;
    81286942+               bi->softDeletions = 0;
    8129 +
    8130 +               yaffs_QueryInitialBlockState(dev, blk, &state, &sequenceNumber);
    8131 +
     6943+                               
     6944+               yaffs_QueryInitialBlockState(dev,blk,&state,&sequenceNumber);
     6945+               
    81326946+               bi->blockState = state;
    8133 +               bi->sequenceNumber = sequenceNumber;
    8134 +
    8135 +               T(YAFFS_TRACE_SCAN_DEBUG,
    8136 +                 (TSTR("Block scanning block %d state %d seq %d" TENDSTR), blk,
    8137 +                  state, sequenceNumber));
    8138 +
    8139 +               if (state == YAFFS_BLOCK_STATE_DEAD) {
    8140 +                       T(YAFFS_TRACE_BAD_BLOCKS,
    8141 +                         (TSTR("block %d is bad" TENDSTR), blk));
    8142 +               } else if (state == YAFFS_BLOCK_STATE_EMPTY) {
    8143 +                       T(YAFFS_TRACE_SCAN_DEBUG,
    8144 +                         (TSTR("Block empty " TENDSTR)));
     6947+               bi->sequenceNumber = sequenceNumber;
     6948+
     6949+               T(YAFFS_TRACE_SCAN_DEBUG,(TSTR("Block scanning block %d state %d seq %d" TENDSTR),blk,state,sequenceNumber));
     6950+               
     6951+               if(state == YAFFS_BLOCK_STATE_DEAD)
     6952+               {
     6953+                       T(YAFFS_TRACE_BAD_BLOCKS,(TSTR("block %d is bad" TENDSTR),blk));
     6954+               }
     6955+               else if(state == YAFFS_BLOCK_STATE_EMPTY)
     6956+               {
     6957+                       T(YAFFS_TRACE_SCAN_DEBUG,(TSTR("Block empty " TENDSTR)));
    81456958+                       dev->nErasedBlocks++;
    81466959+                       dev->nFreeChunks += dev->nChunksPerBlock;
    8147 +               } else if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) {
    8148 +
    8149 +                       /* Determine the highest sequence number */
    8150 +                       if (dev->isYaffs2 &&
     6960+               }
     6961+               else if(state == YAFFS_BLOCK_STATE_NEEDS_SCANNING)
     6962+               {
     6963+                                       
     6964+                       // Determine the highest sequence number
     6965+                       if( dev->isYaffs2 &&
    81516966+                           sequenceNumber >= YAFFS_LOWEST_SEQUENCE_NUMBER &&
    8152 +                           sequenceNumber < YAFFS_HIGHEST_SEQUENCE_NUMBER) {
    8153 +
     6967+                           sequenceNumber < YAFFS_HIGHEST_SEQUENCE_NUMBER)
     6968+                        {
     6969+                               
    81546970+                               blockIndex[nBlocksToScan].seq = sequenceNumber;
    81556971+                               blockIndex[nBlocksToScan].block = blk;
    8156 +
     6972+                               
    81576973+                               nBlocksToScan++;
    81586974+
    8159 +                               if (sequenceNumber >= dev->sequenceNumber) {
    8160 +                                       dev->sequenceNumber = sequenceNumber;
     6975+                               if(sequenceNumber >= dev->sequenceNumber)
     6976+                               {
     6977+                                       dev->sequenceNumber = sequenceNumber;
    81616978+                               }
    8162 +                       } else if (dev->isYaffs2) {
    8163 +                               /* TODO: Nasty sequence number! */
    8164 +                               T(YAFFS_TRACE_SCAN,
    8165 +                                 (TSTR
    8166 +                                  ("Block scanning block %d has bad sequence number %d"
    8167 +                                   TENDSTR), blk, sequenceNumber));
    8168 +
    81696979+                       }
    8170 +               }
    8171 +       }
    8172 +
    8173 +       /* Sort the blocks
    8174 +        * Dungy old bubble sort for now...
    8175 +        */
    8176 +       if (dev->isYaffs2) {
     6980+                       else if(dev->isYaffs2)
     6981+                       {
     6982+                               // TODO: Nasty sequence number!
     6983+                               T(YAFFS_TRACE_SCAN,(TSTR("Block scanning block %d has bad sequence number %d" TENDSTR),blk,sequenceNumber));
     6984+
     6985+                       }
     6986+               }
     6987+       }
     6988+       
     6989+       // Sort the blocks
     6990+       // Dungy old bubble sort for now...
     6991+       if(dev->isYaffs2)
     6992+       {
    81776993+               yaffs_BlockIndex temp;
    81786994+               int i;
    81796995+               int j;
    8180 +
    8181 +               for (i = 0; i < nBlocksToScan; i++)
    8182 +                       for (j = i + 1; j < nBlocksToScan; j++)
    8183 +                               if (blockIndex[i].seq > blockIndex[j].seq) {
    8184 +                                       temp = blockIndex[j];
    8185 +                                       blockIndex[j] = blockIndex[i];
    8186 +                                       blockIndex[i] = temp;
    8187 +                               }
    8188 +       }
    8189 +
    8190 +       /* Now scan the blocks looking at the data. */
    8191 +       if (dev->isYaffs2) {
     6996+               
     6997+               for(i = 0; i < nBlocksToScan; i++)
     6998+                       for(j = i+1; j < nBlocksToScan; j++)
     6999+                        if(blockIndex[i].seq > blockIndex[j].seq)
     7000+                        {
     7001+                               temp = blockIndex[j];
     7002+                               blockIndex[j] = blockIndex[i];
     7003+                               blockIndex[i] = temp;
     7004+                        }
     7005+       }
     7006+       
     7007+       
     7008+       // Now scan the blocks looking at the data.
     7009+       if(dev->isYaffs2)
     7010+       {
    81927011+               startIterator = 0;
    8193 +               endIterator = nBlocksToScan - 1;
    8194 +               T(YAFFS_TRACE_SCAN_DEBUG,
    8195 +                 (TSTR("%d blocks to be scanned" TENDSTR), nBlocksToScan));
    8196 +       } else {
     7012+               endIterator = nBlocksToScan-1;
     7013+               T(YAFFS_TRACE_SCAN_DEBUG,(TSTR("%d blocks to be scanned" TENDSTR),nBlocksToScan));
     7014+       }
     7015+       else
     7016+       {
    81977017+               startIterator = dev->internalStartBlock;
    81987018+               endIterator = dev->internalEndBlock;
    81997019+       }
    8200 +
    8201 +       /* For each block.... */
    8202 +       for (blockIterator = startIterator; blockIterator <= endIterator;
    8203 +            blockIterator++) {
    8204 +
    8205 +               if (dev->isYaffs2) {
    8206 +                       /* get the block to scan in the correct order */
     7020+       
     7021+       // For each block....
     7022+       for(blockIterator = startIterator; blockIterator <= endIterator; blockIterator++)
     7023+       {
     7024+       
     7025+               if(dev->isYaffs2)
     7026+               {
     7027+                       // get the block to scan in the correct order
    82077028+                       blk = blockIndex[blockIterator].block;
    8208 +               } else {
     7029+               }
     7030+               else
     7031+               {
    82097032+                       blk = blockIterator;
    82107033+               }
    82117034+
    8212 +               bi = yaffs_GetBlockInfo(dev, blk);
     7035+
     7036+               bi = yaffs_GetBlockInfo(dev,blk);
    82137037+               state = bi->blockState;
    8214 +
     7038+               
    82157039+               deleted = 0;
    8216 +
    8217 +               /* For each chunk in each block that needs scanning....*/
    8218 +               for (c = 0; c < dev->nChunksPerBlock &&
    8219 +                    state == YAFFS_BLOCK_STATE_NEEDS_SCANNING; c++) {
    8220 +                       /* Read the tags and decide what to do */
     7040+               
     7041+               // For each chunk in each block that needs scanning....
     7042+               for(c = 0; c < dev->nChunksPerBlock &&
     7043+                                  state == YAFFS_BLOCK_STATE_NEEDS_SCANNING; c++)
     7044+               {
     7045+                       // Read the tags and decide what to do
    82217046+                       chunk = blk * dev->nChunksPerBlock + c;
    8222 +
    8223 +                       result = yaffs_ReadChunkWithTagsFromNAND(dev, chunk, NULL,
    8224 +                                                       &tags);
    8225 +
    8226 +                       /* Let's have a good look at this chunk... */
    8227 +
    8228 +                       if (!dev->isYaffs2 && tags.chunkDeleted) {
    8229 +                               /* YAFFS1 only...
    8230 +                                * A deleted chunk
    8231 +                                */
     7047+                       
     7048+                       yaffs_ReadChunkWithTagsFromNAND(dev,chunk,NULL,&tags);
     7049+
     7050+                       // Let's have a good look at this chunk...
     7051+       
     7052+                       
     7053+                       if(!dev->isYaffs2 && tags.chunkDeleted)
     7054+                       {
     7055+                               // YAFFS1 only...
     7056+                               // A deleted chunk
    82327057+                               deleted++;
    8233 +                               dev->nFreeChunks++;
    8234 +                               /*T((" %d %d deleted\n",blk,c)); */
    8235 +                       } else if (!tags.chunkUsed) {
    8236 +                               /* An unassigned chunk in the block
    8237 +                                * This means that either the block is empty or
    8238 +                                * this is the one being allocated from
    8239 +                                */
    8240 +
    8241 +                               if (c == 0) {
    8242 +                                       /* We're looking at the first chunk in the block so the block is unused */
     7058+                               dev->nFreeChunks ++;
     7059+                               //T((" %d %d deleted\n",blk,c));
     7060+                       }
     7061+                       else if(!tags.chunkUsed)
     7062+                       {
     7063+                               // An unassigned chunk in the block
     7064+                               // This means that either the block is empty or
     7065+                               // this is the one being allocated from
     7066+                               
     7067+                               if(c == 0)
     7068+                               {
     7069+                                       // We're looking at the first chunk in the block so the block is unused
    82437070+                                       state = YAFFS_BLOCK_STATE_EMPTY;
    82447071+                                       dev->nErasedBlocks++;
    8245 +                               } else {
    8246 +                                       /* this is the block being allocated from */
    8247 +                                       T(YAFFS_TRACE_SCAN,
    8248 +                                         (TSTR
    8249 +                                          (" Allocating from %d %d" TENDSTR),
    8250 +                                          blk, c));
     7072+                               }
     7073+                               else
     7074+                               {
     7075+                                       // this is the block being allocated from
     7076+                                       T(YAFFS_TRACE_SCAN,(TSTR(" Allocating from %d %d" TENDSTR),blk,c));
    82517077+                                       state = YAFFS_BLOCK_STATE_ALLOCATING;
    82527078+                                       dev->allocationBlock = blk;
    82537079+                                       dev->allocationPage = c;
    8254 +                                       dev->allocationBlockFinder = blk;       
    8255 +                                       /* Set it to here to encourage the allocator to go forth from here. */
    8256 +                                       
    8257 +                                       /* Yaffs2 sanity check:
    8258 +                                        * This should be the one with the highest sequence number
    8259 +                                        */
    8260 +                                       if (dev->isYaffs2
    8261 +                                           && (dev->sequenceNumber !=
    8262 +                                               bi->sequenceNumber)) {
     7080+                                       dev->allocationBlockFinder = blk; // Set it to here to encourage the allocator to
     7081+                                                                                                         // go forth from here.
     7082+                                       //Yaffs2 sanity check:
     7083+                                       // This should be the one with the highest sequence number
     7084+                                       if(dev->isYaffs2 && (dev->sequenceNumber != bi->sequenceNumber))
     7085+                                       {
    82637086+                                               T(YAFFS_TRACE_ALWAYS,
    8264 +                                                 (TSTR
    8265 +                                                  ("yaffs: Allocation block %d was not highest sequence id:"
    8266 +                                                   " block seq = %d, dev seq = %d"
    8267 +                                                   TENDSTR), blk,bi->sequenceNumber,dev->sequenceNumber));
     7087+                                                               (TSTR("yaffs: Allocation block %d was not highest sequence id: block seq = %d, dev seq = %d" TENDSTR),
     7088+                                                               blk,bi->sequenceNumber,dev->sequenceNumber));
    82687089+                                       }
    82697090+                               }
    82707091+
    82717092+                               dev->nFreeChunks += (dev->nChunksPerBlock - c);
    8272 +                       } else if (tags.chunkId > 0) {
    8273 +                               /* chunkId > 0 so it is a data chunk... */
     7093+                       }
     7094+                       else if(tags.chunkId > 0)
     7095+                       {
     7096+                               // chunkId > 0 so it is a data chunk...
    82747097+                               unsigned int endpos;
    82757098+
    8276 +                               yaffs_SetChunkBit(dev, blk, c);
     7099+                               yaffs_SetChunkBit(dev,blk,c);
    82777100+                               bi->pagesInUse++;
    8278 +
    8279 +                               in = yaffs_FindOrCreateObjectByNumber(dev,
    8280 +                                                                     tags.
    8281 +                                                                     objectId,
    8282 +                                                                     YAFFS_OBJECT_TYPE_FILE);
    8283 +                               /* PutChunkIntoFile checks for a clash (two data chunks with
    8284 +                                * the same chunkId).
    8285 +                                */
    8286 +                               yaffs_PutChunkIntoFile(in, tags.chunkId, chunk,
    8287 +                                                      1);
    8288 +                               endpos =
    8289 +                                   (tags.chunkId - 1) * dev->nDataBytesPerChunk +
    8290 +                                   tags.byteCount;
    8291 +                               if (in->variantType == YAFFS_OBJECT_TYPE_FILE
    8292 +                                   && in->variant.fileVariant.scannedFileSize <
    8293 +                                   endpos) {
    8294 +                                       in->variant.fileVariant.
    8295 +                                           scannedFileSize = endpos;
    8296 +                                       if (!dev->useHeaderFileSize) {
    8297 +                                               in->variant.fileVariant.
    8298 +                                                   fileSize =
    8299 +                                                   in->variant.fileVariant.
    8300 +                                                   scannedFileSize;
     7101+                                                               
     7102+                               in = yaffs_FindOrCreateObjectByNumber(dev,tags.objectId,YAFFS_OBJECT_TYPE_FILE);
     7103+                               // PutChunkIntoFile checks for a clash (two data chunks with
     7104+                               // the same chunkId).
     7105+                               yaffs_PutChunkIntoFile(in,tags.chunkId,chunk,1);
     7106+                               endpos = (tags.chunkId - 1)* dev->nBytesPerChunk + tags.byteCount;
     7107+                               if(in->variantType == YAFFS_OBJECT_TYPE_FILE && in->variant.fileVariant.scannedFileSize <endpos)
     7108+                               {
     7109+                                       in->variant.fileVariant.scannedFileSize = endpos;
     7110+                                       if(!dev->useHeaderFileSize)
     7111+                                       {       
     7112+                                                       in->variant.fileVariant.fileSize = in->variant.fileVariant.scannedFileSize;
    83017113+                                       }
    83027114+
    83037115+                               }
    8304 +                               /* T((" %d %d data %d %d\n",blk,c,tags.objectId,tags.chunkId));   */
    8305 +                       } else {
    8306 +                               /* chunkId == 0, so it is an ObjectHeader.
    8307 +                                * Thus, we read in the object header and make the object
    8308 +                                */
    8309 +                               yaffs_SetChunkBit(dev, blk, c);
     7116+                               //T((" %d %d data %d %d\n",blk,c,tags.objectId,tags.chunkId)); 
     7117+                       }
     7118+                       else
     7119+                       {
     7120+                               // chunkId == 0, so it is an ObjectHeader.
     7121+                               // Thus, we read in the object header and make the object
     7122+                               yaffs_SetChunkBit(dev,blk,c);
    83107123+                               bi->pagesInUse++;
    8311 +
    8312 +                               result = yaffs_ReadChunkWithTagsFromNAND(dev, chunk,
    8313 +                                                               chunkData,
    8314 +                                                               NULL);
    8315 +
    8316 +                               oh = (yaffs_ObjectHeader *) chunkData;
    8317 +
    8318 +                               in = yaffs_FindObjectByNumber(dev,
    8319 +                                                             tags.objectId);
    8320 +                               if (in && in->variantType != oh->type) {
    8321 +                                       /* This should not happen, but somehow
    8322 +                                        * Wev'e ended up with an objectId that has been reused but not yet
    8323 +                                        * deleted, and worse still it has changed type. Delete the old object.
    8324 +                                        */
    8325 +
     7124+                                                       
     7125+                               yaffs_ReadChunkWithTagsFromNAND(dev,chunk,chunkData,NULL);
     7126+                               
     7127+                               oh = (yaffs_ObjectHeader *)chunkData;
     7128+                               
     7129+                               in = yaffs_FindObjectByNumber(dev,tags.objectId);
     7130+                               if(in && in->variantType != oh->type)
     7131+                               {
     7132+                                       // This should not happen, but somehow
     7133+                                       // Wev'e ended up with an objectId that has been reused but not yet
     7134+                                       // deleted, and worse still it has changed type. Delete the old object.
     7135+                                       
    83267136+                                       yaffs_DestroyObject(in);
    8327 +
     7137+                                       
    83287138+                                       in = 0;
    83297139+                               }
    8330 +
    8331 +                               in = yaffs_FindOrCreateObjectByNumber(dev,
    8332 +                                                                     tags.
    8333 +                                                                     objectId,
    8334 +                                                                     oh->type);
    8335 +
    8336 +                               if (oh->shadowsObject > 0) {
    8337 +                                       yaffs_HandleShadowedObject(dev,
    8338 +                                                                  oh->
    8339 +                                                                  shadowsObject,
    8340 +                                                                  0);
     7140+                               
     7141+                               in = yaffs_FindOrCreateObjectByNumber(dev,tags.objectId,oh->type);
     7142+                               
     7143+                               if(oh->shadowsObject > 0)
     7144+                               {
     7145+                                       yaffs_HandleShadowedObject(dev,oh->shadowsObject,0);
    83417146+                               }
    8342 +
    8343 +                               if (in->valid) {
    8344 +                                       /* We have already filled this one. We have a duplicate and need to resolve it. */
    8345 +
     7147+                               
     7148+                               if(in->valid)
     7149+                               {
     7150+                                       // We have already filled this one. We have a duplicate and need to resolve it.
     7151+                                       
    83467152+                                       unsigned existingSerial = in->serial;
    83477153+                                       unsigned newSerial = tags.serialNumber;
    8348 +
    8349 +                                       if (dev->isYaffs2 ||
    8350 +                                           ((existingSerial + 1) & 3) ==
    8351 +                                           newSerial) {
    8352 +                                               /* Use new one - destroy the exisiting one */
    8353 +                                               yaffs_DeleteChunk(dev,
    8354 +                                                                 in->chunkId,
    8355 +                                                                 1, __LINE__);
     7154+                                       
     7155+                                       if( dev->isYaffs2 ||
     7156+                                           ((existingSerial+1) & 3) == newSerial)
     7157+                                       {
     7158+                                               // Use new one - destroy the exisiting one
     7159+                                               yaffs_DeleteChunk(dev,in->chunkId,1,__LINE__);
    83567160+                                               in->valid = 0;
    8357 +                                       } else {
    8358 +                                               /* Use existing - destroy this one. */
    8359 +                                               yaffs_DeleteChunk(dev, chunk, 1,
    8360 +                                                                 __LINE__);
     7161+                                       }
     7162+                                       else
     7163+                                       {
     7164+                                               // Use existing - destroy this one.
     7165+                                               yaffs_DeleteChunk(dev,chunk,1,__LINE__);
    83617166+                                       }
    83627167+                               }
    8363 +
    8364 +                               if (!in->valid &&
    8365 +                                   (tags.objectId == YAFFS_OBJECTID_ROOT ||
    8366 +                                    tags.objectId == YAFFS_OBJECTID_LOSTNFOUND)) {
    8367 +                                       /* We only load some info, don't fiddle with directory structure */
     7168+                               
     7169+                               if(!in->valid &&
     7170+                                  (tags.objectId == YAFFS_OBJECTID_ROOT ||
     7171+                                   tags.objectId == YAFFS_OBJECTID_LOSTNFOUND))
     7172+                               {
     7173+                                       // We only load some info, don't fiddle with directory structure
    83687174+                                       in->valid = 1;
    83697175+                                       in->variantType = oh->type;
    8370 +
    8371 +                                       in->yst_mode = oh->yst_mode;
     7176+       
     7177+                                       in->yst_mode  = oh->yst_mode;
    83727178+#ifdef CONFIG_YAFFS_WINCE
    83737179+                                       in->win_atime[0] = oh->win_atime[0];
     
    83787184+                                       in->win_mtime[1] = oh->win_mtime[1];
    83797185+#else
    8380 +                                       in->yst_uid = oh->yst_uid;
    8381 +                                       in->yst_gid = oh->yst_gid;
     7186+                                       in->yst_uid   = oh->yst_uid;
     7187+                                       in->yst_gid   = oh->yst_gid;
    83827188+                                       in->yst_atime = oh->yst_atime;
    83837189+                                       in->yst_mtime = oh->yst_mtime;
     
    83857191+                                       in->yst_rdev = oh->yst_rdev;
    83867192+#endif
    8387 +                                       in->chunkId = chunk;
    8388 +
    8389 +                               } else if (!in->valid) {
    8390 +                                       /* we need to load this info */
    8391 +
     7193+                                       in->chunkId  = chunk;
     7194+
     7195+                               }
     7196+                               else if(!in->valid)
     7197+                               {
     7198+                                       // we need to load this info
     7199+                               
    83927200+                                       in->valid = 1;
    83937201+                                       in->variantType = oh->type;
    8394 +
    8395 +                                       in->yst_mode = oh->yst_mode;
     7202+       
     7203+                                       in->yst_mode  = oh->yst_mode;
    83967204+#ifdef CONFIG_YAFFS_WINCE
    83977205+                                       in->win_atime[0] = oh->win_atime[0];
     
    84027210+                                       in->win_mtime[1] = oh->win_mtime[1];
    84037211+#else
    8404 +                                       in->yst_uid = oh->yst_uid;
    8405 +                                       in->yst_gid = oh->yst_gid;
     7212+                                       in->yst_uid   = oh->yst_uid;
     7213+                                       in->yst_gid   = oh->yst_gid;
    84067214+                                       in->yst_atime = oh->yst_atime;
    84077215+                                       in->yst_mtime = oh->yst_mtime;
     
    84097217+                                       in->yst_rdev = oh->yst_rdev;
    84107218+#endif
    8411 +                                       in->chunkId = chunk;
    8412 +
    8413 +                                       yaffs_SetObjectName(in, oh->name);
     7219+                                       in->chunkId  = chunk;
     7220+
     7221+                                       yaffs_SetObjectName(in,oh->name);
    84147222+                                       in->dirty = 0;
    8415 +
    8416 +                                       /* directory stuff...
    8417 +                                        * hook up to parent
    8418 +                                        */
    8419 +
    8420 +                                       parent =
    8421 +                                           yaffs_FindOrCreateObjectByNumber
    8422 +                                           (dev, oh->parentObjectId,
    8423 +                                            YAFFS_OBJECT_TYPE_DIRECTORY);
    8424 +                                       if (parent->variantType ==
    8425 +                                           YAFFS_OBJECT_TYPE_UNKNOWN) {
    8426 +                                               /* Set up as a directory */
    8427 +                                               parent->variantType =
    8428 +                                                   YAFFS_OBJECT_TYPE_DIRECTORY;
    8429 +                                               INIT_LIST_HEAD(&parent->variant.
    8430 +                                                              directoryVariant.
    8431 +                                                              children);
    8432 +                                       } else if (parent->variantType !=
    8433 +                                                  YAFFS_OBJECT_TYPE_DIRECTORY)
     7223+                                                       
     7224+                                       // directory stuff...
     7225+                                       // hook up to parent
     7226+       
     7227+                                       parent = yaffs_FindOrCreateObjectByNumber(dev,oh->parentObjectId,YAFFS_OBJECT_TYPE_DIRECTORY);
     7228+                                       if(parent->variantType == YAFFS_OBJECT_TYPE_UNKNOWN)
    84347229+                                       {
    8435 +                                               /* Hoosterman, another problem....
    8436 +                                                * We're trying to use a non-directory as a directory
    8437 +                                                */
    8438 +
    8439 +                                               T(YAFFS_TRACE_ERROR,
    8440 +                                                 (TSTR
    8441 +                                                  ("yaffs tragedy: attempting to use non-directory as"
    8442 +                                                   " a directory in scan. Put in lost+found."
    8443 +                                                   TENDSTR)));
     7230+                                               // Set up as a directory
     7231+                                               parent->variantType = YAFFS_OBJECT_TYPE_DIRECTORY;
     7232+                                               INIT_LIST_HEAD(&parent->variant.directoryVariant.children);
     7233+                                       }
     7234+                                       else if(parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY)
     7235+                                       {
     7236+                                               // Hoosterman, another problem....
     7237+                                               // We're trying to use a non-directory as a directory
     7238+
     7239+                                               T(YAFFS_TRACE_ERROR, (TSTR("yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found." TENDSTR)));
    84447240+                                               parent = dev->lostNFoundDir;
    84457241+                                       }
    8446 +
    8447 +                                       yaffs_AddObjectToDirectory(parent, in);
    8448 +
    8449 +                                       if (0 && (parent == dev->deletedDir ||
    8450 +                                                 parent == dev->unlinkedDir)) {
    8451 +                                               in->deleted = 1;        /* If it is unlinked at start up then it wants deleting */
     7242+                               
     7243+                                       yaffs_AddObjectToDirectory(parent,in);
     7244+
     7245+                                       if(0 && (parent == dev->deletedDir ||
     7246+                                          parent == dev->unlinkedDir))
     7247+                                       {
     7248+                                               in->deleted = 1; // If it is unlinked at start up then it wants deleting
    84527249+                                               dev->nDeletedFiles++;
    84537250+                                       }
    8454 +                                       /* Note re hardlinks.
    8455 +                                        * Since we might scan a hardlink before its equivalent object is scanned
    8456 +                                        * we put them all in a list.
    8457 +                                        * After scanning is complete, we should have all the objects, so we run through this
    8458 +                                        * list and fix up all the chains.             
    8459 +                                        */
    8460 +
    8461 +                                       switch (in->variantType) {
    8462 +                                       case YAFFS_OBJECT_TYPE_UNKNOWN:
    8463 +                                               /* Todo got a problem */
    8464 +                                               break;
    8465 +                                       case YAFFS_OBJECT_TYPE_FILE:
    8466 +                                               if (dev->isYaffs2
    8467 +                                                   && oh->isShrink) {
    8468 +                                                       /* Prune back the shrunken chunks */
    8469 +                                                       yaffs_PruneResizedChunks
    8470 +                                                           (in, oh->fileSize);
    8471 +                                                       /* Mark the block as having a shrinkHeader */
    8472 +                                                       bi->hasShrinkHeader = 1;
    8473 +                                               }
    8474 +
    8475 +                                               if (dev->useHeaderFileSize)
    8476 +
    8477 +                                                       in->variant.fileVariant.
    8478 +                                                           fileSize =
    8479 +                                                           oh->fileSize;
    8480 +
    8481 +                                               break;
    8482 +                                       case YAFFS_OBJECT_TYPE_HARDLINK:
    8483 +                                               in->variant.hardLinkVariant.
    8484 +                                                   equivalentObjectId =
    8485 +                                                   oh->equivalentObjectId;
    8486 +                                               in->hardLinks.next =
    8487 +                                                   (struct list_head *)
    8488 +                                                   hardList;
    8489 +                                               hardList = in;
    8490 +                                               break;
    8491 +                                       case YAFFS_OBJECT_TYPE_DIRECTORY:
    8492 +                                               /* Do nothing */
    8493 +                                               break;
    8494 +                                       case YAFFS_OBJECT_TYPE_SPECIAL:
    8495 +                                               /* Do nothing */
    8496 +                                               break;
    8497 +                                       case YAFFS_OBJECT_TYPE_SYMLINK:
    8498 +                                               in->variant.symLinkVariant.
    8499 +                                                   alias =
    8500 +                                                   yaffs_CloneString(oh->alias);
    8501 +                                               break;
     7251+                               
     7252+                                       // Note re hardlinks.
     7253+                                       // Since we might scan a hardlink before its equivalent object is scanned
     7254+                                       // we put them all in a list.
     7255+                                       // After scanning is complete, we should have all the objects, so we run through this
     7256+                                       // list and fix up all the chains.             
     7257+       
     7258+                                       switch(in->variantType)
     7259+                                       {
     7260+                                               case YAFFS_OBJECT_TYPE_UNKNOWN:         // Todo got a problem
     7261+                                                       break;
     7262+                                               case YAFFS_OBJECT_TYPE_FILE:
     7263+                                                       if(dev->isYaffs2 && oh->isShrink)
     7264+                                                       {
     7265+                                                               // Prune back the shrunken chunks
     7266+                                                               yaffs_PruneResizedChunks(in,oh->fileSize);
     7267+                                                               // Mark the block as having a shrinkHeader
     7268+                                                               bi->hasShrinkHeader = 1;
     7269+                                                       }
     7270+                                                       
     7271+                                                       if(dev->useHeaderFileSize)
     7272+                                               
     7273+                                                               in->variant.fileVariant.fileSize = oh->fileSize;
     7274+                                                               
     7275+                                                       break;
     7276+                                               case YAFFS_OBJECT_TYPE_HARDLINK:
     7277+                                                       in->variant.hardLinkVariant.equivalentObjectId = oh->equivalentObjectId;
     7278+                                                       in->hardLinks.next = (struct list_head *)hardList;
     7279+                                                       hardList = in;
     7280+                                                       break;
     7281+                                               case YAFFS_OBJECT_TYPE_DIRECTORY:       // Do nothing
     7282+                                                       break;
     7283+                                               case YAFFS_OBJECT_TYPE_SPECIAL: // Do nothing
     7284+                                                       break;
     7285+                                               case YAFFS_OBJECT_TYPE_SYMLINK:         // Do nothing
     7286+                                                       in->variant.symLinkVariant.alias = yaffs_CloneString(oh->alias);
     7287+                                                       break;
    85027288+                                       }
    85037289+
    8504 +                                       if (parent == dev->deletedDir) {
     7290+                                       if(parent == dev->deletedDir)
     7291+                                       {
    85057292+                                               yaffs_DestroyObject(in);
    85067293+                                               bi->hasShrinkHeader = 1;
    85077294+                                       }
     7295+                                       //T((" %d %d header %d \"%s\" type %d\n",blk,c,tags.objectId,oh->name,in->variantType));       
    85087296+                               }
    85097297+                       }
    85107298+               }
    8511 +
    8512 +               if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) {
    8513 +                       /* If we got this far while scanning, then the block is fully allocated.*/
    8514 +                       state = YAFFS_BLOCK_STATE_FULL;
    8515 +               }
    8516 +
     7299+               
     7300+               if(state == YAFFS_BLOCK_STATE_NEEDS_SCANNING)
     7301+               {
     7302+                       // If we got this far while scanning, then the block is fully allocated.
     7303+                       state = YAFFS_BLOCK_STATE_FULL;
     7304+               }
     7305+               
    85177306+               bi->blockState = state;
    8518 +
    8519 +               /* Now let's see if it was dirty */
    8520 +               if (bi->pagesInUse == 0 &&
    8521 +                   !bi->hasShrinkHeader &&
    8522 +                   bi->blockState == YAFFS_BLOCK_STATE_FULL) {
    8523 +                       yaffs_BlockBecameDirty(dev, blk);
    8524 +               }
    8525 +
    8526 +       }
    8527 +
    8528 +       if (blockIndex) {
     7307+               
     7308+               // Now let's see if it was dirty
     7309+               if(     bi->pagesInUse == 0 &&
     7310+                       !bi->hasShrinkHeader &&
     7311+               bi->blockState == YAFFS_BLOCK_STATE_FULL)
     7312+           {
     7313+               yaffs_BlockBecameDirty(dev,blk);
     7314+           }
     7315+
     7316+       }
     7317+       
     7318+       if(blockIndex)
     7319+       {
    85297320+               YFREE(blockIndex);
    85307321+       }
    85317322+       
    8532 +       
    8533 +       /* Ok, we've done all the scanning.
    8534 +        * Fix up the hard link chains.
    8535 +        * We should now have scanned all the objects, now it's time to add these
    8536 +        * hardlinks.
    8537 +        */
    8538 +
    8539 +       yaffs_HardlinkFixup(dev,hardList);
    8540 +
    8541 +       /* Handle the unlinked files. Since they were left in an unlinked state we should
    8542 +        * just delete them.
    8543 +        */
    8544 +       {
    8545 +               struct list_head *i;
     7323+       // Ok, we've done all the scanning.
     7324+       
     7325+       // Fix up the hard link chains.
     7326+       // We should now have scanned all the objects, now it's time to add these
     7327+       // hardlinks.
     7328+       while(hardList)
     7329+       {
     7330+               hl = hardList;
     7331+               hardList = (yaffs_Object *)(hardList->hardLinks.next);
     7332+               
     7333+               in = yaffs_FindObjectByNumber(dev,hl->variant.hardLinkVariant.equivalentObjectId);
     7334+               
     7335+               if(in)
     7336+               {
     7337+                       // Add the hardlink pointers
     7338+                       hl->variant.hardLinkVariant.equivalentObject=in;
     7339+                       list_add(&hl->hardLinks,&in->hardLinks);
     7340+               }
     7341+               else
     7342+               {
     7343+                       //Todo Need to report/handle this better.
     7344+                       // Got a problem... hardlink to a non-existant object
     7345+                       hl->variant.hardLinkVariant.equivalentObject=NULL;
     7346+                       INIT_LIST_HEAD(&hl->hardLinks);
     7347+                       
     7348+               }
     7349+               
     7350+       }
     7351+       
     7352+       // Handle the unlinked files. Since they were left in an unlinked state we should
     7353+       // just delete them.
     7354+       {
     7355+               struct list_head *i;   
    85467356+               struct list_head *n;
    8547 +
     7357+                       
    85487358+               yaffs_Object *l;
    8549 +               /* Soft delete all the unlinked files */
    8550 +               list_for_each_safe(i, n,
    8551 +                                  &dev->unlinkedDir->variant.directoryVariant.
    8552 +                                  children) {
    8553 +                       if (i) {
    8554 +                               l = list_entry(i, yaffs_Object, siblings);
    8555 +                               yaffs_DestroyObject(l);
     7359+               // Soft delete all the unlinked files
     7360+               list_for_each_safe(i,n,&dev->unlinkedDir->variant.directoryVariant.children)
     7361+               {
     7362+                       if(i)
     7363+                       {
     7364+                               l = list_entry(i, yaffs_Object,siblings);
     7365+                               yaffs_DestroyObject(l);         
    85567366+                       }
    8557 +               }
    8558 +       }
    8559 +
    8560 +       yaffs_ReleaseTempBuffer(dev, chunkData, __LINE__);
    8561 +
    8562 +       T(YAFFS_TRACE_SCAN, (TSTR("yaffs_Scan ends" TENDSTR)));
     7367+               }       
     7368+       }
     7369+       
     7370+       yaffs_ReleaseTempBuffer(dev,chunkData,__LINE__);
     7371+
     7372+       T(YAFFS_TRACE_SCAN,(TSTR("yaffs_Scan ends" TENDSTR)));
    85637373+
    85647374+       return YAFFS_OK;
    85657375+}
    85667376+
    8567 +static void yaffs_CheckObjectDetailsLoaded(yaffs_Object *in)
    8568 +{
    8569 +       __u8 *chunkData;
    8570 +       yaffs_ObjectHeader *oh;
    8571 +       yaffs_Device *dev = in->myDev;
    8572 +       yaffs_ExtendedTags tags;
    8573 +       int result;
    8574 +       
    8575 +#if 0
    8576 +       T(YAFFS_TRACE_SCAN,(TSTR("details for object %d %s loaded" TENDSTR),
    8577 +               in->objectId,
    8578 +               in->lazyLoaded ? "not yet" : "already"));
    8579 +#endif
    8580 +               
    8581 +       if(in->lazyLoaded){
    8582 +               in->lazyLoaded = 0;
    8583 +               chunkData = yaffs_GetTempBuffer(dev, __LINE__);
    8584 +
    8585 +               result = yaffs_ReadChunkWithTagsFromNAND(dev,in->chunkId,chunkData,&tags);
    8586 +               oh = (yaffs_ObjectHeader *) chunkData;         
    8587 +
    8588 +               in->yst_mode = oh->yst_mode;
    8589 +#ifdef CONFIG_YAFFS_WINCE
    8590 +               in->win_atime[0] = oh->win_atime[0];
    8591 +               in->win_ctime[0] = oh->win_ctime[0];
    8592 +               in->win_mtime[0] = oh->win_mtime[0];
    8593 +               in->win_atime[1] = oh->win_atime[1];
    8594 +               in->win_ctime[1] = oh->win_ctime[1];
    8595 +               in->win_mtime[1] = oh->win_mtime[1];
    8596 +#else
    8597 +               in->yst_uid = oh->yst_uid;
    8598 +               in->yst_gid = oh->yst_gid;
    8599 +               in->yst_atime = oh->yst_atime;
    8600 +               in->yst_mtime = oh->yst_mtime;
    8601 +               in->yst_ctime = oh->yst_ctime;
    8602 +               in->yst_rdev = oh->yst_rdev;
    8603 +               
    8604 +#endif
    8605 +               yaffs_SetObjectName(in, oh->name);
    8606 +               
    8607 +               if(in->variantType == YAFFS_OBJECT_TYPE_SYMLINK)
    8608 +                        in->variant.symLinkVariant.alias =
    8609 +                                                   yaffs_CloneString(oh->alias);
    8610 +                                                   
    8611 +               yaffs_ReleaseTempBuffer(dev,chunkData, __LINE__);
    8612 +       }
    8613 +}
    8614 +
    8615 +static int yaffs_ScanBackwards(yaffs_Device * dev)
     7377+
     7378+static int yaffs_ScanBackwards(yaffs_Device *dev)
    86167379+{
    86177380+       yaffs_ExtendedTags tags;
     
    86217384+       int endIterator;
    86227385+       int nBlocksToScan = 0;
    8623 +
     7386+       
    86247387+       int chunk;
    8625 +       int result;
    86267388+       int c;
    86277389+       int deleted;
    86287390+       yaffs_BlockState state;
    86297391+       yaffs_Object *hardList = NULL;
     7392+       yaffs_Object *hl;
    86307393+       yaffs_BlockInfo *bi;
    8631 +       int sequenceNumber;
     7394+       int sequenceNumber;     
    86327395+       yaffs_ObjectHeader *oh;
    86337396+       yaffs_Object *in;
    86347397+       yaffs_Object *parent;
    86357398+       int nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1;
    8636 +       int itsUnlinked;
     7399+       
    86377400+       __u8 *chunkData;
    8638 +       
    8639 +       int fileSize;
    8640 +       int isShrink;
    8641 +       int foundChunksInBlock;
    8642 +       int equivalentObjectId;
    8643 +       
    86447401+
    86457402+       yaffs_BlockIndex *blockIndex = NULL;
    8646 +       int altBlockIndex = 0;
    8647 +
    8648 +       if (!dev->isYaffs2) {
    8649 +               T(YAFFS_TRACE_SCAN,
    8650 +                 (TSTR("yaffs_ScanBackwards is only for YAFFS2!" TENDSTR)));
     7403+
     7404+
     7405+       if(!dev->isYaffs2)
     7406+       {
     7407+               T(YAFFS_TRACE_SCAN,(TSTR("yaffs_ScanBackwards is only for YAFFS2!" TENDSTR)));
    86517408+               return YAFFS_FAIL;
    86527409+       }
    8653 +
    8654 +       T(YAFFS_TRACE_SCAN,
    8655 +         (TSTR
    8656 +          ("yaffs_ScanBackwards starts  intstartblk %d intendblk %d..."
    8657 +           TENDSTR), dev->internalStartBlock, dev->internalEndBlock));
    8658 +
    8659 +
     7410+       
     7411+       T(YAFFS_TRACE_SCAN,(TSTR("yaffs_ScanBackwards starts  intstartblk %d intendblk %d..." TENDSTR),dev->internalStartBlock,dev->internalEndBlock));
     7412+               
     7413+       chunkData = yaffs_GetTempBuffer(dev,__LINE__);
     7414+       
     7415+       
    86607416+       dev->sequenceNumber = YAFFS_LOWEST_SEQUENCE_NUMBER;
    8661 +
    8662 +       blockIndex = YMALLOC(nBlocks * sizeof(yaffs_BlockIndex));
    8663 +       
    8664 +       if(!blockIndex) {
    8665 +               blockIndex = YMALLOC_ALT(nBlocks * sizeof(yaffs_BlockIndex));
    8666 +               altBlockIndex = 1;
    8667 +       }
    8668 +       
    8669 +       if(!blockIndex) {
    8670 +               T(YAFFS_TRACE_SCAN,
    8671 +                 (TSTR("yaffs_Scan() could not allocate block index!" TENDSTR)));
    8672 +               return YAFFS_FAIL;
    8673 +       }
    8674 +       
    8675 +       chunkData = yaffs_GetTempBuffer(dev, __LINE__);
    8676 +
    8677 +       /* Scan all the blocks to determine their state */
    8678 +       for (blk = dev->internalStartBlock; blk <= dev->internalEndBlock; blk++) {
    8679 +               bi = yaffs_GetBlockInfo(dev, blk);
    8680 +               yaffs_ClearChunkBits(dev, blk);
     7417+       
     7418+       blockIndex = YMALLOC(nBlocks * sizeof(yaffs_BlockIndex));               
     7419+       
     7420+       
     7421+       // Scan all the blocks to determine their state
     7422+       for(blk = dev->internalStartBlock; blk <= dev->internalEndBlock; blk++)
     7423+       {
     7424+               bi = yaffs_GetBlockInfo(dev,blk);
     7425+               yaffs_ClearChunkBits(dev,blk);
    86817426+               bi->pagesInUse = 0;
    86827427+               bi->softDeletions = 0;
    8683 +
    8684 +               yaffs_QueryInitialBlockState(dev, blk, &state, &sequenceNumber);
    8685 +
     7428+                               
     7429+               yaffs_QueryInitialBlockState(dev,blk,&state,&sequenceNumber);
     7430+               
    86867431+               bi->blockState = state;
    8687 +               bi->sequenceNumber = sequenceNumber;
    8688 +
    8689 +               if(bi->sequenceNumber == YAFFS_SEQUENCE_CHECKPOINT_DATA)
    8690 +                       bi->blockState = state = YAFFS_BLOCK_STATE_CHECKPOINT;
    8691 +                       
    8692 +               T(YAFFS_TRACE_SCAN_DEBUG,
    8693 +                 (TSTR("Block scanning block %d state %d seq %d" TENDSTR), blk,
    8694 +                  state, sequenceNumber));
    8695 +
    8696 +               
    8697 +               if(state == YAFFS_BLOCK_STATE_CHECKPOINT){
    8698 +                       /* todo .. fix free space ? */
    8699 +                       
    8700 +               } else if (state == YAFFS_BLOCK_STATE_DEAD) {
    8701 +                       T(YAFFS_TRACE_BAD_BLOCKS,
    8702 +                         (TSTR("block %d is bad" TENDSTR), blk));
    8703 +               } else if (state == YAFFS_BLOCK_STATE_EMPTY) {
    8704 +                       T(YAFFS_TRACE_SCAN_DEBUG,
    8705 +                         (TSTR("Block empty " TENDSTR)));
     7432+               bi->sequenceNumber = sequenceNumber;
     7433+
     7434+               T(YAFFS_TRACE_SCAN_DEBUG,(TSTR("Block scanning block %d state %d seq %d" TENDSTR),blk,state,sequenceNumber));
     7435+               
     7436+               if(state == YAFFS_BLOCK_STATE_DEAD)
     7437+               {
     7438+                       T(YAFFS_TRACE_BAD_BLOCKS,(TSTR("block %d is bad" TENDSTR),blk));
     7439+               }
     7440+               else if(state == YAFFS_BLOCK_STATE_EMPTY)
     7441+               {
     7442+                       T(YAFFS_TRACE_SCAN_DEBUG,(TSTR("Block empty " TENDSTR)));
    87067443+                       dev->nErasedBlocks++;
    87077444+                       dev->nFreeChunks += dev->nChunksPerBlock;
    8708 +               } else if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) {
    8709 +
    8710 +                       /* Determine the highest sequence number */
    8711 +                       if (dev->isYaffs2 &&
     7445+               }
     7446+               else if(state == YAFFS_BLOCK_STATE_NEEDS_SCANNING)
     7447+               {
     7448+                                       
     7449+                       // Determine the highest sequence number
     7450+                       if( dev->isYaffs2 &&
    87127451+                           sequenceNumber >= YAFFS_LOWEST_SEQUENCE_NUMBER &&
    8713 +                           sequenceNumber < YAFFS_HIGHEST_SEQUENCE_NUMBER) {
    8714 +
     7452+                           sequenceNumber < YAFFS_HIGHEST_SEQUENCE_NUMBER)
     7453+                        {
     7454+                               
    87157455+                               blockIndex[nBlocksToScan].seq = sequenceNumber;
    87167456+                               blockIndex[nBlocksToScan].block = blk;
    8717 +
     7457+                               
    87187458+                               nBlocksToScan++;
    87197459+
    8720 +                               if (sequenceNumber >= dev->sequenceNumber) {
    8721 +                                       dev->sequenceNumber = sequenceNumber;
     7460+                               if(sequenceNumber >= dev->sequenceNumber)
     7461+                               {
     7462+                                       dev->sequenceNumber = sequenceNumber;
    87227463+                               }
    8723 +                       } else if (dev->isYaffs2) {
    8724 +                               /* TODO: Nasty sequence number! */
    8725 +                               T(YAFFS_TRACE_SCAN,
    8726 +                                 (TSTR
    8727 +                                  ("Block scanning block %d has bad sequence number %d"
    8728 +                                   TENDSTR), blk, sequenceNumber));
    8729 +
    87307464+                       }
    8731 +               }
    8732 +       }
    8733 +
    8734 +       T(YAFFS_TRACE_SCAN,
    8735 +       (TSTR("%d blocks to be sorted..." TENDSTR), nBlocksToScan));
    8736 +
    8737 +
    8738 +
    8739 +       YYIELD();
    8740 +
    8741 +       /* Sort the blocks */
    8742 +#ifndef CONFIG_YAFFS_USE_OWN_SORT
    8743 +       {
    8744 +               /* Use qsort now. */
    8745 +               qsort(blockIndex, nBlocksToScan, sizeof(yaffs_BlockIndex), ybicmp);
    8746 +       }
    8747 +#else
    8748 +       {
    8749 +               /* Dungy old bubble sort... */
    8750 +               
     7465+                       else if(dev->isYaffs2)
     7466+                       {
     7467+                               // TODO: Nasty sequence number!
     7468+                               T(YAFFS_TRACE_SCAN,(TSTR("Block scanning block %d has bad sequence number %d" TENDSTR),blk,sequenceNumber));
     7469+
     7470+                       }
     7471+               }
     7472+       }
     7473+       
     7474+       // Sort the blocks
     7475+       // Dungy old bubble sort for now...
     7476+       {
    87517477+               yaffs_BlockIndex temp;
    87527478+               int i;
    87537479+               int j;
    8754 +
    8755 +               for (i = 0; i < nBlocksToScan; i++)
    8756 +                       for (j = i + 1; j < nBlocksToScan; j++)
    8757 +                               if (blockIndex[i].seq > blockIndex[j].seq) {
    8758 +                                       temp = blockIndex[j];
    8759 +                                       blockIndex[j] = blockIndex[i];
    8760 +                                       blockIndex[i] = temp;
    8761 +                               }
    8762 +       }
    8763 +#endif
    8764 +
    8765 +       YYIELD();
    8766 +
    8767 +       T(YAFFS_TRACE_SCAN, (TSTR("...done" TENDSTR)));
    8768 +
    8769 +       /* Now scan the blocks looking at the data. */
     7480+               
     7481+               for(i = 0; i < nBlocksToScan; i++)
     7482+                       for(j = i+1; j < nBlocksToScan; j++)
     7483+                        if(blockIndex[i].seq > blockIndex[j].seq)
     7484+                        {
     7485+                               temp = blockIndex[j];
     7486+                               blockIndex[j] = blockIndex[i];
     7487+                               blockIndex[i] = temp;
     7488+                        }
     7489+       }
     7490+       
     7491+       
     7492+       // Now scan the blocks looking at the data.
    87707493+       startIterator = 0;
    8771 +       endIterator = nBlocksToScan - 1;
    8772 +       T(YAFFS_TRACE_SCAN_DEBUG,
    8773 +         (TSTR("%d blocks to be scanned" TENDSTR), nBlocksToScan));
    8774 +
    8775 +       /* For each block.... backwards */
    8776 +       for (blockIterator = endIterator; blockIterator >= startIterator;
    8777 +            blockIterator--) {
    8778 +               /* Cooperative multitasking! This loop can run for so
    8779 +                  long that watchdog timers expire. */
    8780 +               YYIELD();
    8781 +
    8782 +               /* get the block to scan in the correct order */
     7494+       endIterator = nBlocksToScan-1;
     7495+       T(YAFFS_TRACE_SCAN_DEBUG,(TSTR("%d blocks to be scanned" TENDSTR),nBlocksToScan));
     7496+
     7497+       
     7498+       // For each block.... backwards
     7499+       for(blockIterator = endIterator; blockIterator >= startIterator; blockIterator--)
     7500+       {
     7501+       
     7502+               // get the block to scan in the correct order
    87837503+               blk = blockIndex[blockIterator].block;
    87847504+
    8785 +               bi = yaffs_GetBlockInfo(dev, blk);
     7505+
     7506+               bi = yaffs_GetBlockInfo(dev,blk);
    87867507+               state = bi->blockState;
    8787 +
     7508+               
    87887509+               deleted = 0;
    8789 +
    8790 +               /* For each chunk in each block that needs scanning.... */
    8791 +               foundChunksInBlock = 0;
    8792 +               for (c = dev->nChunksPerBlock - 1; c >= 0 &&
    8793 +                    (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING ||
    8794 +                     state == YAFFS_BLOCK_STATE_ALLOCATING); c--) {
    8795 +                       /* Scan backwards...
    8796 +                        * Read the tags and decide what to do
    8797 +                        */
     7510+               
     7511+               if( 0 && // Disable since this is redundant.
     7512+                   state == YAFFS_BLOCK_STATE_NEEDS_SCANNING)
     7513+               {
     7514+                       // Let's look at the first chunk in the block
     7515+                       chunk = blk * dev->nChunksPerBlock;
     7516+                       
     7517+                       yaffs_ReadChunkWithTagsFromNAND(dev,chunk,NULL,&tags);
     7518+
     7519+                       // Let's have a good look at this chunk...
     7520+       
     7521+                       if(!tags.chunkUsed)
     7522+                       {
     7523+                               // An unassigned chunk in the block
     7524+                               // This means that either the block is empty or
     7525+                               // this is the one being allocated from
     7526+                               
     7527+                               // We're looking at the first chunk in the block so the block is unused
     7528+                               state = YAFFS_BLOCK_STATE_EMPTY;
     7529+                               dev->nErasedBlocks++;
     7530+                               dev->nFreeChunks += dev->nChunksPerBlock;
     7531+                       }
     7532+               
     7533+               }
     7534+               
     7535+               // For each chunk in each block that needs scanning....
     7536+               for(c = dev->nChunksPerBlock-1; c >= 0 &&
     7537+                                 (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING ||
     7538+                                  state == YAFFS_BLOCK_STATE_ALLOCATING); c--)
     7539+               {
     7540+                       // Scan backwards...
     7541+                       // Read the tags and decide what to do
    87987542+                       chunk = blk * dev->nChunksPerBlock + c;
    8799 +
    8800 +                       result = yaffs_ReadChunkWithTagsFromNAND(dev, chunk, NULL,
    8801 +                                                       &tags);
    8802 +
    8803 +                       /* Let's have a good look at this chunk... */
    8804 +
    8805 +                       if (!tags.chunkUsed) {
    8806 +                               /* An unassigned chunk in the block.
    8807 +                                * If there are used chunks after this one, then
    8808 +                                * it is a chunk that was skipped due to failing the erased
    8809 +                                * check. Just skip it so that it can be deleted.
    8810 +                                * But, more typically, We get here when this is an unallocated
    8811 +                                * chunk and his means that either the block is empty or
    8812 +                                * this is the one being allocated from
    8813 +                                */
    8814 +
    8815 +                               if(foundChunksInBlock)
     7543+                       
     7544+                       yaffs_ReadChunkWithTagsFromNAND(dev,chunk,NULL,&tags);
     7545+
     7546+                       // Let's have a good look at this chunk...
     7547+       
     7548+                       if(!tags.chunkUsed)
     7549+                       {
     7550+                               // An unassigned chunk in the block
     7551+                               // This means that either the block is empty or
     7552+                               // this is the one being allocated from
     7553+                               
     7554+                               if(c == 0)
    88167555+                               {
    8817 +                                       /* This is a chunk that was skipped due to failing the erased check */
    8818 +                                       
    8819 +                               } else if (c == 0) {
    8820 +                                       /* We're looking at the first chunk in the block so the block is unused */
     7556+                                       // We're looking at the first chunk in the block so the block is unused
    88217557+                                       state = YAFFS_BLOCK_STATE_EMPTY;
    88227558+                                       dev->nErasedBlocks++;
    8823 +                               } else {
    8824 +                                       if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING ||
    8825 +                                           state == YAFFS_BLOCK_STATE_ALLOCATING) {
    8826 +                                               if(dev->sequenceNumber == bi->sequenceNumber) {
    8827 +                                                       /* this is the block being allocated from */
    8828 +                                               
    8829 +                                                       T(YAFFS_TRACE_SCAN,
    8830 +                                                         (TSTR
    8831 +                                                          (" Allocating from %d %d"
    8832 +                                                           TENDSTR), blk, c));
    8833 +
    8834 +                                                       state = YAFFS_BLOCK_STATE_ALLOCATING;
    8835 +                                                       dev->allocationBlock = blk;
    8836 +                                                       dev->allocationPage = c;
    8837 +                                                       dev->allocationBlockFinder = blk;       
    8838 +                                               }
    8839 +                                               else {
    8840 +                                                       /* This is a partially written block that is not
    8841 +                                                        * the current allocation block. This block must have
    8842 +                                                        * had a write failure, so set up for retirement.
    8843 +                                                        */
    8844 +                                                 
    8845 +                                                        bi->needsRetiring = 1;
    8846 +                                                        bi->gcPrioritise = 1;
    8847 +                                                                                                       
    8848 +                                                        T(YAFFS_TRACE_ALWAYS,
    8849 +                                                        (TSTR("Partially written block %d being set for retirement" TENDSTR),
    8850 +                                                        blk));
    8851 +                                               }
    8852 +
     7559+                               }
     7560+                               else
     7561+                               {
     7562+                                       // this is the block being allocated from
     7563+                                       if(state == YAFFS_BLOCK_STATE_NEEDS_SCANNING)
     7564+                                       {
     7565+                                         T(YAFFS_TRACE_SCAN,(TSTR(" Allocating from %d %d" TENDSTR),blk,c));
    88537566+                                       }
    8854 +                                       
     7567+                                       state = YAFFS_BLOCK_STATE_ALLOCATING;
     7568+                                       dev->allocationBlock = blk;
     7569+                                       dev->allocationPage = c;
     7570+                                       dev->allocationBlockFinder = blk; // Set it to here to encourage the allocator to
     7571+                                                                                                         // go forth from here.
     7572+                                       //Yaffs2 sanity check:
     7573+                                       // This should be the one with the highest sequence number
     7574+                                       if(dev->isYaffs2 && (dev->sequenceNumber != bi->sequenceNumber))
     7575+                                       {
     7576+                                               T(YAFFS_TRACE_ALWAYS,
     7577+                                                               (TSTR("yaffs: Allocation block %d was not highest sequence id: block seq = %d, dev seq = %d" TENDSTR),
     7578+                                                               blk,bi->sequenceNumber,dev->sequenceNumber));
     7579+                                       }
    88557580+                               }
    88567581+
    8857 +                               dev->nFreeChunks++;
     7582+                               dev->nFreeChunks ++;
     7583+                       }
     7584+                       else if(tags.chunkId > 0)
     7585+                       {
     7586+                               // chunkId > 0 so it is a data chunk...
     7587+                               unsigned int endpos;
    88587588+                               
    8859 +                       } else if (tags.chunkId > 0) {
    8860 +                               /* chunkId > 0 so it is a data chunk... */
    8861 +                               unsigned int endpos;
    8862 +                               __u32 chunkBase =
    8863 +                                   (tags.chunkId - 1) * dev->nDataBytesPerChunk;
     7589+                               __u32 chunkBase = (tags.chunkId - 1)* dev->nBytesPerChunk;
     7590+
     7591+                               yaffs_SetChunkBit(dev,blk,c);
     7592+                               bi->pagesInUse++;
    88647593+                                                               
    8865 +                               foundChunksInBlock = 1;
    8866 +
    8867 +
    8868 +                               yaffs_SetChunkBit(dev, blk, c);
     7594+                               in = yaffs_FindOrCreateObjectByNumber(dev,tags.objectId,YAFFS_OBJECT_TYPE_FILE);
     7595+                               if(in->variantType == YAFFS_OBJECT_TYPE_FILE &&
     7596+                                  chunkBase < in->variant.fileVariant.shrinkSize)
     7597+                               {
     7598+                                       // This has not been invalidated by a resize
     7599+                                       yaffs_PutChunkIntoFile(in,tags.chunkId,chunk,-1);
     7600+                               
     7601+                               
     7602+                                       // File size is calculated by looking at the data chunks if we have not
     7603+                                       // seen an object header yet. Stop this practice once we find an object header.
     7604+                                       endpos = (tags.chunkId - 1)* dev->nBytesPerChunk + tags.byteCount;
     7605+                                       if(!in->valid && // have not got an object header yet
     7606+                                          in->variant.fileVariant.scannedFileSize <endpos)
     7607+                                       {
     7608+                                               in->variant.fileVariant.scannedFileSize = endpos;
     7609+                                               in->variant.fileVariant.fileSize = in->variant.fileVariant.scannedFileSize;
     7610+                                       }
     7611+
     7612+                               }
     7613+                               else
     7614+                               {
     7615+                                       // This chunk has been invalidated by a resize, so delete
     7616+                                       yaffs_DeleteChunk(dev,chunk,1,__LINE__);
     7617+                                       
     7618+                                       
     7619+                               }
     7620+                               //T((" %d %d data %d %d\n",blk,c,tags.objectId,tags.chunkId)); 
     7621+                       }
     7622+                       else
     7623+                       {
     7624+                               // chunkId == 0, so it is an ObjectHeader.
     7625+                               // Thus, we read in the object header and make the object
     7626+                               yaffs_SetChunkBit(dev,blk,c);
    88697627+                               bi->pagesInUse++;
    8870 +
    8871 +                               in = yaffs_FindOrCreateObjectByNumber(dev,
    8872 +                                                                     tags.
    8873 +                                                                     objectId,
    8874 +                                                                     YAFFS_OBJECT_TYPE_FILE);
    8875 +                               if (in->variantType == YAFFS_OBJECT_TYPE_FILE
    8876 +                                   && chunkBase <
    8877 +                                   in->variant.fileVariant.shrinkSize) {
    8878 +                                       /* This has not been invalidated by a resize */
    8879 +                                       yaffs_PutChunkIntoFile(in, tags.chunkId,
    8880 +                                                              chunk, -1);
    8881 +
    8882 +                                       /* File size is calculated by looking at the data chunks if we have not
    8883 +                                        * seen an object header yet. Stop this practice once we find an object header.
    8884 +                                        */
    8885 +                                       endpos =
    8886 +                                           (tags.chunkId -
    8887 +                                            1) * dev->nDataBytesPerChunk +
    8888 +                                           tags.byteCount;
    8889 +                                           
    8890 +                                       if (!in->valid &&       /* have not got an object header yet */
    8891 +                                           in->variant.fileVariant.
    8892 +                                           scannedFileSize < endpos) {
    8893 +                                               in->variant.fileVariant.
    8894 +                                                   scannedFileSize = endpos;
    8895 +                                               in->variant.fileVariant.
    8896 +                                                   fileSize =
    8897 +                                                   in->variant.fileVariant.
    8898 +                                                   scannedFileSize;
    8899 +                                       }
    8900 +
    8901 +                               } else {
    8902 +                                       /* This chunk has been invalidated by a resize, so delete */
    8903 +                                       yaffs_DeleteChunk(dev, chunk, 1, __LINE__);
    8904 +
    8905 +                               }
    8906 +                       } else {
    8907 +                               /* chunkId == 0, so it is an ObjectHeader.
    8908 +                                * Thus, we read in the object header and make the object
    8909 +                                */
    8910 +                               foundChunksInBlock = 1;
    8911 +
    8912 +                               yaffs_SetChunkBit(dev, blk, c);
    8913 +                               bi->pagesInUse++;
    8914 +
     7628+                               
    89157629+                               oh = NULL;
    89167630+                               in = NULL;
    8917 +
    8918 +                               if (tags.extraHeaderInfoAvailable) {
    8919 +                                       in = yaffs_FindOrCreateObjectByNumber
    8920 +                                           (dev, tags.objectId,
    8921 +                                            tags.extraObjectType);
     7631+                               
     7632+                               if(tags.extraHeaderInfoAvailable)
     7633+                               {
     7634+                                       in = yaffs_FindOrCreateObjectByNumber(dev,tags.objectId,tags.extraObjectType);
    89227635+                               }
    89237636+
    8924 +                               if (!in ||
    8925 +#ifdef CONFIG_YAFFS_DISABLE_LAZY_LOAD
    8926 +                                   !in->valid ||
    8927 +#endif
    8928 +                                   tags.extraShadows ||
    8929 +                                   (!in->valid &&
    8930 +                                   (tags.objectId == YAFFS_OBJECTID_ROOT ||
    8931 +                                    tags.objectId == YAFFS_OBJECTID_LOSTNFOUND))
    8932 +                                   ) {
    8933 +
    8934 +                                       /* If we don't have  valid info then we need to read the chunk
    8935 +                                        * TODO In future we can probably defer reading the chunk and
    8936 +                                        * living with invalid data until needed.
    8937 +                                        */
    8938 +
    8939 +                                       result = yaffs_ReadChunkWithTagsFromNAND(dev,
    8940 +                                                                       chunk,
    8941 +                                                                       chunkData,
    8942 +                                                                       NULL);
    8943 +
    8944 +                                       oh = (yaffs_ObjectHeader *) chunkData;
    8945 +
    8946 +                                       if (!in)
    8947 +                                               in = yaffs_FindOrCreateObjectByNumber(dev, tags.objectId, oh->type);
    8948 +
     7637+                               
     7638+                               if(!in || !in->valid)
     7639+                               {
     7640+                               
     7641+                                       // If we don't have  valid info then we need to read the chunk
     7642+                                       // TODO In future we can probably defer reading the chunk and
     7643+                                       // living with invalid data until needed.
     7644+                                                               
     7645+                                       yaffs_ReadChunkWithTagsFromNAND(dev,chunk,chunkData,NULL);
     7646+                               
     7647+                                       oh = (yaffs_ObjectHeader *)chunkData;
     7648+                               
     7649+                                       if(!in)
     7650+                                          in = yaffs_FindOrCreateObjectByNumber(dev,tags.objectId,oh->type);
     7651+                                       
    89497652+                               }
    8950 +
    8951 +                               if (!in) {
    8952 +                                       /* TODO Hoosterman we have a problem! */
    8953 +                                       T(YAFFS_TRACE_ERROR,
    8954 +                                         (TSTR
    8955 +                                          ("yaffs tragedy: Could not make object for object  %d  "
    8956 +                                           "at chunk %d during scan"
    8957 +                                           TENDSTR), tags.objectId, chunk));
     7653+                               
     7654+                               if(!in)
     7655+                               {
     7656+                                       // TODO Hoosterman we have a problem!
     7657+                                       T(YAFFS_TRACE_ERROR, (TSTR("yaffs tragedy: Could not make object for object  %d  at chunk %d during scan" TENDSTR),tags.objectId,chunk));
    89587658+
    89597659+                               }
    8960 +
    8961 +                               if (in->valid) {
    8962 +                                       /* We have already filled this one.
    8963 +                                        * We have a duplicate that will be discarded, but
    8964 +                                        * we first have to suck out resize info if it is a file.
    8965 +                                        */
    8966 +
    8967 +                                       if ((in->variantType == YAFFS_OBJECT_TYPE_FILE) &&
    8968 +                                            ((oh &&
    8969 +                                              oh-> type == YAFFS_OBJECT_TYPE_FILE)||
    8970 +                                             (tags.extraHeaderInfoAvailable  &&
    8971 +                                              tags.extraObjectType == YAFFS_OBJECT_TYPE_FILE))
    8972 +                                           ) {
    8973 +                                               __u32 thisSize =
    8974 +                                                   (oh) ? oh->fileSize : tags.
    8975 +                                                   extraFileLength;
    8976 +                                               __u32 parentObjectId =
    8977 +                                                   (oh) ? oh->
    8978 +                                                   parentObjectId : tags.
    8979 +                                                   extraParentObjectId;
    8980 +                                               unsigned isShrink =
    8981 +                                                   (oh) ? oh->isShrink : tags.
    8982 +                                                   extraIsShrinkHeader;
    8983 +
    8984 +                                               /* If it is deleted (unlinked at start also means deleted)
    8985 +                                                * we treat the file size as being zeroed at this point.
    8986 +                                                */
    8987 +                                               if (parentObjectId ==
    8988 +                                                   YAFFS_OBJECTID_DELETED
    8989 +                                                   || parentObjectId ==
    8990 +                                                   YAFFS_OBJECTID_UNLINKED) {
     7660+                               
     7661+                               if(in->valid)
     7662+                               {
     7663+                                       // We have already filled this one. We have a duplicate that will be discarded, but
     7664+                                       // we first have to suck out resize info if it is a file.
     7665+                                       
     7666+                                       if( (in->variantType == YAFFS_OBJECT_TYPE_FILE) &&
     7667+                                           ((oh && oh->type == YAFFS_OBJECT_TYPE_FILE) ||
     7668+                                           (tags.extraHeaderInfoAvailable && tags.extraObjectType == YAFFS_OBJECT_TYPE_FILE))
     7669+                                          )
     7670+                                       {
     7671+                                               __u32 thisSize = (oh) ? oh->fileSize : tags.extraFileLength;
     7672+                                               __u32 parentObjectId = (oh) ? oh->parentObjectId : tags.extraParentObjectId;
     7673+                                               unsigned isShrink = (oh)  ? oh->isShrink : tags.extraIsShrinkHeader;
     7674+                                               
     7675+                                               // If it is deleted (unlinked at start also means deleted)
     7676+                                               // we treat the file size as being zeroed at this point.
     7677+                                               if(parentObjectId == YAFFS_OBJECTID_DELETED ||
     7678+                                                  parentObjectId == YAFFS_OBJECTID_UNLINKED)
     7679+                                               {
    89917680+                                                       thisSize = 0;
    89927681+                                                       isShrink = 1;
    89937682+                                               }
    8994 +
    8995 +                                               if (isShrink &&
    8996 +                                                   in->variant.fileVariant.
    8997 +                                                   shrinkSize > thisSize) {
    8998 +                                                       in->variant.fileVariant.
    8999 +                                                           shrinkSize =
    9000 +                                                           thisSize;
     7683+                                                                                               
     7684+                                               if(isShrink &&
     7685+                                                  in->variant.fileVariant.shrinkSize > thisSize)
     7686+                                               {
     7687+                                                       in->variant.fileVariant.shrinkSize = thisSize;
    90017688+                                               }
    9002 +
    9003 +                                               if (isShrink) {
     7689+                                               
     7690+                                               if(isShrink)
     7691+                                               {
    90047692+                                                       bi->hasShrinkHeader = 1;
    90057693+                                               }
    9006 +
     7694+                                               
    90077695+                                       }
    9008 +                                       /* Use existing - destroy this one. */
    9009 +                                       yaffs_DeleteChunk(dev, chunk, 1, __LINE__);
    9010 +
     7696+                                       // Use existing - destroy this one.
     7697+                                       yaffs_DeleteChunk(dev,chunk,1,__LINE__);
     7698+               
    90117699+                               }
    9012 +
    9013 +                               if (!in->valid &&
    9014 +                                   (tags.objectId == YAFFS_OBJECTID_ROOT ||
    9015 +                                    tags.objectId ==
    9016 +                                    YAFFS_OBJECTID_LOSTNFOUND)) {
    9017 +                                       /* We only load some info, don't fiddle with directory structure */
     7700+                               
     7701+                               if(!in->valid &&
     7702+                                  (tags.objectId == YAFFS_OBJECTID_ROOT ||
     7703+                                   tags.objectId == YAFFS_OBJECTID_LOSTNFOUND))
     7704+                               {
     7705+                                       // We only load some info, don't fiddle with directory structure
    90187706+                                       in->valid = 1;
     7707+                                       in->variantType = oh->type;
     7708+       
     7709+                                       in->yst_mode  = oh->yst_mode;
     7710+#ifdef CONFIG_YAFFS_WINCE
     7711+                                       in->win_atime[0] = oh->win_atime[0];
     7712+                                       in->win_ctime[0] = oh->win_ctime[0];
     7713+                                       in->win_mtime[0] = oh->win_mtime[0];
     7714+                                       in->win_atime[1] = oh->win_atime[1];
     7715+                                       in->win_ctime[1] = oh->win_ctime[1];
     7716+                                       in->win_mtime[1] = oh->win_mtime[1];
     7717+#else
     7718+                                       in->yst_uid   = oh->yst_uid;
     7719+                                       in->yst_gid   = oh->yst_gid;
     7720+                                       in->yst_atime = oh->yst_atime;
     7721+                                       in->yst_mtime = oh->yst_mtime;
     7722+                                       in->yst_ctime = oh->yst_ctime;
     7723+                                       in->yst_rdev = oh->yst_rdev;
     7724+#endif
     7725+                                       in->chunkId  = chunk;
     7726+
     7727+                               }
     7728+                               else if(!in->valid)
     7729+                               {
     7730+                                       // we need to load this info
     7731+                               
     7732+                                       in->valid = 1;
     7733+                                       in->variantType = oh->type;
     7734+       
     7735+                                       in->yst_mode  = oh->yst_mode;
     7736+#ifdef CONFIG_YAFFS_WINCE
     7737+                                       in->win_atime[0] = oh->win_atime[0];
     7738+                                       in->win_ctime[0] = oh->win_ctime[0];
     7739+                                       in->win_mtime[0] = oh->win_mtime[0];
     7740+                                       in->win_atime[1] = oh->win_atime[1];
     7741+                                       in->win_ctime[1] = oh->win_ctime[1];
     7742+                                       in->win_mtime[1] = oh->win_mtime[1];
     7743+#else
     7744+                                       in->yst_uid   = oh->yst_uid;
     7745+                                       in->yst_gid   = oh->yst_gid;
     7746+                                       in->yst_atime = oh->yst_atime;
     7747+                                       in->yst_mtime = oh->yst_mtime;
     7748+                                       in->yst_ctime = oh->yst_ctime;
     7749+                                       in->yst_rdev = oh->yst_rdev;
     7750+#endif
     7751+                                       in->chunkId  = chunk;
    90197752+                                       
    9020 +                                       if(oh) {
    9021 +                                               in->variantType = oh->type;
    9022 +
    9023 +                                               in->yst_mode = oh->yst_mode;
    9024 +#ifdef CONFIG_YAFFS_WINCE
    9025 +                                               in->win_atime[0] = oh->win_atime[0];
    9026 +                                               in->win_ctime[0] = oh->win_ctime[0];
    9027 +                                               in->win_mtime[0] = oh->win_mtime[0];
    9028 +                                               in->win_atime[1] = oh->win_atime[1];
    9029 +                                               in->win_ctime[1] = oh->win_ctime[1];
    9030 +                                               in->win_mtime[1] = oh->win_mtime[1];
    9031 +#else
    9032 +                                               in->yst_uid = oh->yst_uid;
    9033 +                                               in->yst_gid = oh->yst_gid;
    9034 +                                               in->yst_atime = oh->yst_atime;
    9035 +                                               in->yst_mtime = oh->yst_mtime;
    9036 +                                               in->yst_ctime = oh->yst_ctime;
    9037 +                                               in->yst_rdev = oh->yst_rdev;
    9038 +               
    9039 +#endif
    9040 +                                       } else {
    9041 +                                               in->variantType = tags.extraObjectType;
    9042 +                                               in->lazyLoaded = 1;
     7753+                                       if(oh->shadowsObject > 0)
     7754+                                       {
     7755+                                               yaffs_HandleShadowedObject(dev,oh->shadowsObject,0);
    90437756+                                       }
    9044 +                                               
    9045 +                                       in->chunkId = chunk;
    9046 +
    9047 +                               } else if (!in->valid) {
    9048 +                                       /* we need to load this info */
    9049 +
    9050 +                                       in->valid = 1;
    9051 +                                       in->chunkId = chunk;
    9052 +                                       
    9053 +                                       if(oh) {
    9054 +                                               in->variantType = oh->type;
    9055 +
    9056 +                                               in->yst_mode = oh->yst_mode;
    9057 +#ifdef CONFIG_YAFFS_WINCE
    9058 +                                               in->win_atime[0] = oh->win_atime[0];
    9059 +                                               in->win_ctime[0] = oh->win_ctime[0];
    9060 +                                               in->win_mtime[0] = oh->win_mtime[0];
    9061 +                                               in->win_atime[1] = oh->win_atime[1];
    9062 +                                               in->win_ctime[1] = oh->win_ctime[1];
    9063 +                                               in->win_mtime[1] = oh->win_mtime[1];
    9064 +#else
    9065 +                                               in->yst_uid = oh->yst_uid;
    9066 +                                               in->yst_gid = oh->yst_gid;
    9067 +                                               in->yst_atime = oh->yst_atime;
    9068 +                                               in->yst_mtime = oh->yst_mtime;
    9069 +                                               in->yst_ctime = oh->yst_ctime;
    9070 +                                               in->yst_rdev = oh->yst_rdev;
    9071 +#endif
    9072 +
    9073 +                                               if (oh->shadowsObject > 0)
    9074 +                                                       yaffs_HandleShadowedObject(dev,
    9075 +                                                                          oh->
    9076 +                                                                          shadowsObject,
    9077 +                                                                          1);
    9078 +                                       
    9079 +
    9080 +                                               yaffs_SetObjectName(in, oh->name);
    9081 +                                               parent =
    9082 +                                                   yaffs_FindOrCreateObjectByNumber
    9083 +                                                       (dev, oh->parentObjectId,
    9084 +                                                        YAFFS_OBJECT_TYPE_DIRECTORY);
    9085 +
    9086 +                                                fileSize = oh->fileSize;
    9087 +                                                isShrink = oh->isShrink;
    9088 +                                                equivalentObjectId = oh->equivalentObjectId;
    9089 +
     7757+
     7758+
     7759+                                       yaffs_SetObjectName(in,oh->name);
     7760+                                       in->dirty = 0;
     7761+                                                       
     7762+                                       // directory stuff...
     7763+                                       // hook up to parent
     7764+       
     7765+                                       parent = yaffs_FindOrCreateObjectByNumber(dev,oh->parentObjectId,YAFFS_OBJECT_TYPE_DIRECTORY);
     7766+                                       if(parent->variantType == YAFFS_OBJECT_TYPE_UNKNOWN)
     7767+                                       {
     7768+                                               // Set up as a directory
     7769+                                               parent->variantType = YAFFS_OBJECT_TYPE_DIRECTORY;
     7770+                                               INIT_LIST_HEAD(&parent->variant.directoryVariant.children);
    90907771+                                       }
    9091 +                                       else {
    9092 +                                               in->variantType = tags.extraObjectType;
    9093 +                                               parent =
    9094 +                                                   yaffs_FindOrCreateObjectByNumber
    9095 +                                                       (dev, tags.extraParentObjectId,
    9096 +                                                        YAFFS_OBJECT_TYPE_DIRECTORY);
    9097 +                                                fileSize = tags.extraFileLength;
    9098 +                                                isShrink = tags.extraIsShrinkHeader;
    9099 +                                                equivalentObjectId = tags.extraEquivalentObjectId;
    9100 +                                               in->lazyLoaded = 1;
    9101 +
    9102 +                                       }
    9103 +                                       in->dirty = 0;
    9104 +
    9105 +                                       /* directory stuff...
    9106 +                                        * hook up to parent
    9107 +                                        */
    9108 +
    9109 +                                       if (parent->variantType ==
    9110 +                                           YAFFS_OBJECT_TYPE_UNKNOWN) {
    9111 +                                               /* Set up as a directory */
    9112 +                                               parent->variantType =
    9113 +                                                   YAFFS_OBJECT_TYPE_DIRECTORY;
    9114 +                                               INIT_LIST_HEAD(&parent->variant.
    9115 +                                                              directoryVariant.
    9116 +                                                              children);
    9117 +                                       } else if (parent->variantType !=
    9118 +                                                  YAFFS_OBJECT_TYPE_DIRECTORY)
     7772+                                       else if(parent->variantType != YAFFS_OBJECT_TYPE_DIRECTORY)
    91197773+                                       {
    9120 +                                               /* Hoosterman, another problem....
    9121 +                                                * We're trying to use a non-directory as a directory
    9122 +                                                */
    9123 +
    9124 +                                               T(YAFFS_TRACE_ERROR,
    9125 +                                                 (TSTR
    9126 +                                                  ("yaffs tragedy: attempting to use non-directory as"
    9127 +                                                   " a directory in scan. Put in lost+found."
    9128 +                                                   TENDSTR)));
     7774+                                               // Hoosterman, another problem....
     7775+                                               // We're trying to use a non-directory as a directory
     7776+
     7777+                                               T(YAFFS_TRACE_ERROR, (TSTR("yaffs tragedy: attempting to use non-directory as a directory in scan. Put in lost+found." TENDSTR)));
    91297778+                                               parent = dev->lostNFoundDir;
    91307779+                                       }
    9131 +
    9132 +                                       yaffs_AddObjectToDirectory(parent, in);
    9133 +
    9134 +                                       itsUnlinked = (parent == dev->deletedDir) ||
    9135 +                                                     (parent == dev->unlinkedDir);
    9136 +
    9137 +                                       if (isShrink) {
    9138 +                                               /* Mark the block as having a shrinkHeader */
     7780+                               
     7781+                                       yaffs_AddObjectToDirectory(parent,in);
     7782+
     7783+                                       if((parent == dev->deletedDir ||
     7784+                                          parent == dev->unlinkedDir))
     7785+                                       {
     7786+                                               in->deleted = 1; // If it is unlinked at start up then it wants deleting
     7787+                                       }
     7788+                                       
     7789+                                       if( oh->isShrink)
     7790+                                       {
     7791+                                               // Mark the block as having a shrinkHeader
    91397792+                                               bi->hasShrinkHeader = 1;
    91407793+                                       }
    9141 +
    9142 +                                       /* Note re hardlinks.
    9143 +                                        * Since we might scan a hardlink before its equivalent object is scanned
    9144 +                                        * we put them all in a list.
    9145 +                                        * After scanning is complete, we should have all the objects, so we run
    9146 +                                        * through this list and fix up all the chains.             
    9147 +                                        */
    9148 +
    9149 +                                       switch (in->variantType) {
    9150 +                                       case YAFFS_OBJECT_TYPE_UNKNOWN:
    9151 +                                               /* Todo got a problem */
    9152 +                                               break;
    9153 +                                       case YAFFS_OBJECT_TYPE_FILE:
    9154 +
    9155 +                                               if (in->variant.fileVariant.
    9156 +                                                   scannedFileSize < fileSize) {
    9157 +                                                       /* This covers the case where the file size is greater
    9158 +                                                        * than where the data is
    9159 +                                                        * This will happen if the file is resized to be larger
    9160 +                                                        * than its current data extents.
    9161 +                                                        */
    9162 +                                                       in->variant.fileVariant.fileSize = fileSize;
    9163 +                                                       in->variant.fileVariant.scannedFileSize =
    9164 +                                                           in->variant.fileVariant.fileSize;
    9165 +                                               }
    9166 +
    9167 +                                               if (isShrink &&
    9168 +                                                   in->variant.fileVariant.shrinkSize > fileSize) {
    9169 +                                                       in->variant.fileVariant.shrinkSize = fileSize;
    9170 +                                               }
    9171 +
    9172 +                                               break;
    9173 +                                       case YAFFS_OBJECT_TYPE_HARDLINK:
    9174 +                                               if(!itsUnlinked) {
    9175 +                                                 in->variant.hardLinkVariant.equivalentObjectId =
    9176 +                                                   equivalentObjectId;
    9177 +                                                 in->hardLinks.next =
    9178 +                                                   (struct list_head *) hardList;
    9179 +                                                 hardList = in;
    9180 +                                               }
    9181 +                                               break;
    9182 +                                       case YAFFS_OBJECT_TYPE_DIRECTORY:
    9183 +                                               /* Do nothing */
    9184 +                                               break;
    9185 +                                       case YAFFS_OBJECT_TYPE_SPECIAL:
    9186 +                                               /* Do nothing */
    9187 +                                               break;
    9188 +                                       case YAFFS_OBJECT_TYPE_SYMLINK:
    9189 +                                               if(oh)
    9190 +                                                  in->variant.symLinkVariant.alias =
    9191 +                                                   yaffs_CloneString(oh->
    9192 +                                                                     alias);
    9193 +                                               break;
     7794+                                       
     7795+                               
     7796+                                       // Note re hardlinks.
     7797+                                       // Since we might scan a hardlink before its equivalent object is scanned
     7798+                                       // we put them all in a list.
     7799+                                       // After scanning is complete, we should have all the objects, so we run through this
     7800+                                       // list and fix up all the chains.             
     7801+       
     7802+                                       switch(in->variantType)
     7803+                                       {
     7804+                                               case YAFFS_OBJECT_TYPE_UNKNOWN:         // Todo got a problem
     7805+                                                       break;
     7806+                                               case YAFFS_OBJECT_TYPE_FILE:
     7807+
     7808+                                                       
     7809+                                                       if(in->variant.fileVariant.scannedFileSize < oh->fileSize)
     7810+                                                       {
     7811+                                                               in->variant.fileVariant.fileSize = oh->fileSize;
     7812+                                                               in->variant.fileVariant.scannedFileSize = in->variant.fileVariant.fileSize;
     7813+                                                       }                                                                       
     7814+                                                       
     7815+                                                       if(oh->isShrink &&
     7816+                                                          in->variant.fileVariant.shrinkSize > oh->fileSize)
     7817+                                                       {
     7818+                                                               in->variant.fileVariant.shrinkSize = oh->fileSize;
     7819+                                                       }                                               
     7820+                                                               
     7821+                                                       break;
     7822+                                               case YAFFS_OBJECT_TYPE_HARDLINK:
     7823+                                                       in->variant.hardLinkVariant.equivalentObjectId = oh->equivalentObjectId;
     7824+                                                       in->hardLinks.next = (struct list_head *)hardList;
     7825+                                                       hardList = in;
     7826+                                                       break;
     7827+                                               case YAFFS_OBJECT_TYPE_DIRECTORY:       // Do nothing
     7828+                                                       break;
     7829+                                               case YAFFS_OBJECT_TYPE_SPECIAL: // Do nothing
     7830+                                                       break;
     7831+                                               case YAFFS_OBJECT_TYPE_SYMLINK:         // Do nothing
     7832+                                                       in->variant.symLinkVariant.alias = yaffs_CloneString(oh->alias);
     7833+                                                       break;
    91947834+                                       }
    91957835+
     7836+#if 0
     7837+                                       if(parent == dev->deletedDir)
     7838+                                       {
     7839+                                               yaffs_DestroyObject(in);
     7840+                                               bi->hasShrinkHeader = 1;
     7841+                                       }
     7842+#endif
     7843+                                       //T((" %d %d header %d \"%s\" type %d\n",blk,c,tags.objectId,oh->name,in->variantType));       
    91967844+                               }
    91977845+                       }
    91987846+               }
    9199 +
    9200 +               if (state == YAFFS_BLOCK_STATE_NEEDS_SCANNING) {
    9201 +                       /* If we got this far while scanning, then the block is fully allocated. */
    9202 +                       state = YAFFS_BLOCK_STATE_FULL;
    9203 +               }
    9204 +
     7847+               
     7848+               if(state == YAFFS_BLOCK_STATE_NEEDS_SCANNING)
     7849+               {
     7850+                       // If we got this far while scanning, then the block is fully allocated.
     7851+                       state = YAFFS_BLOCK_STATE_FULL;
     7852+               }
     7853+               
    92057854+               bi->blockState = state;
    9206 +
    9207 +               /* Now let's see if it was dirty */
    9208 +               if (bi->pagesInUse == 0 &&
    9209 +                   !bi->hasShrinkHeader &&
    9210 +                   bi->blockState == YAFFS_BLOCK_STATE_FULL) {
    9211 +                       yaffs_BlockBecameDirty(dev, blk);
    9212 +               }
    9213 +
    9214 +       }
    9215 +
    9216 +       if (altBlockIndex)
    9217 +               YFREE_ALT(blockIndex);
    9218 +       else
     7855+               
     7856+               // Now let's see if it was dirty
     7857+               if(     bi->pagesInUse == 0 &&
     7858+                       !bi->hasShrinkHeader &&
     7859+               bi->blockState == YAFFS_BLOCK_STATE_FULL)
     7860+           {
     7861+               yaffs_BlockBecameDirty(dev,blk);
     7862+           }
     7863+
     7864+       }
     7865+       
     7866+       if(blockIndex)
     7867+       {
    92197868+               YFREE(blockIndex);
    9220 +       
    9221 +       /* Ok, we've done all the scanning.
    9222 +        * Fix up the hard link chains.
    9223 +        * We should now have scanned all the objects, now it's time to add these
    9224 +        * hardlinks.
    9225 +        */
    9226 +       yaffs_HardlinkFixup(dev,hardList);
    9227 +       
    9228 +       
    9229 +       /*
    9230 +       *  Sort out state of unlinked and deleted objects.
    9231 +       */
    9232 +       {
    9233 +               struct list_head *i;
     7869+       }
     7870+       
     7871+       // Ok, we've done all the scanning.
     7872+       
     7873+       // Fix up the hard link chains.
     7874+       // We should now have scanned all the objects, now it's time to add these
     7875+       // hardlinks.
     7876+       while(hardList)
     7877+       {
     7878+               hl = hardList;
     7879+               hardList = (yaffs_Object *)(hardList->hardLinks.next);
     7880+               
     7881+               in = yaffs_FindObjectByNumber(dev,hl->variant.hardLinkVariant.equivalentObjectId);
     7882+               
     7883+               if(in)
     7884+               {
     7885+                       // Add the hardlink pointers
     7886+                       hl->variant.hardLinkVariant.equivalentObject=in;
     7887+                       list_add(&hl->hardLinks,&in->hardLinks);
     7888+               }
     7889+               else
     7890+               {
     7891+                       //Todo Need to report/handle this better.
     7892+                       // Got a problem... hardlink to a non-existant object
     7893+                       hl->variant.hardLinkVariant.equivalentObject=NULL;
     7894+                       INIT_LIST_HEAD(&hl->hardLinks);
     7895+                       
     7896+               }
     7897+               
     7898+       }
     7899+       
     7900+       {
     7901+               struct list_head *i;   
    92347902+               struct list_head *n;
    9235 +
     7903+                       
    92367904+               yaffs_Object *l;
    9237 +
    9238 +               /* Soft delete all the unlinked files */
    9239 +               list_for_each_safe(i, n,
    9240 +                                  &dev->unlinkedDir->variant.directoryVariant.
    9241 +                                  children) {
    9242 +                       if (i) {
    9243 +                               l = list_entry(i, yaffs_Object, siblings);
    9244 +                               yaffs_DestroyObject(l);
     7905+               
     7906+               // Soft delete all the unlinked files
     7907+               list_for_each_safe(i,n,&dev->unlinkedDir->variant.directoryVariant.children)
     7908+               {
     7909+                       if(i)
     7910+                       {
     7911+                               l = list_entry(i, yaffs_Object,siblings);
     7912+                               yaffs_DestroyObject(l);         
    92457913+                       }
    9246 +               }
    9247 +
    9248 +               /* Soft delete all the deletedDir files */
    9249 +               list_for_each_safe(i, n,
    9250 +                                  &dev->deletedDir->variant.directoryVariant.
    9251 +                                  children) {
    9252 +                       if (i) {
    9253 +                               l = list_entry(i, yaffs_Object, siblings);
    9254 +                               yaffs_DestroyObject(l);
    9255 +
     7914+               }       
     7915+               
     7916+               // Soft delete all the deletedDir files
     7917+               list_for_each_safe(i,n,&dev->deletedDir->variant.directoryVariant.children)
     7918+               {
     7919+                       if(i)
     7920+                       {
     7921+                               l = list_entry(i, yaffs_Object,siblings);
     7922+                               yaffs_DestroyObject(l);         
     7923+                               
    92567924+                       }
    9257 +               }
    9258 +       }
    9259 +
    9260 +       yaffs_ReleaseTempBuffer(dev, chunkData, __LINE__);
    9261 +
    9262 +       T(YAFFS_TRACE_SCAN, (TSTR("yaffs_ScanBackwards ends" TENDSTR)));
     7925+               }       
     7926+       }
     7927+       
     7928+       yaffs_ReleaseTempBuffer(dev,chunkData,__LINE__);
     7929+
     7930+       T(YAFFS_TRACE_SCAN,(TSTR("yaffs_ScanBackwards ends" TENDSTR)));
    92637931+
    92647932+       return YAFFS_OK;
    92657933+}
    92667934+
    9267 +/*------------------------------  Directory Functions ----------------------------- */
    9268 +
    9269 +static void yaffs_RemoveObjectFromDirectory(yaffs_Object * obj)
    9270 +{
    9271 +       yaffs_Device *dev = obj->myDev;
    9272 +       
    9273 +       if(dev && dev->removeObjectCallback)
    9274 +               dev->removeObjectCallback(obj);
    9275 +         
    9276 +       list_del_init(&obj->siblings);
    9277 +       obj->parent = NULL;
    9278 +}
    9279 +
    9280 +
    9281 +static void yaffs_AddObjectToDirectory(yaffs_Object * directory,
    9282 +                                      yaffs_Object * obj)
    9283 +{
    9284 +
    9285 +       if (!directory) {
    9286 +               T(YAFFS_TRACE_ALWAYS,
    9287 +                 (TSTR
    9288 +                  ("tragedy: Trying to add an object to a null pointer directory"
    9289 +                   TENDSTR)));
     7935+
     7936+
     7937+////////////////////////// Directory Functions /////////////////////////
     7938+
     7939+
     7940+static void yaffs_AddObjectToDirectory(yaffs_Object *directory, yaffs_Object *obj)
     7941+{
     7942+
     7943+       if(!directory)
     7944+       {
     7945+               T(YAFFS_TRACE_ALWAYS,(TSTR("tragedy: Trying to add an object to a null pointer directory" TENDSTR)));
    92907946+               YBUG();
    92917947+       }
    9292 +       if (directory->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) {
    9293 +               T(YAFFS_TRACE_ALWAYS,
    9294 +                 (TSTR
    9295 +                  ("tragedy: Trying to add an object to a non-directory"
    9296 +                   TENDSTR)));
     7948+       if(directory->variantType != YAFFS_OBJECT_TYPE_DIRECTORY)
     7949+       {
     7950+               T(YAFFS_TRACE_ALWAYS,(TSTR("tragedy: Trying to add an object to a non-directory" TENDSTR)));
    92977951+               YBUG();
    92987952+       }
    92997953+
    9300 +       if (obj->siblings.prev == NULL) {
    9301 +               /* Not initialised */
     7954+               if(obj->siblings.prev == NULL)
     7955+       {
     7956+               // Not initialised
    93027957+               INIT_LIST_HEAD(&obj->siblings);
    9303 +
    9304 +       } else if (!list_empty(&obj->siblings)) {
    9305 +               /* If it is holed up somewhere else, un hook it */
    9306 +               yaffs_RemoveObjectFromDirectory(obj);
    9307 +       }
    9308 +       /* Now add it */
    9309 +       list_add(&obj->siblings, &directory->variant.directoryVariant.children);
     7958+               
     7959+       }
     7960+       else if(!list_empty(&obj->siblings))
     7961+       {
     7962+               // If it is holed up somewhere else, un hook it
     7963+               list_del_init(&obj->siblings);
     7964+       }
     7965+       // Now add it
     7966+       list_add(&obj->siblings,&directory->variant.directoryVariant.children);
    93107967+       obj->parent = directory;
    9311 +
    9312 +       if (directory == obj->myDev->unlinkedDir
    9313 +           || directory == obj->myDev->deletedDir) {
     7968+       
     7969+       if(directory == obj->myDev->unlinkedDir || directory == obj->myDev->deletedDir)
     7970+       {
    93147971+               obj->unlinked = 1;
    93157972+               obj->myDev->nUnlinkedFiles++;
     
    93187975+}
    93197976+
    9320 +yaffs_Object *yaffs_FindObjectByName(yaffs_Object * directory,
    9321 +                                    const YCHAR * name)
     7977+static void yaffs_RemoveObjectFromDirectory(yaffs_Object *obj)
     7978+{
     7979+       list_del_init(&obj->siblings);
     7980+       obj->parent = NULL;
     7981+}
     7982+
     7983+yaffs_Object *yaffs_FindObjectByName(yaffs_Object *directory,const YCHAR *name)
    93227984+{
    93237985+       int sum;
    9324 +
     7986+       
    93257987+       struct list_head *i;
    9326 +       YCHAR buffer[YAFFS_MAX_NAME_LENGTH + 1];
    9327 +
     7988+       YCHAR buffer[YAFFS_MAX_NAME_LENGTH+1];
     7989+       
    93287990+       yaffs_Object *l;
    9329 +
    9330 +       if (!name) {
     7991+       
     7992+       if(!name)
     7993+       {
    93317994+               return NULL;
    93327995+       }
    93337996+
    9334 +       if (!directory) {
    9335 +               T(YAFFS_TRACE_ALWAYS,
    9336 +                 (TSTR
    9337 +                  ("tragedy: yaffs_FindObjectByName: null pointer directory"
    9338 +                   TENDSTR)));
     7997+       if(!directory)
     7998+       {
     7999+               T(YAFFS_TRACE_ALWAYS,(TSTR("tragedy: yaffs_FindObjectByName: null pointer directory"TENDSTR)));
    93398000+               YBUG();
    93408001+       }
    9341 +       if (directory->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) {
    9342 +               T(YAFFS_TRACE_ALWAYS,
    9343 +                 (TSTR
    9344 +                  ("tragedy: yaffs_FindObjectByName: non-directory" TENDSTR)));
     8002+       if(directory->variantType != YAFFS_OBJECT_TYPE_DIRECTORY)
     8003+       {
     8004+               T(YAFFS_TRACE_ALWAYS,(TSTR("tragedy: yaffs_FindObjectByName: non-directory"TENDSTR)));
    93458005+               YBUG();
    93468006+       }
    93478007+
    93488008+       sum = yaffs_CalcNameSum(name);
    9349 +
    9350 +       list_for_each(i, &directory->variant.directoryVariant.children) {
    9351 +               if (i) {
    9352 +                       l = list_entry(i, yaffs_Object, siblings);
    9353 +                       
    9354 +                       yaffs_CheckObjectDetailsLoaded(l);
    9355 +
    9356 +                       /* Special case for lost-n-found */
    9357 +                       if (l->objectId == YAFFS_OBJECTID_LOSTNFOUND) {
    9358 +                               if (yaffs_strcmp(name, YAFFS_LOSTNFOUND_NAME) == 0) {
     8009+       
     8010+       list_for_each(i,&directory->variant.directoryVariant.children)
     8011+       {
     8012+               if(i)
     8013+               {
     8014+                       l = list_entry(i, yaffs_Object,siblings);
     8015+               
     8016+                       // Special case for lost-n-found
     8017+                       if(l->objectId == YAFFS_OBJECTID_LOSTNFOUND)
     8018+                       {
     8019+                               if(yaffs_strcmp(name,YAFFS_LOSTNFOUND_NAME) == 0)
     8020+                               {
    93598021+                                       return l;
    93608022+                               }
    9361 +                       } else if (yaffs_SumCompare(l->sum, sum) || l->chunkId <= 0)   
     8023+                       }
     8024+                       else if(yaffs_SumCompare(l->sum, sum)||
     8025+                                   l->chunkId <= 0) //LostnFound cunk called Objxxx
    93628026+                       {
    9363 +                               /* LostnFound cunk called Objxxx
    9364 +                                * Do a real check
    9365 +                                */
    9366 +                               yaffs_GetObjectName(l, buffer,
    9367 +                                                   YAFFS_MAX_NAME_LENGTH);
    9368 +                               if (yaffs_strcmp(name, buffer) == 0) {
     8027+                               // Do a real check
     8028+                               yaffs_GetObjectName(l,buffer,YAFFS_MAX_NAME_LENGTH);
     8029+                               if(yaffs_strcmp(name,buffer) == 0)
     8030+                               {
    93698031+                                       return l;
    93708032+                               }
    9371 +
    9372 +                       }
    9373 +               }
    9374 +       }
    9375 +
     8033+                       
     8034+                       }                       
     8035+               }
     8036+       }
     8037+       
    93768038+       return NULL;
    93778039+}
    93788040+
    93798041+
    9380 +#if 0
    9381 +int yaffs_ApplyToDirectoryChildren(yaffs_Object * theDir,
    9382 +                                  int (*fn) (yaffs_Object *))
    9383 +{
    9384 +       struct list_head *i;
     8042+int yaffs_ApplyToDirectoryChildren(yaffs_Object *theDir,int (*fn)(yaffs_Object *))
     8043+{
     8044+       struct list_head *i;   
    93858045+       yaffs_Object *l;
    9386 +
    9387 +       if (!theDir) {
    9388 +               T(YAFFS_TRACE_ALWAYS,
    9389 +                 (TSTR
    9390 +                  ("tragedy: yaffs_FindObjectByName: null pointer directory"
    9391 +                   TENDSTR)));
     8046+       
     8047+
     8048+       if(!theDir)
     8049+       {
     8050+               T(YAFFS_TRACE_ALWAYS,(TSTR("tragedy: yaffs_FindObjectByName: null pointer directory"TENDSTR)));
    93928051+               YBUG();
    93938052+       }
    9394 +       if (theDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY) {
    9395 +               T(YAFFS_TRACE_ALWAYS,
    9396 +                 (TSTR
    9397 +                  ("tragedy: yaffs_FindObjectByName: non-directory" TENDSTR)));
     8053+       if(theDir->variantType != YAFFS_OBJECT_TYPE_DIRECTORY)
     8054+       {
     8055+               T(YAFFS_TRACE_ALWAYS,(TSTR("tragedy: yaffs_FindObjectByName: non-directory"TENDSTR)));
    93988056+               YBUG();
    93998057+       }
    9400 +
    9401 +       list_for_each(i, &theDir->variant.directoryVariant.children) {
    9402 +               if (i) {
    9403 +                       l = list_entry(i, yaffs_Object, siblings);
    9404 +                       if (l && !fn(l)) {
     8058+       
     8059+       list_for_each(i,&theDir->variant.directoryVariant.children)
     8060+       {
     8061+               if(i)
     8062+               {
     8063+                       l = list_entry(i, yaffs_Object,siblings);
     8064+                       if(l && !fn(l))
     8065+                       {
    94058066+                               return YAFFS_FAIL;
    94068067+                       }
    94078068+               }
    94088069+       }
    9409 +
     8070+       
    94108071+       return YAFFS_OK;
    94118072+
    94128073+}
    9413 +#endif
    9414 +
    9415 +/* GetEquivalentObject dereferences any hard links to get to the
    9416 + * actual object.
    9417 + */
    9418 +
    9419 +yaffs_Object *yaffs_GetEquivalentObject(yaffs_Object * obj)
    9420 +{
    9421 +       if (obj && obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK) {
    9422 +               /* We want the object id of the equivalent object, not this one */
     8074+
     8075+
     8076+// GetEquivalentObject dereferences any hard links to get to the
     8077+// actual object.
     8078+
     8079+yaffs_Object *yaffs_GetEquivalentObject(yaffs_Object *obj)
     8080+{
     8081+       if(obj && obj->variantType == YAFFS_OBJECT_TYPE_HARDLINK)
     8082+       {
     8083+               // We want the object id of the equivalent object, not this one
    94238084+               obj = obj->variant.hardLinkVariant.equivalentObject;
    94248085+       }
     
    94278088+}
    94288089+
    9429 +int yaffs_GetObjectName(yaffs_Object * obj, YCHAR * name, int buffSize)
    9430 +{
    9431 +       memset(name, 0, buffSize * sizeof(YCHAR));
    9432 +       
    9433 +       yaffs_CheckObjectDetailsLoaded(obj);
    9434 +
    9435 +       if (obj->objectId == YAFFS_OBJECTID_LOSTNFOUND) {
    9436 +               yaffs_strncpy(name, YAFFS_LOSTNFOUND_NAME, buffSize - 1);
    9437 +       } else if (obj->chunkId <= 0) {
     8090+int yaffs_GetObjectName(yaffs_Object *obj,YCHAR *name,int buffSize)
     8091+{
     8092+       memset(name,0,buffSize * sizeof(YCHAR));
     8093+       
     8094+       if(obj->objectId == YAFFS_OBJECTID_LOSTNFOUND)
     8095+       {
     8096+               yaffs_strncpy(name,YAFFS_LOSTNFOUND_NAME,buffSize - 1);
     8097+       }
     8098+       else if(obj->chunkId <= 0)
     8099+       {
    94388100+               YCHAR locName[20];
    9439 +               /* make up a name */
    9440 +               yaffs_sprintf(locName, _Y("%s%d"), YAFFS_LOSTNFOUND_PREFIX,
    9441 +                             obj->objectId);
    9442 +               yaffs_strncpy(name, locName, buffSize - 1);
     8101+               // make up a name
     8102+               yaffs_sprintf(locName,_Y("%s%d"),YAFFS_LOSTNFOUND_PREFIX,obj->objectId);
     8103+               yaffs_strncpy(name,locName,buffSize - 1);
    94438104+
    94448105+       }
    94458106+#ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM
    9446 +       else if (obj->shortName[0]) {
    9447 +               yaffs_strcpy(name, obj->shortName);
    9448 +       }
    9449 +#endif
    9450 +       else {
    9451 +               int result;
    9452 +               __u8 *buffer = yaffs_GetTempBuffer(obj->myDev, __LINE__);
    9453 +
    9454 +               yaffs_ObjectHeader *oh = (yaffs_ObjectHeader *) buffer;
    9455 +
    9456 +               memset(buffer, 0, obj->myDev->nDataBytesPerChunk);
    9457 +
    9458 +               if (obj->chunkId >= 0) {
    9459 +                       result = yaffs_ReadChunkWithTagsFromNAND(obj->myDev,
    9460 +                                                       obj->chunkId, buffer,
    9461 +                                                       NULL);
    9462 +               }
    9463 +               yaffs_strncpy(name, oh->name, buffSize - 1);
    9464 +
    9465 +               yaffs_ReleaseTempBuffer(obj->myDev, buffer, __LINE__);
    9466 +       }
    9467 +
     8107+       else if(obj->shortName[0])
     8108+       {
     8109+               yaffs_strcpy(name,obj->shortName);
     8110+       }
     8111+#endif
     8112+       else
     8113+       {
     8114+               __u8 *buffer = yaffs_GetTempBuffer(obj->myDev,__LINE__);
     8115+               
     8116+               yaffs_ObjectHeader *oh = (yaffs_ObjectHeader *)buffer;
     8117+
     8118+               memset(buffer,0,obj->myDev->nBytesPerChunk);
     8119+       
     8120+               if(obj->chunkId >= 0)
     8121+               {
     8122+                       yaffs_ReadChunkWithTagsFromNAND(obj->myDev,obj->chunkId,buffer,NULL);
     8123+               }
     8124+               yaffs_strncpy(name,oh->name,buffSize - 1);
     8125+
     8126+               yaffs_ReleaseTempBuffer(obj->myDev,buffer,__LINE__);
     8127+       }
     8128+       
    94688129+       return yaffs_strlen(name);
    94698130+}
    94708131+
    9471 +int yaffs_GetObjectFileLength(yaffs_Object * obj)
    9472 +{
    9473 +
    9474 +       /* Dereference any hard linking */
     8132+int yaffs_GetObjectFileLength(yaffs_Object *obj)
     8133+{
     8134+       
     8135+       // Dereference any hard linking
    94758136+       obj = yaffs_GetEquivalentObject(obj);
    9476 +
    9477 +       if (obj->variantType == YAFFS_OBJECT_TYPE_FILE) {
     8137+       
     8138+       if(obj->variantType == YAFFS_OBJECT_TYPE_FILE)
     8139+       {
    94788140+               return obj->variant.fileVariant.fileSize;
    94798141+       }
    9480 +       if (obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK) {
     8142+       if(obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK)
     8143+       {
    94818144+               return yaffs_strlen(obj->variant.symLinkVariant.alias);
    9482 +       } else {
    9483 +               /* Only a directory should drop through to here */
    9484 +               return obj->myDev->nDataBytesPerChunk;
    9485 +       }
    9486 +}
    9487 +
    9488 +int yaffs_GetObjectLinkCount(yaffs_Object * obj)
    9489 +{
    9490 +       int count = 0;
     8145+       }
     8146+       else
     8147+       {
     8148+               // Only a directory should drop through to here
     8149+               return obj->myDev->nBytesPerChunk;
     8150+       }       
     8151+}
     8152+
     8153+int yaffs_GetObjectLinkCount(yaffs_Object *obj)
     8154+{
     8155+       int count = 0;
    94918156+       struct list_head *i;
    9492 +
    9493 +       if (!obj->unlinked) {
    9494 +               count++;        /* the object itself */
    9495 +       }
    9496 +       list_for_each(i, &obj->hardLinks) {
    9497 +               count++;        /* add the hard links; */
     8157+       
     8158+       if(!obj->unlinked)
     8159+       {
     8160+               count++;        // the object itself
     8161+       }
     8162+       list_for_each(i,&obj->hardLinks)
     8163+       {
     8164+               count++;        // add the hard links;
    94988165+       }
    94998166+       return count;
    9500 +
    9501 +}
    9502 +
    9503 +int yaffs_GetObjectInode(yaffs_Object * obj)
     8167+       
     8168+}
     8169+
     8170+
     8171+int yaffs_GetObjectInode(yaffs_Object *obj)
    95048172+{
    95058173+       obj = yaffs_GetEquivalentObject(obj);
    9506 +
     8174+       
    95078175+       return obj->objectId;
    95088176+}
    95098177+
    9510 +unsigned yaffs_GetObjectType(yaffs_Object * obj)
     8178+unsigned yaffs_GetObjectType(yaffs_Object *obj)
    95118179+{
    95128180+       obj = yaffs_GetEquivalentObject(obj);
    9513 +
    9514 +       switch (obj->variantType) {
    9515 +       case YAFFS_OBJECT_TYPE_FILE:
    9516 +               return DT_REG;
    9517 +               break;
    9518 +       case YAFFS_OBJECT_TYPE_DIRECTORY:
    9519 +               return DT_DIR;
    9520 +               break;
    9521 +       case YAFFS_OBJECT_TYPE_SYMLINK:
    9522 +               return DT_LNK;
    9523 +               break;
    9524 +       case YAFFS_OBJECT_TYPE_HARDLINK:
    9525 +               return DT_REG;
    9526 +               break;
    9527 +       case YAFFS_OBJECT_TYPE_SPECIAL:
    9528 +               if (S_ISFIFO(obj->yst_mode))
    9529 +                       return DT_FIFO;
    9530 +               if (S_ISCHR(obj->yst_mode))
    9531 +                       return DT_CHR;
    9532 +               if (S_ISBLK(obj->yst_mode))
    9533 +                       return DT_BLK;
    9534 +               if (S_ISSOCK(obj->yst_mode))
    9535 +                       return DT_SOCK;
    9536 +       default:
    9537 +               return DT_REG;
    9538 +               break;
    9539 +       }
    9540 +}
    9541 +
    9542 +YCHAR *yaffs_GetSymlinkAlias(yaffs_Object * obj)
     8181+       
     8182+       switch(obj->variantType)
     8183+       {
     8184+               case YAFFS_OBJECT_TYPE_FILE:            return DT_REG; break;
     8185+               case YAFFS_OBJECT_TYPE_DIRECTORY:       return DT_DIR; break;
     8186+               case YAFFS_OBJECT_TYPE_SYMLINK:         return DT_LNK; break;
     8187+               case YAFFS_OBJECT_TYPE_HARDLINK:        return DT_REG; break;
     8188+               case YAFFS_OBJECT_TYPE_SPECIAL:         
     8189+                       if(S_ISFIFO(obj->yst_mode)) return DT_FIFO;
     8190+                       if(S_ISCHR(obj->yst_mode)) return DT_CHR;
     8191+                       if(S_ISBLK(obj->yst_mode)) return DT_BLK;
     8192+                       if(S_ISSOCK(obj->yst_mode)) return DT_SOCK;
     8193+               default: return DT_REG; break;
     8194+       }
     8195+}
     8196+
     8197+YCHAR *yaffs_GetSymlinkAlias(yaffs_Object *obj)
    95438198+{
    95448199+       obj = yaffs_GetEquivalentObject(obj);
    9545 +       if (obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK) {
     8200+       if(obj->variantType == YAFFS_OBJECT_TYPE_SYMLINK)
     8201+       {
    95468202+               return yaffs_CloneString(obj->variant.symLinkVariant.alias);
    9547 +       } else {
     8203+       }
     8204+       else
     8205+       {
    95488206+               return yaffs_CloneString(_Y(""));
    95498207+       }
     
    95528210+#ifndef CONFIG_YAFFS_WINCE
    95538211+
    9554 +int yaffs_SetAttributes(yaffs_Object * obj, struct iattr *attr)
     8212+int yaffs_SetAttributes(yaffs_Object *obj, struct iattr *attr)
    95558213+{
    95568214+       unsigned int valid = attr->ia_valid;
    9557 +
    9558 +       if (valid & ATTR_MODE)
    9559 +               obj->yst_mode = attr->ia_mode;
    9560 +       if (valid & ATTR_UID)
    9561 +               obj->yst_uid = attr->ia_uid;
    9562 +       if (valid & ATTR_GID)
    9563 +               obj->yst_gid = attr->ia_gid;
    9564 +
    9565 +       if (valid & ATTR_ATIME)
    9566 +               obj->yst_atime = Y_TIME_CONVERT(attr->ia_atime);
    9567 +       if (valid & ATTR_CTIME)
    9568 +               obj->yst_ctime = Y_TIME_CONVERT(attr->ia_ctime);
    9569 +       if (valid & ATTR_MTIME)
    9570 +               obj->yst_mtime = Y_TIME_CONVERT(attr->ia_mtime);
    9571 +
    9572 +       if (valid & ATTR_SIZE)
    9573 +               yaffs_ResizeFile(obj, attr->ia_size);
    9574 +
    9575 +       yaffs_UpdateObjectHeader(obj, NULL, 1, 0, 0);
    9576 +
     8215+       
     8216+       if(valid & ATTR_MODE) obj->yst_mode = attr->ia_mode;
     8217+       if(valid & ATTR_UID) obj->yst_uid = attr->ia_uid;
     8218+       if(valid & ATTR_GID) obj->yst_gid = attr->ia_gid;
     8219+       
     8220+       if(valid & ATTR_ATIME) obj->yst_atime = Y_TIME_CONVERT(attr->ia_atime);
     8221+       if(valid & ATTR_CTIME) obj->yst_ctime = Y_TIME_CONVERT(attr->ia_ctime);
     8222+       if(valid & ATTR_MTIME) obj->yst_mtime = Y_TIME_CONVERT(attr->ia_mtime);
     8223+       
     8224+       if(valid & ATTR_SIZE) yaffs_ResizeFile(obj,attr->ia_size);
     8225+       
     8226+       yaffs_UpdateObjectHeader(obj,NULL,1,0,0);
     8227+       
    95778228+       return YAFFS_OK;
    9578 +
    9579 +}
    9580 +int yaffs_GetAttributes(yaffs_Object * obj, struct iattr *attr)
     8229+       
     8230+}
     8231+int yaffs_GetAttributes(yaffs_Object *obj, struct iattr *attr)
    95818232+{
    95828233+       unsigned int valid = 0;
    9583 +
    9584 +       attr->ia_mode = obj->yst_mode;
    9585 +       valid |= ATTR_MODE;
    9586 +       attr->ia_uid = obj->yst_uid;
    9587 +       valid |= ATTR_UID;
    9588 +       attr->ia_gid = obj->yst_gid;
    9589 +       valid |= ATTR_GID;
    9590 +
    9591 +       Y_TIME_CONVERT(attr->ia_atime) = obj->yst_atime;
    9592 +       valid |= ATTR_ATIME;
    9593 +       Y_TIME_CONVERT(attr->ia_ctime) = obj->yst_ctime;
    9594 +       valid |= ATTR_CTIME;
    9595 +       Y_TIME_CONVERT(attr->ia_mtime) = obj->yst_mtime;
    9596 +       valid |= ATTR_MTIME;
    9597 +
    9598 +       attr->ia_size = yaffs_GetFileSize(obj);
    9599 +       valid |= ATTR_SIZE;
    9600 +
     8234+       
     8235+       attr->ia_mode = obj->yst_mode;  valid |= ATTR_MODE;
     8236+       attr->ia_uid = obj->yst_uid;            valid |= ATTR_UID;
     8237+       attr->ia_gid = obj->yst_gid;            valid |= ATTR_GID;
     8238+       
     8239+       Y_TIME_CONVERT(attr->ia_atime)= obj->yst_atime; valid |= ATTR_ATIME;
     8240+       Y_TIME_CONVERT(attr->ia_ctime) = obj->yst_ctime;        valid |= ATTR_CTIME;
     8241+       Y_TIME_CONVERT(attr->ia_mtime) = obj->yst_mtime;        valid |= ATTR_MTIME;
     8242+
     8243+       attr->ia_size = yaffs_GetFileSize(obj); valid |= ATTR_SIZE;
     8244+       
    96018245+       attr->ia_valid = valid;
    9602 +
     8246+       
    96038247+       return YAFFS_OK;
    9604 +
    9605 +}
    9606 +
    9607 +#endif
     8248+       
     8249+}
     8250+
     8251+#endif
     8252+
     8253+int yaffs_DumpObject(yaffs_Object *obj)
     8254+{
     8255+//     __u8 buffer[YAFFS_BYTES_PER_CHUNK];
     8256+       YCHAR name[257];
     8257+//     yaffs_ObjectHeader *oh = (yaffs_ObjectHeader *)buffer;
     8258+
     8259+//     memset(buffer,0,YAFFS_BYTES_PER_CHUNK);
     8260+       
     8261+//     if(obj->chunkId >= 0)
     8262+//     {
     8263+//             yaffs_ReadChunkFromNAND(obj->myDev,obj->chunkId,buffer,NULL);
     8264+//     }
     8265+       
     8266+       yaffs_GetObjectName(obj,name,256);
     8267+       
     8268+       T(YAFFS_TRACE_ALWAYS,(TSTR("Object %d, inode %d \"%s\"\n dirty %d valid %d serial %d sum %d chunk %d type %d size %d\n" TENDSTR),
     8269+                       obj->objectId,yaffs_GetObjectInode(obj), name, obj->dirty, obj->valid, obj->serial,
     8270+                       obj->sum, obj->chunkId, yaffs_GetObjectType(obj), yaffs_GetObjectFileLength(obj)));
    96088271+
    96098272+#if 0
    9610 +int yaffs_DumpObject(yaffs_Object * obj)
    9611 +{
    9612 +       YCHAR name[257];
    9613 +
    9614 +       yaffs_GetObjectName(obj, name, 256);
    9615 +
    9616 +       T(YAFFS_TRACE_ALWAYS,
    9617 +         (TSTR
    9618 +          ("Object %d, inode %d \"%s\"\n dirty %d valid %d serial %d sum %d"
    9619 +           " chunk %d type %d size %d\n"
    9620 +           TENDSTR), obj->objectId, yaffs_GetObjectInode(obj), name,
    9621 +          obj->dirty, obj->valid, obj->serial, obj->sum, obj->chunkId,
    9622 +          yaffs_GetObjectType(obj), yaffs_GetObjectFileLength(obj)));
    9623 +
     8273+       YPRINTF(("Object %d \"%s\"\n dirty %d valid %d serial %d sum %d chunk %d\n",
     8274+                       obj->objectId, oh->name, obj->dirty, obj->valid, obj->serial,
     8275+                       obj->sum, obj->chunkId));
     8276+               switch(obj->variantType)
     8277+       {
     8278+               case YAFFS_OBJECT_TYPE_FILE:
     8279+                       YPRINTF((" FILE length %d\n",obj->variant.fileVariant.fileSize));
     8280+                       break;
     8281+               case YAFFS_OBJECT_TYPE_DIRECTORY:
     8282+                       YPRINTF((" DIRECTORY\n"));
     8283+                       break;
     8284+               case YAFFS_OBJECT_TYPE_HARDLINK: //todo
     8285+               case YAFFS_OBJECT_TYPE_SYMLINK:
     8286+               case YAFFS_OBJECT_TYPE_UNKNOWN:
     8287+               default:
     8288+       }
     8289+#endif
     8290+       
    96248291+       return YAFFS_OK;
    96258292+}
    9626 +#endif
    9627 +
    9628 +/*---------------------------- Initialisation code -------------------------------------- */
    9629 +
    9630 +static int yaffs_CheckDevFunctions(const yaffs_Device * dev)
    9631 +{
    9632 +
    9633 +       /* Common functions, gotta have */
    9634 +       if (!dev->eraseBlockInNAND || !dev->initialiseNAND)
    9635 +               return 0;
     8293+
     8294+
     8295+///////////////////////// Initialisation code ///////////////////////////
     8296+
     8297+
     8298+static int yaffs_CheckDevFunctions(const yaffs_Device *dev)
     8299+{
     8300+
     8301+       // Common functions, gotta have
     8302+       if(!dev->eraseBlockInNAND ||
     8303+          !dev->initialiseNAND) return 0;
    96368304+
    96378305+#ifdef CONFIG_YAFFS_YAFFS2
    96388306+
    9639 +       /* Can use the "with tags" style interface for yaffs1 or yaffs2 */
    9640 +       if (dev->writeChunkWithTagsToNAND &&
    9641 +           dev->readChunkWithTagsFromNAND &&
    9642 +           !dev->writeChunkToNAND &&
    9643 +           !dev->readChunkFromNAND &&
    9644 +           dev->markNANDBlockBad && dev->queryNANDBlock)
    9645 +               return 1;
    9646 +#endif
    9647 +
    9648 +       /* Can use the "spare" style interface for yaffs1 */
    9649 +       if (!dev->isYaffs2 &&
    9650 +           !dev->writeChunkWithTagsToNAND &&
    9651 +           !dev->readChunkWithTagsFromNAND &&
    9652 +           dev->writeChunkToNAND &&
    9653 +           dev->readChunkFromNAND &&
    9654 +           !dev->markNANDBlockBad && !dev->queryNANDBlock)
    9655 +               return 1;
    9656 +
    9657 +       return 0;               /* bad */
    9658 +}
    9659 +
    9660 +
    9661 +static void yaffs_CreateInitialDirectories(yaffs_Device *dev)
    9662 +{
    9663 +       /* Initialise the unlinked, deleted, root and lost and found directories */
    9664 +       
    9665 +       dev->lostNFoundDir = dev->rootDir =  NULL;
    9666 +       dev->unlinkedDir = dev->deletedDir = NULL;
    9667 +
    9668 +       dev->unlinkedDir =
    9669 +           yaffs_CreateFakeDirectory(dev, YAFFS_OBJECTID_UNLINKED, S_IFDIR);
    9670 +       dev->deletedDir =
    9671 +           yaffs_CreateFakeDirectory(dev, YAFFS_OBJECTID_DELETED, S_IFDIR);
    9672 +
    9673 +       dev->rootDir =
    9674 +           yaffs_CreateFakeDirectory(dev, YAFFS_OBJECTID_ROOT,
    9675 +                                     YAFFS_ROOT_MODE | S_IFDIR);
    9676 +       dev->lostNFoundDir =
    9677 +           yaffs_CreateFakeDirectory(dev, YAFFS_OBJECTID_LOSTNFOUND,
    9678 +                                     YAFFS_LOSTNFOUND_MODE | S_IFDIR);
    9679 +       yaffs_AddObjectToDirectory(dev->rootDir, dev->lostNFoundDir);
    9680 +}
    9681 +
    9682 +int yaffs_GutsInitialise(yaffs_Device * dev)
     8307+       // Can use the "with tags" style interface for yaffs1 or yaffs2
     8308+       if(dev->writeChunkWithTagsToNAND &&
     8309+          dev->readChunkWithTagsFromNAND &&
     8310+          !dev->writeChunkToNAND &&
     8311+          !dev->readChunkFromNAND &&
     8312+          dev->markNANDBlockBad &&
     8313+          dev->queryNANDBlock) return 1;
     8314+#endif
     8315+
     8316+       // Can use the "spare" style interface for yaffs1
     8317+       if(!dev->isYaffs2 &&
     8318+          !dev->writeChunkWithTagsToNAND &&
     8319+          !dev->readChunkWithTagsFromNAND &&
     8320+          dev->writeChunkToNAND &&
     8321+          dev->readChunkFromNAND &&
     8322+          !dev->markNANDBlockBad &&
     8323+          !dev->queryNANDBlock) return 1;
     8324+
     8325+       return 0; // bad
     8326+}
     8327+
     8328+
     8329+int yaffs_GutsInitialise(yaffs_Device *dev)
    96838330+{
    96848331+       unsigned x;
    96858332+       int bits;
    9686 +
    9687 +       T(YAFFS_TRACE_TRACING, (TSTR("yaffs: yaffs_GutsInitialise()" TENDSTR)));
    9688 +
    9689 +       /* Check stuff that must be set */
    9690 +
    9691 +       if (!dev) {
    9692 +               T(YAFFS_TRACE_ALWAYS, (TSTR("yaffs: Need a device" TENDSTR)));
     8333+       int extraBits;
     8334+       int nBlocks;
     8335+
     8336+       T(YAFFS_TRACE_ALWAYS,(TSTR("yaffs: yaffs_GutsInitialise()" TENDSTR)));
     8337+       // Check stuff that must be set
     8338+
     8339+       if(!dev)
     8340+       {
     8341+               T(YAFFS_TRACE_ALWAYS,(TSTR("yaffs: Need a device" TENDSTR)));
    96938342+               return YAFFS_FAIL;
    96948343+       }
    9695 +
     8344+       
    96968345+       dev->internalStartBlock = dev->startBlock;
    9697 +       dev->internalEndBlock = dev->endBlock;
     8346+       dev->internalEndBlock =  dev->endBlock;
    96988347+       dev->blockOffset = 0;
    96998348+       dev->chunkOffset = 0;
    97008349+       dev->nFreeChunks = 0;
    9701 +
    9702 +       if (dev->startBlock == 0) {
     8350+       
     8351+       if(dev->startBlock == 0)
     8352+       {
    97038353+               dev->internalStartBlock = dev->startBlock + 1;
    9704 +               dev->internalEndBlock = dev->endBlock + 1;
     8354+               dev->internalEndBlock =  dev->endBlock + 1;
    97058355+               dev->blockOffset = 1;
    97068356+               dev->chunkOffset = dev->nChunksPerBlock;
    97078357+       }
    97088358+
    9709 +       /* Check geometry parameters. */
    9710 +
    9711 +       if ((dev->isYaffs2 && dev->nDataBytesPerChunk < 1024) ||
    9712 +           (!dev->isYaffs2 && dev->nDataBytesPerChunk != 512) ||
    9713 +            dev->nChunksPerBlock < 2 ||
    9714 +            dev->nReservedBlocks < 2 ||
    9715 +            dev->internalStartBlock <= 0 ||
    9716 +            dev->internalEndBlock <= 0 ||
    9717 +            dev->internalEndBlock <= (dev->internalStartBlock + dev->nReservedBlocks + 2)      // otherwise it is too small
    9718 +           ) {
    9719 +               T(YAFFS_TRACE_ALWAYS,
    9720 +                 (TSTR
    9721 +                  ("yaffs: NAND geometry problems: chunk size %d, type is yaffs%s "
    9722 +                   TENDSTR), dev->nDataBytesPerChunk, dev->isYaffs2 ? "2" : ""));
     8359+       // Check geometry parameters.
     8360+
     8361+       if(     (dev->isYaffs2 && dev->nBytesPerChunk <1024)  ||
     8362+               (!dev->isYaffs2 && dev->nBytesPerChunk !=512)  ||
     8363+               dev->nChunksPerBlock < 2 ||
     8364+               dev->nReservedBlocks < 2 ||
     8365+               dev->internalStartBlock <= 0 ||
     8366+               dev->internalEndBlock <= 0 ||
     8367+               dev->internalEndBlock <= (dev->internalStartBlock + dev->nReservedBlocks + 2) // otherwise it is too small
     8368+         )
     8369+       {
     8370+               T(YAFFS_TRACE_ALWAYS,(TSTR("yaffs: NAND geometry problems: chunk size %d, type is yaffs%s " TENDSTR),
     8371+                  dev->nBytesPerChunk, dev->isYaffs2 ? "2" : ""));
    97238372+               return YAFFS_FAIL;
    97248373+       }
    97258374+
    9726 +       if (yaffs_InitialiseNAND(dev) != YAFFS_OK) {
    9727 +               T(YAFFS_TRACE_ALWAYS,
    9728 +                 (TSTR("yaffs: InitialiseNAND failed" TENDSTR)));
     8375+       if(yaffs_InitialiseNAND(dev) != YAFFS_OK)
     8376+       {
     8377+               T(YAFFS_TRACE_ALWAYS,(TSTR("yaffs: InitialiseNAND failed" TENDSTR)));
    97298378+               return YAFFS_FAIL;
    97308379+       }
    97318380+
    9732 +       /* Got the right mix of functions? */
    9733 +       if (!yaffs_CheckDevFunctions(dev)) {
    9734 +               /* Function missing */
    9735 +               T(YAFFS_TRACE_ALWAYS,
    9736 +                 (TSTR
    9737 +                  ("yaffs: device function(s) missing or wrong\n" TENDSTR)));
     8381+       // Got the right mix of functions?
     8382+       //
     8383+       if(!yaffs_CheckDevFunctions(dev))
     8384+       {
     8385+               //Function missing
     8386+               T(YAFFS_TRACE_ALWAYS,(TSTR("yaffs: device function(s) missing or wrong\n" TENDSTR)));
    97388387+
    97398388+               return YAFFS_FAIL;
    97408389+       }
    97418390+
    9742 +       /* This is really a compilation check. */
    9743 +       if (!yaffs_CheckStructures()) {
    9744 +               T(YAFFS_TRACE_ALWAYS,
    9745 +                 (TSTR("yaffs_CheckStructures failed\n" TENDSTR)));
     8391+       // This is really a compilation check.
     8392+       if(!yaffs_CheckStructures())
     8393+       {
     8394+               T(YAFFS_TRACE_ALWAYS,(TSTR("yaffs_CheckStructures failed\n" TENDSTR)));
    97468395+               return YAFFS_FAIL;
    97478396+       }
    97488397+
    9749 +       if (dev->isMounted) {
    9750 +               T(YAFFS_TRACE_ALWAYS,
    9751 +                 (TSTR("yaffs: device already mounted\n" TENDSTR)));
     8398+       if(dev->isMounted)
     8399+       {
     8400+               T(YAFFS_TRACE_ALWAYS,(TSTR("yaffs: device already mounted\n" TENDSTR)));
    97528401+               return YAFFS_FAIL;
    97538402+       }
    97548403+
    9755 +       /* Finished with most checks. One or two more checks happen later on too. */
     8404+       //
     8405+       //
     8406+       // Finished with most checks. One or two more checks happen later on too.
     8407+       //
    97568408+
    97578409+       dev->isMounted = 1;
    97588410+
    97598411+
    9760 +
    9761 +       /* OK now calculate a few things for the device */
    9762 +       
    9763 +       /*
    9764 +        *  Calculate all the chunk size manipulation numbers:
    9765 +        */
    9766 +        /* Start off assuming it is a power of 2 */
    9767 +        dev->chunkShift = ShiftDiv(dev->nDataBytesPerChunk);
    9768 +        dev->chunkMask = (1<<dev->chunkShift) - 1;
    9769 +
    9770 +        if(dev->nDataBytesPerChunk == (dev->chunkMask + 1)){
    9771 +               /* Yes it is a power of 2, disable crumbs */
    9772 +               dev->crumbMask = 0;
    9773 +               dev->crumbShift = 0;
    9774 +               dev->crumbsPerChunk = 0;
    9775 +        } else {
    9776 +               /* Not a power of 2, use crumbs instead */
    9777 +               dev->crumbShift = ShiftDiv(sizeof(yaffs_PackedTags2TagsPart));
    9778 +               dev->crumbMask = (1<<dev->crumbShift)-1;
    9779 +               dev->crumbsPerChunk = dev->nDataBytesPerChunk/(1 << dev->crumbShift);
    9780 +               dev->chunkShift = 0;
    9781 +               dev->chunkMask = 0;
    9782 +       }
    9783 +               
    9784 +
    9785 +       /*
    9786 +        * Calculate chunkGroupBits.
    9787 +        * We need to find the next power of 2 > than internalEndBlock
    9788 +        */
    9789 +
    9790 +       x = dev->nChunksPerBlock * (dev->internalEndBlock + 1);
    9791 +       
    9792 +       bits = ShiftsGE(x);
    9793 +       
    9794 +       /* Set up tnode width if wide tnodes are enabled. */
    9795 +       if(!dev->wideTnodesDisabled){
    9796 +               /* bits must be even so that we end up with 32-bit words */
    9797 +               if(bits & 1)
    9798 +                       bits++;
    9799 +               if(bits < 16)
    9800 +                       dev->tnodeWidth = 16;
    9801 +               else
    9802 +                       dev->tnodeWidth = bits;
     8412+       nBlocks = dev->internalEndBlock - dev->internalStartBlock + 1;
     8413+
     8414+
     8415+
     8416+       // OK now calculate a few things for the device
     8417+       // Calculate chunkGroupBits.
     8418+       // We need to find the next power of 2 > than internalEndBlock
     8419+       
     8420+       x = dev->nChunksPerBlock * (dev->internalEndBlock+1);
     8421+       
     8422+       for(bits = extraBits = 0; x > 1; bits++)
     8423+       {
     8424+               if(x & 1) extraBits++;
     8425+               x >>= 1;
     8426+       }
     8427+
     8428+       if(extraBits > 0) bits++;
     8429+       
     8430+       
     8431+       // Level0 Tnodes are 16 bits, so if the bitwidth of the
     8432+       // chunk range we're using is greater than 16 we need
     8433+       // to figure out chunk shift and chunkGroupSize
     8434+       if(bits <= 16)
     8435+       {
     8436+               dev->chunkGroupBits = 0;
    98038437+       }
    98048438+       else
    9805 +               dev->tnodeWidth = 16;
    9806 +
    9807 +       dev->tnodeMask = (1<<dev->tnodeWidth)-1;
    9808 +               
    9809 +       /* Level0 Tnodes are 16 bits or wider (if wide tnodes are enabled),
    9810 +        * so if the bitwidth of the
    9811 +        * chunk range we're using is greater than 16 we need
    9812 +        * to figure out chunk shift and chunkGroupSize
    9813 +        */
    9814 +               
    9815 +       if (bits <= dev->tnodeWidth)
    9816 +               dev->chunkGroupBits = 0;
    9817 +       else
    9818 +               dev->chunkGroupBits = bits - dev->tnodeWidth;
    9819 +               
    9820 +
     8439+       {
     8440+               dev->chunkGroupBits = bits - 16;
     8441+       }
     8442+       
    98218443+       dev->chunkGroupSize = 1 << dev->chunkGroupBits;
    98228444+
    9823 +       if (dev->nChunksPerBlock < dev->chunkGroupSize) {
    9824 +               /* We have a problem because the soft delete won't work if
    9825 +                * the chunk group size > chunks per block.
    9826 +                * This can be remedied by using larger "virtual blocks".
    9827 +                */
    9828 +               T(YAFFS_TRACE_ALWAYS,
    9829 +                 (TSTR("yaffs: chunk group too large\n" TENDSTR)));
    9830 +
     8445+       if(dev->nChunksPerBlock < dev->chunkGroupSize)
     8446+       {
     8447+               // We have a problem because the soft delete won't work if
     8448+               // the chunk group size > chunks per block.
     8449+               // This can be remedied by using larger "virtual blocks".
     8450+               T(YAFFS_TRACE_ALWAYS,(TSTR("yaffs: chunk group too large\n" TENDSTR)));
     8451+               
    98318452+               return YAFFS_FAIL;
    98328453+       }
    98338454+
    9834 +       /* OK, we've finished verifying the device, lets continue with initialisation */
    9835 +
    9836 +       /* More device initialisation */
     8455+       
     8456+       // OK, we've finished verifying the device, lets continue with initialisation
     8457+       
     8458+       // More device initialisation
    98378459+       dev->garbageCollections = 0;
    98388460+       dev->passiveGarbageCollections = 0;
     
    98418463+       dev->doingBufferedBlockRewrite = 0;
    98428464+       dev->nDeletedFiles = 0;
    9843 +       dev->nBackgroundDeletions = 0;
     8465+       dev->nBackgroundDeletions=0;
    98448466+       dev->nUnlinkedFiles = 0;
    9845 +       dev->eccFixed = 0;
    9846 +       dev->eccUnfixed = 0;
    9847 +       dev->tagsEccFixed = 0;
    9848 +       dev->tagsEccUnfixed = 0;
     8467+       dev->eccFixed=0;
     8468+       dev->eccUnfixed=0;
     8469+       dev->tagsEccFixed=0;
     8470+       dev->tagsEccUnfixed=0;
    98498471+       dev->nErasureFailures = 0;
    98508472+       dev->nErasedBlocks = 0;
    98518473+       dev->isDoingGC = 0;
    9852 +       dev->hasPendingPrioritisedGCs = 1; /* Assume the worst for now, will get fixed on first GC */
    9853 +
    9854 +       /* Initialise temporary buffers and caches. */
     8474+       
     8475+       //dev->localBuffer = YMALLOC(dev->nBytesPerChunk);
     8476+       // Initialise temporary buffers
    98558477+       {
    98568478+               int i;
    9857 +               for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
    9858 +                       dev->tempBuffer[i].line = 0;    /* not in use */
    9859 +                       dev->tempBuffer[i].buffer =
    9860 +                           YMALLOC_DMA(dev->nDataBytesPerChunk);
    9861 +               }
    9862 +       }
    9863 +       
    9864 +       if (dev->nShortOpCaches > 0) {
     8479+               for(i = 0; i < YAFFS_N_TEMP_BUFFERS; i++)
     8480+               {
     8481+                       dev->tempBuffer[i].line = 0; // not in use
     8482+                       dev->tempBuffer[i].buffer = YMALLOC(dev->nBytesPerChunk);
     8483+               }
     8484+       }
     8485+       
     8486+
     8487+       
     8488+       yaffs_InitialiseBlocks(dev,nBlocks);
     8489+       
     8490+       yaffs_InitialiseTnodes(dev);
     8491+
     8492+       yaffs_InitialiseObjects(dev);
     8493+       
     8494+       dev->gcCleanupList = YMALLOC(dev->nChunksPerBlock * sizeof(__u32));
     8495+       
     8496+       if(dev->nShortOpCaches > 0)
     8497+       {
    98658498+               int i;
    9866 +
    9867 +               if (dev->nShortOpCaches > YAFFS_MAX_SHORT_OP_CACHES) {
     8499+               
     8500+               if(dev->nShortOpCaches >  YAFFS_MAX_SHORT_OP_CACHES)
     8501+               {
    98688502+                       dev->nShortOpCaches = YAFFS_MAX_SHORT_OP_CACHES;
    98698503+               }
    9870 +
    9871 +               dev->srCache =
    9872 +                   YMALLOC(dev->nShortOpCaches * sizeof(yaffs_ChunkCache));
    9873 +
    9874 +               for (i = 0; i < dev->nShortOpCaches; i++) {
     8504+               
     8505+               dev->srCache = YMALLOC( dev->nShortOpCaches * sizeof(yaffs_ChunkCache));
     8506+               
     8507+               for(i=0; i < dev->nShortOpCaches; i++)
     8508+               {
    98758509+                       dev->srCache[i].object = NULL;
    98768510+                       dev->srCache[i].lastUse = 0;
    98778511+                       dev->srCache[i].dirty = 0;
    9878 +                       dev->srCache[i].data = YMALLOC_DMA(dev->nDataBytesPerChunk);
     8512+                       dev->srCache[i].data = YMALLOC(dev->nBytesPerChunk);
    98798513+               }
    98808514+               dev->srLastUse = 0;
     
    98838517+       dev->cacheHits = 0;
    98848518+       
    9885 +       dev->gcCleanupList = YMALLOC(dev->nChunksPerBlock * sizeof(__u32));
    9886 +
    9887 +       if (dev->isYaffs2) {
     8519+       
     8520+       // Initialise the unlinked, root and lost and found directories
     8521+       dev->lostNFoundDir = dev->rootDir = dev->unlinkedDir = dev->deletedDir = NULL;
     8522+       
     8523+       dev->unlinkedDir = yaffs_CreateFakeDirectory(dev,YAFFS_OBJECTID_UNLINKED, S_IFDIR);
     8524+       dev->deletedDir = yaffs_CreateFakeDirectory(dev,YAFFS_OBJECTID_DELETED, S_IFDIR);
     8525+
     8526+       dev->rootDir = yaffs_CreateFakeDirectory(dev,YAFFS_OBJECTID_ROOT,YAFFS_ROOT_MODE | S_IFDIR);
     8527+       dev->lostNFoundDir = yaffs_CreateFakeDirectory(dev,YAFFS_OBJECTID_LOSTNFOUND,YAFFS_LOSTNFOUND_MODE | S_IFDIR);
     8528+       yaffs_AddObjectToDirectory(dev->rootDir,dev->lostNFoundDir);
     8529+       
     8530+       if(dev->isYaffs2)
     8531+       {
    98888532+               dev->useHeaderFileSize = 1;
    98898533+       }
    9890 +
    9891 +       yaffs_InitialiseBlocks(dev);
    9892 +       yaffs_InitialiseTnodes(dev);
    9893 +       yaffs_InitialiseObjects(dev);
    9894 +
    9895 +       yaffs_CreateInitialDirectories(dev);
    9896 +
    9897 +
    9898 +       /* Now scan the flash. */
    9899 +       if (dev->isYaffs2) {
    9900 +               if(yaffs_CheckpointRestore(dev)) {
    9901 +                       T(YAFFS_TRACE_ALWAYS,
    9902 +                         (TSTR("yaffs: restored from checkpoint" TENDSTR)));
    9903 +               } else {
    9904 +
    9905 +                       /* Clean up the mess caused by an aborted checkpoint load
    9906 +                        * and scan backwards.
    9907 +                        */
    9908 +                       yaffs_DeinitialiseBlocks(dev);
    9909 +                       yaffs_DeinitialiseTnodes(dev);
    9910 +                       yaffs_DeinitialiseObjects(dev);
    9911 +                       yaffs_InitialiseBlocks(dev);
    9912 +                       yaffs_InitialiseTnodes(dev);
    9913 +                       yaffs_InitialiseObjects(dev);
    9914 +                       yaffs_CreateInitialDirectories(dev);
    9915 +
    9916 +                       yaffs_ScanBackwards(dev);
    9917 +               }
    9918 +       }else
     8534+               
     8535+       // Now scan the flash. 
     8536+       
     8537+       if(dev->isYaffs2)
     8538+               yaffs_ScanBackwards(dev);
     8539+       else
    99198540+               yaffs_Scan(dev);
    9920 +
    9921 +       /* Zero out stats */
     8541+       
     8542+       // Zero out stats
    99228543+       dev->nPageReads = 0;
    9923 +       dev->nPageWrites = 0;
     8544+       dev->nPageWrites = 0;
    99248545+       dev->nBlockErasures = 0;
    99258546+       dev->nGCCopies = 0;
     
    99278548+
    99288549+       dev->nRetiredBlocks = 0;
    9929 +
     8550+       
    99308551+       yaffs_VerifyFreeChunks(dev);
    99318552+
    9932 +       T(YAFFS_TRACE_TRACING,
    9933 +         (TSTR("yaffs: yaffs_GutsInitialise() done.\n" TENDSTR)));
     8553+       T(YAFFS_TRACE_ALWAYS,(TSTR("yaffs: yaffs_GutsInitialise() done.\n" TENDSTR)));
    99348554+       return YAFFS_OK;
    9935 +
    9936 +}
    9937 +
    9938 +void yaffs_Deinitialise(yaffs_Device * dev)
    9939 +{
    9940 +       if (dev->isMounted) {
     8555+               
     8556+}
     8557+
     8558+void yaffs_Deinitialise(yaffs_Device *dev)
     8559+{
     8560+       if(dev->isMounted)
     8561+       {
    99418562+               int i;
    9942 +
     8563+       
    99438564+               yaffs_DeinitialiseBlocks(dev);
    99448565+               yaffs_DeinitialiseTnodes(dev);
    99458566+               yaffs_DeinitialiseObjects(dev);
    9946 +               if (dev->nShortOpCaches > 0) {
    9947 +
    9948 +                       for (i = 0; i < dev->nShortOpCaches; i++) {
     8567+               if(dev->nShortOpCaches > 0)
     8568+               {
     8569+                               
     8570+                       for(i=0; i < dev->nShortOpCaches; i++)
     8571+                       {
    99498572+                               YFREE(dev->srCache[i].data);
    99508573+                       }
     
    99558578+               YFREE(dev->gcCleanupList);
    99568579+
    9957 +               for (i = 0; i < YAFFS_N_TEMP_BUFFERS; i++) {
     8580+               for(i = 0; i < YAFFS_N_TEMP_BUFFERS; i++)
     8581+               {
    99588582+                       YFREE(dev->tempBuffer[i].buffer);
    99598583+               }
    9960 +
     8584+               
    99618585+               dev->isMounted = 0;
    99628586+       }
    9963 +
    9964 +}
    9965 +
    9966 +static int yaffs_CountFreeChunks(yaffs_Device * dev)
     8587+       
     8588+}
     8589+
     8590+#if 0
     8591+
     8592+int  yaffs_GetNumberOfFreeChunks(yaffs_Device *dev)
     8593+{
     8594+       int nFree = dev->nFreeChunks - (dev->nChunksPerBlock * YAFFS_RESERVED_BLOCKS);
     8595+       
     8596+       struct list_head *i;   
     8597+       yaffs_Object *l;
     8598+       
     8599+       
     8600+       // To the free chunks add the chunks that are in the deleted unlinked files.
     8601+       list_for_each(i,&dev->deletedDir->variant.directoryVariant.children)
     8602+       {
     8603+               l = list_entry(i, yaffs_Object,siblings);
     8604+               if(l->deleted)
     8605+               {
     8606+                       nFree++;
     8607+                       nFree += l->nDataChunks;
     8608+               }
     8609+       }
     8610+       
     8611+       
     8612+       // printf("___________ nFreeChunks is %d nFree is %d\n",dev->nFreeChunks,nFree);       
     8613+
     8614+       if(nFree < 0) nFree = 0;
     8615+
     8616+       return nFree;   
     8617+       
     8618+}
     8619+
     8620+#endif
     8621+
     8622+static int  yaffs_CountFreeChunks(yaffs_Device *dev)
    99678623+{
    99688624+       int nFree;
    99698625+       int b;
    99708626+
    9971 +       yaffs_BlockInfo *blk;
    9972 +
    9973 +       for (nFree = 0, b = dev->internalStartBlock; b <= dev->internalEndBlock;
    9974 +            b++) {
    9975 +               blk = yaffs_GetBlockInfo(dev, b);
    9976 +
    9977 +               switch (blk->blockState) {
    9978 +               case YAFFS_BLOCK_STATE_EMPTY:
    9979 +               case YAFFS_BLOCK_STATE_ALLOCATING:
    9980 +               case YAFFS_BLOCK_STATE_COLLECTING:
    9981 +               case YAFFS_BLOCK_STATE_FULL:
    9982 +                       nFree +=
    9983 +                           (dev->nChunksPerBlock - blk->pagesInUse +
    9984 +                            blk->softDeletions);
    9985 +                       break;
    9986 +               default:
    9987 +                       break;
    9988 +               }
    9989 +
    9990 +       }
    9991 +
     8627+       yaffs_BlockInfo *blk;   
     8628+
     8629+       
     8630+       for(nFree = 0, b = dev->internalStartBlock; b <= dev->internalEndBlock; b++)
     8631+       {
     8632+               blk = yaffs_GetBlockInfo(dev,b);
     8633+               
     8634+               switch(blk->blockState)
     8635+               {
     8636+                       case YAFFS_BLOCK_STATE_EMPTY:
     8637+                       case YAFFS_BLOCK_STATE_ALLOCATING:
     8638+                       case YAFFS_BLOCK_STATE_COLLECTING:
     8639+                       case YAFFS_BLOCK_STATE_FULL: nFree += (dev->nChunksPerBlock - blk->pagesInUse + blk->softDeletions); break;
     8640+                       default: break;
     8641+               }
     8642+
     8643+       }
     8644+       
    99928645+       return nFree;
    9993 +}
    9994 +
    9995 +int yaffs_GetNumberOfFreeChunks(yaffs_Device * dev)
    9996 +{
    9997 +       /* This is what we report to the outside world */
     8646+}     
     8647+       
     8648+
     8649+
     8650+int yaffs_GetNumberOfFreeChunks(yaffs_Device *dev)
     8651+{
     8652+       // This is what we report to the outside world
    99988653+
    99998654+       int nFree;
    100008655+       int nDirtyCacheChunks;
    10001 +       int blocksForCheckpoint;
    10002 +
    10003 +#if 1
     8656+               
     8657+#if 1 
    100048658+       nFree = dev->nFreeChunks;
    100058659+#else
    100068660+       nFree = yaffs_CountFreeChunks(dev);
    100078661+#endif
    10008 +
    10009 +       nFree += dev->nDeletedFiles;
    10010 +       
    10011 +       /* Now count the number of dirty chunks in the cache and subtract those */
    10012 +
     8662+       
     8663+       // Now count the number of dirty chunks in the cache and subtract those
     8664+       
    100138665+       {
    100148666+               int i;
    10015 +               for (nDirtyCacheChunks = 0, i = 0; i < dev->nShortOpCaches; i++) {
    10016 +                       if (dev->srCache[i].dirty)
    10017 +                               nDirtyCacheChunks++;
    10018 +               }
    10019 +       }
    10020 +
     8667+               for( nDirtyCacheChunks = 0,i = 0; i < dev->nShortOpCaches; i++)
     8668+               {
     8669+                       if(dev->srCache[i].dirty) nDirtyCacheChunks++;
     8670+               }
     8671+       }
     8672+       
    100218673+       nFree -= nDirtyCacheChunks;
    10022 +
     8674+       
    100238675+       nFree -= ((dev->nReservedBlocks + 1) * dev->nChunksPerBlock);
    100248676+       
    10025 +       /* Now we figure out how much to reserve for the checkpoint and report that... */
    10026 +       blocksForCheckpoint = dev->nCheckpointReservedBlocks - dev->blocksInCheckpoint;
    10027 +       if(blocksForCheckpoint < 0)
    10028 +               blocksForCheckpoint = 0;
    10029 +               
    10030 +       nFree -= (blocksForCheckpoint * dev->nChunksPerBlock);
    10031 +
    10032 +       if (nFree < 0)
    10033 +               nFree = 0;
    10034 +
    10035 +       return nFree;
    10036 +
    10037 +}
    10038 +
    10039 +static int yaffs_freeVerificationFailures;
    10040 +
    10041 +static void yaffs_VerifyFreeChunks(yaffs_Device * dev)
     8677+       if(nFree < 0) nFree = 0;
     8678+
     8679+       return nFree;   
     8680+       
     8681+}
     8682+
     8683+static int  yaffs_freeVerificationFailures;
     8684+
     8685+static void yaffs_VerifyFreeChunks(yaffs_Device *dev)
    100428686+{
    100438687+       int counted = yaffs_CountFreeChunks(dev);
    10044 +
     8688+       
    100458689+       int difference = dev->nFreeChunks - counted;
    10046 +
    10047 +       if (difference) {
    10048 +               T(YAFFS_TRACE_ALWAYS,
    10049 +                 (TSTR("Freechunks verification failure %d %d %d" TENDSTR),
    10050 +                  dev->nFreeChunks, counted, difference));
    10051 +               yaffs_freeVerificationFailures++;
    10052 +       }
    10053 +}
    10054 +
    10055 +/*---------------------------------------- YAFFS test code ----------------------*/
     8690+       
     8691+       if(difference)
     8692+       {
     8693+               T(YAFFS_TRACE_ALWAYS,(TSTR("Freechunks verification failure %d %d %d" TENDSTR),dev->nFreeChunks,counted,difference));
     8694+               yaffs_freeVerificationFailures++;       
     8695+       }
     8696+}
     8697+
     8698+/////////////////// YAFFS test code //////////////////////////////////
    100568699+
    100578700+#define yaffs_CheckStruct(structure,syze, name) \
    100588701+           if(sizeof(structure) != syze) \
    100598702+              { \
    10060 +                T(YAFFS_TRACE_ALWAYS,(TSTR("%s should be %d but is %d\n" TENDSTR),\
    10061 +                name,syze,sizeof(structure))); \
     8703+                T(YAFFS_TRACE_ALWAYS,(TSTR("%s should be %d but is %d\n" TENDSTR),name,syze,sizeof(structure))); \
    100628704+                return YAFFS_FAIL; \
    10063 +               }
    10064 +
     8705+                  }
     8706+               
     8707+               
    100658708+static int yaffs_CheckStructures(void)
    100668709+{
    10067 +/*      yaffs_CheckStruct(yaffs_Tags,8,"yaffs_Tags") */
    10068 +/*      yaffs_CheckStruct(yaffs_TagsUnion,8,"yaffs_TagsUnion") */
    10069 +/*      yaffs_CheckStruct(yaffs_Spare,16,"yaffs_Spare") */
     8710+//     yaffs_CheckStruct(yaffs_Tags,8,"yaffs_Tags")
     8711+//     yaffs_CheckStruct(yaffs_TagsUnion,8,"yaffs_TagsUnion")
     8712+//     yaffs_CheckStruct(yaffs_Spare,16,"yaffs_Spare")
    100708713+#ifndef CONFIG_YAFFS_TNODE_LIST_DEBUG
    10071 +       yaffs_CheckStruct(yaffs_Tnode, 2 * YAFFS_NTNODES_LEVEL0, "yaffs_Tnode")
    10072 +#endif
    10073 +           yaffs_CheckStruct(yaffs_ObjectHeader, 512, "yaffs_ObjectHeader")
    10074 +
    10075 +           return YAFFS_OK;
    10076 +}
    10077 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_guts.h linux-2.6.18.2.patched/fs/yaffs2/yaffs_guts.h
    10078 --- linux-2.6.18.2/fs/yaffs2/yaffs_guts.h       1970-01-01 01:00:00.000000000 +0100
    10079 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_guts.h       2006-11-25 00:15:32.000000000 +0100
    10080 @@ -0,0 +1,893 @@
     8714+       yaffs_CheckStruct(yaffs_Tnode,2* YAFFS_NTNODES_LEVEL0,"yaffs_Tnode")
     8715+#endif
     8716+       yaffs_CheckStruct(yaffs_ObjectHeader,512,"yaffs_ObjectHeader")
     8717+       
     8718+       
     8719+       return YAFFS_OK;
     8720+}
     8721+
     8722+#if 0
     8723+void yaffs_GutsTest(yaffs_Device *dev)
     8724+{
     8725+       
     8726+       if(yaffs_CheckStructures() != YAFFS_OK)
     8727+       {
     8728+               T(YAFFS_TRACE_ALWAYS,(TSTR("One or more structures malformed-- aborting\n" TENDSTR)));
     8729+               return;
     8730+       }
     8731+       
     8732+       yaffs_TnodeTest(dev);
     8733+       yaffs_ObjectTest(dev); 
     8734+}
     8735+#endif
     8736+
     8737+
     8738diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_guts.h linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_guts.h
     8739--- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_guts.h      1970-01-01 01:00:00.000000000 +0100
     8740+++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_guts.h   2006-12-10 04:23:35.000000000 +0100
     8741@@ -0,0 +1,760 @@
    100818742+/*
    100828743+ * YAFFS: Yet another FFS. A NAND-flash specific file system.
     
    100958756+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
    100968757+ *
    10097 + * $Id: yaffs_guts.h,v 1.25 2006/10/13 08:52:49 charles Exp $
     8758+ * $Id: yaffs_guts.h,v 1.11 2005/07/31 06:52:40 charles Exp $
    100988759+ */
    100998760+
     
    101078768+#define YAFFS_FAIL  0
    101088769+
    10109 +/* Give us a  Y=0x59,
    10110 + * Give us an A=0x41,
    10111 + * Give us an FF=0xFF
    10112 + * Give us an S=0x53
    10113 + * And what have we got...
    10114 + */
    10115 +#define YAFFS_MAGIC                    0x5941FF53
     8770+// Give us a Y=0x59,
     8771+// Give us an A=0x41,
     8772+// Give us an FF=0xFF
     8773+// Give us an S=0x53
     8774+// And what have we got...
     8775+#define YAFFS_MAGIC                                    0x5941FF53
    101168776+
    101178777+#define YAFFS_NTNODES_LEVEL0           16
     
    101358795+#define YAFFS_MIN_YAFFS2_SPARE_SIZE    32
    101368796+
    10137 +#define YAFFS_MAX_CHUNK_ID             0x000FFFFF
     8797+#define YAFFS_MAX_CHUNK_ID                     0x000FFFFF
    101388798+
    101398799+#define YAFFS_UNUSED_OBJECT_ID         0x0003FFFF
     
    101468806+
    101478807+
    10148 +#define YAFFS_OBJECT_SPACE             0x40000
    10149 +
    10150 +#define YAFFS_NCHECKPOINT_OBJECTS      5000
    10151 +
    10152 +#define YAFFS_CHECKPOINT_VERSION       2
     8808+#define YAFFS_OBJECT_SPACE                     0x40000
    101538809+
    101548810+#ifdef CONFIG_YAFFS_UNICODE
     
    101628818+#define YAFFS_SHORT_NAME_LENGTH                15
    101638819+
    10164 +/* Some special object ids for pseudo objects */
    10165 +#define YAFFS_OBJECTID_ROOT            1
     8820+
     8821+#define YAFFS_OBJECTID_ROOT                    1
    101668822+#define YAFFS_OBJECTID_LOSTNFOUND      2
    101678823+#define YAFFS_OBJECTID_UNLINKED                3
    101688824+#define YAFFS_OBJECTID_DELETED         4
    101698825+
    10170 +/* Sseudo object ids for checkpointing */
    10171 +#define YAFFS_OBJECTID_SB_HEADER       0x10
    10172 +#define YAFFS_OBJECTID_CHECKPOINT_DATA 0x20
    10173 +#define YAFFS_SEQUENCE_CHECKPOINT_DATA  0x21
    10174 +
    10175 +/* */
    10176 +
    101778826+#define YAFFS_MAX_SHORT_OP_CACHES      20
    101788827+
    101798828+#define YAFFS_N_TEMP_BUFFERS           4
    101808829+
    10181 +/* Sequence numbers are used in YAFFS2 to determine block allocation order.
    10182 + * The range is limited slightly to help distinguish bad numbers from good.
    10183 + * This also allows us to perhaps in the future use special numbers for
    10184 + * special purposes.
    10185 + * EFFFFF00 allows the allocation of 8 blocks per second (~1Mbytes) for 15 years,
    10186 + * and is a larger number than the lifetime of a 2GB device.
    10187 + */
     8830+// Sequence numbers are used in YAFFS2 to determine block allocation order.
     8831+// The range is limited slightly to help distinguish bad numbers from good.
     8832+// This also allows us to perhaps in the future use special numbers for
     8833+// special purposes.
     8834+// EFFFFF00 allows the allocation of 8 blocks per second (~1Mbytes) for 15 years,
     8835+// and is a larger number than the lifetime of a 2GB device.
     8836+
    101888837+#define YAFFS_LOWEST_SEQUENCE_NUMBER   0x00001000
    101898838+#define YAFFS_HIGHEST_SEQUENCE_NUMBER  0xEFFFFF00
    101908839+
    10191 +/* ChunkCache is used for short read/write operations.*/
    10192 +typedef struct {
     8840+
     8841+// ChunkCache is used for short read/write operations.
     8842+typedef struct
     8843+{
    101938844+       struct yaffs_ObjectStruct *object;
    101948845+       int chunkId;
    101958846+       int lastUse;
    10196 +       int dirty;
    10197 +       int nBytes;             /* Only valid if the cache is dirty */
    10198 +       int locked;             /* Can't push out or flush while locked. */
     8847+       int dirty;     
     8848+       int nBytes;     // Only valid if the cache is dirty
     8849+       int locked; // Can't push out or flush while locked..
    101998850+#ifdef CONFIG_YAFFS_YAFFS2
    102008851+       __u8 *data;
     
    102058856+
    102068857+
    10207 +
    10208 +/* Tags structures in RAM
    10209 + * NB This uses bitfield. Bitfields should not straddle a u32 boundary otherwise
    10210 + * the structure size will get blown out.
    10211 + */
    10212 +
    102138858+#ifndef CONFIG_YAFFS_NO_YAFFS1
    10214 +typedef struct {
     8859+// Tags structures in RAM
     8860+// NB This uses bitfield. Bitfields should not straddle a u32 boundary otherwise
     8861+// the structure size will get blown out.
     8862+
     8863+typedef struct
     8864+{   
    102158865+       unsigned chunkId:20;
    10216 +       unsigned serialNumber:2;
    10217 +       unsigned byteCount:10;
    10218 +       unsigned objectId:18;
    10219 +       unsigned ecc:12;
    10220 +       unsigned unusedStuff:2;
     8866+    unsigned serialNumber:2;
     8867+    unsigned byteCount:10;
     8868+    unsigned objectId:18;
     8869+    unsigned ecc:12;
     8870+    unsigned unusedStuff:2;
    102218871+
    102228872+} yaffs_Tags;
    102238873+
    10224 +typedef union {
    10225 +       yaffs_Tags asTags;
    10226 +       __u8 asBytes[8];
     8874+typedef union
     8875+{
     8876+    yaffs_Tags asTags;
     8877+    __u8       asBytes[8];
    102278878+} yaffs_TagsUnion;
    102288879+
    102298880+#endif
    102308881+
    10231 +/* Stuff used for extended tags in YAFFS2 */
    10232 +
    10233 +typedef enum {
     8882+typedef enum
     8883+{
    102348884+       YAFFS_ECC_RESULT_UNKNOWN,
    102358885+       YAFFS_ECC_RESULT_NO_ERROR,
     
    102388888+} yaffs_ECCResult;
    102398889+
    10240 +typedef enum {
     8890+typedef enum
     8891+{
    102418892+       YAFFS_OBJECT_TYPE_UNKNOWN,
    102428893+       YAFFS_OBJECT_TYPE_FILE,
     
    102478898+} yaffs_ObjectType;
    102488899+
    10249 +typedef struct {
     8900+
     8901+typedef struct
     8902+{
    102508903+
    102518904+       unsigned validMarker0;
    10252 +       unsigned chunkUsed;     /*  Status of the chunk: used or unused */
    10253 +       unsigned objectId;      /* If 0 then this is not part of an object (unused) */
    10254 +       unsigned chunkId;       /* If 0 then this is a header, else a data chunk */
    10255 +       unsigned byteCount;     /* Only valid for data chunks */
    10256 +
    10257 +       /* The following stuff only has meaning when we read */
    10258 +       yaffs_ECCResult eccResult;
    10259 +       unsigned blockBad;     
    10260 +
    10261 +       /* YAFFS 1 stuff */
    10262 +       unsigned chunkDeleted;  /* The chunk is marked deleted */
    10263 +       unsigned serialNumber;  /* Yaffs1 2-bit serial number */
    10264 +
    10265 +       /* YAFFS2 stuff */
    10266 +       unsigned sequenceNumber;        /* The sequence number of this block */
    10267 +
    10268 +       /* Extra info if this is an object header (YAFFS2 only) */
    10269 +
    10270 +       unsigned extraHeaderInfoAvailable;      /* There is extra info available if this is not zero */
    10271 +       unsigned extraParentObjectId;   /* The parent object */
    10272 +       unsigned extraIsShrinkHeader;   /* Is it a shrink header? */
    10273 +       unsigned extraShadows;          /* Does this shadow another object? */
    10274 +
    10275 +       yaffs_ObjectType extraObjectType;       /* What object type? */
    10276 +
    10277 +       unsigned extraFileLength;               /* Length if it is a file */
    10278 +       unsigned extraEquivalentObjectId;       /* Equivalent object Id if it is a hard link */
    10279 +
    10280 +       unsigned validMarker1;
    10281 +
     8905+       unsigned chunkUsed;                 //  Status of the chunk: used or unused
     8906+       unsigned objectId;                      // If 0 then this is not part of an object (unused)
     8907+       unsigned chunkId;                       // If 0 then this is a header, else a data chunk
     8908+       unsigned byteCount;                 // Only valid for data chunks
     8909+       
     8910+       
     8911+       // The following stuff only has meaning when we read
     8912+       yaffs_ECCResult eccResult;  // Only valid when we read.
     8913+       unsigned blockBad;                      // Only valid on reading
     8914+
     8915+       // YAFFS 1 stuff       
     8916+       unsigned chunkDeleted;          // The chunk is marked deleted
     8917+       unsigned serialNumber;          // Yaffs1 2-bit serial number
     8918+       
     8919+       // YAFFS2 stuff
     8920+       unsigned sequenceNumber;        // The sequence number of this block
     8921+
     8922+       // Extra info if this is an object header (YAFFS2 only)
     8923+       
     8924+       unsigned extraHeaderInfoAvailable; // There is extra info available if this is not zero
     8925+       unsigned extraParentObjectId;      // The parent object
     8926+       unsigned extraIsShrinkHeader;      // Is it a shrink header?
     8927+       unsigned extraShadows;             // Does this shadow another object?
     8928+       
     8929+       yaffs_ObjectType extraObjectType;  // What object type?
     8930+
     8931+       unsigned extraFileLength;          // Length if it is a file
     8932+       unsigned extraEquivalentObjectId;  // Equivalent object Id if it is a hard link
     8933+
     8934+       unsigned validMarker1; 
     8935+       
    102828936+} yaffs_ExtendedTags;
    102838937+
    10284 +/* Spare structure for YAFFS1 */
    10285 +typedef struct {
    10286 +       __u8 tagByte0;
    10287 +       __u8 tagByte1;
    10288 +       __u8 tagByte2;
    10289 +       __u8 tagByte3;
    10290 +       __u8 pageStatus;        /* set to 0 to delete the chunk */
    10291 +       __u8 blockStatus;
    10292 +       __u8 tagByte4;
    10293 +       __u8 tagByte5;
    10294 +       __u8 ecc1[3];
    10295 +       __u8 tagByte6;
    10296 +       __u8 tagByte7;
    10297 +       __u8 ecc2[3];
     8938+#ifndef CONFIG_YAFFS_NO_YAFFS1
     8939+// Spare structure
     8940+typedef struct
     8941+{
     8942+    __u8  tagByte0;
     8943+    __u8  tagByte1;
     8944+    __u8  tagByte2;
     8945+    __u8  tagByte3;
     8946+    __u8  pageStatus;  // set to 0 to delete the chunk
     8947+    __u8  blockStatus;
     8948+    __u8  tagByte4;
     8949+    __u8  tagByte5;
     8950+    __u8  ecc1[3];
     8951+    __u8  tagByte6;
     8952+    __u8  tagByte7;
     8953+    __u8  ecc2[3];
    102988954+} yaffs_Spare;
    102998955+
    10300 +/*Special structure for passing through to mtd */
     8956+//Special structure for passing through to mtd
    103018957+struct yaffs_NANDSpare {
    10302 +       yaffs_Spare spare;
    10303 +       int eccres1;
    10304 +       int eccres2;
     8958+       yaffs_Spare     spare;
     8959+       int             eccres1;
     8960+       int             eccres2;
    103058961+};
    10306 +
    10307 +/* Block data in RAM */
     8962+#endif
     8963+
     8964+
     8965+// Block data in RAM
    103088966+
    103098967+typedef enum {
    10310 +       YAFFS_BLOCK_STATE_UNKNOWN = 0,
     8968+       YAFFS_BLOCK_STATE_UNKNOWN       = 0,
    103118969+
    103128970+       YAFFS_BLOCK_STATE_SCANNING,
    10313 +       YAFFS_BLOCK_STATE_NEEDS_SCANNING,
    10314 +       /* The block might have something on it (ie it is allocating or full, perhaps empty)
    10315 +        * but it needs to be scanned to determine its true state.
    10316 +        * This state is only valid during yaffs_Scan.
    10317 +        * NB We tolerate empty because the pre-scanner might be incapable of deciding
    10318 +        * However, if this state is returned on a YAFFS2 device, then we expect a sequence number
    10319 +        */
    10320 +
    10321 +       YAFFS_BLOCK_STATE_EMPTY,
    10322 +       /* This block is empty */
    10323 +
    10324 +       YAFFS_BLOCK_STATE_ALLOCATING,
    10325 +       /* This block is partially allocated.
    10326 +        * At least one page holds valid data.
    10327 +        * This is the one currently being used for page
    10328 +        * allocation. Should never be more than one of these
    10329 +        */
    10330 +
    10331 +       YAFFS_BLOCK_STATE_FULL,
    10332 +       /* All the pages in this block have been allocated.
    10333 +        */
    10334 +
    10335 +       YAFFS_BLOCK_STATE_DIRTY,
    10336 +       /* All pages have been allocated and deleted.
    10337 +        * Erase me, reuse me.
    10338 +        */
    10339 +
    10340 +       YAFFS_BLOCK_STATE_CHECKPOINT,   
    10341 +       /* This block is assigned to holding checkpoint data.
    10342 +        */
    10343 +
    10344 +       YAFFS_BLOCK_STATE_COLLECTING,   
    10345 +       /* This block is being garbage collected */
    10346 +
    10347 +       YAFFS_BLOCK_STATE_DEAD 
    10348 +       /* This block has failed and is not in use */
     8971+       YAFFS_BLOCK_STATE_NEEDS_SCANNING,// The block might have something on it (ie it is allocating or full, perhaps empty)
     8972+                                                                       // but it needs to be scanned to determine its true state.
     8973+                                                                       // This state is only valid during yaffs_Scan.
     8974+                                                                       // NB We tolerate empty because the pre-scanner might be incapable of deciding
     8975+                                                                       // However, if this state is returned on a YAFFS2 device, then we expect a sequence number
     8976+                                                                       
     8977+       YAFFS_BLOCK_STATE_EMPTY,                // This block is empty
     8978+       
     8979+       YAFFS_BLOCK_STATE_ALLOCATING,   // This block is partially allocated.
     8980+                                                                       // This is the one currently being used for page
     8981+                                                                       // allocation. Should never be more than one of these
     8982+                                                       
     8983+
     8984+       YAFFS_BLOCK_STATE_FULL,                 // All the pages in this block have been allocated.
     8985+                                                                       // At least one page holds valid data.
     8986+                                                       
     8987+       YAFFS_BLOCK_STATE_DIRTY,                // All pages have been allocated and deleted.
     8988+                                                                       // Erase me, reuse me.
     8989+                                                                       
     8990+       YAFFS_BLOCK_STATE_COLLECTING,   // This block is being garbage collected
     8991+                                                       
     8992+       YAFFS_BLOCK_STATE_DEAD                  // This block has failed and is not in use
     8993+
    103498994+} yaffs_BlockState;
    103508995+
    10351 +typedef struct {
    10352 +
    10353 +       int softDeletions:10;   /* number of soft deleted pages */
    10354 +       int pagesInUse:10;      /* number of pages in use */
    10355 +       yaffs_BlockState blockState:4;  /* One of the above block states */
    10356 +       __u32 needsRetiring:1;  /* Data has failed on this block, need to get valid data off */
    10357 +                               /* and retire the block. */
    10358 +       __u32 skipErasedCheck: 1; /* If this is set we can skip the erased check on this block */
    10359 +       __u32 gcPrioritise: 1;  /* An ECC check or bank check has failed on this block.
    10360 +                                  It should be prioritised for GC */
    10361 +        __u32 chunkErrorStrikes:3; /* How many times we've had ecc etc failures on this block and tried to reuse it */
    10362 +
     8996+
     8997+
     8998+
     8999+typedef struct
     9000+{
     9001+
     9002+    int   softDeletions:12;  // number of soft deleted pages
     9003+    int   pagesInUse:12;       // number of pages in use
     9004+    yaffs_BlockState blockState:4;     // One of the above block states
     9005+    __u32 needsRetiring:1;     // Data has failed on this block, need to get valid data off
     9006+                                               // and retire the block.
    103639007+#ifdef CONFIG_YAFFS_YAFFS2
    10364 +       __u32 hasShrinkHeader:1; /* This block has at least one shrink object header */
    10365 +       __u32 sequenceNumber;    /* block sequence number for yaffs2 */
     9008+       __u32 hasShrinkHeader:1;// This block has at least one object header that does a shrink
     9009+       __u32 sequenceNumber;   // block sequence number for yaffs2
    103669010+#endif
    103679011+
    103689012+} yaffs_BlockInfo;
    103699013+
    10370 +/* -------------------------- Object structure -------------------------------*/
    10371 +/* This is the object structure as stored on NAND */
    10372 +
    10373 +typedef struct {
     9014+
     9015+//////////////////// Object structure ///////////////////////////
     9016+// This is the object structure as stored on NAND
     9017+
     9018+typedef struct
     9019+{
    103749020+       yaffs_ObjectType type;
    103759021+
    10376 +       /* Apply to everything  */
    10377 +       int parentObjectId;
    10378 +       __u16 sum__NoLongerUsed;        /* checksum of name. No longer used */
    10379 +       YCHAR name[YAFFS_MAX_NAME_LENGTH + 1];
    10380 +
    10381 +       /* Thes following apply to directories, files, symlinks - not hard links */
    10382 +       __u32 yst_mode;         /* protection */
     9022+       // Apply to everything 
     9023+       int   parentObjectId;
     9024+       __u16 sum__NoLongerUsed;        // checksum of name. Calc this off the name to prevent inconsistencies
     9025+       YCHAR  name[YAFFS_MAX_NAME_LENGTH + 1];
     9026+
     9027+       // Thes following apply to directories, files, symlinks - not hard links
     9028+       __u32 yst_mode;  // protection
    103839029+
    103849030+#ifdef CONFIG_YAFFS_WINCE
    103859031+       __u32 notForWinCE[5];
    103869032+#else
    10387 +       __u32 yst_uid;
    10388 +       __u32 yst_gid;
    10389 +       __u32 yst_atime;
    10390 +       __u32 yst_mtime;
    10391 +       __u32 yst_ctime;
    10392 +#endif
    10393 +
    10394 +       /* File size  applies to files only */
    10395 +       int fileSize;
    10396 +
    10397 +       /* Equivalent object id applies to hard links only. */
    10398 +       int equivalentObjectId;
    10399 +
    10400 +       /* Alias is for symlinks only. */
     9033+       __u32 yst_uid;   // user ID of owner
     9034+       __u32 yst_gid;    // group ID of owner
     9035+       __u32 yst_atime; // time of last access
     9036+       __u32 yst_mtime; // time of last modification
     9037+       __u32 yst_ctime; // time of last change
     9038+#endif
     9039+
     9040+       // File size  applies to files only
     9041+       int fileSize; 
     9042+               
     9043+       // Equivalent object id applies to hard links only.
     9044+       int  equivalentObjectId;
     9045+       
     9046+       // Alias is for symlinks only.
    104019047+       YCHAR alias[YAFFS_MAX_ALIAS_LENGTH + 1];
    10402 +
    10403 +       __u32 yst_rdev;         /* device stuff for block and char devices (major/min) */
    10404 +
     9048+       
     9049+       __u32 yst_rdev;  // device stuff for block and char devices (maj/min)
     9050+       
    104059051+#ifdef CONFIG_YAFFS_WINCE
    104069052+       __u32 win_ctime[2];
     
    104129058+#endif
    104139059+
    10414 +       int shadowsObject;      /* This object header shadows the specified object if > 0 */
    10415 +
    10416 +       /* isShrink applies to object headers written when we shrink the file (ie resize) */
     9060+       int shadowsObject; // This object header shadows the specified object if not > 0
     9061+
     9062+       // isShrink applies to object headers written when we shrink the file (ie resize)
    104179063+       __u32 isShrink;
    10418 +
     9064+       
    104199065+} yaffs_ObjectHeader;
    104209066+
    10421 +/*--------------------------- Tnode -------------------------- */
    10422 +
    10423 +union yaffs_Tnode_union {
     9067+
     9068+
     9069+////////////////////  Tnode ///////////////////////////
     9070+
     9071+union yaffs_Tnode_union
     9072+{
    104249073+#ifdef CONFIG_YAFFS_TNODE_LIST_DEBUG
    10425 +       union yaffs_Tnode_union *internal[YAFFS_NTNODES_INTERNAL + 1];
     9074+       union yaffs_Tnode_union *internal[YAFFS_NTNODES_INTERNAL+1];
    104269075+#else
    104279076+       union yaffs_Tnode_union *internal[YAFFS_NTNODES_INTERNAL];
    104289077+#endif
    10429 +/*     __u16 level0[YAFFS_NTNODES_LEVEL0]; */
    10430 +
     9078+       __u16 level0[YAFFS_NTNODES_LEVEL0];
     9079+       
    104319080+};
    104329081+
    104339082+typedef union yaffs_Tnode_union yaffs_Tnode;
    104349083+
    10435 +struct yaffs_TnodeList_struct {
     9084+struct yaffs_TnodeList_struct
     9085+{
    104369086+       struct yaffs_TnodeList_struct *next;
    104379087+       yaffs_Tnode *tnodes;
     
    104409090+typedef struct yaffs_TnodeList_struct yaffs_TnodeList;
    104419091+
    10442 +/*------------------------  Object -----------------------------*/
    10443 +/* An object can be one of:
    10444 + * - a directory (no data, has children links
    10445 + * - a regular file (data.... not prunes :->).
    10446 + * - a symlink [symbolic link] (the alias).
    10447 + * - a hard link
    10448 + */
    10449 +
    10450 +typedef struct {
     9092+
     9093+
     9094+///////////////////  Object ////////////////////////////////
     9095+// An object can be one of:
     9096+// - a directory (no data, has children links
     9097+// - a regular file (data.... not prunes :->).
     9098+// - a symlink [symbolic link] (the alias).
     9099+// - a hard link
     9100+
     9101+
     9102+typedef struct
     9103+{
    104519104+       __u32 fileSize;
    104529105+       __u32 scannedFileSize;
    104539106+       __u32 shrinkSize;
    10454 +       int topLevel;
     9107+       int   topLevel;
    104559108+       yaffs_Tnode *top;
    104569109+} yaffs_FileStructure;
    104579110+
    10458 +typedef struct {
    10459 +       struct list_head children;      /* list of child links */
     9111+typedef struct
     9112+{
     9113+       struct list_head children; // list of child links
    104609114+} yaffs_DirectoryStructure;
    104619115+
    10462 +typedef struct {
     9116+typedef struct
     9117+{
    104639118+       YCHAR *alias;
    104649119+} yaffs_SymLinkStructure;
    104659120+
    10466 +typedef struct {
     9121+typedef struct
     9122+{
    104679123+       struct yaffs_ObjectStruct *equivalentObject;
    10468 +       __u32 equivalentObjectId;
     9124+       __u32   equivalentObjectId;
    104699125+} yaffs_HardLinkStructure;
    104709126+
    10471 +typedef union {
     9127+typedef union
     9128+{
    104729129+       yaffs_FileStructure fileVariant;
    104739130+       yaffs_DirectoryStructure directoryVariant;
     
    104769133+} yaffs_ObjectVariant;
    104779134+
    10478 +struct yaffs_ObjectStruct {
    10479 +       __u8 deleted:1;         /* This should only apply to unlinked files. */
    10480 +       __u8 softDeleted:1;     /* it has also been soft deleted */
    10481 +       __u8 unlinked:1;        /* An unlinked file. The file should be in the unlinked directory.*/
    10482 +       __u8 fake:1;            /* A fake object has no presence on NAND. */
    10483 +       __u8 renameAllowed:1;   /* Some objects are not allowed to be renamed. */
     9135+
     9136+struct  yaffs_ObjectStruct
     9137+{
     9138+       __u8 deleted: 1;                // This should only apply to unlinked files.
     9139+       __u8 softDeleted: 1;    // it has also been soft deleted
     9140+       __u8 unlinked: 1;               // An unlinked file. The file should be in the unlinked pseudo directory.
     9141+       __u8 fake:1;                    // A fake object has no presence on NAND.
     9142+       __u8 renameAllowed:1;           // Some objects are not allowed to be renamed.
    104849143+       __u8 unlinkAllowed:1;
    10485 +       __u8 dirty:1;           /* the object needs to be written to flash */
    10486 +       __u8 valid:1;           /* When the file system is being loaded up, this
    10487 +                                * object might be created before the data
    10488 +                                * is available (ie. file data records appear before the header).
    10489 +                                */
    10490 +       __u8 lazyLoaded:1;      /* This object has been lazy loaded and is missing some detail */
    10491 +
    10492 +       __u8 deferedFree:1;     /* For Linux kernel. Object is removed from NAND, but is
    10493 +                                * still in the inode cache. Free of object is defered.
    10494 +                                * until the inode is released.
    10495 +                                */
    10496 +
    10497 +       __u8 serial;            /* serial number of chunk in NAND. Cached here */
    10498 +       __u16 sum;              /* sum of the name to speed searching */
    10499 +
    10500 +       struct yaffs_DeviceStruct *myDev;       /* The device I'm on */
    10501 +
    10502 +       struct list_head hashLink;      /* list of objects in this hash bucket */
    10503 +
    10504 +       struct list_head hardLinks;     /* all the equivalent hard linked objects */
    10505 +
    10506 +       /* directory structure stuff */
    10507 +       /* also used for linking up the free list */
    10508 +       struct yaffs_ObjectStruct *parent;
    10509 +       struct list_head siblings;
    10510 +
    10511 +       /* Where's my object header in NAND? */
    10512 +       int chunkId;           
    10513 +
    10514 +       int nDataChunks;        /* Number of data chunks attached to the file. */
    10515 +
    10516 +       __u32 objectId;         /* the object id value */
    10517 +
    10518 +       __u32 yst_mode;
     9144+       __u8 dirty:1;                   // the object needs to be written to flash
     9145+       __u8 valid:1;                   // When the file system is being loaded up, this
     9146+                                                       // object might be created before the data
     9147+                                                       // is available (ie. file data records appear before the header).
     9148+       __u8 serial;                    // serial number of chunk in NAND. Store here so we don't have to
     9149+
     9150+       __u8  deferedFree: 1;           // For Linux kernel. Object is removed from NAND, but still in the inode cache.
     9151+                                       // Free of object is defered.
     9152+                                       
     9153+       __u8 lazyLoaded;                // Vital info has been loaded from tags. Not all info available.
     9154+                                       //
     9155+
     9156+                                       // read back the old one to update.
     9157+       __u16 sum;                      // sum of the name to speed searching
     9158+       
     9159+       struct yaffs_DeviceStruct *myDev; // The device I'm on
     9160+       
     9161+                                                               
     9162+       struct list_head hashLink;      // list of objects in this hash bucket
     9163+                                                       
     9164+
     9165+       struct list_head hardLinks; // all the equivalent hard linked objects
     9166+                                                               // live on this list
     9167+       // directory structure stuff
     9168+       struct yaffs_ObjectStruct  *parent;     //my parent directory
     9169+       struct list_head siblings;      // siblings in a directory
     9170+                                                               // also used for linking up the free list
     9171+               
     9172+       // Where's my object header in NAND?
     9173+       int chunkId;            // where it lives
     9174+
     9175+       int nDataChunks;        // Number of data chunks attached to the file. 
     9176+       
     9177+       __u32 objectId;         // the object id value
     9178+       
     9179+       
     9180+       __u32 yst_mode;         // protection
    105199181+
    105209182+#ifdef CONFIG_YAFFS_SHORT_NAMES_IN_RAM
    10521 +       YCHAR shortName[YAFFS_SHORT_NAME_LENGTH + 1];
     9183+       YCHAR shortName[YAFFS_SHORT_NAME_LENGTH+1];
    105229184+#endif
    105239185+
     
    105319193+       __u32 win_atime[2];
    105329194+#else
    10533 +       __u32 yst_uid;
    10534 +       __u32 yst_gid;
    10535 +       __u32 yst_atime;
    10536 +       __u32 yst_mtime;
    10537 +       __u32 yst_ctime;
    10538 +#endif
    10539 +
    10540 +       __u32 yst_rdev;
     9195+       __u32 yst_uid;          // user ID of owner
     9196+       __u32 yst_gid;          // group ID of owner
     9197+       __u32 yst_atime;        // time of last access
     9198+       __u32 yst_mtime;        // time of last modification
     9199+       __u32 yst_ctime;        // time of last change
     9200+#endif
     9201+
     9202+       __u32 yst_rdev;             // device stuff for block and char devices
     9203+
     9204+
    105419205+
    105429206+#ifdef __KERNEL__
     
    105459209+#endif
    105469210+
     9211+
     9212+       
    105479213+       yaffs_ObjectType variantType;
    10548 +
     9214+       
    105499215+       yaffs_ObjectVariant variant;
    10550 +
     9216+       
    105519217+};
    105529218+
     9219+
     9220+
    105539221+typedef struct yaffs_ObjectStruct yaffs_Object;
    105549222+
    10555 +struct yaffs_ObjectList_struct {
     9223+
     9224+struct yaffs_ObjectList_struct
     9225+{
    105569226+       yaffs_Object *objects;
    105579227+       struct yaffs_ObjectList_struct *next;
     
    105609230+typedef struct yaffs_ObjectList_struct yaffs_ObjectList;
    105619231+
    10562 +typedef struct {
     9232+typedef struct
     9233+{
    105639234+       struct list_head list;
    105649235+       int count;
    105659236+} yaffs_ObjectBucket;
    105669237+
    10567 +
    10568 +/* yaffs_CheckpointObject holds the definition of an object as dumped
    10569 + * by checkpointing.
    10570 + */
    10571 +
    10572 +typedef struct {
    10573 +        int structType;
    10574 +       __u32 objectId;         
    10575 +       __u32 parentId;
    10576 +       int chunkId;
    10577 +                       
    10578 +       yaffs_ObjectType variantType:3;
    10579 +       __u8 deleted:1;         
    10580 +       __u8 softDeleted:1;     
    10581 +       __u8 unlinked:1;       
    10582 +       __u8 fake:1;           
    10583 +       __u8 renameAllowed:1;
    10584 +       __u8 unlinkAllowed:1;
    10585 +       __u8 serial;           
    10586 +       
    10587 +       int nDataChunks;       
    10588 +       __u32 fileSizeOrEquivalentObjectId;
    10589 +
    10590 +}yaffs_CheckpointObject;
    10591 +
    10592 +/*--------------------- Temporary buffers ----------------
    10593 + *
    10594 + * These are chunk-sized working buffers. Each device has a few
    10595 + */
     9238+///////////////////// Temporary buffers ////////////////////
     9239+//
     9240+// These are chunk-sized working buffers. Each device has a few
    105969241+
    105979242+typedef struct {
    105989243+       __u8 *buffer;
    10599 +       int line;       /* track from whence this buffer was allocated */
     9244+       int line; // track from whence this buffer was allocated
    106009245+       int maxLine;
    106019246+} yaffs_TempBuffer;
    106029247+
    10603 +/*----------------- Device ---------------------------------*/
    10604 +
    10605 +struct yaffs_DeviceStruct {
     9248+//////////////////// Device ////////////////////////////////
     9249+
     9250+struct yaffs_DeviceStruct
     9251+{
    106069252+       struct list_head devList;
    106079253+       const char *name;
    106089254+
    10609 +       /* Entry parameters set up way early. Yaffs sets up the rest.*/
    10610 +       int nDataBytesPerChunk; /* Should be a power of 2 >= 512 */
    10611 +       int nChunksPerBlock;    /* does not need to be a power of 2 */
    10612 +       int nBytesPerSpare;     /* spare area size */
    10613 +       int startBlock;         /* Start block we're allowed to use */
    10614 +       int endBlock;           /* End block we're allowed to use */
    10615 +       int nReservedBlocks;    /* We want this tuneable so that we can reduce */
    10616 +                               /* reserved blocks on NOR and RAM. */
    10617 +       
    10618 +       /* Stuff used by the partitioned checkpointing mechanism */
    10619 +       int checkpointStartBlock;
    10620 +       int checkpointEndBlock;
    10621 +       
    10622 +       /* Stuff used by the shared space checkpointing mechanism */
    10623 +       /* If this value is zero, then this mechanism is disabled */
    10624 +       
    10625 +       int nCheckpointReservedBlocks; /* Blocks to reserve for checkpoint data */
    10626 +
    10627 +       
    10628 +
    10629 +
    10630 +       int nShortOpCaches;     /* If <= 0, then short op caching is disabled, else
    10631 +                                * the number of short op caches (don't use too many)
    10632 +                                */
    10633 +
    10634 +       int useHeaderFileSize;  /* Flag to determine if we should use file sizes from the header */
    10635 +
    10636 +       int useNANDECC;         /* Flag to decide whether or not to use NANDECC */
    10637 +
    10638 +       void *genericDevice;    /* Pointer to device context
    10639 +                                * On an mtd this holds the mtd pointer.
    10640 +                                */
    10641 +        void *superBlock;
    10642 +       
    10643 +       /* NAND access functions (Must be set before calling YAFFS)*/
    10644 +
    10645 +       int (*writeChunkToNAND) (struct yaffs_DeviceStruct * dev,
    10646 +                                int chunkInNAND, const __u8 * data,
    10647 +                                const yaffs_Spare * spare);
    10648 +       int (*readChunkFromNAND) (struct yaffs_DeviceStruct * dev,
    10649 +                                 int chunkInNAND, __u8 * data,
    10650 +                                 yaffs_Spare * spare);
    10651 +       int (*eraseBlockInNAND) (struct yaffs_DeviceStruct * dev,
    10652 +                                int blockInNAND);
    10653 +       int (*initialiseNAND) (struct yaffs_DeviceStruct * dev);
     9255+       // Entry parameters set up way early. Yaffs sets up the rest.
     9256+       int nDataBytesPerChunk;
     9257+       int   nBytesPerChunk;    // Should be a power of 2 >= 512
     9258+       int       nChunksPerBlock;       // does not need to be a power of 2
     9259+       int   nBytesPerSpare;    // spare area size
     9260+       int   startBlock;                // Start block we're allowed to use
     9261+       int   endBlock;                  // End block we're allowed to use
     9262+       int   nReservedBlocks;   // We want this tuneable so that we can reduce
     9263+                                                        // reserved blocks on NOR and RAM.
     9264+       
     9265+       int   nShortOpCaches;   // If <= 0, then short op caching is disabled, else
     9266+                                                       // the number of short op caches (don't use too many).
     9267+                                                       
     9268+       int useHeaderFileSize; // Flag to determine if we should use file sizes from the header
     9269+
     9270+       int   useNANDECC;               // Flag to decide whether or not to use NANDECC
     9271+       
     9272+       
     9273+       void *genericDevice; // Pointer to device context
     9274+                                                // On an mtd this holds the mtd pointer.
     9275+
     9276+       // NAND access functions (Must be set before calling YAFFS)
     9277+       
     9278+
     9279+       int (*writeChunkToNAND)(struct yaffs_DeviceStruct *dev,int chunkInNAND, const __u8 *data, const yaffs_Spare *spare);
     9280+       int (*readChunkFromNAND)(struct yaffs_DeviceStruct *dev,int chunkInNAND, __u8 *data, yaffs_Spare *spare);
     9281+       int (*eraseBlockInNAND)(struct yaffs_DeviceStruct *dev,int blockInNAND);       
     9282+       int (*initialiseNAND)(struct yaffs_DeviceStruct *dev);
    106549283+
    106559284+#ifdef CONFIG_YAFFS_YAFFS2
    10656 +       int (*writeChunkWithTagsToNAND) (struct yaffs_DeviceStruct * dev,
    10657 +                                        int chunkInNAND, const __u8 * data,
    10658 +                                        const yaffs_ExtendedTags * tags);
    10659 +       int (*readChunkWithTagsFromNAND) (struct yaffs_DeviceStruct * dev,
    10660 +                                         int chunkInNAND, __u8 * data,
    10661 +                                         yaffs_ExtendedTags * tags);
    10662 +       int (*markNANDBlockBad) (struct yaffs_DeviceStruct * dev, int blockNo);
    10663 +       int (*queryNANDBlock) (struct yaffs_DeviceStruct * dev, int blockNo,
    10664 +                              yaffs_BlockState * state, int *sequenceNumber);
     9285+       int (*writeChunkWithTagsToNAND)(struct yaffs_DeviceStruct *dev,int chunkInNAND, const __u8 *data, const yaffs_ExtendedTags *tags);
     9286+       int (*readChunkWithTagsFromNAND)(struct yaffs_DeviceStruct *dev,int chunkInNAND, __u8 *data, yaffs_ExtendedTags *tags);
     9287+       int (*markNANDBlockBad)(struct yaffs_DeviceStruct *dev, int blockNo);
     9288+       int (*queryNANDBlock)(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, int *sequenceNumber);
    106659289+#endif
    106669290+
    106679291+       int isYaffs2;
    10668 +       
    10669 +       /* The removeObjectCallback function must be supplied by OS flavours that
    10670 +        * need it. The Linux kernel does not use this, but yaffs direct does use
    10671 +        * it to implement the faster readdir
    10672 +        */
    10673 +       void (*removeObjectCallback)(struct yaffs_ObjectStruct *obj);
    10674 +       
    10675 +       /* Callback to mark the superblock dirsty */
    10676 +       void (*markSuperBlockDirty)(void * superblock);
    10677 +       
    10678 +       int wideTnodesDisabled; /* Set to disable wide tnodes */
    10679 +       
    10680 +
    10681 +       /* End of stuff that must be set before initialisation. */
    10682 +
    10683 +       /* Runtime parameters. Set up by YAFFS. */
    10684 +
    10685 +       __u16 chunkGroupBits;   /* 0 for devices <= 32MB. else log2(nchunks) - 16 */
    10686 +       __u16 chunkGroupSize;   /* == 2^^chunkGroupBits */
    10687 +       
    10688 +       /* Stuff to support wide tnodes */
    10689 +       __u32 tnodeWidth;
    10690 +       __u32 tnodeMask;
    10691 +       
    10692 +       /* Stuff to support various file offses to chunk/offset translations */
    10693 +       /* "Crumbs" for nDataBytesPerChunk not being a power of 2 */
    10694 +       __u32 crumbMask;
    10695 +       __u32 crumbShift;
    10696 +       __u32 crumbsPerChunk;
    10697 +       
    10698 +       /* Straight shifting for nDataBytesPerChunk being a power of 2 */
    10699 +       __u32 chunkShift;
    10700 +       __u32 chunkMask;
    10701 +       
    10702 +
     9292+
     9293+       // End of stuff that must be set before initialisation.
     9294+       
     9295+       // Runtime parameters. Set up by YAFFS.
     9296+       
     9297+       __u16 chunkGroupBits; // 0 for devices <= 32MB. else log2(nchunks) - 16
     9298+       __u16 chunkGroupSize; // == 2^^chunkGroupBits
     9299+       
    107039300+#ifdef __KERNEL__
    107049301+
    10705 +       struct semaphore sem;   /* Semaphore for waiting on erasure.*/
    10706 +       struct semaphore grossLock;     /* Gross locking semaphore */
    10707 +       __u8 *spareBuffer;      /* For mtdif2 use. Don't know the size of the buffer
    10708 +                                * at compile time so we have to allocate it.
    10709 +                                */
    10710 +       void (*putSuperFunc) (struct super_block * sb);
     9302+       struct semaphore sem;// Semaphore for waiting on erasure.
     9303+       struct semaphore grossLock; // Gross locking semaphore
     9304+       __u8 * spareBuffer; // For mtdif2 use. Don't know the size of the buffer at compile time so we have to allocate it.
     9305+       void (*putSuperFunc)(struct super_block *sb);
    107119306+#endif
    107129307+
    107139308+       int isMounted;
    107149309+       
    10715 +       int isCheckpointed;
    10716 +
    10717 +
    10718 +       /* Stuff to support block offsetting to support start block zero */
     9310+       // Stuff to support block offsetting to support start block zero
    107199311+       int internalStartBlock;
    107209312+       int internalEndBlock;
     
    107229314+       int chunkOffset;
    107239315+       
    10724 +
    10725 +       /* Runtime checkpointing stuff */
    10726 +       int checkpointPageSequence;   /* running sequence number of checkpoint pages */
    10727 +       int checkpointByteCount;
    10728 +       int checkpointByteOffset;
    10729 +       __u8 *checkpointBuffer;
    10730 +       int checkpointOpenForWrite;
    10731 +       int blocksInCheckpoint;
    10732 +       int checkpointCurrentChunk;
    10733 +       int checkpointCurrentBlock;
    10734 +       int checkpointNextBlock;
    10735 +       int *checkpointBlockList;
    10736 +       int checkpointMaxBlocks;
    10737 +       
    10738 +       /* Block Info */
     9316+       // Block Info
    107399317+       yaffs_BlockInfo *blockInfo;
    10740 +       __u8 *chunkBits;        /* bitmap of chunks in use */
    10741 +       unsigned blockInfoAlt:1;        /* was allocated using alternative strategy */
    10742 +       unsigned chunkBitsAlt:1;        /* was allocated using alternative strategy */
    10743 +       int chunkBitmapStride;  /* Number of bytes of chunkBits per block.
    10744 +                                * Must be consistent with nChunksPerBlock.
    10745 +                                */
    10746 +
    10747 +       int nErasedBlocks;
    10748 +       int allocationBlock;    /* Current block being allocated off */
     9318+       __u8 *chunkBits;   // bitmap of chunks in use
     9319+       int   chunkBitmapStride; // Number of bytes of chunkBits per block.
     9320+                                                        //     Must be consistent with nChunksPerBlock.
     9321+
     9322+
     9323+       int   nErasedBlocks;
     9324+       int   allocationBlock;                  // Current block being allocated off
    107499325+       __u32 allocationPage;
    10750 +       int allocationBlockFinder;      /* Used to search for next allocation block */
    10751 +
    10752 +       /* Runtime state */
    10753 +       int nTnodesCreated;
     9326+       int   allocationBlockFinder;    // Used to search for next allocation block
     9327+       
     9328+       // Runtime state
     9329+       int   nTnodesCreated;   
    107549330+       yaffs_Tnode *freeTnodes;
    10755 +       int nFreeTnodes;
     9331+       int  nFreeTnodes;
    107569332+       yaffs_TnodeList *allocatedTnodeList;
    107579333+
    10758 +       int isDoingGC;
    10759 +
    10760 +       int nObjectsCreated;
     9334+       int   isDoingGC;
     9335+
     9336+       int   nObjectsCreated;
    107619337+       yaffs_Object *freeObjects;
    10762 +       int nFreeObjects;
     9338+       int   nFreeObjects;
    107639339+
    107649340+       yaffs_ObjectList *allocatedObjectList;
     
    107669342+       yaffs_ObjectBucket objectBucket[YAFFS_NOBJECT_BUCKETS];
    107679343+
    10768 +       int nFreeChunks;
    10769 +
    10770 +       int currentDirtyChecker;        /* Used to find current dirtiest block */
    10771 +
    10772 +       __u32 *gcCleanupList;   /* objects to delete at the end of a GC. */
    10773 +
    10774 +       /* Statistcs */
     9344+       int      nFreeChunks;
     9345+               
     9346+       int   currentDirtyChecker;      // Used to find current dirtiest block
     9347+       
     9348+       __u32  *gcCleanupList; // objects to delete at the end of a GC.
     9349+       
     9350+       // Operations since mount
    107759351+       int nPageWrites;
    107769352+       int nPageReads;
     
    107899365+       int nUnmarkedDeletions;
    107909366+       
    10791 +       int hasPendingPrioritisedGCs; /* We think this device might have pending prioritised gcs */
    10792 +
    10793 +       /* Special directories */
    107949367+       yaffs_Object *rootDir;
    107959368+       yaffs_Object *lostNFoundDir;
    10796 +
    10797 +       /* Buffer areas for storing data to recover from write failures TODO
    10798 +        *      __u8            bufferedData[YAFFS_CHUNKS_PER_BLOCK][YAFFS_BYTES_PER_CHUNK];
    10799 +        *      yaffs_Spare bufferedSpare[YAFFS_CHUNKS_PER_BLOCK];
    10800 +        */
    10801 +       
    10802 +       int bufferedBlock;      /* Which block is buffered here? */
     9369+       
     9370+       // Buffer areas for storing data to recover from write failures
     9371+//     __u8            bufferedData[YAFFS_CHUNKS_PER_BLOCK][YAFFS_BYTES_PER_CHUNK];
     9372+//     yaffs_Spare bufferedSpare[YAFFS_CHUNKS_PER_BLOCK];
     9373+       int bufferedBlock;      // Which block is buffered here?
    108039374+       int doingBufferedBlockRewrite;
    108049375+
     
    108089379+       int cacheHits;
    108099380+
    10810 +       /* Stuff for background deletion and unlinked files.*/
    10811 +       yaffs_Object *unlinkedDir;      /* Directory where unlinked and deleted files live. */
    10812 +       yaffs_Object *deletedDir;       /* Directory where deleted objects are sent to disappear. */
    10813 +       yaffs_Object *unlinkedDeletion; /* Current file being background deleted.*/
    10814 +       int nDeletedFiles;              /* Count of files awaiting deletion;*/
    10815 +       int nUnlinkedFiles;             /* Count of unlinked files. */
    10816 +       int nBackgroundDeletions;       /* Count of background deletions. */
    10817 +
    10818 +
     9381+       // Stuff for background deletion and unlinked files.
     9382+       yaffs_Object *unlinkedDir;              // Directory where unlinked and deleted files live.
     9383+       yaffs_Object *deletedDir;               // Directory where deleted objects are sent to disappear.
     9384+       yaffs_Object *unlinkedDeletion; // Current file being background deleted.
     9385+       int nDeletedFiles;                              // Count of files awaiting deletion;
     9386+       int nUnlinkedFiles;                             // Count of unlinked files.
     9387+       int nBackgroundDeletions;                       // Count of background deletions.       
     9388+       
     9389+       //__u8 *localBuffer;
     9390+       
    108199391+       yaffs_TempBuffer tempBuffer[YAFFS_N_TEMP_BUFFERS];
    108209392+       int maxTemp;
    108219393+       int unmanagedTempAllocations;
    108229394+       int unmanagedTempDeallocations;
    10823 +
    10824 +       /* yaffs2 runtime stuff */
    10825 +       unsigned sequenceNumber;        /* Sequence number of currently allocating block */
     9395+       
     9396+       // yaffs2 runtime stuff
     9397+       unsigned sequenceNumber;                //Sequence number of currently allocating block
    108269398+       unsigned oldestDirtySequence;
    10827 +
     9399+       
    108289400+};
    108299401+
    108309402+typedef struct yaffs_DeviceStruct yaffs_Device;
    108319403+
    10832 +/* The static layout of bllock usage etc is stored in the super block header */
    10833 +typedef struct {
    10834 +        int StructType;
    10835 +       int version;
    10836 +       int checkpointStartBlock;
    10837 +       int checkpointEndBlock;
    10838 +       int startBlock;
    10839 +       int endBlock;
    10840 +       int rfu[100];
    10841 +} yaffs_SuperBlockHeader;
    10842 +       
    10843 +/* The CheckpointDevice structure holds the device information that changes at runtime and
    10844 + * must be preserved over unmount/mount cycles.
    10845 + */
    10846 +typedef struct {
    10847 +        int structType;
    10848 +       int nErasedBlocks;
    10849 +       int allocationBlock;    /* Current block being allocated off */
    10850 +       __u32 allocationPage;
    10851 +       int nFreeChunks;
    10852 +
    10853 +       int nDeletedFiles;              /* Count of files awaiting deletion;*/
    10854 +       int nUnlinkedFiles;             /* Count of unlinked files. */
    10855 +       int nBackgroundDeletions;       /* Count of background deletions. */
    10856 +
    10857 +       /* yaffs2 runtime stuff */
    10858 +       unsigned sequenceNumber;        /* Sequence number of currently allocating block */
    10859 +       unsigned oldestDirtySequence;
    10860 +
    10861 +} yaffs_CheckpointDevice;
    10862 +
    10863 +
    10864 +typedef struct {
    10865 +    int structType;
    10866 +    __u32 magic;
    10867 +    __u32 version;
    10868 +    __u32 head;
    10869 +} yaffs_CheckpointValidity;
    10870 +
    10871 +/* Function to manipulate block info */
    10872 +static Y_INLINE yaffs_BlockInfo *yaffs_GetBlockInfo(yaffs_Device * dev, int blk)
    10873 +{
    10874 +       if (blk < dev->internalStartBlock || blk > dev->internalEndBlock) {
    10875 +               T(YAFFS_TRACE_ERROR,
    10876 +                 (TSTR
    10877 +                  ("**>> yaffs: getBlockInfo block %d is not valid" TENDSTR),
    10878 +                  blk));
     9404+
     9405+// Function to manipulate block info
     9406+static  Y_INLINE yaffs_BlockInfo* yaffs_GetBlockInfo(yaffs_Device *dev, int blk)
     9407+{
     9408+       if(blk < dev->internalStartBlock || blk > dev->internalEndBlock)
     9409+       {
     9410+               T(YAFFS_TRACE_ERROR,(TSTR("**>> yaffs: getBlockInfo block %d is not valid" TENDSTR),blk));
    108799411+               YBUG();
    108809412+       }
     
    108829414+}
    108839415+
    10884 +/*----------------------- YAFFS Functions -----------------------*/
    10885 +
    10886 +int yaffs_GutsInitialise(yaffs_Device * dev);
    10887 +void yaffs_Deinitialise(yaffs_Device * dev);
    10888 +
    10889 +int yaffs_GetNumberOfFreeChunks(yaffs_Device * dev);
    10890 +
    10891 +int yaffs_RenameObject(yaffs_Object * oldDir, const YCHAR * oldName,
    10892 +                      yaffs_Object * newDir, const YCHAR * newName);
    10893 +
    10894 +int yaffs_Unlink(yaffs_Object * dir, const YCHAR * name);
    10895 +int yaffs_DeleteFile(yaffs_Object * obj);
    10896 +
    10897 +int yaffs_GetObjectName(yaffs_Object * obj, YCHAR * name, int buffSize);
    10898 +int yaffs_GetObjectFileLength(yaffs_Object * obj);
    10899 +int yaffs_GetObjectInode(yaffs_Object * obj);
    10900 +unsigned yaffs_GetObjectType(yaffs_Object * obj);
    10901 +int yaffs_GetObjectLinkCount(yaffs_Object * obj);
    10902 +
    10903 +int yaffs_SetAttributes(yaffs_Object * obj, struct iattr *attr);
    10904 +int yaffs_GetAttributes(yaffs_Object * obj, struct iattr *attr);
    10905 +
    10906 +/* File operations */
    10907 +int yaffs_ReadDataFromFile(yaffs_Object * obj, __u8 * buffer, loff_t offset,
    10908 +                          int nBytes);
    10909 +int yaffs_WriteDataToFile(yaffs_Object * obj, const __u8 * buffer, loff_t offset,
    10910 +                         int nBytes, int writeThrough);
    10911 +int yaffs_ResizeFile(yaffs_Object * obj, loff_t newSize);
    10912 +
    10913 +yaffs_Object *yaffs_MknodFile(yaffs_Object * parent, const YCHAR * name,
    10914 +                             __u32 mode, __u32 uid, __u32 gid);
    10915 +int yaffs_FlushFile(yaffs_Object * obj, int updateTime);
    10916 +
    10917 +/* Flushing and checkpointing */
    10918 +void yaffs_FlushEntireDeviceCache(yaffs_Device *dev);
    10919 +
    10920 +int yaffs_CheckpointSave(yaffs_Device *dev);
    10921 +int yaffs_CheckpointRestore(yaffs_Device *dev);
    10922 +
    10923 +/* Directory operations */
    10924 +yaffs_Object *yaffs_MknodDirectory(yaffs_Object * parent, const YCHAR * name,
    10925 +                                  __u32 mode, __u32 uid, __u32 gid);
    10926 +yaffs_Object *yaffs_FindObjectByName(yaffs_Object * theDir, const YCHAR * name);
    10927 +int yaffs_ApplyToDirectoryChildren(yaffs_Object * theDir,
    10928 +                                  int (*fn) (yaffs_Object *));
    10929 +
    10930 +yaffs_Object *yaffs_FindObjectByNumber(yaffs_Device * dev, __u32 number);
    10931 +
    10932 +/* Link operations */
    10933 +yaffs_Object *yaffs_Link(yaffs_Object * parent, const YCHAR * name,
    10934 +                        yaffs_Object * equivalentObject);
    10935 +
    10936 +yaffs_Object *yaffs_GetEquivalentObject(yaffs_Object * obj);
    10937 +
    10938 +/* Symlink operations */
    10939 +yaffs_Object *yaffs_MknodSymLink(yaffs_Object * parent, const YCHAR * name,
    10940 +                                __u32 mode, __u32 uid, __u32 gid,
    10941 +                                const YCHAR * alias);
    10942 +YCHAR *yaffs_GetSymlinkAlias(yaffs_Object * obj);
    10943 +
    10944 +/* Special inodes (fifos, sockets and devices) */
    10945 +yaffs_Object *yaffs_MknodSpecial(yaffs_Object * parent, const YCHAR * name,
    10946 +                                __u32 mode, __u32 uid, __u32 gid, __u32 rdev);
    10947 +
    10948 +/* Special directories */
    10949 +yaffs_Object *yaffs_Root(yaffs_Device * dev);
    10950 +yaffs_Object *yaffs_LostNFound(yaffs_Device * dev);
     9416+
     9417+//////////// YAFFS Functions //////////////////
     9418+
     9419+int yaffs_GutsInitialise(yaffs_Device *dev);
     9420+void yaffs_Deinitialise(yaffs_Device *dev);
     9421+
     9422+int yaffs_GetNumberOfFreeChunks(yaffs_Device *dev);
     9423+
     9424+
     9425+// Rename
     9426+int yaffs_RenameObject(yaffs_Object *oldDir, const YCHAR *oldName, yaffs_Object *newDir, const YCHAR *newName);
     9427+
     9428+// generic Object functions
     9429+int yaffs_Unlink(yaffs_Object *dir, const YCHAR *name);
     9430+int yaffs_DeleteFile(yaffs_Object *obj);
     9431+
     9432+// Object access functions.
     9433+int yaffs_GetObjectName(yaffs_Object *obj,YCHAR *name,int buffSize);
     9434+int yaffs_GetObjectFileLength(yaffs_Object *obj);
     9435+int yaffs_GetObjectInode(yaffs_Object *obj);
     9436+unsigned yaffs_GetObjectType(yaffs_Object *obj);
     9437+int yaffs_GetObjectLinkCount(yaffs_Object *obj);
     9438+
     9439+// Change inode attributes
     9440+int yaffs_SetAttributes(yaffs_Object *obj, struct iattr *attr);
     9441+int yaffs_GetAttributes(yaffs_Object *obj, struct iattr *attr);
     9442+
     9443+// File operations
     9444+int yaffs_ReadDataFromFile(yaffs_Object *obj, __u8 *buffer, __u32 offset, int nBytes);
     9445+int yaffs_WriteDataToFile(yaffs_Object *obj, const __u8 *buffer, __u32 offset, int nBytes, int writeThrough);
     9446+int yaffs_ResizeFile(yaffs_Object *obj, int newSize);
     9447+
     9448+yaffs_Object *yaffs_MknodFile(yaffs_Object *parent,const YCHAR *name, __u32 mode, __u32 uid, __u32 gid);
     9449+int yaffs_FlushFile(yaffs_Object *obj,int updateTime);
     9450+
     9451+
     9452+// Directory operations
     9453+yaffs_Object *yaffs_MknodDirectory(yaffs_Object *parent,const YCHAR *name, __u32 mode, __u32 uid, __u32 gid);
     9454+yaffs_Object *yaffs_FindObjectByName(yaffs_Object *theDir,const YCHAR *name);
     9455+int yaffs_ApplyToDirectoryChildren(yaffs_Object *theDir,int (*fn)(yaffs_Object *));
     9456+
     9457+yaffs_Object *yaffs_FindObjectByNumber(yaffs_Device *dev,__u32 number);
     9458+
     9459+// Link operations
     9460+yaffs_Object *yaffs_Link(yaffs_Object *parent, const YCHAR *name, yaffs_Object *equivalentObject);
     9461+
     9462+yaffs_Object *yaffs_GetEquivalentObject(yaffs_Object *obj);
     9463+
     9464+// Symlink operations
     9465+yaffs_Object *yaffs_MknodSymLink(yaffs_Object *parent, const YCHAR *name, __u32 mode,  __u32 uid, __u32 gid, const YCHAR *alias);
     9466+YCHAR *yaffs_GetSymlinkAlias(yaffs_Object *obj);
     9467+
     9468+// Special inodes (fifos, sockets and devices)
     9469+yaffs_Object *yaffs_MknodSpecial(yaffs_Object *parent,const YCHAR *name, __u32 mode, __u32 uid, __u32 gid,__u32 rdev);
     9470+
     9471+
     9472+// Special directories
     9473+yaffs_Object *yaffs_Root(yaffs_Device *dev);
     9474+yaffs_Object *yaffs_LostNFound(yaffs_Device *dev);
    109519475+
    109529476+#ifdef CONFIG_YAFFS_WINCE
    10953 +/* CONFIG_YAFFS_WINCE special stuff */
    10954 +void yfsd_WinFileTimeNow(__u32 target[2]);
     9477+// CONFIG_YAFFS_WINCE special stuff
     9478+void  yfsd_WinFileTimeNow(__u32 target[2]);
    109559479+#endif
    109569480+
    109579481+#ifdef __KERNEL__
    109589482+
    10959 +void yaffs_HandleDeferedFree(yaffs_Object * obj);
    10960 +#endif
    10961 +
    10962 +/* Debug dump  */
    10963 +int yaffs_DumpObject(yaffs_Object * obj);
    10964 +
    10965 +void yaffs_GutsTest(yaffs_Device * dev);
    10966 +
    10967 +/* A few useful functions */
    10968 +void yaffs_InitialiseTags(yaffs_ExtendedTags * tags);
    10969 +void yaffs_DeleteChunk(yaffs_Device * dev, int chunkId, int markNAND, int lyn);
    10970 +int yaffs_CheckFF(__u8 * buffer, int nBytes);
    10971 +void yaffs_HandleChunkError(yaffs_Device *dev, yaffs_BlockInfo *bi);
    10972 +
    10973 +#endif
    10974 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffsinterface.h linux-2.6.18.2.patched/fs/yaffs2/yaffsinterface.h
    10975 --- linux-2.6.18.2/fs/yaffs2/yaffsinterface.h   1970-01-01 01:00:00.000000000 +0100
    10976 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffsinterface.h   2006-11-25 00:15:32.000000000 +0100
    10977 @@ -0,0 +1,23 @@
     9483+void yaffs_HandleDeferedFree(yaffs_Object *obj);
     9484+#endif
     9485+
     9486+
     9487+
     9488+
     9489+// Debug dump
     9490+int yaffs_DumpObject(yaffs_Object *obj);
     9491+
     9492+
     9493+void yaffs_GutsTest(yaffs_Device *dev);
     9494+
     9495+
     9496+void yaffs_InitialiseTags(yaffs_ExtendedTags *tags);
     9497+void yaffs_DeleteChunk(yaffs_Device *dev,int chunkId,int markNAND,int lyn);
     9498+int yaffs_CheckFF(__u8 *buffer,int nBytes);
     9499+
     9500+#endif
     9501+
     9502diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffsinterface.h linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffsinterface.h
     9503--- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffsinterface.h  1970-01-01 01:00:00.000000000 +0100
     9504+++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffsinterface.h       2006-12-10 03:57:50.000000000 +0100
     9505@@ -0,0 +1,25 @@
    109789506+/*
    109799507+ * YAFFS: Yet another FFS. A NAND-flash specific file system.
     
    109929520+ *
    109939521+ */
    10994 +
     9522+ 
    109959523+#ifndef __YAFFSINTERFACE_H__
    109969524+#define __YAFFSINTERFACE_H__
    109979525+
     9526+
    109989527+int yaffs_Initialise(unsigned nBlocks);
    109999528+
    110009529+#endif
    11001 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_mtdif2.c linux-2.6.18.2.patched/fs/yaffs2/yaffs_mtdif2.c
    11002 --- linux-2.6.18.2/fs/yaffs2/yaffs_mtdif2.c     1970-01-01 01:00:00.000000000 +0100
    11003 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_mtdif2.c     2006-11-25 00:15:31.000000000 +0100
    11004 @@ -0,0 +1,234 @@
     9530+
     9531diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_mtdif2.c linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_mtdif2.c
     9532--- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_mtdif2.c    1970-01-01 01:00:00.000000000 +0100
     9533+++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_mtdif2.c 2006-12-10 04:26:05.000000000 +0100
     9534@@ -0,0 +1,211 @@
    110059535+/*
    110069536+ * YAFFS: Yet another FFS. A NAND-flash specific file system.
     
    110189548+ */
    110199549+
    11020 +/* mtd interface for YAFFS2 */
    11021 +
    11022 +const char *yaffs_mtdif2_c_version =
    11023 +    "$Id: yaffs_mtdif2.c,v 1.15 2006/11/08 06:24:34 charles Exp $";
    11024 +
     9550+// mtd interface for YAFFS2
     9551+
     9552+const char *yaffs_mtdif2_c_version = "$Id: yaffs_mtdif2.c,v 1.6 2005/08/01 20:52:35 luc Exp $";
     9553+
    110259554+#include "yportenv.h"
    110269555+
     9556+#ifdef CONFIG_YAFFS_YAFFS2
    110279557+
    110289558+#include "yaffs_mtdif2.h"
     
    110349564+#include "yaffs_packedtags2.h"
    110359565+
    11036 +int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND,
    11037 +                                     const __u8 * data,
    11038 +                                     const yaffs_ExtendedTags * tags)
     9566+
     9567+
     9568+
     9569+int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_ExtendedTags *tags)
    110399570+{
    110409571+       struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
    11041 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
    110429572+       struct mtd_oob_ops ops;
    11043 +#else
    110449573+       size_t dummy;
    11045 +#endif
    110469574+       int retval = 0;
    110479575+
    11048 +       loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
     9576+
     9577+       loff_t addr = ((loff_t)chunkInNAND) * dev->nBytesPerChunk;
    110499578+
    110509579+       yaffs_PackedTags2 pt;
    11051 +
    11052 +       T(YAFFS_TRACE_MTD,
    11053 +         (TSTR
    11054 +          ("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p"
    11055 +           TENDSTR), chunkInNAND, data, tags));
     9580+       
     9581+       T(YAFFS_TRACE_MTD,(TSTR("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p" TENDSTR),chunkInNAND,data,tags)); 
    110569582+
    110579583+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
     
    110729598+               BUG(); /* both tags and data should always be present */
    110739599+#else
    11074 +       if (tags) {
    11075 +               yaffs_PackTags2(&pt, tags);
    11076 +       }
    11077 +
    11078 +       if (data && tags) {
    11079 +               if (dev->useNANDECC)
    11080 +                       retval =
    11081 +                           mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
    11082 +                                          &dummy, data, (__u8 *) & pt, NULL);
     9600+       if(tags)
     9601+       {
     9602+               yaffs_PackTags2(&pt,tags);
     9603+       }
     9604+
     9605+       if(data && tags)
     9606+       {
     9607+               if(dev->useNANDECC)
     9608+                 retval = mtd->write_ecc(mtd,addr,dev->nBytesPerChunk,&dummy,data,(__u8 *)&pt,NULL);
    110839609+               else
    11084 +                       retval =
    11085 +                           mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
    11086 +                                          &dummy, data, (__u8 *) & pt, NULL);
    11087 +       } else {
    11088 +               if (data)
    11089 +                       retval =
    11090 +                           mtd->write(mtd, addr, dev->nDataBytesPerChunk, &dummy,
    11091 +                                      data);
    11092 +               if (tags)
    11093 +                       retval =
    11094 +                           mtd->write_oob(mtd, addr, mtd->oobsize, &dummy,
    11095 +                                          (__u8 *) & pt);
    11096 +
    11097 +       }
    11098 +#endif
    11099 +
    11100 +       if (retval == 0)
    11101 +               return YAFFS_OK;
     9610+                 retval = mtd->write_ecc(mtd,addr,dev->nBytesPerChunk,&dummy,data,(__u8 *)&pt,NULL);
     9611+       }
    111029612+       else
    11103 +               return YAFFS_FAIL;
    11104 +}
    11105 +
    11106 +int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,
    11107 +                                      __u8 * data, yaffs_ExtendedTags * tags)
     9613+       {
     9614+       if(data)
     9615+               retval = mtd->write(mtd,addr,dev->nBytesPerChunk,&dummy,data);
     9616+       if(tags)
     9617+               retval = mtd->write_oob(mtd,addr,mtd->oobsize,&dummy,(__u8 *)&pt);
     9618+               
     9619+       }
     9620+
     9621+#endif
     9622+    if (retval == 0)
     9623+       return YAFFS_OK;
     9624+    else
     9625+        return YAFFS_FAIL;
     9626+}
     9627+
     9628+int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_ExtendedTags *tags)
    111089629+{
    111099630+       struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
    11110 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
    111119631+       struct mtd_oob_ops ops;
    11112 +#endif
    111139632+       size_t dummy;
    11114 +       int retval = 0;
    11115 +
    11116 +       loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
    11117 +
     9633+        int retval = 0;
     9634+       
     9635+
     9636+       loff_t addr = ((loff_t)chunkInNAND) * dev->nBytesPerChunk;
     9637+       
    111189638+       yaffs_PackedTags2 pt;
    111199639+
    11120 +       T(YAFFS_TRACE_MTD,
    11121 +         (TSTR
    11122 +          ("nandmtd2_ReadChunkWithTagsFromNAND chunk %d data %p tags %p"
    11123 +           TENDSTR), chunkInNAND, data, tags));
     9640+       T(YAFFS_TRACE_MTD,(TSTR("nandmtd2_ReadChunkWithTagsToNAND chunk %d data %p tags %p" TENDSTR),chunkInNAND,data,tags));   
    111249641+
    111259642+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
     
    111379654+       }
    111389655+#else
    11139 +       if (data && tags) {
    11140 +               if (dev->useNANDECC) {
    11141 +                       retval =
    11142 +                           mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,
    11143 +                                         &dummy, data, dev->spareBuffer,
    11144 +                                         NULL);
    11145 +               } else {
    11146 +                       retval =
    11147 +                           mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,
    11148 +                                         &dummy, data, dev->spareBuffer,
    11149 +                                         NULL);
    11150 +               }
    11151 +       } else {
    11152 +               if (data)
    11153 +                       retval =
    11154 +                           mtd->read(mtd, addr, dev->nDataBytesPerChunk, &dummy,
    11155 +                                     data);
    11156 +               if (tags)
    11157 +                       retval =
    11158 +                           mtd->read_oob(mtd, addr, mtd->oobsize, &dummy,
    11159 +                                         dev->spareBuffer);
    11160 +       }
    11161 +#endif
    11162 +
    11163 +       memcpy(&pt, dev->spareBuffer, sizeof(pt));
    11164 +
    11165 +       if (tags)
    11166 +               yaffs_UnpackTags2(tags, &pt);
    11167 +       
    11168 +       if(tags && retval == -EBADMSG && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR)
    11169 +               tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;
    11170 +
    11171 +       if (retval == 0)
    11172 +               return YAFFS_OK;
     9656+       if(data && tags)
     9657+       {
     9658+               if(dev->useNANDECC)
     9659+               {
     9660+                       retval = mtd->read_ecc(mtd,addr,dev->nBytesPerChunk,&dummy,data,dev->spareBuffer,NULL);           
     9661+               }
     9662+               else
     9663+               {
     9664+                       retval = mtd->read_ecc(mtd,addr,dev->nBytesPerChunk,&dummy,data,dev->spareBuffer,NULL);
     9665+               }
     9666+               memcpy(&pt,dev->spareBuffer,sizeof(pt));
     9667+       }
    111739668+       else
    11174 +               return YAFFS_FAIL;
     9669+       {
     9670+       if(data)
     9671+               retval = mtd->read(mtd,addr,dev->nBytesPerChunk,&dummy,data);
     9672+       if(tags) {
     9673+               retval = mtd->read_oob(mtd,addr,mtd->oobsize,&dummy,dev->spareBuffer);
     9674+               memcpy(&pt, mtd->oobinfo.oobfree[0][0] + (char *)dev->spareBuffer, sizeof(pt));
     9675+       }
     9676+       }
     9677+
     9678+    if(tags)
     9679+       yaffs_UnpackTags2(tags,&pt);
     9680+#endif   
     9681+    if (retval == 0)
     9682+       return YAFFS_OK;
     9683+    else
     9684+        return YAFFS_FAIL;
    111759685+}
    111769686+
     
    111799689+       struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
    111809690+       int retval;
    11181 +       T(YAFFS_TRACE_MTD,
    11182 +         (TSTR("nandmtd2_MarkNANDBlockBad %d" TENDSTR), blockNo));
    11183 +
    11184 +       retval =
    11185 +           mtd->block_markbad(mtd,
    11186 +                              blockNo * dev->nChunksPerBlock *
    11187 +                              dev->nDataBytesPerChunk);
    11188 +
    11189 +       if (retval == 0)
    11190 +               return YAFFS_OK;
    11191 +       else
    11192 +               return YAFFS_FAIL;
    11193 +
    11194 +}
    11195 +
    11196 +int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
    11197 +                           yaffs_BlockState * state, int *sequenceNumber)
     9691+       T(YAFFS_TRACE_MTD,(TSTR("nandmtd2_MarkNANDBlockBad %d" TENDSTR),blockNo));     
     9692+       
     9693+       
     9694+       retval = mtd->block_markbad(mtd,blockNo * dev->nChunksPerBlock * dev->nBytesPerChunk);
     9695+
     9696+    if (retval == 0)
     9697+       return YAFFS_OK;
     9698+    else
     9699+        return YAFFS_FAIL;
     9700+
     9701+}
     9702+
     9703+int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, int *sequenceNumber)
    111989704+{
    111999705+       struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
    112009706+       int retval;
    11201 +
    11202 +       T(YAFFS_TRACE_MTD,
    11203 +         (TSTR("nandmtd2_QueryNANDBlock %d" TENDSTR), blockNo));
    11204 +       retval =
    11205 +           mtd->block_isbad(mtd,
    11206 +                            blockNo * dev->nChunksPerBlock *
    11207 +                            dev->nDataBytesPerChunk);
    11208 +
    11209 +       if (retval) {
    11210 +               T(YAFFS_TRACE_MTD, (TSTR("block is bad" TENDSTR)));
    11211 +
     9707+       
     9708+       T(YAFFS_TRACE_MTD,(TSTR("nandmtd2_QueryNANDBlock %d" TENDSTR),blockNo));       
     9709+       retval = mtd->block_isbad(mtd,blockNo* dev->nChunksPerBlock * dev->nBytesPerChunk);
     9710+       
     9711+       if(retval)
     9712+       {
     9713+               T(YAFFS_TRACE_MTD,(TSTR("block is bad" TENDSTR)));
     9714+       
    112129715+               *state = YAFFS_BLOCK_STATE_DEAD;
    112139716+               *sequenceNumber = 0;
    11214 +       } else {
     9717+       }
     9718+       else
     9719+       {
    112159720+               yaffs_ExtendedTags t;
    11216 +               nandmtd2_ReadChunkWithTagsFromNAND(dev,
    11217 +                                                  blockNo *
    11218 +                                                  dev->nChunksPerBlock, NULL,
    11219 +                                                  &t);
    11220 +
    11221 +               if (t.chunkUsed) {
    11222 +                       *sequenceNumber = t.sequenceNumber;
    11223 +                       *state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
    11224 +               } else {
    11225 +                       *sequenceNumber = 0;
    11226 +                       *state = YAFFS_BLOCK_STATE_EMPTY;
    11227 +               }
    11228 +       }
    11229 +       T(YAFFS_TRACE_MTD,
    11230 +         (TSTR("block is bad seq %d state %d" TENDSTR), *sequenceNumber,
    11231 +          *state));
    11232 +
    11233 +       if (retval == 0)
    11234 +               return YAFFS_OK;
    11235 +       else
    11236 +               return YAFFS_FAIL;
    11237 +}
    11238 +
    11239 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_mtdif2.h linux-2.6.18.2.patched/fs/yaffs2/yaffs_mtdif2.h
    11240 --- linux-2.6.18.2/fs/yaffs2/yaffs_mtdif2.h     1970-01-01 01:00:00.000000000 +0100
    11241 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_mtdif2.h     2006-11-25 00:15:32.000000000 +0100
    11242 @@ -0,0 +1,29 @@
     9721+               nandmtd2_ReadChunkWithTagsFromNAND(dev,blockNo * dev->nChunksPerBlock,NULL, &t);
     9722+               
     9723+               if(t.chunkUsed)
     9724+               {
     9725+                 *sequenceNumber = t.sequenceNumber;
     9726+                 *state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
     9727+               }
     9728+               else
     9729+               {
     9730+                 *sequenceNumber = 0;
     9731+                 *state = YAFFS_BLOCK_STATE_EMPTY;
     9732+               }
     9733+       }
     9734+               T(YAFFS_TRACE_MTD,(TSTR("block is bad seq %d state %d" TENDSTR), *sequenceNumber,*state));
     9735+
     9736+    if (retval == 0)
     9737+       return YAFFS_OK;
     9738+    else
     9739+        return YAFFS_FAIL;
     9740+}
     9741+
     9742+#endif
     9743+
     9744+
     9745+
     9746diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_mtdif2.h linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_mtdif2.h
     9747--- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_mtdif2.h    1970-01-01 01:00:00.000000000 +0100
     9748+++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_mtdif2.h 2006-12-10 03:57:50.000000000 +0100
     9749@@ -0,0 +1,27 @@
    112439750+/*
    112449751+ * YAFFS: Yet another FFS. A NAND-flash specific file system.
     
    112569763+ */
    112579764+
     9765+
    112589766+#ifndef __YAFFS_MTDIF2_H__
    112599767+#define __YAFFS_MTDIF2_H__
    112609768+
     9769+
    112619770+#include "yaffs_guts.h"
    11262 +int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND,
    11263 +                                     const __u8 * data,
    11264 +                                     const yaffs_ExtendedTags * tags);
    11265 +int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,
    11266 +                                      __u8 * data, yaffs_ExtendedTags * tags);
     9771+int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_ExtendedTags *tags);
     9772+int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_ExtendedTags *tags);
    112679773+int nandmtd2_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo);
    11268 +int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
    11269 +                           yaffs_BlockState * state, int *sequenceNumber);
    11270 +
    11271 +#endif
    11272 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_mtdif.c linux-2.6.18.2.patched/fs/yaffs2/yaffs_mtdif.c
    11273 --- linux-2.6.18.2/fs/yaffs2/yaffs_mtdif.c      1970-01-01 01:00:00.000000000 +0100
    11274 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_mtdif.c      2006-11-25 00:15:31.000000000 +0100
    11275 @@ -0,0 +1,241 @@
     9774+int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, int *sequenceNumber);
     9775+
     9776+#endif
     9777diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_mtdif.c linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_mtdif.c
     9778--- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_mtdif.c     1970-01-01 01:00:00.000000000 +0100
     9779+++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_mtdif.c  2006-12-10 04:19:40.000000000 +0100
     9780@@ -0,0 +1,228 @@
    112769781+/*
    112779782+ * YAFFS: Yet another FFS. A NAND-flash specific file system.
     
    112899794+ */
    112909795+
    11291 +const char *yaffs_mtdif_c_version =
    11292 +    "$Id: yaffs_mtdif.c,v 1.16 2006/11/08 06:24:34 charles Exp $";
    11293 +
     9796+const char *yaffs_mtdif_c_version = "$Id: yaffs_mtdif.c,v 1.7 2005/08/01 20:52:35 luc Exp $";
     9797+
    112949798+#include "yportenv.h"
    112959799+
     9800+#ifdef CONFIG_YAFFS_YAFFS1
    112969801+
    112979802+#include "yaffs_mtdif.h"
     
    113029807+#include "linux/mtd/nand.h"
    113039808+
    11304 +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18))
    113059809+static struct nand_oobinfo yaffs_oobinfo = {
    113069810+       .useecc = 1,
     
    113089812+       .eccpos = {8, 9, 10, 13, 14, 15}
    113099813+};
    11310 +
     9814+static inline void translate_spare2oob(const yaffs_Spare *spare, __u8 *oob)
     9815+{
     9816+        oob[0] = spare->tagByte0;
     9817+        oob[1] = spare->tagByte1;
     9818+        oob[2] = spare->tagByte2;
     9819+        oob[3] = spare->tagByte3;
     9820+        oob[4] = spare->tagByte4;
     9821+        oob[5] = spare->tagByte5 & 0x3f;
     9822+        oob[5] |= spare->blockStatus == 'Y' ? 0: 0x80;
     9823+        oob[5] |= spare->pageStatus == 0 ? 0: 0x40;
     9824+        oob[6] = spare->tagByte6;
     9825+        oob[7] = spare->tagByte7;
     9826+}
     9827+
     9828+static inline void translate_oob2spare(yaffs_Spare *spare, __u8 *oob)
     9829+{
     9830+        struct yaffs_NANDSpare *nspare = (struct yaffs_NANDSpare *)spare;
     9831+        spare->tagByte0 = oob[0];
     9832+        spare->tagByte1 = oob[1];
     9833+        spare->tagByte2 = oob[2];
     9834+        spare->tagByte3 = oob[3];
     9835+        spare->tagByte4 = oob[4];
     9836+        spare->tagByte5 = oob[5] == 0xff ? 0xff : oob[5] & 0x3f;
     9837+        spare->blockStatus = oob[5] & 0x80 ? 0xff : 'Y';
     9838+        spare->pageStatus = oob[5] & 0x40 ? 0xff : 0;
     9839+        spare->tagByte6 = oob[6];
     9840+        spare->tagByte7 = oob[7];
     9841+
     9842+        nspare->eccres1 = nspare->eccres2 = 0; /* FIXME */
     9843+}
    113119844+static struct nand_oobinfo yaffs_noeccinfo = {
    113129845+       .useecc = 0,
    113139846+};
    11314 +#endif
    11315 +
     9847+
     9848+
     9849+int nandmtd_WriteChunkToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_Spare *spare)
     9850+{
     9851+       struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
     9852+       struct mtd_oob_ops ops;
     9853+       size_t dummy;
     9854+    int retval = 0;
     9855+       
     9856+       loff_t addr = ((loff_t)chunkInNAND) * dev->nBytesPerChunk;
     9857+       
    113169858+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
    11317 +static inline void translate_spare2oob(const yaffs_Spare *spare, __u8 *oob)
    11318 +{
    11319 +       oob[0] = spare->tagByte0;
    11320 +       oob[1] = spare->tagByte1;
    11321 +       oob[2] = spare->tagByte2;
    11322 +       oob[3] = spare->tagByte3;
    11323 +       oob[4] = spare->tagByte4;
    11324 +       oob[5] = spare->tagByte5 & 0x3f;
    11325 +       oob[5] |= spare->blockStatus == 'Y' ? 0: 0x80;
    11326 +       oob[5] |= spare->pageStatus == 0 ? 0: 0x40;
    11327 +       oob[6] = spare->tagByte6;
    11328 +       oob[7] = spare->tagByte7;
    11329 +}
    11330 +
    11331 +static inline void translate_oob2spare(yaffs_Spare *spare, __u8 *oob)
    11332 +{
    11333 +       struct yaffs_NANDSpare *nspare = (struct yaffs_NANDSpare *)spare;
    11334 +       spare->tagByte0 = oob[0];
    11335 +       spare->tagByte1 = oob[1];
    11336 +       spare->tagByte2 = oob[2];
    11337 +       spare->tagByte3 = oob[3];
    11338 +       spare->tagByte4 = oob[4];
    11339 +       spare->tagByte5 = oob[5] == 0xff ? 0xff : oob[5] & 0x3f;
    11340 +       spare->blockStatus = oob[5] & 0x80 ? 0xff : 'Y';
    11341 +       spare->pageStatus = oob[5] & 0x40 ? 0xff : 0;
    11342 +       spare->tagByte6 = oob[6];
    11343 +       spare->tagByte7 = oob[7];
    11344 +
    11345 +       nspare->eccres1 = nspare->eccres2 = 0; /* FIXME */
    11346 +}
    11347 +#endif
    11348 +
    11349 +int nandmtd_WriteChunkToNAND(yaffs_Device * dev, int chunkInNAND,
    11350 +                            const __u8 * data, const yaffs_Spare * spare)
     9859+        __u8 spareAsBytes[8]; /* OOB */
     9860+
     9861+        if (data && !spare)
     9862+                retval = mtd->write(mtd, addr, dev->nDataBytesPerChunk,
     9863+                                &dummy, data);
     9864+        else if (spare) {
     9865+                if (dev->useNANDECC) {
     9866+                        translate_spare2oob(spare, spareAsBytes);
     9867+                        ops.mode = MTD_OOB_AUTO;
     9868+                        ops.ooblen = 8; /* temp hack */
     9869+                } else {
     9870+                        ops.mode = MTD_OOB_RAW;
     9871+                        ops.ooblen = YAFFS_BYTES_PER_SPARE;
     9872+                }
     9873+                ops.len = data ? dev->nDataBytesPerChunk : ops.ooblen;
     9874+                ops.datbuf = (u8 *)data;
     9875+                ops.ooboffs = 0;
     9876+                ops.oobbuf = spareAsBytes;
     9877+                retval = mtd->write_oob(mtd, addr, &ops);
     9878+        }
     9879+#else
     9880+       __u8 *spareAsBytes = (__u8 *)spare;
     9881+
     9882+       if(data && spare)
     9883+       {
     9884+               if(dev->useNANDECC)
     9885+                       retval = mtd->write_ecc(mtd,addr,dev->nBytesPerChunk,&dummy,data,spareAsBytes,&yaffs_oobinfo);
     9886+               else
     9887+                       retval = mtd->write_ecc(mtd,addr,dev->nBytesPerChunk,&dummy,data,spareAsBytes,&yaffs_noeccinfo);
     9888+       }
     9889+       else
     9890+       {
     9891+       if(data)
     9892+               retval = mtd->write(mtd,addr,dev->nBytesPerChunk,&dummy,data);
     9893+       if(spare)
     9894+               retval = mtd->write_oob(mtd,addr,YAFFS_BYTES_PER_SPARE,&dummy,spareAsBytes);
     9895+       }
     9896+#endif
     9897+    if (retval == 0)
     9898+       return YAFFS_OK;
     9899+    else
     9900+        return YAFFS_FAIL;
     9901+}
     9902+
     9903+int nandmtd_ReadChunkFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_Spare *spare)
    113519904+{
    113529905+       struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
     9906+       struct mtd_oob_ops ops;
     9907+       size_t dummy;
     9908+    int retval = 0;
     9909+       
     9910+       loff_t addr = ((loff_t)chunkInNAND) * dev->nBytesPerChunk;
    113539911+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
    11354 +       struct mtd_oob_ops ops;
    11355 +#endif
    11356 +       size_t dummy;
    11357 +       int retval = 0;
    11358 +
    11359 +       loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
    11360 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
    11361 +       __u8 spareAsBytes[8]; /* OOB */
    11362 +
    11363 +       if (data && !spare)
    11364 +               retval = mtd->write(mtd, addr, dev->nDataBytesPerChunk,
    11365 +                               &dummy, data);
    11366 +       else if (spare) {
    11367 +               if (dev->useNANDECC) {
    11368 +                       translate_spare2oob(spare, spareAsBytes);
    11369 +                       ops.mode = MTD_OOB_AUTO;
    11370 +                       ops.ooblen = 8; /* temp hack */
    11371 +               } else {
    11372 +                       ops.mode = MTD_OOB_RAW;
    11373 +                       ops.ooblen = YAFFS_BYTES_PER_SPARE;
    11374 +               }
    11375 +               ops.len = data ? dev->nDataBytesPerChunk : ops.ooblen;
    11376 +               ops.datbuf = (u8 *)data;
    11377 +               ops.ooboffs = 0;
    11378 +               ops.oobbuf = spareAsBytes;
    11379 +               retval = mtd->write_oob(mtd, addr, &ops);
    11380 +       }
    11381 +#else
    11382 +       __u8 *spareAsBytes = (__u8 *) spare;
    11383 +
    11384 +       if (data && spare) {
    11385 +               if (dev->useNANDECC)
    11386 +                       retval =
    11387 +                           mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
    11388 +                                          &dummy, data, spareAsBytes,
    11389 +                                          &yaffs_oobinfo);
     9912+        __u8 spareAsBytes[8]; /* OOB */
     9913+
     9914+        if (data && !spare)
     9915+                retval = mtd->read(mtd, addr, dev->nDataBytesPerChunk,
     9916+                                &dummy, data);
     9917+        else if (spare) {
     9918+                if (dev->useNANDECC) {
     9919+                        ops.mode = MTD_OOB_AUTO;
     9920+                        ops.ooblen = 8; /* temp hack */
     9921+                } else {
     9922+                        ops.mode = MTD_OOB_RAW;
     9923+                        ops.ooblen = YAFFS_BYTES_PER_SPARE;
     9924+                }
     9925+                ops.len = data ? dev->nDataBytesPerChunk : ops.ooblen;
     9926+                ops.datbuf = data;
     9927+                ops.ooboffs = 0;
     9928+                ops.oobbuf = spareAsBytes;
     9929+                retval = mtd->read_oob(mtd, addr, &ops);
     9930+                if (dev->useNANDECC)
     9931+                        translate_oob2spare(spare, spareAsBytes);
     9932+        }
     9933+#else 
     9934+       __u8 *spareAsBytes = (__u8 *)spare;
     9935+       
     9936+       if(data && spare)
     9937+       {
     9938+               if(dev->useNANDECC)
     9939+               {   // Careful, this call adds 2 ints to the end of the spare data.  Calling function should
     9940+            // allocate enough memory for spare, i.e. [YAFFS_BYTES_PER_SPARE+2*sizeof(int)].
     9941+               retval = mtd->read_ecc(mtd,addr,dev->nBytesPerChunk,&dummy,data,spareAsBytes,&yaffs_oobinfo);           
     9942+               }
    113909943+               else
    11391 +                       retval =
    11392 +                           mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
    11393 +                                          &dummy, data, spareAsBytes,
    11394 +                                          &yaffs_noeccinfo);
    11395 +       } else {
    11396 +               if (data)
    11397 +                       retval =
    11398 +                           mtd->write(mtd, addr, dev->nDataBytesPerChunk, &dummy,
    11399 +                                      data);
    11400 +               if (spare)
    11401 +                       retval =
    11402 +                           mtd->write_oob(mtd, addr, YAFFS_BYTES_PER_SPARE,
    11403 +                                          &dummy, spareAsBytes);
    11404 +       }
    11405 +#endif
    11406 +
    11407 +       if (retval == 0)
    11408 +               return YAFFS_OK;
     9944+               {
     9945+                       retval = mtd->read_ecc(mtd,addr,dev->nBytesPerChunk,&dummy,data,spareAsBytes,&yaffs_noeccinfo);
     9946+               }
     9947+       }
    114099948+       else
    11410 +               return YAFFS_FAIL;
    11411 +}
    11412 +
    11413 +int nandmtd_ReadChunkFromNAND(yaffs_Device * dev, int chunkInNAND, __u8 * data,
    11414 +                             yaffs_Spare * spare)
     9949+       {
     9950+       if(data)
     9951+               retval = mtd->read(mtd,addr,dev->nBytesPerChunk,&dummy,data);
     9952+       if(spare)
     9953+               retval = mtd->read_oob(mtd,addr,YAFFS_BYTES_PER_SPARE,&dummy,spareAsBytes);
     9954+       }
     9955+#endif
     9956+    if (retval == 0)
     9957+       return YAFFS_OK;
     9958+    else
     9959+        return YAFFS_FAIL;
     9960+}
     9961+
     9962+// Callback not needed for NAND
     9963+#if 0
     9964+static void nandmtd_EraseCallback(struct erase_info *ei)
     9965+{
     9966+       yaffs_Device *dev = (yaffs_Device *)ei->priv;   
     9967+       up(&dev->sem);
     9968+}
     9969+#endif
     9970+
     9971+
     9972+int nandmtd_EraseBlockInNAND(yaffs_Device *dev, int blockNumber)
    114159973+{
    114169974+       struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
    11417 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
    11418 +       struct mtd_oob_ops ops;
    11419 +#endif
    11420 +       size_t dummy;
    11421 +       int retval = 0;
    11422 +
    11423 +       loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;
    11424 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
    11425 +       __u8 spareAsBytes[8]; /* OOB */
    11426 +
    11427 +       if (data && !spare)
    11428 +               retval = mtd->read(mtd, addr, dev->nDataBytesPerChunk,
    11429 +                               &dummy, data);
    11430 +       else if (spare) {
    11431 +               if (dev->useNANDECC) {
    11432 +                       ops.mode = MTD_OOB_AUTO;
    11433 +                       ops.ooblen = 8; /* temp hack */
    11434 +               } else {
    11435 +                       ops.mode = MTD_OOB_RAW;
    11436 +                       ops.ooblen = YAFFS_BYTES_PER_SPARE;
    11437 +               }
    11438 +               ops.len = data ? dev->nDataBytesPerChunk : ops.ooblen;
    11439 +               ops.datbuf = data;
    11440 +               ops.ooboffs = 0;
    11441 +               ops.oobbuf = spareAsBytes;
    11442 +               retval = mtd->read_oob(mtd, addr, &ops);
    11443 +               if (dev->useNANDECC)
    11444 +                       translate_oob2spare(spare, spareAsBytes);
    11445 +       }
    11446 +#else
    11447 +       __u8 *spareAsBytes = (__u8 *) spare;
    11448 +
    11449 +       if (data && spare) {
    11450 +               if (dev->useNANDECC) { 
    11451 +                       /* Careful, this call adds 2 ints */
    11452 +                       /* to the end of the spare data.  Calling function */
    11453 +                       /* should allocate enough memory for spare, */
    11454 +                       /* i.e. [YAFFS_BYTES_PER_SPARE+2*sizeof(int)]. */
    11455 +                       retval =
    11456 +                           mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,
    11457 +                                         &dummy, data, spareAsBytes,
    11458 +                                         &yaffs_oobinfo);
    11459 +               } else {
    11460 +                       retval =
    11461 +                           mtd->read_ecc(mtd, addr, dev->nDataBytesPerChunk,
    11462 +                                         &dummy, data, spareAsBytes,
    11463 +                                         &yaffs_noeccinfo);
    11464 +               }
    11465 +       } else {
    11466 +               if (data)
    11467 +                       retval =
    11468 +                           mtd->read(mtd, addr, dev->nDataBytesPerChunk, &dummy,
    11469 +                                     data);
    11470 +               if (spare)
    11471 +                       retval =
    11472 +                           mtd->read_oob(mtd, addr, YAFFS_BYTES_PER_SPARE,
    11473 +                                         &dummy, spareAsBytes);
    11474 +       }
    11475 +#endif
    11476 +
    11477 +       if (retval == 0)
    11478 +               return YAFFS_OK;
    11479 +       else
    11480 +               return YAFFS_FAIL;
    11481 +}
    11482 +
    11483 +int nandmtd_EraseBlockInNAND(yaffs_Device * dev, int blockNumber)
    11484 +{
    11485 +       struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
    11486 +       __u32 addr =
    11487 +           ((loff_t) blockNumber) * dev->nDataBytesPerChunk
    11488 +               * dev->nChunksPerBlock;
     9975+       __u32 addr = ((loff_t) blockNumber) * dev->nBytesPerChunk * dev->nChunksPerBlock;
    114899976+       struct erase_info ei;
    11490 +       int retval = 0;
    11491 +
     9977+    int retval = 0;
     9978+       
    114929979+       ei.mtd = mtd;
    114939980+       ei.addr = addr;
    11494 +       ei.len = dev->nDataBytesPerChunk * dev->nChunksPerBlock;
     9981+       ei.len = dev->nBytesPerChunk * dev->nChunksPerBlock;
    114959982+       ei.time = 1000;
    114969983+       ei.retries = 2;
    114979984+       ei.callback = NULL;
    11498 +       ei.priv = (u_long) dev;
    11499 +
    11500 +       /* Todo finish off the ei if required */
    11501 +
    11502 +       sema_init(&dev->sem, 0);
    11503 +
    11504 +       retval = mtd->erase(mtd, &ei);
    11505 +
    11506 +       if (retval == 0)
    11507 +               return YAFFS_OK;
    11508 +       else
    11509 +               return YAFFS_FAIL;
    11510 +}
    11511 +
    11512 +int nandmtd_InitialiseNAND(yaffs_Device * dev)
     9985+       ei.priv = (u_long)dev;
     9986+       
     9987+       // Todo finish off the ei if required
     9988+       
     9989+       sema_init(&dev->sem,0);
     9990+
     9991+       retval = mtd->erase(mtd,&ei);   
     9992+       
     9993+       //No need for callback
     9994+       // down(&dev->sem); // Wait for the erasure to complete
     9995+
     9996+    if (retval == 0)   
     9997+       return YAFFS_OK;
     9998+    else
     9999+        return YAFFS_FAIL;
     10000+}
     10001+
     10002+int nandmtd_InitialiseNAND(yaffs_Device *dev)
    1151310003+{
    1151410004+       return YAFFS_OK;
    1151510005+}
    1151610006+
    11517 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_mtdif.h linux-2.6.18.2.patched/fs/yaffs2/yaffs_mtdif.h
    11518 --- linux-2.6.18.2/fs/yaffs2/yaffs_mtdif.h      1970-01-01 01:00:00.000000000 +0100
    11519 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_mtdif.h      2006-11-25 00:15:32.000000000 +0100
    11520 @@ -0,0 +1,31 @@
     10007+#endif // CONFIG_YAFFS_YAFFS1
     10008+
     10009diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_mtdif.h linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_mtdif.h
     10010--- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_mtdif.h     1970-01-01 01:00:00.000000000 +0100
     10011+++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_mtdif.h  2006-12-10 03:57:50.000000000 +0100
     10012@@ -0,0 +1,33 @@
    1152110013+/*
    1152210014+ * YAFFS: Yet another FFS. A NAND-flash specific file system.
     
    1153510027+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
    1153610028+ *
    11537 + * $Id: yaffs_mtdif.h,v 1.3 2005/08/11 01:07:43 marty Exp $
     10029+ * $Id: yaffs_mtdif.h,v 1.2 2005/07/19 20:41:59 charles Exp $
    1153810030+ */
    1153910031+
     
    1154310035+#include "yaffs_guts.h"
    1154410036+
    11545 +int nandmtd_WriteChunkToNAND(yaffs_Device * dev, int chunkInNAND,
    11546 +                            const __u8 * data, const yaffs_Spare * spare);
    11547 +int nandmtd_ReadChunkFromNAND(yaffs_Device * dev, int chunkInNAND, __u8 * data,
    11548 +                             yaffs_Spare * spare);
    11549 +int nandmtd_EraseBlockInNAND(yaffs_Device * dev, int blockNumber);
    11550 +int nandmtd_InitialiseNAND(yaffs_Device * dev);
    11551 +#endif
    11552 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_nand.c linux-2.6.18.2.patched/fs/yaffs2/yaffs_nand.c
    11553 --- linux-2.6.18.2/fs/yaffs2/yaffs_nand.c       1970-01-01 01:00:00.000000000 +0100
    11554 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_nand.c       2006-11-25 00:15:31.000000000 +0100
    11555 @@ -0,0 +1,135 @@
    11556 +/*
    11557 + * YAFFS: Yet another FFS. A NAND-flash specific file system.
    11558 + *
    11559 + * Copyright (C) 2002 Aleph One Ltd.
    11560 + *   for Toby Churchill Ltd and Brightstar Engineering
    11561 + *
    11562 + * Created by Charles Manning <charles@aleph1.co.uk>
    11563 + *
    11564 + * This program is free software; you can redistribute it and/or modify
    11565 + * it under the terms of the GNU General Public License version 2 as
    11566 + * published by the Free Software Foundation.
    11567 + *
    11568 + */
    11569 +
    11570 +const char *yaffs_nand_c_version =
    11571 +    "$Id: yaffs_nand.c,v 1.5 2006/11/08 09:52:12 charles Exp $";
    11572 +
    11573 +#include "yaffs_nand.h"
    11574 +#include "yaffs_tagscompat.h"
    11575 +#include "yaffs_tagsvalidity.h"
    11576 +
    11577 +
    11578 +int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,
    11579 +                                          __u8 * buffer,
    11580 +                                          yaffs_ExtendedTags * tags)
    11581 +{
    11582 +       int result;
    11583 +       yaffs_ExtendedTags localTags;
    11584 +       
    11585 +       int realignedChunkInNAND = chunkInNAND - dev->chunkOffset;
    11586 +       
    11587 +       /* If there are no tags provided, use local tags to get prioritised gc working */
    11588 +       if(!tags)
    11589 +               tags = &localTags;
    11590 +
    11591 +       if (dev->readChunkWithTagsFromNAND)
    11592 +               result = dev->readChunkWithTagsFromNAND(dev, realignedChunkInNAND, buffer,
    11593 +                                                     tags);
    11594 +       else
    11595 +               result = yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(dev,
    11596 +                                                                       realignedChunkInNAND,
    11597 +                                                                       buffer,
    11598 +                                                                       tags); 
    11599 +       if(tags &&
    11600 +          tags->eccResult > YAFFS_ECC_RESULT_NO_ERROR){
    11601 +       
    11602 +               yaffs_BlockInfo *bi = yaffs_GetBlockInfo(dev, chunkInNAND/dev->nChunksPerBlock);
    11603 +                yaffs_HandleChunkError(dev,bi);
    11604 +       }
    11605 +                                                               
    11606 +       return result;
    11607 +}
    11608 +
    11609 +int yaffs_WriteChunkWithTagsToNAND(yaffs_Device * dev,
    11610 +                                                  int chunkInNAND,
    11611 +                                                  const __u8 * buffer,
    11612 +                                                  yaffs_ExtendedTags * tags)
    11613 +{
    11614 +       chunkInNAND -= dev->chunkOffset;
    11615 +
    11616 +       
    11617 +       if (tags) {
    11618 +               tags->sequenceNumber = dev->sequenceNumber;
    11619 +               tags->chunkUsed = 1;
    11620 +               if (!yaffs_ValidateTags(tags)) {
    11621 +                       T(YAFFS_TRACE_ERROR,
    11622 +                         (TSTR("Writing uninitialised tags" TENDSTR)));
    11623 +                       YBUG();
    11624 +               }
    11625 +               T(YAFFS_TRACE_WRITE,
    11626 +                 (TSTR("Writing chunk %d tags %d %d" TENDSTR), chunkInNAND,
    11627 +                  tags->objectId, tags->chunkId));
    11628 +       } else {
    11629 +               T(YAFFS_TRACE_ERROR, (TSTR("Writing with no tags" TENDSTR)));
    11630 +               YBUG();
    11631 +       }
    11632 +
    11633 +       if (dev->writeChunkWithTagsToNAND)
    11634 +               return dev->writeChunkWithTagsToNAND(dev, chunkInNAND, buffer,
    11635 +                                                    tags);
    11636 +       else
    11637 +               return yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(dev,
    11638 +                                                                      chunkInNAND,
    11639 +                                                                      buffer,
    11640 +                                                                      tags);
    11641 +}
    11642 +
    11643 +int yaffs_MarkBlockBad(yaffs_Device * dev, int blockNo)
    11644 +{
    11645 +       blockNo -= dev->blockOffset;
    11646 +
    11647 +;
    11648 +       if (dev->markNANDBlockBad)
    11649 +               return dev->markNANDBlockBad(dev, blockNo);
    11650 +       else
    11651 +               return yaffs_TagsCompatabilityMarkNANDBlockBad(dev, blockNo);
    11652 +}
    11653 +
    11654 +int yaffs_QueryInitialBlockState(yaffs_Device * dev,
    11655 +                                                int blockNo,
    11656 +                                                yaffs_BlockState * state,
    11657 +                                                unsigned *sequenceNumber)
    11658 +{
    11659 +       blockNo -= dev->blockOffset;
    11660 +
    11661 +       if (dev->queryNANDBlock)
    11662 +               return dev->queryNANDBlock(dev, blockNo, state, sequenceNumber);
    11663 +       else
    11664 +               return yaffs_TagsCompatabilityQueryNANDBlock(dev, blockNo,
    11665 +                                                            state,
    11666 +                                                            sequenceNumber);
    11667 +}
    11668 +
    11669 +
    11670 +int yaffs_EraseBlockInNAND(struct yaffs_DeviceStruct *dev,
    11671 +                                 int blockInNAND)
    11672 +{
    11673 +       int result;
    11674 +
    11675 +       blockInNAND -= dev->blockOffset;
    11676 +
    11677 +
    11678 +       dev->nBlockErasures++;
    11679 +       result = dev->eraseBlockInNAND(dev, blockInNAND);
    11680 +
    11681 +       return result;
    11682 +}
    11683 +
    11684 +int yaffs_InitialiseNAND(struct yaffs_DeviceStruct *dev)
    11685 +{
    11686 +       return dev->initialiseNAND(dev);
    11687 +}
    11688 +
    11689 +
    11690 +
    11691 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_nandemul2k.h linux-2.6.18.2.patched/fs/yaffs2/yaffs_nandemul2k.h
    11692 --- linux-2.6.18.2/fs/yaffs2/yaffs_nandemul2k.h 1970-01-01 01:00:00.000000000 +0100
    11693 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_nandemul2k.h 2006-11-25 00:15:32.000000000 +0100
    11694 @@ -0,0 +1,42 @@
     10037+int nandmtd_WriteChunkToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_Spare *spare);
     10038+int nandmtd_ReadChunkFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_Spare *spare);
     10039+int nandmtd_EraseBlockInNAND(yaffs_Device *dev, int blockNumber);
     10040+int nandmtd_InitialiseNAND(yaffs_Device *dev);
     10041+#endif
     10042+
     10043+
     10044+
     10045+
     10046diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_nandemul2k.h linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_nandemul2k.h
     10047--- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_nandemul2k.h        1970-01-01 01:00:00.000000000 +0100
     10048+++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_nandemul2k.h     2006-12-10 03:57:50.000000000 +0100
     10049@@ -0,0 +1,38 @@
    1169510050+/*
    1169610051+ * YAFFS: Yet another FFS. A NAND-flash specific file system.
     
    1171010065+ * yaffs_nandemul2k.h: Interface to emulated NAND functions (2k page size)
    1171110066+ *
    11712 + * $Id: yaffs_nandemul2k.h,v 1.2 2005/08/11 02:37:49 marty Exp $
     10067+ * $Id: yaffs_nandemul2k.h,v 1.1 2004/12/17 04:39:04 charles Exp $
    1171310068+ */
    11714 +
     10069+ 
    1171510070+#ifndef __YAFFS_NANDEMUL2K_H__
    1171610071+#define __YAFFS_NANDEMUL2K_H__
    1171710072+
    11718 +#include "yaffs_guts.h"
    11719 +
    11720 +int nandemul2k_WriteChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev,
    11721 +                                       int chunkInNAND, const __u8 * data,
    11722 +                                       yaffs_ExtendedTags * tags);
    11723 +int nandemul2k_ReadChunkWithTagsFromNAND(struct yaffs_DeviceStruct *dev,
    11724 +                                        int chunkInNAND, __u8 * data,
    11725 +                                        yaffs_ExtendedTags * tags);
     10073+#include "yaffs_guts.h"
     10074+
     10075+
     10076+int nandemul2k_WriteChunkWithTagsToNAND(struct yaffs_DeviceStruct *dev,int chunkInNAND, const __u8 *data, yaffs_ExtendedTags *tags);
     10077+int nandemul2k_ReadChunkWithTagsFromNAND(struct yaffs_DeviceStruct *dev,int chunkInNAND, __u8 *data, yaffs_ExtendedTags *tags);
    1172610078+int nandemul2k_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo);
    11727 +int nandemul2k_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
    11728 +                             yaffs_BlockState * state, int *sequenceNumber);
    11729 +int nandemul2k_EraseBlockInNAND(struct yaffs_DeviceStruct *dev,
    11730 +                               int blockInNAND);
     10079+int nandemul2k_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, int *sequenceNumber);
     10080+int nandemul2k_EraseBlockInNAND(struct yaffs_DeviceStruct *dev,int blockInNAND);
    1173110081+int nandemul2k_InitialiseNAND(struct yaffs_DeviceStruct *dev);
    1173210082+int nandemul2k_GetBytesPerChunk(void);
     
    1173510085+
    1173610086+#endif
    11737 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_nand.h linux-2.6.18.2.patched/fs/yaffs2/yaffs_nand.h
    11738 --- linux-2.6.18.2/fs/yaffs2/yaffs_nand.h       1970-01-01 01:00:00.000000000 +0100
    11739 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_nand.h       2006-11-25 00:15:32.000000000 +0100
    11740 @@ -0,0 +1,43 @@
    11741 +/*
    11742 + * YAFFS: Yet another FFS. A NAND-flash specific file system.
    11743 + *
    11744 + * Copyright (C) 2002 Aleph One Ltd.
    11745 + *   for Toby Churchill Ltd and Brightstar Engineering
    11746 + *
    11747 + * Created by Charles Manning <charles@aleph1.co.uk>
    11748 + *
    11749 + * This program is free software; you can redistribute it and/or modify
    11750 + * it under the terms of the GNU General Public License version 2 as
    11751 + * published by the Free Software Foundation.
    11752 + *
    11753 + */
    11754 +
    11755 +#ifndef __YAFFS_NAND_H__
    11756 +#define __YAFFS_NAND_H__
    11757 +#include "yaffs_guts.h"
    11758 +
    11759 +
    11760 +
    11761 +int yaffs_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,
    11762 +                                          __u8 * buffer,
    11763 +                                          yaffs_ExtendedTags * tags);
    11764 +
    11765 +int yaffs_WriteChunkWithTagsToNAND(yaffs_Device * dev,
    11766 +                                                  int chunkInNAND,
    11767 +                                                  const __u8 * buffer,
    11768 +                                                  yaffs_ExtendedTags * tags);
    11769 +
    11770 +int yaffs_MarkBlockBad(yaffs_Device * dev, int blockNo);
    11771 +
    11772 +int yaffs_QueryInitialBlockState(yaffs_Device * dev,
    11773 +                                                int blockNo,
    11774 +                                                yaffs_BlockState * state,
    11775 +                                                unsigned *sequenceNumber);
    11776 +
    11777 +int yaffs_EraseBlockInNAND(struct yaffs_DeviceStruct *dev,
    11778 +                                 int blockInNAND);
    11779 +
    11780 +int yaffs_InitialiseNAND(struct yaffs_DeviceStruct *dev);
    11781 +
    11782 +#endif
    11783 +
    11784 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_packedtags1.c linux-2.6.18.2.patched/fs/yaffs2/yaffs_packedtags1.c
    11785 --- linux-2.6.18.2/fs/yaffs2/yaffs_packedtags1.c        1970-01-01 01:00:00.000000000 +0100
    11786 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_packedtags1.c        2006-11-25 00:15:32.000000000 +0100
    11787 @@ -0,0 +1,39 @@
     10087+
     10088diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_packedtags1.c linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_packedtags1.c
     10089--- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_packedtags1.c       1970-01-01 01:00:00.000000000 +0100
     10090+++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_packedtags1.c    2006-12-10 03:57:50.000000000 +0100
     10091@@ -0,0 +1,42 @@
    1178810092+#include "yaffs_packedtags1.h"
    1178910093+#include "yportenv.h"
    1179010094+
    11791 +void yaffs_PackTags1(yaffs_PackedTags1 * pt, const yaffs_ExtendedTags * t)
     10095+void yaffs_PackTags1(yaffs_PackedTags1 *pt, const yaffs_ExtendedTags *t)
    1179210096+{
    1179310097+       pt->chunkId = t->chunkId;
     
    1179910103+       pt->unusedStuff = 0;
    1180010104+       pt->shouldBeFF = 0xFFFFFFFF;
    11801 +
    11802 +}
    11803 +
    11804 +void yaffs_UnpackTags1(yaffs_ExtendedTags * t, const yaffs_PackedTags1 * pt)
    11805 +{
    11806 +       static const __u8 allFF[] =
    11807 +           { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    11808 +0xff };
    11809 +
    11810 +       if (memcmp(allFF, pt, sizeof(yaffs_PackedTags1))) {
     10105+       
     10106+}
     10107+
     10108+void yaffs_UnpackTags1(yaffs_ExtendedTags *t, const yaffs_PackedTags1 *pt)
     10109+{
     10110+       static const __u8 allFF[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff, 0xff};
     10111+       
     10112+       if(memcmp(allFF,pt,sizeof(yaffs_PackedTags1)))
     10113+       {
    1181110114+               t->blockBad = 0;
    11812 +               if (pt->shouldBeFF != 0xFFFFFFFF) {
     10115+               if(pt->shouldBeFF != 0xFFFFFFFF)
     10116+               {
    1181310117+                       t->blockBad = 1;
    1181410118+               }
     
    1181710121+               t->chunkId = pt->chunkId;
    1181810122+               t->byteCount = pt->byteCount;
    11819 +               t->eccResult = YAFFS_ECC_RESULT_NO_ERROR;
     10123+               t->eccResult =  YAFFS_ECC_RESULT_NO_ERROR;
    1182010124+               t->chunkDeleted = (pt->deleted) ? 0 : 1;
    1182110125+               t->serialNumber = pt->serialNumber;
    11822 +       } else {
    11823 +               memset(t, 0, sizeof(yaffs_ExtendedTags));
    11824 +
    11825 +       }
    11826 +}
    11827 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_packedtags1.h linux-2.6.18.2.patched/fs/yaffs2/yaffs_packedtags1.h
    11828 --- linux-2.6.18.2/fs/yaffs2/yaffs_packedtags1.h        1970-01-01 01:00:00.000000000 +0100
    11829 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_packedtags1.h        2006-11-25 00:15:32.000000000 +0100
    11830 @@ -0,0 +1,22 @@
     10126+       }
     10127+       else
     10128+       {
     10129+               memset(t,0,sizeof(yaffs_ExtendedTags));
     10130+               
     10131+       }
     10132+}
     10133+
     10134diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_packedtags1.h linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_packedtags1.h
     10135--- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_packedtags1.h       1970-01-01 01:00:00.000000000 +0100
     10136+++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_packedtags1.h    2006-12-10 03:57:50.000000000 +0100
     10137@@ -0,0 +1,28 @@
    1183110138+// This is used to pack YAFFS1 tags, not YAFFS2 tags.
    1183210139+
     
    1183410141+#define __YAFFS_PACKEDTAGS1_H__
    1183510142+
     10143+
    1183610144+#include "yaffs_guts.h"
    1183710145+
    11838 +typedef struct {
    11839 +       unsigned chunkId:20;
    11840 +       unsigned serialNumber:2;
    11841 +       unsigned byteCount:10;
    11842 +       unsigned objectId:18;
    11843 +       unsigned ecc:12;
    11844 +       unsigned deleted:1;
    11845 +       unsigned unusedStuff:1;
    11846 +       unsigned shouldBeFF;
     10146+typedef struct
     10147+{   
     10148+    unsigned chunkId:20;
     10149+    unsigned serialNumber:2;
     10150+    unsigned byteCount:10;
     10151+    unsigned objectId:18;
     10152+    unsigned ecc:12;
     10153+    unsigned deleted:1;
     10154+    unsigned unusedStuff:1;
     10155+    unsigned shouldBeFF;
    1184710156+
    1184810157+} yaffs_PackedTags1;
    1184910158+
    11850 +void yaffs_PackTags1(yaffs_PackedTags1 * pt, const yaffs_ExtendedTags * t);
    11851 +void yaffs_UnpackTags1(yaffs_ExtendedTags * t, const yaffs_PackedTags1 * pt);
    11852 +#endif
    11853 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_packedtags2.c linux-2.6.18.2.patched/fs/yaffs2/yaffs_packedtags2.c
    11854 --- linux-2.6.18.2/fs/yaffs2/yaffs_packedtags2.c        1970-01-01 01:00:00.000000000 +0100
    11855 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_packedtags2.c        2006-11-25 00:15:32.000000000 +0100
    11856 @@ -0,0 +1,184 @@
     10159+
     10160+
     10161+void yaffs_PackTags1(yaffs_PackedTags1 *pt, const yaffs_ExtendedTags *t);
     10162+void yaffs_UnpackTags1(yaffs_ExtendedTags *t, const yaffs_PackedTags1 *pt);
     10163+#endif
     10164+
     10165+
     10166diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_packedtags2.c linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_packedtags2.c
     10167--- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_packedtags2.c       1970-01-01 01:00:00.000000000 +0100
     10168+++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_packedtags2.c    2006-12-10 03:57:50.000000000 +0100
     10169@@ -0,0 +1,164 @@
    1185710170+/*
    1185810171+ * YAFFS: Yet another FFS. A NAND-flash specific file system.
     
    1186910182+ * version 2.1 as published by the Free Software Foundation.
    1187010183+ */
    11871 +
     10184+ 
    1187210185+#include "yaffs_packedtags2.h"
    1187310186+#include "yportenv.h"
    1187410187+#include "yaffs_tagsvalidity.h"
    1187510188+
    11876 +/* This code packs a set of extended tags into a binary structure for
    11877 + * NAND storage
    11878 + */
    11879 +
    11880 +/* Some of the information is "extra" struff which can be packed in to
    11881 + * speed scanning
    11882 + * This is defined by having the EXTRA_HEADER_INFO_FLAG set.
    11883 + */
    11884 +
    11885 +/* Extra flags applied to chunkId */
     10189+
     10190+
     10191+// This code packs a set of extended tags into a binary structure for NAND storage
     10192+
     10193+// Some of the information is "extra" struff which can be packed in to speed scanning
     10194+// This is defined by having the EXTRA_HEADER_INFO_FLAG set.
     10195+
     10196+
     10197+// Extra flags applied to chunkId
    1188610198+
    1188710199+#define EXTRA_HEADER_INFO_FLAG 0x80000000
     
    1189210204+#define ALL_EXTRA_FLAGS                0xF0000000
    1189310205+
    11894 +/* Also, the top 4 bits of the object Id are set to the object type. */
     10206+
     10207+
     10208+// Also, the top 4 bits of the object Id are set to the object type.
    1189510209+#define EXTRA_OBJECT_TYPE_SHIFT (28)
    1189610210+#define EXTRA_OBJECT_TYPE_MASK  ((0x0F) << EXTRA_OBJECT_TYPE_SHIFT)
    1189710211+
    11898 +static void yaffs_DumpPackedTags2(const yaffs_PackedTags2 * pt)
    11899 +{
    11900 +       T(YAFFS_TRACE_MTD,
    11901 +         (TSTR("packed tags obj %d chunk %d byte %d seq %d" TENDSTR),
    11902 +          pt->t.objectId, pt->t.chunkId, pt->t.byteCount,
    11903 +          pt->t.sequenceNumber));
    11904 +}
    11905 +
    11906 +static void yaffs_DumpTags2(const yaffs_ExtendedTags * t)
    11907 +{
    11908 +       T(YAFFS_TRACE_MTD,
    11909 +         (TSTR
    11910 +          ("ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte "
    11911 +           "%d del %d ser %d seq %d"
    11912 +           TENDSTR), t->eccResult, t->blockBad, t->chunkUsed, t->objectId,
    11913 +          t->chunkId, t->byteCount, t->chunkDeleted, t->serialNumber,
    11914 +          t->sequenceNumber));
    11915 +
    11916 +}
    11917 +
    11918 +void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags * t)
     10212+
     10213+
     10214+static void yaffs_DumpPackedTags2(const yaffs_PackedTags2 *pt)
     10215+{
     10216+       T(YAFFS_TRACE_MTD,(TSTR("packed tags obj %d chunk %d byte %d seq %d"TENDSTR),pt->t.objectId,pt->t.chunkId,pt->t.byteCount,pt->t.sequenceNumber));
     10217+}
     10218+
     10219+static void yaffs_DumpTags2(const yaffs_ExtendedTags *t)
     10220+{
     10221+       T(YAFFS_TRACE_MTD,(TSTR("ext.tags eccres %d blkbad %d chused %d obj %d chunk%d byte %d del %d ser %d seq %d"TENDSTR),
     10222+            t->eccResult, t->blockBad, t->chunkUsed, t->objectId, t->chunkId, t->byteCount, t->chunkDeleted, t->serialNumber, t->sequenceNumber));
     10223+         
     10224+}
     10225+
     10226+void yaffs_PackTags2(yaffs_PackedTags2 *pt, const yaffs_ExtendedTags *t)
    1191910227+{
    1192010228+       pt->t.chunkId = t->chunkId;
     
    1192210230+       pt->t.byteCount = t->byteCount;
    1192310231+       pt->t.objectId = t->objectId;
    11924 +
    11925 +       if (t->chunkId == 0 && t->extraHeaderInfoAvailable) {
    11926 +               /* Store the extra header info instead */
    11927 +               /* We save the parent object in the chunkId */
    11928 +               pt->t.chunkId = EXTRA_HEADER_INFO_FLAG
    11929 +                       | t->extraParentObjectId;
    11930 +               if (t->extraIsShrinkHeader) {
    11931 +                       pt->t.chunkId |= EXTRA_SHRINK_FLAG;
    11932 +               }
    11933 +               if (t->extraShadows) {
    11934 +                       pt->t.chunkId |= EXTRA_SHADOWS_FLAG;
    11935 +               }
    11936 +
     10232+       
     10233+       if(t->chunkId == 0 && t->extraHeaderInfoAvailable)
     10234+       {
     10235+               // Store the extra header info instead
     10236+               pt->t.chunkId = EXTRA_HEADER_INFO_FLAG | t->extraParentObjectId; // We save the parent object in the chunkId
     10237+               if(t->extraIsShrinkHeader)
     10238+               {
     10239+                   pt->t.chunkId |= EXTRA_SHRINK_FLAG;
     10240+               }
     10241+               if(t->extraShadows)
     10242+               {
     10243+                   pt->t.chunkId |= EXTRA_SHADOWS_FLAG;
     10244+               }
     10245+               
    1193710246+               pt->t.objectId &= ~EXTRA_OBJECT_TYPE_MASK;
    11938 +               pt->t.objectId |=
    11939 +                   (t->extraObjectType << EXTRA_OBJECT_TYPE_SHIFT);
    11940 +
    11941 +               if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) {
    11942 +                       pt->t.byteCount = t->extraEquivalentObjectId;
    11943 +               } else if (t->extraObjectType == YAFFS_OBJECT_TYPE_FILE) {
    11944 +                       pt->t.byteCount = t->extraFileLength;
    11945 +               } else {
    11946 +                       pt->t.byteCount = 0;
    11947 +               }
    11948 +       }
    11949 +
     10247+               pt->t.objectId |= (t->extraObjectType << EXTRA_OBJECT_TYPE_SHIFT);
     10248+               
     10249+               if(t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK)
     10250+               {
     10251+                  pt->t.byteCount = t->extraEquivalentObjectId;
     10252+               }
     10253+               else if(t->extraObjectType == YAFFS_OBJECT_TYPE_FILE)
     10254+               {
     10255+                  pt->t.byteCount = t->extraFileLength;
     10256+               }
     10257+               else
     10258+               {
     10259+                  pt->t.byteCount = 0;
     10260+               }
     10261+       }
     10262+       
    1195010263+       yaffs_DumpPackedTags2(pt);
    1195110264+       yaffs_DumpTags2(t);
    11952 +
     10265+       
    1195310266+#ifndef YAFFS_IGNORE_TAGS_ECC
    11954 +       {
    11955 +               yaffs_ECCCalculateOther((unsigned char *)&pt->t,
    11956 +                                       sizeof(yaffs_PackedTags2TagsPart),
    11957 +                                       &pt->ecc);
    11958 +       }
    11959 +#endif
    11960 +}
    11961 +
    11962 +void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt)
    11963 +{
    11964 +
    11965 +       memset(t, 0, sizeof(yaffs_ExtendedTags));
    11966 +
     10267+       {
     10268+         yaffs_ECCCalculateOther((unsigned char *)&pt->t,sizeof(yaffs_PackedTags2TagsPart),&pt->ecc);
     10269+       }
     10270+#endif
     10271+}
     10272+
     10273+void yaffs_UnpackTags2(yaffs_ExtendedTags *t, yaffs_PackedTags2 *pt)
     10274+{
     10275+
     10276+       
     10277+       memset(t,0,sizeof(yaffs_ExtendedTags));
     10278+       
    1196710279+       yaffs_InitialiseTags(t);
    11968 +
    11969 +       if (pt->t.sequenceNumber != 0xFFFFFFFF) {
    11970 +               /* Page is in use */
     10280+       
     10281+       if(pt->t.sequenceNumber != 0xFFFFFFFF)
     10282+       {
     10283+               // Page is in use
    1197110284+#ifdef YAFFS_IGNORE_TAGS_ECC
    1197210285+               {
    11973 +                       t->eccResult = YAFFS_ECC_RESULT_NO_ERROR;
     10286+                       t->eccResult = 0;
    1197410287+               }
    1197510288+#else
    1197610289+               {
    1197710290+                       yaffs_ECCOther ecc;
    11978 +                       int result;
    11979 +                       yaffs_ECCCalculateOther((unsigned char *)&pt->t,
    11980 +                                               sizeof
    11981 +                                               (yaffs_PackedTags2TagsPart),
    11982 +                                               &ecc);
    11983 +                       result =
    11984 +                           yaffs_ECCCorrectOther((unsigned char *)&pt->t,
    11985 +                                                 sizeof
    11986 +                                                 (yaffs_PackedTags2TagsPart),
    11987 +                                                 &pt->ecc, &ecc);
    11988 +                       switch(result){
    11989 +                               case 0:
    11990 +                                       t->eccResult = YAFFS_ECC_RESULT_NO_ERROR;
    11991 +                                       break;
    11992 +                               case 1:
    11993 +                                       t->eccResult = YAFFS_ECC_RESULT_FIXED;
    11994 +                                       break;
    11995 +                               case -1:
    11996 +                                       t->eccResult = YAFFS_ECC_RESULT_UNFIXED;
    11997 +                                       break;
    11998 +                               default:
    11999 +                                       t->eccResult = YAFFS_ECC_RESULT_UNKNOWN;
    12000 +                       }
     10291+                       yaffs_ECCCalculateOther((unsigned char *)&pt->t,sizeof(yaffs_PackedTags2TagsPart),&ecc);
     10292+                       t->eccResult = yaffs_ECCCorrectOther((unsigned char *)&pt->t,sizeof(yaffs_PackedTags2TagsPart),&pt->ecc,&ecc);
    1200110293+               }
    1200210294+#endif
     
    1200410296+               t->chunkUsed = 1;
    1200510297+               t->objectId = pt->t.objectId;
    12006 +               t->chunkId = pt->t.chunkId;
     10298+               t->chunkId =  pt->t.chunkId;
    1200710299+               t->byteCount = pt->t.byteCount;
    1200810300+               t->chunkDeleted = 0;
    1200910301+               t->serialNumber = 0;
    1201010302+               t->sequenceNumber = pt->t.sequenceNumber;
    12011 +
    12012 +               /* Do extra header info stuff */
    12013 +
    12014 +               if (pt->t.chunkId & EXTRA_HEADER_INFO_FLAG) {
     10303+               
     10304+               // Do extra header info stuff
     10305+               
     10306+               if(pt->t.chunkId & EXTRA_HEADER_INFO_FLAG)
     10307+               {
    1201510308+                       t->chunkId = 0;
    1201610309+                       t->byteCount = 0;
    12017 +
     10310+                       
    1201810311+                       t->extraHeaderInfoAvailable = 1;
    12019 +                       t->extraParentObjectId =
    12020 +                           pt->t.chunkId & (~(ALL_EXTRA_FLAGS));
    12021 +                       t->extraIsShrinkHeader =
    12022 +                           (pt->t.chunkId & EXTRA_SHRINK_FLAG) ? 1 : 0;
    12023 +                       t->extraShadows =
    12024 +                           (pt->t.chunkId & EXTRA_SHADOWS_FLAG) ? 1 : 0;
    12025 +                       t->extraObjectType =
    12026 +                           pt->t.objectId >> EXTRA_OBJECT_TYPE_SHIFT;
     10312+                       t->extraParentObjectId = pt->t.chunkId & (~(ALL_EXTRA_FLAGS));
     10313+                       t->extraIsShrinkHeader =  (pt->t.chunkId & EXTRA_SHRINK_FLAG) ? 1 : 0;
     10314+                       t->extraShadows =  (pt->t.chunkId & EXTRA_SHADOWS_FLAG) ? 1 : 0;
     10315+                       t->extraObjectType = pt->t.objectId >> EXTRA_OBJECT_TYPE_SHIFT;
    1202710316+                       t->objectId &= ~EXTRA_OBJECT_TYPE_MASK;
    12028 +
    12029 +                       if (t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK) {
    12030 +                               t->extraEquivalentObjectId = pt->t.byteCount;
    12031 +                       } else {
    12032 +                               t->extraFileLength = pt->t.byteCount;
     10317+                       
     10318+                       if(t->extraObjectType == YAFFS_OBJECT_TYPE_HARDLINK)
     10319+                       {
     10320+                           t->extraEquivalentObjectId = pt->t.byteCount;
     10321+                       }
     10322+                       else
     10323+                       {
     10324+                           t->extraFileLength = pt->t.byteCount;
    1203310325+                       }
    1203410326+               }
     
    1203910331+
    1204010332+}
    12041 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_packedtags2.h linux-2.6.18.2.patched/fs/yaffs2/yaffs_packedtags2.h
    12042 --- linux-2.6.18.2/fs/yaffs2/yaffs_packedtags2.h        1970-01-01 01:00:00.000000000 +0100
    12043 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_packedtags2.h        2006-11-25 00:15:32.000000000 +0100
    12044 @@ -0,0 +1,23 @@
    12045 +/* This is used to pack YAFFS2 tags, not YAFFS1tags. */
     10333+
     10334diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_packedtags2.h linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_packedtags2.h
     10335--- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_packedtags2.h       1970-01-01 01:00:00.000000000 +0100
     10336+++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_packedtags2.h    2006-12-10 03:57:50.000000000 +0100
     10337@@ -0,0 +1,30 @@
     10338+// This is used to pack YAFFS2 tags, not YAFFS1tags.
    1204610339+
    1204710340+#ifndef __YAFFS_PACKEDTAGS2_H__
    1204810341+#define __YAFFS_PACKEDTAGS2_H__
    1204910342+
     10343+
    1205010344+#include "yaffs_guts.h"
    1205110345+#include "yaffs_ecc.h"
    1205210346+
    12053 +typedef struct {
    12054 +       unsigned sequenceNumber;
    12055 +       unsigned objectId;
    12056 +       unsigned chunkId;
    12057 +       unsigned byteCount;
     10347+
     10348+typedef struct
     10349+{   
     10350+    unsigned sequenceNumber;
     10351+    unsigned objectId;   
     10352+    unsigned chunkId;
     10353+    unsigned byteCount;   
    1205810354+} yaffs_PackedTags2TagsPart;
    1205910355+
    12060 +typedef struct {
    12061 +       yaffs_PackedTags2TagsPart t;
    12062 +       yaffs_ECCOther ecc;
     10356+typedef struct
     10357+{
     10358+    yaffs_PackedTags2TagsPart t;
     10359+    yaffs_ECCOther ecc;
    1206310360+} yaffs_PackedTags2;
    1206410361+
    12065 +void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags * t);
    12066 +void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt);
    12067 +#endif
    12068 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_qsort.c linux-2.6.18.2.patched/fs/yaffs2/yaffs_qsort.c
    12069 --- linux-2.6.18.2/fs/yaffs2/yaffs_qsort.c      1970-01-01 01:00:00.000000000 +0100
    12070 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_qsort.c      2006-11-25 00:15:32.000000000 +0100
    12071 @@ -0,0 +1,156 @@
    12072 +/*
    12073 + * Copyright (c) 1992, 1993
    12074 + *     The Regents of the University of California.  All rights reserved.
    12075 + *
    12076 + * Redistribution and use in source and binary forms, with or without
    12077 + * modification, are permitted provided that the following conditions
    12078 + * are met:
    12079 + * 1. Redistributions of source code must retain the above copyright
    12080 + *    notice, this list of conditions and the following disclaimer.
    12081 + * 2. Redistributions in binary form must reproduce the above copyright
    12082 + *    notice, this list of conditions and the following disclaimer in the
    12083 + *    documentation and/or other materials provided with the distribution.
    12084 + * 3. Neither the name of the University nor the names of its contributors
    12085 + *    may be used to endorse or promote products derived from this software
    12086 + *    without specific prior written permission.
    12087 + *
    12088 + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
    12089 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    12090 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    12091 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
    12092 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    12093 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    12094 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    12095 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    12096 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    12097 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    12098 + * SUCH DAMAGE.
    12099 + */
    12100 +
    12101 +#include "yportenv.h"
    12102 +//#include <linux/string.h>
    12103 +
    12104 +/*
    12105 + * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
    12106 + */
    12107 +#define swapcode(TYPE, parmi, parmj, n) {              \
    12108 +       long i = (n) / sizeof (TYPE);                   \
    12109 +       register TYPE *pi = (TYPE *) (parmi);           \
    12110 +       register TYPE *pj = (TYPE *) (parmj);           \
    12111 +       do {                                            \
    12112 +               register TYPE   t = *pi;                \
    12113 +               *pi++ = *pj;                            \
    12114 +               *pj++ = t;                              \
    12115 +        } while (--i > 0);                             \
    12116 +}
    12117 +
    12118 +#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
    12119 +       es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
    12120 +
    12121 +static __inline void
    12122 +swapfunc(char *a, char *b, int n, int swaptype)
    12123 +{
    12124 +       if (swaptype <= 1)
    12125 +               swapcode(long, a, b, n)
    12126 +       else
    12127 +               swapcode(char, a, b, n)
    12128 +}
    12129 +
    12130 +#define swap(a, b)                                     \
    12131 +       if (swaptype == 0) {                            \
    12132 +               long t = *(long *)(a);                  \
    12133 +               *(long *)(a) = *(long *)(b);            \
    12134 +               *(long *)(b) = t;                       \
    12135 +       } else                                          \
    12136 +               swapfunc(a, b, es, swaptype)
    12137 +
    12138 +#define vecswap(a, b, n)       if ((n) > 0) swapfunc(a, b, n, swaptype)
    12139 +
    12140 +static __inline char *
    12141 +med3(char *a, char *b, char *c, int (*cmp)(const void *, const void *))
    12142 +{
    12143 +       return cmp(a, b) < 0 ?
    12144 +              (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a ))
    12145 +              :(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c ));
    12146 +}
    12147 +
    12148 +#define min(a,b) (((a) < (b)) ? (a) : (b))
    12149 +void
    12150 +qsort(void *aa, size_t n, size_t es, int (*cmp)(const void *, const void *))
    12151 +{
    12152 +       char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
    12153 +       int d, r, swaptype, swap_cnt;
    12154 +       register char *a = aa;
    12155 +
    12156 +loop:  SWAPINIT(a, es);
    12157 +       swap_cnt = 0;
    12158 +       if (n < 7) {
    12159 +               for (pm = (char *)a + es; pm < (char *) a + n * es; pm += es)
    12160 +                       for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
    12161 +                            pl -= es)
    12162 +                               swap(pl, pl - es);
    12163 +               return;
    12164 +       }
    12165 +       pm = (char *)a + (n / 2) * es;
    12166 +       if (n > 7) {
    12167 +               pl = (char *)a;
    12168 +               pn = (char *)a + (n - 1) * es;
    12169 +               if (n > 40) {
    12170 +                       d = (n / 8) * es;
    12171 +                       pl = med3(pl, pl + d, pl + 2 * d, cmp);
    12172 +                       pm = med3(pm - d, pm, pm + d, cmp);
    12173 +                       pn = med3(pn - 2 * d, pn - d, pn, cmp);
    12174 +               }
    12175 +               pm = med3(pl, pm, pn, cmp);
    12176 +       }
    12177 +       swap(a, pm);
    12178 +       pa = pb = (char *)a + es;
    12179 +
    12180 +       pc = pd = (char *)a + (n - 1) * es;
    12181 +       for (;;) {
    12182 +               while (pb <= pc && (r = cmp(pb, a)) <= 0) {
    12183 +                       if (r == 0) {
    12184 +                               swap_cnt = 1;
    12185 +                               swap(pa, pb);
    12186 +                               pa += es;
    12187 +                       }
    12188 +                       pb += es;
    12189 +               }
    12190 +               while (pb <= pc && (r = cmp(pc, a)) >= 0) {
    12191 +                       if (r == 0) {
    12192 +                               swap_cnt = 1;
    12193 +                               swap(pc, pd);
    12194 +                               pd -= es;
    12195 +                       }
    12196 +                       pc -= es;
    12197 +               }
    12198 +               if (pb > pc)
    12199 +                       break;
    12200 +               swap(pb, pc);
    12201 +               swap_cnt = 1;
    12202 +               pb += es;
    12203 +               pc -= es;
    12204 +       }
    12205 +       if (swap_cnt == 0) {  /* Switch to insertion sort */
    12206 +               for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)
    12207 +                       for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
    12208 +                            pl -= es)
    12209 +                               swap(pl, pl - es);
    12210 +               return;
    12211 +       }
    12212 +
    12213 +       pn = (char *)a + n * es;
    12214 +       r = min(pa - (char *)a, pb - pa);
    12215 +       vecswap(a, pb - r, r);
    12216 +       r = min((long)(pd - pc), (long)(pn - pd - es));
    12217 +       vecswap(pb, pn - r, r);
    12218 +       if ((r = pb - pa) > es)
    12219 +               qsort(a, r / es, es, cmp);
    12220 +       if ((r = pd - pc) > es) {
    12221 +               /* Iterate rather than recurse to save stack space */
    12222 +               a = pn - r;
    12223 +               n = r / es;
    12224 +               goto loop;
    12225 +       }
    12226 +/*             qsort(pn - r, r / es, es, cmp);*/
    12227 +}
    12228 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_qsort.h linux-2.6.18.2.patched/fs/yaffs2/yaffs_qsort.h
    12229 --- linux-2.6.18.2/fs/yaffs2/yaffs_qsort.h      1970-01-01 01:00:00.000000000 +0100
    12230 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_qsort.h      2006-11-25 00:15:32.000000000 +0100
    12231 @@ -0,0 +1,23 @@
    12232 +/*
    12233 + * YAFFS: Yet another FFS. A NAND-flash specific file system.
    12234 + * yaffs_qsort.h: Interface to BSD-licensed qsort routine.
    12235 + *
    12236 + * Copyright (C) 2002 Aleph One Ltd.
    12237 + *   for Toby Churchill Ltd and Brightstar Engineering
    12238 + *
    12239 + * Created by Charles Manning <charles@aleph1.co.uk>
    12240 + *
    12241 + * This program is free software; you can redistribute it and/or modify
    12242 + * it under the terms of the GNU Lesser General Public License version 2.1 as
    12243 + * published by the Free Software Foundation.
    12244 + *
    12245 + * $Id: yaffs_qsort.h,v 1.2 2006/11/07 23:20:09 charles Exp $
    12246 + */
    12247 +
    12248 +#ifndef __YAFFS_QSORT_H__
    12249 +#define __YAFFS_QSORT_H__
    12250 +
    12251 +extern void qsort (void *const base, size_t total_elems, size_t size,
    12252 +                   int (*cmp)(const void *, const void *));
    12253 +
    12254 +#endif
    12255 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_tagscompat.c linux-2.6.18.2.patched/fs/yaffs2/yaffs_tagscompat.c
    12256 --- linux-2.6.18.2/fs/yaffs2/yaffs_tagscompat.c 1970-01-01 01:00:00.000000000 +0100
    12257 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_tagscompat.c 2006-11-25 00:15:32.000000000 +0100
    12258 @@ -0,0 +1,532 @@
     10362+
     10363+void yaffs_PackTags2(yaffs_PackedTags2 *pt, const  yaffs_ExtendedTags *t);
     10364+void yaffs_UnpackTags2(yaffs_ExtendedTags *t, yaffs_PackedTags2 *pt);
     10365+#endif
     10366+
     10367+
     10368diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_tagscompat.c linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_tagscompat.c
     10369--- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_tagscompat.c        1970-01-01 01:00:00.000000000 +0100
     10370+++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_tagscompat.c     2006-12-10 03:57:50.000000000 +0100
     10371@@ -0,0 +1,698 @@
    1225910372+/*
    1226010373+ * YAFFS: Yet another FFS. A NAND-flash specific file system.
     
    1226910382+ * published by the Free Software Foundation.
    1227010383+ *
    12271 + * $Id: yaffs_tagscompat.c,v 1.8 2005/11/29 20:54:32 marty Exp $
     10384+ * $Id: yaffs_tagscompat.c,v 1.3 2005/07/31 06:47:12 marty Exp $
    1227210385+ */
    1227310386+
     
    1227610389+#include "yaffs_ecc.h"
    1227710390+
    12278 +static void yaffs_HandleReadDataError(yaffs_Device * dev, int chunkInNAND);
     10391+static void yaffs_HandleReadDataError(yaffs_Device *dev,int chunkInNAND);
    1227910392+#ifdef NOTYET
    12280 +static void yaffs_CheckWrittenBlock(yaffs_Device * dev, int chunkInNAND);
    12281 +static void yaffs_HandleWriteChunkOk(yaffs_Device * dev, int chunkInNAND,
    12282 +                                    const __u8 * data,
    12283 +                                    const yaffs_Spare * spare);
    12284 +static void yaffs_HandleUpdateChunk(yaffs_Device * dev, int chunkInNAND,
    12285 +                                   const yaffs_Spare * spare);
    12286 +static void yaffs_HandleWriteChunkError(yaffs_Device * dev, int chunkInNAND);
    12287 +#endif
    12288 +
    12289 +static const char yaffs_countBitsTable[256] = {
    12290 +       0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
    12291 +       1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
    12292 +       1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
    12293 +       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    12294 +       1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
    12295 +       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    12296 +       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    12297 +       3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
    12298 +       1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
    12299 +       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    12300 +       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    12301 +       3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
    12302 +       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
    12303 +       3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
    12304 +       3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
    12305 +       4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
     10393+static void yaffs_CheckWrittenBlock(yaffs_Device *dev,int chunkInNAND);
     10394+static void yaffs_HandleWriteChunkOk(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_Spare *spare);
     10395+static void yaffs_HandleUpdateChunk(yaffs_Device *dev,int chunkInNAND, const yaffs_Spare *spare);
     10396+static void yaffs_HandleWriteChunkError(yaffs_Device *dev,int chunkInNAND);
     10397+#endif
     10398+
     10399+
     10400+static const char yaffs_countBitsTable[256] =
     10401+{
     10402+0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,
     10403+1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
     10404+1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
     10405+2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
     10406+1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
     10407+2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
     10408+2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
     10409+3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
     10410+1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
     10411+2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
     10412+2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
     10413+3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
     10414+2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
     10415+3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
     10416+3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
     10417+4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8
    1230610418+};
    1230710419+
     
    1231310425+}
    1231410426+
    12315 +/********** Tags ECC calculations  *********/
    12316 +
    12317 +void yaffs_CalcECC(const __u8 * data, yaffs_Spare * spare)
    12318 +{
    12319 +       yaffs_ECCCalculate(data, spare->ecc1);
    12320 +       yaffs_ECCCalculate(&data[256], spare->ecc2);
    12321 +}
    12322 +
    12323 +void yaffs_CalcTagsECC(yaffs_Tags * tags)
    12324 +{
    12325 +       /* Calculate an ecc */
    12326 +
    12327 +       unsigned char *b = ((yaffs_TagsUnion *) tags)->asBytes;
    12328 +       unsigned i, j;
    12329 +       unsigned ecc = 0;
     10427+
     10428+/////////////// Tags ECC calculations ///////////////////
     10429+
     10430+void yaffs_CalcECC(const __u8 *data, yaffs_Spare *spare)
     10431+{
     10432+       yaffs_ECCCalculate(data , spare->ecc1);
     10433+       yaffs_ECCCalculate(&data[256] , spare->ecc2);
     10434+}
     10435+
     10436+void yaffs_CalcTagsECC(yaffs_Tags *tags)
     10437+{
     10438+       // Calculate an ecc
     10439+
     10440+       unsigned char *b = ((yaffs_TagsUnion *)tags)->asBytes;
     10441+       unsigned  i,j;
     10442+       unsigned  ecc = 0;
    1233010443+       unsigned bit = 0;
    1233110444+
    1233210445+       tags->ecc = 0;
    1233310446+
    12334 +       for (i = 0; i < 8; i++) {
    12335 +               for (j = 1; j & 0xff; j <<= 1) {
     10447+       for(i = 0; i < 8; i++)
     10448+       {
     10449+               for(j = 1; j &0xff; j<<=1)
     10450+               {
    1233610451+                       bit++;
    12337 +                       if (b[i] & j) {
     10452+                       if(b[i] & j)
     10453+                       {
    1233810454+                               ecc ^= bit;
    1233910455+                       }
     
    1234310459+       tags->ecc = ecc;
    1234410460+
    12345 +}
    12346 +
    12347 +int yaffs_CheckECCOnTags(yaffs_Tags * tags)
     10461+
     10462+}
     10463+
     10464+int  yaffs_CheckECCOnTags(yaffs_Tags *tags)
    1234810465+{
    1234910466+       unsigned ecc = tags->ecc;
     
    1235210469+
    1235310470+       ecc ^= tags->ecc;
    12354 +
    12355 +       if (ecc && ecc <= 64) {
    12356 +               /* TODO: Handle the failure better. Retire? */
    12357 +               unsigned char *b = ((yaffs_TagsUnion *) tags)->asBytes;
     10471+       
     10472+       if(ecc && ecc <= 64)
     10473+       {
     10474+               // TODO: Handle the failure better. Retire?
     10475+               unsigned char *b = ((yaffs_TagsUnion *)tags)->asBytes;
    1235810476+
    1235910477+               ecc--;
     
    1236110479+               b[ecc / 8] ^= (1 << (ecc & 7));
    1236210480+
    12363 +               /* Now recvalc the ecc */
     10481+               // Now recvalc the ecc
    1236410482+               yaffs_CalcTagsECC(tags);
    1236510483+
    12366 +               return 1;       /* recovered error */
    12367 +       } else if (ecc) {
    12368 +               /* Wierd ecc failure value */
    12369 +               /* TODO Need to do somethiong here */
    12370 +               return -1;      /* unrecovered error */
     10484+               return 1; // recovered error
     10485+       }
     10486+       else if(ecc)
     10487+       {
     10488+               // Wierd ecc failure value
     10489+               // TODO Need to do somethiong here
     10490+               return -1; //unrecovered error
    1237110491+       }
    1237210492+
     
    1237410494+}
    1237510495+
    12376 +/********** Tags **********/
    12377 +
    12378 +static void yaffs_LoadTagsIntoSpare(yaffs_Spare * sparePtr,
    12379 +                                   yaffs_Tags * tagsPtr)
    12380 +{
    12381 +       yaffs_TagsUnion *tu = (yaffs_TagsUnion *) tagsPtr;
     10496+//////////////////////////// Tags ///////////////////////////////////////
     10497+
     10498+static void yaffs_LoadTagsIntoSpare(yaffs_Spare *sparePtr, yaffs_Tags *tagsPtr)
     10499+{
     10500+       yaffs_TagsUnion *tu = (yaffs_TagsUnion *)tagsPtr;
    1238210501+
    1238310502+       yaffs_CalcTagsECC(tagsPtr);
    12384 +
     10503+       
    1238510504+       sparePtr->tagByte0 = tu->asBytes[0];
    1238610505+       sparePtr->tagByte1 = tu->asBytes[1];
     
    1239310512+}
    1239410513+
    12395 +static void yaffs_GetTagsFromSpare(yaffs_Device * dev, yaffs_Spare * sparePtr,
    12396 +                                  yaffs_Tags * tagsPtr)
    12397 +{
    12398 +       yaffs_TagsUnion *tu = (yaffs_TagsUnion *) tagsPtr;
     10514+static void yaffs_GetTagsFromSpare(yaffs_Device *dev, yaffs_Spare *sparePtr,yaffs_Tags *tagsPtr)
     10515+{
     10516+       yaffs_TagsUnion *tu = (yaffs_TagsUnion *)tagsPtr;
    1239910517+       int result;
    1240010518+
    12401 +       tu->asBytes[0] = sparePtr->tagByte0;
    12402 +       tu->asBytes[1] = sparePtr->tagByte1;
    12403 +       tu->asBytes[2] = sparePtr->tagByte2;
    12404 +       tu->asBytes[3] = sparePtr->tagByte3;
    12405 +       tu->asBytes[4] = sparePtr->tagByte4;
    12406 +       tu->asBytes[5] = sparePtr->tagByte5;
    12407 +       tu->asBytes[6] = sparePtr->tagByte6;
    12408 +       tu->asBytes[7] = sparePtr->tagByte7;
    12409 +
    12410 +       result = yaffs_CheckECCOnTags(tagsPtr);
    12411 +       if (result > 0) {
     10519+       tu->asBytes[0]= sparePtr->tagByte0;
     10520+       tu->asBytes[1]= sparePtr->tagByte1;
     10521+       tu->asBytes[2]= sparePtr->tagByte2;
     10522+       tu->asBytes[3]= sparePtr->tagByte3;
     10523+       tu->asBytes[4]= sparePtr->tagByte4;
     10524+       tu->asBytes[5]= sparePtr->tagByte5;
     10525+       tu->asBytes[6]= sparePtr->tagByte6;
     10526+       tu->asBytes[7]= sparePtr->tagByte7;
     10527+       
     10528+       result =  yaffs_CheckECCOnTags(tagsPtr);
     10529+       if(result> 0)
     10530+       {
    1241210531+               dev->tagsEccFixed++;
    12413 +       } else if (result < 0) {
     10532+       }
     10533+       else if(result <0)
     10534+       {
    1241410535+               dev->tagsEccUnfixed++;
    1241510536+       }
    1241610537+}
    1241710538+
    12418 +static void yaffs_SpareInitialise(yaffs_Spare * spare)
    12419 +{
    12420 +       memset(spare, 0xFF, sizeof(yaffs_Spare));
    12421 +}
    12422 +
    12423 +static int yaffs_WriteChunkToNAND(struct yaffs_DeviceStruct *dev,
    12424 +                                 int chunkInNAND, const __u8 * data,
    12425 +                                 yaffs_Spare * spare)
    12426 +{
    12427 +       if (chunkInNAND < dev->startBlock * dev->nChunksPerBlock) {
    12428 +               T(YAFFS_TRACE_ERROR,
    12429 +                 (TSTR("**>> yaffs chunk %d is not valid" TENDSTR),
    12430 +                  chunkInNAND));
     10539+static void yaffs_SpareInitialise(yaffs_Spare *spare)
     10540+{
     10541+       memset(spare,0xFF,sizeof(yaffs_Spare));
     10542+}
     10543+
     10544+
     10545+
     10546+
     10547+static int yaffs_WriteChunkToNAND(struct yaffs_DeviceStruct *dev,int chunkInNAND, const __u8 *data, yaffs_Spare *spare)
     10548+{
     10549+       if(chunkInNAND < dev->startBlock * dev->nChunksPerBlock)
     10550+       {
     10551+               T(YAFFS_TRACE_ERROR,(TSTR("**>> yaffs chunk %d is not valid" TENDSTR),chunkInNAND));
    1243110552+               return YAFFS_FAIL;
    1243210553+       }
    1243310554+
    1243410555+       dev->nPageWrites++;
    12435 +       return dev->writeChunkToNAND(dev, chunkInNAND, data, spare);
    12436 +}
     10556+       return dev->writeChunkToNAND(dev,chunkInNAND,data,spare);
     10557+}
     10558+
     10559+
    1243710560+
    1243810561+static int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev,
    12439 +                                  int chunkInNAND,
    12440 +                                  __u8 * data,
    12441 +                                  yaffs_Spare * spare,
    12442 +                                  yaffs_ECCResult * eccResult,
    12443 +                                  int doErrorCorrection)
     10562+                                                       int chunkInNAND,
     10563+                                                       __u8 *data,
     10564+                                                       yaffs_Spare *spare,
     10565+                                                       yaffs_ECCResult *eccResult,
     10566+                                                       int doErrorCorrection)
    1244410567+{
    1244510568+       int retVal;
     
    1244710570+
    1244810571+       dev->nPageReads++;
    12449 +
    12450 +       if (!spare && data) {
    12451 +               /* If we don't have a real spare, then we use a local one. */
    12452 +               /* Need this for the calculation of the ecc */
     10572+       
     10573+       
     10574+
     10575+       
     10576+       if(!spare && data)
     10577+       {
     10578+               // If we don't have a real spare, then we use a local one.
     10579+               // Need this for the calculation of the ecc
    1245310580+               spare = &localSpare;
    1245410581+       }
    12455 +
    12456 +       if (!dev->useNANDECC) {
    12457 +               retVal = dev->readChunkFromNAND(dev, chunkInNAND, data, spare);
    12458 +               if (data && doErrorCorrection) {
    12459 +                       /* Do ECC correction */
    12460 +                       /* Todo handle any errors */
    12461 +                       int eccResult1, eccResult2;
    12462 +                       __u8 calcEcc[3];
    12463 +
    12464 +                       yaffs_ECCCalculate(data, calcEcc);
    12465 +                       eccResult1 =
    12466 +                           yaffs_ECCCorrect(data, spare->ecc1, calcEcc);
    12467 +                       yaffs_ECCCalculate(&data[256], calcEcc);
    12468 +                       eccResult2 =
    12469 +                           yaffs_ECCCorrect(&data[256], spare->ecc2, calcEcc);
    12470 +
    12471 +                       if (eccResult1 > 0) {
    12472 +                               T(YAFFS_TRACE_ERROR,
    12473 +                                 (TSTR
    12474 +                                  ("**>>yaffs ecc error fix performed on chunk %d:0"
    12475 +                                   TENDSTR), chunkInNAND));
     10582+       
     10583+
     10584+       if(!dev->useNANDECC)
     10585+       {
     10586+               retVal  = dev->readChunkFromNAND(dev,chunkInNAND,data,spare);
     10587+               if(data && doErrorCorrection)
     10588+               {
     10589+                       // Do ECC correction
     10590+                       //Todo handle any errors
     10591+               int eccResult1,eccResult2;
     10592+               __u8 calcEcc[3];
     10593+               
     10594+                       yaffs_ECCCalculate(data,calcEcc);
     10595+                       eccResult1 = yaffs_ECCCorrect (data,spare->ecc1, calcEcc);
     10596+                       yaffs_ECCCalculate(&data[256],calcEcc);
     10597+                       eccResult2 = yaffs_ECCCorrect(&data[256],spare->ecc2, calcEcc);
     10598+
     10599+                       if(eccResult1>0)
     10600+                       {
     10601+                               T(YAFFS_TRACE_ERROR, (TSTR("**>>ecc error fix performed on chunk %d:0" TENDSTR),chunkInNAND));
    1247610602+                               dev->eccFixed++;
    12477 +                       } else if (eccResult1 < 0) {
    12478 +                               T(YAFFS_TRACE_ERROR,
    12479 +                                 (TSTR
    12480 +                                  ("**>>yaffs ecc error unfixed on chunk %d:0"
    12481 +                                   TENDSTR), chunkInNAND));
     10603+                       }
     10604+                       else if(eccResult1<0)
     10605+                       {
     10606+                               T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error unfixed on chunk %d:0" TENDSTR),chunkInNAND));
    1248210607+                               dev->eccUnfixed++;
    1248310608+                       }
    1248410609+
    12485 +                       if (eccResult2 > 0) {
    12486 +                               T(YAFFS_TRACE_ERROR,
    12487 +                                 (TSTR
    12488 +                                  ("**>>yaffs ecc error fix performed on chunk %d:1"
    12489 +                                   TENDSTR), chunkInNAND));
     10610+                       if(eccResult2>0)
     10611+                       {
     10612+                               T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error fix performed on chunk %d:1" TENDSTR),chunkInNAND));
    1249010613+                               dev->eccFixed++;
    12491 +                       } else if (eccResult2 < 0) {
    12492 +                               T(YAFFS_TRACE_ERROR,
    12493 +                                 (TSTR
    12494 +                                  ("**>>yaffs ecc error unfixed on chunk %d:1"
    12495 +                                   TENDSTR), chunkInNAND));
     10614+                       }
     10615+                       else if(eccResult2<0)
     10616+                       {
     10617+                               T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error unfixed on chunk %d:1" TENDSTR),chunkInNAND));
    1249610618+                               dev->eccUnfixed++;
    1249710619+                       }
    1249810620+
    12499 +                       if (eccResult1 || eccResult2) {
    12500 +                               /* We had a data problem on this page */
    12501 +                               yaffs_HandleReadDataError(dev, chunkInNAND);
     10621+                       if(eccResult1 || eccResult2)
     10622+                       {
     10623+                               // Hoosterman, we had a data problem on this page
     10624+                               yaffs_HandleReadDataError(dev,chunkInNAND);
    1250210625+                       }
    12503 +
    12504 +                       if (eccResult1 < 0 || eccResult2 < 0)
     10626+                       
     10627+                       if(eccResult1 < 0 || eccResult2 < 0)
    1250510628+                               *eccResult = YAFFS_ECC_RESULT_UNFIXED;
    12506 +                       else if (eccResult1 > 0 || eccResult2 > 0)
     10629+                       else if(eccResult1 > 0 || eccResult2 > 0)
    1250710630+                               *eccResult = YAFFS_ECC_RESULT_FIXED;
    1250810631+                       else
    1250910632+                               *eccResult = YAFFS_ECC_RESULT_NO_ERROR;
    1251010633+               }
    12511 +       } else {
    12512 +               /* Must allocate enough memory for spare+2*sizeof(int) */
    12513 +               /* for ecc results from device. */
    12514 +               struct yaffs_NANDSpare nspare;
    12515 +               retVal =
    12516 +                   dev->readChunkFromNAND(dev, chunkInNAND, data,
    12517 +                                          (yaffs_Spare *) & nspare);
    12518 +               memcpy(spare, &nspare, sizeof(yaffs_Spare));
    12519 +               if (data && doErrorCorrection) {
    12520 +                       if (nspare.eccres1 > 0) {
    12521 +                               T(YAFFS_TRACE_ERROR,
    12522 +                                 (TSTR
    12523 +                                  ("**>>mtd ecc error fix performed on chunk %d:0"
    12524 +                                   TENDSTR), chunkInNAND));
    12525 +                       } else if (nspare.eccres1 < 0) {
    12526 +                               T(YAFFS_TRACE_ERROR,
    12527 +                                 (TSTR
    12528 +                                  ("**>>mtd ecc error unfixed on chunk %d:0"
    12529 +                                   TENDSTR), chunkInNAND));
     10634+       }
     10635+       else
     10636+       {
     10637+        // Must allocate enough memory for spare+2*sizeof(int) for ecc results from device.
     10638+       struct yaffs_NANDSpare nspare;
     10639+               retVal  = dev->readChunkFromNAND(dev,chunkInNAND,data,(yaffs_Spare*)&nspare);
     10640+               memcpy (spare, &nspare, sizeof(yaffs_Spare));
     10641+               if(data && doErrorCorrection)
     10642+               {
     10643+                       if(nspare.eccres1>0)
     10644+                       {
     10645+                               T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error fix performed on chunk %d:0" TENDSTR),chunkInNAND));
    1253010646+                       }
    12531 +
    12532 +                       if (nspare.eccres2 > 0) {
    12533 +                               T(YAFFS_TRACE_ERROR,
    12534 +                                 (TSTR
    12535 +                                  ("**>>mtd ecc error fix performed on chunk %d:1"
    12536 +                                   TENDSTR), chunkInNAND));
    12537 +                       } else if (nspare.eccres2 < 0) {
    12538 +                               T(YAFFS_TRACE_ERROR,
    12539 +                                 (TSTR
    12540 +                                  ("**>>mtd ecc error unfixed on chunk %d:1"
    12541 +                                   TENDSTR), chunkInNAND));
     10647+                       else if(nspare.eccres1<0)
     10648+                       {
     10649+                               T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error unfixed on chunk %d:0" TENDSTR),chunkInNAND));
    1254210650+                       }
    1254310651+
    12544 +                       if (nspare.eccres1 || nspare.eccres2) {
    12545 +                               /* We had a data problem on this page */
    12546 +                               yaffs_HandleReadDataError(dev, chunkInNAND);
     10652+                       if(nspare.eccres2>0)
     10653+                       {
     10654+                               T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error fix performed on chunk %d:1" TENDSTR),chunkInNAND));
    1254710655+                       }
    12548 +
    12549 +                       if (nspare.eccres1 < 0 || nspare.eccres2 < 0)
     10656+                       else if(nspare.eccres2<0)
     10657+                       {
     10658+                               T(YAFFS_TRACE_ERROR,(TSTR("**>>ecc error unfixed on chunk %d:1" TENDSTR),chunkInNAND));
     10659+                       }
     10660+
     10661+                       if(nspare.eccres1 || nspare.eccres2)
     10662+                       {
     10663+                               // Hoosterman, we had a data problem on this page
     10664+                               yaffs_HandleReadDataError(dev,chunkInNAND);
     10665+                       }
     10666+                       
     10667+                       if(nspare.eccres1 < 0 || nspare.eccres2 < 0)
    1255010668+                               *eccResult = YAFFS_ECC_RESULT_UNFIXED;
    12551 +                       else if (nspare.eccres1 > 0 || nspare.eccres2 > 0)
     10669+                       else if(nspare.eccres1 > 0 || nspare.eccres2 > 0)
    1255210670+                               *eccResult = YAFFS_ECC_RESULT_FIXED;
    1255310671+                       else
    1255410672+                               *eccResult = YAFFS_ECC_RESULT_NO_ERROR;
    1255510673+
     10674+
    1255610675+               }
    1255710676+       }
     
    1256010679+
    1256110680+#ifdef NOTYET
    12562 +static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,
    12563 +                                 int chunkInNAND)
     10681+static int yaffs_CheckChunkErased(struct yaffs_DeviceStruct *dev,int chunkInNAND)
    1256410682+{
    1256510683+
     
    1256710685+       static __u8 cmpbuf[YAFFS_BYTES_PER_CHUNK];
    1256810686+       static __u8 data[YAFFS_BYTES_PER_CHUNK];
    12569 +       /* Might as well always allocate the larger size for */
    12570 +       /* dev->useNANDECC == true; */
     10687+    // Might as well always allocate the larger size for dev->useNANDECC == true;
    1257110688+       static __u8 spare[sizeof(struct yaffs_NANDSpare)];
    1257210689+
    12573 +       dev->readChunkFromNAND(dev, chunkInNAND, data, (yaffs_Spare *) spare);
    12574 +
    12575 +       if (!init) {
    12576 +               memset(cmpbuf, 0xff, YAFFS_BYTES_PER_CHUNK);
     10690+       dev->readChunkFromNAND(dev,chunkInNAND,data,(yaffs_Spare *)spare);
     10691+
     10692+       if(!init)
     10693+       {
     10694+               memset(cmpbuf,0xff,YAFFS_BYTES_PER_CHUNK);
    1257710695+               init = 1;
    1257810696+       }
    1257910697+
    12580 +       if (memcmp(cmpbuf, data, YAFFS_BYTES_PER_CHUNK))
    12581 +               return YAFFS_FAIL;
    12582 +       if (memcmp(cmpbuf, spare, 16))
    12583 +               return YAFFS_FAIL;
     10698+       if(memcmp(cmpbuf,data,YAFFS_BYTES_PER_CHUNK)) return  YAFFS_FAIL;
     10699+       if(memcmp(cmpbuf,spare,16)) return YAFFS_FAIL;
     10700+
    1258410701+
    1258510702+       return YAFFS_OK;
     
    1258810705+#endif
    1258910706+
    12590 +/*
    12591 + * Functions for robustisizing
    12592 + */
    12593 +
    12594 +static void yaffs_HandleReadDataError(yaffs_Device * dev, int chunkInNAND)
    12595 +{
    12596 +       int blockInNAND = chunkInNAND / dev->nChunksPerBlock;
    12597 +
    12598 +       /* Mark the block for retirement */
    12599 +       yaffs_GetBlockInfo(dev, blockInNAND)->needsRetiring = 1;
    12600 +       T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,
    12601 +         (TSTR("**>>Block %d marked for retirement" TENDSTR), blockInNAND));
    12602 +
    12603 +       /* TODO:
    12604 +        * Just do a garbage collection on the affected block
    12605 +        * then retire the block
    12606 +        * NB recursion
    12607 +        */
    12608 +}
     10707+#if 0
     10708+int yaffs_EraseBlockInNAND(struct yaffs_DeviceStruct *dev,int blockInNAND)
     10709+{
     10710+       dev->nBlockErasures++;
     10711+       return dev->eraseBlockInNAND(dev,blockInNAND);
     10712+}
     10713+
     10714+int yaffs_InitialiseNAND(struct yaffs_DeviceStruct *dev)
     10715+{
     10716+       return dev->initialiseNAND(dev);
     10717+}
     10718+
     10719+#endif
     10720+
     10721+#if 0
     10722+static int yaffs_WriteNewChunkToNAND(struct yaffs_DeviceStruct *dev, const __u8 *data, yaffs_Spare *spare,int useReserve)
     10723+{
     10724+       int chunk;
     10725+
     10726+       int writeOk = 1;
     10727+       int attempts = 0;
     10728+
     10729+       unsigned char rbData[YAFFS_BYTES_PER_CHUNK];
     10730+       yaffs_Spare rbSpare;
     10731+
     10732+       do{
     10733+               chunk = yaffs_AllocateChunk(dev,useReserve);
     10734+
     10735+               if(chunk >= 0)
     10736+               {
     10737+
     10738+                       // First check this chunk is erased...
     10739+#ifndef CONFIG_YAFFS_DISABLE_CHUNK_ERASED_CHECK
     10740+                       writeOk = yaffs_CheckChunkErased(dev,chunk);
     10741+#endif
     10742+                       if(!writeOk)
     10743+                       {
     10744+                               T(YAFFS_TRACE_ERROR,(TSTR("**>> yaffs chunk %d was not erased" TENDSTR),chunk));
     10745+                       }
     10746+                       else
     10747+                       {
     10748+                               writeOk =  yaffs_WriteChunkToNAND(dev,chunk,data,spare);
     10749+                       }
     10750+                       attempts++;
     10751+                       if(writeOk)
     10752+                       {
     10753+                               // Readback & verify
     10754+                               // If verify fails, then delete this chunk and try again
     10755+                               // To verify we compare everything except the block and
     10756+                               // page status bytes.
     10757+                               // NB We check a raw read without ECC correction applied
     10758+                               yaffs_ReadChunkFromNAND(dev,chunk,rbData,&rbSpare,0);
     10759+
     10760+#ifndef CONFIG_YAFFS_DISABLE_WRITE_VERIFY
     10761+                               if(!yaffs_VerifyCompare(data,rbData,spare,&rbSpare))
     10762+                               {
     10763+                                       // Didn't verify
     10764+                                       T(YAFFS_TRACE_ERROR,(TSTR("**>> yaffs write verify failed on chunk %d" TENDSTR), chunk));
     10765+
     10766+                                       writeOk = 0;
     10767+                               }
     10768+#endif
     10769+
     10770+                       }
     10771+                       if(writeOk)
     10772+                       {
     10773+                               // Copy the data into the write buffer.
     10774+                               // NB We do this at the end to prevent duplicates in the case of a write error.
     10775+                               //Todo
     10776+                               yaffs_HandleWriteChunkOk(dev,chunk,data,spare);
     10777+                       }
     10778+                       else
     10779+                       {
     10780+                               yaffs_HandleWriteChunkError(dev,chunk);
     10781+                       }
     10782+               }
     10783+
     10784+       } while(chunk >= 0 && ! writeOk);
     10785+
     10786+       if(attempts > 1)
     10787+       {
     10788+               T(YAFFS_TRACE_ERROR,(TSTR("**>> yaffs write required %d attempts" TENDSTR),attempts));
     10789+               dev->nRetriedWrites+= (attempts - 1);
     10790+       }
     10791+
     10792+       return chunk;
     10793+}
     10794+
     10795+#endif
     10796+
     10797+///
     10798+// Functions for robustisizing
     10799+//
     10800+//
     10801+#if 0
     10802+
     10803+static void yaffs_RetireBlock(yaffs_Device *dev,int blockInNAND)
     10804+{
     10805+       // Ding the blockStatus in the first two pages of the block.
     10806+
     10807+       yaffs_Spare spare;
     10808+
     10809+       memset(&spare, 0xff,sizeof(yaffs_Spare));
     10810+
     10811+       spare.blockStatus = 0;
     10812+
     10813+       // TODO change this retirement marking for other NAND types
     10814+       yaffs_WriteChunkToNAND(dev, blockInNAND * dev->nChunksPerBlock, NULL , &spare);
     10815+       yaffs_WriteChunkToNAND(dev, blockInNAND * dev->nChunksPerBlock + 1, NULL , &spare);
     10816+
     10817+       yaffs_GetBlockInfo(dev,blockInNAND)->blockState = YAFFS_BLOCK_STATE_DEAD;
     10818+       dev->nRetiredBlocks++;
     10819+}
     10820+
     10821+#endif
     10822+
     10823+#if 0
     10824+static int yaffs_RewriteBufferedBlock(yaffs_Device *dev)
     10825+{
     10826+       dev->doingBufferedBlockRewrite = 1;
     10827+       //
     10828+       //      Remove erased chunks
     10829+       //  Rewrite existing chunks to a new block
     10830+       //      Set current write block to the new block
     10831+
     10832+       dev->doingBufferedBlockRewrite = 0;
     10833+
     10834+       return 1;
     10835+}
     10836+
     10837+#endif
     10838+
     10839+static void yaffs_HandleReadDataError(yaffs_Device *dev,int chunkInNAND)
     10840+{
     10841+       int blockInNAND = chunkInNAND/dev->nChunksPerBlock;
     10842+
     10843+       // Mark the block for retirement
     10844+       yaffs_GetBlockInfo(dev,blockInNAND)->needsRetiring = 1;
     10845+       T(YAFFS_TRACE_ERROR | YAFFS_TRACE_BAD_BLOCKS,(TSTR("**>>Block %d marked for retirement" TENDSTR),blockInNAND));
     10846+
     10847+
     10848+       //TODO
     10849+       // Just do a garbage collection on the affected block then retire the block
     10850+       // NB recursion
     10851+}
     10852+
    1260910853+
    1261010854+#ifdef NOTYET
    12611 +static void yaffs_CheckWrittenBlock(yaffs_Device * dev, int chunkInNAND)
    12612 +{
    12613 +}
    12614 +
    12615 +static void yaffs_HandleWriteChunkOk(yaffs_Device * dev, int chunkInNAND,
    12616 +                                    const __u8 * data,
    12617 +                                    const yaffs_Spare * spare)
    12618 +{
    12619 +}
    12620 +
    12621 +static void yaffs_HandleUpdateChunk(yaffs_Device * dev, int chunkInNAND,
    12622 +                                   const yaffs_Spare * spare)
    12623 +{
    12624 +}
    12625 +
    12626 +static void yaffs_HandleWriteChunkError(yaffs_Device * dev, int chunkInNAND)
    12627 +{
    12628 +       int blockInNAND = chunkInNAND / dev->nChunksPerBlock;
    12629 +
    12630 +       /* Mark the block for retirement */
    12631 +       yaffs_GetBlockInfo(dev, blockInNAND)->needsRetiring = 1;
    12632 +       /* Delete the chunk */
    12633 +       yaffs_DeleteChunk(dev, chunkInNAND, 1, __LINE__);
    12634 +}
    12635 +
    12636 +static int yaffs_VerifyCompare(const __u8 * d0, const __u8 * d1,
    12637 +                              const yaffs_Spare * s0, const yaffs_Spare * s1)
    12638 +{
    12639 +
    12640 +       if (memcmp(d0, d1, YAFFS_BYTES_PER_CHUNK) != 0 ||
    12641 +           s0->tagByte0 != s1->tagByte0 ||
    12642 +           s0->tagByte1 != s1->tagByte1 ||
    12643 +           s0->tagByte2 != s1->tagByte2 ||
    12644 +           s0->tagByte3 != s1->tagByte3 ||
    12645 +           s0->tagByte4 != s1->tagByte4 ||
    12646 +           s0->tagByte5 != s1->tagByte5 ||
    12647 +           s0->tagByte6 != s1->tagByte6 ||
    12648 +           s0->tagByte7 != s1->tagByte7 ||
    12649 +           s0->ecc1[0] != s1->ecc1[0] ||
    12650 +           s0->ecc1[1] != s1->ecc1[1] ||
    12651 +           s0->ecc1[2] != s1->ecc1[2] ||
    12652 +           s0->ecc2[0] != s1->ecc2[0] ||
    12653 +           s0->ecc2[1] != s1->ecc2[1] || s0->ecc2[2] != s1->ecc2[2]) {
    12654 +               return 0;
    12655 +       }
     10855+static void yaffs_CheckWrittenBlock(yaffs_Device *dev,int chunkInNAND)
     10856+{
     10857+}
     10858+
     10859+static void yaffs_HandleWriteChunkOk(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_Spare *spare)
     10860+{
     10861+}
     10862+
     10863+static void yaffs_HandleUpdateChunk(yaffs_Device *dev,int chunkInNAND, const yaffs_Spare *spare)
     10864+{
     10865+}
     10866+
     10867+static void yaffs_HandleWriteChunkError(yaffs_Device *dev,int chunkInNAND)
     10868+{
     10869+       int blockInNAND = chunkInNAND/dev->nChunksPerBlock;
     10870+
     10871+       // Mark the block for retirement
     10872+       yaffs_GetBlockInfo(dev,blockInNAND)->needsRetiring = 1;
     10873+       // Delete the chunk
     10874+       yaffs_DeleteChunk(dev,chunkInNAND,1,__LINE__);
     10875+}
     10876+
     10877+
     10878+
     10879+
     10880+static int yaffs_VerifyCompare(const __u8 *d0, const __u8 * d1, const yaffs_Spare *s0, const yaffs_Spare *s1)
     10881+{
     10882+
     10883+
     10884+       if( memcmp(d0,d1,YAFFS_BYTES_PER_CHUNK) != 0 ||
     10885+               s0->tagByte0 != s1->tagByte0 ||
     10886+               s0->tagByte1 != s1->tagByte1 ||
     10887+               s0->tagByte2 != s1->tagByte2 ||
     10888+               s0->tagByte3 != s1->tagByte3 ||
     10889+               s0->tagByte4 != s1->tagByte4 ||
     10890+               s0->tagByte5 != s1->tagByte5 ||
     10891+               s0->tagByte6 != s1->tagByte6 ||
     10892+               s0->tagByte7 != s1->tagByte7 ||
     10893+               s0->ecc1[0]  != s1->ecc1[0]  ||
     10894+               s0->ecc1[1]  != s1->ecc1[1]  ||
     10895+               s0->ecc1[2]  != s1->ecc1[2]  ||
     10896+               s0->ecc2[0]  != s1->ecc2[0]  ||
     10897+               s0->ecc2[1]  != s1->ecc2[1]  ||
     10898+               s0->ecc2[2]  != s1->ecc2[2] )
     10899+               {
     10900+                       return 0;
     10901+               }
    1265610902+
    1265710903+       return 1;
    1265810904+}
    12659 +#endif                         /* NOTYET */
    12660 +
    12661 +int yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(yaffs_Device * dev,
    12662 +                                                   int chunkInNAND,
    12663 +                                                   const __u8 * data,
    12664 +                                                   const yaffs_ExtendedTags *
    12665 +                                                   eTags)
     10905+#endif /* NOTYET */
     10906+
     10907+#if 0
     10908+typedef struct
     10909+{
     10910+
     10911+       unsigned validMarker0;
     10912+       unsigned chunkUsed;                 //  Status of the chunk: used or unused
     10913+       unsigned objectId;                      // If 0 then this is not part of an object (unused)
     10914+       unsigned chunkId;                       // If 0 then this is a header
     10915+       unsigned byteCount;                 // Only valid for data chunks
     10916+       // The following stuff only has meaning when we read
     10917+       yaffs_ECCResult eccResult;  // Only valid when we read.
     10918+       unsigned blockBad;                      // Only valid on reading
     10919+
     10920+       // YAFFS 1 stuff       
     10921+       unsigned chunkDeleted;          // The chunk is marked deleted
     10922+       unsigned serialNumber;          // Yaffs1 2-bit serial number
     10923+       
     10924+       // YAFFS2 stuff
     10925+       unsigned sequenceNumber;        // The sequence number of this block
     10926+
     10927+       unsigned validMarker1;
     10928+
     10929+} yaffs_ExtendedTags;
     10930+
     10931+
     10932+typedef struct
     10933+{   
     10934+    unsigned chunkId:20;
     10935+    unsigned serialNumber:2;
     10936+    unsigned byteCount:10;
     10937+    unsigned objectId:18;
     10938+    unsigned ecc:12;
     10939+    unsigned unusedStuff:2;
     10940+} yaffs_Tags;
     10941+
     10942+
     10943+#endif
     10944+
     10945+int yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_ExtendedTags *eTags)
    1266610946+{
    1266710947+       yaffs_Spare spare;
    12668 +       yaffs_Tags tags;
    12669 +
     10948+       yaffs_Tags tags;       
     10949+       
    1267010950+       yaffs_SpareInitialise(&spare);
    12671 +
    12672 +       if (eTags->chunkDeleted) {
     10951+       
     10952+       if(eTags->chunkDeleted)
     10953+       {
    1267310954+               spare.pageStatus = 0;
    12674 +       } else {
     10955+       }
     10956+       else
     10957+       {
    1267510958+               tags.objectId = eTags->objectId;
    1267610959+               tags.chunkId = eTags->chunkId;
    1267710960+               tags.byteCount = eTags->byteCount;
    1267810961+               tags.serialNumber = eTags->serialNumber;
    12679 +
    12680 +               if (!dev->useNANDECC && data) {
    12681 +                       yaffs_CalcECC(data, &spare);
    12682 +               }
    12683 +               yaffs_LoadTagsIntoSpare(&spare, &tags);
    12684 +
    12685 +       }
    12686 +
    12687 +       return yaffs_WriteChunkToNAND(dev, chunkInNAND, data, &spare);
    12688 +}
    12689 +
    12690 +int yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(yaffs_Device * dev,
    12691 +                                                    int chunkInNAND,
    12692 +                                                    __u8 * data,
    12693 +                                                    yaffs_ExtendedTags * eTags)
     10962+               
     10963+// NCB
     10964+               if (!dev->useNANDECC && data)
     10965+               {
     10966+                   yaffs_CalcECC(data,&spare);
     10967+               }
     10968+
     10969+// /NCB
     10970+                yaffs_LoadTagsIntoSpare(&spare,&tags);
     10971+               
     10972+       }
     10973+       
     10974+       return yaffs_WriteChunkToNAND(dev,chunkInNAND,data,&spare);
     10975+}
     10976+
     10977+
     10978+int yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_ExtendedTags *eTags)
    1269410979+{
    1269510980+
     
    1269710982+       yaffs_Tags tags;
    1269810983+       yaffs_ECCResult eccResult;
    12699 +
    12700 +       static yaffs_Spare spareFF;
    12701 +       static int init;
    12702 +
    12703 +       if (!init) {
    12704 +               memset(&spareFF, 0xFF, sizeof(spareFF));
    12705 +               init = 1;
    12706 +       }
    12707 +
    12708 +       if (yaffs_ReadChunkFromNAND
    12709 +           (dev, chunkInNAND, data, &spare, &eccResult, 1)) {
    12710 +               /* eTags may be NULL */
     10984+       
     10985+// NCB
     10986+     static yaffs_Spare spareFF;
     10987+     static int init;
     10988+     
     10989+     if(!init)
     10990+     {
     10991+            memset(&spareFF,0xFF,sizeof(spareFF));
     10992+            init = 1;
     10993+     }
     10994+// /NCB
     10995+       if(yaffs_ReadChunkFromNAND(dev,chunkInNAND,data,&spare,&eccResult,1))
     10996+       {
     10997+// added NCB - eTags may be NULL
    1271110998+               if (eTags) {
    1271210999+
    12713 +                       int deleted =
    12714 +                           (yaffs_CountBits(spare.pageStatus) < 7) ? 1 : 0;
    12715 +
    12716 +                       eTags->chunkDeleted = deleted;
    12717 +                       eTags->eccResult = eccResult;
    12718 +                       eTags->blockBad = 0;    /* We're reading it */
    12719 +                       /* therefore it is not a bad block */
    12720 +                       eTags->chunkUsed =
    12721 +                           (memcmp(&spareFF, &spare, sizeof(spareFF)) !=
    12722 +                            0) ? 1 : 0;
    12723 +
    12724 +                       if (eTags->chunkUsed) {
    12725 +                               yaffs_GetTagsFromSpare(dev, &spare, &tags);
    12726 +
    12727 +                               eTags->objectId = tags.objectId;
    12728 +                               eTags->chunkId = tags.chunkId;
    12729 +                               eTags->byteCount = tags.byteCount;
    12730 +                               eTags->serialNumber = tags.serialNumber;
    12731 +                       }
    12732 +               }
    12733 +
    12734 +               return YAFFS_OK;
    12735 +       } else {
     11000+                int deleted = (yaffs_CountBits(spare.pageStatus) < 7) ? 1 : 0;
     11001+                       
     11002+                yaffs_GetTagsFromSpare(dev,&spare,&tags);
     11003+               
     11004+                eTags->chunkDeleted = deleted;
     11005+                eTags->objectId = tags.objectId;
     11006+                eTags->chunkId = tags.chunkId;
     11007+                eTags->byteCount = tags.byteCount;
     11008+                eTags->serialNumber = tags.serialNumber;
     11009+                eTags->eccResult = eccResult;
     11010+                eTags->blockBad = 0; // We're reading it therefore it is not a bad block
     11011+               
     11012+// NCB added 18/2/2005
     11013+                eTags->chunkUsed = (memcmp(&spareFF,&spare,sizeof(spareFF)) != 0) ? 1:0;
     11014+               }
     11015+               
     11016+                return YAFFS_OK;
     11017+       }
     11018+       else
     11019+       {
    1273611020+               return YAFFS_FAIL;
    1273711021+       }
    1273811022+}
    1273911023+
    12740 +int yaffs_TagsCompatabilityMarkNANDBlockBad(struct yaffs_DeviceStruct *dev,
    12741 +                                           int blockInNAND)
     11024+int yaffs_TagsCompatabilityMarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockInNAND)
    1274211025+{
    1274311026+
    1274411027+       yaffs_Spare spare;
    1274511028+
    12746 +       memset(&spare, 0xff, sizeof(yaffs_Spare));
    12747 +
    12748 +       spare.blockStatus = 'Y';
    12749 +
    12750 +       yaffs_WriteChunkToNAND(dev, blockInNAND * dev->nChunksPerBlock, NULL,
    12751 +                              &spare);
    12752 +       yaffs_WriteChunkToNAND(dev, blockInNAND * dev->nChunksPerBlock + 1,
    12753 +                              NULL, &spare);
    12754 +
     11029+       memset(&spare, 0xff,sizeof(yaffs_Spare));
     11030+
     11031+       spare.blockStatus = 0;
     11032+
     11033+       yaffs_WriteChunkToNAND(dev, blockInNAND * dev->nChunksPerBlock, NULL , &spare);
     11034+       yaffs_WriteChunkToNAND(dev, blockInNAND * dev->nChunksPerBlock + 1, NULL , &spare);
     11035+       
    1275511036+       return YAFFS_OK;
    12756 +
    12757 +}
    12758 +
    12759 +int yaffs_TagsCompatabilityQueryNANDBlock(struct yaffs_DeviceStruct *dev,
    12760 +                                         int blockNo, yaffs_BlockState *
    12761 +                                         state,
    12762 +                                         int *sequenceNumber)
    12763 +{
    12764 +
    12765 +       yaffs_Spare spare0, spare1;
    12766 +       static yaffs_Spare spareFF;
    12767 +       static int init;
    12768 +       yaffs_ECCResult dummy;
    12769 +
    12770 +       if (!init) {
    12771 +               memset(&spareFF, 0xFF, sizeof(spareFF));
    12772 +               init = 1;
    12773 +       }
    12774 +
    12775 +       *sequenceNumber = 0;
    12776 +
    12777 +       yaffs_ReadChunkFromNAND(dev, blockNo * dev->nChunksPerBlock, NULL,
    12778 +                               &spare0, &dummy, 1);
    12779 +       yaffs_ReadChunkFromNAND(dev, blockNo * dev->nChunksPerBlock + 1, NULL,
    12780 +                               &spare1, &dummy, 1);
    12781 +
    12782 +       if (yaffs_CountBits(spare0.blockStatus & spare1.blockStatus) < 7)
    12783 +               *state = YAFFS_BLOCK_STATE_DEAD;
    12784 +       else if (memcmp(&spareFF, &spare0, sizeof(spareFF)) == 0)
    12785 +               *state = YAFFS_BLOCK_STATE_EMPTY;
    12786 +       else
    12787 +               *state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
    12788 +
    12789 +       return YAFFS_OK;
    12790 +}
    12791 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_tagscompat.h linux-2.6.18.2.patched/fs/yaffs2/yaffs_tagscompat.h
    12792 --- linux-2.6.18.2/fs/yaffs2/yaffs_tagscompat.h 1970-01-01 01:00:00.000000000 +0100
    12793 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_tagscompat.h 2006-11-25 00:15:32.000000000 +0100
    12794 @@ -0,0 +1,40 @@
     11037+       
     11038+}
     11039+
     11040+
     11041+int yaffs_TagsCompatabilityQueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, int *sequenceNumber)
     11042+{
     11043+     
     11044+     yaffs_Spare spare0,spare1;
     11045+     static yaffs_Spare spareFF;
     11046+     static int init;
     11047+     yaffs_ECCResult dummy;
     11048+     
     11049+     if(!init)
     11050+     {
     11051+            memset(&spareFF,0xFF,sizeof(spareFF));
     11052+            init = 1;
     11053+     }
     11054+     
     11055+     *sequenceNumber = 0;
     11056+     
     11057+     yaffs_ReadChunkFromNAND(dev,blockNo * dev->nChunksPerBlock,NULL,&spare0,&dummy,1);
     11058+     yaffs_ReadChunkFromNAND(dev,blockNo * dev->nChunksPerBlock + 1,NULL,&spare1,&dummy,1);
     11059+     
     11060+     if(yaffs_CountBits(spare0.blockStatus & spare1.blockStatus) < 7)
     11061+       *state = YAFFS_BLOCK_STATE_DEAD;
     11062+     else if(memcmp(&spareFF,&spare0,sizeof(spareFF)) == 0)
     11063+         *state = YAFFS_BLOCK_STATE_EMPTY;
     11064+     else
     11065+        *state = YAFFS_BLOCK_STATE_NEEDS_SCANNING; 
     11066+
     11067+     return YAFFS_OK;
     11068+}
     11069+
     11070diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_tagscompat.h linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_tagscompat.h
     11071--- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_tagscompat.h        1970-01-01 01:00:00.000000000 +0100
     11072+++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_tagscompat.h     2006-12-10 03:57:50.000000000 +0100
     11073@@ -0,0 +1,30 @@
    1279511074+/*
    1279611075+ * YAFFS: Yet another FFS. A NAND-flash specific file system.
     
    1280511084+ * published by the Free Software Foundation.
    1280611085+ *
    12807 + * $Id: yaffs_tagscompat.h,v 1.2 2005/08/11 02:33:03 marty Exp $
     11086+ * $Id: yaffs_tagscompat.h,v 1.1 2004/11/03 08:14:07 charles Exp $
    1280811087+ */
    1280911088+
    12810 +/* This provides a ram disk under yaffs.
    12811 + * NB this is not intended for NAND emulation.
    12812 + * Use this with dev->useNANDECC enabled, then ECC overheads are not required.
    12813 + */
     11089+// This provides a rma disk under yaffs.
     11090+// NB this is not intended for NAND emulation.
     11091+// Use this with dev->useNANDECC enabled, then ECC overheads are not required.
     11092+
    1281411093+#ifndef __YAFFS_TAGSCOMPAT_H__
    1281511094+#define __YAFFS_TAGSCOMPAT_H__
    1281611095+
     11096+
    1281711097+#include "yaffs_guts.h"
    12818 +int yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(yaffs_Device * dev,
    12819 +                                                   int chunkInNAND,
    12820 +                                                   const __u8 * data,
    12821 +                                                   const yaffs_ExtendedTags *
    12822 +                                                   tags);
    12823 +int yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(yaffs_Device * dev,
    12824 +                                                    int chunkInNAND,
    12825 +                                                    __u8 * data,
    12826 +                                                    yaffs_ExtendedTags *
    12827 +                                                    tags);
    12828 +int yaffs_TagsCompatabilityMarkNANDBlockBad(struct yaffs_DeviceStruct *dev,
    12829 +                                           int blockNo);
    12830 +int yaffs_TagsCompatabilityQueryNANDBlock(struct yaffs_DeviceStruct *dev,
    12831 +                                         int blockNo, yaffs_BlockState *
    12832 +                                         state, int *sequenceNumber);
    12833 +
    12834 +#endif
    12835 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_tagsvalidity.c linux-2.6.18.2.patched/fs/yaffs2/yaffs_tagsvalidity.c
    12836 --- linux-2.6.18.2/fs/yaffs2/yaffs_tagsvalidity.c       1970-01-01 01:00:00.000000000 +0100
    12837 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_tagsvalidity.c       2006-11-25 00:15:32.000000000 +0100
    12838 @@ -0,0 +1,31 @@
     11098+int yaffs_TagsCompatabilityWriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_ExtendedTags *tags);
     11099+int yaffs_TagsCompatabilityReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_ExtendedTags *tags);
     11100+int yaffs_TagsCompatabilityMarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo);
     11101+int yaffs_TagsCompatabilityQueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, int *sequenceNumber);
     11102+
     11103+#endif
     11104diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_tagsvalidity.c linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_tagsvalidity.c
     11105--- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_tagsvalidity.c      1970-01-01 01:00:00.000000000 +0100
     11106+++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_tagsvalidity.c   2006-12-10 03:57:50.000000000 +0100
     11107@@ -0,0 +1,35 @@
    1283911108+
    1284011109+/*
     
    1285011119+ * published by the Free Software Foundation.
    1285111120+ *
    12852 + * $Id: yaffs_tagsvalidity.c,v 1.2 2005/08/11 02:33:03 marty Exp $
     11121+ * $Id: yaffs_tagsvalidity.c,v 1.1 2005/04/29 18:09:16 charles Exp $
    1285311122+ */
     11123+//yaffs_tagsvalidity.c
    1285411124+
    1285511125+#include "yaffs_tagsvalidity.h"
    1285611126+
    12857 +void yaffs_InitialiseTags(yaffs_ExtendedTags * tags)
    12858 +{
    12859 +       memset(tags, 0, sizeof(yaffs_ExtendedTags));
     11127+
     11128+
     11129+void yaffs_InitialiseTags(yaffs_ExtendedTags *tags)
     11130+{
     11131+       memset(tags,0,sizeof(yaffs_ExtendedTags));
    1286011132+       tags->validMarker0 = 0xAAAAAAAA;
    1286111133+       tags->validMarker1 = 0x55555555;
    1286211134+}
    1286311135+
    12864 +int yaffs_ValidateTags(yaffs_ExtendedTags * tags)
     11136+int yaffs_ValidateTags(yaffs_ExtendedTags *tags)
    1286511137+{
    1286611138+       return (tags->validMarker0 == 0xAAAAAAAA &&
     
    1286811140+
    1286911141+}
    12870 diff -NaurB linux-2.6.18.2/fs/yaffs2/yaffs_tagsvalidity.h linux-2.6.18.2.patched/fs/yaffs2/yaffs_tagsvalidity.h
    12871 --- linux-2.6.18.2/fs/yaffs2/yaffs_tagsvalidity.h       1970-01-01 01:00:00.000000000 +0100
    12872 +++ linux-2.6.18.2.patched/fs/yaffs2/yaffs_tagsvalidity.h       2006-11-25 00:15:32.000000000 +0100
    12873 @@ -0,0 +1,25 @@
     11142+
     11143diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_tagsvalidity.h linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_tagsvalidity.h
     11144--- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_tagsvalidity.h      1970-01-01 01:00:00.000000000 +0100
     11145+++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yaffs_tagsvalidity.h   2006-12-10 03:57:50.000000000 +0100
     11146@@ -0,0 +1,27 @@
    1287411147+
    1287511148+/*
     
    1288511158+ * published by the Free Software Foundation.
    1288611159+ *
    12887 + * $Id: yaffs_tagsvalidity.h,v 1.2 2005/08/11 02:33:03 marty Exp $
     11160+ * $Id: yaffs_tagsvalidity.h,v 1.1 2005/04/29 18:09:16 charles Exp $
    1288811161+ */
    1288911162+//yaffs_tagsvalidity.h
    1289011163+
     11164+
    1289111165+#ifndef __YAFFS_TAGS_VALIDITY_H__
    1289211166+#define __YAFFS_TAGS_VALIDITY_H__
     
    1289411168+#include "yaffs_guts.h"
    1289511169+
    12896 +void yaffs_InitialiseTags(yaffs_ExtendedTags * tags);
    12897 +int yaffs_ValidateTags(yaffs_ExtendedTags * tags);
    12898 +#endif
    12899 diff -NaurB linux-2.6.18.2/fs/yaffs2/yportenv.h linux-2.6.18.2.patched/fs/yaffs2/yportenv.h
    12900 --- linux-2.6.18.2/fs/yaffs2/yportenv.h 1970-01-01 01:00:00.000000000 +0100
    12901 +++ linux-2.6.18.2.patched/fs/yaffs2/yportenv.h 2006-11-25 00:15:32.000000000 +0100
     11170+void yaffs_InitialiseTags(yaffs_ExtendedTags *tags);
     11171+int yaffs_ValidateTags(yaffs_ExtendedTags *tags);
     11172+#endif
     11173+
     11174diff -NaurB build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yportenv.h linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yportenv.h
     11175--- build_mipsel/linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yportenv.h        1970-01-01 01:00:00.000000000 +0100
     11176+++ linux-2.6-rb/linux-2.6.18.2/fs/yaffs/yportenv.h     2006-12-10 03:57:50.000000000 +0100
    1290211177@@ -0,0 +1,165 @@
    1290311178+/*
     
    1291811193+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
    1291911194+ *
    12920 + * $Id: yportenv.h,v 1.11 2006/05/21 09:39:12 charles Exp $
     11195+ * $Id: yportenv.h,v 1.6 2005/07/31 00:26:57 charles Exp $
    1292111196+ *
    1292211197+ */
    12923 +
     11198+ 
    1292411199+#ifndef __YPORTENV_H__
    1292511200+#define __YPORTENV_H__
    1292611201+
     11202+
    1292711203+#if defined CONFIG_YAFFS_WINCE
    1292811204+
     
    1293111207+#elif  defined __KERNEL__
    1293211208+
    12933 +#include "moduleconfig.h"
    12934 +
    12935 +/* Linux kernel */
     11209+
     11210+
     11211+// Linux kernel
    1293611212+#include <linux/config.h>
    1293711213+#include <linux/kernel.h>
     
    1294011216+#include <linux/string.h>
    1294111217+#include <linux/slab.h>
    12942 +#include <linux/vmalloc.h>
    1294311218+
    1294411219+#define YCHAR char
     
    1295611231+#define YAFFS_LOSTNFOUND_PREFIX                "obj"
    1295711232+
    12958 +/* #define YPRINTF(x) printk x */
     11233+//#define YPRINTF(x) printk x
    1295911234+#define YMALLOC(x) kmalloc(x,GFP_KERNEL)
    1296011235+#define YFREE(x)   kfree(x)
    12961 +#define YMALLOC_ALT(x) vmalloc(x)
    12962 +#define YFREE_ALT(x)   vfree(x)
    12963 +#define YMALLOC_DMA(x) YMALLOC(x)
    12964 +
    12965 +// KR - added for use in scan so processes aren't blocked indefinitely.
    12966 +#define YYIELD() schedule()
    1296711236+
    1296811237+#define YAFFS_ROOT_MODE                                0666
     
    1298411253+#define TOUT(p) printk p
    1298511254+
     11255+
    1298611256+#elif defined CONFIG_YAFFS_DIRECT
    1298711257+
    12988 +/* Direct interface */
     11258+// Direct interface
    1298911259+#include "ydirectenv.h"
    1299011260+
    1299111261+#elif defined CONFIG_YAFFS_UTIL
    1299211262+
    12993 +/* Stuff for YAFFS utilities */
     11263+// Stuff for YAFFS utilities
    1299411264+
    1299511265+#include "stdlib.h"
     
    1300111271+#define YMALLOC(x) malloc(x)
    1300211272+#define YFREE(x)   free(x)
    13003 +#define YMALLOC_ALT(x) malloc(x)
    13004 +#define YFREE_ALT(x) free(x)
     11273+
    1300511274+
    1300611275+#define YCHAR char
     
    1301511284+#define Y_INLINE inline
    1301611285+
    13017 +/* #define YINFO(s) YPRINTF(( __FILE__ " %d %s\n",__LINE__,s)) */
    13018 +/* #define YALERT(s) YINFO(s) */
     11286+//#define YINFO(s) YPRINTF(( __FILE__ " %d %s\n",__LINE__,s))
     11287+//#define YALERT(s) YINFO(s)
     11288+
    1301911289+
    1302011290+#define TENDSTR "\n"
     
    1302211292+#define TOUT(p) printf p
    1302311293+
     11294+
    1302411295+#define YAFFS_LOSTNFOUND_NAME          "lost+found"
    1302511296+#define YAFFS_LOSTNFOUND_PREFIX                "obj"
    13026 +/* #define YPRINTF(x) printf x */
     11297+//#define YPRINTF(x) printf x
     11298+
    1302711299+
    1302811300+#define YAFFS_ROOT_MODE                                0666
     
    1303311305+
    1303411306+#else
    13035 +/* Should have specified a configuration type */
     11307+// Should have specified a configuration type
    1303611308+#error Unknown configuration
    1303711309+
    13038 +#endif
     11310+#endif
     11311+
    1303911312+
    1304011313+extern unsigned yaffs_traceMask;
     
    1305511328+#define YAFFS_TRACE_SCAN_DEBUG         0x00002000
    1305611329+#define YAFFS_TRACE_MTD                        0x00004000
    13057 +#define YAFFS_TRACE_CHECKPOINT         0x00008000
    1305811330+#define YAFFS_TRACE_ALWAYS             0x40000000
    1305911331+#define YAFFS_TRACE_BUG                        0x80000000
    1306011332+
    13061 +#define T(mask,p) do{ if((mask) & (yaffs_traceMask | YAFFS_TRACE_ERROR)) TOUT(p);} while(0)
     11333+#define T(mask,p) do{ if((mask) & (yaffs_traceMask | YAFFS_TRACE_ERROR)) TOUT(p);} while(0)
     11334+
    1306211335+
    1306311336+#ifndef CONFIG_YAFFS_WINCE
     
    1306611339+
    1306711340+#endif
     11341+
     11342+
Note: See TracChangeset for help on using the changeset viewer.