Remove misnamed test
[yaffs2.git] / yaffs_vfs_multi.c
index 9feecdf82ef85eeb63e941607feaf36f190ad265..3cf6dde1717c394487c3780189da83801fddcb52 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
  *
- * Copyright (C) 2002-2010 Aleph One Ltd.
+ * Copyright (C) 2002-2011 Aleph One Ltd.
  *   for Toby Churchill Ltd and Brightstar Engineering
  *
  * Created by Charles Manning <charles@aleph1.co.uk>
 
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10))
 #define YAFFS_COMPILE_BACKGROUND
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6, 23))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23))
 #define YAFFS_COMPILE_FREEZER
 #endif
 #endif
 
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
 #define YAFFS_COMPILE_EXPORTFS
 #endif
 
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35))
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35))
 #define YAFFS_USE_SETATTR_COPY
 #define YAFFS_USE_TRUNCATE_SETSIZE
 #endif
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35))
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35))
 #define YAFFS_HAS_EVICT_INODE
 #endif
 
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13))
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13))
 #define YAFFS_NEW_FOLLOW_LINK 1
 #else
 #define YAFFS_NEW_FOLLOW_LINK 0
@@ -72,7 +72,9 @@
 #include <linux/init.h>
 #include <linux/fs.h>
 #include <linux/proc_fs.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39))
 #include <linux/smp_lock.h>
+#endif
 #include <linux/pagemap.h>
 #include <linux/mtd/mtd.h>
 #include <linux/interrupt.h>
 #define YPROC_ROOT  NULL
 #endif
 
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26))
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26))
 #define Y_INIT_TIMER(a)        init_timer(a)
 #else
 #define Y_INIT_TIMER(a)        init_timer_on_stack(a)
 #define YAFFS_USE_WRITE_BEGIN_END 0
 #endif
 
+
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0))
+#define set_nlink(inode, count)  do { (inode)->i_nlink = (count); } while(0)
+#endif
+
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 28))
 static uint32_t YCALCBLOCKS(uint64_t partition_size, uint32_t block_size)
 {
@@ -168,15 +176,13 @@ static uint32_t YCALCBLOCKS(uint64_t partition_size, uint32_t block_size)
 #include "yaffs_linux.h"
 
 #include "yaffs_mtdif.h"
-#include "yaffs_mtdif1.h"
-#include "yaffs_mtdif2.h"
 
 unsigned int yaffs_trace_mask = YAFFS_TRACE_BAD_BLOCKS | YAFFS_TRACE_ALWAYS;
 unsigned int yaffs_wr_attempts = YAFFS_WR_ATTEMPTS;
 unsigned int yaffs_auto_checkpoint = 1;
 unsigned int yaffs_gc_control = 1;
 unsigned int yaffs_bg_enable = 1;
-
+unsigned int yaffs_auto_select = 1;
 /* Module Parameters */
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
 module_param(yaffs_trace_mask, uint, 0644);
@@ -210,7 +216,8 @@ static struct inode *yaffs_iget(struct super_block *sb, unsigned long ino);
 #define yaffs_inode_to_obj_lv(iptr) ((iptr)->u.generic_ip)
 #endif
 
-#define yaffs_inode_to_obj(iptr) ((struct yaffs_obj *)(yaffs_inode_to_obj_lv(iptr)))
+#define yaffs_inode_to_obj(iptr) \
+       ((struct yaffs_obj *)(yaffs_inode_to_obj_lv(iptr)))
 #define yaffs_dentry_to_obj(dptr) yaffs_inode_to_obj((dptr)->d_inode)
 
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
@@ -221,12 +228,12 @@ static struct inode *yaffs_iget(struct super_block *sb, unsigned long ino);
 
 #define update_dir_time(dir) do {\
                        (dir)->i_ctime = (dir)->i_mtime = CURRENT_TIME; \
-               } while(0)
+               } while (0)
 
 static void yaffs_put_super(struct super_block *sb);
 
 static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n,
-                               loff_t * pos);
+                               loff_t *pos);
 static ssize_t yaffs_hold_space(struct file *f);
 static void yaffs_release_space(struct file *f);
 
@@ -236,7 +243,9 @@ static int yaffs_file_flush(struct file *file, fl_owner_t id);
 static int yaffs_file_flush(struct file *file);
 #endif
 
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 34))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
+static int yaffs_sync_object(struct file *file, loff_t start, loff_t end, int datasync);
+#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 34))
 static int yaffs_sync_object(struct file *file, int datasync);
 #else
 static int yaffs_sync_object(struct file *file, struct dentry *dentry,
@@ -306,14 +315,12 @@ static int yaffs_writepage(struct page *page, struct writeback_control *wbc);
 static int yaffs_writepage(struct page *page);
 #endif
 
-#ifdef CONFIG_YAFFS_XATTR
 static int yaffs_setxattr(struct dentry *dentry, const char *name,
                   const void *value, size_t size, int flags);
-static ssize_t yaffs_getxattr(struct dentry *dentry, const char *name, void *buff,
-                      size_t size);
+static ssize_t yaffs_getxattr(struct dentry *dentry, const char *name,
+                               void *buff, size_t size);
 static int yaffs_removexattr(struct dentry *dentry, const char *name);
 static ssize_t yaffs_listxattr(struct dentry *dentry, char *buff, size_t size);
-#endif
 
 #if (YAFFS_USE_WRITE_BEGIN_END != 0)
 static int yaffs_write_begin(struct file *filp, struct address_space *mapping,
@@ -396,7 +403,7 @@ static const struct file_operations yaffs_file_operations = {
 };
 #endif
 
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25))
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25))
 static void zero_user_segment(struct page *page, unsigned start, unsigned end)
 {
        void *kaddr = kmap_atomic(page, KM_USER0);
@@ -408,12 +415,10 @@ static void zero_user_segment(struct page *page, unsigned start, unsigned end)
 
 static const struct inode_operations yaffs_file_inode_operations = {
        .setattr = yaffs_setattr,
-#ifdef CONFIG_YAFFS_XATTR
        .setxattr = yaffs_setxattr,
        .getxattr = yaffs_getxattr,
        .listxattr = yaffs_listxattr,
        .removexattr = yaffs_removexattr,
-#endif
 };
 
 static const struct inode_operations yaffs_symlink_inode_operations = {
@@ -423,12 +428,10 @@ static const struct inode_operations yaffs_symlink_inode_operations = {
        .put_link = yaffs_put_link,
 #endif
        .setattr = yaffs_setattr,
-#ifdef CONFIG_YAFFS_XATTR
        .setxattr = yaffs_setxattr,
        .getxattr = yaffs_getxattr,
        .listxattr = yaffs_listxattr,
        .removexattr = yaffs_removexattr,
-#endif
 };
 
 static const struct inode_operations yaffs_dir_inode_operations = {
@@ -442,12 +445,10 @@ static const struct inode_operations yaffs_dir_inode_operations = {
        .mknod = yaffs_mknod,
        .rename = yaffs_rename,
        .setattr = yaffs_setattr,
-#ifdef CONFIG_YAFFS_XATTR
        .setxattr = yaffs_setxattr,
        .getxattr = yaffs_getxattr,
        .listxattr = yaffs_listxattr,
        .removexattr = yaffs_removexattr,
-#endif
 };
 
 static const struct file_operations yaffs_dir_operations = {
@@ -479,7 +480,7 @@ static const struct super_operations yaffs_super_ops = {
 
 static int yaffs_vfs_setattr(struct inode *inode, struct iattr *attr)
 {
-#ifdef  YAFFS_USE_SETATTR_COPY
+#ifdef YAFFS_USE_SETATTR_COPY
        setattr_copy(inode, attr);
        return 0;
 #else
@@ -490,7 +491,7 @@ static int yaffs_vfs_setattr(struct inode *inode, struct iattr *attr)
 
 static int yaffs_vfs_setsize(struct inode *inode, loff_t newsize)
 {
-#ifdef  YAFFS_USE_TRUNCATE_SETSIZE
+#ifdef YAFFS_USE_TRUNCATE_SETSIZE
        truncate_setsize(inode, newsize);
        return 0;
 #else
@@ -692,11 +693,9 @@ static void yaffs_remove_obj_callback(struct yaffs_obj *obj)
         * the search context to the next object to prevent a hanging pointer.
         */
        list_for_each(i, search_contexts) {
-               if (i) {
-                       sc = list_entry(i, struct yaffs_search_context, others);
-                       if (sc->next_return == obj)
-                               yaffs_search_advance(sc);
-               }
+               sc = list_entry(i, struct yaffs_search_context, others);
+               if (sc->next_return == obj)
+                       yaffs_search_advance(sc);
        }
 
 }
@@ -793,7 +792,7 @@ static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry)
        if (current != yaffs_dev_to_lc(dev)->readdir_process)
                yaffs_gross_lock(dev);
 
-       yaffs_trace(YAFFS_TRACE_OS,"yaffs_lookup for %d:%s",
+       yaffs_trace(YAFFS_TRACE_OS, "yaffs_lookup for %d:%s",
                yaffs_inode_to_obj(dir)->obj_id, dentry->d_name.name);
 
        obj = yaffs_find_by_name(yaffs_inode_to_obj(dir), dentry->d_name.name);
@@ -975,13 +974,13 @@ static int yaffs_readpage_nolock(struct file *f, struct page *pg)
        struct yaffs_obj *obj;
        unsigned char *pg_buf;
        int ret;
-
+       loff_t pos = ((loff_t) pg->index) << PAGE_CACHE_SHIFT;
        struct yaffs_dev *dev;
 
        yaffs_trace(YAFFS_TRACE_OS,
-               "yaffs_readpage_nolock at %08x, size %08x",
-               (unsigned)(pg->index << PAGE_CACHE_SHIFT),
-               (unsigned)PAGE_CACHE_SIZE);
+               "yaffs_readpage_nolock at %lld, size %08x",
+               (long long)pos,
+               (unsigned)PAGE_CACHE_SIZE);
 
        obj = yaffs_dentry_to_obj(f->f_dentry);
 
@@ -999,8 +998,7 @@ static int yaffs_readpage_nolock(struct file *f, struct page *pg)
 
        yaffs_gross_lock(dev);
 
-       ret = yaffs_file_rd(obj, pg_buf,
-                           pg->index << PAGE_CACHE_SHIFT, PAGE_CACHE_SIZE);
+       ret = yaffs_file_rd(obj, pg_buf, pos, PAGE_CACHE_SIZE);
 
        yaffs_gross_unlock(dev);
 
@@ -1073,9 +1071,9 @@ static int yaffs_writepage(struct page *page)
 
                if (page->index > end_index || !n_bytes) {
                        yaffs_trace(YAFFS_TRACE_OS,
-                               "yaffs_writepage at %08x, inode size = %08x!!",
-                               (unsigned)(page->index << PAGE_CACHE_SHIFT),
-                               (unsigned)inode->i_size);
+                               "yaffs_writepage at %lld, inode size = %lld!!",
+                               ((loff_t)page->index) << PAGE_CACHE_SHIFT,
+                               inode->i_size);
                        yaffs_trace(YAFFS_TRACE_OS,
                                "                -> don't care!!");
 
@@ -1099,20 +1097,20 @@ static int yaffs_writepage(struct page *page)
        yaffs_gross_lock(dev);
 
        yaffs_trace(YAFFS_TRACE_OS,
-               "yaffs_writepage at %08x, size %08x",
-               (unsigned)(page->index << PAGE_CACHE_SHIFT), n_bytes);
+               "yaffs_writepage at %lld, size %08x",
+               ((loff_t)page->index) << PAGE_CACHE_SHIFT, n_bytes);
        yaffs_trace(YAFFS_TRACE_OS,
-               "writepag0: obj = %05x, ino = %05x",
-               (int)obj->variant.file_variant.file_size, (int)inode->i_size);
+               "writepag0: obj = %lld, ino = %lld",
+               obj->variant.file_variant.file_size, inode->i_size);
 
        n_written = yaffs_wr_file(obj, buffer,
-                                 page->index << PAGE_CACHE_SHIFT, n_bytes, 0);
+                                 ((loff_t)page->index) << PAGE_CACHE_SHIFT, n_bytes, 0);
 
        yaffs_touch_super(dev);
 
        yaffs_trace(YAFFS_TRACE_OS,
-               "writepag1: obj = %05x, ino = %05x",
-               (int)obj->variant.file_variant.file_size, (int)inode->i_size);
+               "writepag1: obj = %lld, ino = %lld",
+               obj->variant.file_variant.file_size, inode->i_size);
 
        yaffs_gross_unlock(dev);
 
@@ -1211,8 +1209,8 @@ static int yaffs_write_end(struct file *filp, struct address_space *mapping,
        addr = kva + offset_into_page;
 
        yaffs_trace(YAFFS_TRACE_OS,
-               "yaffs_write_end addr %p pos %x n_bytes %d",
-               addr, (unsigned)pos, copied);
+               "yaffs_write_end addr %p pos %lld n_bytes %d",
+               addr, pos, copied);
 
        ret = yaffs_file_write(filp, addr, copied, &pos);
 
@@ -1241,17 +1239,12 @@ static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset,
        int n_bytes = to - offset;
        int n_written;
 
-       unsigned spos = pos;
-       unsigned saddr;
-
        kva = kmap(pg);
        addr = kva + offset;
 
-       saddr = (unsigned)addr;
-
        yaffs_trace(YAFFS_TRACE_OS,
-               "yaffs_commit_write addr %x pos %x n_bytes %d",
-               saddr, spos, n_bytes);
+               "yaffs_commit_write addr %p pos %lld n_bytes %d",
+               addr, pos, n_bytes);
 
        n_written = yaffs_file_write(f, addr, n_bytes, &pos);
 
@@ -1335,12 +1328,12 @@ static void yaffs_fill_inode_from_obj(struct inode *inode,
                inode->i_size = yaffs_get_obj_length(obj);
                inode->i_blocks = (inode->i_size + 511) >> 9;
 
-               inode->i_nlink = yaffs_get_obj_link_count(obj);
+               set_nlink(inode, yaffs_get_obj_link_count(obj));
 
                yaffs_trace(YAFFS_TRACE_OS,
-                       "yaffs_fill_inode mode %x uid %d gid %d size %d count %d",
+                       "yaffs_fill_inode mode %x uid %d gid %d size %lld count %d",
                        inode->i_mode, inode->i_uid, inode->i_gid,
-                       (int)inode->i_size, atomic_read(&inode->i_count));
+                       inode->i_size, atomic_read(&inode->i_count));
 
                switch (obj->yst_mode & S_IFMT) {
                default:        /* fifo, device or socket */
@@ -1415,12 +1408,19 @@ static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n,
                                loff_t * pos)
 {
        struct yaffs_obj *obj;
-       int n_written, ipos;
+       int n_written;
+       loff_t ipos;
        struct inode *inode;
        struct yaffs_dev *dev;
 
        obj = yaffs_dentry_to_obj(f->f_dentry);
 
+       if (!obj) {
+               yaffs_trace(YAFFS_TRACE_OS,
+                       "yaffs_file_write: hey obj is null!");
+                return -EINVAL;
+        }
+
        dev = obj->my_dev;
 
        yaffs_gross_lock(dev);
@@ -1432,13 +1432,9 @@ static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n,
        else
                ipos = *pos;
 
-       if (!obj)
-               yaffs_trace(YAFFS_TRACE_OS,
-                       "yaffs_file_write: hey obj is null!");
-       else
-               yaffs_trace(YAFFS_TRACE_OS,
-                       "yaffs_file_write about to write writing %u(%x) bytes to object %d at %d(%x)",
-                       (unsigned)n, (unsigned)n, obj->obj_id, ipos, ipos);
+       yaffs_trace(YAFFS_TRACE_OS,
+               "yaffs_file_write about to write writing %u(%x) bytes to object %d at %lld",
+               (unsigned)n, (unsigned)n, obj->obj_id, ipos);
 
        n_written = yaffs_wr_file(obj, buf, ipos, n, 0);
 
@@ -1456,7 +1452,7 @@ static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n,
                        inode->i_blocks = (ipos + 511) >> 9;
 
                        yaffs_trace(YAFFS_TRACE_OS,
-                               "yaffs_file_write size updated to %d bytes, %d blocks",
+                               "yaffs_file_write size updated to %lld bytes, %d blocks",
                                ipos, (int)(inode->i_blocks));
                }
 
@@ -1747,10 +1743,9 @@ static int yaffs_unlink(struct inode *dir, struct dentry *dentry)
        ret_val = yaffs_unlinker(obj, dentry->d_name.name);
 
        if (ret_val == YAFFS_OK) {
-               dentry->d_inode->i_nlink--;
+               inode_dec_link_count(dentry->d_inode);
                dir->i_version++;
                yaffs_gross_unlock(dev);
-               mark_inode_dirty(dentry->d_inode);
                update_dir_time(dir);
                return 0;
        }
@@ -1782,7 +1777,7 @@ static int yaffs_link(struct dentry *old_dentry, struct inode *dir,
                                   obj);
 
        if (link) {
-               old_dentry->d_inode->i_nlink = yaffs_get_obj_link_count(obj);
+               set_nlink(old_dentry->d_inode, yaffs_get_obj_link_count(obj));
                d_instantiate(dentry, old_dentry->d_inode);
                atomic_inc(&old_dentry->d_inode->i_count);
                yaffs_trace(YAFFS_TRACE_OS,
@@ -1812,6 +1807,14 @@ static int yaffs_symlink(struct inode *dir, struct dentry *dentry,
 
        yaffs_trace(YAFFS_TRACE_OS, "yaffs_symlink");
 
+       if (strnlen(dentry->d_name.name, YAFFS_MAX_NAME_LENGTH + 1) >
+                               YAFFS_MAX_NAME_LENGTH)
+               return -ENAMETOOLONG;
+
+       if (strnlen(symname, YAFFS_MAX_ALIAS_LENGTH + 1) >
+                               YAFFS_MAX_ALIAS_LENGTH)
+               return -ENAMETOOLONG;
+
        dev = yaffs_inode_to_obj(dir)->my_dev;
        yaffs_gross_lock(dev);
        obj = yaffs_create_symlink(yaffs_inode_to_obj(dir), dentry->d_name.name,
@@ -1833,7 +1836,9 @@ static int yaffs_symlink(struct inode *dir, struct dentry *dentry,
        return -ENOMEM;
 }
 
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 34))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
+static int yaffs_sync_object(struct file *file, loff_t start, loff_t end, int datasync)
+#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 34))
 static int yaffs_sync_object(struct file *file, int datasync)
 #else
 static int yaffs_sync_object(struct file *file, struct dentry *dentry,
@@ -1898,10 +1903,8 @@ static int yaffs_rename(struct inode *old_dir, struct dentry *old_dentry,
        yaffs_gross_unlock(dev);
 
        if (ret_val == YAFFS_OK) {
-               if (target) {
-                       new_dentry->d_inode->i_nlink--;
-                       mark_inode_dirty(new_dentry->d_inode);
-               }
+               if (target)
+                       inode_dec_link_count(new_dentry->d_inode);
 
                update_dir_time(old_dir);
                if (old_dir != new_dir)
@@ -1921,10 +1924,11 @@ static int yaffs_setattr(struct dentry *dentry, struct iattr *attr)
        yaffs_trace(YAFFS_TRACE_OS,
                "yaffs_setattr of object %d",
                yaffs_inode_to_obj(inode)->obj_id);
-
+#if 0
        /* Fail if a requested resize >= 2GB */
        if (attr->ia_valid & ATTR_SIZE && (attr->ia_size >> 31))
                error = -EINVAL;
+#endif
 
        if (error == 0)
                error = inode_change_ok(inode, attr);
@@ -1961,7 +1965,6 @@ static int yaffs_setattr(struct dentry *dentry, struct iattr *attr)
        return error;
 }
 
-#ifdef CONFIG_YAFFS_XATTR
 static int yaffs_setxattr(struct dentry *dentry, const char *name,
                   const void *value, size_t size, int flags)
 {
@@ -2064,7 +2067,6 @@ static ssize_t yaffs_listxattr(struct dentry * dentry, char *buff, size_t size)
        return error;
 }
 
-#endif
 
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
 static int yaffs_statfs(struct dentry *dentry, struct kstatfs *buf)
@@ -2226,7 +2228,7 @@ static int yaffs_do_sync_fs(struct super_block *sb, int request_checkpoint)
  * yaffs_bg_start() launches the background thread.
  * yaffs_bg_stop() cleans up the background thread.
  *
- * NB: 
+ * NB:
  * The thread should only run after the yaffs is initialised
  * The thread should be stopped before yaffs is unmounted.
  * The thread should not do any writing while the fs is in read only.
@@ -2471,8 +2473,10 @@ struct mutex yaffs_context_lock;
 static void yaffs_put_super(struct super_block *sb)
 {
        struct yaffs_dev *dev = yaffs_super_to_dev(sb);
+       struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
 
-       yaffs_trace(YAFFS_TRACE_OS, "yaffs_put_super");
+       yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_ALWAYS,
+                       "yaffs_put_super");
 
        yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_BACKGROUND,
                "Shutting down yaffs background thread");
@@ -2484,9 +2488,6 @@ static void yaffs_put_super(struct super_block *sb)
 
        yaffs_flush_super(sb, 1);
 
-       if (yaffs_dev_to_lc(dev)->put_super_fn)
-               yaffs_dev_to_lc(dev)->put_super_fn(sb);
-
        yaffs_deinitialise(dev);
 
        yaffs_gross_unlock(dev);
@@ -2501,18 +2502,18 @@ static void yaffs_put_super(struct super_block *sb)
        }
 
        kfree(dev);
-}
-
-static void yaffs_mtd_put_super(struct super_block *sb)
-{
-       struct mtd_info *mtd = yaffs_dev_to_mtd(yaffs_super_to_dev(sb));
 
-       if (mtd->sync)
+       if (mtd && mtd->sync)
                mtd->sync(mtd);
 
-       put_mtd_device(mtd);
+       if(mtd)
+               put_mtd_device(mtd);
+
+       yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_ALWAYS,
+                       "yaffs_put_super done");
 }
 
+
 static void yaffs_touch_super(struct yaffs_dev *dev)
 {
        struct super_block *sb = yaffs_dev_to_lc(dev)->super;
@@ -2533,6 +2534,7 @@ struct yaffs_options {
        int lazy_loading_overridden;
        int empty_lost_and_found;
        int empty_lost_and_found_overridden;
+       int disable_summary;
 };
 
 #define MAX_OPT_LEN 30
@@ -2574,6 +2576,8 @@ static int yaffs_parse_options(struct yaffs_options *options,
                } else if (!strcmp(cur_opt, "lazy-loading-on")) {
                        options->lazy_loading_enabled = 1;
                        options->lazy_loading_overridden = 1;
+               } else if (!strcmp(cur_opt, "disable-summary")) {
+                       options->disable_summary = 1;
                } else if (!strcmp(cur_opt, "empty-lost-and-found-off")) {
                        options->empty_lost_and_found = 0;
                        options->empty_lost_and_found_overridden = 1;
@@ -2623,6 +2627,11 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version,
        struct yaffs_linux_context *context_iterator;
        struct list_head *l;
 
+       if (!sb) {
+               printk(KERN_INFO "yaffs: sb is NULL\n");
+               return NULL;
+        }
+
        sb->s_magic = YAFFS_MAGIC;
        sb->s_op = &yaffs_super_ops;
        sb->s_flags |= MS_NOATIME;
@@ -2633,9 +2642,7 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version,
        sb->s_export_op = &yaffs_export_ops;
 #endif
 
-       if (!sb)
-               printk(KERN_INFO "yaffs: sb is NULL\n");
-       else if (!sb->s_dev)
+       if (!sb->s_dev)
                printk(KERN_INFO "yaffs: sb->s_dev is NULL\n");
        else if (!yaffs_devname(sb, devname_buf))
                printk(KERN_INFO "yaffs: devname is NULL\n");
@@ -2705,9 +2712,7 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version,
        yaffs_trace(YAFFS_TRACE_OS, " size %lld", mtd->size);
 #endif
 
-#ifdef CONFIG_YAFFS_AUTO_YAFFS2
-
-       if (yaffs_version == 1 && WRITE_SIZE(mtd) >= 2048) {
+       if (yaffs_auto_select && yaffs_version == 1 && WRITE_SIZE(mtd) >= 2048) {
                yaffs_trace(YAFFS_TRACE_ALWAYS, "auto selecting yaffs2");
                yaffs_version = 2;
        }
@@ -2718,7 +2723,6 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version,
                yaffs_trace(YAFFS_TRACE_ALWAYS, "auto selecting yaffs1");
                yaffs_version = 1;
        }
-#endif
 
        if (yaffs_version == 2) {
                /* Check for version 2 style functions */
@@ -2818,69 +2822,35 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version,
        sb->u.generic_sbp = dev;
 #endif
 
+
        dev->driver_context = mtd;
        param->name = mtd->name;
 
        /* Set up the memory size parameters.... */
 
-       n_blocks =
-           YCALCBLOCKS(mtd->size,
-                       (YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK));
 
-       param->start_block = 0;
-       param->end_block = n_blocks - 1;
-       param->chunks_per_block = YAFFS_CHUNKS_PER_BLOCK;
-       param->total_bytes_per_chunk = YAFFS_BYTES_PER_CHUNK;
        param->n_reserved_blocks = 5;
        param->n_caches = (options.no_cache) ? 0 : 10;
        param->inband_tags = options.inband_tags;
 
-#ifdef CONFIG_YAFFS_DISABLE_LAZY_LOAD
-       param->disable_lazy_load = 1;
-#endif
-#ifdef CONFIG_YAFFS_XATTR
        param->enable_xattr = 1;
-#endif
        if (options.lazy_loading_overridden)
                param->disable_lazy_load = !options.lazy_loading_enabled;
 
-#ifdef CONFIG_YAFFS_DISABLE_TAGS_ECC
-       param->no_tags_ecc = 1;
-#endif
-
-#ifdef CONFIG_YAFFS_DISABLE_BACKGROUND
-#else
        param->defered_dir_update = 1;
-#endif
 
        if (options.tags_ecc_overridden)
                param->no_tags_ecc = !options.tags_ecc_on;
 
-#ifdef CONFIG_YAFFS_EMPTY_LOST_AND_FOUND
        param->empty_lost_n_found = 1;
-#endif
-
-#ifdef CONFIG_YAFFS_DISABLE_BLOCK_REFRESHING
-       param->refresh_period = 0;
-#else
        param->refresh_period = 500;
-#endif
-
-#ifdef CONFIG_YAFFS__ALWAYS_CHECK_CHUNK_ERASED
-       param->always_check_erased = 1;
-#endif
+       param->disable_summary = options.disable_summary;
 
        if (options.empty_lost_and_found_overridden)
                param->empty_lost_n_found = options.empty_lost_and_found;
 
        /* ... and the functions. */
        if (yaffs_version == 2) {
-               param->write_chunk_tags_fn = nandmtd2_write_chunk_tags;
-               param->read_chunk_tags_fn = nandmtd2_read_chunk_tags;
-               param->bad_block_fn = nandmtd2_mark_block_bad;
-               param->query_block_fn = nandmtd2_query_block;
-               yaffs_dev_to_lc(dev)->spare_buffer = 
-                               kmalloc(mtd->oobsize, GFP_NOFS);
                param->is_yaffs2 = 1;
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
                param->total_bytes_per_chunk = mtd->writesize;
@@ -2894,36 +2864,25 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version,
                param->start_block = 0;
                param->end_block = n_blocks - 1;
        } else {
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
-               /* use the MTD interface in yaffs_mtdif1.c */
-               param->write_chunk_tags_fn = nandmtd1_write_chunk_tags;
-               param->read_chunk_tags_fn = nandmtd1_read_chunk_tags;
-               param->bad_block_fn = nandmtd1_mark_block_bad;
-               param->query_block_fn = nandmtd1_query_block;
-#else
-               param->write_chunk_fn = nandmtd_write_chunk;
-               param->read_chunk_fn = nandmtd_read_chunk;
-#endif
                param->is_yaffs2 = 0;
+               n_blocks = YCALCBLOCKS(mtd->size,
+                            YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK);
+
+               param->chunks_per_block = YAFFS_CHUNKS_PER_BLOCK;
+               param->total_bytes_per_chunk = YAFFS_BYTES_PER_CHUNK;
        }
-       /* ... and common functions */
-       param->erase_fn = nandmtd_erase_block;
-       param->initialise_flash_fn = nandmtd_initialise;
 
-       yaffs_dev_to_lc(dev)->put_super_fn = yaffs_mtd_put_super;
+       param->start_block = 0;
+       param->end_block = n_blocks - 1;
+
+       yaffs_mtd_drv_install(dev);
 
        param->sb_dirty_fn = yaffs_touch_super;
-       param->gc_control = yaffs_gc_control_callback;
+       param->gc_control_fn = yaffs_gc_control_callback;
 
        yaffs_dev_to_lc(dev)->super = sb;
 
-#ifndef CONFIG_YAFFS_DOES_ECC
        param->use_nand_ecc = 1;
-#endif
-
-#ifdef CONFIG_YAFFS_DISABLE_WIDE_TNODES
-       param->wide_tnodes_disabled = 1;
-#endif
 
        param->skip_checkpt_rd = options.skip_checkpoint_read;
        param->skip_checkpt_wr = options.skip_checkpoint_write;
@@ -2957,7 +2916,7 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version,
 
        err = yaffs_guts_initialise(dev);
 
-       yaffs_trace(YAFFS_TRACE_OS, 
+       yaffs_trace(YAFFS_TRACE_OS,
                "yaffs_read_super: guts initialised %s",
                (err == YAFFS_OK) ? "OK" : "FAILED");
 
@@ -2967,6 +2926,8 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version,
        if (!context->bg_thread)
                param->defered_dir_update = 0;
 
+       sb->s_maxbytes = yaffs_max_file_size(dev);
+
        /* Release lock before yaffs_get_inode() */
        yaffs_gross_unlock(dev);
 
@@ -3007,7 +2968,13 @@ static int yaffs_internal_read_super_mtd(struct super_block *sb, void *data,
        return yaffs_internal_read_super(1, sb, data, silent) ? 0 : -EINVAL;
 }
 
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
+static struct dentry *yaffs_mount(struct file_system_type *fs_type, int flags,
+        const char *dev_name, void *data)
+{
+    return mount_bdev(fs_type, flags, dev_name, data, yaffs_internal_read_super_mtd);
+}
+#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
 static int yaffs_read_super(struct file_system_type *fs,
                            int flags, const char *dev_name,
                            void *data, struct vfsmount *mnt)
@@ -3030,8 +2997,12 @@ static struct super_block *yaffs_read_super(struct file_system_type *fs,
 static struct file_system_type yaffs_fs_type = {
        .owner = THIS_MODULE,
        .name = "yaffs",
-       .get_sb = yaffs_read_super,
-       .kill_sb = kill_block_super,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
+        .mount = yaffs_mount,
+#else
+        .get_sb = yaffs_read_super,
+#endif
+       .kill_sb = kill_block_super,
        .fs_flags = FS_REQUIRES_DEV,
 };
 #else
@@ -3045,7 +3016,6 @@ static DECLARE_FSTYPE(yaffs_fs_type, "yaffs", yaffs_read_super,
                      FS_REQUIRES_DEV);
 #endif
 
-#ifdef CONFIG_YAFFS_YAFFS2
 
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
 static int yaffs2_internal_read_super_mtd(struct super_block *sb, void *data,
@@ -3054,7 +3024,13 @@ static int yaffs2_internal_read_super_mtd(struct super_block *sb, void *data,
        return yaffs_internal_read_super(2, sb, data, silent) ? 0 : -EINVAL;
 }
 
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
+static struct dentry *yaffs2_mount(struct file_system_type *fs_type, int flags,
+        const char *dev_name, void *data)
+{
+        return mount_bdev(fs_type, flags, dev_name, data, yaffs2_internal_read_super_mtd);
+}
+#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
 static int yaffs2_read_super(struct file_system_type *fs,
                             int flags, const char *dev_name, void *data,
                             struct vfsmount *mnt)
@@ -3076,8 +3052,12 @@ static struct super_block *yaffs2_read_super(struct file_system_type *fs,
 static struct file_system_type yaffs2_fs_type = {
        .owner = THIS_MODULE,
        .name = "yaffs2",
-       .get_sb = yaffs2_read_super,
-       .kill_sb = kill_block_super,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
+        .mount = yaffs2_mount,
+#else
+        .get_sb = yaffs2_read_super,
+#endif
+       .kill_sb = kill_block_super,
        .fs_flags = FS_REQUIRES_DEV,
 };
 #else
@@ -3091,7 +3071,6 @@ static DECLARE_FSTYPE(yaffs2_fs_type, "yaffs2", yaffs2_read_super,
                      FS_REQUIRES_DEV);
 #endif
 
-#endif /* CONFIG_YAFFS_YAFFS2 */
 
 static struct proc_dir_entry *my_proc_entry;
 
@@ -3125,6 +3104,8 @@ static char *yaffs_dump_dev_part0(char *buf, struct yaffs_dev *dev)
 
 static char *yaffs_dump_dev_part1(char *buf, struct yaffs_dev *dev)
 {
+       buf += sprintf(buf, "max file size....... %lld\n",
+                               (long long) yaffs_max_file_size(dev));
        buf += sprintf(buf, "data_bytes_per_chunk. %d\n",
                                dev->data_bytes_per_chunk);
        buf += sprintf(buf, "chunk_grp_bits....... %d\n", dev->chunk_grp_bits);
@@ -3148,8 +3129,8 @@ static char *yaffs_dump_dev_part1(char *buf, struct yaffs_dev *dev)
                                dev->oldest_dirty_gc_count);
        buf += sprintf(buf, "n_gc_blocks.......... %u\n", dev->n_gc_blocks);
        buf += sprintf(buf, "bg_gcs............... %u\n", dev->bg_gcs);
-       buf += sprintf(buf, "n_retired_writes..... %u\n",
-                               dev->n_retired_writes);
+       buf += sprintf(buf, "n_retried_writes..... %u\n",
+                               dev->n_retried_writes);
        buf += sprintf(buf, "n_retired_blocks..... %u\n",
                                dev->n_retired_blocks);
        buf += sprintf(buf, "n_ecc_fixed.......... %u\n", dev->n_ecc_fixed);
@@ -3164,6 +3145,8 @@ static char *yaffs_dump_dev_part1(char *buf, struct yaffs_dev *dev)
                                dev->n_unlinked_files);
        buf += sprintf(buf, "refresh_count........ %u\n", dev->refresh_count);
        buf += sprintf(buf, "n_bg_deletions....... %u\n", dev->n_bg_deletions);
+       buf += sprintf(buf, "tags_used............ %u\n", dev->tags_used);
+       buf += sprintf(buf, "summary_used......... %u\n", dev->summary_used);
 
        return buf;
 }
@@ -3390,12 +3373,6 @@ static int __init init_yaffs_fs(void)
        yaffs_trace(YAFFS_TRACE_ALWAYS,
                "yaffs built " __DATE__ " " __TIME__ " Installing.");
 
-#ifdef CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED
-       yaffs_trace(YAFFS_TRACE_ALWAYS,
-               " \n\n\n\nYAFFS-WARNING CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED selected.\n\n\n\n"
-       );
-#endif
-
        mutex_init(&yaffs_context_lock);
 
        /* Install the proc_fs entries */
@@ -3462,5 +3439,5 @@ module_init(init_yaffs_fs)
     module_exit(exit_yaffs_fs)
 
     MODULE_DESCRIPTION("YAFFS2 - a NAND specific flash file system");
-MODULE_AUTHOR("Charles Manning, Aleph One Ltd., 2002-2010");
+MODULE_AUTHOR("Charles Manning, Aleph One Ltd., 2002-2011");
 MODULE_LICENSE("GPL");