aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-11-17 20:37:39 -0500
committerChris Mason <chris.mason@oracle.com>2008-11-17 20:37:39 -0500
commit0660b5af3f7ac0fac69de975914e1f4a3a586fb3 (patch)
tree5e911dfad23df29f1815fbbc76d38ffff7fe36d8 /fs
parent3394e1607eaf870ebba37d303fbd590a4c569908 (diff)
Btrfs: Add backrefs and forward refs for subvols and snapshots
Subvols and snapshots can now be referenced from any point in the directory tree. We need to maintain back refs for them so we can find lost subvols. Forward refs are added so that we know all of the subvols and snapshots referenced anywhere in the directory tree of a single subvol. This can be used to do recursive snapshotting (but they aren't yet) and it is also used to detect and prevent directory loops when creating new snapshots. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/ctree.h67
-rw-r--r--fs/btrfs/inode.c6
-rw-r--r--fs/btrfs/ioctl.c24
-rw-r--r--fs/btrfs/root-tree.c76
-rw-r--r--fs/btrfs/transaction.c31
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 */
475struct 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
1275BTRFS_SETGET_FUNCS(dir_log_end, struct btrfs_dir_log_item, end, 64); 1298BTRFS_SETGET_FUNCS(dir_log_end, struct btrfs_dir_log_item, end, 64);
1276 1299
1300/*
1301 * struct btrfs_root_ref
1302 */
1303BTRFS_SETGET_FUNCS(root_ref_dirid, struct btrfs_root_ref, dirid, 64);
1304BTRFS_SETGET_FUNCS(root_ref_sequence, struct btrfs_root_ref, sequence, 64);
1305BTRFS_SETGET_FUNCS(root_ref_name_len, struct btrfs_root_ref, name_len, 16);
1306
1277/* struct btrfs_dir_item */ 1307/* struct btrfs_dir_item */
1278BTRFS_SETGET_FUNCS(dir_data_len, struct btrfs_dir_item, data_len, 16); 1308BTRFS_SETGET_FUNCS(dir_data_len, struct btrfs_dir_item, data_len, 16);
1279BTRFS_SETGET_FUNCS(dir_type, struct btrfs_dir_item, type, 8); 1309BTRFS_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 */
1804int 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);
1774int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, 1809int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
1775 struct btrfs_key *key); 1810 struct btrfs_key *key);
1776int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root 1811int 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
279int 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 */
316int 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);
858fail: 873fail: