Skip to content

devscan: driver configuration directories of mount points, by ioctl on the mount - #75

Merged
JohnAmadis merged 6 commits into
mainfrom
feat/per-mount-config-dirs
Oct 25, 2026
Merged

JohnAmadis merged 6 commits into
mainfrom
feat/per-mount-config-dirs

Conversation

@JaxCalder

@JaxCalder JaxCalder commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

What

Every mounted file system may bring driver configurations of its own, in <mount point>/cfg/drivers (the layout of the directory dmdevfs is configured from).

  • An ioctl on the mount itself. Opening the root of a dmdevfs mount (/dev, not a node in it) gives a handle without a device behind it (a built-in node like /dev/null: EOF on read, writes discarded) that answers DMDEVFS_IOCTL_ADD_CONFIG_DIR and DMDEVFS_IOCTL_REMOVE_CONFIG_DIR (include/dmdevfs.h), argument: the mount point. The command works on the mount that was opened, and only on it. Queued for the hot-plug thread: same procedure as at start (driver_order, dependencies, nodes reported to libsystemd, partitions exposed); removal reports nodes, partitions and hot-plugged devices removed and frees the driver (dmdrvi_free(), module release) after the last open handle. A driver is appended to the mount's list under g_devfs_mutex; configuration file paths may be longer than a node path.

  • services/devscan - a one-shot service (like dmdevmon: unit templates + a rule + its own stack):

    devscan add    <dmdevfs path> <mount point>
    devscan remove <dmdevfs path> <mount point>
    

    libsystemd reports every mount as a device of class mount (libsystemd: mounts as devices, a rule key to run a unit on removal, configuration directories of mount points dmsystem#9) and configs/devscan.rules says what to do:

    [class=mount]
    start=devscan@%name              # mounted: configure its cfg/drivers
    remove=devscan-remove@%name      # about to be unmounted: drop them (the unmount waits for it)

    Both units are type=oneshot; nothing stays running. The process runs at priority 3: the unmount waits for the remove unit (up to 20 s) and at priority 0 it did not get the CPU for all of it with the car HMI running. The path of the dmdevfs (/dev) is in the unit file. Only the drivers are dmdevfs's: the units and rules of a mount point (cfg/services, cfg/rules) are loaded by libsystemd itself when the file system is mounted (libsystemd: mounts as devices, a rule key to run a unit on removal, configuration directories of mount points dmsystem#9).

This replaces the earlier revision of the PR (mountcfg + a public dmdevfs_add_config_dir() that loaded into every dmdevfs mount and called libsystemd, too).

Known limitation

devscan add does not wait for the drivers (the hot-plug thread configures them after it returns).

Testing

  • Host: ctest 11/11, incl. test_config_dir (7 steps: arguments, the root handle, configure/remove, only the mount that was asked, once-only loading, driver freed after its last handle, driver goes with its hot-plugged devices).
  • STM32F746G-DISCO (dmod-boot#148): devscan runs for every mount and unmount (service list); on a RAM file system with cfg/drivers/dmgpio/x.ini mounted by hand, the node count of /dev goes 63 -> 64 with devscan add and back to 63 when it is unmounted (the rule's remove unit).

Found on the way (not in this PR)

🤖 Generated with Claude Code

dmdevfs_add_config_dir(mount_point) configures the drivers of
<mount_point>/cfg/drivers in every dmdevfs mount, as if they were in its own
directory; dmdevfs_remove_config_dir() removes them again: every node - its
partitions and hot-plugged devices first - is reported removed, and the driver
is freed once the last handle on any of its nodes is closed (the nodes sharing
its context hold a reference on it). Both are queued for the hot-plug thread.
A driver is now added to the mount's list under g_devfs_mutex, and a
configuration file path may be longer than a node path.

mountcfg (services/mountcfg), a Library module started by a type=library unit,
follows the mounts with dmvfs's mount listener and hands every mount point to
dmdevfs (cfg/drivers) and libsystemd (cfg/services, cfg/rules) - neither of
which depends on dmvfs, so both still run on the host loader.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dmvfs reports mounts through a DIF now instead of registered callbacks:
mountcfg implements _mount_changed, so there is nothing to register or remove,
and loads the mounts made before it started (dmvfs_get_mount_point()) on its own
thread first - not on the stack of whoever enabled the module.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The mount reports moved from a dif of dmvfs (a static library without a
generated _defs.h) to dmfsi's _mount_changed dif, implemented with the usual
dmod_dmfsi_dif_api_declaration().

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@JohnAmadis JohnAmadis left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pogielo cie? Recznie tworzyc milion procesow i watkow? Po pierwsze to ja nie widze powodu dla ktorego niby potrzebujesz specjalnie uslugi do tego. Po drugie jesli juz to wystarczy jeden watek, po trzecie to przeciez masz obsluge ruli w libsystem - nie widze zadnego powodu aby je tworzyc recznie

dmdevfs implements the dif, so a mounted card or /ext brings its configuration
without a module of its own (mountcfg is gone): a mount queues the directory
for the hot-plug thread - drivers first, then libsystemd_add_config_dir(); an
unmount stops the units of the mount point before it goes on, and queues the
removal of its drivers. The units are stopped by a thread that lives for the
time of one unmount: not the unmounting thread (automount's stack is 2.5 kB)
and not the hot-plug thread (when a card is pulled out it is busy waiting for
automount to stop, which is what unmounts - waiting for it would deadlock).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@JaxCalder JaxCalder changed the title Configuration directories of mount points (dmdevfs_add_config_dir) and mountcfg dmdevfs follows the mounts: configuration directories of mount points Oct 25, 2026
…llowing mounts

dmdevfs no longer implements the _mount_changed dif (and the thread that
stopped units for an unmount is gone). libsystemd reports mounts as devices of
class "mount"; services/mountcfg is a one-shot application (4 kB of stack of
its own) started by the rule for a mount - `mountcfg load <mount point>` - and
by the rule's "remove" key before an unmount - `mountcfg unload` - which the
unmount waits for. It calls the add/remove config dir functions of dmdevfs and
libsystemd and ends; nothing stays running.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@JaxCalder JaxCalder changed the title dmdevfs follows the mounts: configuration directories of mount points mountcfg: a one-shot service loading the configuration directory of a mount point Oct 25, 2026
…stead of mountcfg

The config-directory calls were a public module API that configured the
drivers in every dmdevfs mount. They are now commands of the mount itself:
opening its root (`/dev`) gives a handle without a device behind it that
answers DMDEVFS_IOCTL_ADD_CONFIG_DIR / DMDEVFS_IOCTL_REMOVE_CONFIG_DIR
(argument: the mount point), and only the mount that was opened is touched.

services/mountcfg becomes services/devscan: a one-shot service started by a
libsystemd rule on class `mount` (start for a mount, `remove` for an unmount),
`devscan <add|remove> <dmdevfs path> <mount point>`. The path of the dmdevfs is
in the unit file (`/dev`). It no longer touches libsystemd's units and rules:
libsystemd does not load a mount's cfg/services or cfg/rules any more.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@JaxCalder JaxCalder changed the title mountcfg: a one-shot service loading the configuration directory of a mount point devscan: driver configuration directories of mount points, by ioctl on the mount Oct 25, 2026
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