Skip to content

Commit ce0acb6

Browse files
committed
rust: fs: introduce FileSystem::read_xattr
Allow Rust file systems to expose xattrs associated with inodes. `overlayfs` uses an xattr to indicate that a directory is opaque (i.e., that lower layers should not be looked up). The planned file systems need to support opaque directories, so they must be able to implement this. Signed-off-by: Wedson Almeida Filho <[email protected]>
1 parent c02d2b9 commit ce0acb6

File tree

3 files changed

+46
-0
lines changed

3 files changed

+46
-0
lines changed

rust/bindings/bindings_helper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <linux/refcount.h>
1616
#include <linux/wait.h>
1717
#include <linux/sched.h>
18+
#include <linux/xattr.h>
1819

1920
/* `bindgen` gets confused at certain things. */
2021
const size_t BINDINGS_ARCH_SLAB_MINALIGN = ARCH_SLAB_MINALIGN;

rust/kernel/error.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ pub mod code {
8181
declare_err!(EIOCBQUEUED, "iocb queued, will get completion event.");
8282
declare_err!(ERECALLCONFLICT, "Conflict with recalled state.");
8383
declare_err!(ENOGRACE, "NFS file lock reclaim refused.");
84+
declare_err!(ENODATA, "No data available.");
85+
declare_err!(EOPNOTSUPP, "Operation not supported on transport endpoint.");
8486
}
8587

8688
/// Generic integer kernel error.

rust/kernel/fs.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,14 @@ pub trait FileSystem {
4242

4343
/// Reads the contents of the inode into the given folio.
4444
fn read_folio(inode: &INode<Self>, folio: LockedFolio<'_>) -> Result;
45+
46+
/// Reads an xattr.
47+
///
48+
/// Returns the number of bytes written to `outbuf`. If it is too small, returns the number of
49+
/// bytes needs to hold the attribute.
50+
fn read_xattr(_inode: &INode<Self>, _name: &CStr, _outbuf: &mut [u8]) -> Result<usize> {
51+
Err(EOPNOTSUPP)
52+
}
4553
}
4654

4755
/// The types of directory entries reported by [`FileSystem::read_dir`].
@@ -418,6 +426,7 @@ impl<T: FileSystem + ?Sized> Tables<T> {
418426

419427
sb.0.s_magic = params.magic as _;
420428
sb.0.s_op = &Tables::<T>::SUPER_BLOCK;
429+
sb.0.s_xattr = &Tables::<T>::XATTR_HANDLERS[0];
421430
sb.0.s_maxbytes = params.maxbytes;
422431
sb.0.s_time_gran = params.time_gran;
423432
sb.0.s_blocksize_bits = params.blocksize_bits;
@@ -487,6 +496,40 @@ impl<T: FileSystem + ?Sized> Tables<T> {
487496
shutdown: None,
488497
};
489498

499+
const XATTR_HANDLERS: [*const bindings::xattr_handler; 2] = [&Self::XATTR_HANDLER, ptr::null()];
500+
501+
const XATTR_HANDLER: bindings::xattr_handler = bindings::xattr_handler {
502+
name: ptr::null(),
503+
prefix: crate::c_str!("").as_char_ptr(),
504+
flags: 0,
505+
list: None,
506+
get: Some(Self::xattr_get_callback),
507+
set: None,
508+
};
509+
510+
unsafe extern "C" fn xattr_get_callback(
511+
_handler: *const bindings::xattr_handler,
512+
_dentry: *mut bindings::dentry,
513+
inode_ptr: *mut bindings::inode,
514+
name: *const core::ffi::c_char,
515+
buffer: *mut core::ffi::c_void,
516+
size: usize,
517+
) -> core::ffi::c_int {
518+
from_result(|| {
519+
// SAFETY: The C API guarantees that `inode_ptr` is a valid inode.
520+
let inode = unsafe { &*inode_ptr.cast::<INode<T>>() };
521+
522+
// SAFETY: The c API guarantees that `name` is a valid null-terminated string. It
523+
// also guarantees that it's valid for the duration of the callback.
524+
let name = unsafe { CStr::from_char_ptr(name) };
525+
526+
// SAFETY: The C API guarantees that `buffer` is at least `size` bytes in length.
527+
let buf = unsafe { core::slice::from_raw_parts_mut(buffer.cast(), size) };
528+
let len = T::read_xattr(inode, name, buf)?;
529+
Ok(len.try_into()?)
530+
})
531+
}
532+
490533
const DIR_FILE_OPERATIONS: bindings::file_operations = bindings::file_operations {
491534
owner: ptr::null_mut(),
492535
llseek: Some(bindings::generic_file_llseek),

0 commit comments

Comments
 (0)