Commit Graph
452 Commits
Author SHA1 Message Date
ferrumclaudepilgrimandNick Craig-Wood 2cec6065d3 local: make out of space errors fatal during multi-thread transfers 2026-09-08 16:35:36 +01:00
ferrumclaudepilgrimandNick Craig-Wood e724790620 vfs/vfscache: fix hang when the cache cleaner is disabled
KickCleaner sets the out of space flag, kicks the cleaner and then waits for
that flag to clear. Only the cleaner clears it, and the cleaner returns
immediately when the cache poll interval is not positive, so when it is
disabled nothing ever reads the kick or clears the flag and the caller waits
forever.

It now returns straight away in that case, under the same condition the
cleaner itself uses to decide it is disabled. Callers already retry a bounded
number of times and then report the error, which is the right outcome when
nothing is going to free space.
2026-09-08 16:35:36 +01:00
Dhevenddra K GandGitHub 3d7b101c7f docs: fix duplicated words in vfs and backend documentation 2026-09-05 17:53:08 +01:00
Vijay MisalandNick Craig-Wood efa5e8fcc1 vfscache: fix log message growing without bound on repeated write errors
Write() overwrote a successful write's nil error with the stale
lastErr returned by kickWaiters() once the downloader had recorded
too many errors. download() then wrapped that stale error again and
stored it back as the new lastErr, so every subsequent write added
another "vfs reader: failed to write to cache file:" prefix - fixes #4998
2026-08-27 12:10:25 +01:00
Nick Craig-Wood a017a54bef build: modernize with "go fix -waitgroupgo": use WaitGroup.Go 2026-08-21 12:23:31 +01:00
Nick Craig-Wood a64c0a0fde build: modernize with "go fix -rangeint": use range over int 2026-08-21 12:23:31 +01:00
Shantanav MukherjeeandGitHub 4f22d62c66 docs: clarify VFS cache age semantics 2026-08-18 09:49:42 +01:00
Hakan İSMAİLandNick Craig-Wood 30e79a017b serve, mountlib: test VFS release on shutdown and mount failure 2026-08-18 09:03:12 +01:00
DaveandNick Craig-Wood 6e0c71bd27 vfs/vfscache: fix reader deadlock when the item size drops below the read offset
_dispatchWaiters decided whether a waiter was satisfied by clipping its
range against dls.src.Size(), the size of the fs.Object snapshot taken
when the Downloaders was created. _ensureDownloader decided whether to
start a downloader from Item.FindMissing, which clips against
item.info.Size instead.

When item.info.Size dropped below the offset a waiter was parked on while
the source object still reported the full size, the two disagreed.
_ensureDownloader found nothing missing so it started no downloader, and
_dispatchWaiters found the range absent so it never released the waiter.
Nothing was downloaded and no error was produced, so the error count never
reached maxErrorCount and the waiter was never woken. The reader blocked
forever with nothing logged at any level.

Wake a waiter when FindMissing reports nothing left to download for it as
well as when its data has arrived. Since _ensureDownloader starts a
downloader only when FindMissing is non empty, a waiter with nothing
missing has nothing that could ever wake it.

Fixes #9769
2026-08-14 18:51:49 +02:00
RecoordinateandGitHub cfdc9d0558 docs: fix doubled words 2026-08-12 10:59:44 +01:00
Nick Craig-Wood 2f0657c35b vfs: add WriteFileHandle.CloseWithError to abandon streaming writes
Closing a streaming write handle sends a clean EOF to the backend
upload, so a writer which knows its data source failed part way through
had no way to stop the truncated file being stored as if it were
complete.

CloseWithError closes the handle failing the upload with the given
reason instead. EOF-like reasons are rewritten so the layers reading
the pipe can't mistake them for a clean end of stream and commit the
partial file.

Needed by serve s3 to abort interrupted PUTs - see #9718
2026-08-11 20:58:48 +01:00
Loi NguyenandNick Craig-Wood 1d03a77172 vfs: make poll shutdown lifecycle deterministic 2026-08-01 12:44:42 +01:00
Loi NguyenandNick Craig-Wood d5275c4ebb vfs: test poll interval update lifecycle 2026-08-01 12:44:42 +01:00
Loi NguyenandNick Craig-Wood f132aef295 vfs: synchronize poll updates with shutdown - fixes #9689 2026-08-01 12:44:42 +01:00
SillyZirandNick Craig-Wood 7804c1b315 serve nfs: fix EIO when creating symlinks with --vfs-links
The macOS NFS client sends SETATTR after SYMLINK, which arrives as
Chmod/Chown on the link path. These opened the target with vfs.Open,
which follows symlinks - a freshly created symlink usually dangles, so
the open failed with ENOENT, surfaced to the client as NFS3ERR_IO even
though the link was created.

Add path-based VFS.Chmod and VFS.Chown mirroring VFS.Chtimes. They do
not follow symlinks (lstat semantics, matching VFS.Stat) and return
ENOSYS when the node exists, since the VFS stores neither permissions
nor ownership; serve nfs calls them and masks ENOSYS as before.

Fixes #9627
2026-08-01 12:17:20 +01:00
Nick Craig-Wood 208d7df877 vfs: don't crash the process if a backend panics on a background goroutine GHSA-6jcg-q3wp-x2f4
The VFS calls backends from goroutines of its own. A panic on any of these
cannot be recovered. So a backend panicking on a single file killed the whole
process, taking down a mount or every user of a serve command, even for servers
such as serve http whose library recovers panics raised on its own request
goroutines.

Recover panics at those goroutines and log them with a stack trace. Where the
surrounding code already handles a failure, recover around the backend call
itself rather than the whole goroutine, so a panicking upload is retried like
any other failed upload and a panicking download is reported to the waiters,
instead of abandoning the work part way through and leaving the bookkeeping
inconsistent.

Addresses GHSA-6jcg-q3wp-x2f4
2026-07-31 13:21:59 +01:00
36ea20b0cc vfs: build the real uid/gid lookup on OpenBSD too
Mounted files showed up owned by 4294967295 (^uint32(0)) on OpenBSD.
vfsflags_unix.go, which calls unix.Geteuid()/unix.Getegid() to get the
real uid/gid, only builds for linux, darwin and freebsd; OpenBSD fell
through to vfsflags_non_unix.go's zero-value stub instead.

OpenBSD has no linux/darwin/freebsd-specific fields here, just the same
POSIX Geteuid/Getegid/Umask calls golang.org/x/sys/unix already ships
for openbsd on every arch, so this just adds openbsd to both build tags
rather than needing a separate file.

Cross-compiled for GOOS=openbsd (arm64, amd64) and go vet clean; ran the
existing vfs test suite on darwin, no regressions. Not yet verified on a
live OpenBSD mount, only that the right uid/gid syscalls now get called
in this codepath.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-30 19:54:16 +01:00
Nick Craig-Wood b6ffdfa8e6 vfs: rename aux.go to nodeaux.go as aux is a reserved file name on Windows
This commit introduced aux.go which unfortunately is illegal on windows.

e006d7c13f vfs: fix crash when multiple mounts or servers share the same VFS

Rename aux_test.go too to keep the pair together.
2026-07-27 16:35:08 +01:00
Nick Craig-Wood e006d7c13f vfs: fix crash when multiple mounts or servers share the same VFS
The VFS is shared between users with the same remote and options, for
example two mounts created over the rc, or a mount and an NFS server.

Each node has a single Sys() slot which mount, mount2 and serve nfs
all used to attach their per-node data. With a shared VFS the users
overwrote each other's data: at best churning the cached FUSE nodes,
and since the slot was an atomic.Value, panicking with "store of
inconsistently typed value" as soon as two users stored different
types on the same node.

This change gives each node auxiliary values keyed by owner, set with
SetAux and read with Aux, so each user of the VFS has an independent
slot. The mounts now cache their FUSE nodes under their own key,
leaving Sys - which is read through the os.FileInfo interface -
reserved for users like serve nfs which need to control what that
returns.

Nodes with nothing attached use less memory than before (one pointer
instead of an atomic.Value) and reads remain lock free.

Bug discovered while thinking about #9617
2026-07-27 14:55:20 +01:00
Nick Craig-Wood c851d4dec5 vfs: fix vfs cache writeback timer not being stopped when --transfers reached
When processItems filled the last free transfer slot it checked the
next queued item's expiry before the transfer limit, so if that
expiry was still fractionally in the future the timer was reset
instead of stopped. This caused intermittent failures in
TestWriteBackMaxQueue which asserts the timer is stopped once
--transfers uploads are in progress.

Check the transfer limit first so the timer is always stopped when
the transfer limit is reached. The timer is restarted when an upload
finishes so nothing stalls.

Also fix a typo in TestWriteBackMaxQueue which named every queued
item "number1".
2026-07-14 14:29:21 +01:00
Nick Craig-Wood 16e199067e vfs/vfscache: fix "invalid seek position" error when cache files larger than the remote
Previously if a cached file had grown larger than the remote object
and the cached range metadata was out of sync with the cache file
(e.g. after an unclean shutdown) - reloading the file failed with an
"invalid seek position" error. This aborted the writeback and left the
file inaccessible.

Rclone now recovers the bytes that are still available from the remote
and logs an ERROR that the local file is likely corrupted after an
interrupted upload.

See #9231.
2026-07-13 15:30:03 +01:00
Nick Craig-Wood 6e0cde076a vfs/vfscache: fix IO error by recreating the cache file if it has been removed
_createFile opened the cache file with O_RDWR but not O_CREATE, relying
on the file already existing. When the file had been removed underneath
rclone - either by _checkObject dropping a stale entry during open, or by
external deletion - the open failed and surfaced a hard "IO error" to the
application instead of recreating the file. Add O_CREATE so the cache
self-heals in that case.
2026-07-09 17:46:31 +01:00
Sandy LuppinoandNick Craig-Wood c1b5756eec vfs/vfstest: add Mknod test exercising all three mount backends
Mknod is now implemented by mount, mount2 and cmount, so exercise it from
the shared vfstest suite: create a regular file (S_IFREG) through the
mounted path and check it reads back as a 0-byte regular file. This is the
path the kernel NFS server drives when a client creates a file over an
exported mount.

Before this there was no shared coverage for Mknod; it now runs against
each backend via RunTests.

Suggested in #9548.

Signed-off-by: Sandy Luppino <s.luppino@opendrives.com>
2026-07-02 11:14:13 +01:00
Nick Craig-Wood 9728fa0ede vfs: fix hang reopening a file during the handle-caching grace period
When a cached file was closed, --vfs-handle-caching kept its handle and
downloaders alive for a grace period and closed them later from a timer.
The deferred close drops the item lock while tearing down the
downloaders, leaving the file handle open. A reopen landing in that
window saw no grace timer and a live handle, failed to create the cache
file with "internal error: didn't Close file" and removed the cache
file, which hung the application reopening the file.

Reopens now wait for an in-progress grace-period close to finish so they
start from a fully closed item.

See: https://forum.rclone.org/t/opening-a-recently-closed-and-cached-file-hangs-rclone/53986/
2026-06-30 20:30:49 +01:00
00bd00d83d mount2: fix empty directory listings on re-read
With cmd/mount2, reading a directory more than once returned the correct
entries on the first read but nothing on subsequent reads. Plain `ls`
triggers this: it does lseek(fd, 0, SEEK_SET) to rewind the directory
before a second getdents.

go-fuse v2.9.0 rewinds a directory stream by calling Seekdir on the
FileSeekdirer interface. dirStream did not implement it, so go-fuse
returned ENOTSUP and produced an empty listing on every read after the
first.

This implements Seekdir on dirStream: a rewind to offset 0 resets the
stream to the start, restoring correct listings on re-read. Non-zero
offsets are uncommon for in-memory listings and still return ENOTSUP,
matching go-fuse's own default. A compile-time interface assertion is
added so signature drift on future go-fuse updates is caught at build
time.

Before: second and subsequent reads of a directory returned no entries.
After: directories list correctly on every read.

See: https://github.com/hanwen/go-fuse/issues/549
Co-authored-by: Nick Craig-Wood <nick@craig-wood.com>
2026-06-01 12:06:03 +01:00
Lucky945HandNick Craig-Wood f7d371fc37 vfs/vfscache: fix silent write failure when mounting with remote:.
When mounting with 'remote:.' (dot notation for current directory),
the '.' is passed through toOSPath() which encodes it to full-width
'.' (U+FF0E) via EncodeDot. This caused the VFS cache data/meta root
to be written to a full-width-dot directory while the local cache
backend pointed to the canonicalized path, resulting in writes being
cached but never uploaded.

Fix by calling clean() on the relativeDirPath before toOSPath(),
so path.Clean() strips the trailing '/.' removing the dot before
encoding.
2026-05-18 18:34:55 +01:00
Nick Craig-Wood 6b67be9d48 mountlib: rc: fix mounts created with mountPoint "*" overwriting each other
On Windows, passing "*" as mountPoint to the mount/mount RC command
auto-assigns a drive letter (e.g. "Z:"), but the resolved letter was
never propagated back to mountlib. This caused liveMounts to be keyed
on the literal "*", breaking tracking of multiple mounts and making
unmount unreliable.

Change MountFn to return the actual mount point as an additional
return value. Update MountPoint.Mount() to store the resolved value,
and mountRc() to use it as the liveMounts key. The mount/mount RC
response now returns the actual mountPoint so callers can discover
which drive letter was assigned.
2026-04-27 15:09:14 +01:00
Nick Craig-Wood d2b8b73ea3 vfs/vfscache/downloaders: kick waiters periodically, not just once
The background kicker goroutine had a bare select outside a for loop,
so the 5s ticker fired at most once before the goroutine exited. The
intent was to run every 5s for the lifetime of the Downloaders.

This wraps the select in a for loop so the ticker fires repeatedly
until ctx is cancelled.

In practice this was benign because every downloader exit and every
successful Write already calls kickWaiters, so the background kicker
is only load-bearing when a waiter is queued, no downloader is
running, and _ensureDownloader failed transiently. In that state,
before this fix, the waiter would hang until another Download() call
or Close() arrived; now it gets retried every 5s and will either
recover or accumulate enough errors to trip maxErrorCount and error
out cleanly.
2026-04-27 15:08:33 +01:00
Nick Craig-Wood f191448b0d rc: flip auth default so all endpoints require auth unless opted out
Replace AuthRequired bool with NoAuth bool on the rc.Call struct and
flip the auth check logic. Previously endpoints were unauthenticated
by default and had to opt in with AuthRequired: true, which led to
security vulnerabilities when developers forgot to set the flag.

Now all endpoints require authentication by default. Only explicitly
safe read-only endpoints are marked with NoAuth: true:

- rc/noop
- rc/error
- rc/list
- core/version
- core/stats
- core/group-list
- core/transferred
- core/du
- cache/stats
- vfs/list
- vfs/stats
- vfs/queue
- job/status
- job/list

See GHSA-25qr-6mpr-f7qx, GHSA-jfwf-28xr-xw6q
2026-04-19 13:31:27 +01:00
Nick Craig-Wood 7b8994ab32 vfs: add context parameter to New() for config propagation
Add a ctx parameter to vfs.New() so callers can pass in context
carrying ConfigInfo and FilterInfo. The context is stripped of
cancellation but config and filter values are preserved into a fresh
background context.
2026-04-13 12:48:38 +01:00
Nick Craig-Wood 9f2edc3077 vfs: replace context.TODO/Background with stored VFS context
Add a ctx field to the VFS struct, initialized in New() from the
existing cancellable context. Propagate this through the cache
subsystem hierarchy.

This ensures proper context cancellation when a VFS shuts down, rather
than using disconnected context.TODO() or context.Background() calls
throughout and paves the way for VFS to have its own config.
2026-04-13 12:48:38 +01:00
Nick Craig-Wood 0b4c21fbda downloaders: fix flaky TestDownloaders/EnsureDownloader test
Replace racy assert.False/Sleep/assert.True pattern with
assert.Eventually which polls until the async download completes.
2026-04-09 17:00:45 +01:00
Nick Craig-Wood bfd650b428 vfscache: fix grace timer reusing stale fd after _checkObject removes cache file
Before this change when a cache item was in its grace period (with
HandleCaching) and the file is reopened, _checkObject runs before the
grace timer recovery check. If the remote object's fingerprint changed
_checkObject removes the cache file from disk. However the grace
recovery path still reused the now-stale fd pointing to a deleted
inode, skipping _createFile entirely. This left no cache file on disk,
causing cache.Exists() to return false and breaking
rename-while-writing logic.

Fix this by checking the cache file still exists before reusing the fd
in grace recovery. If the file was removed, close the stale fd and
downloaders and fall through to _createFile.

Also update the fingerprint in item.rename after setting the new object,
preventing unnecessary cache invalidation when a file is reopened after
a rename.

This was discovered in the integration tests on backends that update
modtime on rename (like mailru).
2026-04-09 12:49:21 +01:00
Nick Craig-Wood 1ac0c3eecb vfs: fix tests after --vfs-handle-caching
In this commit

0db3e7a2a0 vfs: fix slow nfs serve by adding --vfs-handle-caching

We added --vfs-handle-caching but unfortunately forgot to disable it
for the TestRWCacheUpdate test.
2026-04-07 23:27:25 +01:00
Nick Craig-Wood 0db3e7a2a0 vfs: fix slow nfs serve by adding --vfs-handle-caching
Add a configurable grace period (default 5s) that delays closing file
handles and downloaders when the last handle closes. If a new handle
opens within the grace period, it reuses the existing resources.

This fixes 40x performance degradation with serve nfs vs serve sftp
caused by go-nfs opening/reading/closing on every NFS READ RPC, which
destroyed read-ahead prefetch before it could accumulate.

The grace period only applies to non-dirty files so that writeback
proceeds immediately on close.

Fixes #9251
2026-04-03 11:10:50 +01:00
Nick Craig-Wood b2866f0291 build: modernize Go code with go fix for go1.25 2026-02-18 12:11:52 +00:00
Nick Craig-Wood 5c4af237e4 vfs: make mount tests run on OpenBSD 2026-01-29 10:24:33 +00:00
yyandGitHub b728929f44 docs: fix typos in comments and messages 2026-01-18 20:48:33 +01:00
albertony 059ad47336 docs: change syntax hightlighting for command examples from sh to console 2025-11-01 15:33:38 +01:00
Nick Craig-Wood e42fa9f92d vfs: remove unecessary import in tests to fix import cycles 2025-10-28 11:05:41 +00:00
Andrew GunnersonandNick Craig-Wood 0a82929b94 rc: fix name of "queue" JSON key in docs for vfs/cache
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
2025-10-27 13:28:24 +00:00
vastonusandGitHub c4eef3065f build: remove obsolete build tag 2025-10-21 18:56:06 +01:00
dougalanddougal 79281354c7 vfs: fix chunker integration test 2025-10-03 17:10:24 +01:00
dougalandNick Craig-Wood 8ed55c61e1 serve http: download folders as zip
Now folders can be downloaded as a zip. You can also use --disable-zip
to not show this.
2025-09-26 15:18:02 +01:00
Nick Craig-Wood 71b9b4ad7a build: use sequence Split introduced in go1.24 2025-09-15 12:45:57 +01:00
dougalandNick Craig-Wood a4962e21d1 vfs: fix SIGHUP killing serve instead of flushing directory caches
Before, rclone serve would crash when sent a SIGHUP which contradicts
the documentation - saying it should flush the directory caches.

Moved signal handling from the mount into the vfs layer, which now
handles SIGHUP on all uses of the VFS including mount and serve.

Fixes #8607
2025-09-01 13:15:11 +01:00
albertony 2e02d49578 docs: fix markdown lint issues in command docs 2025-08-26 12:04:00 +02:00
Nick Craig-Wood d9c227eff6 vfs: make integration TestDirEntryModTimeInvalidation test more reliable
Before this change it was not taking the Precision of the remote into account.
2025-07-06 14:35:16 +01:00
huanghaojunandGitHub 49f6ed5f5e vfs: fix inefficient directory caching when directory reads are slow
Before this change, when querying directories with large datasets, if
the query duration exceeded the directory cache expiration time, the
cache became invalid by the time results were retrieved. This means
every execution of `_readDir` triggers `_readDirFromEntries`,
resulting in prolonged processing times.

After this change we update the directory time with the time at the
end of the query.
2025-04-09 11:58:09 +01:00
Nick Craig-Wood 533c6438f3 vfs: add --vfs-metadata-extension to expose metadata sidecar files
This adds --vfs-metadata-extension which can be used to expose sidecar
files with file metadata in. These files don't exist in the listings
until they are accessed.
2025-04-07 13:41:29 +01:00