generic: test for file loss after mix of rename, fsync and inode eviction
[xfstests-dev.git] / tests / generic / 589
1 #! /bin/bash
2 # SPDX-License-Identifier: GPL-2.0
3 # Copyright (c) 2019 Red Hat Inc.  All Rights Reserved.
4 #
5 # FS QA Test 589
6 #
7 # Test mount shared subtrees, verify the move semantics:
8 #
9 # ---------------------------------------------------------------------------
10 # |         MOVE MOUNT OPERATION                                            |
11 # |**************************************************************************
12 # |source(A)->| shared       |       private  |       slave    | unbindable |
13 # | dest(B)  |               |                |                |            |
14 # |   |      |               |                |                |            |
15 # |   v      |               |                |                |            |
16 # |**************************************************************************
17 # |  shared  | shared        |     shared     | shared & slave |  invalid   |
18 # |          |               |                |                |            |
19 # |non-shared| shared        |      private   |      slave     | unbindable |
20 # ***************************************************************************
21 #   NOTE: moving a mount residing under a shared mount is invalid.
22 #
23 #-----------------------------------------------------------------------
24 #
25 . ./common/preamble
26 _begin_fstest auto mount
27
28 # Override the default cleanup function.
29 _cleanup()
30 {
31         cd /
32         rm -f $tmp.*
33         _clear_mount_stack
34         # make sure there's no bug cause dentry isn't be freed
35         rm -rf $MNTHEAD
36 }
37
38 # Import common functions.
39 . ./common/filter
40
41 # real QA test starts here
42 _supported_fs generic
43 _require_test
44 _require_scratch
45 _require_local_device $SCRATCH_DEV
46
47 fs_stress()
48 {
49         local target=$1
50
51         $FSSTRESS_PROG -n 50 -p 3 -d $target >/dev/null
52         sync
53 }
54
55 # prepare some mountpoint dir
56 SRCHEAD=$TEST_DIR/$seq-src
57 DSTHEAD=$TEST_DIR/$seq-dst
58 rm -rf $SRCHEAD $DSTHEAD
59 mkdir $SRCHEAD $DSTHEAD 2>>$seqres.full
60 mpA=$SRCHEAD/"$$"_mpA
61 mpB=$SRCHEAD/"$$"_mpB
62 mpC=$DSTHEAD/"$$"_mpC
63 mpD=$DSTHEAD/"$$"_mpD
64
65 find_mnt()
66 {
67         echo "------"
68         findmnt -n -o TARGET,SOURCE $SCRATCH_DEV | \
69                 sed -e "s;$mpA;mpA;g" \
70                     -e "s;$mpB;mpB;g" \
71                     -e "s;$mpC;mpC;g" \
72                     -e "s;$mpD;mpD;g" | \
73                 _filter_spaces | _filter_testdir_and_scratch | sort
74         echo "======"
75 }
76
77 start_test()
78 {
79         local type=$1
80
81         _scratch_mkfs >$seqres.full 2>&1
82
83         _get_mount -t $FSTYP $SCRATCH_DEV $SRCHEAD
84         # make sure $SRCHEAD is private
85         $MOUNT_PROG --make-private $SRCHEAD
86
87         _get_mount -t $FSTYP $SCRATCH_DEV $DSTHEAD
88         # test start with a bind, then make-shared $DSTHEAD
89         _get_mount --bind $DSTHEAD $DSTHEAD
90         $MOUNT_PROG --make-"${type}" $DSTHEAD
91         mkdir $mpA $mpB $mpC $mpD
92 }
93
94 end_test()
95 {
96         _clear_mount_stack
97         rm -rf $mpA $mpB $mpC $mpD
98 }
99
100 move_run()
101 {
102         local source=$1
103         local dest=$2
104
105         start_test $dest
106
107         echo "move $source to $dest"
108         _get_mount -t $FSTYP $SCRATCH_DEV $mpA
109         mkdir -p $mpA/dir 2>/dev/null
110         $MOUNT_PROG --make-shared $mpA
111         # need a peer for slave later
112         _get_mount --bind $mpA $mpB
113         $MOUNT_PROG --make-"$source" $mpB
114         # maybe unbindable at here
115         _get_mount --move $mpB $mpC 2>/dev/null
116         if [ $? -ne 0 ]; then
117                 find_mnt
118                 end_test
119                 return 0
120         fi
121
122         # check mpC after move B to C
123         for m in $mpA $mpC; do
124                 _get_mount -t $FSTYP $SCRATCH_DEV $m/dir
125                 fs_stress $m/dir
126                 find_mnt
127                 _put_mount
128         done
129
130         # mpC will be in different parent mount, test moving from different
131         # parent mount, and moving a mount residing under a shared mount is
132         # invalid
133         _get_mount --move $mpC $mpD 2>/dev/null
134         if [ $? -ne 0 ]; then
135                 find_mnt
136                 end_test
137                 return 0
138         fi
139         for m in $mpA $mpD; do
140                 _get_mount -t $FSTYP $SCRATCH_DEV $m/dir
141                 fs_stress $m/dir
142                 find_mnt
143                 _put_mount
144         done
145
146         end_test
147 }
148
149 move_test()
150 {
151         #        source     dest
152         move_run shared     shared
153         move_run slave      shared
154         move_run private    shared
155         move_run unbindable shared
156
157         move_run shared     slave
158         move_run slave      slave
159         move_run private    slave
160         move_run unbindable slave
161
162         move_run shared     private
163         move_run slave      private
164         move_run private    private
165         move_run unbindable private
166 }
167
168 move_test
169
170 # success, all done
171 status=0
172 exit