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.