Skip to content

Add Filesystem::syncfs() for FUSE_SYNCFS - #738

Merged
cberner merged 1 commit into
masterfrom
claude/github-issues-triage-dv6dhi
Aug 4, 2026
Merged

Add Filesystem::syncfs() for FUSE_SYNCFS#738
cberner merged 1 commit into
masterfrom
claude/github-issues-triage-dv6dhi

Conversation

@cberner

@cberner cberner commented Aug 4, 2026

Copy link
Copy Markdown
Owner

Fixes #359.

FUSE_SYNCFS is opcode 50, ABI 7.34, carrying struct fuse_syncfs_in { uint64_t padding; } and answered with an empty reply. fuser reports 7.44, so nothing needs version gating on the receive side. Adds the opcode, the argument struct, an Operation::SyncFs, the dispatch, and Filesystem::syncfs().

Leaving syncfs() unimplemented reports ENOSYS, which is what the unknown-opcode path already produced, and the kernel then clears fc->sync_fs and stops asking for the lifetime of the connection. So this changes nothing for a filesystem that does not want it.

One thing worth knowing before merging

The kernel only propagates syncfs(2) on fuseblk and virtiofs connections. fc->sync_fs is set in exactly two places -- fuse_fill_super_common() under if (ctx->is_bdev), and virtio_fs.c -- and fuse_sync_fs() returns 0 immediately when it is unset. fuser mounts filesystem type fuse, never fuseblk, so on a filesystem fuser mounts the kernel never sends this and syncfs(2) succeeds without a round trip.

That leaves one reachable path: a session built with Session::from_fd on a fuseblk or virtiofs connection. The trait method and the changelog both say so, so nobody implements it expecting it to fire on an ordinary mount.

It is still worth having -- it is protocol coverage, it is what the issue asked for, and from_fd is public API -- but it is not something I can demonstrate end to end, and I would rather you knew that than found it later.

Testing

ll::request::tests::syncfs and syncfs_without_its_argument, in the byte-level style of the existing request tests, for both endiannesses. They cover the parse and that a request whose header declares no argument is rejected rather than parsed. Confirmed the second fails if the argument fetch is dropped.

No e2e test, for the reason above: the kernel will not send this to anything fuser can mount, so a fuser-tests case would assert nothing.

cargo fmt, all three clippy invocations from make pre, cargo doc, cargo test --all with and without libfuse, the musl build, cargo check --target x86_64-apple-darwin --features=macos-no-mount, and make test_passthrough are green. Docker was unavailable here, so mount_tests/pjdfs_tests/xfstests did not run locally; this adds an opcode none of them exercise.

🤖 Generated with Claude Code

https://claude.ai/code/session_01H5akmePV1VnD9YRQLZH4gv


Generated by Claude Code

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 12cedba171

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/request.rs
The kernel sends this for syncfs(2), asking the filesystem to make everything
it holds durable. Without it fuser answered the opcode with ENOSYS from the
unknown-operation path, so a filesystem had no way to implement the call.

Leaving syncfs() unimplemented still reports ENOSYS, and the kernel then stops
sending it for the lifetime of the connection, so nothing changes for a
filesystem that does not want it.

SyncFs is deliberately not added to the list of operations exempt from the
SessionACL check. That list is for requests the kernel issues on its own
behalf with no caller; syncfs(2) has one, and its request carries that
caller's credentials like any other. Since every access decision fuser makes
rests on that, and it is easy to assume wrongly, a test now pins it down.

Note that the kernel only propagates syncfs(2) on fuseblk and virtiofs
connections - fc->sync_fs is set nowhere else - and fuser mounts neither. This
is therefore reachable only for a session built with Session::from_fd on such
a connection, which is what the trait method and the changelog say.

Fixes #359

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H5akmePV1VnD9YRQLZH4gv
@cberner
cberner force-pushed the claude/github-issues-triage-dv6dhi branch from 12cedba to 65d75fc Compare August 4, 2026 02:45
@cberner
cberner merged commit 2c3b9b5 into master Aug 4, 2026
9 checks passed
@cberner
cberner deleted the claude/github-issues-triage-dv6dhi branch August 4, 2026 03:14
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.

add FUSE_SYNCFS

2 participants