--- /dev/null
+#! /bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (c) 2024-2026 Oracle. All Rights Reserved.
+#
+# FS QA Test No. 655
+#
+# Corrupt some metadata and try to access it with the health monitoring program
+# running. Check that healthmon observes a metadata error.
+#
+. ./common/preamble
+_begin_fstest auto quick eio selfhealing
+
+_cleanup()
+{
+ cd /
+ test -n "$healer_pid" && kill $healer_pid &>/dev/null
+ wait
+ rm -rf $tmp.* $testdir
+}
+
+. ./common/filter
+
+_require_scratch_nocheck
+_require_scratch_xfs_crc # can't detect minor corruption w/o crc
+_require_xfs_io_command healthmon
+
+# Disable the scratch rt device to avoid test failures relating to the rt
+# bitmap consuming all the free space in our small data device.
+unset SCRATCH_RTDEV
+
+echo "Format and mount"
+_scratch_mkfs -d agcount=1 | _filter_mkfs 2> $tmp.mkfs >> $seqres.full
+. $tmp.mkfs
+_scratch_mount
+mkdir $SCRATCH_MNT/a/
+# Enough entries to get to a single block directory
+for ((i = 0; i < ( (isize + 255) / 256); i++)); do
+ path="$(printf "%s/a/%0255d" "$SCRATCH_MNT" "$i")"
+ touch "$path"
+done
+inum="$(stat -c %i "$SCRATCH_MNT/a")"
+_scratch_unmount
+
+# Fuzz the directory block so that the touch below will be guaranteed to trip
+# a runtime sickness report in exactly the manner we desire.
+_scratch_xfs_db -x -c "inode $inum" -c "dblock 0" -c 'fuzz bhdr.hdr.owner add' -c print &>> $seqres.full
+
+# Try to allocate space to trigger a metadata corruption event
+echo "Runtime corruption detection"
+_scratch_mount
+$XFS_IO_PROG -c 'healthmon -c -v' $SCRATCH_MNT > $tmp.healthmon &
+healer_pid=$!
+sleep 1 # wait for program to start up
+touch $SCRATCH_MNT/a/farts &>> $seqres.full
+_scratch_unmount
+
+wait # for healthmon to finish
+unset healer_pid
+
+# Did we get errors?
+check_healthmon()
+{
+ cat $tmp.healthmon >> $seqres.full
+ _filter_scratch < $tmp.healthmon | \
+ grep -E '(sick|corrupt)' | \
+ sed -e 's|SCRATCH_MNT/a|VICTIM|g' \
+ -e 's|SCRATCH_MNT ino [0-9]* gen 0x[0-9a-f]*|VICTIM|g' | \
+ sort | \
+ uniq
+}
+check_healthmon
+
+# Run scrub to trigger a health event from there too.
+echo "Scrub corruption detection"
+_scratch_mount
+if _supports_xfs_scrub $SCRATCH_MNT $SCRATCH_DEV; then
+ $XFS_IO_PROG -c 'healthmon -c -v' $SCRATCH_MNT > $tmp.healthmon &
+ healer_pid=$!
+ sleep 1 # wait for program to start up
+ $XFS_SCRUB_PROG -n $SCRATCH_MNT &>> $seqres.full
+ _scratch_unmount
+
+ wait # for healthmon to finish
+ unset healer_pid
+
+ # Did we get errors?
+ check_healthmon
+else
+ # mock the output since we don't support scrub
+ _scratch_unmount
+ cat << ENDL
+VICTIM directory: corrupt
+VICTIM directory: sick
+VICTIM parent: corrupt
+ENDL
+fi
+
+_exit 0