Skip to contentSkip to conversation

btrfs-convert: make more use of cache_free_extents

PATCH In review Sean Bartell 2 participants 3 messages Mar 20, 2010 – May 18, 2010 Btrfs file system

lore
Share & tools
lore
#0 lore raw

PATCH 1/4 btrfs-convert: make more use of cache_free_extents

An extent_io_tree is used for all free space information. This allows removal of ext2_alloc_block and ext2_free_block, and makes create_ext2_image less ext2-specific.

---
 convert.c |  154 +++++++++++++++++++++++++++++++++++++++----------------------
 1 files changed, 99 insertions(+), 55 deletions(-)
convert.c +99 -55
index d037c98..c48f8ba 100644
@@ -95,29 +95,10 @@ static int close_ext2fs(ext2_filsys fs)
 	return 0;
 }
 
-static int ext2_alloc_block(ext2_filsys fs, u64 goal, u64 *block_ret)
+static int ext2_cache_free_extents(ext2_filsys ext2_fs,
+				   struct extent_io_tree *free_tree)
 {
-	blk_t block;
-
-	if (!ext2fs_new_block(fs, goal, NULL, &block)) {
-		ext2fs_fast_mark_block_bitmap(fs->block_map, block);
-		*block_ret = block;
-		return 0;
-	}
-	return -ENOSPC;
-}
-
-static int ext2_free_block(ext2_filsys fs, u64 block)
-{
-	BUG_ON(block != (blk_t)block);
-	ext2fs_fast_unmark_block_bitmap(fs->block_map, block);
-	return 0;
-}
-
-static int cache_free_extents(struct btrfs_root *root, ext2_filsys ext2_fs)
-
-{
-	int i, ret = 0;
+	int ret = 0;
 	blk_t block;
 	u64 bytenr;
 	u64 blocksize = ext2_fs->blocksize;
@@ -127,29 +108,68 @@ static int cache_free_extents(struct btrfs_root *root, ext2_filsys ext2_fs)
 		if (ext2fs_fast_test_block_bitmap(ext2_fs->block_map, block))
 			continue;
 		bytenr = block * blocksize;
-		ret = set_extent_dirty(&root->fs_info->free_space_cache,
-				       bytenr, bytenr + blocksize - 1, 0);
+		ret = set_extent_dirty(free_tree, bytenr,
+				       bytenr + blocksize - 1, 0);
 		BUG_ON(ret);
 	}
 
+	return 0;
+}
+
+/* mark btrfs-reserved blocks as used */
+static void adjust_free_extents(ext2_filsys ext2_fs,
+				struct extent_io_tree *free_tree)
+{
+	int i;
+	u64 bytenr;
+	u64 blocksize = ext2_fs->blocksize;
+
+	clear_extent_dirty(free_tree, 0, BTRFS_SUPER_INFO_OFFSET - 1, 0);
+
 	for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) {
 		bytenr = btrfs_sb_offset(i);
 		bytenr &= ~((u64)STRIPE_LEN - 1);
 		if (bytenr >= blocksize * ext2_fs->super->s_blocks_count)
 			break;
-		clear_extent_dirty(&root->fs_info->free_space_cache, bytenr,
-				   bytenr + STRIPE_LEN - 1, 0);
+		clear_extent_dirty(free_tree, bytenr, bytenr + STRIPE_LEN - 1,
+				   0);
 	}
+}
 
-	clear_extent_dirty(&root->fs_info->free_space_cache,
-			   0, BTRFS_SUPER_INFO_OFFSET - 1, 0);
-
+static int alloc_blocks(struct extent_io_tree *free_tree,
+			u64 *blocks, int num, u64 blocksize)
+{
+	u64 start;
+	u64 end;
+	u64 last = 0;
+	u64 mask = blocksize - 1;
+	int ret;
+	while(num) {
+		ret = find_first_extent_bit(free_tree, last, &start, &end,
+					    EXTENT_DIRTY);
+		if (ret)
+			goto fail;
+		last = end + 1;
+		if (start & mask)
+			start = (start & mask) + blocksize;
+		if (last - start < blocksize)
+			continue;
+		*blocks++ = start;
+		num--;
+		last = start + blocksize;
+		clear_extent_dirty(free_tree, start, last - 1, 0);
+	}
 	return 0;
+fail:
+	fprintf(stderr, "not enough free space\n");
+	return -ENOSPC;
 }
 
 static int custom_alloc_extent(struct btrfs_root *root, u64 num_bytes,
 			       u64 hint_byte, struct btrfs_key *ins)
 {
+	u64 blocksize = root->sectorsize;
+	u64 mask = blocksize - 1;
 	u64 start;
 	u64 end;
 	u64 last = hint_byte;
@@ -171,6 +191,8 @@ static int custom_alloc_extent(struct btrfs_root *root, u64 num_bytes,
 
 		start = max(last, start);
 		last = end + 1;
+		if (start & mask)
+			start = (start & mask) + blocksize;
 		if (last - start < num_bytes)
 			continue;
 
@@ -1186,9 +1208,9 @@ static int create_image_file_range(struct btrfs_trans_handle *trans,
 				   struct btrfs_root *root, u64 objectid,
 				   struct btrfs_inode_item *inode,
 				   u64 start_byte, u64 end_byte,
-				   ext2_filsys ext2_fs)
+				   struct extent_io_tree *orig_free_tree)
 {
-	u32 blocksize = ext2_fs->blocksize;
+	u32 blocksize = root->sectorsize;
 	u32 block = start_byte / blocksize;
 	u32 last_block = (end_byte + blocksize - 1) / blocksize;
 	int ret = 0;
@@ -1205,7 +1227,8 @@ static int create_image_file_range(struct btrfs_trans_handle *trans,
 		.errcode	= 0,
 	};
 	for (; start_byte < end_byte; block++, start_byte += blocksize) {
-		if (!ext2fs_fast_test_block_bitmap(ext2_fs->block_map, block))
+		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) {
@@ -1234,8 +1257,8 @@ fail:
 /*
  * Create the ext2fs image file.
  */
-static int create_ext2_image(struct btrfs_root *root, ext2_filsys ext2_fs,
-			     const char *name)
+static int create_ext2_image(struct btrfs_root *root, const char *name,
+			     struct extent_io_tree *orig_free_tree)
 {
 	int ret;
 	struct btrfs_key key;
@@ -1348,7 +1371,7 @@ next:
 		if (bytenr > last_byte) {
 			ret = create_image_file_range(trans, root, objectid,
 						      &btrfs_inode, last_byte,
-						      bytenr, ext2_fs);
+						      bytenr, orig_free_tree);
 			if (ret)
 				goto fail;
 		}
@@ -1370,7 +1393,7 @@ next:
 	if (total_bytes > last_byte) {
 		ret = create_image_file_range(trans, root, objectid,
 					      &btrfs_inode, last_byte,
-					      total_bytes, ext2_fs);
+					      total_bytes, orig_free_tree);
 		if (ret)
 			goto fail;
 	}
@@ -2332,9 +2355,23 @@ err:
 	return ret;
 }
 
+static int copy_dirtiness(struct extent_io_tree *out,
+			  struct extent_io_tree *in)
+{
+	int ret;
+	u64 start, end, last = 0;
+	while (!find_first_extent_bit(in, last, &start, &end, EXTENT_DIRTY)) {
+		ret = set_extent_dirty(out, start, end, 0);
+		if (ret)
+			return ret;
+		last = end + 1;
+	}
+	return 0;
+}
+
 int do_convert(const char *devname, int datacsum, int packing, int noxattr)
 {
-	int i, fd, ret;
+	int fd, ret;
 	u32 blocksize;
 	u64 blocks[7];
 	u64 total_bytes;
@@ -2342,7 +2379,11 @@ int do_convert(const char *devname, int datacsum, int packing, int noxattr)
 	ext2_filsys ext2_fs;
 	struct btrfs_root *root;
 	struct btrfs_root *ext2_root;
+	struct extent_io_tree free_tree;
+	struct extent_io_tree orig_free_tree;
 
+	extent_io_tree_init(&free_tree);
+	extent_io_tree_init(&orig_free_tree);
 	ret = open_ext2fs(devname, &ext2_fs);
 	if (ret) {
 		fprintf(stderr, "unable to open the Ext2fs\n");
@@ -2359,13 +2400,23 @@ int do_convert(const char *devname, int datacsum, int packing, int noxattr)
 		fprintf(stderr, "filetype feature is missing\n");
 		goto fail;
 	}
-	for (i = 0; i < 7; i++) {
-		ret = ext2_alloc_block(ext2_fs, 0, blocks + i);
-		if (ret) {
-			fprintf(stderr, "not enough free space\n");
-			goto fail;
-		}
-		blocks[i] *= blocksize;
+	ret = ext2_cache_free_extents(ext2_fs, &orig_free_tree);
+	if (ret) {
+		fprintf(stderr, "error during cache_free_extents %d\n", ret);
+		goto fail;
+	}
+	/* preserve first 64KiB, just in case */
+	clear_extent_dirty(&orig_free_tree, 0, BTRFS_SUPER_INFO_OFFSET - 1, 0);
+
+	ret = copy_dirtiness(&free_tree, &orig_free_tree);
+	if (ret) {
+		fprintf(stderr, "error during copy_dirtiness %d\n", ret);
+		goto fail;
+	}
+	adjust_free_extents(ext2_fs, &free_tree);
+	ret = alloc_blocks(&free_tree, blocks, 7, blocksize);
+	if (ret) {
+		goto fail;
 	}
 	super_bytenr = blocks[0];
 	fd = open(devname, O_RDWR);
@@ -2391,17 +2442,9 @@ int do_convert(const char *devname, int datacsum, int packing, int noxattr)
 		fprintf(stderr, "unable to open ctree\n");
 		goto fail;
 	}
-	ret = cache_free_extents(root, ext2_fs);
-	if (ret) {
-		fprintf(stderr, "error during cache_free_extents %d\n", ret);
-		goto fail;
-	}
+	copy_dirtiness(&root->fs_info->free_space_cache, &free_tree);
+	extent_io_tree_cleanup(&free_tree);
 	root->fs_info->extent_ops = &extent_ops;
-	/* recover block allocation bitmap */
-	for (i = 0; i < 7; i++) {
-		blocks[i] /= blocksize;
-		ext2_free_block(ext2_fs, blocks[i]);
-	}
 	ret = init_btrfs(root);
 	if (ret) {
 		fprintf(stderr, "unable to setup the root tree\n");
@@ -2419,11 +2462,12 @@ int do_convert(const char *devname, int datacsum, int packing, int noxattr)
 		fprintf(stderr, "unable to create subvol\n");
 		goto fail;
 	}
-	ret = create_ext2_image(ext2_root, ext2_fs, "image");
+	ret = create_ext2_image(ext2_root, "image", &orig_free_tree);
 	if (ret) {
 		fprintf(stderr, "error during create_ext2_image %d\n", ret);
 		goto fail;
 	}
+	extent_io_tree_cleanup(&orig_free_tree);
 	printf("cleaning up system chunk.\n");
 	ret = cleanup_sys_chunk(root, ext2_root);
 	if (ret) {
Signature · 1 line
1.6.4.4
#1 lore raw
Quoted 5 lines · Sean Bartell

An extent_io_tree is used for all free space information. This allows removal of ext2_alloc_block and ext2_free_block, and makes create_ext2_image less ext2-specific.
---
=A0convert.c | =A0154 +++++++++++++++++++++++++++++++++++++++--------=

--------------

convert.c static int close_ext2fs(ext2_filsys fs) · line 98

Quoted 11 lines

=A01 files changed, 99 insertions(+), 55 deletions(-)

convert.c +0 -1
index d037c98..c48f8ba 100644
@@ -95,29 +95,10 @@ static int close_ext2fs(ext2_filsys fs)
 =A0 =A0 =A0 =A0return 0;
 =A0}
 
-static int ext2_alloc_block(ext2_filsys fs, u64 goal, u64 *block_ret=

)

convert.c static int close_ext2fs(ext2_filsys fs) · line 99

Quoted 2 lines
convert.c +2 -0
+static int ext2_cache_free_extents(ext2_filsys ext2_fs,
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=

struct extent_io_tree *free_tree)

convert.c static int close_ext2fs(ext2_filsys fs) · line 103

Quoted 5 lines
convert.c +0 -4
 =A0{
- =A0 =A0 =A0 blk_t block;
-
- =A0 =A0 =A0 if (!ext2fs_new_block(fs, goal, NULL, &block)) {
- =A0 =A0 =A0 =A0 =A0 =A0 =A0 ext2fs_fast_mark_block_bitmap(fs->block=

_map, block);

Quoted 4 lines
convert.c +0 -4
- =A0 =A0 =A0 =A0 =A0 =A0 =A0 *block_ret =3D block;
- =A0 =A0 =A0 =A0 =A0 =A0 =A0 return 0;
- =A0 =A0 =A0 }
- =A0 =A0 =A0 return -ENOSPC;

convert.c static int close_ext2fs(ext2_filsys fs) · line 117

Quoted 10 lines
convert.c +0 -10
-}
-
-static int ext2_free_block(ext2_filsys fs, u64 block)
-{
- =A0 =A0 =A0 BUG_ON(block !=3D (blk_t)block);
- =A0 =A0 =A0 ext2fs_fast_unmark_block_bitmap(fs->block_map, block);
- =A0 =A0 =A0 return 0;
-}
-
-static int cache_free_extents(struct btrfs_root *root, ext2_filsys e=

xt2_fs)

convert.c static int cache_free_extents(struct btrfs_root=

Quoted 8 lines
convert.c +1 -3
-
-{
- =A0 =A0 =A0 int i, ret =3D 0;
+ =A0 =A0 =A0 int ret =3D 0;
 =A0 =A0 =A0 =A0blk_t block;
 =A0 =A0 =A0 =A0u64 bytenr;
 =A0 =A0 =A0 =A0u64 blocksize =3D ext2_fs->blocksize;
@@ -127,29 +108,68 @@ static int cache_free_extents(struct btrfs_root=

*root, ext2_filsys ext2_fs)

Quoted 1 line

=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (ext2fs_fast_test_block_bitmap(ext2=

_fs->block_map, block))

Quoted 3 lines

=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0continue; =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0bytenr =3D block * blocksize;
- =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D set_extent_dirty(&root->fs_info=

->free_space_cache,

Quoted 1 line

- =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=

=A0 =A0bytenr, bytenr + blocksize - 1, 0);

Quoted 1 line

+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D set_extent_dirty(free_tree, byt=

enr,

Quoted 1 line

+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=

=A0 =A0bytenr + blocksize - 1, 0);

convert.c static int cache_free_extents(struct btrfs_root *root, ext2_filsys ext2_fs)

Quoted 9 lines

=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0BUG_ON(ret);
=A0 =A0 =A0 =A0}

+ =A0 =A0 =A0 return 0;

convert.c +5 -0
+}
+
+/* mark btrfs-reserved blocks as used */
+static void adjust_free_extents(ext2_filsys ext2_fs,
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 struct =

extent_io_tree *free_tree)

convert.c

Quoted 6 lines
convert.c +6 -0
+{
+ =A0 =A0 =A0 int i;
+ =A0 =A0 =A0 u64 bytenr;
+ =A0 =A0 =A0 u64 blocksize =3D ext2_fs->blocksize;
+
+ =A0 =A0 =A0 clear_extent_dirty(free_tree, 0, BTRFS_SUPER_INFO_OFFSE=

T - 1, 0);

Quoted 5 lines

+
=A0 =A0 =A0 =A0for (i =3D 0; i < BTRFS_SUPER_MIRROR_MAX; i++) { =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0bytenr =3D btrfs_sb_offset(i); =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0bytenr &=3D ~((u64)STRIPE_LEN - 1); =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (bytenr >=3D blocksize * ext2_fs->s=

uper->s_blocks_count)

Quoted 2 lines

=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0break;
- =A0 =A0 =A0 =A0 =A0 =A0 =A0 clear_extent_dirty(&root->fs_info->free=

_space_cache, bytenr,

Quoted 1 line

- =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=

bytenr + STRIPE_LEN - 1, 0);

Quoted 1 line

+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 clear_extent_dirty(free_tree, bytenr, b=

ytenr + STRIPE_LEN - 1,

Quoted 1 line

+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=

0);

Quoted 5 lines

=A0 =A0 =A0 =A0}
+}

- =A0 =A0 =A0 clear_extent_dirty(&root->fs_info->free_space_cache,
- =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A00, BTRFS_SUPER_I=

NFO_OFFSET - 1, 0);

convert.c static int cache_free_extents(struct btrfs_root *root, ext2_filsys ext2_fs)

Quoted 3 lines
convert.c +2 -1
-
+static int alloc_blocks(struct extent_io_tree *free_tree,
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 u64 *blocks, int num, u=

64 blocksize)

Quoted 8 lines

+{
+ =A0 =A0 =A0 u64 start;
+ =A0 =A0 =A0 u64 end;
+ =A0 =A0 =A0 u64 last =3D 0;
+ =A0 =A0 =A0 u64 mask =3D blocksize - 1;
+ =A0 =A0 =A0 int ret;
+ =A0 =A0 =A0 while(num) {
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D find_first_extent_bit(free_tree=

, last, &start, &end,

Quoted 1 line

+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=

=A0 =A0 =A0 =A0 EXTENT_DIRTY);

Quoted 5 lines

+ =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 last =3D end + 1;
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (start & mask)
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 start =3D (start & mask=

) + blocksize;

Quoted 6 lines

+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (last - start < blocksize)
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 continue;
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 *blocks++ =3D start;
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 num--;
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 last =3D start + blocksize;
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 clear_extent_dirty(free_tree, start, la=

st - 1, 0);

Quoted 8 lines

+ =A0 =A0 =A0 }
=A0 =A0 =A0 =A0return 0;
+fail:
+ =A0 =A0 =A0 fprintf(stderr, "not enough free space\n");
+ =A0 =A0 =A0 return -ENOSPC;
=A0}

=A0static int custom_alloc_extent(struct btrfs_root *root, u64 num_by=

tes,

Quoted 1 line

=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 u64 hint_=

byte, struct btrfs_key *ins)

convert.c static int custom_alloc_extent(struct btrfs_root =

Quoted 7 lines

=A0{
+ =A0 =A0 =A0 u64 blocksize =3D root->sectorsize;
+ =A0 =A0 =A0 u64 mask =3D blocksize - 1;
=A0 =A0 =A0 =A0u64 start;
=A0 =A0 =A0 =A0u64 end;
=A0 =A0 =A0 =A0u64 last =3D hint_byte;

convert.c +0 -0
@@ -171,6 +191,8 @@ static int custom_alloc_extent(struct btrfs_root =

*root, u64 num_bytes,

convert.c static int custom_alloc_extent(struct btrfs_root = · line 194

Quoted 5 lines
convert.c +2 -0
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0start =3D max(last, start);
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0last =3D end + 1;
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (start & mask)
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 start =3D (start & mask=

) + blocksize;

convert.c static int create_image_file_range(struct btrfs=

Quoted 4 lines
convert.c +0 -0
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (last - start < num_bytes)
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0continue;
 
@@ -1186,9 +1208,9 @@ static int create_image_file_range(struct btrfs=

_trans_handle *trans,

Quoted 1 line

=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 s=

truct btrfs_root *root, u64 objectid,

Quoted 1 line

=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 s=

truct btrfs_inode_item *inode,

Quoted 1 line

=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 u=

64 start_byte, u64 end_byte,

Quoted 1 line

- =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=

ext2_filsys ext2_fs)

Quoted 1 line

+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=

struct extent_io_tree *orig_free_tree)

Quoted 5 lines

=A0{
- =A0 =A0 =A0 u32 blocksize =3D ext2_fs->blocksize;
+ =A0 =A0 =A0 u32 blocksize =3D root->sectorsize;
=A0 =A0 =A0 =A0u32 block =3D start_byte / blocksize;
=A0 =A0 =A0 =A0u32 last_block =3D (end_byte + blocksize - 1) / blocks=

ize;

convert.c static int create_image_file_range(struct btrfs=

Quoted 2 lines

=A0 =A0 =A0 =A0int ret =3D 0;

convert.c +0 -0
@@ -1205,7 +1227,8 @@ static int create_image_file_range(struct btrfs=

_trans_handle *trans,

Quoted 3 lines
convert.c +0 -0
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0.errcode =A0 =A0 =A0 =A0=3D 0,
 =A0 =A0 =A0 =A0};

=A0 =A0 =A0 =A0for (; start_byte < end_byte; block++, start_byte +=3D=

blocksize) {

Quoted 1 line

- =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (!ext2fs_fast_test_block_bitmap(ext2=

_fs->block_map, block))

Quoted 1 line

+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (test_range_bit(orig_free_tree, star=

t_byte,

Quoted 1 line

+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=

start_byte + blocksize, EXTENT_DIRTY, 1))

Quoted 2 lines

=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0continue; =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0ret =3D block_iterate_proc(NULL, block=

, block, &data);

Quoted 6 lines

=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (ret & BLOCK_ABORT) {

convert.c +0 -0
@@ -1234,8 +1257,8 @@ fail:

=A0/*
=A0* Create the ext2fs image file.
=A0*/
-static int create_ext2_image(struct btrfs_root *root, ext2_filsys ex=

t2_fs,

Quoted 1 line

- =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0const char *=

name)

Quoted 1 line

+static int create_ext2_image(struct btrfs_root *root, const char *na=

me,

Quoted 1 line

+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0struct exten=

t_io_tree *orig_free_tree)

Quoted 6 lines

=A0{
=A0 =A0 =A0 =A0int ret;
=A0 =A0 =A0 =A0struct btrfs_key key;

convert.c +0 -0
@@ -1348,7 +1371,7 @@ 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,

Quoted 1 line

=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 =A0&btrfs_inode, last_byte,

Quoted 1 line

- =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 bytenr, ext2_fs);

Quoted 1 line

+ =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 bytenr, orig_free_tree);

Quoted 2 lines

=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;

Quoted 4 lines

=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0}

convert.c +0 -0
@@ -1370,7 +1393,7 @@ next:
 =A0 =A0 =A0 =A0if (total_bytes > last_byte) {

=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0ret =3D create_image_file_range(trans,=

root, objectid,

Quoted 1 line

=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,

Quoted 1 line

- =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=

=A0 =A0 =A0 =A0 =A0 total_bytes, ext2_fs);

Quoted 1 line

+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=

=A0 =A0 =A0 =A0 =A0 total_bytes, orig_free_tree);

convert.c err: · line 2359

Quoted 9 lines

=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}

convert.c +2 -0
@@ -2332,9 +2355,23 @@ err:
 =A0 =A0 =A0 =A0return ret;
 =A0}
 
+static int copy_dirtiness(struct extent_io_tree *out,
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 struct extent_io_tr=

ee *in)

convert.c err: · line 2363

Quoted 4 lines
convert.c +4 -0
+{
+ =A0 =A0 =A0 int ret;
+ =A0 =A0 =A0 u64 start, end, last =3D 0;
+ =A0 =A0 =A0 while (!find_first_extent_bit(in, last, &start, &end, E=

XTENT_DIRTY)) {

convert.c err: · line 2364

Quoted 1 line
convert.c +1 -0
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D set_extent_dirty(out, start, en=

d, 0);

Quoted 8 lines
convert.c +7 -0
+ =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 last =3D end + 1;
+ =A0 =A0 =A0 }
+ =A0 =A0 =A0 return 0;
+}
+

=A0int do_convert(const char *devname, int datacsum, int packing, int=

noxattr)

convert.c int do_convert(const char *devname, int datacs=

Quoted 7 lines

=A0{
- =A0 =A0 =A0 int i, fd, ret;
+ =A0 =A0 =A0 int fd, ret;
=A0 =A0 =A0 =A0u32 blocksize;
=A0 =A0 =A0 =A0u64 blocks[7];
=A0 =A0 =A0 =A0u64 total_bytes;

convert.c +0 -0
@@ -2342,7 +2379,11 @@ int do_convert(const char *devname, int datacs=

um, int packing, int noxattr)

Quoted 11 lines
convert.c +4 -0
 =A0 =A0 =A0 =A0ext2_filsys ext2_fs;
 =A0 =A0 =A0 =A0struct btrfs_root *root;
 =A0 =A0 =A0 =A0struct btrfs_root *ext2_root;
+ =A0 =A0 =A0 struct extent_io_tree free_tree;
+ =A0 =A0 =A0 struct extent_io_tree orig_free_tree;
 
+ =A0 =A0 =A0 extent_io_tree_init(&free_tree);
+ =A0 =A0 =A0 extent_io_tree_init(&orig_free_tree);
 =A0 =A0 =A0 =A0ret =3D open_ext2fs(devname, &ext2_fs);
 =A0 =A0 =A0 =A0if (ret) {

=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0fprintf(stderr, "unable to open the Ex=

t2fs\n");

convert.c int do_convert(const char *devname, int datac=

Quoted 1 line
convert.c +0 -0
@@ -2359,13 +2400,23 @@ int do_convert(const char *devname, int datac=

sum, int packing, int noxattr)

Quoted 1 line

=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0fprintf(stderr, "filetype feature is m=

issing\n");

Quoted 4 lines

=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0goto fail;
=A0 =A0 =A0 =A0}
- =A0 =A0 =A0 for (i =3D 0; i < 7; i++) {
- =A0 =A0 =A0 =A0 =A0 =A0 =A0 ret =3D ext2_alloc_block(ext2_fs, 0, bl=

ocks + i);

Quoted 2 lines

- =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (ret) {
- =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 fprintf(stderr, "not en=

ough free space\n");

Quoted 4 lines

- =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 =A0 blocks[i] *=3D blocksize;
+ =A0 =A0 =A0 ret =3D ext2_cache_free_extents(ext2_fs, &orig_free_tre=

e);

Quoted 2 lines

+ =A0 =A0 =A0 if (ret) {
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 fprintf(stderr, "error during cache_fre=

e_extents %d\n", ret);

Quoted 4 lines

+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto fail;
+ =A0 =A0 =A0 }
+ =A0 =A0 =A0 /* preserve first 64KiB, just in case */
+ =A0 =A0 =A0 clear_extent_dirty(&orig_free_tree, 0, BTRFS_SUPER_INFO=

_OFFSET - 1, 0);

Quoted 4 lines

+
+ =A0 =A0 =A0 ret =3D copy_dirtiness(&free_tree, &orig_free_tree);
+ =A0 =A0 =A0 if (ret) {
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 fprintf(stderr, "error during copy_dirt=

iness %d\n", ret);

convert.c int do_convert(const char *devname, int datacs=

Quoted 10 lines

+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto fail;
+ =A0 =A0 =A0 }
+ =A0 =A0 =A0 adjust_free_extents(ext2_fs, &free_tree);
+ =A0 =A0 =A0 ret =3D alloc_blocks(&free_tree, blocks, 7, blocksize);
+ =A0 =A0 =A0 if (ret) {
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto fail;
=A0 =A0 =A0 =A0}
=A0 =A0 =A0 =A0super_bytenr =3D blocks[0];
=A0 =A0 =A0 =A0fd =3D open(devname, O_RDWR);

convert.c +0 -0
@@ -2391,17 +2442,9 @@ int do_convert(const char *devname, int datacs=

um, int packing, int noxattr)

Quoted 1 line

=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0fprintf(stderr, "unable to open ctree\=

n");

Quoted 5 lines

=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0goto fail;
=A0 =A0 =A0 =A0}
- =A0 =A0 =A0 ret =3D cache_free_extents(root, ext2_fs);
- =A0 =A0 =A0 if (ret) {
- =A0 =A0 =A0 =A0 =A0 =A0 =A0 fprintf(stderr, "error during cache_fre=

e_extents %d\n", ret);

Quoted 3 lines

- =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto fail;
- =A0 =A0 =A0 }
+ =A0 =A0 =A0 copy_dirtiness(&root->fs_info->free_space_cache, &free_=

tree);

Quoted 10 lines

+ =A0 =A0 =A0 extent_io_tree_cleanup(&free_tree);
=A0 =A0 =A0 =A0root->fs_info->extent_ops =3D &extent_ops;
- =A0 =A0 =A0 /* recover block allocation bitmap */
- =A0 =A0 =A0 for (i =3D 0; i < 7; i++) {
- =A0 =A0 =A0 =A0 =A0 =A0 =A0 blocks[i] /=3D blocksize;
- =A0 =A0 =A0 =A0 =A0 =A0 =A0 ext2_free_block(ext2_fs, blocks[i]);
- =A0 =A0 =A0 }
=A0 =A0 =A0 =A0ret =3D init_btrfs(root);
=A0 =A0 =A0 =A0if (ret) {
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0fprintf(stderr, "unable to setup the r=

oot tree\n");

convert.c int do_convert(const char *devname, int datac=

Quoted 1 line
convert.c +0 -0
@@ -2419,11 +2462,12 @@ int do_convert(const char *devname, int datac=

sum, int packing, int noxattr)

Quoted 1 line

=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0fprintf(stderr, "unable to create subv=

ol\n");

Quoted 4 lines

=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0goto fail;
=A0 =A0 =A0 =A0}
- =A0 =A0 =A0 ret =3D create_ext2_image(ext2_root, ext2_fs, "image");
+ =A0 =A0 =A0 ret =3D create_ext2_image(ext2_root, "image", &orig_fre=

e_tree);

extent_io_tree is not very space efficient. caching free space in several places is not good. I prefer adding a function that checks if a given block is used to the 'convert_fs' structure.

Quoted 2 lines

=A0 =A0 =A0 =A0if (ret) {
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0fprintf(stderr, "error during create_e=

xt2_image %d\n", ret);

Quoted 11 lines

=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0goto fail;
=A0 =A0 =A0 =A0}
+ =A0 =A0 =A0 extent_io_tree_cleanup(&orig_free_tree); =A0 =A0 =A0 =A0printf("cleaning up system chunk.\n"); =A0 =A0 =A0 =A0ret =3D cleanup_sys_chunk(root, ext2_root); =A0 =A0 =A0 =A0if (ret) {
--
1.6.4.4

--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs=

" in

Quoted 3 lines

the body of a message to [email protected]
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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#2 lore raw
Quoted 3 lines · Zheng
Quoted 1 line · Sean Bartell

An extent_io_tree is used for all free space information. This allo=

ws

Quoted 4 lines
Quoted 4 lines

removal of ext2_alloc_block and ext2_free_block, and makes create_ext2_image less ext2-specific.

+ =A0 =A0 =A0 ret =3D ext2_cache_free_extents(ext2_fs, &orig_free_t=

ree);

Quoted 2 lines
Quoted 2 lines

+ =A0 =A0 =A0 if (ret) {
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 fprintf(stderr, "error during cache_f=

ree_extents %d\n", ret);

Quoted 4 lines
Quoted 4 lines

+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto fail;
+ =A0 =A0 =A0 }
+ =A0 =A0 =A0 /* preserve first 64KiB, just in case */
+ =A0 =A0 =A0 clear_extent_dirty(&orig_free_tree, 0, BTRFS_SUPER_IN=

=46O_OFFSET - 1, 0);

Quoted 4 lines
Quoted 4 lines

+
+ =A0 =A0 =A0 ret =3D copy_dirtiness(&free_tree, &orig_free_tree);
+ =A0 =A0 =A0 if (ret) {
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 fprintf(stderr, "error during copy_di=

rtiness %d\n", ret);

Quoted 6 lines
Quoted 2 lines

+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 goto fail;
+ =A0 =A0 =A0 }

extent_io_tree is not very space efficient. caching free space in several places is not good. I prefer adding a function that checks if a given block is used to the 'convert_fs' structure.

Good point. I'll change cache_free_extents to something like
int (*iterate_used_extents)(struct convert_fs *fs, u64 start, u64 end=
,

                              void *priv, int (*cb)(u64 start, u64 end)=

)
create_image_file_range and do_convert should work well with a callback= =2E

This also opens up the possibility of finding free extents
incrementally: call iterate_used_extents on the first GB, then custom_alloc_extent will call it on the next GB once free space runs out.
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" = in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html