Btrfs: groundwork for subvolume and snapshot roots

Signed-off-by: Chris Mason <chris.mason@oracle.com>
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 66d9fb2..3c9236c 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -436,7 +436,6 @@
 {
 	struct btrfs_path *path;
 	struct btrfs_root_item *ri;
-	int ret;
 
 	if (btrfs_key_type(location) != BTRFS_ROOT_ITEM_KEY)
 		return 0;
@@ -447,22 +446,19 @@
 	BUG_ON(!path);
 	mutex_lock(&root->fs_info->fs_mutex);
 
-	ret = btrfs_lookup_inode(NULL, root, path, location, 0);
-	if (ret)
-		goto out;
-	ri = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]),
-			  path->slots[0],
-			  struct btrfs_root_item);
+	*sub_root = btrfs_read_fs_root(root->fs_info, location);
+	if (IS_ERR(*sub_root))
+		return PTR_ERR(*sub_root);
+
+	ri = &(*sub_root)->root_item;
 	location->objectid = btrfs_root_dirid(ri);
 	location->flags = 0;
 	btrfs_set_key_type(location, BTRFS_INODE_ITEM_KEY);
 	location->offset = 0;
-	/* FIXME properly select the root */
-	*sub_root = root->fs_info->fs_root;
-out:
+
 	btrfs_free_path(path);
 	mutex_unlock(&root->fs_info->fs_mutex);
-	return ret;
+	return 0;
 }
 
 
@@ -494,6 +490,15 @@
 		if (!inode)
 			return ERR_PTR(-EACCES);
 		if (inode->i_state & I_NEW) {
+			if (sub_root != root) {
+				ret = radix_tree_insert(
+						&root->fs_info->fs_roots_radix,
+						(unsigned long)sub_root,
+						sub_root);
+printk("adding new root for inode %lu\n", inode->i_ino);
+				igrab(inode);
+				sub_root->inode = inode;
+			}
 			BTRFS_I(inode)->root = sub_root;
 			memcpy(&BTRFS_I(inode)->location, &location,
 			       sizeof(location));
@@ -605,7 +610,7 @@
 	struct inode * inode;
 	struct dentry * root_dentry;
 	struct btrfs_super_block *disk_super;
-	struct btrfs_root *root;
+	struct btrfs_root *tree_root;
 	struct btrfs_inode *bi;
 
 	sb->s_maxbytes = MAX_LFS_FILESIZE;
@@ -613,14 +618,14 @@
 	sb->s_op = &btrfs_super_ops;
 	sb->s_time_gran = 1;
 
-	root = open_ctree(sb);
+	tree_root = open_ctree(sb);
 
-	if (!root) {
+	if (!tree_root) {
 		printk("btrfs: open_ctree failed\n");
 		return -EIO;
 	}
-	sb->s_fs_info = root;
-	disk_super = root->fs_info->disk_super;
+	sb->s_fs_info = tree_root;
+	disk_super = tree_root->fs_info->disk_super;
 	printk("read in super total blocks %Lu root %Lu\n",
 	       btrfs_super_total_blocks(disk_super),
 	       btrfs_super_root_dir(disk_super));
@@ -630,7 +635,7 @@
 	bi->location.objectid = inode->i_ino;
 	bi->location.offset = 0;
 	bi->location.flags = 0;
-	bi->root = root->fs_info->tree_root;
+	bi->root = tree_root;
 	btrfs_set_key_type(&bi->location, BTRFS_INODE_ITEM_KEY);
 
 	if (!inode)