summaryrefslogtreecommitdiff
path: root/fs/btrfs/ioctl.c
diff options
context:
space:
mode:
authorZheng Yan <zheng.yan@oracle.com>2008-09-23 13:14:14 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:07 -0400
commit31840ae1a6b433ca0e6a8d341756ff478bbf959e (patch)
tree9343db596aec175e9640aa2800b80f01496d7047 /fs/btrfs/ioctl.c
parent1c2308f8e7d8491467e0095af2b01500f1b70819 (diff)
Btrfs: Full back reference support
This patch makes the back reference system to explicit record the location of parent node for all types of extents. The location of parent node is placed into the offset field of backref key. Every time a tree block is balanced, the back references for the affected lower level extents are updated. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r--fs/btrfs/ioctl.c57
1 files changed, 32 insertions, 25 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index f84b5f6991cc..4c6e0c15754d 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -76,9 +76,8 @@ static noinline int create_subvol(struct btrfs_root *root, char *name,
if (ret)
goto fail;
- leaf = btrfs_alloc_free_block(trans, root, root->leafsize,
- objectid, trans->transid, 0, 0,
- 0, 0);
+ leaf = btrfs_alloc_free_block(trans, root, root->leafsize, 0,
+ objectid, trans->transid, 0, 0, 0);
if (IS_ERR(leaf)) {
ret = PTR_ERR(leaf);
goto fail;
@@ -525,13 +524,10 @@ long btrfs_ioctl_clone(struct file *file, unsigned long src_fd)
struct file *src_file;
struct inode *src;
struct btrfs_trans_handle *trans;
- struct btrfs_ordered_extent *ordered;
struct btrfs_path *path;
struct extent_buffer *leaf;
char *buf;
struct btrfs_key key;
- struct btrfs_key new_key;
- u32 size;
u32 nritems;
int slot;
int ret;
@@ -576,6 +572,7 @@ long btrfs_ioctl_clone(struct file *file, unsigned long src_fd)
/* do any pending delalloc/csum calc on src, one way or
another, and lock file content */
while (1) {
+ struct btrfs_ordered_extent *ordered;
lock_extent(&BTRFS_I(src)->io_tree, 0, (u64)-1, GFP_NOFS);
ordered = btrfs_lookup_first_ordered_extent(inode, (u64)-1);
if (BTRFS_I(src)->delalloc_bytes == 0 && !ordered)
@@ -619,6 +616,32 @@ long btrfs_ioctl_clone(struct file *file, unsigned long src_fd)
key.objectid != src->i_ino)
break;
+ if (btrfs_key_type(&key) == BTRFS_EXTENT_DATA_KEY ||
+ btrfs_key_type(&key) == BTRFS_CSUM_ITEM_KEY) {
+ u32 size;
+ struct btrfs_key new_key;
+
+ size = btrfs_item_size_nr(leaf, slot);
+ read_extent_buffer(leaf, buf,
+ btrfs_item_ptr_offset(leaf, slot),
+ size);
+ btrfs_release_path(root, path);
+
+ memcpy(&new_key, &key, sizeof(new_key));
+ new_key.objectid = inode->i_ino;
+ ret = btrfs_insert_empty_item(trans, root, path,
+ &new_key, size);
+ if (ret)
+ goto out;
+
+ leaf = path->nodes[0];
+ slot = path->slots[0];
+ write_extent_buffer(leaf, buf,
+ btrfs_item_ptr_offset(leaf, slot),
+ size);
+ btrfs_mark_buffer_dirty(leaf);
+ }
+
if (btrfs_key_type(&key) == BTRFS_EXTENT_DATA_KEY) {
struct btrfs_file_extent_item *extent;
int found_type;
@@ -634,31 +657,15 @@ long btrfs_ioctl_clone(struct file *file, unsigned long src_fd)
/* ds == 0 means there's a hole */
if (ds != 0) {
ret = btrfs_inc_extent_ref(trans, root,
- ds, dl,
+ ds, dl, leaf->start,
root->root_key.objectid,
trans->transid,
inode->i_ino, key.offset);
- if (ret)
- goto out;
+ BUG_ON(ret);
}
}
}
-
- if (btrfs_key_type(&key) == BTRFS_EXTENT_DATA_KEY ||
- btrfs_key_type(&key) == BTRFS_CSUM_ITEM_KEY) {
- size = btrfs_item_size_nr(leaf, slot);
- read_extent_buffer(leaf, buf,
- btrfs_item_ptr_offset(leaf, slot),
- size);
- btrfs_release_path(root, path);
- memcpy(&new_key, &key, sizeof(new_key));
- new_key.objectid = inode->i_ino;
- ret = btrfs_insert_item(trans, root, &new_key,
- buf, size);
- BUG_ON(ret);
- } else {
- btrfs_release_path(root, path);
- }
+ btrfs_release_path(root, path);
key.offset++;
}
ret = 0;