diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/ctree.h | 7 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 14 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 50 | ||||
-rw-r--r-- | fs/btrfs/ioctl.c | 71 | ||||
-rw-r--r-- | fs/btrfs/ioctl.h | 7 | ||||
-rw-r--r-- | fs/btrfs/super.c | 10 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 66 | ||||
-rw-r--r-- | fs/btrfs/transaction.h | 2 |
8 files changed, 162 insertions, 65 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 5ff74282a620..5611f8e035a4 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -606,6 +606,7 @@ struct btrfs_fs_info { | |||
606 | struct btrfs_root *tree_root; | 606 | struct btrfs_root *tree_root; |
607 | struct btrfs_root *chunk_root; | 607 | struct btrfs_root *chunk_root; |
608 | struct btrfs_root *dev_root; | 608 | struct btrfs_root *dev_root; |
609 | struct btrfs_root *fs_root; | ||
609 | 610 | ||
610 | /* the log root tree is a directory of all the other log roots */ | 611 | /* the log root tree is a directory of all the other log roots */ |
611 | struct btrfs_root *log_root_tree; | 612 | struct btrfs_root *log_root_tree; |
@@ -758,7 +759,6 @@ struct btrfs_root { | |||
758 | struct btrfs_root_item root_item; | 759 | struct btrfs_root_item root_item; |
759 | struct btrfs_key root_key; | 760 | struct btrfs_key root_key; |
760 | struct btrfs_fs_info *fs_info; | 761 | struct btrfs_fs_info *fs_info; |
761 | struct inode *inode; | ||
762 | struct extent_io_tree dirty_log_pages; | 762 | struct extent_io_tree dirty_log_pages; |
763 | 763 | ||
764 | struct kobject root_kobj; | 764 | struct kobject root_kobj; |
@@ -1876,6 +1876,8 @@ int btrfs_csum_truncate(struct btrfs_trans_handle *trans, | |||
1876 | #define PageChecked PageFsMisc | 1876 | #define PageChecked PageFsMisc |
1877 | #endif | 1877 | #endif |
1878 | 1878 | ||
1879 | struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry); | ||
1880 | int btrfs_set_inode_index(struct inode *dir, u64 *index); | ||
1879 | int btrfs_unlink_inode(struct btrfs_trans_handle *trans, | 1881 | int btrfs_unlink_inode(struct btrfs_trans_handle *trans, |
1880 | struct btrfs_root *root, | 1882 | struct btrfs_root *root, |
1881 | struct inode *dir, struct inode *inode, | 1883 | struct inode *dir, struct inode *inode, |
@@ -1896,9 +1898,6 @@ int btrfs_create_subvol_root(struct btrfs_root *new_root, struct dentry *dentry, | |||
1896 | struct btrfs_trans_handle *trans, u64 new_dirid, | 1898 | struct btrfs_trans_handle *trans, u64 new_dirid, |
1897 | struct btrfs_block_group_cache *block_group); | 1899 | struct btrfs_block_group_cache *block_group); |
1898 | 1900 | ||
1899 | void btrfs_invalidate_dcache_root(struct btrfs_root *root, char *name, | ||
1900 | int namelen); | ||
1901 | |||
1902 | int btrfs_merge_bio_hook(struct page *page, unsigned long offset, | 1901 | int btrfs_merge_bio_hook(struct page *page, unsigned long offset, |
1903 | size_t size, struct bio *bio, unsigned long bio_flags); | 1902 | size_t size, struct bio *bio, unsigned long bio_flags); |
1904 | 1903 | ||
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, | |||
838 | u64 objectid) | 838 | u64 objectid) |
839 | { | 839 | { |
840 | root->node = NULL; | 840 | root->node = NULL; |
841 | root->inode = NULL; | ||
842 | root->commit_root = NULL; | 841 | root->commit_root = NULL; |
843 | root->ref_tree = NULL; | 842 | root->ref_tree = NULL; |
844 | root->sectorsize = sectorsize; | 843 | root->sectorsize = sectorsize; |
@@ -1430,6 +1429,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1430 | u32 blocksize; | 1429 | u32 blocksize; |
1431 | u32 stripesize; | 1430 | u32 stripesize; |
1432 | u64 generation; | 1431 | u64 generation; |
1432 | struct btrfs_key location; | ||
1433 | struct buffer_head *bh; | 1433 | struct buffer_head *bh; |
1434 | struct btrfs_root *extent_root = kzalloc(sizeof(struct btrfs_root), | 1434 | struct btrfs_root *extent_root = kzalloc(sizeof(struct btrfs_root), |
1435 | GFP_NOFS); | 1435 | GFP_NOFS); |
@@ -1729,7 +1729,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1729 | goto fail_cleaner; | 1729 | goto fail_cleaner; |
1730 | 1730 | ||
1731 | if (sb->s_flags & MS_RDONLY) | 1731 | if (sb->s_flags & MS_RDONLY) |
1732 | return tree_root; | 1732 | goto read_fs_root; |
1733 | 1733 | ||
1734 | if (btrfs_super_log_root(disk_super) != 0) { | 1734 | if (btrfs_super_log_root(disk_super) != 0) { |
1735 | u32 blocksize; | 1735 | u32 blocksize; |
@@ -1755,6 +1755,14 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1755 | ret = btrfs_cleanup_reloc_trees(tree_root); | 1755 | ret = btrfs_cleanup_reloc_trees(tree_root); |
1756 | BUG_ON(ret); | 1756 | BUG_ON(ret); |
1757 | 1757 | ||
1758 | location.objectid = BTRFS_FS_TREE_OBJECTID; | ||
1759 | location.type = BTRFS_ROOT_ITEM_KEY; | ||
1760 | location.offset = (u64)-1; | ||
1761 | |||
1762 | read_fs_root: | ||
1763 | fs_info->fs_root = btrfs_read_fs_root_no_name(fs_info, &location); | ||
1764 | if (!fs_info->fs_root) | ||
1765 | goto fail_cleaner; | ||
1758 | return tree_root; | 1766 | return tree_root; |
1759 | 1767 | ||
1760 | fail_cleaner: | 1768 | fail_cleaner: |
@@ -1944,8 +1952,6 @@ int btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root) | |||
1944 | (unsigned long)root->root_key.objectid); | 1952 | (unsigned long)root->root_key.objectid); |
1945 | if (root->in_sysfs) | 1953 | if (root->in_sysfs) |
1946 | btrfs_sysfs_del_root(root); | 1954 | btrfs_sysfs_del_root(root); |
1947 | if (root->inode) | ||
1948 | iput(root->inode); | ||
1949 | if (root->node) | 1955 | if (root->node) |
1950 | free_extent_buffer(root->node); | 1956 | free_extent_buffer(root->node); |
1951 | if (root->commit_root) | 1957 | if (root->commit_root) |
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 | ||
3041 | static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry, | 3041 | struct 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 | |||
3073 | static 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 | ||
3217 | skip: | ||
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 | */ |
3321 | static int btrfs_set_inode_index(struct inode *dir, struct inode *inode, | 3337 | int 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 | */ |
4352 | void btrfs_invalidate_dcache_root(struct btrfs_root *root, char *name, | 4367 | void 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 | ||
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index f43df72b0e17..ec45b3086136 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -67,6 +67,7 @@ static noinline int create_subvol(struct btrfs_root *root, | |||
67 | int err; | 67 | int err; |
68 | u64 objectid; | 68 | u64 objectid; |
69 | u64 new_dirid = BTRFS_FIRST_FREE_OBJECTID; | 69 | u64 new_dirid = BTRFS_FIRST_FREE_OBJECTID; |
70 | u64 index = 0; | ||
70 | unsigned long nr = 1; | 71 | unsigned long nr = 1; |
71 | 72 | ||
72 | ret = btrfs_check_free_space(root, 1, 0); | 73 | ret = btrfs_check_free_space(root, 1, 0); |
@@ -126,6 +127,7 @@ static noinline int create_subvol(struct btrfs_root *root, | |||
126 | key.objectid = objectid; | 127 | key.objectid = objectid; |
127 | key.offset = 1; | 128 | key.offset = 1; |
128 | btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY); | 129 | btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY); |
130 | printk("inserting root objectid %Lu\n", objectid); | ||
129 | ret = btrfs_insert_root(trans, root->fs_info->tree_root, &key, | 131 | ret = btrfs_insert_root(trans, root->fs_info->tree_root, &key, |
130 | &root_item); | 132 | &root_item); |
131 | if (ret) | 133 | if (ret) |
@@ -135,24 +137,27 @@ static noinline int create_subvol(struct btrfs_root *root, | |||
135 | * insert the directory item | 137 | * insert the directory item |
136 | */ | 138 | */ |
137 | key.offset = (u64)-1; | 139 | key.offset = (u64)-1; |
138 | dir = root->fs_info->sb->s_root->d_inode; | 140 | dir = dentry->d_parent->d_inode; |
139 | ret = btrfs_insert_dir_item(trans, root->fs_info->tree_root, | 141 | ret = btrfs_set_inode_index(dir, &index); |
142 | BUG_ON(ret); | ||
143 | |||
144 | ret = btrfs_insert_dir_item(trans, root, | ||
140 | name, namelen, dir->i_ino, &key, | 145 | name, namelen, dir->i_ino, &key, |
141 | BTRFS_FT_DIR, 0); | 146 | BTRFS_FT_DIR, index); |
142 | if (ret) | 147 | if (ret) |
143 | goto fail; | 148 | goto fail; |
144 | 149 | #if 0 | |
145 | ret = btrfs_insert_inode_ref(trans, root->fs_info->tree_root, | 150 | ret = btrfs_insert_inode_ref(trans, root->fs_info->tree_root, |
146 | name, namelen, objectid, | 151 | name, namelen, objectid, |
147 | root->fs_info->sb->s_root->d_inode->i_ino, 0); | 152 | root->fs_info->sb->s_root->d_inode->i_ino, 0); |
148 | if (ret) | 153 | if (ret) |
149 | goto fail; | 154 | goto fail; |
150 | 155 | #endif | |
151 | ret = btrfs_commit_transaction(trans, root); | 156 | ret = btrfs_commit_transaction(trans, root); |
152 | if (ret) | 157 | if (ret) |
153 | goto fail_commit; | 158 | goto fail_commit; |
154 | 159 | ||
155 | new_root = btrfs_read_fs_root(root->fs_info, &key, name, namelen); | 160 | new_root = btrfs_read_fs_root_no_name(root->fs_info, &key); |
156 | BUG_ON(!new_root); | 161 | BUG_ON(!new_root); |
157 | 162 | ||
158 | trans = btrfs_start_transaction(new_root, 1); | 163 | trans = btrfs_start_transaction(new_root, 1); |
@@ -170,14 +175,16 @@ fail: | |||
170 | ret = err; | 175 | ret = err; |
171 | fail_commit: | 176 | fail_commit: |
172 | btrfs_btree_balance_dirty(root, nr); | 177 | btrfs_btree_balance_dirty(root, nr); |
178 | printk("all done ret %d\n", ret); | ||
173 | return ret; | 179 | return ret; |
174 | } | 180 | } |
175 | 181 | ||
176 | static int create_snapshot(struct btrfs_root *root, char *name, int namelen) | 182 | static int create_snapshot(struct btrfs_root *root, struct dentry *dentry, |
183 | char *name, int namelen) | ||
177 | { | 184 | { |
178 | struct btrfs_pending_snapshot *pending_snapshot; | 185 | struct btrfs_pending_snapshot *pending_snapshot; |
179 | struct btrfs_trans_handle *trans; | 186 | struct btrfs_trans_handle *trans; |
180 | int ret; | 187 | int ret = 0; |
181 | int err; | 188 | int err; |
182 | unsigned long nr = 0; | 189 | unsigned long nr = 0; |
183 | 190 | ||
@@ -188,7 +195,7 @@ static int create_snapshot(struct btrfs_root *root, char *name, int namelen) | |||
188 | if (ret) | 195 | if (ret) |
189 | goto fail_unlock; | 196 | goto fail_unlock; |
190 | 197 | ||
191 | pending_snapshot = kmalloc(sizeof(*pending_snapshot), GFP_NOFS); | 198 | pending_snapshot = kzalloc(sizeof(*pending_snapshot), GFP_NOFS); |
192 | if (!pending_snapshot) { | 199 | if (!pending_snapshot) { |
193 | ret = -ENOMEM; | 200 | ret = -ENOMEM; |
194 | goto fail_unlock; | 201 | goto fail_unlock; |
@@ -201,12 +208,12 @@ static int create_snapshot(struct btrfs_root *root, char *name, int namelen) | |||
201 | } | 208 | } |
202 | memcpy(pending_snapshot->name, name, namelen); | 209 | memcpy(pending_snapshot->name, name, namelen); |
203 | pending_snapshot->name[namelen] = '\0'; | 210 | pending_snapshot->name[namelen] = '\0'; |
211 | pending_snapshot->dentry = dentry; | ||
204 | trans = btrfs_start_transaction(root, 1); | 212 | trans = btrfs_start_transaction(root, 1); |
205 | BUG_ON(!trans); | 213 | BUG_ON(!trans); |
206 | pending_snapshot->root = root; | 214 | pending_snapshot->root = root; |
207 | list_add(&pending_snapshot->list, | 215 | list_add(&pending_snapshot->list, |
208 | &trans->transaction->pending_snapshots); | 216 | &trans->transaction->pending_snapshots); |
209 | ret = btrfs_update_inode(trans, root, root->inode); | ||
210 | err = btrfs_commit_transaction(trans, root); | 217 | err = btrfs_commit_transaction(trans, root); |
211 | 218 | ||
212 | fail_unlock: | 219 | fail_unlock: |
@@ -230,7 +237,8 @@ static inline int btrfs_may_create(struct inode *dir, struct dentry *child) | |||
230 | * inside this filesystem so it's quite a bit simpler. | 237 | * inside this filesystem so it's quite a bit simpler. |
231 | */ | 238 | */ |
232 | static noinline int btrfs_mksubvol(struct path *parent, char *name, | 239 | static noinline int btrfs_mksubvol(struct path *parent, char *name, |
233 | int mode, int namelen) | 240 | int mode, int namelen, |
241 | struct btrfs_root *snap_src) | ||
234 | { | 242 | { |
235 | struct dentry *dentry; | 243 | struct dentry *dentry; |
236 | int error; | 244 | int error; |
@@ -248,6 +256,7 @@ static noinline int btrfs_mksubvol(struct path *parent, char *name, | |||
248 | 256 | ||
249 | if (!IS_POSIXACL(parent->dentry->d_inode)) | 257 | if (!IS_POSIXACL(parent->dentry->d_inode)) |
250 | mode &= ~current->fs->umask; | 258 | mode &= ~current->fs->umask; |
259 | |||
251 | error = mnt_want_write(parent->mnt); | 260 | error = mnt_want_write(parent->mnt); |
252 | if (error) | 261 | if (error) |
253 | goto out_dput; | 262 | goto out_dput; |
@@ -266,8 +275,12 @@ static noinline int btrfs_mksubvol(struct path *parent, char *name, | |||
266 | * Also we should pass on the mode eventually to allow creating new | 275 | * Also we should pass on the mode eventually to allow creating new |
267 | * subvolume with specific mode bits. | 276 | * subvolume with specific mode bits. |
268 | */ | 277 | */ |
269 | error = create_subvol(BTRFS_I(parent->dentry->d_inode)->root, dentry, | 278 | if (snap_src) { |
270 | name, namelen); | 279 | error = create_snapshot(snap_src, dentry, name, namelen); |
280 | } else { | ||
281 | error = create_subvol(BTRFS_I(parent->dentry->d_inode)->root, | ||
282 | dentry, name, namelen); | ||
283 | } | ||
271 | if (error) | 284 | if (error) |
272 | goto out_drop_write; | 285 | goto out_drop_write; |
273 | 286 | ||
@@ -471,15 +484,16 @@ out: | |||
471 | } | 484 | } |
472 | 485 | ||
473 | static noinline int btrfs_ioctl_snap_create(struct file *file, | 486 | static noinline int btrfs_ioctl_snap_create(struct file *file, |
474 | void __user *arg) | 487 | void __user *arg, int subvol) |
475 | { | 488 | { |
476 | struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root; | 489 | struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root; |
477 | struct btrfs_ioctl_vol_args *vol_args; | 490 | struct btrfs_ioctl_vol_args *vol_args; |
478 | struct btrfs_dir_item *di; | 491 | struct btrfs_dir_item *di; |
479 | struct btrfs_path *path; | 492 | struct btrfs_path *path; |
493 | struct file *src_file; | ||
480 | u64 root_dirid; | 494 | u64 root_dirid; |
481 | int namelen; | 495 | int namelen; |
482 | int ret; | 496 | int ret = 0; |
483 | 497 | ||
484 | if (root->fs_info->sb->s_flags & MS_RDONLY) | 498 | if (root->fs_info->sb->s_flags & MS_RDONLY) |
485 | return -EROFS; | 499 | return -EROFS; |
@@ -523,12 +537,29 @@ static noinline int btrfs_ioctl_snap_create(struct file *file, | |||
523 | goto out; | 537 | goto out; |
524 | } | 538 | } |
525 | 539 | ||
526 | if (root == root->fs_info->tree_root) { | 540 | if (subvol) { |
527 | ret = btrfs_mksubvol(&file->f_path, vol_args->name, | 541 | ret = btrfs_mksubvol(&file->f_path, vol_args->name, |
528 | file->f_path.dentry->d_inode->i_mode, | 542 | file->f_path.dentry->d_inode->i_mode, |
529 | namelen); | 543 | namelen, NULL); |
530 | } else { | 544 | } else { |
531 | ret = create_snapshot(root, vol_args->name, namelen); | 545 | struct inode *src_inode; |
546 | src_file = fget(vol_args->fd); | ||
547 | if (!src_file) { | ||
548 | ret = -EINVAL; | ||
549 | goto out; | ||
550 | } | ||
551 | |||
552 | src_inode = src_file->f_path.dentry->d_inode; | ||
553 | if (src_inode->i_sb != file->f_path.dentry->d_inode->i_sb) { | ||
554 | printk("btrfs: Snapshot src from another FS\n"); | ||
555 | ret = -EINVAL; | ||
556 | fput(src_file); | ||
557 | goto out; | ||
558 | } | ||
559 | ret = btrfs_mksubvol(&file->f_path, vol_args->name, | ||
560 | file->f_path.dentry->d_inode->i_mode, | ||
561 | namelen, BTRFS_I(src_inode)->root); | ||
562 | fput(src_file); | ||
532 | } | 563 | } |
533 | 564 | ||
534 | out: | 565 | out: |
@@ -1030,7 +1061,9 @@ long btrfs_ioctl(struct file *file, unsigned int | |||
1030 | 1061 | ||
1031 | switch (cmd) { | 1062 | switch (cmd) { |
1032 | case BTRFS_IOC_SNAP_CREATE: | 1063 | case BTRFS_IOC_SNAP_CREATE: |
1033 | return btrfs_ioctl_snap_create(file, (void __user *)arg); | 1064 | return btrfs_ioctl_snap_create(file, (void __user *)arg, 0); |
1065 | case BTRFS_IOC_SUBVOL_CREATE: | ||
1066 | return btrfs_ioctl_snap_create(file, (void __user *)arg, 1); | ||
1034 | case BTRFS_IOC_DEFRAG: | 1067 | case BTRFS_IOC_DEFRAG: |
1035 | return btrfs_ioctl_defrag(file); | 1068 | return btrfs_ioctl_defrag(file); |
1036 | case BTRFS_IOC_RESIZE: | 1069 | case BTRFS_IOC_RESIZE: |
diff --git a/fs/btrfs/ioctl.h b/fs/btrfs/ioctl.h index 989ba8a01215..78049ea208db 100644 --- a/fs/btrfs/ioctl.h +++ b/fs/btrfs/ioctl.h | |||
@@ -22,9 +22,10 @@ | |||
22 | 22 | ||
23 | #define BTRFS_IOCTL_MAGIC 0x94 | 23 | #define BTRFS_IOCTL_MAGIC 0x94 |
24 | #define BTRFS_VOL_NAME_MAX 255 | 24 | #define BTRFS_VOL_NAME_MAX 255 |
25 | #define BTRFS_PATH_NAME_MAX 4095 | 25 | #define BTRFS_PATH_NAME_MAX 3072 |
26 | 26 | ||
27 | struct btrfs_ioctl_vol_args { | 27 | struct btrfs_ioctl_vol_args { |
28 | __s64 fd; | ||
28 | char name[BTRFS_PATH_NAME_MAX + 1]; | 29 | char name[BTRFS_PATH_NAME_MAX + 1]; |
29 | }; | 30 | }; |
30 | 31 | ||
@@ -51,7 +52,6 @@ struct btrfs_ioctl_vol_args { | |||
51 | struct btrfs_ioctl_vol_args) | 52 | struct btrfs_ioctl_vol_args) |
52 | #define BTRFS_IOC_BALANCE _IOW(BTRFS_IOCTL_MAGIC, 12, \ | 53 | #define BTRFS_IOC_BALANCE _IOW(BTRFS_IOCTL_MAGIC, 12, \ |
53 | struct btrfs_ioctl_vol_args) | 54 | struct btrfs_ioctl_vol_args) |
54 | |||
55 | struct btrfs_ioctl_clone_range_args { | 55 | struct btrfs_ioctl_clone_range_args { |
56 | __s64 src_fd; | 56 | __s64 src_fd; |
57 | __u64 src_offset, src_length; | 57 | __u64 src_offset, src_length; |
@@ -61,4 +61,7 @@ struct btrfs_ioctl_clone_range_args { | |||
61 | #define BTRFS_IOC_CLONE_RANGE _IOW(BTRFS_IOCTL_MAGIC, 13, \ | 61 | #define BTRFS_IOC_CLONE_RANGE _IOW(BTRFS_IOCTL_MAGIC, 13, \ |
62 | struct btrfs_ioctl_clone_range_args) | 62 | struct btrfs_ioctl_clone_range_args) |
63 | 63 | ||
64 | #define BTRFS_IOC_SUBVOL_CREATE _IOW(BTRFS_IOCTL_MAGIC, 14, \ | ||
65 | struct btrfs_ioctl_vol_args) | ||
66 | |||
64 | #endif | 67 | #endif |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 92393cc60d08..77c5eff3e209 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -285,11 +285,11 @@ static int btrfs_parse_early_options(const char *options, int flags, | |||
285 | out: | 285 | out: |
286 | /* | 286 | /* |
287 | * If no subvolume name is specified we use the default one. Allocate | 287 | * If no subvolume name is specified we use the default one. Allocate |
288 | * a copy of the string "default" here so that code later in the | 288 | * a copy of the string "." here so that code later in the |
289 | * mount path doesn't care if it's the default volume or another one. | 289 | * mount path doesn't care if it's the default volume or another one. |
290 | */ | 290 | */ |
291 | if (!*subvol_name) { | 291 | if (!*subvol_name) { |
292 | *subvol_name = kstrdup("default", GFP_KERNEL); | 292 | *subvol_name = kstrdup(".", GFP_KERNEL); |
293 | if (!*subvol_name) | 293 | if (!*subvol_name) |
294 | return -ENOMEM; | 294 | return -ENOMEM; |
295 | } | 295 | } |
@@ -323,12 +323,12 @@ static int btrfs_fill_super(struct super_block * sb, | |||
323 | } | 323 | } |
324 | sb->s_fs_info = tree_root; | 324 | sb->s_fs_info = tree_root; |
325 | disk_super = &tree_root->fs_info->super_copy; | 325 | disk_super = &tree_root->fs_info->super_copy; |
326 | inode = btrfs_iget_locked(sb, btrfs_super_root_dir(disk_super), | 326 | inode = btrfs_iget_locked(sb, BTRFS_FIRST_FREE_OBJECTID, |
327 | tree_root); | 327 | tree_root->fs_info->fs_root); |
328 | bi = BTRFS_I(inode); | 328 | bi = BTRFS_I(inode); |
329 | bi->location.objectid = inode->i_ino; | 329 | bi->location.objectid = inode->i_ino; |
330 | bi->location.offset = 0; | 330 | bi->location.offset = 0; |
331 | bi->root = tree_root; | 331 | bi->root = tree_root->fs_info->fs_root; |
332 | 332 | ||
333 | btrfs_set_key_type(&bi->location, BTRFS_INODE_ITEM_KEY); | 333 | btrfs_set_key_type(&bi->location, BTRFS_INODE_ITEM_KEY); |
334 | 334 | ||
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 202c1b6df4a4..eec8b2465039 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -779,7 +779,6 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
779 | struct extent_buffer *tmp; | 779 | struct extent_buffer *tmp; |
780 | struct extent_buffer *old; | 780 | struct extent_buffer *old; |
781 | int ret; | 781 | int ret; |
782 | int namelen; | ||
783 | u64 objectid; | 782 | u64 objectid; |
784 | 783 | ||
785 | new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS); | 784 | new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS); |
@@ -816,28 +815,48 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
816 | if (ret) | 815 | if (ret) |
817 | goto fail; | 816 | goto fail; |
818 | 817 | ||
818 | key.offset = (u64)-1; | ||
819 | memcpy(&pending->root_key, &key, sizeof(key)); | ||
820 | fail: | ||
821 | kfree(new_root_item); | ||
822 | return ret; | ||
823 | } | ||
824 | |||
825 | static noinline int finish_pending_snapshot(struct btrfs_fs_info *fs_info, | ||
826 | struct btrfs_pending_snapshot *pending) | ||
827 | { | ||
828 | int ret; | ||
829 | int namelen; | ||
830 | u64 index = 0; | ||
831 | struct btrfs_trans_handle *trans; | ||
832 | struct inode *parent_inode; | ||
833 | struct inode *inode; | ||
834 | |||
835 | trans = btrfs_start_transaction(fs_info->fs_root, 1); | ||
836 | |||
819 | /* | 837 | /* |
820 | * insert the directory item | 838 | * insert the directory item |
821 | */ | 839 | */ |
822 | key.offset = (u64)-1; | ||
823 | namelen = strlen(pending->name); | 840 | namelen = strlen(pending->name); |
824 | ret = btrfs_insert_dir_item(trans, root->fs_info->tree_root, | 841 | parent_inode = pending->dentry->d_parent->d_inode; |
825 | pending->name, namelen, | 842 | ret = btrfs_set_inode_index(parent_inode, &index); |
826 | root->fs_info->sb->s_root->d_inode->i_ino, | 843 | ret = btrfs_insert_dir_item(trans, |
827 | &key, BTRFS_FT_DIR, 0); | 844 | BTRFS_I(parent_inode)->root, |
845 | pending->name, namelen, | ||
846 | parent_inode->i_ino, | ||
847 | &pending->root_key, BTRFS_FT_DIR, index); | ||
828 | 848 | ||
829 | if (ret) | 849 | if (ret) |
830 | goto fail; | 850 | goto fail; |
831 | 851 | #if 0 | |
832 | ret = btrfs_insert_inode_ref(trans, root->fs_info->tree_root, | 852 | ret = btrfs_insert_inode_ref(trans, root->fs_info->tree_root, |
833 | pending->name, strlen(pending->name), objectid, | 853 | pending->name, strlen(pending->name), objectid, |
834 | root->fs_info->sb->s_root->d_inode->i_ino, 0); | 854 | root->fs_info->sb->s_root->d_inode->i_ino, 0); |
835 | 855 | #endif | |
836 | /* Invalidate existing dcache entry for new snapshot. */ | 856 | inode = btrfs_lookup_dentry(parent_inode, pending->dentry); |
837 | btrfs_invalidate_dcache_root(root, pending->name, namelen); | 857 | d_instantiate(pending->dentry, inode); |
838 | |||
839 | fail: | 858 | fail: |
840 | kfree(new_root_item); | 859 | btrfs_end_transaction(trans, fs_info->fs_root); |
841 | return ret; | 860 | return ret; |
842 | } | 861 | } |
843 | 862 | ||
@@ -849,12 +868,28 @@ static noinline int create_pending_snapshots(struct btrfs_trans_handle *trans, | |||
849 | { | 868 | { |
850 | struct btrfs_pending_snapshot *pending; | 869 | struct btrfs_pending_snapshot *pending; |
851 | struct list_head *head = &trans->transaction->pending_snapshots; | 870 | struct list_head *head = &trans->transaction->pending_snapshots; |
871 | struct list_head *cur; | ||
872 | int ret; | ||
873 | |||
874 | list_for_each(cur, head) { | ||
875 | pending = list_entry(cur, struct btrfs_pending_snapshot, list); | ||
876 | ret = create_pending_snapshot(trans, fs_info, pending); | ||
877 | BUG_ON(ret); | ||
878 | } | ||
879 | return 0; | ||
880 | } | ||
881 | |||
882 | static noinline int finish_pending_snapshots(struct btrfs_trans_handle *trans, | ||
883 | struct btrfs_fs_info *fs_info) | ||
884 | { | ||
885 | struct btrfs_pending_snapshot *pending; | ||
886 | struct list_head *head = &trans->transaction->pending_snapshots; | ||
852 | int ret; | 887 | int ret; |
853 | 888 | ||
854 | while(!list_empty(head)) { | 889 | while(!list_empty(head)) { |
855 | pending = list_entry(head->next, | 890 | pending = list_entry(head->next, |
856 | struct btrfs_pending_snapshot, list); | 891 | struct btrfs_pending_snapshot, list); |
857 | ret = create_pending_snapshot(trans, fs_info, pending); | 892 | ret = finish_pending_snapshot(fs_info, pending); |
858 | BUG_ON(ret); | 893 | BUG_ON(ret); |
859 | list_del(&pending->list); | 894 | list_del(&pending->list); |
860 | kfree(pending->name); | 895 | kfree(pending->name); |
@@ -1033,11 +1068,15 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
1033 | btrfs_drop_dead_reloc_roots(root); | 1068 | btrfs_drop_dead_reloc_roots(root); |
1034 | mutex_unlock(&root->fs_info->tree_reloc_mutex); | 1069 | mutex_unlock(&root->fs_info->tree_reloc_mutex); |
1035 | 1070 | ||
1071 | /* do the directory inserts of any pending snapshot creations */ | ||
1072 | finish_pending_snapshots(trans, root->fs_info); | ||
1073 | |||
1036 | mutex_lock(&root->fs_info->trans_mutex); | 1074 | mutex_lock(&root->fs_info->trans_mutex); |
1037 | 1075 | ||
1038 | cur_trans->commit_done = 1; | 1076 | cur_trans->commit_done = 1; |
1039 | root->fs_info->last_trans_committed = cur_trans->transid; | 1077 | root->fs_info->last_trans_committed = cur_trans->transid; |
1040 | wake_up(&cur_trans->commit_wait); | 1078 | wake_up(&cur_trans->commit_wait); |
1079 | |||
1041 | put_transaction(cur_trans); | 1080 | put_transaction(cur_trans); |
1042 | put_transaction(cur_trans); | 1081 | put_transaction(cur_trans); |
1043 | 1082 | ||
@@ -1046,6 +1085,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
1046 | list_splice_init(&root->fs_info->dead_roots, &dirty_fs_roots); | 1085 | list_splice_init(&root->fs_info->dead_roots, &dirty_fs_roots); |
1047 | 1086 | ||
1048 | mutex_unlock(&root->fs_info->trans_mutex); | 1087 | mutex_unlock(&root->fs_info->trans_mutex); |
1088 | |||
1049 | kmem_cache_free(btrfs_trans_handle_cachep, trans); | 1089 | kmem_cache_free(btrfs_trans_handle_cachep, trans); |
1050 | 1090 | ||
1051 | if (root->fs_info->closing) { | 1091 | if (root->fs_info->closing) { |
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h index eef2cb7d7e78..202c8be6c05d 100644 --- a/fs/btrfs/transaction.h +++ b/fs/btrfs/transaction.h | |||
@@ -47,8 +47,10 @@ struct btrfs_trans_handle { | |||
47 | }; | 47 | }; |
48 | 48 | ||
49 | struct btrfs_pending_snapshot { | 49 | struct btrfs_pending_snapshot { |
50 | struct dentry *dentry; | ||
50 | struct btrfs_root *root; | 51 | struct btrfs_root *root; |
51 | char *name; | 52 | char *name; |
53 | struct btrfs_key root_key; | ||
52 | struct list_head list; | 54 | struct list_head list; |
53 | }; | 55 | }; |
54 | 56 | ||