| #! /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 |
| _supported_os Linux |
| _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 |