mbox series

[0/3] btrfs-progs: convert: proper ext4 unwritten extents handling

Message ID cover.1715051693.git.wqu@suse.com (mailing list archive)
Headers show
Series btrfs-progs: convert: proper ext4 unwritten extents handling | expand

Message

Qu Wenruo May 7, 2024, 3:22 a.m. UTC
[REPO]
https://github.com/adam900710/btrfs-progs/tree/unwritten_extent

There is a bug report that ext4 unwritten extents (extent with
EXT2_EXTENT_FLAGS_UNINIT, acts the same as BTRFS_FILE_EXTENT_PREALLOC)
would result a regular btrfs file extent.

Instead of filling the range with zero, converted btrfs would read
whatever from the disk, causing corruption.

Although there are some attempts trying to fix the problem, the resulted
patches are not meeting our standard, so I have to come up a fix by
myself.

The root cause is that, ext2fs_block_iterate2() won't report any extent
info, thus it's more or less only useful for ext2 filesystems.
For ext4 filesystems, inodes can have a feature called EXT4_EXTENTS_FL,
allowing a proper extent based iteratioin.

So this patch would keep the old ext2fs_block_iterate2() as fallback (as
for older ext2 fses, they do not support fallocate anyway), while for
newer ext4 fses, go with ect2fs_extent_*() APIs to iterate the file
extents.

The new APIs provides the extra extent.e_flags to indicate whether the
extent is unwritten or not.
For unwritten extents, we just puch it as a hole for now, since even if
we create a correct preallocated file extent, the space can not be
utlized as it's shared between the file extent and ext2 image.

So just punching a hole would be the simplest workaround for now.

Qu Wenruo (3):
  Revert "btrfs-progs: convert: add raid-stripe-tree to allowed
    features"
  btrfs-progs: convert: rework file extent iteration to handle unwritten
    extents
  btrfs-progs: tests/convert: add test case for ext4 unwritten extents

 common/fsfeatures.h                           |   3 +-
 convert/source-ext2.c                         | 116 ++++++++++++++++--
 tests/common.convert                          |  44 ++-----
 tests/convert-tests/001-ext2-basic/test.sh    |   2 +-
 tests/convert-tests/003-ext4-basic/test.sh    |   2 +-
 .../005-delete-all-rollback/test.sh           |   6 +-
 .../convert-tests/010-reiserfs-basic/test.sh  |   2 +-
 .../011-reiserfs-delete-all-rollback/test.sh  |   6 +-
 tests/convert-tests/024-ntfs-basic/test.sh    |   2 +-
 .../025-ext4-uninit-written/test.sh           |  53 ++++++++
 10 files changed, 177 insertions(+), 59 deletions(-)
 create mode 100755 tests/convert-tests/025-ext4-uninit-written/test.sh

--
2.45.0

Comments

David Sterba June 3, 2024, 8:14 p.m. UTC | #1
On Tue, May 07, 2024 at 12:52:52PM +0930, Qu Wenruo wrote:
> [REPO]
> https://github.com/adam900710/btrfs-progs/tree/unwritten_extent
> 
> There is a bug report that ext4 unwritten extents (extent with
> EXT2_EXTENT_FLAGS_UNINIT, acts the same as BTRFS_FILE_EXTENT_PREALLOC)
> would result a regular btrfs file extent.
> 
> Instead of filling the range with zero, converted btrfs would read
> whatever from the disk, causing corruption.
> 
> Although there are some attempts trying to fix the problem, the resulted
> patches are not meeting our standard, so I have to come up a fix by
> myself.
> 
> The root cause is that, ext2fs_block_iterate2() won't report any extent
> info, thus it's more or less only useful for ext2 filesystems.
> For ext4 filesystems, inodes can have a feature called EXT4_EXTENTS_FL,
> allowing a proper extent based iteratioin.
> 
> So this patch would keep the old ext2fs_block_iterate2() as fallback (as
> for older ext2 fses, they do not support fallocate anyway), while for
> newer ext4 fses, go with ect2fs_extent_*() APIs to iterate the file
> extents.
> 
> The new APIs provides the extra extent.e_flags to indicate whether the
> extent is unwritten or not.
> For unwritten extents, we just puch it as a hole for now, since even if
> we create a correct preallocated file extent, the space can not be
> utlized as it's shared between the file extent and ext2 image.
> 
> So just punching a hole would be the simplest workaround for now.
> 
> Qu Wenruo (3):
>   Revert "btrfs-progs: convert: add raid-stripe-tree to allowed
>     features"
>   btrfs-progs: convert: rework file extent iteration to handle unwritten
>     extents
>   btrfs-progs: tests/convert: add test case for ext4 unwritten extents

Added to devel, thanks.