0

In /usr/lib/modules/$(uname -r)/modules.devname, the first line is a comment:

# Device nodes to trigger on-demand module loading.

Assuming what it means is that the first time a device file under /dev is accessed, a module which populates that file will be automatically loaded.

But I don't see the code that does module loading when a file lookup failed, in /drivers/base/devtmpfs.c or /mm/shmem.c(tmpfs). Where does that logic live then?

Marco Bonelli
  • 63,369
  • 21
  • 118
  • 128
QnA
  • 1,035
  • 10
  • 25

1 Answers1

3

The modules.devname file has nothing to do with module auto-loading. It contains information that can be used during system initialization to create files in the /dev directory. The file is read by the kmod static-nodes command. By default, kmod static-nodes produces human-readable output, but during system initialization it is run as kmod static-nodes --format=tmpfiles to generate output in a more machine-parseable form. Each line contains information that can be used to create a single directory or a single special file (see the tmpfiles.d man page for details of the format). It does not contain the module name.

On systems using Systemd init, the kmod command is run from the kmod-static-nodes.service service. The output file in tmpfiles.d format is placed in "/run/tmpfiles.d/static-nodes.conf", which will be read later by the systemd-tmpfiles --prefix=/dev --create --boot command run from the systemd-tmpfiles-setup-dev.service service to create the actual files in "/dev".

On systems using Sysv init, the kmod command may be run by the /etc/init.d/udev init script (on Debian type systems) or from somewhere else. The same init script creates the actual files in "/dev" based on the output from kmod.


When a character special file for an unregistered character device number is being opened, the kernel will request the module with alias char-major-MAJOR-MINOR or char-major-MAJOR where MAJOR and MINOR are the major and minor device numbers of the special file. (See base_probe() in "fs/char_dev.c".) If the kernel is configured with CONFIG_BLOCK_LEGACY_AUTOLOAD=y, there is similar functionality when opening block special files for unregistered block device numbers, the kernel will request the module with alias block-major-MAJOR-MINOR or block-major-MAJOR. (See blk_request_module() in "block/genhd.c" and blkdev_get_no_open() in "block/bdev.c".)

The source code for a module uses the MODULE_ALIAS_CHARDEV(), MODULE_ALIAS_CHARDEV_MAJOR(), MODULE_ALIAS_BLOCKDEV(), or MODULE_ALIAS_BLOCKDEV_MAJOR() macros (which wrap the MODULE_ALIAS() macro) to put these aliases into the module's .modinfo section where the depmod command can find them.

Ian Abbott
  • 15,083
  • 19
  • 33
  • 2
    For reference, [here's the relevant piece of code in `misc_open()`](https://elixir.bootlin.com/linux/v5.10/source/drivers/char/misc.c#L118) asking for the module to be loaded by the kernel. The loading itself is done through [kmod](https://elixir.bootlin.com/linux/v5.10/source/kernel/kmod.c) which invokes `modprobe` through `call_usermodehelper_exec`. – Marco Bonelli Jul 20 '22 at 20:37
  • @Ian Your explanations make a lot of sense. One question though, I found `dm_interface_init()` from `dm-ioctl.c`, which actually registers and adds `/dev/mapper/control` by eventually calling `device_register()/device_add()/devtmpfs_create_node()`. If `dm_interface_init()` is called upon module `dm-mod` loading, then isn't that duplicating the creation of node `/dev/mapper/control` which is already made by systemd-tmpfiles service? – QnA Jul 21 '22 at 03:06
  • @MarcoBonelli Thanks for the additional location for module loading, although the one in `misc_open()` is only used for char major 10 (misc) devices. – Ian Abbott Jul 21 '22 at 09:01
  • @QnA Indeed, the `devtmpfs_create_node(dev);` call from `device_add(dev)` will return `-EEXIST` but the error is ignored. However, when the `dm-mod` module is unloaded (which will remove the control device), the `/dev/mapper/control` file (and `/dev/mapper` directory) will be deleted, which seems like a bug. (The same problem does not occur with the "nvram" module, for example, because it doesn't set the `nodename` member of its `struct miscdevice`.) – Ian Abbott Jul 21 '22 at 11:06
  • @Ian All clear now, thanks a ton! – QnA Jul 21 '22 at 14:04