aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--btrfs-convert.c154
-rw-r--r--ctree.h10
-rw-r--r--disk-io.c31
-rw-r--r--disk-io.h2
-rw-r--r--extent-tree.c104
-rw-r--r--mkfs.c231
6 files changed, 235 insertions, 297 deletions
diff --git a/btrfs-convert.c b/btrfs-convert.c
index edef1bd..26c7b5f 100644
--- a/btrfs-convert.c
+++ b/btrfs-convert.c
@@ -351,124 +351,33 @@ fail:
ret = -1;
return ret;
}
-/*
- * 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.
- */
-static int 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 checksum)
+
+static int csum_disk_extent(struct btrfs_trans_handle *trans,
+ struct btrfs_root *root,
+ 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;
u32 blocksize = root->sectorsize;
- 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);
-
- if (checksum) {
- u64 offset;
- char *buffer;
+ u64 offset;
+ char *buffer;
+ int ret = 0;
- ret = -ENOMEM;
- buffer = malloc(blocksize);
- if (!buffer)
- goto fail;
- for (offset = 0; offset < num_bytes; offset += blocksize) {
- ret = read_disk_extent(root, disk_bytenr + offset,
- blocksize, buffer);
- if (ret)
- break;
- ret = btrfs_csum_file_block(trans,
- root->fs_info->csum_root,
- disk_bytenr + num_bytes,
- disk_bytenr + offset,
- buffer, blocksize);
- if (ret)
- break;
- }
- free(buffer);
+ buffer = malloc(blocksize);
+ if (!buffer)
+ return -ENOMEM;
+ for (offset = 0; offset < num_bytes; offset += blocksize) {
+ ret = read_disk_extent(root, disk_bytenr + offset,
+ blocksize, buffer);
if (ret)
- goto fail;
- }
-
- 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);
+ break;
+ ret = btrfs_csum_file_block(trans,
+ root->fs_info->csum_root,
+ disk_bytenr + num_bytes,
+ disk_bytenr + offset,
+ buffer, blocksize);
if (ret)
- goto fail;
- } else if (ret != -EEXIST) {
- goto fail;
+ break;
}
- 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);
+ free(buffer);
return ret;
}
@@ -478,11 +387,17 @@ static int record_file_blocks(struct btrfs_trans_handle *trans,
u64 file_block, u64 disk_block,
u64 num_blocks, int checksum)
{
+ int ret;
u64 file_pos = file_block * root->sectorsize;
u64 disk_bytenr = disk_block * root->sectorsize;
u64 num_bytes = num_blocks * root->sectorsize;
- return record_file_extent(trans, root, objectid, inode, file_pos,
- disk_bytenr, num_bytes, checksum);
+ ret = btrfs_record_file_extent(trans, root, objectid, inode, file_pos,
+ disk_bytenr, num_bytes);
+
+ if (ret || !checksum)
+ return ret;
+
+ return csum_disk_extent(trans, root, disk_bytenr, num_bytes);
}
struct blk_iterate_data {
@@ -1293,9 +1208,9 @@ static int create_ext2_image(struct btrfs_root *root, ext2_filsys ext2_fs,
sectorsize);
if (ret)
goto fail;
- ret = record_file_extent(trans, root, objectid,
- &btrfs_inode, last_byte,
- key.objectid, sectorsize, 0);
+ ret = btrfs_record_file_extent(trans, root, objectid,
+ &btrfs_inode, last_byte,
+ key.objectid, sectorsize);
if (ret)
goto fail;
}
@@ -1354,8 +1269,9 @@ next:
if (ret)
goto fail;
}
- ret = record_file_extent(trans, root, objectid, &btrfs_inode,
- bytenr, bytenr, num_bytes, 0);
+ ret = btrfs_record_file_extent(trans, root, objectid,
+ &btrfs_inode, bytenr, bytenr,
+ num_bytes);
if (ret)
goto fail;
last_byte = bytenr + num_bytes;
diff --git a/ctree.h b/ctree.h
index 8ca3e76..2117374 100644
--- a/ctree.h
+++ b/ctree.h
@@ -2124,6 +2124,11 @@ static inline int btrfs_fs_incompat(struct btrfs_fs_info *fs_info, u64 flag)
btrfs_item_offset_nr(leaf, slot)))
/* extent-tree.c */
+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_fix_block_accounting(struct btrfs_trans_handle *trans,
struct btrfs_root *root);
void btrfs_pin_extent(struct btrfs_fs_info *fs_info, u64 bytenr, u64 num_bytes);
@@ -2191,6 +2196,11 @@ int btrfs_make_block_groups(struct btrfs_trans_handle *trans,
int btrfs_update_block_group(struct btrfs_trans_handle *trans,
struct btrfs_root *root, u64 bytenr, u64 num,
int alloc, int mark_free);
+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);
/* ctree.c */
int btrfs_del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
struct btrfs_path *path, int level, int slot);
diff --git a/disk-io.c b/disk-io.c
index b06eb03..ca76c42 100644
--- a/disk-io.c
+++ b/disk-io.c
@@ -312,9 +312,9 @@ struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
return NULL;
}
-static int write_tree_block(struct btrfs_trans_handle *trans,
- struct btrfs_root *root,
- struct extent_buffer *eb)
+int write_and_map_eb(struct btrfs_trans_handle *trans,
+ struct btrfs_root *root,
+ struct extent_buffer *eb)
{
int ret;
int dev_nr;
@@ -322,15 +322,6 @@ static int write_tree_block(struct btrfs_trans_handle *trans,
u64 *raid_map = NULL;
struct btrfs_multi_bio *multi = NULL;
- if (check_tree_block(root, eb))
- BUG();
-
- if (!btrfs_buffer_uptodate(eb, trans->transid))
- BUG();
-
- btrfs_set_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN);
- csum_tree_block(root, eb, 0);
-
dev_nr = 0;
length = eb->len;
ret = btrfs_map_block(&root->fs_info->mapping_tree, WRITE,
@@ -353,6 +344,22 @@ static int write_tree_block(struct btrfs_trans_handle *trans,
return 0;
}
+int write_tree_block(struct btrfs_trans_handle *trans,
+ struct btrfs_root *root,
+ struct extent_buffer *eb)
+{
+ if (check_tree_block(root, eb))
+ BUG();
+
+ if (!btrfs_buffer_uptodate(eb, trans->transid))
+ BUG();
+
+ btrfs_set_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN);
+ csum_tree_block(root, eb, 0);
+
+ return write_and_map_eb(trans, root, eb);
+}
+
int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
u32 stripesize, struct btrfs_root *root,
struct btrfs_fs_info *fs_info, u64 objectid)
diff --git a/disk-io.h b/disk-io.h
index 681ff79..6f2d4f4 100644
--- a/disk-io.h
+++ b/disk-io.h
@@ -101,6 +101,8 @@ int csum_tree_block_size(struct extent_buffer *buf, u16 csum_sectorsize,
int verify);
int verify_tree_block_csum_silent(struct extent_buffer *buf, u16 csum_size);
int btrfs_read_buffer(struct extent_buffer *buf, u64 parent_transid);
+int write_and_map_eb(struct btrfs_trans_handle *trans, struct btrfs_root *root,
+ struct extent_buffer *eb);
#endif
/* raid6.c */
diff --git a/extent-tree.c b/extent-tree.c
index 48d06d8..7860d1d 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;
+}
diff --git a/mkfs.c b/mkfs.c
index 40da546..d576797 100644
--- a/mkfs.c
+++ b/mkfs.c
@@ -567,137 +567,6 @@ static int add_xattr_item(struct btrfs_trans_handle *trans,
return ret;
}
-static int custom_alloc_extent(struct btrfs_root *root, u64 num_bytes,
- u64 hint_byte, struct btrfs_key *ins)
-{
- u64 start;
- u64 end;
- u64 last = hint_byte;
- int ret;
- int wrapped = 0;
- struct btrfs_block_group_cache *cache;
-
- while (1) {
- ret = find_first_extent_bit(&root->fs_info->free_space_cache,
- last, &start, &end, EXTENT_DIRTY);
- if (ret) {
- if (wrapped++ == 0) {
- last = 0;
- continue;
- } else {
- goto fail;
- }
- }
-
- start = max(last, start);
- last = end + 1;
- if (last - start < num_bytes)
- continue;
-
- last = start + num_bytes;
- if (test_range_bit(&root->fs_info->pinned_extents,
- start, last - 1, EXTENT_DIRTY, 0))
- continue;
-
- cache = btrfs_lookup_block_group(root->fs_info, start);
- BUG_ON(!cache);
- if (cache->flags & BTRFS_BLOCK_GROUP_SYSTEM ||
- last > cache->key.objectid + cache->key.offset) {
- last = cache->key.objectid + cache->key.offset;
- continue;
- }
-
- if (cache->flags & (BTRFS_BLOCK_GROUP_SYSTEM |
- BTRFS_BLOCK_GROUP_METADATA)) {
- last = cache->key.objectid + cache->key.offset;
- continue;
- }
-
- clear_extent_dirty(&root->fs_info->free_space_cache,
- start, start + num_bytes - 1, 0);
-
- ins->objectid = start;
- ins->offset = num_bytes;
- ins->type = BTRFS_EXTENT_ITEM_KEY;
- return 0;
- }
-fail:
- fprintf(stderr, "not enough free space\n");
- return -ENOSPC;
-}
-
-static int 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;
-
- btrfs_init_path(&path);
-
- ins_key.objectid = objectid;
- ins_key.offset = 0;
- 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);
-
- 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, trans->transid);
- 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;
- }
-
- ret = btrfs_inc_extent_ref(trans, root, disk_bytenr, num_bytes, 0,
- root->root_key.objectid,
- objectid, 0);
-fail:
- btrfs_release_path(&path);
- return ret;
-}
static int add_symbolic_link(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
@@ -735,12 +604,14 @@ static int add_file_items(struct btrfs_trans_handle *trans,
int ret = -1;
ssize_t ret_read;
u64 bytes_read = 0;
- char *buffer = NULL;
struct btrfs_key key;
int blocks;
u32 sectorsize = root->sectorsize;
u64 first_block = 0;
- u64 num_blocks = 0;
+ u64 file_pos = 0;
+ u64 cur_bytes;
+ u64 total_bytes;
+ struct extent_buffer *eb = NULL;
int fd;
fd = open(path_name, O_RDONLY);
@@ -754,7 +625,7 @@ static int add_file_items(struct btrfs_trans_handle *trans,
blocks += 1;
if (st->st_size <= BTRFS_MAX_INLINE_DATA_SIZE(root)) {
- buffer = malloc(st->st_size);
+ char *buffer = malloc(st->st_size);
ret_read = pread64(fd, buffer, st->st_size, bytes_read);
if (ret_read == -1) {
fprintf(stderr, "%s read failed\n", path_name);
@@ -763,57 +634,89 @@ static int add_file_items(struct btrfs_trans_handle *trans,
ret = btrfs_insert_inline_extent(trans, root, objectid, 0,
buffer, st->st_size);
+ free(buffer);
+ goto end;
+ }
+
+ /* round up our st_size to the FS blocksize */
+ total_bytes = (u64)blocks * sectorsize;
+
+ /*
+ * do our IO in extent buffers so it can work
+ * against any raid type
+ */
+ eb = malloc(sizeof(*eb) + sectorsize);
+ if (!eb) {
+ ret = -ENOMEM;
goto end;
}
+ memset(eb, 0, sizeof(*eb) + sectorsize);
+
+again:
- ret = custom_alloc_extent(root, blocks * sectorsize, 0, &key);
+ /*
+ * keep our extent size at 1MB max, this makes it easier to work inside
+ * the tiny block groups created during mkfs
+ */
+ cur_bytes = min(total_bytes, 1024ULL * 1024);
+ ret = btrfs_reserve_extent(trans, root, cur_bytes, 0, 0, (u64)-1,
+ &key, 1);
if (ret)
goto end;
first_block = key.objectid;
bytes_read = 0;
- buffer = malloc(sectorsize);
- do {
- memset(buffer, 0, sectorsize);
- ret_read = pread64(fd, buffer, sectorsize, bytes_read);
+ while (bytes_read < cur_bytes) {
+
+ memset(eb->data, 0, sectorsize);
+
+ ret_read = pread64(fd, eb->data, sectorsize, file_pos + bytes_read);
if (ret_read == -1) {
fprintf(stderr, "%s read failed\n", path_name);
goto end;
}
- ret = pwrite64(out_fd, buffer, sectorsize,
- first_block + bytes_read);
- if (ret != sectorsize) {
- fprintf(stderr, "output file write failed\n");
- goto end;
- }
+ eb->start = first_block + bytes_read;
+ eb->len = sectorsize;
- /* checksum for file data */
+ /*
+ * we're doing the csum before we record the extent, but
+ * that's ok
+ */
ret = btrfs_csum_file_block(trans, root->fs_info->csum_root,
- first_block + (blocks * sectorsize),
- first_block + bytes_read,
- buffer, sectorsize);
+ first_block + bytes_read + sectorsize,
+ first_block + bytes_read,
+ eb->data, sectorsize);
+ if (ret)
+ goto end;
+
+ ret = write_and_map_eb(trans, root, eb);
if (ret) {
- fprintf(stderr, "%s checksum failed\n", path_name);
+ fprintf(stderr, "output file write failed\n");
goto end;
}
- bytes_read += ret_read;
- num_blocks++;
- } while (ret_read == sectorsize);
+ bytes_read += sectorsize;
+ }
- if (num_blocks > 0) {
- ret = record_file_extent(trans, root, objectid, btrfs_inode,
- first_block, first_block,
- blocks * sectorsize);
+ if (bytes_read) {
+ ret = btrfs_record_file_extent(trans, root, objectid, btrfs_inode,
+ file_pos, first_block, cur_bytes);
if (ret)
goto end;
+
}
+ file_pos += cur_bytes;
+ total_bytes -= cur_bytes;
+
+ if (total_bytes)
+ goto again;
+
end:
- if (buffer)
- free(buffer);
+ if (eb)
+ free(eb);
close(fd);
return ret;
}
@@ -1019,6 +922,7 @@ static int create_chunks(struct btrfs_trans_handle *trans,
if (size_of_data < minimum_data_chunk_size)
size_of_data = minimum_data_chunk_size;
+
ret = btrfs_alloc_data_chunk(trans, root->fs_info->extent_root,
&chunk_start, size_of_data, data_type);
BUG_ON(ret);
@@ -1099,6 +1003,7 @@ static u64 size_sourcedir(char *dir_name, u64 sectorsize,
u64 allocated_meta_size = 8 * 1024 * 1024; /* 8MB */
u64 allocated_total_size = 20 * 1024 * 1024; /* 20MB */
u64 num_of_meta_chunks = 0;
+ u64 num_of_data_chunks = 0;
u64 num_of_allocated_meta_chunks =
allocated_meta_size / default_chunk_size;
@@ -1111,6 +1016,9 @@ static u64 size_sourcedir(char *dir_name, u64 sectorsize,
exit(1);
}
+ num_of_data_chunks = (dir_size + default_chunk_size - 1) /
+ default_chunk_size;
+
num_of_meta_chunks = (dir_size / 2) / default_chunk_size;
if (((dir_size / 2) % default_chunk_size) != 0)
num_of_meta_chunks++;
@@ -1119,11 +1027,12 @@ static u64 size_sourcedir(char *dir_name, u64 sectorsize,
else
num_of_meta_chunks -= num_of_allocated_meta_chunks;
- total_size = allocated_total_size + dir_size +
+ total_size = allocated_total_size +
+ (num_of_data_chunks * default_chunk_size) +
(num_of_meta_chunks * default_chunk_size);
*num_of_meta_chunks_ret = num_of_meta_chunks;
-
+ *size_of_data_ret = num_of_data_chunks * default_chunk_size;
return total_size;
}