btrfs-convert: make more use of cache_free_extents
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
@@ -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
Quoted 5 lines · Sean Bartell
An
extent_io_treeis used for all free space information. This allows removal ofext2_alloc_blockandext2_free_block, and makescreate_ext2_imageless 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@@ -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 =3Dbtrfs_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 =A0fprintf(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 =3Droot->sectorsize;
+ =A0 =A0 =A0 u64 mask =3D blocksize - 1;
=A0 =A0 =A0 =A0u64 start;
=A0 =A0 =A0 =A0u64 end;
=A0 =A0 =A0 =A0u64 last =3Dhint_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 =3Dext2_fs->blocksize;
+ =A0 =A0 =A0 u32 blocksize =3Droot->sectorsize;
=A0 =A0 =A0 =A0u32 block =3Dstart_byte/ blocksize;
=A0 =A0 =A0 =A0u32last_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(structbtrfs_root*root,ext2_filsysex=
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 =A0structbtrfs_keykey;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 =A0u64total_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 =3Dcopy_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 =A0adjust_free_extents(ext2_fs, &free_tree);
+ =A0 =A0 =A0 ret =3Dalloc_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 =3Dopen(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 =3Dcache_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 =A0ext2_free_block(ext2_fs, blocks[i]);
- =A0 =A0 =A0 }
=A0 =A0 =A0 =A0ret =3Dinit_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 =3Dcreate_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 =A0extent_io_tree_cleanup(&orig_free_tree); =A0 =A0 =A0 =A0printf("cleaning up system chunk.\n"); =A0 =A0 =A0 =A0ret =3Dcleanup_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
Quoted 3 lines · Zheng
Quoted 1 line · Sean Bartell
An
extent_io_treeis used for all free space information. This allo=
ws
Quoted 4 lines
Quoted 4 lines
removal of
ext2_alloc_blockandext2_free_block, and makescreate_ext2_imageless 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 =3Dcopy_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_treeis 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