blob: ca22ce1f26757d68fc1dc0833b7d8c938249d975 [file] [log] [blame]
#! /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.
#
#-----------------------------------------------------------------------
#
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 -n 50 -p 3 -d $target >/dev/null
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