virtiofs and MAP_SHARED
Anything that mmaps a shared file needs type: block, NOT filesystem — virtiofs cannot back MAP_SHARED.
Incus attaches a type: filesystem volume to a VM over virtiofs, which does not support shared file mappings. Every symptom names the application rather than the cause, so this gets rediagnosed from scratch each time:
| Service | Symptom |
|---|---|
| MariaDB 11.8 | tc.log init fails — “Can’t init tc log” |
| kanidm (SQLite WAL) | SQLITE_IOERR_SHMMAP (extended_code 5386) / “disk I/O error” on the -shm file |
The 10-second test
Confirm or eliminate it before investigating anything else — a block-backed path such as /root is the control:
incus exec <host>:<vm> -- python3 -c "import mmap; f=open('<path>/t','w+b'); f.write(b'x'*4096); f.flush(); mmap.mmap(f.fileno(),4096,mmap.MAP_SHARED); print('MAP_SHARED ok')"# virtiofs -> OSError: [Errno 19] No such device# virtio-blk -> MAP_SHARED okThe block-volume contract
A block volume carries no path: — it arrives as a raw disk and the consuming role formats + mounts it (e.g. the MariaDB role → /var/lib/mysql; the kanidm role → /srv/kanidm). The Incus device name → in-guest path contract is:
/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_incus_<device>— and udev doubles every hyphen in the serial, so device kanidm-db appears as incus_kanidm--db (compare the root disk’s incus_root-part1, where the single hyphen is udev’s own suffix). The kanidm role derives that escaping from the device name; the MariaDB role hardcodes its path and gets away with it only because db has no hyphen. Don’t rename a device without updating its consuming role.
Related
- Architecture → Volumes and lifecycle — the protected/unprotected volume model this contract lives inside.
- QVO fsync cliff — the fleet’s other storage sharp edge (fsync latency, distinct from this mmap issue).