summaryrefslogtreecommitdiff
path: root/extent-tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'extent-tree.c')
-rw-r--r--extent-tree.c104
1 files changed, 99 insertions, 5 deletions
diff --git a/extent-tree.c b/extent-tree.c
index 48d06d85..7860d1d9 100644
--- a/extent-tree.c
+++ b/extent-tree.c
@@ -2629,11 +2629,11 @@ error:
return ret;
}
-static int btrfs_reserve_extent(struct btrfs_trans_handle *trans,
- struct btrfs_root *root,
- u64 num_bytes, u64 empty_size,
- u64 hint_byte, u64 search_end,
- struct btrfs_key *ins, int data)
+int btrfs_reserve_extent(struct btrfs_trans_handle *trans,
+ struct btrfs_root *root,
+ u64 num_bytes, u64 empty_size,
+ u64 hint_byte, u64 search_end,
+ struct btrfs_key *ins, int data)
{
int ret;
u64 search_start = 0;
@@ -3488,3 +3488,97 @@ int btrfs_fix_block_accounting(struct btrfs_trans_handle *trans,
btrfs_release_path(&path);
return 0;
}
+
+/*
+ * Record a file extent. Do all the required works, such as inserting
+ * file extent item, inserting extent item and backref item into extent
+ * tree and updating block accounting.
+ */
+int btrfs_record_file_extent(struct btrfs_trans_handle *trans,
+ struct btrfs_root *root, u64 objectid,
+ struct btrfs_inode_item *inode,
+ u64 file_pos, u64 disk_bytenr,
+ u64 num_bytes)
+{
+ int ret;
+ struct btrfs_fs_info *info = root->fs_info;
+ struct btrfs_root *extent_root = info->extent_root;
+ struct extent_buffer *leaf;
+ struct btrfs_file_extent_item *fi;
+ struct btrfs_key ins_key;
+ struct btrfs_path path;
+ struct btrfs_extent_item *ei;
+ u64 nbytes;
+
+ if (disk_bytenr == 0) {
+ ret = btrfs_insert_file_extent(trans, root, objectid,
+ file_pos, disk_bytenr,
+ num_bytes, num_bytes);
+ return ret;
+ }
+
+ btrfs_init_path(&path);
+
+ ins_key.objectid = objectid;
+ ins_key.offset = file_pos;
+ btrfs_set_key_type(&ins_key, BTRFS_EXTENT_DATA_KEY);
+ ret = btrfs_insert_empty_item(trans, root, &path, &ins_key,
+ sizeof(*fi));
+ if (ret)
+ goto fail;
+ leaf = path.nodes[0];
+ fi = btrfs_item_ptr(leaf, path.slots[0],
+ struct btrfs_file_extent_item);
+ btrfs_set_file_extent_generation(leaf, fi, trans->transid);
+ btrfs_set_file_extent_type(leaf, fi, BTRFS_FILE_EXTENT_REG);
+ btrfs_set_file_extent_disk_bytenr(leaf, fi, disk_bytenr);
+ btrfs_set_file_extent_disk_num_bytes(leaf, fi, num_bytes);
+ btrfs_set_file_extent_offset(leaf, fi, 0);
+ btrfs_set_file_extent_num_bytes(leaf, fi, num_bytes);
+ btrfs_set_file_extent_ram_bytes(leaf, fi, num_bytes);
+ btrfs_set_file_extent_compression(leaf, fi, 0);
+ btrfs_set_file_extent_encryption(leaf, fi, 0);
+ btrfs_set_file_extent_other_encoding(leaf, fi, 0);
+ btrfs_mark_buffer_dirty(leaf);
+
+ nbytes = btrfs_stack_inode_nbytes(inode) + num_bytes;
+ btrfs_set_stack_inode_nbytes(inode, nbytes);
+
+ btrfs_release_path(&path);
+
+ ins_key.objectid = disk_bytenr;
+ ins_key.offset = num_bytes;
+ ins_key.type = BTRFS_EXTENT_ITEM_KEY;
+
+ ret = btrfs_insert_empty_item(trans, extent_root, &path,
+ &ins_key, sizeof(*ei));
+ if (ret == 0) {
+ leaf = path.nodes[0];
+ ei = btrfs_item_ptr(leaf, path.slots[0],
+ struct btrfs_extent_item);
+
+ btrfs_set_extent_refs(leaf, ei, 0);
+ btrfs_set_extent_generation(leaf, ei, 0);
+ btrfs_set_extent_flags(leaf, ei, BTRFS_EXTENT_FLAG_DATA);
+
+ btrfs_mark_buffer_dirty(leaf);
+
+ ret = btrfs_update_block_group(trans, root, disk_bytenr,
+ num_bytes, 1, 0);
+ if (ret)
+ goto fail;
+ } else if (ret != -EEXIST) {
+ goto fail;
+ }
+ btrfs_extent_post_op(trans, extent_root);
+
+ ret = btrfs_inc_extent_ref(trans, root, disk_bytenr, num_bytes, 0,
+ root->root_key.objectid,
+ objectid, file_pos);
+ if (ret)
+ goto fail;
+ ret = 0;
+fail:
+ btrfs_release_path(&path);
+ return ret;
+}