summaryrefslogtreecommitdiff
path: root/tests/btrfs/220
blob: 2b62c9bbef13fe5828262bf7f3817f51b9ac427e (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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
#! /bin/bash
# SPDX-License-Identifier: GPL-2.0
# Copyright (C) 2020 SUSE Linux Products GmbH. All Rights Reserved.
#
# FS QA Test 220
#
# Test all existent mount options of btrfs
# * device= argument is already being test by btrfs/125
# * space cache test already covered by test btrfs/131
. ./common/preamble
_begin_fstest auto quick remount

_register_cleanup "cleanup"

. ./common/filter

_supported_fs btrfs
_require_scratch

cleanup()
{
	cd /
	rm -f $tmp.*
}

# Compare the mounted flags with $opt_check. When the comparison fails, $opt is
# echoed to help to track which option was used to trigger the unexpected
# results.
test_mount_flags()
{
	local opt
	local opt_check
	local stripped
	opt="$1"
	opt_check="$2"

	active_opt=$(cat /proc/self/mounts | grep $SCRATCH_MNT | \
					$AWK_PROG '{ print $4 }')

	if [ "$opt_check" != "$DEFAULT_OPTS" ]; then
		# We only care about the common things between defaults and the
		# active set, so strip out the uniq lines between the two, and
		# then we'll add this to our $opt_check which should equal
		# $active_opt.  We also strip 'rw' as we may be checking 'ro',
		# so we need to adjust that accordingly
		stripped=$(echo "$DEFAULT_OPTS,$active_opt" | tr ',' '\n' | \
				sort | grep -v 'rw' | uniq -d | tr '\n' ',' | \
				sed 's/.$//')
		opt_check="$opt_check,$stripped"
	fi

	# We diff by putting our wanted opts together with the current opts,
	# turning it into one option per line, sort'ing, and then printing out
	# any uniq lines left.  This will catch anything that is set that we're
	# not expecting, or anything that wasn't set that we wanted.
	#
	# We strip 'rw' because some tests flip ro, so just ignore rw.
	diff=$(echo "$opt_check,$active_opt" | tr ',' '\n' | \
		sort | grep -v 'rw' | uniq -u)
	if [ -n "$diff" ]; then
		echo "Unexepcted mount options, checking for '$opt_check' in '$active_opt' using '$opt'"
	fi
}

# Mounts using opt ($1), remounts using remount_opt ($2), and remounts again
# using opt again (1), checking if the mount opts are being enabled/disabled by
# using _check arguments ($3 and $4)
test_enable_disable_mount_opt()
{
	local opt
	local opt_check
	local remount_opt
	local remount_opt_check
	opt="$1"
	opt_check="$2"
	remount_opt="$3"
	remount_opt_check="$4"

	_scratch_mount "-o $opt"

	test_mount_flags $opt $opt_check

	_scratch_remount $remount_opt

	test_mount_flags $remount_opt $remount_opt_check

	_scratch_remount $opt

	test_mount_flags $opt $opt_check

	_scratch_unmount
}

# Checks if mount options are applied and reverted correctly.
# By using options to mount ($1) and remount ($2), this function will mount,
# remount, and the mount with the original args, checking if the mount options
# match the _check args ($3 and $4).

# Later, opt and remount_opt are swapped, testing the counterpart option if used
# to first mount the fs.
test_roundtrip_mount()
{
	local opt
	local opt_check
	local remount_opt
	local remount_opt_check
	opt="$1"
	opt_check="$2"
	remount_opt="$3"
	remount_opt_check="$4"

	# invert the args to make sure that both options work at mount and
	# remount time
	test_enable_disable_mount_opt $opt $opt_check $remount_opt $remount_opt_check
	test_enable_disable_mount_opt $remount_opt $remount_opt_check $opt $opt_check
}

# Just mount and check if the options were mounted correctly by comparing the
# results with $opt_check
test_mount_opt()
{
	local opt
	local opt_check
	local active_opt
	opt="$1"
	opt_check="$2"

	_scratch_mount "-o $opt"

	test_mount_flags $opt $opt_check

	_scratch_unmount
}

# Test mount options that should fail, usually by wrong arguments to options
test_should_fail()
{
	local opt
	opt="$1"

	# wrong $opt on purpose, should fail
	_try_scratch_mount "-o $opt" >/dev/null 2>&1
	if [ $? -ne 0 ]; then
		return
	fi
	echo "Option $opt should fail to mount"
	_scratch_unmount
}

# Try to mount using $opt, and bail our if the mount fails without errors. If
# the mount succeeds, then compare the mount options with $opt_check
test_optional_mount_opts()
{
	local opt
	local opt_check
	opt="$1"
	opt_check="$2"

	# $opt not enabled, return without running any tests
	_try_scratch_mount "-o $opt" >/dev/null 2>&1 || return
	_scratch_unmount

	# option enabled, run the test
	test_mount_opt $opt $opt_check
}

# Testes related to subvolumes, from subvol and subvolid options.
test_subvol()
{
	test_should_fail "subvol=vol2"

	_scratch_mount "-o subvol=vol1"
	if [ ! -f "$SCRATCH_MNT/file.txt" ]; then
		echo "file.txt not found inside vol1 using subvol=vol1 mount option"
	fi
	_scratch_unmount

	test_should_fail "subvolid=222"

	_scratch_mount "-o subvolid=256"
	if [ ! -f "$SCRATCH_MNT/file.txt" ]; then
		echo "file.txt not found inside vol1 using subvolid=256 mount option"
	fi
	_scratch_unmount

	# subvol and subvolid should point to the same subvolume
	test_should_fail "-o subvol=vol1,subvolid=1234132"

	test_mount_opt "subvol=vol1,subvolid=256" "subvolid=256,subvol=/vol1"
	test_roundtrip_mount "subvol=vol1" "subvolid=256,subvol=/vol1" "subvolid=256" "subvolid=256,subvol=/vol1"
}

# These options are enable at kernel compile time, so no bother if they fail
test_optional_kernel_features()
{
	# Test options that are enabled by kernel config, and so can fail safely
	test_optional_mount_opts "check_int" "check_int"
	test_optional_mount_opts "check_int_data" "check_int_data"
	test_optional_mount_opts "check_int_print_mask=123" "check_int_print_mask=123"

	test_should_fail "fragment=invalid"
	test_optional_mount_opts "fragment=all" "fragment=data,fragment=metadata"
	test_optional_mount_opts "fragment=data" "fragment=data"
	test_optional_mount_opts "fragment=metadata" "fragment=metadata"
}

test_non_revertible_options()
{
	test_mount_opt "degraded" "degraded"

	# nologreplay should be used only with readonly
	test_should_fail "nologreplay"

	if [ "$enable_rescue_nologreplay" = true ]; then
		#rescue=nologreplay should be used only with readonly
		test_should_fail "rescue=nologreplay"

		test_mount_opt "nologreplay,ro" "ro,rescue=nologreplay"
		test_mount_opt "rescue=nologreplay,ro" "ro,rescue=nologreplay"
	else
		test_mount_opt "nologreplay,ro" "ro,nologreplay"
	fi

	test_mount_opt "rescan_uuid_tree" "rescan_uuid_tree"
	test_mount_opt "skip_balance" "skip_balance"
	test_mount_opt "user_subvol_rm_allowed" "user_subvol_rm_allowed"

	test_should_fail "rescue=invalid"
}

test_one_shot_options()
{
	if [ "$enable_clear_cache_shown" = true ]; then
		test_mount_opt "clear_cache" "clear_cache"
	else
		test_mount_opt "clear_cache" ""
	fi
}

# All these options can be reverted (with their "no" counterpart), or can have
# their values set to default on remount
test_revertible_options()
{
	test_roundtrip_mount "acl" "$DEFAULT_OPTS" "noacl" "noacl"
	test_roundtrip_mount "autodefrag" "autodefrag" "noautodefrag" "$DEFAULT_OPTS"
	test_roundtrip_mount "barrier" "$DEFAULT_OPTS" "nobarrier" "nobarrier"

	test_should_fail "commit=-10"
	# commit=0 sets the default, so btrfs hides this mount opt
	test_roundtrip_mount "commit=35" "commit=35" "commit=0" "$DEFAULT_OPTS"

	test_should_fail "compress=invalid"
	test_should_fail "compress-force=invalid"
	test_roundtrip_mount "compress" "compress=zlib:3" "compress=lzo" "compress=lzo"
	test_roundtrip_mount "compress=zstd" "compress=zstd:3" "compress=no" "$DEFAULT_OPTS"
	test_roundtrip_mount "compress-force=no" "$DEFAULT_OPTS" "compress-force=zstd" "compress-force=zstd:3"
	# zlib's max level is 9 and zstd's max level is 15
	test_roundtrip_mount "compress=zlib:20" "compress=zlib:9" "compress=zstd:16" "compress=zstd:15"
	test_roundtrip_mount "compress-force=lzo" "compress-force=lzo" "compress-force=zlib:4" "compress-force=zlib:4"

	if ! _scratch_btrfs_is_zoned; then
		# on remount, if we only pass datacow after nodatacow was used it will remain with nodatasum
		test_roundtrip_mount "nodatacow" "nodatasum,nodatacow" "datacow,datasum" "$DEFAULT_OPTS"
		# nodatacow disabled compression
		test_roundtrip_mount "compress-force" "compress-force=zlib:3" "nodatacow" "nodatasum,nodatacow"

		# nodatacow disabled both datacow and datasum, and datasum enabled datacow and datasum
		test_roundtrip_mount "nodatacow" "nodatasum,nodatacow" "datasum" "$DEFAULT_OPTS"
		test_roundtrip_mount "nodatasum" "nodatasum" "datasum" "$DEFAULT_OPTS"
	fi

	test_should_fail "discard=invalid"
	if [ "$enable_discard_sync" = true ]; then
		test_roundtrip_mount "discard" "discard" "discard=sync" "discard"
		if ! _scratch_btrfs_is_zoned; then
			test_roundtrip_mount "discard=async" "discard=async" "discard=sync" "discard"
		fi
		test_roundtrip_mount "discard=sync" "discard" "nodiscard" "$DEFAULT_NODISCARD_OPTS"
	else
		test_roundtrip_mount "discard" "discard" "discard" "discard"
		test_roundtrip_mount "discard" "discard" "nodiscard" "$DEFAULT_NODISCARD_OPTS"
	fi

	test_roundtrip_mount "enospc_debug" "enospc_debug" "noenospc_debug" "$DEFAULT_OPTS"

	test_should_fail "fatal_errors=pani"
	# fatal_errors=bug is the default
	test_roundtrip_mount "fatal_errors=panic" "fatal_errors=panic" "fatal_errors=bug" "$DEFAULT_OPTS"

	test_roundtrip_mount "flushoncommit" "flushoncommit" "noflushoncommit" "$DEFAULT_OPTS"

	# 2048 is the max_inline default value
	test_roundtrip_mount "max_inline=1024" "max_inline=1024" "max_inline=2048" "$DEFAULT_OPTS"

	test_roundtrip_mount "metadata_ratio=0" "$DEFAULT_OPTS" "metadata_ratio=10" "metadata_ratio=10"

	# ssd_spread implies ssd, while nossd_spread only disables ssd_spread
	test_roundtrip_mount "ssd_spread" "ssd_spread" "nossd" "nossd"
	test_roundtrip_mount "ssd" "ssd" "nossd" "nossd"
	test_mount_opt "ssd" "ssd"

	test_should_fail "thread_pool=-10"
	test_should_fail "thread_pool=0"
	test_roundtrip_mount "thread_pool=10" "thread_pool=10" "thread_pool=50" "thread_pool=50"

	test_roundtrip_mount "notreelog" "notreelog" "treelog" "$DEFAULT_OPTS"
}

# Find out if the running kernel supports the -o discard=sync option.
_scratch_mkfs >/dev/null
MOUNT_OPTIONS=
enable_discard_sync=false
_try_scratch_mount "-o discard=sync" > /dev/null 2>&1 && \
	{ enable_discard_sync=true; _scratch_unmount; }

enable_rescue_nologreplay=false
_try_scratch_mount "-o ro,rescue=nologreplay" > /dev/null 2>&1 && \
	{ enable_rescue_nologreplay=true; _scratch_unmount; }

enable_clear_cache_shown=false
_try_scratch_mount "-o clear_cache" > /dev/null 2>&1 && \
	{ shown_opts=$(cat /proc/self/mounts | grep $SCRATCH_MNT | \
		       $AWK_PROG '{ print $4 }')
	  echo $shown_opts | grep -q clear_cache && enable_clear_cache_shown=true
	  _scratch_unmount; }

_scratch_mkfs >/dev/null

# This test checks mount options, so having random MOUNT_OPTIONS set could
# affect the results of a few of these tests.
MOUNT_OPTIONS=

# create a subvolume that will be used later
_scratch_mount

# We need to save the current default options so we can validate our changes
# from one mount option to the next one.
DEFAULT_OPTS=$(cat /proc/self/mounts | grep $SCRATCH_MNT | \
		$AWK_PROG '{ print $4 }')

# Since 63a7cb130718 ("btrfs: auto enable discard=async when possible"),
# "discard=async" will be automatically enabled if the device supports.
# This can screw up our test against nodiscard options, thus remove the
# default "discard=async" mount option for "nodiscard" tests.
DEFAULT_NODISCARD_OPTS=$(echo -n "$DEFAULT_OPTS" | $SED_PROG 's/,discard=async//')

$BTRFS_UTIL_PROG subvolume create "$SCRATCH_MNT/vol1" > /dev/null
touch "$SCRATCH_MNT/vol1/file.txt"
_scratch_unmount

test_optional_kernel_features

test_non_revertible_options

test_one_shot_options

test_revertible_options

test_subvol

echo "Silence is golden"

status=0
exit