linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Benno Lossin <benno.lossin@proton.me>
To: "Alice Ryhl" <aliceryhl@google.com>,
	"Miguel Ojeda" <ojeda@kernel.org>,
	"Alex Gaynor" <alex.gaynor@gmail.com>,
	"Wedson Almeida Filho" <wedsonaf@gmail.com>,
	"Boqun Feng" <boqun.feng@gmail.com>,
	"Gary Guo" <gary@garyguo.net>,
	"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
	"Andreas Hindborg" <a.hindborg@samsung.com>,
	"Peter Zijlstra" <peterz@infradead.org>,
	"Alexander Viro" <viro@zeniv.linux.org.uk>,
	"Christian Brauner" <brauner@kernel.org>,
	"Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
	"Arve Hjønnevåg" <arve@android.com>,
	"Todd Kjos" <tkjos@android.com>,
	"Martijn Coenen" <maco@android.com>,
	"Joel Fernandes" <joel@joelfernandes.org>,
	"Carlos Llamas" <cmllamas@google.com>,
	"Suren Baghdasaryan" <surenb@google.com>
Cc: Dan Williams <dan.j.williams@intel.com>,
	Kees Cook <keescook@chromium.org>,
	Matthew Wilcox <willy@infradead.org>,
	Thomas Gleixner <tglx@linutronix.de>, Daniel Xu <dxu@dxuuu.xyz>,
	linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org,
	linux-fsdevel@vger.kernel.org
Subject: Re: [PATCH v3 1/9] rust: file: add Rust abstraction for `struct file`
Date: Fri, 26 Jan 2024 15:04:23 +0000	[thread overview]
Message-ID: <5dbbaba2-fd7f-4734-9f44-15d2a09b4216@proton.me> (raw)
In-Reply-To: <20240118-alice-file-v3-1-9694b6f9580c@google.com>

On 18.01.24 15:36, Alice Ryhl wrote:
> +/// Wraps the kernel's `struct file`.
> +///
> +/// # Refcounting
> +///
> +/// Instances of this type are reference-counted. The reference count is incremented by the
> +/// `fget`/`get_file` functions and decremented by `fput`. The Rust type `ARef<File>` represents a
> +/// pointer that owns a reference count on the file.
> +///
> +/// Whenever a process opens a file descriptor (fd), it stores a pointer to the file in its `struct
> +/// files_struct`. This pointer owns a reference count to the file, ensuring the file isn't
> +/// prematurely deleted while the file descriptor is open. In Rust terminology, the pointers in
> +/// `struct files_struct` are `ARef<File>` pointers.
> +///
> +/// ## Light refcounts
> +///
> +/// Whenever a process has an fd to a file, it may use something called a "light refcount" as a
> +/// performance optimization. Light refcounts are acquired by calling `fdget` and released with
> +/// `fdput`. The idea behind light refcounts is that if the fd is not closed between the calls to
> +/// `fdget` and `fdput`, then the refcount cannot hit zero during that time, as the `struct
> +/// files_struct` holds a reference until the fd is closed. This means that it's safe to access the
> +/// file even if `fdget` does not increment the refcount.
> +///
> +/// The requirement that the fd is not closed during a light refcount applies globally across all
> +/// threads - not just on the thread using the light refcount. For this reason, light refcounts are
> +/// only used when the `struct files_struct` is not shared with other threads, since this ensures
> +/// that other unrelated threads cannot suddenly start using the fd and close it. Therefore,
> +/// calling `fdget` on a shared `struct files_struct` creates a normal refcount instead of a light
> +/// refcount.
> +///
> +/// Light reference counts must be released with `fdput` before the system call returns to
> +/// userspace. This means that if you wait until the current system call returns to userspace, then
> +/// all light refcounts that existed at the time have gone away.
> +///
> +/// ## Rust references
> +///
> +/// The reference type `&File` is similar to light refcounts:
> +///
> +/// * `&File` references don't own a reference count. They can only exist as long as the reference
> +///   count stays positive, and can only be created when there is some mechanism in place to ensure
> +///   this.
> +///
> +/// * The Rust borrow-checker normally ensures this by enforcing that the `ARef<File>` from which
> +///   a `&File` is created outlives the `&File`.
> +///
> +/// * Using the unsafe [`File::from_ptr`] means that it is up to the caller to ensure that the
> +///   `&File` only exists while the reference count is positive.
> +///
> +/// * You can think of `fdget` as using an fd to look up an `ARef<File>` in the `struct
> +///   files_struct` and create an `&File` from it. The "fd cannot be closed" rule is like the Rust
> +///   rule "the `ARef<File>` must outlive the `&File`".
> +///
> +/// # Invariants
> +///
> +/// * Instances of this type are refcounted using the `f_count` field.
> +/// * If an fd with active light refcounts is closed, then it must be the case that the file
> +///   refcount is positive until there are no more light refcounts created from the fd that got

I think this wording can be easily misinterpreted: "until there
are no more light refcounts created" could mean that you are allowed
to drop the refcount to zero after the last light refcount has been
created. But in reality you want all light refcounts to be released
first.
I would suggest "until all light refcounts of the fd have been dropped"
or similar.

> +///   closed.
> +/// * A light refcount must be dropped before returning to userspace.
> +#[repr(transparent)]
> +pub struct File(Opaque<bindings::file>);
> +
> +// SAFETY: By design, the only way to access a `File` is via an immutable reference or an `ARef`.
> +// This means that the only situation in which a `File` can be accessed mutably is when the
> +// refcount drops to zero and the destructor runs. It is safe for that to happen on any thread, so
> +// it is ok for this type to be `Send`.

Technically, `drop` is never called for `File`, since it is only used
via `ARef<File>` which calls `dec_ref` instead. Also since it only contains
an `Opaque`, dropping it is a noop.
But what does `Send` mean for this type? Since it is used together with
`ARef`, being `Send` means that `File::dec_ref` can be called from any
thread. I think we are missing this as a safety requirement on
`AlwaysRefCounted`, do you agree?
I think the safety justification here could be (with the requirement added
to `AlwaysRefCounted`):

     SAFETY:
     - `File::drop` can be called from any thread.
     - `File::dec_ref` can be called from any thread.

--
Cheers,
Benno

> +unsafe impl Send for File {}
> +
> +// SAFETY: All methods defined on `File` that take `&self` are safe to call even if other threads
> +// are concurrently accessing the same `struct file`, because those methods either access immutable
> +// properties or have proper synchronization to ensure that such accesses are safe.
> +unsafe impl Sync for File {}


  parent reply	other threads:[~2024-01-26 15:04 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-18 14:36 [PATCH v3 0/9] File abstractions needed by Rust Binder Alice Ryhl
2024-01-18 14:36 ` [PATCH v3 1/9] rust: file: add Rust abstraction for `struct file` Alice Ryhl
2024-01-18 22:37   ` Valentin Obst
2024-01-26 15:04   ` Benno Lossin [this message]
2024-01-29 16:34     ` Alice Ryhl
2024-02-01  9:30       ` Benno Lossin
2024-02-01  9:33         ` Alice Ryhl
2024-02-01  9:38           ` Benno Lossin
2024-02-01  9:41             ` Alice Ryhl
2024-02-01  9:48               ` Benno Lossin
2024-01-18 14:36 ` [PATCH v3 2/9] rust: cred: add Rust abstraction for `struct cred` Alice Ryhl
2024-01-19  9:37   ` Benno Lossin
2024-01-19  9:52     ` Alice Ryhl
2024-01-24  9:51       ` Benno Lossin
2024-01-18 14:36 ` [PATCH v3 3/9] rust: security: add abstraction for secctx Alice Ryhl
2024-01-19  9:41   ` Benno Lossin
2024-01-18 14:36 ` [PATCH v3 4/9] rust: types: add `NotThreadSafe` Alice Ryhl
2024-01-19  9:43   ` Benno Lossin
2024-01-18 14:36 ` [PATCH v3 5/9] rust: file: add `FileDescriptorReservation` Alice Ryhl
2024-01-19  9:48   ` Benno Lossin
2024-01-18 14:36 ` [PATCH v3 6/9] rust: task: add `Task::current_raw` Alice Ryhl
2024-01-19  9:52   ` Benno Lossin
2024-01-18 14:36 ` [PATCH v3 7/9] rust: file: add `Kuid` wrapper Alice Ryhl
2024-01-24  9:55   ` Benno Lossin
2024-01-18 14:36 ` [PATCH v3 8/9] rust: file: add `DeferredFdCloser` Alice Ryhl
2024-01-22 17:59   ` Boqun Feng
2024-01-24 10:07   ` Benno Lossin
2024-01-18 14:36 ` [PATCH v3 9/9] rust: file: add abstraction for `poll_table` Alice Ryhl
2024-01-24 10:11   ` Benno Lossin
2024-01-29 17:08     ` Alice Ryhl
2024-02-01  9:33       ` Benno Lossin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5dbbaba2-fd7f-4734-9f44-15d2a09b4216@proton.me \
    --to=benno.lossin@proton.me \
    --cc=a.hindborg@samsung.com \
    --cc=alex.gaynor@gmail.com \
    --cc=aliceryhl@google.com \
    --cc=arve@android.com \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun.feng@gmail.com \
    --cc=brauner@kernel.org \
    --cc=cmllamas@google.com \
    --cc=dan.j.williams@intel.com \
    --cc=dxu@dxuuu.xyz \
    --cc=gary@garyguo.net \
    --cc=gregkh@linuxfoundation.org \
    --cc=joel@joelfernandes.org \
    --cc=keescook@chromium.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=maco@android.com \
    --cc=ojeda@kernel.org \
    --cc=peterz@infradead.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=surenb@google.com \
    --cc=tglx@linutronix.de \
    --cc=tkjos@android.com \
    --cc=viro@zeniv.linux.org.uk \
    --cc=wedsonaf@gmail.com \
    --cc=willy@infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).