Skip to content

Commit 8518498

Browse files
wedsonafbrauner
authored andcommitted
rust: file: add Rust abstraction for struct file
This abstraction makes it possible to manipulate the open files for a process. The new `File` struct wraps the C `struct file`. When accessing it using the smart pointer `ARef<File>`, the pointer will own a reference count to the file. When accessing it as `&File`, then the reference does not own a refcount, but the borrow checker will ensure that the reference count does not hit zero while the `&File` is live. Since this is intended to manipulate the open files of a process, we introduce an `fget` constructor that corresponds to the C `fget` method. In future patches, it will become possible to create a new fd in a process and bind it to a `File`. Rust Binder will use these to send fds from one process to another. We also provide a method for accessing the file's flags. Rust Binder will use this to access the flags of the Binder fd to check whether the non-blocking flag is set, which affects what the Binder ioctl does. This introduces a struct for the EBADF error type, rather than just using the Error type directly. This has two advantages: * `File::fget` returns a `Result<ARef<File>, BadFdError>`, which the compiler will represent as a single pointer, with null being an error. This is possible because the compiler understands that `BadFdError` has only one possible value, and it also understands that the `ARef<File>` smart pointer is guaranteed non-null. * Additionally, we promise to users of the method that the method can only fail with EBADF, which means that they can rely on this promise without having to inspect its implementation. That said, there are also two disadvantages: * Defining additional error types involves boilerplate. * The question mark operator will only utilize the `From` trait once, which prevents you from using the question mark operator on `BadFdError` in methods that return some third error type that the kernel `Error` is convertible into. (However, it works fine in methods that return `Error`.) Signed-off-by: Wedson Almeida Filho <[email protected]> Co-developed-by: Daniel Xu <[email protected]> Signed-off-by: Daniel Xu <[email protected]> Co-developed-by: Alice Ryhl <[email protected]> Reviewed-by: Benno Lossin <[email protected]> Signed-off-by: Alice Ryhl <[email protected]> Link: https://lore.kernel.org/r/[email protected] Reviewed-by: Gary Guo <[email protected]> Signed-off-by: Christian Brauner <[email protected]>
1 parent 913f8cf commit 8518498

File tree

7 files changed

+406
-0
lines changed

7 files changed

+406
-0
lines changed

fs/file.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,6 +1123,13 @@ EXPORT_SYMBOL(task_lookup_next_fdget_rcu);
11231123
*
11241124
* The fput_needed flag returned by fget_light should be passed to the
11251125
* corresponding fput_light.
1126+
*
1127+
* (As an exception to rule 2, you can call filp_close between fget_light and
1128+
* fput_light provided that you capture a real refcount with get_file before
1129+
* the call to filp_close, and ensure that this real refcount is fput *after*
1130+
* the fput_light call.)
1131+
*
1132+
* See also the documentation in rust/kernel/file.rs.
11261133
*/
11271134
static unsigned long __fget_light(unsigned int fd, fmode_t mask)
11281135
{

rust/bindings/bindings_helper.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212
#include <linux/blkdev.h>
1313
#include <linux/errname.h>
1414
#include <linux/ethtool.h>
15+
#include <linux/file.h>
1516
#include <linux/firmware.h>
17+
#include <linux/fs.h>
1618
#include <linux/jiffies.h>
1719
#include <linux/mdio.h>
1820
#include <linux/phy.h>

rust/helpers/fs.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
/*
4+
* Copyright (C) 2024 Google LLC.
5+
*/
6+
7+
#include <linux/fs.h>
8+
9+
struct file *rust_helper_get_file(struct file *f)
10+
{
11+
return get_file(f);
12+
}

rust/helpers/helpers.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "build_assert.c"
1313
#include "build_bug.c"
1414
#include "err.c"
15+
#include "fs.c"
1516
#include "kunit.c"
1617
#include "mutex.c"
1718
#include "page.c"

rust/kernel/fs.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
//! Kernel file systems.
4+
//!
5+
//! C headers: [`include/linux/fs.h`](srctree/include/linux/fs.h)
6+
7+
pub mod file;
8+
pub use self::file::{File, LocalFile};

0 commit comments

Comments
 (0)