fstests: Fix block device requirements and manual scratch mounts
[xfstests-dev.git] / tests / generic / 410
1 #! /bin/bash
2 # FS QA Test 410
3 #
4 # Test mount shared subtrees, verify the state transition when use:
5 #   --make-shared
6 #   --make-slave
7 #   --make-private
8 #   --make-unbindable
9 #
10 # ------------------------------------------------------------------------
11 # |             |make-shared |  make-slave  | make-private |make-unbindab|
12 # --------------|------------|--------------|--------------|-------------|
13 # |shared       |shared      |*slave/private|   private    | unbindable  |
14 # |             |            |              |              |             |
15 # |-------------|------------|--------------|--------------|-------------|
16 # |slave        |shared      |    **slave   |    private   | unbindable  |
17 # |             |and slave   |              |              |             |
18 # |-------------|------------|--------------|--------------|-------------|
19 # |shared       |shared      |    slave     |    private   | unbindable  |
20 # |and slave    |and slave   |              |              |             |
21 # |-------------|------------|--------------|--------------|-------------|
22 # |private      |shared      |  **private   |    private   | unbindable  |
23 # |-------------|------------|--------------|--------------|-------------|
24 # |unbindable   |shared      |**unbindable  |    private   | unbindable  |
25 # ------------------------------------------------------------------------
26 #
27 #-----------------------------------------------------------------------
28 # Copyright (c) 2016 Red Hat Inc.  All Rights Reserved.
29 #
30 # This program is free software; you can redistribute it and/or
31 # modify it under the terms of the GNU General Public License as
32 # published by the Free Software Foundation.
33 #
34 # This program is distributed in the hope that it would be useful,
35 # but WITHOUT ANY WARRANTY; without even the implied warranty of
36 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
37 # GNU General Public License for more details.
38 #
39 # You should have received a copy of the GNU General Public License
40 # along with this program; if not, write the Free Software Foundation,
41 # Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
42 #-----------------------------------------------------------------------
43 #
44
45 seq=`basename $0`
46 seqres=$RESULT_DIR/$seq
47 echo "QA output created by $seq"
48
49 here=`pwd`
50 tmp=/tmp/$$
51 status=1        # failure is the default!
52 trap "_cleanup; exit \$status" 0 1 2 3 15
53
54 _cleanup()
55 {
56         cd /
57         rm -f $tmp.*
58         _clear_mount_stack
59         # make sure there's no bug cause dentry isn't be freed
60         rm -rf $MNTHEAD
61 }
62
63 # get standard environment, filters and checks
64 . ./common/rc
65 . ./common/filter
66
67 # remove previous $seqres.full before test
68 rm -f $seqres.full
69
70 # real QA test starts here
71 _supported_fs generic
72 _supported_os Linux
73 _require_test
74 _require_scratch
75 _require_local_device $SCRATCH_DEV
76
77 fs_stress()
78 {
79         local target=$1
80
81         $FSSTRESS_PROG -z -n 50 -p 3 \
82                        -f creat=5 \
83                        -f mkdir=5 \
84                        -f link=2 \
85                        -f rename=1 \
86                        -f rmdir=2 \
87                        -f unlink=1 \
88                        -f symlink=1 \
89                        -f write=1 \
90                        -f read=1 \
91                        -f chown=1 \
92                        -f getdents=1 \
93                        -f fiemap=1 \
94                        -d $target >/dev/null
95         sync
96 }
97
98 # prepare some mountpoint dir
99 MNTHEAD=$TEST_DIR/$seq
100 rm -rf $MNTHEAD
101 mkdir $MNTHEAD 2>>$seqres.full
102 mpA=$MNTHEAD/"$$"_mpA
103 mpB=$MNTHEAD/"$$"_mpB
104 mpC=$MNTHEAD/"$$"_mpC
105
106 find_mnt()
107 {
108         echo "------"
109         findmnt -n -o TARGET,SOURCE $SCRATCH_DEV | \
110                 sed -e "s;$mpA;mpA;g" \
111                     -e "s;$mpB;mpB;g" \
112                     -e "s;$mpC;mpC;g" | \
113                 _filter_spaces | _filter_scratch | \
114                 _filter_test_dir | sort
115         echo "======"
116 }
117
118 start_test()
119 {
120         local type=$1
121
122         _scratch_mkfs >$seqres.full 2>&1
123         _get_mount -t $FSTYP $SCRATCH_DEV $MNTHEAD
124         $MOUNT_PROG --make-"${type}" $MNTHEAD
125         mkdir $mpA $mpB $mpC
126 }
127
128 end_test()
129 {
130         _clear_mount_stack
131         rm -rf $mpA $mpB $mpC
132 }
133
134 run()
135 {
136         # command include make-shared/slave/private/unbindable
137         local cmd=$1
138         # orginal status include shared/slave/shared&slave/private/unbindable
139         local orgs="$2"
140
141         # bind anything on un-shared dest will keep the source type
142         # So use un-shared dest at here
143         start_test private
144
145         echo "make-$cmd a $orgs mount"
146         _get_mount -t $FSTYP $SCRATCH_DEV $mpA
147         mkdir -p $mpA/dir 2>/dev/null
148         $MOUNT_PROG --make-shared $mpA
149
150         # prepare the original status on mpB
151         _get_mount --bind $mpA $mpB
152         # shared&slave status need to do make-slave then make-shared
153         # two operations.
154         for t in $orgs; do
155                 $MOUNT_PROG --make-"$t" $mpB
156         done
157
158         # "before" for prepare and check original status
159         # "after" for check the impact of make-$cmd command
160         for i in before after; do
161                 echo "$i make-$cmd run on $orgs"
162                 # maybe unbindable at here
163                 _get_mount --bind $mpB $mpC 2>/dev/null
164                 if [ $? -ne 0 ];then
165                         find_mnt
166                 else
167                         for m in $mpA $mpB $mpC; do
168                                 _get_mount -t $FSTYP $SCRATCH_DEV $m/dir
169                                 fs_stress $m/dir
170                                 find_mnt
171                                 _put_mount
172                         done
173                         _put_mount # umount C
174                 fi
175                 if [ "$i" = "before" ];then
176                         $MOUNT_PROG --make-"${cmd}" $mpB
177                 fi
178         done
179
180         end_test
181 }
182
183 do_test()
184 {
185     #   operation  original_status
186     run shared     shared
187     run shared     slave
188     run shared     "slave shared"
189     run shared     private
190     run shared     unbindable
191
192     run slave      shared
193     run slave      slave
194     run slave      "slave shared"
195     run slave      private
196     run slave      unbindable
197
198     run private    shared
199     run private    slave
200     run private    "slave shared"
201     run private    private
202     run private    unbindable
203
204     run unbindable shared
205     run unbindable slave
206     run unbindable "slave shared"
207     run unbindable private
208     run unbindable unbindable
209 }
210
211 do_test
212
213 # success, all done
214 status=0
215 exit