X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=blobdiff_plain;f=yaffs_fs.c;h=625683ca8bcdc4988616bacb261a8efbc77bf6b4;hp=7c04ed3a3de175076f27be67fdb3d995a617cda6;hb=f0193bed34c1323e2894c72ffccc28e7b31215f7;hpb=b027e02d89da77f2977c2af70f661274be3c2228 diff --git a/yaffs_fs.c b/yaffs_fs.c index 7c04ed3..625683c 100644 --- a/yaffs_fs.c +++ b/yaffs_fs.c @@ -32,7 +32,7 @@ */ const char *yaffs_fs_c_version = - "$Id: yaffs_fs.c,v 1.79 2009-03-17 01:12:00 wookey Exp $"; + "$Id: yaffs_fs.c,v 1.88 2009-11-29 21:42:47 charles Exp $"; extern const char *yaffs_guts_c_version; #include @@ -118,7 +118,7 @@ static uint32_t YCALCBLOCKS(uint64_t partition_size, uint32_t block_size) #include "yaffs_mtdif1.h" #include "yaffs_mtdif2.h" -unsigned int yaffs_traceMask = YAFFS_TRACE_BAD_BLOCKS; +unsigned int yaffs_traceMask = YAFFS_TRACE_BAD_BLOCKS | YAFFS_TRACE_ALWAYS; unsigned int yaffs_wr_attempts = YAFFS_WR_ATTEMPTS; unsigned int yaffs_auto_checkpoint = 1; @@ -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, @@ -584,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); @@ -746,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); @@ -1075,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 */ @@ -1286,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))); @@ -1339,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); @@ -1379,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; } @@ -1406,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 { @@ -1428,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; } @@ -1478,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; @@ -1583,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) { @@ -1594,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); } @@ -1783,9 +1812,15 @@ typedef struct { int skip_checkpoint_read; int skip_checkpoint_write; int no_cache; + int tags_ecc_on; + int tags_ecc_overridden; + int lazy_loading_enabled; + int lazy_loading_overridden; + int empty_lost_and_found; + int empty_lost_and_found_overridden; } yaffs_options; -#define MAX_OPT_LEN 20 +#define MAX_OPT_LEN 30 static int yaffs_parse_options(yaffs_options *options, const char *options_str) { char cur_opt[MAX_OPT_LEN + 1]; @@ -1798,6 +1833,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; @@ -1808,7 +1846,25 @@ 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, "lazy-loading-off")){ + options->lazy_loading_enabled = 0; + options->lazy_loading_overridden=1; + } else if (!strcmp(cur_opt, "lazy-loading-on")){ + options->lazy_loading_enabled = 1; + options->lazy_loading_overridden = 1; + } else if (!strcmp(cur_opt, "empty-lost-and-found-off")){ + options->empty_lost_and_found = 0; + options->empty_lost_and_found_overridden=1; + } else if (!strcmp(cur_opt, "empty-lost-and-found-on")){ + options->empty_lost_and_found = 1; + options->empty_lost_and_found_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; @@ -2024,6 +2080,24 @@ 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_LAZY_LOAD + dev->disableLazyLoad = 1; +#endif + if(options.lazy_loading_overridden) + dev->disableLazyLoad = !options.lazy_loading_enabled; + +#ifdef CONFIG_YAFFS_DISABLE_TAGS_ECC + dev->noTagsECC = 1; +#endif + if(options.tags_ecc_overridden) + dev->noTagsECC = !options.tags_ecc_on; + +#ifdef CONFIG_YAFFS_EMPTY_LOST_AND_FOUND + dev->emptyLostAndFound = 1; +#endif + if(options.empty_lost_and_found_overridden) + dev->emptyLostAndFound = options.empty_lost_and_found; + /* ... and the functions. */ if (yaffsVersion == 2) { dev->writeChunkWithTagsToNAND = @@ -2224,7 +2298,7 @@ static DECLARE_FSTYPE(yaffs2_fs_type, "yaffs2", yaffs2_read_super, static struct proc_dir_entry *my_proc_entry; -static char *yaffs_dump_dev(char *buf, yaffs_Device * dev) +static char *yaffs_dump_dev_part0(char *buf, yaffs_Device * dev) { buf += sprintf(buf, "startBlock......... %d\n", dev->startBlock); buf += sprintf(buf, "endBlock........... %d\n", dev->endBlock); @@ -2259,9 +2333,19 @@ static char *yaffs_dump_dev(char *buf, yaffs_Device * dev) buf += sprintf(buf, "nUnlinkedFiles..... %d\n", dev->nUnlinkedFiles); buf += sprintf(buf, "nBackgroudDeletions %d\n", dev->nBackgroundDeletions); + + return buf; +} + + +static char *yaffs_dump_dev_part1(char *buf, yaffs_Device * dev) +{ 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); + buf += sprintf(buf, "emptyLostAndFound.. %d\n", dev->emptyLostAndFound); + buf += sprintf(buf, "disableLazyLoad.... %d\n", dev->disableLazyLoad); return buf; } @@ -2284,27 +2368,35 @@ static int yaffs_proc_read(char *page, *(int *)start = 1; /* Print header first */ - if (step == 0) { + if (step == 0) buf += sprintf(buf, "YAFFS built:" __DATE__ " " __TIME__ "\n%s\n%s\n", yaffs_fs_c_version, yaffs_guts_c_version); - } - - /* hold lock_kernel while traversing yaffs_dev_list */ - lock_kernel(); - - /* Locate and print the Nth entry. Order N-squared but N is small. */ - ylist_for_each(item, &yaffs_dev_list) { - yaffs_Device *dev = ylist_entry(item, yaffs_Device, devList); - if (n < step) { - n++; - continue; + else if (step == 1) + buf += sprintf(buf,"\n"); + else { + step-=2; + + /* hold lock_kernel while traversing yaffs_dev_list */ + lock_kernel(); + + /* Locate and print the Nth entry. Order N-squared but N is small. */ + ylist_for_each(item, &yaffs_dev_list) { + yaffs_Device *dev = ylist_entry(item, yaffs_Device, devList); + if (n < (step & ~1)) { + n+=2; + continue; + } + if((step & 1)==0){ + buf += sprintf(buf, "\nDevice %d \"%s\"\n", n, dev->name); + buf = yaffs_dump_dev_part0(buf, dev); + } else + buf = yaffs_dump_dev_part1(buf, dev); + + break; } - buf += sprintf(buf, "\nDevice %d \"%s\"\n", n, dev->name); - buf = yaffs_dump_dev(buf, dev); - break; + unlock_kernel(); } - unlock_kernel(); return buf - page < count ? buf - page : count; } @@ -2349,7 +2441,7 @@ static struct { }; #define MAX_MASK_NAME_LENGTH 40 -static int yaffs_proc_write(struct file *file, const char *buf, +static int yaffs_proc_write_trace_options(struct file *file, const char *buf, unsigned long count, void *data) { unsigned rg = 0, mask_bitfield; @@ -2441,6 +2533,13 @@ static int yaffs_proc_write(struct file *file, const char *buf, 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 { struct file_system_type *fst;