From: Chad Aldreda <ca@modelmiser.com>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
"Rafael J. Wysocki" <rafael@kernel.org>,
Danilo Krummrich <dakr@kernel.org>
Cc: Johan Hovold <johan@kernel.org>, Jonathan Corbet <corbet@lwn.net>,
Shuah Khan <skhan@linuxfoundation.org>,
Randy Dunlap <rdunlap@infradead.org>,
Mauro Carvalho Chehab <mchehab@kernel.org>,
Hans Verkuil <hverkuil+cisco@kernel.org>,
Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
driver-core@lists.linux.dev, linux-media@vger.kernel.org,
linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH] Documentation: devres: warn about device nodes in managed memory
Date: Fri, 06 Nov 2026 19:36:07 +0000 [thread overview]
Message-ID: <20261106193600.3267465-2-ca@modelmiser.com> (raw)
devres entries are not reference counted, so managed memory must not
hold state that can still be reached after the driver unbinds. State
that rule for its common case, a cdev, miscdevice or video_device
embedded in devm_kzalloc()'d driver state that an open file can still
reach, including the v4l2_device and media_device that v4l2_release() in
v4l2-dev.c reads on every close, and say where each kind of node frees
its state on the last reference: the struct device release behind
cdev_device_add(), per its kernel-doc in fs/char_dev.c, and the
v4l2_device release callback in
Documentation/driver-api/media/v4l2-device.rst. That the video_device
release callback runs first, and must not free the shared state, follows
v4l2_device_release() in v4l2-dev.c, the video_device's struct device
release. A miscdevice has no release callback, so a kref, with its
ordering against misc_deregister(), is spelled out here; it is not in
the miscdevice documentation. An embedded media_device is also reached
by media request files and the media device node without a v4l2_device
reference, and has no reference count of its own; the text says so and
leaves its lifetime out. The point that unregistering does not close
open files follows the cdev_del() kernel-doc. That an open through a
cached inode can still reach ->open() follows chrdev_open(), which uses
inode->i_cdev while the cdev has references; the same kernel-doc says
the cdev can no longer be opened, which holds for a new lookup, and for
a cached inode only once the last reference is gone.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Chad Aldreda <ca@modelmiser.com>
---
.../driver-api/driver-model/devres.rst | 36 +++++++++++++++++++
1 file changed, 36 insertions(+)
diff --git a/Documentation/driver-api/driver-model/devres.rst b/Documentation/driver-api/driver-model/devres.rst
index 4f0b90e7e1..6dc6ab261e 100644
--- a/Documentation/driver-api/driver-model/devres.rst
+++ b/Documentation/driver-api/driver-model/devres.rst
@@ -208,6 +208,42 @@ Lifetime of a devres entry begins on devres allocation and finishes
when it is released or destroyed (removed and freed) - no reference
counting.
+Because nothing counts references, managed memory must not hold state
+that the core or the driver's file operations can still reach after the
+driver unbinds. A common case is driver state in devm_kzalloc()'d
+memory that an open file can still reach: state embedding a struct cdev
+or struct video_device, or the v4l2_device and media_device a
+video_device points to, which the core touches on every close, or a
+struct miscdevice whose file operations use the state. Unregistering
+the node in ->remove() does not close files that are already open, and
+for a cdev an open through an already cached inode can still reach the
+driver's ->open(). Allocate such state with kzalloc() and free it when
+the last reference to it is dropped:
+
+- for a cdev, from the release callback of a struct device embedded in
+ the same state, with dev->devt set, and added with cdev_device_add();
+ see its kernel-doc in fs/char_dev.c. ->remove() calls
+ cdev_device_del() and then put_device(); a probe that fails after
+ device_initialize() calls cdev_device_del() if cdev_device_add()
+ succeeded, then put_device(), never kfree().
+- for a video_device, from the release callback of its v4l2_device; see
+ Documentation/driver-api/media/v4l2-device.rst. The video_device
+ release callback runs before that and must not free the state. The
+ v4l2_device release callback is not the last access to an embedded
+ struct media_device: media request files and the media device node
+ reach it without a v4l2_device reference, and the media core gives it
+ no reference count, so its lifetime is not covered here.
+- a miscdevice has no release callback, so the driver counts the
+ references itself, for example with a kref that ->probe()
+ initializes, ->open() takes (and drops again if it then fails) and
+ ->release() drops, and that ->remove(), or a probe that fails after
+ misc_register(), drops only after misc_deregister() has returned.
+
+In each case, dropping a reference is the last access to the state by
+whoever drops it. Keeping the memory is not enough on its own: file
+operations that run after ->remove() must not touch the hardware or
+other managed resources.
+
devres core guarantees atomicity to all basic devres operations and
has support for single-instance devres types (atomic
lookup-and-add-if-not-found). Other than that, synchronizing
--
2.43.0
reply other threads:[~2026-11-06 19:36 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
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=20261106193600.3267465-2-ca@modelmiser.com \
--to=ca@modelmiser.com \
--cc=corbet@lwn.net \
--cc=dakr@kernel.org \
--cc=driver-core@lists.linux.dev \
--cc=gregkh@linuxfoundation.org \
--cc=hverkuil+cisco@kernel.org \
--cc=johan@kernel.org \
--cc=laurent.pinchart@ideasonboard.com \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=mchehab@kernel.org \
--cc=rafael@kernel.org \
--cc=rdunlap@infradead.org \
--cc=skhan@linuxfoundation.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.