Skip to content

mount: list the current borg mounts when no MOUNTPOINT is given, fixes #2579 - #10514

Merged
ThomasWaldmann merged 1 commit into
borgbackup:masterfrom
ThomasWaldmann:mount-list-2579
Oct 12, 2026
Merged

ThomasWaldmann merged 1 commit into
borgbackup:masterfrom
ThomasWaldmann:mount-list-2579

Conversation

@ThomasWaldmann

@ThomasWaldmann ThomasWaldmann commented Oct 10, 2026 •

Copy link
Copy Markdown
Member

Fixes #2579.

borg mount without a MOUNTPOINT now prints the mountpoints of all file systems mounted by borg mount, one per line; --json gives a JSON list with mountpoint, source and fstype. This needs neither a repository nor FUSE (no passphrase prompt, no FUSE binding import). borgfs still requires the mountpoint.

Per-OS mount table findings (measured on the test boxes)

How a FUSE file system mounted with fsname=borgfs shows up, and which API enumerates it:

OS source fstype enumerate via
Linux borgfs fuse (now fuse.borgfs, see below) /proc/self/mountinfo
macOS (macFUSE) borgfs macfuse getmntinfo() via ctypes (getmntinfo$INODE64 on x86_64, 2168-byte struct statfs)
FreeBSD borgfs fusefs getmntinfo() via ctypes
NetBSD (librefuse/puffs) /dev/puffs puffs|borgfs (the fsname lands in the fstype) __getvfsstat90() via ctypes (the plain getvfsstat symbol is the pre-9 compat version and returns nothing)
illumos (OmniOS) borgfs fuse /etc/mnttab (5 tab-separated fields)
Windows (WinFsp) volume label (from volname) FUSE GetLogicalDriveStringsW + GetVolumeInformationW

Changes

  • new platform API platform.list_mounts() returning the mount table as MountEntry(source, fstype, mountpoint) tuples, implemented in the per-OS platform modules: /proc/self/mountinfo parser in linux.pyx, /etc/mnttab parser in solaris.py, getmntinfo() / getvfsstat() as Cython externs in darwin.pyx, freebsd.pyx and netbsd.pyx (the C headers provide the struct layouts and the getmntinfo$INODE64 / __getvfsstat90 symbol mapping), drive letter enumeration in windows.pyx; other platforms get an empty list with a warning.
  • vfs.is_borgfs_mount() holds the recognition rule in one place: source == "borgfs" or fstype.endswith("borgfs"); on Windows: fs name FUSE and a volume label containing borgfs.
  • Linux: parse_mount_options adds subtype=borgfs to the libfuse options, so the file system type is fuse.borgfs (matching the fstab examples in the docs) and a borg mount is recognized even with a user-supplied -o fsname=. Verified with llfuse on Debian 13; the llfuse / pyfuse3 / mfusepy CI jobs cover the three bindings. Not added on other platforms (FreeBSD ignores it).
  • Linux: list_mounts() raises a clear OSError ("cannot read /proc/self/mountinfo (is /proc mounted?)") when the file is unreadable, and the listing reports any enumerator OSError as a runtime error rather than a traceback.
  • tests: parser unit tests with captured mountinfo / mnttab lines, a live list_mounts() test, rule tests, output/JSON tests with a faked mount table, and a FUSE test that mounts a repo and checks it is listed (and no longer listed after unmounting).
  • docs: mount epilog, usage example, changelog.

Limitations

  • Windows: only mounts on a drive letter are listed. A directory mountpoint is a junction created by WinFsp and there is no API to enumerate those (documented in the epilog and the changelog).
  • NetBSD: a user-supplied -o fsname=other makes the fstype puffs|other, which is then not recognized (macOS and FreeBSD ignore such an override, Linux is covered by the subtype).
  • OpenBSD: not supported (warning + empty list). The kernel sets the mount source of every FUSE file system to the literal fusefs and ignores fsname, so a borg mount cannot be told apart from other FUSE mounts; borg mount is not usable there with packaged software anyway (no FUSE binding in the port or the ports tree).

The enumerators were run on the Debian 13, OmniOS r151058, FreeBSD 15.1 and NetBSD 11 test boxes (the FreeBSD and NetBSD extensions compiled there against the real headers) and on macOS 27 (where the end-to-end listing of a real borg mount, including a mountpoint with a space, was checked).

🤖 Generated with Claude Code

@codecov

codecov Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.54545% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.34%. Comparing base (4c563dc) to head (2155628).
⚠️ Report is 37 commits behind head on master.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/borg/archiver/mount_cmds.py 89.47% 2 Missing ⚠️
src/borg/platform/__init__.py 85.71% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master   #10514      +/-   ##
==========================================
+ Coverage   89.30%   89.34%   +0.03%     
==========================================
  Files         104      104              
  Lines       20027    20079      +52     
  Branches     3144     3152       +8     
==========================================
+ Hits        17886    17940      +54     
+ Misses       1482     1481       -1     
+ Partials      659      658       -1     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

@ThomasWaldmann
ThomasWaldmann force-pushed the mount-list-2579 branch 3 times, most recently from ff7d605 to 3996a22 Compare October 12, 2026 15:14
…borgbackup#2579

"borg mount" without a MOUNTPOINT now prints the mountpoints of all file systems
mounted by borg mount, one per line (--json: a JSON list with mountpoint, source
and fstype). This needs neither a repository nor FUSE. borgfs still requires the
mountpoint.

New platform API platform.list_mounts() returning the mount table as MountEntry
(source, fstype, mountpoint) tuples, implemented in the per-OS platform modules:

- Linux: /proc/self/mountinfo (fields after the "-" separator, octal escapes);
  raises a clear OSError if the file can not be read (/proc not mounted).
- illumos: /etc/mnttab
- macOS, FreeBSD: getmntinfo() as a Cython extern (the header maps it to
  getmntinfo$INODE64 on x86_64 macOS; sys/mount.h is self-contained on all
  supported FreeBSD releases, the sys/param.h / sys/ucred.h includes listed by
  getmntinfo(3) are not needed)
- NetBSD: getvfsstat() as a Cython extern (the header maps it to the libc
  symbol of the current struct layout, __getvfsstat90)
- Windows: GetLogicalDriveStringsW + GetVolumeInformationW, i.e. drive letter
  mounts only - directory mountpoints (junctions) can not be enumerated.
- other platforms (e.g. OpenBSD, whose kernel names every FUSE mount "fusefs"
  and ignores fsname): empty list, with a warning.

An OSError from the enumerator is reported as a runtime error by the listing,
not as a traceback.

vfs.is_borgfs_mount() has the recognition rule in one place: source "borgfs"
(Linux, macOS, FreeBSD, illumos) or an fstype ending in "borgfs" (NetBSD shows
"puffs|borgfs", Linux "fuse.borgfs"); on Windows the fs name "FUSE" with a
volume label containing "borgfs".

On Linux, parse_mount_options now also gives libfuse "subtype=borgfs", so the
file system type is "fuse.borgfs" (as in the fstab examples) and the mount is
recognized even if the user overrides fsname.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@ThomasWaldmann
ThomasWaldmann merged commit b51fefd into borgbackup:master Oct 12, 2026
28 checks passed
@ThomasWaldmann
ThomasWaldmann deleted the mount-list-2579 branch October 12, 2026 17:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature Request - List borgfs mounts

1 participant