Files
scoutfs/tests/tests/basic-posix-consistency.sh
Auke Kok 8a4b0967cb Add fiemap output through scoutfs util.
There's filefrag already, and that works, but, it's output is very
inconsistent between various OS release versions, and it has already
meant that we'd needed to adjust tests to account for these little
but insignificant changes. A lot more work than useful. It's even
more changed in el9.

This adds `scoutfs get-fiemap FILE` and prints out block extent
info with flags that we care about as an abbreviated letter: U for
Unwritten, L for Last, and O for Unknown (as in, "offline").

The -P/--physical and -L/--logical options turn off logical or physical
offset display, in case you only want to see the offsets in either
units. You can pass -b/--byte to display offsets and lengths in
byte values. The block size will then be obtained from fstat() of
the queried file (4096 for scoutfs).

I've removed all uses of filefrag from our scoutfs tests. Xfstests
still calls it but their internal diff takes care of that issue.

Where needed and appropriate, the tests are adjusted so that the output
of `scoutfs get-fiemap` is as close as it can to what it used to be,
so that reading the test results allows the quick view of what might
have been going wrong.

There are some output strings I have not bothered to update because
there's no real value to updating every output string to match,
and we just adjust the golden file accordingly.

Signed-off-by: Auke Kok <auke.kok@versity.com>
2024-10-03 15:38:34 -07:00

217 lines
6.6 KiB
Bash

#
# Test basic clustered posix consistency. We perform a bunch of
# operations in one mount and verify the results in another.
#
t_require_commands getfattr setfattr dd diff touch stat scoutfs
t_require_mounts 2
GETFATTR="getfattr --absolute-names"
SETFATTR="setfattr"
DD="dd status=none"
FIEMAP="scoutfs get-fiemap"
echo "== root inode updates flow back and forth"
sleep 1
touch "$T_M1"
stat "$T_M0" 2>&1 | t_filter_fs > "$T_TMP.0"
stat "$T_M1" 2>&1 | t_filter_fs > "$T_TMP.1"
diff -u "$T_TMP.0" "$T_TMP.1"
sleep 1
touch "$T_M0"
stat "$T_M0" 2>&1 | t_filter_fs > "$T_TMP.0"
stat "$T_M1" 2>&1 | t_filter_fs > "$T_TMP.1"
diff -u "$T_TMP.0" "$T_TMP.1"
echo "== stat of created file matches"
touch "$T_D0/file"
stat "$T_D0/file" 2>&1 | t_filter_fs > "$T_TMP.0"
stat "$T_D1/file" 2>&1 | t_filter_fs > "$T_TMP.1"
diff -u "$T_TMP.0" "$T_TMP.1"
echo "== written file contents match"
$DD if=/dev/urandom of="$T_D0/file" bs=4K count=1024
od -x "$T_D0/file" > "$T_TMP.0"
od -x "$T_D1/file" > "$T_TMP.1"
diff -u "$T_TMP.0" "$T_TMP.1"
echo "== overwritten file contents match"
$DD if=/dev/urandom of="$T_D0/file" bs=4K count=1024 conv=notrunc
od -x "$T_D0/file" > "$T_TMP.0"
od -x "$T_D1/file" > "$T_TMP.1"
diff -u "$T_TMP.0" "$T_TMP.1"
echo "== appended file contents match"
$DD if=/dev/urandom of="$T_D0/file" bs=1 count=1 conv=notrunc oflag=append
od -x "$T_D0/file" > "$T_TMP.0"
od -x "$T_D1/file" > "$T_TMP.1"
diff -u "$T_TMP.0" "$T_TMP.1"
echo "== fiemap matches after racey appends"
for i in $(seq 1 10); do
$DD if=/dev/urandom of="$T_D0/file" bs=4096 count=1 \
conv=notrunc oflag=append &
$DD if=/dev/urandom of="$T_D1/file" bs=4096 count=1 \
conv=notrunc oflag=append &
wait
done
$FIEMAP "$T_D0/file" > "$T_TMP.0"
$FIEMAP "$T_D1/file" > "$T_TMP.1"
diff -u "$T_TMP.0" "$T_TMP.1"
echo "== unlinked file isn't found"
rm -f "$T_D0/file"
stat "$T_D0/file" 2>&1 | t_filter_fs > "$T_TMP.0"
stat "$T_D1/file" 2>&1 | t_filter_fs > "$T_TMP.1"
diff -u "$T_TMP.0" "$T_TMP.1"
echo "== symlink targets match"
ln -s "$T_D0/file.targ" "$T_D0/file"
readlink "$T_D0/file" | t_filter_fs
readlink "$T_D1/file" | t_filter_fs
rm -f "$T_D1/file"
ln -s "$T_D0/file.targ2" "$T_D0/file"
readlink "$T_D0/file" | t_filter_fs
readlink "$T_D1/file" | t_filter_fs
rm -f "$T_D1/file"
echo "== new xattrs are visible"
touch "$T_D0/file"
$SETFATTR -n user.xat -v 1 "$T_D0/file"
$GETFATTR -n user.xat "$T_D0/file" 2>&1 | t_filter_fs
$GETFATTR -n user.xat "$T_D1/file" 2>&1 | t_filter_fs
echo "== modified xattrs are updated"
$SETFATTR -n user.xat -v 2 "$T_D1/file"
$GETFATTR -n user.xat "$T_D0/file" 2>&1 | t_filter_fs
$GETFATTR -n user.xat "$T_D1/file" 2>&1 | t_filter_fs
echo "== deleted xattrs"
$SETFATTR -x user.xat "$T_D0/file"
$GETFATTR -n user.xat "$T_D0/file" 2>&1 | t_filter_fs
$GETFATTR -n user.xat "$T_D1/file" 2>&1 | t_filter_fs
rm -f "$T_D1/file"
echo "== readdir after modification"
mkdir "$T_D0/dir"
ls -UA "$T_D0/dir"
ls -UA "$T_D1/dir"
touch "$T_D1/dir"/{one,two,three,four}
ls -UA "$T_D0/dir"
ls -UA "$T_D1/dir"
rm -f "$T_D0/dir"/{one,three}
ls -UA "$T_D0/dir"
ls -UA "$T_D1/dir"
rm -f "$T_D0/dir"/{two,four}
ls -UA "$T_D0/dir"
ls -UA "$T_D1/dir"
echo "== can delete empty dir"
rmdir "$T_D1/dir"
echo "== some easy rename cases"
echo "--- file between dirs"
mkdir -p "$T_D0/dir/a"
mkdir -p "$T_D0/dir/b"
touch "$T_D0/dir/a/file"
mv "$T_D1/dir/a/file" "$T_D1/dir/b/file"
find "$T_D0/dir" -ls 2>&1 | t_filter_fs > "$T_TMP.0"
find "$T_D1/dir" -ls 2>&1 | t_filter_fs > "$T_TMP.1"
diff -u "$T_TMP.0" "$T_TMP.1"
echo "--- file within dir"
mv "$T_D1/dir/b/file" "$T_D1/dir/b/file2"
find "$T_D0/dir" -ls 2>&1 | t_filter_fs > "$T_TMP.0"
find "$T_D1/dir" -ls 2>&1 | t_filter_fs > "$T_TMP.1"
diff -u "$T_TMP.0" "$T_TMP.1"
echo "--- dir within dir"
mv "$T_D0/dir/b" "$T_D0/dir/c"
find "$T_D0/dir" -ls 2>&1 | t_filter_fs > "$T_TMP.0"
find "$T_D1/dir" -ls 2>&1 | t_filter_fs > "$T_TMP.1"
diff -u "$T_TMP.0" "$T_TMP.1"
echo "--- overwrite file"
touch "$T_D1/dir/c/file"
mv "$T_D0/dir/c/file2" "$T_D0/dir/c/file"
find "$T_D0/dir" -ls 2>&1 | t_filter_fs > "$T_TMP.0"
find "$T_D1/dir" -ls 2>&1 | t_filter_fs > "$T_TMP.1"
diff -u "$T_TMP.0" "$T_TMP.1"
echo "--- can't overwrite non-empty dir"
mkdir "$T_D0/dir/a/dir"
touch "$T_D0/dir/a/dir/nope"
mkdir "$T_D1/dir/c/clobber"
mv -T "$T_D1/dir/c/clobber" "$T_D1/dir/a/dir" 2>&1 | t_filter_fs
find "$T_D0/dir" -ls 2>&1 | t_filter_fs > "$T_TMP.0"
find "$T_D1/dir" -ls 2>&1 | t_filter_fs > "$T_TMP.1"
diff -u "$T_TMP.0" "$T_TMP.1"
echo "--- can overwrite empty dir"
rm "$T_D0/dir/a/dir/nope"
mv -T "$T_D1/dir/c/clobber" "$T_D1/dir/a/dir"
find "$T_D0/dir" -ls 2>&1 | t_filter_fs > "$T_TMP.0"
find "$T_D1/dir" -ls 2>&1 | t_filter_fs > "$T_TMP.1"
diff -u "$T_TMP.0" "$T_TMP.1"
rm -rf "$T_D0/dir"
echo "--- can rename into root"
touch "$T_D0/rename-into-root"
mv "$T_D0/rename-into-root" "$T_M0/"
rm -f "$T_M0/rename-into-root"
echo "== path resoluion"
touch "$T_D0/file"
ino=$(stat -c '%i' $T_D0/file)
for i in $(seq 1 1); do
for j in $(seq 1 4); do
lnk="$T_D0/dir/$RANDOM/$RANDOM/$RANDOM/$RANDOM"
mkdir -p $(dirname $lnk)
ln "$T_D0/file" $lnk
scoutfs ino-path -p "$T_M0" $ino > "$T_TMP.0"
scoutfs ino-path -p "$T_M1" $ino > "$T_TMP.1"
diff -u "$T_TMP.0" "$T_TMP.1"
done
done
rm -rf "$T_D0/dir"
echo "== inode indexes match after syncing existing"
t_sync_seq_index
scoutfs walk-inodes -p "$T_M0" -- meta_seq 0 -1 > "$T_TMP.0"
scoutfs walk-inodes -p "$T_M1" -- meta_seq 0 -1 > "$T_TMP.1"
diff -u "$T_TMP.0" "$T_TMP.1"
scoutfs walk-inodes -p "$T_M0" -- data_seq 0 -1 > "$T_TMP.0"
scoutfs walk-inodes -p "$T_M1" -- data_seq 0 -1 > "$T_TMP.1"
diff -u "$T_TMP.0" "$T_TMP.1"
echo "== inode indexes match after copying and syncing"
mkdir "$T_D0/dir"
cp -ar /boot/conf* "$T_D0/dir"
t_sync_seq_index
scoutfs walk-inodes -p "$T_M0" -- meta_seq 0 -1 > "$T_TMP.0"
scoutfs walk-inodes -p "$T_M1" -- meta_seq 0 -1 > "$T_TMP.1"
diff -u "$T_TMP.0" "$T_TMP.1"
scoutfs walk-inodes -p "$T_M0" -- data_seq 0 -1 > "$T_TMP.0"
scoutfs walk-inodes -p "$T_M1" -- data_seq 0 -1 > "$T_TMP.1"
diff -u "$T_TMP.0" "$T_TMP.1"
echo "== inode indexes match after removing and syncing"
rm -f "$T_D1/dir/conf*"
t_sync_seq_index
scoutfs walk-inodes -p "$T_M0" -- meta_seq 0 -1 > "$T_TMP.0"
scoutfs walk-inodes -p "$T_M1" -- meta_seq 0 -1 > "$T_TMP.1"
diff -u "$T_TMP.0" "$T_TMP.1"
scoutfs walk-inodes -p "$T_M0" -- data_seq 0 -1 > "$T_TMP.0"
scoutfs walk-inodes -p "$T_M1" -- data_seq 0 -1 > "$T_TMP.1"
diff -u "$T_TMP.0" "$T_TMP.1"
echo "== concurrent creates make one file"
mkdir "$T_D0/concurrent"
for i in $(t_fs_nrs); do
eval p="\$T_D${i}/concurrent/one-file"
touch "$p" 2>&1 > "$T_TMP.multi-create.$i" &
done
wait
ls "$T_D0/concurrent"
echo "== cleanup"
rm -f "$T_TMP.0" "$T_TMP.1"
t_pass