Message ID | 20250411-no-offset-v3-1-c0b174640ec3@gmail.com (mailing list archive) |
---|---|
State | Handled Elsewhere |
Delegated to: | Bjorn Helgaas |
Headers | show |
Series | [v3] rust: workqueue: remove HasWork::OFFSET | expand |
On Fri, Apr 11, 2025 at 4:08 PM Tamir Duberstein <tamird@gmail.com> wrote: > > Implement `HasWork::work_container_of` in `impl_has_work!`, narrowing > the interface of `HasWork` and replacing pointer arithmetic with > `container_of!`. Remove the provided implementation of > `HasWork::get_work_offset` without replacement; an implementation is > already generated in `impl_has_work!`. Remove the `Self: Sized` bound on > `HasWork::work_container_of` which was apparently necessary to access > `OFFSET` as `OFFSET` no longer exists. > > A similar API change was discussed on the hrtimer series[1]. > > Link: https://lore.kernel.org/all/20250224-hrtimer-v3-v6-12-rc2-v9-1-5bd3bf0ce6cc@kernel.org/ [1] > Reviewed-by: Benno Lossin <benno.lossin@proton.me> > Reviewed-by: Alice Ryhl <aliceryhl@google.com> > Tested-by: Alice Ryhl <aliceryhl@google.com> > Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org> > Signed-off-by: Tamir Duberstein <tamird@gmail.com> Seems reasonable enough. Reviewed-by: Alice Ryhl <aliceryhl@google.com> > --- > Changes in v3: > - Extract first commit to its own series as it is shared with other > series. > - Reword `HasWork` safety comment. > - Link to v2: https://lore.kernel.org/r/20250409-no-offset-v2-0-dda8e141a909@gmail.com > > Changes in v2: > - Rebase on v6.15-rc1. > - Add WORKQUEUE maintainers to cc. > - Link to v1: https://lore.kernel.org/r/20250307-no-offset-v1-0-0c728f63b69c@gmail.com > --- > rust/kernel/workqueue.rs | 50 ++++++++++++++++-------------------------------- > 1 file changed, 17 insertions(+), 33 deletions(-) > > diff --git a/rust/kernel/workqueue.rs b/rust/kernel/workqueue.rs > index f98bd02b838f..d092112d843f 100644 > --- a/rust/kernel/workqueue.rs > +++ b/rust/kernel/workqueue.rs > @@ -429,51 +429,28 @@ pub unsafe fn raw_get(ptr: *const Self) -> *mut bindings::work_struct { > /// > /// # Safety > /// > -/// The [`OFFSET`] constant must be the offset of a field in `Self` of type [`Work<T, ID>`]. The > -/// methods on this trait must have exactly the behavior that the definitions given below have. > +/// The methods [`raw_get_work`] and [`work_container_of`] must return valid pointers and must be > +/// true inverses of each other; that is, they must satisfy the following invariants: > +/// - `work_container_of(raw_get_work(ptr)) == ptr` for any `ptr: *mut Self`. > +/// - `raw_get_work(work_container_of(ptr)) == ptr` for any `ptr: *mut Work<T, ID>`. > /// > /// [`impl_has_work!`]: crate::impl_has_work > -/// [`OFFSET`]: HasWork::OFFSET > +/// [`raw_get_work`]: HasWork::raw_get_work > +/// [`work_container_of`]: HasWork::work_container_of > pub unsafe trait HasWork<T, const ID: u64 = 0> { > - /// The offset of the [`Work<T, ID>`] field. > - const OFFSET: usize; > - > - /// Returns the offset of the [`Work<T, ID>`] field. > - /// > - /// This method exists because the [`OFFSET`] constant cannot be accessed if the type is not > - /// [`Sized`]. > - /// > - /// [`OFFSET`]: HasWork::OFFSET > - #[inline] > - fn get_work_offset(&self) -> usize { > - Self::OFFSET > - } > - > /// Returns a pointer to the [`Work<T, ID>`] field. > /// > /// # Safety > /// > /// The provided pointer must point at a valid struct of type `Self`. > - #[inline] > - unsafe fn raw_get_work(ptr: *mut Self) -> *mut Work<T, ID> { > - // SAFETY: The caller promises that the pointer is valid. > - unsafe { (ptr as *mut u8).add(Self::OFFSET) as *mut Work<T, ID> } > - } > + unsafe fn raw_get_work(ptr: *mut Self) -> *mut Work<T, ID>; > > /// Returns a pointer to the struct containing the [`Work<T, ID>`] field. > /// > /// # Safety > /// > /// The pointer must point at a [`Work<T, ID>`] field in a struct of type `Self`. > - #[inline] > - unsafe fn work_container_of(ptr: *mut Work<T, ID>) -> *mut Self > - where > - Self: Sized, > - { > - // SAFETY: The caller promises that the pointer points at a field of the right type in the > - // right kind of struct. > - unsafe { (ptr as *mut u8).sub(Self::OFFSET) as *mut Self } > - } > + unsafe fn work_container_of(ptr: *mut Work<T, ID>) -> *mut Self; > } > > /// Used to safely implement the [`HasWork<T, ID>`] trait. > @@ -504,8 +481,6 @@ macro_rules! impl_has_work { > // SAFETY: The implementation of `raw_get_work` only compiles if the field has the right > // type. > unsafe impl$(<$($generics)+>)? $crate::workqueue::HasWork<$work_type $(, $id)?> for $self { > - const OFFSET: usize = ::core::mem::offset_of!(Self, $field) as usize; > - > #[inline] > unsafe fn raw_get_work(ptr: *mut Self) -> *mut $crate::workqueue::Work<$work_type $(, $id)?> { > // SAFETY: The caller promises that the pointer is not dangling. > @@ -513,6 +488,15 @@ unsafe fn raw_get_work(ptr: *mut Self) -> *mut $crate::workqueue::Work<$work_typ > ::core::ptr::addr_of_mut!((*ptr).$field) > } > } > + > + #[inline] > + unsafe fn work_container_of( > + ptr: *mut $crate::workqueue::Work<$work_type $(, $id)?>, > + ) -> *mut Self { > + // SAFETY: The caller promises that the pointer points at a field of the right type > + // in the right kind of struct. > + unsafe { $crate::container_of!(ptr, Self, $field) } > + } > } > )*}; > } > > --- > base-commit: 0af2f6be1b4281385b618cb86ad946eded089ac8 > change-id: 20250307-no-offset-e463667a72fb > prerequisite-change-id: 20250409-container-of-mutness-b153dab4388d:v1 > prerequisite-patch-id: 53d5889db599267f87642bb0ae3063c29bc24863 > > Best regards, > -- > Tamir Duberstein <tamird@gmail.com> >
On Fri, Apr 11, 2025 at 04:14:35PM +0200, Alice Ryhl wrote: > On Fri, Apr 11, 2025 at 4:08 PM Tamir Duberstein <tamird@gmail.com> wrote: > > > > Implement `HasWork::work_container_of` in `impl_has_work!`, narrowing > > the interface of `HasWork` and replacing pointer arithmetic with > > `container_of!`. Remove the provided implementation of > > `HasWork::get_work_offset` without replacement; an implementation is > > already generated in `impl_has_work!`. Remove the `Self: Sized` bound on > > `HasWork::work_container_of` which was apparently necessary to access > > `OFFSET` as `OFFSET` no longer exists. > > > > A similar API change was discussed on the hrtimer series[1]. > > > > Link: https://lore.kernel.org/all/20250224-hrtimer-v3-v6-12-rc2-v9-1-5bd3bf0ce6cc@kernel.org/ [1] > > Reviewed-by: Benno Lossin <benno.lossin@proton.me> > > Reviewed-by: Alice Ryhl <aliceryhl@google.com> > > Tested-by: Alice Ryhl <aliceryhl@google.com> > > Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org> > > Signed-off-by: Tamir Duberstein <tamird@gmail.com> > > Seems reasonable enough. > Reviewed-by: Alice Ryhl <aliceryhl@google.com> Acked-by: Tejun Heo <tj@kernel.org> Please let me know how you want it routed. Thanks.
On Mon, Apr 14, 2025 at 7:24 PM Tejun Heo <tj@kernel.org> wrote: > > Acked-by: Tejun Heo <tj@kernel.org> > > Please let me know how you want it routed. If you would like to take it, then that would be nice. Otherwise, I can also take it. Thanks! Cheers, Miguel
On Mon, Apr 14, 2025 at 07:34:51PM +0200, Miguel Ojeda wrote: > On Mon, Apr 14, 2025 at 7:24 PM Tejun Heo <tj@kernel.org> wrote: > > > > Acked-by: Tejun Heo <tj@kernel.org> > > > > Please let me know how you want it routed. > > If you would like to take it, then that would be nice. Otherwise, I > can also take it. Alright, applied to wq/for-6.16. Thanks.
On Mon, Apr 14, 2025 at 1:37 PM Tejun Heo <tj@kernel.org> wrote: > > On Mon, Apr 14, 2025 at 07:34:51PM +0200, Miguel Ojeda wrote: > > On Mon, Apr 14, 2025 at 7:24 PM Tejun Heo <tj@kernel.org> wrote: > > > > > > Acked-by: Tejun Heo <tj@kernel.org> > > > > > > Please let me know how you want it routed. > > > > If you would like to take it, then that would be nice. Otherwise, I > > can also take it. > > Alright, applied to wq/for-6.16. Looks like you took it without the prerequisite patch.
On Mon, Apr 14, 2025 at 01:44:31PM -0400, Tamir Duberstein wrote: > On Mon, Apr 14, 2025 at 1:37 PM Tejun Heo <tj@kernel.org> wrote: > > > > On Mon, Apr 14, 2025 at 07:34:51PM +0200, Miguel Ojeda wrote: > > > On Mon, Apr 14, 2025 at 7:24 PM Tejun Heo <tj@kernel.org> wrote: > > > > > > > > Acked-by: Tejun Heo <tj@kernel.org> > > > > > > > > Please let me know how you want it routed. > > > > > > If you would like to take it, then that would be nice. Otherwise, I > > > can also take it. > > > > Alright, applied to wq/for-6.16. > > Looks like you took it without the prerequisite patch. Ah, okay. Lemme track back and apply the prerequisite first. Thanks.
On Mon, Apr 14, 2025 at 07:47:51AM -1000, Tejun Heo wrote: > On Mon, Apr 14, 2025 at 01:44:31PM -0400, Tamir Duberstein wrote: > > On Mon, Apr 14, 2025 at 1:37 PM Tejun Heo <tj@kernel.org> wrote: > > > > > > On Mon, Apr 14, 2025 at 07:34:51PM +0200, Miguel Ojeda wrote: > > > > On Mon, Apr 14, 2025 at 7:24 PM Tejun Heo <tj@kernel.org> wrote: > > > > > > > > > > Acked-by: Tejun Heo <tj@kernel.org> > > > > > > > > > > Please let me know how you want it routed. > > > > > > > > If you would like to take it, then that would be nice. Otherwise, I > > > > can also take it. > > > > > > Alright, applied to wq/for-6.16. > > > > Looks like you took it without the prerequisite patch. > > Ah, okay. Lemme track back and apply the prerequisite first. Miguel, now that I thought a bit about it, I probably shouldn't be applying patches that I don't understand enough to tell which one depends on what. Can you please apply this series and the delayed_work one? Thanks.
On Mon, Apr 14, 2025 at 7:49 PM Tejun Heo <tj@kernel.org> wrote: > > Miguel, now that I thought a bit about it, I probably shouldn't be applying > patches that I don't understand enough to tell which one depends on what. > Can you please apply this series and the delayed_work one? Yeah, sorry. Tamir: I know you the "prerequisite" at the footer, but it is best to explain what has happened in words. If I understand correctly, the last "version" is: https://lore.kernel.org/all/20250409-container-of-mutness-v1-1-64f472b94534@gmail.com/ Right? Cheers, Miguel
On Mon, Apr 14, 2025 at 1:57 PM Miguel Ojeda <miguel.ojeda.sandonis@gmail.com> wrote: > > On Mon, Apr 14, 2025 at 7:49 PM Tejun Heo <tj@kernel.org> wrote: > > > > Miguel, now that I thought a bit about it, I probably shouldn't be applying > > patches that I don't understand enough to tell which one depends on what. > > Can you please apply this series and the delayed_work one? > > Yeah, sorry. > > Tamir: I know you the "prerequisite" at the footer, but it is best to > explain what has happened in words. If I understand correctly, the > last "version" is: > > https://lore.kernel.org/all/20250409-container-of-mutness-v1-1-64f472b94534@gmail.com/ > > Right? Yeah, correct. FWIW I was hoping the automatic prerequisite handling in b4 was sufficient - I'll also include mention of prerequisites in the cover letter in the future. Thanks all.
diff --git a/rust/kernel/workqueue.rs b/rust/kernel/workqueue.rs index f98bd02b838f..d092112d843f 100644 --- a/rust/kernel/workqueue.rs +++ b/rust/kernel/workqueue.rs @@ -429,51 +429,28 @@ pub unsafe fn raw_get(ptr: *const Self) -> *mut bindings::work_struct { /// /// # Safety /// -/// The [`OFFSET`] constant must be the offset of a field in `Self` of type [`Work<T, ID>`]. The -/// methods on this trait must have exactly the behavior that the definitions given below have. +/// The methods [`raw_get_work`] and [`work_container_of`] must return valid pointers and must be +/// true inverses of each other; that is, they must satisfy the following invariants: +/// - `work_container_of(raw_get_work(ptr)) == ptr` for any `ptr: *mut Self`. +/// - `raw_get_work(work_container_of(ptr)) == ptr` for any `ptr: *mut Work<T, ID>`. /// /// [`impl_has_work!`]: crate::impl_has_work -/// [`OFFSET`]: HasWork::OFFSET +/// [`raw_get_work`]: HasWork::raw_get_work +/// [`work_container_of`]: HasWork::work_container_of pub unsafe trait HasWork<T, const ID: u64 = 0> { - /// The offset of the [`Work<T, ID>`] field. - const OFFSET: usize; - - /// Returns the offset of the [`Work<T, ID>`] field. - /// - /// This method exists because the [`OFFSET`] constant cannot be accessed if the type is not - /// [`Sized`]. - /// - /// [`OFFSET`]: HasWork::OFFSET - #[inline] - fn get_work_offset(&self) -> usize { - Self::OFFSET - } - /// Returns a pointer to the [`Work<T, ID>`] field. /// /// # Safety /// /// The provided pointer must point at a valid struct of type `Self`. - #[inline] - unsafe fn raw_get_work(ptr: *mut Self) -> *mut Work<T, ID> { - // SAFETY: The caller promises that the pointer is valid. - unsafe { (ptr as *mut u8).add(Self::OFFSET) as *mut Work<T, ID> } - } + unsafe fn raw_get_work(ptr: *mut Self) -> *mut Work<T, ID>; /// Returns a pointer to the struct containing the [`Work<T, ID>`] field. /// /// # Safety /// /// The pointer must point at a [`Work<T, ID>`] field in a struct of type `Self`. - #[inline] - unsafe fn work_container_of(ptr: *mut Work<T, ID>) -> *mut Self - where - Self: Sized, - { - // SAFETY: The caller promises that the pointer points at a field of the right type in the - // right kind of struct. - unsafe { (ptr as *mut u8).sub(Self::OFFSET) as *mut Self } - } + unsafe fn work_container_of(ptr: *mut Work<T, ID>) -> *mut Self; } /// Used to safely implement the [`HasWork<T, ID>`] trait. @@ -504,8 +481,6 @@ macro_rules! impl_has_work { // SAFETY: The implementation of `raw_get_work` only compiles if the field has the right // type. unsafe impl$(<$($generics)+>)? $crate::workqueue::HasWork<$work_type $(, $id)?> for $self { - const OFFSET: usize = ::core::mem::offset_of!(Self, $field) as usize; - #[inline] unsafe fn raw_get_work(ptr: *mut Self) -> *mut $crate::workqueue::Work<$work_type $(, $id)?> { // SAFETY: The caller promises that the pointer is not dangling. @@ -513,6 +488,15 @@ unsafe fn raw_get_work(ptr: *mut Self) -> *mut $crate::workqueue::Work<$work_typ ::core::ptr::addr_of_mut!((*ptr).$field) } } + + #[inline] + unsafe fn work_container_of( + ptr: *mut $crate::workqueue::Work<$work_type $(, $id)?>, + ) -> *mut Self { + // SAFETY: The caller promises that the pointer points at a field of the right type + // in the right kind of struct. + unsafe { $crate::container_of!(ptr, Self, $field) } + } } )*}; }