Skip to content

incusd/fsmonitor: Read multiple fanotify events#2961

Merged
stgraber merged 1 commit intolxc:mainfrom
zgttotev:hotplug
Feb 22, 2026
Merged

incusd/fsmonitor: Read multiple fanotify events#2961
stgraber merged 1 commit intolxc:mainfrom
zgttotev:hotplug

Conversation

@zgttotev
Copy link
Copy Markdown
Contributor

@zgttotev zgttotev commented Feb 20, 2026

fanotify(7) states:

After a successful read(2), the read buffer contains one or more of
the following structures [events].
...
For performance reasons, it is recommended to use a large buffer size
(for example, 4096 bytes), so that multiple events can be retrieved by a
single read(2).

func getEvents was only processing one event from a buffer which potentially contained more, leading to dropped events as observed with a watch on /dev/loop0p{1,2} where frequently only one partition would make it to the Incus device directory.

Unfortunately, just reading more events did not solve the issue. It seems the watch callbacks spawned in goroutines would race and again result in missing partitions in the device directory. I suspect the real culprit behind issue #2404 was not reading multiple events from the buffer as is fixed here. To address the concern about kernel-dropped events, I've added a warning here to diagnose but fanotify(7) seems to indicate this will be rare (I certainly never saw it trigger):

FAN_Q_OVERFLOW
The event queue exceeded the limit of 16384 entries.

In testing I used a small 2-partition img file, two unix-block devices on loop0p{1,2} with required=false, and following script:

devs=/var/lib/incus/devices/warpstation/unix.hotplug-dev-loop0p
loops() { echo ${devs}${1}.dev-loop0p$1; }
while true; do
  losetup -d /dev/loop0
  losetup -P /dev/loop0 loopit.img
  sleep 1
  if [ ! -e $(loops 1) ] || [ ! -e $(loops 2) ]; then
    ls -l ${devs}*
    break
  fi
done

On Incus 6.21 stable, it fails within the first few iterations (increasing the timeout did not help either). With this patch it has not once failed over several minutes.

Additionally, a potential fd leak is addressed for the file handle.

@zgttotev
Copy link
Copy Markdown
Contributor Author

zgttotev commented Feb 20, 2026

Seems the GitHub diff viewer doesn't handle the new indent well, git diff --ignore-space-change works better.

fanotify(7) states:
> After a successful read(2), the read buffer contains one or more of
> the following structures [events].
...
> For performance reasons, it is recommended to use a large buffer size
> (for example, 4096 bytes), so that multiple events can be retrieved by a
> single read(2).

func getEvents was only processing one event from a buffer which
potentially contained more, leading to dropped events as observed with
a watch on /dev/loop0p{1,2} where frequently only one partition would
make it to the Incus device directory.

Unfortunately, just reading more events did not solve the issue. It
seems the watch callbacks spawned in goroutines would race and again
result in missing partitions in the device directory. I suspect the real
culprit behind issue lxc#2404 was not reading multiple events from the
buffer as is fixed here. To address the concern about kernel-dropped
events, I've added a warning here to diagnose but fanotify(7) seems to
indicate this will be rare (I certainly never saw it trigger):
> FAN_Q_OVERFLOW
>        The  event  queue  exceeded the limit of 16384 entries.

In testing I used a small 2-partition img file, two unix-block devices
on loop0p{1,2} with required=false, and following script:

devs=/var/lib/incus/devices/warpstation/unix.hotplug-dev-loop0p
loops() { echo ${devs}${1}.dev-loop0p$1; }
while true; do
  losetup -d /dev/loop0
  losetup -P /dev/loop0 loopit.img
  sleep 1
  if [ ! -e $(loops 1) ] || [ ! -e $(loops 2) ]; then
    ls -l ${devs}*
    break
  fi
done

On Incus 6.21 stable, it fails within the first few iterations
(increasing the timeout did not help either). With this patch it has not
once failed over several minutes.

Additionally, a potential fd leak is addressed for the file handle.

Signed-off-by: Gabriel Totev <[email protected]>
@stgraber
Copy link
Copy Markdown
Member

git diff --ignore-space-change

Haha, a lot better indeed!

@stgraber stgraber merged commit d5660ab into lxc:main Feb 22, 2026
53 of 56 checks passed
@zgttotev zgttotev deleted the hotplug branch February 23, 2026 16:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants