Skip to content

Commit 8c3eaaf

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 c82f5e4 commit 8c3eaaf

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`].
@@ -500,7 +525,7 @@ impl<T: FileSystem + ?Sized> Tables<T> {
500525
freeze_fs: None,
501526
thaw_super: None,
502527
unfreeze_fs: None,
503-
statfs: None,
528+
statfs: Some(Self::statfs_callback),
504529
remount_fs: None,
505530
umount_begin: None,
506531
show_options: None,
@@ -518,6 +543,31 @@ impl<T: FileSystem + ?Sized> Tables<T> {
518543
shutdown: None,
519544
};
520545

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

523573
const XATTR_HANDLER: bindings::xattr_handler = bindings::xattr_handler {

0 commit comments

Comments
 (0)