Merge branch 'driver-refactoring' into new-driver-refactoring
authorCharles Manning <cdhmanning@gmail.com>
Tue, 2 Oct 2012 02:41:32 +0000 (15:41 +1300)
committerCharles Manning <cdhmanning@gmail.com>
Tue, 2 Oct 2012 02:41:32 +0000 (15:41 +1300)
1  2 
direct/test-framework/basic-tests/dtest.c
direct/yaffsfs.c
yaffs_guts.c
yaffs_guts.h

index 3cd13abe5593d7c9d6df12b9125e27c7f6342725,153d274d3a54db1db8b2cf0764faf9c099840674..3cd13abe5593d7c9d6df12b9125e27c7f6342725
@@@ -3042,70 -3042,6 +3042,70 @@@ void large_file_test(const char *mountp
  }
  
  
 +int  mk_dir(const char *mp, const char *name)
 +{
 +      char full_name[100];
 +
 +      sprintf(full_name, "%s/%s", mp, name);
 +
 +      return yaffs_mkdir(full_name, S_IREAD| S_IWRITE);
 +}
 +
 +int  mk_file(const char *mp, const char *name)
 +{
 +      char full_name[100];
 +      int h;
 +
 +      sprintf(full_name, "%s/%s", mp, name);
 +
 +      h = yaffs_open(full_name, O_RDWR | O_CREAT | O_TRUNC, S_IREAD| S_IWRITE);
 +
 +      yaffs_write(h, name, strlen(name));
 +
 +      yaffs_close(h);
 +      return 0;
 +}
 +
 +void xx_test(const char *mountpt)
 +{
 +      char xx_buffer[1000];
 +
 +      yaffs_start_up();
 +
 +      yaffs_format(mountpt,0,0,0);
 +
 +      yaffs_mount(mountpt);
 +      printf("mounted\n");
 +      dumpDir(mountpt);
 +
 +      printf("create files\n");
 +
 +      mk_dir(mountpt, "foo");
 +      mk_file(mountpt, "foo/f1");
 +      mk_file(mountpt, "foo/f2");
 +      mk_file(mountpt, "foo/f3");
 +      mk_file(mountpt, "foo/f4");
 +      dump_directory_tree(mountpt);
 +
 +      printf("unmount and remount\n");
 +
 +      /* Unmount/remount */
 +      yaffs_unmount(mountpt);
 +      yaffs_mount(mountpt);
 +      dump_directory_tree(mountpt);
 +}
 +
 +void yy_test(const char *mountpt)
 +{
 +      char xx_buffer[1000];
 +
 +      yaffs_start_up();
 +
 +      yaffs_mount(mountpt);
 +      dump_directory_tree(mountpt);
 +}
 +
 +
  void readdir_test(const char *mountpt)
  {
        char xx_buffer[1000];
  
  }
  
 +void format_test(const char *mountpt)
 +{
 +      int ret;
 +
 +      yaffs_start_up();
 +
 +      ret = yaffs_format(mountpt, 0, 0, 0);
 +      printf("yaffs_format(...,0, 0, 0) of unmounted returned %d\n", ret);
 +
 +      yaffs_mount(mountpt);
 +
 +      ret = yaffs_format(mountpt, 0, 0, 0);
 +      printf("yaffs_format(...,0, 0, 0) of mounted returned %d\n", ret);
 +
 +      ret = yaffs_format(mountpt, 1, 0, 0);
 +      printf("yaffs_format(...,1, 0, 0) of mounted returned %d\n", ret);
 +
 +      ret = yaffs_mount(mountpt);
 +      printf("mount should return 0 returned %d\n", ret);
 +
 +      ret = yaffs_format(mountpt, 1, 0, 1);
 +      printf("yaffs_format(...,1, 0, 1) of mounted returned %d\n", ret);
 +
 +      ret = yaffs_mount(mountpt);
 +      printf("mount should return -1 returned %d\n", ret);
 +}
  
  int random_seed;
  int simulate_power_failure;
@@@ -3239,10 -3149,7 +3239,10 @@@ int main(int argc, char *argv[]
         // link_follow_test("/yaffs2");
         //basic_utime_test("/yaffs2");
  
 -      max_files_test("/yaffs2");
 +
 +      //format_test("/yaffs2");
 +
 +      //max_files_test("/yaffs2");
  
         //start_twice("/yaffs2");
  
         //basic_utime_test("/yaffs2");
         //case_insensitive_test("/yaffs2");
  
 +       yy_test("/yaffs2");
 +
 +
         return 0;
  
  }
diff --combined direct/yaffsfs.c
index 705106e7a13e603333fbeaf15c02ca5f9d26a1fa,def672dbafc783a9fbc2c0c034ad8ec4635821c5..7ee486a8d0d95cb2afa2dcd2eb69dd368db441de
@@@ -501,6 -501,9 +501,9 @@@ static struct yaffs_dev *yaffsfs_FindDe
                thisMatchLength = 0;
                matching = 1;
  
+               if(!p)
+                       continue;
                while (matching && *p && *leftOver) {
                        /* Skip over any /s */
                        while (yaffsfs_IsPathDivider(*p))
@@@ -793,7 -796,7 +796,7 @@@ int yaffs_open_sharing(const YCHAR *pat
        int notDir = 0;
        int loop = 0;
  
-       if (!path) {
+       if (yaffsfs_CheckMemRegion(path, 0, 0)< 0) {
                yaffsfs_SetError(-EFAULT);
                return -1;
        }
@@@ -1077,7 -1080,7 +1080,7 @@@ static int yaffsfs_do_read(int handle, 
        Y_LOFF_T maxRead;
        u8 *buf = (u8 *) vbuf;
  
-       if (!vbuf) {
+       if (yaffsfs_CheckMemRegion(vbuf, nbyte, 1) < 0) {
                yaffsfs_SetError(-EFAULT);
                return -1;
        }
@@@ -1199,7 -1202,7 +1202,7 @@@ static int yaffsfs_do_write(int handle
        int nToWrite = 0;
        const u8 *buf = (const u8 *)vbuf;
  
-       if (!vbuf) {
+       if (yaffsfs_CheckMemRegion(vbuf, nbyte, 0) < 0) {
                yaffsfs_SetError(-EFAULT);
                return -1;
        }
@@@ -1310,7 -1313,7 +1313,7 @@@ int yaffs_truncate(const YCHAR *path, Y
        int notDir = 0;
        int loop = 0;
  
-       if (!path) {
+       if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
                yaffsfs_SetError(-EFAULT);
                return -1;
        }
@@@ -1425,7 -1428,7 +1428,7 @@@ static int yaffsfs_DoUnlink(const YCHA
        int notDir = 0;
        int loop = 0;
  
-       if (!path) {
+       if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
                yaffsfs_SetError(-EFAULT);
                return -1;
        }
@@@ -1494,7 -1497,8 +1497,8 @@@ int yaffs_rename(const YCHAR *oldPath, 
  
        YCHAR *alt_newpath = NULL;
  
-       if (!oldPath || !newPath) {
+       if (yaffsfs_CheckMemRegion(oldPath, 0, 0) < 0 ||
+           yaffsfs_CheckMemRegion(newPath, 0, 0) < 0) {
                yaffsfs_SetError(-EFAULT);
                return -1;
        }
@@@ -1633,7 -1637,8 +1637,8 @@@ static int yaffsfs_DoStatOrLStat(const 
        int notDir = 0;
        int loop = 0;
  
-       if (!path || !buf) {
+       if (yaffsfs_CheckMemRegion(path, 0, 0) < 0 ||
+           yaffsfs_CheckMemRegion(buf, sizeof(*buf), 1) < 0) {
                yaffsfs_SetError(-EFAULT);
                return -1;
        }
@@@ -1681,7 -1686,7 +1686,7 @@@ int yaffs_fstat(int fd, struct yaffs_st
  
        int retVal = -1;
  
-       if (!buf) {
+       if (yaffsfs_CheckMemRegion(buf, sizeof(*buf), 1) < 0) {
                yaffsfs_SetError(-EFAULT);
                return -1;
        }
@@@ -1802,7 -1807,9 +1807,9 @@@ static int yaffs_do_setxattr(const YCHA
  
        int retVal = -1;
  
-       if (!path || !name || !data) {
+       if (yaffsfs_CheckMemRegion(path, 0, 0) < 0 ||
+           yaffsfs_CheckMemRegion(name, 0, 0) < 0 ||
+           yaffsfs_CheckMemRegion(data, size, 0) < 0) {
                yaffsfs_SetError(-EFAULT);
                return -1;
        }
@@@ -1858,7 -1865,8 +1865,8 @@@ int yaffs_fsetxattr(int fd, const char 
  
        int retVal = -1;
  
-       if (!name || !data) {
+       if (yaffsfs_CheckMemRegion(name, 0, 0) < 0 ||
+           yaffsfs_CheckMemRegion(data, size, 0) < 0) {
                yaffsfs_SetError(-EFAULT);
                return -1;
        }
@@@ -1890,7 -1898,9 +1898,9 @@@ static int yaffs_do_getxattr(const YCHA
        int notDir = 0;
        int loop = 0;
  
-       if (!path || !name || !data) {
+       if (yaffsfs_CheckMemRegion(path, 0, 0) < 0 ||
+           yaffsfs_CheckMemRegion(name, 0, 0) < 0 ||
+           yaffsfs_CheckMemRegion(data, size, 1) < 0) {
                yaffsfs_SetError(-EFAULT);
                return -1;
        }
@@@ -1942,7 -1952,8 +1952,8 @@@ int yaffs_fgetxattr(int fd, const char 
  
        int retVal = -1;
  
-       if (!name || !data) {
+       if (yaffsfs_CheckMemRegion(name, 0, 0) < 0 ||
+           yaffsfs_CheckMemRegion(data, size, 1) < 0) {
                yaffsfs_SetError(-EFAULT);
                return -1;
        }
@@@ -1974,7 -1985,8 +1985,8 @@@ static int yaffs_do_listxattr(const YCH
        int notDir = 0;
        int loop = 0;
  
-       if (!path || !data) {
+       if (yaffsfs_CheckMemRegion(path, 0, 0) < 0 ||
+           yaffsfs_CheckMemRegion(data, size, 1) < 0) {
                yaffsfs_SetError(-EFAULT);
                return -1;
        }
@@@ -2027,7 -2039,7 +2039,7 @@@ int yaffs_flistxattr(int fd, char *data
  
        int retVal = -1;
  
-       if (!data) {
+       if (yaffsfs_CheckMemRegion(data, size, 1) < 0) {
                yaffsfs_SetError(-EFAULT);
                return -1;
        }
@@@ -2059,7 -2071,8 +2071,8 @@@ static int yaffs_do_removexattr(const Y
        int loop = 0;
        int retVal = -1;
  
-       if (!path || !name) {
+       if (yaffsfs_CheckMemRegion(path, 0, 0) < 0 ||
+           yaffsfs_CheckMemRegion(name, 0, 0) < 0) {
                yaffsfs_SetError(-EFAULT);
                return -1;
        }
@@@ -2112,7 -2125,7 +2125,7 @@@ int yaffs_fremovexattr(int fd, const ch
  
        int retVal = -1;
  
-       if (!name) {
+       if (yaffsfs_CheckMemRegion(name, 0, 0) < 0) {
                yaffsfs_SetError(-EFAULT);
                return -1;
        }
@@@ -2236,7 -2249,7 +2249,7 @@@ int yaffs_access(const YCHAR *path, in
        int loop = 0;
        int retval = -1;
  
-       if (!path) {
+       if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
                yaffsfs_SetError(-EFAULT);
                return -1;
        }
@@@ -2294,7 -2307,7 +2307,7 @@@ int yaffs_chmod(const YCHAR *path, mode
        int notDir = 0;
        int loop = 0;
  
-       if (!path) {
+       if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
                yaffsfs_SetError(-EFAULT);
                return -1;
        }
@@@ -2366,7 -2379,7 +2379,7 @@@ int yaffs_mkdir(const YCHAR *path, mode
        int notDir = 0;
        int loop = 0;
  
-       if (!path) {
+       if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
                yaffsfs_SetError(-EFAULT);
                return -1;
        }
@@@ -2420,7 -2433,7 +2433,7 @@@ int yaffs_rmdir(const YCHAR *path
        int result;
        YCHAR *alt_path;
  
-       if (!path) {
+       if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
                yaffsfs_SetError(-EFAULT);
                return -1;
        }
@@@ -2457,7 -2470,7 +2470,7 @@@ int yaffs_mount_common(const YCHAR *pat
        int result = YAFFS_FAIL;
        struct yaffs_dev *dev = NULL;
  
-       if (!path) {
+       if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
                yaffsfs_SetError(-EFAULT);
                return -1;
        }
@@@ -2516,7 -2529,7 +2529,7 @@@ int yaffs_sync(const YCHAR *path
        struct yaffs_dev *dev = NULL;
        YCHAR *dummy;
  
-       if (!path) {
+       if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
                yaffsfs_SetError(-EFAULT);
                return -1;
        }
@@@ -2565,7 -2578,7 +2578,7 @@@ int yaffs_remount(const YCHAR *path, in
        int retVal = -1;
        struct yaffs_dev *dev = NULL;
  
-       if (!path) {
+       if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
                yaffsfs_SetError(-EFAULT);
                return -1;
        }
@@@ -2605,7 -2618,7 +2618,7 @@@ int yaffs_unmount2(const YCHAR *path, i
        int retVal = -1;
        struct yaffs_dev *dev = NULL;
  
-       if (!path) {
+       if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
                yaffsfs_SetError(-EFAULT);
                return -1;
        }
@@@ -2648,74 -2661,13 +2661,74 @@@ int yaffs_unmount(const YCHAR *path
        return yaffs_unmount2(path, 0);
  }
  
 +int yaffs_format(const YCHAR *path,
 +              int unmount_flag,
 +              int force_unmount_flag,
 +              int remount_flag)
 +{
 +      int retVal = 0;
 +      struct yaffs_dev *dev = NULL;
 +      int result;
 +
 +      if (!path) {
 +              yaffsfs_SetError(-EFAULT);
 +              return -1;
 +      }
 +
 +      if (yaffsfs_CheckPath(path) < 0) {
 +              yaffsfs_SetError(-ENAMETOOLONG);
 +              return -1;
 +      }
 +
 +      yaffsfs_Lock();
 +      dev = yaffsfs_FindMountPoint(path);
 +
 +      if (dev) {
 +              int was_mounted = dev->is_mounted;
 +
 +              if (dev->is_mounted && unmount_flag) {
 +                      int inUse;
 +                      yaffs_flush_whole_cache(dev);
 +                      yaffs_checkpoint_save(dev);
 +                      inUse = yaffsfs_IsDevBusy(dev);
 +                      if (!inUse || force_unmount_flag) {
 +                              if (inUse)
 +                                      yaffsfs_BreakDeviceHandles(dev);
 +                              yaffs_deinitialise(dev);
 +                      }
 +              }
 +
 +              if(dev->is_mounted) {
 +                              yaffsfs_SetError(-EBUSY);
 +                              retVal = -1;
 +              } else {
 +                      yaffs_format_dev(dev);
 +                      if(was_mounted && remount_flag) {
 +                              result = yaffs_guts_initialise(dev);
 +                              if (result == YAFFS_FAIL) {
 +                                      yaffsfs_SetError(-ENOMEM);
 +                                      retVal = -1;
 +                              }
 +                      }
 +              }
 +      } else {
 +              yaffsfs_SetError(-ENODEV);
 +              retVal = -1;
 +      }
 +
 +      yaffsfs_Unlock();
 +      return retVal;
 +
 +}
 +
 +
  Y_LOFF_T yaffs_freespace(const YCHAR *path)
  {
        Y_LOFF_T retVal = -1;
        struct yaffs_dev *dev = NULL;
        YCHAR *dummy;
  
-       if (!path) {
+       if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
                yaffsfs_SetError(-EFAULT);
                return -1;
        }
@@@ -2744,7 -2696,7 +2757,7 @@@ Y_LOFF_T yaffs_totalspace(const YCHAR *
        struct yaffs_dev *dev = NULL;
        YCHAR *dummy;
  
-       if (!path) {
+       if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
                yaffsfs_SetError(-EFAULT);
                return -1;
        }
@@@ -2775,7 -2727,7 +2788,7 @@@ int yaffs_inodecount(const YCHAR *path
        struct yaffs_dev *dev = NULL;
        YCHAR *dummy;
  
-       if (!path) {
+       if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
                yaffsfs_SetError(-EFAULT);
                return -1;
        }
@@@ -2927,7 -2879,7 +2940,7 @@@ yaffs_DIR *yaffs_opendir(const YCHAR *d
        int notDir = 0;
        int loop = 0;
  
-       if (!dirname) {
+       if (yaffsfs_CheckMemRegion(dirname, 0, 0) < 0) {
                yaffsfs_SetError(-EFAULT);
                return NULL;
        }
@@@ -3021,6 -2973,9 +3034,9 @@@ void yaffs_rewinddir(yaffs_DIR *dirp
  
        dsc = (struct yaffsfs_DirSearchContxt *) dirp;
  
+       if (yaffsfs_CheckMemRegion(dirp, sizeof(*dsc), 0) < 0)
+               return;
        yaffsfs_Lock();
  
        yaffsfs_SetDirRewound(dsc);
@@@ -3034,7 -2989,7 +3050,7 @@@ int yaffs_closedir(yaffs_DIR *dirp
  
        dsc = (struct yaffsfs_DirSearchContxt *) dirp;
  
-       if (!dsc) {
+       if (yaffsfs_CheckMemRegion(dirp, sizeof(*dsc), 0) < 0) {
                yaffsfs_SetError(-EFAULT);
                return -1;
        }
@@@ -3058,7 -3013,8 +3074,8 @@@ int yaffs_symlink(const YCHAR *oldpath
        int notDir = 0;
        int loop = 0;
  
-       if (!oldpath || !newpath) {
+       if (yaffsfs_CheckMemRegion(oldpath, 0, 0) < 0 ||
+           yaffsfs_CheckMemRegion(newpath, 0, 0) < 0) {
                yaffsfs_SetError(-EFAULT);
                return -1;
        }
@@@ -3105,7 -3061,8 +3122,8 @@@ int yaffs_readlink(const YCHAR *path, Y
        int notDir = 0;
        int loop = 0;
  
-       if (!path || !buf) {
+       if (yaffsfs_CheckMemRegion(path, 0, 0) < 0 ||
+           yaffsfs_CheckMemRegion(buf, bufsiz, 1) < 0) {
                yaffsfs_SetError(-EFAULT);
                return -1;
        }
@@@ -3146,7 -3103,8 +3164,8 @@@ int yaffs_link(const YCHAR *oldpath, co
        int lnkLoop = 0;
        YCHAR *newname;
  
-       if (!oldpath || !linkpath) {
+       if (yaffsfs_CheckMemRegion(oldpath, 0, 0) < 0 ||
+           yaffsfs_CheckMemRegion(linkpath, 0, 0) < 0) {
                yaffsfs_SetError(-EFAULT);
                return -1;
        }
@@@ -3218,7 -3176,7 +3237,7 @@@ int yaffs_n_handles(const YCHAR *path
  {
        struct yaffs_obj *obj;
  
-       if (!path) {
+       if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
                yaffsfs_SetError(-EFAULT);
                return -1;
        }
diff --combined yaffs_guts.c
index 9c296e24bcd181440cdb254f3dc3b3602f3730a9,3c1aa105f35fcf18f1cb73cbe06f4dd0e3e20c7d..9f6b40964b5e85d154294fef73af38b544634cd8
@@@ -17,6 -17,7 +17,7 @@@
  #include "yaffs_guts.h"
  #include "yaffs_getblockinfo.h"
  #include "yaffs_tagscompat.h"
+ #include "yaffs_tagsmarshall.h"
  #include "yaffs_nand.h"
  #include "yaffs_yaffs1.h"
  #include "yaffs_yaffs2.h"
@@@ -40,8 -41,7 +41,8 @@@
  static int yaffs_wr_data_obj(struct yaffs_obj *in, int inode_chunk,
                             const u8 *buffer, int n_bytes, int use_reserve);
  
 -
 +static void yaffs_fix_null_name(struct yaffs_obj *obj, YCHAR *name,
 +                              int buffer_size);
  
  /* Function to calculate chunk and offset */
  
@@@ -609,10 -609,10 +610,10 @@@ static void yaffs_retire_block(struct y
                        memset(buffer, 0xff, dev->data_bytes_per_chunk);
                        memset(&tags, 0, sizeof(tags));
                        tags.seq_number = YAFFS_SEQUENCE_BAD_BLOCK;
-                       if (dev->param.write_chunk_tags_fn(dev, chunk_id -
-                                                          dev->chunk_offset,
-                                                          buffer,
-                                                          &tags) != YAFFS_OK)
+                       if (dev->tagger.write_chunk_tags_fn(dev, chunk_id -
+                                                       dev->chunk_offset,
+                                                       buffer,
+                                                       &tags) != YAFFS_OK)
                                yaffs_trace(YAFFS_TRACE_ALWAYS,
                                        "yaffs: Failed to write bad block marker to block %d",
                                        flash_block);
@@@ -648,21 -648,15 +649,21 @@@ static u16 yaffs_calc_name_sum(const YC
        return sum;
  }
  
 +
  void yaffs_set_obj_name(struct yaffs_obj *obj, const YCHAR * name)
  {
        memset(obj->short_name, 0, sizeof(obj->short_name));
 -      if (name &&
 +
 +      if (name && !name[0]) {
 +              yaffs_fix_null_name(obj, obj->short_name,
 +                              YAFFS_SHORT_NAME_LENGTH);
 +              name = obj->short_name;
 +      } else if (name &&
                strnlen(name, YAFFS_SHORT_NAME_LENGTH + 1) <=
 -              YAFFS_SHORT_NAME_LENGTH)
 +              YAFFS_SHORT_NAME_LENGTH)  {
                strcpy(obj->short_name, name);
 -      else
 -              obj->short_name[0] = _Y('\0');
 +      }
 +
        obj->sum = yaffs_calc_name_sum(name);
  }
  
@@@ -2804,7 -2798,8 +2805,8 @@@ static int yaffs_check_gc(struct yaffs_
        int erased_chunks;
        int checkpt_block_adjust;
  
-       if (dev->param.gc_control && (dev->param.gc_control(dev) & 1) == 0)
+       if (dev->param.gc_control_fn &&
+               (dev->param.gc_control_fn(dev) & 1) == 0)
                return YAFFS_OK;
  
        if (dev->gc_disable)
@@@ -3566,9 -3561,11 +3568,11 @@@ int yaffs_do_file_wr(struct yaffs_obj *
                }
  
                if (n_copy != dev->data_bytes_per_chunk ||
+                   !dev->param.cache_bypass_aligned ||
                    dev->param.inband_tags) {
                        /* An incomplete start or end chunk (or maybe both
                         * start and end chunk), or we're using inband tags,
+                        * or we're forcing writes through the cache,
                         * so we want to use the cache buffers.
                         */
                        if (dev->param.n_caches > 0) {
@@@ -4536,30 -4533,33 +4540,33 @@@ YCHAR *yaffs_get_symlink_alias(struct y
  
  /*--------------------------- Initialisation code -------------------------- */
  
- static int yaffs_check_dev_fns(const struct yaffs_dev *dev)
+ static int yaffs_check_dev_fns(struct yaffs_dev *dev)
  {
+       struct yaffs_driver *drv = &dev->drv;
+       struct yaffs_tags_handler *tagger = &dev->tagger;
        /* Common functions, gotta have */
-       if (!dev->param.erase_fn || !dev->param.initialise_flash_fn)
+       if (!drv->drv_read_chunk_fn ||
+           !drv->drv_write_chunk_fn ||
+           !drv->drv_erase_fn)
                return 0;
  
-       /* Can use the "with tags" style interface for yaffs1 or yaffs2 */
-       if (dev->param.write_chunk_tags_fn &&
-           dev->param.read_chunk_tags_fn &&
-           !dev->param.write_chunk_fn &&
-           !dev->param.read_chunk_fn &&
-           dev->param.bad_block_fn && dev->param.query_block_fn)
-               return 1;
+       if (dev->param.is_yaffs2 &&
+            (!drv->drv_mark_bad_fn  || !drv->drv_check_bad_fn))
+               return 0;
  
-       /* Can use the "spare" style interface for yaffs1 */
-       if (!dev->param.is_yaffs2 &&
-           !dev->param.write_chunk_tags_fn &&
-           !dev->param.read_chunk_tags_fn &&
-           dev->param.write_chunk_fn &&
-           dev->param.read_chunk_fn &&
-           !dev->param.bad_block_fn && !dev->param.query_block_fn)
-               return 1;
+       /* Install the default tags marshalling functions if needed. */
+       yaffs_tags_compat_install(dev);
+       yaffs_tags_marshall_install(dev);
  
-       return 0;               /* bad */
+       /* Check we now have the marshalling functions required. */
+       if (!tagger->write_chunk_tags_fn ||
+           !tagger->read_chunk_tags_fn ||
+           !tagger->query_block_fn ||
+           !tagger->mark_bad_fn)
+               return 0;
+       return 1;
  }
  
  static int yaffs_create_initial_dir(struct yaffs_dev *dev)
@@@ -4929,8 -4929,7 +4936,7 @@@ void yaffs_deinitialise(struct yaffs_de
  
                dev->is_mounted = 0;
  
-               if (dev->param.deinitialise_flash_fn)
-                       dev->param.deinitialise_flash_fn(dev);
+               yaffs_deinit_nand(dev);
        }
  }
  
@@@ -4993,42 -4992,6 +4999,42 @@@ int yaffs_get_n_free_chunks(struct yaff
        return n_free;
  }
  
 +
 +int yaffs_format_dev(struct yaffs_dev *dev)
 +{
 +      int i;
 +      enum yaffs_block_state state;
 +      u32 dummy;
 +
 +      if(dev->is_mounted)
 +              return YAFFS_FAIL;
 +
 +      /*
 +      * The runtime variables might not have been set up,
 +      * so set up what we need.
 +      */
 +      dev->internal_start_block = dev->param.start_block;
 +      dev->internal_end_block = dev->param.end_block;
 +      dev->block_offset = 0;
 +      dev->chunk_offset = 0;
 +
 +      if (dev->param.start_block == 0) {
 +              dev->internal_start_block = dev->param.start_block + 1;
 +              dev->internal_end_block = dev->param.end_block + 1;
 +              dev->block_offset = 1;
 +              dev->chunk_offset = dev->param.chunks_per_block;
 +      }
 +
 +      for (i = dev->internal_start_block; i <= dev->internal_end_block; i++) {
 +              yaffs_query_init_block_state(dev, i, &state, &dummy);
 +              if (state != YAFFS_BLOCK_STATE_DEAD)
 +                      yaffs_erase_block(dev, i);
 +      }
 +
 +      return YAFFS_OK;
 +}
 +
 +
  /*
   * Marshalling functions to get loff_t file sizes into and out of
   * object headers.
diff --combined yaffs_guts.h
index 0e334bdd5e723ad6a028d10e1c5b1b1cda9092e8,62d18cb6525567c40303fea61714274e0bd1ba5c..26ad54d401028020c356edc2d1c6b70a72aeadc5
@@@ -520,7 -520,7 +520,7 @@@ struct yaffs_param 
        /*
         * Entry parameters set up way early. Yaffs sets up the rest.
         * The structure should be zeroed out before use so that unused
-        * and defualt values are zero.
+        * and default values are zero.
         */
  
        int inband_tags;        /* Use unband tags */
        int n_caches;           /* If <= 0, then short op caching is disabled,
                                 * else the number of short op caches.
                                 */
+       int cache_bypass_aligned; /* If non-zero then bypass the cache for
+                                  * aligned writes.
+                                  */
        int use_nand_ecc;       /* Flag to decide whether or not to use
                                 * NAND driver ECC on data (yaffs1) */
        int tags_9bytes;        /* Use 9 byte tags */
  
        int enable_xattr;       /* Enable xattribs */
  
-       /* NAND access functions (Must be set before calling YAFFS) */
-       int (*write_chunk_fn) (struct yaffs_dev *dev,
-                              int nand_chunk, const u8 *data,
-                              const struct yaffs_spare *spare);
-       int (*read_chunk_fn) (struct yaffs_dev *dev,
-                             int nand_chunk, u8 *data,
-                             struct yaffs_spare *spare);
-       int (*erase_fn) (struct yaffs_dev *dev, int flash_block);
-       int (*initialise_flash_fn) (struct yaffs_dev *dev);
-       int (*deinitialise_flash_fn) (struct yaffs_dev *dev);
-       /* yaffs2 mode functions */
-       int (*write_chunk_tags_fn) (struct yaffs_dev *dev,
-                                   int nand_chunk, const u8 *data,
-                                   const struct yaffs_ext_tags *tags);
-       int (*read_chunk_tags_fn) (struct yaffs_dev *dev,
-                                  int nand_chunk, u8 *data,
-                                  struct yaffs_ext_tags *tags);
-       int (*bad_block_fn) (struct yaffs_dev *dev, int block_no);
-       int (*query_block_fn) (struct yaffs_dev *dev, int block_no,
-                              enum yaffs_block_state *state,
-                              u32 *seq_number);
+       int max_objects;        /*
+                                * Set to limit the number of objects created.
+                                * 0 = no limit.
+                               */
  
        /* The remove_obj_fn function must be supplied by OS flavours that
         * need it.
        void (*sb_dirty_fn) (struct yaffs_dev *dev);
  
        /*  Callback to control garbage collection. */
-       unsigned (*gc_control) (struct yaffs_dev *dev);
+       unsigned (*gc_control_fn) (struct yaffs_dev *dev);
  
        /* Debug control flags. Don't use unless you know what you're doing */
        int use_header_file_size;       /* Flag to determine if we should use
  
        int disable_summary;
  
-       int max_objects;        /*
-                                * Set to limit the number of objects created.
-                                * 0 = no limit.
-                               */
+ };
+ struct yaffs_driver {
+       int (*drv_write_chunk_fn) (struct yaffs_dev *dev, int nand_chunk,
+                                  const u8 *data, int data_len,
+                                  const u8 *oob, int oob_len);
+       int (*drv_read_chunk_fn) (struct yaffs_dev *dev, int nand_chunk,
+                                  u8 *data, int data_len,
+                                  u8 *oob, int oob_len,
+                                  enum yaffs_ecc_result *ecc_result);
+       int (*drv_erase_fn) (struct yaffs_dev *dev, int block_no);
+       int (*drv_mark_bad_fn) (struct yaffs_dev *dev, int block_no);
+       int (*drv_check_bad_fn) (struct yaffs_dev *dev, int block_no);
+       int (*drv_initialise_fn) (struct yaffs_dev *dev);
+       int (*drv_deinitialise_fn) (struct yaffs_dev *dev);
+ };
+ struct yaffs_tags_handler {
+       int (*write_chunk_tags_fn) (struct yaffs_dev *dev,
+                                   int nand_chunk, const u8 *data,
+                                   const struct yaffs_ext_tags *tags);
+       int (*read_chunk_tags_fn) (struct yaffs_dev *dev,
+                                  int nand_chunk, u8 *data,
+                                  struct yaffs_ext_tags *tags);
+       int (*query_block_fn) (struct yaffs_dev *dev, int block_no,
+                              enum yaffs_block_state *state,
+                              u32 *seq_number);
+       int (*mark_bad_fn) (struct yaffs_dev *dev, int block_no);
  };
  
  struct yaffs_dev {
        struct yaffs_param param;
+       struct yaffs_driver drv;
+       struct yaffs_tags_handler tagger;
  
        /* Context storage. Holds extra OS specific data for this device */
  
        u32 n_page_writes;
        u32 n_page_reads;
        u32 n_erasures;
+       u32 n_bad_markings;
        u32 n_erase_failures;
        u32 n_gc_copies;
        u32 all_gcs;
@@@ -961,8 -974,6 +974,8 @@@ u32 yaffs_get_group_base(struct yaffs_d
  
  int yaffs_is_non_empty_dir(struct yaffs_obj *obj);
  
 +int yaffs_format_dev(struct yaffs_dev *dev);
 +
  void yaffs_addr_to_chunk(struct yaffs_dev *dev, loff_t addr,
                                int *chunk_out, u32 *offset_out);
  /*