X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=blobdiff_plain;f=yaffs_fs.c;h=a51dc20de633f900f25cf4ba5c8d993142956012;hp=f2f709b1aaa0efdf33cb769fde65391b519bedb6;hb=1ffa02489a63129109b66774681c94fe0a8a946a;hpb=17b102ed84b24f9c45ebdba39cacc73eb39e8cae diff --git a/yaffs_fs.c b/yaffs_fs.c index f2f709b..a51dc20 100644 --- a/yaffs_fs.c +++ b/yaffs_fs.c @@ -1,7 +1,7 @@ /* * YAFFS: Yet Another Flash File System. A NAND-flash specific file system. * - * Copyright (C) 2002-2007 Aleph One Ltd. + * Copyright (C) 2002-2009 Aleph One Ltd. * for Toby Churchill Ltd and Brightstar Engineering * * Created by Charles Manning @@ -32,7 +32,7 @@ */ const char *yaffs_fs_c_version = - "$Id: yaffs_fs.c,v 1.77 2009-03-09 07:25:09 charles Exp $"; + "$Id: yaffs_fs.c,v 1.84 2009-10-14 00:01:56 charles Exp $"; extern const char *yaffs_guts_c_version; #include @@ -163,6 +163,11 @@ static struct inode *yaffs_iget(struct super_block *sb, unsigned long ino); #define yaffs_SuperToDevice(sb) ((yaffs_Device *)sb->u.generic_sbp) #endif + +#define update_dir_time(dir) do {\ + (dir)->i_ctime = (dir)->i_mtime = CURRENT_TIME; \ + } while(0) + static void yaffs_put_super(struct super_block *sb); static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n, @@ -489,8 +494,6 @@ static struct dentry *yaffs_lookup(struct inode *dir, struct dentry *dentry) d_add(dentry, inode); return NULL; - /* return (ERR_PTR(-EIO)); */ - } @@ -586,7 +589,7 @@ static int yaffs_file_flush(struct file *file) yaffs_GrossLock(dev); - yaffs_FlushFile(obj, 1); + yaffs_FlushFile(obj, 1,0); yaffs_GrossUnlock(dev); @@ -623,8 +626,7 @@ static int yaffs_readpage_nolock(struct file *f, struct page *pg) yaffs_GrossLock(dev); - ret = - yaffs_ReadDataFromFile(obj, pg_buf, + ret = yaffs_ReadDataFromFile(obj, pg_buf, pg->index << PAGE_CACHE_SHIFT, PAGE_CACHE_SIZE); @@ -749,7 +751,7 @@ static int yaffs_write_begin(struct file *filp, struct address_space *mapping, T(YAFFS_TRACE_OS, ("start yaffs_write_begin\n")); /* Get a page */ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 28) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28) pg = grab_cache_page_write_begin(mapping, index, flags); #else pg = __grab_cache_page(mapping, index); @@ -1078,7 +1080,7 @@ static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n, } yaffs_GrossUnlock(dev); - return nWritten == 0 ? -ENOSPC : nWritten; + return (nWritten == 0) && (n > 0) ? -ENOSPC : nWritten; } /* Space holding and freeing is done to ensure we have space available for write_begin/end */ @@ -1289,6 +1291,7 @@ static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, if (obj) { inode = yaffs_get_inode(dir->i_sb, mode, rdev, obj); d_instantiate(dentry, inode); + update_dir_time(dir); T(YAFFS_TRACE_OS, ("yaffs_mknod created object %d count = %d\n", obj->objectId, atomic_read(&inode->i_count))); @@ -1342,6 +1345,7 @@ static int yaffs_unlink(struct inode *dir, struct dentry *dentry) dir->i_version++; yaffs_GrossUnlock(dev); mark_inode_dirty(dentry->d_inode); + update_dir_time(dir); return 0; } yaffs_GrossUnlock(dev); @@ -1382,8 +1386,10 @@ static int yaffs_link(struct dentry *old_dentry, struct inode *dir, yaffs_GrossUnlock(dev); - if (link) + if (link){ + update_dir_time(dir); return 0; + } return -EPERM; } @@ -1409,6 +1415,7 @@ static int yaffs_symlink(struct inode *dir, struct dentry *dentry, inode = yaffs_get_inode(dir->i_sb, obj->yst_mode, 0, obj); d_instantiate(dentry, inode); + update_dir_time(dir); T(YAFFS_TRACE_OS, ("symlink created OK\n")); return 0; } else { @@ -1431,7 +1438,7 @@ static int yaffs_sync_object(struct file *file, struct dentry *dentry, T(YAFFS_TRACE_OS, ("yaffs_sync_object\n")); yaffs_GrossLock(dev); - yaffs_FlushFile(obj, 1); + yaffs_FlushFile(obj, 1, datasync); yaffs_GrossUnlock(dev); return 0; } @@ -1481,7 +1488,10 @@ static int yaffs_rename(struct inode *old_dir, struct dentry *old_dentry, new_dentry->d_inode->i_nlink--; mark_inode_dirty(new_dentry->d_inode); } - + + update_dir_time(old_dir); + if(old_dir != new_dir) + update_dir_time(new_dir); return 0; } else { return -ENOTEMPTY; @@ -1586,6 +1596,21 @@ static int yaffs_statfs(struct super_block *sb, struct statfs *buf) } + +static void yaffs_flush_sb_inodes(struct super_block *sb) +{ + struct inode *iptr; + yaffs_Object *obj; + + list_for_each_entry(iptr,&sb->s_inodes, i_sb_list){ + obj = yaffs_InodeToObject(iptr); + if(obj){ + T(YAFFS_TRACE_OS, ("flushing obj %d\n",obj->objectId)); + yaffs_FlushFile(obj,1,0); + } + } +} + static int yaffs_do_sync_fs(struct super_block *sb) { @@ -1597,6 +1622,7 @@ static int yaffs_do_sync_fs(struct super_block *sb) if (dev) { yaffs_FlushEntireDeviceCache(dev); + yaffs_flush_sb_inodes(sb); yaffs_CheckpointSave(dev); } @@ -1786,6 +1812,8 @@ typedef struct { int skip_checkpoint_read; int skip_checkpoint_write; int no_cache; + int tags_ecc_on; + int tags_ecc_overridden; } yaffs_options; #define MAX_OPT_LEN 20 @@ -1801,6 +1829,9 @@ static int yaffs_parse_options(yaffs_options *options, const char *options_str) memset(cur_opt, 0, MAX_OPT_LEN + 1); p = 0; + while(*options_str == ',') + options_str++; + while (*options_str && *options_str != ',') { if (p < MAX_OPT_LEN) { cur_opt[p] = *options_str; @@ -1811,7 +1842,13 @@ static int yaffs_parse_options(yaffs_options *options, const char *options_str) if (!strcmp(cur_opt, "inband-tags")) options->inband_tags = 1; - else if (!strcmp(cur_opt, "no-cache")) + else if (!strcmp(cur_opt, "tags-ecc-off")){ + options->tags_ecc_on = 0; + options->tags_ecc_overridden=1; + } else if (!strcmp(cur_opt, "tags-ecc-on")){ + options->tags_ecc_on = 1; + options->tags_ecc_overridden = 1; + } else if (!strcmp(cur_opt, "no-cache")) options->no_cache = 1; else if (!strcmp(cur_opt, "no-checkpoint-read")) options->skip_checkpoint_read = 1; @@ -2027,6 +2064,12 @@ static struct super_block *yaffs_internal_read_super(int yaffsVersion, dev->nShortOpCaches = (options.no_cache) ? 0 : 10; dev->inbandTags = options.inband_tags; +#ifdef CONFIG_YAFFS_DISABLE_TAGS_ECC + dev->noTagsECC = 1; +#endif + if(options.tags_ecc_overridden) + dev->noTagsECC = !options.tags_ecc_on; + /* ... and the functions. */ if (yaffsVersion == 2) { dev->writeChunkWithTagsToNAND = @@ -2263,6 +2306,7 @@ static char *yaffs_dump_dev(char *buf, yaffs_Device * dev) buf += sprintf(buf, "nBackgroudDeletions %d\n", dev->nBackgroundDeletions); buf += sprintf(buf, "useNANDECC......... %d\n", dev->useNANDECC); + buf += sprintf(buf, "noTagsECC.......... %d\n", dev->noTagsECC); buf += sprintf(buf, "isYaffs2........... %d\n", dev->isYaffs2); buf += sprintf(buf, "inbandTags......... %d\n", dev->inbandTags);