| ##/bin/bash | |
| # SPDX-License-Identifier: GPL-2.0+ | |
| # Copyright (c) 2016 Oracle. All Rights Reserved. | |
| # | |
| # Routines for injecting errors into filesystems | |
| . ./common/log | |
| # Tests whether $FSTYP is one of the filesystems that supports error injection | |
| _require_error_injection() | |
| { | |
| case "$FSTYP" in | |
| "xfs") | |
| grep -q 'debug 1' /proc/fs/xfs/stat || \ | |
| _notrun "XFS error injection requires CONFIG_XFS_DEBUG" | |
| ;; | |
| *) | |
| _notrun "Error injection not supported on filesystem type: $FSTYP" | |
| esac | |
| } | |
| # Find the errortag injection knob in sysfs for a given xfs mount's | |
| # block device. | |
| _find_xfs_mountdev_errortag_knob() | |
| { | |
| dev="$1" | |
| knob="$2" | |
| shortdev="$(_short_dev "${dev}")" | |
| tagfile="/sys/fs/xfs/${shortdev}/errortag/${knob}" | |
| # Some of the new sysfs errortag knobs were previously available via | |
| # another sysfs path. | |
| case "${knob}" in | |
| "log_bad_crc") | |
| if [ ! -w "${tagfile}" ]; then | |
| tagfile="/sys/fs/xfs/${shortdev}/log/log_badcrc_factor" | |
| fi | |
| ;; | |
| "drop_writes") | |
| if [ ! -w "${tagfile}" ]; then | |
| tagfile="/sys/fs/xfs/${shortdev}/drop_writes" | |
| fi | |
| if [ ! -w "${tagfile}" ]; then | |
| tagfile="/sys/fs/xfs/${shortdev}/fail_writes" | |
| fi | |
| ;; | |
| *) | |
| ;; | |
| esac | |
| echo "${tagfile}" | |
| } | |
| # Requires that xfs_io inject command knows about this error type | |
| _require_xfs_io_error_injection() | |
| { | |
| type="$1" | |
| _require_error_injection | |
| # Can we find the error injection knobs via the new errortag | |
| # configuration mechanism? | |
| knob="$(_find_xfs_mountdev_errortag_knob "${TEST_DEV}" "${type}")" | |
| test -w "${knob}" && return | |
| # If the directory containing the sysfs error injection knob exists | |
| # but the knob itself isn't usable, this kernel doesn't know about | |
| # the knob. Skip the test. | |
| if [ -d "$(dirname "${knob}")" ]; then | |
| _notrun "XFS error injection $type unknown on this kernel." | |
| fi | |
| # NOTE: We can't actually test error injection here because xfs | |
| # hasn't always range checked the argument to xfs_errortag_add. | |
| # We also don't want to trip an error before we're ready to deal | |
| # with it. | |
| $XFS_IO_PROG -x -c 'inject' $TEST_DIR | grep -q "$type" || \ | |
| _notrun "XFS error injection $type unknown." | |
| } | |
| # Inject an error into the test fs | |
| _test_inject_error() | |
| { | |
| type="$1" | |
| value="$2" | |
| knob="$(_find_xfs_mountdev_errortag_knob "${TEST_DEV}" "${type}")" | |
| if [ -w "${knob}" ]; then | |
| test -z "${value}" && value="default" | |
| echo -n "${value}" > "${knob}" | |
| elif [ -z "${value}" ] || [ "${value}" = "default" ]; then | |
| $XFS_IO_PROG -x -c "inject $type" $TEST_DIR | |
| else | |
| _fail "Cannot inject error ${type} value ${value}." | |
| fi | |
| } | |
| # Inject an error into the scratch fs | |
| _scratch_inject_error() | |
| { | |
| type="$1" | |
| value="$2" | |
| knob="$(_find_xfs_mountdev_errortag_knob "${SCRATCH_DEV}" "${type}")" | |
| if [ -w "${knob}" ]; then | |
| test -z "${value}" && value="default" | |
| echo -n "${value}" > "${knob}" | |
| elif [ -z "${value}" ] || [ "${value}" = "default" ]; then | |
| $XFS_IO_PROG -x -c "inject $type" $SCRATCH_MNT | |
| else | |
| _fail "Cannot inject error ${type} value ${value}." | |
| fi | |
| } |