Skip to content

VFS OnlineOnly pin state doesn't dehydrate on Linux — 34.0.2 / 3.16.7 #10691

Description

@r7db86mnwr-rgb

⚠️ Before submitting, please verify the following: ⚠️

Bug description

Bug: VFS pin state OnlineOnly does not trigger dehydration on Linux (suffix VFS)

Environment

  • Client versions tested: AppImage 34.0.2, Debian package 3.16.7-1~deb13u1
  • Desktop: KDE Plasma 6
  • VFS mode: Suffix-based virtual files (virtualFilesMode=suffix)
  • Server: Nextcloud 34.0.1 (self-hosted, Docker)
  • Sync folder: Mix of native storage and S3-backed external storage (Backblaze B2)

Summary

Setting a file's pin state to OnlineOnly (value 2) in the sync journal's flags table — either via the SocketAPI MAKE_ONLINE_ONLY command or by writing directly to the SQLite journal — does not cause the client to dehydrate the file, even after a full client restart. The file remains fully materialized on disk indefinitely.

This same mechanism (direct SQL write to flags.pinState = 2, followed by stopping and restarting the client) previously worked correctly on an Arch Linux + AUR nextcloud-client-git build, evicting large numbers of stale local files as expected.

Related issues

Steps to reproduce

  1. Enable suffix-based VFS on a Linux sync folder.
  2. Let a file fully hydrate locally (real file, not placeholder).
  3. Confirm no existing pin state: SELECT pinState FROM flags WHERE path = '<relpath>' returns no row.
  4. Set the pin state directly:
   INSERT OR REPLACE INTO flags(path, pinState) VALUES('<relpath>', 2);
  1. Stop the client (SIGTERM, wait, SIGKILL if needed), confirm it's fully exited.
  2. Restart the client (nextcloud --background).
  3. Wait for sync to settle (confirmed via debug log: local discovery completes, no pending jobs).
  4. Check the file on disk.

Expected behavior

After restart, the client's local discovery should see the OnlineOnly pin state, recognize a mismatch with the currently-hydrated file, and convert it to a placeholder (.nextcloud suffix, near-zero size), freeing the local disk space.

Which files are affected by this bug

GrumpyGeode/Photos/Frog.jpg (native storage) — confirmed pinState=2 in journal, file remained 448K on disk after restart and full sync. Also reproduced on GrumpyGeode/GrumpyGeode/Obsidian_GIT.txt (S3-backed external storage) with identical result.

Operating system

Linux

Which version of the operating system you are running.

Debian 13 (Trixie)

Installation method

Official Linux AppImage

Nextcloud Server version

34.0.1

Nextcloud Desktop Client version

34.0.2

Did this occur after an update or on a clean installation?

Clean desktop client installation

Are you using the Nextcloud Server Encryption module?

No

Are you using an external user-backend?

  • Default internal user-backend
  • LDAP or Active Directory
  • SSO - SAML
  • Other

Nextcloud Server logs

Additional info

Actual behavior

The file remains fully hydrated at full size indefinitely. Verified via:

$ sqlite3 journal.db "SELECT path, pinState FROM flags WHERE path = 'Photos/Frog.jpg';"
Photos/Frog.jpg|2
$ du -sh ~/Nextcloud/Photos/Frog.jpg
448K    /home/mani/Nextcloud/Photos/Frog.jpg

The pin state is correctly persisted (3,430 files were set in one run, confirmed via direct journal query), but no corresponding filesystem change occurs even after a clean restart and full local discovery pass.


Debug log evidence (SocketAPI path, --logdebug)

Sending MAKE_ONLINE_ONLY over the socket while the client is running registers the command and schedules a targeted local discovery for exactly that file:

[ SocketApi::slotReadSocket ]: Received SocketAPI message <-- "MAKE_ONLINE_ONLY:/home/mani/Nextcloud/Photos/Frog.jpg"
[ LocalDiscoveryTracker::addTouchedPath ]: inserted touched "Photos/Frog.jpg"
[ SyncEngine::setLocalDiscoveryOptions ]: paths to discover locally "Photos/Frog.jpg"
[ LocalDiscoveryTracker::startSyncPartialDiscovery ]: partial discovery with paths: QList("Photos/Frog.jpg")
[ ProcessDirectoryJob::processFileFinalize ]: discovered "Photos/Frog.jpg" CSYNC_INSTRUCTION_NONE OCC::SyncFileItem::None CSyncEnums::ItemTypeFile

The engine reaches a final decision of CSYNC_INSTRUCTION_NONE — no action — despite the file having just been flagged OnlineOnly. This happens whether the pin state was set via the socket command's own setPinState() call, or via direct SQL write before restart.

Separately, sending MAKE_ONLINE_ONLY via the socket API alone never resulted in a flags table row at all (SELECT COUNT(*) FROM flags returned 0 after multiple attempts on multiple files), suggesting SocketApi::command_MAKE_ONLINE_ONLY → Vfs::setPinState() may also be failing silently, independent of the restart-based issue above.


Question for maintainers

Is there a known regression in how PinState::OnlineOnly is reconciled during local discovery on Linux suffix-VFS, between the AUR git build (worked) and the 34.0.2 / 3.16.7 releases (don't)? Pointers into the reconciliation code path — I traced as far as SyncJournalDb::PinStateInterface and SocketApi::command_MAKE_ONLINE_ONLY but not where effectiveForPath()'s result should actually get acted on during discovery — would help.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions