Improve sync to flush metadata
[yaffs2.git] / yaffs_fs.c
index 5c368087f90f33398127e231c0c70da6a338c4ce..3fd94df12bab57878658836f06b4a0056ce0a7e8 100644 (file)
@@ -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 <charles@aleph1.co.uk>
@@ -32,7 +32,7 @@
  */
 
 const char *yaffs_fs_c_version =
-    "$Id: yaffs_fs.c,v 1.78 2009-03-09 13:08:09 wookey Exp $";
+    "$Id: yaffs_fs.c,v 1.83 2009-09-23 23:24:55 charles Exp $";
 extern const char *yaffs_guts_c_version;
 
 #include <linux/version.h>
@@ -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);
                }