generic/413, xfs/260: Improve format operation for PMD fault testing
[xfstests-dev.git] / common / inject
1 ##/bin/bash
2 # SPDX-License-Identifier: GPL-2.0+
3 # Copyright (c) 2016 Oracle.  All Rights Reserved.
4 #
5 # Routines for injecting errors into filesystems
6
7 . ./common/log
8
9 # Tests whether $FSTYP is one of the filesystems that supports error injection
10 _require_error_injection()
11 {
12         case "$FSTYP" in
13         "xfs")
14                 grep -q 'debug 1' /proc/fs/xfs/stat || \
15                         _notrun "XFS error injection requires CONFIG_XFS_DEBUG"
16                 ;;
17         *)
18                 _notrun "Error injection not supported on filesystem type: $FSTYP"
19         esac
20 }
21
22 # Find the errortag injection knob in sysfs for a given xfs mount's
23 # block device.
24 _find_xfs_mountdev_errortag_knob()
25 {
26         dev="$1"
27         knob="$2"
28         shortdev="$(_short_dev "${dev}")"
29         tagfile="/sys/fs/xfs/${shortdev}/errortag/${knob}"
30
31         # Some of the new sysfs errortag knobs were previously available via
32         # another sysfs path.
33         case "${knob}" in
34         "log_bad_crc")
35                 if [ ! -w "${tagfile}" ]; then
36                         tagfile="/sys/fs/xfs/${shortdev}/log/log_badcrc_factor"
37                 fi
38                 ;;
39         "drop_writes")
40                 if [ ! -w "${tagfile}" ]; then
41                         tagfile="/sys/fs/xfs/${shortdev}/drop_writes"
42                 fi
43                 if [ ! -w "${tagfile}" ]; then
44                         tagfile="/sys/fs/xfs/${shortdev}/fail_writes"
45                 fi
46                 ;;
47         *)
48                 ;;
49         esac
50
51         echo "${tagfile}"
52 }
53
54 # Requires that xfs_io inject command knows about this error type
55 _require_xfs_io_error_injection()
56 {
57         type="$1"
58         _require_error_injection
59
60         # Can we find the error injection knobs via the new errortag
61         # configuration mechanism?
62         knob="$(_find_xfs_mountdev_errortag_knob "${TEST_DEV}" "${type}")"
63         test -w "${knob}" && return
64
65         # If the directory containing the sysfs error injection knob exists
66         # but the knob itself isn't usable, this kernel doesn't know about
67         # the knob.  Skip the test.
68         if [ -d "$(dirname "${knob}")" ]; then
69                 _notrun "XFS error injection $type unknown on this kernel."
70         fi
71
72         # NOTE: We can't actually test error injection here because xfs
73         # hasn't always range checked the argument to xfs_errortag_add.
74         # We also don't want to trip an error before we're ready to deal
75         # with it.
76
77         $XFS_IO_PROG -x -c 'inject' $TEST_DIR | grep -q "$type" || \
78                 _notrun "XFS error injection $type unknown."
79 }
80
81 # Inject an error into the test fs
82 _test_inject_error()
83 {
84         type="$1"
85         value="$2"
86
87         knob="$(_find_xfs_mountdev_errortag_knob "${TEST_DEV}" "${type}")"
88         if [ -w "${knob}" ]; then
89                 test -z "${value}" && value="default"
90                 echo -n "${value}" > "${knob}"
91         elif [ -z "${value}" ] || [ "${value}" = "default" ]; then
92                 $XFS_IO_PROG -x -c "inject $type" $TEST_DIR
93         else
94                 _fail "Cannot inject error ${type} value ${value}."
95         fi
96 }
97
98 # Inject an error into the scratch fs
99 _scratch_inject_error()
100 {
101         type="$1"
102         value="$2"
103
104         knob="$(_find_xfs_mountdev_errortag_knob "${SCRATCH_DEV}" "${type}")"
105         if [ -w "${knob}" ]; then
106                 test -z "${value}" && value="default"
107                 echo -n "${value}" > "${knob}"
108         elif [ -z "${value}" ] || [ "${value}" = "default" ]; then
109                 $XFS_IO_PROG -x -c "inject $type" $SCRATCH_MNT
110         else
111                 _fail "Cannot inject error ${type} value ${value}."
112         fi
113 }
114
115 # Unmount and remount the scratch device, dumping the log
116 _scratch_inject_logprint()
117 {
118         local opts="$1"
119
120         if test -n "$opts"; then
121                 opts="-o $opts"
122         fi
123         _scratch_unmount
124         _scratch_dump_log
125         _scratch_mount "$opts"
126 }
127
128 # Unmount and remount the test device, dumping the log
129 _test_inject_logprint()
130 {
131         local opts="$1"
132
133         if test -n "$opts"; then
134                 opts="-o $opts"
135         fi
136         _test_unmount
137         _test_dump_log
138         _test_mount "$opts"
139 }