--- /dev/null
+#! /bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (C) 2022 SUSE Linux Products GmbH. All Rights Reserved.
+#
+# FS QA Test 702
+#
+# Test that if we have two consecutive extents and only one of them is cloned,
+# then fiemap correctly reports which one is shared and reports the other as not
+# shared.
+#
+. ./common/preamble
+_begin_fstest auto quick clone fiemap
+
+. ./common/filter
+. ./common/reflink
+
+_fixed_by_kernel_commit ac3c0d36a2a2f7 \
+ "btrfs: make fiemap more efficient and accurate reporting extent sharedness"
+
+_supported_fs generic
+_require_scratch_reflink
+_require_xfs_io_command "fiemap"
+
+fiemap_test_file()
+{
+ local filepath=$1
+
+ # Skip the first two lines of xfs_io's fiemap output (file path and
+ # header describing the output columns).
+ #
+ # Print the first column (extent number), second column (file range),
+ # fourth column (extent size) and fifth column (flags) of the fiemap
+ # output.
+ #
+ # We filter the flags column to only tell us if an extent is shared or
+ # not (flag 0x2000, which matches FIEMAP_EXTENT_SHARED) because on some
+ # filesystem configs we may have other flags printed - for example
+ # running btrfs with "-o compress" we get the flag 0x8 as well (which
+ # is FIEMAP_EXTENT_ENCODED).
+ #
+ # The third column is the physical location of the extents, so it's
+ # omitted because the location varies between different filesystems.
+ #
+ $XFS_IO_PROG -c "fiemap -v" $filepath | tail -n +3 | \
+ $AWK_PROG '{ print $1, $2, $4, \
+ and(strtonum($5), 0x2000) ? "shared" : "not_shared" }'
+}
+
+_scratch_mkfs >> $seqres.full
+_scratch_mount
+
+# We create 128K extents in the test files below.
+_require_congruent_file_oplen $SCRATCH_MNT $((128 * 1024))
+
+# Create file foo with 2 consecutive extents, each one with a size of 128K.
+echo "Creating file foo"
+$XFS_IO_PROG -f -c "pwrite -b 128K 0 128K" -c "fsync" \
+ -c "pwrite -b 128K 128K 128K" -c "fsync" \
+ $SCRATCH_MNT/foo | _filter_xfs_io
+
+# Clone only the first extent into another file.
+echo "Cloning first extent of file foo to file bar"
+$XFS_IO_PROG -f -c "reflink $SCRATCH_MNT/foo 0 0 128K" $SCRATCH_MNT/bar | \
+ _filter_xfs_io
+
+# Now fiemap file foo, it should report the first 128K extent as shared and the
+# second 128K extent as not shared.
+echo "fiemap of file foo:"
+fiemap_test_file $SCRATCH_MNT/foo
+
+# Now do a similar test as above, except that this time only the second 128K
+# extent is cloned, the first extent is not cloned.
+
+# Create file foo2 with 2 consecutive extents, each one with a size of 128K.
+echo "Creating file foo2"
+$XFS_IO_PROG -f -c "pwrite -b 128K 0 128K" -c "fsync" \
+ -c "pwrite -b 128K 128K 128K" -c "fsync" \
+ $SCRATCH_MNT/foo2 | _filter_xfs_io
+
+# Clone only the second extent of foo2 into another file.
+echo "Cloning second extent of file foo2 to file bar2"
+$XFS_IO_PROG -f -c "reflink $SCRATCH_MNT/foo2 128K 0 128K" $SCRATCH_MNT/bar2 | \
+ _filter_xfs_io
+
+# Now fiemap file foo2, it should report the first 128K extent as not shared and
+# the second 128K extent as shared
+echo "fiemap of file foo2:"
+fiemap_test_file $SCRATCH_MNT/foo2
+
+# success, all done
+status=0
+exit
--- /dev/null
+QA output created by 702
+Creating file foo
+wrote 131072/131072 bytes at offset 0
+XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 131072/131072 bytes at offset 131072
+XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+Cloning first extent of file foo to file bar
+linked 131072/131072 bytes at offset 0
+XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+fiemap of file foo:
+0: [0..255]: 256 shared
+1: [256..511]: 256 not_shared
+Creating file foo2
+wrote 131072/131072 bytes at offset 0
+XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+wrote 131072/131072 bytes at offset 131072
+XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+Cloning second extent of file foo2 to file bar2
+linked 131072/131072 bytes at offset 0
+XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+fiemap of file foo2:
+0: [0..255]: 256 not_shared
+1: [256..511]: 256 shared