generic: Verify the inheritance behavior of FS_XFLAG_DAX flag in various combinations
[xfstests-dev.git] / tests / generic / 478
1 #! /bin/bash
2 # SPDX-License-Identifier: GPL-2.0
3 # Copyright (c) 2018 Red Hat Inc.  All Rights Reserved.
4 #
5 # FS QA Test 478
6 #
7 # Test OFD lock. fcntl F_OFD_SETLK to set lock, then F_OFD_GETLK
8 # to verify we are being given correct advice by kernel.
9 #
10 # OFD lock combines POSIX lock and BSD flock:
11 #   + does not share between threads
12 #   + byte granularity
13 #            (both tested by LTP/fcntl3{4,6})
14 #   + only release automatically after all open fd closed
15 #
16 # This test target the third one and expand a little bit.
17 #
18 # The basic idea is one setlk routine setting locks via fcntl
19 # *_SETLK, followed by operations like clone, dup then close fd;
20 # another routine getlk getting locks via fcntl *_GETLK.
21 #
22 # Firstly in setlk routine process P0, place a lock L0 on an
23 # opened testfile, then
24 #
25 #   + clone() a child P1 to close the fd then tell getlk to go,
26 #     parent P0 wait getlk done then close fd.
27 # or
28 #   + dup() fd to a newfd then close newfd then tell getlk to go,
29 #     then wait getlk done then close fd.
30 #
31 # In getlk process P2, do fcntl *_GETLK with lock L1 after get
32 # notified by setlk routine.
33 #
34 # In the end, getlk routine check the returned struct flock.l_type
35 # to see if the lock mechanism works fine.
36 #
37 # When testing with clone,
38 #    + CLONE_FILES set, close releases all locks;
39 #    + CLONE_FILES not set, locks remain in P0;
40 #
41 # If L0 is a POSIX lock,
42 #   + it is not inherited into P1
43 #   + it is released after dup & close
44 #
45 # If L0 is a OFD lock,
46 #   + it is inherited into P1
47 #   + it is not released after dup & close
48 #
49 #  setlk routine:                        * getlk routine:
50 #    start                               *   start
51 #      |                                 *     |
52 #   open file                            *  open file
53 #      |                                 *     |
54 #   init sem                             *     |
55 #      |                                 *     |
56 #  wait init sem done                    * wait init sem done
57 #      |                                 *     |
58 #    setlk L0                            *     |
59 #      |                                 *     |
60 #      |---------clone()--------|        *     |
61 #      |                        |        *     |
62 #      |(child P1)   (parent P0)|        *     | (P2)
63 #      |                        |        *     |
64 #      |                   close fd      *     |
65 #      |                        |        *     |
66 #      |                 set sem0=0      *  wait sem0==0
67 #      |                        |        *     |
68 #      |                        |        *   getlk L1
69 #      |                        |        *     |
70 #   wait sem1==0                |        *  set sem1=0
71 #      |                        |        *     |
72 #     exit                wait child     *     |
73 #                               |        *  check result
74 #                           cleanup      *     |
75 #                               |        *     |
76 #                             exit       *    exit
77 #
78 # We can test combainations of:
79 #       + shared or exclusive lock
80 #       + these locks are conflicting or not
81 #       + one OFD lock and one POSIX lock
82 #       + that open testfile RDONLY or RDWR
83 #       + clone with CLONE_FILES or not
84 #       + dup and close newfd
85 #
86 seq=`basename $0`
87 seqres=$RESULT_DIR/$seq
88 echo "QA output created by $seq"
89
90 here=`pwd`
91 tmp=/tmp/$$
92 status=1        # failure is the default!
93 trap "_cleanup; exit \$status" 0 1 2 3 15
94
95 _cleanup()
96 {
97         cd /
98         rm -f $tmp.*
99 }
100
101 # get standard environment, filters and checks
102 . ./common/rc
103 . ./common/filter
104
105 # remove previous $seqres.full before test
106 rm -f $seqres.full
107
108 # Modify as appropriate.
109 _supported_fs generic
110 _supported_os Linux
111 _require_test
112 _require_ofd_locks
113
114 # real QA test starts here
115 # prepare a 4k testfile in TEST_DIR
116 $XFS_IO_PROG -f -c "pwrite -S 0xFF 0 4096" \
117         $TEST_DIR/testfile >> $seqres.full 2>&1
118
119 do_test()
120 {
121         local soptions="$1"
122         local goptions="$2"
123         # print options and getlk output for debug
124         echo $* >> $seqres.full 2>&1
125         # -s : do setlk
126         $here/src/t_ofd_locks $soptions $TEST_DIR/testfile &
127         # -g : do getlk
128         $here/src/t_ofd_locks $goptions $TEST_DIR/testfile | \
129                 tee -a $seqres.full
130         wait $!
131
132         # add -F to clone with CLONE_FILES
133         soptions="$1 -F"
134         # with -F, new locks are always file to place
135         $here/src/t_ofd_locks $soptions $TEST_DIR/testfile &
136         $here/src/t_ofd_locks $goptions $TEST_DIR/testfile | \
137                 tee -a $seqres.full
138         wait $!
139
140         # add -d to dup and close
141         soptions="$1 -d"
142         $here/src/t_ofd_locks $soptions $TEST_DIR/testfile &
143         $here/src/t_ofd_locks $goptions $TEST_DIR/testfile | \
144                 tee -a $seqres.full
145         wait $!
146 }
147
148 # Always setlk at range [0,9], getlk at range [0,9] [5,24] or [20,29].
149 # To open file RDONLY or RDWR should not break the locks.
150 # POSIX locks should be released after closed fd, so it wont conflict
151 # with other locks in tests
152
153 # -P : operate posix lock
154 # -w : operate on F_WRLCK
155 # -r : operate on F_RDLCK
156 # -R : open file RDONLY
157 # -W : open file RDWR
158 # -o : file offset where the lock starts
159 # -l : lock length
160 # -F : clone with CLONE_FILES in setlk
161 # -d : dup and close in setlk
162
163 # setlk wrlck [0,9], getlk wrlck [0,9], expect
164 #    + wrlck when CLONE_FILES not set
165 #    + unlck when CLONE_FILES set
166 #    + wrlck when dup & close
167 do_test "-s -w -o 0 -l 10 -W" "-g -w -o 0 -l 10 -W" "wrlck" "unlck" "wrlck"
168 # setlk wrlck [0,9], getlk posix wrlck [5,24]
169 do_test "-s -w -o 0 -l 10 -W" "-g -w -o 5 -l 20 -W -P" "wrlck" "unlck" "wrlck"
170 # setlk wrlck [0,9], getlk wrlck [20,29]
171 do_test "-s -w -o 0 -l 10 -W" "-g -w -o 20 -l 10 -W" "unlck" "unlck" "unlck"
172 # setlk posix wrlck [0,9], getlk wrlck [5,24]
173 do_test "-s -w -o 0 -l 10 -W -P" "-g -w -o 5 -l 20 -W" "wrlck" "unlck" "unlck"
174 # setlk posix wrlck [0,9], getlk wrlck [20,29]
175 do_test "-s -w -o 0 -l 10 -W -P" "-g -w -o 20 -l 10 -W" "unlck" "unlck" "unlck"
176
177 # setlk wrlck [0,9], getlk rdlck [0,9]
178 do_test "-s -w -o 0 -l 10 -W" "-g -r -o 0 -l 10 -W" "wrlck" "unlck" "wrlck"
179 # setlk wrlck [0,9], getlk posix rdlck [5,24]
180 do_test "-s -w -o 0 -l 10" "-g -r -o 5 -l 20 -P" "wrlck" "unlck" "wrlck"
181 # setlk wrlck [0,9], getlk rdlck [20,29]
182 do_test "-s -w -o 0 -l 10" "-g -r -o 20 -l 10" "unlck" "unlck" "unlck"
183 # setlk posix wrlck [0,9], getlk rdlck [5,24]
184 do_test "-s -w -o 0 -l 10 -P" "-g -r -o 5 -l 20" "wrlck" "unlck" "unlck"
185 # setlk posix wrlck [0,9], getlk rdlck [20,29]
186 do_test "-s -w -o 0 -l 10 -P" "-g -r -o 20 -l 10" "unlck" "unlck" "unlck"
187
188 # setlk rdlck [0,9], getlk wrlck [0,9], open RDONLY
189 do_test "-s -r -o 0 -l 10 -R" "-g -w -o 0 -l 10 -R" "rdlck" "unlck" "rdlck"
190 # setlk rdlck [0,9], getlk wrlck [5,24], open RDONLY
191 do_test "-s -r -o 0 -l 10 -R" "-g -w -o 5 -l 20 -R -P" "rdlck" "unlck" "rdlck"
192 # setlk posix rdlck [0,9], getlk wrlck [5,24], open RDONLY
193 do_test "-s -r -o 0 -l 10 -R -P" "-g -w -o 5 -l 20 -R" "rdlck" "unlck" "unlck"
194
195 # setlk rdlck [0,9], getlk wrlck [0,9]
196 do_test "-s -r -o 0 -l 10" "-g -w -o 0 -l 10" "rdlck" "unlck" "rdlck"
197 # setlk rdlck [0,9], getlk posix wrlck [5,24]
198 do_test "-s -r -o 0 -l 10" "-g -w -o 5 -l 20 -P" "rdlck" "unlck" "rdlck"
199 # setlk posix rdlck [0,9], getlk wrlck [5,24]
200 do_test "-s -r -o 0 -l 10 -P" "-g -w -o 5 -l 20" "rdlck" "unlck" "unlck"
201
202 # setlk rdlck [0,9], getlk wrlck [20,29], open RDONLY
203 do_test "-s -r -o 0 -l 10 -R" "-g -w -o 20 -l 10 -R" "unlck" "unlck" "unlck"
204 # setlk posix rdlck [0,9], getlk wrlck [20,29], open RDONLY
205 do_test "-s -r -o 0 -l 10 -R -P" "-g -w -o 20 -l 10 -R" "unlck" "unlck" "unlck"
206 # setlk rdlck [0,9], getlk wrlck [20,29]
207 do_test "-s -r -o 0 -l 10" "-g -w -o 20 -l 10" "unlck" "unlck" "unlck"
208 # setlk posix rdlck [0,9], getlk wrlck [20,29]
209 do_test "-s -r -o 0 -l 10 -P" "-g -w -o 20 -l 10" "unlck" "unlck" "unlck"
210
211 # setlk rdlck [0,9], getlk rdlck [0,9], open RDONLY
212 do_test "-s -r -o 0 -l 10 -R" "-g -r -o 0 -l 10 -R" "unlck" "unlck" "unlck"
213 # setlk rdlck [0,9], getlk posix rdlck [0,9], open RDONLY
214 do_test "-s -r -o 0 -l 10 -R" "-g -r -o 0 -l 10 -R -P" "unlck" "unlck" "unlck"
215 # setlk posix rdlck [0,9], getlk rdlck [0,9], open RDONLY
216 do_test "-s -r -o 0 -l 10 -R -P" "-g -r -o 0 -l 10 -R" "unlck" "unlck" "unlck"
217 # setlk rdlck [0,9], getlk rdlck [0,9]
218 do_test "-s -r -o 0 -l 10" "-g -r -o 0 -l 10" "unlck" "unlck" "unlck"
219 # setlk posix rdlck [0,9], getlk rdlck [0,9]
220 do_test "-s -r -o 0 -l 10 -P" "-g -r -o 0 -l 10" "unlck" "unlck" "unlck"
221
222 # setlk rdlck [0,9], getlk rdlck [20,29], open RDONLY
223 do_test "-s -r -o 0 -l 10 -R" "-g -r -o 20 -l 10 -R" "unlck" "unlck" "unlck"
224 # setlk rdlck [0,9], getlk posix rdlck [20,29], open RDONLY
225 do_test "-s -r -o 0 -l 10 -R" "-g -r -o 20 -l 10 -R -P" "unlck" "unlck" "unlck"
226 # setlk posix rdlck [0,9], getlk rdlck [20,29], open RDONLY
227 do_test "-s -r -o 0 -l 10 -R -P" "-g -r -o 20 -l 10 -R" "unlck" "unlck" "unlck"
228 # setlk rdlck [0,9], getlk rdlck [20,29]
229 do_test "-s -r -o 0 -l 10" "-g -r -o 20 -l 10" "unlck" "unlck" "unlck"
230 # setlk posix rdlck [0,9], getlk rdlck [20,29]
231 do_test "-s -r -o 0 -l 10 -P" "-g -r -o 20 -l 10" "unlck" "unlck" "unlck"
232
233 # success, all done
234 status=0
235 exit