Add a configfs attribute to configure the virtual memory boundary mask for the rnull block device. This allows testing how drivers and filesystems handle devices with specific alignment requirements. Signed-off-by: Andreas Hindborg --- drivers/block/rnull/configfs.rs | 5 +++++ drivers/block/rnull/rnull.rs | 17 ++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/drivers/block/rnull/configfs.rs b/drivers/block/rnull/configfs.rs index 9eaace8b4257e..8b9ad8a1a243b 100644 --- a/drivers/block/rnull/configfs.rs +++ b/drivers/block/rnull/configfs.rs @@ -123,6 +123,7 @@ fn make_group( poll_queues: 27, fua: 28, max_sectors: 29, + virt_boundary: 30, ], }; @@ -210,6 +211,7 @@ fn make_group( #[cfg(CONFIG_BLK_DEV_RUST_NULL_FAULT_INJECTION)] init_hctx_inject, max_sectors: 0, + virt_boundary: false, }), }), default_groups, @@ -293,6 +295,7 @@ struct DeviceConfigInner { #[cfg(CONFIG_BLK_DEV_RUST_NULL_FAULT_INJECTION)] init_hctx_inject: Arc, max_sectors: u32, + virt_boundary: bool, } #[vtable] @@ -351,6 +354,7 @@ fn store(this: &DeviceConfig, page: &[u8]) -> Result { #[cfg(CONFIG_BLK_DEV_RUST_NULL_FAULT_INJECTION)] timeout_inject: guard.timeout_inject.clone(), max_sectors: guard.max_sectors, + virt_boundary: guard.virt_boundary, })?); guard.powered = true; } else if guard.powered && !power_op { @@ -629,3 +633,4 @@ fn store(this: &DeviceConfig, page: &[u8]) -> Result { } configfs_simple_bool_field!(DeviceConfig, 28, fua); configfs_simple_field!(DeviceConfig, 29, max_sectors, u32); +configfs_simple_bool_field!(DeviceConfig, 30, virt_boundary); diff --git a/drivers/block/rnull/rnull.rs b/drivers/block/rnull/rnull.rs index 495a810f4f4e1..dfdb56bd76f52 100644 --- a/drivers/block/rnull/rnull.rs +++ b/drivers/block/rnull/rnull.rs @@ -28,7 +28,10 @@ BadBlocks, // }, bio::Segment, - error::{BlkError, BlkResult}, + error::{ + BlkError, + BlkResult, // + }, mq::{ self, gen_disk::{ @@ -53,6 +56,7 @@ impl_has_hr_timer, new_mutex, new_spinlock, + page::PAGE_SIZE, pr_info, prelude::*, revocable::Revocable, @@ -210,6 +214,10 @@ default: 0, description: "Maximum size of a command (in 512B sectors)", }, + virt_boundary: u8 { + default: 0, + description: "Set alignment requirement for IO buffers to be page size.", + }, }, } @@ -287,6 +295,7 @@ fn init(_module: &'static ThisModule) -> impl PinInit { #[cfg(CONFIG_BLK_DEV_RUST_NULL_FAULT_INJECTION)] timeout_inject: Arc::pin_init(FaultConfig::new(c"timeout_inject"), GFP_KERNEL)?, max_sectors: *module_parameters::max_sectors.value(), + virt_boundary: *module_parameters::virt_boundary.value() != 0, })?; disks.push(disk, GFP_KERNEL)?; } @@ -342,6 +351,7 @@ struct NullBlkOptions<'a> { #[cfg(CONFIG_BLK_DEV_RUST_NULL_FAULT_INJECTION)] timeout_inject: Arc, max_sectors: u32, + virt_boundary: bool, } static SHARED_TAG_SET: SetOnce>> = SetOnce::new(); @@ -414,6 +424,7 @@ fn new(options: NullBlkOptions<'_>) -> Result>> { #[cfg(CONFIG_BLK_DEV_RUST_NULL_FAULT_INJECTION)] timeout_inject, max_sectors, + virt_boundary, } = options; let mut flags = mq::tag_set::Flags::default(); @@ -512,6 +523,10 @@ fn new(options: NullBlkOptions<'_>) -> Result>> { .forced_unit_access(forced_unit_access && storage.cache_enabled()) .max_sectors(max_sectors); + if virt_boundary { + builder = builder.virt_boundary_mask(PAGE_SIZE - 1); + } + #[cfg(CONFIG_BLK_DEV_ZONED)] { builder = builder -- 2.51.2