Btrfs: Add flush barriers on commit

Signed-off-by: Chris Mason <chris.mason@oracle.com>
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 7eda515..0c0edac 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -440,8 +440,9 @@
  */
 #define BTRFS_STRING_ITEM_KEY	253
 
-#define BTRFS_MOUNT_NODATASUM		0x1
-#define BTRFS_MOUNT_NODATACOW		0x2
+#define BTRFS_MOUNT_NODATASUM		(1 << 0)
+#define BTRFS_MOUNT_NODATACOW		(1 << 1)
+#define BTRFS_MOUNT_NOBARRIER		(1 << 2)
 
 #define btrfs_clear_opt(o, opt)		((o) &= ~BTRFS_MOUNT_##opt)
 #define btrfs_set_opt(o, opt)		((o) |= BTRFS_MOUNT_##opt)
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index e0940a3..a481b97 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -762,10 +762,15 @@
 	int ret;
 	struct extent_buffer *super = root->fs_info->sb_buffer;
 	struct inode *btree_inode = root->fs_info->btree_inode;
+	struct super_block *sb = root->fs_info->sb;
 
+	if (!btrfs_test_opt(root, NOBARRIER))
+		blkdev_issue_flush(sb->s_bdev, NULL);
 	set_extent_buffer_dirty(&BTRFS_I(btree_inode)->extent_tree, super);
 	ret = sync_page_range_nolock(btree_inode, btree_inode->i_mapping,
 				     super->start, super->len);
+	if (!btrfs_test_opt(root, NOBARRIER))
+		blkdev_issue_flush(sb->s_bdev, NULL);
 	return ret;
 }
 
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index f1b56eb..9ab4086 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -64,13 +64,14 @@
 
 enum {
 	Opt_subvol, Opt_nodatasum, Opt_nodatacow, Opt_max_extent,
-	Opt_alloc_start, Opt_err,
+	Opt_alloc_start, Opt_nobarrier, Opt_err,
 };
 
 static match_table_t tokens = {
 	{Opt_subvol, "subvol=%s"},
 	{Opt_nodatasum, "nodatasum"},
 	{Opt_nodatacow, "nodatacow"},
+	{Opt_nobarrier, "nobarrier"},
 	{Opt_max_extent, "max_extent=%s"},
 	{Opt_alloc_start, "alloc_start=%s"},
 	{Opt_err, NULL}
@@ -148,6 +149,12 @@
 				btrfs_set_opt(info->mount_opt, NODATASUM);
 			}
 			break;
+		case Opt_nobarrier:
+			if (info) {
+				printk("btrfs: turning off barriers\n");
+				btrfs_set_opt(info->mount_opt, NOBARRIER);
+			}
+			break;
 		case Opt_max_extent:
 			if (info) {
 				char *num = match_strdup(&args[0]);