Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 31 additions & 1 deletion drivers/block/rnull/configfs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ impl AttributeOperations<0> for Config {

fn show(_this: &Config, page: &mut [u8; PAGE_SIZE]) -> Result<usize> {
let mut writer = kernel::str::Formatter::new(page);
writer.write_str("blocksize,size,rotational,irqmode\n")?;
writer.write_str("blocksize,size,rotational,irqmode,blocking\n")?;
Ok(writer.bytes_written())
}
}
Expand All @@ -58,6 +58,7 @@ impl configfs::GroupOperations for Config {
rotational: 2,
size: 3,
irqmode: 4,
blocking: 5,
],
};

Expand All @@ -73,6 +74,7 @@ impl configfs::GroupOperations for Config {
disk: None,
capacity_mib: 4096,
irq_mode: IRQMode::None,
blocking: false,
name: name.try_into()?,
}),
}),
Expand Down Expand Up @@ -122,6 +124,7 @@ struct DeviceConfigInner {
rotational: bool,
capacity_mib: u64,
irq_mode: IRQMode,
blocking: bool,
disk: Option<GenDisk<NullBlkDevice>>,
}

Expand Down Expand Up @@ -152,6 +155,7 @@ impl configfs::AttributeOperations<0> for DeviceConfig {
guard.rotational,
guard.capacity_mib,
guard.irq_mode,
guard.blocking,
)?);
guard.powered = true;
} else if guard.powered && !power_op {
Expand Down Expand Up @@ -259,3 +263,29 @@ impl configfs::AttributeOperations<4> for DeviceConfig {
Ok(())
}
}

#[vtable]
impl configfs::AttributeOperations<5> for DeviceConfig {
type Data = DeviceConfig;

fn show(this: &DeviceConfig, page: &mut [u8; PAGE_SIZE]) -> Result<usize> {
let mut writer = kernel::str::Formatter::new(page);

if this.data.lock().blocking {
writer.write_str("1\n")?;
} else {
writer.write_str("0\n")?;
}

Ok(writer.bytes_written())
}

fn store(this: &DeviceConfig, page: &[u8]) -> Result {
if this.data.lock().powered {
return Err(EBUSY);
}

this.data.lock().blocking = kstrtobool_bytes(page)?;
Ok(())
}
}
11 changes: 9 additions & 2 deletions drivers/block/rnull/rnull.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use kernel::{
mq::{
self,
gen_disk::{self, GenDisk},
Operations, TagSet,
Operations, TagSet, TagSetFlags,
},
},
prelude::*,
Expand Down Expand Up @@ -51,8 +51,15 @@ impl NullBlkDevice {
rotational: bool,
capacity_mib: u64,
irq_mode: IRQMode,
blocking: bool,
) -> Result<GenDisk<Self>> {
let tagset = Arc::pin_init(TagSet::new(1, 256, 1), GFP_KERNEL)?;
let flags = if blocking {
TagSetFlags::BLOCKING
} else {
TagSetFlags::empty()
};

let tagset = Arc::pin_init(TagSet::new_with_flags(1, 256, 1, flags), GFP_KERNEL)?;

let queue_data = Box::new(QueueData { irq_mode }, GFP_KERNEL)?;

Expand Down
2 changes: 1 addition & 1 deletion rust/kernel/block/mq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,4 +100,4 @@ mod tag_set;

pub use operations::Operations;
pub use request::Request;
pub use tag_set::TagSet;
pub use tag_set::{TagSet, TagSetFlags};
86 changes: 85 additions & 1 deletion rust/kernel/block/mq/tag_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,80 @@ use crate::{
use core::{convert::TryInto, marker::PhantomData};
use pin_init::{pin_data, pinned_drop, PinInit};

/// Flags that control blk-mq tag set behavior.
///
/// They can be combined with the operators `|`, `&`, and `!`.
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct TagSetFlags(u32);

impl TagSetFlags {
/// Returns an empty instance where no flags are set.
pub const fn empty() -> Self {
Self(0)
}

/// Register as a blocking blk-mq driver device.
pub const BLOCKING: Self = Self::new(bindings::BLK_MQ_F_BLOCKING as u32);

/// Use an underlying blk-mq device for completing I/O.
pub const STACKING: Self = Self::new(bindings::BLK_MQ_F_STACKING as u32);

/// Share hardware contexts between tags.
pub const TAG_HCTX_SHARED: Self = Self::new(bindings::BLK_MQ_F_TAG_HCTX_SHARED as u32);

/// Allocate tags on a round-robin basis.
pub const TAG_RR: Self = Self::new(bindings::BLK_MQ_F_TAG_RR as u32);

/// Disable the I/O scheduler by default.
pub const NO_SCHED_BY_DEFAULT: Self =
Self::new(bindings::BLK_MQ_F_NO_SCHED_BY_DEFAULT as u32);

/// Check whether `flags` is contained in `self`.
pub fn contains(self, flags: Self) -> bool {
(self & flags) == flags
}

pub(crate) const fn as_raw(self) -> u32 {
self.0
}

const fn all_bits() -> u32 {
Self::BLOCKING.0
| Self::STACKING.0
| Self::TAG_HCTX_SHARED.0
| Self::TAG_RR.0
| Self::NO_SCHED_BY_DEFAULT.0
}

const fn new(value: u32) -> Self {
Self(value)
}
}

impl core::ops::BitOr for TagSetFlags {
type Output = Self;

fn bitor(self, rhs: Self) -> Self::Output {
Self(self.0 | rhs.0)
}
}

impl core::ops::BitAnd for TagSetFlags {
type Output = Self;

fn bitand(self, rhs: Self) -> Self::Output {
Self(self.0 & rhs.0)
}
}

impl core::ops::Not for TagSetFlags {
type Output = Self;

fn not(self) -> Self::Output {
Self(!self.0 & Self::all_bits())
}
}

/// A wrapper for the C `struct blk_mq_tag_set`.
///
/// `struct blk_mq_tag_set` contains a `struct list_head` and so must be pinned.
Expand All @@ -37,6 +111,16 @@ impl<T: Operations> TagSet<T> {
nr_hw_queues: u32,
num_tags: u32,
num_maps: u32,
) -> impl PinInit<Self, error::Error> {
Self::new_with_flags(nr_hw_queues, num_tags, num_maps, TagSetFlags::empty())
}

/// Try to create a new tag set with the given blk-mq flags.
pub fn new_with_flags(
nr_hw_queues: u32,
num_tags: u32,
num_maps: u32,
flags: TagSetFlags,
) -> impl PinInit<Self, error::Error> {
let tag_set: bindings::blk_mq_tag_set = pin_init::zeroed();
let tag_set: Result<_> = core::mem::size_of::<RequestDataWrapper>()
Expand All @@ -49,7 +133,7 @@ impl<T: Operations> TagSet<T> {
numa_node: bindings::NUMA_NO_NODE,
queue_depth: num_tags,
cmd_size,
flags: 0,
flags: flags.as_raw(),
driver_data: core::ptr::null_mut::<crate::ffi::c_void>(),
nr_maps: num_maps,
..tag_set
Expand Down
Loading