summaryrefslogtreecommitdiff
path: root/btrfs-convert.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@fusionio.com>2013-10-16 10:36:55 -0400
committerChris Mason <chris.mason@fusionio.com>2013-10-16 10:42:53 -0400
commitd1570a06184ed3748536a67693ef5cfd954d4032 (patch)
tree3fe610614ddc64a510006820a518297d14a9dec1 /btrfs-convert.c
parent005d7d2efb0aaaae056584f3cbd25d3bfce73ea3 (diff)
mkfs: fix mkfs -r to properly allocate space
mkfs -r wasn't creating chunks properly, making it very difficult to allocate space for anything except tiny filesystems. This changes it around to use more of the generic infrastructure, and to do actual logical->physical block number translation. It also allocates space to the files in smaller extents (max 1MB), which keeps the allocator from trying to allocate an extent bigger than a single chunk. It doesn't quite support multi-device mkfs -r yet, but is much closer. Signed-off-by: Chris Mason <chris.mason@fusionio.com>
Diffstat (limited to 'btrfs-convert.c')
-rw-r--r--btrfs-convert.c154
1 files changed, 35 insertions, 119 deletions
diff --git a/btrfs-convert.c b/btrfs-convert.c
index edef1bd7..26c7b5fd 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;