File Index
Files and directories
Sign in
FILE

rnull.rs

File preview with syntax highlighting.

linux-6.19.14/drivers/block/rnull/rnull.rs RUST
  1// SPDX-License-Identifier: GPL-2.0
  2
  3//! This is a Rust implementation of the C null block driver.
  4
  5mod configfs;
  6
  7use configfs::IRQMode;
  8use kernel::{
  9    block::{
 10        self,
 11        mq::{
 12            self,
 13            gen_disk::{self, GenDisk},
 14            Operations, TagSet,
 15        },
 16    },
 17    error::Result,
 18    pr_info,
 19    prelude::*,
 20    sync::{aref::ARef, Arc},
 21};
 22use pin_init::PinInit;
 23
 24module! {
 25    type: NullBlkModule,
 26    name: "rnull_mod",
 27    authors: ["Andreas Hindborg"],
 28    description: "Rust implementation of the C null block driver",
 29    license: "GPL v2",
 30}
 31
 32#[pin_data]
 33struct NullBlkModule {
 34    #[pin]
 35    configfs_subsystem: kernel::configfs::Subsystem<configfs::Config>,
 36}
 37
 38impl kernel::InPlaceModule for NullBlkModule {
 39    fn init(_module: &'static ThisModule) -> impl PinInit<Self, Error> {
 40        pr_info!("Rust null_blk loaded\n");
 41
 42        try_pin_init!(Self {
 43            configfs_subsystem <- configfs::subsystem(),
 44        })
 45    }
 46}
 47
 48struct NullBlkDevice;
 49
 50impl NullBlkDevice {
 51    fn new(
 52        name: &CStr,
 53        block_size: u32,
 54        rotational: bool,
 55        capacity_mib: u64,
 56        irq_mode: IRQMode,
 57    ) -> Result<GenDisk<Self>> {
 58        let tagset = Arc::pin_init(TagSet::new(1, 256, 1), GFP_KERNEL)?;
 59
 60        let queue_data = Box::new(QueueData { irq_mode }, GFP_KERNEL)?;
 61
 62        gen_disk::GenDiskBuilder::new()
 63            .capacity_sectors(capacity_mib << (20 - block::SECTOR_SHIFT))
 64            .logical_block_size(block_size)?
 65            .physical_block_size(block_size)?
 66            .rotational(rotational)
 67            .build(fmt!("{}", name.to_str()?), tagset, queue_data)
 68    }
 69}
 70
 71struct QueueData {
 72    irq_mode: IRQMode,
 73}
 74
 75#[vtable]
 76impl Operations for NullBlkDevice {
 77    type QueueData = KBox<QueueData>;
 78
 79    #[inline(always)]
 80    fn queue_rq(queue_data: &QueueData, rq: ARef<mq::Request<Self>>, _is_last: bool) -> Result {
 81        match queue_data.irq_mode {
 82            IRQMode::None => mq::Request::end_ok(rq)
 83                .map_err(|_e| kernel::error::code::EIO)
 84                // We take no refcounts on the request, so we expect to be able to
 85                // end the request. The request reference must be unique at this
 86                // point, and so `end_ok` cannot fail.
 87                .expect("Fatal error - expected to be able to end request"),
 88            IRQMode::Soft => mq::Request::complete(rq),
 89        }
 90        Ok(())
 91    }
 92
 93    fn commit_rqs(_queue_data: &QueueData) {}
 94
 95    fn complete(rq: ARef<mq::Request<Self>>) {
 96        mq::Request::end_ok(rq)
 97            .map_err(|_e| kernel::error::code::EIO)
 98            // We take no refcounts on the request, so we expect to be able to
 99            // end the request. The request reference must be unique at this
100            // point, and so `end_ok` cannot fail.
101            .expect("Fatal error - expected to be able to end request");
102    }
103}
~/ Read-only file preview.