summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@tuxera.com>2010-11-23 14:38:21 +0100
committerChristoph Hellwig <hch@lst.de>2010-11-23 14:38:21 +0100
commit34a2d313c51f47cae50ccb89f4196462665f2c48 (patch)
treec641c7bd24b9e343139a3e1c4d81e51822114cd9
parenthfsplus: optimize fsync (diff)
downloadlinux-34a2d313c51f47cae50ccb89f4196462665f2c48.tar.xz
linux-34a2d313c51f47cae50ccb89f4196462665f2c48.zip
hfsplus: flush disk caches in sync and fsync
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>
-rw-r--r--fs/hfsplus/hfsplus_fs.h1
-rw-r--r--fs/hfsplus/inode.c4
-rw-r--r--fs/hfsplus/options.c11
-rw-r--r--fs/hfsplus/super.c5
4 files changed, 21 insertions, 0 deletions
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index 65c698f78ef7..17ac254e72cb 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -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)
{
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index bf6535b73261..bda7464c205d 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -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;
}
diff --git a/fs/hfsplus/options.c b/fs/hfsplus/options.c
index 43b02b5525eb..dbd9d0c426cb 100644
--- a/fs/hfsplus/options.c
+++ b/fs/hfsplus/options.c
@@ -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;
}
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index 036650123c4c..154478c71f25 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -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;
}