##/bin/bash
-
-# Routines for fuzzing and scrubbing a filesystem.
-#
-#-----------------------------------------------------------------------
-# Copyright (c) 2017 Oracle. All Rights Reserved.
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2017 Oracle. All Rights Reserved.
#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
-# USA
-#-----------------------------------------------------------------------
+# Routines for fuzzing and scrubbing a filesystem.
# Modify various files after a fuzzing operation
_scratch_fuzz_modify() {
$XFS_IO_PROG -f -c "pwrite -S 0x63 0 ${blk_sz}" "/tmp/afile" > /dev/null
date="$(date)"
find "${SCRATCH_MNT}/" -type f 2> /dev/null | head -n "${nr}" | while read f; do
+ # try to remove append, immutable (and even dax) flag if exists
+ $XFS_IO_PROG -rc 'chattr -x -i -a' "$f" > /dev/null 2>&1
setfattr -n "user.date" -v "${date}" "$f"
cat "/tmp/afile" >> "$f"
mv "$f" "$f.longer"
_scratch_xfs_db "${cmds[@]}" -c print | __filter_xfs_db_print_fields "${filter}"
}
-# Get a metadata field
-# The first arg is the field name
-# The rest of the arguments are xfs_db commands to find the metadata.
-_scratch_xfs_get_metadata_field() {
- key="$1"
- shift
-
- grep_key="$(echo "${key}" | tr '[]()' '....')"
- local cmds=()
- for arg in "$@"; do
- cmds+=("-c" "${arg}")
- done
- _scratch_xfs_db "${cmds[@]}" -c "print ${key}" | grep "^${grep_key}" | \
- sed -e 's/^.* = //g'
-}
-
-# Set a metadata field
-# The first arg is the field name
-# The second arg is the new value
-# The rest of the arguments are xfs_db commands to find the metadata.
-_scratch_xfs_set_metadata_field() {
- key="$1"
- value="$2"
- shift; shift
-
- local cmds=()
- for arg in "$@"; do
- cmds+=("-c" "${arg}")
- done
- _scratch_xfs_db -x "${cmds[@]}" -c "write -d ${key} ${value}"
- echo
-}
-
# Fuzz a metadata field
# The first arg is the field name
# The second arg is the xfs_db fuzz verb
for arg in "$@"; do
cmds+=("-c" "${arg}")
done
- _scratch_xfs_db -x "${cmds[@]}" -c "fuzz ${fuzz_arg} ${key} ${value}"
- echo
- newval="$(_scratch_xfs_get_metadata_field "${key}" "$@" 2> /dev/null)"
+ while true; do
+ _scratch_xfs_db -x "${cmds[@]}" -c "fuzz ${fuzz_arg} ${key} ${value}"
+ echo
+ newval="$(_scratch_xfs_get_metadata_field "${key}" "$@" 2> /dev/null)"
+ if [ "${key}" != "random" ] || [ "${oldval}" != "${newval}" ]; then
+ break;
+ fi
+ done
if [ "${oldval}" = "${newval}" ]; then
echo "Field ${key} already set to ${newval}, skipping test."
return 1
# Fuzz one field of some piece of metadata.
# First arg is the field name
# Second arg is the fuzz verb (ones, zeroes, random, add, sub...)
-# Third arg is the repair mode (online, offline, both)
+# Third arg is the repair mode (online, offline, both, none)
__scratch_xfs_fuzz_field_test() {
field="$1"
fuzzverb="$2"
# Try to catch the error with scrub
echo "+ Try to catch the error"
- _scratch_mount 2>&1
+ _try_scratch_mount 2>&1
res=$?
if [ $res -eq 0 ]; then
# Try an online scrub unless we're fuzzing ag 0's sb,
# which scrub doesn't know how to fix.
- echo "++ Online scrub"
- if [ "$1" != "sb 0" ]; then
- _scratch_scrub -n -a 1 -e continue 2>&1
- res=$?
- test $res -eq 0 && \
- (>&2 echo "scrub didn't fail with ${field} = ${fuzzverb}.")
+ if [ "${repair}" != "none" ]; then
+ echo "++ Online scrub"
+ if [ "$1" != "sb 0" ]; then
+ _scratch_scrub -n -a 1 -e continue 2>&1
+ res=$?
+ test $res -eq 0 && \
+ (>&2 echo "scrub didn't fail with ${field} = ${fuzzverb}.")
+ fi
fi
# Try fixing the filesystem online?!
if [ "${repair}" = "online" ] || [ "${repair}" = "both" ]; then
__fuzz_notify "++ Try to repair filesystem online"
- _scratch_scrub -y 2>&1
+ _scratch_scrub 2>&1
res=$?
test $res -ne 0 && \
(>&2 echo "online repair failed ($res) with ${field} = ${fuzzverb}.")
fi
# See if repair finds a clean fs
- echo "+ Make sure error is gone (offline)"
- _scratch_xfs_repair -n 2>&1
- res=$?
- test $res -ne 0 && \
- (>&2 echo "offline re-scrub ($res) with ${field} = ${fuzzverb}.")
+ if [ "${repair}" != "none" ]; then
+ echo "+ Make sure error is gone (offline)"
+ _scratch_xfs_repair -n 2>&1
+ res=$?
+ test $res -ne 0 && \
+ (>&2 echo "offline re-scrub ($res) with ${field} = ${fuzzverb}.")
+ fi
# See if scrub finds a clean fs
echo "+ Make sure error is gone (online)"
- _scratch_mount 2>&1
+ _try_scratch_mount 2>&1
res=$?
if [ $res -eq 0 ]; then
# Try an online scrub unless we're fuzzing ag 0's sb,
# which scrub doesn't know how to fix.
- echo "++ Online scrub"
- if [ "$1" != "sb 0" ]; then
- _scratch_scrub -n -e continue 2>&1
- res=$?
- test $res -ne 0 && \
- (>&2 echo "online re-scrub ($res) with ${field} = ${fuzzverb}.")
+ if [ "${repair}" != "none" ]; then
+ echo "++ Online scrub"
+ if [ "$1" != "sb 0" ]; then
+ _scratch_scrub -n -e continue 2>&1
+ res=$?
+ test $res -ne 0 && \
+ (>&2 echo "online re-scrub ($res) with ${field} = ${fuzzverb}.")
+ fi
fi
# Try modifying the filesystem again!
fi
# See if repair finds a clean fs
- echo "+ Re-check the filesystem (offline)"
- _scratch_xfs_repair -n 2>&1
- res=$?
- test $res -ne 0 && \
- (>&2 echo "re-repair failed ($res) with ${field} = ${fuzzverb}.")
+ if [ "${repair}" != "none" ]; then
+ echo "+ Re-check the filesystem (offline)"
+ _scratch_xfs_repair -n 2>&1
+ res=$?
+ test $res -ne 0 && \
+ (>&2 echo "re-repair failed ($res) with ${field} = ${fuzzverb}.")
+ fi
}
# Make sure we have all the pieces we need for field fuzzing
echo "Verbs we propose to fuzz with:"
echo $(echo "${verbs}")
+ # Always capture full core dumps from crashing tools
+ ulimit -c unlimited
+
echo "${fields}" | while read field; do
echo "${verbs}" | while read fuzzverb; do
__scratch_xfs_fuzz_mdrestore