From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [IPv6:2a01:7e0:0:424::9]) by lore.proxmox.com (Postfix) with ESMTPS id 7C16E1FF13F for ; Thu, 12 Feb 2026 08:09:59 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id B2EB76CF3; Thu, 12 Feb 2026 08:10:42 +0100 (CET) From: Kefu Chai To: pve-devel@lists.proxmox.com Subject: [PATCH proxmox-fuse-rs v1] Add statfs support to proxmox-fuse Date: Thu, 12 Feb 2026 15:05:47 +0800 Message-ID: <20260212071003.1544536-4-k.chai@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260212071003.1544536-1-k.chai@proxmox.com> References: <20260212071003.1544536-1-k.chai@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1770880151271 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.130 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Message-ID-Hash: DBULSOSRAMYA3ISEI7GU34H6UPHLOMG5 X-Message-ID-Hash: DBULSOSRAMYA3ISEI7GU34H6UPHLOMG5 X-MailFrom: k.chai@proxmox.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox VE development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: - Add fuse_reply_statfs FFI binding in sys.rs - Add Statfs request struct in requests.rs - Add Statfs variant to Request enum - Add statfs callback to FuseData - Add enable_statfs() method to FuseSessionBuilder This enables filesystems to handle statfs requests and return filesystem statistics. Signed-off-by: Kefu Chai --- examples/tmpfs/main.rs | 4 ++-- src/requests.rs | 24 ++++++++++++++++++++++++ src/session.rs | 17 +++++++++++++++++ src/sys.rs | 1 + 4 files changed, 44 insertions(+), 2 deletions(-) diff --git a/examples/tmpfs/main.rs b/examples/tmpfs/main.rs index f3f7d26..36db9e8 100644 --- a/examples/tmpfs/main.rs +++ b/examples/tmpfs/main.rs @@ -3,11 +3,11 @@ use std::ffi::OsStr; use std::path::Path; use std::{io, mem}; -use anyhow::{bail, format_err, Error}; +use anyhow::{Error, bail, format_err}; use futures::future::FutureExt; use futures::select; use futures::stream::TryStreamExt; -use tokio::signal::unix::{signal, SignalKind}; +use tokio::signal::unix::{SignalKind, signal}; use proxmox_fuse::requests::{self, FuseRequest, SetTime}; use proxmox_fuse::{EntryParam, Fuse, ReplyBufState, Request}; diff --git a/src/requests.rs b/src/requests.rs index d1846cc..458b956 100644 --- a/src/requests.rs +++ b/src/requests.rs @@ -106,6 +106,7 @@ pub enum Request { Forget(Forget), Getattr(Getattr), Setattr(Setattr), + Statfs(Statfs), Readdir(Readdir), ReaddirPlus(ReaddirPlus), Mkdir(Mkdir), @@ -144,6 +145,7 @@ impl FuseRequest for Request { Request::Lookup(r) => r.fail(errno), Request::Getattr(r) => r.fail(errno), Request::Setattr(r) => r.fail(errno), + Request::Statfs(r) => r.fail(errno), Request::Readdir(r) => r.fail(errno), Request::ReaddirPlus(r) => r.fail(errno), Request::Mkdir(r) => r.fail(errno), @@ -239,6 +241,28 @@ impl Getattr { } } +/// Get filesystem statistics. +/// +/// This is the equivalent of a `statfs` call. +#[derive(Debug)] +pub struct Statfs { + pub(crate) request: RequestGuard, + pub inode: u64, +} + +impl FuseRequest for Statfs { + fn fail(self, errno: libc::c_int) -> io::Result<()> { + reply_err(self.request, errno) + } +} + +impl Statfs { + /// Send a reply for a `Statfs` request. + pub fn reply(self, stbuf: &libc::statvfs) -> io::Result<()> { + reply_result!(self: sys::fuse_reply_statfs(self.request.raw, stbuf as *const _)) + } +} + /// Get the contents of a directory without changing any lookup counts. (Contrary to /// `ReaddirPlus`). #[derive(Debug)] diff --git a/src/session.rs b/src/session.rs index 62a8a9e..3e4841c 100644 --- a/src/session.rs +++ b/src/session.rs @@ -94,6 +94,17 @@ impl FuseData { })); } + extern "C" fn statfs(request: sys::Request, inode: u64) { + let fuse_data = unsafe { &*(sys::fuse_req_userdata(request) as *mut FuseData) }; + fuse_data + .pending_requests + .borrow_mut() + .push_back(Request::Statfs(requests::Statfs { + request: RequestGuard::from_raw(request), + inode, + })); + } + extern "C" fn readdir( request: sys::Request, inode: u64, @@ -547,6 +558,12 @@ impl FuseSessionBuilder { self } + /// Enable `Statfs` requests. + pub fn enable_statfs(mut self) -> Self { + self.operations.statfs = Some(FuseData::statfs); + self + } + /// Enable `Unlink` requests. pub fn enable_unlink(mut self) -> Self { self.operations.unlink = Some(FuseData::unlink); diff --git a/src/sys.rs b/src/sys.rs index 17a01de..186b0ec 100644 --- a/src/sys.rs +++ b/src/sys.rs @@ -77,6 +77,7 @@ unsafe extern "C" { pub fn fuse_reply_readlink(req: Request, link: StrPtr) -> c_int; pub fn fuse_reply_none(req: Request); pub fn fuse_reply_write(req: Request, count: libc::size_t) -> c_int; + pub fn fuse_reply_statfs(req: Request, stbuf: *const libc::statvfs) -> c_int; pub fn fuse_req_userdata(req: Request) -> MutPtr; pub fn fuse_add_direntry_plus(req: Request, buf: MutStrPtr, bufsize: size_t, name: StrPtr, stbuf: Option<&EntryParam>, off: c_int) -> size_t; pub fn fuse_add_direntry(req: Request, buf: MutStrPtr, bufsize: size_t, name: StrPtr, stbuf: Option<&libc::stat>, off: c_int) -> size_t; -- 2.47.3