Received: by 2002:a89:48b:0:b0:1f5:f2ab:c469 with SMTP id a11csp1415956lqd; Thu, 25 Apr 2024 15:13:43 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCWuXfcdfS1uR+AvX7tWoRPkJBL5nRTvrFbJVTDNkQSBzJfl2i0vCmelBXG9XiZIJ4fbu3osCv+kLyXc3yJlNqAEBpLOMhTzhIaih4QbKw== X-Google-Smtp-Source: AGHT+IGqpiwmJn9dHXxok2miY/cs7YKoukoBABjE5D4FiUBwEibvX7VxPq/kjG32ljJupYYr64s0 X-Received: by 2002:a05:6870:3845:b0:234:2553:7bbf with SMTP id z5-20020a056870384500b0023425537bbfmr764537oal.43.1714083222760; Thu, 25 Apr 2024 15:13:42 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1714083222; cv=pass; d=google.com; s=arc-20160816; b=qkeXep44vSMttYyDJboc19eHhs6C+fggLdi5dmPEGJ9keSWqVfoy0qT2NiPdH1ssDv fu2BQwK8APNAgMy6WPZUMBxiiSdGdHKh9M/T6zBkDgv44ktn3FBry7qCnVLsHRSqlgHS uJvn9i995aUKS52kf0i4HuX3sLwM8S7kQ8kvG/rxaev1/ZUTcLUrfj1xMySPeYmGliNy gkd996bBnBf1YDt2kzzeJuIist810DeaWhYfG3XfaWjQnt3OQqWAa9ApbGzgXuXMd6gY VgT9ImZIO/27SchcmDynXGZ3tccbKLx+nGn4NHVzIpECfttNgzLx3sqjJkZoiGlC+cyn kk6Q== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:feedback-id:references :in-reply-to:message-id:subject:cc:from:to:date:dkim-signature; bh=X4GK0qT25GBqVlUpxE1T+oiI6ffMY6kIFUz9p2N2THk=; fh=jz9ZYdkZU3gmm8weL7yql0hVHDdlmm49R0ERliAl9tY=; b=EplGFcQJpbs/zqxi/p9RTRGlM2SAdTlo9okmQn7rqy9aDWobmGATGwjEGChkUTWRL6 6IwmoLYyruVLwD2h4pUbHUpAp9sotpUR5bqPsukhaTRmY0Pw4kFmPlZvpS89GOnf/M9G cZaFB4ds2O0Jc6L3vbjW4WbMhadUYmmtPQ/MjJkZ3ygL2xaCfP3LlsmDLUWSBvanUF+Y QJ7tGJguXSMqyZJlIg7kJwx0E++dz9AdLAon6KAzGVO2FvjI3s5dKnvbKsO/6IiGVsXP nTaUpXyvsZXMgZh1zEUdX68AXpmEVMsQox5TRtgOBJFB1YTFG2HpJgxqxFndc2CuvEu/ 2GTQ==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@proton.me header.s=protonmail header.b=jyyf58Bg; arc=pass (i=1 spf=pass spfdomain=proton.me dkim=pass dkdomain=proton.me dmarc=pass fromdomain=proton.me); spf=pass (google.com: domain of linux-kernel+bounces-159289-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-159289-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=proton.me Return-Path: Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [2604:1380:45e3:2400::1]) by mx.google.com with ESMTPS id s18-20020a639e12000000b005f40318db6dsi13673324pgd.756.2024.04.25.15.13.42 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 25 Apr 2024 15:13:42 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel+bounces-159289-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) client-ip=2604:1380:45e3:2400::1; Authentication-Results: mx.google.com; dkim=pass header.i=@proton.me header.s=protonmail header.b=jyyf58Bg; arc=pass (i=1 spf=pass spfdomain=proton.me dkim=pass dkdomain=proton.me dmarc=pass fromdomain=proton.me); spf=pass (google.com: domain of linux-kernel+bounces-159289-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-159289-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=proton.me Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sv.mirrors.kernel.org (Postfix) with ESMTPS id B011728338F for ; Thu, 25 Apr 2024 22:08:51 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 7638C15B15D; Thu, 25 Apr 2024 21:58:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=proton.me header.i=@proton.me header.b="jyyf58Bg" Received: from mail-4322.protonmail.ch (mail-4322.protonmail.ch [185.70.43.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B67F0156223 for ; Thu, 25 Apr 2024 21:58:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.70.43.22 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714082299; cv=none; b=kvJ9F5Uu+zOUXAPxOdSYhj+8bXkllPi8YVGV/6ko62AKHLjtxc6CLljfQ6i4t1Azb8nnZX4aiJN9B42LdQ9uRsyYCWzcpYZzb6UFlbj9JjoLDyQv9OWb8+NRoqwRk10OWcS3grTIOdrjy5yMOc470c2B4S6MaoZqPJ8Xs/AV/+8= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1714082299; c=relaxed/simple; bh=KgIjecV6C7Nk07SLdfHCvsEa6tmgp+Vm85Nrr1SnqGU=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=sXvHM8mQJks+BkOG7NpItmGtkctS44NwSM7ecMYxFqJB5nGEUGwtofbIzmbj8grgJQXiPqx/jPiutcYHJlw97dXh58fsZ5ClTcNC6qxSJHswwgULjx8R1Z2RiwsLWg+LJKrsxpaObpGnIUR19YvOp8cJWeR7yl6VARV1edDRUDA= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=proton.me; spf=pass smtp.mailfrom=proton.me; dkim=pass (2048-bit key) header.d=proton.me header.i=@proton.me header.b=jyyf58Bg; arc=none smtp.client-ip=185.70.43.22 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=proton.me Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=proton.me DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=proton.me; s=protonmail; t=1714082294; x=1714341494; bh=X4GK0qT25GBqVlUpxE1T+oiI6ffMY6kIFUz9p2N2THk=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector; b=jyyf58Bg0cq4jXXMO3vLB/DwWO+rUR1zjGnZv1baRXXTPt+jFYEx9h5pzExB0BhdK CqYNx8U91c7MNF5pjVk8FnkSOScXuQGvpoolKe1qM6cAn135dEn0oPqpj1IuMCL1LB EcnG5xKepZY0VcW+lb/44fOJfiiwHl16o/lcw3Apn+0bWFP37ArflQ0Mej5N7nIYpn f/kZfitOMSjtotySOlibLHWwPfQTvQ61PgRrCT8Nt4nq5i4rWkqdR7RggDdjH4QzY7 +YxbKGU3hmHya1gnmyjxqoq2c01X7IN+lUnexp8gG2N57GewzlmzytpPD8jvG0Zbmd vi5oXgaCask1w== Date: Thu, 25 Apr 2024 21:58:09 +0000 To: Matt Gilbride , Miguel Ojeda , Alex Gaynor , Wedson Almeida Filho , Boqun Feng , Gary Guo , =?utf-8?Q?Bj=C3=B6rn_Roy_Baron?= , Andreas Hindborg , Alice Ryhl , Greg Kroah-Hartman , =?utf-8?Q?Arve_Hj=C3=B8nnev=C3=A5g?= , Todd Kjos , Martijn Coenen , Joel Fernandes , Carlos Llamas , Suren Baghdasaryan , Christian Brauner From: Benno Lossin Cc: Rob Landley , Davidlohr Bueso , Michel Lespinasse , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org Subject: Re: [PATCH v3 3/5] rust: rbtree: add `RBTreeIteratorMut` Message-ID: In-Reply-To: <20240418-b4-rbtree-v3-3-323e134390ce@google.com> References: <20240418-b4-rbtree-v3-0-323e134390ce@google.com> <20240418-b4-rbtree-v3-3-323e134390ce@google.com> Feedback-ID: 71780778:user:proton X-Pm-Message-ID: d84f15a7d28ce27feb45bee2c48c45d49781f864 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable On 18.04.24 16:15, Matt Gilbride wrote: > From: Wedson Almeida Filho >=20 > Add mutable Iterator implementation (`RBTreeIteratorMut`) for `RBTree`, > allowing iteration over (key, value) pairs in key order. Only values are > mutable, as mutating keys implies modifying a node's position in the tree= . >=20 > Mutable iteration is used by the binder driver during shutdown to > clean up the tree maintained by the "range allocator" [1]. >=20 > Link: https://lore.kernel.org/rust-for-linux/20231101-rust-binder-v1-6-08= ba9197f637@google.com/ [1] > Signed-off-by: Wedson Almeida Filho > Signed-off-by: Matt Gilbride > Reviewed-by: Alice Ryhl > Tested-by: Alice Ryhl > --- > rust/kernel/rbtree.rs | 64 +++++++++++++++++++++++++++++++++++++++++++++= ++++++ > 1 file changed, 64 insertions(+) >=20 > diff --git a/rust/kernel/rbtree.rs b/rust/kernel/rbtree.rs > index 2f836be7bdbe..50d440c9926d 100644 > --- a/rust/kernel/rbtree.rs > +++ b/rust/kernel/rbtree.rs > @@ -222,6 +222,15 @@ pub fn iter(&self) -> RBTreeIterator<'_, K, V> { > } > } >=20 > + /// Returns a mutable iterator over the tree nodes, sorted by key. > + pub fn iter_mut(&mut self) -> RBTreeIteratorMut<'_, K, V> { > + RBTreeIteratorMut { This is missing an INVARIANT comment. > + _tree: PhantomData, > + // SAFETY: `root` is valid as it's embedded in `self` and we= have a valid `self`. > + next: unsafe { bindings::rb_first(&self.root) }, > + } > + } > + > /// Returns an iterator over the keys of the nodes in the tree, in s= orted order. > pub fn keys(&self) -> impl Iterator { > self.iter().map(|(k, _)| k) > @@ -231,6 +240,11 @@ pub fn keys(&self) -> impl Iterator = { > pub fn values(&self) -> impl Iterator { > self.iter().map(|(_, v)| v) > } > + > + /// Returns a mutable iterator over the values of the nodes in the t= ree, sorted by key. > + pub fn values_mut(&mut self) -> impl Iterator { > + self.iter_mut().map(|(_, v)| v) > + } > } >=20 > impl RBTree > @@ -466,6 +480,56 @@ fn next(&mut self) -> Option { > } > } >=20 > +impl<'a, K, V> IntoIterator for &'a mut RBTree { > + type Item =3D (&'a K, &'a mut V); > + type IntoIter =3D RBTreeIteratorMut<'a, K, V>; > + > + fn into_iter(self) -> Self::IntoIter { > + self.iter_mut() > + } > +} > + > +/// A mutable iterator over the nodes of a [`RBTree`]. > +/// > +/// Instances are created by calling [`RBTree::iter_mut`]. > +/// > +/// # Invariants > +/// - `self.next` is a valid pointer. > +/// - `self.next` points to a node stored inside of a valid `RBTree`. > +pub struct RBTreeIteratorMut<'a, K, V> { I think the names `Iter` and `IterMut` are more natural. That is what the collections in `std::collections` do. These are in the module `rbtree`, so you can refer to them as `rbtree::Iter`. > + _tree: PhantomData<&'a RBTree>, This should have the type `PhantomData<&'a mut RBTree>`. > + next: *mut bindings::rb_node, > +} You could create a common iterator type, since both `RBTreeIterator` and `RBTreeIteratorMut` are very similar. How about a (private) `RawIter`: struct RawIter { next: *mut bindings::rb_node, _phantom: PhantomData (K, V)>, } And implement `Iterator` with `Item =3D (*mut K, *mut V)` for `RawIter`. Then you can change `Iter` to be: pub struct Iter<'a, K, V> { raw_iter: RawIter, _tree: PhantomData<&'a RBTree>, } --=20 Cheers, Benno > + > +// SAFETY: The [`RBTreeIterator`] gives out mutable references to K and = V, so it has the same > +// thread safety requirements as mutable references. > +unsafe impl<'a, K: Send, V: Send> Send for RBTreeIteratorMut<'a, K, V> {= } > + > +// SAFETY: The [`RBTreeIterator`] gives out mutable references to K and = V, so it has the same > +// thread safety requirements as mutable references. > +unsafe impl<'a, K: Sync, V: Sync> Sync for RBTreeIteratorMut<'a, K, V> {= } > + > +impl<'a, K, V> Iterator for RBTreeIteratorMut<'a, K, V> { > + type Item =3D (&'a K, &'a mut V); > + > + fn next(&mut self) -> Option { > + if self.next.is_null() { > + return None; > + } > + > + // SAFETY: By the type invariant of `Self`, all non-null `rb_nod= e` pointers stored in `self` > + // point to the links field of `Node` objects. > + let cur =3D unsafe { container_of!(self.next, Node, links)= }.cast_mut(); > + > + // SAFETY: `self.next` is a valid tree node by the type invarian= ts. > + self.next =3D unsafe { bindings::rb_next(self.next) }; > + > + // SAFETY: By the same reasoning above, it is safe to dereferenc= e the node. Additionally, > + // it is ok to return a reference to members because the iterato= r must outlive it. > + Some(unsafe { (&(*cur).key, &mut (*cur).value) }) > + } > +} > + > /// A memory reservation for a red-black tree node. > /// > /// It contains the memory needed to hold a node that can be inserted in= to a red-black tree. One >=20 > -- > 2.44.0.769.g3c40516874-goog >=20