lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20230625121657.3631109-6-changxian.cqs@antgroup.com>
Date:   Sun, 25 Jun 2023 20:16:54 +0800
From:   "Qingsong Chen" <changxian.cqs@...group.com>
To:     linux-kernel@...r.kernel.org
Cc:     "田洪亮" <tate.thl@...group.com>,
        "Qingsong Chen" <changxian.cqs@...group.com>,
        "Miguel Ojeda" <ojeda@...nel.org>,
        "Alex Gaynor" <alex.gaynor@...il.com>,
        "Wedson Almeida Filho" <wedsonaf@...il.com>,
        "Boqun Feng" <boqun.feng@...il.com>, "Gary Guo" <gary@...yguo.net>,
        "Björn Roy Baron" <bjorn3_gh@...tonmail.com>,
        "Benno Lossin" <benno.lossin@...ton.me>,
        <rust-for-linux@...r.kernel.org>
Subject: [RFC PATCH 5/8] rust: kernel: add underlying device related TargetOperations

- Add `prepare_ioctl` to pass ioctls to underlying device.
- Add `iterate_devices` to iterate underlying devices.
- Add `io_hints` to setup target request queue limits.

Signed-off-by: Qingsong Chen <changxian.cqs@...group.com>
---
 rust/kernel/device_mapper.rs | 101 +++++++++++++++++++++++++++++++++++
 1 file changed, 101 insertions(+)

diff --git a/rust/kernel/device_mapper.rs b/rust/kernel/device_mapper.rs
index 9a62208fda56..ba13294f2d0b 100644
--- a/rust/kernel/device_mapper.rs
+++ b/rust/kernel/device_mapper.rs
@@ -118,6 +118,24 @@ fn message(t: &mut Target<Self>, args: Args) -> Result<CString> {
     fn report_zones(t: &mut Target<Self>, args: &mut [ReportZonesArgs]) -> Result {
         unimplemented!()
     }
+
+    /// Pass on ioctl to the underlying device.
+    #[allow(unused)]
+    fn prepare_ioctl(t: &mut Target<Self>) -> (i32, Option<NonNull<TargetDevice<Self>>>) {
+        unimplemented!()
+    }
+
+    /// Iterate the underlying devices.
+    #[allow(unused)]
+    fn iterate_devices(t: &mut Target<Self>) -> Result<Box<dyn Iterator<Item = IterDevice<Self>>>> {
+        unimplemented!()
+    }
+
+    /// Setup target request queue limits.
+    #[allow(unused)]
+    fn io_hints(t: &mut Target<Self>, limits: &mut QueueLimits) {
+        unimplemented!()
+    }
 }
 
 /// Wrap the kernel struct `target_type`.
@@ -193,6 +211,9 @@ pub fn register<T: TargetOperations>(
                     (HAS_STATUS, status, dm_status_fn),
                     (HAS_MESSAGE, message, dm_message_fn),
                     (HAS_REPORT_ZONES, report_zones, dm_report_zones_fn),
+                    (HAS_PREPARE_IOCTL, prepare_ioctl, dm_prepare_ioctl_fn),
+                    (HAS_ITERATE_DEVICES, iterate_devices, dm_iterate_devices_fn),
+                    (HAS_IO_HINTS, io_hints, dm_io_hints_fn),
                 );
 
                 to_result(bindings::dm_register_target(tt))
@@ -411,6 +432,68 @@ impl TargetType {
         };
         T::report_zones(t, args).map_or_else(|e| e.to_errno(), |_| 0)
     }
+    unsafe extern "C" fn dm_prepare_ioctl_fn<T: TargetOperations>(
+        ti: *mut bindings::dm_target,
+        bdev: *mut *mut bindings::block_device,
+    ) -> core::ffi::c_int {
+        // SAFETY: the kernel should pass valid `dm_target` pointer.
+        let t = unsafe { Target::borrow_mut(ti) };
+
+        match T::prepare_ioctl(t) {
+            (err, None) => err,
+            // SAFETY: `td` and `dev` is `NonNull`, both of them are valid.
+            (ret, Some(td)) => unsafe {
+                let dm_dev = td.as_ref().dev.as_ptr();
+                let block_dev = (*dm_dev).bdev;
+                *bdev = block_dev;
+                ret
+            },
+        }
+    }
+    unsafe extern "C" fn dm_iterate_devices_fn<T: TargetOperations>(
+        ti: *mut bindings::dm_target,
+        fn_: bindings::iterate_devices_callout_fn,
+        data: *mut core::ffi::c_void,
+    ) -> core::ffi::c_int {
+        let Some(fn_) = fn_ else {
+            pr_warn!("Invalid iterate_devices_callout_fn, skipped!");
+            return 0;
+        };
+
+        // SAFETY: the kernel should pass valid `dm_target` pointer.
+        let t = unsafe { Target::borrow_mut(ti) };
+        let devices = match T::iterate_devices(t) {
+            Err(e) => return e.to_errno(),
+            Ok(devices) => devices,
+        };
+
+        let mut ret = 0;
+        for (target_device, start, len) in devices {
+            // SAFETY: `target_device` is `NonNull`, it is also valid.
+            // `fn_` is checked above, it is non-null, and the kernel
+            // should pass valid `iterate_devices_callout_fn`.
+            unsafe {
+                let dev = target_device.as_ref().dev.as_ptr();
+                ret = fn_(ti, dev, start as _, len as _, data);
+                if ret != 0 {
+                    break;
+                }
+            }
+        }
+        ret
+    }
+    unsafe extern "C" fn dm_io_hints_fn<T: TargetOperations>(
+        ti: *mut bindings::dm_target,
+        limits: *mut bindings::queue_limits,
+    ) {
+        // SAFETY: the kernel should pass valid `dm_target` and `queue_limits`
+        // pointers.
+        unsafe {
+            let t = Target::borrow_mut(ti);
+            let limits = QueueLimits::borrow_mut(limits);
+            T::io_hints(t, limits);
+        }
+    }
 }
 
 /// Wrap the kernel struct `dm_target`.
@@ -549,6 +632,12 @@ fn drop(&mut self) {
     }
 }
 
+/// Gather info about underlying device of target.
+///
+/// The first is the [`TargetDevice`], the second is the start sector of
+/// the device, and the third is the length (in sectors) of the device.
+pub type IterDevice<T> = (NonNull<TargetDevice<T>>, usize, usize);
+
 /// The return values of target map function, i.e., [`TargetOperations::map`].
 #[repr(u32)]
 pub enum MapState {
@@ -802,3 +891,15 @@ fn from(value: u32) -> Self {
         }
     }
 }
+
+/// Wrap the kernel struct `queue_limits`.
+///
+/// Dummy.
+pub struct QueueLimits(Opaque<bindings::queue_limits>);
+
+impl QueueLimits {
+    unsafe fn borrow_mut<'a>(ptr: *mut bindings::queue_limits) -> &'a mut Self {
+        // SAFETY: the caller should pass a valid `ptr`.
+        unsafe { &mut *(ptr as *mut Self) }
+    }
+}
-- 
2.40.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ