From nobody Tue Feb 10 04:03:36 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B8086EB64DD for ; Sun, 25 Jun 2023 12:18:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232210AbjFYMSN (ORCPT ); Sun, 25 Jun 2023 08:18:13 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49644 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232140AbjFYMSA (ORCPT ); Sun, 25 Jun 2023 08:18:00 -0400 Received: from out0-216.mail.aliyun.com (out0-216.mail.aliyun.com [140.205.0.216]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8E82CE67; Sun, 25 Jun 2023 05:17:40 -0700 (PDT) X-Alimail-AntiSpam: AC=PASS;BC=-1|-1;BR=01201311R101e4;CH=green;DM=||false|;DS=||;FP=0|-1|-1|-1|0|-1|-1|-1;HT=ay29a033018047187;MF=changxian.cqs@antgroup.com;NM=1;PH=DS;RN=13;SR=0;TI=SMTPD_---.TdIoyYF_1687695455; Received: from localhost(mailfrom:changxian.cqs@antgroup.com fp:SMTPD_---.TdIoyYF_1687695455) by smtp.aliyun-inc.com; Sun, 25 Jun 2023 20:17:35 +0800 From: "Qingsong Chen" To: linux-kernel@vger.kernel.org Cc: "=?UTF-8?B?55Sw5rSq5Lqu?=" , "Qingsong Chen" , "Miguel Ojeda" , "Alex Gaynor" , "Wedson Almeida Filho" , "Boqun Feng" , "Gary Guo" , "=?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?=" , "Benno Lossin" , "Martin Rodriguez Reboredo" , "Alice Ryhl" , Subject: [RFC PATCH 6/8] rust: kernel: add DAX related TargetOperations Date: Sun, 25 Jun 2023 20:16:55 +0800 Message-Id: <20230625121657.3631109-7-changxian.cqs@antgroup.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230625121657.3631109-1-changxian.cqs@antgroup.com> References: <20230625121657.3631109-1-changxian.cqs@antgroup.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" - Add `direct_access` to translate `pgoff` to `pfn`. - Add `dax_zero_page_range` to zero page range. - Add `dax_recovery_write` to recover a poisoned range. Signed-off-by: Qingsong Chen --- rust/bindings/bindings_helper.h | 1 + rust/kernel/device_mapper.rs | 139 +++++++++++++++++++++++++++++++- 2 files changed, 139 insertions(+), 1 deletion(-) diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helpe= r.h index 807fc9cf41b8..edda3a9173dd 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -12,6 +12,7 @@ #include #include #include +#include =20 /* `bindgen` gets confused at certain things. */ const gfp_t BINDINGS_GFP_KERNEL =3D GFP_KERNEL; diff --git a/rust/kernel/device_mapper.rs b/rust/kernel/device_mapper.rs index ba13294f2d0b..d2c9d0a5bcd5 100644 --- a/rust/kernel/device_mapper.rs +++ b/rust/kernel/device_mapper.rs @@ -5,7 +5,7 @@ //! C header: [`include/linux/device-mapper.h`](../../../../include/linux/= device-mapper.h) =20 use core::marker::PhantomData; -use core::ops::Index; +use core::ops::{Index, Range}; use core::ptr::{addr_of, NonNull}; =20 use crate::error::to_result; @@ -136,6 +136,39 @@ fn iterate_devices(t: &mut Target) -> Result, limits: &mut QueueLimits) { unimplemented!() } + + /// Translate a device-relative logical-page-offset into an + /// absolute physical pfn. + /// + /// Return the `addr` and the `pages` available for `DAX` at + /// that pfn, if success. + #[allow(unused)] + fn direct_access( + t: &mut Target, + pgoff: usize, + nr_pages: usize, + mode: DaxMode, + ) -> Result<(usize, Range)> { + unimplemented!() + } + + /// Zero page range. + #[allow(unused)] + fn dax_zero_page_range(t: &mut Target, pgoff: usize, nr_pages: u= size) -> Result { + unimplemented!() + } + + /// Recover a poisoned range by DAX device driver capable of + /// clearing poison. + #[allow(unused)] + fn dax_recovery_write( + t: &mut Target, + iov_iter: Pin<&mut IovIter>, + pgoff: usize, + region: Range, + ) -> usize { + unimplemented!() + } } =20 /// Wrap the kernel struct `target_type`. @@ -214,6 +247,17 @@ pub fn register( (HAS_PREPARE_IOCTL, prepare_ioctl, dm_prepare_ioctl_fn= ), (HAS_ITERATE_DEVICES, iterate_devices, dm_iterate_devi= ces_fn), (HAS_IO_HINTS, io_hints, dm_io_hints_fn), + (HAS_DIRECT_ACCESS, direct_access, dm_dax_direct_acces= s_fn), + ( + HAS_DAX_ZERO_PAGE_RANGE, + dax_zero_page_range, + dm_dax_zero_page_range_fn + ), + ( + HAS_DAX_RECOVERY_WRITE, + dax_recovery_write, + dm_dax_recovery_write_fn + ), ); =20 to_result(bindings::dm_register_target(tt)) @@ -494,6 +538,60 @@ impl TargetType { T::io_hints(t, limits); } } + unsafe extern "C" fn dm_dax_direct_access_fn( + ti: *mut bindings::dm_target, + pgoff: core::ffi::c_ulong, + nr_pages: core::ffi::c_long, + mode: bindings::dax_access_mode, + kaddr: *mut *mut core::ffi::c_void, + pfn: *mut bindings::pfn_t, + ) -> core::ffi::c_long { + // SAFETY: the kernel should pass valid `dm_target`, `kaddr` and + // `pfn` pointers. + unsafe { + let t =3D Target::borrow_mut(ti); + match T::direct_access(t, pgoff as _, nr_pages as _, mode.into= ()) { + Ok((addr, pages)) =3D> { + *kaddr =3D addr as _; + (*pfn).val =3D pages.start as _; + pages.len() as _ + } + Err(e) =3D> e.to_errno() as _, + } + } + } + unsafe extern "C" fn dm_dax_zero_page_range_fn( + ti: *mut bindings::dm_target, + pgoff: core::ffi::c_ulong, + nr_pages: usize, + ) -> core::ffi::c_int { + // SAFETY: the kernel should pass valid `dm_target` pointer. + unsafe { + let t =3D Target::borrow_mut(ti); + T::dax_zero_page_range(t, pgoff as _, nr_pages as _) + .map_or_else(|e| e.to_errno(), |_| 0) + } + } + unsafe extern "C" fn dm_dax_recovery_write_fn( + ti: *mut bindings::dm_target, + pgoff: core::ffi::c_ulong, + addr: *mut core::ffi::c_void, + bytes: usize, + i: *mut bindings::iov_iter, + ) -> usize { + let region =3D Range { + start: addr as usize, + end: (addr as usize) + bytes, + }; + + // SAFETY: the kernel should pass valid `dm_target` and `iov_iter` + // pointers. + unsafe { + let t =3D Target::borrow_mut(ti); + let iov_iter =3D IovIter::from_raw(i); + T::dax_recovery_write(t, iov_iter, pgoff as _, region) + } + } } =20 /// Wrap the kernel struct `dm_target`. @@ -903,3 +1001,42 @@ unsafe fn borrow_mut<'a>(ptr: *mut bindings::queue_li= mits) -> &'a mut Self { unsafe { &mut *(ptr as *mut Self) } } } + +/// Define dax direct_access mode. +pub enum DaxMode { + /// Normal dax access. + Access, + + /// Recovery write. + RecoveryWrite, + + /// Undefined. + Undefined, +} + +impl From for DaxMode { + fn from(value: i32) -> Self { + match value { + bindings::dax_access_mode_DAX_ACCESS =3D> Self::Access, + bindings::dax_access_mode_DAX_RECOVERY_WRITE =3D> Self::Recove= ryWrite, + _ =3D> Self::Undefined, + } + } +} + +/// Wrap the kernel struct `iov_iter`. +/// +/// Dummy. +#[allow(dead_code)] +#[pin_data] +pub struct IovIter { + #[pin] + opaque: Opaque, +} + +impl IovIter { + unsafe fn from_raw<'a>(ptr: *mut bindings::iov_iter) -> Pin<&'a mut Se= lf> { + // SAFETY: the caller should pass a valid `ptr`. + unsafe { Pin::new_unchecked(&mut *(ptr as *mut Self)) } + } +} --=20 2.40.1