[PATCH v2] scsi: core: Balance the pseudo target reap reference

From: Giuseppe Piscitelli

Date: Tue Oct 27 2026 - 06:10:08 EST


With memory allocation profiling enabled, unloading scsi_debug reports
allocations left at module unload. A stock Linux 7.2.11 VM without OpenZFS
emitted the following on each of three load/unload cycles:

[ 1.644665] drivers/scsi/scsi_debug.c:8863 module scsi_debug func:sdebug_add_host_helper has 1024 allocated at module unload
[ 1.656260] drivers/scsi/scsi_debug.c:1261 module scsi_debug func:sdebug_target_alloc has 16 allocated at module unload

scsi_alloc_target() supplies a reap reference for its caller. The SCSI
device initializer takes another reference, which device removal drops.
scsi_get_pseudo_sdev() drops its caller reference only when device
allocation fails. On success the target cannot be destroyed, retaining
its driver-private data and its parent host and adapter.

Drop the caller reference in the common cleanup path, as the other
scsi_alloc_target() callers do.

Fixes: d630fbf6fc8c ("scsi: core: Support allocating a pseudo SCSI device")
Signed-off-by: Giuseppe Piscitelli <ooonea@xxxxxxxxx>
---
OpenAI Codex analyzed the teardown diagnostics and wrote this fix and
its local validation. The new unpatched capture reproduces the symptom;
it does not establish which of this fix and the separately proposed
scsi_debug asynchronous cleanup fix removes each diagnostic.

Changes in v2:
- Include the allocation-at-unload diagnostics requested by Bart.
- No code changes.

Earlier validation covered four constructor/reference-count cases, a
Linux 7.3 build and three ordinary corrected-module lifecycles. The new
stock 7.2.11 run above captures the unpatched diagnostics only; no new
patched-kernel build or comparison was run.

drivers/scsi/scsi_scan.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 0f0f243..90e67f3 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -2156,14 +2156,13 @@ struct scsi_device *scsi_get_pseudo_sdev(struct Scsi_Host *shost)
goto out;

sdev = scsi_alloc_sdev(starget, U64_MAX, NULL);
- if (!sdev) {
- scsi_target_reap(starget);
+ if (!sdev)
goto put_target;
- }

sdev->borken = 0;

put_target:
+ scsi_target_reap(starget);
/* See also the get_device(dev) call in scsi_alloc_target(). */
put_device(&starget->dev);

base-commit: 6a53f401e671b75c129245e371ca6e9d47fc3c9a
--
2.54.0