summaryrefslogtreecommitdiff
path: root/fs/btrfs/disk-io.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-11-17 21:02:50 -0500
committerChris Mason <chris.mason@oracle.com>2008-11-17 21:02:50 -0500
commit3de4586c5278a28107030c336956381f69ff7a9d (patch)
treed636e3806cd5ecff71927d0300e46526fa23de1a /fs/btrfs/disk-io.c
parent4ce4cb526f67775c1cce3e3fa01c292672ba874e (diff)
downloadlwn-3de4586c5278a28107030c336956381f69ff7a9d.tar.gz
lwn-3de4586c5278a28107030c336956381f69ff7a9d.zip
Btrfs: Allow subvolumes and snapshots anywhere in the directory tree
Before, all snapshots and subvolumes lived in a single flat directory. This was awkward and confusing because the single flat directory was only writable with the ioctls. This commit changes the ioctls to create subvols and snapshots at any point in the directory tree. This requires making separate ioctls for snapshot and subvol creation instead of a combining them into one. The subvol ioctl does: btrfsctl -S subvol_name parent_dir After the ioctl is done subvol_name lives inside parent_dir. The snapshot ioctl does: btrfsctl -s path_for_snapshot root_to_snapshot path_for_snapshot can be an absolute or relative path. btrfsctl breaks it up into directory and basename components. root_to_snapshot can be any file or directory in the FS. The snapshot is taken of the entire root where that file lives. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r--fs/btrfs/disk-io.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 82833e5d84b6..0a5350573f61 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -838,7 +838,6 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
u64 objectid)
{
root->node = NULL;
- root->inode = NULL;
root->commit_root = NULL;
root->ref_tree = NULL;
root->sectorsize = sectorsize;
@@ -1430,6 +1429,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
u32 blocksize;
u32 stripesize;
u64 generation;
+ struct btrfs_key location;
struct buffer_head *bh;
struct btrfs_root *extent_root = kzalloc(sizeof(struct btrfs_root),
GFP_NOFS);
@@ -1729,7 +1729,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
goto fail_cleaner;
if (sb->s_flags & MS_RDONLY)
- return tree_root;
+ goto read_fs_root;
if (btrfs_super_log_root(disk_super) != 0) {
u32 blocksize;
@@ -1755,6 +1755,14 @@ struct btrfs_root *open_ctree(struct super_block *sb,
ret = btrfs_cleanup_reloc_trees(tree_root);
BUG_ON(ret);
+ location.objectid = BTRFS_FS_TREE_OBJECTID;
+ location.type = BTRFS_ROOT_ITEM_KEY;
+ location.offset = (u64)-1;
+
+read_fs_root:
+ fs_info->fs_root = btrfs_read_fs_root_no_name(fs_info, &location);
+ if (!fs_info->fs_root)
+ goto fail_cleaner;
return tree_root;
fail_cleaner:
@@ -1944,8 +1952,6 @@ int btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root)
(unsigned long)root->root_key.objectid);
if (root->in_sysfs)
btrfs_sysfs_del_root(root);
- if (root->inode)
- iput(root->inode);
if (root->node)
free_extent_buffer(root->node);
if (root->commit_root)