kernel/bitmap.rs
1// SPDX-License-Identifier: GPL-2.0
2
3// Copyright (C) 2025 Google LLC.
4
5//! Rust API for bitmap.
6//!
7//! C headers: [`include/linux/bitmap.h`](srctree/include/linux/bitmap.h).
8
9use crate::alloc::{AllocError, Flags};
10use crate::bindings;
11#[cfg(not(CONFIG_RUST_BITMAP_HARDENED))]
12use crate::pr_err;
13use core::ptr::NonNull;
14
15/// Represents a C bitmap. Wraps underlying C bitmap API.
16///
17/// # Invariants
18///
19/// Must reference a `[c_ulong]` long enough to fit `data.len()` bits.
20/// Must not be longer than [`i32::MAX`] bits, so offsets and lengths used with
21/// [`Bitmap`] functions fit in the `int` and `unsigned int` arguments of the C bitmap API.
22/// This also matches [`BitmapVec::MAX_LEN`].
23#[cfg_attr(CONFIG_64BIT, repr(align(8)))]
24#[cfg_attr(not(CONFIG_64BIT), repr(align(4)))]
25pub struct Bitmap {
26 data: [()],
27}
28
29macro_rules! bitmap_assert {
30 ($cond:expr, $($arg:tt)+) => {
31 #[cfg(CONFIG_RUST_BITMAP_HARDENED)]
32 assert!($cond, $($arg)*);
33 }
34}
35
36macro_rules! bitmap_assert_return {
37 ($cond:expr, $($arg:tt)+) => {
38 #[cfg(CONFIG_RUST_BITMAP_HARDENED)]
39 assert!($cond, $($arg)*);
40
41 #[cfg(not(CONFIG_RUST_BITMAP_HARDENED))]
42 if !($cond) {
43 pr_err!($($arg)*);
44 return
45 }
46 }
47}
48
49impl Bitmap {
50 /// Borrows a C bitmap.
51 ///
52 /// # Panics
53 ///
54 /// Panics if CONFIG_RUST_BITMAP_HARDENED is enabled and `nbits` exceeds [`i32::MAX`].
55 ///
56 /// # Safety
57 ///
58 /// * `ptr` holds a non-null address of an initialized array of `unsigned long`
59 /// that is large enough to hold `nbits` bits.
60 /// * `nbits` must not exceed [`i32::MAX`].
61 /// * the array must not be freed for the lifetime of this [`Bitmap`]
62 /// * concurrent access only happens through atomic operations
63 pub unsafe fn from_raw<'a>(ptr: *const usize, nbits: usize) -> &'a Bitmap {
64 bitmap_assert!(
65 nbits <= i32::MAX as usize,
66 "`nbits` must be <= {}, was {}",
67 i32::MAX,
68 nbits
69 );
70 let data: *const [()] = core::ptr::slice_from_raw_parts(ptr.cast(), nbits);
71 // INVARIANT: `data` references an initialized array that can hold `nbits` bits.
72 // INVARIANT: The caller guarantees that `nbits` does not exceed `i32::MAX`.
73 // SAFETY:
74 // The caller guarantees that `data` (derived from `ptr` and `nbits`)
75 // points to a valid, initialized, and appropriately sized memory region
76 // that will not be freed for the lifetime 'a.
77 // We are casting `*const [()]` to `*const Bitmap`. The `Bitmap`
78 // struct is a ZST with a `data: [()]` field. This means its layout
79 // is compatible with a slice of `()`, and effectively it's a "thin pointer"
80 // (its size is 0 and alignment is 1). The `slice_from_raw_parts`
81 // function correctly encodes the length (number of bits, not elements)
82 // into the metadata of the fat pointer. Therefore, dereferencing this
83 // pointer as `&Bitmap` is safe given the caller's guarantees.
84 unsafe { &*(data as *const Bitmap) }
85 }
86
87 /// Borrows a C bitmap exclusively.
88 ///
89 /// # Panics
90 ///
91 /// Panics if CONFIG_RUST_BITMAP_HARDENED is enabled and `nbits` exceeds [`i32::MAX`].
92 ///
93 /// # Safety
94 ///
95 /// * `ptr` holds a non-null address of an initialized array of `unsigned long`
96 /// that is large enough to hold `nbits` bits.
97 /// * `nbits` must not exceed [`i32::MAX`].
98 /// * the array must not be freed for the lifetime of this [`Bitmap`]
99 /// * no concurrent access may happen.
100 pub unsafe fn from_raw_mut<'a>(ptr: *mut usize, nbits: usize) -> &'a mut Bitmap {
101 bitmap_assert!(
102 nbits <= i32::MAX as usize,
103 "`nbits` must be <= {}, was {}",
104 i32::MAX,
105 nbits
106 );
107 let data: *mut [()] = core::ptr::slice_from_raw_parts_mut(ptr.cast(), nbits);
108 // INVARIANT: `data` references an initialized array that can hold `nbits` bits.
109 // INVARIANT: The caller guarantees that `nbits` does not exceed `i32::MAX`.
110 // SAFETY:
111 // The caller guarantees that `data` (derived from `ptr` and `nbits`)
112 // points to a valid, initialized, and appropriately sized memory region
113 // that will not be freed for the lifetime 'a.
114 // Furthermore, the caller guarantees no concurrent access will happen,
115 // which upholds the exclusivity requirement for a mutable reference.
116 // Similar to `from_raw`, casting `*mut [()]` to `*mut Bitmap` is
117 // safe because `Bitmap` is a ZST with a `data: [()]` field,
118 // making its layout compatible with a slice of `()`.
119 unsafe { &mut *(data as *mut Bitmap) }
120 }
121
122 /// Returns a raw pointer to the backing [`Bitmap`].
123 pub fn as_ptr(&self) -> *const usize {
124 core::ptr::from_ref::<Bitmap>(self).cast::<usize>()
125 }
126
127 /// Returns a mutable raw pointer to the backing [`Bitmap`].
128 pub fn as_mut_ptr(&mut self) -> *mut usize {
129 core::ptr::from_mut::<Bitmap>(self).cast::<usize>()
130 }
131
132 /// Returns length of this [`Bitmap`].
133 #[expect(clippy::len_without_is_empty)]
134 pub fn len(&self) -> usize {
135 self.data.len()
136 }
137}
138
139/// Holds either a pointer to array of `unsigned long` or a small bitmap.
140#[repr(C)]
141union BitmapRepr {
142 bitmap: usize,
143 ptr: NonNull<usize>,
144}
145
146/// Represents an owned bitmap.
147///
148/// Wraps underlying C bitmap API. See [`Bitmap`] for available
149/// methods.
150///
151/// # Examples
152///
153/// Basic usage
154///
155/// ```
156/// use kernel::alloc::flags::GFP_KERNEL;
157/// use kernel::bitmap::BitmapVec;
158///
159/// let mut b = BitmapVec::new(16, GFP_KERNEL)?;
160///
161/// assert_eq!(16, b.len());
162/// for i in 0..16 {
163/// if i % 4 == 0 {
164/// b.set_bit(i);
165/// }
166/// }
167/// assert_eq!(Some(0), b.next_bit(0));
168/// assert_eq!(Some(1), b.next_zero_bit(0));
169/// assert_eq!(Some(4), b.next_bit(1));
170/// assert_eq!(Some(5), b.next_zero_bit(4));
171/// assert_eq!(Some(12), b.last_bit());
172/// # Ok::<(), Error>(())
173/// ```
174///
175/// # Invariants
176///
177/// * `nbits` is `<= MAX_LEN`.
178/// * if `nbits <= MAX_INLINE_LEN`, then `repr` is a `usize`.
179/// * otherwise, `repr` holds a non-null pointer to an initialized
180/// array of `unsigned long` that is large enough to hold `nbits` bits.
181pub struct BitmapVec {
182 /// Representation of bitmap.
183 repr: BitmapRepr,
184 /// Length of this bitmap. Must be `<= MAX_LEN`.
185 nbits: usize,
186}
187
188impl core::ops::Deref for BitmapVec {
189 type Target = Bitmap;
190
191 fn deref(&self) -> &Bitmap {
192 let ptr = if self.nbits <= BitmapVec::MAX_INLINE_LEN {
193 // SAFETY: Bitmap is represented inline.
194 #[allow(unused_unsafe, reason = "Safe since Rust 1.92.0")]
195 unsafe {
196 core::ptr::addr_of!(self.repr.bitmap)
197 }
198 } else {
199 // SAFETY: Bitmap is represented as array of `unsigned long`.
200 unsafe { self.repr.ptr.as_ptr() }
201 };
202
203 // SAFETY: We got the right pointer and invariants of [`Bitmap`] hold.
204 // An inline bitmap is treated like an array with single element.
205 unsafe { Bitmap::from_raw(ptr, self.nbits) }
206 }
207}
208
209impl core::ops::DerefMut for BitmapVec {
210 fn deref_mut(&mut self) -> &mut Bitmap {
211 let ptr = if self.nbits <= BitmapVec::MAX_INLINE_LEN {
212 // SAFETY: Bitmap is represented inline.
213 #[allow(unused_unsafe, reason = "Safe since Rust 1.92.0")]
214 unsafe {
215 core::ptr::addr_of_mut!(self.repr.bitmap)
216 }
217 } else {
218 // SAFETY: Bitmap is represented as array of `unsigned long`.
219 unsafe { self.repr.ptr.as_ptr() }
220 };
221
222 // SAFETY: We got the right pointer and invariants of [`BitmapVec`] hold.
223 // An inline bitmap is treated like an array with single element.
224 unsafe { Bitmap::from_raw_mut(ptr, self.nbits) }
225 }
226}
227
228/// Enable ownership transfer to other threads.
229///
230/// SAFETY: We own the underlying bitmap representation.
231unsafe impl Send for BitmapVec {}
232
233/// Enable unsynchronized concurrent access to [`BitmapVec`] through shared references.
234///
235/// SAFETY: `deref()` will return a reference to a [`Bitmap`]. Its methods
236/// take immutable references are either atomic or read-only.
237unsafe impl Sync for BitmapVec {}
238
239impl Drop for BitmapVec {
240 fn drop(&mut self) {
241 if self.nbits <= BitmapVec::MAX_INLINE_LEN {
242 return;
243 }
244 // SAFETY: `self.ptr` was returned by the C `bitmap_zalloc`.
245 //
246 // INVARIANT: there is no other use of the `self.ptr` after this
247 // call and the value is being dropped so the broken invariant is
248 // not observable on function exit.
249 unsafe { bindings::bitmap_free(self.repr.ptr.as_ptr()) };
250 }
251}
252
253impl BitmapVec {
254 /// The maximum possible length of a `BitmapVec`.
255 pub const MAX_LEN: usize = i32::MAX as usize;
256
257 /// The maximum length that uses the inline representation.
258 pub const MAX_INLINE_LEN: usize = usize::BITS as usize;
259
260 /// Construct a longest possible inline [`BitmapVec`].
261 #[inline]
262 pub fn new_inline() -> Self {
263 // INVARIANT: `nbits <= MAX_INLINE_LEN`, so an inline bitmap is the right repr.
264 BitmapVec {
265 repr: BitmapRepr { bitmap: 0 },
266 nbits: BitmapVec::MAX_INLINE_LEN,
267 }
268 }
269
270 /// Constructs a new [`BitmapVec`].
271 ///
272 /// Fails with [`AllocError`] when the [`BitmapVec`] could not be allocated. This
273 /// includes the case when `nbits` is greater than `MAX_LEN`.
274 #[inline]
275 pub fn new(nbits: usize, flags: Flags) -> Result<Self, AllocError> {
276 if nbits <= BitmapVec::MAX_INLINE_LEN {
277 return Ok(BitmapVec {
278 repr: BitmapRepr { bitmap: 0 },
279 nbits,
280 });
281 }
282 if nbits > Self::MAX_LEN {
283 return Err(AllocError);
284 }
285 let nbits_u32 = u32::try_from(nbits).unwrap();
286 // SAFETY: `MAX_INLINE_LEN < nbits` and `nbits <= MAX_LEN`.
287 let ptr = unsafe { bindings::bitmap_zalloc(nbits_u32, flags.as_raw()) };
288 let ptr = NonNull::new(ptr).ok_or(AllocError)?;
289 // INVARIANT: `ptr` returned by C `bitmap_zalloc` and `nbits` checked.
290 Ok(BitmapVec {
291 repr: BitmapRepr { ptr },
292 nbits,
293 })
294 }
295
296 /// Returns length of this [`Bitmap`].
297 #[allow(clippy::len_without_is_empty)]
298 #[inline]
299 pub fn len(&self) -> usize {
300 self.nbits
301 }
302
303 /// Fills this `Bitmap` with random bits.
304 #[cfg(CONFIG_FIND_BIT_BENCHMARK_RUST)]
305 pub fn fill_random(&mut self) {
306 // SAFETY: `self.as_mut_ptr` points to either an array of the
307 // appropriate length or one usize.
308 unsafe {
309 bindings::get_random_bytes(
310 self.as_mut_ptr().cast::<ffi::c_void>(),
311 usize::div_ceil(self.nbits, bindings::BITS_PER_LONG as usize)
312 * bindings::BITS_PER_LONG as usize
313 / 8,
314 );
315 }
316 }
317}
318
319impl Bitmap {
320 /// Set bit with index `index`.
321 ///
322 /// ATTENTION: `set_bit` is non-atomic, which differs from the naming
323 /// convention in C code. The corresponding C function is `__set_bit`.
324 ///
325 /// If CONFIG_RUST_BITMAP_HARDENED is not enabled and `index` is greater than
326 /// or equal to `self.nbits`, does nothing.
327 ///
328 /// # Panics
329 ///
330 /// Panics if CONFIG_RUST_BITMAP_HARDENED is enabled and `index` is greater than
331 /// or equal to `self.nbits`.
332 #[inline]
333 pub fn set_bit(&mut self, index: usize) {
334 bitmap_assert_return!(
335 index < self.len(),
336 "Bit `index` must be < {}, was {}",
337 self.len(),
338 index
339 );
340 // SAFETY: Bit `index` is within bounds.
341 unsafe { bindings::__set_bit(index, self.as_mut_ptr()) };
342 }
343
344 /// Set bit with index `index`, atomically.
345 ///
346 /// This is a relaxed atomic operation (no implied memory barriers).
347 ///
348 /// ATTENTION: The naming convention differs from C, where the corresponding
349 /// function is called `set_bit`.
350 ///
351 /// If CONFIG_RUST_BITMAP_HARDENED is not enabled and `index` is greater than
352 /// or equal to `self.len()`, does nothing.
353 ///
354 /// # Panics
355 ///
356 /// Panics if CONFIG_RUST_BITMAP_HARDENED is enabled and `index` is greater than
357 /// or equal to `self.len()`.
358 #[inline]
359 pub fn set_bit_atomic(&self, index: usize) {
360 bitmap_assert_return!(
361 index < self.len(),
362 "Bit `index` must be < {}, was {}",
363 self.len(),
364 index
365 );
366 // SAFETY: `index` is within bounds and the caller has ensured that
367 // there is no mix of non-atomic and atomic operations.
368 unsafe { bindings::set_bit(index, self.as_ptr().cast_mut()) };
369 }
370
371 /// Clear `index` bit.
372 ///
373 /// ATTENTION: `clear_bit` is non-atomic, which differs from the naming
374 /// convention in C code. The corresponding C function is `__clear_bit`.
375 ///
376 /// If CONFIG_RUST_BITMAP_HARDENED is not enabled and `index` is greater than
377 /// or equal to `self.len()`, does nothing.
378 ///
379 /// # Panics
380 ///
381 /// Panics if CONFIG_RUST_BITMAP_HARDENED is enabled and `index` is greater than
382 /// or equal to `self.len()`.
383 #[inline]
384 pub fn clear_bit(&mut self, index: usize) {
385 bitmap_assert_return!(
386 index < self.len(),
387 "Bit `index` must be < {}, was {}",
388 self.len(),
389 index
390 );
391 // SAFETY: `index` is within bounds.
392 unsafe { bindings::__clear_bit(index, self.as_mut_ptr()) };
393 }
394
395 /// Clear `index` bit, atomically.
396 ///
397 /// This is a relaxed atomic operation (no implied memory barriers).
398 ///
399 /// ATTENTION: The naming convention differs from C, where the corresponding
400 /// function is called `clear_bit`.
401 ///
402 /// If CONFIG_RUST_BITMAP_HARDENED is not enabled and `index` is greater than
403 /// or equal to `self.len()`, does nothing.
404 ///
405 /// # Panics
406 ///
407 /// Panics if CONFIG_RUST_BITMAP_HARDENED is enabled and `index` is greater than
408 /// or equal to `self.len()`.
409 #[inline]
410 pub fn clear_bit_atomic(&self, index: usize) {
411 bitmap_assert_return!(
412 index < self.len(),
413 "Bit `index` must be < {}, was {}",
414 self.len(),
415 index
416 );
417 // SAFETY: `index` is within bounds and the caller has ensured that
418 // there is no mix of non-atomic and atomic operations.
419 unsafe { bindings::clear_bit(index, self.as_ptr().cast_mut()) };
420 }
421
422 /// Copy `src` into this [`Bitmap`] and set any remaining bits to zero.
423 ///
424 /// # Examples
425 ///
426 /// ```
427 /// use kernel::alloc::{AllocError, flags::GFP_KERNEL};
428 /// use kernel::bitmap::BitmapVec;
429 ///
430 /// let mut long_bitmap = BitmapVec::new(256, GFP_KERNEL)?;
431 ///
432 /// assert_eq!(None, long_bitmap.last_bit());
433 ///
434 /// let mut short_bitmap = BitmapVec::new(16, GFP_KERNEL)?;
435 ///
436 /// short_bitmap.set_bit(7);
437 /// long_bitmap.copy_and_extend(&short_bitmap);
438 /// assert_eq!(Some(7), long_bitmap.last_bit());
439 ///
440 /// # Ok::<(), AllocError>(())
441 /// ```
442 #[inline]
443 pub fn copy_and_extend(&mut self, src: &Bitmap) {
444 let len = core::cmp::min(src.len(), self.len());
445 // SAFETY: Access to `self` and `src` is within bounds. Both lengths fit in `u32`
446 // because a `Bitmap` is at most `i32::MAX` bits, so the casts are lossless.
447 unsafe {
448 bindings::bitmap_copy_and_extend(
449 self.as_mut_ptr(),
450 src.as_ptr(),
451 len as u32,
452 self.len() as u32,
453 )
454 };
455 }
456
457 /// Finds last set bit.
458 ///
459 /// # Examples
460 ///
461 /// ```
462 /// use kernel::alloc::{AllocError, flags::GFP_KERNEL};
463 /// use kernel::bitmap::BitmapVec;
464 ///
465 /// let bitmap = BitmapVec::new(64, GFP_KERNEL)?;
466 ///
467 /// match bitmap.last_bit() {
468 /// Some(idx) => {
469 /// pr_info!("The last bit has index {idx}.\n");
470 /// }
471 /// None => {
472 /// pr_info!("All bits in this bitmap are 0.\n");
473 /// }
474 /// }
475 /// # Ok::<(), AllocError>(())
476 /// ```
477 #[inline]
478 pub fn last_bit(&self) -> Option<usize> {
479 // SAFETY: `_find_next_bit` access is within bounds due to invariant.
480 let index = unsafe { bindings::_find_last_bit(self.as_ptr(), self.len()) };
481 if index >= self.len() {
482 None
483 } else {
484 Some(index)
485 }
486 }
487
488 /// Finds next set bit, starting from `start`.
489 ///
490 /// Returns `None` if `start` is greater or equal to `self.nbits`.
491 #[inline]
492 pub fn next_bit(&self, start: usize) -> Option<usize> {
493 bitmap_assert!(
494 start < self.len(),
495 "`start` must be < {} was {}",
496 self.len(),
497 start
498 );
499 // SAFETY: `_find_next_bit` tolerates out-of-bounds arguments and returns a
500 // value larger than or equal to `self.len()` in that case.
501 let index = unsafe { bindings::_find_next_bit(self.as_ptr(), self.len(), start) };
502 if index >= self.len() {
503 None
504 } else {
505 Some(index)
506 }
507 }
508
509 /// Finds next zero bit, starting from `start`.
510 /// Returns `None` if `start` is greater than or equal to `self.len()`.
511 #[inline]
512 pub fn next_zero_bit(&self, start: usize) -> Option<usize> {
513 bitmap_assert!(
514 start < self.len(),
515 "`start` must be < {} was {}",
516 self.len(),
517 start
518 );
519 // SAFETY: `_find_next_zero_bit` tolerates out-of-bounds arguments and returns a
520 // value larger than or equal to `self.len()` in that case.
521 let index = unsafe { bindings::_find_next_zero_bit(self.as_ptr(), self.len(), start) };
522 if index >= self.len() {
523 None
524 } else {
525 Some(index)
526 }
527 }
528}
529
530#[cfg(CONFIG_RUST_BITMAP_KUNIT_TEST)]
531#[macros::kunit_tests(rust_kernel_bitmap)]
532mod tests {
533 use super::*;
534 use kernel::alloc::flags::GFP_KERNEL;
535
536 #[test]
537 fn bitmap_borrow() {
538 let fake_bitmap: [usize; 2] = [0, 0];
539 let fake_bitmap_len = 2 * usize::BITS as usize;
540 // SAFETY: `fake_c_bitmap` is an array of expected length.
541 let b = unsafe { Bitmap::from_raw(fake_bitmap.as_ptr(), fake_bitmap_len) };
542 assert_eq!(fake_bitmap_len, b.len());
543 assert_eq!(None, b.next_bit(0));
544 }
545
546 #[test]
547 fn bitmap_copy() {
548 let fake_bitmap: usize = 0xFF;
549 // SAFETY: `fake_c_bitmap` can be used as one-element array of expected length.
550 let b = unsafe { Bitmap::from_raw(core::ptr::addr_of!(fake_bitmap), 8) };
551 assert_eq!(8, b.len());
552 assert_eq!(None, b.next_zero_bit(0));
553 }
554
555 #[test]
556 fn bitmap_vec_new() -> Result<(), AllocError> {
557 let b = BitmapVec::new(0, GFP_KERNEL)?;
558 assert_eq!(0, b.len());
559
560 let b = BitmapVec::new(3, GFP_KERNEL)?;
561 assert_eq!(3, b.len());
562
563 let b = BitmapVec::new(1024, GFP_KERNEL)?;
564 assert_eq!(1024, b.len());
565
566 // Requesting too large values results in [`AllocError`].
567 let res = BitmapVec::new(1 << 31, GFP_KERNEL);
568 assert!(res.is_err());
569 Ok(())
570 }
571
572 #[test]
573 fn bitmap_set_clear_find() -> Result<(), AllocError> {
574 let mut b = BitmapVec::new(128, GFP_KERNEL)?;
575
576 // Zero-initialized
577 assert_eq!(None, b.next_bit(0));
578 assert_eq!(Some(0), b.next_zero_bit(0));
579 assert_eq!(None, b.last_bit());
580
581 b.set_bit(17);
582
583 assert_eq!(Some(17), b.next_bit(0));
584 assert_eq!(Some(17), b.next_bit(17));
585 assert_eq!(None, b.next_bit(18));
586 assert_eq!(Some(17), b.last_bit());
587
588 b.set_bit(107);
589
590 assert_eq!(Some(17), b.next_bit(0));
591 assert_eq!(Some(17), b.next_bit(17));
592 assert_eq!(Some(107), b.next_bit(18));
593 assert_eq!(Some(107), b.last_bit());
594
595 b.clear_bit(17);
596
597 assert_eq!(Some(107), b.next_bit(0));
598 assert_eq!(Some(107), b.last_bit());
599 Ok(())
600 }
601
602 #[test]
603 fn owned_bitmap_out_of_bounds() -> Result<(), AllocError> {
604 // TODO: Kunit #[test]s do not support `cfg` yet,
605 // so we add it here in the body.
606 #[cfg(not(CONFIG_RUST_BITMAP_HARDENED))]
607 {
608 let mut b = BitmapVec::new(128, GFP_KERNEL)?;
609 b.set_bit(2048);
610 b.set_bit_atomic(2048);
611 b.clear_bit(2048);
612 b.clear_bit_atomic(2048);
613 assert_eq!(None, b.next_bit(2048));
614 assert_eq!(None, b.next_zero_bit(2048));
615 assert_eq!(None, b.last_bit());
616 }
617 Ok(())
618 }
619
620 // TODO: uncomment once kunit supports [should_panic] and `cfg`.
621 // #[cfg(CONFIG_RUST_BITMAP_HARDENED)]
622 // #[test]
623 // #[should_panic]
624 // fn owned_bitmap_out_of_bounds() -> Result<(), AllocError> {
625 // let mut b = BitmapVec::new(128, GFP_KERNEL)?;
626 //
627 // b.set_bit(2048);
628 // }
629
630 #[test]
631 fn bitmap_copy_and_extend() -> Result<(), AllocError> {
632 let mut long_bitmap = BitmapVec::new(256, GFP_KERNEL)?;
633
634 long_bitmap.set_bit(3);
635 long_bitmap.set_bit(200);
636
637 let mut short_bitmap = BitmapVec::new(32, GFP_KERNEL)?;
638
639 short_bitmap.set_bit(17);
640
641 long_bitmap.copy_and_extend(&short_bitmap);
642
643 // Previous bits have been cleared.
644 assert_eq!(Some(17), long_bitmap.next_bit(0));
645 assert_eq!(Some(17), long_bitmap.last_bit());
646 Ok(())
647 }
648}