]> git.apps.os.sepia.ceph.com Git - xfstests-dev.git/commitdiff
overlay: Add test for follow of lowerdata in data-only layers
authorAmir Goldstein <amir73il@gmail.com>
Mon, 10 Jul 2023 09:07:12 +0000 (11:07 +0200)
committerZorro Lang <zlang@kernel.org>
Sun, 23 Jul 2023 04:56:22 +0000 (12:56 +0800)
Add test coverage for following metacopy from lower layer to
data-only lower layers.

Data-only lower layers are configured using the syntax:
lowerdir=<lowerdir1>:<lowerdir2>::<lowerdata1>::<lowerdata2>.

Test that lowerdata files can be followed only by absolute redirect
from lower layer.

Test that with two lowerdata dirs, we can lookup individual lowerdata
files in both, and that a shared file is resolved from the uppermost
lowerdata dir.

There is also test case for lazy-data lookups, where we remove the
lowerdata file and validate that we get metadata from the metacopy
file, but open fails.

Signed-off-by: Alexander Larsson <alexl@redhat.com>
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Reviewed-by: Zorro Lang <zlang@redhat.com>
Signed-off-by: Zorro Lang <zlang@kernel.org>
common/overlay
tests/overlay/079 [new file with mode: 0755]
tests/overlay/079.out [new file with mode: 0644]

index 452b3b0994f3bca6080c2167e951957d22838ffc..816ed66da4ee5087d2273c2c47b93961d005db98 100644 (file)
@@ -201,6 +201,19 @@ _require_scratch_overlay_features()
        _scratch_unmount
 }
 
+# Check kernel support for <lowerdirs>::<lowerdatadir> format
+_require_scratch_overlay_lowerdata_layers()
+{
+       local lowerdirs="$OVL_BASE_SCRATCH_MNT/$OVL_UPPER::$OVL_BASE_SCRATCH_MNT/$OVL_LOWER"
+
+       _scratch_mkfs > /dev/null 2>&1
+       _overlay_scratch_mount_dirs "$lowerdirs" "-" "-" \
+               -o ro,redirect_dir=follow,metacopy=on > /dev/null 2>&1 || \
+               _notrun "overlay data-only layers not supported on ${SCRATCH_DEV}"
+
+       _scratch_unmount
+}
+
 # Helper function to check underlying dirs of overlay filesystem
 _overlay_fsck_dirs()
 {
diff --git a/tests/overlay/079 b/tests/overlay/079
new file mode 100755 (executable)
index 0000000..77f9459
--- /dev/null
@@ -0,0 +1,325 @@
+#! /bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (C) 2018 Red Hat, Inc. All Rights Reserved.
+# Copyright (C) 2023 CTERA Networks. All Rights Reserved.
+#
+# FS QA Test No. 079
+#
+# Test data-only layers functionality.
+#
+. ./common/preamble
+_begin_fstest auto quick metacopy redirect prealloc
+
+# Import common functions.
+. ./common/filter
+. ./common/attr
+
+# real QA test starts here
+_supported_fs overlay
+# We use non-default scratch underlying overlay dirs, we need to check
+# them explicity after test.
+_require_scratch_nocheck
+_require_scratch_overlay_features redirect_dir metacopy
+_require_scratch_overlay_lowerdata_layers
+_require_xfs_io_command "falloc"
+
+# remove all files from previous tests
+_scratch_mkfs
+
+# File size on lower
+dataname="datafile"
+sharedname="shared"
+datacontent="data"
+dataname2="datafile2"
+datacontent2="data2"
+datasize="4096"
+
+# Number of blocks allocated by filesystem on lower. Will be queried later.
+datarblocks=""
+datarblocksize=""
+estimated_datablocks=""
+
+udirname="pureupper"
+ufile="upperfile"
+
+# Check metacopy xattr
+check_metacopy()
+{
+       local target=$1 exist=$2
+       local out_f target_f
+       local msg
+
+       out_f=$(_getfattr --absolute-names --only-values -n \
+               $OVL_XATTR_METACOPY $target 2>&1 | _filter_scratch)
+
+       if [ "$exist" == "y" ];then
+               [ "$out_f" == "" ] && return
+               echo "Metacopy xattr does not exist on ${target}. stdout=$out_f"
+               return
+       fi
+
+       if [ "$out_f" == "" ];then
+               echo "Metacopy xattr exists on ${target} unexpectedly."
+               return
+       fi
+
+       target_f=`echo $target | _filter_scratch`
+       msg="$target_f: trusted.overlay.metacopy: No such attribute"
+
+       [ "$out_f" == "$msg" ] && return
+
+       echo "Error while checking xattr on ${target}. stdout=$out"
+}
+
+# Check redirect xattr
+check_redirect()
+{
+       local target=$1
+       local expect=$2
+
+       value=$(_getfattr --absolute-names --only-values -n \
+               $OVL_XATTR_REDIRECT $target)
+
+       [[ "$value" == "$expect" ]] || echo "Redirect xattr incorrect. Expected=\"$expect\", actual=\"$value\""
+}
+
+# Check size
+check_file_size()
+{
+       local target=$1 expected_size=$2 actual_size
+
+       actual_size=$(_get_filesize $target)
+
+       [ "$actual_size" == "$expected_size" ] || echo "Expected file size $expected_size but actual size is $actual_size"
+}
+
+check_file_blocks()
+{
+       local target=$1 expected_blocks=$2 nr_blocks
+
+       nr_blocks=$(stat -c "%b" $target)
+
+       [ "$nr_blocks" == "$expected_blocks" ] || echo "Expected $expected_blocks blocks but actual number of blocks is ${nr_blocks}."
+}
+
+check_file_contents()
+{
+       local target=$1 expected=$2
+       local actual target_f
+
+       target_f=`echo $target | _filter_scratch`
+
+       read actual<$target
+
+       [ "$actual" == "$expected" ] || echo "Expected file $target_f contents to be \"$expected\" but actual contents are \"$actual\""
+}
+
+check_no_file_contents()
+{
+       local target=$1
+       local actual target_f out_f
+
+       target_f=`echo $target | _filter_scratch`
+       out_f=`cat $target 2>&1 | _filter_scratch`
+       msg="cat: $target_f: No such file or directory"
+
+       [ "$out_f" == "$msg" ] && return
+
+       echo "$target_f unexpectedly has content"
+}
+
+
+check_file_size_contents()
+{
+       local target=$1 expected_size=$2 expected_content=$3
+
+       check_file_size $target $expected_size
+       check_file_contents $target $expected_content
+}
+
+mount_overlay()
+{
+       local _lowerdir=$1
+
+       _overlay_scratch_mount_dirs "$_lowerdir" $upperdir $workdir -o redirect_dir=on,index=on,metacopy=on
+}
+
+mount_ro_overlay()
+{
+       local _lowerdir=$1
+
+       _overlay_scratch_mount_dirs "$_lowerdir" "-" "-" -o ro,redirect_dir=follow,metacopy=on
+}
+
+umount_overlay()
+{
+       $UMOUNT_PROG $SCRATCH_MNT
+}
+
+test_no_access()
+{
+       local _target=$1
+
+       mount_ro_overlay "$lowerdir::$datadir2::$datadir"
+
+       stat $SCRATCH_MNT/$_target >> $seqres.full 2>&1 || \
+               echo "No access to lowerdata layer $_target"
+
+       echo "Unmount and Mount rw"
+       umount_overlay
+       mount_overlay "$lowerdir::$datadir2::$datadir"
+       stat $SCRATCH_MNT/$_target >> $seqres.full 2>&1 || \
+               echo "No access to lowerdata layer $_target"
+       umount_overlay
+}
+
+test_common()
+{
+       local _lowerdirs=$1 _target=$2 _size=$3 _blocks=$4 _data="$5"
+       local _redirect=$6
+
+       echo "Mount ro"
+       mount_ro_overlay $_lowerdirs
+
+       # Check redirect xattr to lowerdata
+       [ -n "$_redirect" ] && check_redirect $lowerdir/$_target "$_redirect"
+
+       echo "check properties of metadata copied up file $_target"
+       check_file_size_contents $SCRATCH_MNT/$_target $_size "$_data"
+       check_file_blocks $SCRATCH_MNT/$_target $_blocks
+
+       # Do a mount cycle and check size and contents again.
+       echo "Unmount and Mount rw"
+       umount_overlay
+       mount_overlay $_lowerdirs
+       echo "check properties of metadata copied up file $_target"
+       check_file_size_contents $SCRATCH_MNT/$_target $_size "$_data"
+       check_file_blocks $SCRATCH_MNT/$_target $_blocks
+
+       # Trigger metadata copy up and check existence of metacopy xattr.
+       chmod 400 $SCRATCH_MNT/$_target
+       umount_overlay
+       check_metacopy $upperdir/$_target "y"
+       check_file_size_contents $upperdir/$_target $_size ""
+
+       # Trigger data copy up and check absence of metacopy xattr.
+       mount_overlay $_lowerdirs
+       $XFS_IO_PROG -c "falloc 0 1" $SCRATCH_MNT/$_target >> $seqres.full
+       echo "check properties of data copied up file $_target"
+       check_file_size_contents $SCRATCH_MNT/$_target $_size "$_data"
+       umount_overlay
+       check_metacopy $upperdir/$_target "n"
+       check_file_size_contents $upperdir/$_target $_size "$_data"
+}
+
+test_lazy()
+{
+       local _target=$1
+
+       mount_overlay "$lowerdir::$datadir2::$datadir"
+
+       # Metadata should be valid
+       check_file_size $SCRATCH_MNT/$_target $datasize
+       check_file_blocks $SCRATCH_MNT/$_target $estimated_datablocks
+
+       # But have no content
+       check_no_file_contents $SCRATCH_MNT/$_target
+
+       umount_overlay
+}
+
+create_basic_files()
+{
+       _scratch_mkfs
+       mkdir -p $datadir/subdir $datadir2/subdir $lowerdir $lowerdir2 $upperdir $workdir $workdir2
+       mkdir -p $upperdir/$udirname
+       echo "$datacontent" > $datadir/$dataname
+       chmod 600 $datadir/$dataname
+       echo "$datacontent2" > $datadir2/$dataname2
+       chmod 600 $datadir2/$dataname2
+
+       echo "$datacontent" > $datadir/$sharedname
+       echo "$datacontent2" > $datadir2/$sharedname
+       chmod 600 $datadir/$sharedname  $datadir2/$sharedname
+
+       # Create files of size datasize.
+       for f in $datadir/$dataname $datadir2/$dataname2 $datadir/$sharedname $datadir2/$sharedname; do
+               $XFS_IO_PROG -c "falloc 0 $datasize" $f
+               $XFS_IO_PROG -c "fsync" $f
+       done
+
+       # Query number of block
+       datablocks=$(stat -c "%b" $datadir/$dataname)
+
+       # For lazy lookup file the block count is estimated based on size and block size
+       datablocksize=$(stat -c "%B" $datadir/$dataname)
+       estimated_datablocks=$(( ($datasize + $datablocksize - 1)/$datablocksize ))
+}
+
+prepare_midlayer()
+{
+       local _redirect=$1
+
+       _scratch_mkfs
+       create_basic_files
+       if [ -n "$_redirect" ]; then
+               mv "$datadir/$dataname" "$datadir/$_redirect"
+               mv "$datadir2/$dataname2" "$datadir2/$_redirect.2"
+               mv "$datadir/$sharedname" "$datadir/$_redirect.shared"
+               mv "$datadir2/$sharedname" "$datadir2/$_redirect.shared"
+       fi
+       # Create midlayer
+       _overlay_scratch_mount_dirs $datadir2:$datadir $lowerdir $workdir2 -o redirect_dir=on,index=on,metacopy=on
+       # Trigger a metacopy with or without redirect
+       if [ -n "$_redirect" ]; then
+               mv "$SCRATCH_MNT/$_redirect" "$SCRATCH_MNT/$dataname"
+               mv "$SCRATCH_MNT/$_redirect.2" "$SCRATCH_MNT/$dataname2"
+               mv "$SCRATCH_MNT/$_redirect.shared" "$SCRATCH_MNT/$sharedname"
+       else
+               chmod 400 $SCRATCH_MNT/$dataname
+               chmod 400 $SCRATCH_MNT/$dataname2
+               chmod 400 $SCRATCH_MNT/$sharedname
+       fi
+       umount_overlay
+}
+
+# Create test directories
+datadir=$OVL_BASE_SCRATCH_MNT/data
+datadir2=$OVL_BASE_SCRATCH_MNT/data2
+lowerdir=$OVL_BASE_SCRATCH_MNT/lower
+upperdir=$OVL_BASE_SCRATCH_MNT/upper
+workdir=$OVL_BASE_SCRATCH_MNT/workdir
+workdir2=$OVL_BASE_SCRATCH_MNT/workdir2
+
+echo -e "\n== Check no follow to lowerdata layer without redirect =="
+prepare_midlayer
+test_no_access "$dataname"
+test_no_access "$dataname2"
+test_no_access "$sharedname"
+
+echo -e "\n== Check no follow to lowerdata layer with relative redirect =="
+prepare_midlayer "$dataname.renamed"
+test_no_access "$dataname"
+test_no_access "$dataname2"
+test_no_access "$sharedname"
+
+echo -e "\n== Check follow to lowerdata layer with absolute redirect =="
+prepare_midlayer "/subdir/$dataname"
+test_common "$lowerdir::$datadir2::$datadir" "$dataname" $datasize $datablocks \
+               "$datacontent" "/subdir/$dataname"
+test_common "$lowerdir::$datadir2::$datadir" "$dataname2" $datasize $datablocks \
+               "$datacontent2" "/subdir/$dataname.2"
+# Shared file should be picked from upper datadir
+test_common "$lowerdir::$datadir2::$datadir" "$sharedname" $datasize $datablocks \
+               "$datacontent2" "/subdir/$dataname.shared"
+
+echo -e "\n== Check lazy follow to lowerdata layer =="
+
+prepare_midlayer "/subdir/$dataname"
+rm $datadir/subdir/$dataname
+test_lazy $dataname
+
+
+# success, all done
+status=0
+exit
diff --git a/tests/overlay/079.out b/tests/overlay/079.out
new file mode 100644 (file)
index 0000000..4807cdb
--- /dev/null
@@ -0,0 +1,42 @@
+QA output created by 079
+
+== Check no follow to lowerdata layer without redirect ==
+No access to lowerdata layer datafile
+Unmount and Mount rw
+No access to lowerdata layer datafile
+No access to lowerdata layer datafile2
+Unmount and Mount rw
+No access to lowerdata layer datafile2
+No access to lowerdata layer shared
+Unmount and Mount rw
+No access to lowerdata layer shared
+
+== Check no follow to lowerdata layer with relative redirect ==
+No access to lowerdata layer datafile
+Unmount and Mount rw
+No access to lowerdata layer datafile
+No access to lowerdata layer datafile2
+Unmount and Mount rw
+No access to lowerdata layer datafile2
+No access to lowerdata layer shared
+Unmount and Mount rw
+No access to lowerdata layer shared
+
+== Check follow to lowerdata layer with absolute redirect ==
+Mount ro
+check properties of metadata copied up file datafile
+Unmount and Mount rw
+check properties of metadata copied up file datafile
+check properties of data copied up file datafile
+Mount ro
+check properties of metadata copied up file datafile2
+Unmount and Mount rw
+check properties of metadata copied up file datafile2
+check properties of data copied up file datafile2
+Mount ro
+check properties of metadata copied up file shared
+Unmount and Mount rw
+check properties of metadata copied up file shared
+check properties of data copied up file shared
+
+== Check lazy follow to lowerdata layer ==