rnull.rs 2.8 KB

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