Skip to content

Commit 0d231e7

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 3caeee5 commit 0d231e7

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
@@ -55,6 +55,31 @@ pub trait FileSystem {
5555
fn read_xattr(_inode: &INode<Self>, _name: &CStr, _outbuf: &mut [u8]) -> Result<usize> {
5656
Err(EOPNOTSUPP)
5757
}
58+
59+
/// Get filesystem statistics.
60+
fn statfs(_sb: &SuperBlock<Self>) -> Result<Stat> {
61+
Err(ENOSYS)
62+
}
63+
}
64+
65+
/// File system stats.
66+
///
67+
/// A subset of C's `kstatfs`.
68+
pub struct Stat {
69+
/// Magic number of the file system.
70+
pub magic: u32,
71+
72+
/// The maximum length of a file name.
73+
pub namelen: i64,
74+
75+
/// Block size.
76+
pub bsize: i64,
77+
78+
/// Number of files in the file system.
79+
pub files: u64,
80+
81+
/// Number of blocks in the file system.
82+
pub blocks: u64,
5883
}
5984

6085
/// The types of directory entries reported by [`FileSystem::read_dir`].
@@ -505,7 +530,7 @@ impl<T: FileSystem + ?Sized> Tables<T> {
505530
freeze_fs: None,
506531
thaw_super: None,
507532
unfreeze_fs: None,
508-
statfs: None,
533+
statfs: Some(Self::statfs_callback),
509534
remount_fs: None,
510535
umount_begin: None,
511536
show_options: None,
@@ -523,6 +548,31 @@ impl<T: FileSystem + ?Sized> Tables<T> {
523548
shutdown: None,
524549
};
525550

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

528578
const XATTR_HANDLER: bindings::xattr_handler = bindings::xattr_handler {

0 commit comments

Comments
 (0)