While building an SMB 2/3 client as an FSKit file system module (FSUnaryFileSystem + FSVolume, the macOS 27 Handler protocols), I ran into a number of framework-level issues. I have filed each one with a title starting "FSKit:" so they are easy to find, and every report has a minimal reproduction attached: a small in-memory FSKit module (no network, no disk, no cache of its own), so none of them depend on SMB. All were measured on macOS 27.0 (26A5406e and 26A5416b) with Xcode 27.0 beta 5.
Summaries below in case anyone else is hitting these.
FB24419773: renameatx_np with RENAME_SWAP returns success but destroys the destination file. On any FSKit volume a RENAME_SWAP is performed as an ordinary clobbering rename: rc=0, but the destination's contents are silently lost instead of exchanged. The module cannot refuse it because renameItem receives no flags; a swap and a plain overwriting rename look identical. (RENAME_EXCL works correctly.)
FB24419825: a negative lookup is cached permanently. Once anything gets ENOENT for a name on an FSKit volume, the kernel serves that ENOENT for the life of the vnode. If the file is created later (for example by another machine on a network volume), it stays unopenable by that name indefinitely, while ls of the same directory lists it. There is no API through which a module can report that a name now exists.
FB24419858: a data-cache grant from openItem can be applied after the module has already invalidated. The grant in FSOpenItemResult is applied asynchronously after the module's reply, and an invalidation issued in that window succeeds (setCacheState returns no error) and is then overwritten by the stale grant. The result is a kernel cache no future event will invalidate; readers see stale data.
FB24419870: synchronize(flags:) is never called on a URL-backed volume. fsync(2), fcntl(F_FULLFSYNC), fcntl(F_BARRIERFSYNC) and sync(8) all return success with zero calls reaching the module, so durability is reported and never established. A packet capture of the same SMB share shows five SMB2 FLUSH requests through Apple's smbfs and zero through an FSKit module.
FB24419894: FSItemSetAttributesRequest.consumedAttributes is never observed, and wasAttributeConsumed(.changeTime) answers about the wrong attribute. Consuming everything and consuming nothing are indistinguishable to the caller (chmod returns 0 either way), even though the setAttributes documentation says the upper layers will detect unsupported attributes. Separately, wasAttributeConsumed answers YES for changeTime when only accessTime was consumed, and never answers correctly about changeTime itself; this part reproduces by constructing the request directly, no file system needed.
FB24419911: restrictsOwnershipChanges = true does not reject non-superuser chown. The property is documented as "the volume rejects a chown(2) from anyone other than the superuser", but on an -o owners mount a non-root chgrp is delivered to the module's setAttributes anyway, so every module has to enforce the policy itself.
FB24419932: a failed activate wedges the resource URL. After a module's activate throws once, every later mount of the same URL string fails with "Resource busy" (fskitd logs "Can't start new task, resource state is 5"), while the same volume under a different URL spelling mounts fine. For a network module the ordinary trigger is one wrong password. Recovery requires killing both fskitd and the extension process.
FB24419964: enumeration cannot report extended-attribute presence. FSItem.Attributes has no per-item "has xattrs" field, so one cold ls -l of a 500-entry directory costs about 2,000 FSKit boundary crossings: an xattr call per entry plus a "._name" AppleDouble sidecar lookup per entry, and each of those ENOENTs is then pinned by FB24419825. Suggestion: a per-entry hasExtendedAttributes flag so getattrlistbulk can be satisfied from the enumeration.
FB24419974: no byte-range lock operations. flock(2) and fcntl(2) locks on an FSKit mount stay kernel-local and never reach the module, so advisory locks cannot coordinate between clients of a network file system. Suggestion: an optional lock-operations handler.
FB24419979: no ACL or security descriptor operations. ls -le, chmod +a, acl_get_file(3) and cp -p with ACLs cannot work on any FSKit volume; a network server's real ACLs are invisible behind synthesized mode bits. The nearest surface, FSVolumeAccessCheckHandler, can only be asked yes/no questions about a descriptor the module has no way to provide. Suggestion: an optional ACL-operations protocol.
If any of these are biting you too, duplicate feedbacks referencing the FB numbers above genuinely help with prioritization.
While building an SMB 2/3 client as an FSKit file system module (FSUnaryFileSystem + FSVolume, the macOS 27 Handler protocols)
To start with, as a general comment, the reality is that FSKit isn't currently at a place where it can properly support a network file system. It's certainly closer this year than it was last year, but it's not really "there" yet. As usual, I can't talk about our future plans, but the reality is that FSKit's basic function is to replace the in-kernel VFS layer, a task which it clearly cannot yet do. For most of the bugs I don't specifically mention, the answer boils down to "yes, that's a VFS feature FSKit does not yet support".
Looking at a few issues that I wanted to directly address:
FB24419773: renameatx_np with RENAME_SWAP returns success but destroys the destination file.
This is entirely a bug. In the long run, FSKit needs an API to support this properly, but until then (and the default behavior), VOL_CAP_INT_RENAME_SWAP should be 0, which would mean RENAME_SWAP never reached your extension.
FB24419894: FSItemSetAttributesRequest.consumedAttributes is never observed, and wasAttributeConsumed(.changeTime) answers about the wrong attribute. Consuming everything and consuming nothing are indistinguishable to the caller (chmod returns 0 either way), even though the setAttributes documentation says the upper layers will detect unsupported attributes.
First off, to clarify, "unsupported" and "failed" are totally different cases, with the behavior of unsupported attributes being varying depending on the attribute. For many attributes, the unsupported behavior is that the operation succeeds without actually changing anything.
Separately, wasAttributeConsumed answers YES for changeTime when only accessTime was consumed, and never answers correctly about changeTime itself; this part reproduces by constructing the request directly, no file system needed.
...and, yes, that's a bug.
FB24419858: a data-cache grant from openItem FB24419825: a negative lookup is cached permanently. FB24419932: a failed activate wedges the resource URL.
Those are bugs as well.
FB24419911: restrictsOwnershipChanges = true does not reject non-superuser chown. The property is documented as "the volume rejects a chown(2) from anyone other than the superuser", but on an -o owners mount a non-root chgrp is delivered to the module's setAttributes anyway, so every module has to enforce the policy itself.
...and so is this, though it (r.177650457) appears to actually be a complicated side effect of doing the pathconf man page ("return 1") says instead of what POSIX requires ("return _PC_CHOWN_RESTRICTED").
FB24419870: synchronize(flags:) is never called on a URL-backed volume. fsync(2), fcntl(F_FULLFSYNC), fcntl(F_BARRIERFSYNC) and sync(8) all return success with zero calls
FYI, the complication here is that both fcntl calls (and I think the other two as well) are actually built on the generic VFS IOCTL system. Implementing that generic mechanism for FSKit is slightly broken/strange, since the main problem it solves (the VFS layer has a difficult time communicating with user space) is a problem FSKit simply does not have. Putting that another way, if you want to send commands to your FSKit extension, routing those commands through the kernel is a bit silly. FSKit will need to address this issue, but it’s going to require more work than it would otherwise appear.
__
Kevin Elliott
DTS Engineer, CoreOS/Hardware