Skip to content

Commit caf9b29

Browse files
committed
rust: mem_cache: introduce MemCache
This is just the basics of `kmem_cache` to be used in file systems for inodes. All dead-code annotations will be removed in the next commit. Signed-off-by: Wedson Almeida Filho <[email protected]>
1 parent a44bdcc commit caf9b29

File tree

4 files changed

+73
-0
lines changed

4 files changed

+73
-0
lines changed

rust/bindings/bindings_helper.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,7 @@
1717
const size_t BINDINGS_ARCH_SLAB_MINALIGN = ARCH_SLAB_MINALIGN;
1818
const gfp_t BINDINGS_GFP_KERNEL = GFP_KERNEL;
1919
const gfp_t BINDINGS___GFP_ZERO = __GFP_ZERO;
20+
21+
const slab_flags_t BINDINGS_SLAB_RECLAIM_ACCOUNT = SLAB_RECLAIM_ACCOUNT;
22+
const slab_flags_t BINDINGS_SLAB_MEM_SPREAD = SLAB_MEM_SPREAD;
23+
const slab_flags_t BINDINGS_SLAB_ACCOUNT = SLAB_ACCOUNT;

rust/bindings/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,7 @@ pub use bindings_raw::*;
5151

5252
pub const GFP_KERNEL: gfp_t = BINDINGS_GFP_KERNEL;
5353
pub const __GFP_ZERO: gfp_t = BINDINGS___GFP_ZERO;
54+
55+
pub const SLAB_RECLAIM_ACCOUNT: slab_flags_t = BINDINGS_SLAB_RECLAIM_ACCOUNT;
56+
pub const SLAB_MEM_SPREAD: slab_flags_t = BINDINGS_SLAB_MEM_SPREAD;
57+
pub const SLAB_ACCOUNT: slab_flags_t = BINDINGS_SLAB_ACCOUNT;

rust/kernel/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ pub mod init;
3838
pub mod ioctl;
3939
#[cfg(CONFIG_KUNIT)]
4040
pub mod kunit;
41+
pub mod mem_cache;
4142
pub mod prelude;
4243
pub mod print;
4344
mod static_assert;

rust/kernel/mem_cache.rs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
//! Kernel memory caches (kmem_cache).
4+
//!
5+
//! C headers: [`include/linux/slab.h`](../../include/linux/slab.h)
6+
7+
use crate::error::{code::*, Result};
8+
use crate::{bindings, str::CStr};
9+
use core::ptr;
10+
11+
/// A kernel memory cache.
12+
///
13+
/// This isn't ready to be made public yet because it only provides functionality useful for the
14+
/// allocation of inodes in file systems.
15+
pub(crate) struct MemCache {
16+
ptr: ptr::NonNull<bindings::kmem_cache>,
17+
}
18+
19+
impl MemCache {
20+
/// Allocates a new `kmem_cache` for type `T`.
21+
///
22+
/// `init` is called by the C code when entries are allocated.
23+
#[allow(dead_code)]
24+
pub(crate) fn try_new<T>(
25+
name: &'static CStr,
26+
init: Option<unsafe extern "C" fn(*mut core::ffi::c_void)>,
27+
) -> Result<Self> {
28+
// SAFETY: `name` is static, so always valid.
29+
let ptr = ptr::NonNull::new(unsafe {
30+
bindings::kmem_cache_create(
31+
name.as_char_ptr(),
32+
core::mem::size_of::<T>().try_into()?,
33+
core::mem::align_of::<T>().try_into()?,
34+
bindings::SLAB_RECLAIM_ACCOUNT | bindings::SLAB_MEM_SPREAD | bindings::SLAB_ACCOUNT,
35+
init,
36+
)
37+
})
38+
.ok_or(ENOMEM)?;
39+
40+
Ok(Self { ptr })
41+
}
42+
43+
/// Returns the pointer to the `kmem_cache` instance, or null if it's `None`.
44+
///
45+
/// This is a helper for functions like `alloc_inode_sb` where the cache is optional.
46+
#[allow(dead_code)]
47+
pub(crate) fn ptr(c: &Option<Self>) -> *mut bindings::kmem_cache {
48+
match c {
49+
Some(m) => m.ptr.as_ptr(),
50+
None => ptr::null_mut(),
51+
}
52+
}
53+
}
54+
55+
impl Drop for MemCache {
56+
fn drop(&mut self) {
57+
// SAFETY: Just an FFI call with no additional safety requirements.
58+
unsafe { bindings::rcu_barrier() };
59+
60+
// SAFETY: `ptr` was previously returned by successful call to `kmem_cache_create`, so it's
61+
// ok to destroy it here.
62+
unsafe { bindings::kmem_cache_destroy(self.ptr.as_ptr()) };
63+
}
64+
}

0 commit comments

Comments
 (0)