aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/inode.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/inode.c
parent4ce4cb526f67775c1cce3e3fa01c292672ba874e (diff)
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/inode.c')
-rw-r--r--fs/btrfs/inode.c50
1 files changed, 32 insertions, 18 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 3e3620e69bb9..e163b1b74707 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -3038,8 +3038,7 @@ struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location,
3038 return inode; 3038 return inode;
3039} 3039}
3040 3040
3041static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry, 3041struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry)
3042 struct nameidata *nd)
3043{ 3042{
3044 struct inode * inode; 3043 struct inode * inode;
3045 struct btrfs_inode *bi = BTRFS_I(dir); 3044 struct btrfs_inode *bi = BTRFS_I(dir);
@@ -3067,13 +3066,21 @@ static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry,
3067 inode = btrfs_iget(dir->i_sb, &location, sub_root, &new); 3066 inode = btrfs_iget(dir->i_sb, &location, sub_root, &new);
3068 if (IS_ERR(inode)) 3067 if (IS_ERR(inode))
3069 return ERR_CAST(inode); 3068 return ERR_CAST(inode);
3070
3071 /* the inode and parent dir are two different roots */
3072 if (new && root != sub_root) {
3073 igrab(inode);
3074 sub_root->inode = inode;
3075 }
3076 } 3069 }
3070 return inode;
3071}
3072
3073static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry,
3074 struct nameidata *nd)
3075{
3076 struct inode *inode;
3077
3078 if (dentry->d_name.len > BTRFS_NAME_LEN)
3079 return ERR_PTR(-ENAMETOOLONG);
3080
3081 inode = btrfs_lookup_dentry(dir, dentry);
3082 if (IS_ERR(inode))
3083 return ERR_CAST(inode);
3077 3084
3078 return d_splice_alias(inode, dentry); 3085 return d_splice_alias(inode, dentry);
3079} 3086}
@@ -3129,7 +3136,6 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
3129 return 0; 3136 return 0;
3130 filp->f_pos = 2; 3137 filp->f_pos = 2;
3131 } 3138 }
3132
3133 path = btrfs_alloc_path(); 3139 path = btrfs_alloc_path();
3134 path->reada = 2; 3140 path->reada = 2;
3135 3141
@@ -3159,6 +3165,7 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
3159 path->slots[0]++; 3165 path->slots[0]++;
3160 } 3166 }
3161 } 3167 }
3168
3162 advance = 1; 3169 advance = 1;
3163 item = btrfs_item_nr(leaf, slot); 3170 item = btrfs_item_nr(leaf, slot);
3164 btrfs_item_key_to_cpu(leaf, &found_key, slot); 3171 btrfs_item_key_to_cpu(leaf, &found_key, slot);
@@ -3194,16 +3201,25 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
3194 3201
3195 d_type = btrfs_filetype_table[btrfs_dir_type(leaf, di)]; 3202 d_type = btrfs_filetype_table[btrfs_dir_type(leaf, di)];
3196 btrfs_dir_item_key_to_cpu(leaf, di, &location); 3203 btrfs_dir_item_key_to_cpu(leaf, di, &location);
3204
3205 /* is this a reference to our own snapshot? If so
3206 * skip it
3207 */
3208 if (location.type == BTRFS_ROOT_ITEM_KEY &&
3209 location.objectid == root->root_key.objectid) {
3210 over = 0;
3211 goto skip;
3212 }
3197 over = filldir(dirent, name_ptr, name_len, 3213 over = filldir(dirent, name_ptr, name_len,
3198 found_key.offset, location.objectid, 3214 found_key.offset, location.objectid,
3199 d_type); 3215 d_type);
3200 3216
3217skip:
3201 if (name_ptr != tmp_name) 3218 if (name_ptr != tmp_name)
3202 kfree(name_ptr); 3219 kfree(name_ptr);
3203 3220
3204 if (over) 3221 if (over)
3205 goto nopos; 3222 goto nopos;
3206
3207 di_len = btrfs_dir_name_len(leaf, di) + 3223 di_len = btrfs_dir_name_len(leaf, di) +
3208 btrfs_dir_data_len(leaf, di) + sizeof(*di); 3224 btrfs_dir_data_len(leaf, di) + sizeof(*di);
3209 di_cur += di_len; 3225 di_cur += di_len;
@@ -3318,8 +3334,7 @@ out:
3318 * helper to find a free sequence number in a given directory. This current 3334 * helper to find a free sequence number in a given directory. This current
3319 * code is very simple, later versions will do smarter things in the btree 3335 * code is very simple, later versions will do smarter things in the btree
3320 */ 3336 */
3321static int btrfs_set_inode_index(struct inode *dir, struct inode *inode, 3337int btrfs_set_inode_index(struct inode *dir, u64 *index)
3322 u64 *index)
3323{ 3338{
3324 int ret = 0; 3339 int ret = 0;
3325 3340
@@ -3365,7 +3380,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
3365 return ERR_PTR(-ENOMEM); 3380 return ERR_PTR(-ENOMEM);
3366 3381
3367 if (dir) { 3382 if (dir) {
3368 ret = btrfs_set_inode_index(dir, inode, index); 3383 ret = btrfs_set_inode_index(dir, index);
3369 if (ret) 3384 if (ret)
3370 return ERR_PTR(ret); 3385 return ERR_PTR(ret);
3371 } 3386 }
@@ -3651,7 +3666,7 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
3651 err = btrfs_check_free_space(root, 1, 0); 3666 err = btrfs_check_free_space(root, 1, 0);
3652 if (err) 3667 if (err)
3653 goto fail; 3668 goto fail;
3654 err = btrfs_set_inode_index(dir, inode, &index); 3669 err = btrfs_set_inode_index(dir, &index);
3655 if (err) 3670 if (err)
3656 goto fail; 3671 goto fail;
3657 3672
@@ -4349,13 +4364,13 @@ out:
4349 * Invalidate a single dcache entry at the root of the filesystem. 4364 * Invalidate a single dcache entry at the root of the filesystem.
4350 * Needed after creation of snapshot or subvolume. 4365 * Needed after creation of snapshot or subvolume.
4351 */ 4366 */
4352void btrfs_invalidate_dcache_root(struct btrfs_root *root, char *name, 4367void btrfs_invalidate_dcache_root(struct inode *dir, char *name,
4353 int namelen) 4368 int namelen)
4354{ 4369{
4355 struct dentry *alias, *entry; 4370 struct dentry *alias, *entry;
4356 struct qstr qstr; 4371 struct qstr qstr;
4357 4372
4358 alias = d_find_alias(root->fs_info->sb->s_root->d_inode); 4373 alias = d_find_alias(dir);
4359 if (alias) { 4374 if (alias) {
4360 qstr.name = name; 4375 qstr.name = name;
4361 qstr.len = namelen; 4376 qstr.len = namelen;
@@ -4387,7 +4402,6 @@ int btrfs_create_subvol_root(struct btrfs_root *new_root, struct dentry *dentry,
4387 return PTR_ERR(inode); 4402 return PTR_ERR(inode);
4388 inode->i_op = &btrfs_dir_inode_operations; 4403 inode->i_op = &btrfs_dir_inode_operations;
4389 inode->i_fop = &btrfs_dir_file_operations; 4404 inode->i_fop = &btrfs_dir_file_operations;
4390 new_root->inode = inode;
4391 4405
4392 inode->i_nlink = 1; 4406 inode->i_nlink = 1;
4393 btrfs_i_size_write(inode, 0); 4407 btrfs_i_size_write(inode, 0);
@@ -4590,7 +4604,7 @@ static int btrfs_rename(struct inode * old_dir, struct dentry *old_dentry,
4590 } 4604 }
4591 4605
4592 } 4606 }
4593 ret = btrfs_set_inode_index(new_dir, old_inode, &index); 4607 ret = btrfs_set_inode_index(new_dir, &index);
4594 if (ret) 4608 if (ret)
4595 goto out_fail; 4609 goto out_fail;
4596 4610