Mounting FSKit with FSPathURLResource programatically in MacOS 26

Hi, I'm trying to mount my FSKit volume with a client app (SwiftUI).

I already successfully did it with the "mount" command and I can instantiate my file-system with FSPathURLResource.

Also, I managed to mount the file-system with DiskArbitration in a SwiftUI app, but I only managed to get it working with FSBlockDeviceResource.

Is there a way to programmatically do it in a client app? Or is "mount" command currently the only option?

Answered by DTS Engineer in 856791022

I already successfully did it with the "mount" command and I can instantiate my file-system with FSPathURLResource.

What is your file system actually "doing"? What's the path target?

The issue here:

Also, I managed to mount the file-system with DiskArbitration in a SwiftUI app, but I only managed to get it working with FSBlockDeviceResource.

...is that block storage devices are the only reason DiskArbitration exists at all. More specifically, DiskArb exists because the expectation that disk will automatically mount when you plug them in is fairly complicated to implement, which then to its larger role of telling the rest of the system what was going to happen and letting them "vote" on that activity. None of that really applies to other file system types (for example, network file systems or disk images), which basically all work by saying "mount this target using this specific file system". Note, for example, that while DiskArb can "see" network volume mounts (meaning, they appear in its callbacks), it can't actually initiate them. The mount itself is either initiated through the NetFS.framework or one of the mount_* commands.

That leads to here:

Or is "mount" command currently the only option?

In practice, "/sbin/mount" is the system’s primary mounting interface. I think the "mount()" syscall is better understood as the SPI mount commands use to communicate with the kernel, NOT the API apps use to "mount volumes". Notably, the way diskarbitrationd ultimately mounts volumes is by using posix_spawn to run "/sbin/mount". There's nothing particularly "wrong" about doing the same thing by calling "/sbin/mount" yourself.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

I already successfully did it with the "mount" command and I can instantiate my file-system with FSPathURLResource.

What is your file system actually "doing"? What's the path target?

The issue here:

Also, I managed to mount the file-system with DiskArbitration in a SwiftUI app, but I only managed to get it working with FSBlockDeviceResource.

...is that block storage devices are the only reason DiskArbitration exists at all. More specifically, DiskArb exists because the expectation that disk will automatically mount when you plug them in is fairly complicated to implement, which then to its larger role of telling the rest of the system what was going to happen and letting them "vote" on that activity. None of that really applies to other file system types (for example, network file systems or disk images), which basically all work by saying "mount this target using this specific file system". Note, for example, that while DiskArb can "see" network volume mounts (meaning, they appear in its callbacks), it can't actually initiate them. The mount itself is either initiated through the NetFS.framework or one of the mount_* commands.

That leads to here:

Or is "mount" command currently the only option?

In practice, "/sbin/mount" is the system’s primary mounting interface. I think the "mount()" syscall is better understood as the SPI mount commands use to communicate with the kernel, NOT the API apps use to "mount volumes". Notably, the way diskarbitrationd ultimately mounts volumes is by using posix_spawn to run "/sbin/mount". There's nothing particularly "wrong" about doing the same thing by calling "/sbin/mount" yourself.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Thanks for the comprehensive answer!

My file system is mounting a video container which contains RAW DNG images, so the volume is actually exposing these DNG files.

I'm glad to say that mounting with "mount" command also works with passed security scope, when enabling "FSRequiresSecurityScopedPathURLResources". I was constantly trying to pass in a security scope bookmark through my client app, but in the end this option did it for me.

If I may ask a follow up question, what do you think would be a preferred way to mount these files that my file system supports (they have ".mcraw" file extension) in Finder? Is having a client app that associates with this file extension okay? Which in turn calls the "mount" command internally.

But that would cause some problems with App Sandbox, since I don't think it's possible to call "mount" with Sandbox enabled. That I think is the current limitation.

Are there any plans to be able to do it with Sandbox in the future?

Thanks for the comprehensive answer! My file system is mounting a video container which contains RAW DNG images, so the volume is actually exposing these DNG files.

Cool! That's exactly the kind of thing FSPathURLResource is intended to support.

If I may ask a follow-up question, what do you think would be a preferred way to mount these files that my file system supports (they have ".mcraw" file extension) in Finder? Is having a client app that associates with this file extension okay?

Yes, that's exactly what I'd do. FYI, this is basically how DiskImage mounting works except that it's preparing the content for the KEXT when it publishes an artificial block device.

But that would cause some problems with App Sandbox, since I don't think it's possible to call "mount" with Sandbox enabled. That I think is the current limitation.

Please file a bug on this, then post the bug number back here. As part of that bug, please note how close you are to shipping and if you want to ship on the Mac App Store.

Are there any plans to be able to do it with Sandbox in the future?

As you might expect, I can't talk about our future plans. What I will say here is that part of FSKit's designs is that it not only replaces the VFS layer itself but that it also helps file systems "fit" comfortably into the larger system. As part of that integration, I do think it's important that we provide a mount API solution that works with systems like the App Sandbox.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Actually, for now, I'm going to put the project on ice, since I can't get the satisfactory performance out of it.

This project is actually just a rewrite of an existig project I did a while ago, but it used macFUSE and its kernel extension.

To compare, for the same functionality, the macFUSE implementation uses about 40% of CPU, while the FSKit one uses between 100 and 150%.

I tried squeezing the last drops of performace out of the FSKit one, but it seems I hit the ceiling.

Unfortunately, I also can't seem FSVolumeKernelOffloadedIOOperations, since this is a virtual filesystem, without the underlying block device or similar (correct me if I'm wrong).

Nevertheless, I fully support FSKit and the efforts behind it.

If you're interested in the code, you can find it here: https://github.com/baso53/mcrawfs

Actually, for now, I'm going to put the project on ice, since I can't get the satisfactory performance out of it.

I totally understand, but I'd still appreciate you filing a bug for an App Sandox compliant, non-block FS mount API. This is an area that we're actively looking at, and developer bugs are helpful for scheduling and work prioritization.

To compare, for the same functionality, the macFUSE implementation uses about 40% of CPU, while the FSKit one uses between 100 and 150%.

I tried squeezing the last drops of performance out of the FSKit one, but it seems I hit the ceiling.

Unfortunately, the answer here is basically "yes, that's where things stand today". We haven't done much to optimize the FSVolumeReadWriteOperations path, so its current performance is not great. That's definitely something I'd expect to improve over time.

Unfortunately, I also can't seem to use FSVolumeKernelOffloadedIOOperations, since this is a virtual filesystem, without the underlying block device or similar (correct me if I'm wrong).

Hmmm.... well, yes and no. Strictly speaking, you're absolutely right. FSVolumeKernelOffloadedIOOperations works by passing dev node offsets into the kernel, so you can't use it without a dev node.

However, strictly speaking, you can actually pass the "diskimage-class=CRawDiskImage" option into hdiutil, which will then use the backing store for a device node. There's actually a post on this here by someone trying to get MFSLives working again.

Actually, using this technique on an arbitrary file might require zero padding the file so that you're an even block multiple, but file cloning means that isn't a particularly slow/expensive operation. Aside from that, I think this would let you use FSVolumeKernelOffloadedIOOperations for anything that only targeted a single file. Ironically, it would also sidestep the app sandbox mount issue, as you'd not be able to mount using DAMount.

Having said that, using FSVolumeKernelOffloadedIOOperations also requires you to be directly returning the source data (not post-processing the data first), so I'm not sure how well it would work for what you're doing. I'm also not sure how the performance and effort would work out, but there certainly are cases where it might be a useful approach.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Mounting FSKit with FSPathURLResource programatically in MacOS 26
 
 
Q