From patchwork Sat Mar 20 04:26:49 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Bartell X-Patchwork-Id: 87071 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o2K4QqL4006855 for ; Sat, 20 Mar 2010 04:26:52 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751161Ab0CTE0v (ORCPT ); Sat, 20 Mar 2010 00:26:51 -0400 Received: from mail-gw0-f46.google.com ([74.125.83.46]:57827 "EHLO mail-gw0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751007Ab0CTE0u (ORCPT ); Sat, 20 Mar 2010 00:26:50 -0400 Received: by gwaa18 with SMTP id a18so129452gwa.19 for ; Fri, 19 Mar 2010 21:26:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:date:from:to:subject :message-id:mail-followup-to:mime-version:content-type :content-disposition:user-agent; bh=hcScV7ARKlKe/xRe0rrCXVF2H8UeFnPtnOI+8yZQPy0=; b=mTRLvJBaNK28AZ7B2NHGosWRrqYSK4SJPixoatX8uFIfDhbQxthaCuj/KiYegPqVz0 of/m36Cm7y+VZhSCttt18YTIJzGcRjS9nipvTsgbroc1pCPghZyaaXlN+1S25D6uS35t xh8GTkGXdEXFOWC7e6iMgfGTfbDki2LmZ5XHc= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=date:from:to:subject:message-id:mail-followup-to:mime-version :content-type:content-disposition:user-agent; b=CHoTlUzLbRRVZs3Cv7wTq4OxsLr7VVTj0tcYppj725RMPHqHIdUGDpp5ag4Nddslzu YqWIkl8d1Ee0iBx4QN1ad6eOgwakY7olteJGI7ocgquNoFD7QKvbV2V2MHzlFLnA59pg Pv9pE7LU9eMll+KgO08cdb6Fx9TgdviAmXJaI= Received: by 10.101.17.5 with SMTP id u5mr1947035ani.131.1269059209307; Fri, 19 Mar 2010 21:26:49 -0700 (PDT) Received: from flcl.lan (cpe-065-190-001-228.nc.res.rr.com [65.190.1.228]) by mx.google.com with ESMTPS id 23sm590167ywh.45.2010.03.19.21.26.46 (version=TLSv1/SSLv3 cipher=RC4-MD5); Fri, 19 Mar 2010 21:26:48 -0700 (PDT) Date: Sat, 20 Mar 2010 00:26:49 -0400 From: Sean Bartell To: linux-btrfs@vger.kernel.org Subject: [PATCH 2/4] btrfs-convert: Add extent iteration functions. Message-ID: <20100320042649.GA17106@flcl.lan> Mail-Followup-To: linux-btrfs@vger.kernel.org MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.20 (2009-06-14) Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Sat, 20 Mar 2010 04:26:52 +0000 (UTC) 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) { + /* 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;