X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=blobdiff_plain;f=yaffs_vfs_single.c;h=d77c87dabfd85b3dafa9b9eb9fd9fc5975a5f344;hp=1893125d338f4322ec27bde53a4e1839b1b67cc5;hb=6076b3bffffb8c1b26b41674cd9e6c5b7eeb1293;hpb=6820610d6b3ea887af57fbd9706fff78923a2115 diff --git a/yaffs_vfs_single.c b/yaffs_vfs_single.c index 1893125..d77c87d 100644 --- a/yaffs_vfs_single.c +++ b/yaffs_vfs_single.c @@ -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 @@ -36,14 +36,12 @@ * a single version and should not include any multi-version code. */ #include - #include #include #include #include #include #include -#include #include #include #include @@ -54,27 +52,8 @@ #include #include #include - #include - #include - -#define yaffs_devname(sb, buf) bdevname(sb->s_bdev, buf) - -#define YPROC_ROOT NULL - -#define Y_INIT_TIMER(a) init_timer_on_stack(a) - -#define WRITE_SIZE_STR "writesize" -#define WRITE_SIZE(mtd) ((mtd)->writesize) - -static uint32_t YCALCBLOCKS(uint64_t partition_size, uint32_t block_size) -{ - uint64_t result = partition_size; - do_div(result, block_size); - return (uint32_t) result; -} - #include #include @@ -82,9 +61,7 @@ static uint32_t YCALCBLOCKS(uint64_t partition_size, uint32_t block_size) #include "yaffs_trace.h" #include "yaffs_guts.h" #include "yaffs_attribs.h" - #include "yaffs_linux.h" - #include "yaffs_mtdif.h" #include "yaffs_mtdif1.h" #include "yaffs_mtdif2.h" @@ -94,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); @@ -101,16 +79,27 @@ 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) + +static uint32_t YCALCBLOCKS(uint64_t partition_size, uint32_t block_size) +{ + uint64_t result = partition_size; + do_div(result, block_size); + return (uint32_t) result; +} #define yaffs_inode_to_obj_lv(iptr) ((iptr)->i_private) -#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) #define yaffs_super_to_dev(sb) ((struct yaffs_dev *)sb->s_fs_info) #define update_dir_time(dir) do {\ (dir)->i_ctime = (dir)->i_mtime = CURRENT_TIME; \ - } while(0) + } while (0) static unsigned yaffs_gc_control_callback(struct yaffs_dev *dev) @@ -156,7 +145,6 @@ static struct inode *yaffs_iget(struct super_block *sb, unsigned long ino) yaffs_gross_lock(dev); obj = yaffs_find_by_number(dev, inode->i_ino); - yaffs_fill_inode_from_obj(inode, obj); yaffs_gross_unlock(dev); @@ -203,13 +191,10 @@ static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) { struct inode *inode; - 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; @@ -217,16 +202,16 @@ static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, 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); @@ -235,6 +220,11 @@ static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, 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...) */ @@ -259,24 +249,29 @@ static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, 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) @@ -311,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, @@ -335,31 +330,38 @@ static int yaffs_symlink(struct inode *dir, struct dentry *dentry, { 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, @@ -367,7 +369,6 @@ static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry, { struct yaffs_obj *obj; struct inode *inode = NULL; - struct yaffs_dev *dev = yaffs_inode_to_obj(dir)->my_dev; if (current != yaffs_dev_to_lc(dev)->readdir_process) @@ -411,7 +412,6 @@ static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry, static int yaffs_unlink(struct inode *dir, struct dentry *dentry) { int ret_val; - struct yaffs_dev *dev; struct yaffs_obj *obj; @@ -426,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; } @@ -437,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; @@ -450,7 +450,7 @@ static int yaffs_sync_object(struct file *file, int datasync) yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_SYNC, "yaffs_sync_object"); yaffs_gross_lock(dev); - yaffs_flush_file(obj, 1, datasync); + yaffs_flush_file(obj, 1, datasync, 0); yaffs_gross_unlock(dev); return 0; } @@ -493,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) @@ -512,6 +510,7 @@ static int yaffs_setattr(struct dentry *dentry, struct iattr *attr) 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", @@ -521,17 +520,15 @@ static int yaffs_setattr(struct dentry *dentry, struct iattr *attr) 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) { @@ -539,15 +536,12 @@ static int yaffs_setattr(struct dentry *dentry, struct iattr *attr) (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); - } yaffs_trace(YAFFS_TRACE_OS, "yaffs_setattr done returning %d", error); @@ -555,39 +549,31 @@ 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) { 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; } -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) { struct inode *inode = dentry->d_inode; - int error = 0; + int error; struct yaffs_dev *dev; struct yaffs_obj *obj = yaffs_inode_to_obj(inode); @@ -595,13 +581,11 @@ static ssize_t yaffs_getxattr(struct dentry * dentry, const char *name, void *bu "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; @@ -610,56 +594,45 @@ static ssize_t yaffs_getxattr(struct dentry * dentry, const char *name, void *bu 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); return error; } -static ssize_t yaffs_listxattr(struct dentry * dentry, char *buff, size_t size) +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, @@ -671,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 @@ -715,18 +686,21 @@ static struct yaffs_search_context *yaffs_new_search(struct yaffs_obj *dir) struct yaffs_dev *dev = dir->my_dev; 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; } @@ -799,7 +773,6 @@ static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir) unsigned long offset, curoffs; struct yaffs_obj *l; int ret_val = 0; - char name[YAFFS_MAX_NAME_LENGTH + 1]; obj = yaffs_dentry_to_obj(f->f_dentry); @@ -909,16 +882,15 @@ static const struct file_operations yaffs_dir_operations = { static int yaffs_file_flush(struct file *file, fl_owner_t id) { struct yaffs_obj *obj = yaffs_dentry_to_obj(file->f_dentry); - struct yaffs_dev *dev = obj->my_dev; yaffs_trace(YAFFS_TRACE_OS, - "yaffs_file_flush object %d (%s)", + "yaffs_file_flush object %d (%s)", obj->obj_id, obj->dirty ? "dirty" : "clean"); yaffs_gross_lock(dev); - yaffs_flush_file(obj, 1, 0); + yaffs_flush_file(obj, 1, 0, 0); yaffs_gross_unlock(dev); @@ -991,7 +963,6 @@ struct dentry *yaffs2_get_parent(struct dentry *dentry) } } } - return parent; } @@ -1013,7 +984,6 @@ static int yaffs_readlink(struct dentry *dentry, char __user * buffer, { unsigned char *alias; int ret; - struct yaffs_dev *dev = yaffs_dentry_to_obj(dentry)->my_dev; yaffs_gross_lock(dev); @@ -1127,14 +1097,15 @@ static int yaffs_readpage_nolock(struct file *f, struct page *pg) struct yaffs_obj *obj; 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; @@ -1146,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); @@ -1172,6 +1142,7 @@ static int yaffs_readpage_nolock(struct file *f, struct page *pg) static int yaffs_readpage_unlock(struct file *f, struct page *pg) { int ret = yaffs_readpage_nolock(f, pg); + unlock_page(pg); return ret; } @@ -1249,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); @@ -1268,18 +1240,17 @@ static int yaffs_writepage(struct page *page, struct writeback_control *wbc) return (n_written == n_bytes) ? 0 : -ENOSPC; } -/* Space holding and freeing is done to ensure we have space available for +/* Space holding and freeing is done to ensure we have space available for * write_begin/end. * For now we just assume few parallel writes and check against a small * number. - * Todo: need to do this with a counter to handle parallel reads better. + * Todo: need to do this with a counter to handle parallel reads better */ static ssize_t yaffs_hold_space(struct file *f) { struct yaffs_obj *obj; struct yaffs_dev *dev; - int n_free_chunks; obj = yaffs_dentry_to_obj(f->f_dentry); @@ -1315,7 +1286,6 @@ static int yaffs_write_begin(struct file *filp, struct address_space *mapping, { struct page *pg = NULL; pgoff_t index = pos >> PAGE_CACHE_SHIFT; - int ret = 0; int space_held = 0; @@ -1365,7 +1335,7 @@ out: } static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n, - loff_t * pos) + loff_t *pos) { struct yaffs_obj *obj; int n_written, ipos; @@ -1375,11 +1345,11 @@ static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n, obj = yaffs_dentry_to_obj(f->f_dentry); if (!obj) { - /* This should not happen */ + /* This should not happen */ yaffs_trace(YAFFS_TRACE_OS, "yaffs_file_write: hey obj is null!"); - return -ENINVAL; - } + return -EINVAL; + } dev = obj->my_dev; @@ -1415,7 +1385,6 @@ static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n, "yaffs_file_write size updated to %d bytes, %d blocks", ipos, (int)(inode->i_blocks)); } - } yaffs_gross_unlock(dev); return (n_written == 0) && (n > 0) ? -ENOSPC : n_written; @@ -1474,11 +1443,12 @@ static int yaffs_statfs(struct dentry *dentry, struct kstatfs *buf) 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); /* bytes_in_dev becomes the number of blocks */ + do_div(bytes_in_dev, sb->s_blocksize); + /* bytes_in_dev becomes the number of blocks */ buf->f_blocks = bytes_in_dev; bytes_free = ((uint64_t) (yaffs_get_n_free_chunks(dev))) * @@ -1526,7 +1496,7 @@ static void yaffs_flush_inodes(struct super_block *sb) if (obj) { yaffs_trace(YAFFS_TRACE_OS, "flushing obj %d", obj->obj_id); - yaffs_flush_file(obj, 1, 0); + yaffs_flush_file(obj, 1, 0, 0); } } } @@ -1534,12 +1504,13 @@ static void yaffs_flush_inodes(struct super_block *sb) static void yaffs_flush_super(struct super_block *sb, int do_checkpoint) { struct yaffs_dev *dev = yaffs_super_to_dev(sb); + if (!dev) return; yaffs_flush_inodes(sb); yaffs_update_dirty_dirs(dev); - yaffs_flush_whole_cache(dev); + yaffs_flush_whole_cache(dev, 1); if (do_checkpoint) yaffs_checkpoint_save(dev); } @@ -1602,7 +1573,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. @@ -1622,7 +1593,6 @@ static int yaffs_bg_thread_fn(void *data) unsigned long next_gc = now; unsigned long expires; unsigned int urgency; - int gc_result; struct timer_list timer; @@ -1659,12 +1629,12 @@ static int yaffs_bg_thread_fn(void *data) else next_gc = now + HZ * 2; } else { - /* + /* * gc not running so set to next_dir_update * to cut down on wake ups */ next_gc = next_dir_update; - } + } } yaffs_gross_unlock(dev); expires = next_dir_update; @@ -1673,7 +1643,7 @@ static int yaffs_bg_thread_fn(void *data) if (time_before(expires, now)) expires = now + HZ; - Y_INIT_TIMER(&timer); + init_timer_on_stack(&timer); timer.expires = expires + 1; timer.data = (unsigned long)current; timer.function = yaffs_background_waker; @@ -1745,12 +1715,9 @@ static int yaffs_sync_fs(struct super_block *sb, int wait) return 0; } - static LIST_HEAD(yaffs_context_list); struct mutex yaffs_context_lock; - - struct yaffs_options { int inband_tags; int skip_checkpoint_read; @@ -1766,7 +1733,7 @@ struct yaffs_options { #define MAX_OPT_LEN 30 static int yaffs_parse_options(struct yaffs_options *options, - const char *options_str) + const char *options_str) { char cur_opt[MAX_OPT_LEN + 1]; int p; @@ -1824,11 +1791,10 @@ static int yaffs_parse_options(struct yaffs_options *options, error = 1; } } - return error; } -static struct address_space_operations yaffs_file_address_operations = { +static const struct address_space_operations yaffs_file_address_operations = { .readpage = yaffs_readpage, .writepage = yaffs_writepage, .write_begin = yaffs_write_begin, @@ -1839,12 +1805,10 @@ static 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 = { @@ -1852,109 +1816,103 @@ 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) { + u32 mode; - /* 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; - } + if (!inode || !obj) { + yaffs_trace(YAFFS_TRACE_OS, + "yaffs_fill_inode invalid parameters"); + return; + } - break; - case YAFFS_OBJECT_TYPE_SYMLINK: - if (!S_ISLNK(mode)) { - obj->yst_mode &= ~S_IFMT; - obj->yst_mode |= S_IFLNK; - } + /* Check mode against the variant type + * and attempt to repair if broken. */ + mode = obj->yst_mode; - 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; + 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; + 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; - obj->my_inode = inode; + inode->i_rdev = old_decode_dev(obj->yst_rdev); - } else { - yaffs_trace(YAFFS_TRACE_OS, - "yaffs_fill_inode invalid parameters"); + 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"); @@ -1984,24 +1942,62 @@ static void yaffs_put_super(struct super_block *sb) } kfree(dev); + + if (mtd && mtd->sync) + mtd->sync(mtd); + + if (mtd) + put_mtd_device(mtd); } -static void yaffs_mtd_put_super(struct super_block *sb) +/* the function only is used to change dev->read_only when this file system + * is remounted. + */ +static int yaffs_remount_fs(struct super_block *sb, int *flags, char *data) { - struct mtd_info *mtd = yaffs_dev_to_mtd(yaffs_super_to_dev(sb)); + int read_only = 0; + struct mtd_info *mtd; + struct yaffs_dev *dev = 0; - if (mtd->sync) - mtd->sync(mtd); + /* Get the device */ + mtd = get_mtd_device(NULL, MINOR(sb->s_dev)); + if (!mtd) { + yaffs_trace(YAFFS_TRACE_ALWAYS, + "MTD device #%u doesn't appear to exist", + MINOR(sb->s_dev)); + return 1; + } - put_mtd_device(mtd); + /* Check it's NAND */ + if (mtd->type != MTD_NANDFLASH) { + yaffs_trace(YAFFS_TRACE_ALWAYS, + "MTD device is not NAND it's type %d", + mtd->type); + return 1; + } + + read_only = ((*flags & MS_RDONLY) != 0); + if (!read_only && !(mtd->flags & MTD_WRITEABLE)) { + read_only = 1; + printk(KERN_INFO + "yaffs: mtd is read only, setting superblock read only"); + *flags |= MS_RDONLY; + } + + dev = sb->s_fs_info; + dev->read_only = read_only; + + return 0; } + static const struct super_operations yaffs_super_ops = { .statfs = yaffs_statfs, .put_super = yaffs_put_super, .evict_inode = yaffs_evict_inode, .sync_fs = yaffs_sync_fs, .write_super = yaffs_write_super, + .remount_fs = yaffs_remount_fs, }; static struct super_block *yaffs_internal_read_super(int yaffs_version, @@ -2018,11 +2014,8 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version, char *data_str = (char *)data; struct yaffs_linux_context *context = NULL; struct yaffs_param *param; - int read_only = 0; - struct yaffs_options options; - unsigned mount_id; int found; struct yaffs_linux_context *context_iterator; @@ -2031,7 +2024,7 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version, if (!sb) { printk(KERN_INFO "yaffs: sb is NULL\n"); return NULL; - } + } sb->s_magic = YAFFS_MAGIC; sb->s_op = &yaffs_super_ops; @@ -2057,10 +2050,9 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version, 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; @@ -2081,7 +2073,7 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version, /* Get the device */ mtd = get_mtd_device(NULL, MINOR(sb->s_dev)); - if (!mtd) { + if (IS_ERR(mtd)) { yaffs_trace(YAFFS_TRACE_ALWAYS, "MTD device #%u doesn't appear to exist", MINOR(sb->s_dev)); @@ -2102,25 +2094,21 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version, 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, " %s %d", WRITE_SIZE_STR, WRITE_SIZE(mtd)); + 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 && WRITE_SIZE(mtd) >= 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 - && WRITE_SIZE(mtd) == 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 */ @@ -2134,7 +2122,7 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version, return NULL; } - if ((WRITE_SIZE(mtd) < 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, @@ -2151,7 +2139,7 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version, return NULL; } - if (WRITE_SIZE(mtd) < 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"); @@ -2175,15 +2163,11 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version, context = kmalloc(sizeof(struct yaffs_linux_context), GFP_KERNEL); if (!dev || !context) { - if (dev) - kfree(dev); - if (context) - kfree(context); + kfree(dev); + kfree(context); dev = NULL; context = NULL; - } - if (!dev) { /* Deep shit could not allocate device structure */ yaffs_trace(YAFFS_TRACE_ALWAYS, "yaffs_read_super failed trying to allocate yaffs_dev"); @@ -2219,40 +2203,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; @@ -2263,8 +2226,8 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version, 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); + yaffs_dev_to_lc(dev)->spare_buffer = + kmalloc(mtd->oobsize, GFP_NOFS); param->is_yaffs2 = 1; param->total_bytes_per_chunk = mtd->writesize; param->chunks_per_block = mtd->erasesize / mtd->writesize; @@ -2287,26 +2250,23 @@ 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; 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 = - list_entry(l, struct yaffs_linux_context, - context_list); + list_entry(l, struct yaffs_linux_context, + context_list); if (context_iterator->mount_id == mount_id) found = 0; } @@ -2337,6 +2297,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); @@ -2376,53 +2338,50 @@ 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; static char *yaffs_dump_dev_part0(char *buf, struct yaffs_dev *dev) { struct yaffs_param *param = &dev->param; + buf += sprintf(buf, "start_block........... %d\n", param->start_block); buf += sprintf(buf, "end_block............. %d\n", param->end_block); buf += sprintf(buf, "total_bytes_per_chunk. %d\n", @@ -2449,9 +2408,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 += @@ -2476,7 +2436,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); @@ -2524,7 +2484,8 @@ static int yaffs_proc_read(char *page, mutex_lock(&yaffs_context_lock); - /* Locate and print the Nth entry. Order N-squared but N is small. */ + /* Locate and print the Nth entry. + * Order N-squared but N is small. */ list_for_each(item, &yaffs_context_list) { struct yaffs_linux_context *dc = list_entry(item, struct yaffs_linux_context, @@ -2542,7 +2503,7 @@ static int yaffs_proc_read(char *page, buf = yaffs_dump_dev_part0(buf, dev); } else { buf = yaffs_dump_dev_part1(buf, dev); - } + } break; } @@ -2553,149 +2514,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 { @@ -2717,24 +2535,19 @@ 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 */ my_proc_entry = create_proc_entry("yaffs", - S_IRUGO | S_IFREG, YPROC_ROOT); + 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 { return -ENOMEM; - } + } /* Now add the file system entries */ @@ -2772,7 +2585,7 @@ static void __exit exit_yaffs_fs(void) yaffs_trace(YAFFS_TRACE_ALWAYS, "yaffs built " __DATE__ " " __TIME__ " removing."); - remove_proc_entry("yaffs", YPROC_ROOT); + remove_proc_entry("yaffs", NULL); fsinst = fs_to_install; @@ -2786,8 +2599,8 @@ static void __exit exit_yaffs_fs(void) } module_init(init_yaffs_fs) - module_exit(exit_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_DESCRIPTION("YAFFS2 - a NAND specific flash file system"); +MODULE_AUTHOR("Charles Manning, Aleph One Ltd., 2002-2011"); MODULE_LICENSE("GPL");