On Sat, Mar 20, 2010 at 12:26 PM, Sean Bartell
<wingedtachikoma@xxxxxxxxx> wrote:
> A filesystem can have disk extents in arbitrary places on the disk, as
> well as extents that must be read into memory because they have
> compression or encryption btrfs doesn't support. These extents can be
> passed to the new extent iteration functions, which will handle all the
> details of alignment, allocation, etc.
> ---
> convert.c | 604 ++++++++++++++++++++++++++++++++++++++++---------------------
> 1 files changed, 401 insertions(+), 203 deletions(-)
>
> diff --git a/convert.c b/convert.c
> index c48f8ba..bd91990 100644
> --- a/convert.c
> +++ b/convert.c
> @@ -357,7 +357,7 @@ error:
> }
>
> static int read_disk_extent(struct btrfs_root *root, u64 bytenr,
> - u32 num_bytes, char *buffer)
> + u64 num_bytes, char *buffer)
> {
> int ret;
> struct btrfs_fs_devices *fs_devs = root->fs_info->fs_devices;
> @@ -371,6 +371,23 @@ fail:
> ret = -1;
> return ret;
> }
> +
> +static int write_disk_extent(struct btrfs_root *root, u64 bytenr,
> + u64 num_bytes, const char *buffer)
> +{
> + int ret;
> + struct btrfs_fs_devices *fs_devs = root->fs_info->fs_devices;
> +
> + ret = pwrite(fs_devs->latest_bdev, buffer, num_bytes, bytenr);
> + if (ret != num_bytes)
> + goto fail;
> + ret = 0;
> +fail:
> + if (ret > 0)
> + 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
> @@ -378,8 +395,7 @@ fail:
> */
> 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 *inode_nbytes, u64 file_pos, u64 disk_bytenr,
> u64 num_bytes, int checksum)
> {
> int ret;
> @@ -391,7 +407,6 @@ static int record_file_extent(struct btrfs_trans_handle *trans,
> 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,
> @@ -450,8 +465,7 @@ static int record_file_extent(struct btrfs_trans_handle *trans,
> 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);
> + *inode_nbytes += num_bytes;
>
> btrfs_release_path(root, &path);
>
> @@ -492,95 +506,355 @@ fail:
> return ret;
> }
>
> -static int record_file_blocks(struct btrfs_trans_handle *trans,
> - struct btrfs_root *root, u64 objectid,
> - struct btrfs_inode_item *inode,
> - u64 file_block, u64 disk_block,
> - u64 num_blocks, int checksum)
> -{
> - 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);
> -}
> -
> -struct blk_iterate_data {
> +struct extent_iterate_data {
> struct btrfs_trans_handle *trans;
> struct btrfs_root *root;
> - struct btrfs_inode_item *inode;
> + u64 *inode_nbytes;
> u64 objectid;
> - u64 first_block;
> - u64 disk_block;
> - u64 num_blocks;
> - u64 boundary;
> - int checksum;
> - int errcode;
> + int checksum, packing;
> + u64 last_file_off;
> + u64 total_size;
> + enum {EXTENT_ITERATE_TYPE_NONE, EXTENT_ITERATE_TYPE_MEM,
> + EXTENT_ITERATE_TYPE_DISK} type;
> + u64 size;
> + u64 file_off; /* always aligned to sectorsize */
> + char *data; /* for mem */
> + u64 disk_off; /* for disk */
> };
>
> -static int block_iterate_proc(ext2_filsys ext2_fs,
> - u64 disk_block, u64 file_block,
> - struct blk_iterate_data *idata)
> +static u64 extent_boundary(struct btrfs_root *root, u64 extent_start)
> {
> - int ret;
> - int sb_region;
> - int do_barrier;
> - struct btrfs_root *root = idata->root;
> - struct btrfs_trans_handle *trans = idata->trans;
> - struct btrfs_block_group_cache *cache;
> - u64 bytenr = disk_block * root->sectorsize;
> -
> - sb_region = intersect_with_sb(bytenr, root->sectorsize);
> - do_barrier = sb_region || disk_block >= idata->boundary;
> - if ((idata->num_blocks > 0 && do_barrier) ||
> - (file_block > idata->first_block + idata->num_blocks) ||
> - (disk_block != idata->disk_block + idata->num_blocks)) {
> - if (idata->num_blocks > 0) {
> - ret = record_file_blocks(trans, root, idata->objectid,
> - idata->inode, idata->first_block,
> - idata->disk_block, idata->num_blocks,
> - idata->checksum);
> - if (ret)
> - goto fail;
> - idata->first_block += idata->num_blocks;
> - idata->num_blocks = 0;
> + int i;
> + u64 offset;
> + u64 boundary = (u64)-1;
> + for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) {
> + offset = btrfs_sb_offset(i);
> + offset &= ~((u64)STRIPE_LEN - 1);
> + if (offset > extent_start) {
> + boundary = offset;
> + break;
> + }
> + if (offset + STRIPE_LEN > extent_start) {
> + boundary = offset + STRIPE_LEN;
> + break;
> }
> - if (file_block > idata->first_block) {
> - ret = record_file_blocks(trans, root, idata->objectid,
> - idata->inode, idata->first_block,
> - 0, file_block - idata->first_block,
> - idata->checksum);
> + }
> +
> + struct btrfs_block_group_cache *cache;
> + cache = btrfs_lookup_block_group(root->fs_info, extent_start);
> + BUG_ON(!cache);
> + offset = cache->key.objectid + cache->key.offset;
> + return min_t(u64, boundary, offset);
> +}
> +
> +static int commit_disk_extent(struct extent_iterate_data *priv,
> + u64 file_pos, u64 disk_bytenr, u64 num_bytes)
> +{
> + u64 boundary;
> + int ret;
> + if (disk_bytenr == 0)
> + return record_file_extent(priv->trans, priv->root,
> + priv->objectid, priv->inode_nbytes,
> + file_pos, disk_bytenr, num_bytes,
> + priv->checksum);
> + /* Break up the disk extent on blockgroup and superblock boundaries. */
> + while (num_bytes) {
> + boundary = extent_boundary(priv->root, disk_bytenr);
> + u64 size = min_t(u64, boundary - disk_bytenr, num_bytes);
> + ret = record_file_extent(priv->trans, priv->root,
> + priv->objectid, priv->inode_nbytes,
> + file_pos, disk_bytenr, size,
> + priv->checksum);
> + if (ret)
> + return ret;
> + file_pos += size;
> + disk_bytenr += size;
> + num_bytes -= size;
> + }
> + return 0;
> +}
> +
> +static int commit_file_extents(struct extent_iterate_data *priv)
> +{
> + int ret;
> + if (priv->type == EXTENT_ITERATE_TYPE_NONE)
> + return 0;
> + if (priv->size == 0)
> + return 0;
> + if (priv->file_off > priv->last_file_off) {
> + ret = commit_disk_extent(priv, priv->last_file_off, 0,
> + priv->file_off - priv->last_file_off);
> + if (ret)
> + return ret;
> + }
> + priv->last_file_off = priv->file_off + priv->size;
> +
> + if (priv->type == EXTENT_ITERATE_TYPE_MEM) {
> + /* allocate and write to disk */
> + struct btrfs_key key;
> + ret = custom_alloc_extent(priv->root, priv->root->sectorsize,
> + 0, &key);
> + if (ret)
> + return ret;
> + ret = write_disk_extent(priv->root, key.objectid, priv->size,
> + priv->data);
> + if (ret)
> + return ret;
> + priv->type = EXTENT_ITERATE_TYPE_DISK;
> + priv->disk_off = key.objectid;
> + }
> +
> + u64 sectorsize = priv->root->sectorsize;
> + if (priv->size & (sectorsize - 1))
> + priv->size = (priv->size & ~(sectorsize - 1)) + sectorsize;
> + ret = commit_disk_extent(priv, priv->file_off, priv->disk_off,
> + priv->size);
> + if (ret)
> + return ret;
> + priv->type = EXTENT_ITERATE_TYPE_NONE;
> + return 0;
> +}
> +
> +int start_file_extents(struct extent_iterate_data *priv,
> + struct btrfs_trans_handle *trans,
> + struct btrfs_root *root, u64 *inode_nbytes,
> + u64 objectid, int checksum, int packing, u64 total_size)
> +{
> + priv->trans = trans;
> + priv->root = root;
> + priv->inode_nbytes = inode_nbytes;
> + priv->objectid = objectid;
> + priv->checksum = checksum;
> + priv->packing = packing;
> + priv->last_file_off = 0;
> + priv->type = 0;
> + priv->total_size = total_size;
> + priv->data = malloc(root->sectorsize);
> + if (!priv->data)
> + return -ENOMEM;
> + return 0;
> +}
> +
> +int start_file_extents_range(struct extent_iterate_data *priv,
> + struct btrfs_trans_handle *trans,
> + struct btrfs_root *root, u64 *inode_nbytes,
> + u64 objectid, int checksum, u64 start, u64 end)
> +{
> + priv->trans = trans;
> + priv->root = root;
> + priv->inode_nbytes = inode_nbytes;
> + priv->objectid = objectid;
> + priv->checksum = checksum;
> + priv->packing = 0;
> + priv->last_file_off = start;
> + priv->type = 0;
> + priv->total_size = end;
> + priv->data = malloc(root->sectorsize);
> + if (!priv->data)
> + return -ENOMEM;
> + return 0;
> +}
> +
> +int finish_file_extents(struct extent_iterate_data *priv)
> +{
> + int ret;
> +
> + if (priv->packing
> + && priv->type != EXTENT_ITERATE_TYPE_NONE
> + && priv->total_size <= BTRFS_MAX_INLINE_DATA_SIZE(priv->root)) {
> + priv->size = min_t(u64, priv->size,
> + priv->total_size - priv->file_off);
> + /* make inline extent */
> + if (priv->type == EXTENT_ITERATE_TYPE_DISK) {
> + ret = read_disk_extent(priv->root, priv->disk_off,
> + priv->size, priv->data);
> if (ret)
> - goto fail;
> + return ret;
> }
> + *priv->inode_nbytes += priv->size;
> + return btrfs_insert_inline_extent(priv->trans, priv->root,
> + priv->objectid,
> + priv->file_off, priv->data,
> + priv->size);
> + }
>
> - if (sb_region) {
> - bytenr += STRIPE_LEN - 1;
> - bytenr &= ~((u64)STRIPE_LEN - 1);
> - } else {
> - cache = btrfs_lookup_block_group(root->fs_info, bytenr);
> - BUG_ON(!cache);
> - bytenr = cache->key.objectid + cache->key.offset;
> + ret = commit_file_extents(priv);
> + if (ret)
> + return ret;
> +
> + if (priv->total_size > priv->last_file_off) {
> + ret = commit_disk_extent(priv, priv->last_file_off, 0,
> + priv->total_size - priv->last_file_off);
> + if (ret)
> + return ret;
> + }
> + free(priv->data);
> + return 0;
> +}
> +
> +int add_file_mem_extent(struct extent_iterate_data *priv, u64 file_off,
> + u64 size, char *data);
> +
> +int add_file_disk_extent(struct extent_iterate_data *priv, u64 file_off,
> + u64 disk_off, u64 size)
> +{
> + BUG_ON(file_off < priv->last_file_off);
> + int ret;
> + u64 sectorsize = priv->root->sectorsize;
> + u64 mask = sectorsize - 1;
> + if (size == 0)
> + return 0;
> + if ((file_off & mask) != (disk_off & mask)) {
> + /* It's unclear how to CoW this, so don't. */
> + char *data = malloc(size);
> + if (!data)
> + return -ENOMEM;
> + ret = read_disk_extent(priv->root, disk_off, size, data);
> + if (ret) {
> + free(data);
> + return ret;
> }
> + ret = add_file_mem_extent(priv, file_off, size, data);
> + free(data);
> + return ret;
> + }
> + if (priv->type == EXTENT_ITERATE_TYPE_DISK
> + && priv->file_off + priv->size == file_off
> + && priv->disk_off + priv->size == disk_off) {
> + /* It's a continuation of the same disk extent. */
> + priv->size += size;
> + return 0;
> + }
> + if (disk_off == 0 || disk_off & mask) {
why "disk_off == 0" is needed here?
> + /* We need to have an aligned start, so give the first part to
> + * add_file_mem_extent if necessary. */
> + u64 mem_size = min_t(u64, sectorsize - (disk_off & mask), size);
> + char *data = malloc(mem_size);
> + if (!data)
> + return -ENOMEM;
> + ret = read_disk_extent(priv->root, disk_off, mem_size, data);
> + if (ret) {
> + free(data);
> + return ret;
> + }
> + ret = add_file_mem_extent(priv, file_off, mem_size, data);
> + free(data);
> + if (ret)
> + return ret;
> + file_off += mem_size;
> + disk_off += mem_size;
> + size -= mem_size;
> + if (size == 0)
> + return 0;
> + }
> + ret = commit_file_extents(priv);
> + if (ret)
> + return ret;
> + priv->type = EXTENT_ITERATE_TYPE_DISK;
> + priv->size = size;
> + priv->file_off = file_off;
> + priv->disk_off = disk_off;
> + return 0;
> +}
> +
> +int add_file_mem_extent(struct extent_iterate_data *priv, u64 file_off,
> + u64 size, char *data)
> +{
> + BUG_ON(file_off < priv->last_file_off);
> + int ret;
> + u64 sectorsize = priv->root->sectorsize;
> + u64 mask = sectorsize - 1;
> + u64 aligned_file_off = file_off & ~mask;
> + u32 alignment = file_off - aligned_file_off;
> + size += alignment;
> +
> + /* If we share a sector with a DISK extent, commit most of it and turn
> + * the shared part into a MEM extent. */
> + if (priv->type == EXTENT_ITERATE_TYPE_DISK
> + && priv->file_off + priv->size > aligned_file_off) {
> + u64 mem_size = priv->file_off + priv->size - aligned_file_off;
> + ret = read_disk_extent(priv->root, aligned_file_off, mem_size,
> + priv->data);
> + if (ret)
> + return ret;
> + priv->size -= mem_size;
> + ret = commit_file_extents(priv);
> + if (ret)
> + return ret;
> + priv->type = EXTENT_ITERATE_TYPE_MEM;
> + priv->size = mem_size;
> + priv->file_off = aligned_file_off;
> + }
> +
> + /* Put our first sector in priv->data. If we share a sector with the
> + * previous extent, combine with it. */
> + if (priv->type == EXTENT_ITERATE_TYPE_MEM
> + && priv->file_off + priv->size > aligned_file_off) {
> + BUG_ON(priv->file_off != aligned_file_off);
> + memset(priv->data + priv->size, 0, sectorsize - priv->size);
> + } else {
> + ret = commit_file_extents(priv);
> + if (ret)
> + return ret;
> + memset(priv->data, 0, sectorsize);
> + }
> + if (size < sectorsize) {
> + memcpy(priv->data + alignment, data, size - alignment);
> + priv->type = EXTENT_ITERATE_TYPE_MEM;
> + priv->file_off = aligned_file_off;
> + priv->size = size;
> + return 0;
> + }
> + memcpy(priv->data + alignment, data, sectorsize - alignment);
> + data += sectorsize - alignment;
> +
> + /* We have full sectors; allocate and write them. */
> + u64 aligned_size = size & ~mask;
> + struct btrfs_key key;
> + ret = custom_alloc_extent(priv->root, aligned_size, 0, &key);
> + if (ret)
> + return ret;
> + ret = write_disk_extent(priv->root, key.objectid,
> + sectorsize, priv->data);
> + if (ret)
> + return ret;
> + ret = write_disk_extent(priv->root, key.objectid + sectorsize,
> + aligned_size - sectorsize, data);
> + if (ret)
> + return ret;
> + ret = add_file_disk_extent(priv, aligned_file_off, key.objectid,
> + aligned_size);
> + if (ret)
> + return ret;
>
> - idata->first_block = file_block;
> - idata->disk_block = disk_block;
> - idata->boundary = bytenr / root->sectorsize;
> + /* Leave the rest in priv. */
> + size -= aligned_size;
> + if (size) {
> + ret = commit_file_extents(priv);
> + if (ret)
> + return ret;
> + aligned_file_off += aligned_size;
> + data += aligned_size - sectorsize;
> + priv->type = EXTENT_ITERATE_TYPE_MEM;
> + priv->file_off = aligned_file_off;
> + priv->size = size;
> + memcpy(priv->data, data, size);
> }
> - idata->num_blocks++;
> return 0;
> -fail:
> - idata->errcode = ret;
> - return BLOCK_ABORT;
> }
>
> static int __block_iterate_proc(ext2_filsys fs, blk_t *blocknr,
> e2_blkcnt_t blockcnt, blk_t ref_block,
> int ref_offset, void *priv_data)
> {
> - struct blk_iterate_data *idata;
> - idata = (struct blk_iterate_data *)priv_data;
> - return block_iterate_proc(fs, *blocknr, blockcnt, idata);
> + struct extent_iterate_data *idata;
> + idata = (struct extent_iterate_data *)priv_data;
> + u64 blocksize = fs->blocksize;
> + int ret = add_file_disk_extent(idata, blocksize * blockcnt,
> + blocksize * *blocknr, blocksize);
> + if (ret)
> + return BLOCK_ABORT;
> + return 0;
> }
>
> /*
> @@ -593,68 +867,23 @@ static int create_file_extents(struct btrfs_trans_handle *trans,
> int datacsum, int packing)
> {
> int ret;
> - char *buffer = NULL;
> errcode_t err;
> - u32 last_block;
> - u32 sectorsize = root->sectorsize;
> + u64 inode_nbytes = 0;
> u64 inode_size = btrfs_stack_inode_size(btrfs_inode);
> - struct blk_iterate_data data = {
> - .trans = trans,
> - .root = root,
> - .inode = btrfs_inode,
> - .objectid = objectid,
> - .first_block = 0,
> - .disk_block = 0,
> - .num_blocks = 0,
> - .boundary = (u64)-1,
> - .checksum = datacsum,
> - .errcode = 0,
> - };
> + struct extent_iterate_data data;
> + ret = start_file_extents(&data, trans, root, &inode_nbytes, objectid,
> + datacsum, packing, inode_size);
> + if (ret)
> + return ret;
> err = ext2fs_block_iterate2(ext2_fs, ext2_ino, BLOCK_FLAG_DATA_ONLY,
> NULL, __block_iterate_proc, &data);
> if (err)
> goto error;
> - ret = data.errcode;
> + ret = finish_file_extents(&data);
> if (ret)
> - goto fail;
> - if (packing && data.first_block == 0 && data.num_blocks > 0 &&
> - inode_size <= BTRFS_MAX_INLINE_DATA_SIZE(root)) {
> - u64 num_bytes = data.num_blocks * sectorsize;
> - u64 disk_bytenr = data.disk_block * sectorsize;
> - u64 nbytes;
> -
> - buffer = malloc(num_bytes);
> - if (!buffer)
> - return -ENOMEM;
> - ret = read_disk_extent(root, disk_bytenr, num_bytes, buffer);
> - if (ret)
> - goto fail;
> - if (num_bytes > inode_size)
> - num_bytes = inode_size;
> - ret = btrfs_insert_inline_extent(trans, root, objectid,
> - 0, buffer, num_bytes);
> - if (ret)
> - goto fail;
> - nbytes = btrfs_stack_inode_nbytes(btrfs_inode) + num_bytes;
> - btrfs_set_stack_inode_nbytes(btrfs_inode, nbytes);
> - } else if (data.num_blocks > 0) {
> - ret = record_file_blocks(trans, root, objectid, btrfs_inode,
> - data.first_block, data.disk_block,
> - data.num_blocks, data.checksum);
> - if (ret)
> - goto fail;
> - }
> - data.first_block += data.num_blocks;
> - last_block = (inode_size + sectorsize - 1) / sectorsize;
> - if (last_block > data.first_block) {
> - ret = record_file_blocks(trans, root, objectid, btrfs_inode,
> - data.first_block, 0, last_block -
> - data.first_block, data.checksum);
> - }
> -fail:
> - if (buffer)
> - free(buffer);
> - return ret;
> + return ret;
> + btrfs_set_stack_inode_nbytes(btrfs_inode, inode_nbytes);
> + return 0;
> error:
> fprintf(stderr, "ext2fs_block_iterate2: %s\n", error_message(err));
> return -1;
> @@ -1206,52 +1435,33 @@ static int copy_inodes(struct btrfs_root *root, ext2_filsys ext2_fs,
> */
> static int create_image_file_range(struct btrfs_trans_handle *trans,
> struct btrfs_root *root, u64 objectid,
> - struct btrfs_inode_item *inode,
> + u64 *inode_nbytes,
> u64 start_byte, u64 end_byte,
> struct extent_io_tree *orig_free_tree)
> {
> - u32 blocksize = root->sectorsize;
> - u32 block = start_byte / blocksize;
> - u32 last_block = (end_byte + blocksize - 1) / blocksize;
> int ret = 0;
> - struct blk_iterate_data data = {
> - .trans = trans,
> - .root = root,
> - .inode = inode,
> - .objectid = objectid,
> - .first_block = block,
> - .disk_block = 0,
> - .num_blocks = 0,
> - .boundary = (u64)-1,
> - .checksum = 0,
> - .errcode = 0,
> - };
> - for (; start_byte < end_byte; block++, start_byte += blocksize) {
> - if (test_range_bit(orig_free_tree, start_byte,
> - start_byte + blocksize, EXTENT_DIRTY, 1))
> - continue;
> - ret = block_iterate_proc(NULL, block, block, &data);
> - if (ret & BLOCK_ABORT) {
> - ret = data.errcode;
> - goto fail;
> - }
> - }
> - if (data.num_blocks > 0) {
> - ret = record_file_blocks(trans, root, objectid, inode,
> - data.first_block, data.disk_block,
> - data.num_blocks, 0);
> - if (ret)
> - goto fail;
> - data.first_block += data.num_blocks;
> - }
> - if (last_block > data.first_block) {
> - ret = record_file_blocks(trans, root, objectid, inode,
> - data.first_block, 0, last_block -
> - data.first_block, 0);
> + struct extent_iterate_data data;
> + ret = start_file_extents_range(&data, trans, root, inode_nbytes,
> + objectid, 0, start_byte, end_byte);
> + if (ret)
> + return ret;
> + while (start_byte < end_byte) {
> + u64 start, end;
> + ret = find_first_extent_bit(orig_free_tree, start_byte,
> + &start, &end, EXTENT_DIRTY);
> if (ret)
> - goto fail;
> + start = end_byte;
> + if (start > start_byte) {
> + u64 size = min_t(u64, start - start_byte,
> + end_byte - start_byte);
> + ret = add_file_disk_extent(&data, start_byte,
> + start_byte, size);
> + if (ret)
> + return ret;
> + }
> + start_byte = end + 1;
> }
> -fail:
> + ret = finish_file_extents(&data);
> return ret;
> }
> /*
> @@ -1279,6 +1489,7 @@ static int create_ext2_image(struct btrfs_root *root, const char *name,
> u64 last_byte;
> u64 first_free;
> u64 total_bytes;
> + u64 inode_nbytes;
> u32 sectorsize = root->sectorsize;
>
> total_bytes = btrfs_super_total_bytes(&fs_info->super_copy);
> @@ -1289,7 +1500,7 @@ static int create_ext2_image(struct btrfs_root *root, const char *name,
> btrfs_set_stack_inode_generation(&btrfs_inode, 1);
> btrfs_set_stack_inode_size(&btrfs_inode, total_bytes);
> btrfs_set_stack_inode_nlink(&btrfs_inode, 1);
> - btrfs_set_stack_inode_nbytes(&btrfs_inode, 0);
> + inode_nbytes = 0;
> btrfs_set_stack_inode_mode(&btrfs_inode, S_IFREG | 0400);
> btrfs_set_stack_inode_flags(&btrfs_inode, BTRFS_INODE_NODATASUM |
> BTRFS_INODE_READONLY);
> @@ -1315,7 +1526,7 @@ static int create_ext2_image(struct btrfs_root *root, const char *name,
> if (ret)
> goto fail;
> ret = record_file_extent(trans, root, objectid,
> - &btrfs_inode, last_byte,
> + &inode_nbytes, last_byte,
> key.objectid, sectorsize, 0);
> if (ret)
> goto fail;
> @@ -1370,12 +1581,12 @@ next:
>
> if (bytenr > last_byte) {
> ret = create_image_file_range(trans, root, objectid,
> - &btrfs_inode, last_byte,
> + &inode_nbytes, last_byte,
> bytenr, orig_free_tree);
> if (ret)
> goto fail;
> }
> - ret = record_file_extent(trans, root, objectid, &btrfs_inode,
> + ret = record_file_extent(trans, root, objectid, &inode_nbytes,
> bytenr, bytenr, num_bytes, 0);
> if (ret)
> goto fail;
> @@ -1392,12 +1603,14 @@ next:
> btrfs_release_path(root, &path);
> if (total_bytes > last_byte) {
> ret = create_image_file_range(trans, root, objectid,
> - &btrfs_inode, last_byte,
> + &inode_nbytes, last_byte,
> total_bytes, orig_free_tree);
> if (ret)
> goto fail;
> }
>
> + btrfs_set_stack_inode_nbytes(&btrfs_inode, inode_nbytes);
> +
> ret = btrfs_insert_inode(trans, root, objectid, &btrfs_inode);
> if (ret)
> goto fail;
> @@ -1934,7 +2147,7 @@ static int relocate_one_reference(struct btrfs_trans_handle *trans,
> struct btrfs_key key;
> struct btrfs_path path;
> struct btrfs_inode_item inode;
> - struct blk_iterate_data data;
> + struct extent_iterate_data data;
> u64 bytenr;
> u64 num_bytes;
> u64 cur_offset;
> @@ -1990,22 +2203,14 @@ static int relocate_one_reference(struct btrfs_trans_handle *trans,
> btrfs_release_path(root, &path);
>
> BUG_ON(num_bytes & (sectorsize - 1));
> - nbytes = btrfs_stack_inode_nbytes(&inode) - num_bytes;
> - btrfs_set_stack_inode_nbytes(&inode, nbytes);
> datacsum = !(btrfs_stack_inode_flags(&inode) & BTRFS_INODE_NODATASUM);
>
> - data = (struct blk_iterate_data) {
> - .trans = trans,
> - .root = root,
> - .inode = &inode,
> - .objectid = extent_key->objectid,
> - .first_block = extent_key->offset / sectorsize,
> - .disk_block = 0,
> - .num_blocks = 0,
> - .boundary = (u64)-1,
> - .checksum = datacsum,
> - .errcode = 0,
> - };
> + ret = start_file_extents_range(&data, trans, root, &nbytes,
> + extent_key->objectid, datacsum,
> + extent_key->offset,
> + extent_key->offset + num_bytes);
> + if (ret)
> + goto fail;
>
> cur_offset = extent_key->offset;
> while (num_bytes > 0) {
> @@ -2035,26 +2240,19 @@ static int relocate_one_reference(struct btrfs_trans_handle *trans,
> BUG_ON(ret);
> }
>
> - ret = block_iterate_proc(NULL, new_pos / sectorsize,
> - cur_offset / sectorsize, &data);
> - if (ret & BLOCK_ABORT) {
> - ret = data.errcode;
> + ret = add_file_disk_extent(&data, cur_offset, new_pos,
> + sectorsize);
> + if (ret)
> goto fail;
> - }
>
> cur_offset += sectorsize;
> bytenr += sectorsize;
> num_bytes -= sectorsize;
> }
>
> - if (data.num_blocks > 0) {
> - ret = record_file_blocks(trans, root,
> - extent_key->objectid, &inode,
> - data.first_block, data.disk_block,
> - data.num_blocks, datacsum);
> - if (ret)
> - goto fail;
> - }
> + ret = finish_file_extents(&data);
> + if (ret)
> + goto fail;
>
> key.objectid = extent_key->objectid;
> key.offset = 0;
> --
> 1.6.4.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html