X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=blobdiff_plain;f=yaffs_vfs_single.c;h=32734a68ee21dfeefda42cd86d5056d7fc8cc848;hp=d5b875314005a36afe115ba7abd656bf6b3eff39;hb=6500cebaa2c93512d544719956af259ca13f83b7;hpb=79d0e028d5b777b2e4cf55d96b737cb024988abe diff --git a/yaffs_vfs_single.c b/yaffs_vfs_single.c index d5b8753..32734a6 100644 --- a/yaffs_vfs_single.c +++ b/yaffs_vfs_single.c @@ -36,7 +36,6 @@ * a single version and should not include any multi-version code. */ #include - #include #include #include @@ -54,30 +53,8 @@ #include #include #include - #include - #include - -#define UnlockPage(p) unlock_page(p) -#define Page_Uptodate(page) test_bit(PG_uptodate, &(page)->flags) - -#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 @@ -85,9 +62,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" @@ -105,15 +80,25 @@ module_param(yaffs_auto_checkpoint, uint, 0644); module_param(yaffs_gc_control, uint, 0644); module_param(yaffs_bg_enable, 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) @@ -159,7 +144,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); @@ -206,12 +190,9 @@ 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; uid_t uid = current->cred->fsuid; gid_t gid = @@ -220,16 +201,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); @@ -265,21 +246,20 @@ static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, /* 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 { + if (!obj) { yaffs_trace(YAFFS_TRACE_OS, "yaffs_mknod failed making object"); - error = -ENOMEM; + return -ENOMEM; } - return error; + 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; } static int yaffs_mkdir(struct inode *dir, struct dentry *dentry, int mode) @@ -338,6 +318,7 @@ 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; @@ -350,19 +331,17 @@ static int yaffs_symlink(struct inode *dir, struct dentry *dentry, 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, @@ -370,7 +349,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) @@ -414,7 +392,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; @@ -515,6 +492,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", @@ -524,17 +502,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) { @@ -542,15 +518,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); @@ -563,34 +536,27 @@ 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); @@ -598,13 +564,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; @@ -613,48 +577,39 @@ 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); @@ -718,18 +673,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; } @@ -786,11 +744,9 @@ static void yaffs_remove_obj_callback(struct yaffs_obj *obj) * the search context to the next object to prevent a hanging pointer. */ list_for_each(i, search_contexts) { - if (i) { - sc = list_entry(i, struct yaffs_search_context, others); - if (sc->next_return == obj) - yaffs_search_advance(sc); - } + sc = list_entry(i, struct yaffs_search_context, others); + if (sc->next_return == obj) + yaffs_search_advance(sc); } } @@ -804,7 +760,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); @@ -914,11 +869,10 @@ 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); @@ -996,7 +950,6 @@ struct dentry *yaffs2_get_parent(struct dentry *dentry) } } } - return parent; } @@ -1018,7 +971,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); @@ -1132,7 +1084,6 @@ 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; yaffs_trace(YAFFS_TRACE_OS, @@ -1177,7 +1128,8 @@ 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); - UnlockPage(pg); + + unlock_page(pg); return ret; } @@ -1273,18 +1225,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); @@ -1320,7 +1271,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; @@ -1334,7 +1284,7 @@ static int yaffs_write_begin(struct file *filp, struct address_space *mapping, } yaffs_trace(YAFFS_TRACE_OS, "start yaffs_write_begin index %d(%x) uptodate %d", - (int)index, (int)index, Page_Uptodate(pg) ? 1 : 0); + (int)index, (int)index, PageUptodate(pg) ? 1 : 0); /* Get fs space */ space_held = yaffs_hold_space(filp); @@ -1346,7 +1296,7 @@ static int yaffs_write_begin(struct file *filp, struct address_space *mapping, /* Update page if required */ - if (!Page_Uptodate(pg)) + if (!PageUptodate(pg)) ret = yaffs_readpage_nolock(filp, pg); if (ret) @@ -1370,7 +1320,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; @@ -1379,6 +1329,13 @@ 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 */ + yaffs_trace(YAFFS_TRACE_OS, + "yaffs_file_write: hey obj is null!"); + return -EINVAL; + } + dev = obj->my_dev; yaffs_gross_lock(dev); @@ -1390,13 +1347,9 @@ static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n, else ipos = *pos; - if (!obj) - yaffs_trace(YAFFS_TRACE_OS, - "yaffs_file_write: hey obj is null!"); - else - yaffs_trace(YAFFS_TRACE_OS, - "yaffs_file_write about to write writing %u(%x) bytes to object %d at %d(%x)", - (unsigned)n, (unsigned)n, obj->obj_id, ipos, ipos); + yaffs_trace(YAFFS_TRACE_OS, + "yaffs_file_write about to write writing %u(%x) bytes to object %d at %d(%x)", + (unsigned)n, (unsigned)n, obj->obj_id, ipos, ipos); n_written = yaffs_wr_file(obj, buf, ipos, n, 0); @@ -1417,7 +1370,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; @@ -1476,11 +1428,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))) * @@ -1536,6 +1489,7 @@ 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; @@ -1604,7 +1558,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. @@ -1624,7 +1578,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; @@ -1661,12 +1614,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; @@ -1675,7 +1628,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; @@ -1747,12 +1700,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; @@ -1768,7 +1718,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; @@ -1826,11 +1776,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, @@ -1865,93 +1814,86 @@ static const struct inode_operations yaffs_symlink_inode_operations = { 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; - } - - 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. */ + u32 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; + 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; + 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; } + + yaffs_inode_to_obj_lv(inode) = obj; + obj->my_inode = inode; } static void yaffs_put_super(struct super_block *sb) @@ -2020,16 +1962,18 @@ 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; struct list_head *l; + if (!sb) { + printk(KERN_INFO "yaffs: sb is NULL\n"); + return NULL; + } + sb->s_magic = YAFFS_MAGIC; sb->s_op = &yaffs_super_ops; sb->s_flags |= MS_NOATIME; @@ -2038,9 +1982,7 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version, sb->s_export_op = &yaffs_export_ops; - if (!sb) - printk(KERN_INFO "yaffs: sb is NULL\n"); - else if (!sb->s_dev) + if (!sb->s_dev) printk(KERN_INFO "yaffs: sb->s_dev is NULL\n"); else if (!yaffs_devname(sb, devname_buf)) printk(KERN_INFO "yaffs: devname is NULL\n"); @@ -2056,10 +1998,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; @@ -2101,21 +2042,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_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_version == 2 && !options.inband_tags && + mtd->writesize == 512) { yaffs_trace(YAFFS_TRACE_ALWAYS, "auto selecting yaffs1"); yaffs_version = 1; } @@ -2133,7 +2074,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, @@ -2150,7 +2091,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"); @@ -2174,10 +2115,8 @@ 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; } @@ -2262,8 +2201,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; @@ -2299,13 +2238,12 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version, 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; } @@ -2422,6 +2360,7 @@ 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", @@ -2523,7 +2462,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, @@ -2541,7 +2481,7 @@ static int yaffs_proc_read(char *page, buf = yaffs_dump_dev_part0(buf, dev); } else { buf = yaffs_dump_dev_part1(buf, dev); - } + } break; } @@ -2562,7 +2502,7 @@ static struct { char *mask_name; unsigned mask_bitfield; } mask_flags[] = { - {"allocate", YAFFS_TRACE_ALLOCATE}, + {"allocate", YAFFS_TRACE_ALLOCATE}, {"always", YAFFS_TRACE_ALWAYS}, {"background", YAFFS_TRACE_BACKGROUND}, {"bad_blocks", YAFFS_TRACE_BAD_BLOCKS}, @@ -2725,7 +2665,7 @@ static int __init init_yaffs_fs(void) /* 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; @@ -2733,7 +2673,7 @@ static int __init init_yaffs_fs(void) my_proc_entry->data = NULL; } else { return -ENOMEM; - } + } /* Now add the file system entries */ @@ -2771,7 +2711,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; @@ -2785,8 +2725,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_DESCRIPTION("YAFFS2 - a NAND specific flash file system"); MODULE_AUTHOR("Charles Manning, Aleph One Ltd., 2002-2010"); MODULE_LICENSE("GPL");