From: Alice Ryhl <aliceryhl@google.com>
To: Andreas Hindborg <a.hindborg@kernel.org>
Cc: "Boqun Feng" <boqun.feng@gmail.com>,
"Jens Axboe" <axboe@kernel.dk>, "Miguel Ojeda" <ojeda@kernel.org>,
"Gary Guo" <gary@garyguo.net>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
"Benno Lossin" <lossin@kernel.org>,
"Trevor Gross" <tmgross@umich.edu>,
"Danilo Krummrich" <dakr@kernel.org>,
"FUJITA Tomonori" <fujita.tomonori@gmail.com>,
"Frederic Weisbecker" <frederic@kernel.org>,
"Lyude Paul" <lyude@redhat.com>,
"Thomas Gleixner" <tglx@kernel.org>,
"Anna-Maria Behnsen" <anna-maria@linutronix.de>,
"John Stultz" <jstultz@google.com>,
"Stephen Boyd" <sboyd@kernel.org>,
"Lorenzo Stoakes" <lorenzo.stoakes@oracle.com>,
"Liam R. Howlett" <Liam.Howlett@oracle.com>,
linux-block@vger.kernel.org, rust-for-linux@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-mm@kvack.org
Subject: Re: [PATCH 24/79] block: rust: add `BadBlocks` for bad block tracking
Date: Mon, 16 Mar 2026 11:55:26 +0000 [thread overview]
Message-ID: <abfvrh0ObKhtsR8I@google.com> (raw)
In-Reply-To: <20260216-rnull-v6-19-rc5-send-v1-24-de9a7af4b469@kernel.org>
On Mon, Feb 16, 2026 at 12:35:11AM +0100, Andreas Hindborg wrote:
> Add a safe Rust wrapper around the Linux kernel's badblocks infrastructure
> to track and manage defective sectors on block devices. The BadBlocks type
> provides methods to:
>
> - Mark sectors as bad or good (set_bad/set_good)
> - Check if sector ranges contain bad blocks (check)
> - Automatically handle memory management with PinnedDrop
>
> The implementation includes comprehensive documentation with examples for
> block device drivers that need to avoid known bad sectors to maintain
> data integrity. Bad blocks information is used by device drivers,
> filesystem layers, and device management tools.
>
> Signed-off-by: Andreas Hindborg <a.hindborg@kernel.org>
> diff --git a/rust/kernel/block/badblocks.rs b/rust/kernel/block/badblocks.rs
> new file mode 100644
> index 0000000000000..a5fe0fde2e755
> --- /dev/null
> +++ b/rust/kernel/block/badblocks.rs
> @@ -0,0 +1,721 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +//! Bad blocks tracking for block devices.
> +//!
> +//! This module provides a safe Rust wrapper around the badblocks
> +//! infrastructure, which is used to track and manage bad sectors on block
> +//! devices. Bad blocks are sectors that cannot reliably store data and should
> +//! be avoided during I/O operations.
Could use a srctree link to badblocks.h here.
> +/// # Examples
> +///
> +/// Basic usage:
> +///
> +/// ```rust
> +/// # use kernel::block::badblocks::{BadBlocks, BlockStatus};
> +/// # use kernel::prelude::*;
> +///
Unhide the imports or remove this empty line.
> +/// // Create a new bad blocks tracker
> +/// let bad_blocks = KBox::pin_init(BadBlocks::new(true), GFP_KERNEL)?;
> +///
> +/// // Mark sectors 100-109 as bad (unacknowledged)
> +/// bad_blocks.set_bad(100..110, false)?;
> +///
> +/// // Check if sector range 95-104 contains bad blocks
> +/// match bad_blocks.check(95..105) {
> +/// BlockStatus::None => pr_info!("No bad blocks found"),
> +/// BlockStatus::Acknowledged(range) => pr_warn!("Acknowledged bad blocks: {:?}", range),
> +/// BlockStatus::Unacknowledged(range) => pr_err!("Unacknowledged bad blocks: {:?}", range),
> +/// }
> +/// # Ok::<(), kernel::error::Error>(())
> +/// ```
> +/// # Invariants
> +///
> +/// - `self.blocks` is a valid `bindings::badblocks` struct.
> +#[pin_data(PinnedDrop)]
> +pub struct BadBlocks {
> + #[pin]
> + blocks: Opaque<bindings::badblocks>,
> +}
> +
> +impl BadBlocks {
> + /// Creates a new bad blocks tracker.
> + ///
> + /// Initializes an empty bad blocks tracker that can manage defective sectors
> + /// on a block device. The tracker starts with no bad blocks recorded and
> + /// allocates a single page for storing bad block entries.
> + ///
> + /// # Returns
> + ///
> + /// Returns a [`PinInit`] that can be used to initialize a [`BadBlocks`] instance.
> + /// Initialization may fail with `ENOMEM` if memory allocation fails.
> + ///
> + /// # Examples
> + ///
> + /// ```rust
> + /// # use kernel::block::badblocks::{BadBlocks, BlockStatus};
> + /// # use kernel::prelude::*;
> + ///
Ditto. (Many times throughout file.)
> + /// // Create and initialize a bad blocks tracker
> + /// let bad_blocks = KBox::pin_init(BadBlocks::new(true), GFP_KERNEL)?;
> + ///
> + /// // The tracker is ready to use with no bad blocks initially
> + /// match bad_blocks.check(0..100) {
> + /// BlockStatus::None => pr_info!("No bad blocks found initially"),
> + /// _ => unreachable!(),
> + /// }
> + /// # Ok::<(), kernel::error::Error>(())
> + /// ```
> + pub fn new(enable: bool) -> impl PinInit<Self, Error> {
> + // INVARIANT: We initialize `self.blocks` below. If initialization fails, an error is
> + // returned.
> + try_pin_init!(Self {
> + blocks <- Opaque::try_ffi_init(|slot| {
> + // SAFETY: `slot` is a valid pointer to uninitialized memory
> + // allocated by the Opaque type. `badblocks_init` is safe to
> + // call with uninitialized memory.
> + to_result(unsafe {bindings::badblocks_init(slot, if enable {1} else {0})})
I think you can just cast the boolean to an integer.
Also, formatting here is off (but ignored by rustfmt due to macro.)
> + /// Enables the bad blocks tracker if it was previously disabled.
> + ///
> + /// Attempts to enable bad block tracking by transitioning the tracker from
> + /// a disabled state to an enabled state.
> + ///
> + /// # Behavior
> + ///
> + /// - If the tracker is disabled, it will be enabled.
> + /// - If the tracker is already enabled, this operation has no effect.
> + /// - The operation is atomic and thread-safe.
> + ///
> + /// # Usage
> + ///
> + /// Bad blocks trackers can be created in a disabled state and enabled later
> + /// when needed. This is useful for conditional bad block tracking or for
> + /// deferring activation until the device is fully initialized.
> + ///
> + /// # Examples
> + ///
> + /// ```rust
> + /// # use kernel::block::badblocks::BadBlocks;
> + /// # use kernel::prelude::*;
> + ///
> + /// // Create a disabled bad blocks tracker
> + /// let bad_blocks = KBox::pin_init(BadBlocks::new(false), GFP_KERNEL)?;
> + /// assert!(!bad_blocks.enabled());
> + ///
> + /// // Enable it when needed
> + /// bad_blocks.enable();
> + /// assert!(bad_blocks.enabled());
> + ///
> + /// // Subsequent enable calls have no effect
> + /// bad_blocks.enable();
> + /// assert!(bad_blocks.enabled());
> + /// # Ok::<(), kernel::error::Error>(())
> + /// ```
> + pub fn enable(&self) {
> + let _ = self.shift_ref().cmpxchg(-1, 0, ordering::Relaxed);
Is there not a C function you can call here? It would be simpler that
way. Surely drivers don't do this directly.
> + }
> +
> + /// Checks whether the bad blocks tracker is currently enabled.
> + ///
> + /// Returns `true` if bad block tracking is active, `false` if it is disabled.
> + /// When disabled, the tracker will not perform bad block checks or operations.
> + ///
> + /// # Returns
> + ///
> + /// - `true` - Bad block tracking is enabled and operational
> + /// - `false` - Bad block tracking is disabled
You explain the meaning of return values twice here. Just drop the
'Returns' section.
> + /// # Thread Safety
> + ///
> + /// This method is thread-safe and uses atomic operations to check the
> + /// tracker's state without requiring external synchronization.
This is implicit from the signature of the function.
> + pub fn set_good(&self, range: impl RangeBounds<u64>) -> Result {
> + let range = Self::range(range);
> + // SAFETY: By type invariant `self.blocks` is valid. The C function
> + // `badblocks_clear` handles synchronization internally.
> + unsafe {
> + bindings::badblocks_clear(self.blocks.get(), range.start, range.end - range.start)
> + }
> + .then_some(())
> + .ok_or(EINVAL)
then_some() is quite obscure. I would recommend if/else here.
Alice
next prev parent reply other threads:[~2026-03-16 11:55 UTC|newest]
Thread overview: 114+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-15 23:34 [PATCH 00/79] block: rnull: complete the rust null block driver Andreas Hindborg
2026-02-15 23:34 ` [PATCH 01/79] block: rnull: adopt new formatting guidelines Andreas Hindborg
2026-03-16 9:14 ` Alice Ryhl
2026-02-15 23:34 ` [PATCH 02/79] block: rnull: add module parameters Andreas Hindborg
2026-03-16 9:18 ` Alice Ryhl
2026-02-15 23:34 ` [PATCH 03/79] block: rnull: add macros to define configfs attributes Andreas Hindborg
2026-03-16 9:23 ` Alice Ryhl
2026-02-15 23:34 ` [PATCH 04/79] block: rust: fix generation of bindings to `BLK_STS_.*` Andreas Hindborg
2026-03-16 9:27 ` Alice Ryhl
2026-03-16 11:58 ` Alice Ryhl
2026-02-15 23:34 ` [PATCH 05/79] block: rust: change `queue_rq` request type to `Owned` Andreas Hindborg
2026-03-16 10:01 ` Alice Ryhl
2026-03-23 12:08 ` Andreas Hindborg
2026-03-24 13:27 ` Alice Ryhl
2026-04-08 11:54 ` Andreas Hindborg
2026-02-15 23:34 ` [PATCH 06/79] block: rust: add `Request` private data support Andreas Hindborg
2026-03-16 10:10 ` Alice Ryhl
2026-02-15 23:34 ` [PATCH 07/79] block: rust: allow `hrtimer::Timer` in `RequestData` Andreas Hindborg
2026-02-15 23:34 ` [PATCH 08/79] block: rnull: add timer completion mode Andreas Hindborg
2026-02-15 23:34 ` [PATCH 09/79] block: rust: introduce `kernel::block::bio` module Andreas Hindborg
2026-03-16 10:29 ` Alice Ryhl
2026-02-15 23:34 ` [PATCH 10/79] block: rust: add `command` getter to `Request` Andreas Hindborg
2026-03-16 10:30 ` Alice Ryhl
2026-02-15 23:34 ` [PATCH 11/79] block: rust: mq: use GFP_KERNEL from prelude Andreas Hindborg
2026-03-16 10:30 ` Alice Ryhl
2026-02-15 23:34 ` [PATCH 12/79] block: rust: add `TagSet` flags Andreas Hindborg
2026-03-16 10:34 ` Alice Ryhl
2026-02-15 23:35 ` [PATCH 13/79] block: rnull: add memory backing Andreas Hindborg
2026-03-16 10:38 ` Alice Ryhl
2026-02-15 23:35 ` [PATCH 14/79] block: rnull: add submit queue count config option Andreas Hindborg
2026-03-16 10:40 ` Alice Ryhl
2026-02-15 23:35 ` [PATCH 15/79] block: rnull: add `use_per_node_hctx` " Andreas Hindborg
2026-03-16 10:43 ` Alice Ryhl
2026-03-16 11:01 ` Gary Guo
2026-03-16 13:57 ` Andreas Hindborg
2026-03-16 14:02 ` Miguel Ojeda
2026-03-16 14:05 ` Alice Ryhl
2026-02-15 23:35 ` [PATCH 16/79] block: rust: allow specifying home node when constructing `TagSet` Andreas Hindborg
2026-03-16 10:46 ` Alice Ryhl
2026-02-15 23:35 ` [PATCH 17/79] block: rnull: allow specifying the home numa node Andreas Hindborg
2026-02-15 23:35 ` [PATCH 18/79] block: rust: add Request::sectors() method Andreas Hindborg
2026-03-16 10:48 ` Alice Ryhl
2026-02-15 23:35 ` [PATCH 19/79] block: rust: mq: add max_hw_discard_sectors support to GenDiskBuilder Andreas Hindborg
2026-03-16 10:50 ` Alice Ryhl
2026-02-15 23:35 ` [PATCH 20/79] block: rnull: add discard support Andreas Hindborg
2026-03-16 10:52 ` Alice Ryhl
2026-02-15 23:35 ` [PATCH 21/79] block: rust: add `NoDefaultScheduler` flag for `TagSet` Andreas Hindborg
2026-03-16 10:53 ` Alice Ryhl
2026-02-15 23:35 ` [PATCH 22/79] block: rnull: add no_sched module parameter and configfs attribute Andreas Hindborg
2026-03-16 10:54 ` Alice Ryhl
2026-02-15 23:35 ` [PATCH 23/79] block: rust: change sector type from usize to u64 Andreas Hindborg
2026-03-16 10:56 ` Alice Ryhl
2026-02-15 23:35 ` [PATCH 24/79] block: rust: add `BadBlocks` for bad block tracking Andreas Hindborg
2026-03-16 11:55 ` Alice Ryhl [this message]
2026-02-15 23:35 ` [PATCH 25/79] block: rust: mq: add Request::end() method for custom status codes Andreas Hindborg
2026-03-16 11:57 ` Alice Ryhl
2026-02-15 23:35 ` [PATCH 26/79] block: rnull: add badblocks support Andreas Hindborg
2026-03-16 12:02 ` Alice Ryhl
2026-02-15 23:35 ` [PATCH 27/79] block: rnull: add badblocks_once support Andreas Hindborg
2026-02-15 23:35 ` [PATCH 28/79] block: rnull: add partial I/O support for bad blocks Andreas Hindborg
2026-03-16 12:14 ` Alice Ryhl
2026-02-15 23:35 ` [PATCH 29/79] block: rust: add `TagSet` private data support Andreas Hindborg
2026-02-15 23:35 ` [PATCH 30/79] block: rust: add `hctx` " Andreas Hindborg
2026-02-15 23:35 ` [PATCH 31/79] block: rnull: add volatile cache emulation Andreas Hindborg
2026-02-15 23:35 ` [PATCH 32/79] block: rust: implement `Sync` for `GenDisk` Andreas Hindborg
2026-02-15 23:35 ` [PATCH 33/79] block: rust: add a back reference feature to `GenDisk` Andreas Hindborg
2026-02-15 23:35 ` [PATCH 34/79] block: rust: introduce an idle type state for `Request` Andreas Hindborg
2026-02-15 23:35 ` [PATCH 35/79] block: rust: add a request queue abstraction Andreas Hindborg
2026-02-15 23:35 ` [PATCH 36/79] block: rust: add a method to get the request queue for a request Andreas Hindborg
2026-02-15 23:35 ` [PATCH 37/79] block: rust: introduce `kernel::block::error` Andreas Hindborg
2026-02-15 23:35 ` [PATCH 38/79] block: rust: require `queue_rq` to return a `BlkResult` Andreas Hindborg
2026-02-15 23:35 ` [PATCH 39/79] block: rust: add `GenDisk::queue_data` Andreas Hindborg
2026-02-15 23:35 ` [PATCH 40/79] block: rnull: add bandwidth limiting Andreas Hindborg
2026-02-15 23:35 ` [PATCH 41/79] block: rnull: add blocking queue mode Andreas Hindborg
2026-02-15 23:35 ` [PATCH 42/79] block: rnull: add shared tags Andreas Hindborg
2026-02-15 23:35 ` [PATCH 43/79] block: rnull: add queue depth config option Andreas Hindborg
2026-02-15 23:35 ` [PATCH 44/79] block: rust: add an abstraction for `bindings::req_op` Andreas Hindborg
2026-02-15 23:35 ` [PATCH 45/79] block: rust: add a method to set the target sector of a request Andreas Hindborg
2026-02-15 23:35 ` [PATCH 46/79] block: rust: move gendisk vtable construction to separate function Andreas Hindborg
2026-02-15 23:35 ` [PATCH 47/79] block: rust: add zoned block device support Andreas Hindborg
2026-02-15 23:35 ` [PATCH 48/79] block: rnull: add zoned storage support Andreas Hindborg
2026-02-15 23:35 ` [PATCH 49/79] block: rust: add `map_queues` support Andreas Hindborg
2026-02-15 23:35 ` [PATCH 50/79] block: rust: add an abstraction for `struct blk_mq_queue_map` Andreas Hindborg
2026-02-15 23:35 ` [PATCH 51/79] block: rust: add polled completion support Andreas Hindborg
2026-02-15 23:35 ` [PATCH 52/79] block: rust: add accessors to `TagSet` Andreas Hindborg
2026-02-15 23:35 ` [PATCH 53/79] block: rnull: add polled completion support Andreas Hindborg
2026-02-15 23:35 ` [PATCH 54/79] block: rnull: add REQ_OP_FLUSH support Andreas Hindborg
2026-02-15 23:35 ` [PATCH 55/79] block: rust: add request flags abstraction Andreas Hindborg
2026-02-15 23:35 ` [PATCH 56/79] block: rust: add abstraction for block queue feature flags Andreas Hindborg
2026-02-15 23:35 ` [PATCH 57/79] block: rust: allow setting write cache and FUA flags for `GenDisk` Andreas Hindborg
2026-02-15 23:35 ` [PATCH 58/79] block: rust: add `Segment::copy_to_page_limit` Andreas Hindborg
2026-02-15 23:35 ` [PATCH 59/79] block: rnull: add fua support Andreas Hindborg
2026-02-15 23:35 ` [PATCH 60/79] block: fix arg type in `blk_mq_update_nr_hw_queues` Andreas Hindborg
2026-02-15 23:35 ` [PATCH 61/79] block: rust: add `GenDisk::tag_set` Andreas Hindborg
2026-02-15 23:35 ` [PATCH 62/79] block: rust: add `TagSet::update_hw_queue_count` Andreas Hindborg
2026-02-16 23:59 ` Ken Kurematsu
2026-02-17 9:54 ` Andreas Hindborg
2026-02-15 23:35 ` [PATCH 63/79] block: rnull: add an option to change the number of hardware queues Andreas Hindborg
2026-02-15 23:35 ` [PATCH 64/79] block: rust: add an abstraction for `struct rq_list` Andreas Hindborg
2026-02-15 23:35 ` [PATCH 65/79] block: rust: add `queue_rqs` vtable hook Andreas Hindborg
2026-02-15 23:35 ` [PATCH 66/79] block: rnull: support queue_rqs Andreas Hindborg
2026-02-15 23:35 ` [PATCH 67/79] block: rust: remove the `is_poll` parameter from `queue_rq` Andreas Hindborg
2026-02-15 23:35 ` [PATCH 68/79] block: rust: add a debug assert for refcounts Andreas Hindborg
2026-02-15 23:35 ` [PATCH 69/79] block: rust: add `TagSet::tag_to_rq` Andreas Hindborg
2026-02-15 23:35 ` [PATCH 70/79] block: rust: add `Request::queue_index` Andreas Hindborg
2026-02-15 23:35 ` [PATCH 71/79] block: rust: add `Request::requeue` Andreas Hindborg
2026-02-15 23:35 ` [PATCH 72/79] block: rust: add `request_timeout` hook Andreas Hindborg
2026-02-15 23:36 ` [PATCH 73/79] block: rnull: add fault injection support Andreas Hindborg
2026-02-15 23:36 ` [PATCH 74/79] block: rust: add max_sectors option to `GenDiskBuilder` Andreas Hindborg
2026-02-15 23:36 ` [PATCH 75/79] block: rnull: allow configuration of the maximum IO size Andreas Hindborg
2026-02-15 23:36 ` [PATCH 76/79] block: rust: add `virt_boundary_mask` option to `GenDiskBuilder` Andreas Hindborg
2026-02-15 23:36 ` [PATCH 77/79] block: rnull: add `virt_boundary` option Andreas Hindborg
2026-02-15 23:36 ` [PATCH 78/79] block: rnull: add `shared_tag_bitmap` config option Andreas Hindborg
2026-02-15 23:36 ` [PATCH 79/79] block: rnull: add zone offline and readonly configfs files Andreas Hindborg
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=abfvrh0ObKhtsR8I@google.com \
--to=aliceryhl@google.com \
--cc=Liam.Howlett@oracle.com \
--cc=a.hindborg@kernel.org \
--cc=anna-maria@linutronix.de \
--cc=axboe@kernel.dk \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun.feng@gmail.com \
--cc=dakr@kernel.org \
--cc=frederic@kernel.org \
--cc=fujita.tomonori@gmail.com \
--cc=gary@garyguo.net \
--cc=jstultz@google.com \
--cc=linux-block@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=lorenzo.stoakes@oracle.com \
--cc=lossin@kernel.org \
--cc=lyude@redhat.com \
--cc=ojeda@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=sboyd@kernel.org \
--cc=tglx@kernel.org \
--cc=tmgross@umich.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.