fstests: fix group list generation for whacky test names
[xfstests-dev.git] / tests / btrfs / 220
1 #! /bin/bash
2 # SPDX-License-Identifier: GPL-2.0
3 # Copyright (C) 2020 SUSE Linux Products GmbH. All Rights Reserved.
4 #
5 # FS QA Test 220
6 #
7 # Test all existent mount options of btrfs
8 # * device= argument is already being test by btrfs/125
9 # * space cache test already covered by test btrfs/131
10 . ./common/preamble
11 _begin_fstest auto quick
12
13 _register_cleanup "cleanup"
14
15 # Import common functions.
16 . ./common/filter
17
18 _supported_fs btrfs
19 _require_scratch
20
21 cleanup()
22 {
23         cd /
24         rm -f $tmp.*
25 }
26
27 # Compare the mounted flags with $opt_check. When the comparison fails, $opt is
28 # echoed to help to track which option was used to trigger the unexpected
29 # results.
30 test_mount_flags()
31 {
32         local opt
33         local opt_check
34         local stripped
35         opt="$1"
36         opt_check="$2"
37
38         active_opt=$(cat /proc/self/mounts | grep $SCRATCH_MNT | \
39                                         $AWK_PROG '{ print $4 }')
40
41         if [ "$opt_check" != "$DEFAULT_OPTS" ]; then
42                 # We only care about the common things between defaults and the
43                 # active set, so strip out the uniq lines between the two, and
44                 # then we'll add this to our $opt_check which should equal
45                 # $active_opt.  We also strip 'rw' as we may be checking 'ro',
46                 # so we need to adjust that accordingly
47                 stripped=$(echo "$DEFAULT_OPTS,$active_opt" | tr ',' '\n' | \
48                                 sort | grep -v 'rw' | uniq -d | tr '\n' ',' | \
49                                 sed 's/.$//')
50                 opt_check="$opt_check,$stripped"
51         fi
52
53         # We diff by putting our wanted opts together with the current opts,
54         # turning it into one option per line, sort'ing, and then printing out
55         # any uniq lines left.  This will catch anything that is set that we're
56         # not expecting, or anything that wasn't set that we wanted.
57         #
58         # We strip 'rw' because some tests flip ro, so just ignore rw.
59         diff=$(echo "$opt_check,$active_opt" | tr ',' '\n' | \
60                 sort | grep -v 'rw' | uniq -u)
61         if [ -n "$diff" ]; then
62                 echo "Unexepcted mount options, checking for '$opt_check' in '$active_opt' using '$opt'"
63         fi
64 }
65
66 # Mounts using opt ($1), remounts using remount_opt ($2), and remounts again
67 # using opt again (1), checking if the mount opts are being enabled/disabled by
68 # using _check arguments ($3 and $4)
69 test_enable_disable_mount_opt()
70 {
71         local opt
72         local opt_check
73         local remount_opt
74         local remount_opt_check
75         opt="$1"
76         opt_check="$2"
77         remount_opt="$3"
78         remount_opt_check="$4"
79
80         _scratch_mount "-o $opt"
81
82         test_mount_flags $opt $opt_check
83
84         _scratch_remount $remount_opt
85
86         test_mount_flags $remount_opt $remount_opt_check
87
88         _scratch_remount $opt
89
90         test_mount_flags $opt $opt_check
91
92         _scratch_unmount
93 }
94
95 # Checks if mount options are applied and reverted correctly.
96 # By using options to mount ($1) and remount ($2), this function will mount,
97 # remount, and the mount with the original args, checking if the mount options
98 # match the _check args ($3 and $4).
99
100 # Later, opt and remount_opt are swapped, testing the counterpart option if used
101 # to first mount the fs.
102 test_roundtrip_mount()
103 {
104         local opt
105         local opt_check
106         local remount_opt
107         local remount_opt_check
108         opt="$1"
109         opt_check="$2"
110         remount_opt="$3"
111         remount_opt_check="$4"
112
113         # invert the args to make sure that both options work at mount and
114         # remount time
115         test_enable_disable_mount_opt $opt $opt_check $remount_opt $remount_opt_check
116         test_enable_disable_mount_opt $remount_opt $remount_opt_check $opt $opt_check
117 }
118
119 # Just mount and check if the options were mounted correctly by comparing the
120 # results with $opt_check
121 test_mount_opt()
122 {
123         local opt
124         local opt_check
125         local active_opt
126         opt="$1"
127         opt_check="$2"
128
129         _scratch_mount "-o $opt"
130
131         test_mount_flags $opt $opt_check
132
133         _scratch_unmount
134 }
135
136 # Test mount options that should fail, usually by wrong arguments to options
137 test_should_fail()
138 {
139         local opt
140         opt="$1"
141
142         # wrong $opt on purpose, should fail
143         _try_scratch_mount "-o $opt" >/dev/null 2>&1
144         if [ $? -ne 0 ]; then
145                 return
146         fi
147         echo "Option $opt should fail to mount"
148         _scratch_unmount
149 }
150
151 # Try to mount using $opt, and bail our if the mount fails without errors. If
152 # the mount succeeds, then compare the mount options with $opt_check
153 test_optional_mount_opts()
154 {
155         local opt
156         local opt_check
157         opt="$1"
158         opt_check="$2"
159
160         # $opt not enabled, return without running any tests
161         _try_scratch_mount "-o $opt" >/dev/null 2>&1 || return
162         _scratch_unmount
163
164         # option enabled, run the test
165         test_mount_opt $opt $opt_check
166 }
167
168 # Testes related to subvolumes, from subvol and subvolid options.
169 test_subvol()
170 {
171         test_should_fail "subvol=vol2"
172
173         _scratch_mount "-o subvol=vol1"
174         if [ ! -f "$SCRATCH_MNT/file.txt" ]; then
175                 echo "file.txt not found inside vol1 using subvol=vol1 mount option"
176         fi
177         _scratch_unmount
178
179         test_should_fail "subvolid=222"
180
181         _scratch_mount "-o subvolid=256"
182         if [ ! -f "$SCRATCH_MNT/file.txt" ]; then
183                 echo "file.txt not found inside vol1 using subvolid=256 mount option"
184         fi
185         _scratch_unmount
186
187         # subvol and subvolid should point to the same subvolume
188         test_should_fail "-o subvol=vol1,subvolid=1234132"
189
190         test_mount_opt "subvol=vol1,subvolid=256" "subvolid=256,subvol=/vol1"
191         test_roundtrip_mount "subvol=vol1" "subvolid=256,subvol=/vol1" "subvolid=256" "subvolid=256,subvol=/vol1"
192 }
193
194 # These options are enable at kernel compile time, so no bother if they fail
195 test_optional_kernel_features()
196 {
197         # Test options that are enabled by kernel config, and so can fail safely
198         test_optional_mount_opts "check_int" "check_int"
199         test_optional_mount_opts "check_int_data" "check_int_data"
200         test_optional_mount_opts "check_int_print_mask=123" "check_int_print_mask=123"
201
202         test_should_fail "fragment=invalid"
203         test_optional_mount_opts "fragment=all" "fragment=data,fragment=metadata"
204         test_optional_mount_opts "fragment=data" "fragment=data"
205         test_optional_mount_opts "fragment=metadata" "fragment=metadata"
206 }
207
208 test_non_revertible_options()
209 {
210         test_mount_opt "degraded" "degraded"
211
212         # nologreplay should be used only with readonly
213         test_should_fail "nologreplay"
214
215         # norecovery should be used only with readonly.
216         # This options is an alias to nologreplay
217         test_should_fail "norecovery"
218
219         if [ "$enable_rescue_nologreplay" = true ]; then
220                 #rescue=nologreplay should be used only with readonly
221                 test_should_fail "rescue=nologreplay"
222
223                 test_mount_opt "nologreplay,ro" "ro,rescue=nologreplay"
224                 test_mount_opt "norecovery,ro" "ro,rescue=nologreplay"
225                 test_mount_opt "rescue=nologreplay,ro" "ro,rescue=nologreplay"
226         else
227                 test_mount_opt "nologreplay,ro" "ro,nologreplay"
228                 test_mount_opt "norecovery,ro" "ro,nologreplay"
229         fi
230
231         test_mount_opt "rescan_uuid_tree" "rescan_uuid_tree"
232         test_mount_opt "skip_balance" "skip_balance"
233         test_mount_opt "user_subvol_rm_allowed" "user_subvol_rm_allowed"
234
235         test_should_fail "rescue=invalid"
236 }
237
238 test_one_shot_options()
239 {
240         if [ "$enable_clear_cache_shown" = true ]; then
241                 test_mount_opt "clear_cache" "clear_cache"
242         else
243                 test_mount_opt "clear_cache" ""
244         fi
245 }
246
247 # All these options can be reverted (with their "no" counterpart), or can have
248 # their values set to default on remount
249 test_revertible_options()
250 {
251         test_roundtrip_mount "acl" "$DEFAULT_OPTS" "noacl" "noacl"
252         test_roundtrip_mount "autodefrag" "autodefrag" "noautodefrag" "$DEFAULT_OPTS"
253         test_roundtrip_mount "barrier" "$DEFAULT_OPTS" "nobarrier" "nobarrier"
254
255         test_should_fail "commit=-10"
256         # commit=0 sets the default, so btrfs hides this mount opt
257         test_roundtrip_mount "commit=35" "commit=35" "commit=0" "$DEFAULT_OPTS"
258
259         test_should_fail "compress=invalid"
260         test_should_fail "compress-force=invalid"
261         test_roundtrip_mount "compress" "compress=zlib:3" "compress=lzo" "compress=lzo"
262         test_roundtrip_mount "compress=zstd" "compress=zstd:3" "compress=no" "$DEFAULT_OPTS"
263         test_roundtrip_mount "compress-force=no" "$DEFAULT_OPTS" "compress-force=zstd" "compress-force=zstd:3"
264         # zlib's max level is 9 and zstd's max level is 15
265         test_roundtrip_mount "compress=zlib:20" "compress=zlib:9" "compress=zstd:16" "compress=zstd:15"
266         test_roundtrip_mount "compress-force=lzo" "compress-force=lzo" "compress-force=zlib:4" "compress-force=zlib:4"
267
268         # on remount, if we only pass datacow after nodatacow was used it will remain with nodatasum
269         test_roundtrip_mount "nodatacow" "nodatasum,nodatacow" "datacow,datasum" "$DEFAULT_OPTS"
270         # nodatacow disabled compression
271         test_roundtrip_mount "compress-force" "compress-force=zlib:3" "nodatacow" "nodatasum,nodatacow"
272
273         # nodatacow disabled both datacow and datasum, and datasum enabled datacow and datasum
274         test_roundtrip_mount "nodatacow" "nodatasum,nodatacow" "datasum" "$DEFAULT_OPTS"
275         test_roundtrip_mount "nodatasum" "nodatasum" "datasum" "$DEFAULT_OPTS"
276
277         test_should_fail "discard=invalid"
278         if [ "$enable_discard_sync" = true ]; then
279                 test_roundtrip_mount "discard" "discard" "discard=sync" "discard"
280                 test_roundtrip_mount "discard=async" "discard=async" "discard=sync" "discard"
281                 test_roundtrip_mount "discard=sync" "discard" "nodiscard" "$DEFAULT_OPTS"
282         else
283                 test_roundtrip_mount "discard" "discard" "discard" "discard"
284                 test_roundtrip_mount "discard" "discard" "nodiscard" "$DEFAULT_OPTS"
285         fi
286
287         test_roundtrip_mount "enospc_debug" "enospc_debug" "noenospc_debug" "$DEFAULT_OPTS"
288
289         test_should_fail "fatal_errors=pani"
290         # fatal_errors=bug is the default
291         test_roundtrip_mount "fatal_errors=panic" "fatal_errors=panic" "fatal_errors=bug" "$DEFAULT_OPTS"
292
293         test_roundtrip_mount "flushoncommit" "flushoncommit" "noflushoncommit" "$DEFAULT_OPTS"
294
295         # 2048 is the max_inline default value
296         test_roundtrip_mount "max_inline=1024" "max_inline=1024" "max_inline=2048" "$DEFAULT_OPTS"
297
298         test_roundtrip_mount "metadata_ratio=0" "$DEFAULT_OPTS" "metadata_ratio=10" "metadata_ratio=10"
299
300         # ssd_spread implies ssd, while nossd_spread only disables ssd_spread
301         test_roundtrip_mount "ssd_spread" "ssd_spread" "nossd" "nossd"
302         test_roundtrip_mount "ssd" "ssd" "nossd" "nossd"
303         test_mount_opt "ssd" "ssd"
304
305         test_should_fail "thread_pool=-10"
306         test_should_fail "thread_pool=0"
307         test_roundtrip_mount "thread_pool=10" "thread_pool=10" "thread_pool=50" "thread_pool=50"
308
309         test_roundtrip_mount "notreelog" "notreelog" "treelog" "$DEFAULT_OPTS"
310 }
311
312 # Find out if the running kernel supports the -o discard=sync option.
313 _scratch_mkfs >/dev/null
314 MOUNT_OPTIONS=
315 enable_discard_sync=false
316 _try_scratch_mount "-o discard=sync" > /dev/null 2>&1 && \
317         { enable_discard_sync=true; _scratch_unmount; }
318
319 enable_rescue_nologreplay=false
320 _try_scratch_mount "-o ro,rescue=nologreplay" > /dev/null 2>&1 && \
321         { enable_rescue_nologreplay=true; _scratch_unmount; }
322
323 enable_clear_cache_shown=false
324 _try_scratch_mount "-o clear_cache" > /dev/null 2>&1 && \
325         { shown_opts=$(cat /proc/self/mounts | grep $SCRATCH_MNT | \
326                        $AWK_PROG '{ print $4 }')
327           echo $shown_opts | grep -q clear_cache && enable_clear_cache_shown=true
328           _scratch_unmount; }
329
330 # real QA test starts here
331 _scratch_mkfs >/dev/null
332
333 # This test checks mount options, so having random MOUNT_OPTIONS set could
334 # affect the results of a few of these tests.
335 MOUNT_OPTIONS=
336
337 # create a subvolume that will be used later
338 _scratch_mount
339
340 # We need to save the current default options so we can validate our changes
341 # from one mount option to the next one.
342 DEFAULT_OPTS=$(cat /proc/self/mounts | grep $SCRATCH_MNT | \
343                 $AWK_PROG '{ print $4 }')
344
345 $BTRFS_UTIL_PROG subvolume create "$SCRATCH_MNT/vol1" > /dev/null
346 touch "$SCRATCH_MNT/vol1/file.txt"
347 _scratch_unmount
348
349 test_optional_kernel_features
350
351 test_non_revertible_options
352
353 test_one_shot_options
354
355 test_revertible_options
356
357 test_subvol
358
359 echo "Silence is golden"
360
361 status=0
362 exit