Skip to content

Commit 3f94966

Browse files
committed
rust: fs: introduce FileSystem::statfs
Allow Rust file systems to expose their stats. `overlayfs` requires that this be implemented by all file systems that are part of an overlay. The planned file systems need to be overlayed with overlayfs, so they must be able to implement this. Signed-off-by: Wedson Almeida Filho <[email protected]>
1 parent ce0acb6 commit 3f94966

File tree

3 files changed

+53
-1
lines changed

3 files changed

+53
-1
lines changed

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

5580
/// The types of directory entries reported by [`FileSystem::read_dir`].
@@ -478,7 +503,7 @@ impl<T: FileSystem + ?Sized> Tables<T> {
478503
freeze_fs: None,
479504
thaw_super: None,
480505
unfreeze_fs: None,
481-
statfs: None,
506+
statfs: Some(Self::statfs_callback),
482507
remount_fs: None,
483508
umount_begin: None,
484509
show_options: None,
@@ -496,6 +521,31 @@ impl<T: FileSystem + ?Sized> Tables<T> {
496521
shutdown: None,
497522
};
498523

524+
unsafe extern "C" fn statfs_callback(
525+
dentry: *mut bindings::dentry,
526+
buf: *mut bindings::kstatfs,
527+
) -> core::ffi::c_int {
528+
from_result(|| {
529+
// SAFETY: The C API guarantees that `dentry` is valid for read. `d_sb` is
530+
// immutable, so it's safe to read it. The superblock is guaranteed to be valid dor
531+
// the duration of the call.
532+
let sb = unsafe { &*(*dentry).d_sb.cast::<SuperBlock<T>>() };
533+
let s = T::statfs(sb)?;
534+
535+
// SAFETY: The C API guarantees that `buf` is valid for read and write.
536+
let buf = unsafe { &mut *buf };
537+
buf.f_type = s.magic.into();
538+
buf.f_namelen = s.namelen;
539+
buf.f_bsize = s.bsize;
540+
buf.f_files = s.files;
541+
buf.f_blocks = s.blocks;
542+
buf.f_bfree = 0;
543+
buf.f_bavail = 0;
544+
buf.f_ffree = 0;
545+
Ok(0)
546+
})
547+
}
548+
499549
const XATTR_HANDLERS: [*const bindings::xattr_handler; 2] = [&Self::XATTR_HANDLER, ptr::null()];
500550

501551
const XATTR_HANDLER: bindings::xattr_handler = bindings::xattr_handler {

0 commit comments

Comments
 (0)