aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/root-tree.c
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/btrfs/root-tree.c
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/btrfs/root-tree.c')
-rw-r--r--fs/btrfs/root-tree.c76
1 files changed, 75 insertions, 1 deletions
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}