summaryrefslogtreecommitdiff
path: root/common/config
blob: 479e50d1ad56a759ebf75283d569894453f1f76f (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
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
##/bin/bash
# SPDX-License-Identifier: GPL-2.0
# Copyright (c) 2000-2003,2006 Silicon Graphics, Inc.  All Rights Reserved.
#
# setup and check for config parameters, and in particular
#
# EMAIL -           email of the script runner.
# TEST_DIR -        scratch test directory that is in an already
#                   mounted XFS file system, needs to be be world
#                   writeable
# TEST_DEV -        device for file system containing TEST_DIR
#
# and optionally:
# SCRATCH_DEV -     device you can make a scratch file system on
# SCRATCH_MNT -     mount point for scratch file system
# SCRATCH_LOGDEV -  scratch log device for external log testing
# SCRATCH_RTDEV -   scratch rt dev
# TEST_LOGDEV -     test log device for external log testing
# TEST_RTDEV -      test rt dev
# TAPE_DEV -        the tape device for the xfsdump tests
# RMT_TAPE_DEV -    the remote tape device for the xfsdump tests
# RMT_IRIXTAPE_DEV- the IRIX remote tape device for the xfsdump tests
# RMT_TAPE_USER -   remote user for tape device
# SELINUX_MOUNT_OPTIONS - Options to use when SELinux is enabled.
# KEEP_DMESG -      whether to keep all dmesg for each test case.
#                   yes: keep all dmesg
#                   no: only keep dmesg with error/warning (default)
#
# - These can be added to $HOST_CONFIG_DIR (witch default to ./config)
#   below or a separate local configuration file can be used (using
#   the HOST_OPTIONS variable).
# - This script is shared by the stress test system and the auto-qa
#   system
# - TEST_DEV & TEST_DIR must be assigned.
# - this script shouldn't make any assertions about filesystem
#   validity or mountedness.
#

. common/test_names

# all tests should use a common language setting to prevent golden
# output mismatches.
export LANG=C
export LC_ALL=C

PATH=".:$PATH"

export HOST=`hostname -s`
test `uname -s` = "Linux" || _fatal "fstests only supports Linux"

export MODULAR=0               # using XFS as a module or not
export BOOT="/boot"            # install target for kernels
export EXTRA=${EXTRA:=xfs-qa}

# general parameters (mainly for auto-qa)
export SOAK_PROC=3             # -p option to fsstress
export SOAK_STRESS=10000       # -n option to fsstress
export SOAK_PASSES=-1          # count of repetitions of fsstress (while soaking)
export EMAIL=root@localhost    # where auto-qa will send its status messages
export HOST_OPTIONS=${HOST_OPTIONS:=local.config}
export CHECK_OPTIONS=${CHECK_OPTIONS:="-g auto"}
export BENCH_PASSES=${BENCH_PASSES:=5}
export TIME_FACTOR=${TIME_FACTOR:=1}
export LOAD_FACTOR=${LOAD_FACTOR:=1}
export DEBUGFS_MNT=${DEBUGFS_MNT:="/sys/kernel/debug"}

# some constants for overlayfs setup
export OVL_UPPER="ovl-upper"
export OVL_LOWER="ovl-lower"
export OVL_WORK="ovl-work"
# overlay mount point parent must be the base fs root
export OVL_MNT="ovl-mnt"
# By default unionmount-testsuite is expected under src
export UNIONMOUNT_TESTSUITE=${UNIONMOUNT_TESTSUITE:=$here/src/unionmount-testsuite}

# From e2fsprogs/e2fsck/e2fsck.h:
# Exit code used by fsck-type programs
export FSCK_OK=0
export FSCK_NONDESTRUCT=1
export FSCK_REBOOT=2
export FSCK_UNCORRECTED=4
export FSCK_ERROR=8
export FSCK_USAGE=16
export FSCK_CANCELED=32
export FSCK_LIBRARY=128

export PWD=`pwd`
#export DEBUG=${DEBUG:=...} # arbitrary CFLAGS really.
export MALLOCLIB=${MALLOCLIB:=/usr/lib/libefence.a}
export LOCAL_CONFIGURE_OPTIONS=${LOCAL_CONFIGURE_OPTIONS:=--enable-readline=yes}

export RECREATE_TEST_DEV=false

# Handle mkfs.$fstyp which does (or does not) require -f to overwrite
set_mkfs_prog_path_with_opts()
{
	local fstyp=$1
	local p=$(type -P mkfs.$fstyp)

	# Note: mkfs.f2fs doesn't support the --help option yet, but it doesn't
	# matter since it also prints the help when an invalid option is given.
	if [ "$p" != "" ] && \
		$p --help |& grep -q "[[:space:]]-f[[:space:]|]"; then
		echo "$p -f"
	else
		echo $p
	fi
}

_fatal()
{
    echo "$*"
    status=1
    exit 1
}

export MKFS_PROG="$(type -P mkfs)"
[ "$MKFS_PROG" = "" ] && _fatal "mkfs not found"

export MOUNT_PROG="$(type -P mount)"
[ "$MOUNT_PROG" = "" ] && _fatal "mount not found"

export UMOUNT_PROG="$(type -P umount)"
[ "$UMOUNT_PROG" = "" ] && _fatal "umount not found"

export FSSTRESS_PROG="./ltp/fsstress"
[ ! -x $FSSTRESS_PROG ] && _fatal "fsstress not found or executable"

export PERL_PROG="$(type -P perl)"
[ "$PERL_PROG" = "" ] && _fatal "perl not found"

export AWK_PROG="$(type -P awk)"
[ "$AWK_PROG" = "" ] && _fatal "awk not found"

export SED_PROG="$(type -P sed)"
[ "$SED_PROG" = "" ] && _fatal "sed not found"

export BC_PROG="$(type -P bc)"
[ "$BC_PROG" = "" ] && _fatal "bc not found"

export PS_ALL_FLAGS="-ef"

export DF_PROG="$(type -P df)"
[ "$DF_PROG" = "" ] && _fatal "df not found"
export DF_PROG="$DF_PROG -T -P"	# Linux

export XFS_IO_PROG="$(type -P xfs_io)"
[ "$XFS_IO_PROG" = "" ] && _fatal "xfs_io not found"

export MKSWAP_PROG="$(type -P mkswap)"
# mkswap from util-linux v2.17.2 or older needs "-f" option to force to erase
# bootbits sectors
MKSWAP_PROG="$MKSWAP_PROG -f"

export XFS_LOGPRINT_PROG="$(type -P xfs_logprint)"
export XFS_REPAIR_PROG="$(type -P xfs_repair)"
export XFS_DB_PROG="$(type -P xfs_db)"
export XFS_METADUMP_PROG="$(type -P xfs_metadump)"
export XFS_ADMIN_PROG="$(type -P xfs_admin)"
export XFS_GROWFS_PROG=$(type -P xfs_growfs)
export XFS_SPACEMAN_PROG="$(type -P xfs_spaceman)"
export XFS_SCRUB_PROG="$(type -P xfs_scrub)"
export XFS_PARALLEL_REPAIR_PROG="$(type -P xfs_prepair)"
export XFS_PARALLEL_REPAIR64_PROG="$(type -P xfs_prepair64)"
export __XFSDUMP_PROG="$(type -P xfsdump)"
if [ -n "$__XFSDUMP_PROG" ]; then
	export XFSDUMP_PROG="$__XFSDUMP_PROG -e"
else
	export XFSDUMP_PROG=""
fi
export XFSRESTORE_PROG="$(type -P xfsrestore)"
export XFSINVUTIL_PROG="$(type -P xfsinvutil)"
export GETFATTR_PROG="$(type -P getfattr)"
export SETFATTR_PROG="$(type -P setfattr)"
export CHACL_PROG="$(type -P chacl)"
export ATTR_PROG="$(type -P attr)"
export QUOTA_PROG="$(type -P quota)"
export XFS_QUOTA_PROG="$(type -P xfs_quota)"
export KILLALL_PROG="$(type -P killall)"
export INDENT_PROG="$(type -P indent)"
export XFS_COPY_PROG="$(type -P xfs_copy)"
export FSTRIM_PROG="$(type -P fstrim)"
export DUMPE2FS_PROG="$(type -P dumpe2fs)"
export RESIZE2FS_PROG="$(type -P resize2fs)"
export F2FS_IO_PROG="$(type -P f2fs_io)"
export FIO_PROG="$(type -P fio)"
export FILEFRAG_PROG="$(type -P filefrag)"
export E4DEFRAG_PROG="$(type -P e4defrag)"
export LOGGER_PROG="$(type -P logger)"
export DBENCH_PROG="$(type -P dbench)"
export DMSETUP_PROG="$(type -P dmsetup)"
export WIPEFS_PROG="$(type -P wipefs)"
export BLKDISCARD_PROG="$(type -P blkdiscard)"
export DUMP_PROG="$(type -P dump)"
export RESTORE_PROG="$(type -P restore)"
export LVM_PROG="$(type -P lvm)"
export LSATTR_PROG="$(type -P lsattr)"
export CHATTR_PROG="$(type -P chattr)"
export DEBUGFS_PROG="$(type -P debugfs)"
export UUIDGEN_PROG="$(type -P uuidgen)"
export GETRICHACL_PROG="$(type -P getrichacl)"
export SETRICHACL_PROG="$(type -P setrichacl)"
export KEYCTL_PROG="$(type -P keyctl)"
export XZ_PROG="$(type -P xz)"
export LZ4_PROG="$(type -P lz4)"
export FLOCK_PROG="$(type -P flock)"
export LDD_PROG="$(type -P ldd)"
export TIMEOUT_PROG="$(type -P timeout)"
export MAN_PROG="$(type -P man)"
export NFS4_SETFACL_PROG="$(type -P nfs4_setfacl)"
export NFS4_GETFACL_PROG="$(type -P nfs4_getfacl)"
export UBIUPDATEVOL_PROG="$(type -P ubiupdatevol)"
export THIN_CHECK_PROG="$(type -P thin_check)"
export PYTHON2_PROG="$(type -P python2)"
export SQLITE3_PROG="$(type -P sqlite3)"
export TIMEOUT_PROG="$(type -P timeout)"
export SETCAP_PROG="$(type -P setcap)"
export GETCAP_PROG="$(type -P getcap)"
export CAPSH_PROG="$(type -P capsh)"
export CHECKBASHISMS_PROG="$(type -P checkbashisms)"
export XFS_INFO_PROG="$(type -P xfs_info)"
export DUPEREMOVE_PROG="$(type -P duperemove)"
export CC_PROG="$(type -P cc)"
export FSVERITY_PROG="$(type -P fsverity)"
export OPENSSL_PROG="$(type -P openssl)"
export ACCTON_PROG="$(type -P accton)"
export E2IMAGE_PROG="$(type -P e2image)"
export BLKZONE_PROG="$(type -P blkzone)"
export GZIP_PROG="$(type -P gzip)"
export BTRFS_IMAGE_PROG="$(type -P btrfs-image)"

# use 'udevadm settle' or 'udevsettle' to wait for lv to be settled.
# newer systems have udevadm command but older systems like RHEL5 don't.
# But if neither one is available, just set it to "sleep 1" to wait for lv to
# be settled
UDEV_SETTLE_PROG="$(type -P udevadm)"
if [ "$UDEV_SETTLE_PROG" == "" ]; then
	# try udevsettle command
	UDEV_SETTLE_PROG="$(type -P udevsettle)"
else
	# udevadm is available, add 'settle' as subcommand
	UDEV_SETTLE_PROG="$UDEV_SETTLE_PROG settle"
fi
# neither command is available, use sleep 1
#
# Udev events are sent via netlink to userspace through
# kobject_uevent_net_broadcast(), and udev in userspace is in charge of
# handling the events. The command `udevadm settle` just checks if
# /run/udev/queue is 0, however, a kernel without CONFIG_NET will have
# kobject_uevent_net_broadcast() be a no-op, and so /run/udev/queue may not
# exist or always be 0. We check for /proc/net to see CONFIG_NET was enabled.
if [[ "$UDEV_SETTLE_PROG" == "" || ! -d /proc/net ]]; then
	UDEV_SETTLE_PROG="sleep 1"
fi
export UDEV_SETTLE_PROG

# Set MODPROBE_PATIENT_RM_TIMEOUT_SECONDS to "forever" if you want the patient
# modprobe removal to run forever trying to remove a module.
MODPROBE_REMOVE_PATIENT=""
modprobe --help >& /dev/null && modprobe --help | grep -q -1 "remove-patiently"
if [[ $? -ne 0 ]]; then
	if [[ -z "$MODPROBE_PATIENT_RM_TIMEOUT_SECONDS" ]]; then
		# We will open code our own implementation of patient module
		# remover in fstests. Use a 50 second default.
		export MODPROBE_PATIENT_RM_TIMEOUT_SECONDS="50"
	fi
else
	MODPROBE_RM_PATIENT_TIMEOUT_ARGS=""
	if [[ ! -z "$MODPROBE_PATIENT_RM_TIMEOUT_SECONDS" ]]; then
		if [[ "$MODPROBE_PATIENT_RM_TIMEOUT_SECONDS" != "forever" ]]; then
			MODPROBE_PATIENT_RM_TIMEOUT_MS="$((MODPROBE_PATIENT_RM_TIMEOUT_SECONDS * 1000))"
			MODPROBE_RM_PATIENT_TIMEOUT_ARGS="-t $MODPROBE_PATIENT_RM_TIMEOUT_MS"
		fi
	else
		# We export MODPROBE_PATIENT_RM_TIMEOUT_SECONDS here for parity
		# with environments without support for modprobe -p, but we
		# only really need it exported right now for environments which
		# don't have support for modprobe -p to implement our own
		# patient module removal support within fstests.
		export MODPROBE_PATIENT_RM_TIMEOUT_SECONDS="50"
		MODPROBE_PATIENT_RM_TIMEOUT_MS="$((MODPROBE_PATIENT_RM_TIMEOUT_SECONDS * 1000))"
		MODPROBE_RM_PATIENT_TIMEOUT_ARGS="-t $MODPROBE_PATIENT_RM_TIMEOUT_MS"
	fi
	MODPROBE_REMOVE_PATIENT="modprobe -p $MODPROBE_RM_PATIENT_TIMEOUT_ARGS"
fi
export MODPROBE_REMOVE_PATIENT

export MKFS_XFS_PROG=$(type -P mkfs.xfs)
export MKFS_EXT4_PROG=$(type -P mkfs.ext4)
export MKFS_UDF_PROG=$(type -P mkudffs)
export MKFS_BTRFS_PROG=$(set_mkfs_prog_path_with_opts btrfs)
export MKFS_F2FS_PROG=$(set_mkfs_prog_path_with_opts f2fs)
export DUMP_F2FS_PROG=$(type -P dump.f2fs)
export F2FS_IO_PROG=$(type -P f2fs_io)
export BTRFS_UTIL_PROG=$(type -P btrfs)
export BTRFS_SHOW_SUPER_PROG=$(type -P btrfs-show-super)
export BTRFS_CONVERT_PROG=$(type -P btrfs-convert)
export BTRFS_TUNE_PROG=$(type -P btrfstune)
export XFS_FSR_PROG=$(type -P xfs_fsr)
export MKFS_NFS_PROG="false"
export MKFS_CIFS_PROG="false"
export MKFS_OVERLAY_PROG="false"
export MKFS_REISER4_PROG=$(type -P mkfs.reiser4)
export E2FSCK_PROG=$(type -P e2fsck)
export TUNE2FS_PROG=$(type -P tune2fs)
export FSCK_OVERLAY_PROG=$(type -P fsck.overlay)

# SELinux adds extra xattrs which can mess up our expected output.
# So, mount with a context, and they won't be created.
#
# Since the context= option only accepts contexts defined in the SELinux
# policy, and different systems may have different policies with
# different context names, use the context of an existing directory.
# Assume that any valid context is fine, since xfstests should really
# only be run from an "unconfined" process, or with SELinux in permissive
# mode.  But if not, just specify your own SELINUX_MOUNT_OPTIONS.
if [ -x /usr/sbin/selinuxenabled ] && /usr/sbin/selinuxenabled; then
	: ${SELINUX_MOUNT_OPTIONS:="-o context=$(stat -c %C /)"}
	export SELINUX_MOUNT_OPTIONS
fi

# check if mkfs.xfs supports v5 xfs
if [ "$FSTYP" == "xfs" ]; then
	XFS_MKFS_HAS_NO_META_SUPPORT=""
	touch /tmp/crc_check.img
	$MKFS_XFS_PROG -N -d file,name=/tmp/crc_check.img,size=32m -m crc=0 \
		>/dev/null 2>&1;
	if [ $? -ne 0 ]; then
		XFS_MKFS_HAS_NO_META_SUPPORT=true
	fi
	rm -f /tmp/crc_check.img
	export XFS_MKFS_HAS_NO_META_SUPPORT
fi

_mount_opts()
{
	case $FSTYP in
	9p)
		export MOUNT_OPTIONS=$PLAN9_MOUNT_OPTIONS
		;;
	xfs)
		export MOUNT_OPTIONS=$XFS_MOUNT_OPTIONS
		;;
	udf)
		export MOUNT_OPTIONS=$UDF_MOUNT_OPTIONS
		;;
	nfs)
		export MOUNT_OPTIONS=$NFS_MOUNT_OPTIONS
		;;
	cifs)
		export MOUNT_OPTIONS=$CIFS_MOUNT_OPTIONS
		;;
	ceph)
		export MOUNT_OPTIONS=$CEPHFS_MOUNT_OPTIONS
		;;
	glusterfs)
		export MOUNT_OPTIONS=$GLUSTERFS_MOUNT_OPTIONS
		;;
	overlay)
		export MOUNT_OPTIONS=$OVERLAY_MOUNT_OPTIONS
		;;
	ext2|ext3|ext4|ext4dev)
		# acls & xattrs aren't turned on by default on ext$FOO
		export MOUNT_OPTIONS="-o acl,user_xattr $EXT_MOUNT_OPTIONS"
		;;
	f2fs)
		export MOUNT_OPTIONS="-o acl,user_xattr $F2FS_MOUNT_OPTIONS"
		;;
	reiserfs)
		# acls & xattrs aren't turned on by default on reiserfs
		export MOUNT_OPTIONS="-o acl,user_xattr $REISERFS_MOUNT_OPTIONS"
		;;
       reiser4)
               # acls & xattrs aren't supported by reiser4
               export MOUNT_OPTIONS=$REISER4_MOUNT_OPTIONS
               ;;
	gfs2)
		# acls aren't turned on by default on gfs2
		export MOUNT_OPTIONS="-o acl $GFS2_MOUNT_OPTIONS"
		;;
	tmpfs)
		# We need to specify the size at mount, use 1G by default
		export MOUNT_OPTIONS="-o size=1G $TMPFS_MOUNT_OPTIONS"
		;;
	ubifs)
		export MOUNT_OPTIONS=$UBIFS_MOUNT_OPTIONS
		;;
	*)
		;;
	esac
}

_test_mount_opts()
{
	case $FSTYP in
	9p)
		export TEST_FS_MOUNT_OPTS=$PLAN9_MOUNT_OPTIONS
		;;
	cifs)
		export TEST_FS_MOUNT_OPTS=$CIFS_MOUNT_OPTIONS
		;;
	ceph)
		export TEST_FS_MOUNT_OPTS=$CEPHFS_MOUNT_OPTIONS
		;;
	nfs)
		export TEST_FS_MOUNT_OPTS=$NFS_MOUNT_OPTIONS
		;;
	glusterfs)
		export TEST_FS_MOUNT_OPTS=$GLUSTERFS_MOUNT_OPTIONS
		;;
	ext2|ext3|ext4|ext4dev)
		# acls & xattrs aren't turned on by default on older ext$FOO
		export TEST_FS_MOUNT_OPTS="-o acl,user_xattr $EXT_MOUNT_OPTIONS"
		;;
	*)
		;;
	esac
}

_mkfs_opts()
{
	case $FSTYP in
	xfs)
		export MKFS_OPTIONS=$XFS_MKFS_OPTIONS
		;;
	udf)
		[ ! -z "$udf_fsize" ] && \
			UDF_MKFS_OPTIONS="$UDF_MKFS_OPTIONS -s $udf_fsize"
		export MKFS_OPTIONS=$UDF_MKFS_OPTIONS
		;;
	nfs)
		export MKFS_OPTIONS=$NFS_MKFS_OPTIONS
		;;
	cifs)
		export MKFS_OPTIONS=$CIFS_MKFS_OPTIONS
		;;
	ceph)
		export MKFS_OPTIONS=$CEPHFS_MKFS_OPTIONS
		;;
	reiserfs)
		export MKFS_OPTIONS="$REISERFS_MKFS_OPTIONS -q"
		;;
       reiser4)
		export MKFS_OPTIONS=$REISER4_MKFS_OPTIONS
		;;
	gfs2)
		export MKFS_OPTIONS="$GFS2_MKFS_OPTIONS -O -p lock_nolock"
		;;
	jfs)
		export MKFS_OPTIONS="$JFS_MKFS_OPTIONS -q"
		;;
	f2fs)
		export MKFS_OPTIONS="$F2FS_MKFS_OPTIONS"
		;;
	btrfs)
		export MKFS_OPTIONS="$BTRFS_MKFS_OPTIONS"
		;;
	bcachefs)
		export MKFS_OPTIONS=$BCACHEFS_MKFS_OPTIONS
		;;
	*)
		;;
	esac
}

_fsck_opts()
{
	case $FSTYP in
	ext2|ext3|ext4|ext4dev)
		export FSCK_OPTIONS="-nf"
		;;
	reiser*)
		export FSCK_OPTIONS="--yes"
		;;
	f2fs)
		export FSCK_OPTIONS=""
		;;
	*)
		export FSCK_OPTIONS="-n"
		;;
	esac
}

known_hosts()
{
	[ "$HOST_CONFIG_DIR" ] || HOST_CONFIG_DIR=`pwd`/configs

	[ -f /etc/xfsqa.config ]             && export HOST_OPTIONS=/etc/xfsqa.config
	[ -f $HOST_CONFIG_DIR/$HOST ]        && export HOST_OPTIONS=$HOST_CONFIG_DIR/$HOST
	[ -f $HOST_CONFIG_DIR/$HOST.config ] && export HOST_OPTIONS=$HOST_CONFIG_DIR/$HOST.config
}

# Returns a list of sections in config file
# Each section starts with the section name in the format
# [section_name1]. Only alphanumeric characters and '_' is allowed
# in the section name otherwise the section will not be resognised.
# Section name must be contained between square brackets.
get_config_sections() {
	sed -n -e "s/^\[\([[:alnum:]_-]*\)\]/\1/p" < $1
}

if [ ! -f "$HOST_OPTIONS" ]; then
	known_hosts
fi

export HOST_OPTIONS_SECTIONS="-no-sections-"
export OPTIONS_HAVE_SECTIONS=false
if [ -f "$HOST_OPTIONS" ]; then
	export HOST_OPTIONS_SECTIONS=`get_config_sections $HOST_OPTIONS`
	if [ -z "$HOST_OPTIONS_SECTIONS" ]; then
		. $HOST_OPTIONS
		export HOST_OPTIONS_SECTIONS="-no-sections-"
	else
		export OPTIONS_HAVE_SECTIONS=true
	fi
fi

_check_device()
{
	local name=$1
	local dev_needed=$2
	local dev=$3

	if [ -z "$dev" ]; then
		if [ "$dev_needed" == "required" ]; then
			_fatal "common/config: $name is required but not defined!"
		fi
		return 0
	fi

	if [ -b "$dev" ] || ( echo $dev | grep -qE ":|//" ); then
		# block device or a network url
		return 0
	fi

	case "$FSTYP" in
	9p|tmpfs|virtiofs)
		# 9p and virtiofs mount tags are just plain strings, so anything is allowed
		# tmpfs doesn't use mount source, ignore
		;;
	ceph)
		# ceph has two different possible syntaxes for mount devices. The
		# network URL check above catches the legacy syntax. Check for the
		# new-style syntax here.
		if ( echo $dev | grep -qEv "=/" ); then
			_fatal "common/config: $name ($dev) is not a valid ceph mount string"
		fi
		;;
	overlay)
		if [ ! -d "$dev" ]; then
			_fatal "common/config: $name ($dev) is not a directory for overlay"
		fi
		;;
	ubifs)
		if [ ! -c "$dev" ]; then
			_fatal "common/config: $name ($dev) is not a character device"
		fi
		;;
	*)
		_fatal "common/config: $name ($dev) is not a block device or a network filesystem"
	esac
}

# check and return a canonical mount point path
_canonicalize_mountpoint()
{
	local name=$1
	local dir=$2

	if [ -d "$dir" ]; then
		# this follows symlinks and removes all trailing "/"s
		readlink -e "$dir"
		return 0
	fi

	if [ "$FSTYP" != "overlay" ] || [[ "$name" == OVL_BASE_* ]]; then
		_fatal "common/config: $name ($dir) is not a directory"
	fi

	# base fs may not be mounted yet, so just check that parent dir
	# exists (where base fs will be mounted) because we are going to
	# mkdir the overlay mount point dir anyway
	local base=`basename $dir`
	local parent=`dirname $dir`
	parent=`_canonicalize_mountpoint OVL_BASE_$name "$parent"`

	# prepend the overlay mount point to canonical parent path
	echo "$parent/$base"
}

# On check -overlay, for the non multi section config case, this
# function is called on every test, before init_rc().
# When SCRATCH/TEST_* vars are defined in config file, config file
# is sourced on every test and this function overrides the vars
# every time.
# When SCRATCH/TEST_* vars are defined in evironment and not
# in config file, this function is called after vars have already
# been overriden in the previous test.
# In that case, TEST_DEV is a directory and not a blockdev/chardev and
# the function will return without overriding the SCRATCH/TEST_* vars.
_overlay_config_override()
{
	# There are 2 options for configuring overlayfs tests:
	#
	# 1. (legacy) SCRATCH/TEST_DEV point to existing directories
	#    on an already mounted fs.  In this case, the new
	#    OVL_BASE_SCRATCH/TEST_* vars are set to use the legacy
	#    vars values (even though they may not be mount points).
	#
	[ ! -d "$TEST_DEV" ] || export OVL_BASE_TEST_DIR="$TEST_DEV"
	[ ! -d "$SCRATCH_DEV" ] || export OVL_BASE_SCRATCH_MNT="$SCRATCH_DEV"

	# 2. SCRATCH/TEST_DEV point to the base fs partitions.  In this case,
	#    the new OVL_BASE_SCRATCH/TEST_DEV/MNT vars are set to the values
	#    of the configured base fs and SCRATCH/TEST_DEV vars are set to the
	#    overlayfs base and mount dirs inside base fs mount.
	[ -b "$TEST_DEV" ] || [ -c "$TEST_DEV" ] || return 0

	# Config file may specify base fs type, but we obay -overlay flag
	[ "$FSTYP" == overlay ] || export OVL_BASE_FSTYP="$FSTYP"
	export FSTYP=overlay

	# Store original base fs vars
	export OVL_BASE_TEST_DEV="$TEST_DEV"
	export OVL_BASE_TEST_DIR="$TEST_DIR"
	# If config does not set MOUNT_OPTIONS, its value may be
	# leftover from previous _overlay_config_override, so
	# don't use that value for base fs mount
	[ "$MOUNT_OPTIONS" != "$OVERLAY_MOUNT_OPTIONS" ] || unset MOUNT_OPTIONS
	export OVL_BASE_MOUNT_OPTIONS="$MOUNT_OPTIONS"

	# Set TEST vars to overlay base and mount dirs inside base fs
	export TEST_DEV="$OVL_BASE_TEST_DIR"
	export TEST_DIR="$OVL_BASE_TEST_DIR/$OVL_MNT"
	export MOUNT_OPTIONS="$OVERLAY_MOUNT_OPTIONS"

	[ -b "$SCRATCH_DEV" ] || [ -c "$SCRATCH_DEV" ] || return 0

	# Store original base fs vars
	export OVL_BASE_SCRATCH_DEV="$SCRATCH_DEV"
	export OVL_BASE_SCRATCH_MNT="$SCRATCH_MNT"

	# Set SCRATCH vars to overlay base and mount dirs inside base fs
	export SCRATCH_DEV="$OVL_BASE_SCRATCH_MNT"
	export SCRATCH_MNT="$OVL_BASE_SCRATCH_MNT/$OVL_MNT"

	# Set fsck options, use default if user not set directly.
	export FSCK_OPTIONS="$OVERLAY_FSCK_OPTIONS"
	[ -z "$FSCK_OPTIONS" ] && _fsck_opts
}

_overlay_config_restore()
{
	export OVERLAY=true
	[ -z "$OVL_BASE_FSTYP" ] || export FSTYP=$OVL_BASE_FSTYP
	[ -z "$OVL_BASE_TEST_DEV" ] || export TEST_DEV=$OVL_BASE_TEST_DEV
	[ -z "$OVL_BASE_TEST_DIR" ] || export TEST_DIR=$OVL_BASE_TEST_DIR
	[ -z "$OVL_BASE_SCRATCH_DEV" ] || export SCRATCH_DEV=$OVL_BASE_SCRATCH_DEV
	[ -z "$OVL_BASE_SCRATCH_MNT" ] || export SCRATCH_MNT=$OVL_BASE_SCRATCH_MNT
	[ -z "$OVL_BASE_MOUNT_OPTIONS" ] || export MOUNT_OPTIONS=$OVL_BASE_MOUNT_OPTIONS
}

# Parse config section options. This function will parse all the configuration
# within a single section which name is passed as an argument. For section
# name format see comments in get_config_sections().
# Empty lines and everything after '#' will be ignored.
# Configuration options should be defined in the format
#
# CONFIG_OPTION=value
#
# This 'CONFIG_OPTION' variable and will be exported as an environment variable.
parse_config_section() {
	SECTION=$1
	if ! $OPTIONS_HAVE_SECTIONS; then
		return 0
	fi
	eval `sed -e 's/[[:space:]]*\=[[:space:]]*/=/g' \
		-e 's/#.*$//' \
		-e 's/[[:space:]]*$//' \
		-e 's/^[[:space:]]*//' \
		-e "s/^\([^=]*\)=\"\?'\?\([^\"']*\)\"\?'\?$/export \1=\"\2\"/" \
		< $HOST_OPTIONS \
		| sed -n -e "/^\[$SECTION\]/,/^\s*\[/{/^[^#].*\=.*/p;}"`
}

get_next_config() {
	if [ ! -z "$CONFIG_INCLUDED" ] && ! $OPTIONS_HAVE_SECTIONS; then
		return 0
	fi

	# We might have overriden FSTYP and TEST/SCRATCH vars with overlay values
	# in the previous section, so restore them to original values stored in
	# OVL_BASE_*.
	# We need to do this *before* old FSTYP and MOUNT_OPTIONS are recorded
	# and *before* SCRATCH_DEV and MOUNT_OPTIONS are unset
	if [ "$FSTYP" == "overlay" ]; then
		_overlay_config_restore
	fi

	local OLD_FSTYP=$FSTYP
	local OLD_MOUNT_OPTIONS=$MOUNT_OPTIONS
	local OLD_TEST_FS_MOUNT_OPTS=$TEST_FS_MOUNT_OPTS
	local OLD_MKFS_OPTIONS=$MKFS_OPTIONS
	local OLD_FSCK_OPTIONS=$FSCK_OPTIONS
	local OLD_USE_EXTERNAL=$USE_EXTERNAL

	unset MOUNT_OPTIONS
	unset TEST_FS_MOUNT_OPTS
	unset MKFS_OPTIONS
	unset FSCK_OPTIONS
	unset USE_EXTERNAL

	# We might have deduced SCRATCH_DEV from the SCRATCH_DEV_POOL in the previous
	# run, so we have to unset it now.
	if [ "$SCRATCH_DEV_NOT_SET" == "true" ]; then
		unset SCRATCH_DEV
	fi

	parse_config_section $1

	if [ ! -z "$OLD_FSTYP" ] && [ $OLD_FSTYP != $FSTYP ]; then
		[ -z "$MOUNT_OPTIONS" ] && _mount_opts
		[ -z "$TEST_FS_MOUNT_OPTS" ] && _test_mount_opts
		[ -z "$MKFS_OPTIONS" ] && _mkfs_opts
		[ -z "$FSCK_OPTIONS" ] && _fsck_opts

		# clear the external devices if we are not using them
		if [ -z "$USE_EXTERNAL" ]; then
			unset TEST_RTDEV
			unset TEST_LOGDEV
			unset SCRATCH_RTDEV
			unset SCRATCH_LOGDEV
		fi
	else
		[ -z "$MOUNT_OPTIONS" ] && export MOUNT_OPTIONS=$OLD_MOUNT_OPTIONS
		[ -z "$TEST_FS_MOUNT_OPTS" ] && export TEST_FS_MOUNT_OPTS=$OLD_TEST_FS_MOUNT_OPTS
		[ -z "$MKFS_OPTIONS" ] && export MKFS_OPTIONS=$OLD_MKFS_OPTIONS
		[ -z "$FSCK_OPTIONS" ] && export FSCK_OPTIONS=$OLD_FSCK_OPTIONS
		[ -z "$USE_EXTERNAL" ] && export USE_EXTERNAL=$OLD_USE_EXTERNAL
	fi

	# set default RESULT_BASE
	if [ -z "$RESULT_BASE" ]; then
		export RESULT_BASE="$here/results/"
	fi

	if [ "$FSTYP" == "tmpfs" ]; then
		if [ -z "TEST_DEV" ]; then
			export TEST_DEV=tmpfs_test
		fi
		if [ -z "SCRATCH_DEV" ]; then
			export TEST_DEV=tmpfs_scratch
		fi
	fi

	#  Mandatory Config values.
	MC=""
	[ -z "$EMAIL" ]          && MC="$MC EMAIL"
	[ -z "$TEST_DIR" ]       && MC="$MC TEST_DIR"
	[ -z "$TEST_DEV" ]       && MC="$MC TEST_DEV"

	if [ -n "$MC" ]; then
		echo "Warning: need to define parameters for host $HOST"
		echo "       or set variables:"
		echo "       $MC"
		exit 1
	fi

	_check_device TEST_DEV required $TEST_DEV
	export TEST_DIR=`_canonicalize_mountpoint TEST_DIR $TEST_DIR`

	# a btrfs tester will set only SCRATCH_DEV_POOL, we will put first of its dev
	# to SCRATCH_DEV and rest to SCRATCH_DEV_POOL to maintain the backward compatibility
	if [ ! -z "$SCRATCH_DEV_POOL" ]; then
		if [ ! -z "$SCRATCH_DEV" ]; then
			echo "common/config: Error: \$SCRATCH_DEV ($SCRATCH_DEV) should be unset when \$SCRATCH_DEV_POOL ($SCRATCH_DEV_POOL) is set"
			exit 1
		fi
		SCRATCH_DEV=`echo $SCRATCH_DEV_POOL | awk '{print $1}'`
		export SCRATCH_DEV
		export SCRATCH_DEV_NOT_SET=true
	fi

	_check_device SCRATCH_DEV optional $SCRATCH_DEV
	export SCRATCH_MNT=`_canonicalize_mountpoint SCRATCH_MNT $SCRATCH_MNT`

	if [ -n "$USE_EXTERNAL" ]; then
		_check_device TEST_RTDEV optional $TEST_RTDEV
		_check_device TEST_LOGDEV optional $TEST_LOGDEV
		_check_device SCRATCH_RTDEV optional $SCRATCH_RTDEV
		_check_device SCRATCH_LOGDEV optional $SCRATCH_LOGDEV
	fi

	# Override FSTYP from config when running ./check -overlay
	# and maybe override base fs TEST/SCRATCH_DEV with overlay base dirs.
	# We need to do this *after* default mount options are set by base FSTYP
	# and *after* SCRATCH_DEV is deduced from SCRATCH_DEV_POOL
	if [ "$OVERLAY" == "true" -o "$FSTYP" == "overlay" ]; then
		_overlay_config_override
	fi
}

if [ -z "$CONFIG_INCLUDED" ]; then
	get_next_config `echo $HOST_OPTIONS_SECTIONS | cut -f1 -d" "`
	export CONFIG_INCLUDED=true

	# Autodetect fs type based on what's on $TEST_DEV unless it's been set
	# externally
	if [ -z "$FSTYP" ] && [ ! -z "$TEST_DEV" ]; then
		FSTYP=`blkid -c /dev/null -s TYPE -o value $TEST_DEV`
	fi
	FSTYP=${FSTYP:=xfs}
	export FSTYP
	[ -z "$MOUNT_OPTIONS" ] && _mount_opts
	[ -z "$TEST_FS_MOUNT_OPTS" ] && _test_mount_opts
	[ -z "$MKFS_OPTIONS" ] && _mkfs_opts
	[ -z "$FSCK_OPTIONS" ] && _fsck_opts
else
	# We get here for the non multi section case, on every test that sources
	# common/rc after re-sourcing the HOST_OPTIONS config file.
	# Because of this re-sourcing, we need to re-canonicalize the configured
	# mount points and re-override TEST/SCRATCH_DEV overlay vars.

	# canonicalize the mount points
	# this follows symlinks and removes all trailing "/"s
	export TEST_DIR=`_canonicalize_mountpoint TEST_DIR $TEST_DIR`
	export SCRATCH_MNT=`_canonicalize_mountpoint SCRATCH_MNT $SCRATCH_MNT`

	# Override FSTYP from config when running ./check -overlay
	# and maybe override base fs TEST/SCRATCH_DEV with overlay base dirs
	if [ "$OVERLAY" == "true" -o "$FSTYP" == "overlay" ]; then
		_overlay_config_override
	fi
fi

# make sure this script returns success
/bin/true