Skip to content

Commit f5535d7

Browse files
DarksonnYuryNorov
authored andcommitted
rust: bitmap: add MAX_LEN and MAX_INLINE_LEN constants
To avoid hard-coding these values in drivers, define constants for them that drivers can reference. Also, update all instances in bitmap.rs and id_pool.rs that use these values to use the new constants. Signed-off-by: Alice Ryhl <aliceryhl@google.com> Reviewed-by: Burak Emir <bqe@google.com> Signed-off-by: Yury Norov (NVIDIA) <yury.norov@gmail.com>
1 parent 4bd68e4 commit f5535d7

2 files changed

Lines changed: 41 additions & 31 deletions

File tree

rust/kernel/bitmap.rs

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ use crate::bindings;
1212
use crate::pr_err;
1313
use core::ptr::NonNull;
1414

15-
const BITS_PER_LONG: usize = bindings::BITS_PER_LONG as usize;
16-
1715
/// Represents a C bitmap. Wraps underlying C bitmap API.
1816
///
1917
/// # Invariants
@@ -149,22 +147,22 @@ macro_rules! bitmap_assert_return {
149147
///
150148
/// # Invariants
151149
///
152-
/// * `nbits` is `<= i32::MAX` and never changes.
153-
/// * if `nbits <= bindings::BITS_PER_LONG`, then `repr` is a `usize`.
150+
/// * `nbits` is `<= MAX_LEN`.
151+
/// * if `nbits <= MAX_INLINE_LEN`, then `repr` is a `usize`.
154152
/// * otherwise, `repr` holds a non-null pointer to an initialized
155153
/// array of `unsigned long` that is large enough to hold `nbits` bits.
156154
pub struct BitmapVec {
157155
/// Representation of bitmap.
158156
repr: BitmapRepr,
159-
/// Length of this bitmap. Must be `<= i32::MAX`.
157+
/// Length of this bitmap. Must be `<= MAX_LEN`.
160158
nbits: usize,
161159
}
162160

163161
impl core::ops::Deref for BitmapVec {
164162
type Target = Bitmap;
165163

166164
fn deref(&self) -> &Bitmap {
167-
let ptr = if self.nbits <= BITS_PER_LONG {
165+
let ptr = if self.nbits <= BitmapVec::MAX_INLINE_LEN {
168166
// SAFETY: Bitmap is represented inline.
169167
#[allow(unused_unsafe, reason = "Safe since Rust 1.92.0")]
170168
unsafe {
@@ -183,7 +181,7 @@ impl core::ops::Deref for BitmapVec {
183181

184182
impl core::ops::DerefMut for BitmapVec {
185183
fn deref_mut(&mut self) -> &mut Bitmap {
186-
let ptr = if self.nbits <= BITS_PER_LONG {
184+
let ptr = if self.nbits <= BitmapVec::MAX_INLINE_LEN {
187185
// SAFETY: Bitmap is represented inline.
188186
#[allow(unused_unsafe, reason = "Safe since Rust 1.92.0")]
189187
unsafe {
@@ -213,7 +211,7 @@ unsafe impl Sync for BitmapVec {}
213211

214212
impl Drop for BitmapVec {
215213
fn drop(&mut self) {
216-
if self.nbits <= BITS_PER_LONG {
214+
if self.nbits <= BitmapVec::MAX_INLINE_LEN {
217215
return;
218216
}
219217
// SAFETY: `self.ptr` was returned by the C `bitmap_zalloc`.
@@ -226,23 +224,29 @@ impl Drop for BitmapVec {
226224
}
227225

228226
impl BitmapVec {
227+
/// The maximum possible length of a `BitmapVec`.
228+
pub const MAX_LEN: usize = i32::MAX as usize;
229+
230+
/// The maximum length that uses the inline representation.
231+
pub const MAX_INLINE_LEN: usize = usize::BITS as usize;
232+
229233
/// Constructs a new [`BitmapVec`].
230234
///
231235
/// Fails with [`AllocError`] when the [`BitmapVec`] could not be allocated. This
232-
/// includes the case when `nbits` is greater than `i32::MAX`.
236+
/// includes the case when `nbits` is greater than `MAX_LEN`.
233237
#[inline]
234238
pub fn new(nbits: usize, flags: Flags) -> Result<Self, AllocError> {
235-
if nbits <= BITS_PER_LONG {
239+
if nbits <= BitmapVec::MAX_INLINE_LEN {
236240
return Ok(BitmapVec {
237241
repr: BitmapRepr { bitmap: 0 },
238242
nbits,
239243
});
240244
}
241-
if nbits > i32::MAX.try_into().unwrap() {
245+
if nbits > Self::MAX_LEN {
242246
return Err(AllocError);
243247
}
244248
let nbits_u32 = u32::try_from(nbits).unwrap();
245-
// SAFETY: `BITS_PER_LONG < nbits` and `nbits <= i32::MAX`.
249+
// SAFETY: `MAX_INLINE_LEN < nbits` and `nbits <= MAX_LEN`.
246250
let ptr = unsafe { bindings::bitmap_zalloc(nbits_u32, flags.as_raw()) };
247251
let ptr = NonNull::new(ptr).ok_or(AllocError)?;
248252
// INVARIANT: `ptr` returned by C `bitmap_zalloc` and `nbits` checked.
@@ -495,9 +499,10 @@ mod tests {
495499
#[test]
496500
fn bitmap_borrow() {
497501
let fake_bitmap: [usize; 2] = [0, 0];
502+
let fake_bitmap_len = 2 * usize::BITS as usize;
498503
// SAFETY: `fake_c_bitmap` is an array of expected length.
499-
let b = unsafe { Bitmap::from_raw(fake_bitmap.as_ptr(), 2 * BITS_PER_LONG) };
500-
assert_eq!(2 * BITS_PER_LONG, b.len());
504+
let b = unsafe { Bitmap::from_raw(fake_bitmap.as_ptr(), fake_bitmap_len) };
505+
assert_eq!(fake_bitmap_len, b.len());
501506
assert_eq!(None, b.next_bit(0));
502507
}
503508

rust/kernel/id_pool.rs

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
use crate::alloc::{AllocError, Flags};
88
use crate::bitmap::BitmapVec;
99

10-
const BITS_PER_LONG: usize = bindings::BITS_PER_LONG as usize;
11-
1210
/// Represents a dynamic ID pool backed by a [`BitmapVec`].
1311
///
1412
/// Clients acquire and release IDs from unset bits in a bitmap.
@@ -97,13 +95,12 @@ impl ReallocRequest {
9795
impl IdPool {
9896
/// Constructs a new [`IdPool`].
9997
///
100-
/// A capacity below [`BITS_PER_LONG`] is adjusted to
101-
/// [`BITS_PER_LONG`].
98+
/// A capacity below [`MAX_INLINE_LEN`] is adjusted to [`MAX_INLINE_LEN`].
10299
///
103-
/// [`BITS_PER_LONG`]: srctree/include/asm-generic/bitsperlong.h
100+
/// [`MAX_INLINE_LEN`]: BitmapVec::MAX_INLINE_LEN
104101
#[inline]
105102
pub fn new(num_ids: usize, flags: Flags) -> Result<Self, AllocError> {
106-
let num_ids = core::cmp::max(num_ids, BITS_PER_LONG);
103+
let num_ids = usize::max(num_ids, BitmapVec::MAX_INLINE_LEN);
107104
let map = BitmapVec::new(num_ids, flags)?;
108105
Ok(Self { map })
109106
}
@@ -116,28 +113,34 @@ impl IdPool {
116113

117114
/// Returns a [`ReallocRequest`] if the [`IdPool`] can be shrunk, [`None`] otherwise.
118115
///
119-
/// The capacity of an [`IdPool`] cannot be shrunk below [`BITS_PER_LONG`].
116+
/// The capacity of an [`IdPool`] cannot be shrunk below [`MAX_INLINE_LEN`].
120117
///
121-
/// [`BITS_PER_LONG`]: srctree/include/asm-generic/bitsperlong.h
118+
/// [`MAX_INLINE_LEN`]: BitmapVec::MAX_INLINE_LEN
122119
///
123120
/// # Examples
124121
///
125122
/// ```
126-
/// use kernel::alloc::{AllocError, flags::GFP_KERNEL};
127-
/// use kernel::id_pool::{ReallocRequest, IdPool};
123+
/// use kernel::{
124+
/// alloc::AllocError,
125+
/// bitmap::BitmapVec,
126+
/// id_pool::{
127+
/// IdPool,
128+
/// ReallocRequest,
129+
/// },
130+
/// };
128131
///
129132
/// let mut pool = IdPool::new(1024, GFP_KERNEL)?;
130133
/// let alloc_request = pool.shrink_request().ok_or(AllocError)?;
131134
/// let resizer = alloc_request.realloc(GFP_KERNEL)?;
132135
/// pool.shrink(resizer);
133-
/// assert_eq!(pool.capacity(), kernel::bindings::BITS_PER_LONG as usize);
136+
/// assert_eq!(pool.capacity(), BitmapVec::MAX_INLINE_LEN);
134137
/// # Ok::<(), AllocError>(())
135138
/// ```
136139
#[inline]
137140
pub fn shrink_request(&self) -> Option<ReallocRequest> {
138141
let cap = self.capacity();
139-
// Shrinking below [`BITS_PER_LONG`] is never possible.
140-
if cap <= BITS_PER_LONG {
142+
// Shrinking below `MAX_INLINE_LEN` is never possible.
143+
if cap <= BitmapVec::MAX_INLINE_LEN {
141144
return None;
142145
}
143146
// Determine if the bitmap can shrink based on the position of
@@ -146,13 +149,13 @@ impl IdPool {
146149
// bitmap should shrink to half its current size.
147150
let Some(bit) = self.map.last_bit() else {
148151
return Some(ReallocRequest {
149-
num_ids: BITS_PER_LONG,
152+
num_ids: BitmapVec::MAX_INLINE_LEN,
150153
});
151154
};
152155
if bit >= (cap / 4) {
153156
return None;
154157
}
155-
let num_ids = usize::max(BITS_PER_LONG, cap / 2);
158+
let num_ids = usize::max(BitmapVec::MAX_INLINE_LEN, cap / 2);
156159
Some(ReallocRequest { num_ids })
157160
}
158161

@@ -177,11 +180,13 @@ impl IdPool {
177180

178181
/// Returns a [`ReallocRequest`] for growing this [`IdPool`], if possible.
179182
///
180-
/// The capacity of an [`IdPool`] cannot be grown above [`i32::MAX`].
183+
/// The capacity of an [`IdPool`] cannot be grown above [`MAX_LEN`].
184+
///
185+
/// [`MAX_LEN`]: BitmapVec::MAX_LEN
181186
#[inline]
182187
pub fn grow_request(&self) -> Option<ReallocRequest> {
183188
let num_ids = self.capacity() * 2;
184-
if num_ids > i32::MAX.try_into().unwrap() {
189+
if num_ids > BitmapVec::MAX_LEN {
185190
return None;
186191
}
187192
Some(ReallocRequest { num_ids })

0 commit comments

Comments
 (0)