hfsplus: flush disk caches in sync and fsync
Christoph Hellwig [Tue, 23 Nov 2010 13:38:21 +0000 (14:38 +0100)]
Flush the disk cache in fsync and sync to make sure data actually is
on disk on completion of these system calls.  There is a nobarrier
mount option to disable this behaviour.  It's slightly misnamed now
that barrier actually are gone, but it matches the name used by all
major filesystems.

Signed-off-by: Christoph Hellwig <hch@tuxera.com>

fs/hfsplus/hfsplus_fs.h
fs/hfsplus/inode.c
fs/hfsplus/options.c
fs/hfsplus/super.c

index 65c698f..17ac254 100644 (file)
@@ -156,6 +156,7 @@ struct hfsplus_sb_info {
 #define HFSPLUS_SB_FORCE       2
 #define HFSPLUS_SB_HFSX                3
 #define HFSPLUS_SB_CASEFOLD    4
+#define HFSPLUS_SB_NOBARRIER   5
 
 static inline struct hfsplus_sb_info *HFSPLUS_SB(struct super_block *sb)
 {
index bf6535b..bda7464 100644 (file)
@@ -8,6 +8,7 @@
  * Inode handling routines
  */
 
+#include <linux/blkdev.h>
 #include <linux/mm.h>
 #include <linux/fs.h>
 #include <linux/pagemap.h>
@@ -334,6 +335,9 @@ int hfsplus_file_fsync(struct file *file, int datasync)
                        error = error2;
        }
 
+       if (!test_bit(HFSPLUS_SB_NOBARRIER, &sbi->flags))
+               blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
+
        return error;
 }
 
index 43b02b5..dbd9d0c 100644 (file)
@@ -23,6 +23,7 @@ enum {
        opt_umask, opt_uid, opt_gid,
        opt_part, opt_session, opt_nls,
        opt_nodecompose, opt_decompose,
+       opt_barrier, opt_nobarrier,
        opt_force, opt_err
 };
 
@@ -37,6 +38,8 @@ static const match_table_t tokens = {
        { opt_nls, "nls=%s" },
        { opt_decompose, "decompose" },
        { opt_nodecompose, "nodecompose" },
+       { opt_barrier, "barrier" },
+       { opt_nobarrier, "nobarrier" },
        { opt_force, "force" },
        { opt_err, NULL }
 };
@@ -174,6 +177,12 @@ int hfsplus_parse_options(char *input, struct hfsplus_sb_info *sbi)
                case opt_nodecompose:
                        set_bit(HFSPLUS_SB_NODECOMPOSE, &sbi->flags);
                        break;
+               case opt_barrier:
+                       clear_bit(HFSPLUS_SB_NOBARRIER, &sbi->flags);
+                       break;
+               case opt_nobarrier:
+                       set_bit(HFSPLUS_SB_NOBARRIER, &sbi->flags);
+                       break;
                case opt_force:
                        set_bit(HFSPLUS_SB_FORCE, &sbi->flags);
                        break;
@@ -212,5 +221,7 @@ int hfsplus_show_options(struct seq_file *seq, struct vfsmount *mnt)
                seq_printf(seq, ",nls=%s", sbi->nls->charset);
        if (test_bit(HFSPLUS_SB_NODECOMPOSE, &sbi->flags))
                seq_printf(seq, ",nodecompose");
+       if (test_bit(HFSPLUS_SB_NOBARRIER, &sbi->flags))
+               seq_printf(seq, ",nobarrier");
        return 0;
 }
index 0366501..154478c 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/pagemap.h>
+#include <linux/blkdev.h>
 #include <linux/fs.h>
 #include <linux/slab.h>
 #include <linux/vfs.h>
@@ -212,6 +213,10 @@ int hfsplus_sync_fs(struct super_block *sb, int wait)
 out:
        mutex_unlock(&sbi->alloc_mutex);
        mutex_unlock(&sbi->vh_mutex);
+
+       if (!test_bit(HFSPLUS_SB_NOBARRIER, &sbi->flags))
+               blkdev_issue_flush(sb->s_bdev, GFP_KERNEL, NULL);
+
        return error;
 }