#! /bin/bash # SPDX-License-Identifier: GPL-2.0 # Copyright (C) 2018 CTERA Networks. All Rights Reserved. # # FS QA Test No. 055 # # Test overlay file handle of dir with ancestor under lower redirect # # Overlayfs with nfs_export enabled, indexes all directories on copy up. # Directory index is requires for decoding lower directory file handles # in case ancestors have been renamed. # # When enabling nfs_export on an overlay that has merge dirs with lower # layer redirects, the possibility of ancestor rename requires special # handling when encoding lower directory file handles from layer > 1. # # - Check decode of lower dir with parent under lower redirect # - Check decode of lower dir with grandparent under lower redirect # - Check decode of lower dir after rename of lower redirected parent # - Check decode of lower dir after rename of lower redirected grandparent # # This test requires and enables overlayfs NFS export support and merge # dir rename support (redirect_dir). # NFS export support depends on and requires overlayfs index feature. # # Regression test for kernel commit 2ca3c148a062 ("ovl: check lower ancestry # on encode of lower dir file handle") # seq=`basename $0` seqres=$RESULT_DIR/$seq echo "QA output created by $seq" here=`pwd` tmp=/tmp/$$ status=1 # failure is the default! trap "_cleanup; exit \$status" 0 1 2 3 15 _cleanup() { cd / rm -f $tmp.* # Cleanup overlay scratch mount that is holding base test mount # to prevent _check_test_fs and _test_umount from failing before # _check_scratch_fs _scratch_umount $UMOUNT_PROG $SCRATCH_MNT 2>/dev/null } # get standard environment, filters and checks . ./common/rc . ./common/filter # real QA test starts here _supported_fs overlay _require_test _require_test_program "open_by_handle" # Use non-default scratch underlying overlay dirs, we need to check # them explicity after test. _require_scratch_nocheck # We need to require all features together, because nfs_export cannot # be enabled when index is disabled _require_scratch_overlay_features index nfs_export redirect_dir # Lower is on test partition lower=$OVL_BASE_TEST_DIR/$OVL_LOWER-$seq # Upper/work are on scratch partition middle=$OVL_BASE_SCRATCH_MNT/$OVL_LOWER upper=$OVL_BASE_SCRATCH_MNT/$OVL_UPPER work=$OVL_BASE_SCRATCH_MNT/$OVL_WORK NUMFILES=1 # Create test dir and empty test files create_test_files() { local dir=$1 local opt=$2 mkdir -p $dir $here/src/open_by_handle -cp $opt $dir $NUMFILES } # Test encode/decode file handles on overlay mount test_file_handles() { local dir=$1 shift echo test_file_handles $dir $* | _filter_scratch | \ sed -e "s,$tmp\.,,g" $here/src/open_by_handle $* $dir $NUMFILES } # Re-create lower/middle/upper/work dirs create_dirs() { # Create lower dir on test partition rm -rf $lower mkdir $lower # Create middle/upper/work dirs on scratch partition _scratch_mkfs } # Mount an overlay on $SCRATCH_MNT with lower layer on test partition # and middle and upper layer on scratch partition mount_dirs() { _overlay_scratch_mount_dirs $middle:$lower $upper $work \ -o "index=on,nfs_export=on,redirect_dir=on" } # Unmount the overlay without unmounting base fs and check the # underlying dirs unmount_dirs() { $UMOUNT_PROG $SCRATCH_MNT _overlay_check_scratch_dirs $middle:$lower $upper $work \ -o "index=on,nfs_export=on,redirect_dir=on" } # Check file handles of dir with ancestor under lower redirect create_dirs create_test_files $lower/origin -w create_test_files $lower/origin/dir -w create_test_files $lower/origin/dir/subdir -w create_test_files $lower/origin/parent/child -w # Create lower redirected merge dir mkdir $middle/merged setfattr -n "trusted.overlay.redirect" -v "origin" $middle/merged mount_dirs # Check encode/decode/read of lower dir with parent under lower redirect # This is expected to copy up merged/dir and encode an upper file handle test_file_handles $SCRATCH_MNT/merged/dir -p -o $tmp.dir_file_handles test -d $upper/merged/dir || echo "merged/dir not copied up" # Check encode/decode/read of lower dir with grandparent under lower redirect # This is expected to encode a lower file handle test_file_handles $SCRATCH_MNT/merged/dir/subdir -p -o $tmp.subdir_file_handles test -d $upper/merged/dir/subdir && echo "merged/dir/subdir unexpected copy up" # This is expected to copy up parent and encode a lower file handle test_file_handles $SCRATCH_MNT/merged/parent/child -p -o $tmp.child_file_handles test -d $upper/merged/parent || echo "merged/parent not copied up" test -d $upper/merged/parent/child && echo "merged/parent/child unexpected copy up" # Rename lower redirected merge dir mv $SCRATCH_MNT/merged $SCRATCH_MNT/merged.new/ # Check open, read and readdir from stored file handles # (testdir argument is the mount point and NOT the dir # we are trying to open by stored file handle) test_file_handles $SCRATCH_MNT -rp -i $tmp.dir_file_handles test_file_handles $SCRATCH_MNT -rp -i $tmp.subdir_file_handles test_file_handles $SCRATCH_MNT -rp -i $tmp.child_file_handles # Retry decoding lower subdir file handles when indexed ancestor is in dcache # (providing the ancestor dir argument pins the ancestor to dcache) test_file_handles $SCRATCH_MNT/merged.new/dir -rp -i $tmp.dir_file_handles test_file_handles $SCRATCH_MNT/merged.new/dir -rp -i $tmp.subdir_file_handles test_file_handles $SCRATCH_MNT/merged.new/parent -rp -i $tmp.child_file_handles unmount_dirs status=0 exit