Received: by 2002:a05:7412:419a:b0:f3:1519:9f41 with SMTP id i26csp4930357rdh; Wed, 29 Nov 2023 15:18:10 -0800 (PST) X-Google-Smtp-Source: AGHT+IH1p+A4dIrIACkvdJQ3a82QyIMnklOJZDksN/IXgk0Vd5+kuZ5pyCBodI+3D7mOH8x6QtXD X-Received: by 2002:a05:6a20:7488:b0:18c:5795:669c with SMTP id p8-20020a056a20748800b0018c5795669cmr15542013pzd.46.1701299890350; Wed, 29 Nov 2023 15:18:10 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1701299890; cv=none; d=google.com; s=arc-20160816; b=d4LmD7RHuoGE/55ZGJG6Xy3H4jm15fMVfv9wv2ibw2aqE/OR4wzBMwssr+yxB1AF0b 3/K+VCZcjrAX5ipxuEs9uYTjBiWnMfQAHBJnFiIhS3klg476UDdrsZgAoiNtzEuZJtqK CsIf0JATVvh4riHt8vhcxQCT85Ejzf5wZ7sbPyw0JQiT5sq3HVQnKWLvjrYdKzOJAIAY WiAEcp0vaIfqdl4Rdq84W4pym+kRxgktk/7/rdWmkw6FO+VOFcxo5TVDEFmIQJSHjWFD PNMhbCm5uAVVq3tUN+IW0Qh76Y7jGJsh80BKYcCqg5J+vPfDgRJhEhTTz72EXI5Ogc0c BFIQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :feedback-id:references:in-reply-to:message-id:subject:cc:from:to :date:dkim-signature; bh=ioPvELIdRThD715hd8zdKjIZrjzPAQE7wm474WJAqF4=; fh=YQNu/qd5xsKucRUuP5LJL3TRwcBnmkib1ekrqfEMTnk=; b=bC5dywNO6CUNY40GTjDEgB/cL0thLTzThn8BXMeFFElzOzueak4cCbJS4bepHJnYWn IpTIWYRnowfWdHZYuBZ5fOXQXgZ2CeQg79FDL1pWpefmBGF5zKVnXC+oPjCtjEgTIlNy jIvXdlbH9tK4+tVt+DYGq4SBhojugiBHlb5PU/2uAcxyWiqqC9dl7y0tww9uqnQptOkA uMEiOrW/vqdU47bcMhzEPhoEjX73kYW9ouWO7aH0Pu7h6Zgry2c/J5wyweFgiCU13SXx rbsYOBBj5CCU6g26YK6JvL44Htj8mwVxrZdo31GNt97+yBwaN74pg7LbqijDqXoB5GsT NEkA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@proton.me header.s=protonmail header.b="AwPlFmo/"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.37 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=proton.me Return-Path: Received: from snail.vger.email (snail.vger.email. [23.128.96.37]) by mx.google.com with ESMTPS id p4-20020a056a000b4400b006cd94e0c112si6944021pfo.285.2023.11.29.15.18.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Nov 2023 15:18:10 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.37 as permitted sender) client-ip=23.128.96.37; Authentication-Results: mx.google.com; dkim=pass header.i=@proton.me header.s=protonmail header.b="AwPlFmo/"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.37 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=proton.me Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by snail.vger.email (Postfix) with ESMTP id B4C90804596E; Wed, 29 Nov 2023 15:18:08 -0800 (PST) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.11 at snail.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231618AbjK2XR6 (ORCPT + 99 others); Wed, 29 Nov 2023 18:17:58 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45526 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229575AbjK2XR6 (ORCPT ); Wed, 29 Nov 2023 18:17:58 -0500 Received: from mail-40134.protonmail.ch (mail-40134.protonmail.ch [185.70.40.134]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 688D6D54 for ; Wed, 29 Nov 2023 15:18:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=proton.me; s=protonmail; t=1701299880; x=1701559080; bh=ioPvELIdRThD715hd8zdKjIZrjzPAQE7wm474WJAqF4=; 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=AwPlFmo/rkoaSEPLXDBUp5RYZFXhpXPmSN6/Sm6NfyJ+oigu8XxK4W/gqsAM1FEqU fhrkTv5wjXZgD7Aq+B5tak0rHosBg877xvVCiaGbHI4JOcVwGc6ECWq42tjDcBc936 HcNJC2aaJQxe4qrvtg+gj+CWdXuJTMrbdcXS99DIiSf2sX9h1Njl+xvIrgrUlDpJgZ ECqqyFTfFyLl5pTQtR9LACRlHFZZQSHFfVzylMJeRMvi4V+9gekLxNnCy07U0exkYw X1hjuGlRj/Ebqqy68A6T0xpwvuprtuwAD4a462iDagk8Mi7gGhB0Dkkjur7lB1SmXb ts/cDgCkDR89w== Date: Wed, 29 Nov 2023 23:17:48 +0000 To: Alice Ryhl From: Benno Lossin Cc: brauner@kernel.org, a.hindborg@samsung.com, alex.gaynor@gmail.com, arve@android.com, bjorn3_gh@protonmail.com, boqun.feng@gmail.com, cmllamas@google.com, dan.j.williams@intel.com, dxu@dxuuu.xyz, gary@garyguo.net, gregkh@linuxfoundation.org, joel@joelfernandes.org, keescook@chromium.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, maco@android.com, ojeda@kernel.org, peterz@infradead.org, rust-for-linux@vger.kernel.org, surenb@google.com, tglx@linutronix.de, tkjos@android.com, viro@zeniv.linux.org.uk, wedsonaf@gmail.com, willy@infradead.org Subject: Re: [PATCH 1/7] rust: file: add Rust abstraction for `struct file` Message-ID: <1cT5uqAdTaJ2sJVCILPrVHczVq1z2BZfCXy3wOHJKhMx7RFSATPcdAFpYT9y6h6nZBvHcQsYbeJMXMqB6u3i85yDRIO6iGwUoerIaSWdEn4=@proton.me> In-Reply-To: <20231129212707.3520214-1-aliceryhl@google.com> References: <20231129-geleckt-verebben-04ea0c08a53c@brauner> <20231129212707.3520214-1-aliceryhl@google.com> Feedback-ID: 71780778:user:proton MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_BLOCKED, RCVD_IN_MSPIKE_H5,RCVD_IN_MSPIKE_WL,SPF_HELO_PASS,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (snail.vger.email [0.0.0.0]); Wed, 29 Nov 2023 15:18:08 -0800 (PST) On 29.11.23 22:27, Alice Ryhl wrote: > Another example: >=20 > =09void set_nonblocking_and_fput(struct file *file) { > =09=09// Let's just ignore the lock for this example. > =09=09file->f_flags |=3D O_NONBLOCK; >=20 > =09=09fput(file); > =09} >=20 > This method takes a file, sets it to non-blocking, and then destroys the > ref-count. What are the ownership semantics? Well, the caller should own > an `fget` ref-count, and we consume that ref-count. The equivalent Rust > code would be to take an `ARef`: >=20 > =09fn set_nonblocking_and_fput(file: ARef) { > =09=09file.set_flag(O_NONBLOCK); >=20 > =09=09// When `file` goes out of scope here, the destructor > =09=09// runs and calls `fput`. (Since that's what we defined > =09=09// `ARef` to do on drop in `fn dec_ref`.) > =09} >=20 > You can also explicitly call the destructor with `drop(file)`: >=20 > =09fn set_nonblocking_and_fput(file: ARef) { > =09=09file.set_flag(O_NONBLOCK); > =09=09drop(file); >=20 > =09=09// When `file` goes out of scope, the destructor does > =09=09// *not* run. This is because `drop(file)` is a move > =09=09// (due to the signature of drop), and if you perform a > =09=09// move, then the destructor no longer runs at the end > =09=09// of the scope. I want to note that while the destructor does not run at the end of the scope, it still *does* run: the `drop(file)` call runs the destructor. > =09} >=20 > And note that this would not compile, because we give up ownership of > the `ARef` by passing it to `drop`: >=20 > =09fn set_nonblocking_and_fput(file: ARef) { > =09=09drop(file); > =09=09file.set_flag(O_NONBLOCK); > =09} > [...] >>> +// SAFETY: The type invariants guarantee that `File` is always ref-cou= nted. >>> +unsafe impl AlwaysRefCounted for File { >>> + fn inc_ref(&self) { >>> + // SAFETY: The existence of a shared reference means that the = refcount is nonzero. >>> + unsafe { bindings::get_file(self.0.get()) }; >>> + } >> >> Why inc_ref() and not just get_file()? >=20 > Whenever you see an impl block that uses the keyword "for", then the > code is implementing a trait. In this case, the trait being implemented > is AlwaysRefCounted, which allows File to work with ARef. >=20 > It has to be `inc_ref` because that's what AlwaysRefCounted calls this > method. I am not sure if the Rust term "trait" is well-known, so for a bit more context, I am quoting the Rust Book [1]: A *trait* defines functionality a particular type has and can share with other types. We can use traits to define shared behavior in an abstract way. We can use *trait bounds* to specify that a generic type can be any type that has certain behavior. [1]: https://doc.rust-lang.org/book/ch10-02-traits.html We have created an abstraction over reference counting: the trait `AlwaysRefCounted` and the struct `ARef` where `T` implements `AlwaysRefCounted`. As Alice already explained, `ARef` is a pointer that owns a refcount on the object. Because `ARef` needs to know how to increment and decrement that counter. For example, when you want to create another `ARef` you can `clone()` it and therefore `ARef` needs to increment the refcount. And when you drop it, `ARef` needs to decrement it. The "`ARef` knows how to inc/dec the refcount" part is done by the `AlwaysRefCounted` trait. And there we chose to name the functions `inc_ref` and `dec_ref`, since these are the *general*/*abstract* operations and not any specific refcount adjustment. Hope that also helped and did not create confusion. -- Cheers, Benno