Skip to content

Commit 49f0b54

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 cbc6b12 commit 49f0b54

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`].
@@ -494,7 +519,7 @@ impl<T: FileSystem + ?Sized> Tables<T> {
494519
freeze_fs: None,
495520
thaw_super: None,
496521
unfreeze_fs: None,
497-
statfs: None,
522+
statfs: Some(Self::statfs_callback),
498523
remount_fs: None,
499524
umount_begin: None,
500525
show_options: None,
@@ -512,6 +537,31 @@ impl<T: FileSystem + ?Sized> Tables<T> {
512537
shutdown: None,
513538
};
514539

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

517567
const XATTR_HANDLER: bindings::xattr_handler = bindings::xattr_handler {

0 commit comments

Comments
 (0)