summaryrefslogtreecommitdiff
path: root/tests/generic/409
blob: 432befaca6826487f3b610fb38ee0cc7d7bacc4c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#! /bin/bash
# SPDX-License-Identifier: GPL-2.0
# Copyright (c) 2016 Red Hat Inc.  All Rights Reserved.
#
# FS QA Test 409
#
# Test mount shared subtrees, verify the bind semantics:
#
# ---------------------------------------------------------------------------
# |         BIND MOUNT OPERATION                                            |
# |**************************************************************************
# |source(A)->| shared       |       private  |       slave    | unbindable |
# | dest(B)  |               |                |                |            |
# |   |      |               |                |                |            |
# |   v      |               |                |                |            |
# |**************************************************************************
# |  shared  | shared        |     shared     | shared & slave |  invalid   |
# |          |               |                |                |            |
# |non-shared| shared        |      private   |      slave     |  invalid   |
# ***************************************************************************
#
. ./common/preamble
_begin_fstest auto quick 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

# 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 >>$seqres.full
	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
mpD=$MNTHEAD/"$$"_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 $MNTHEAD
	$MOUNT_PROG --make-"${type}" $MNTHEAD
	mkdir $mpA $mpB $mpC $mpD
}

end_test()
{
	_clear_mount_stack
	rm -rf $mpA $mpB $mpC $mpD
}

bind_run()
{
	local source=$1
	local dest=$2

	start_test $dest

	echo "bind $source on $dest"
	_get_mount -t $FSTYP $SCRATCH_DEV $mpA
	mkdir -p $mpA/dir 2>/dev/null
	$MOUNT_PROG --make-shared $mpA
	_get_mount --bind $mpA $mpB
	$MOUNT_PROG --make-"$source" $mpB
	# maybe unbindable at here
	_get_mount --bind $mpB $mpC 2>/dev/null
	if [ $? -ne 0 ]; then
		find_mnt
		end_test
		return 0
	fi
	_get_mount --bind $mpC $mpD
	for m in $mpA $mpB $mpC $mpD; do
		_get_mount -t $FSTYP $SCRATCH_DEV $m/dir
		fs_stress $m/dir
		find_mnt
		_put_mount
	done

	end_test
}

bind_test()
{
        #        source     dest
	bind_run shared     shared
	bind_run slave      shared
	bind_run private    shared
	bind_run unbindable shared

	bind_run shared     slave
	bind_run slave      slave
	bind_run private    slave
	bind_run unbindable slave

	bind_run shared     private
	bind_run slave      private
	bind_run private    private
	bind_run unbindable private
}

bind_test

# success, all done
status=0
exit