From: Filipe Manana <fdmanana@xxxxxxxx> In upcoming changes there will be the need to find out the logical disk address (bytenr) that a particular file extent item points to. This is already implemented as local functions in the test btrfs/299, which is a bit limited but works fine for that test. Some important or subtle details why it works for this test: 1) It dumps all trees of the filesystem; 2) It relies on fsync'ing a file and then finding the desired file extent item in the log tree from the dump; 3) There's a single subvolume, so it always finds the correct file extent item. In case there were multiple subvolumes, it could pick the wrong file extent item in case we have inodes with the same number on multiple subvolumes (inode numbers are unique only within a subvolume, they are not unique across an entire filesystem). So add a helper to get the bytenr associated to a file extent item to common/btrfs and use it at btrfs/299 and the upcoming changes. This helper will dump only the tree of the default subvolume, will sync the filesystem to commit any open transaction and works only in case the filesystem is using the scratch device. This is explicitly documented. Signed-off-by: Filipe Manana <fdmanana@xxxxxxxx> --- common/btrfs | 23 +++++++++++++++++++++++ tests/btrfs/299 | 18 +----------------- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/common/btrfs b/common/btrfs index 344509ce..42777df2 100644 --- a/common/btrfs +++ b/common/btrfs @@ -624,3 +624,26 @@ _require_btrfs_send_v2() [ $(cat /sys/fs/btrfs/features/send_stream_version) -gt 1 ] || \ _notrun "kernel does not support send stream v2" } + +# Get the bytenr associated to a file extent item at a given file offset. +# +# NOTE: At the moment this only works if the file is on a filesystem on top of +# the scratch device and the file is in the default subvolume (tree id 5). +_btrfs_get_file_extent_item_bytenr() +{ + local file="$1" + local offset="$2" + local ino=$(stat -c "%i" "$file") + local file_extent_key="($ino EXTENT_DATA $offset)" + + _require_btrfs_command inspect-internal dump-tree + + # The tree dump command below works on committed roots, by reading from + # a device directly, so we have to sync the filesystem to commit any + # open transaction. + $BTRFS_UTIL_PROG filesystem sync $SCRATCH_MNT + + $BTRFS_UTIL_PROG inspect-internal dump-tree -t 5 $SCRATCH_DEV | \ + grep -A4 "$file_extent_key" | grep "disk byte" | \ + $AWK_PROG '{ print $5 }' +} diff --git a/tests/btrfs/299 b/tests/btrfs/299 index 8ed23ac5..2ac05957 100755 --- a/tests/btrfs/299 +++ b/tests/btrfs/299 @@ -22,25 +22,10 @@ _begin_fstest auto quick preallocrw _supported_fs btrfs _require_scratch _require_xfs_io_command "falloc" "-k" -_require_btrfs_command inspect-internal dump-tree _require_btrfs_command inspect-internal logical-resolve _fixed_by_kernel_commit 560840afc3e6 \ "btrfs: fix resolving backrefs for inline extent followed by prealloc" -dump_tree() { - $BTRFS_UTIL_PROG inspect-internal dump-tree $SCRATCH_DEV -} - -get_extent_data() { - local ino=$1 - dump_tree $SCRATCH_DEV | grep -A4 "($ino EXTENT_DATA " -} - -get_prealloc_offset() { - local ino=$1 - get_extent_data $ino | grep "disk byte" | $AWK_PROG '{print $5}' -} - # This test needs to create conditions s.t. the special inode's inline extent # is the first item in a leaf. Therefore, fix a leaf size and add # items that are otherwise not necessary to reproduce the inline-prealloc @@ -81,8 +66,7 @@ done # grab the prealloc offset from dump tree while it's still the only # extent data item for the inode -ino=$(stat -c '%i' $f.evil) -logical=$(get_prealloc_offset $ino) +logical=$(_btrfs_get_file_extent_item_bytenr $f.evil 0) # do the "small write; fsync; small write" pattern which reproduces the desired # item pattern of an inline extent followed by a preallocated extent. The 23 -- 2.35.1