blob: ce949b1157f10ad3a2a9d251d001b0bbe8bb039e [file] [log] [blame]
#! /bin/bash
# SPDX-License-Identifier: GPL-2.0
# Copyright (C) 2022 SUSE Linux Products GmbH. All Rights Reserved.
#
# FS QA Test 260
#
# Make sure "btrfs filesystem defragment" can still convert the compression
# algorithm of all regular extents.
#
. ./common/preamble
_begin_fstest auto quick defrag compress prealloc fiemap
# Override the default cleanup function.
# _cleanup()
# {
# cd /
# rm -r -f $tmp.*
# }
. ./common/filter
_require_scratch
_require_xfs_io_command "fiemap" "ranged"
_require_xfs_io_command "falloc"
_require_btrfs_command inspect-internal dump-tree
get_inode_number()
{
local file="$1"
stat -c "%i" "$file"
}
get_file_extent()
{
local file="$1"
local offset="$2"
local ino=$(get_inode_number "$file")
local file_extent_key="($ino EXTENT_DATA $offset)"
$BTRFS_UTIL_PROG inspect-internal dump-tree -t 5 $SCRATCH_DEV |\
grep -A4 "$file_extent_key"
}
check_file_extent()
{
local file="$1"
local offset="$2"
local expected="$3"
echo "=== file extent at file '$file' offset $offset ===" >> $seqres.full
get_file_extent "$file" "$offset" > $tmp.output
cat $tmp.output >> $seqres.full
grep -q "$expected" $tmp.output ||\
echo "file \"$file\" offset $offset doesn't have expected string \"$expected\""
}
# Unlike file extents whose btrfs specific attributes need to be grabbed from
# dump-tree, we can check holes by fiemap. And mkfs enables no-holes feature by
# default in recent versions of btrfs-progs, preventing us from grabbing holes
# from dump-tree.
check_hole()
{
local file="$1"
local offset="$2"
local len="$3"
output=$($XFS_IO_PROG -c "fiemap $offset $len" "$file" |\
_filter_xfs_io_fiemap | head -n1)
if [ -z $output ]; then
echo "=== file extent at file '$file' offset $offset is a hole ===" \
>> $seqres.full
else
echo "=== file extent at file '$file' offset $offset is not a hole ==="
fi
}
# Needs 4K sectorsize as the test is crafted using that sectorsize
_require_btrfs_support_sectorsize 4096
_scratch_mkfs -s 4k >> $seqres.full 2>&1
# Initial data is compressed using lzo
_scratch_mount -o compress=lzo
# file 'large' has all of its compressed extents at their maximum size
$XFS_IO_PROG -f -c "pwrite 0 1m" "$SCRATCH_MNT/large" >> $seqres.full
# file 'fragment' has all of its compressed extents adjacent to
# preallocated/hole ranges, which should not be defragged with regular
# defrag ioctl, but should still be defragged by
# "btrfs filesystem defragment -c"
$XFS_IO_PROG -f -c "pwrite 0 16k" \
-c "pwrite 32k 16k" -c "pwrite 64k 16k" \
"$SCRATCH_MNT/fragment" >> $seqres.full
sync
# We only do the falloc after the compressed data reached disk.
# Or the inode could have PREALLOC flag, and prevent the
# data from being compressed.
$XFS_IO_PROG -c "falloc 16k 16k" "$SCRATCH_MNT/fragment"
sync
echo "====== Before the defrag ======" >> $seqres.full
# Should be lzo compressed
check_file_extent "$SCRATCH_MNT/large" 0 "compression 2"
# Should be lzo compressed
check_file_extent "$SCRATCH_MNT/fragment" 0 "compression 2"
# Should be preallocated
check_file_extent "$SCRATCH_MNT/fragment" 16384 "type 2"
# Should be lzo compressed
check_file_extent "$SCRATCH_MNT/fragment" 32768 "compression 2"
# Should be hole
check_hole "$SCRATCH_MNT/fragment" 49152 16384
# Should be lzo compressed
check_file_extent "$SCRATCH_MNT/fragment" 65536 "compression 2"
$BTRFS_UTIL_PROG filesystem defragment "$SCRATCH_MNT/large" -czstd \
"$SCRATCH_MNT/fragment" >> $seqres.full
# Need to commit the transaction or dump-tree won't grab the new
# metadata on-disk.
sync
echo "====== After the defrag ======" >> $seqres.full
# Should be zstd compressed
check_file_extent "$SCRATCH_MNT/large" 0 "compression 3"
# Should be zstd compressed
check_file_extent "$SCRATCH_MNT/fragment" 0 "compression 3"
# Should be preallocated
check_file_extent "$SCRATCH_MNT/fragment" 16384 "type 2"
# Should be zstd compressed
check_file_extent "$SCRATCH_MNT/fragment" 32768 "compression 3"
# Should be hole
check_hole "$SCRATCH_MNT/fragment" 49152 16384
# Should be zstd compressed
check_file_extent "$SCRATCH_MNT/fragment" 65536 "compression 3"
echo "Silence is golden"
# success, all done
status=0
exit