Kevin, thank you for the detailed responses — this is exactly the kind of
clarity we were hoping for. Let me work through your points.
On app-sandbox=true
The reframe is helpful. We were reading "sandbox" as "locked down" rather than
"opt-in capability declaration." That makes much more sense architecturally.
The practical follow-on question: what entitlements exist today for block
device ioctls (DKIOCGETBLOCKSIZE, DKIOCGETBLOCKCOUNT)? We currently work
around their absence with a path→size registry, but if we can simply declare
the entitlement, that's the right fix. Similarly for any IPC socket path we'd
use for the management layer.
On the management plane
Good news: we already implemented a UNIX socket approach — a zfsd management
daemon that receives ZFS_IOC_* requests over a socket, paired with a
libzfs_core transport that connects to it instead of opening /dev/zfs. The
open question is whether the sandboxed extension can create and bind a socket
at a path reachable by privileged tools outside the sandbox (e.g.,
/var/run/zfs/zfsd.sock). If that's permitted without a special entitlement,
this blocker is resolved for us.
Your third option — using the filesystem itself as a control channel — is
interesting for in-band dataset operations, but circular for pool-level work
(create, import, destroy) that must happen before any dataset is mounted.
On zvols
The hdiutil/CRawDiskImage suggestion could work for VM disk image consumers
(Parallels, VMware) if the extension can present zvol I/O as a file-like
object. Two follow-up questions:
Is IOUserBlockStorageDevice in DriverKit a viable path for dynamically publishing block devices from userspace? Could an FSKit extension coordinate with a companion DriverKit extension to publish zvols when a pool is imported?
Is the hdiutil path accessible from within the extension's sandbox, or does it require coordination with a process outside?
On N:M
The APFS observation is the most useful validation we could have asked for. Apple knows about it.
On ARC memory limits
Fair point — we were speculating. We haven't actually hit a limit yet. The
concern was that ARC on a 64 GB system typically uses 20–30 GB, and we were
anticipating that a sandboxed process holding that much memory would attract
attention from the system.
The metadataRead suggestion is interesting. We're currently using the standard
read path. If metadata reads are accounted to the kernel rather than the
process, that could meaningfully reduce ARC's apparent footprint. We'll
revisit with actual numbers when we get there. Is there documentation on what
memory limits a sandboxed FSKit extension actually operates under?
On background operations
We were speculating here too — haven't tried it. Good to know threads are
unrestricted while mounted. We'll come back if we actually hit a problem.
On UBC / buffer cache
Thank you for the correction — that's a much clearer framing. The issue isn't
UBC access; it's that ZFS needs to sit below the UBC as well as above it, and
FSKit currently only provides the top layer. The two-layer architecture you
described (IOMedia below UBC for transformation + VFS above for the POSIX
layer) is exactly what the kext implements today.
You mentioned SCSIControllerDriverKit with
UserGetDataBuffer/UserProcessBundledParallelTasks as a potential path for a
virtual I/O transformation layer. Is that a supported and documented route for
this use case, even if difficult? Or is it more theoretical? If it's
genuinely viable, we'd rather know that now than assume the door is closed.
Action items
We'll file separate bugs for the three hard blockers (management plane, zvols,
N:M multi-device/multi-dataset) and post the numbers back here.
But at the end of the day, we wanted to test out the fit with FSKit and it is rather pleasing we got it to do "something at all", which is quite hopeful if'en Apple does decide to remove KEXT support. Shiny.
Topic:
App & System Services
SubTopic:
Core OS
Tags: