Add a trigger to force an ENOBUFS return from scoutfs_alloc_data()

Create the force-enobufs test and use the trigger to inject ENOBUFS
to test its handling in the direct and buffered write paths.

Signed-off-by: Chris Kirby <ckirby@versity.com>
This commit is contained in:
Chris Kirby
2026-10-13 13:28:09 -05:00
parent 9519f9813e
commit 8fbdca8750
7 changed files with 65 additions and 0 deletions
+9
View File
@@ -744,6 +744,15 @@ int scoutfs_alloc_data(struct super_block *sb, struct scoutfs_alloc *alloc,
u64 len;
int ret;
/*
* Force an ENOBUFS error below by pretending we got -ENOENT back from
* the extent allocator.
*/
if (unlikely(scoutfs_trigger(sb, ALLOC_DATA_ENOBUFS))) {
ret = -ENOENT;
goto out;
}
/* large allocations come straight from the allocator */
if (count >= SCOUTFS_ALLOC_DATA_LG_THRESH) {
ret = scoutfs_ext_alloc(sb, &alloc_ext_ops, &args,
+1
View File
@@ -48,6 +48,7 @@ static char *names[] = {
[SCOUTFS_TRIGGER_RECLAIM_SKIP_FINALIZE] = "reclaim_skip_finalize",
[SCOUTFS_TRIGGER_LOG_MERGE_FORCE_PARTIAL] = "log_merge_force_partial",
[SCOUTFS_TRIGGER_ALLOC_FILL_FREED_LIST] = "alloc_fill_freed_list",
[SCOUTFS_TRIGGER_ALLOC_DATA_ENOBUFS] = "alloc_data_enobufs",
};
bool scoutfs_trigger_test_and_clear(struct super_block *sb, unsigned int t)
+1
View File
@@ -11,6 +11,7 @@ enum scoutfs_trigger {
SCOUTFS_TRIGGER_RECLAIM_SKIP_FINALIZE,
SCOUTFS_TRIGGER_LOG_MERGE_FORCE_PARTIAL,
SCOUTFS_TRIGGER_ALLOC_FILL_FREED_LIST,
SCOUTFS_TRIGGER_ALLOC_DATA_ENOBUFS,
SCOUTFS_TRIGGER_NR,
};
+9
View File
@@ -38,3 +38,12 @@ t_require_meta_size() {
test "$dev_bytes" -ge "$req_bytes" || \
t_skip "$dev must be at least $req_iec, is $dev_iec"
}
#
# Filter out direct I/O tests on platforms where we don't support it
#
t_require_o_direct() {
dd if=/dev/zero of="$T_D0/dio_test_file" count=0 oflag=direct status=none
test "$?" -eq "0" || \
t_skip_permitted "direct I/O not supported"
}
+7
View File
@@ -0,0 +1,7 @@
== arm trigger
== generate some direct I/O
== confirm trigger fired
== arm trigger
== generate some buffered I/O
== confirm trigger fired
== cleanup
+1
View File
@@ -12,6 +12,7 @@ simple-readdir.sh
get-referring-entries.sh
fallocate.sh
basic-truncate.sh
force-enobufs.sh
punch-offline.sh
data-prealloc.sh
setattr_more.sh
+37
View File
@@ -0,0 +1,37 @@
#
# Use the ALLOC_DATA_ENOBUFS trigger to force an ENOBUFS return from
# the data allocator.
#
t_require_commands dd rm
t_require_o_direct
echo "== arm trigger"
t_trigger_arm_silent alloc_data_enobufs 0
echo "== generate some direct I/O"
dd if=/dev/zero of="$T_D0"/outfile_direct bs=65536 count=4096 oflag=direct status=none
echo "== confirm trigger fired"
if [ "$(t_trigger_get alloc_data_enobufs 0)" -ne "0" ]
then
echo "trigger didn't fire for direct I/O"
fi
echo "== arm trigger"
t_trigger_arm_silent alloc_data_enobufs 0
echo "== generate some buffered I/O"
dd if=/dev/zero of="$T_D0"/outfile_buffered bs=65536 count=1024 status=none
echo "== confirm trigger fired"
if [ "$(t_trigger_get alloc_data_enobufs 0)" -ne "0" ]
then
echo "trigger didn't fire for buffered I/O"
fi
echo "== cleanup"
rm -f "$T_D0"/outfile_direct
rm -f "$T_D0"/outfile_buffered
t_pass