linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 2/4] btrfs-convert: Add extent iteration functions.
@ 2010-03-20  4:26 Sean Bartell
  2010-03-22  4:55 ` Sean Bartell
  2010-05-18 13:06 ` Yan, Zheng 
  0 siblings, 2 replies; 4+ messages in thread
From: Sean Bartell @ 2010-03-20  4:26 UTC (permalink / raw)
  To: linux-btrfs

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) {
+		/* 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


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 2/4] btrfs-convert: Add extent iteration functions.
  2010-03-20  4:26 [PATCH 2/4] btrfs-convert: Add extent iteration functions Sean Bartell
@ 2010-03-22  4:55 ` Sean Bartell
  2010-05-18 13:06 ` Yan, Zheng 
  1 sibling, 0 replies; 4+ messages in thread
From: Sean Bartell @ 2010-03-22  4:55 UTC (permalink / raw)
  To: linux-btrfs

Whoops, there's a major memory leak. Please apply this patch to the
patch :).

diff --git a/convert.c b/convert.c
index dfd2976..7bb4ed0 100644
--- a/convert.c
+++ b/convert.c
@@ -471,21 +471,24 @@ int finish_file_extents(struct extent_iterate_data *priv)
 				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);
-	}
-
-	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);
+		ret = btrfs_insert_inline_extent(priv->trans, priv->root,
+						 priv->objectid,
+						 priv->file_off, priv->data,
+						 priv->size);
 		if (ret)
 			return ret;
+	} else {
+		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;

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 2/4] btrfs-convert: Add extent iteration functions.
  2010-03-20  4:26 [PATCH 2/4] btrfs-convert: Add extent iteration functions Sean Bartell
  2010-03-22  4:55 ` Sean Bartell
@ 2010-05-18 13:06 ` Yan, Zheng 
  2010-05-18 15:37   ` Sean Bartell
  1 sibling, 1 reply; 4+ messages in thread
From: Yan, Zheng  @ 2010-05-18 13:06 UTC (permalink / raw)
  To: linux-btrfs; +Cc: wingedtachikoma

On Sat, Mar 20, 2010 at 12:26 PM, Sean Bartell
<wingedtachikoma@gmail.com> wrote:
> A filesystem can have disk extents in arbitrary places on the disk, a=
s
> 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 t=
he
> details of alignment, allocation, etc.
> ---
> =A0convert.c | =A0604 ++++++++++++++++++++++++++++++++++++++++-------=
--------------
> =A01 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:
> =A0}
>
> =A0static int read_disk_extent(struct btrfs_root *root, u64 bytenr,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 u32 num_bytes, =
char *buffer)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 u64 num_bytes, =
char *buffer)
> =A0{
> =A0 =A0 =A0 =A0int ret;
> =A0 =A0 =A0 =A0struct btrfs_fs_devices *fs_devs =3D root->fs_info->fs=
_devices;
> @@ -371,6 +371,23 @@ fail:
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0ret =3D -1;
> =A0 =A0 =A0 =A0return ret;
> =A0}
> +
> +static int write_disk_extent(struct btrfs_root *root, u64 bytenr,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0u64 num_byte=
s, const char *buffer)
> +{
> + =A0 =A0 =A0 int ret;
> + =A0 =A0 =A0 struct btrfs_fs_devices *fs_devs =3D root->fs_info->fs_=
devices;
> +
> + =A0 =A0 =A0 ret =3D pwrite(fs_devs->latest_bdev, buffer, num_bytes,=
 bytenr);
> + =A0 =A0 =A0 if (ret !=3D num_bytes)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto fail;
> + =A0 =A0 =A0 ret =3D 0;
> +fail:
> + =A0 =A0 =A0 if (ret > 0)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D -1;
> + =A0 =A0 =A0 return ret;
> +}
> +
> =A0/*
> =A0* Record a file extent. Do all the required works, such as inserti=
ng
> =A0* file extent item, inserting extent item and backref item into ex=
tent
> @@ -378,8 +395,7 @@ fail:
> =A0*/
> =A0static int record_file_extent(struct btrfs_trans_handle *trans,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0struct btr=
fs_root *root, u64 objectid,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 struct btrf=
s_inode_item *inode,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 u64 file_po=
s, u64 disk_bytenr,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 u64 *inode_=
nbytes, u64 file_pos, u64 disk_bytenr,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0u64 num_by=
tes, int checksum)
> =A0{
> =A0 =A0 =A0 =A0int ret;
> @@ -391,7 +407,6 @@ static int record_file_extent(struct btrfs_trans_=
handle *trans,
> =A0 =A0 =A0 =A0struct btrfs_path path;
> =A0 =A0 =A0 =A0struct btrfs_extent_item *ei;
> =A0 =A0 =A0 =A0u32 blocksize =3D root->sectorsize;
> - =A0 =A0 =A0 u64 nbytes;
>
> =A0 =A0 =A0 =A0if (disk_bytenr =3D=3D 0) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0ret =3D btrfs_insert_file_extent(trans=
, root, objectid,
> @@ -450,8 +465,7 @@ static int record_file_extent(struct btrfs_trans_=
handle *trans,
> =A0 =A0 =A0 =A0btrfs_set_file_extent_other_encoding(leaf, fi, 0);
> =A0 =A0 =A0 =A0btrfs_mark_buffer_dirty(leaf);
>
> - =A0 =A0 =A0 nbytes =3D btrfs_stack_inode_nbytes(inode) + num_bytes;
> - =A0 =A0 =A0 btrfs_set_stack_inode_nbytes(inode, nbytes);
> + =A0 =A0 =A0 *inode_nbytes +=3D num_bytes;
>
> =A0 =A0 =A0 =A0btrfs_release_path(root, &path);
>
> @@ -492,95 +506,355 @@ fail:
> =A0 =A0 =A0 =A0return ret;
> =A0}
>
> -static int record_file_blocks(struct btrfs_trans_handle *trans,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 struct btrf=
s_root *root, u64 objectid,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 struct btrf=
s_inode_item *inode,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 u64 file_bl=
ock, u64 disk_block,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 u64 num_blo=
cks, int checksum)
> -{
> - =A0 =A0 =A0 u64 file_pos =3D file_block * root->sectorsize;
> - =A0 =A0 =A0 u64 disk_bytenr =3D disk_block * root->sectorsize;
> - =A0 =A0 =A0 u64 num_bytes =3D num_blocks * root->sectorsize;
> - =A0 =A0 =A0 return record_file_extent(trans, root, objectid, inode,=
 file_pos,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 dis=
k_bytenr, num_bytes, checksum);
> -}
> -
> -struct blk_iterate_data {
> +struct extent_iterate_data {
> =A0 =A0 =A0 =A0struct btrfs_trans_handle *trans;
> =A0 =A0 =A0 =A0struct btrfs_root *root;
> - =A0 =A0 =A0 struct btrfs_inode_item *inode;
> + =A0 =A0 =A0 u64 *inode_nbytes;
> =A0 =A0 =A0 =A0u64 objectid;
> - =A0 =A0 =A0 u64 first_block;
> - =A0 =A0 =A0 u64 disk_block;
> - =A0 =A0 =A0 u64 num_blocks;
> - =A0 =A0 =A0 u64 boundary;
> - =A0 =A0 =A0 int checksum;
> - =A0 =A0 =A0 int errcode;
> + =A0 =A0 =A0 int checksum, packing;
> + =A0 =A0 =A0 u64 last_file_off;
> + =A0 =A0 =A0 u64 total_size;
> + =A0 =A0 =A0 enum {EXTENT_ITERATE_TYPE_NONE, EXTENT_ITERATE_TYPE_MEM=
,
> + =A0 =A0 =A0 =A0 =A0 =A0 EXTENT_ITERATE_TYPE_DISK} type;
> + =A0 =A0 =A0 u64 size;
> + =A0 =A0 =A0 u64 file_off; /* always aligned to sectorsize */
> + =A0 =A0 =A0 char *data; /* for mem */
> + =A0 =A0 =A0 u64 disk_off; /* for disk */
> =A0};
>
> -static int block_iterate_proc(ext2_filsys ext2_fs,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 u64 disk_bl=
ock, u64 file_block,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 struct blk_=
iterate_data *idata)
> +static u64 extent_boundary(struct btrfs_root *root, u64 extent_start=
)
> =A0{
> - =A0 =A0 =A0 int ret;
> - =A0 =A0 =A0 int sb_region;
> - =A0 =A0 =A0 int do_barrier;
> - =A0 =A0 =A0 struct btrfs_root *root =3D idata->root;
> - =A0 =A0 =A0 struct btrfs_trans_handle *trans =3D idata->trans;
> - =A0 =A0 =A0 struct btrfs_block_group_cache *cache;
> - =A0 =A0 =A0 u64 bytenr =3D disk_block * root->sectorsize;
> -
> - =A0 =A0 =A0 sb_region =3D intersect_with_sb(bytenr, root->sectorsiz=
e);
> - =A0 =A0 =A0 do_barrier =3D sb_region || disk_block >=3D idata->boun=
dary;
> - =A0 =A0 =A0 if ((idata->num_blocks > 0 && do_barrier) ||
> - =A0 =A0 =A0 =A0 =A0 (file_block > idata->first_block + idata->num_b=
locks) ||
> - =A0 =A0 =A0 =A0 =A0 (disk_block !=3D idata->disk_block + idata->num=
_blocks)) {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (idata->num_blocks > 0) {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D record_file_blo=
cks(trans, root, idata->objectid,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 idata->inode, idata->first_block,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 idata->disk_block, idata->num_blocks,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 idata->checksum);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (ret)
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto fa=
il;
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 idata->first_block +=3D=
 idata->num_blocks;
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 idata->num_blocks =3D 0=
;
> + =A0 =A0 =A0 int i;
> + =A0 =A0 =A0 u64 offset;
> + =A0 =A0 =A0 u64 boundary =3D (u64)-1;
> + =A0 =A0 =A0 for (i =3D 0; i < BTRFS_SUPER_MIRROR_MAX; i++) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 offset =3D btrfs_sb_offset(i);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 offset &=3D ~((u64)STRIPE_LEN - 1);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (offset > extent_start) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 boundary =3D offset;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (offset + STRIPE_LEN > extent_start)=
 {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 boundary =3D offset + S=
TRIPE_LEN;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0}
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (file_block > idata->first_block) {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D record_file_blo=
cks(trans, root, idata->objectid,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 idata->inode, idata->first_block,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 0, file_block - idata->first_block,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 idata->checksum);
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 struct btrfs_block_group_cache *cache;
> + =A0 =A0 =A0 cache =3D btrfs_lookup_block_group(root->fs_info, exten=
t_start);
> + =A0 =A0 =A0 BUG_ON(!cache);
> + =A0 =A0 =A0 offset =3D cache->key.objectid + cache->key.offset;
> + =A0 =A0 =A0 return min_t(u64, boundary, offset);
> +}
> +
> +static int commit_disk_extent(struct extent_iterate_data *priv,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 u64 file_po=
s, u64 disk_bytenr, u64 num_bytes)
> +{
> + =A0 =A0 =A0 u64 boundary;
> + =A0 =A0 =A0 int ret;
> + =A0 =A0 =A0 if (disk_bytenr =3D=3D 0)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return record_file_extent(priv->trans, =
priv->root,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 priv->objectid, priv->inode_nbytes,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 file_pos, disk_bytenr, num_bytes,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 priv->checksum);
> + =A0 =A0 =A0 /* Break up the disk extent on blockgroup and superbloc=
k boundaries. */
> + =A0 =A0 =A0 while (num_bytes) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 boundary =3D extent_boundary(priv->root=
, disk_bytenr);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 u64 size =3D min_t(u64, boundary - disk=
_bytenr, num_bytes);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D record_file_extent(priv->trans,=
 priv->root,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0priv->objectid, priv->inode_nbytes,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0file_pos, disk_bytenr, size,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0priv->checksum);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (ret)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return ret;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 file_pos +=3D size;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 disk_bytenr +=3D size;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 num_bytes -=3D size;
> + =A0 =A0 =A0 }
> + =A0 =A0 =A0 return 0;
> +}
> +
> +static int commit_file_extents(struct extent_iterate_data *priv)
> +{
> + =A0 =A0 =A0 int ret;
> + =A0 =A0 =A0 if (priv->type =3D=3D EXTENT_ITERATE_TYPE_NONE)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return 0;
> + =A0 =A0 =A0 if (priv->size =3D=3D 0)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return 0;
> + =A0 =A0 =A0 if (priv->file_off > priv->last_file_off) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D commit_disk_extent(priv, priv->=
last_file_off, 0,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0priv->file_off - priv->last_file_off);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (ret)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return ret;
> + =A0 =A0 =A0 }
> + =A0 =A0 =A0 priv->last_file_off =3D priv->file_off + priv->size;
> +
> + =A0 =A0 =A0 if (priv->type =3D=3D EXTENT_ITERATE_TYPE_MEM) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* allocate and write to disk */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 struct btrfs_key key;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D custom_alloc_extent(priv->root,=
 priv->root->sectorsize,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 0, &key);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (ret)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return ret;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D write_disk_extent(priv->root, k=
ey.objectid, priv->size,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 priv->data);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (ret)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return ret;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 priv->type =3D EXTENT_ITERATE_TYPE_DISK=
;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 priv->disk_off =3D key.objectid;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 u64 sectorsize =3D priv->root->sectorsize;
> + =A0 =A0 =A0 if (priv->size & (sectorsize - 1))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 priv->size =3D (priv->size & ~(sectorsi=
ze - 1)) + sectorsize;
> + =A0 =A0 =A0 ret =3D commit_disk_extent(priv, priv->file_off, priv->=
disk_off,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0priv=
->size);
> + =A0 =A0 =A0 if (ret)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return ret;
> + =A0 =A0 =A0 priv->type =3D EXTENT_ITERATE_TYPE_NONE;
> + =A0 =A0 =A0 return 0;
> +}
> +
> +int start_file_extents(struct extent_iterate_data *priv,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0struct btrfs_trans_handl=
e *trans,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0struct btrfs_root *root,=
 u64 *inode_nbytes,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0u64 objectid, int checks=
um, int packing, u64 total_size)
> +{
> + =A0 =A0 =A0 priv->trans =3D trans;
> + =A0 =A0 =A0 priv->root =3D root;
> + =A0 =A0 =A0 priv->inode_nbytes =3D inode_nbytes;
> + =A0 =A0 =A0 priv->objectid =3D objectid;
> + =A0 =A0 =A0 priv->checksum =3D checksum;
> + =A0 =A0 =A0 priv->packing =3D packing;
> + =A0 =A0 =A0 priv->last_file_off =3D 0;
> + =A0 =A0 =A0 priv->type =3D 0;
> + =A0 =A0 =A0 priv->total_size =3D total_size;
> + =A0 =A0 =A0 priv->data =3D malloc(root->sectorsize);
> + =A0 =A0 =A0 if (!priv->data)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENOMEM;
> + =A0 =A0 =A0 return 0;
> +}
> +
> +int start_file_extents_range(struct extent_iterate_data *priv,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0struct btrfs=
_trans_handle *trans,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0struct btrfs=
_root *root, u64 *inode_nbytes,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0u64 objectid=
, int checksum, u64 start, u64 end)
> +{
> + =A0 =A0 =A0 priv->trans =3D trans;
> + =A0 =A0 =A0 priv->root =3D root;
> + =A0 =A0 =A0 priv->inode_nbytes =3D inode_nbytes;
> + =A0 =A0 =A0 priv->objectid =3D objectid;
> + =A0 =A0 =A0 priv->checksum =3D checksum;
> + =A0 =A0 =A0 priv->packing =3D 0;
> + =A0 =A0 =A0 priv->last_file_off =3D start;
> + =A0 =A0 =A0 priv->type =3D 0;
> + =A0 =A0 =A0 priv->total_size =3D end;
> + =A0 =A0 =A0 priv->data =3D malloc(root->sectorsize);
> + =A0 =A0 =A0 if (!priv->data)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENOMEM;
> + =A0 =A0 =A0 return 0;
> +}
> +
> +int finish_file_extents(struct extent_iterate_data *priv)
> +{
> + =A0 =A0 =A0 int ret;
> +
> + =A0 =A0 =A0 if (priv->packing
> + =A0 =A0 =A0 =A0 =A0 && priv->type !=3D EXTENT_ITERATE_TYPE_NONE
> + =A0 =A0 =A0 =A0 =A0 && priv->total_size <=3D BTRFS_MAX_INLINE_DATA_=
SIZE(priv->root)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 priv->size =3D min_t(u64, priv->size,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 priv->total_size - priv->file_off);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* make inline extent */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (priv->type =3D=3D EXTENT_ITERATE_TY=
PE_DISK) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D read_disk_exten=
t(priv->root, priv->disk_off,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0priv->size, priv->data);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (ret)
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto fa=
il;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return =
ret;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0}
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 *priv->inode_nbytes +=3D priv->size;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return btrfs_insert_inline_extent(priv-=
>trans, priv->root,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 priv->objectid,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 priv->file_off, priv->data,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 priv->size);
> + =A0 =A0 =A0 }
>
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (sb_region) {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 bytenr +=3D STRIPE_LEN =
- 1;
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 bytenr &=3D ~((u64)STRI=
PE_LEN - 1);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 } else {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 cache =3D btrfs_lookup_=
block_group(root->fs_info, bytenr);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 BUG_ON(!cache);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 bytenr =3D cache->key.o=
bjectid + cache->key.offset;
> + =A0 =A0 =A0 ret =3D commit_file_extents(priv);
> + =A0 =A0 =A0 if (ret)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return ret;
> +
> + =A0 =A0 =A0 if (priv->total_size > priv->last_file_off) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D commit_disk_extent(priv, priv->=
last_file_off, 0,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 priv->total_size - priv->last_file_off);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (ret)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return ret;
> + =A0 =A0 =A0 }
> + =A0 =A0 =A0 free(priv->data);
> + =A0 =A0 =A0 return 0;
> +}
> +
> +int add_file_mem_extent(struct extent_iterate_data *priv, u64 file_o=
ff,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 u64 size, char *data);
> +
> +int add_file_disk_extent(struct extent_iterate_data *priv, u64 file_=
off,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0u64 disk_off, u64 si=
ze)
> +{
> + =A0 =A0 =A0 BUG_ON(file_off < priv->last_file_off);
> + =A0 =A0 =A0 int ret;
> + =A0 =A0 =A0 u64 sectorsize =3D priv->root->sectorsize;
> + =A0 =A0 =A0 u64 mask =3D sectorsize - 1;
> + =A0 =A0 =A0 if (size =3D=3D 0)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return 0;
> + =A0 =A0 =A0 if ((file_off & mask) !=3D (disk_off & mask)) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* It's unclear how to CoW this, so don=
't. */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 char *data =3D malloc(size);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!data)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENOMEM;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D read_disk_extent(priv->root, di=
sk_off, size, data);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (ret) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 free(data);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return ret;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0}
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D add_file_mem_extent(priv, file_=
off, size, data);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 free(data);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return ret;
> + =A0 =A0 =A0 }
> + =A0 =A0 =A0 if (priv->type =3D=3D EXTENT_ITERATE_TYPE_DISK
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 && priv->file_off + pri=
v->size =3D=3D file_off
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 && priv->disk_off + pri=
v->size =3D=3D disk_off) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* It's a continuation of the same disk=
 extent. */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 priv->size +=3D size;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return 0;
> + =A0 =A0 =A0 }
> + =A0 =A0 =A0 if (disk_off =3D=3D 0 || disk_off & mask) {

why "disk_off =3D=3D 0" is needed here?

> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* We need to have an aligned start, so=
 give the first part to
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* add_file_mem_extent if necessary. =
*/
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 u64 mem_size =3D min_t(u64, sectorsize =
- (disk_off & mask), size);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 char *data =3D malloc(mem_size);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!data)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENOMEM;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D read_disk_extent(priv->root, di=
sk_off, mem_size, data);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (ret) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 free(data);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return ret;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D add_file_mem_extent(priv, file_=
off, mem_size, data);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 free(data);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (ret)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return ret;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 file_off +=3D mem_size;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 disk_off +=3D mem_size;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 size -=3D mem_size;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (size =3D=3D 0)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return 0;
> + =A0 =A0 =A0 }
> + =A0 =A0 =A0 ret =3D commit_file_extents(priv);
> + =A0 =A0 =A0 if (ret)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return ret;
> + =A0 =A0 =A0 priv->type =3D EXTENT_ITERATE_TYPE_DISK;
> + =A0 =A0 =A0 priv->size =3D size;
> + =A0 =A0 =A0 priv->file_off =3D file_off;
> + =A0 =A0 =A0 priv->disk_off =3D disk_off;
> + =A0 =A0 =A0 return 0;
> +}
> +
> +int add_file_mem_extent(struct extent_iterate_data *priv, u64 file_o=
ff,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 u64 size, char *data)
> +{
> + =A0 =A0 =A0 BUG_ON(file_off < priv->last_file_off);
> + =A0 =A0 =A0 int ret;
> + =A0 =A0 =A0 u64 sectorsize =3D priv->root->sectorsize;
> + =A0 =A0 =A0 u64 mask =3D sectorsize - 1;
> + =A0 =A0 =A0 u64 aligned_file_off =3D file_off & ~mask;
> + =A0 =A0 =A0 u32 alignment =3D file_off - aligned_file_off;
> + =A0 =A0 =A0 size +=3D alignment;
> +
> + =A0 =A0 =A0 /* If we share a sector with a DISK extent, commit most=
 of it and turn
> + =A0 =A0 =A0 =A0* the shared part into a MEM extent. */
> + =A0 =A0 =A0 if (priv->type =3D=3D EXTENT_ITERATE_TYPE_DISK
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 && priv->file_off + pri=
v->size > aligned_file_off) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 u64 mem_size =3D priv->file_off + priv-=
>size - aligned_file_off;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D read_disk_extent(priv->root, al=
igned_file_off, mem_size,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0priv->data);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (ret)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return ret;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 priv->size -=3D mem_size;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D commit_file_extents(priv);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (ret)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return ret;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 priv->type =3D EXTENT_ITERATE_TYPE_MEM;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 priv->size =3D mem_size;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 priv->file_off =3D aligned_file_off;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* Put our first sector in priv->data. If we share a se=
ctor with the
> + =A0 =A0 =A0 =A0* previous extent, combine with it. */
> + =A0 =A0 =A0 if (priv->type =3D=3D EXTENT_ITERATE_TYPE_MEM
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 && priv->file_off + pri=
v->size > aligned_file_off) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 BUG_ON(priv->file_off !=3D aligned_file=
_off);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 memset(priv->data + priv->size, 0, sect=
orsize - priv->size);
> + =A0 =A0 =A0 } else {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D commit_file_extents(priv);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (ret)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return ret;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 memset(priv->data, 0, sectorsize);
> + =A0 =A0 =A0 }
> + =A0 =A0 =A0 if (size < sectorsize) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 memcpy(priv->data + alignment, data, si=
ze - alignment);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 priv->type =3D EXTENT_ITERATE_TYPE_MEM;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 priv->file_off =3D aligned_file_off;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 priv->size =3D size;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return 0;
> + =A0 =A0 =A0 }
> + =A0 =A0 =A0 memcpy(priv->data + alignment, data, sectorsize - align=
ment);
> + =A0 =A0 =A0 data +=3D sectorsize - alignment;
> +
> + =A0 =A0 =A0 /* We have full sectors; allocate and write them. */
> + =A0 =A0 =A0 u64 aligned_size =3D size & ~mask;
> + =A0 =A0 =A0 struct btrfs_key key;
> + =A0 =A0 =A0 ret =3D custom_alloc_extent(priv->root, aligned_size, 0=
, &key);
> + =A0 =A0 =A0 if (ret)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return ret;
> + =A0 =A0 =A0 ret =3D write_disk_extent(priv->root, key.objectid,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 sectors=
ize, priv->data);
> + =A0 =A0 =A0 if (ret)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return ret;
> + =A0 =A0 =A0 ret =3D write_disk_extent(priv->root, key.objectid + se=
ctorsize,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 aligned=
_size - sectorsize, data);
> + =A0 =A0 =A0 if (ret)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return ret;
> + =A0 =A0 =A0 ret =3D add_file_disk_extent(priv, aligned_file_off, ke=
y.objectid,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
aligned_size);
> + =A0 =A0 =A0 if (ret)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return ret;
>
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 idata->first_block =3D file_block;
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 idata->disk_block =3D disk_block;
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 idata->boundary =3D bytenr / root->sect=
orsize;
> + =A0 =A0 =A0 /* Leave the rest in priv. */
> + =A0 =A0 =A0 size -=3D aligned_size;
> + =A0 =A0 =A0 if (size) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D commit_file_extents(priv);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (ret)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return ret;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 aligned_file_off +=3D aligned_size;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 data +=3D aligned_size - sectorsize;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 priv->type =3D EXTENT_ITERATE_TYPE_MEM;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 priv->file_off =3D aligned_file_off;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 priv->size =3D size;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 memcpy(priv->data, data, size);
> =A0 =A0 =A0 =A0}
> - =A0 =A0 =A0 idata->num_blocks++;
> =A0 =A0 =A0 =A0return 0;
> -fail:
> - =A0 =A0 =A0 idata->errcode =3D ret;
> - =A0 =A0 =A0 return BLOCK_ABORT;
> =A0}
>
> =A0static int __block_iterate_proc(ext2_filsys fs, blk_t *blocknr,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0e2_blk=
cnt_t blockcnt, blk_t ref_block,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0int re=
f_offset, void *priv_data)
> =A0{
> - =A0 =A0 =A0 struct blk_iterate_data *idata;
> - =A0 =A0 =A0 idata =3D (struct blk_iterate_data *)priv_data;
> - =A0 =A0 =A0 return block_iterate_proc(fs, *blocknr, blockcnt, idata=
);
> + =A0 =A0 =A0 struct extent_iterate_data *idata;
> + =A0 =A0 =A0 idata =3D (struct extent_iterate_data *)priv_data;
> + =A0 =A0 =A0 u64 blocksize =3D fs->blocksize;
> + =A0 =A0 =A0 int ret =3D add_file_disk_extent(idata, blocksize * blo=
ckcnt,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0blocksize * *blocknr, blocksize);
> + =A0 =A0 =A0 if (ret)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return BLOCK_ABORT;
> + =A0 =A0 =A0 return 0;
> =A0}
>
> =A0/*
> @@ -593,68 +867,23 @@ static int create_file_extents(struct btrfs_tra=
ns_handle *trans,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 int datac=
sum, int packing)
> =A0{
> =A0 =A0 =A0 =A0int ret;
> - =A0 =A0 =A0 char *buffer =3D NULL;
> =A0 =A0 =A0 =A0errcode_t err;
> - =A0 =A0 =A0 u32 last_block;
> - =A0 =A0 =A0 u32 sectorsize =3D root->sectorsize;
> + =A0 =A0 =A0 u64 inode_nbytes =3D 0;
> =A0 =A0 =A0 =A0u64 inode_size =3D btrfs_stack_inode_size(btrfs_inode)=
;
> - =A0 =A0 =A0 struct blk_iterate_data data =3D {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 .trans =A0 =A0 =A0 =A0 =A0=3D trans,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 .root =A0 =A0 =A0 =A0 =A0 =3D root,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 .inode =A0 =A0 =A0 =A0 =A0=3D btrfs_ino=
de,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 .objectid =A0 =A0 =A0 =3D objectid,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 .first_block =A0 =A0=3D 0,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 .disk_block =A0 =A0 =3D 0,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 .num_blocks =A0 =A0 =3D 0,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 .boundary =A0 =A0 =A0 =3D (u64)-1,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 .checksum =A0 =A0 =A0 =3D datacsum,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 .errcode =A0 =A0 =A0 =A0=3D 0,
> - =A0 =A0 =A0 };
> + =A0 =A0 =A0 struct extent_iterate_data data;
> + =A0 =A0 =A0 ret =3D start_file_extents(&data, trans, root, &inode_n=
bytes, objectid,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0data=
csum, packing, inode_size);
> + =A0 =A0 =A0 if (ret)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return ret;
> =A0 =A0 =A0 =A0err =3D ext2fs_block_iterate2(ext2_fs, ext2_ino, BLOCK=
_FLAG_DATA_ONLY,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
NULL, __block_iterate_proc, &data);
> =A0 =A0 =A0 =A0if (err)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0goto error;
> - =A0 =A0 =A0 ret =3D data.errcode;
> + =A0 =A0 =A0 ret =3D finish_file_extents(&data);
> =A0 =A0 =A0 =A0if (ret)
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto fail;
> - =A0 =A0 =A0 if (packing && data.first_block =3D=3D 0 && data.num_bl=
ocks > 0 &&
> - =A0 =A0 =A0 =A0 =A0 inode_size <=3D BTRFS_MAX_INLINE_DATA_SIZE(root=
)) {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 u64 num_bytes =3D data.num_blocks * sec=
torsize;
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 u64 disk_bytenr =3D data.disk_block * s=
ectorsize;
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 u64 nbytes;
> -
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 buffer =3D malloc(num_bytes);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!buffer)
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENOMEM;
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D read_disk_extent(root, disk_byt=
enr, num_bytes, buffer);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (ret)
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto fail;
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (num_bytes > inode_size)
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 num_bytes =3D inode_siz=
e;
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D btrfs_insert_inline_extent(tran=
s, root, objectid,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0 =A00, buffer, num_bytes);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (ret)
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto fail;
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 nbytes =3D btrfs_stack_inode_nbytes(btr=
fs_inode) + num_bytes;
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 btrfs_set_stack_inode_nbytes(btrfs_inod=
e, nbytes);
> - =A0 =A0 =A0 } else if (data.num_blocks > 0) {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D record_file_blocks(trans, root,=
 objectid, btrfs_inode,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0data.first_block, data.disk_block,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0data.num_blocks, data.checksum);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (ret)
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto fail;
> - =A0 =A0 =A0 }
> - =A0 =A0 =A0 data.first_block +=3D data.num_blocks;
> - =A0 =A0 =A0 last_block =3D (inode_size + sectorsize - 1) / sectorsi=
ze;
> - =A0 =A0 =A0 if (last_block > data.first_block) {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D record_file_blocks(trans, root,=
 objectid, btrfs_inode,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0data.first_block, 0, last_block -
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0data.first_block, data.checksum);
> - =A0 =A0 =A0 }
> -fail:
> - =A0 =A0 =A0 if (buffer)
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 free(buffer);
> - =A0 =A0 =A0 return ret;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return ret;
> + =A0 =A0 =A0 btrfs_set_stack_inode_nbytes(btrfs_inode, inode_nbytes)=
;
> + =A0 =A0 =A0 return 0;
> =A0error:
> =A0 =A0 =A0 =A0fprintf(stderr, "ext2fs_block_iterate2: %s\n", error_m=
essage(err));
> =A0 =A0 =A0 =A0return -1;
> @@ -1206,52 +1435,33 @@ static int copy_inodes(struct btrfs_root *roo=
t, ext2_filsys ext2_fs,
> =A0*/
> =A0static int create_image_file_range(struct btrfs_trans_handle *tran=
s,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 s=
truct btrfs_root *root, u64 objectid,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
struct btrfs_inode_item *inode,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
u64 *inode_nbytes,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 u=
64 start_byte, u64 end_byte,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 s=
truct extent_io_tree *orig_free_tree)
> =A0{
> - =A0 =A0 =A0 u32 blocksize =3D root->sectorsize;
> - =A0 =A0 =A0 u32 block =3D start_byte / blocksize;
> - =A0 =A0 =A0 u32 last_block =3D (end_byte + blocksize - 1) / blocksi=
ze;
> =A0 =A0 =A0 =A0int ret =3D 0;
> - =A0 =A0 =A0 struct blk_iterate_data data =3D {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 .trans =A0 =A0 =A0 =A0 =A0=3D trans,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 .root =A0 =A0 =A0 =A0 =A0 =3D root,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 .inode =A0 =A0 =A0 =A0 =A0=3D inode,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 .objectid =A0 =A0 =A0 =3D objectid,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 .first_block =A0 =A0=3D block,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 .disk_block =A0 =A0 =3D 0,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 .num_blocks =A0 =A0 =3D 0,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 .boundary =A0 =A0 =A0 =3D (u64)-1,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 .checksum =A0 =A0 =A0 =3D 0,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 .errcode =A0 =A0 =A0 =A0=3D 0,
> - =A0 =A0 =A0 };
> - =A0 =A0 =A0 for (; start_byte < end_byte; block++, start_byte +=3D =
blocksize) {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (test_range_bit(orig_free_tree, star=
t_byte,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
start_byte + blocksize, EXTENT_DIRTY, 1))
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 continue;
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D block_iterate_proc(NULL, block,=
 block, &data);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (ret & BLOCK_ABORT) {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D data.errcode;
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto fail;
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> - =A0 =A0 =A0 }
> - =A0 =A0 =A0 if (data.num_blocks > 0) {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D record_file_blocks(trans, root,=
 objectid, inode,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0data.first_block, data.disk_block,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0data.num_blocks, 0);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (ret)
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto fail;
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 data.first_block +=3D data.num_blocks;
> - =A0 =A0 =A0 }
> - =A0 =A0 =A0 if (last_block > data.first_block) {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D record_file_blocks(trans, root,=
 objectid, inode,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0data.first_block, 0, last_block -
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0data.first_block, 0);
> + =A0 =A0 =A0 struct extent_iterate_data data;
> + =A0 =A0 =A0 ret =3D start_file_extents_range(&data, trans, root, in=
ode_nbytes,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0objectid, 0, start_byte, end_byte);
> + =A0 =A0 =A0 if (ret)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return ret;
> + =A0 =A0 =A0 while (start_byte < end_byte) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 u64 start, end;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D find_first_extent_bit(orig_free=
_tree, start_byte,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 &start, &end, EXTENT_DIRTY);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (ret)
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto fail;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 start =3D end_byte;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (start > start_byte) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 u64 size =3D min_t(u64,=
 start - start_byte,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 end_byte - start_byte);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D add_file_disk_e=
xtent(&data, start_byte,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0start_byte, size);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (ret)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return =
ret;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 start_byte =3D end + 1;
> =A0 =A0 =A0 =A0}
> -fail:
> + =A0 =A0 =A0 ret =3D finish_file_extents(&data);
> =A0 =A0 =A0 =A0return ret;
> =A0}
> =A0/*
> @@ -1279,6 +1489,7 @@ static int create_ext2_image(struct btrfs_root =
*root, const char *name,
> =A0 =A0 =A0 =A0u64 last_byte;
> =A0 =A0 =A0 =A0u64 first_free;
> =A0 =A0 =A0 =A0u64 total_bytes;
> + =A0 =A0 =A0 u64 inode_nbytes;
> =A0 =A0 =A0 =A0u32 sectorsize =3D root->sectorsize;
>
> =A0 =A0 =A0 =A0total_bytes =3D btrfs_super_total_bytes(&fs_info->supe=
r_copy);
> @@ -1289,7 +1500,7 @@ static int create_ext2_image(struct btrfs_root =
*root, const char *name,
> =A0 =A0 =A0 =A0btrfs_set_stack_inode_generation(&btrfs_inode, 1);
> =A0 =A0 =A0 =A0btrfs_set_stack_inode_size(&btrfs_inode, total_bytes);
> =A0 =A0 =A0 =A0btrfs_set_stack_inode_nlink(&btrfs_inode, 1);
> - =A0 =A0 =A0 btrfs_set_stack_inode_nbytes(&btrfs_inode, 0);
> + =A0 =A0 =A0 inode_nbytes =3D 0;
> =A0 =A0 =A0 =A0btrfs_set_stack_inode_mode(&btrfs_inode, S_IFREG | 040=
0);
> =A0 =A0 =A0 =A0btrfs_set_stack_inode_flags(&btrfs_inode, BTRFS_INODE_=
NODATASUM |
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
BTRFS_INODE_READONLY);
> @@ -1315,7 +1526,7 @@ static int create_ext2_image(struct btrfs_root =
*root, const char *name,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (ret)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0goto fail;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0ret =3D record_file_extent(trans, root=
, objectid,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0&btrfs_inode, last_byte,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0&inode_nbytes, last_byte,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 key.objectid, sectorsize, 0);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (ret)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0goto fail;
> @@ -1370,12 +1581,12 @@ next:
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (bytenr > last_byte) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0ret =3D create_image_f=
ile_range(trans, root, objectid,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 &btrfs_inode, last_byte,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 &inode_nbytes, last_byte,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0bytenr, orig_free_tree);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (ret)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0goto f=
ail;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0}
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D record_file_extent(trans, root,=
 objectid, &btrfs_inode,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D record_file_extent(trans, root,=
 objectid, &inode_nbytes,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 bytenr, bytenr, num_bytes, 0);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (ret)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0goto fail;
> @@ -1392,12 +1603,14 @@ next:
> =A0 =A0 =A0 =A0btrfs_release_path(root, &path);
> =A0 =A0 =A0 =A0if (total_bytes > last_byte) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0ret =3D create_image_file_range(trans,=
 root, objectid,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 &btrfs_inode, last_byte,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0 &inode_nbytes, last_byte,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0 =A0total_bytes, orig_free_tree);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (ret)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0goto fail;
> =A0 =A0 =A0 =A0}
>
> + =A0 =A0 =A0 btrfs_set_stack_inode_nbytes(&btrfs_inode, inode_nbytes=
);
> +
> =A0 =A0 =A0 =A0ret =3D btrfs_insert_inode(trans, root, objectid, &btr=
fs_inode);
> =A0 =A0 =A0 =A0if (ret)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0goto fail;
> @@ -1934,7 +2147,7 @@ static int relocate_one_reference(struct btrfs_=
trans_handle *trans,
> =A0 =A0 =A0 =A0struct btrfs_key key;
> =A0 =A0 =A0 =A0struct btrfs_path path;
> =A0 =A0 =A0 =A0struct btrfs_inode_item inode;
> - =A0 =A0 =A0 struct blk_iterate_data data;
> + =A0 =A0 =A0 struct extent_iterate_data data;
> =A0 =A0 =A0 =A0u64 bytenr;
> =A0 =A0 =A0 =A0u64 num_bytes;
> =A0 =A0 =A0 =A0u64 cur_offset;
> @@ -1990,22 +2203,14 @@ static int relocate_one_reference(struct btrf=
s_trans_handle *trans,
> =A0 =A0 =A0 =A0btrfs_release_path(root, &path);
>
> =A0 =A0 =A0 =A0BUG_ON(num_bytes & (sectorsize - 1));
> - =A0 =A0 =A0 nbytes =3D btrfs_stack_inode_nbytes(&inode) - num_bytes=
;
> - =A0 =A0 =A0 btrfs_set_stack_inode_nbytes(&inode, nbytes);
> =A0 =A0 =A0 =A0datacsum =3D !(btrfs_stack_inode_flags(&inode) & BTRFS=
_INODE_NODATASUM);
>
> - =A0 =A0 =A0 data =3D (struct blk_iterate_data) {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 .trans =A0 =A0 =A0 =A0 =A0=3D trans,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 .root =A0 =A0 =A0 =A0 =A0 =3D root,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 .inode =A0 =A0 =A0 =A0 =A0=3D &inode,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 .objectid =A0 =A0 =A0 =3D extent_key->o=
bjectid,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 .first_block =A0 =A0=3D extent_key->off=
set / sectorsize,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 .disk_block =A0 =A0 =3D 0,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 .num_blocks =A0 =A0 =3D 0,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 .boundary =A0 =A0 =A0 =3D (u64)-1,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 .checksum =A0 =A0 =A0 =3D datacsum,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 .errcode =A0 =A0 =A0 =A0=3D 0,
> - =A0 =A0 =A0 };
> + =A0 =A0 =A0 ret =3D start_file_extents_range(&data, trans, root, &n=
bytes,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0extent_key->objectid, datacsum,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0extent_key->offset,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0extent_key->offset + num_bytes);
> + =A0 =A0 =A0 if (ret)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto fail;
>
> =A0 =A0 =A0 =A0cur_offset =3D extent_key->offset;
> =A0 =A0 =A0 =A0while (num_bytes > 0) {
> @@ -2035,26 +2240,19 @@ static int relocate_one_reference(struct btrf=
s_trans_handle *trans,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0BUG_ON(ret);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0}
>
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D block_iterate_proc(NULL, new_po=
s / sectorsize,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0cur_offset / sectorsize, &data);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (ret & BLOCK_ABORT) {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D data.errcode;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D add_file_disk_extent(&data, cur=
_offset, new_pos,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0 =A0sectorsize);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (ret)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0goto fail;
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0cur_offset +=3D sectorsize;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0bytenr +=3D sectorsize;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0num_bytes -=3D sectorsize;
> =A0 =A0 =A0 =A0}
>
> - =A0 =A0 =A0 if (data.num_blocks > 0) {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D record_file_blocks(trans, root,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0extent_key->objectid, &inode,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0data.first_block, data.disk_block,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 =A0 =A0data.num_blocks, datacsum);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (ret)
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto fail;
> - =A0 =A0 =A0 }
> + =A0 =A0 =A0 ret =3D finish_file_extents(&data);
> + =A0 =A0 =A0 if (ret)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto fail;
>
> =A0 =A0 =A0 =A0key.objectid =3D extent_key->objectid;
> =A0 =A0 =A0 =A0key.offset =3D 0;
> --
> 1.6.4.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-btrfs=
" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at =A0http://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@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 2/4] btrfs-convert: Add extent iteration functions.
  2010-05-18 13:06 ` Yan, Zheng 
@ 2010-05-18 15:37   ` Sean Bartell
  0 siblings, 0 replies; 4+ messages in thread
From: Sean Bartell @ 2010-05-18 15:37 UTC (permalink / raw)
  To: Yan, Zheng ; +Cc: linux-btrfs

On Tue, May 18, 2010 at 09:06:54PM +0800, Yan, Zheng  wrote:
> On Sat, Mar 20, 2010 at 12:26 PM, Sean Bartell
> <wingedtachikoma@gmail.com> wrote:
> > +int add_file_disk_extent(struct extent_iterate_data *priv, u64 fil=
e_off,
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0u64 disk_off, u64 =
size)
> > +{
> > + =A0 =A0 =A0 BUG_ON(file_off < priv->last_file_off);
> > + =A0 =A0 =A0 int ret;
> > + =A0 =A0 =A0 u64 sectorsize =3D priv->root->sectorsize;
> > + =A0 =A0 =A0 u64 mask =3D sectorsize - 1;
> > + =A0 =A0 =A0 if (size =3D=3D 0)
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return 0;
> > + =A0 =A0 =A0 if ((file_off & mask) !=3D (disk_off & mask)) {
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* It's unclear how to CoW this, so d=
on't. */
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 char *data =3D malloc(size);
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!data)
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENOMEM;
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D read_disk_extent(priv->root, =
disk_off, size, data);
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (ret) {
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 free(data);
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return ret;
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0}
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D add_file_mem_extent(priv, fil=
e_off, size, data);
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 free(data);
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return ret;
> > + =A0 =A0 =A0 }
> > + =A0 =A0 =A0 if (priv->type =3D=3D EXTENT_ITERATE_TYPE_DISK
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 && priv->file_off + p=
riv->size =3D=3D file_off
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 && priv->disk_off + p=
riv->size =3D=3D disk_off) {
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* It's a continuation of the same di=
sk extent. */
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 priv->size +=3D size;
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return 0;
> > + =A0 =A0 =A0 }
> > + =A0 =A0 =A0 if (disk_off =3D=3D 0 || disk_off & mask) {
>=20
> why "disk_off =3D=3D 0" is needed here?

To btrfs, a disk offset of 0 represents a sparse extent. If the origina=
l
filesystem passes in an extent at 0, this chops off the first block to
prevent it from being mistakenly interpreted as a sparse extent.

> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* We need to have an aligned start, =
so give the first part to
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* add_file_mem_extent if necessary=
=2E */
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 u64 mem_size =3D min_t(u64, sectorsiz=
e - (disk_off & mask), size);
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 char *data =3D malloc(mem_size);
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!data)
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return -ENOMEM;
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D read_disk_extent(priv->root, =
disk_off, mem_size, data);
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (ret) {
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 free(data);
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return ret;
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D add_file_mem_extent(priv, fil=
e_off, mem_size, data);
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 free(data);
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (ret)
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return ret;
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 file_off +=3D mem_size;
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 disk_off +=3D mem_size;
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 size -=3D mem_size;
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (size =3D=3D 0)
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return 0;
> > + =A0 =A0 =A0 }
> > + =A0 =A0 =A0 ret =3D commit_file_extents(priv);
> > + =A0 =A0 =A0 if (ret)
> > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return ret;
> > + =A0 =A0 =A0 priv->type =3D EXTENT_ITERATE_TYPE_DISK;
> > + =A0 =A0 =A0 priv->size =3D size;
> > + =A0 =A0 =A0 priv->file_off =3D file_off;
> > + =A0 =A0 =A0 priv->disk_off =3D disk_off;
> > + =A0 =A0 =A0 return 0;
> > +}
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" =
in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2010-05-18 15:37 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-03-20  4:26 [PATCH 2/4] btrfs-convert: Add extent iteration functions Sean Bartell
2010-03-22  4:55 ` Sean Bartell
2010-05-18 13:06 ` Yan, Zheng 
2010-05-18 15:37   ` Sean Bartell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).