Skip to content

/configs -> /cfg; configuration goes where the module goes (per-mount cfg/, devscan) - #148

Merged
JohnAmadis merged 9 commits into
masterfrom
feat/per-mount-cfg
Oct 26, 2026
Merged

JohnAmadis merged 9 commits into
masterfrom
feat/per-mount-cfg

Conversation

@JaxCalder

@JaxCalder JaxCalder commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

Problem

carhmi (moved to the SD card in #145/#147) never started: its unit was in the firmware's /configs, started at boot before automount had mounted the card, and libsystemd skips a unit whose module it cannot find.

Change

  • The config filesystem is mounted at /cfg (systemd gets /cfg/services /cfg/rules, dmdevfs /cfg/drivers); a build directory that still holds the old defaults in its cache is switched over.
  • Configuration goes where the module goes: the service=, rules=, driver= files of the sdcard and ext modules go to build/sdcard/cfg and build/ext/cfg (= <card>/cfg, /ext/cfg) instead of the firmware; upload-files / upload-ext send them with the modules.
  • libsystemd loads <mount point>/cfg/services and cfg/rules by itself when a file system is mounted (it implements dmfsi's _mount_changed dif, called by dmvfs) and drops them before the unmount. %m in such a unit is the mount point, so it stays bound to its own card. The unit of the car HMI demo is the one it ships (carhmi.ini, now on the card).
  • devscan: the same mount is a device of class mount; devscan.rules starts the one-shot devscan service (dmdevfs) for it - add when it is mounted, remove before it is unmounted (the unmount waits for it); it asks dmdevfs, by an ioctl on /dev, to configure / drop <mount point>/cfg/drivers, and ends.
  • lib/dmvfs -> develop (mount reports through dmfsi's dif).
  • docs and tests/test_module_layout.py updated (passes).

Dependencies - do not merge before

Testing (STM32F746G-DISCO, real board)

  • The firmware builds and flashes; after a cold boot the card is mounted by automount, devscan runs for every mount, and carhmi starts by itself from the unit on the card (service list: running).
  • A probe unit in /ext/cfg/services: umount /ext + mount loads it (%m = /ext), once per cycle with a fresh instance, devscan-remove@ext / devscan@ext run every time.
  • A RAM file system mounted by hand with cfg/drivers/dmgpio/x.ini: devscan add /dev /rt adds the node (63 -> 64), umount /rt runs the remove units and the node is gone (63).

Known problems (not in this PR)

  • carhmi stops too slowly (5+ s, libsystemd kills it after 3 s, in the middle of a file operation, which leaves the dmvfs mutex locked by a dead thread). Fixed in Stop on request in 3.7 s instead of 5+: stop all threads at once; the unit waits 15 s carhmi-demo#15 (stops all its threads at once, stop_timeout_ms=15000 in its unit: 5.4 s -> 3.7 s, and the stop is waited for, not killed). With it, dmblock#6 (60 s for automount's stop) and devscan at priority 3, unmounting the card with the HMI running completes (25 s on the board) instead of hanging.
  • dmqspi under load: with carhmi running, /ext reads started failing (EIO/EBUSY) ~1 min after boot, until reset - QUADSPI is left with an indirect read stalled on a full FIFO and the driver never aborted it. Fixed in port: recover a controller left with a transfer; waits bounded by time dmqspi#4 (the firmware tested here carries it: 500+ commands from /ext in a row over 9 minutes, none failed).

🤖 Generated with Claude Code

…goes

The configuration filesystem is mounted at /cfg (systemd gets /cfg/services and
/cfg/rules, dmdevfs /cfg/drivers); a build directory still holding the old
defaults in its cache is switched over.

The service=, rules= and driver= files of the sdcard and ext modules go to
build/sdcard/cfg and build/ext/cfg - <card>/cfg and /ext/cfg on the device -
instead of the firmware. mountcfg (dmdevfs), started from the common flash.dmd,
loads the cfg/ of every mount point once it is mounted and unloads it before it
is unmounted: carhmi's unit is on the card now and starts when the card is
there, not at boot before automount has mounted it.

lib/dmvfs: mount listeners, which mountcfg uses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
JaxCalder and others added 7 commits October 24, 2026 22:40
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dmdevfs implements dmfsi's _mount_changed dif itself and loads the cfg/ of every
mount point, so the mountcfg unit is dropped from the common flash.dmd and the
documentation says dmdevfs. lib/dmvfs: develop (mount reports through the dif).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
flash.dmd: mountcfg's two unit templates and its rule - libsystemd reports mounts
as devices of class "mount", the rule starts `mountcfg load` for a mount and
`mountcfg unload` before an unmount; docs say so.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
libsystemd no longer loads a mount point's cfg/services and cfg/rules, and the
config-dir calls of dmdevfs are an ioctl on the mount now (dmdevfs
services/devscan). So:

- flash.dmd ships devscan (unit templates and the [class=mount] rule) instead of
  mountcfg;
- only `driver=` files of the sdcard and ext modules go to their own medium
  (<medium>/cfg/drivers, handed to dmdevfs by devscan); `service=` and `rules=`
  files always go to DMBOOT_CONFIG_DIR, and the config image waits for the
  sdcard and ext downloads;
- the car HMI demo, a module of the SD card, gets the board's own unit and rule
  (carhmi@.ini, carhmi.rules) instead of the unit it carried on the card: the
  rule starts carhmi-start@<mount>, a one-shot `service start carhmi@<mount>`,
  for every mount, and carhmi-stop@<mount> before it is unmounted. Loading the
  module from the card, with its dependencies, takes far more stack than the
  thread that reports a mount has, so it is done by a process of its own.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@JaxCalder JaxCalder changed the title /configs -> /cfg; configuration goes where the module goes (per-mount cfg/, mountcfg) /configs -> /cfg; drivers of a mount point from <mount>/cfg/drivers (devscan); carhmi started by a rule Oct 25, 2026
libsystemd loads <mount point>/cfg/services and cfg/rules by itself when a file
system is mounted (and drops them before the unmount), so the units and rules of
the sdcard and ext modules go back to their own medium (build/sdcard/cfg,
build/ext/cfg), exactly as before devscan - and the unit of the car HMI demo is
the one it ships (carhmi.ini on the card) again: the board's carhmi@ unit, its
launcher units and its rule are gone. devscan stays for cfg/drivers (dmdevfs).

The mount's unit starts in the thread that mounts - automount's - so automount
needs a 4 kB stack (choco-technologies/dmblkid).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@JohnAmadis
JohnAmadis merged commit 44e61f0 into master Oct 26, 2026
6 of 10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants