Skip to content

Commit 727b01e

Browse files
hoshinolinajannau
authored andcommitted
rust: xarray: Add an abstraction for XArray
The XArray is an abstract data type which behaves like a very large array of pointers. Add a Rust abstraction for this data type. The initial implementation uses explicit locking on get operations and returns a guard which blocks mutation, ensuring that the referenced object remains alive. To avoid excessive serialization, users are expected to use an inner type that can be efficiently cloned (such as Arc<T>), and eagerly clone and drop the guard to unblock other users after a lookup. Future variants may support using RCU instead to avoid mutex locking. This abstraction also introduces a reservation mechanism, which can be used by alloc-capable XArrays to reserve a free slot without immediately filling it, and then do so at a later time. If the reservation is dropped without being filled, the slot is freed again for other users, which eliminates the need for explicit cleanup code. Signed-off-by: Asahi Lina <lina@asahilina.net> --- Hi everyone! This abstraction is part of the set of dependencies for the drm/asahi Apple M1/M2 GPU driver. The branch at [1] contains the full series of patches rebased on upstream leading to the complete driver, for reference on how it is intended to be used. Thank you everyone who helped review this on GitHub [2]! I hope I didn't forget any CCs... Note that I dropped the convenience `Deref` impl for `Guard`, since I couldn't figure out how to do it safely. Suggestions welcome, or we can leave it for a future improvement ^^ [1] https://github.com/AsahiLinux/linux/tree/gpu/rebase-20230224 [2] Rust-for-Linux#952 Changes in v3: - Updated to the error v2/v3 series API. - Renamed `err` to `ret` for consistency with the other instance. - Link to v2: https://lore.kernel.org/r/20230224-rust-xarray-v2-1-4eeb0134944c@asahilina.net Changes in v2: - Added Pin requirement for all XArray operations, to close a soundness hole due to the lock in the XArray (locks are not safe to move while locked). Creation does not require pinning in place, since the lock cannot be acquired at that point. - Added safety note to Drop impl about why we don't need to do the lock unlock dance to ensure soundness in case of a dropped lock guard. - Downstream drm/asahi driver was also rebased on this version to prove it works (previously it was still on a pre-v1 version). - This still depends on the Error series (v1). v2 of that will need a trivial rename of Error::from_kernel_errno -> Error::from_errno. If this version of XArray ends up looking good, I'll send a trivial v4 of XArray with the rename, after sending the v2 of the Error series. - Link to v1: https://lore.kernel.org/r/20230224-rust-xarray-v1-1-80f0904ce5d3@asahilina.net
1 parent 0c246c5 commit 727b01e

5 files changed

Lines changed: 392 additions & 0 deletions

File tree

rust/bindings/bindings_helper.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include <linux/tracepoint.h>
4343
#include <linux/wait.h>
4444
#include <linux/workqueue.h>
45+
#include <linux/xarray.h>
4546
#include <trace/events/rust_sample.h>
4647

4748
#if defined(CONFIG_DRM_PANIC_SCREEN_QR_CODE)
@@ -60,3 +61,19 @@ const gfp_t RUST_CONST_HELPER___GFP_ZERO = __GFP_ZERO;
6061
const gfp_t RUST_CONST_HELPER___GFP_HIGHMEM = ___GFP_HIGHMEM;
6162
const gfp_t RUST_CONST_HELPER___GFP_NOWARN = ___GFP_NOWARN;
6263
const blk_features_t RUST_CONST_HELPER_BLK_FEAT_ROTATIONAL = BLK_FEAT_ROTATIONAL;
64+
65+
const gfp_t BINDINGS_XA_FLAGS_LOCK_IRQ = XA_FLAGS_LOCK_IRQ;
66+
const gfp_t BINDINGS_XA_FLAGS_LOCK_BH = XA_FLAGS_LOCK_BH;
67+
const gfp_t BINDINGS_XA_FLAGS_TRACK_FREE = XA_FLAGS_TRACK_FREE;
68+
const gfp_t BINDINGS_XA_FLAGS_ZERO_BUSY = XA_FLAGS_ZERO_BUSY;
69+
const gfp_t BINDINGS_XA_FLAGS_ALLOC_WRAPPED = XA_FLAGS_ALLOC_WRAPPED;
70+
const gfp_t BINDINGS_XA_FLAGS_ACCOUNT = XA_FLAGS_ACCOUNT;
71+
const gfp_t BINDINGS_XA_FLAGS_ALLOC = XA_FLAGS_ALLOC;
72+
const gfp_t BINDINGS_XA_FLAGS_ALLOC1 = XA_FLAGS_ALLOC1;
73+
74+
const xa_mark_t BINDINGS_XA_MARK_0 = XA_MARK_0;
75+
const xa_mark_t BINDINGS_XA_MARK_1 = XA_MARK_1;
76+
const xa_mark_t BINDINGS_XA_MARK_2 = XA_MARK_2;
77+
const xa_mark_t BINDINGS_XA_PRESENT = XA_PRESENT;
78+
const xa_mark_t BINDINGS_XA_MARK_MAX = XA_MARK_MAX;
79+
const xa_mark_t BINDINGS_XA_FREE_MARK = XA_FREE_MARK;

rust/helpers/helpers.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,4 @@
4040
#include "vmalloc.c"
4141
#include "wait.c"
4242
#include "workqueue.c"
43+
#include "xarray.c"

rust/helpers/xarray.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
2+
// SPDX-License-Identifier: GPL-2.0
3+
4+
#include <linux/xarray.h>
5+
6+
void rust_helper_xa_init_flags(struct xarray *xa, gfp_t flags)
7+
{
8+
xa_init_flags(xa, flags);
9+
}
10+
11+
bool rust_helper_xa_empty(struct xarray *xa)
12+
{
13+
return xa_empty(xa);
14+
}
15+
16+
int rust_helper_xa_alloc(struct xarray *xa, u32 *id, void *entry, struct xa_limit limit, gfp_t gfp)
17+
{
18+
return xa_alloc(xa, id, entry, limit, gfp);
19+
}
20+
21+
void rust_helper_xa_lock(struct xarray *xa)
22+
{
23+
xa_lock(xa);
24+
}
25+
26+
void rust_helper_xa_unlock(struct xarray *xa)
27+
{
28+
xa_unlock(xa);
29+
}
30+
31+
int rust_helper_xa_err(void *entry)
32+
{
33+
return xa_err(entry);
34+
}

rust/kernel/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ pub mod transmute;
9393
pub mod types;
9494
pub mod uaccess;
9595
pub mod workqueue;
96+
pub mod xarray;
9697

9798
#[doc(hidden)]
9899
pub use bindings;

0 commit comments

Comments
 (0)