BlockStorageDeviceDriverKit grant confirmed by support but shows "No Requests" in the portal. How to resolve?

Hello!

I am hoping a DTS engineer or someone who knows the Capability Requests portal can help, because I am stuck between a written support confirmation and what the portal actually shows.

Background. We are building a native macOS iSCSI initiator for SOHO and home NAS use, developed over close to two years. A userspace daemon runs the iSCSI protocol and a DriverKit system extension presents the remote LUN as a block device. The code is essentially complete. Only the DriverKit extension cannot be signed, loaded and validated without the entitlement.

We submitted request 32PC8MGU57 for two entitlements: com.apple.developer.driverkit.family.block-storage-device for the extension com.aviontex.iscsi.AviontexISCSI.AviontexInitiator com.apple.developer.driverkit.userclient-access for the app com.aviontex.iscsi.AviontexISCSI, scoped to the extension bundle id

The problem. On June 25 Developer Support confirmed in writing that both entitlements were granted. The portal does not match that: Block Storage Device: No Requests: on both App IDs UserClient Access: Assigned: on the app SCSI Controller: Submitted: on the app

So the one entitlement we actually need, Block Storage Device, shows as never requested, even though request 32PC8MGU57 covered it and support confirmed the grant. The case was escalated to the senior team on July 2 (case 102922935570). Follow-up emails since then have not received a response.

Why Block Storage Device specifically

Our initiator has no PCI or Thunderbolt bus and no DMA path, so SCSIControllerDriverKit does not fit. This is confirmed by DTS in thread 776020, where Kevin Elliott explains that SCSIControllerDriverKit passes data through fBufferIOVMAddr as a physical address with no mechanism to convert it into a VM address the dext can access. He also notes it cannot be used with any bus other than PCI or Thunderbolt. Block Storage Device is therefore the family we need.

My questions: Am I reading the portal correctly: Block Storage Device not requested, UserClient Access assigned, SCSI Controller submitted? From here, what is the correct way to get Block Storage Device onto these two App IDs, with both the Development and the Distribution grant, since our public beta depends on Distribution? Should I submit a new request through the Capability Requests tab or does the escalated case handle it? Is there any way to get visibility on the escalated case, since email follow-ups are not being answered?

A full technical justification is prepared and we are happy to share the source code. Any guidance would be appreciated.

Thank you.

I am hoping a DTS engineer or someone who knows the Capability Requests portal can help, because I am stuck between a written support confirmation and what the portal actually shows.

Looking into this, it looks like this was sorted out earlier today.

However, I have another question:

Our initiator has no PCI or Thunderbolt bus and no DMA path, so SCSIControllerDriverKit does not fit. This is confirmed by DTS in thread 776020, where Kevin Elliott explains that SCSIControllerDriverKit passes data through fBufferIOVMAddr as a physical address with no mechanism to convert it into a VM address the dext can access. He also notes it cannot be used with any bus other than PCI or Thunderbolt. Block Storage Device is therefore the family we need.

Unfortunately, I don't see how BlockStorageDeviceDriverKit will work any better. The I/O path here is DoAsyncReadWrite, which passes in "dmaAddr", which creates exactly the same problem SCSIControllerDriverKit has. I'd love to be wrong about this, but I don't see how this is going to work.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Thanks Kevin, that was fast and clear, and I appreciate you taking the time to look at it.

I really hope you are wrong, and not just for selfish reasons. If neither storage family can carry a network backed block device, then there is no DEXT path to iSCSI on macOS at all. Not for us, not for anyone. It stays a kext, and on Apple Silicon that means telling users to drop to Reduced Security to reach their own storage. Nobody should have to weaken their machine to mount a disk. As a product that is simply not shippable, so for us that road ends there.

The selfish reason is easier to explain: three years of my life are in this thing. So you can imagine I read your reply twice, went for a walk, and read it a third time. Right now the outcome is either "we built something that cannot exist" or "the DTS engineer is wrong about one detail". I know which one I am betting on, though I admit the odds are not in my favour.

No argument from me either way, you know this stack better than I ever will. But I would rather find out than debate it. We are going to test this thoroughly now and see what actually happens, and as soon as I know more I will come back with the details.

Thanks again.

I really hope you are wrong, and not just for selfish reasons. If neither storage family can carry a network-backed block device, then there is no DEXT path to iSCSI on macOS at all. Not for us, not for anyone. It stays a kext, and on Apple Silicon that means telling users to drop to Reduced Security to reach their own storage. Nobody should have to weaken their machine to mount a disk.

I completely agree and, in fact, a lot of my attention this week has been on trying to sort out what a solution for this should actually look like. The summary is that I think we should have a better solution for this, but also that this probably is possible today. So, summarizing the situation:

  1. BlockStorageDeviceDriverKit -> I don't think this is currently workable. I'd strongly encourage you to file a bug asking for or it to add a memory descriptor only I/O path, then post that bug number back here.

  2. SCSIControllerDriverKit -> It appears I was actually wrong about this, as UserMapHBAData UserGetDataBuffer does give access to a semi-working MemoryDescriptor and, I'm told, it does work. Unfortunately, it appears there's also an issue on the DMA side which means you have to use a configuration that forces every I/O request to a single page. Again, I'd strongly encourage you to file a bug asking for or it to add a memory descriptor only I/O path, then post that bug number back here.

  3. FSKit Dark Horse -> This is an odd idea I just came up with this week. The details are below, but implementation should be straightforward and performance might actually be quite good.

As noted above, please get both of those bugs filed and the numbers back to me. I can't promise if/when we'll address these issues, but I think this is something we should provide better support for and I'm trying to collect bugs to "encourage".

Shifting back to the "FSKit Dark Horse", the idea here is to combine FSKit and our DiskImage infrastructure so that the system ends up handling all of the "drive" infrastructure while your FSKit extension does all of the I/O.

Here's how that would work:

(1)
Create a very simple FSKit extension. This is mounted as normal (probably at a "private" location, as the user never needs to see) but all it exposes is a single file, which corresponds to the device you'll ultimately be presenting to the user.

Note that the file handling here could actually be handled by either having one file per mount and one mount per device, or by having a single mount point which adds/removes device files dynamically (as you add or remove new devices). I think either approach could work fine, so this really depends on how you want the overall experience to work.

(2)
Create a dev node for that file using this hdiutil command:

hdiutil attach -imagekey diskimage-class=CRawDiskImage -nomount <file target>

...or the "raw" format of DiskImageKit. This target is what's then mounted and what the user interacts with.

(3)
Handle all I/O requests through the normal FSKit read/write process.

...and that's it. It may seem like a strange architecture, but at a technical level, this is exactly how disk images already work on any other file system. On the performance side, my guess is that it's probably slower than the "ideal" version of #1 & #2 but probably faster than #2 (in its current state). However, no matter what, I think it will be FAR easier to build/debug than either of the other options.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware


Hi Kevin,

I'm afraid I have to disagree with one detail. Please give me two seconds to enjoy the moment.

You know, the Big Five for Life: getting married, having children, planting a tree, building a house and correcting an Apple DTS engineer. :-)

All right, moment over. Seriously, though: thank you for revisiting this so openly, investigating the alternatives and trying to move the underlying issues forward internally.

Your revised overall conclusion appears to be correct: SCSIControllerDriverKit is viable for this use case, at least on the system we have now tested.

One detail may need clarification, though: the descriptor API path.

In the public DriverKit 25.5 headers, UserMapHBAData does not return a memory descriptor. Its only output is the unique controller task identifier:

UserMapHBAData(
    uint32_t *uniqueTaskID
);

The descriptor itself is retrieved later through:

UserGetDataBuffer(
    targetID,
    controllerTaskID,
    &buffer
);

when called from UserProcessParallelTask, using the request's fControllerTaskIdentifier.

Perhaps this is the mechanism you meant. UserMapHBAData establishes the task identity, and UserGetDataBuffer subsequently retrieves the task's IOBufferMemoryDescriptor.

As we are still testing, we would like to keep the conclusions narrow and clearly distinguish between what we have measured and what remains open.

Current test configuration

Hardware:       Intel Mac
macOS:          26.5.2
Xcode:          26.5
DriverKit SDK:  25.5

IOClass:
IOUserSCSIParallelInterfaceController

IOProviderClass:
IOUserResources

There is no PCI or Thunderbolt provider. The signed DEXT does not request the PCI transport entitlement.

The extension was installed and activated successfully. The controller became registered, matched and active.

The following lifecycle and reporting steps completed:

UserInitializeController
UserReportHBAConstraints
UserStartController
UserInitializeTargetForID

The framework then submitted real SCSI commands through UserProcessParallelTask.

Inside those callbacks:

UserGetDataBuffer
    -> kIOReturnSuccess
    -> non-null IOBufferMemoryDescriptor

GetAddressRange
    -> kIOReturnSuccess
    -> nonzero DEXT-local address
    -> expected transfer length

We initially performed a descriptor-only probe without touching the buffer. That succeeded.

We then performed a strictly bounded standard INQUIRY write using the address returned by GetAddressRange.

The observed sequence was:

INQUIRY allocation length 6
    -> wrote 6 bytes
    -> completed GOOD

INQUIRY allocation length 36
    -> wrote 36 bytes
    -> completed GOOD

macOS consumed the initial six bytes and subsequently requested the complete 36-byte INQUIRY response.

The resulting IORegistry properties contained the exact data written by the DEXT:

Vendor:    AVIONTEX
Product:   iSCSI4NAS VIRT
Revision:  0001

The native storage stack then advanced through:

IOSCSIParallelInterfaceDevice
IOSCSITargetDevice
IOSCSIHierarchicalLogicalUnit
IOSCSIPeripheralDeviceType00
IOBlockStorageServices
IOBlockStorageDriver

It is now issuing subsequent discovery commands, including READ CAPACITY(10).

There were no panics and no DEXT crashes. The DriverKit crash counter remained at zero.

For this specific configuration, we have therefore demonstrated:

IOUserResources
-> IOUserSCSIParallelInterfaceController
-> UserProcessParallelTask
-> UserGetDataBuffer
-> IOBufferMemoryDescriptor
-> GetAddressRange
-> bounded byte write
-> successful SCSI completion
-> data consumed and interpreted by the macOS storage stack

This confirms your revised conclusion that the SCSI path is possible today.

It also shows that the original fBufferIOVMAddr limitation does not prevent the DEXT from accessing the request data, because UserGetDataBuffer provides a separate descriptor-based path. We still do not use or dereference fBufferIOVMAddr.

Single-page limitation

Your warning about the single-page DMA limitation remains open.

Our successful transfers were only:

6 bytes
36 bytes

These results therefore neither confirm nor disprove a single-page limitation. We have not yet tested a cross-page request, Scatter/Gather I/O or real READ/WRITE commands.

Could you clarify the exact configuration Apple currently recommends to enforce the single-page restriction?

In particular, should a virtual HBA use:

maximum segment count read  = 1
maximum segment count write = 1

maximum segment byte count read  = runtime system page size
maximum segment byte count write = runtime system page size

maxTransferSize = runtime system page size

Should any additional alignment constraint be applied?

And should "one page" always use the runtime system page size rather than a fixed 4096-byte value, particularly when validating the same implementation across Intel and Apple Silicon?

BlockStorageDeviceDriverKit and FSKit

We also agree with your assessment of BlockStorageDeviceDriverKit.

Its current DoAsyncReadWrite interface exposes only the DMA address and does not provide an equivalent to UserGetDataBuffer. We will file the two requested Feedback Assistant reports:

  1. A descriptor-only read/write path for BlockStorageDeviceDriverKit
  2. A documented descriptor-only, multi-page I/O path for SCSIControllerDriverKit

We will post both feedback numbers here once they have been submitted.

We will also retain the FSKit/raw-DiskImage design as a fallback and potential performance comparison. For now, however, the SCSI path has progressed far enough that we would like to finish validating it before changing architectures.

Scope

For completeness, the results above currently apply only to:

Intel
macOS 26.5.2
DriverKit 25.5
development signing
Developer Mode
SIP disabled

The following remain separate validation steps:

Apple Silicon
SIP-enabled standard security
distribution provisioning
multi-page I/O
real READ/WRITE traffic
long-running stability

This is an early status report, not a final result. We will keep testing and keep you posted as we go, including the feedback numbers once both reports are filed.

One more thing, and I mean it. When we started, we did not see the SCSI option at all. In hindsight we were probably too fixated on BlockStorageDeviceDriverKit, because from where we sit that is the more logical family for this product. It took both the entitlement process and your pointers to send us back to the SCSI DEXT and look at it properly.

So thank you again. Your correction and the pointer back toward the SCSI path appear to have saved the architecture.

Perhaps this is the mechanism you meant. UserMapHBAData establishes the task identity, and UserGetDataBuffer subsequently retrieves the task's IOBufferMemoryDescriptor.

UserMapHBAData was a typo on my part, and UserGetDataBuffer is what I meant. I've corrected that above.

Could you clarify the exact configuration Apple currently recommends to enforce the single-page restriction?

In particular, should a virtual HBA use:

Yes, that looks right.

Your warning about the single-page DMA limitation remains open.

One more quick comment here. The actual failure here is specifically caused by IODMACommand forcing multiple segments (due to the lack of DART), which means the actual failure case is more complicated than "anything greater than 1 page always fails".

And should "one page" always use the runtime system page size rather than a fixed 4096-byte value, particularly when validating the same implementation across Intel and Apple Silicon?

Yes, you should use the system page size, and that's 16k (not 4k) on Apple Silicon.

We will post both feedback numbers here once they have been submitted.

Thank you...

We will also retain the FSKit/raw-DiskImage design as a fallback and potential performance comparison. For now, however, the SCSI path has progressed far enough that we would like to finish validating it before changing architectures.

So, just so you're aware, my intuition is that the FSKit approach will be faster, potentially MUCH faster, right now. I don't think that would be true without the single-page I/O limitation, but the overhead cost here is quite high.

One final note— given all the entitlement shuffling that happened here, I went ahead and requested SCSIControllerDriverKit on your behalf, which I expect should be approved shortly.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Hi Kevin,

Both bugs are filed:

FB23814013
FB23814092

If you need more detail on either, or want anything in a different form, just say the word and I will add it.

Filing them was the easy part. We spent most of yesterday testing, so the data was already sitting there.

Thanks again for requesting SCSIControllerDriverKit on our behalf. That was not something I expected and it is appreciated.

We will keep testing and give you an update once we know more, probably sometime next week.

Best regards & enjoy your weekend!!!

Torsten

Both bugs are filed:

Perfect, thank you.

Thanks again for requesting SCSIControllerDriverKit on our behalf. That was not something I expected and it is appreciated.

You're very welcome.

We will keep testing and give you an update once we know more, probably sometime next week.

Sounds good and good luck!

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

We ran the whole thing through on paper first. Everything below is calculation and assumption, not measurement. The real numbers come once we measure, but the calculations already let us make a call.

Short version: we build on SCSI and validate it. FSKit stays as a last resort. Extending BlockStorage with a descriptor path looks like the clean fix.

1. SCSI DEXT

On the single-page limit we did the math instead of guessing. Assuming 16 KB per request on Apple Silicon, a 20 GB transfer comes to 1,310,720 requests (on Intel at 4 KB it would be 5,242,880). Whether that becomes a problem depends on per-request latency. Working it through, in theory it looks like this:

Latency per request   20 GB @ 16 KB     Effective throughput
   10 us                     13 s             1.5 GB/s
   50 us                     66 s             305 MB/s
  100 us                    131 s             153 MB/s
  140 us                    183 s             110 MB/s   <- 1 GbE line
  200 us                    262 s              76 MB/s
  500 us                     11 min            31 MB/s

If those numbers hold, the single-page limit stays acceptable up to roughly 140 us per request, which keeps us at or above the 1 GbE ceiling of about 110 MB/s. Our target market of SOHO and home NAS runs mostly on 1 GbE and Wi-Fi anyway, where real-world throughput sits at or below that line. And if there is a way to lift the single-page constraint, that only improves the picture.

2. FSKit

This is the option you raised, and on raw speed you are probably right: it avoids the DMA path completely. We took the suggestion seriously and ran the numbers. Since FSKit has no fixed transfer size like the single-page SCSI path, the only thing we can really compare is request count. Assuming cluster-sized I/O, a 20 GB transfer looks like this:

20 GB transfer, requests by I/O size (assumption)

  SCSI single-page   16 KB   1,310,720 requests
  FSKit              64 KB     327,680 requests    (4x fewer)
  FSKit             128 KB     163,840 requests    (8x fewer)
  FSKit               1 MB      20,480 requests   (64x fewer)

On request count FSKit in theory clearly wins. The trade-off is higher per-request overhead through the VFS layer, so which approach is faster in the end we cannot say without measuring both.

What makes FSKit unattractive for us is not throughput, but what it costs at the layer above it. It hands us file offsets instead of SCSI semantics. Reservation handling, sense data, command ordering and error semantics would all have to be rebuilt on top of a layer that no longer speaks SCSI.

And more important, our own in-house iSCSI protocol extensions (iSCSI-over-TLS or iSCSI-via-Remote) are built on native iSCSI. A SCSI or BlockStorage DEXT keeps that native layer underneath them. FSKit replaces it, and we cannot yet say what that does to those extensions, but building on a file abstraction instead of the native wire is a risk we would rather not take. If nothing else works we would have to, but it would set our development back considerably.

3. Extending BlockStorage with a descriptor path

This would be additive and entitlement-gated. Leaving architecture, design, conception, testing and review aside completely and looking purely at the implementation effort, our estimate is less than a week of native code with no impact, since it is an extension and not a change.

The reasoning:

DoAsyncUnmap already carries an IOMemoryDescriptor across the DriverKit boundary in the same class, while DoAsyncReadWrite carries only a bare address one method away. So the plumbing to pass a descriptor already exists in the family. The descriptor also has to stay alive in the request until CompleteIO regardless, so it looks reachable via request ID.

More broadly, this looks like a gap and not a missing capability. Other DriverKit families hand the dext a real IOMemoryDescriptor for their data path. Even SCSIController does, through UserGetDataBuffer, which is exactly what we are relying on. BlockStorage is the one that does not: its DoAsyncReadWrite passes only a bare address, with no descriptor equivalent anywhere in the class. And storage is exactly the area where getting the bytes wrong costs data.

Our conclusion

Of the three paths, only the descriptor extension actually solves this rather than working around it. SCSI seems to work but stays capped. FSKit works but breaks the native semantics. The descriptor path is the only one that removes the underlying reason this device class still needs a kext.

Laid out plainly, this is why it looks like the right call to us, and why we think it is the sensible one for the platform too:

  • Apple users finally get a native iSCSI solution. The missing piece is only the descriptor path in the family.
  • It makes the DMA problem moot instead of fixing it. No IODMACommand, no segments, no DART, no single-page limit, and no impact on the general DMA path that every driver depends on.
  • It moves a whole device class off kexts. iSCSI on macOS means a kext today, and on Apple Silicon that means Reduced Security. The descriptor path removes the technical reason for that, for everyone, not just us.
  • It strengthens platform security. Nobody has to weaken their machine to reach their own storage.
  • It gives people a reason to move to Apple Silicon. A fix lands from macOS 27 onward, which is Apple Silicon only, so native high-throughput iSCSI becomes a capability of the newer machines rather than a reason to stay on a kext.

Realistically a change like this would take maybe six to nine months through the normal release cycle. That would put it in macOS 27 or later. Older Intel machines would keep running on the single-page SCSI path on Tahoe, without regression. Nobody would lose a working setup. That is a bigger outcome than one product, and that is why we keep coming back to it.

We are building on SCSI now and will test whether it holds up. If it is good enough for SOHO and home NAS traffic, we can live with it, and none of this blocks us.

We would of course like to know how long something like this might take, but we know that is not a question you can answer.

The one thing we are asking for is your technical read. Does this match how you see the constraints today? And is there a fundamental blocker in this approach that we are missing?

Best regards,

Torsten

Hi Kevin,

We now have the measurements we promised. My previous post was still based on calculations and on the assumption that the single-page SCSI path might remain viable if per-request overhead stayed low enough. On our Intel test system, that assumption does not hold.

Functional result

SCSIControllerDriverKit works functionally for a native software-backed iSCSI device. We validated an RMB=0 fixed disk backed by a real 4.29 TB Synology LUN with 512-byte blocks, native IOMedia and APFS mounting, verified READ and WRITE traffic, clean target creation and removal, QD64, bundled task intake, multiple iSCSI ITTs, 64 KB Data-In PDUs and ImmediateData. This is a mounted native macOS disk carrying real file I/O, not an INQUIRY-only probe.

Measured performance

The same approximately 152 MiB file was used throughout.

Path / directionElapsed timeEffective rate
Initial request-by-request path, WRITE7-8 minutes0.32-0.36 MB/s
Shared-memory ring, WRITE52.5-62 seconds2.5-2.9 MB/s
Shared-memory ring, READ19.8-26.3 seconds5.8-8.0 MB/s
1 GbE payload ceiling, context only~1.4 seconds~110 MB/s

The ring improved representative WRITE performance by roughly 7-9x. That is a real gain, but a result of only a few MB/s is still not viable for a LAN-connected NAS block device.

Why we built the ring

The initial request-by-request path took seven to eight minutes for 152 MiB, so we built a substantial workaround to determine whether the App/DEXT handoff was the primary bottleneck.

The DEXT now creates and shares a roughly 16 MB IOBufferMemoryDescriptor containing a request queue, a completion queue, 64 request slots, 64 completion slots and 64 payload slots of 256 KB each. The path supports QD64, bundled DriverKit intake, multiple ITTs, out-of-order completion, doorbells, completion kicks and ImmediateData.

The data path is effectively:

SCSI task -> UserGetDataBuffer -> request mapping -> shared staging slot -> userspace iSCSI -> completion ring -> READ copy-back -> individual framework completion

This removed the old payload-sized UserClient transport and the QD1 bottleneck. It did not remove the framework lifecycle of each original SCSI task.

What remained

Despite advertising 256 KB through Block Limits VPD, representative epochs were still almost entirely 4 KB tasks:

Task sizeWRITEREAD
exact 4 KB37,23838,315
exact 16 KB182
exact 64 KB022
exact 128/256 KB00
other small1025

An application-side coalescer was byte-correct, but 92,026 original requests became 91,876 wire commands, a reduction of only 0.16%. The requests were already individually active rather than accumulating as a mergeable batch. The limiting granularity therefore originates above the ring.

The single-page restriction is the blocker

Every workaround still pays one complete framework lifecycle per page-sized task: callback, UserGetDataBuffer, descriptor and mapping ownership, data movement and individual completion. QD64 can overlap these lifecycles; it cannot remove them.

For a 152 MiB transfer, the arithmetic is:

Request sizeRequest count
4 KB38,912
16 KB9,728
64 KB2,432
256 KB608

We have not yet measured Apple Silicon, but its 16 KB page does not change the verdict. Even assuming ideal 16 KB tasks, the same file still requires almost ten thousand complete framework lifecycles. A larger system page reduces the count but does not remove the page-bound architecture. Measuring Silicon would refine the number, not the conclusion, because the constraint we need removed is single-page, not 4 KB specifically.

What we actually need

A self-created IOBufferMemoryDescriptor only describes DEXT-owned staging memory. It is not the descriptor of the current DoAsyncReadWrite request, and it does not make dmaAddr a documented CPU-accessible pointer.

For a software-backed block device, we need the request-scoped memory object: a documented, CPU-accessible, multi-page descriptor with defined length, direction, mapping, synchronization, ownership and asynchronous lifetime. DoAsyncUnmap already carries an IOMemoryDescriptor in the same IOUserBlockStorageDevice class, while DoAsyncReadWrite exposes only dmaAddr.

Such an API would not guarantee line-rate performance. It would remove the artificial requirement that a software network block device be forced through an IODMACommand/DART-dependent single-page workaround.

FSKit

We considered the FSKit/raw-DiskImage approach seriously, but for a native iSCSI initiator it is not an equivalent solution.

The device it produces is a raw disk image, not a SCSI device. It exposes disk-image block semantics, so the behavior our initiator implements at the SCSI transport level has nowhere to live: Persistent Reservations, sense data, Unit Attention, proper SCSI error reporting, task management and task ordering. FSKit models a filesystem, and the disk-image indirection repurposes it as a byte-backing store, so the result is a block device layered over a file rather than a native one.

It is also fragile as a product foundation. The block device exists only while the FSKit mount and the hdiutil attachment stay alive, so an extension crash, an app update or an unclean teardown takes the device, and anything mounted on it, with it.

For byte movement it may well be faster than the current single-page SCSI path, and we are not disputing that. It is a different, non-native architecture that discards the SCSI device model our product is built on.

SCSIControllerDriverKit is therefore functionally viable for this use case, but the current page-bound request path is not product-viable for us. The shared ring makes the workaround substantially better; it cannot remove the reason the workaround exists.

Without the single-page restriction, performance is an engineering problem. With it, performance is an API-architecture problem.

Does this measured result match your technical view of the remaining constraint?

If it does, we are left waiting for a kernel fix: a request-scoped, multi-page descriptor. For a software device the clean home for it is BlockStorageDeviceDriverKit, which sidesteps IODMACommand entirely; without a multi-page path there or in SCSIControllerDriverKit, every path we have stays pinned to one page per request, 4 KB on Intel and 16 KB on Apple Silicon. Such a change would ship only in a future macOS, which puts Intel-based Macs permanently outside this feature. That is a trade-off we can live with.

Best regards,

Torsten

Hello @Aviontex and @DTS Engineer, I am a user who has been following this thread from the sidelines. I will not rehash the technical detail. You and the developer have that covered in far more depth than I could add. My angle is simpler. For a long time the ways to reach a NAS over iSCSI on a Mac have felt either dated or expensive to me, so a modern native option is something I would really want for home or business use. If it can reach normal LAN speed, I am in.

So here is my only question. From where things stand today, do you see a realistic chance that write speed on this native path reaches usable levels? Or is that a hard limit for the foreseeable future? I am not asking for a date, only your honest read, because it tells someone in my position whether to wait for the native route or stay on what exists now.

Thank you for the time you have already put in here.

Best regards!

Hi @lazarro!

That’s exactly our goal. We want the native iSCSI path to be really fast.

From my side it no longer feels like a question of if Apple will provide the missing descriptor support, but rather when. I’m hoping they play along because without that change this path simply won’t become what it needs to be. I’m keeping my fingers crossed for all of us ;)

I don’t expect Kevin to be able to answer the timing question here in the forum anytime soon. We will probably both have to wait a bit and it might unfortunately take some more time.

Best regards,

Torsten

BlockStorageDeviceDriverKit grant confirmed by support but shows "No Requests" in the portal. How to resolve?
 
 
Q