[DriverKit SCSI] SCSI probe stalls for Target ID > 0 with IOUserSCSIParallelInterfaceController

Hello everyone,

We are migrating a KEXT storage driver to DriverKit. In our KEXT, we use a "one LUN = one Target" model and successfully create multiple targets in a loop during initialization. We are now trying to replicate this architecture in our DEXT.

The issue is that only Target 0 is fully probed and mounted. For Target 1, the lifecycle silently stops after the first TEST UNIT READY command is successfully acknowledged. The macOS SCSI layer never sends any subsequent probe commands (like INQUIRY) to this target.

The failure sequence for Target 1, observed from our logs (regardless of whether Target 0 is created), is as follows:

  1. AsyncCreateTargetForID(1) -> UserInitializeTargetForID(1) (Succeeds)
  2. UserProcessParallelTask(Target: 1, Opcode: TUR) (Succeeds)
  3. The DEXT correctly acknowledges the TUR command for Target 1 by returning kSCSITaskStatus_CHECK_CONDITION with UNIT ATTENTION in the Sense Data (Succeeds)
  4. <-- Breakpoint -->
  5. UserProcessParallelTask(Target: 1, Opcode: INQUIRY) (Never happens)

Through log comparison, we have confirmed that the DEXT's response to the TUR command for Target 1 is identical to the successful KEXT's response.

We have tried creating only Target 1 (skipping Target 0 entirely), but the behavior is exactly the same -> the probe still stalls after the TUR.

We initially suspected a race condition caused by consecutive calls to AsyncCreateTargetForID(). We attempted several methods to ensure that targets are created sequentially, such as trying to build a "creation chain" using OSAction completion handlers. However, these attempts were unsuccessful due to various compilation errors and API misunderstandings.

In any case, this "race condition" theory was ultimately disproven by our experiment where creating only Target 1 still resulted in failure.

We would like to ask two questions:

  1. Is our inability to have a Target ID greater than 0 fully probed by macOS a bug in our own code, or could there be another reason we are unaware of?
  2. If we do indeed need a "one-after-another" creation mechanism for AsyncCreateTargetForID, what is the correct way to implement a "chained creation" using OSAction completion handlers in DriverKit?

Thank you for any help or guidance.

Best Regards,

Charles

  1. Is our inability to have a Target ID greater than 0 fully probed by macOS a bug in our own code, or could there be another reason we are unaware of?

It's a bug in your code.

  1. If we do indeed need a "one-after-another" creation mechanism for AsyncCreateTargetForID, what is the correct way to implement a "chained creation" using OSAction completion handlers in DriverKit?

You do NOT need to do this. The snippet in our documentation has a model of "one event per ID", but our production DEXT is just using a single call with a set of nested loops checking IDs and calling UserCreateTargetForID.

In terms of what could be going wrong, a few thoughts:

  • Looking through the method list, what do you return for "UserReportHBAHighestLogicalUnitNumber"? If you didn't implement it or return "0", then I think you'd get exactly the behavior you're seeing. Make sure you check this first, as this is the best idea I've come up with.

  • Look at your iig and audit it for "QUEUENAME". Most DEXTs use VERY few of these and they shouldn't be on any of "our" methods. In early development, I'd actually expect that the ONLY use would be for target creation.

  • Is Target ID 0 "fully" functional, meaning you get the entire storage stack to build out and can do I/O to it? It's fine if it isn't (after all, you're not done...), but if it isn't I would take a look in IORegistryExplorer to validate how far you're "getting" and that all the properties look right.

We have tried creating only Target 1 (skipping Target 0 entirely), but the behavior is exactly the same -> the probe still stalls after the TUR.

  • The fact you're failing on "1+", not just "the second" implies that there could be some kind of issue on the I/O side of this. As an "odd" test, what happens if you tell the system it's "1" but you ACTUALLY do everything to "0"? Or the reverse (tell the system "0", but actually target "1")?

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

[DriverKit SCSI] SCSI probe stalls for Target ID &gt; 0 with IOUserSCSIParallelInterfaceController
 
 
Q