SMF Migration — Handoff to Hammerhead
This document hands off the remaining SMF-removal work from the zyginit project to
the Hammerhead team. It covers source vendoring, build integration, the decision
process for converting each SMF manifest to a zyginit TOML service definition,
worked examples, anti-patterns drawn from the iter 1-20 development history,
per-category guidance, and a coarse catalog of all 128 manifests found on
hh-prototest as of 2026-05-02.
See also: docs/DESIGN.md for the zyginit architecture reference;
docs/ROADMAP.md for the forward-looking task checklist.
1. Handoff Brief
This section orients the Hammerhead team on what zyginit has done, what is left,
and where to ask questions.
What zyginit has done (through rev 82)
zyginit is a working replacement for svc.startd, svc.configd, and the SMF
master restarter — a single Reef process that acts as PID 1, supervises services
defined in TOML files, and exposes an administrative socket for zygctl.
As of rev 82 (2026-05-02), zyginit boots Hammerhead to a fully-functional
multi-user state on hh-prototest (192.168.122.50) without any SMF
infrastructure running:
- Multi-user boot — all tier-0 through tier-7 services start cleanly.
- Single-user mode — boot arg
-sor runtimezygctl singledrops to
/sbin/shon/dev/console. - Runtime runlevel transitions —
zygctl single/zygctl multi(and the
init s/init 3sysv wrappers) work bidirectionally. - Clean shutdown —
zygctl halt/reboot/poweroffperform a
reverse-tier stop, ZFS sync,umountall -l, anduadminfrom a forked
non-PID-1 child. - utmpx integration —
who -b,who -r, anduptimereport correctly. - ~18 core services converted — the methodology is established for the
full Hammerhead service set. The production TOMLs now live in Hammerhead's
overlay tree atbase/usr/src/zyginit/overrides/(absorbed during Phase D).
See the worked examples in Section 3 and the catalog in Section 7 for
the conversion patterns.
What the Hammerhead team must do
- Vendor zyginit source into
hammerhead-userland(see Section 5 for the
file-by-file layout and build instructions). - Wire the build to produce
/sbin/init(zyginit),/sbin/zygctl, and
/sbin/sysv-wrapperwith its symlinks. - Source the production TOMLs from Hammerhead's overlay tree at
base/usr/src/zyginit/overrides/(already absorbed during Phase D);
install them to/etc/zyginit/and symlink inenabled.d/. - Validate that the vendored source builds and boots identically to
hh-prototestbefore starting new conversions. - Convert the remaining ~110 SMF manifests using the decision tree in
Section 2, the worked examples in Section 3, the per-category guidance in
Section 6, and the catalog in Section 7. - Remove SMF infrastructure —
svc.startd,svc.configd, master restarter
binaries, manifest infrastructure, andlibscf-only consumers — from
hammerhead-userlandpackaging.
Done criteria for "SMF removal complete"
- Hammerhead boots to multi-user without
svc.startdorsvc.configdever
being invoked (verify withpgrep -fl svc.startd; expect zero results). libscfis not linked into any binary in the default boot path (acceptable to
keeplibscfinstalled for optional/zports consumers, but no required boot
service calls into it).- All zyginit-managed services continue to work at least as well as the
SMF-managed equivalents they replaced. - Manifest XML files and
svc:/repository infrastructure are removed from
default packaging (they may be retained in asmf-compatoptional package
for administrators who need to run SMF tooling temporarily). halt,reboot,poweroff, andinit <N>reach the hardware-level
operation cleanly.
Coordination
- Questions about existing zyginit behavior — open an issue against the
zyginit repo. Include the service name, the symptom, and the hh-prototest log
output. - TOML fields that don't fit a service's needs — file an RFE against zyginit.
Do not work around missing features in the service scripts; get the runtime
feature first. - Hammerhead team's scope — modifying
hammerhead-userlandis the
Hammerhead team's job. The zyginit CLAUDE.md constraint "DO NOT modify
Hammerhead source code" applies to the zyginit-project Claude, not to the
Hammerhead Claude. The Hammerhead Claude should freely modify its own tree.
See also: Section 5 (Integration with Hammerhead), docs/ROADMAP.md
"SMF Removal from Hammerhead."
2. Decision Tree
This section is the core reference for every manifest conversion. Walk each
manifest through the three steps in order.
Step 1 — Should this service exist on Hammerhead at all?
Does Hammerhead ship this functionality?
|
+-- No: deprecated, SPARC-only, SMF infrastructure, or NIS/iSCSI/etc.
| --> DROP. Remove from packaging; do not write a TOML.
| The catalog (Section 7) lists the obvious drops.
|
+-- Possibly, but as an optional zports add-on (Kerberos KDC, iSNS, etc.)
| --> DEFER. Out of scope for hammerhead-userland; leave for zports.
|
+-- Yes, ships in hammerhead-userland
--> Continue to Step 2.
Mandatory: do not skip Step 1. Converting a service "because it exists" is
the single biggest source of wasted effort. The 128 manifests include services
Hammerhead does not and should never ship (SMF infrastructure, SPARC platform
code, NIS, iSCSI target, Trusted Extensions label daemon, etc.). These are
straightforward drops.
Step 2 — Is the service coupled to SMF infrastructure at runtime?
Does the daemon call into svc.configd / libscf / the SMF repository door
at runtime (not just at startup)?
|
+-- Yes, fundamentally requires libscf or the repository for ongoing
| operation (e.g., svc.startd, svc.configd themselves)
| --> DROP (if it IS SMF) or INVESTIGATE (if it merely uses libscf).
| For investigate: look for a foreground/standalone mode flag.
| Coordinate with the daemon's upstream if none exists.
|
+-- Yes at startup, but the daemon has a non-SMF mode flag
| (-d, -f, -D, or similar) that skips the startup gate and the
| daemonize double-fork
| --> CONVERT using the foreground-mode pattern. See Example 1.
| Known flags on Hammerhead daemons:
| dlmgmtd -d (debug/foreground; bypasses SMF_FMRI gate)
| ipmgmtd -f (identical pattern)
| sshd -D (standard OpenSSH; no daemonize)
| syslogd -d (foreground; standard illumos)
| fmd -f (foreground; from fmd source)
| Check each daemon's man page and source before assuming
| SMF coupling is unavoidable.
|
+-- No SMF coupling, or coupling is purely cosmetic (e.g., SMF_FMRI
env var used only for a cache-file name)
--> Continue to Step 3.
Getting Step 2 wrong was the entire iter 1-5 dead end. When dlmgmtd was
started without its foreground flag, it failed silently — no error on stderr
(daemonize had already closed fd 2), and the network never came up. See
memory/pid1_boot_iter11_15.md for the full diagnosis.
Step 3 — What runs the service today?
What does the SMF exec_method actually invoke?
|
+-- Direct daemon binary (no method script)
| --> CONVERT with a simple TOML. exec.start = the binary + args.
| Most daemons with exec=':kill' for stop use the contract
| signal by default — omit [stop] unless you need custom signal.
|
+-- /lib/svc/method/<name> shell script
| |
| +-- Script is trivial (rm a FIFO, mkdir, then exec the daemon)
| | --> INLINE the setup into a wrapper start.sh. See Example 2.
| | Services that take this path: cron (rm FIFO + exec),
| | syslogd (touch /var/adm/messages + exec), console-login
| | (write utmpx entry + exec ttymon).
| |
| +-- Script sources /lib/svc/share/smf_include.sh AND calls
| | smf_present() or smf_clear_method_context()
| | --> Check if smf_present() branch is the failure path only.
| | If so, the script works fine without configd (smf_present
| | returns false; the relevant branch is skipped). Test
| | carefully. Many scripts are safe even with smf_include.sh.
| |
| +-- Script does substantial, maintained setup work
| --> KEEP the method script as exec.start. Add SMF_FMRI to
| [exec] environment if the script requires it for
| non-configd purposes (e.g., FIFO name, log prefix).
| See Example 2 alternate form.
|
+-- Oneshot configuration command (mountall, swapadd, dumpadm, coreadm)
| --> CONVERT as type = "oneshot". See the worked examples in
| Section 3 and the Hammerhead overrides for root-fs, swap,
| filesystem patterns.
| Onshots use restart.on = "never".
|
+-- inetd-managed service (not a standalone daemon)
--> DROP unless there is a strong reason to keep inetd.
Hammerhead does not run inetd. If the underlying
functionality is needed (e.g., legacy RPC), the service
needs its own TOML as a standalone daemon.
Field-by-field translation table
| SMF manifest element | TOML field | Notes |
|---|---|---|
<service name='X'> |
[service] name |
Strip the category prefix (e.g., network/ssh → "sshd") |
<template><common_name> |
[service] description |
Plain string; omit XML whitespace |
| SMF behavior class | [service] type |
Map: continuous daemon → "daemon"; fire-and-forget → "oneshot"; transient SMF → "transient" |
<exec_method name='start' exec='...'> |
[exec] start |
Replace with binary + foreground flag if Step 2 says foreground-mode; or use method script path if Step 3 says keep |
<exec_method name='stop' exec=':kill'> |
(omit — default) | :kill in SMF = send contract signal; zyginit does this by default via [stop] method = "contract" |
<exec_method name='stop' exec='some-cmd'> |
[stop] method = "exec" + [exec] stop = "some-cmd" |
For custom stop scripts |
<dependency type='service' ...><service_fmri value='svc:/X'> |
[dependencies] requires = ["X"] |
Translate FMRI basename; drop all SMF-internal dependencies (milestone/, system/svc/, restarter) |
<dependency type='path' ...> |
[dependencies] requires = ["filesystem"] |
Path deps mean "filesystem is up"; map to the filesystem service |
<property_group name='startd'><propval name='duration' value='transient'> |
[service] type = "oneshot" |
SMF transient duration = zyginit oneshot |
<property_group name='general'><propval name='enabled'> |
(not in TOML) | Enabled state is set by the operator via symlink in /etc/zyginit/enabled.d/ |
| Restart policy | [restart] on = "always|failure|never" |
SMF ignore_error → on = "failure"; SMF restart contract → on = "always" |
<property_group name='startd'><propval name='ignore_error' value='core,signal'> |
[restart] on = "failure" |
Core + signal ignores = only restart on clean failure |
<method_context><method_credential user='X' group='Y'> |
[exec] user = "X" and [exec] group = "Y" |
Drop privileges before exec |
<method_context working_directory='/'> |
[exec] working_directory = "/" |
Inherited if omitted; specify if non-root |
| Contract params | [contract] param = [...] |
Defaults (["inherit", "noorphan"]) are correct for most services |
See also: docs/man/man5/zyginit.5 for the authoritative field-by-field
TOML format reference; this table covers patterns and translation, not syntax.
3. Worked Examples
This section walks three representative manifests through the full
conversion process.
Example 1 — Foreground-mode conversion: dlmgmtd
Manifest: /lib/svc/manifest/network/dlmgmt.xml
Result: base/usr/src/zyginit/overrides/dlmgmtd/service.toml (Hammerhead overlay tree)
Pattern: foreground-mode (Decision Tree Step 2, middle branch)
Original manifest (key lines)
<service name='network/datalink-management' type='service' version='1'>
<dependent name='dlmgmt-device-system' grouping='require_all'
restart_on='none'>
<service_fmri value='svc:/system/device/local' />
</dependent>
<exec_method type='method' name='start'
exec='/lib/svc/method/svc-dlmgmtd' timeout_seconds='60' />
<exec_method type='method' name='stop' exec=':kill' timeout_seconds='3' />
/lib/svc/method/svc-dlmgmtd checks for SMF_FMRI and calls dlmgmtd
with no additional flags — dlmgmtd daemonizes on its own.
Decision-tree walk
- Step 1: Yes, Hammerhead ships dlmgmtd. It is required for
ifconfig plumb
anddladmto work at all on illumos; libdladm resolves link names through
dlmgmtd's door. - Step 2: Yes, dlmgmtd checks
getenv("SMF_FMRI")at startup to derive a
cache-file name, then callsdaemonize(). Without the foreground flag, both
checks happen even when started outside SMF. Butdlmgmtd -dskips both:
the debug-mode branch indlmgmt_main.cbypasses theSMF_FMRIcheck and
thedlmgmt_daemonize()call entirely. The door is still created at the same
path. This is the foreground-mode pattern — use-d. - Step 3: not reached (Step 2 resolved it).
Resulting TOML
The production TOML in the Hammerhead overlay tree captures these decisions.
Its comment block reads as follows (inlined here for reference):
# dlmgmtd — Datalink management daemon
#
# Runs in `-d` (debug) mode, which on dlmgmtd means "single foreground
# process, no double-fork daemonize." Three reasons we use it:
# 1. Skips the SMF_FMRI startup gate (debug mode bypasses the check).
# 2. Keeps stderr connected to our log; without it dlmgmtd's daemonize
# runs fdwalk(closefunc), closing fd 2 — any startup error then
# goes to syslog, which isn't running yet at this tier.
# 3. zyginit's contract tracks a single PID instead of dealing with
# the parent-exits-0-after-handshake daemonize pattern.
# Cosmetic effect: the cache file is named "dlmgmtd.debug.cache" instead
# of "network-datalink-management:default.cache". Nothing external reads
# this file — only dlmgmtd itself, for fast restart state recovery.
[service]
name = "dlmgmtd"
description = "Datalink management daemon (foreground)"
type = "daemon"
[exec]
start = "/sbin/dlmgmtd -d"
[dependencies]
requires = ["filesystem"]
[restart]
on = "failure"
delay = 5
max_retries = 3
[contract]
param = ["inherit", "noorphan"]
fatal = ["hwerr"]
Key field mapping decisions
name— FMRI basenamenetwork/datalink-managementcollapsed todlmgmtd.exec.start— direct binary + flag; method script path dropped entirely.dependencies.requires = ["filesystem"]— the SMF<dependent>blocks on
network/physicalare dropped (SMF-internal ordering, not real deps).stop— omitted; SMF's:kill= zyginit's default contract signal.contract.fatal = ["hwerr"]not["hwerr", "empty"]— the daemonize
handshake transiently empties the contract; zyginit handles that correctly.
Verify after boot: pgrep -fl dlmgmtd shows dlmgmtd -d; ls /etc/svc/volatile/dladm/dlmgmt_door shows the door; dladm show-phys returns the NIC list.
See also: memory/pid1_boot_iter11_15.md for the diagnostic history;
base/usr/src/zyginit/overrides/ipmgmtd/service.toml (Hammerhead overlay) for
the identical pattern applied to ipmgmtd.
Example 2 — Method-script wrap: cron
Manifest: /lib/svc/manifest/system/cron.xml
Result: base/usr/src/zyginit/overrides/cron/service.toml + start.sh (Hammerhead overlay tree)
Pattern: trivial method-script inlined (Decision Tree Step 3, inline branch)
Original manifest (key lines)
<service name='system/cron' type='service' version='1'>
<dependency name='usr' type='service' grouping='require_all' restart_on='none'>
<service_fmri value='svc:/system/filesystem/local' />
</dependency>
<dependency name='ns' type='service' grouping='require_all' restart_on='none'>
<service_fmri value='svc:/milestone/name-services' />
</dependency>
<exec_method type='method' name='start' exec='/lib/svc/method/svc-cron'
timeout_seconds='60'>
<method_context><method_credential user='root' group='root' /></method_context>
</exec_method>
<exec_method type='method' name='stop' exec=':kill' timeout_seconds='60' />
/lib/svc/method/svc-cron sources smf_include.sh (for $SMF_EXIT_*
constants and smf_zonename — no configd call), removes /etc/cron.d/FIFO if
stale, and runs /usr/sbin/cron &.
Decision-tree walk
- Step 1: Yes, Hammerhead ships cron. Required for log rotation and
scheduled tasks. - Step 2: No SMF coupling.
svc-cronsourcessmf_include.shonly for
$SMF_EXIT_*constants andsmf_zonename(which calls/sbin/zonename— no
configd). The exit codes are not observed by zyginit's contract model anyway.
No configd calls anywhere. - Step 3: Method script. Assessment: trivial. The script does two things
before starting cron: check for a stale FIFO and remove it. Thepgrepguard
is irrelevant under zyginit (supervisor doesn't double-start). Thecron &
backgrounding is replaced byexec /usr/sbin/cronin the wrapper.
Two valid TOML forms
Form A — Inline the setup in a wrapper start.sh (production choice):
[service]
name = "cron"
description = "cron daemon"
type = "daemon"
[exec]
start = "/etc/zyginit/cron/start.sh"
[dependencies]
requires = ["syslogd"]
[restart]
on = "failure"
delay = 5
max_retries = 3
[contract]
param = ["inherit", "noorphan"]
fatal = ["hwerr"]
With start.sh (lives alongside service.toml in the Hammerhead overlay):
#!/bin/zsh
# Clean up stale FIFO before starting cron.
# /usr/sbin/cron creates /etc/cron.d/FIFO at startup and refuses to
# start if the file already exists — mirrors svc-cron's behavior.
set -e
/bin/rm -f /etc/cron.d/FIFO
exec /usr/sbin/cron
Form B — Use method script directly (transitional):
[exec]
start = "/lib/svc/method/svc-cron"
environment = ["SMF_FMRI=svc:/system/cron:default"]
Choose Form A when the setup is short and you want to decouple from SMF method
script files (the preferred end state — /lib/svc/method/svc-cron will be
removed). Choose Form B as a transitional step when the method script does
substantial correct setup and does not call smf_present() in any required
code path.
Key field mapping decisions
dependencies.requires = ["syslogd"]— SMF's milestone deps (filesystem/local,
name-services) are replaced with direct deps on zyginit services. Drop all
milestone FMRI references; they don't exist in zyginit.type = "daemon"— continuous daemon; SMF's<single_instance/>is implicit.stopomitted;working_directoryanduser/group = rootomitted (defaults).
See also: base/usr/src/zyginit/overrides/syslogd/ (Hammerhead overlay) for
the same pattern (touch log file + exec daemon);
base/usr/src/zyginit/overrides/console-login/ for a more involved wrapper
(write utmpx entry + exec ttymon).
Example 3 — Drop: svc.startd / system/svc/restarter
Manifest: /lib/svc/manifest/system/svc/restarter.xml
Result: DROP — no TOML.
Pattern: Decision Tree Step 1, no branch.
Original manifest (key lines)
<service name='system/svc/restarter' type='restarter' version='1'>
<create_default_instance enabled='true' />
<exec_method type='method' name='start' exec=':true' timeout_seconds='0' />
<exec_method type='method' name='stop' exec=':true' timeout_seconds='0' />
FMRI: svc:/system/svc/restarter:default. The exec methods are :true because
the kernel never invokes them — init starts svc.startd directly, and this
manifest exists only so svc.startd can store its own properties in the
SMF repository.
Decision-tree walk
- Step 1: No. This manifest IS SMF. zyginit replaces the functionality of
svc.startd,svc.configd, and the master restarter framework entirely.
There is nothing to convert. DROP.
The cascade
Every other SMF manifest on the system has at least one <dependency> block
referencing SMF-internal FMRIs. When you convert those services, drop all such
references. They are not real ordering constraints between daemons — they are
SMF's internal "this-service-needs-the-SMF-infrastructure" boilerplate.
Common SMF-internal FMRIs to drop from requires when converting:
svc:/system/svc/restarter:default (the restarter framework itself)
svc:/milestone/single-user:default (SMF single-user milestone)
svc:/milestone/multi-user:default (SMF multi-user milestone)
svc:/milestone/name-services:default (SMF name-services milestone)
svc:/milestone/network:default (SMF network milestone)
svc:/milestone/sysconfig:default (SMF sysconfig milestone)
svc:/system/manifest-import:default (SMF manifest import oneshot)
svc:/system/early-manifest-import:default
Replace the real ordering constraints (filesystem, syslogd, dlmgmtd, etc.)
with bare service names pointing at the corresponding zyginit-managed services.
Companion drops
The following manifests are all SMF infrastructure and must be dropped along
with the restarter:
| Manifest | FMRI | Reason |
|---|---|---|
system/svc/restarter.xml |
svc:/system/svc/restarter:default |
Is svc.startd |
system/svc/global.xml |
svc:/system/svc/global:default |
SMF global property store |
system/early-manifest-import.xml |
svc:/system/early-manifest-import:default |
SMF import at boot |
system/manifest-import.xml |
svc:/system/manifest-import:default |
SMF import daemon |
The SMF binaries to remove from hammerhead-userland packaging:
/lib/svc/bin/svc.startd, /lib/svc/bin/svc.configd,
/usr/sbin/svcadm, /usr/sbin/svccfg, /usr/sbin/svcs,
/usr/sbin/svcprop. The /lib/svc/share/smf_include.sh helper library
can remain if any method scripts continue to be used during the transition
(Form B of method-wrap); remove it when all method scripts are replaced.
See also: Section 6 "Per-Category Guidance" for the full system/svc/
category drop rule.
4. Anti-patterns and Gotchas
This section documents known failure modes from the iter 1-20 development
history. Each entry gives the symptom, root cause, and fix.
1. configd-coupled daemons degrade silently
Symptom: Service starts (fork succeeds, contract created), but functionality
is absent — dladm show-phys returns empty, ifconfig plumb returns
"no such interface."
Cause: Daemon checks getenv("SMF_FMRI") or calls into libscf at startup.
Without svc.configd running, the check fails or the call blocks/returns
error, and the daemon silently skips its initialization. No log output because
the daemon's daemonize() call has already closed stderr (fd 2) before the
error is reached.
Fix: Use the daemon's foreground/debug flag (see Decision Tree Step 2).
In foreground mode the SMF_FMRI check is bypassed AND stderr stays connected
to zyginit's log, so startup errors are visible. Never start a configd-coupled
daemon without its foreground flag.
Reference: memory/pid1_boot_iter11_15.md (dlmgmtd and ipmgmtd diagnosis).
2. Foreground-flag names vary by daemon
Symptom: You know a foreground mode exists but can't find the right flag.
Cause: There is no standard flag name. Each daemon chose its own.
Fix: Check the daemon's man page, its main() usage string, and
(for open-source daemons) its source. Known Hammerhead flags:
| Daemon | Flag | Effect |
|---|---|---|
dlmgmtd |
-d |
foreground, no daemonize, bypass SMF_FMRI gate |
ipmgmtd |
-f |
identical pattern |
sshd |
-D |
foreground, no daemonize (standard OpenSSH) |
syslogd |
-d |
foreground (standard illumos) |
fmd |
-f |
foreground (Fault Manager Daemon) |
inetd |
n/a | SMF_FMRI env var required instead |
For daemons where no foreground flag exists, consider Form B method-wrap
(keep the SMF method script) as a transitional option.
3. soconfig must run before any network sockets
Symptom: socket(AF_INET, ...) returns EAFNOSUPPORT even though the
network interface is up.
Cause: illumos sockfs's protocol map is not populated until soconfig -d /etc/sock2path.d runs. SMF's system/device/local did this; without it AF_INET is unknown to the kernel.
Fix: The Hammerhead overlay devfs/start.sh runs soconfig in the devfs tier.
All services that need networking depend (directly or transitively) on devfs.
Reference: memory/pid1_boot_iter11_15.md, iter 11.
4. Daemonize handshake: supervisor sees "stopped (exit 0)"
Symptom: zygctl status shows a daemon as STOPPED right after start even though it is running.
Cause: Double-fork daemonize — the wrapper parent exits 0 while the daemon child is alive in the contract.
Fix: zyginit (rev 78+) detects the handshake: type = "daemon" + parent exits 0 + contract still has processes → clear rt.pid but keep the contract. Ensure TOML says type = "daemon", not "oneshot".
Reference: memory/pid1_boot_iter16.md.
5. /var/run is not tmpfs in the current zyginit BE
Symptom: Stale socket, PID, or lock files survive reboots.
Cause: Standard illumos mounts /var/run as tmpfs via fs-minimal. zyginit's filesystem/start.sh does not yet do this.
Fix (short-term): Add rm -f /var/run/<svc>.pid in affected start.sh wrappers. Long-term: add mount -F tmpfs swap /var/run to filesystem/start.sh. socket.reef already handles stale socket recovery via unlink-before-bind.
6. utmpx record positioning for who(1) -r
Symptom: who -r reports the wrong runlevel after a zygctl single / zygctl multi transition.
Cause: pututxline(3C) appends a new RUN_LVL record unless getutxid positions the cursor on an existing one first. who -r reads only the first matching record.
Fix: Call getutxid before pututxline. The zyginit_write_runlvl_utmpx helper in src/helpers.c does this correctly; use it.
Reference: memory/pid1_boot_iter18.md.
7. Do not set ZFS readonly=on during shutdown
Symptom: After zygctl reboot, the next boot sees pre-shutdown state — stale socket, daemons appear wrong.
Cause: zfs set readonly=on on the live root mid-shutdown makes all subsequent writes (including socket unlink and log writes) silently fail. ZFS records the pre-readonly txg; next boot sees it.
Fix: Remove readonly=on from any stop script. ZFS is transactionally consistent; zpool sync + umountall -l + kernel's vfs_syncall (in mdboot) is sufficient. root-fs/stop.sh was corrected in rev 82.
Reference: memory/pid1_shutdown_fix.md, bug #2.
8. uadmin must not be called from PID 1
Symptom: zygctl reboot completes the shutdown log but does not reset the hardware. The kernel re-execs /sbin/init; uptime does not reset; orphaned daemons collide with the new instance.
Cause: uadmin called from PID 1 hits the restart_init path — the kernel re-execs init before mdboot() fires the hardware reset.
Fix: Fork a child; call uadmin from the child (non-PID-1). Parent enters infinite sleep. This mirrors cmd/svc/startd/graph.c:do_uadmin. See src/main.reef shutdown sequence.
Reference: memory/pid1_shutdown_fix.md, bug #1.
9. /etc/hosts: localhost only, no hostname entry
Symptom: SSH login takes ~20 seconds even with the network up.
Cause: The bare Hammerhead BE ships /etc/hosts with only localhost. sshd does a reverse DNS lookup on the client address; without a local entry or working resolver, it times out.
Fix (operator): Add the system's IP and hostname to /etc/hosts.
Fix (upstream): File as a Hammerhead base-system bug; the install or identity service should populate /etc/hosts. Not a zyginit issue.
5. Integration with Hammerhead
This section specifies how to vendor zyginit into hammerhead-userland and
wire it into the Hammerhead build.
5.1 Source layout
Recommended target layout in the Hammerhead source tree (BSD/illumos convention
for cmd/ userland utilities):
usr/src/cmd/init/
src/ <- zyginit Reef source files
src/helpers.c <- required C helper (non-optional)
services/ <- service TOML definitions and start/stop scripts
reef.toml <- reefc project config
usr/src/cmd/zygctl/
src/ <- zygctl Reef source files
src/symlink_wrapper.c <- required C helper for zygctl
usr/src/cmd/sysv-wrapper/
wrapper.c
Makefile
<- builds /sbin/sysv-wrapper; Makefile install creates symlinks
usr/src/man/man5/
zyginit.5
usr/src/man/man8/
zyginit.8
zygctl.8
The sync mechanism (git submodule, source snapshot, or fetch-and-extract)
is the Hammerhead team's call. A simple approach: tag zyginit releases in its
repo, fetch a source archive at a known tag, unpack under usr/src/cmd/init/.
5.2 File-by-file source mapping
| zyginit repo path | Hammerhead target | Notes |
|---|---|---|
src/*.reef |
usr/src/cmd/init/src/ |
All Reef source files |
src/helpers.c |
usr/src/cmd/init/src/ |
Required for link |
src/contract_linux_stubs.c |
DROP | Linux-only stubs; not for Hammerhead |
Hammerhead overlay tree (base/usr/src/zyginit/overrides/) |
usr/src/cmd/init/services/ |
Production service definitions (already in-tree; deploy from Hammerhead side) |
reef.toml |
usr/src/cmd/init/reef.toml |
reefc project config |
tools/zygctl/src/ |
usr/src/cmd/zygctl/src/ |
zygctl Reef source |
tools/zygctl/src/symlink_wrapper.c |
usr/src/cmd/zygctl/src/ |
Required for zygctl link |
tools/zygctl/reef.toml |
usr/src/cmd/zygctl/reef.toml |
zygctl reefc config |
tools/sysv-wrapper/wrapper.c |
usr/src/cmd/sysv-wrapper/ |
sysv-init compat wrapper |
tools/sysv-wrapper/Makefile |
usr/src/cmd/sysv-wrapper/ |
Builds + installs symlinks |
docs/man/man5/zyginit.5 |
usr/src/man/man5/ |
|
docs/man/man8/zyginit.8 |
usr/src/man/man8/ |
|
docs/man/man8/zygctl.8 |
usr/src/man/man8/ |
5.3 Build invocation
The Hammerhead master build must invoke these steps for usr/src/cmd/init/:
# Build helpers.o
gcc -c src/helpers.c -o build/helpers.o
# Build zyginit daemon (produces build/zyginit)
reefc build -l contract --obj build/helpers.o
# Install
cp build/zyginit /sbin/init
For usr/src/cmd/zygctl/:
gcc -c src/symlink_wrapper.c -o build/symlink_wrapper.o
reefc build --obj build/symlink_wrapper.o
cp build/zygctl /sbin/zygctl
For usr/src/cmd/sysv-wrapper/:
make
make install
# Creates /sbin/sysv-wrapper and symlinks:
# /sbin/halt -> /sbin/sysv-wrapper
# /sbin/reboot -> /sbin/sysv-wrapper
# /sbin/poweroff -> /sbin/sysv-wrapper
# /sbin/telinit -> /sbin/sysv-wrapper
Service files must be installed to /etc/zyginit/. Source them from the
Hammerhead overlay tree (base/usr/src/zyginit/overrides/):
# Install per-service directory (contains service.toml + start.sh / stop.sh)
cp -r overrides/<svc>/ /etc/zyginit/services/<svc>/
# Enable services by symlinking into enabled.d/
ln -s /etc/zyginit/services/<svc> /etc/zyginit/enabled.d/<svc>
The enabled.d/ naming convention uses the service name as the symlink name.
Tier ordering is derived from [dependencies] in the TOML; see the
base/usr/src/zyginit/overrides/ tree for the current tier assignments.
5.4 Reef compiler dependency
Hammerhead's build requires reefc. Options:
- Bootstrap from Reef repo — clone
~/repos/reef-lang/(or the Reef
upstream repo) and buildreefcas part of the Hammerhead build setup.
Required version: Reef 0.4.0+. - Pre-built reefc — package a pre-built
reefcbinary for the Hammerhead
build host (thehammerhead-buildVM at 192.168.122.66 already has
a workingreefc). Simpler short-term; breaks if the build host is
reprovisioned.
clang is not available on Hammerhead (standard Hammerhead build host uses
gcc); use gcc for helpers.c and symlink_wrapper.c.
5.5 First migration step (concrete deliverable)
Before starting any new manifest conversions, complete this validation
sequence:
- Vendor zyginit source at a known rev into
usr/src/cmd/init/and
usr/src/cmd/zygctl/andusr/src/cmd/sysv-wrapper/. - Wire the build to produce
/sbin/init,/sbin/zygctl, and
/sbin/sysv-wrapper. - Deploy the production TOMLs from Hammerhead's overlay tree
(base/usr/src/zyginit/overrides/) into/etc/zyginit/and
symlink them inenabled.d/. - Build a Hammerhead BE with the new binaries and service definitions.
- Boot hh-prototest from the new BE; verify all 18 services reach
RUNNINGinzygctl status; verify SSH is reachable; verify console
login works. - Only then begin the per-manifest conversion work using the decision
tree and catalog.
Starting new conversions before step 5 is validated means any new issue
could be caused by the vendoring/build change rather than the conversion.
5.6 SMF removal step
Removing SMF infrastructure is a separate Hammerhead task after all needed
services have been converted. The sequence:
- Remove
svc.startdandsvc.configdbinaries from the build and packaging. - Remove SMF manifest XML files from
/lib/svc/manifest/packaging. - Remove
libscflinkage from any binary that links it but can be updated
(check withldd -r /sbin/initand any other boot-path binary). - Remove
svcadm,svccfg,svcs,svcpropfrom the default packaging
(optionally retain in asmf-compatpackage for administrators). - Verify boot still works end-to-end.
5.7 Upstream sync workflow
When zyginit ships new features (new TOML fields, runtime improvements):
- Fetch the zyginit repo at a new tag or commit hash.
- Refresh the vendored source under
usr/src/cmd/init/. - Resolve any local Hammerhead patches that conflict.
- Rebuild and test on
hh-prototest. - Record the sync point (commit hash / rev number) in Hammerhead's
changelog entry.
See also: Section 2 (Decision Tree), docs/man/man5/zyginit.5.
6. Per-Category Guidance
This section gives top-down guidance for each SMF manifest tree category.
Read once for orientation, then drop into the catalog appendix (Section 7)
for per-manifest decisions.
milestone/
Default: DROP all. The six milestone manifests (single-user, multi-user,
multi-user-server, network, name-services, sysconfig) are SMF's
internal synchronization fences. zyginit replaces them with tier-ordered
service startup. When converting other manifests, drop all <dependency>
references to milestone FMRIs; replace with direct deps on the zyginit-managed
services that actually matter for ordering.
platform/
Default: keep amd64; drop all others. There is only one platform manifest
on hh-prototest: platform/amd64/acpihpd.xml (ACPI hotplug daemon).
Hammerhead is amd64-only; no sun4u/sun4v entries exist on this system.
acpihpd is an amd64-platform-specific daemon for hotplug events —
investigate whether Hammerhead ships the hardware that needs it;
needs-investigation until confirmed.
network/
Selective. Core networking (dlmgmtd, ipmgmtd — already converted, sshd)
are kept. The decision landscape:
- Already converted: dlmgmtd, ipmgmtd, sshd.
- Consolidated into
network.toml: loopback, physical, initial, netmask,
service, routing-setup — all collapsed into the singlenetworkoneshot. - Needs investigation: NFS (does Hammerhead ship NFS client? server?),
DNS resolver (likely needed; investigate whether to use a standalone
resolv.confor runnscd), ipfilter (does Hammerhead use it?),
IPsec (policy and algs may be needed). - Drop: NIS (
/network/nis/— deprecated everywhere), iSCSI target/initiator
(storage-specific; defer to zports), iSNS server, SMB client/server (defer),
Kerberos KDC components (server-role only; defer to zports), LDAP client
(environment-specific), loadbalancer (ilbd), Trusted Networking (tnctl/tnd
— Trusted Extensions, which Hammerhead does not ship). - Drop inetd: Hammerhead does not run inetd. The
inetd.xmland
inetd-upgrade.xmlmanifests are dropped. If any inetd-managed service is
needed, write a standalone TOML for it.
system/
The largest category; mixed disposition:
- Already converted: cron, cryptosvc (as
crypto), devfs (devices-local),
filesystem (local-fs + minimal-fs + root-fs), fmd, identity, pfexecd,
syseventd, system-log (assyslogd), utmp (asutmpd), zones is pending. - Keep and convert: coreadm, dumpadm, hotplug (if hardware warrants it),
intrd (interrupt balancer daemon), keymap, power (powerd), rbac (config
oneshot), scheduler, vtdaemon (VT multiplexer). - Needs investigation: auditd (does Hammerhead ship BSM auditing?), idmap
(identity mapping — needed if SMB/NFS Kerberos are used), name-service-cache
(nscd), pools (resource pools — does Hammerhead use them?), rcap (resource
capping), zonestat (zone statistics — relevant once zones are enabled). - Drop: All of
system/svc/(SMF infrastructure itself),manifest-import,
early-manifest-import,logadm-upgrade(upgrade artifact),boot-archive
andboot-archive-update(SMF-managed tasks; zyginit doesn't use
boot-archive service),update-man-index(defer),extended-accounting
(rarely used),fcoe_initiator/fcoe_target(storage-specific), IBSRP
target (InfiniBand SRP — hardware-specific),i2csimd(platform-specific
sensor daemon from a test tree),labeld(Trusted Extensions label daemon —
Hammerhead does not ship TX),tsol-zones(Trusted Extensions zones),ndmp
(backup protocol — defer to zports),stmf(SCSI Target Mode Framework —
storage specific),vscan(virus scan framework — defer),ipagent(from
a specific Nexenta/Triton context — likely irrelevant),hostid(sets
hardware hostid; verify if Hammerhead needs it),process-security(noop
service — just drop).
system/filesystem/
Default: all converted or redundant. All four filesystem-related manifests
(minimal-fs, local-fs, root-fs, usr-fs) are collapsed into zyginit's
filesystem.toml and root-fs.toml onshots. autofs should be dropped
unless Hammerhead actively uses automounting. vscan is dropped.
system/fm/
fmd.xml is already converted. notify-params.xml and smtp-notify.xml are
SMF notification hooks — drop or defer; zyginit has no equivalent mechanism.
system/device/
devices-local.xml is the basis for the Hammerhead devfs service (the
devfsadm + soconfig oneshot; see base/usr/src/zyginit/overrides/devfs/).
devices-audio.xml can be method-wrapped or
dropped depending on whether Hammerhead ships audio support. mpxio-upgrade.xml
is an upgrade artifact; drop.
See also: Section 7 (Catalog Appendix) for per-manifest classification.
7. Catalog Appendix
This appendix is a snapshot of all 128 SMF manifests found in
/lib/svc/manifest/ and /var/svc/manifest/ on hh-prototest as of
2026-05-02. It is a starting-point reference, not a living index — as
Hammerhead evolves, this catalog will drift from the actual source tree.
Classifications: already-converted (TOML exists in Hammerhead's overlay tree
at base/usr/src/zyginit/overrides/), drop (should not be in Hammerhead),
foreground (use daemon's foreground flag), method-wrap (keep the SMF method
script as exec.start), or needs-investigation (Hammerhead-team policy decision
required).
| Manifest path | Category | Classification | Note |
|---|---|---|---|
/lib/svc/manifest/milestone/multi-user-server.xml |
milestone | drop | SMF milestone — no zyginit equivalent; referenced <dependency> blocks must be dropped from other conversions |
/lib/svc/manifest/milestone/multi-user.xml |
milestone | drop | SMF milestone — tier ordering replaces it |
/lib/svc/manifest/milestone/name-services.xml |
milestone | drop | SMF milestone — no zyginit equivalent |
/lib/svc/manifest/milestone/network.xml |
milestone | drop | SMF milestone — network.toml replaces it |
/lib/svc/manifest/milestone/single-user.xml |
milestone | drop | SMF milestone — single-user-shell.toml and runlevel mode replace it |
/lib/svc/manifest/milestone/sysconfig.xml |
milestone | drop | SMF milestone — exec=:true; purely a dependency fence |
/lib/svc/manifest/platform/amd64/acpihpd.xml |
platform | needs-investigation | ACPI hotplug daemon; amd64-specific; method script /lib/svc/method/svc-acpihpd; determine if Hammerhead hardware needs hotplug events |
/lib/svc/manifest/network/bridge.xml |
network | needs-investigation | Bridge networking daemon; determine if Hammerhead uses software bridging |
/lib/svc/manifest/network/dlmgmt.xml |
network | already-converted | Hammerhead overrides as dlmgmtd; foreground flag -d |
/lib/svc/manifest/network/dns/client.xml |
network | needs-investigation | DNS client configuration service (exec=:true — just stores resolver config in SMF repo); in zyginit world resolv.conf is written directly by the installer; determine if a service is needed |
/lib/svc/manifest/network/dns/install.xml |
network | drop | Install-time DNS setup artifact |
/lib/svc/manifest/network/dns/multicast.xml |
network | needs-investigation | mDNS daemon (/usr/lib/inet/mdnsd); determine if Hammerhead needs mDNS |
/lib/svc/manifest/network/forwarding.xml |
network | needs-investigation | IPv4/IPv6 forwarding toggle; determine if Hammerhead acts as a router |
/lib/svc/manifest/network/ibd-post-upgrade.xml |
network | drop | InfiniBand IPoIB upgrade artifact |
/lib/svc/manifest/network/inetd-upgrade.xml |
network | drop | inetd upgrade artifact; Hammerhead does not run inetd |
/lib/svc/manifest/network/inetd.xml |
network | drop | Hammerhead does not run inetd; existing inetd.toml in repo is an experiment, not production |
/lib/svc/manifest/network/ipfilter.xml |
network | needs-investigation | IP packet filter daemon; determine if Hammerhead uses ipfilter for firewall |
/lib/svc/manifest/network/ipsec/ipsecalgs.xml |
network | needs-investigation | IPsec algorithm loader (ipsecalgs -s); needed if Hammerhead uses IPsec; simple oneshot |
/lib/svc/manifest/network/ipsec/manual-key.xml |
network | needs-investigation | IPsec manual key management; needs-investigation if IPsec is used |
/lib/svc/manifest/network/ipsec/policy.xml |
network | needs-investigation | IPsec policy loader; simple oneshot if used |
/lib/svc/manifest/network/ipsec/tcpkey.xml |
network | needs-investigation | TCP MD5 key loading; obscure; likely drop |
/lib/svc/manifest/network/iscsi/iscsi-initiator.xml |
network | drop | iSCSI initiator; storage-specific; defer to zports |
/lib/svc/manifest/network/iscsi/iscsi-target.xml |
network | drop | iSCSI target; storage-specific; defer to zports |
/lib/svc/manifest/network/isns_server.xml |
network | drop | iSNS server; storage-specific; defer to zports |
/lib/svc/manifest/network/ldap/client.xml |
network | drop | LDAP client; enterprise-specific; defer to zports or site customization |
/lib/svc/manifest/network/loadbalancer/ilbd.xml |
network | drop | illumos load balancer daemon; Hammerhead does not ship this use case |
/lib/svc/manifest/network/network-initial.xml |
network | drop | Consolidated into network.toml |
/lib/svc/manifest/network/network-install.xml |
network | drop | Install-time artifact |
/lib/svc/manifest/network/network-ipmgmt.xml |
network | already-converted | Hammerhead overrides as ipmgmtd; foreground flag -f |
/lib/svc/manifest/network/network-ipmp.xml |
network | needs-investigation | IP Multipathing daemon (in.mpathd); needed if Hammerhead uses IPMP for NIC bonding |
/lib/svc/manifest/network/network-ipqos.xml |
network | needs-investigation | IP Quality of Service configuration; determine if Hammerhead uses IPQoS |
/lib/svc/manifest/network/network-iptun.xml |
network | needs-investigation | IP tunnel interfaces (GRE, etc.); determine if Hammerhead uses IP tunnels |
/lib/svc/manifest/network/network-location.xml |
network | drop | Network location/profile management (NWAM); Hammerhead uses static config |
/lib/svc/manifest/network/network-loopback.xml |
network | drop | Consolidated into network.toml |
/lib/svc/manifest/network/network-netmask.xml |
network | drop | Consolidated into network.toml; netmask config read directly |
/lib/svc/manifest/network/network-physical.xml |
network | drop | Consolidated into network.toml |
/lib/svc/manifest/network/network-routing-setup.xml |
network | drop | Consolidated into network.toml; static routing via /etc/defaultrouter |
/lib/svc/manifest/network/network-service.xml |
network | drop | Consolidated into network.toml |
/lib/svc/manifest/network/nfs/cbd.xml |
network | needs-investigation | NFS v4 callback daemon; needed only if NFS client is active |
/lib/svc/manifest/network/nfs/client.xml |
network | needs-investigation | NFS client; determine if Hammerhead ships NFS client support |
/lib/svc/manifest/network/nfs/mapid.xml |
network | needs-investigation | NFS v4 user/group ID mapping; needed with NFS v4 |
/lib/svc/manifest/network/nfs/nfslogd.xml |
network | needs-investigation | NFS logging daemon; server-side; drop unless NFS server is shipped |
/lib/svc/manifest/network/nfs/nlockmgr.xml |
network | needs-investigation | NFS lock manager; needed with NFS client or server |
/lib/svc/manifest/network/nfs/rquota.xml |
network | needs-investigation | Remote quota daemon; server-side; likely drop |
/lib/svc/manifest/network/nfs/server.xml |
network | needs-investigation | NFS server; determine if Hammerhead ships NFS server |
/lib/svc/manifest/network/nfs/status.xml |
network | needs-investigation | NFS status monitor; needed with NFS client or server |
/lib/svc/manifest/network/routing/legacy-routing.xml |
network | drop | Legacy in.routed/in.rdisc; Hammerhead uses static routing |
/lib/svc/manifest/network/routing/ndp.xml |
network | needs-investigation | IPv6 NDP daemon (in.ndpd); needed for IPv6 operation |
/lib/svc/manifest/network/routing/ripng.xml |
network | drop | RIPng routing daemon; dynamic routing; not needed for base system |
/lib/svc/manifest/network/rpc/bind.xml |
network | already-converted | Hammerhead overrides as rpcbind; direct exec /usr/sbin/rpcbind |
/lib/svc/manifest/network/rpc/gss.xml |
network | drop | GSSAPI daemon; needed only with Kerberos/NFS |
/lib/svc/manifest/network/rpc/smserver.xml |
network | drop | Removable media RPC service; obsolete |
/lib/svc/manifest/network/security/kadmin.xml |
network | drop | Kerberos admin server; server-role; defer to zports |
/lib/svc/manifest/network/security/krb5_prop.xml |
network | drop | Kerberos slave propagation; server-role |
/lib/svc/manifest/network/security/krb5kdc.xml |
network | drop | Kerberos KDC; server-role; defer to zports |
/lib/svc/manifest/network/security/ktkt_warn.xml |
network | drop | Kerberos ticket warning daemon; drop unless Kerberos client is used |
/lib/svc/manifest/network/shares/group.xml |
network | drop | Share group management (NFS/SMB shares); defer to zports |
/lib/svc/manifest/network/shares/reparsed.xml |
network | drop | Reparse point daemon (CIFS/SMB); drop |
/lib/svc/manifest/network/smb/client.xml |
network | drop | SMB client (smbfs); defer to zports |
/lib/svc/manifest/network/smb/server.xml |
network | drop | SMB server (smbd); defer to zports |
/lib/svc/manifest/network/ssh.xml |
network | already-converted | Hammerhead overrides as sshd; foreground flag -D |
/lib/svc/manifest/network/tnctl.xml |
network | drop | Trusted Extensions network control; TX not shipped in Hammerhead |
/lib/svc/manifest/network/tnd.xml |
network | drop | Trusted Extensions network daemon; TX not shipped in Hammerhead |
/lib/svc/manifest/network/varpd.xml |
network | needs-investigation | Virtual ARP daemon for overlay networking (VXLAN); determine if Hammerhead ships overlay networking |
/lib/svc/manifest/network/wpa.xml |
network | needs-investigation | WPA supplicant daemon; determine if Hammerhead supports Wi-Fi |
/lib/svc/manifest/system/auditd.xml |
system | needs-investigation | BSM audit daemon; determine if Hammerhead ships BSM auditing; method-wrap /lib/svc/method/svc-auditd if kept |
/lib/svc/manifest/system/auditset.xml |
system | needs-investigation | Audit policy oneshot; companion to auditd; same decision |
/lib/svc/manifest/system/boot-archive-update.xml |
system | drop | Updates boot archive after upgrade; SMF-infrastructure concern |
/lib/svc/manifest/system/boot-archive.xml |
system | drop | Checks boot archive consistency; zyginit does not manage boot archive |
/lib/svc/manifest/system/boot-config.xml |
system | drop | SMF boot config property store; no zyginit equivalent needed |
/lib/svc/manifest/system/consadm.xml |
system | needs-investigation | Console administration (alternate console); determine if needed |
/lib/svc/manifest/system/console-login.xml |
system | already-converted | Hammerhead overrides as console-login; complex wrapper writes utmpx entry before exec of ttymon |
/lib/svc/manifest/system/coreadm.xml |
system | method-wrap | coreadm -U to apply coreadm configuration; simple oneshot; inline coreadm -U directly in a TOML oneshot |
/lib/svc/manifest/system/cron.xml |
system | already-converted | Hammerhead overrides as cron; start.sh removes stale FIFO |
/lib/svc/manifest/system/cryptosvc.xml |
system | already-converted | Hammerhead overrides as crypto; cryptoadm oneshot |
/lib/svc/manifest/system/device/devices-audio.xml |
system | needs-investigation | Audio device setup; determine if Hammerhead ships audio support |
/lib/svc/manifest/system/device/devices-local.xml |
system | already-converted | Hammerhead overrides as devfs; start.sh runs devfsadm + soconfig |
/lib/svc/manifest/system/device/mpxio-upgrade.xml |
system | drop | MPXIO upgrade artifact |
/lib/svc/manifest/system/dumpadm.xml |
system | method-wrap | svc-dumpadm applies crash dump configuration; oneshot; wrap or inline /usr/sbin/dumpadm -r / |
/lib/svc/manifest/system/early-manifest-import.xml |
system | drop | SMF manifest import; exec=:true; no-op without SMF repo |
/lib/svc/manifest/system/extended-accounting.xml |
system | needs-investigation | Process/task/flow accounting via acctadm; rare use case |
/lib/svc/manifest/system/fcoe_initiator.xml |
system | drop | FCoE initiator; storage-specific; defer to zports |
/lib/svc/manifest/system/fcoe_target.xml |
system | drop | FCoE target; storage-specific; defer to zports |
/lib/svc/manifest/system/filesystem/autofs.xml |
system | drop | Automounter; not needed unless Hammerhead actively uses autofs |
/lib/svc/manifest/system/filesystem/local-fs.xml |
system | already-converted | Consolidated into Hammerhead overrides filesystem |
/lib/svc/manifest/system/filesystem/minimal-fs.xml |
system | already-converted | Consolidated into Hammerhead overrides filesystem; /var/run tmpfs mount is a follow-up |
/lib/svc/manifest/system/filesystem/root-fs.xml |
system | already-converted | Hammerhead overrides as root-fs; ZFS readonly assertion |
/lib/svc/manifest/system/filesystem/usr-fs.xml |
system | already-converted | Consolidated into Hammerhead overrides filesystem |
/lib/svc/manifest/system/filesystem/vscan.xml |
system | drop | Virus scan framework; defer to zports |
/lib/svc/manifest/system/fm/notify-params.xml |
system | drop | SMF notification hooks (exec=:true); no zyginit equivalent |
/lib/svc/manifest/system/fm/smtp-notify.xml |
system | needs-investigation | SMTP fault notification daemon; determine if Hammerhead ships this; foreground check: try smtp-notify without args |
/lib/svc/manifest/system/fmd.xml |
system | already-converted | Hammerhead overrides as fmd; foreground flag -f |
/lib/svc/manifest/system/hostid.xml |
system | needs-investigation | Sets hardware hostid via svc-hostid script; verify if Hammerhead needs a hostid set at boot |
/lib/svc/manifest/system/hotplug.xml |
system | needs-investigation | Hotplug daemon (hotplugd via svc-hotplug); determine if Hammerhead hardware needs it |
/lib/svc/manifest/system/i2csimd.xml |
system | drop | I2C sensor daemon from a test harness (/opt/i2c-tests/); not part of base system |
/lib/svc/manifest/system/ibsrp/target.xml |
system | drop | InfiniBand SRP target; hardware-specific; defer to zports |
/lib/svc/manifest/system/identity.xml |
system | already-converted | Hammerhead overrides as identity; sets hostname/nodename |
/lib/svc/manifest/system/idmap.xml |
system | needs-investigation | Identity mapping daemon (idmapd); needed with SMB or Kerberos |
/lib/svc/manifest/system/intrd.xml |
system | foreground | Interrupt distribution daemon; svc-intrd calls /usr/lib/intrd; check intrd source for -f or -d flag; method-wrap if no flag |
/lib/svc/manifest/system/ipagent.xml |
system | drop | Triton/SmartOS IP agent; not part of base Hammerhead |
/lib/svc/manifest/system/keymap.xml |
system | method-wrap | Keyboard map configuration; keymap script applies console keymap; simple oneshot via method-wrap or inline |
/lib/svc/manifest/system/labeld.xml |
system | drop | Trusted Extensions label daemon; TX not shipped in Hammerhead |
/lib/svc/manifest/system/logadm-upgrade.xml |
system | drop | Log rotation config upgrade artifact |
/lib/svc/manifest/system/manifest-import.xml |
system | drop | SMF manifest import daemon |
/lib/svc/manifest/system/name-service-cache.xml |
system | needs-investigation | nscd name service cache daemon; determine if Hammerhead needs nscd |
/lib/svc/manifest/system/ndmp.xml |
system | drop | NDMP backup protocol; defer to zports |
/lib/svc/manifest/system/pfexecd.xml |
system | already-converted | Hammerhead overrides as pfexecd; direct exec /usr/lib/pfexecd |
/lib/svc/manifest/system/picl.xml |
system | drop | PICL platform information daemon; Sun hardware-specific; not relevant for x86 virtual hardware |
/lib/svc/manifest/system/pools.xml |
system | needs-investigation | Resource pools (FSSv2); determine if Hammerhead uses resource pools |
/lib/svc/manifest/system/power.xml |
system | already-converted | Hammerhead overrides as powerd; direct exec or method-wrap svc-power |
/lib/svc/manifest/system/process-security.xml |
system | drop | Noop service (exec=:true); no functionality |
/lib/svc/manifest/system/rbac.xml |
system | method-wrap | RBAC database initialization; svc-rbac start oneshot; method-wrap or inline /usr/sbin/svcadm alternative — check what svc-rbac actually does |
/lib/svc/manifest/system/rcap.xml |
system | needs-investigation | Resource capping daemon (rcapd); determine if Hammerhead uses resource capping |
/lib/svc/manifest/system/resource-mgmt.xml |
system | needs-investigation | Resource management configuration; companion to pools and rcap |
/lib/svc/manifest/system/rmtmpfiles.xml |
system | method-wrap | Removes tmp files at boot (rmtmpfiles oneshot); simple method-wrap or inline /bin/rm -rf /tmp/* equivalent |
/lib/svc/manifest/system/sar.xml |
system | needs-investigation | System activity reporter (sar/sa); determine if Hammerhead ships sar |
/lib/svc/manifest/system/scheduler.xml |
system | method-wrap | Sets default scheduler class (svc-scheduler); oneshot; inspect svc-scheduler and inline if trivial |
/lib/svc/manifest/system/stmf.xml |
system | drop | SCSI Target Mode Framework; storage-specific; defer to zports |
/lib/svc/manifest/system/svc/global.xml |
system | drop | SMF global property store |
/lib/svc/manifest/system/svc/restarter.xml |
system | drop | IS svc.startd; zyginit replaces it |
/lib/svc/manifest/system/sysevent.xml |
system | already-converted | Hammerhead overrides as syseventd; method-wrap svc-syseventd |
/lib/svc/manifest/system/system-log.xml |
system | already-converted | Hammerhead overrides as syslogd; foreground flag -d; start.sh touches /var/adm/messages first |
/lib/svc/manifest/system/tsol-zones.xml |
system | drop | Trusted Extensions zones; TX not shipped in Hammerhead |
/lib/svc/manifest/system/update-man-index.xml |
system | drop | Man page index update; not needed at every boot |
/lib/svc/manifest/system/utmp.xml |
system | already-converted | Hammerhead overrides as utmpd; method-wrap svc-utmpd |
/lib/svc/manifest/system/vtdaemon.xml |
system | method-wrap | Virtual terminal multiplexer; vtdaemon script; determine if Hammerhead uses VTs; method-wrap if kept |
/lib/svc/manifest/system/zones.xml |
system | needs-investigation | Zones boot/halt service; zyginit will need a zones oneshot for autoboot=true zones; see docs/DESIGN.md Zones section |
/lib/svc/manifest/system/zonestat.xml |
system | needs-investigation | Zone statistics daemon (zonestatd); needed once zones are enabled |
Catalog summary:
| Classification | Count |
|---|---|
already-converted |
19 |
drop |
61 |
foreground |
1 |
method-wrap |
7 |
needs-investigation |
40 |
| Total | 128 |
8. Format Reference Pointer
This section points to the authoritative TOML format documentation.
The zyginit service definition format — all valid fields, their types,
defaults, and semantics — is documented in docs/man/man5/zyginit.5.
The decision tree (Section 2) and catalog appendix (Section 7) use
field names from that reference. If a field name here appears to conflict
with what man zyginit.5 says, the man page is authoritative.
For runtime behavior, signal handling, and socket protocol, see
docs/man/man8/zyginit.8 and docs/man/man8/zygctl.8.
9. Glossary
Definitions of SMF concepts that appear in this document for readers
without an illumos background.
BE (Boot Environment): A ZFS dataset snapshot that represents a complete,
bootable OS image. Hammerhead supports multiple BEs; beadm (or direct
zpool set bootfs) selects which one the kernel boots.
Contract (process contract): A Hammerhead kernel mechanism that groups
related processes. When all processes in a contract exit, the kernel fires a
contract event. zyginit uses contracts to track service processes and detect
daemon exit without polling. See docs/DESIGN.md Contracts section.
FMRI (Fault Management Resource Identifier): SMF's naming scheme for
services, e.g., svc:/network/ssh:default. zyginit uses bare names (e.g.,
sshd) in TOML files instead.
libcontract: The Hammerhead userland library for managing process contracts.
zyginit links against it (-l contract). Not available on Linux.
libscf (Service Configuration Facility): The Hammerhead userland library
for reading and writing the SMF repository. Calls into svc.configd via a
door. A daemon that calls scf_handle_create() at startup requires configd
to be running.
Manifest: An XML file that describes an SMF service — its name, method
(start/stop command), dependencies, and properties. Stored in
/lib/svc/manifest/. zyginit replaces manifests with TOML files in
/etc/zyginit/.
Method (SMF method): The start, stop, or refresh command for an SMF
service, optionally implemented as a shell script in /lib/svc/method/.
The equivalent in zyginit is [exec] start and [exec] stop.
Profile (SMF profile): An XML file that selects which services are enabled
by default. zyginit replaces profiles with symlinks in /etc/zyginit/enabled.d/.
Repository: The SMF configuration database managed by svc.configd.
Stored in /etc/svc/repository.db (SQLite). zyginit has no database — service
state is in-memory only; configuration is in TOML files.
Restarter: In SMF, a service that manages other services. The master
restarter is svc.startd. zyginit is a single-process init that plays the
role of the restarter for all services.
soconfig: A Hammerhead utility (/sbin/soconfig) that loads the sockfs
protocol-to-module mapping from /etc/sock2path.d/. Must run before any
socket(AF_INET, ...) call succeeds. See Anti-patterns section 3.
uadmin: The Hammerhead system call for administrative operations including
halt, reboot, and poweroff. Must be called from a non-PID-1 process to avoid
the restart_init race. See Anti-patterns section 8.