Btrfs: very minimal locking

Signed-off-by: Chris Mason <chris.mason@oracle.com>
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 96cec63..68cafae 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -231,6 +231,7 @@
 	struct buffer_head *sb_buffer;
 	struct super_block *sb;
 	struct mutex trans_mutex;
+	struct mutex fs_mutex;
 };
 
 /*
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 3dea757..e32ddff 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -116,6 +116,7 @@
 	fs_info->sb_buffer = sb_buffer;
 	fs_info->sb = sb;
 	mutex_init(&fs_info->trans_mutex);
+	mutex_init(&fs_info->fs_mutex);
 	memset(&fs_info->current_insert, 0, sizeof(fs_info->current_insert));
 	memset(&fs_info->last_insert, 0, sizeof(fs_info->last_insert));
 
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index c86f0e6..9583a9a 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -168,9 +168,10 @@
 	BUG_ON(!bh);
 	err = radix_tree_insert(&root->fs_info->pinned_radix,
 				blocknr, bh);
-	BUG_ON(err);
-	if (err)
+	if (err && err != -EEXIST) {
+		BUG();
 		return err;
+	}
 	radix_tree_tag_set(&root->fs_info->pinned_radix, blocknr,
 			   tag);
 	return 0;
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index a2db055..0ca1080 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -453,25 +453,21 @@
 	struct inode *inode;
 	int err;
 
+	mutex_lock(&root->fs_info->fs_mutex);
 	trans = btrfs_start_transaction(root, 1);
 	inode = btrfs_new_inode(trans, dir, mode);
 	err = PTR_ERR(inode);
 	if (IS_ERR(inode))
-		return err;
+		goto out_unlock;
 	// FIXME mark the inode dirty
 	err = btrfs_add_nondir(trans, dentry, inode);
 	dir->i_sb->s_dirt = 1;
 	btrfs_end_transaction(trans, root);
+out_unlock:
+	mutex_unlock(&root->fs_info->fs_mutex);
 	return err;
 }
 
-static void btrfs_write_super(struct super_block *sb)
-{
-	sb->s_dirt = 0;
-printk("btrfs write_super!\n");
-	filemap_flush(sb->s_bdev->bd_inode->i_mapping);
-}
-
 static int btrfs_sync_fs(struct super_block *sb, int wait)
 {
 	struct btrfs_trans_handle *trans;
@@ -479,17 +475,29 @@
 	int ret;
 
 	sb->s_dirt = 0;
-	return 0;
+	if (!wait) {
+		filemap_flush(sb->s_bdev->bd_inode->i_mapping);
+		return 0;
+	}
+	filemap_write_and_wait(sb->s_bdev->bd_inode->i_mapping);
 
 	root = btrfs_sb(sb);
+	mutex_lock(&root->fs_info->fs_mutex);
 	trans = btrfs_start_transaction(root, 1);
 	ret = btrfs_commit_transaction(trans, root);
 	sb->s_dirt = 0;
 	BUG_ON(ret);
 printk("btrfs sync_fs\n");
+	mutex_unlock(&root->fs_info->fs_mutex);
 	return 0;
 }
 
+static void btrfs_write_super(struct super_block *sb)
+{
+	btrfs_sync_fs(sb, 1);
+}
+
+
 static int btrfs_get_sb(struct file_system_type *fs_type,
 	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {