Skip to content

Commit 0cfce9e

Browse files
committed
rust: fs: introduce FileSystem::statfs
This allows file systems to expose their stats. overlayfs requires that this be implemented by all file systems that are part of an overlay. Signed-off-by: Wedson Almeida Filho <walmeida@microsoft.com>
1 parent d1367c9 commit 0cfce9e

3 files changed

Lines changed: 53 additions & 1 deletion

File tree

rust/bindings/bindings_helper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <linux/fs.h>
1212
#include <linux/fs_context.h>
1313
#include <linux/slab.h>
14+
#include <linux/statfs.h>
1415
#include <linux/pagemap.h>
1516
#include <linux/refcount.h>
1617
#include <linux/wait.h>

rust/kernel/error.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ pub mod code {
8383
declare_err!(ENOGRACE, "NFS file lock reclaim refused.");
8484
declare_err!(ENODATA, "No data available.");
8585
declare_err!(EOPNOTSUPP, "Operation not supported on transport endpoint.");
86+
declare_err!(ENOSYS, "Invalid system call number.");
8687
}
8788

8889
/// Generic integer kernel error.

rust/kernel/fs.rs

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,31 @@ pub trait FileSystem {
4444
fn read_xattr(_inode: &INode<Self>, _name: &CStr, _outbuf: &mut [u8]) -> Result<usize> {
4545
Err(EOPNOTSUPP)
4646
}
47+
48+
/// Get filesystem statistics.
49+
fn statfs(_sb: &SuperBlock<Self>) -> Result<Stat> {
50+
Err(ENOSYS)
51+
}
52+
}
53+
54+
/// File system stats.
55+
///
56+
/// A subset of C's `kstatfs`.
57+
pub struct Stat {
58+
/// Magic number of the file system.
59+
pub magic: u32,
60+
61+
/// The maximum length of a file name.
62+
pub namelen: i64,
63+
64+
/// Block size.
65+
pub bsize: i64,
66+
67+
/// Number of files in the file system.
68+
pub files: u64,
69+
70+
/// Number of blocks in the file system.
71+
pub blocks: u64,
4772
}
4873

4974
/// The types of directory entries reported by [`FileSystem::read_dir`].
@@ -497,7 +522,7 @@ impl<T: FileSystem + ?Sized> Tables<T> {
497522
freeze_fs: None,
498523
thaw_super: None,
499524
unfreeze_fs: None,
500-
statfs: None,
525+
statfs: Some(Self::statfs_callback),
501526
remount_fs: None,
502527
umount_begin: None,
503528
show_options: None,
@@ -515,6 +540,31 @@ impl<T: FileSystem + ?Sized> Tables<T> {
515540
shutdown: None,
516541
};
517542

543+
unsafe extern "C" fn statfs_callback(
544+
dentry: *mut bindings::dentry,
545+
buf: *mut bindings::kstatfs,
546+
) -> core::ffi::c_int {
547+
from_result(|| {
548+
// SAFETY: The C API guarantees that `dentry` is valid for read. `d_sb` is
549+
// immutable, so it's safe to read it. The superblock is guaranteed to be valid dor
550+
// the duration of the call.
551+
let sb = unsafe { &*(*dentry).d_sb.cast::<SuperBlock<T>>() };
552+
let s = T::statfs(sb)?;
553+
554+
// SAFETY: The C API guarantees that `buf` is valid for read and write.
555+
let buf = unsafe { &mut *buf };
556+
buf.f_type = s.magic.into();
557+
buf.f_namelen = s.namelen;
558+
buf.f_bsize = s.bsize;
559+
buf.f_files = s.files;
560+
buf.f_blocks = s.blocks;
561+
buf.f_bfree = 0;
562+
buf.f_bavail = 0;
563+
buf.f_ffree = 0;
564+
Ok(0)
565+
})
566+
}
567+
518568
const XATTR_HANDLERS: [*const bindings::xattr_handler; 2] = [&Self::XATTR_HANDLER, ptr::null()];
519569

520570
const XATTR_HANDLER: bindings::xattr_handler = bindings::xattr_handler {

0 commit comments

Comments
 (0)