From nobody Sat Nov 23 14:46:23 2024 Received: from mail-lf1-f41.google.com (mail-lf1-f41.google.com [209.85.167.41]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B81DB1C68BD; Tue, 19 Nov 2024 11:24:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.41 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732015483; cv=none; b=p7VZWTGnUEZg+RC/cZf2Ur44mlkHmBWbLFvz2uO4QVES3QMXz8xYYlpjuu+fDkzGdqaocrCr24yJXpLY/J+TvY7DT7kVHzRIDulDMostsvCaf1GexX59m0uocsCqtBInZyOnDUaL8MWcTPlFfoB+ph7pPUX2580+Gz4ezCIxa4Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732015483; c=relaxed/simple; bh=snTqUG7s09jGXe3ajPlD0Twq9dDrU08jBXd87FsFqM8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=uO0uEUEHYJUC4qc9dehx8uHbrTJ+z9JcuN8BEad2qrsOVfN9jZr4qJfnayF6VKzz0clWML20n4k5jycU6vwce9G932jzS+2EZyjDlrJ7ISWaxaTFUIxJtZ54WbUPYVH41rJeIUhjOGHSJzPZDFcnrR3LorwSz46WVzcXAoZ/Yew= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Y6IgJbgM; arc=none smtp.client-ip=209.85.167.41 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Y6IgJbgM" Received: by mail-lf1-f41.google.com with SMTP id 2adb3069b0e04-53da4fd084dso5385867e87.0; Tue, 19 Nov 2024 03:24:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1732015480; x=1732620280; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=O5in6My0kdNSS1puRd/yLqubLQBCE2d2SsFq7ndctiY=; b=Y6IgJbgMAT/pt5vzlWqqJ1CmPw2dNfeozYPvmzF/CSZdZZhV/UfHpTXTE8rfEg5TOC EtvsiwYL2yE1gfYWpmXlFjDBEkk5jN6nmgwRgebv9Zu/wfIL73pNt1DREZVJI8HGgYFp MGl2WLzyDf9jaYqnp8qYQkaO/odRtc7Wwnjfs0vf+6Vj//K4rBRtxbZNjRaJBNFhzWlB +mHFEgMe1cM1gCy6+uuZcdtkDsY7+7uMiImqaGbqVMtdSEl1fUo+cMjLkMipoedQrbQw Hit+Smvz5Al5u1MZ1ph9RbmsWhVzKp15oiYiwgtgpcIWHVWQAhHK0hLbAHE3mx5Qk6nd XJ+A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1732015480; x=1732620280; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=O5in6My0kdNSS1puRd/yLqubLQBCE2d2SsFq7ndctiY=; b=j6gvhpkje+N4qaRkODRXPVbU67JlkgHtmiyjTlZWrro9oAWhHZ078v0U493XoNb9Vt IjBKgF68ypF7acopgq3tfcC53O/ZGGNn0JBd2blFPeCbrrdObAqPWABlQxFzzOFIikB+ lV4j2K8Zq5NWlLLqsGPiUZKbkK6SvKfYc2PQiVtk60hO6pT9MuvsShDX22iPplgi730V /T6aA5UO7QzDannQmgJLpuQIHP0YyB4i/fteN+VorXt41Jsg6qmALJyUrTznXWiWzNW7 McRkR3GSGSK+6vNcuoIvGVbDyW791QHH37fKhiLpX+wWZqx5UhEX0ZcnRQ/XncP/5aFd k7UA== X-Forwarded-Encrypted: i=1; AJvYcCV7iSEO83z2SqePPGlRxDV0gu3+sqmHq93qLmDa1IrXkjljqwdeqv/VkAZ+7HV10vKufezxhaNpw0RKn+4=@vger.kernel.org X-Gm-Message-State: AOJu0YzsvAqf/Iur7+ylAZ9R0Z0fM4aDzZdOLWYumta4sMauYDJFjfDf p2iqmJxQqNnfry8ZB/CpISHZ4PCF1jrdRUfHWN6udR1Ml8WlZibnFxClIQ== X-Google-Smtp-Source: AGHT+IEKjqLZdyXdfGQjRw6AYYj6v+Q15TvM5GNLUQ+CaJiPip4JE/yx1g/kjPZdw+FLybza4MV/MQ== X-Received: by 2002:a19:8c05:0:b0:53d:abc4:820f with SMTP id 2adb3069b0e04-53dbd47128bmr779557e87.6.1732015479658; Tue, 19 Nov 2024 03:24:39 -0800 (PST) Received: from abj-NUC9VXQNX.. (87-94-132-183.rev.dnainternet.fi. [87.94.132.183]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-53dbd478279sm271899e87.232.2024.11.19.03.24.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 19 Nov 2024 03:24:38 -0800 (PST) From: Abdiel Janulgue To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Wedson Almeida Filho , Valentin Obst , linux-kernel@vger.kernel.org (open list), Andrew Morton , linux-mm@kvack.org (open list:MEMORY MANAGEMENT), airlied@redhat.com, Abdiel Janulgue Subject: [PATCH v3 1/2] rust: page: use the page's reference count to decide when to free the allocation Date: Tue, 19 Nov 2024 13:24:02 +0200 Message-ID: <20241119112408.779243-2-abdiel.janulgue@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20241119112408.779243-1-abdiel.janulgue@gmail.com> References: <20241119112408.779243-1-abdiel.janulgue@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Ensure pages returned by the constructor are always reference counted. This requires that we replace the page pointer wrapper with Opaque instead of NonNull to make it possible to cast to a Page pointer from a raw struct page pointer which is needed to create an ARef instance. Signed-off-by: Abdiel Janulgue --- rust/bindings/bindings_helper.h | 1 + rust/helpers/page.c | 10 +++++++++ rust/kernel/page.rs | 38 ++++++++++++++++++++++----------- 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helpe= r.h index a80783fcbe04..daa3225a185f 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include diff --git a/rust/helpers/page.c b/rust/helpers/page.c index b3f2b8fbf87f..48d4481c1e33 100644 --- a/rust/helpers/page.c +++ b/rust/helpers/page.c @@ -17,3 +17,13 @@ void rust_helper_kunmap_local(const void *addr) { kunmap_local(addr); } + +void rust_helper_put_page(struct page *page) +{ + put_page(page); +} + +void rust_helper_get_page(struct page *page) +{ + get_page(page); +} diff --git a/rust/kernel/page.rs b/rust/kernel/page.rs index fdac6c375fe4..fdf7ee203597 100644 --- a/rust/kernel/page.rs +++ b/rust/kernel/page.rs @@ -8,6 +8,7 @@ error::code::*, error::Result, uaccess::UserSliceReader, + types::{Opaque, ARef}, }; use core::ptr::{self, NonNull}; =20 @@ -30,13 +31,14 @@ pub const fn page_align(addr: usize) -> usize { (addr + (PAGE_SIZE - 1)) & PAGE_MASK } =20 -/// A pointer to a page that owns the page allocation. +/// A pointer to a reference-counted page. /// /// # Invariants /// -/// The pointer is valid, and has ownership over the page. +/// The pointer is valid. +#[repr(transparent)] pub struct Page { - page: NonNull, + page: Opaque, } =20 // SAFETY: Pages have no logic that relies on them staying on a given thre= ad, so moving them across @@ -71,19 +73,23 @@ impl Page { /// let page =3D Page::alloc_page(GFP_KERNEL | __GFP_ZERO)?; /// # Ok(()) } /// ``` - pub fn alloc_page(flags: Flags) -> Result { + pub fn alloc_page(flags: Flags) -> Result, AllocError> { // SAFETY: Depending on the value of `gfp_flags`, this call may sl= eep. Other than that, it // is always safe to call this method. let page =3D unsafe { bindings::alloc_pages(flags.as_raw(), 0) }; - let page =3D NonNull::new(page).ok_or(AllocError)?; - // INVARIANT: We just successfully allocated a page, so we now hav= e ownership of the newly - // allocated page. We transfer that ownership to the new `Page` ob= ject. - Ok(Self { page }) + if page.is_null() { + return Err(AllocError); + } + // CAST: Self` is a `repr(transparent)` wrapper around `bindings::= page`. + let ptr =3D page.cast::(); + // INVARIANT: We just successfully allocated a page, ptr points to= the new `Page` object. + // SAFETY: According to invariant above ptr is valid. + Ok(unsafe { ARef::from_raw(NonNull::new_unchecked(ptr)) }) } =20 /// Returns a raw pointer to the page. pub fn as_ptr(&self) -> *mut bindings::page { - self.page.as_ptr() + self.page.get() } =20 /// Runs a piece of code with this page mapped to an address. @@ -252,9 +258,15 @@ pub unsafe fn copy_from_user_slice_raw( } } =20 -impl Drop for Page { - fn drop(&mut self) { - // SAFETY: By the type invariants, we have ownership of the page a= nd can free it. - unsafe { bindings::__free_pages(self.page.as_ptr(), 0) }; +// SAFETY: Instances of `Page` are always reference-counted. +unsafe impl crate::types::AlwaysRefCounted for Page { + fn inc_ref(&self) { + // SAFETY: The existence of a shared reference guarantees that the= refcount is non-zero. + unsafe { bindings::get_page(self.as_ptr()) }; + } + + unsafe fn dec_ref(obj: ptr::NonNull) { + // SAFETY: The safety requirements guarantee that the refcount is = non-zero. + unsafe { bindings::put_page(obj.cast().as_ptr()) } } } --=20 2.43.0 From nobody Sat Nov 23 14:46:23 2024 Received: from mail-lf1-f47.google.com (mail-lf1-f47.google.com [209.85.167.47]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 75D0A1C761C; Tue, 19 Nov 2024 11:24:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732015486; cv=none; b=uYm+ZJ3JZh3OTcPs855KJS4gjNw/BcprA1nh1PiDmDmEEgG9uIyxbzkUhtOeDopyEx7AvGjIH8pAMJu5CBSa4DNIdEtjYVai4zYMovrK1ggbyiGLnDEpZuEbHH6qzrYq+wl84NreNfnpf9MF/PV7SKK92UE4wC0hMCuMosN+8u0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1732015486; c=relaxed/simple; bh=hCtDuutp78iLtmROwjXb1QaB1d1QC/MDZD6AHGd5tjQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=clTlSvJMDxk0ermtmiAnQC5jF6Ih6rZRDRQMyTrRPpn8rX+RgoC0VB4gWnT5Um8rF0kAtyISHn2tHMDof1yQlgUdmodHfHBeGISMd9hyKGJcaMxI35ibAVpzfy7cW2TwhFmhkIm627GCREROsQ5BmOYNkDiL84VbhGlec86wgr8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=BATn507I; arc=none smtp.client-ip=209.85.167.47 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="BATn507I" Received: by mail-lf1-f47.google.com with SMTP id 2adb3069b0e04-53da3b911b9so4752007e87.2; Tue, 19 Nov 2024 03:24:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1732015483; x=1732620283; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=YSlE2AobDBjXj75h9dVNPb0c+CAMh4Q+j+w/qWySOZo=; b=BATn507IVRRvKM4vh6SpG9weus2GCaTzmSnX0KyhL51vcrEhQ154QiILBsYeywmJTH KwmPCNZxtnwW/4kIXMBy78NAFlh2hsUwaB30cKTPY4ECIDr3x4IACnwjA9BQbwzTmVXK CcPDSAY+Gh/YEHeVnK6Z/hPvxTTVDgQSWLW9LvgFMnqXOt9Fdt+Ctk77umjxgqe22P5E CYG22Ekuxh9oW/63ZGlyciSG7WNkEzw7ZmZbG1ss47UJDBJuGdZ4ocsD6MxRwVMhQJWP v4nWo4lPl0xxJiUq93J1pIsh/Kc4XUH474g+RfwrY2/kpss1WjJz7cgVm2RRBZGsqCat yK8Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1732015483; x=1732620283; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=YSlE2AobDBjXj75h9dVNPb0c+CAMh4Q+j+w/qWySOZo=; b=l+MmDjvZ2jS3uWCfVEGX6OUtqsRNU/iWBuZyIvQ6Ect04B328R2AMRbb6NbZpTg3Yd 0wCxrLUOYb0AJCQD1CJ9e+Apjm9P9jt20QZxZ0hYvZ6cQprvW0500eKV7VPGBKMvJCus 3qDvITSj5Gmh3T31AUtd8n+dlnWtnApZneqoxXh6FzqSZyRVXKfd4CkIrr7NGArh5K0f FU42Ulo1Hd+b87a6Yhf4jc7YyhldRsK00ZuuleIHWZHhcwakFrN1Z31ZpuNJ+EW8yOKY 00T3EZZWCdiaFHGQoFox0MlQi5g/HHGfultwmq/7xJcoWBHdueeKucIDiQeMQ6jL/xlm bVGg== X-Forwarded-Encrypted: i=1; AJvYcCWOqvqVlm4H66qpiJoQn0nl9ZKzr2/buKwSEdt8tS5148JQtga5htoHvYIDd+t52khp3XXmi0+ROBRiAAo=@vger.kernel.org X-Gm-Message-State: AOJu0YwMvskRlZCAS6O++arjjnvtAzFQCKXB4kso5ovVwVhYiJEHr6NZ uikhhMWyaCYpdUDCFJts4Q8Mp1mrNoJgJemeupensfeGbSG/xXH21QbEJw== X-Google-Smtp-Source: AGHT+IHClMNtG+d6fxlDY8MwP736UMKm9XCqQoUw9TgnQS0hL5N5cc0pjQHQFoHV43cUof90JEBn9w== X-Received: by 2002:a05:6512:3b86:b0:53d:a24b:db0f with SMTP id 2adb3069b0e04-53dab3c50b3mr6607291e87.57.1732015482420; Tue, 19 Nov 2024 03:24:42 -0800 (PST) Received: from abj-NUC9VXQNX.. (87-94-132-183.rev.dnainternet.fi. [87.94.132.183]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-53dbd478279sm271899e87.232.2024.11.19.03.24.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 19 Nov 2024 03:24:41 -0800 (PST) From: Abdiel Janulgue To: rust-for-linux@vger.kernel.org Cc: Miguel Ojeda , Alex Gaynor , Boqun Feng , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Wedson Almeida Filho , Valentin Obst , linux-kernel@vger.kernel.org (open list), Andrew Morton , linux-mm@kvack.org (open list:MEMORY MANAGEMENT), airlied@redhat.com, Abdiel Janulgue Subject: [PATCH v3 2/2] rust: page: Extend support to existing struct page mappings Date: Tue, 19 Nov 2024 13:24:03 +0200 Message-ID: <20241119112408.779243-3-abdiel.janulgue@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20241119112408.779243-1-abdiel.janulgue@gmail.com> References: <20241119112408.779243-1-abdiel.janulgue@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Extend Page to support pages that are not allocated by the constructor, for example, those returned by vmalloc_to_page() or virt_to_page(). Since we don't own those pages we shouldn't Drop them either. Hence we take advantage of the switch to Opaque so we can cast to a Page pointer from a struct page pointer and be able to retrieve the reference on an existing struct page mapping. In this case no destructor will be called since we are not instantiating a new Page instance. The new page_slice_to_page wrapper ensures that it explicity accepts only page-sized chunks. Signed-off-by: Abdiel Janulgue --- rust/helpers/page.c | 10 +++++ rust/kernel/page.rs | 97 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 106 insertions(+), 1 deletion(-) diff --git a/rust/helpers/page.c b/rust/helpers/page.c index 48d4481c1e33..784563924b83 100644 --- a/rust/helpers/page.c +++ b/rust/helpers/page.c @@ -27,3 +27,13 @@ void rust_helper_get_page(struct page *page) { get_page(page); } + +struct page *rust_helper_virt_to_page(const void *kaddr) +{ + return virt_to_page(kaddr); +} + +bool rust_helper_virt_addr_valid(const void *kaddr) +{ + return virt_addr_valid(kaddr); +} diff --git a/rust/kernel/page.rs b/rust/kernel/page.rs index fdf7ee203597..d0a896f53afb 100644 --- a/rust/kernel/page.rs +++ b/rust/kernel/page.rs @@ -3,7 +3,7 @@ //! Kernel page allocation and management. =20 use crate::{ - alloc::{AllocError, Flags}, + alloc::{AllocError, Allocator, Flags, VVec, KVec, KVVec, Vec, flags::*= }, bindings, error::code::*, error::Result, @@ -87,6 +87,49 @@ pub fn alloc_page(flags: Flags) -> Result, Al= locError> { Ok(unsafe { ARef::from_raw(NonNull::new_unchecked(ptr)) }) } =20 + /// Create a page object from a buffer which is associated with an exi= sting C `struct page`. + /// + /// This function ensures it takes a page-sized buffer as represented = by `PageSlice`. + /// + /// # Examples + /// + /// ``` + /// use kernel::page::*; + /// + /// let somedata: [u8; PAGE_SIZE * 2] =3D [0; PAGE_SIZE * 2]; + /// let buf: &[u8] =3D &somedata; + /// let pages: VVec =3D buf.try_into()?; + /// let page =3D Page::page_slice_to_page(&pages[0])?; + /// # Ok::<(), Error>(()) + /// ``` + pub fn page_slice_to_page<'a>(page: &PageSlice) -> Result<&'a Self> + { + let ptr: *const core::ffi::c_void =3D page.0.as_ptr() as _; + if ptr.is_null() { + return Err(EINVAL) + } + // SAFETY: We've checked that `ptr` is non-null, hence it's safe t= o call this method. + let page =3D if unsafe { bindings::is_vmalloc_addr(ptr) } { + // SAFETY: We've checked that `ptr` is non-null and within the= vmalloc range, hence + // it's safe to call this method. + unsafe { bindings::vmalloc_to_page(ptr) } + // SAFETY: We've checked that `ptr` is non-null, hence it's safe t= o call this method. + } else if unsafe { bindings::virt_addr_valid(ptr) } { + // SAFETY: We've checked that `ptr` is non-null and a valid vi= rtual address, hence + // it's safe to call this method. + unsafe { bindings::virt_to_page(ptr) } + } else { + ptr::null_mut() + }; + if page.is_null() { + return Err(EINVAL); + } + // CAST: `Self` is a `repr(transparent)` wrapper around `bindings:= :page`. + // SAFETY: We just successfully retrieved an existing `bindings::p= age`, therefore + // dereferencing the page pointer is valid. + Ok(unsafe { &*page.cast() }) + } + /// Returns a raw pointer to the page. pub fn as_ptr(&self) -> *mut bindings::page { self.page.get() @@ -270,3 +313,55 @@ unsafe fn dec_ref(obj: ptr::NonNull) { unsafe { bindings::put_page(obj.cast().as_ptr()) } } } + +/// A page-aligned, page-sized object. +/// +/// This is used for convenience to convert a large buffer into an array o= f page-sized chunks +/// allocated with the kernel's allocators which can then be used in the +/// `Page::page_slice_to_page` wrapper. +/// +// FIXME: This should be `PAGE_SIZE`, but the compiler rejects everything = except a literal +// integer argument for the `repr(align)` attribute. +#[repr(align(4096))] +pub struct PageSlice([u8; PAGE_SIZE]); + +fn to_vec_with_allocator(val: &[u8]) -> Result, AllocError> { + let mut k =3D Vec::::new(); + let pages =3D page_align(val.len()) >> PAGE_SHIFT; + match k.reserve(pages, GFP_KERNEL) { + Ok(()) =3D> { + // SAFETY: from above, the length should be equal to the vecto= r's capacity + unsafe { k.set_len(pages); } + // SAFETY: src buffer sized val.len() does not overlap with ds= t buffer since + // the dst buffer's size is val.len() padded up to a multiple = of PAGE_SIZE. + unsafe { ptr::copy_nonoverlapping(val.as_ptr(), k.as_mut_ptr()= as *mut u8, + val.len()) }; + Ok(k) + }, + Err(_) =3D> Err(AllocError), + } +} + +impl TryFrom<&[u8]> for VVec { + type Error =3D AllocError; + + fn try_from(val: &[u8]) -> Result { + to_vec_with_allocator(val) + } +} + +impl TryFrom<&[u8]> for KVec { + type Error =3D AllocError; + + fn try_from(val: &[u8]) -> Result { + to_vec_with_allocator(val) + } +} + +impl TryFrom<&[u8]> for KVVec { + type Error =3D AllocError; + + fn try_from(val: &[u8]) -> Result { + to_vec_with_allocator(val) + } +} --=20 2.43.0