← Back · NextBSD Research · supersedes FreeBSD DiskArbitration — porting plan (2026-05, deferred)
Who should mount what on NextBSD, and when? This covers the root filesystem, the live union, the Linux ABI filesystems, and USB sticks going to /Volumes. It answers each by asking what Apple actually does and reading the code NextBSD ships. Three questions drove it: do we need /etc/fstab at all, how should the Linuxulator's mounts be handled, and what would a real DiskArbitration epic look like, including whether vermaden's automount fits.
The short answers.
/etc/fstab on Macs in 10.4. The boot hook NextBSD vendored runs mount -vat nonfs only if the file exists (launchctl.c:2401), and it never ran on a stock Mac. Nothing on either NextBSD medium needs the file to boot, fsck, remount root rw, run df or shut down. Removing it fixes #467 by construction. It needs two small companion changes: move noatime into launchd's root remount, and pick a single owner for the root fsck. See §3.container system start. Your #54 decision (“no LaunchDaemon, mounts stay manual”) still stands under no-fstab: the manual path becomes “an admin creates /etc/fstab”, which is Apple's own admin hook. An org.nextbsd.linux one-shot is the Darwin-shaped upgrade for when Linux support becomes default. See §5.automount. Use its per-filesystem mount table as a reference and nothing more. It needs devd, which NextBSD removed. It sets no nosuid/nodev, runs fsck -y on every plug, uses one static owner, and its detach step deletes every empty directory under the mount prefix. Under /Volumes that would include Gershwin's own disk-image and network mount points. See §6./Volumes, vermaden and GershwinThe whole boot mount sequence, in execution order. All of it is on main and was confirmed against the CI boot log.
| # | Step | Where | Needs fstab? |
|---|---|---|---|
| 1 | Kernel mounts root read-only from the baked ROOTDEVNAME="ufs:/dev/ufs/ROOTFS". On installed EFI systems, loader.conf overrides it with vfs.root.mountfrom=ufs:/dev/ufs/NEXTBSD. The kernel forces ro regardless of options. devfs goes on /dev. | nextbsd-kernel config/NEXTBSD:15; FreeBSD vfs_mountroot.c:789, 1148-1153; installer do-install.sh:300 | no |
| 1′ | Live media only: the mfsroot /init runs devfs, then cd9660 on /media, then uzip on /rofs, then tmpfs /cow, then mount_unionfs /cow /rofs, then devfs on /rofs/dev, then vfs.pivot, then execs launchd. | nextbsd build.sh:885-975 | no |
| 2 | launchd (PID 1), before any job: if / is MNT_RDONLY, run fsck -p / and then mount -uw /. This is NextBSD-local code; Apple's launchd did no mount work. | launchd.c:306-313, 443-475 | no (statfs fallback) |
| 3 | launchd spawns launchctl bootstrap -S System, which runs system_specific_bootstrap(). That function is byte-identical to Apple's launchd-842.92.1 up to line 2570. | core.c:7336; launchctl.c:2285-2494 | — |
| 3a | Applies /etc/sysctl.conf (one sysctl -w per line). | launchctl.c:2326, 4330-4365 | — |
| 3b | do_potential_fsck() is dormant: it returns immediately because step 2 already made / rw. Its Darwin fsck -q is not a valid FreeBSD flag anyway. | launchctl.c:2357, 4019-4113 | only in a failure path |
| 3c | Reads /etc/launchd.conf. | launchctl.c:2394 | — |
| 3d | if (path_check("/etc/fstab")) mount -vat nonfs. This is plain -a, so late lines are never mounted. It remounts / from the root line, which is where noatime comes from today and is also the cause of #467 on the live union. | launchctl.c:2400-2405; FreeBSD mount.c:300-323, 456-458, 567 | this is the only fstab consumer |
| 3e | empty_dir(/var/run) and empty_dir(/tmp). These force-unmount anything mounted beneath either path, so an fstab mount on /tmp/scratch is undone one step after it is mounted. A mount on /tmp itself survives, because the baseline is the directory’s own st_dev (launchctl.c:4252-4258). | launchctl.c:2432-2433, 4246, 4289 | — |
| 3f | load -D all starts every LaunchDaemon, diskarbitrationd included. No plist mounts anything. | launchctl.c:2469-2476 | — |
The shipped fstab, from nextbsd-overlays rootfs/private/etc/fstab, has a single commit. Both claims in its header are now false: root comes from the kernel's ROOTDEVNAME (#188), not loader.conf, and launchctl does run mount -a.
# The kernel mounts root directly via loader.conf's vfs.root.mountfrom
# (ufs:/dev/ufs/ROOTFS, options=rw). This entry exists for mount(8) /
# df(1) correctness; launchd is PID 1 and bypasses rc.d, so nothing
# runs `mount -a` over the rest of this file.
/dev/ufs/ROOTFS / ufs rw,noatime 1 1
| Step | FreeBSD rc.d | Mac OS X 10.0–10.3 (/etc/rc) | 10.4–10.9 (rc → launchctl bootstrap) | 10.10+ / APFS |
|---|---|---|---|---|
| Root mounted ro | kernel | kernel | kernel | kernel; sealed snapshot, verified by the bootloader or kernel |
| Root fsck | rc.d/fsck, fstab pass numbers (skipped if there is no fstab) | /etc/rc.boot fsck -p | do_potential_fsck() fsck -q/-fy, no fstab | launchd boot task fsck -qL -R 1 |
| Root rw | rc.d/root mount -uw / | via mount -vat hfs (see †) | mount -uw /, only if ro | mount -P 2: upgrade_mount("/"), or on ROSV root stays ro and apfs_boot_util 2 mounts Data |
/dev, /dev/fd | kernel devfs; fdescfs optional | kernel devfs, plus mount -t fdesc -o union stdin /dev in rc | kernel devfs, with fdesc folded in | kernel (bsd_init.c:999-1006, devfs_fdesc_init()) |
| Other local filesystems | mountcritlocal mount -a | mount -vat hfs, mount -vat ufs | [ -f /etc/fstab ] && mount -vat nonfs, skipped on every stock Mac | no mount -a task; apfs_boot_util 1/2 mounts the volume group; fstab is honoured by diskarbitrationd |
| Network filesystems | mountcritremote | NetInfo /mounts | automountd (10.5+) | automountd -fstab/-static maps |
| Swap | swapon -aq (fstab sw) | dynamic_pager | dynamic_pager | enable-swap task; VM volume |
/tmp, /var/run cleanup | cleartmp, var | rc | empty_dir() (force-unmounts) | dirs_cleaner |
| Mount points on a ro root | — | — | — | /etc/synthetic.conf, materialised by the kernel via apfs.util |
Ships /etc/fstab? | yes | 10.0: no (only NeXT fstab.hd/.sd/.rd). 10.3: comment-only | no. From files-467 on, the files project installs fstab only ifeq "$(Product)" "iPhone" | no (verified on macOS 27.0) |
† The 10.0–10.3 rc scripts contain no unconditional mount -uw /. Darwin mount(8) forces MNT_UPDATE for / (diskdev_cmds mount.c:779), and later Libinfo synthesises a root fstab entry when the file is missing (Libinfo-600 file_module.c:1876-1913, 2011-2015). That is how getfsfile("/") and df stay correct on a Mac with no fstab. The exact 10.0 mechanism is unverified.
What fstab is for on modern macOS. fstab(5) describes it as an admin-maintained file, edited with vifs(8), that is read by diskarbitrationd, fsck, mount and umount. diskarbitrationd consults it “for user-defined mount points, indexed by filesystem” by UUID=/LABEL=, and automountd builds its -fstab/-static maps from it. It is a policy overlay, not a boot mount list. Apple moved the boot-critical set out of fstab and into code (mount -P never reads fstab on macOS: diskdev_cmds-757 mount.c:286-288).
The model that fits the live ISO is modern macOS, not 10.x. A read-only sealed root plus a writable volume mounted by a PID-1 boot task, with top-level mount points declared in synthetic.conf, is structurally NextBSD's read-only uzip base plus the tmpfs union assembled by /init. The Darwin lesson is to keep boot-critical mounts in boot code and never express them as fstab lines.
We checked every consumer of /etc/fstab that ships in the image. The base is a full buildworld minus the superseded list, and the Darwin userland was grepped for getfsent/getfsfile/_PATH_FSTAB: only launchctl.c uses them. The FreeBSD loader is the one consumer outside userland.
| Consumer | Runs at boot? | Without fstab |
|---|---|---|
launchctl mount -vat nonfs | yes, if the file exists | skipped entirely, so #467 cannot happen |
Loader getrootmount() | yes | reads the fstab root line to set vfs.root.mountfrom and .options (FreeBSD stand/common/boot.c:320-407). That is where CI’s Trying to mount root from ufs:/dev/ufs/ROOTFS [rw,noatime] comes from. Without the file, the kernel falls back to ROOTDEVNAME (vfs_mountroot.c:930-932) or the installer’s loader.conf line. |
launchd fsck -p / | yes (disk) | resolves / via getmntpoint(), defaults to ufs, and runs the same fsck_ufs -p (fsck.c:192-230). Root is still checked. |
launchd mount -uw / | yes (disk) | have_fstab=0 branch uses f_mntfromname (mount.c:357-395). Identical result. |
Root noatime | via step 3d | lost. Without fstab, mount -uw / passes only noro, and an MNT_UPDATE clears every update-mask flag not re-specified, MNT_NOATIME included (vfs_mount.c:1423-1430). So it must be on launchd’s command line. |
launchctl fallback fsck -fy | dormant | no-arg checkfstab returns 8 and the machine halts (preen.c:99-102). Reachable only if launchd's own remount has already failed. |
swapon -a, umount -a, bare fsck | nothing runs them | “fstab: /etc/fstab:0: No such file” when run by hand (umount -a exits 1) |
df, mount (no args), shutdown | — | unaffected: getmntinfo, and launchd calls reboot(2). The header's “exists for mount(8)/df(1) correctness” is wrong. |
| Installer | — | does not write an fstab. It cpdup-clones the running root and seds the label only if [ -f ] (do-install.sh:288). |
| Swap | none exists | no dependency. E14's swapd is the activation path (see below). |
| diskarbitrationd | skeleton | unaffected today |
| Option | Live | Installed | Verdict |
|---|---|---|---|
| A. Ship no fstab | fixes #467 | boots fine; needs noatime moved into launchd; the fsck -fy halt edge case remains unless that dead Darwin path is removed | recommended: this is what every Mac since 10.4 does |
| B. Comment-only fstab (root line removed) | fixes #467; mount -a becomes a no-op | same as A, minus the stderr noise and the halt edge case; an obvious place for admin lines | conservative fallback, also fine |
C. Root line with noauto (#467 option A) | fixes #467 | keeps a misleading entry that names the wrong device on live media | works, but fixes the symptom rather than the model |
| D. Live-only removal | fixes #467 | unchanged, except the installer clones the live root, so installs differ by which medium they came from | not recommended |
Recommendation: A, with two companion changes.
launchd.c:446: remount with mount -u -o rw,noatime / so installed disks keep today's observed noatime (CI log line 7985).launchd_root_make_writable() and launchctl's do_potential_fsck() exist, and Apple's launchd did neither itself. Keep launchd's version, because it runs first and uses valid FreeBSD flags. Delete or #ifdef the dormant Darwin fsck -q/-fy path, which removes the halt edge case with it.Existing installs keep their fstab: the overlay is not package-owned, so pkg upgrade never touches it. The new behaviour applies to new images only. If anyone wants B instead, the only difference is whether the overlays repo ships an empty file.
Read from apple-oss-distributions/DiskArbitration at 535.120.1.0.1 (current) and 268 (10.9).
getfsent copy (diskarbitrationd/fstab.c) and builds a mount map in __DAMountMapCreate1 (DASupport.m:1488-1634). Only three spec forms are accepted: UUID=, LABEL= (matched against the volume name) and DEVICE=<plist>. Anything else produces no entry: /dev/da0p1, tmpfs, host:/export, none, and a root line are all ignored.none means the default), options passed through verbatim, noauto, and a type filter matched against the fs-bundle CFBundleName. freq and passno are ignored.DAMountWithArguments(disk, …) (DAMount.c:1312-1430), which takes a disk DiskArbitration has already discovered. gDAMountMapList1 has exactly three references, and none of them iterates fstab to mount. Re-reading is gated on mtime at the next disk event after idle; there is no file watch.mount -vat nonfs path would act on it.IOMedia appears, then Probe, then Peek, then Mount, then Appeared (DAStage.c:139-559).
/System/Library/Filesystems/*.fs whose FSMediaProperties (content hint, Leaf, Whole) match, sorted by FSProbeOrder. Each bundle's <util> -p returns the name, -k the UUID, and fsck -q reports whether the volume is clean./sbin/mount -t <kind> -k -o … as the disk's owner uid. FreeBSD mount(8) has no -k, and CFBundleName must be the FreeBSD vfs type (msdosfs, not msdos)./Volumes/<name>, falling back to <name> 1 … <name> 99. It is created with mkdir 0111 and chowned (DAMount.c:725-898). At startup DiskArbitration sweeps /Volumes and removes stale directories (DAMain.c:150-246), so the OS owns /Volumes, which settles gershwin-internal#22. (Gershwin’s dscli init currently creates it 01777, dscli/main.m:1085-1092.)DAMount.c:940-972, 1527-1543): removable and external media are untrusted and get nosuid,nodev,noowners; internal media is trusted. Media that is not writable gets rdonly. On FreeBSD, nodev no longer exists and noowners has no equivalent; ownership-less filesystems get it through the helper’s -u/-g/-m options instead.DAMount.c:1498-1521). They are mounted at login and unmounted at logout.fsck -y once, then retries with force,rdonly.kNotifyVFSMount, DiskArbitration walks getmntinfo and adopts NFS/SMB mounts as disks (DAServer.c:3362-3406). That is how Finder sees them. DiskArbitration never initiates network or pseudo-filesystem mounts.Force overrides, and on EBUSY a dissenter carries the offending PID. The “volume mounted” signal clients watch for is DescriptionChanged on VolumePath.MachServices com.apple.DiskArbitration.diskarbitrationd, KeepAlive, no RunAtLoad.| Item | NextBSD today | Apple |
|---|---|---|
| Mach service | com.apple.DiskArbitration (diskarbitrationd.c:97, plist) | com.apple.DiskArbitration.diskarbitrationd (DAInternal.h:41). The client framework looks this name up, so rename before porting clients. |
| What it watches | newbus nodes via /dev/ioregistry (vtblk, umass, ahcich) | IOMedia: one object per whole disk and per partition. On FreeBSD that is the GEOM provider graph. |
| Framework, MIG, mounting, fstab | none; the daemon sleeps in while(!got_term) sleep(60) | full |
| Consumers | only datest | Finder, Disk Utility, installers |
What ports and what doesn't. The stage machine, request and queue plumbing, DAMount.c policy, fstab/vsdb overlays, the fs-bundle model, DACommand, the MIG interface and the whole client framework are C over CF, libdispatch and Mach, all of which NextBSD has. What needs rewriting is everything IOKit-specific: IOMedia creation and description, interest notifications, DKIOCEJECT, SCDynamicStore console user, notify(3) VFS keys, sandbox_check, Authorization Services, and proc_listpidspath. APFS, CoreStorage and FSKit are deleted. The code is APSL 2.0, like launchd already in the tree.
IOMedia → GEOM mapping. Whole disk = DISK-class provider; partition = PART provider. The content hint is gpart rawtype. GPT GUIDs are the same values Apple uses, but gpart prints them lower-case (kern_uuid.c:277), so they are upper-cased before matching fs-bundle FSMediaTypes keys. MBR rawtype is the decimal partition type and needs Apple’s IOStorageFamily name table. Probing is done with fstyp(8) (-l gives the label), wrapped in a *.util -p/-k shim. Removable, vendor and model come from CAM and the newbus parent, which is where the existing ioregistry watch is still useful. Adopting mounts it didn't make uses kqueue EVFILT_FS; that it delivers VQ_MOUNT on NextBSD is unverified. There is no devd, so the arrival event is the kernel registry channel plus a libgeom walk.
What's left of rc.d/linux's job on NextBSD. The module loads are gone: the Linuxulator, linprocfs and linsysfs are compiled into the kernel, NO_MODULES=yes is set, and kldload is stripped. fallback_brand=3 is already the kernel default (patch 0009). The only unowned piece is the five mounts:
linprocfs $emul/proc nocover
linsysfs $emul/sys nocover
devfs $emul/dev nocover
fdescfs $emul/dev/fd nocover,linrdlnk
tmpfs $emul/dev/shm nocover,mode=1777
These are rc.d/linux:74-80. /dev/shm needs no mkdir, because linux_dev_shm_create() puts shm/ in every devfs instance at ABI init (linux.c:699-709). #460 wants the same set on the native root for AppImages as well.
Apple never uses fstab or autofs for a subsystem's pseudo filesystems:
proc, sysfs, devtmpfs, /dev/shm and devpts per container (LinuxContainer.swift:445-456). The Rosetta guest agent mounts the virtiofs share and then writes the binfmt_misc registration (Vminitd+Rosetta.swift:21-34, Binfmt.swift:64-82). That registration is the exact analogue of fallback_brand.Disabled until turned on, and then mounts the SAN.container system start: registers its own launchd job.RunAtLoad; the kernel upcalls it through HostSpecialPort 11.| Option | Precedent | Status on NextBSD | Verdict |
|---|---|---|---|
H. Manual (the #54 decision). Under no-fstab it becomes “admin creates /etc/fstab with these lines”. | Apple's admin hook (mount -vat nonfs if fstab exists) | works today (#171's reboot evidence). Lines mount in file order, so devfs comes before fdescfs. Never use late; the lindebugfs … late line in #460 will never mount. | keep as the default while Linux support is opt-in |
a. org.nextbsd.linux one-shot (RunAtLoad, KeepAlive false) plus /usr/libexec/nextbsd-linux --compat [--native] | vminitd, the Rosetta guest, xsand, rc.d/linux | no kernel or launchd change. It ships in the package, so installs get it on upgrade, and it no-ops if /compat/linux is absent. For installs made after boot, use launchctl start org.nextbsd.linux, optionally from a pkg trigger. (NextBSD’s launchctl is the launchd-842 CLI, which has no kickstart.) | the Darwin-shaped upgrade when Linux support becomes default; this revisits #54 |
b. autofs direct map (/- auto_linux, -fstype=linprocfs) | macOS /- -static | technically works: automountd passes the location verbatim (automountd.c:347). But it needs options AUTOFS, which is absent and cannot be loaded as a module. Nested dev* keys trigger eagerly. stat() doesn't trigger. autounmountd would wipe /dev/shm. A dead daemon means a 30 s hang with no fallback to native /proc. | no; maybe later, for lazily mounting native /proc//sys only |
| c. Kernel mounts on ABI init | devfs | linux_common inits at SI_SUB_EXEC, before root exists, so this needs a mountroot hook and a new kernel patch | no |
e. WatchPaths/PathState on /compat/linux | — | inert: launchctl rewrites these keys to com.apple.fsevents.matching LaunchEvents (launchctl.c:1610-1648), and nothing on NextBSD delivers them (no EventMonitor job, no PATH_* semaphores in core.c:322-333) | not viable without writing an event monitor |
FUSE for AppImage (#460) needs no provisioning. fusefs is static, /dev/fuse exists from boot with mode 0666 (fuse_device.c:615-619), vfs.usermount=1 is patch 0008, and the Linuxulator itself translates Linux mount("fuse.*") into a fusefs mount (linux_file.c:1108-1132). An unprivileged mount end to end is still the untested item #460 lists.
/Volumes, vermaden and GershwinA 779-line sh script (v1.8.0, BSD-2 in its header) run by devd on every DEVFS CREATE/DESTROY for da|mmcsd|ugen|cd. Gershwin already installs it on its FreeBSD target (SystemPrepare.sh:584) and documents it. gershwin-desktop#60 only asks for MNT_PREFIX=/Volumes.
| Good reference material | Wrong for NextBSD |
|---|---|
The per-filesystem helper table: mount_msdosfs -L -D -u -g, mount.exfat, ntfs-3g, lklfuse for ext4/XFS, hfsfuse, mount -t cd9660 -o -e,-C=UTF-8. (The -C and mount_msdosfs -L/-D charset options need *_ICONV kernel options, which NextBSD’s module-less kernel lacks; see C7.) Also the ro fallback after retries, label-based names with collision suffixes (NICENAMES), and skipping system partitions (IGNORE_SYS_PARTS). | Requires devd, which NextBSD removed. Sets no nosuid/nodev, only noatime. Runs fsck -y on every plug. Uses one static USER/MNT_GROUP. USERUMOUNT setuids /sbin/mount*. It has no NVMe case, no eject and no API. Detach runs find $MNT_PREFIX -depth 1 -empty -delete, which under /Volumes would remove Gershwin's VolumeManager and NetworkVolumeManager mount points. |
The alternatives are worse fits:
-media has no events, no eject and no user ownership.GWDesktopManager.m:1142) diffs libs-gui’s mountedLocalVolumePaths (getmntinfo, NSWorkspace.m:2295) for mounts under the roots in +volumeMountRoots (/media, /Volumes, /run/media: Workspace.m:5493-5502). Anything DiskArbitration mounts under /Volumes appears with zero Gershwin changes.NSWorkspaceDidMountNotification is observed, but nothing on FreeBSD posts it. GNUstep's _GSWorkspaceCenter rebroadcasts workspace notifications over NSDistributedNotificationCenter (NSWorkspace.m:327-457). Gershwin itself posts Will/DidUnmount on [NSNotificationCenter defaultCenter] while its observers listen on [ws notificationCenter], so today those notifications never reach them (GWUnmountHelper.m:65-66, GWDesktopManager.m:155-168). A daemon posting NSWorkspaceDidMountNotification (object GSWorkspaceNotification, NSDevicePath) reaches every app. This is the bridge proposed in gershwin-desktop/issues#26.GWUnmountHelper falls back to sudo -A -E umount -f (GWUnmountHelper.m:102), and there is no real USB eject anywhere. That is exactly DADiskUnmount/DADiskEject with dissenters.If a demo is needed before Stage C lands, a throwaway vermaden setup is possible, but only with devd run from a LaunchDaemon, REMOVEDIRS=NO (to protect /Volumes), and USERUMOUNT=NO. It would still have no nosuid and would still run fsck -y. It is not recommended for a release.
Every ticket below is written out in full, with repo, labels, dependencies and exact Markdown body, on the E15 ticket drafts page. The drafting pass split C5 (adding C6, the fstab overlay) and D3 (into D3a–D3c), and added C7, a kernel ticket. The tables here are the summary.
| # | Repo | Ticket |
|---|---|---|
| A1 | nextbsd-overlays | Stop shipping rootfs/private/etc/fstab (or ship a comment-only one: option B). Closes #467. |
| A2 | nextbsd-userland | launchd root remount applies noatime (launchd.c:446). CI asserts noatime in the mount line. |
| A3 | nextbsd-userland | Single owner for root fsck and remount: remove or #ifdef launchctl's dormant Darwin do_potential_fsck() path (fsck -q is invalid on FreeBSD; fsck -fy halts without fstab). |
| A4 | nextbsd, nextbsd-userland | Fix stale comments: build.sh:318-319, 356-357, do-install.sh:14-15, 282-288 and the installer README. Add a boot-test gate on Cannot union mount root filesystem and fwexec(mount_tool. |
| A5 | nextbsd-userland | Decide on empty_dir() force-unmounting /tmp and /var/run children after mount -a. Either leave it as Apple did (document it) or skip mount points, as modern dirs_cleaner does. This matters for anything mounted beneath those paths; a tmpfs on /tmp itself is unaffected. |
| # | Repo | Ticket |
|---|---|---|
| B1 | docs / #54 | Document the manual path under no-fstab: “create /etc/fstab with these five lines, no late”. Correct #171's title and premise and #460's lindebugfs … late line. |
| B2 | nextbsd-userland | (When Linux support becomes default.) org.nextbsd.linux one-shot plus /usr/libexec/nextbsd-linux --compat [--native], idempotent (nocover), a no-op without /compat/linux, and launchctl start after pkg installs. |
| # | Repo | Ticket |
|---|---|---|
| C1 | nextbsd-userland | Rename the Mach service to com.apple.DiskArbitration.diskarbitrationd (daemon, plist, datest). Refresh the stale hwregd comments. |
| C2 | nextbsd-userland | DADisk model from GEOM. On a kernel-registry arrival, walk libgeom DISK, PART and LABEL providers and build the kDADiskDescription* keys (BSD name, whole/leaf, size, content hint = gpart rawtype, partition UUID, removable, internal, vendor, model). Log only. Reference: the installer's probe-disks.sh. |
| C3 | nextbsd-userland | Adopt mounts DiskArbitration didn't make: EVFILT_FS plus a getmntinfo diff, then DADiskCreateFromVolumePath. First verify VQ_MOUNT delivery on NextBSD. |
| C4 | nextbsd-userland | Filesystem bundles: /System/Library/Filesystems/{msdos,exfat,ntfs,ufs,cd9660,udf}.fs in Apple's schema, with an fstyp-backed *.util -p/-k shim that follows the FSUR_* exit contract. |
| C5 | nextbsd-userland | Stage machine and mount executor: /Volumes/<name>[ N] with mkdir 0111. Untrusted media gets Apple’s nosuid,nodev,noowners (noexec is open question 3); ms-dos gets -u/-g of the console user. Clean check without auto-repair; dirty volumes mount read-only. The helper table comes from vermaden's and dsbmd's. Includes the fstab UUID=/LABEL= overlay. Create and sweep /Volumes at startup. |
| C6 | nextbsd-userland | fstab UUID=/LABEL=/DEVICE= mount-map overlay with Apple’s exact semantics, using Apple’s vendored fstab.c (FreeBSD getfsent rejects noauto-only lines). |
| C7 | nextbsd-kernel | Compile in UDF, LIBICONV, MSDOSFS_ICONV, CD9660_ICONV, UDF_ICONV. Under NO_MODULES, mount_msdosfs -L/-D, mount_cd9660 -C and any UDF mount are otherwise impossible. |
| # | Repo | Ticket |
|---|---|---|
| D1 | nextbsd-userland | Port DAServer.defs and the client library (flat /usr/lib/system/libDiskArbitration.so, like SystemConfiguration and CoreFoundation in the tree) (sessions, Register*, CopyDescription, DiskListComplete/Idle replay). datest becomes a real client. |
| D2 | nextbsd-userland | Unmount and eject with approval broadcast, dissenters and PID lookup. Eject via CAM START STOP UNIT or CDIOCEJECT. |
| D3 | gershwin | Bridge: post NSWorkspaceDidMount/WillUnmount/DidUnmount as distributed notifications. GWUnmountHelper calls DiskArbitration instead of sudo umount -f. Making /Volumes mounts count as removable in NSWorkspace (exact-match GSRemovableMediaPaths) is a spike under E11: #474, with no upstream ticket for now. |
| D4 | nextbsd-userland | Console user source (the SCDynamicStore analogue from loginwindow) and deferral of removable mounts until login. A minimal DiskArbitrationAgent for “not ejected properly” and “unreadable” dialogs. |
| D5 | nextbsd-kernel | Drop patch 0008 (vfs.usermount=1) once Workspace's image mounts go through DiskArbitration. kernel#62 already says to do this “when that lands”. |
Relationship to E14. The swap plan's swapd is the dynamic_pager shape and is already the right activation path under no-fstab. One E14 acceptance line, “an fstab entry for /private/var/vm/swapfile0 activates via swapon -a”, should become swapon /private/var/vm/swapfile0. E14's premise “launchd never runs mount -a (#171)” is half right: mount -a does run, but swapon -a and dumpon don't.
| Where | Says | Actually |
|---|---|---|
| overlays fstab header; userland#54 option F; #171 title; #460/#461; kernel#60/#61/#65; E14 | “nothing runs mount -a” | launchctl.c:2400-2405 runs mount -vat nonfs whenever fstab exists |
| kernel#62, kernel#68, nextbsd#231 | “/etc/sysctl.conf is never read” | launchctl.c:2326 applies it at bootstrap. Patches 0008 and 0009 may not have needed to be kernel patches (untested on a running box). |
| userland#54 option B; nextbsd#278 “Lever D” | WatchPaths is “verified present” | Inert: the keys are rewritten to fsevents LaunchEvents with no deliverer (launchctl.c:1610-1648, core.c:322-333) |
| #171 suggested verification | “tmpfs on /tmp/scratch in fstab” | force-unmounted by empty_dir(/tmp) one step later |
| #460 fstab block | lindebugfs … rw,late | late is never mounted by mount -vat |
| DiskArbitration plan (2026-05) | hwregd, /usr/libexec, com.apple.DiskArbitration | hwregd is retired, the binary is /usr/sbin, Apple's service name is …diskarbitrationd, and the tree installs flat libraries, not .framework bundles |
| compat audit | diskarbitrationd “supersedes devd/autofs glue” | not yet: it only logs storage devices |
org.nextbsd.linux? And should the native /proc=linprocfs set ever be on by default, given it is a system-wide change?noexec on untrusted media? Apple doesn't set it. It blocks running AppImages straight off a stick, which Gershwin users may expect.VQ_MOUNT reach userland on NextBSD? It is untested. FreeBSD signals VQ_MOUNT and VQ_UNMOUNT only; mount -u signals nothing. C3 carries a test program./etc/sysctl.conf really applies, that the automount binaries ship, and that a fstab-less image boots clean. The last is covered by CI once A1 lands.There were two fact-gathering agents (site conventions; tickets and code state) and five Fable research agents: the Darwin boot mount sequence, the DiskArbitration source, the Linux-compat mount design, the installed-system fstab audit, and USB automount with Gershwin. Where agents disagreed, the page says so. The one real disagreement was A versus B for fstab: the Darwin agent pointed out that Apple ships no file, and the audit agent pointed out FreeBSD's no-file stderr and halt edge case. The DiskArbitration agent proposed devd as the event source; that was corrected here because NextBSD removed devd. Claims marked unverified were not run on hardware.
Evidence: nextbsd@37a3b6e, nextbsd-userland@f035d62, nextbsd-overlays@c0d0d1f, nextbsd-kernel main, FreeBSD releng/15.0; apple-oss-distributions DiskArbitration-535.120.1.0.1 & -268, launchd-106/-258.1/-329.3.3/-392.39/-442.26.2/-842.92.1, Startup-60/-177.8, files-363 through -662.1.1, xnu-201/-12377.121.6, diskdev_cmds-143/-757, Libinfo-78/-600, autofs-322; apple/containerization, apple/container; vermaden/automount 1.8.0; dsbmd 1.12; bsdisks 0.41; gnustep/libs-gui f285e90; gershwin-workspace 817491d; CI run 35544120227. Related: nextbsd#467, userland#171, userland#54, #460, #461, gershwin-desktop#49, #60, swap plan (E14).