diff options
-rw-r--r-- | fs/btrfs/ctree.h | 67 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 6 | ||||
-rw-r--r-- | fs/btrfs/ioctl.c | 24 | ||||
-rw-r--r-- | fs/btrfs/root-tree.c | 76 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 31 |
5 files changed, 172 insertions, 32 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index b3bc65b08c6a..ad2cbe63503c 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -469,6 +469,15 @@ struct btrfs_root_item { | |||
469 | u8 level; | 469 | u8 level; |
470 | } __attribute__ ((__packed__)); | 470 | } __attribute__ ((__packed__)); |
471 | 471 | ||
472 | /* | ||
473 | * this is used for both forward and backward root refs | ||
474 | */ | ||
475 | struct btrfs_root_ref { | ||
476 | __le64 dirid; | ||
477 | __le64 sequence; | ||
478 | __le16 name_len; | ||
479 | } __attribute__ ((__packed__)); | ||
480 | |||
472 | #define BTRFS_FILE_EXTENT_INLINE 0 | 481 | #define BTRFS_FILE_EXTENT_INLINE 0 |
473 | #define BTRFS_FILE_EXTENT_REG 1 | 482 | #define BTRFS_FILE_EXTENT_REG 1 |
474 | #define BTRFS_FILE_EXTENT_PREALLOC 2 | 483 | #define BTRFS_FILE_EXTENT_PREALLOC 2 |
@@ -814,27 +823,27 @@ struct btrfs_root { | |||
814 | * the FS | 823 | * the FS |
815 | */ | 824 | */ |
816 | #define BTRFS_INODE_ITEM_KEY 1 | 825 | #define BTRFS_INODE_ITEM_KEY 1 |
817 | #define BTRFS_INODE_REF_KEY 2 | 826 | #define BTRFS_INODE_REF_KEY 12 |
818 | #define BTRFS_XATTR_ITEM_KEY 8 | 827 | #define BTRFS_XATTR_ITEM_KEY 24 |
819 | #define BTRFS_ORPHAN_ITEM_KEY 9 | 828 | #define BTRFS_ORPHAN_ITEM_KEY 48 |
820 | /* reserve 2-15 close to the inode for later flexibility */ | 829 | /* reserve 2-15 close to the inode for later flexibility */ |
821 | 830 | ||
822 | /* | 831 | /* |
823 | * dir items are the name -> inode pointers in a directory. There is one | 832 | * dir items are the name -> inode pointers in a directory. There is one |
824 | * for every name in a directory. | 833 | * for every name in a directory. |
825 | */ | 834 | */ |
826 | #define BTRFS_DIR_LOG_ITEM_KEY 14 | 835 | #define BTRFS_DIR_LOG_ITEM_KEY 60 |
827 | #define BTRFS_DIR_LOG_INDEX_KEY 15 | 836 | #define BTRFS_DIR_LOG_INDEX_KEY 72 |
828 | #define BTRFS_DIR_ITEM_KEY 16 | 837 | #define BTRFS_DIR_ITEM_KEY 84 |
829 | #define BTRFS_DIR_INDEX_KEY 17 | 838 | #define BTRFS_DIR_INDEX_KEY 96 |
830 | /* | 839 | /* |
831 | * extent data is for file data | 840 | * extent data is for file data |
832 | */ | 841 | */ |
833 | #define BTRFS_EXTENT_DATA_KEY 18 | 842 | #define BTRFS_EXTENT_DATA_KEY 108 |
834 | /* | 843 | /* |
835 | * csum items have the checksums for data in the extents | 844 | * csum items have the checksums for data in the extents |
836 | */ | 845 | */ |
837 | #define BTRFS_CSUM_ITEM_KEY 19 | 846 | #define BTRFS_CSUM_ITEM_KEY 120 |
838 | 847 | ||
839 | 848 | ||
840 | /* reserve 21-31 for other file/dir stuff */ | 849 | /* reserve 21-31 for other file/dir stuff */ |
@@ -843,23 +852,37 @@ struct btrfs_root { | |||
843 | * root items point to tree roots. There are typically in the root | 852 | * root items point to tree roots. There are typically in the root |
844 | * tree used by the super block to find all the other trees | 853 | * tree used by the super block to find all the other trees |
845 | */ | 854 | */ |
846 | #define BTRFS_ROOT_ITEM_KEY 32 | 855 | #define BTRFS_ROOT_ITEM_KEY 132 |
856 | |||
857 | /* | ||
858 | * root backrefs tie subvols and snapshots to the directory entries that | ||
859 | * reference them | ||
860 | */ | ||
861 | #define BTRFS_ROOT_BACKREF_KEY 144 | ||
862 | |||
863 | /* | ||
864 | * root refs make a fast index for listing all of the snapshots and | ||
865 | * subvolumes referenced by a given root. They point directly to the | ||
866 | * directory item in the root that references the subvol | ||
867 | */ | ||
868 | #define BTRFS_ROOT_REF_KEY 156 | ||
869 | |||
847 | /* | 870 | /* |
848 | * extent items are in the extent map tree. These record which blocks | 871 | * extent items are in the extent map tree. These record which blocks |
849 | * are used, and how many references there are to each block | 872 | * are used, and how many references there are to each block |
850 | */ | 873 | */ |
851 | #define BTRFS_EXTENT_ITEM_KEY 33 | 874 | #define BTRFS_EXTENT_ITEM_KEY 168 |
852 | #define BTRFS_EXTENT_REF_KEY 34 | 875 | #define BTRFS_EXTENT_REF_KEY 180 |
853 | 876 | ||
854 | /* | 877 | /* |
855 | * block groups give us hints into the extent allocation trees. Which | 878 | * block groups give us hints into the extent allocation trees. Which |
856 | * blocks are free etc etc | 879 | * blocks are free etc etc |
857 | */ | 880 | */ |
858 | #define BTRFS_BLOCK_GROUP_ITEM_KEY 50 | 881 | #define BTRFS_BLOCK_GROUP_ITEM_KEY 192 |
859 | 882 | ||
860 | #define BTRFS_DEV_EXTENT_KEY 75 | 883 | #define BTRFS_DEV_EXTENT_KEY 204 |
861 | #define BTRFS_DEV_ITEM_KEY 76 | 884 | #define BTRFS_DEV_ITEM_KEY 216 |
862 | #define BTRFS_CHUNK_ITEM_KEY 77 | 885 | #define BTRFS_CHUNK_ITEM_KEY 228 |
863 | 886 | ||
864 | /* | 887 | /* |
865 | * string items are for debugging. They just store a short string of | 888 | * string items are for debugging. They just store a short string of |
@@ -1274,6 +1297,13 @@ static inline void btrfs_set_item_key(struct extent_buffer *eb, | |||
1274 | 1297 | ||
1275 | BTRFS_SETGET_FUNCS(dir_log_end, struct btrfs_dir_log_item, end, 64); | 1298 | BTRFS_SETGET_FUNCS(dir_log_end, struct btrfs_dir_log_item, end, 64); |
1276 | 1299 | ||
1300 | /* | ||
1301 | * struct btrfs_root_ref | ||
1302 | */ | ||
1303 | BTRFS_SETGET_FUNCS(root_ref_dirid, struct btrfs_root_ref, dirid, 64); | ||
1304 | BTRFS_SETGET_FUNCS(root_ref_sequence, struct btrfs_root_ref, sequence, 64); | ||
1305 | BTRFS_SETGET_FUNCS(root_ref_name_len, struct btrfs_root_ref, name_len, 16); | ||
1306 | |||
1277 | /* struct btrfs_dir_item */ | 1307 | /* struct btrfs_dir_item */ |
1278 | BTRFS_SETGET_FUNCS(dir_data_len, struct btrfs_dir_item, data_len, 16); | 1308 | BTRFS_SETGET_FUNCS(dir_data_len, struct btrfs_dir_item, data_len, 16); |
1279 | BTRFS_SETGET_FUNCS(dir_type, struct btrfs_dir_item, type, 8); | 1309 | BTRFS_SETGET_FUNCS(dir_type, struct btrfs_dir_item, type, 8); |
@@ -1771,6 +1801,11 @@ int btrfs_drop_subtree(struct btrfs_trans_handle *trans, | |||
1771 | struct extent_buffer *node, | 1801 | struct extent_buffer *node, |
1772 | struct extent_buffer *parent); | 1802 | struct extent_buffer *parent); |
1773 | /* root-item.c */ | 1803 | /* root-item.c */ |
1804 | int btrfs_add_root_ref(struct btrfs_trans_handle *trans, | ||
1805 | struct btrfs_root *tree_root, | ||
1806 | u64 root_id, u8 type, u64 ref_id, | ||
1807 | u64 dirid, u64 sequence, | ||
1808 | const char *name, int name_len); | ||
1774 | int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 1809 | int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
1775 | struct btrfs_key *key); | 1810 | struct btrfs_key *key); |
1776 | int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root | 1811 | int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 7ef79ce86e25..6854bf41856a 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -4580,6 +4580,12 @@ static int btrfs_rename(struct inode * old_dir, struct dentry *old_dentry, | |||
4580 | return -ENOTEMPTY; | 4580 | return -ENOTEMPTY; |
4581 | } | 4581 | } |
4582 | 4582 | ||
4583 | /* to rename a snapshot or subvolume, we need to juggle the | ||
4584 | * backrefs. This isn't coded yet | ||
4585 | */ | ||
4586 | if (old_inode->i_ino == BTRFS_FIRST_FREE_OBJECTID) | ||
4587 | return -EXDEV; | ||
4588 | |||
4583 | ret = btrfs_check_free_space(root, 1, 0); | 4589 | ret = btrfs_check_free_space(root, 1, 0); |
4584 | if (ret) | 4590 | if (ret) |
4585 | goto out_unlock; | 4591 | goto out_unlock; |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 773db07b5f72..536ae8837801 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -145,13 +145,23 @@ static noinline int create_subvol(struct btrfs_root *root, | |||
145 | BTRFS_FT_DIR, index); | 145 | BTRFS_FT_DIR, index); |
146 | if (ret) | 146 | if (ret) |
147 | goto fail; | 147 | goto fail; |
148 | #if 0 | 148 | |
149 | ret = btrfs_insert_inode_ref(trans, root->fs_info->tree_root, | 149 | /* add the backref first */ |
150 | name, namelen, objectid, | 150 | ret = btrfs_add_root_ref(trans, root->fs_info->tree_root, |
151 | root->fs_info->sb->s_root->d_inode->i_ino, 0); | 151 | objectid, BTRFS_ROOT_BACKREF_KEY, |
152 | if (ret) | 152 | root->root_key.objectid, |
153 | goto fail; | 153 | dir->i_ino, index, name, namelen); |
154 | #endif | 154 | |
155 | BUG_ON(ret); | ||
156 | |||
157 | /* now add the forward ref */ | ||
158 | ret = btrfs_add_root_ref(trans, root->fs_info->tree_root, | ||
159 | root->root_key.objectid, BTRFS_ROOT_REF_KEY, | ||
160 | objectid, | ||
161 | dir->i_ino, index, name, namelen); | ||
162 | |||
163 | BUG_ON(ret); | ||
164 | |||
155 | ret = btrfs_commit_transaction(trans, root); | 165 | ret = btrfs_commit_transaction(trans, root); |
156 | if (ret) | 166 | if (ret) |
157 | goto fail_commit; | 167 | goto fail_commit; |
diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c index eb7f7655e9d5..e9be3abcb368 100644 --- a/fs/btrfs/root-tree.c +++ b/fs/btrfs/root-tree.c | |||
@@ -84,7 +84,7 @@ int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, | |||
84 | int slot; | 84 | int slot; |
85 | 85 | ||
86 | search_key.objectid = objectid; | 86 | search_key.objectid = objectid; |
87 | search_key.type = (u8)-1; | 87 | search_key.type = BTRFS_ROOT_ITEM_KEY; |
88 | search_key.offset = (u64)-1; | 88 | search_key.offset = (u64)-1; |
89 | 89 | ||
90 | path = btrfs_alloc_path(); | 90 | path = btrfs_alloc_path(); |
@@ -275,3 +275,77 @@ out: | |||
275 | btrfs_free_path(path); | 275 | btrfs_free_path(path); |
276 | return ret; | 276 | return ret; |
277 | } | 277 | } |
278 | |||
279 | int btrfs_del_root_ref(struct btrfs_trans_handle *trans, | ||
280 | struct btrfs_root *tree_root, | ||
281 | u64 root_id, u8 type, u64 ref_id) | ||
282 | { | ||
283 | struct btrfs_key key; | ||
284 | int ret; | ||
285 | struct btrfs_path *path; | ||
286 | |||
287 | path = btrfs_alloc_path(); | ||
288 | |||
289 | key.objectid = root_id; | ||
290 | key.type = type; | ||
291 | key.offset = ref_id; | ||
292 | |||
293 | ret = btrfs_search_slot(trans, tree_root, &key, path, -1, 1); | ||
294 | BUG_ON(ret); | ||
295 | |||
296 | ret = btrfs_del_item(trans, tree_root, path); | ||
297 | BUG_ON(ret); | ||
298 | |||
299 | btrfs_free_path(path); | ||
300 | return ret; | ||
301 | } | ||
302 | |||
303 | /* | ||
304 | * add a btrfs_root_ref item. type is either BTRFS_ROOT_REF_KEY | ||
305 | * or BTRFS_ROOT_BACKREF_KEY. | ||
306 | * | ||
307 | * The dirid, sequence, name and name_len refer to the directory entry | ||
308 | * that is referencing the root. | ||
309 | * | ||
310 | * For a forward ref, the root_id is the id of the tree referencing | ||
311 | * the root and ref_id is the id of the subvol or snapshot. | ||
312 | * | ||
313 | * For a back ref the root_id is the id of the subvol or snapshot and | ||
314 | * ref_id is the id of the tree referencing it. | ||
315 | */ | ||
316 | int btrfs_add_root_ref(struct btrfs_trans_handle *trans, | ||
317 | struct btrfs_root *tree_root, | ||
318 | u64 root_id, u8 type, u64 ref_id, | ||
319 | u64 dirid, u64 sequence, | ||
320 | const char *name, int name_len) | ||
321 | { | ||
322 | struct btrfs_key key; | ||
323 | int ret; | ||
324 | struct btrfs_path *path; | ||
325 | struct btrfs_root_ref *ref; | ||
326 | struct extent_buffer *leaf; | ||
327 | unsigned long ptr; | ||
328 | |||
329 | |||
330 | path = btrfs_alloc_path(); | ||
331 | |||
332 | key.objectid = root_id; | ||
333 | key.type = type; | ||
334 | key.offset = ref_id; | ||
335 | |||
336 | ret = btrfs_insert_empty_item(trans, tree_root, path, &key, | ||
337 | sizeof(*ref) + name_len); | ||
338 | BUG_ON(ret); | ||
339 | |||
340 | leaf = path->nodes[0]; | ||
341 | ref = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_root_ref); | ||
342 | btrfs_set_root_ref_dirid(leaf, ref, dirid); | ||
343 | btrfs_set_root_ref_sequence(leaf, ref, sequence); | ||
344 | btrfs_set_root_ref_name_len(leaf, ref, name_len); | ||
345 | ptr = (unsigned long)(ref + 1); | ||
346 | write_extent_buffer(leaf, name, ptr, name_len); | ||
347 | btrfs_mark_buffer_dirty(leaf); | ||
348 | |||
349 | btrfs_free_path(path); | ||
350 | return ret; | ||
351 | } | ||
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 93f23a456a36..e9c8ebeedd7e 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -831,28 +831,43 @@ static noinline int finish_pending_snapshot(struct btrfs_fs_info *fs_info, | |||
831 | struct btrfs_trans_handle *trans; | 831 | struct btrfs_trans_handle *trans; |
832 | struct inode *parent_inode; | 832 | struct inode *parent_inode; |
833 | struct inode *inode; | 833 | struct inode *inode; |
834 | struct btrfs_root *parent_root; | ||
834 | 835 | ||
835 | parent_inode = pending->dentry->d_parent->d_inode; | 836 | parent_inode = pending->dentry->d_parent->d_inode; |
836 | trans = btrfs_start_transaction(BTRFS_I(parent_inode)->root, 1); | 837 | parent_root = BTRFS_I(parent_inode)->root; |
838 | trans = btrfs_start_transaction(parent_root, 1); | ||
837 | 839 | ||
838 | /* | 840 | /* |
839 | * insert the directory item | 841 | * insert the directory item |
840 | */ | 842 | */ |
841 | namelen = strlen(pending->name); | 843 | namelen = strlen(pending->name); |
842 | ret = btrfs_set_inode_index(parent_inode, &index); | 844 | ret = btrfs_set_inode_index(parent_inode, &index); |
843 | ret = btrfs_insert_dir_item(trans, | 845 | ret = btrfs_insert_dir_item(trans, parent_root, |
844 | BTRFS_I(parent_inode)->root, | ||
845 | pending->name, namelen, | 846 | pending->name, namelen, |
846 | parent_inode->i_ino, | 847 | parent_inode->i_ino, |
847 | &pending->root_key, BTRFS_FT_DIR, index); | 848 | &pending->root_key, BTRFS_FT_DIR, index); |
848 | 849 | ||
849 | if (ret) | 850 | if (ret) |
850 | goto fail; | 851 | goto fail; |
851 | #if 0 | 852 | |
852 | ret = btrfs_insert_inode_ref(trans, root->fs_info->tree_root, | 853 | /* add the backref first */ |
853 | pending->name, strlen(pending->name), objectid, | 854 | ret = btrfs_add_root_ref(trans, parent_root->fs_info->tree_root, |
854 | root->fs_info->sb->s_root->d_inode->i_ino, 0); | 855 | pending->root_key.objectid, |
855 | #endif | 856 | BTRFS_ROOT_BACKREF_KEY, |
857 | parent_root->root_key.objectid, | ||
858 | parent_inode->i_ino, index, pending->name, | ||
859 | namelen); | ||
860 | |||
861 | BUG_ON(ret); | ||
862 | |||
863 | /* now add the forward ref */ | ||
864 | ret = btrfs_add_root_ref(trans, parent_root->fs_info->tree_root, | ||
865 | parent_root->root_key.objectid, | ||
866 | BTRFS_ROOT_REF_KEY, | ||
867 | pending->root_key.objectid, | ||
868 | parent_inode->i_ino, index, pending->name, | ||
869 | namelen); | ||
870 | |||
856 | inode = btrfs_lookup_dentry(parent_inode, pending->dentry); | 871 | inode = btrfs_lookup_dentry(parent_inode, pending->dentry); |
857 | d_instantiate(pending->dentry, inode); | 872 | d_instantiate(pending->dentry, inode); |
858 | fail: | 873 | fail: |