Add move-blocks test

Add a basic test of the move_blocks ioctl.

Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
Zach Brown
2021-01-06 10:59:14 -08:00
parent eb3981c103
commit 773eb129ed
3 changed files with 203 additions and 0 deletions

33
tests/golden/move-blocks Normal file
View File

@@ -0,0 +1,33 @@
== build test files
== wrapped offsets should fail
ioctl failed on '/mnt/test/test/move-blocks/to': Value too large for defined data type (75)
scoutfs: move-blocks failed: Value too large for defined data type (75)
ioctl failed on '/mnt/test/test/move-blocks/to': Value too large for defined data type (75)
scoutfs: move-blocks failed: Value too large for defined data type (75)
== specifying same file fails
ioctl failed on '/mnt/test/test/move-blocks/hardlink': Invalid argument (22)
scoutfs: move-blocks failed: Invalid argument (22)
== specifying files in other file systems fails
ioctl failed on '/mnt/test/test/move-blocks/to': Invalid cross-device link (18)
scoutfs: move-blocks failed: Invalid cross-device link (18)
== offsets must be multiples of 4KB
ioctl failed on '/mnt/test/test/move-blocks/to': Invalid argument (22)
scoutfs: move-blocks failed: Invalid argument (22)
ioctl failed on '/mnt/test/test/move-blocks/to': Invalid argument (22)
scoutfs: move-blocks failed: Invalid argument (22)
ioctl failed on '/mnt/test/test/move-blocks/to': Invalid argument (22)
scoutfs: move-blocks failed: Invalid argument (22)
== can't move onto existing extent
ioctl failed on '/mnt/test/test/move-blocks/to': Invalid argument (22)
scoutfs: move-blocks failed: Invalid argument (22)
== can't move between files with offline extents
ioctl failed on '/mnt/test/test/move-blocks/to': No data available (61)
scoutfs: move-blocks failed: No data available (61)
ioctl failed on '/mnt/test/test/move-blocks/to': No data available (61)
scoutfs: move-blocks failed: No data available (61)
== basic moves work
== moving final partial block sets partial i_size
123
== moving updates inode fields
== moving blocks backwards works
== combine many files into one

View File

@@ -6,6 +6,7 @@ simple-staging.sh
simple-release-extents.sh
setattr_more.sh
offline-extent-waiting.sh
move-blocks.sh
srch-basic-functionality.sh
simple-xattr-unit.sh
lock-refleak.sh

169
tests/tests/move-blocks.sh Normal file
View File

@@ -0,0 +1,169 @@
#
# test MOVE_BLOCKS ioctl, mostly basic error testing and functionality,
# but a bit of expected use.
#
t_require_commands scoutfs dd
FROM="$T_D0/from"
TO="$T_D0/to"
HARD="$T_D0/hardlink"
OTHER="$T_TMP.other"
BLOCKS=8
BS=4096
PART=123
LEN=$(((BS * BLOCKS) + PART))
PIECES=8
regenerate_files() {
rm -f "$FROM"
rm -f "$TO"
dd if=/dev/urandom of="$FROM" bs=$LEN count=1 status=none
touch "$TO"
}
set_updated_fields() {
local arr="$1"
local path="$2"
eval $arr["ctime"]="$(stat -c '%Z' "$path")"
eval $arr["mtime"]="$(stat -c '%Y' "$path")"
eval $arr["data_version"]="$(scoutfs stat -s data_version "$path")"
eval $arr["meta_seq"]="$(scoutfs stat -s meta_seq "$path")"
eval $arr["data_seq"]="$(scoutfs stat -s data_seq "$path")"
}
#
# before moving extents manually copy the byte regions so that we have
# expected good file contents to compare to. We know that the byte
# regions are 4KB block aligned (with an allowance for a len that ends
# on from i_size).
#
move_and_compare() {
local from="$1"
local from_off="$2"
local from_blk="$((from_off / BS))"
local len="$3"
local blocks="$(((len + BS - 1) / BS))"
local to="$4"
local to_off="$5"
local to_blk="$((to_off / BS))"
local right_start=$((from_blk + blocks))
local from_size=$(stat -c "%s" "$from")
local from_blocks=$(( (from_size + BS - 1) / BS ))
local right_len=$((from_blocks - right_start))
# copying around instead of punching hole
dd if="$from" of="$from.expected" bs="$BS" \
skip=0 seek=0 count="$from_blk" \
status=none
dd if="$from" of="$from.expected" bs="$BS" \
skip="$right_start" seek="$right_start" count="$right_len" \
status=none conv=notrunc
# moving doesn't truncate, expect full size when no data
truncate -s "$from_size" "$from.expected"
cp "$to" "$to.expected"
dd if="$from" of="$to.expected" bs="$BS" \
skip="$from_blk" seek="$to_blk" count="$blocks" \
status=none conv=notrunc
scoutfs move-blocks "$from" -f "$from_off" -l "$len" "$to" -t "$to_off" \
2>&1 | t_filter_fs
cmp "$from" "$from.expected"
cmp "$to" "$to.expected"
}
echo "== build test files"
regenerate_files
touch "$OTHER"
ln "$FROM" "$HARD"
echo "== wrapped offsets should fail"
HUGE=0x8000000000000000
scoutfs move-blocks "$FROM" -f "$HUGE" -l "$HUGE" "$TO" -t 0 2>&1 | t_filter_fs
scoutfs move-blocks "$FROM" -f 0 -l "$HUGE" "$TO" -t "$HUGE" 2>&1 | t_filter_fs
echo "== specifying same file fails"
scoutfs move-blocks "$FROM" -f 0 -l "$BS" "$HARD" -t 0 2>&1 | t_filter_fs
echo "== specifying files in other file systems fails"
scoutfs move-blocks "$OTHER" -f 0 -l "$BS" "$TO" -t 0 2>&1 | t_filter_fs
echo "== offsets must be multiples of 4KB"
scoutfs move-blocks "$FROM" -f 1 -l "$BS" "$TO" -t 0 2>&1 | t_filter_fs
scoutfs move-blocks "$FROM" -f 0 -l 1 "$TO" -t 0 2>&1 | t_filter_fs
scoutfs move-blocks "$FROM" -f 0 -l "$BS" "$TO" -t 1 2>&1 | t_filter_fs
echo "== can't move onto existing extent"
dd if=/dev/urandom of="$TO" bs=$BS count=1 status=none
scoutfs move-blocks "$FROM" -f 0 -l "$BS" "$TO" -t 0 2>&1 | t_filter_fs
echo "== can't move between files with offline extents"
dd if=/dev/zero of="$TO" bs=$BS count=1 status=none
vers=$(scoutfs stat -s data_version "$TO")
scoutfs release "$TO" -V "$vers" -o 0 -l $BS
scoutfs move-blocks "$FROM" -f 0 -l "$BS" "$TO" -t 0 2>&1 | t_filter_fs
regenerate_files
vers=$(scoutfs stat -s data_version "$FROM")
scoutfs release "$FROM" -V "$vers" -o 0 -l $BS
scoutfs move-blocks "$FROM" -f 0 -l "$BS" "$TO" -t 0 2>&1 | t_filter_fs
regenerate_files
echo "== basic moves work"
move_and_compare "$FROM" 0 "$BS" "$TO" 0
regenerate_files
move_and_compare "$FROM" 0 "$BS" "$TO" "$BS"
regenerate_files
move_and_compare "$FROM" 0 "$LEN" "$TO" 0
regenerate_files
echo "== moving final partial block sets partial i_size"
move_and_compare "$FROM" $((LEN - PART)) "$PART" "$TO" 0
stat -c '%s' "$TO"
regenerate_files
echo "== moving updates inode fields"
declare -A from_before from_after to_before to_after
set_updated_fields from_before "$FROM"
set_updated_fields to_before "$TO"
t_quiet sync
sleep 1
move_and_compare "$FROM" 0 "$BS" "$TO" 0
set_updated_fields from_after "$FROM"
set_updated_fields to_after "$TO"
for k in ${!from_after[@]}; do
if [ "${from_before[$k]}" == "${from_after[$k]}" ]; then
echo "move didn't change from $k ${from_before[$k]}"
fi
if [ "${to_before[$k]}" == "${to_after[$k]}" ]; then
echo "move didn't change to $k ${to_before[$k]}"
fi
done
regenerate_files
echo "== moving blocks backwards works"
cp "$FROM" "$FROM.orig"
move_and_compare "$FROM" $((LEN - PART)) "$PART" "$TO" $((LEN - PART))
for i in $(seq $((BLOCKS - 1)) -1 0); do
move_and_compare "$FROM" $((i * BS)) "$BS" "$TO" $((i * BS))
done
cmp "$TO" "$FROM.orig"
regenerate_files
echo "== combine many files into one"
for i in $(seq 0 $((PIECES - 1))); do
dd if=/dev/urandom of="$FROM.$i" bs=$BS count=$BLOCKS status=none
cat "$FROM.$i" >> "$TO.large"
move_and_compare "$FROM.$i" 0 "$((BS * BLOCKS))" \
"$TO" $((i * BS * BLOCKS))
done
((i++))
cat "$FROM" >> "$TO.large"
move_and_compare "$FROM" 0 "$LEN" "$TO" $((i * BS * BLOCKS))
cmp "$TO.large" "$TO"
t_pass