yaffs: More clean up
authorCharles Manning <cdhmanning@gmail.com>
Wed, 3 Nov 2010 01:04:02 +0000 (14:04 +1300)
committerCharles Manning <cdhmanning@gmail.com>
Wed, 3 Nov 2010 01:04:02 +0000 (14:04 +1300)
Signed-off-by: Charles Manning <cdhmanning@gmail.com>
19 files changed:
Makefile
Makefile.kernel
direct/basic-test/Makefile
direct/basic-test/yaffs_fileem2k.c
direct/python/Makefile
direct/tests/Makefile
direct/yaffs_attribs.c [new file with mode: 0644]
direct/yaffs_flashif2.h
yaffs_attribs.c [new file with mode: 0644]
yaffs_attribs.h [new file with mode: 0644]
yaffs_guts.c
yaffs_guts.h
yaffs_mtdif1_multi.c [new file with mode: 0644]
yaffs_mtdif2_multi.c [new file with mode: 0644]
yaffs_vfs_multi.c
yaffs_vfs_single.c
yaffs_yaffs1.c
yaffs_yaffs2.c
yportenv.h [new symlink]

index 1be1ab9..1dbafc6 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -33,7 +33,7 @@ ifneq ($(KERNELRELEASE),)
        yaffs2-objs += yaffs_tagscompat.o yaffs_tagsvalidity.o
        yaffs2-objs += yaffs_checkptrw.o yaffs_nand.o
        yaffs2-objs += yaffs_checkptrw.o yaffs_nand.o yaffs_nameval.o
-       yaffs2-objs += yaffs_allocator.o yaffs_bitmap.o
+       yaffs2-objs += yaffs_allocator.o yaffs_bitmap.o yaffs_attribs.o
        yaffs2-objs += yaffs_yaffs1.o
        yaffs2-objs += yaffs_yaffs2.o
        yaffs2-objs += yaffs_verify.o
@@ -45,7 +45,7 @@ ifneq ($(KERNELRELEASE),)
        yaffs2multi-objs += yaffs_tagscompat.o yaffs_tagsvalidity.o
        yaffs2multi-objs += yaffs_checkptrw.o yaffs_nand.o
        yaffs2multi-objs += yaffs_checkptrw.o yaffs_nand.o yaffs_nameval.o
-       yaffs2multi-objs += yaffs_allocator.o yaffs_bitmap.o
+       yaffs2multi-objs += yaffs_allocator.o yaffs_bitmap.o yaffs_attribs.o
        yaffs2multi-objs += yaffs_yaffs1.o
        yaffs2multi-objs += yaffs_yaffs2.o
        yaffs2multi-objs += yaffs_verify.o
index 9011f70..e63a28a 100644 (file)
@@ -8,7 +8,7 @@ yaffs-y := yaffs_ecc.o yaffs_vfs.o yaffs_guts.o yaffs_checkptrw.o
 yaffs-y += yaffs_packedtags1.o yaffs_packedtags2.o yaffs_nand.o
 yaffs-y += yaffs_tagscompat.o yaffs_tagsvalidity.o
 yaffs-y += yaffs_mtdif.o yaffs_mtdif1.o yaffs_mtdif2.o
-yaffs-y += yaffs_nameval.o
+yaffs-y += yaffs_nameval.o yaffs_attribs.o
 yaffs-y += yaffs_allocator.o
 yaffs-y += yaffs_yaffs1.o
 yaffs-y += yaffs_yaffs2.o
index 542efba..7847528 100644 (file)
@@ -34,8 +34,8 @@ COMMONTESTOBJS = yaffscfg2k.o yaffs_ecc.o yaffs_fileem.o yaffs_fileem2k.o yaffsf
                 yaffs_packedtags1.o yaffs_ramdisk.o yaffs_ramem2k.o \
                 yaffs_tagscompat.o yaffs_packedtags2.o yaffs_tagsvalidity.o yaffs_nand.o \
                 yaffs_checkptrw.o  yaffs_qsort.o\
-                yaffs_nameval.o \
-                yaffs_norif1.o  ynorsim.o nor_stress.o yaffs_fsx.o \
+                yaffs_nameval.o yaffs_attribs.o \
+                yaffs_norif1.o  ynorsim.o \
                 yaffs_allocator.o \
                 yaffs_bitmap.o \
                 yaffs_yaffs1.o \
@@ -44,17 +44,13 @@ COMMONTESTOBJS = yaffscfg2k.o yaffs_ecc.o yaffs_fileem.o yaffs_fileem2k.o yaffsf
 
 #               yaffs_checkptrwtest.o\
 
-YAFFSTESTOBJS  = $(COMMONTESTOBJS) yaffs_test.o
-
-
-ALLOBJS = $(sort $(YAFFSTESTOBJS))
 
 YAFFSSYMLINKS = yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h yaffs_tagscompat.c yaffs_tagscompat.h \
           yaffs_packedtags1.c yaffs_packedtags1.h yaffs_packedtags2.c yaffs_packedtags2.h \
           yaffs_nand.c yaffs_nand.h yaffs_getblockinfo.h \
           yaffs_tagsvalidity.c yaffs_tagsvalidity.h yaffs_checkptrw.h yaffs_checkptrw.c \
           yaffs_nameval.c yaffs_nameval.h \
-          yaffs_trace.h \
+          yaffs_trace.h yaffs_attribs.h \
           yaffs_allocator.c yaffs_allocator.h \
           yaffs_yaffs1.c yaffs_yaffs1.h \
           yaffs_yaffs2.c yaffs_yaffs2.h \
@@ -64,7 +60,7 @@ YAFFSSYMLINKS = yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h yaffs_tagscomp
 YAFFSDIRECTSYMLINKS =  yaffsfs.c yaffs_flashif.h yaffs_flashif2.h\
                       yaffsfs.h yaffs_malloc.h ydirectenv.h \
                       yaffs_flashif.c yaffscfg.h yaffs_list.h \
-                      yaffs_qsort.c yportenv.h \
+                      yaffs_qsort.c yportenv.h yaffs_attribs.c \
                       yaffs_nandif.c yaffs_nandif.h yaffs_nandemul2k.h
 
 
@@ -72,21 +68,6 @@ YAFFSDIRECTSYMLINKS =  yaffsfs.c yaffs_flashif.h yaffs_flashif2.h\
 SYMLINKS = $(YAFFSSYMLINKS) $(YAFFSDIRECTSYMLINKS)
 
 
-
-
-COMMONTESTOBJS = yaffsnewcfg.o  yramsim.o \
-                yaffsfs.o yaffs_guts.o yaffs_ecc.o yaffs_nandif.o \
-                yaffs_packedtags1.o yaffs_ramdisk.o yaffs_ramem2k.o \
-                yaffs_tagscompat.o yaffs_packedtags2.o yaffs_tagsvalidity.o yaffs_nand.o \
-                yaffs_checkptrw.o  yaffs_qsort.o\
-                yaffs_nameval.o \
-                yaffs_norif1.o  ynorsim.o \
-                yaffs_allocator.o yaffs_yaffs1.o \
-                yaffs_yaffs2.o \
-                yaffs_bitmap.o yaffs_verify.o
-
-#               yaffs_checkptrwtest.o\
-
 DIRECTTESTOBJS = $(COMMONTESTOBJS) dtest.o
 
 BOOTTESTOBJS = bootldtst.o yboot.o yaffs_fileem.o nand_ecc.o
index d8fde73..06e41e5 100644 (file)
@@ -24,15 +24,16 @@ const char *yaffs_flashif2_c_version = "$Id: yaffs_fileem2k.c,v 1.24 2010-02-18
 
 #include "yaffs_flashif2.h"
 #include "yaffs_guts.h"
+#include "yaffs_fileem2k.h"
+#include "yaffs_packedtags2.h"
+#include "yaffs_tagsvalidity.h"
+
 
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <unistd.h> 
 
-#include "yaffs_fileem2k.h"
-#include "yaffs_packedtags2.h"
-
 
 
 #define REPORT_ERROR 0
@@ -65,7 +66,6 @@ int yaffs_test_partial_write = 0;
 
 extern int random_seed;
 extern int simulate_power_failure;
-static int initialised = 0;
 static int remaining_ops;
 static int nops_so_far;
 
@@ -179,7 +179,7 @@ int yflash2_WriteChunkWithTagsToNAND(struct yaffs_dev *dev,int nand_chunk,const
        int nRead;
        int error;
        
-       T(YAFFS_TRACE_MTD,(TSTR("write chunk %d data %x tags %x" TENDSTR),nand_chunk,(unsigned)data, (unsigned)tags));
+       T(YAFFS_TRACE_MTD,(TSTR("write chunk %d data %p tags %p" TENDSTR),nand_chunk, data, tags));
 
        CheckInit();
        
@@ -396,7 +396,7 @@ int yflash2_ReadChunkWithTagsFromNAND(struct yaffs_dev *dev,int nand_chunk, u8 *
        int retval = YAFFS_OK;
        int nRead;
        
-       T(YAFFS_TRACE_MTD,(TSTR("read chunk %d data %x tags %x" TENDSTR),nand_chunk,(unsigned)data, (unsigned)tags));
+       T(YAFFS_TRACE_MTD,(TSTR("read chunk %d data %p tags %p" TENDSTR),nand_chunk, data, tags));
        
        CheckInit();
        
index f571cf4..7c7a063 100644 (file)
@@ -30,7 +30,7 @@ CFLAGS +=    -O0 -fPIC
 
 
 COMMONTESTOBJS = yaffscfg2k.o yramsim.o yaffs_fileem2k.o\
-                yaffs_nandif.o \
+                yaffs_nandif.o yaffs_attribs.o \
                 yaffsfs.o  yaffs_ecc.o yaffs_guts.o \
                 yaffs_packedtags1.o yaffs_ramdisk.o yaffs_ramem2k.o \
                 yaffs_tagscompat.o yaffs_packedtags2.o yaffs_tagsvalidity.o yaffs_nand.o \
@@ -51,7 +51,7 @@ YAFFSSYMLINKS = yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h yaffs_tagscomp
           yaffs_packedtags1.c yaffs_packedtags1.h yaffs_packedtags2.c yaffs_packedtags2.h  \
           yaffs_nand.c yaffs_nand.h yaffs_getblockinfo.h  \
           yaffs_tagsvalidity.c yaffs_tagsvalidity.h yaffs_checkptrw.h yaffs_checkptrw.c \
-          yaffs_nameval.c yaffs_nameval.h \
+          yaffs_nameval.c yaffs_nameval.h yaffs_attribs.h \
           yaffs_trace.h \
           yaffs_allocator.c yaffs_allocator.h \
           yaffs_yaffs1.c yaffs_yaffs1.h \
@@ -63,7 +63,7 @@ YAFFSSYMLINKS = yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h yaffs_tagscomp
 YAFFSDIRECTSYMLINKS =  yaffsfs.c yaffsfs.h yaffscfg.h yaffs_malloc.h ydirectenv.h \
                       yaffs_flashif.c yaffs_flashif.h yaffs_flashif2.h yaffs_list.h \
                       yaffs_nandif.c yaffs_nandif.h yaffs_qsort.c yaffs_nandemul2k.h \
-                      yportenv.h
+                      yportenv.h yaffs_attribs.c
 
 DIRECTEXTRASYMLINKS =   yaffscfg2k.c yaffs_fileem2k.c yaffs_fileem2k.h\
                         yaffs_fileem.c yaffs_norif1.c yaffs_norif1.h \
index cb90c29..016b934 100644 (file)
@@ -34,7 +34,7 @@ COMMONTESTOBJS = yaffscfg2k.o yaffs_ecc.o yaffs_fileem.o yaffs_fileem2k.o yaffsf
                 yaffs_packedtags1.o yaffs_ramdisk.o yaffs_ramem2k.o \
                 yaffs_tagscompat.o yaffs_packedtags2.o yaffs_tagsvalidity.o yaffs_nand.o \
                 yaffs_checkptrw.o  yaffs_qsort.o\
-                yaffs_nameval.o \
+                yaffs_nameval.o yaffs_attribs.o \
                 yaffs_norif1.o  ynorsim.o nor_stress.o yaffs_fsx.o \
                 yaffs_allocator.o \
                 yaffs_bitmap.o \
@@ -54,7 +54,7 @@ YAFFSSYMLINKS = yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h yaffs_tagscomp
           yaffs_nand.c yaffs_nand.h yaffs_getblockinfo.h \
           yaffs_tagsvalidity.c yaffs_tagsvalidity.h yaffs_checkptrw.h yaffs_checkptrw.c \
           yaffs_nameval.c yaffs_nameval.h \
-          yaffs_trace.h \
+          yaffs_trace.h yaffs_attribs.h \
           yaffs_allocator.c yaffs_allocator.h \
           yaffs_yaffs1.c yaffs_yaffs1.h \
           yaffs_yaffs2.c yaffs_yaffs2.h \
@@ -65,6 +65,7 @@ YAFFSDIRECTSYMLINKS =  yaffsfs.c yaffs_flashif.h yaffs_flashif2.h\
                       yaffsfs.h yaffs_malloc.h ydirectenv.h \
                       yaffs_flashif.c yaffscfg.h yaffs_qsort.c \
                       yaffs_nandemul2k.h yaffs_list.h \
+                      yaffs_attribs.c \
                       yaffs_nandif.c yaffs_nandif.h yportenv.h
 
 
diff --git a/direct/yaffs_attribs.c b/direct/yaffs_attribs.c
new file mode 100644 (file)
index 0000000..89cd7fc
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2010 Aleph One Ltd.
+ *   for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "yaffs_attribs.h"
+
+
+void yaffs_load_attribs(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh)
+{
+       obj->yst_uid = oh->yst_uid;
+       obj->yst_gid = oh->yst_gid;
+       obj->yst_atime = oh->yst_atime;
+       obj->yst_mtime = oh->yst_mtime;
+       obj->yst_ctime = oh->yst_ctime;
+       obj->yst_rdev = oh->yst_rdev;
+}
+
+
+void yaffs_load_attribs_oh(struct yaffs_obj_hdr *oh, struct yaffs_obj *obj)
+{
+#ifdef CONFIG_YAFFS_WINCE
+               oh->win_atime[0] = obj->win_atime[0];
+               oh->win_ctime[0] = obj->win_ctime[0];
+               oh->win_mtime[0] = obj->win_mtime[0];
+               oh->win_atime[1] = obj->win_atime[1];
+               oh->win_ctime[1] = obj->win_ctime[1];
+               oh->win_mtime[1] = obj->win_mtime[1];
+#else
+               oh->yst_uid = obj->yst_uid;
+               oh->yst_gid = obj->yst_gid;
+               oh->yst_atime = obj->yst_atime;
+               oh->yst_mtime = obj->yst_mtime;
+               oh->yst_ctime = obj->yst_ctime;
+               oh->yst_rdev = obj->yst_rdev;
+#endif
+
+}
+
+void yaffs_attribs_init(struct yaffs_obj *obj, u32 gid, u32 uid, u32 rdev)
+{
+
+#ifdef CONFIG_YAFFS_WINCE
+               yfsd_win_file_time_now(obj->win_atime);
+               obj->win_ctime[0] = obj->win_mtime[0] = obj->win_atime[0];
+               obj->win_ctime[1] = obj->win_mtime[1] = obj->win_atime[1];
+
+#else
+       yaffs_load_current_time(obj,1,1);
+       obj->yst_rdev = rdev;
+       obj->yst_uid = uid;
+       obj->yst_gid = gid;
+#endif
+}
+
+void yaffs_load_current_time(struct yaffs_obj *obj, int do_a, int do_c)
+{
+#ifdef CONFIG_YAFFS_WINCE
+               yfsd_win_file_time_now(the_obj->win_atime);
+               the_obj->win_ctime[0] = the_obj->win_mtime[0] =
+                   the_obj->win_atime[0];
+               the_obj->win_ctime[1] = the_obj->win_mtime[1] =
+                   the_obj->win_atime[1];
+
+#else
+
+        obj->yst_mtime = Y_CURRENT_TIME;
+        if(do_a)
+                obj->yst_atime = obj->yst_atime;
+        if(do_c)
+                obj->yst_ctime = obj->yst_atime;
+#endif
+}
+
+loff_t yaffs_get_file_size(struct yaffs_obj *obj)
+{
+       YCHAR *alias = NULL;
+       obj = yaffs_get_equivalent_obj(obj);
+
+       switch (obj->variant_type) {
+       case YAFFS_OBJECT_TYPE_FILE:
+               return obj->variant.file_variant.file_size;
+       case YAFFS_OBJECT_TYPE_SYMLINK:
+               alias = obj->variant.symlink_variant.alias;
+               if(!alias)
+                       return 0;
+               return yaffs_strnlen(alias,YAFFS_MAX_ALIAS_LENGTH);
+       default:
+               return 0;
+       }
+}
+
+int yaffs_set_attribs(struct yaffs_obj *obj, struct iattr *attr)
+{
+       unsigned int valid = attr->ia_valid;
+
+       if (valid & ATTR_MODE)
+               obj->yst_mode = attr->ia_mode;
+       if (valid & ATTR_UID)
+               obj->yst_uid = attr->ia_uid;
+       if (valid & ATTR_GID)
+               obj->yst_gid = attr->ia_gid;
+
+       if (valid & ATTR_ATIME)
+               obj->yst_atime = Y_TIME_CONVERT(attr->ia_atime);
+       if (valid & ATTR_CTIME)
+               obj->yst_ctime = Y_TIME_CONVERT(attr->ia_ctime);
+       if (valid & ATTR_MTIME)
+               obj->yst_mtime = Y_TIME_CONVERT(attr->ia_mtime);
+
+       if (valid & ATTR_SIZE)
+               yaffs_resize_file(obj, attr->ia_size);
+
+       yaffs_update_oh(obj, NULL, 1, 0, 0, NULL);
+
+       return YAFFS_OK;
+
+}
+
+int yaffs_get_attribs(struct yaffs_obj *obj, struct iattr *attr)
+{
+       unsigned int valid = 0;
+
+       attr->ia_mode = obj->yst_mode;
+       valid |= ATTR_MODE;
+       attr->ia_uid = obj->yst_uid;
+       valid |= ATTR_UID;
+       attr->ia_gid = obj->yst_gid;
+       valid |= ATTR_GID;
+
+       Y_TIME_CONVERT(attr->ia_atime) = obj->yst_atime;
+       valid |= ATTR_ATIME;
+       Y_TIME_CONVERT(attr->ia_ctime) = obj->yst_ctime;
+       valid |= ATTR_CTIME;
+       Y_TIME_CONVERT(attr->ia_mtime) = obj->yst_mtime;
+       valid |= ATTR_MTIME;
+
+       attr->ia_size = yaffs_get_file_size(obj);
+       valid |= ATTR_SIZE;
+
+       attr->ia_valid = valid;
+
+       return YAFFS_OK;
+}
+
index 17d2dfa..75a66de 100644 (file)
@@ -23,7 +23,6 @@ int yflash2_WriteChunkToNAND(struct yaffs_dev *dev,int nand_chunk,const u8 *data
 int yflash2_WriteChunkWithTagsToNAND(struct yaffs_dev *dev,int nand_chunk,const u8 *data, const struct yaffs_ext_tags *tags);
 int yflash2_ReadChunkFromNAND(struct yaffs_dev *dev,int nand_chunk, u8 *data, struct yaffs_spare *spare);
 int yflash2_ReadChunkWithTagsFromNAND(struct yaffs_dev *dev,int nand_chunk, u8 *data, struct yaffs_ext_tags *tags);
-int yflash2_EraseBlockInNAND(struct yaffs_dev *dev, int blockNumber);
 int yflash2_InitialiseNAND(struct yaffs_dev *dev);
 int yflash2_MarkNANDBlockBad(struct yaffs_dev *dev, int block_no);
 int yflash2_QueryNANDBlock(struct yaffs_dev *dev, int block_no, enum yaffs_block_state *state, u32 *seq_number);
diff --git a/yaffs_attribs.c b/yaffs_attribs.c
new file mode 100644 (file)
index 0000000..651a473
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2010 Aleph One Ltd.
+ *   for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+
+#include "yaffs_guts.h"
+#include "yaffs_attribs.h"
+
+void yaffs_load_attribs(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh)
+{
+       obj->yst_uid = oh->yst_uid;
+       obj->yst_gid = oh->yst_gid;
+       obj->yst_atime = oh->yst_atime;
+       obj->yst_mtime = oh->yst_mtime;
+       obj->yst_ctime = oh->yst_ctime;
+       obj->yst_rdev = oh->yst_rdev;
+}
+
+void yaffs_load_attribs_oh(struct yaffs_obj_hdr *oh, struct yaffs_obj *obj)
+{
+        oh->yst_uid = obj->yst_uid;
+       oh->yst_gid = obj->yst_gid;
+       oh->yst_atime = obj->yst_atime;
+       oh->yst_mtime = obj->yst_mtime;
+       oh->yst_ctime = obj->yst_ctime;
+       oh->yst_rdev = obj->yst_rdev;
+
+}
+
+void yaffs_load_current_time(struct yaffs_obj *obj, int do_a, int do_c)
+{
+        obj->yst_mtime = Y_CURRENT_TIME;
+        if(do_a)
+                obj->yst_atime = obj->yst_atime;
+        if(do_c)
+                obj->yst_ctime = obj->yst_atime;
+}
+
+void yaffs_attribs_init(struct yaffs_obj *obj, u32 gid, u32 uid, u32 rdev)
+{
+       yaffs_load_current_time(obj,1,1);
+       obj->yst_rdev = rdev;
+       obj->yst_uid = uid;
+       obj->yst_gid = gid;
+}
+
+
+loff_t yaffs_get_file_size(struct yaffs_obj *obj)
+{
+       YCHAR *alias = NULL;
+       obj = yaffs_get_equivalent_obj(obj);
+
+       switch (obj->variant_type) {
+       case YAFFS_OBJECT_TYPE_FILE:
+               return obj->variant.file_variant.file_size;
+       case YAFFS_OBJECT_TYPE_SYMLINK:
+               alias = obj->variant.symlink_variant.alias;
+               if(!alias)
+                       return 0;
+               return yaffs_strnlen(alias,YAFFS_MAX_ALIAS_LENGTH);
+       default:
+               return 0;
+       }
+}
+
+int yaffs_set_attribs(struct yaffs_obj *obj, struct iattr *attr)
+{
+       unsigned int valid = attr->ia_valid;
+
+       if (valid & ATTR_MODE)
+               obj->yst_mode = attr->ia_mode;
+       if (valid & ATTR_UID)
+               obj->yst_uid = attr->ia_uid;
+       if (valid & ATTR_GID)
+               obj->yst_gid = attr->ia_gid;
+
+       if (valid & ATTR_ATIME)
+               obj->yst_atime = Y_TIME_CONVERT(attr->ia_atime);
+       if (valid & ATTR_CTIME)
+               obj->yst_ctime = Y_TIME_CONVERT(attr->ia_ctime);
+       if (valid & ATTR_MTIME)
+               obj->yst_mtime = Y_TIME_CONVERT(attr->ia_mtime);
+
+       if (valid & ATTR_SIZE)
+               yaffs_resize_file(obj, attr->ia_size);
+
+       yaffs_update_oh(obj, NULL, 1, 0, 0, NULL);
+
+       return YAFFS_OK;
+
+}
+
+int yaffs_get_attribs(struct yaffs_obj *obj, struct iattr *attr)
+{
+       unsigned int valid = 0;
+
+       attr->ia_mode = obj->yst_mode;
+       valid |= ATTR_MODE;
+       attr->ia_uid = obj->yst_uid;
+       valid |= ATTR_UID;
+       attr->ia_gid = obj->yst_gid;
+       valid |= ATTR_GID;
+
+       Y_TIME_CONVERT(attr->ia_atime) = obj->yst_atime;
+       valid |= ATTR_ATIME;
+       Y_TIME_CONVERT(attr->ia_ctime) = obj->yst_ctime;
+       valid |= ATTR_CTIME;
+       Y_TIME_CONVERT(attr->ia_mtime) = obj->yst_mtime;
+       valid |= ATTR_MTIME;
+
+       attr->ia_size = yaffs_get_file_size(obj);
+       valid |= ATTR_SIZE;
+
+       attr->ia_valid = valid;
+
+       return YAFFS_OK;
+}
+
+
diff --git a/yaffs_attribs.h b/yaffs_attribs.h
new file mode 100644 (file)
index 0000000..c9a0867
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2010 Aleph One Ltd.
+ *   for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+#ifndef __YAFFS_ATTRIBS_H__
+#define __YAFFS_ATTRIBS_H__
+
+
+#include "yaffs_guts.h"
+
+
+void yaffs_load_attribs(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh);
+void yaffs_load_attribs_oh(struct yaffs_obj_hdr *oh, struct yaffs_obj *obj);
+void yaffs_attribs_init(struct yaffs_obj *obj, u32 gid, u32 uid, u32 rdev);
+void yaffs_load_current_time(struct yaffs_obj *obj, int do_a, int do_c);
+int yaffs_set_attribs(struct yaffs_obj *obj, struct iattr *attr);
+int yaffs_get_attribs(struct yaffs_obj *obj, struct iattr *attr);
+
+
+#endif
+
index cd1bb12..ce7ed7e 100644 (file)
@@ -33,6 +33,8 @@
 #include "yaffs_nameval.h"
 #include "yaffs_allocator.h"
 
+#include "yaffs_attribs.h"
+
 /* Note YAFFS_GC_GOOD_ENOUGH must be <= YAFFS_GC_PASSIVE_THRESHOLD */
 #define YAFFS_GC_GOOD_ENOUGH 2
 #define YAFFS_GC_PASSIVE_THRESHOLD 4
@@ -1366,23 +1368,13 @@ struct yaffs_obj *yaffs_new_obj(struct yaffs_dev *dev, int number,
                the_obj->obj_id = number;
                yaffs_hash_obj(the_obj);
                the_obj->variant_type = type;
-#ifdef CONFIG_YAFFS_WINCE
-               yfsd_win_file_time_now(the_obj->win_atime);
-               the_obj->win_ctime[0] = the_obj->win_mtime[0] =
-                   the_obj->win_atime[0];
-               the_obj->win_ctime[1] = the_obj->win_mtime[1] =
-                   the_obj->win_atime[1];
-
-#else
+               yaffs_load_current_time(the_obj,1,1);
 
-               the_obj->yst_atime = the_obj->yst_mtime =
-                   the_obj->yst_ctime = Y_CURRENT_TIME;
-#endif
                switch (type) {
                case YAFFS_OBJECT_TYPE_FILE:
                        the_obj->variant.file_variant.file_size = 0;
                        the_obj->variant.file_variant.scanned_size = 0;
-                       the_obj->variant.file_variant.shrink_size = 0xFFFFFFFF; /* max u32 */
+                       the_obj->variant.file_variant.shrink_size = ~0;/* max */
                        the_obj->variant.file_variant.top_level = 0;
                        the_obj->variant.file_variant.top = tn;
                        break;
@@ -1491,18 +1483,8 @@ static struct yaffs_obj *yaffs_create_obj(enum yaffs_obj_type type,
 
                in->yst_mode = mode;
 
-#ifdef CONFIG_YAFFS_WINCE
-               yfsd_win_file_time_now(in->win_atime);
-               in->win_ctime[0] = in->win_mtime[0] = in->win_atime[0];
-               in->win_ctime[1] = in->win_mtime[1] = in->win_atime[1];
+               yaffs_attribs_init(in, gid, uid, rdev);
 
-#else
-               in->yst_atime = in->yst_mtime = in->yst_ctime = Y_CURRENT_TIME;
-
-               in->yst_rdev = rdev;
-               in->yst_uid = uid;
-               in->yst_gid = gid;
-#endif
                in->n_data_chunks = 0;
 
                yaffs_set_obj_name(in, name);
@@ -1664,7 +1646,7 @@ int yaffs_rename_obj(struct yaffs_obj *old_dir, const YCHAR *old_name,
        dev = old_dir->my_dev;
 
 #ifdef CONFIG_YAFFS_CASE_INSENSITIVE
-       /* Special case for case insemsitive systems (eg. WinCE).
+       /* Special case for case insemsitive systems.
         * While look-up is case insensitive, the name isn't.
         * Therefore we might want to change x.txt to X.txt
        */
@@ -2945,21 +2927,8 @@ int yaffs_update_oh(struct yaffs_obj *in, const YCHAR *name, int force,
                oh->yst_mode = in->yst_mode;
                oh->shadows_obj = oh->inband_shadowed_obj_id = shadows;
 
-#ifdef CONFIG_YAFFS_WINCE
-               oh->win_atime[0] = in->win_atime[0];
-               oh->win_ctime[0] = in->win_ctime[0];
-               oh->win_mtime[0] = in->win_mtime[0];
-               oh->win_atime[1] = in->win_atime[1];
-               oh->win_ctime[1] = in->win_ctime[1];
-               oh->win_mtime[1] = in->win_mtime[1];
-#else
-               oh->yst_uid = in->yst_uid;
-               oh->yst_gid = in->yst_gid;
-               oh->yst_atime = in->yst_atime;
-               oh->yst_mtime = in->yst_mtime;
-               oh->yst_ctime = in->yst_ctime;
-               oh->yst_rdev = in->yst_rdev;
-#endif
+               yaffs_load_attribs_oh(oh,in);
+
                if (in->parent)
                        oh->parent_obj_id = in->parent->obj_id;
                else
@@ -3068,13 +3037,13 @@ int yaffs_update_oh(struct yaffs_obj *in, const YCHAR *name, int force,
 }
 
 /*------------------------ Short Operations Cache ----------------------------------------
- *   In many situations where there is no high level buffering (eg WinCE) a lot of
+ *   In many situations where there is no high level buffering  a lot of
  *   reads might be short sequential reads, and a lot of writes may be short
  *   sequential writes. eg. scanning/writing a jpeg file.
- *   In these cases, a short read/write cache can provide a huge perfomance benefit
- *   with dumb-as-a-rock code.
- *   In Linux, the page cache provides read buffering aand the short op cache provides write
- *   buffering.
+ *   In these cases, a short read/write cache can provide a huge perfomance
+ *   benefit with dumb-as-a-rock code.
+ *   In Linux, the page cache provides read buffering and the short op cache 
+ *   provides write buffering.
  *
  *   There are a limited number (~10) of cache chunks per device so that we don't
  *   need a very intelligent search.
@@ -3725,25 +3694,6 @@ int yaffs_resize_file(struct yaffs_obj *in, loff_t new_size)
        return YAFFS_OK;
 }
 
-loff_t yaffs_get_file_size(struct yaffs_obj *obj)
-{
-       YCHAR *alias = NULL;
-       obj = yaffs_get_equivalent_obj(obj);
-
-       switch (obj->variant_type) {
-       case YAFFS_OBJECT_TYPE_FILE:
-               return obj->variant.file_variant.file_size;
-       case YAFFS_OBJECT_TYPE_SYMLINK:
-               alias = obj->variant.symlink_variant.alias;
-               if(!alias)
-                       return 0;
-               return yaffs_strnlen(alias,YAFFS_MAX_ALIAS_LENGTH);
-       default:
-               return 0;
-       }
-}
-
-
 
 int yaffs_flush_file(struct yaffs_obj *in, int update_time, int data_sync)
 {
@@ -3753,15 +3703,8 @@ int yaffs_flush_file(struct yaffs_obj *in, int update_time, int data_sync)
                if(data_sync) /* Only sync data */
                        ret_val=YAFFS_OK;
                else {
-                       if (update_time) {
-#ifdef CONFIG_YAFFS_WINCE
-                               yfsd_win_file_time_now(in->win_mtime);
-#else
-
-                               in->yst_mtime = Y_CURRENT_TIME;
-
-#endif
-                       }
+                       if (update_time)
+                               yaffs_load_current_time(in,0,0);
 
                        ret_val = (yaffs_update_oh(in, NULL, 0, 0, 0, NULL) >=
                                0) ? YAFFS_OK : YAFFS_FAIL;
@@ -4264,22 +4207,7 @@ static void yaffs_check_obj_details_loaded(struct yaffs_obj *in)
                oh = (struct yaffs_obj_hdr *) chunk_data;
 
                in->yst_mode = oh->yst_mode;
-#ifdef CONFIG_YAFFS_WINCE
-               in->win_atime[0] = oh->win_atime[0];
-               in->win_ctime[0] = oh->win_ctime[0];
-               in->win_mtime[0] = oh->win_mtime[0];
-               in->win_atime[1] = oh->win_atime[1];
-               in->win_ctime[1] = oh->win_ctime[1];
-               in->win_mtime[1] = oh->win_mtime[1];
-#else
-               in->yst_uid = oh->yst_uid;
-               in->yst_gid = oh->yst_gid;
-               in->yst_atime = oh->yst_atime;
-               in->yst_mtime = oh->yst_mtime;
-               in->yst_ctime = oh->yst_ctime;
-               in->yst_rdev = oh->yst_rdev;
-
-#endif
+               yaffs_load_attribs(in, oh);
                yaffs_set_obj_name_from_oh(in, oh);
 
                if (in->variant_type == YAFFS_OBJECT_TYPE_SYMLINK) {
@@ -4316,22 +4244,21 @@ static void yaffs_update_parent(struct yaffs_obj *obj)
        struct yaffs_dev *dev;
        if(!obj)
                return;
-#ifndef CONFIG_YAFFS_WINCE
-
        dev = obj->my_dev;
        obj->dirty = 1;
-       obj->yst_mtime = obj->yst_ctime = Y_CURRENT_TIME;
+       yaffs_load_current_time(obj,0,1);
        if(dev->param.defered_dir_update){
                struct list_head *link = &obj->variant.dir_variant.dirty; 
        
                if(list_empty(link)){
                        list_add(link,&dev->dirty_dirs);
-                       T(YAFFS_TRACE_BACKGROUND, (TSTR("Added object %d to dirty directories" TENDSTR),obj->obj_id));
+                       T(YAFFS_TRACE_BACKGROUND, 
+                       (TSTR("Added object %d to dirty directories" TENDSTR),
+                       obj->obj_id));
                }
 
        } else
                yaffs_update_oh(obj, NULL, 0, 0, 0, NULL);
-#endif
 }
 
 void yaffs_update_dirty_dirs(struct yaffs_dev *dev)
@@ -4716,63 +4643,6 @@ YCHAR *yaffs_get_symlink_alias(struct yaffs_obj *obj)
                return yaffs_clone_str(_Y(""));
 }
 
-#ifndef CONFIG_YAFFS_WINCE
-
-int yaffs_set_attribs(struct yaffs_obj *obj, struct iattr *attr)
-{
-       unsigned int valid = attr->ia_valid;
-
-       if (valid & ATTR_MODE)
-               obj->yst_mode = attr->ia_mode;
-       if (valid & ATTR_UID)
-               obj->yst_uid = attr->ia_uid;
-       if (valid & ATTR_GID)
-               obj->yst_gid = attr->ia_gid;
-
-       if (valid & ATTR_ATIME)
-               obj->yst_atime = Y_TIME_CONVERT(attr->ia_atime);
-       if (valid & ATTR_CTIME)
-               obj->yst_ctime = Y_TIME_CONVERT(attr->ia_ctime);
-       if (valid & ATTR_MTIME)
-               obj->yst_mtime = Y_TIME_CONVERT(attr->ia_mtime);
-
-       if (valid & ATTR_SIZE)
-               yaffs_resize_file(obj, attr->ia_size);
-
-       yaffs_update_oh(obj, NULL, 1, 0, 0, NULL);
-
-       return YAFFS_OK;
-
-}
-int yaffs_get_attribs(struct yaffs_obj *obj, struct iattr *attr)
-{
-       unsigned int valid = 0;
-
-       attr->ia_mode = obj->yst_mode;
-       valid |= ATTR_MODE;
-       attr->ia_uid = obj->yst_uid;
-       valid |= ATTR_UID;
-       attr->ia_gid = obj->yst_gid;
-       valid |= ATTR_GID;
-
-       Y_TIME_CONVERT(attr->ia_atime) = obj->yst_atime;
-       valid |= ATTR_ATIME;
-       Y_TIME_CONVERT(attr->ia_ctime) = obj->yst_ctime;
-       valid |= ATTR_CTIME;
-       Y_TIME_CONVERT(attr->ia_mtime) = obj->yst_mtime;
-       valid |= ATTR_MTIME;
-
-       attr->ia_size = yaffs_get_file_size(obj);
-       valid |= ATTR_SIZE;
-
-       attr->ia_valid = valid;
-
-       return YAFFS_OK;
-}
-
-#endif
-
-
 static int yaffs_do_xattrib_mod(struct yaffs_obj *obj, int set, const YCHAR *name, const void *value, int size, int flags)
 {
        struct yaffs_xattr_mod xmod;
index 13a2e87..fe6e934 100644 (file)
@@ -306,15 +306,11 @@ struct yaffs_obj_hdr {
        /* The following apply to directories, files, symlinks - not hard links */
        u32 yst_mode;         /* protection */
 
-#ifdef CONFIG_YAFFS_WINCE
-       u32 not_for_wince[5];
-#else
        u32 yst_uid;
        u32 yst_gid;
        u32 yst_atime;
        u32 yst_mtime;
        u32 yst_ctime;
-#endif
 
        /* File size  applies to files only */
        int file_size;
@@ -327,14 +323,10 @@ struct yaffs_obj_hdr {
 
        u32 yst_rdev;           /* device stuff for block and char devices (major/min) */
 
-#ifdef CONFIG_YAFFS_WINCE
        u32 win_ctime[2];
        u32 win_atime[2];
        u32 win_mtime[2];
-#else
-       u32 room_to_grow[6];
 
-#endif
        u32 inband_shadowed_obj_id;
        u32 inband_is_shrink;
 
@@ -829,9 +821,6 @@ int yaffs_get_obj_inode(struct yaffs_obj *obj);
 unsigned yaffs_get_obj_type(struct yaffs_obj *obj);
 int yaffs_get_obj_link_count(struct yaffs_obj *obj);
 
-int yaffs_set_attribs(struct yaffs_obj *obj, struct iattr *attr);
-int yaffs_get_attribs(struct yaffs_obj *obj, struct iattr *attr);
-
 /* File operations */
 int yaffs_file_rd(struct yaffs_obj *obj, u8 *buffer, loff_t offset,
                                int n_bytes);
@@ -882,11 +871,6 @@ int yaffs_remove_xattrib(struct yaffs_obj *obj, const YCHAR *name);
 struct yaffs_obj *yaffs_root(struct yaffs_dev *dev);
 struct yaffs_obj *yaffs_lost_n_found(struct yaffs_dev *dev);
 
-#ifdef CONFIG_YAFFS_WINCE
-/* CONFIG_YAFFS_WINCE special stuff */
-void yfsd_win_file_time_now(u32 target[2]);
-#endif
-
 void yaffs_handle_defered_free(struct yaffs_obj *obj);
 
 void yaffs_update_dirty_dirs(struct yaffs_dev *dev);
diff --git a/yaffs_mtdif1_multi.c b/yaffs_mtdif1_multi.c
new file mode 100644 (file)
index 0000000..ac0f00c
--- /dev/null
@@ -0,0 +1,362 @@
+/*
+ * YAFFS: Yet another FFS. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2010 Aleph One Ltd.
+ *   for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * This module provides the interface between yaffs_nand.c and the
+ * MTD API.  This version is used when the MTD interface supports the
+ * 'mtd_oob_ops' style calls to read_oob and write_oob, circa 2.6.17,
+ * and we have small-page NAND device.
+ *
+ * These functions are invoked via function pointers in yaffs_nand.c.
+ * This replaces functionality provided by functions in yaffs_mtdif.c
+ * and the yaffs_tags compatability functions in yaffs_tagscompat.c that are
+ * called in yaffs_mtdif.c when the function pointers are NULL.
+ * We assume the MTD layer is performing ECC (use_nand_ecc is true).
+ */
+
+#include "yportenv.h"
+#include "yaffs_trace.h"
+#include "yaffs_guts.h"
+#include "yaffs_packedtags1.h"
+#include "yaffs_tagscompat.h"  /* for yaffs_calc_tags_ecc */
+#include "yaffs_linux.h"
+
+#include "linux/kernel.h"
+#include "linux/version.h"
+#include "linux/types.h"
+#include "linux/mtd/mtd.h"
+
+/* Don't compile this module if we don't have MTD's mtd_oob_ops interface */
+#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17))
+
+#ifndef CONFIG_YAFFS_9BYTE_TAGS
+# define YTAG1_SIZE 8
+#else
+# define YTAG1_SIZE 9
+#endif
+
+#if 0
+/* Use the following nand_ecclayout with MTD when using
+ * CONFIG_YAFFS_9BYTE_TAGS and the older on-NAND tags layout.
+ * If you have existing Yaffs images and the byte order differs from this,
+ * adjust 'oobfree' to match your existing Yaffs data.
+ *
+ * This nand_ecclayout scatters/gathers to/from the old-yaffs layout with the
+ * page_status byte (at NAND spare offset 4) scattered/gathered from/to
+ * the 9th byte.
+ *
+ * Old-style on-NAND format: T0,T1,T2,T3,P,B,T4,T5,E0,E1,E2,T6,T7,E3,E4,E5
+ * We have/need packed_tags1 plus page_status: T0,T1,T2,T3,T4,T5,T6,T7,P
+ * where Tn are the tag bytes, En are MTD's ECC bytes, P is the page_status
+ * byte and B is the small-page bad-block indicator byte.
+ */
+static struct nand_ecclayout nand_oob_16 = {
+       .eccbytes = 6,
+       .eccpos = { 8, 9, 10, 13, 14, 15 },
+       .oobavail = 9,
+       .oobfree = { { 0, 4 }, { 6, 2 }, { 11, 2 }, { 4, 1 } }
+};
+#endif
+
+/* Write a chunk (page) of data to NAND.
+ *
+ * Caller always provides ExtendedTags data which are converted to a more
+ * compact (packed) form for storage in NAND.  A mini-ECC runs over the
+ * contents of the tags meta-data; used to valid the tags when read.
+ *
+ *  - Pack ExtendedTags to packed_tags1 form
+ *  - Compute mini-ECC for packed_tags1
+ *  - Write data and packed tags to NAND.
+ *
+ * Note: Due to the use of the packed_tags1 meta-data which does not include
+ * a full sequence number (as found in the larger packed_tags2 form) it is
+ * necessary for Yaffs to re-write a chunk/page (just once) to mark it as
+ * discarded and dirty.  This is not ideal: newer NAND parts are supposed
+ * to be written just once.  When Yaffs performs this operation, this
+ * function is called with a NULL data pointer -- calling MTD write_oob
+ * without data is valid usage (2.6.17).
+ *
+ * Any underlying MTD error results in YAFFS_FAIL.
+ * Returns YAFFS_OK or YAFFS_FAIL.
+ */
+int nandmtd1_write_chunk_tags(struct yaffs_dev *dev,
+       int nand_chunk, const u8 *data, const struct yaffs_ext_tags *etags)
+{
+       struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
+       int chunk_bytes = dev->data_bytes_per_chunk;
+       loff_t addr = ((loff_t)nand_chunk) * chunk_bytes;
+       struct mtd_oob_ops ops;
+       struct yaffs_packed_tags1 pt1;
+       int retval;
+
+       /* we assume that packed_tags1 and struct yaffs_tags are compatible */
+       compile_time_assertion(sizeof(struct yaffs_packed_tags1) == 12);
+       compile_time_assertion(sizeof(struct yaffs_tags) == 8);
+
+       yaffs_pack_tags1(&pt1, etags);
+       yaffs_calc_tags_ecc((struct yaffs_tags *)&pt1);
+
+       /* When deleting a chunk, the upper layer provides only skeletal
+        * etags, one with is_deleted set.  However, we need to update the
+        * tags, not erase them completely.  So we use the NAND write property
+        * that only zeroed-bits stick and set tag bytes to all-ones and
+        * zero just the (not) deleted bit.
+        */
+#ifndef CONFIG_YAFFS_9BYTE_TAGS
+       if (etags->is_deleted) {
+               memset(&pt1, 0xff, 8);
+               /* clear delete status bit to indicate deleted */
+               pt1.deleted = 0;
+       }
+#else
+       ((u8 *)&pt1)[8] = 0xff;
+       if (etags->is_deleted) {
+               memset(&pt1, 0xff, 8);
+               /* zero page_status byte to indicate deleted */
+               ((u8 *)&pt1)[8] = 0;
+       }
+#endif
+
+       memset(&ops, 0, sizeof(ops));
+       ops.mode = MTD_OOB_AUTO;
+       ops.len = (data) ? chunk_bytes : 0;
+       ops.ooblen = YTAG1_SIZE;
+       ops.datbuf = (u8 *)data;
+       ops.oobbuf = (u8 *)&pt1;
+
+       retval = mtd->write_oob(mtd, addr, &ops);
+       if (retval) {
+               T(YAFFS_TRACE_MTD,
+                       (TSTR("write_oob failed, chunk %d, mtd error %d"TENDSTR),
+                       nand_chunk, retval));
+       }
+       return retval ? YAFFS_FAIL : YAFFS_OK;
+}
+
+/* Return with empty ExtendedTags but add ecc_result.
+ */
+static int rettags(struct yaffs_ext_tags *etags, int ecc_result, int retval)
+{
+       if (etags) {
+               memset(etags, 0, sizeof(*etags));
+               etags->ecc_result = ecc_result;
+       }
+       return retval;
+}
+
+/* Read a chunk (page) from NAND.
+ *
+ * Caller expects ExtendedTags data to be usable even on error; that is,
+ * all members except ecc_result and block_bad are zeroed.
+ *
+ *  - Check ECC results for data (if applicable)
+ *  - Check for blank/erased block (return empty ExtendedTags if blank)
+ *  - Check the packed_tags1 mini-ECC (correct if necessary/possible)
+ *  - Convert packed_tags1 to ExtendedTags
+ *  - Update ecc_result and block_bad members to refect state.
+ *
+ * Returns YAFFS_OK or YAFFS_FAIL.
+ */
+int nandmtd1_read_chunk_tags(struct yaffs_dev *dev,
+       int nand_chunk, u8 *data, struct yaffs_ext_tags *etags)
+{
+       struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
+       int chunk_bytes = dev->data_bytes_per_chunk;
+       loff_t addr = ((loff_t)nand_chunk) * chunk_bytes;
+       int eccres = YAFFS_ECC_RESULT_NO_ERROR;
+       struct mtd_oob_ops ops;
+       struct yaffs_packed_tags1 pt1;
+       int retval;
+       int deleted;
+
+       memset(&ops, 0, sizeof(ops));
+       ops.mode = MTD_OOB_AUTO;
+       ops.len = (data) ? chunk_bytes : 0;
+       ops.ooblen = YTAG1_SIZE;
+       ops.datbuf = data;
+       ops.oobbuf = (u8 *)&pt1;
+
+#if (MTD_VERSION_CODE < MTD_VERSION(2, 6, 20))
+       /* In MTD 2.6.18 to 2.6.19 nand_base.c:nand_do_read_oob() has a bug;
+        * help it out with ops.len = ops.ooblen when ops.datbuf == NULL.
+        */
+       ops.len = (ops.datbuf) ? ops.len : ops.ooblen;
+#endif
+       /* Read page and oob using MTD.
+        * Check status and determine ECC result.
+        */
+       retval = mtd->read_oob(mtd, addr, &ops);
+       if (retval) {
+               T(YAFFS_TRACE_MTD,
+                       (TSTR("read_oob failed, chunk %d, mtd error %d"TENDSTR),
+                       nand_chunk, retval));
+       }
+
+       switch (retval) {
+       case 0:
+               /* no error */
+               break;
+
+       case -EUCLEAN:
+               /* MTD's ECC fixed the data */
+               eccres = YAFFS_ECC_RESULT_FIXED;
+               dev->n_ecc_fixed++;
+               break;
+
+       case -EBADMSG:
+               /* MTD's ECC could not fix the data */
+               dev->n_ecc_unfixed++;
+               /* fall into... */
+       default:
+               rettags(etags, YAFFS_ECC_RESULT_UNFIXED, 0);
+               etags->block_bad = (mtd->block_isbad)(mtd, addr);
+               return YAFFS_FAIL;
+       }
+
+       /* Check for a blank/erased chunk.
+        */
+       if (yaffs_check_ff((u8 *)&pt1, 8)) {
+               /* when blank, upper layers want ecc_result to be <= NO_ERROR */
+               return rettags(etags, YAFFS_ECC_RESULT_NO_ERROR, YAFFS_OK);
+       }
+
+#ifndef CONFIG_YAFFS_9BYTE_TAGS
+       /* Read deleted status (bit) then return it to it's non-deleted
+        * state before performing tags mini-ECC check. pt1.deleted is
+        * inverted.
+        */
+       deleted = !pt1.deleted;
+       pt1.deleted = 1;
+#else
+       deleted = (yaffs_count_bits(((u8 *)&pt1)[8]) < 7);
+#endif
+
+       /* Check the packed tags mini-ECC and correct if necessary/possible.
+        */
+       retval = yaffs_check_tags_ecc((struct yaffs_tags *)&pt1);
+       switch (retval) {
+       case 0:
+               /* no tags error, use MTD result */
+               break;
+       case 1:
+               /* recovered tags-ECC error */
+               dev->n_tags_ecc_fixed++;
+               if (eccres == YAFFS_ECC_RESULT_NO_ERROR)
+                       eccres = YAFFS_ECC_RESULT_FIXED;
+               break;
+       default:
+               /* unrecovered tags-ECC error */
+               dev->n_tags_ecc_unfixed++;
+               return rettags(etags, YAFFS_ECC_RESULT_UNFIXED, YAFFS_FAIL);
+       }
+
+       /* Unpack the tags to extended form and set ECC result.
+        * [set should_be_ff just to keep yaffs_unpack_tags1 happy]
+        */
+       pt1.should_be_ff = 0xFFFFFFFF;
+       yaffs_unpack_tags1(etags, &pt1);
+       etags->ecc_result = eccres;
+
+       /* Set deleted state */
+       etags->is_deleted = deleted;
+       return YAFFS_OK;
+}
+
+/* Mark a block bad.
+ *
+ * This is a persistant state.
+ * Use of this function should be rare.
+ *
+ * Returns YAFFS_OK or YAFFS_FAIL.
+ */
+int nandmtd1_mark_block_bad(struct yaffs_dev *dev, int block_no)
+{
+       struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
+       int blocksize = dev->param.chunks_per_block * dev->data_bytes_per_chunk;
+       int retval;
+
+       T(YAFFS_TRACE_BAD_BLOCKS,(TSTR("marking block %d bad"TENDSTR), block_no));
+
+       retval = mtd->block_markbad(mtd, (loff_t)blocksize * block_no);
+       return (retval) ? YAFFS_FAIL : YAFFS_OK;
+}
+
+/* Check any MTD prerequists.
+ *
+ * Returns YAFFS_OK or YAFFS_FAIL.
+ */
+static int nandmtd1_test_prerequists(struct mtd_info *mtd)
+{
+       /* 2.6.18 has mtd->ecclayout->oobavail */
+       /* 2.6.21 has mtd->ecclayout->oobavail and mtd->oobavail */
+       int oobavail = mtd->ecclayout->oobavail;
+
+       if (oobavail < YTAG1_SIZE) {
+               T(YAFFS_TRACE_ERROR,
+                       (TSTR("mtd device has only %d bytes for tags, need %d"TENDSTR),
+                       oobavail, YTAG1_SIZE));
+               return YAFFS_FAIL;
+       }
+       return YAFFS_OK;
+}
+
+/* Query for the current state of a specific block.
+ *
+ * Examine the tags of the first chunk of the block and return the state:
+ *  - YAFFS_BLOCK_STATE_DEAD, the block is marked bad
+ *  - YAFFS_BLOCK_STATE_NEEDS_SCANNING, the block is in use
+ *  - YAFFS_BLOCK_STATE_EMPTY, the block is clean
+ *
+ * Always returns YAFFS_OK.
+ */
+int nandmtd1_query_block(struct yaffs_dev *dev, int block_no,
+       enum yaffs_block_state *state_ptr, u32 *seq_ptr)
+{
+       struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
+       int chunk_num = block_no * dev->param.chunks_per_block;
+       loff_t addr = (loff_t)chunk_num * dev->data_bytes_per_chunk;
+       struct yaffs_ext_tags etags;
+       int state = YAFFS_BLOCK_STATE_DEAD;
+       int seqnum = 0;
+       int retval;
+
+       /* We don't yet have a good place to test for MTD config prerequists.
+        * Do it here as we are called during the initial scan.
+        */
+       if (nandmtd1_test_prerequists(mtd) != YAFFS_OK)
+               return YAFFS_FAIL;
+
+       retval = nandmtd1_read_chunk_tags(dev, chunk_num, NULL, &etags);
+       etags.block_bad = (mtd->block_isbad)(mtd, addr);
+       if (etags.block_bad) {
+               T(YAFFS_TRACE_BAD_BLOCKS,
+                       (TSTR("block %d is marked bad"TENDSTR), block_no));
+               state = YAFFS_BLOCK_STATE_DEAD;
+       } else if (etags.ecc_result != YAFFS_ECC_RESULT_NO_ERROR) {
+               /* bad tags, need to look more closely */
+               state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
+       } else if (etags.chunk_used) {
+               state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
+               seqnum = etags.seq_number;
+       } else {
+               state = YAFFS_BLOCK_STATE_EMPTY;
+       }
+
+       *state_ptr = state;
+       *seq_ptr = seqnum;
+
+       /* query always succeeds */
+       return YAFFS_OK;
+}
+
+#endif /*MTD_VERSION*/
diff --git a/yaffs_mtdif2_multi.c b/yaffs_mtdif2_multi.c
new file mode 100644 (file)
index 0000000..04fb39d
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2010 Aleph One Ltd.
+ *   for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* mtd interface for YAFFS2 */
+
+#include "yportenv.h"
+#include "yaffs_trace.h"
+
+#include "yaffs_mtdif2.h"
+
+#include "linux/mtd/mtd.h"
+#include "linux/types.h"
+#include "linux/time.h"
+
+#include "yaffs_packedtags2.h"
+
+#include "yaffs_linux.h"
+
+/* NB For use with inband tags....
+ * We assume that the data buffer is of size total_bytes_per_chunk so that we can also
+ * use it to load the tags.
+ */
+int nandmtd2_write_chunk_tags(struct yaffs_dev *dev, int nand_chunk,
+                                     const u8 *data,
+                                     const struct yaffs_ext_tags *tags)
+{
+       struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
+#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17))
+       struct mtd_oob_ops ops;
+#else
+       size_t dummy;
+#endif
+       int retval = 0;
+
+       loff_t addr;
+
+       struct yaffs_packed_tags2 pt;
+
+       int packed_tags_size = dev->param.no_tags_ecc ? sizeof(pt.t) : sizeof(pt);
+       void * packed_tags_ptr = dev->param.no_tags_ecc ? (void *) &pt.t : (void *)&pt;
+
+       T(YAFFS_TRACE_MTD,
+         (TSTR
+          ("nandmtd2_write_chunk_tags chunk %d data %p tags %p"
+           TENDSTR), nand_chunk, data, tags));
+
+
+       addr  = ((loff_t) nand_chunk) * dev->param.total_bytes_per_chunk;
+
+       /* For yaffs2 writing there must be both data and tags.
+        * If we're using inband tags, then the tags are stuffed into
+        * the end of the data buffer.
+        */
+       if (!data || !tags)
+               BUG();
+       else if (dev->param.inband_tags) {
+               struct yaffs_packed_tags2_tags_only *pt2tp;
+               pt2tp = (struct yaffs_packed_tags2_tags_only *)(data + dev->data_bytes_per_chunk);
+               yaffs_pack_tags2_tags_only(pt2tp, tags);
+       } else
+               yaffs_pack_tags2(&pt, tags, !dev->param.no_tags_ecc);
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
+       ops.mode = MTD_OOB_AUTO;
+       ops.ooblen = (dev->param.inband_tags) ? 0 : packed_tags_size;
+       ops.len = dev->param.total_bytes_per_chunk;
+       ops.ooboffs = 0;
+       ops.datbuf = (u8 *)data;
+       ops.oobbuf = (dev->param.inband_tags) ? NULL : packed_tags_ptr;
+       retval = mtd->write_oob(mtd, addr, &ops);
+
+#else
+       if (!dev->param.inband_tags) {
+               retval =
+                   mtd->write_ecc(mtd, addr, dev->data_bytes_per_chunk,
+                                  &dummy, data, (u8 *) packed_tags_ptr, NULL);
+       } else {
+               retval =
+                   mtd->write(mtd, addr, dev->param.total_bytes_per_chunk, &dummy,
+                              data);
+       }
+#endif
+
+       if (retval == 0)
+               return YAFFS_OK;
+       else
+               return YAFFS_FAIL;
+}
+
+int nandmtd2_read_chunk_tags(struct yaffs_dev *dev, int nand_chunk,
+                                      u8 *data, struct yaffs_ext_tags *tags)
+{
+       struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
+#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17))
+       struct mtd_oob_ops ops;
+#endif
+       size_t dummy;
+       int retval = 0;
+       int local_data = 0;
+
+       loff_t addr = ((loff_t) nand_chunk) * dev->param.total_bytes_per_chunk;
+
+       struct yaffs_packed_tags2 pt;
+
+       int packed_tags_size = dev->param.no_tags_ecc ? sizeof(pt.t) : sizeof(pt);
+       void * packed_tags_ptr = dev->param.no_tags_ecc ? (void *) &pt.t: (void *)&pt;
+
+       T(YAFFS_TRACE_MTD,
+         (TSTR
+          ("nandmtd2_read_chunk_tags chunk %d data %p tags %p"
+           TENDSTR), nand_chunk, data, tags));
+
+       if (dev->param.inband_tags) {
+
+               if (!data) {
+                       local_data = 1;
+                       data = yaffs_get_temp_buffer(dev, __LINE__);
+               }
+
+
+       }
+
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
+       if (dev->param.inband_tags || (data && !tags))
+               retval = mtd->read(mtd, addr, dev->param.total_bytes_per_chunk,
+                               &dummy, data);
+       else if (tags) {
+               ops.mode = MTD_OOB_AUTO;
+               ops.ooblen = packed_tags_size;
+               ops.len = data ? dev->data_bytes_per_chunk : packed_tags_size;
+               ops.ooboffs = 0;
+               ops.datbuf = data;
+               ops.oobbuf = yaffs_dev_to_lc(dev)->spare_buffer;
+               retval = mtd->read_oob(mtd, addr, &ops);
+       }
+#else
+       if (!dev->param.inband_tags && data && tags) {
+
+               retval = mtd->read_ecc(mtd, addr, dev->data_bytes_per_chunk,
+                                         &dummy, data, dev->spare_buffer,
+                                         NULL);
+       } else {
+               if (data)
+                       retval =
+                           mtd->read(mtd, addr, dev->data_bytes_per_chunk, &dummy,
+                                     data);
+               if (!dev->param.inband_tags && tags)
+                       retval =
+                           mtd->read_oob(mtd, addr, mtd->oobsize, &dummy,
+                                         dev->spare_buffer);
+       }
+#endif
+
+
+       if (dev->param.inband_tags) {
+               if (tags) {
+                       struct yaffs_packed_tags2_tags_only *pt2tp;
+                       pt2tp = (struct yaffs_packed_tags2_tags_only *)&data[dev->data_bytes_per_chunk];
+                       yaffs_unpack_tags2_tags_only(tags, pt2tp);
+               }
+       } else {
+               if (tags) {
+                       memcpy(packed_tags_ptr, yaffs_dev_to_lc(dev)->spare_buffer, packed_tags_size);
+                       yaffs_unpack_tags2(tags, &pt, !dev->param.no_tags_ecc);
+               }
+       }
+
+       if (local_data)
+               yaffs_release_temp_buffer(dev, data, __LINE__);
+
+       if (tags && retval == -EBADMSG && tags->ecc_result == YAFFS_ECC_RESULT_NO_ERROR) {
+               tags->ecc_result = YAFFS_ECC_RESULT_UNFIXED;
+               dev->n_ecc_unfixed++;
+       }
+       if(tags && retval == -EUCLEAN && tags->ecc_result == YAFFS_ECC_RESULT_NO_ERROR) {
+               tags->ecc_result = YAFFS_ECC_RESULT_FIXED;
+               dev->n_ecc_fixed++;
+       }
+       if (retval == 0)
+               return YAFFS_OK;
+       else
+               return YAFFS_FAIL;
+}
+
+int nandmtd2_mark_block_bad(struct yaffs_dev *dev, int block_no)
+{
+       struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
+       int retval;
+       T(YAFFS_TRACE_MTD,
+         (TSTR("nandmtd2_mark_block_bad %d" TENDSTR), block_no));
+
+       retval =
+           mtd->block_markbad(mtd,
+                              block_no * dev->param.chunks_per_block *
+                              dev->param.total_bytes_per_chunk);
+
+       if (retval == 0)
+               return YAFFS_OK;
+       else
+               return YAFFS_FAIL;
+
+}
+
+int nandmtd2_query_block(struct yaffs_dev *dev, int block_no,
+                           enum yaffs_block_state *state, u32 *seq_number)
+{
+       struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
+       int retval;
+
+       T(YAFFS_TRACE_MTD,
+         (TSTR("nandmtd2_query_block %d" TENDSTR), block_no));
+       retval =
+           mtd->block_isbad(mtd,
+                            block_no * dev->param.chunks_per_block *
+                            dev->param.total_bytes_per_chunk);
+
+       if (retval) {
+               T(YAFFS_TRACE_MTD, (TSTR("block is bad" TENDSTR)));
+
+               *state = YAFFS_BLOCK_STATE_DEAD;
+               *seq_number = 0;
+       } else {
+               struct yaffs_ext_tags t;
+               nandmtd2_read_chunk_tags(dev, block_no *
+                                                  dev->param.chunks_per_block, NULL,
+                                                  &t);
+
+               if (t.chunk_used) {
+                       *seq_number = t.seq_number;
+                       *state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
+               } else {
+                       *seq_number = 0;
+                       *state = YAFFS_BLOCK_STATE_EMPTY;
+               }
+       }
+       T(YAFFS_TRACE_MTD,
+         (TSTR("block is bad seq %d state %d" TENDSTR), *seq_number,
+          *state));
+
+       if (retval == 0)
+               return YAFFS_OK;
+       else
+               return YAFFS_FAIL;
+}
+
index fa83cab..6e2f8f8 100644 (file)
@@ -163,6 +163,7 @@ static uint32_t YCALCBLOCKS(uint64_t partition_size, uint32_t block_size)
 #include "yportenv.h"
 #include "yaffs_trace.h"
 #include "yaffs_guts.h"
+#include "yaffs_attribs.h"
 
 #include "yaffs_linux.h"
 
index cb5968f..aa1c15e 100644 (file)
@@ -86,6 +86,7 @@ static uint32_t YCALCBLOCKS(uint64_t partition_size, uint32_t block_size)
 #include "yportenv.h"
 #include "yaffs_trace.h"
 #include "yaffs_guts.h"
+#include "yaffs_attribs.h"
 
 #include "yaffs_linux.h"
 
index 3816962..059d125 100644 (file)
@@ -17,7 +17,7 @@
 #include "yaffs_bitmap.h"
 #include "yaffs_getblockinfo.h"
 #include "yaffs_nand.h"
-
+#include "yaffs_attribs.h"
 
 int yaffs1_scan(struct yaffs_dev *dev)
 {
@@ -259,21 +259,7 @@ int yaffs1_scan(struct yaffs_dev *dev)
                                        in->variant_type = oh->type;
 
                                        in->yst_mode = oh->yst_mode;
-#ifdef CONFIG_YAFFS_WINCE
-                                       in->win_atime[0] = oh->win_atime[0];
-                                       in->win_ctime[0] = oh->win_ctime[0];
-                                       in->win_mtime[0] = oh->win_mtime[0];
-                                       in->win_atime[1] = oh->win_atime[1];
-                                       in->win_ctime[1] = oh->win_ctime[1];
-                                       in->win_mtime[1] = oh->win_mtime[1];
-#else
-                                       in->yst_uid = oh->yst_uid;
-                                       in->yst_gid = oh->yst_gid;
-                                       in->yst_atime = oh->yst_atime;
-                                       in->yst_mtime = oh->yst_mtime;
-                                       in->yst_ctime = oh->yst_ctime;
-                                       in->yst_rdev = oh->yst_rdev;
-#endif
+                                       yaffs_load_attribs(in, oh);
                                        in->hdr_chunk = chunk;
                                        in->serial = tags.serial_number;
 
@@ -284,21 +270,7 @@ int yaffs1_scan(struct yaffs_dev *dev)
                                        in->variant_type = oh->type;
 
                                        in->yst_mode = oh->yst_mode;
-#ifdef CONFIG_YAFFS_WINCE
-                                       in->win_atime[0] = oh->win_atime[0];
-                                       in->win_ctime[0] = oh->win_ctime[0];
-                                       in->win_mtime[0] = oh->win_mtime[0];
-                                       in->win_atime[1] = oh->win_atime[1];
-                                       in->win_ctime[1] = oh->win_ctime[1];
-                                       in->win_mtime[1] = oh->win_mtime[1];
-#else
-                                       in->yst_uid = oh->yst_uid;
-                                       in->yst_gid = oh->yst_gid;
-                                       in->yst_atime = oh->yst_atime;
-                                       in->yst_mtime = oh->yst_mtime;
-                                       in->yst_ctime = oh->yst_ctime;
-                                       in->yst_rdev = oh->yst_rdev;
-#endif
+                                       yaffs_load_attribs(in, oh);
                                        in->hdr_chunk = chunk;
                                        in->serial = tags.serial_number;
 
index d5b167f..debb56d 100644 (file)
@@ -20,6 +20,7 @@
 #include "yaffs_nand.h"
 #include "yaffs_getblockinfo.h"
 #include "yaffs_verify.h"
+#include "yaffs_attribs.h"
 
 /*
  * Checkpoints are really no benefit on very small partitions.
@@ -1318,24 +1319,8 @@ int yaffs2_scan_backwards(struct yaffs_dev *dev)
                                        if (oh) {
 
                                                in->yst_mode = oh->yst_mode;
-#ifdef CONFIG_YAFFS_WINCE
-                                               in->win_atime[0] = oh->win_atime[0];
-                                               in->win_ctime[0] = oh->win_ctime[0];
-                                               in->win_mtime[0] = oh->win_mtime[0];
-                                               in->win_atime[1] = oh->win_atime[1];
-                                               in->win_ctime[1] = oh->win_ctime[1];
-                                               in->win_mtime[1] = oh->win_mtime[1];
-#else
-                                               in->yst_uid = oh->yst_uid;
-                                               in->yst_gid = oh->yst_gid;
-                                               in->yst_atime = oh->yst_atime;
-                                               in->yst_mtime = oh->yst_mtime;
-                                               in->yst_ctime = oh->yst_ctime;
-                                               in->yst_rdev = oh->yst_rdev;
-
+                                               yaffs_load_attribs(in, oh);
                                                in->lazy_loaded = 0;
-
-#endif
                                        } else
                                                in->lazy_loaded = 1;
 
@@ -1351,21 +1336,7 @@ int yaffs2_scan_backwards(struct yaffs_dev *dev)
                                                in->variant_type = oh->type;
 
                                                in->yst_mode = oh->yst_mode;
-#ifdef CONFIG_YAFFS_WINCE
-                                               in->win_atime[0] = oh->win_atime[0];
-                                               in->win_ctime[0] = oh->win_ctime[0];
-                                               in->win_mtime[0] = oh->win_mtime[0];
-                                               in->win_atime[1] = oh->win_atime[1];
-                                               in->win_ctime[1] = oh->win_ctime[1];
-                                               in->win_mtime[1] = oh->win_mtime[1];
-#else
-                                               in->yst_uid = oh->yst_uid;
-                                               in->yst_gid = oh->yst_gid;
-                                               in->yst_atime = oh->yst_atime;
-                                               in->yst_mtime = oh->yst_mtime;
-                                               in->yst_ctime = oh->yst_ctime;
-                                               in->yst_rdev = oh->yst_rdev;
-#endif
+                                               yaffs_load_attribs(in, oh);
 
                                                if (oh->shadows_obj > 0)
                                                        yaffs_handle_shadowed_obj(dev,
diff --git a/yportenv.h b/yportenv.h
new file mode 120000 (symlink)
index 0000000..b21fbc6
--- /dev/null
@@ -0,0 +1 @@
+yportenv_multi.h
\ No newline at end of file