Summary
Files whose name contains a backslash character (\, 0x5C) cause the FUSE open() syscall to deadlock indefinitely in the kernel page cache layer. The mount stays "healthy" from a small-block read perspective, but any process that attempts to open() these files (Plex Media Scanner, ffprobe, etc.) ends up in uninterruptible D state and can only be cleared by rebooting the host/LXC.
We hit this four times in 26 hours before tracing it to backslash-in-path. Surfaces a lot like #647 ("multi-segment sequential reads deadlock") but the trigger and the surviving kernel stack are different, and rolling back to the dev_20260529-0315 build that #647's reporter confirmed good did not fix it on our deployment.
Symptoms
ls, stat, directory listing on the mount: all fine.
open() on an affected file: never returns. Process state = DN, wchan = folio_wait_bit_common.
- altmount's own health-check (2% segment sample) reports the file as
healthy.
- altmount's
streaming_failure_count for the file stays at 0 because the read never reaches userspace.
- The wedge is not consumer-driven: any subsequent
open() on the same inode also blocks, even from a fresh process.
- Recovery: only by rebooting the host.
docker stop on the consumer cannot reap a D-state process; the kernel folio stays locked.
Kernel stack (live D-state process captured pre-reboot)
[<0>] folio_wait_bit_common+0x136/0x330
[<0>] __folio_lock+0x17/0x30
[<0>] invalidate_inode_pages2_range+0x1b2/0x440
[<0>] invalidate_inode_pages2+0x17/0x30
[<0>] fuse_open_common+0x1c3/0x210
[<0>] fuse_open+0x10/0x20
[<0>] do_dentry_open+0x21d/0x570
[<0>] vfs_open+0x33/0x50
[<0>] path_openat+0xb1c/0x1190
[<0>] do_filp_open+0xaf/0x170
[<0>] do_sys_openat2+0xb3/0xe0
[<0>] __x64_sys_open+0x6e/0xa0
The same stack reproduces across all wedged processes (we counted 8 in one cascade, each on a different file, all with \ in the path).
Reproducer
Some NZB releases contain Windows-style backslashes inside their RAR-extracted directory structure. After altmount unpacks them, the virtual paths look like:
/mnt/altmount/complete/movies/<Release.Name>/Subdir name\Filename.mkv
^
single literal backslash inside the filename
To reproduce:
- Locate any altmount-served file whose name contains
\ (we have ~78 of these across 38 release-dirs in our deployment).
- From any client that mounts the altmount FUSE (rclone-mount sidecar, in our case): run ffprobe, dd, or any binary that does
open(2) on the file.
- The process enters
DN state and never returns. kill -9 does not free it.
cat /proc/<pid>/stack shows the trace above.
Example paths
Three patterns we see in the wedge-triggering files (release-group names removed for brevity):
/mnt/altmount/complete/movies/<release>/<X>\<X>.mkv
/mnt/altmount/complete/movies/<release>/<hex>\<hex>\<filename>.mkv
/mnt/altmount/complete/movies/<release>/<dir-name>.mkv\<dir-name>.mkv
The third pattern (last path component being <name>.mkv\<name>.mkv, literally) makes me suspect the WebDAV path resolver and the FUSE page-cache layer disagree about whether they are looking at one file or a directory plus file.
Multiple release groups are involved, so it is not a single-uploader issue. It looks more like a class of older scene archives that were packed on Windows with backslashes inside their internal directory structure, and the structure survives through RAR extraction into altmount's virtual filesystem.
What we have ruled out
Workaround we deployed
Two layers:
- Quarantine on disk. Move the offending release-dirs out of the Sonarr/Radarr scan paths into a sibling quarantine directory. Plex/Radarr mark the items as unavailable on the next scan and stop launching
--analyze on them. Load returns to baseline within minutes.
- Radarr custom format. Added a custom format matching
\\ in release titles, scored -10000, applied to the relevant quality profiles with minFormatScore=0. Prevents the next import from putting these releases back into the library.
Both are workarounds. The actual fix belongs in altmount's path-handling layer somewhere between RAR extraction, WebDAV path emission, and FUSE response. A backslash in a filename is technically legal on Linux, but altmount could either normalize it on extraction (replace \ with / and split, or with _) or reject the file with a clean EIO at open() time instead of hanging the kernel folio.
Environment
- altmount image:
ghcr.io/javi11/altmount:dev_20260529-0315 (also reproduces on pinned-20260513)
- rclone-mount sidecar:
rclone/rclone:latest, --vfs-cache-mode=full, --timeout=2m, --vfs-read-chunk-streams=4
- Host: LXC on Proxmox PVE, Linux 6.8.12-16-pve, x86_64
- Docker with userns-remap,
cap_add: SYS_ADMIN, /dev/fuse
- Three NNTP providers
Happy to provide
- Full snapshot tarball (dmesg,
ps auxf, kernel-stack dump for all D-state procs, altmount.log tail). ~450 KB.
- Specific paths for clean repro (the release-dirs survive in our quarantine if you want to inspect over WebDAV).
- The Radarr custom format JSON and the daily scan script we deployed as defense layers.
Summary
Files whose name contains a backslash character (
\, 0x5C) cause the FUSEopen()syscall to deadlock indefinitely in the kernel page cache layer. The mount stays "healthy" from a small-block read perspective, but any process that attempts toopen()these files (Plex Media Scanner, ffprobe, etc.) ends up in uninterruptibleDstate and can only be cleared by rebooting the host/LXC.We hit this four times in 26 hours before tracing it to backslash-in-path. Surfaces a lot like #647 ("multi-segment sequential reads deadlock") but the trigger and the surviving kernel stack are different, and rolling back to the
dev_20260529-0315build that #647's reporter confirmed good did not fix it on our deployment.Symptoms
ls,stat, directory listing on the mount: all fine.open()on an affected file: never returns. Process state =DN, wchan =folio_wait_bit_common.healthy.streaming_failure_countfor the file stays at 0 because the read never reaches userspace.open()on the same inode also blocks, even from a fresh process.docker stopon the consumer cannot reap aD-state process; the kernel folio stays locked.Kernel stack (live D-state process captured pre-reboot)
The same stack reproduces across all wedged processes (we counted 8 in one cascade, each on a different file, all with
\in the path).Reproducer
Some NZB releases contain Windows-style backslashes inside their RAR-extracted directory structure. After altmount unpacks them, the virtual paths look like:
To reproduce:
\(we have ~78 of these across 38 release-dirs in our deployment).open(2)on the file.DNstate and never returns.kill -9does not free it.cat /proc/<pid>/stackshows the trace above.Example paths
Three patterns we see in the wedge-triggering files (release-group names removed for brevity):
The third pattern (last path component being
<name>.mkv\<name>.mkv, literally) makes me suspect the WebDAV path resolver and the FUSE page-cache layer disagree about whether they are looking at one file or a directory plus file.Multiple release groups are involved, so it is not a single-uploader issue. It looks more like a class of older scene archives that were packed on Windows with backslashes inside their internal directory structure, and the structure survives through RAR extraction into altmount's virtual filesystem.
What we have ruled out
pinned-20260513todev_20260529-0315(the known-good build per Regression (#629): FUSE multi-segment sequential reads deadlock → playback hangs (single reads OK, data fetchable) #647). The wedge still happens on the same files. The behavior predates feat(fuse): hardened async read-ahead buffer for smoother streaming #629.Workaround we deployed
Two layers:
--analyzeon them. Load returns to baseline within minutes.\\in release titles, scored -10000, applied to the relevant quality profiles withminFormatScore=0. Prevents the next import from putting these releases back into the library.Both are workarounds. The actual fix belongs in altmount's path-handling layer somewhere between RAR extraction, WebDAV path emission, and FUSE response. A backslash in a filename is technically legal on Linux, but altmount could either normalize it on extraction (replace
\with/and split, or with_) or reject the file with a cleanEIOat open() time instead of hanging the kernel folio.Environment
ghcr.io/javi11/altmount:dev_20260529-0315(also reproduces onpinned-20260513)rclone/rclone:latest,--vfs-cache-mode=full,--timeout=2m,--vfs-read-chunk-streams=4cap_add: SYS_ADMIN,/dev/fuseHappy to provide
ps auxf, kernel-stack dump for all D-state procs, altmount.log tail). ~450 KB.