Page MenuHomeFreeBSD

mpi3mr: Re-resolve target handle during error recovery and flush
Needs ReviewPublic

Authored by chandrakanth.patil_broadcom.com on Sun, Oct 4, 2:24 PM.

Details

Summary

When an I/O request encounters a timeout or requires error recovery (such
as aborts or target resets), the recovery routines previously dereferenced
the cached target structure pointer stored in the command. If the target
device was detached or removed from the system while the timed-out request
was pending, the target structure had already been freed, causing error
recovery and I/O flush routines to dereference freed memory.

Store the target device's hardware handle in the command structure at
submission time, and re-resolve the target by handle from the active device
list during error recovery, task management, and I/O flushing. If the
target no longer exists in the active list, recovery routines skip the
command safely without dereferencing freed pointers.

Test Plan
  • Clean build with WERROR=-Werror across FreeBSD 16, 15, and 14 with INVARIANTS/WITNESS enabled; git bisect verified.
  • Tested SCSI error recovery, command timeouts, and target resets during concurrent drive hot-unplug on SAS4116/SAS5116 controllers.
  • Verified that target handles are dynamically re-resolved during recovery and I/O flushing without use-after-free conditions.

Diff Detail

Lint
Lint Skipped
Unit
Tests Skipped

Event Timeline

sys/dev/mpi3mr/mpi3mr.c
6391

Isn't there still a race here, since target might be removed if we exceed the loop count in remove_device_from_os with outstanding != 0, which then proceeds to the remove after it returns? The race is small, but not closed entirely by looking it up here.

sys/dev/mpi3mr/mpi3mr.c
6391

Isn't there still a race here, since target might be removed if we exceed the loop count in remove_device_from_os with outstanding != 0, which then proceeds to the remove after it returns? The race is small, but not closed entirely by looking it up here.

Yes. Looking up the target outside target_lock leaves a race window if remove_device_from_os() exits while outstanding != 0.

I will hold target_lock across the lookup and decrement here (matching D60335), and ensure remove_device_from_list() does not free the target while outstanding > 0 in V2 patch.