Skip to content
daniel@cosenza:~/blog
WSLDeep Dive August 6, 2026 2 min read

How WSL Bridges Two Completely Different Filesystems

Linux and Windows filesystems handle permissions, case sensitivity, and paths in fundamentally different ways. WSL's cross-OS file access works by translating between them at the protocol level — and that translation has real performance costs.

Being able to run explorer.exe . from a Linux shell and have Windows Explorer open the current Linux directory feels seamless — underneath, it’s bridging two filesystems with genuinely different semantics, and that bridging isn’t free.

The two directions of access, and why they’re not symmetric

Accessing Windows files from Linux (via /mnt/c/...) and accessing Linux files from Windows (via the \\wsl$\ network path) are implemented differently, and perform differently, because the “native” filesystem on each side has fundamentally different characteristics the other side has to accommodate.

Why Linux-native files perform better than /mnt/c access

WSL2’s Linux filesystem lives inside the lightweight VM on a virtual disk formatted as ext4 — genuinely native Linux filesystem performance for anything staying within that Linux-side filesystem. Accessing Windows files from /mnt/c instead, goes through a 9P protocol bridge to the Windows host’s own NTFS filesystem, adding real per-operation overhead compared to native ext4 access.

Why this specific direction is slower, concretely

Every file operation crossing from Linux to /mnt/c has to translate Linux filesystem semantics (permissions bits, symlinks, case-sensitive filenames) into NTFS’s different semantics, over the 9P protocol connection to the Windows host — for workloads doing large numbers of small file operations (like node_modules-heavy JavaScript projects), this overhead compounds into a genuinely noticeable slowdown compared to keeping the same project entirely on the Linux-native filesystem.

The other direction: accessing WSL files from Windows

Windows accesses WSL2’s Linux filesystem through the \\wsl$\ (or newer \\wsl.localhost\) network path, which Windows treats similarly to any other network share — convenient for occasionally reaching into a Linux project from Windows tools, but not the path you’d want for sustained, intensive file operations from the Windows side either.

The practical rule this leads to

The consistent, practical guidance from Microsoft’s own WSL documentation is: keep a project’s files on the filesystem matching whichever OS’s tools you’re using most intensively — a Node.js or Python project you’re actively building and running from the Linux side belongs on the Linux-native filesystem (~/projects/, not /mnt/c/Users/.../projects/), even if you occasionally open individual files from Windows-side tools.

Why case sensitivity is a frequent, specific gotcha

Linux filesystems are case-sensitive by default (File.txt and file.txt are different files); NTFS is case-insensitive by default. This mismatch occasionally surfaces as confusing behavior — a Linux tool creating two files that Windows sees as a naming conflict, or a Windows-side tool failing to find a file due to a case mismatch that Linux tooling wouldn’t have cared about.

Why understanding this bridge matters beyond just performance

Beyond raw speed, understanding that /mnt/c and \\wsl$\ are genuinely different access paths, going through genuinely different translation layers, explains a range of WSL behavior that otherwise looks inconsistent — from performance differences to permission-bit oddities to occasional case-sensitivity surprises, all tracing back to the same underlying reality: two different filesystems, with different rules, being bridged rather than unified.