Skip to content

Commit 516d0e4

Browse files
committed
rust: fs: add basic support for fs buffer heads
Introduce the abstractions that will be used by modules to handle buffer heads, which will be used to access cached blocks from block devices. All dead-code annotations are removed in the next commit in the series. Signed-off-by: Wedson Almeida Filho <[email protected]>
1 parent 1cf6e5e commit 516d0e4

File tree

4 files changed

+80
-0
lines changed

4 files changed

+80
-0
lines changed

rust/bindings/bindings_helper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*/
88

99
#include <kunit/test.h>
10+
#include <linux/buffer_head.h>
1011
#include <linux/errname.h>
1112
#include <linux/fs.h>
1213
#include <linux/fs_context.h>

rust/helpers.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
*/
2222

2323
#include <kunit/test-bug.h>
24+
#include <linux/buffer_head.h>
2425
#include <linux/bug.h>
2526
#include <linux/build_bug.h>
2627
#include <linux/cacheflush.h>
@@ -250,6 +251,20 @@ unsigned int rust_helper_MKDEV(unsigned int major, unsigned int minor)
250251
}
251252
EXPORT_SYMBOL_GPL(rust_helper_MKDEV);
252253

254+
#ifdef CONFIG_BUFFER_HEAD
255+
void rust_helper_get_bh(struct buffer_head *bh)
256+
{
257+
get_bh(bh);
258+
}
259+
EXPORT_SYMBOL_GPL(rust_helper_get_bh);
260+
261+
void rust_helper_put_bh(struct buffer_head *bh)
262+
{
263+
put_bh(bh);
264+
}
265+
EXPORT_SYMBOL_GPL(rust_helper_put_bh);
266+
#endif
267+
253268
/*
254269
* `bindgen` binds the C `size_t` type as the Rust `usize` type, so we can
255270
* use it in contexts where Rust expects a `usize` like slice (array) indices.

rust/kernel/fs.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ use crate::{
1515
use core::{marker::PhantomData, marker::PhantomPinned, mem::ManuallyDrop, pin::Pin, ptr};
1616
use macros::{pin_data, pinned_drop};
1717

18+
#[cfg(CONFIG_BUFFER_HEAD)]
19+
pub mod buffer;
20+
1821
/// Maximum size of an inode.
1922
pub const MAX_LFS_FILESIZE: i64 = bindings::MAX_LFS_FILESIZE;
2023

rust/kernel/fs/buffer.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
//! File system buffers.
4+
//!
5+
//! C headers: [`include/linux/buffer_head.h`](../../../include/linux/buffer_head.h)
6+
7+
use crate::types::{ARef, AlwaysRefCounted, Opaque};
8+
use core::ptr;
9+
10+
/// Wraps the kernel's `struct buffer_head`.
11+
///
12+
/// # Invariants
13+
///
14+
/// Instances of this type are always ref-counted, that is, a call to `get_bh` ensures that the
15+
/// allocation remains valid at least until the matching call to `put_bh`.
16+
#[repr(transparent)]
17+
pub struct Head(Opaque<bindings::buffer_head>);
18+
19+
// SAFETY: The type invariants guarantee that `INode` is always ref-counted.
20+
unsafe impl AlwaysRefCounted for Head {
21+
fn inc_ref(&self) {
22+
// SAFETY: The existence of a shared reference means that the refcount is nonzero.
23+
unsafe { bindings::get_bh(self.0.get()) };
24+
}
25+
26+
unsafe fn dec_ref(obj: ptr::NonNull<Self>) {
27+
// SAFETY: The safety requirements guarantee that the refcount is nonzero.
28+
unsafe { bindings::put_bh(obj.cast().as_ptr()) }
29+
}
30+
}
31+
32+
impl Head {
33+
/// Returns the block data associated with the given buffer head.
34+
pub fn data(&self) -> &[u8] {
35+
let h = self.0.get();
36+
// SAFETY: The existence of a shared reference guarantees that the buffer head is
37+
// available and so we can access its contents.
38+
unsafe { core::slice::from_raw_parts((*h).b_data.cast(), (*h).b_size) }
39+
}
40+
}
41+
42+
/// A view of a buffer.
43+
///
44+
/// It may contain just a contiguous subset of the buffer.
45+
pub struct View {
46+
head: ARef<Head>,
47+
offset: usize,
48+
size: usize,
49+
}
50+
51+
impl View {
52+
#[allow(dead_code)]
53+
pub(crate) fn new(head: ARef<Head>, offset: usize, size: usize) -> Self {
54+
Self { head, size, offset }
55+
}
56+
57+
/// Returns the view of the buffer head.
58+
pub fn data(&self) -> &[u8] {
59+
&self.head.data()[self.offset..][..self.size]
60+
}
61+
}

0 commit comments

Comments
 (0)