#! /bin/bash # SPDX-License-Identifier: GPL-2.0 # Copyright (c) 2016 Red Hat Inc. All Rights Reserved. # # FS QA Test 410 # # Test mount shared subtrees, verify the state transition when use: # --make-shared # --make-slave # --make-private # --make-unbindable # # ------------------------------------------------------------------------ # | |make-shared | make-slave | make-private |make-unbindab| # --------------|------------|--------------|--------------|-------------| # |shared |shared |*slave/private| private | unbindable | # | | | | | | # |-------------|------------|--------------|--------------|-------------| # |slave |shared | **slave | private | unbindable | # | |and slave | | | | # |-------------|------------|--------------|--------------|-------------| # |shared |shared | slave | private | unbindable | # |and slave |and slave | | | | # |-------------|------------|--------------|--------------|-------------| # |private |shared | **private | private | unbindable | # |-------------|------------|--------------|--------------|-------------| # |unbindable |shared |**unbindable | private | unbindable | # ------------------------------------------------------------------------ # 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.* _clear_mount_stack # make sure there's no bug cause dentry isn't be freed rm -rf $MNTHEAD } # get standard environment, filters and checks . ./common/rc . ./common/filter # remove previous $seqres.full before test rm -f $seqres.full # real QA test starts here _supported_fs generic _require_test _require_scratch _require_local_device $SCRATCH_DEV fs_stress() { local target=$1 $FSSTRESS_PROG -z -n 50 -p 3 \ -f creat=5 \ -f mkdir=5 \ -f link=2 \ -f rename=1 \ -f rmdir=2 \ -f unlink=1 \ -f symlink=1 \ -f write=1 \ -f read=1 \ -f chown=1 \ -f getdents=1 \ -f fiemap=1 \ -d $target >/dev/null sync } # prepare some mountpoint dir MNTHEAD=$TEST_DIR/$seq rm -rf $MNTHEAD mkdir $MNTHEAD 2>>$seqres.full mpA=$MNTHEAD/"$$"_mpA mpB=$MNTHEAD/"$$"_mpB mpC=$MNTHEAD/"$$"_mpC find_mnt() { echo "------" findmnt -n -o TARGET,SOURCE $SCRATCH_DEV | \ sed -e "s;$mpA;mpA;g" \ -e "s;$mpB;mpB;g" \ -e "s;$mpC;mpC;g" | \ _filter_spaces | _filter_testdir_and_scratch | sort echo "======" } start_test() { local type=$1 _scratch_mkfs >$seqres.full 2>&1 _get_mount -t $FSTYP $SCRATCH_DEV $MNTHEAD $MOUNT_PROG --make-"${type}" $MNTHEAD mkdir $mpA $mpB $mpC } end_test() { _clear_mount_stack rm -rf $mpA $mpB $mpC } run() { # command include make-shared/slave/private/unbindable local cmd=$1 # orginal status include shared/slave/shared&slave/private/unbindable local orgs="$2" # bind anything on un-shared dest will keep the source type # So use un-shared dest at here start_test private echo "make-$cmd a $orgs mount" _get_mount -t $FSTYP $SCRATCH_DEV $mpA mkdir -p $mpA/dir 2>/dev/null $MOUNT_PROG --make-shared $mpA # prepare the original status on mpB _get_mount --bind $mpA $mpB # shared&slave status need to do make-slave then make-shared # two operations. for t in $orgs; do $MOUNT_PROG --make-"$t" $mpB done # "before" for prepare and check original status # "after" for check the impact of make-$cmd command for i in before after; do echo "$i make-$cmd run on $orgs" # maybe unbindable at here _get_mount --bind $mpB $mpC 2>/dev/null if [ $? -ne 0 ];then find_mnt else for m in $mpA $mpB $mpC; do _get_mount -t $FSTYP $SCRATCH_DEV $m/dir fs_stress $m/dir find_mnt _put_mount done _put_mount # umount C fi if [ "$i" = "before" ];then $MOUNT_PROG --make-"${cmd}" $mpB fi done end_test } do_test() { # operation original_status run shared shared run shared slave run shared "slave shared" run shared private run shared unbindable run slave shared run slave slave run slave "slave shared" run slave private run slave unbindable run private shared run private slave run private "slave shared" run private private run private unbindable run unbindable shared run unbindable slave run unbindable "slave shared" run unbindable private run unbindable unbindable } do_test # success, all done status=0 exit