yaffs all timothy_tests makefiles are working. threading test is broken.
[yaffs2.git] / yaffs_vfs_single.c
index 724bd3f..145517b 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/init.h>
 #include <linux/fs.h>
 #include <linux/proc_fs.h>
-#include <linux/smp_lock.h>
 #include <linux/pagemap.h>
 #include <linux/mtd/mtd.h>
 #include <linux/interrupt.h>
@@ -72,6 +71,7 @@ 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 */
 module_param(yaffs_trace_mask, uint, 0644);
@@ -79,6 +79,7 @@ module_param(yaffs_wr_attempts, uint, 0644);
 module_param(yaffs_auto_checkpoint, uint, 0644);
 module_param(yaffs_gc_control, uint, 0644);
 module_param(yaffs_bg_enable, uint, 0644);
+module_param(yaffs_auto_select, uint, 0644);
 
 #define yaffs_devname(sb, buf) bdevname(sb->s_bdev, buf)
 
@@ -305,7 +306,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,
@@ -336,6 +337,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,
@@ -417,10 +426,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;
        }
@@ -428,7 +436,8 @@ static int yaffs_unlink(struct inode *dir, struct dentry *dentry)
        return -ENOTEMPTY;
 }
 
-static int yaffs_sync_object(struct file *file, int datasync)
+static int yaffs_sync_object(struct file *file,
+                               loff_t start, loff_t end, int datasync)
 {
 
        struct yaffs_obj *obj;
@@ -484,10 +493,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)
@@ -542,7 +549,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)
 {
@@ -627,8 +633,6 @@ static ssize_t yaffs_listxattr(struct dentry *dentry, char *buff, size_t size)
        return error;
 }
 
-#endif
-
 static const struct inode_operations yaffs_dir_inode_operations = {
        .create = yaffs_create,
        .lookup = yaffs_lookup,
@@ -640,12 +644,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
 };
 /*-----------------------------------------------------------------*/
 /* Directory search context allows us to unlock access to yaffs during
@@ -1096,12 +1098,14 @@ static int yaffs_readpage_nolock(struct file *f, struct page *pg)
        unsigned char *pg_buf;
        int ret;
        struct yaffs_dev *dev;
+       loff_t pos = ((loff_t) pg->index) << PAGE_CACHE_SHIFT;
 
        yaffs_trace(YAFFS_TRACE_OS,
-               "yaffs_readpage_nolock at %08x, size %08x",
-               (unsigned)(pg->index << PAGE_CACHE_SHIFT),
+               "yaffs_readpage_nolock at %lld, size %08x",
+               (long long)pos,
                (unsigned)PAGE_CACHE_SIZE);
 
+
        obj = yaffs_dentry_to_obj(f->f_dentry);
 
        dev = obj->my_dev;
@@ -1113,8 +1117,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);
 
@@ -1217,7 +1220,8 @@ static int yaffs_writepage(struct page *page, struct writeback_control *wbc)
                (int)obj->variant.file_variant.file_size, (int)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);
 
@@ -1801,12 +1805,10 @@ static const struct address_space_operations yaffs_file_address_operations = {
 
 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 = {
@@ -1814,12 +1816,10 @@ static const struct inode_operations yaffs_symlink_inode_operations = {
        .follow_link = yaffs_follow_link,
        .put_link = yaffs_put_link,
        .setattr = yaffs_setattr,
-#ifdef CONFIG_YAFFS_XATTR
        .setxattr = yaffs_setxattr,
        .getxattr = yaffs_getxattr,
        .listxattr = yaffs_listxattr,
        .removexattr = yaffs_removexattr,
-#endif
 };
 
 static void yaffs_fill_inode_from_obj(struct inode *inode,
@@ -1880,7 +1880,7 @@ static void yaffs_fill_inode_from_obj(struct inode *inode,
        inode->i_ctime.tv_nsec = 0;
        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",
                inode->i_mode, inode->i_uid, inode->i_gid,
@@ -1912,6 +1912,7 @@ static void yaffs_fill_inode_from_obj(struct inode *inode,
 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");
 
@@ -1941,16 +1942,14 @@ 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);
 }
 
 static const struct super_operations yaffs_super_ops = {
@@ -2060,20 +2059,16 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version,
        yaffs_trace(YAFFS_TRACE_OS, " erasesize %d", mtd->erasesize);
        yaffs_trace(YAFFS_TRACE_OS, " size %lld", mtd->size);
 
-#ifdef CONFIG_YAFFS_AUTO_YAFFS2
-
-       if (yaffs_version == 1 && mtd->writesize >= 2048) {
+       if (yaffs_auto_select && yaffs_version == 1 && mtd->writesize >= 2048) {
                yaffs_trace(YAFFS_TRACE_ALWAYS, "auto selecting yaffs2");
                yaffs_version = 2;
        }
 
-       /* Added NCB 26/5/2006 for completeness */
-       if (yaffs_version == 2 && !options.inband_tags &&
+       if (yaffs_auto_select && yaffs_version == 2 && !options.inband_tags &&
                mtd->writesize == 512) {
                yaffs_trace(YAFFS_TRACE_ALWAYS, "auto selecting yaffs1");
                yaffs_version = 1;
        }
-#endif
 
        if (yaffs_version == 2) {
                /* Check for version 2 style functions */
@@ -2170,40 +2165,19 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version,
        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
 
        if (options.empty_lost_and_found_overridden)
                param->empty_lost_n_found = options.empty_lost_and_found;
@@ -2238,13 +2212,11 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version,
        yaffs_dev_to_lc(dev)->put_super_fn = yaffs_mtd_put_super;
 
        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
 
        param->skip_checkpt_rd = options.skip_checkpoint_read;
        param->skip_checkpt_wr = options.skip_checkpoint_write;
@@ -2287,6 +2259,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);
 
@@ -2326,47 +2300,43 @@ static int yaffs_internal_read_super_mtd(struct super_block *sb, void *data,
        return yaffs_internal_read_super(1, sb, data, silent) ? 0 : -EINVAL;
 }
 
-static int yaffs_read_super(struct file_system_type *fs,
+static struct dentry *yaffs_mount(struct file_system_type *fs,
                            int flags, const char *dev_name,
-                           void *data, struct vfsmount *mnt)
+                           void *data)
 {
-
-       return get_sb_bdev(fs, flags, dev_name, data,
-                          yaffs_internal_read_super_mtd, mnt);
+       return mount_bdev(fs, flags, dev_name, data,
+                          yaffs_internal_read_super_mtd);
 }
 
 static struct file_system_type yaffs_fs_type = {
        .owner = THIS_MODULE,
        .name = "yaffs",
-       .get_sb = yaffs_read_super,
+       .mount = yaffs_mount,
        .kill_sb = kill_block_super,
        .fs_flags = FS_REQUIRES_DEV,
 };
 
-#ifdef CONFIG_YAFFS_YAFFS2
-
 static int yaffs2_internal_read_super_mtd(struct super_block *sb, void *data,
                                          int silent)
 {
        return yaffs_internal_read_super(2, sb, data, silent) ? 0 : -EINVAL;
 }
 
-static int yaffs2_read_super(struct file_system_type *fs,
-                            int flags, const char *dev_name, void *data,
-                            struct vfsmount *mnt)
+static struct dentry *yaffs2_mount(struct file_system_type *fs,
+                            int flags, const char *dev_name, void *data)
 {
-       return get_sb_bdev(fs, flags, dev_name, data,
-                          yaffs2_internal_read_super_mtd, mnt);
+       return mount_bdev(fs, flags, dev_name, data,
+                          yaffs2_internal_read_super_mtd);
 }
 
 static struct file_system_type yaffs2_fs_type = {
        .owner = THIS_MODULE,
        .name = "yaffs2",
-       .get_sb = yaffs2_read_super,
+       .mount = yaffs2_mount,
        .kill_sb = kill_block_super,
        .fs_flags = FS_REQUIRES_DEV,
 };
-#endif /* CONFIG_YAFFS_YAFFS2 */
+
 
 static struct proc_dir_entry *my_proc_entry;
 
@@ -2400,9 +2370,10 @@ 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, "data_bytes_per_chunk.. %d\n",
-                   dev->data_bytes_per_chunk);
+       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);
        buf += sprintf(buf, "chunk_grp_size........ %d\n", dev->chunk_grp_size);
        buf +=
@@ -2427,7 +2398,7 @@ static char *yaffs_dump_dev_part1(char *buf, struct yaffs_dev *dev)
        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);
+           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);
@@ -2505,149 +2476,6 @@ static int yaffs_proc_read(char *page,
 }
 
 
-/**
- * Set the verbosity of the warnings and error messages.
- *
- * Note that the names can only be a..z or _ with the current code.
- */
-
-static struct {
-       char *mask_name;
-       unsigned mask_bitfield;
-} mask_flags[] = {
-       {"allocate", YAFFS_TRACE_ALLOCATE},
-       {"always", YAFFS_TRACE_ALWAYS},
-       {"background", YAFFS_TRACE_BACKGROUND},
-       {"bad_blocks", YAFFS_TRACE_BAD_BLOCKS},
-       {"buffers", YAFFS_TRACE_BUFFERS},
-       {"bug", YAFFS_TRACE_BUG},
-       {"checkpt", YAFFS_TRACE_CHECKPOINT},
-       {"deletion", YAFFS_TRACE_DELETION},
-       {"erase", YAFFS_TRACE_ERASE},
-       {"error", YAFFS_TRACE_ERROR},
-       {"gc_detail", YAFFS_TRACE_GC_DETAIL},
-       {"gc", YAFFS_TRACE_GC},
-       {"lock", YAFFS_TRACE_LOCK},
-       {"mtd", YAFFS_TRACE_MTD},
-       {"nandaccess", YAFFS_TRACE_NANDACCESS},
-       {"os", YAFFS_TRACE_OS},
-       {"scan_debug", YAFFS_TRACE_SCAN_DEBUG},
-       {"scan", YAFFS_TRACE_SCAN},
-       {"mount", YAFFS_TRACE_MOUNT},
-       {"tracing", YAFFS_TRACE_TRACING},
-       {"sync", YAFFS_TRACE_SYNC},
-       {"write", YAFFS_TRACE_WRITE},
-       {"verify", YAFFS_TRACE_VERIFY},
-       {"verify_nand", YAFFS_TRACE_VERIFY_NAND},
-       {"verify_full", YAFFS_TRACE_VERIFY_FULL},
-       {"verify_all", YAFFS_TRACE_VERIFY_ALL},
-       {"all", 0xffffffff},
-       {"none", 0},
-       {NULL, 0},
-};
-
-#define MAX_MASK_NAME_LENGTH 40
-static int yaffs_proc_write_trace_options(struct file *file, const char *buf,
-                                         unsigned long count, void *data)
-{
-       unsigned rg = 0, mask_bitfield;
-       char *end;
-       char *mask_name;
-       const char *x;
-       char substring[MAX_MASK_NAME_LENGTH + 1];
-       int i;
-       int done = 0;
-       int add, len = 0;
-       int pos = 0;
-
-       rg = yaffs_trace_mask;
-
-       while (!done && (pos < count)) {
-               done = 1;
-               while ((pos < count) && isspace(buf[pos]))
-                       pos++;
-
-               switch (buf[pos]) {
-               case '+':
-               case '-':
-               case '=':
-                       add = buf[pos];
-                       pos++;
-                       break;
-
-               default:
-                       add = ' ';
-                       break;
-               }
-               mask_name = NULL;
-
-               mask_bitfield = simple_strtoul(buf + pos, &end, 0);
-
-               if (end > buf + pos) {
-                       mask_name = "numeral";
-                       len = end - (buf + pos);
-                       pos += len;
-                       done = 0;
-               } else {
-                       for (x = buf + pos, i = 0;
-                            (*x == '_' || (*x >= 'a' && *x <= 'z')) &&
-                            i < MAX_MASK_NAME_LENGTH; x++, i++, pos++)
-                               substring[i] = *x;
-                       substring[i] = '\0';
-
-                       for (i = 0; mask_flags[i].mask_name != NULL; i++) {
-                               if (strcmp(substring, mask_flags[i].mask_name)
-                                   == 0) {
-                                       mask_name = mask_flags[i].mask_name;
-                                       mask_bitfield =
-                                           mask_flags[i].mask_bitfield;
-                                       done = 0;
-                                       break;
-                               }
-                       }
-               }
-
-               if (mask_name != NULL) {
-                       done = 0;
-                       switch (add) {
-                       case '-':
-                               rg &= ~mask_bitfield;
-                               break;
-                       case '+':
-                               rg |= mask_bitfield;
-                               break;
-                       case '=':
-                               rg = mask_bitfield;
-                               break;
-                       default:
-                               rg |= mask_bitfield;
-                               break;
-                       }
-               }
-       }
-
-       yaffs_trace_mask = rg | YAFFS_TRACE_ALWAYS;
-
-       printk(KERN_DEBUG "new trace = 0x%08X\n", yaffs_trace_mask);
-
-       if (rg & YAFFS_TRACE_ALWAYS) {
-               for (i = 0; mask_flags[i].mask_name != NULL; i++) {
-                       char flag;
-                       flag = ((rg & mask_flags[i].mask_bitfield) ==
-                               mask_flags[i].mask_bitfield) ? '+' : '-';
-                       printk(KERN_DEBUG "%c%s\n", flag,
-                              mask_flags[i].mask_name);
-               }
-       }
-
-       return count;
-}
-
-static int yaffs_proc_write(struct file *file, const char *buf,
-                           unsigned long count, void *data)
-{
-       return yaffs_proc_write_trace_options(file, buf, count, data);
-}
 
 /* Stuff to handle installation of file systems */
 struct file_system_to_install {
@@ -2669,11 +2497,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\nYAFFS-WARNING CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED selected.\n\n\n");
-#endif
-
        mutex_init(&yaffs_context_lock);
 
        /* Install the proc_fs entries */
@@ -2681,7 +2504,7 @@ static int __init init_yaffs_fs(void)
                                          S_IRUGO | S_IFREG, NULL);
 
        if (my_proc_entry) {
-               my_proc_entry->write_proc = yaffs_proc_write;
+               my_proc_entry->write_proc = NULL;
                my_proc_entry->read_proc = yaffs_proc_read;
                my_proc_entry->data = NULL;
        } else {