/*
* 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>
#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>
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);
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)
struct yaffs_obj *obj = NULL;
struct yaffs_dev *dev;
struct yaffs_obj *parent = yaffs_inode_to_obj(dir);
- int error = -ENOSPC;
+ int error;
uid_t uid = current->cred->fsuid;
gid_t gid =
(dir->i_mode & S_ISGID) ? dir->i_gid : current->cred->fsgid;
if ((dir->i_mode & S_ISGID) && S_ISDIR(mode))
mode |= S_ISGID;
- if (parent) {
- yaffs_trace(YAFFS_TRACE_OS,
- "yaffs_mknod: parent object %d type %d",
- parent->obj_id, parent->variant_type);
- } else {
+ if (!parent) {
yaffs_trace(YAFFS_TRACE_OS,
"yaffs_mknod: could not get parent object");
return -EPERM;
}
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_mknod: parent object %d type %d",
+ parent->obj_id, parent->variant_type);
+
yaffs_trace(YAFFS_TRACE_OS,
"yaffs_mknod: making oject for %s, mode %x dev %x",
dentry->d_name.name, mode, rdev);
yaffs_gross_lock(dev);
+ if (yaffs_get_n_free_chunks(dev) < 1) {
+ error = -ENOSPC;
+ goto err_out;
+ }
+
switch (mode & S_IFMT) {
default:
/* Special (socket, fifo, device...) */
break;
}
+ if (!obj) {
+ error = -ENOMEM;
+ goto err_out;
+ }
+
/* Can not call yaffs_get_inode() with gross lock held */
yaffs_gross_unlock(dev);
- if (obj) {
- inode = yaffs_get_inode(dir->i_sb, mode, rdev, obj);
- d_instantiate(dentry, inode);
- update_dir_time(dir);
- yaffs_trace(YAFFS_TRACE_OS,
- "yaffs_mknod created object %d count = %d",
- obj->obj_id, atomic_read(&inode->i_count));
- error = 0;
- yaffs_fill_inode_from_obj(dir, parent);
- } else {
- yaffs_trace(YAFFS_TRACE_OS, "yaffs_mknod failed making object");
- error = -ENOMEM;
- }
+ inode = yaffs_get_inode(dir->i_sb, mode, rdev, obj);
+ d_instantiate(dentry, inode);
+ update_dir_time(dir);
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_mknod created object %d count = %d",
+ obj->obj_id, atomic_read(&inode->i_count));
+ yaffs_fill_inode_from_obj(dir, parent);
+ return 0;
+
+err_out:
+ yaffs_gross_unlock(dev);
+ yaffs_trace(YAFFS_TRACE_OS, "yaffs_mknod error %d", error);
return error;
+
}
static int yaffs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
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,
{
struct yaffs_obj *obj;
struct yaffs_dev *dev;
+ struct inode *inode;
uid_t uid = current->cred->fsuid;
gid_t gid =
(dir->i_mode & S_ISGID) ? dir->i_gid : current->cred->fsgid;
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,
S_IFLNK | S_IRWXUGO, uid, gid, symname);
yaffs_gross_unlock(dev);
- if (obj) {
- struct inode *inode;
-
- inode = yaffs_get_inode(dir->i_sb, obj->yst_mode, 0, obj);
- d_instantiate(dentry, inode);
- update_dir_time(dir);
- yaffs_trace(YAFFS_TRACE_OS, "symlink created OK");
- return 0;
- } else {
+ if (!obj) {
yaffs_trace(YAFFS_TRACE_OS, "symlink not created");
+ return -ENOMEM;
}
- return -ENOMEM;
+ inode = yaffs_get_inode(dir->i_sb, obj->yst_mode, 0, obj);
+ d_instantiate(dentry, inode);
+ update_dir_time(dir);
+ yaffs_trace(YAFFS_TRACE_OS, "symlink created OK");
+
+ return 0;
}
static struct dentry *yaffs_lookup(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;
}
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;
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)
struct inode *inode = dentry->d_inode;
int error = 0;
struct yaffs_dev *dev;
+ int result;
yaffs_trace(YAFFS_TRACE_OS,
"yaffs_setattr of object %d",
if (attr->ia_valid & ATTR_SIZE && (attr->ia_size >> 31))
error = -EINVAL;
- if (error == 0)
+ if (!error)
error = inode_change_ok(inode, attr);
- if (error == 0) {
- int result;
- if (!error) {
- setattr_copy(inode, attr);
- yaffs_trace(YAFFS_TRACE_OS, "inode_setattr called");
- if (attr->ia_valid & ATTR_SIZE) {
- truncate_setsize(inode, attr->ia_size);
- inode->i_blocks = (inode->i_size + 511) >> 9;
- }
+
+ if (!error) {
+ setattr_copy(inode, attr);
+ yaffs_trace(YAFFS_TRACE_OS, "inode_setattr called");
+ if (attr->ia_valid & ATTR_SIZE) {
+ truncate_setsize(inode, attr->ia_size);
+ inode->i_blocks = (inode->i_size + 511) >> 9;
}
dev = yaffs_inode_to_obj(inode)->my_dev;
if (attr->ia_valid & ATTR_SIZE) {
(int)(attr->ia_size),
(int)(attr->ia_size));
}
+
yaffs_gross_lock(dev);
result = yaffs_set_attribs(yaffs_inode_to_obj(inode), attr);
- if (result == YAFFS_OK)
- error = 0;
- else
+ if (result != YAFFS_OK)
error = -EPERM;
yaffs_gross_unlock(dev);
}
return error;
}
-#ifdef CONFIG_YAFFS_XATTR
static int yaffs_setxattr(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
{
struct inode *inode = dentry->d_inode;
- int error = 0;
+ int error;
struct yaffs_dev *dev;
struct yaffs_obj *obj = yaffs_inode_to_obj(inode);
yaffs_trace(YAFFS_TRACE_OS, "yaffs_setxattr of object %d", obj->obj_id);
- if (error == 0) {
- int result;
- dev = obj->my_dev;
- yaffs_gross_lock(dev);
- result = yaffs_set_xattrib(obj, name, value, size, flags);
- if (result == YAFFS_OK)
- error = 0;
- else if (result < 0)
- error = result;
- yaffs_gross_unlock(dev);
- }
+ dev = obj->my_dev;
+ yaffs_gross_lock(dev);
+ error = yaffs_set_xattrib(obj, name, value, size, flags);
+ yaffs_gross_unlock(dev);
+
yaffs_trace(YAFFS_TRACE_OS, "yaffs_setxattr done returning %d", error);
return error;
void *buff, size_t size)
{
struct inode *inode = dentry->d_inode;
- int error = 0;
+ int error;
struct yaffs_dev *dev;
struct yaffs_obj *obj = yaffs_inode_to_obj(inode);
"yaffs_getxattr \"%s\" from object %d",
name, obj->obj_id);
- if (error == 0) {
- dev = obj->my_dev;
- yaffs_gross_lock(dev);
- error = yaffs_get_xattrib(obj, name, buff, size);
- yaffs_gross_unlock(dev);
- }
+ dev = obj->my_dev;
+ yaffs_gross_lock(dev);
+ error = yaffs_get_xattrib(obj, name, buff, size);
+ yaffs_gross_unlock(dev);
+
yaffs_trace(YAFFS_TRACE_OS, "yaffs_getxattr done returning %d", error);
return error;
static int yaffs_removexattr(struct dentry *dentry, const char *name)
{
struct inode *inode = dentry->d_inode;
- int error = 0;
+ int error;
struct yaffs_dev *dev;
struct yaffs_obj *obj = yaffs_inode_to_obj(inode);
yaffs_trace(YAFFS_TRACE_OS,
"yaffs_removexattr of object %d", obj->obj_id);
- if (error == 0) {
- int result;
- dev = obj->my_dev;
- yaffs_gross_lock(dev);
- result = yaffs_remove_xattrib(obj, name);
- if (result == YAFFS_OK)
- error = 0;
- else if (result < 0)
- error = result;
- yaffs_gross_unlock(dev);
- }
+ dev = obj->my_dev;
+ yaffs_gross_lock(dev);
+ error = yaffs_remove_xattrib(obj, name);
+ yaffs_gross_unlock(dev);
+
yaffs_trace(YAFFS_TRACE_OS,
"yaffs_removexattr done returning %d", error);
static ssize_t yaffs_listxattr(struct dentry *dentry, char *buff, size_t size)
{
struct inode *inode = dentry->d_inode;
- int error = 0;
+ int error;
struct yaffs_dev *dev;
struct yaffs_obj *obj = yaffs_inode_to_obj(inode);
yaffs_trace(YAFFS_TRACE_OS,
"yaffs_listxattr of object %d", obj->obj_id);
- if (error == 0) {
- dev = obj->my_dev;
- yaffs_gross_lock(dev);
- error = yaffs_list_xattrib(obj, buff, size);
- yaffs_gross_unlock(dev);
- }
+ dev = obj->my_dev;
+ yaffs_gross_lock(dev);
+ error = yaffs_list_xattrib(obj, buff, size);
+ yaffs_gross_unlock(dev);
+
yaffs_trace(YAFFS_TRACE_OS,
"yaffs_listxattr done returning %d", error);
return error;
}
-#endif
-
static const struct inode_operations yaffs_dir_inode_operations = {
.create = yaffs_create,
.lookup = yaffs_lookup,
.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
struct yaffs_search_context *sc =
kmalloc(sizeof(struct yaffs_search_context), GFP_NOFS);
- if (sc) {
- sc->dir_obj = dir;
- sc->dev = dev;
- if (list_empty(&sc->dir_obj->variant.dir_variant.children))
- sc->next_return = NULL;
- else
- sc->next_return =
- list_entry(dir->variant.dir_variant.children.next,
- struct yaffs_obj, siblings);
- INIT_LIST_HEAD(&sc->others);
- list_add(&sc->others, &(yaffs_dev_to_lc(dev)->search_contexts));
- }
+ if (!sc)
+ return NULL;
+
+ sc->dir_obj = dir;
+ sc->dev = dev;
+ if (list_empty(&sc->dir_obj->variant.dir_variant.children))
+ sc->next_return = NULL;
+ else
+ sc->next_return =
+ list_entry(dir->variant.dir_variant.children.next,
+ struct yaffs_obj, siblings);
+ INIT_LIST_HEAD(&sc->others);
+ list_add(&sc->others, &(yaffs_dev_to_lc(dev)->search_contexts));
+
return sc;
}
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;
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);
(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);
/* This should not happen */
yaffs_trace(YAFFS_TRACE_OS,
"yaffs_file_write: hey obj is null!");
- return -ENINVAL;
+ return -EINVAL;
}
dev = obj->my_dev;
bytes_in_dev =
((uint64_t)
- ((dev->param.end_block - dev->param.start_block +
- 1))) * ((uint64_t) (dev->param.chunks_per_block *
+ ((dev->param.end_block - dev->param.start_block + 1))) *
+ ((uint64_t) (dev->param.chunks_per_block *
dev->data_bytes_per_chunk));
do_div(bytes_in_dev, sb->s_blocksize);
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 = {
.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,
struct yaffs_obj *obj)
{
- if (inode && obj) {
- /* Check mode against the variant type
- * and attempt to repair if broken. */
- u32 mode = obj->yst_mode;
- switch (obj->variant_type) {
- case YAFFS_OBJECT_TYPE_FILE:
- if (!S_ISREG(mode)) {
- obj->yst_mode &= ~S_IFMT;
- obj->yst_mode |= S_IFREG;
- }
+ u32 mode;
- break;
- case YAFFS_OBJECT_TYPE_SYMLINK:
- if (!S_ISLNK(mode)) {
- obj->yst_mode &= ~S_IFMT;
- obj->yst_mode |= S_IFLNK;
- }
+ if (!inode || !obj) {
+ yaffs_trace(YAFFS_TRACE_OS,
+ "yaffs_fill_inode invalid parameters");
+ return;
+ }
- break;
- case YAFFS_OBJECT_TYPE_DIRECTORY:
- if (!S_ISDIR(mode)) {
- obj->yst_mode &= ~S_IFMT;
- obj->yst_mode |= S_IFDIR;
- }
+ /* Check mode against the variant type
+ * and attempt to repair if broken. */
+ mode = obj->yst_mode;
- break;
- case YAFFS_OBJECT_TYPE_UNKNOWN:
- case YAFFS_OBJECT_TYPE_HARDLINK:
- case YAFFS_OBJECT_TYPE_SPECIAL:
- default:
- /* TODO? */
- break;
+ switch (obj->variant_type) {
+ case YAFFS_OBJECT_TYPE_FILE:
+ if (!S_ISREG(mode)) {
+ obj->yst_mode &= ~S_IFMT;
+ obj->yst_mode |= S_IFREG;
}
-
- inode->i_flags |= S_NOATIME;
-
- inode->i_ino = obj->obj_id;
- inode->i_mode = obj->yst_mode;
- inode->i_uid = obj->yst_uid;
- inode->i_gid = obj->yst_gid;
-
- inode->i_rdev = old_decode_dev(obj->yst_rdev);
-
- inode->i_atime.tv_sec = (time_t) (obj->yst_atime);
- inode->i_atime.tv_nsec = 0;
- inode->i_mtime.tv_sec = (time_t) obj->yst_mtime;
- inode->i_mtime.tv_nsec = 0;
- inode->i_ctime.tv_sec = (time_t) obj->yst_ctime;
- 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);
-
- 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,
- (int)inode->i_size, atomic_read(&inode->i_count));
-
- switch (obj->yst_mode & S_IFMT) {
- default: /* fifo, device or socket */
- init_special_inode(inode, obj->yst_mode,
- old_decode_dev(obj->yst_rdev));
- break;
- case S_IFREG: /* file */
- inode->i_op = &yaffs_file_inode_operations;
- inode->i_fop = &yaffs_file_operations;
- inode->i_mapping->a_ops =
- &yaffs_file_address_operations;
- break;
- case S_IFDIR: /* directory */
- inode->i_op = &yaffs_dir_inode_operations;
- inode->i_fop = &yaffs_dir_operations;
- break;
- case S_IFLNK: /* symlink */
- inode->i_op = &yaffs_symlink_inode_operations;
- break;
+ break;
+ case YAFFS_OBJECT_TYPE_SYMLINK:
+ if (!S_ISLNK(mode)) {
+ obj->yst_mode &= ~S_IFMT;
+ obj->yst_mode |= S_IFLNK;
}
+ break;
+ case YAFFS_OBJECT_TYPE_DIRECTORY:
+ if (!S_ISDIR(mode)) {
+ obj->yst_mode &= ~S_IFMT;
+ obj->yst_mode |= S_IFDIR;
+ }
+ break;
+ case YAFFS_OBJECT_TYPE_UNKNOWN:
+ case YAFFS_OBJECT_TYPE_HARDLINK:
+ case YAFFS_OBJECT_TYPE_SPECIAL:
+ default:
+ /* TODO? */
+ break;
+ }
- yaffs_inode_to_obj_lv(inode) = obj;
- obj->my_inode = inode;
+ inode->i_flags |= S_NOATIME;
+ inode->i_ino = obj->obj_id;
+ inode->i_mode = obj->yst_mode;
+ inode->i_uid = obj->yst_uid;
+ inode->i_gid = obj->yst_gid;
- } else {
- yaffs_trace(YAFFS_TRACE_OS,
- "yaffs_fill_inode invalid parameters");
+ inode->i_rdev = old_decode_dev(obj->yst_rdev);
+
+ inode->i_atime.tv_sec = (time_t) (obj->yst_atime);
+ inode->i_atime.tv_nsec = 0;
+ inode->i_mtime.tv_sec = (time_t) obj->yst_mtime;
+ inode->i_mtime.tv_nsec = 0;
+ inode->i_ctime.tv_sec = (time_t) obj->yst_ctime;
+ inode->i_ctime.tv_nsec = 0;
+ inode->i_size = yaffs_get_obj_length(obj);
+ inode->i_blocks = (inode->i_size + 511) >> 9;
+ 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,
+ (int)inode->i_size, atomic_read(&inode->i_count));
+
+ switch (obj->yst_mode & S_IFMT) {
+ default: /* fifo, device or socket */
+ init_special_inode(inode, obj->yst_mode,
+ old_decode_dev(obj->yst_rdev));
+ break;
+ case S_IFREG: /* file */
+ inode->i_op = &yaffs_file_inode_operations;
+ inode->i_fop = &yaffs_file_operations;
+ inode->i_mapping->a_ops = &yaffs_file_address_operations;
+ break;
+ case S_IFDIR: /* directory */
+ inode->i_op = &yaffs_dir_inode_operations;
+ inode->i_fop = &yaffs_dir_operations;
+ break;
+ case S_IFLNK: /* symlink */
+ inode->i_op = &yaffs_symlink_inode_operations;
+ break;
}
+
+ yaffs_inode_to_obj_lv(inode) = obj;
+ obj->my_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");
}
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 = {
memset(&options, 0, sizeof(options));
- if (yaffs_parse_options(&options, data_str)) {
+ if (yaffs_parse_options(&options, data_str))
/* Option parsing failed */
return NULL;
- }
sb->s_blocksize = PAGE_CACHE_SIZE;
sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
yaffs_trace(YAFFS_TRACE_OS, " writeoob %p", mtd->write_oob);
yaffs_trace(YAFFS_TRACE_OS, " block_isbad %p", mtd->block_isbad);
yaffs_trace(YAFFS_TRACE_OS, " block_markbad %p", mtd->block_markbad);
- yaffs_trace(YAFFS_TRACE_OS, " write_size %d", mtd->write_size);
+ yaffs_trace(YAFFS_TRACE_OS, " writesize %d", mtd->writesize);
yaffs_trace(YAFFS_TRACE_OS, " oobsize %d", mtd->oobsize);
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->write_size >= 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 &&
- mtd->write_size == 512) {
+ 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 */
return NULL;
}
- if ((mtd->write_size < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
+ if ((mtd->writesize < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
mtd->oobsize < YAFFS_MIN_YAFFS2_SPARE_SIZE) &&
!options.inband_tags) {
yaffs_trace(YAFFS_TRACE_ALWAYS,
return NULL;
}
- if (mtd->write_size < YAFFS_BYTES_PER_CHUNK ||
+ if (mtd->writesize < YAFFS_BYTES_PER_CHUNK ||
mtd->oobsize != YAFFS_BYTES_PER_SPARE) {
yaffs_trace(YAFFS_TRACE_ALWAYS,
"MTD device does not support have the right page sizes");
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;
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;
mutex_lock(&yaffs_context_lock);
/* Get a mount id */
- found = 0;
- for (mount_id = 0; !found; mount_id++) {
+ for (mount_id = 0, found = 0; !found; mount_id++) {
found = 1;
list_for_each(l, &yaffs_context_list) {
context_iterator =
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);
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;
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 +=
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);
}
-/**
- * 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 {
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 */
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 {
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");