|  | #! /bin/bash | 
|  | # SPDX-License-Identifier: GPL-2.0 | 
|  | # Copyright (c) 2019 Red Hat Inc.  All Rights Reserved. | 
|  | # | 
|  | # FS QA Test 589 | 
|  | # | 
|  | # Test mount shared subtrees, verify the move semantics: | 
|  | # | 
|  | # --------------------------------------------------------------------------- | 
|  | # |         MOVE MOUNT OPERATION                                            | | 
|  | # |************************************************************************** | 
|  | # |source(A)->| shared       |       private  |       slave    | unbindable | | 
|  | # | dest(B)  |               |                |                |            | | 
|  | # |   |      |               |                |                |            | | 
|  | # |   v      |               |                |                |            | | 
|  | # |************************************************************************** | 
|  | # |  shared  | shared        |     shared     | shared & slave |  invalid   | | 
|  | # |          |               |                |                |            | | 
|  | # |non-shared| shared        |      private   |      slave     | unbindable | | 
|  | # *************************************************************************** | 
|  | #   NOTE: moving a mount residing under a shared mount is invalid. | 
|  | # | 
|  | #----------------------------------------------------------------------- | 
|  | # | 
|  | . ./common/preamble | 
|  | _begin_fstest auto mount | 
|  |  | 
|  | # Override the default cleanup function. | 
|  | _cleanup() | 
|  | { | 
|  | cd / | 
|  | rm -f $tmp.* | 
|  | _clear_mount_stack | 
|  | # make sure there's no bug cause dentry isn't be freed | 
|  | rm -rf $MNTHEAD | 
|  | } | 
|  |  | 
|  | # Import common functions. | 
|  | . ./common/filter | 
|  |  | 
|  | _require_test | 
|  | _require_scratch | 
|  | _require_local_device $SCRATCH_DEV | 
|  |  | 
|  | fs_stress() | 
|  | { | 
|  | local target=$1 | 
|  |  | 
|  | $FSSTRESS_PROG -n 50 -p 3 -d $target >>$seqres.full | 
|  | sync | 
|  | } | 
|  |  | 
|  | # prepare some mountpoint dir | 
|  | SRCHEAD=$TEST_DIR/$seq-src | 
|  | DSTHEAD=$TEST_DIR/$seq-dst | 
|  | rm -rf $SRCHEAD $DSTHEAD | 
|  | mkdir $SRCHEAD $DSTHEAD 2>>$seqres.full | 
|  | mpA=$SRCHEAD/"$$"_mpA | 
|  | mpB=$SRCHEAD/"$$"_mpB | 
|  | mpC=$DSTHEAD/"$$"_mpC | 
|  | mpD=$DSTHEAD/"$$"_mpD | 
|  |  | 
|  | 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" \ | 
|  | -e "s;$mpD;mpD;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 $SRCHEAD | 
|  | # make sure $SRCHEAD is private | 
|  | $MOUNT_PROG --make-private $SRCHEAD | 
|  |  | 
|  | _get_mount -t $FSTYP $SCRATCH_DEV $DSTHEAD | 
|  | # test start with a bind, then make-shared $DSTHEAD | 
|  | _get_mount --bind $DSTHEAD $DSTHEAD | 
|  | $MOUNT_PROG --make-"${type}" $DSTHEAD | 
|  | mkdir $mpA $mpB $mpC $mpD | 
|  | } | 
|  |  | 
|  | end_test() | 
|  | { | 
|  | _clear_mount_stack | 
|  | rm -rf $mpA $mpB $mpC $mpD | 
|  | } | 
|  |  | 
|  | move_run() | 
|  | { | 
|  | local source=$1 | 
|  | local dest=$2 | 
|  |  | 
|  | start_test $dest | 
|  |  | 
|  | echo "move $source to $dest" | 
|  | _get_mount -t $FSTYP $SCRATCH_DEV $mpA | 
|  | mkdir -p $mpA/dir 2>/dev/null | 
|  | $MOUNT_PROG --make-shared $mpA | 
|  | # need a peer for slave later | 
|  | _get_mount --bind $mpA $mpB | 
|  | $MOUNT_PROG --make-"$source" $mpB | 
|  | # maybe unbindable at here | 
|  | _get_mount --move $mpB $mpC 2>/dev/null | 
|  | if [ $? -ne 0 ]; then | 
|  | find_mnt | 
|  | end_test | 
|  | return 0 | 
|  | fi | 
|  |  | 
|  | # check mpC after move B to C | 
|  | for m in $mpA $mpC; do | 
|  | _get_mount -t $FSTYP $SCRATCH_DEV $m/dir | 
|  | fs_stress $m/dir | 
|  | find_mnt | 
|  | _put_mount | 
|  | done | 
|  |  | 
|  | # mpC will be in different parent mount, test moving from different | 
|  | # parent mount, and moving a mount residing under a shared mount is | 
|  | # invalid | 
|  | _get_mount --move $mpC $mpD 2>/dev/null | 
|  | if [ $? -ne 0 ]; then | 
|  | find_mnt | 
|  | end_test | 
|  | return 0 | 
|  | fi | 
|  | for m in $mpA $mpD; do | 
|  | _get_mount -t $FSTYP $SCRATCH_DEV $m/dir | 
|  | fs_stress $m/dir | 
|  | find_mnt | 
|  | _put_mount | 
|  | done | 
|  |  | 
|  | end_test | 
|  | } | 
|  |  | 
|  | move_test() | 
|  | { | 
|  | #        source     dest | 
|  | move_run shared     shared | 
|  | move_run slave      shared | 
|  | move_run private    shared | 
|  | move_run unbindable shared | 
|  |  | 
|  | move_run shared     slave | 
|  | move_run slave      slave | 
|  | move_run private    slave | 
|  | move_run unbindable slave | 
|  |  | 
|  | move_run shared     private | 
|  | move_run slave      private | 
|  | move_run private    private | 
|  | move_run unbindable private | 
|  | } | 
|  |  | 
|  | move_test | 
|  |  | 
|  | # success, all done | 
|  | status=0 | 
|  | exit |