From: Philipp Stanner <phasta@kernel.org>
To: "Sumit Semwal" <sumit.semwal@linaro.org>,
"Christian König" <christian.koenig@amd.com>,
"Jani Nikula" <jani.nikula@linux.intel.com>,
"Joonas Lahtinen" <joonas.lahtinen@linux.intel.com>,
"Rodrigo Vivi" <rodrigo.vivi@intel.com>,
"Tvrtko Ursulin" <tursulin@ursulin.net>,
"David Airlie" <airlied@gmail.com>,
"Simona Vetter" <simona@ffwll.ch>,
"Steven Rostedt" <rostedt@goodmis.org>,
"Masami Hiramatsu" <mhiramat@kernel.org>,
"Mathieu Desnoyers" <mathieu.desnoyers@efficios.com>,
"Miguel Ojeda" <ojeda@kernel.org>,
"Boqun Feng" <boqun@kernel.org>, "Gary Guo" <gary@garyguo.net>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
"Benno Lossin" <lossin@kernel.org>,
"Andreas Hindborg" <a.hindborg@kernel.org>,
"Alice Ryhl" <aliceryhl@google.com>,
"Trevor Gross" <tmgross@umich.edu>,
"Danilo Krummrich" <dakr@kernel.org>,
"Daniel Almeida" <daniel.almeida@collabora.com>,
"Tamir Duberstein" <tamird@kernel.org>,
"Alexandre Courbot" <acourbot@nvidia.com>,
"Onur Özkan" <work@onurozkan.dev>,
"Boris Brezillon" <boris.brezillon@collabora.com>,
"Alex Deucher" <alexdeucher@gmail.com>
Cc: linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org,
linux-kernel@vger.kernel.org, intel-gfx@lists.freedesktop.org,
linux-trace-kernel@vger.kernel.org,
rust-for-linux@vger.kernel.org,
Philipp Stanner <phasta@kernel.org>
Subject: [RFC PATCH v2 3/3] dma-fence: Support unload for ops->get_XXX_name()
Date: Tue, 20 Oct 2026 12:00:34 +0200 [thread overview]
Message-ID: <20261020100034.759183-5-phasta@kernel.org> (raw)
In-Reply-To: <20261020100034.759183-2-phasta@kernel.org>
dma_fence's backend_ops get_driver_name() and get_timeline_name() have
an unnecessary and complicated RCU requirement.
Usage in sync_file, however, already shows how it can be done
significantly simpler: Copy the name strings to the user.
All that needs to be ensured for that is that the signaled-state is
checked and that it cannot change while the callback runs, i.e., the
lock must be held.
Adjust the two callbacks so that they deep-copy name parameters under
lock-protection.
Signed-off-by: Philipp Stanner <phasta@kernel.org>
---
drivers/dma-buf/dma-fence.c | 73 ++++++++++-----------
drivers/dma-buf/sync_file.c | 29 ++++----
drivers/gpu/drm/i915/gt/intel_gt_requests.c | 16 ++---
drivers/gpu/drm/i915/i915_request.c | 9 ++-
drivers/gpu/drm/i915/i915_sw_fence.c | 15 ++---
include/linux/dma-fence.h | 22 ++-----
include/trace/events/dma_fence.h | 12 ++--
7 files changed, 77 insertions(+), 99 deletions(-)
diff --git a/drivers/dma-buf/dma-fence.c b/drivers/dma-buf/dma-fence.c
index e4350bce9cf9..d473d4ea601a 100644
--- a/drivers/dma-buf/dma-fence.c
+++ b/drivers/dma-buf/dma-fence.c
@@ -555,23 +555,22 @@ void dma_fence_release(struct kref *kref)
struct dma_fence *fence =
container_of(kref, struct dma_fence, refcount);
const struct dma_fence_ops *ops = fence->ops;
+ const unsigned short len = 64;
+ char timeline[len];
+ char driver[len];
- rcu_read_lock();
trace_dma_fence_destroy(fence);
if (!list_empty(&fence->cb_list) &&
!dma_fence_test_signaled_flag(fence)) {
- const char __rcu *timeline;
- const char __rcu *driver;
unsigned long flags;
- driver = dma_fence_driver_name(fence);
- timeline = dma_fence_timeline_name(fence);
+ dma_fence_driver_name(fence, driver, len);
+ dma_fence_timeline_name(fence, timeline, len);
WARN(1,
"Fence %s:%s:%llx:%llx released with pending signals!\n",
- rcu_dereference(driver), rcu_dereference(timeline),
- fence->context, fence->seqno);
+ driver, timeline, fence->context, fence->seqno);
/*
* Failed to signal before release, likely a refcounting issue.
@@ -590,7 +589,6 @@ void dma_fence_release(struct kref *kref)
ops->release(fence);
else
dma_fence_free(fence);
- rcu_read_unlock();
}
EXPORT_SYMBOL(dma_fence_release);
@@ -1017,23 +1015,20 @@ EXPORT_SYMBOL(dma_fence_set_deadline);
*/
void dma_fence_describe(struct dma_fence *fence, struct seq_file *seq)
{
- const char __rcu *timeline = (const char __rcu *)"";
- const char __rcu *driver = (const char __rcu *)"";
- const char *signaled = "";
-
- rcu_read_lock();
+ const unsigned short len = 64;
+ char timeline[len];
+ char driver[len];
+ char *signaled;
if (!dma_fence_is_signaled(fence)) {
- timeline = dma_fence_timeline_name(fence);
- driver = dma_fence_driver_name(fence);
+ dma_fence_timeline_name(fence, timeline, len);
+ dma_fence_driver_name(fence, driver, len);
signaled = "un";
}
seq_printf(seq, "%llu:%llu %s %s %ssignalled\n",
fence->context, fence->seqno, timeline, driver,
signaled);
-
- rcu_read_unlock();
}
EXPORT_SYMBOL(dma_fence_describe);
@@ -1129,20 +1124,22 @@ EXPORT_SYMBOL(dma_fence_init64);
* memory potentially accessed by the &dma_fence.ops functions, is forbidden
* after the fence has been signalled. Drivers are allowed to free that data,
* and some do.
- *
- * To allow safe access drivers are mandated to guarantee a RCU grace period
- * between signalling the fence and freeing said data.
- *
- * As such access to the driver name is only valid inside a RCU locked section.
- * The pointer MUST be both queried and USED ONLY WITHIN a SINGLE block guarded
- * by the &rcu_read_lock and &rcu_read_unlock pair.
*/
-const char __rcu *dma_fence_driver_name(struct dma_fence *fence)
+void dma_fence_driver_name(struct dma_fence *fence, char *s, unsigned short len)
{
+ unsigned long flags;
+ const char *tmp;
+
+ dma_fence_lock_irqsave(fence, flags);
+
if (!dma_fence_test_signaled_flag(fence))
- return (const char __rcu *)fence->ops->get_driver_name(fence);
+ tmp = fence->ops->get_driver_name(fence);
else
- return (const char __rcu *)"detached-driver";
+ tmp = "detached-driver";
+
+ strscpy(s, tmp, len);
+
+ dma_fence_unlock_irqrestore(fence, flags);
}
EXPORT_SYMBOL(dma_fence_driver_name);
@@ -1158,19 +1155,21 @@ EXPORT_SYMBOL(dma_fence_driver_name);
* memory potentially accessed by the &dma_fence.ops functions, is forbidden
* after the fence has been signalled. Drivers are allowed to free that data,
* and some do.
- *
- * To allow safe access drivers are mandated to guarantee a RCU grace period
- * between signalling the fence and freeing said data.
- *
- * As such access to the driver name is only valid inside a RCU locked section.
- * The pointer MUST be both queried and USED ONLY WITHIN a SINGLE block guarded
- * by the &rcu_read_lock and &rcu_read_unlock pair.
*/
-const char __rcu *dma_fence_timeline_name(struct dma_fence *fence)
+void dma_fence_timeline_name(struct dma_fence *fence, char *s, unsigned short len)
{
+ unsigned long flags;
+ const char *tmp;
+
+ dma_fence_lock_irqsave(fence, flags);
+
if (!dma_fence_test_signaled_flag(fence))
- return (const char __rcu *)fence->ops->get_timeline_name(fence);
+ tmp = fence->ops->get_timeline_name(fence);
else
- return (const char __rcu *)"signaled-timeline";
+ tmp = "signaled-timeline";
+
+ strscpy(s, tmp, len);
+
+ dma_fence_unlock_irqrestore(fence, flags);
}
EXPORT_SYMBOL(dma_fence_timeline_name);
diff --git a/drivers/dma-buf/sync_file.c b/drivers/dma-buf/sync_file.c
index 2166bbdf7e4a..0f08713b3b5e 100644
--- a/drivers/dma-buf/sync_file.c
+++ b/drivers/dma-buf/sync_file.c
@@ -18,6 +18,8 @@
#include <linux/sync_file.h>
#include <uapi/linux/sync_file.h>
+#define FENCE_NAME_LEN 64
+
static const struct file_operations sync_file_fops;
static struct sync_file *sync_file_alloc(void)
@@ -131,22 +133,21 @@ EXPORT_SYMBOL(sync_file_get_fence);
*/
char *sync_file_get_name(struct sync_file *sync_file, char *buf, int len)
{
+ char timeline[FENCE_NAME_LEN];
+ char driver[FENCE_NAME_LEN];
+
if (sync_file->user_name[0]) {
strscpy(buf, sync_file->user_name, len);
} else {
struct dma_fence *fence = sync_file->fence;
- const char __rcu *timeline;
- const char __rcu *driver;
- rcu_read_lock();
- driver = dma_fence_driver_name(fence);
- timeline = dma_fence_timeline_name(fence);
+ dma_fence_driver_name(fence, driver, FENCE_NAME_LEN);
+ dma_fence_timeline_name(fence, timeline, FENCE_NAME_LEN);
snprintf(buf, len, "%s-%s%llu-%lld",
- rcu_dereference(driver),
- rcu_dereference(timeline),
+ driver,
+ timeline,
fence->context,
fence->seqno);
- rcu_read_unlock();
}
return buf;
@@ -268,19 +269,11 @@ static long sync_file_ioctl_merge(struct sync_file *sync_file,
static int sync_fill_fence_info(struct dma_fence *fence,
struct sync_fence_info *info)
{
- const char __rcu *timeline;
- const char __rcu *driver;
+ dma_fence_timeline_name(fence, info->obj_name, sizeof(info->obj_name));
+ dma_fence_driver_name(fence, info->driver_name, sizeof(info->driver_name));
rcu_read_lock();
- driver = dma_fence_driver_name(fence);
- timeline = dma_fence_timeline_name(fence);
-
- strscpy(info->obj_name, rcu_dereference(timeline),
- sizeof(info->obj_name));
- strscpy(info->driver_name, rcu_dereference(driver),
- sizeof(info->driver_name));
-
info->status = dma_fence_get_status(fence);
info->timestamp_ns =
dma_fence_is_signaled(fence) ?
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_requests.c b/drivers/gpu/drm/i915/gt/intel_gt_requests.c
index 93298820bee2..a37069ca6d2a 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_requests.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt_requests.c
@@ -240,8 +240,12 @@ void intel_gt_watchdog_work(struct work_struct *work)
{
struct intel_gt *gt =
container_of(work, typeof(*gt), watchdog.work);
+ const unsigned short len = 64;
struct i915_request *rq, *rn;
struct llist_node *first;
+ char timeline[len];
+ char driver[len];
+
first = llist_del_all(>->watchdog.list);
if (!first)
@@ -250,17 +254,13 @@ void intel_gt_watchdog_work(struct work_struct *work)
llist_for_each_entry_safe(rq, rn, first, watchdog.link) {
if (!i915_request_completed(rq)) {
struct dma_fence *f = &rq->fence;
- const char __rcu *timeline;
- const char __rcu *driver;
- rcu_read_lock();
- driver = dma_fence_driver_name(f);
- timeline = dma_fence_timeline_name(f);
+ dma_fence_driver_name(f, driver, len);
+ dma_fence_timeline_name(f, timeline, len);
pr_notice("Fence expiration time out i915-%s:%s:%llx!\n",
- rcu_dereference(driver),
- rcu_dereference(timeline),
+ driver,
+ timeline,
f->seqno);
- rcu_read_unlock();
i915_request_cancel(rq, -EINTR);
}
i915_request_put(rq);
diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c
index d2c7b1090df0..c81902d8a89a 100644
--- a/drivers/gpu/drm/i915/i915_request.c
+++ b/drivers/gpu/drm/i915/i915_request.c
@@ -2185,7 +2185,8 @@ void i915_request_show(struct drm_printer *m,
const char *prefix,
int indent)
{
- const char __rcu *timeline;
+ const unsigned short len = 64;
+ char timeline[len];
char buf[80] = "";
int x = 0;
@@ -2221,8 +2222,7 @@ void i915_request_show(struct drm_printer *m,
x = print_sched_attr(&rq->sched.attr, buf, x, sizeof(buf));
- rcu_read_lock();
- timeline = dma_fence_timeline_name((struct dma_fence *)&rq->fence);
+ dma_fence_timeline_name((struct dma_fence *)&rq->fence, timeline, len);
drm_printf(m, "%s%.*s%c %llx:%lld%s%s %s @ %dms: %s\n",
prefix, indent, " ",
queue_status(rq),
@@ -2231,8 +2231,7 @@ void i915_request_show(struct drm_printer *m,
fence_status(rq),
buf,
jiffies_to_msecs(jiffies - rq->emitted_jiffies),
- rcu_dereference(timeline));
- rcu_read_unlock();
+ timeline);
}
static bool engine_match_ring(struct intel_engine_cs *engine, struct i915_request *rq)
diff --git a/drivers/gpu/drm/i915/i915_sw_fence.c b/drivers/gpu/drm/i915/i915_sw_fence.c
index f24f616e23ee..08b5f96ae2a5 100644
--- a/drivers/gpu/drm/i915/i915_sw_fence.c
+++ b/drivers/gpu/drm/i915/i915_sw_fence.c
@@ -429,23 +429,22 @@ static void timer_i915_sw_fence_wake(struct timer_list *t)
{
struct i915_sw_dma_fence_cb_timer *cb = timer_container_of(cb, t,
timer);
+ const unsigned short len = 64;
struct i915_sw_fence *fence;
- const char __rcu *timeline;
- const char __rcu *driver;
+ char timeline[len];
+ char driver[len];
fence = xchg(&cb->base.fence, NULL);
if (!fence)
return;
- rcu_read_lock();
- driver = dma_fence_driver_name(cb->dma);
- timeline = dma_fence_timeline_name(cb->dma);
+ dma_fence_driver_name(cb->dma, driver, len);
+ dma_fence_timeline_name(cb->dma, timeline, len);
pr_notice("Asynchronous wait on fence %s:%s:%llx timed out (hint:%ps)\n",
- rcu_dereference(driver),
- rcu_dereference(timeline),
+ driver,
+ timeline,
cb->dma->seqno,
i915_sw_fence_debug_hint(fence));
- rcu_read_unlock();
i915_sw_fence_set_error_once(fence, -ETIMEDOUT);
i915_sw_fence_complete(fence);
diff --git a/include/linux/dma-fence.h b/include/linux/dma-fence.h
index 2223d75c5a49..08ecbc101f4c 100644
--- a/include/linux/dma-fence.h
+++ b/include/linux/dma-fence.h
@@ -459,25 +459,11 @@ void dma_fence_enable_signaling(struct dma_fence *fence);
/**
* DOC: Safe external access to driver provided object members
*
- * All data not stored directly in the dma-fence object, such as the
- * &dma_fence.lock and memory potentially accessed by functions in the
- * &dma_fence.ops table, MUST NOT be accessed after the fence has been signalled
- * because after that point drivers are allowed to free it.
- *
- * All code accessing that data via the dma-fence API (or directly, which is
- * discouraged), MUST make sure to contain the complete access within a
- * &rcu_read_lock and &rcu_read_unlock pair.
- *
- * Some dma-fence API handles this automatically, while other, as for example
- * &dma_fence_driver_name and &dma_fence_timeline_name, leave that
- * responsibility to the caller.
- *
- * To enable this scheme to work drivers MUST ensure a RCU grace period elapses
- * between signalling the fence and freeing the said data.
- *
+ * Provides naming information strings about the fence if it is not yet signaled.
+ * Otherwise, provides default strings.
*/
-const char __rcu *dma_fence_driver_name(struct dma_fence *fence);
-const char __rcu *dma_fence_timeline_name(struct dma_fence *fence);
+void dma_fence_driver_name(struct dma_fence *fence, char *s, unsigned short len);
+void dma_fence_timeline_name(struct dma_fence *fence, char *s, unsigned short len);
/*
* dma_fence_test_signaled_flag - Only check whether a fence is signaled yet.
diff --git a/include/trace/events/dma_fence.h b/include/trace/events/dma_fence.h
index 5b10a9e06fb4..f3b929b98cf4 100644
--- a/include/trace/events/dma_fence.h
+++ b/include/trace/events/dma_fence.h
@@ -9,6 +9,8 @@
struct dma_fence;
+#define FENCE_NAME_LEN 64
+
DECLARE_EVENT_CLASS(dma_fence,
TP_PROTO(struct dma_fence *fence),
@@ -16,21 +18,21 @@ DECLARE_EVENT_CLASS(dma_fence,
TP_ARGS(fence),
TP_STRUCT__entry(
- __string(driver, dma_fence_driver_name(fence))
- __string(timeline, dma_fence_timeline_name(fence))
+ __array(char, driver, FENCE_NAME_LEN)
+ __array(char, timeline, FENCE_NAME_LEN)
__field(unsigned int, context)
__field(unsigned int, seqno)
),
TP_fast_assign(
- __assign_str(driver);
- __assign_str(timeline);
+ dma_fence_driver_name(fence, __entry->driver, FENCE_NAME_LEN);
+ dma_fence_timeline_name(fence, __entry->timeline, FENCE_NAME_LEN);
__entry->context = fence->context;
__entry->seqno = fence->seqno;
),
TP_printk("driver=%s timeline=%s context=%u seqno=%u",
- __get_str(driver), __get_str(timeline), __entry->context,
+ __entry->driver, __entry->timeline, __entry->context,
__entry->seqno)
);
--
2.56.0
next prev parent reply other threads:[~2026-10-20 10:01 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-20 10:00 [RFC PATCH v2 0/3] Solve dma_fence's problems by locking Philipp Stanner
2026-10-20 10:00 ` [RFC PATCH v2 1/3] dma-fence: Remove RCU protection for fence->ops Philipp Stanner
2026-10-20 10:20 ` sashiko-bot
2026-10-20 10:00 ` [RFC PATCH v2 2/3] dma-fence: use lock to protect against module-unload Philipp Stanner
2026-10-20 10:19 ` sashiko-bot
2026-10-20 10:00 ` Philipp Stanner [this message]
2026-10-20 10:27 ` [RFC PATCH v2 3/3] dma-fence: Support unload for ops->get_XXX_name() sashiko-bot
2026-10-20 11:48 ` ✓ i915.CI.BAT: success for Solve dma_fence's problems by locking Patchwork
2026-10-20 12:02 ` [RFC PATCH v2 0/3] " Christian König
2026-10-20 14:41 ` Philipp Stanner
2026-10-20 15:07 ` Christian König
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=20261020100034.759183-5-phasta@kernel.org \
--to=phasta@kernel.org \
--cc=a.hindborg@kernel.org \
--cc=acourbot@nvidia.com \
--cc=airlied@gmail.com \
--cc=alexdeucher@gmail.com \
--cc=aliceryhl@google.com \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun@kernel.org \
--cc=boris.brezillon@collabora.com \
--cc=christian.koenig@amd.com \
--cc=dakr@kernel.org \
--cc=daniel.almeida@collabora.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=gary@garyguo.net \
--cc=intel-gfx@lists.freedesktop.org \
--cc=jani.nikula@linux.intel.com \
--cc=joonas.lahtinen@linux.intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=linux-trace-kernel@vger.kernel.org \
--cc=lossin@kernel.org \
--cc=mathieu.desnoyers@efficios.com \
--cc=mhiramat@kernel.org \
--cc=ojeda@kernel.org \
--cc=rodrigo.vivi@intel.com \
--cc=rostedt@goodmis.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=simona@ffwll.ch \
--cc=sumit.semwal@linaro.org \
--cc=tamird@kernel.org \
--cc=tmgross@umich.edu \
--cc=tursulin@ursulin.net \
--cc=work@onurozkan.dev \
/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.