On Fri, Aug 21, 2026 at 07:48:40PM +1000, NeilBrown wrote:
> On Fri, 21 Aug 2026, David Hildenbrand (Arm) wrote:
> > [...]
> >
> > > Exactly. That's why we use classification e.g. lock class - DEPT also
> > > makes use of the concept.
> > >
> > > DEPT doesn't use a full map in each page but uses a minimum space for a
> > > timestamp in each to track when each starts to wait so as to use the
> > > recorded timestamp when the event occurs e.g. folio_unlock().
> >
> > Thanks for that information!
> >
> > >
> > >> Given that lockdep is a debug feature, and we will at some point allocate struct
> > >> folio separately, I assume we could just squeeze a "struct lockdep_map" in there
> > >> in such debug configs and the world would not collapse.
> > >
> > > That's a good news for lockdep. (And even for DEPT :)
> >
> > He :) Where do you currently store the additional per-page information?
>
> lockdep doesn't need to store per-page information. Possibly DEPT
> doesn't either.
Class can be stored in global map, but DEPT needs to keep a timestamp
in each page to track when a potential-wait e.g. folio_lock() has been
started and to refer to the information on its event e.g. folio_unlock().
> lockdep needs one lockdep_map for each lock class. It would make sense
> for all folio locks to use the same global lockdep_map.
Exactly. Only considering classes, you are right.
> Each specific lock is known to lockdep as a task which holds the lock, a
> lockdep_map which represents the class of locks, and subclass number
> which allows a given task to hold multiple locks of the same class
> providing it declare (e.g. with spin_lock_nested() etc).
Right, lockdep works that way.
> > >> Doing that today (one "struct lockdep_map" in each "struct page") wouldn't work
> > >> as mm_zero_struct_page() would not expect such large "struct page". But
> > >> conceptually, for a debug kernel with a special CONFIG_LOCKDEP_PAGE_LOCK, maybe
> > >> that would already be ok and we could just do that (and optimize it as we
> > >> allocate folios separately).
> > >
> > > Sounds great.
> > >
> > >> Not that it's ideal, but for a debug feature to at least check PG_lock, probably
> > >> an easier way to achieve it than some completely new infrastructure.
> > >
> > > I understand what you are going to tell.
> > >
> > > However, it's worth noting that lockdep tracks dependencies basically
> > > based on **lock acqusition orders** in the system. To make it track
> > > even rwlock and general synchronization mechanism as well, lockdep has
> > > no choice but to get more complicated.
> >
> > Well, yes, sure :)
> >
> > >
> > > Focusing on only the dependency checking, the most parts of lockdep are
> > > for the tricky things, so the reusable parts are not that big.
> > >
> > >> Now, Willy said "locking rules don't really apply to individual folios", I
> > >> wonder if that could just help to also let lockdep check PG_lock with less
> > >> metadata? (didn't fully wrap my head around the implications)
> > >
> > > That's what DEPT did and what brought external wgen introduced in DEPT.
> > > I was considering the exactly same thing :)
> > >
> > > Again, lockdep that tracks lock acquisition orders can't do that.
> > >
> > >> [1]
> > >> https://lore.kernel.org/all/aR3WHf9QZ_dizNun@casper.infradead.org/?utm_sour…
> > >>
> > >>
> > >> It's your guiding example, that's why I mention it. You do mention other wait
> > >> cases here, I don't know anything about them, but for folios it's really just
> > >> "we used a single bit so far" AFAIKs.
> > >
> > > It doesn't matter whether it's implemented using bit or not. folio lock
> > > is quite special since it's allowed to be released other than the
> > > acquisition context that makes lockdep impossible to track them.
> >
> > Does that really make lockdep *impossible* to track them? IOW, there is no way
> > to extend lockdep to support lock release in different context?
>
> Yes and no....
>
> lockdep has no knowledge of control flows moving across threads in the
> way that I assume DEPT does. But it should be possible to tell it.
>
> If you have some code that takes a lock and then hands it off to
> another thread, at the hand-off point you call
> lock_map_release(&the_lock_map)
>
> This says "no task owns this lock any more".
>
> maybe you put the folio which is locked on a queue or an lru or
> whatever.
>
> There is no way to say "that queue owns this lock". Maybe that could
> usefully be added - assuming coherent semantics can be designed.
It's certainly useful to track who owns the lock, but the essence, when
it comes to deadlock detection, lies elsewhere. DEPT is based on the
essence, that is, a deadlock comes from waits that are never awakened.
> Somewhere else some other task takes responsibility for that folio and
> the lock. maybe it dequeues a page, or maybe an lru callback gives the
> locked page to some code.
> That code then calls
> lock_map_acquire_try(&the_lock_map)
>
> This says "this task is now holding this lock" (or more accurately "now
> holding a lock of this class").
> Note the "_try" - that says that the task didn't have to wait for the
> lock, it just got it for free, which in fact it did.
>
> Now if that task takes some other lock, lockdep will see a dependency
> between the page lock and the new lock, and will accept or reject it as
> you would expect.
It's an interesting approach if your goal is to track the owenership,
but if the goal is for tracking dependencies.. well.. I'm not sure.
Byungchul
> So you definitely *can* send lock dependency information between tasks
> with lockdep. I have only tried it in extremely simple cases where a
> single object is being locked by one task and unlocked by another - no
> queues or lists.
> There may be - and probably are - more complexities involved with
> locking folios and passing them around. Maybe it is so complex that you
> need all the support that DEPT provides. But I'd like to see a coherent
> explanation of how the functionality offered by DEPT is clearly better.
>
> NeilBrown
>
> >
> > I guess there is a way, but the question is at which price (I seriously have no
> > idea, maybe this was already discussed and people have a pointer for me).
> >
> > >
> > >> [...]
> > >>
> > >>>
> > >>> Q. Why not build DEPT into lockdep?
> > >>>
> > >>> A. Lockdep is stable, battle-tested code. I chose separation because
> > >>> while DEPT borrows BFS and hashing ideas, the wait/event model
> > >>> requires rebuilding from scratch. Lockdep was designed for lock
> > >>> acquisition order — retrofitting it would risk its stability.
> > >>
> > >> Why can't this just be some configurable extension to lockdep
> > >> (CONFIG_LOCKDEP_XYZ) until the feature is stable and can unconditionally be
> > >> enabled along with it?
> > >
> > > Answered?
> >
> > Not quite. I don't understand why this must be a completely separate machinery,
> > even if, conceptually, it would do more than traditional lockdep.
> >
> > Is it either DEPT or LOCKDEP in current configurations? Can both run at the same
> > time?
> >
> > >
> > >> I don't quite buy the "would risk its stability" argument. A lot of stuff we do
> > >> "risks stability", every day :)
> > >
> > > That's awsome anyway :)
> > >
> > >> Is there another good reason (incompatible with X, dangerous with Y, cinfusing
> > >> Z) why this really must be a separate thing?
> > >
> > > Roughly:
> > >
> > > 1. Similar or less effort is needed for the new one - retrofitting
> > > lockdep is not easy and big changes are required since the
> > > reusable parts are not that big.
> > >
> > > 2. Even though you didn't agree, retrofitting it would risk its
> > > stability.
> >
> > Well, I don't buy the stability argument, really :)
> >
> > Retrofitting effort for lockdep is an interesting point, though. Lockdep
> > maintainers would have to make the call here regarding direction and feasibility.
> >
> > [...]
> >
> > >> But I am not a locking maintainer. I think there was plenty of discussion in the
> > >> past, so I might just be raising points that were already discussed in the past,
> > >> but I really just read some random pieces of earlier discussions. (ideally
> > >> previous discussions would be summarized here)
> > >>
> > >> Long story short: we are now in v19 and I think there was pushback in the past.
> > >> Did the opinion of locking maintainers change, or is there a way forward to
> > >> integrate this in a way that would make locking maintainers accept this?
> > >
> > > One of locking maintainers who I met in an LPC told me that he agrees
> > > with the direction of DEPT and supports DEPT, not officially tho.
> >
> > Hm.
> >
> > >
> > > What he and other people are concerning w.r.t DEPT the most is, false
> > > positives, which is the most important issue for now.
> >
> > Thanks for highlighting that. What's the main reason for false positives? Is it
> > something conceptual that is mostly impossible to solve, or rather just
> > implementation work to cover all edge cases?
> >
> > >
> > > At the same time, I think the most important thing is to make DEPT
> > > useful in practice especially with folio locks involved. Actually, I'm
> > > planning to share DEPT's true reports periodically to LKML and work with
> > > people who believe DEPT can make things better.
> > >
> > > Any advices will be welcome. Thanks for your opinions.
> >
> > I think we must come to some conclusion on how to proceed with DEPT. I see the
> > following options:
> >
> > (1) Don't merge it and carry it OOT. Shame if it delivers real value.
> >
> > (2) Merge it (after proper review and acks from relevant maintainers ;) ),
> > keeping it entirely separate from lockdep.
> >
> > (3) Integrate it with lockdep on a high level, giving us a single locking
> > dependency checker, but mostly letting dept have a separate implementation.
> > Look into possible merging afterwards.
> >
> > (4) Retrofit and extend lockdep to really have one mechanism.
> >
> > As the saying goes, it's hard to teach old dogs new tricks, but in the end
> > taking care of two dogs is likely harder than only a single dog? :)
> >
> > I tend to favor (4) (or 3 with possible future work to achieve 4), but I am not
> > a locking maintainer, so really they have to voice what to do.
> >
> > I do see value in DEPT (even if the folio lock might be handled differently).
> >
> > --
> > Cheers,
> >
> > David
> >
>
On 20.08.2026 20:04, David Hildenbrand (Arm) wrote:
>> /* This part must be outside protection */> diff --git a/mm/cma.c b/mm/cma.c
>> index a10ea37a261d..1e1ebae79090 100644
>> --- a/mm/cma.c
>> +++ b/mm/cma.c
>> @@ -936,6 +936,141 @@ struct page *cma_alloc_frozen_compound(struct cma *cma, unsigned int order)
>> return __cma_alloc_frozen(cma, 1 << order, order, gfp);
>> }
>> +static int cma_range_alloc_at(struct cma *cma, struct cma_memrange *cmr,
>> + unsigned long offset, unsigned long count,
>> + struct page **pagep, gfp_t gfp)
>> +{
>> + struct page *page = NULL;
>> + unsigned long pfn;
>> + int ret = -EBUSY;
>> +
>> + spin_lock_irq(&cma->lock);
>> +
>> + /*
>> + * If the request is larger than the available number of pages, stop
>> + * right away.
>> + */
>> + if (count > cma->available_count)
>> + goto unlock;
>> +
>> + ret = bitmap_allocate(cmr->bitmap, offset, count);
>> + if (ret < 0)
>> + goto unlock;
>> +
>> + pfn = cmr->base_pfn + offset;
>> + page = pfn_to_page(pfn);
>> +
>> + /*
>> + * Do not hand out page ranges that are not contiguous, so
>> + * callers can just iterate the pages without having to worry
>> + * about these corner cases.
>> + */
>> + if (!page_range_contiguous(page, count)) {
>> + pr_warn_ratelimited("%s: %s: skipping non-contiguous area [0x%lx-0x%lx]",
>> + __func__, cma->name, pfn, pfn + count - 1);
>> + ret = -EBUSY;
>> + goto clear;
>> + }
>> +
>> + cma->available_count -= count;
>> +
>> + /*
>> + * It's safe to drop the lock here. We've marked this region for
>> + * our exclusive use. If the migration fails we will take the
>> + * lock again and unmark it.
>> + */
>> + spin_unlock_irq(&cma->lock);
>> +
>> + mutex_lock(&cma->alloc_mutex);
>> + ret = alloc_contig_frozen_range(pfn, pfn + count, ACR_FLAGS_CMA, gfp);
>> + mutex_unlock(&cma->alloc_mutex);
>> +
> There is quite some code duplication with cma_range_alloc(). Please try harder
> to factor common code out and reuse it.
>
>
> > ...
> Also here, way too much code duplication with __cma_alloc_frozen().
>
> There must be a better way :)
Maybe the existing 'alloc' functions could call 'alloc_at' variant internally
(with locks adjusted and moved out).
> (I really prefer this direction of the patch set)
Definitely, I also like this approach much more than previous attempt with
'dynamically' instantiated cma regions.
Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland
On 8/20/26 21:08, Ferran Duarri wrote:
> dma-buf has no generic mechanism for a buffer's exporter, importer, or
> a cooperating userspace agent to signal how eagerly a given buffer's
> backing memory should be given up relative to other buffers when the
> system is under memory pressure. Pages pinned via pin_user_pages()/
> FOLL_LONGTERM sit outside the normal reclaim path by design, so any
> subsystem that wants a "prefer to keep A over B under pressure" policy
> for its pinned dma-buf allocations currently has to invent its own
> private, driver-specific side channel to express it.
Well to start exporting pages pinned with FOLL_LONGTERM as DMA-buf is absolutely *STRICTLY* forbidden. I hope that you know this.
What can be done is for exporters to migrate a DMA-buf between local memory, system memory and swap, but even that usually doesn't happen depending on the normal reclaim mechanism.
It could be interesting to implement something like that for backing some Vulkan extension, but IIRC that is currently not even supported by anybody.
Anyway as long as you can demonstrate any of this with an in tree driver the whole approach is not something we would discuss in the first place.
Regards,
Christian.
>
> This is a real, recurring pattern: GPU drivers juggling foreground and
> background clients want it, and it shows up concretely in large-model
> AI/ML inference stacks that tier working sets across VRAM/system-RAM/
> NVMe using their own dma-buf exporters -- e.g. an out-of-tree memory
> tiering driver we've been using has its own gaming_mode sysfs flag and
> a per-buffer "heat" score, moving its own DMA-BUF-backed allocations to
> its own private LRU tail under a private IOCTL, purely because there is
> nowhere generic to express "this buffer can go first."
>
> Add one small, opt-in hint instead of another private channel:
>
> - struct dma_buf gains a `priority` field (atomic_t, plain hint, no
> new locking), defaulting to DMA_BUF_PRIORITY_DEFAULT (128) and
> ranging DMA_BUF_PRIORITY_MIN (0) to DMA_BUF_PRIORITY_MAX (255).
> Lower values should be reclaimed EARLIER under memory pressure.
>
> - dma_buf_set_priority()/dma_buf_get_priority(), exported under the
> DMA_BUF symbol namespace, so any dma-buf exporter (in-tree or an
> out-of-tree module) can set/read it directly.
>
> - DMA_BUF_IOCTL_SET_PRIORITY / DMA_BUF_IOCTL_GET_PRIORITY so
> userspace holding an fd can do the same, without needing a private
> driver ioctl.
>
> - The current value is reported via fdinfo (`priority:`) for
> debugging/accounting, next to the existing size/name/exp_name
> fields.
>
> This is deliberately a hint only: dma-buf core stores and reports the
> value, it implements no eviction policy of its own, and it changes no
> behavior for any existing exporter or importer that doesn't opt in.
> No existing dma_buf_ops callback is touched. Compile-tested: drivers/
> dma-buf/ (incl. the selftest module) and drivers/gpu/drm/drm_prime.o
> both build clean against this change.
>
> Signed-off-by: Ferran Duarri <ferran.duarri(a)me.com>
> ---
> drivers/dma-buf/dma-buf.c | 51 ++++++++++++++++++++++++++++++++++++
> include/linux/dma-buf.h | 26 ++++++++++++++++++
> include/uapi/linux/dma-buf.h | 33 +++++++++++++++++++++++
> 3 files changed, 110 insertions(+)
>
> diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
> index d504c636dc29..1b1d3ee77f47 100644
> --- a/drivers/dma-buf/dma-buf.c
> +++ b/drivers/dma-buf/dma-buf.c
> @@ -432,6 +432,39 @@ static long dma_buf_set_name(struct dma_buf *dmabuf, const char __user *buf)
> return 0;
> }
>
> +/**
> + * dma_buf_set_priority - Set the reclaim-priority hint on a dma_buf.
> + * @dmabuf: [in] buffer to update.
> + * @priority: [in] new priority, clamped to
> + * [DMA_BUF_PRIORITY_MIN, DMA_BUF_PRIORITY_MAX].
> + *
> + * Lower values should be reclaimed EARLIER under memory pressure. This is
> + * a hint only , dma-buf core stores and reports it, it implements no
> + * eviction policy itself. Safe to call at any time, from any context that
> + * can call dma_buf_get()/hold a reference (no locking required beyond
> + * that reference).
> + */
> +void dma_buf_set_priority(struct dma_buf *dmabuf, unsigned int priority)
> +{
> + if (priority > DMA_BUF_PRIORITY_MAX)
> + priority = DMA_BUF_PRIORITY_MAX;
> + atomic_set(&dmabuf->priority, priority);
> +}
> +EXPORT_SYMBOL_NS_GPL(dma_buf_set_priority, "DMA_BUF");
> +
> +/**
> + * dma_buf_get_priority - Read back the current reclaim-priority hint.
> + * @dmabuf: [in] buffer to query.
> + *
> + * Returns the value most recently set via dma_buf_set_priority() (or
> + * DMA_BUF_PRIORITY_DEFAULT if never set).
> + */
> +unsigned int dma_buf_get_priority(struct dma_buf *dmabuf)
> +{
> + return atomic_read(&dmabuf->priority);
> +}
> +EXPORT_SYMBOL_NS_GPL(dma_buf_get_priority, "DMA_BUF");
> +
> #if IS_ENABLED(CONFIG_SYNC_FILE)
> static long dma_buf_export_sync_file(struct dma_buf *dmabuf,
> void __user *user_data)
> @@ -542,6 +575,7 @@ static long dma_buf_ioctl(struct file *file,
> {
> struct dma_buf *dmabuf;
> struct dma_buf_sync sync;
> + struct dma_buf_priority prio;
> enum dma_data_direction direction;
> int ret;
>
> @@ -580,6 +614,21 @@ static long dma_buf_ioctl(struct file *file,
> case DMA_BUF_SET_NAME_B:
> return dma_buf_set_name(dmabuf, (const char __user *)arg);
>
> + case DMA_BUF_IOCTL_SET_PRIORITY:
> + if (copy_from_user(&prio, (void __user *)arg, sizeof(prio)))
> + return -EFAULT;
> + if (prio.pad || prio.priority > DMA_BUF_PRIORITY_MAX)
> + return -EINVAL;
> + dma_buf_set_priority(dmabuf, prio.priority);
> + return 0;
> +
> + case DMA_BUF_IOCTL_GET_PRIORITY:
> + memset(&prio, 0, sizeof(prio));
> + prio.priority = dma_buf_get_priority(dmabuf);
> + if (copy_to_user((void __user *)arg, &prio, sizeof(prio)))
> + return -EFAULT;
> + return 0;
> +
> #if IS_ENABLED(CONFIG_SYNC_FILE)
> case DMA_BUF_IOCTL_EXPORT_SYNC_FILE:
> return dma_buf_export_sync_file(dmabuf, (void __user *)arg);
> @@ -604,6 +653,7 @@ static void dma_buf_show_fdinfo(struct seq_file *m, struct file *file)
> if (dmabuf->name)
> seq_printf(m, "name:\t%s\n", dmabuf->name);
> spin_unlock(&dmabuf->name_lock);
> + seq_printf(m, "priority:\t%u\n", dma_buf_get_priority(dmabuf));
> }
>
> static const struct file_operations dma_buf_fops = {
> @@ -748,6 +798,7 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
> dmabuf->exp_name = exp_info->exp_name;
> dmabuf->owner = exp_info->owner;
> spin_lock_init(&dmabuf->name_lock);
> + atomic_set(&dmabuf->priority, DMA_BUF_PRIORITY_DEFAULT);
> init_waitqueue_head(&dmabuf->poll);
> dmabuf->cb_in.poll = dmabuf->cb_out.poll = &dmabuf->poll;
> dmabuf->cb_in.active = dmabuf->cb_out.active = 0;
> diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h
> index d1203da56fc5..b3d3f2858704 100644
> --- a/include/linux/dma-buf.h
> +++ b/include/linux/dma-buf.h
> @@ -354,6 +354,29 @@ struct dma_buf {
> /** @name_lock: Spinlock to protect name access for read access. */
> spinlock_t name_lock;
>
> + /**
> + * @priority:
> + *
> + * Reclaim-priority hint for this buffer's backing memory, in the
> + * range DMA_BUF_PRIORITY_MIN..DMA_BUF_PRIORITY_MAX (see
> + * include/uapi/linux/dma-buf.h). Lower values should be reclaimed
> + * EARLIER under memory pressure. Defaults to
> + * DMA_BUF_PRIORITY_DEFAULT.
> + *
> + * This is a hint only: dma-buf core implements no eviction policy
> + * of its own, it merely stores and reports the value so exporters
> + * (and cooperating shrinkers) have one shared, generic place to
> + * look instead of each inventing a private side channel. Read with
> + * dma_buf_get_priority(), set with dma_buf_set_priority() , also
> + * reachable from userspace via DMA_BUF_IOCTL_SET_PRIORITY /
> + * DMA_BUF_IOCTL_GET_PRIORITY.
> + *
> + * Plain atomic_t rather than a lock: this is a coarse, racy-by-
> + * design hint consulted opportunistically, not a value anything
> + * synchronizes correctness on.
> + */
> + atomic_t priority;
> +
> /**
> * @owner:
> *
> @@ -566,6 +589,9 @@ void dma_buf_unpin(struct dma_buf_attachment *attach);
>
> struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info);
>
> +void dma_buf_set_priority(struct dma_buf *dmabuf, unsigned int priority);
> +unsigned int dma_buf_get_priority(struct dma_buf *dmabuf);
> +
> int dma_buf_fd(struct dma_buf *dmabuf, int flags);
> struct dma_buf *dma_buf_get(int fd);
> void dma_buf_put(struct dma_buf *dmabuf);
> diff --git a/include/uapi/linux/dma-buf.h b/include/uapi/linux/dma-buf.h
> index e827c9d20c5d..4a1d26e0b0a0 100644
> --- a/include/uapi/linux/dma-buf.h
> +++ b/include/uapi/linux/dma-buf.h
> @@ -168,6 +168,37 @@ struct dma_buf_import_sync_file {
> __s32 fd;
> };
>
> +/**
> + * struct dma_buf_priority - Reclaim-priority hint for a dma-buf
> + *
> + * dma-buf has no generic mechanism for a buffer's exporter, importer, or
> + * a cooperating userspace agent to signal how eagerly this buffer's
> + * backing memory should be given up relative to other buffers when the
> + * system is under memory pressure. Every subsystem that wants this today
> + * (GPU drivers juggling foreground/background clients, memory-tiering
> + * allocators for large ML/AI working sets, ...) has to build its own
> + * private, driver-specific side channel to express it.
> + *
> + * DMA_BUF_IOCTL_SET_PRIORITY / DMA_BUF_IOCTL_GET_PRIORITY add one shared,
> + * generic hint that any dma-buf exporter MAY consult. This is a hint
> + * only: the dma-buf core stores and reports the value, it implements no
> + * eviction policy of its own and by itself changes no behavior for any
> + * existing exporter.
> + */
> +struct dma_buf_priority {
> + /**
> + * @priority: DMA_BUF_PRIORITY_MIN..DMA_BUF_PRIORITY_MAX. Lower
> + * values should be reclaimed EARLIER under memory pressure.
> + */
> + __u32 priority;
> + /** @pad: must be zero, reserved for future use. */
> + __u32 pad;
> +};
> +
> +#define DMA_BUF_PRIORITY_MIN 0
> +#define DMA_BUF_PRIORITY_DEFAULT 128
> +#define DMA_BUF_PRIORITY_MAX 255
> +
> #define DMA_BUF_BASE 'b'
> #define DMA_BUF_IOCTL_SYNC _IOW(DMA_BUF_BASE, 0, struct dma_buf_sync)
>
> @@ -179,5 +210,7 @@ struct dma_buf_import_sync_file {
> #define DMA_BUF_SET_NAME_B _IOW(DMA_BUF_BASE, 1, __u64)
> #define DMA_BUF_IOCTL_EXPORT_SYNC_FILE _IOWR(DMA_BUF_BASE, 2, struct dma_buf_export_sync_file)
> #define DMA_BUF_IOCTL_IMPORT_SYNC_FILE _IOW(DMA_BUF_BASE, 3, struct dma_buf_import_sync_file)
> +#define DMA_BUF_IOCTL_SET_PRIORITY _IOW(DMA_BUF_BASE, 4, struct dma_buf_priority)
> +#define DMA_BUF_IOCTL_GET_PRIORITY _IOR(DMA_BUF_BASE, 5, struct dma_buf_priority)
>
> #endif
> --
> 2.53.0
>
On Fri, Aug 21, 2026 at 09:56:05AM +0200, David Hildenbrand (Arm) wrote:
[...]
> >>> Q. Why not build DEPT into lockdep?
> >>>
> >>> A. Lockdep is stable, battle-tested code. I chose separation because
> >>> while DEPT borrows BFS and hashing ideas, the wait/event model
> >>> requires rebuilding from scratch. Lockdep was designed for lock
> >>> acquisition order — retrofitting it would risk its stability.
> >>
> >> Why can't this just be some configurable extension to lockdep
> >> (CONFIG_LOCKDEP_XYZ) until the feature is stable and can unconditionally be
> >> enabled along with it?
> >
> > Answered?
>
> Not quite. I don't understand why this must be a completely separate machinery,
> even if, conceptually, it would do more than traditional lockdep.
>
> Is it either DEPT or LOCKDEP in current configurations? Can both run at the same
> time?
Yes.
> >
> >> I don't quite buy the "would risk its stability" argument. A lot of stuff we do
> >> "risks stability", every day :)
> >
> > That's awsome anyway :)
> >
> >> Is there another good reason (incompatible with X, dangerous with Y, cinfusing
> >> Z) why this really must be a separate thing?
> >
> > Roughly:
> >
> > 1. Similar or less effort is needed for the new one - retrofitting
> > lockdep is not easy and big changes are required since the
> > reusable parts are not that big.
> >
> > 2. Even though you didn't agree, retrofitting it would risk its
> > stability.
>
> Well, I don't buy the stability argument, really :)
>
> Retrofitting effort for lockdep is an interesting point, though. Lockdep
> maintainers would have to make the call here regarding direction and feasibility.
>
> [...]
>
> >> But I am not a locking maintainer. I think there was plenty of discussion in the
> >> past, so I might just be raising points that were already discussed in the past,
> >> but I really just read some random pieces of earlier discussions. (ideally
> >> previous discussions would be summarized here)
> >>
> >> Long story short: we are now in v19 and I think there was pushback in the past.
> >> Did the opinion of locking maintainers change, or is there a way forward to
> >> integrate this in a way that would make locking maintainers accept this?
> >
> > One of locking maintainers who I met in an LPC told me that he agrees
> > with the direction of DEPT and supports DEPT, not officially tho.
>
> Hm.
>
> >
> > What he and other people are concerning w.r.t DEPT the most is, false
> > positives, which is the most important issue for now.
>
> Thanks for highlighting that. What's the main reason for false positives? Is it
> something conceptual that is mostly impossible to solve, or rather just
> implementation work to cover all edge cases?
It's because of lack of annotations for proper classification. As Willy
mentioned, different call paths for various usages should be annotated
with different classes throughout the kernel.
> > At the same time, I think the most important thing is to make DEPT
> > useful in practice especially with folio locks involved. Actually, I'm
> > planning to share DEPT's true reports periodically to LKML and work with
> > people who believe DEPT can make things better.
> >
> > Any advices will be welcome. Thanks for your opinions.
>
> I think we must come to some conclusion on how to proceed with DEPT. I see the
> following options:
>
> (1) Don't merge it and carry it OOT. Shame if it delivers real value.
>
> (2) Merge it (after proper review and acks from relevant maintainers ;) ),
> keeping it entirely separate from lockdep.
>
> (3) Integrate it with lockdep on a high level, giving us a single locking
> dependency checker, but mostly letting dept have a separate implementation.
> Look into possible merging afterwards.
>
> (4) Retrofit and extend lockdep to really have one mechanism.
>
> As the saying goes, it's hard to teach old dogs new tricks, but in the end
> taking care of two dogs is likely harder than only a single dog? :)
Or it's better to train a unmatured hunting dog than to teach a pet dog,
how to hunt, for better hunting, even though the pet dog might
eventually become able to.
> I tend to favor (4) (or 3 with possible future work to achieve 4), but I am not
> a locking maintainer, so really they have to voice what to do.
Right. However, thanks for your opinion.
> I do see value in DEPT (even if the folio lock might be handled differently).
Thanks!
Byungchul
>
> --
> Cheers,
>
> David
Arm CCA includes "Memory Encryption Contexts" (MEC) which allows the
private and shared data accessible to a guest to have different memory
encryption keys. Consequently when converting memory to shared, the
memory encryption key used to access the physical page will change.
Both the GICv3 ITS driver and the system_cc_shared dma-buf heap
currently allocate memory with __GFP_ZERO and then decrypt it. With MEC
the zeroing is done with the wrong encryption key and the data visible
after decryption may be ciphertext. The RMM is required to scrub the
data, but may perform this scrub with a different encryption key to the
eventual key that will be used for shared access.
Fix these two sites by avoiding the __GFP_ZERO during the allocation and
performing a clear_pages() call after the decryption.
Steven Price (2):
irqchip/gic-v3-its: Zero shared pages after conversion
dma-buf: heaps: Zero system shared heap pages after conversion
drivers/dma-buf/heaps/system_heap.c | 14 +++++++++++---
drivers/irqchip/irq-gic-v3-its.c | 7 ++++++-
2 files changed, 17 insertions(+), 4 deletions(-)
--
2.43.0
DMA-buf lets an exporter pin, move or revoke the backing storage under
an importer, and which of the three applies is decided by the optional
callbacks each side implements and by whether dma_buf_pin() succeeds.
Nothing in Documentation/ describes that, and the single reference to
the mechanism still names move_notify(), removed in v7.1.
Thanks
Signed-off-by: Leon Romanovsky <leonro(a)nvidia.com>
---
Leon Romanovsky (2):
PCI/P2PDMA: Update DMABUF lifecycle docs after move_notify() rename
dma-buf: Document how exporters and importers agree on mapping lifetime
Documentation/driver-api/dma-buf.rst | 6 +++
Documentation/driver-api/pci/p2pdma.rst | 6 ++-
drivers/dma-buf/dma-buf.c | 85 ++++++++++++++++++++++++++++++++-
3 files changed, 94 insertions(+), 3 deletions(-)
---
base-commit: 8049741ac93acd3a590dac070e12571fddf0e294
change-id: 20260820-document-dma-buf-3f8b41e32f57
Best regards,
--
Leon Romanovsky <leonro(a)nvidia.com>
On 8/13/26 09:46, Taimuraz Kaitmazov wrote:
> amdxdna_gem_obj_vmap() takes whatever dma_buf_vmap() returns and only
> rejects a NULL vaddr. iosys_map is discriminated by is_iomem, so an
> exporter answering with an I/O mapping leaves a void __iomem pointer in
> abo->mem.kva, which amdxdna_cmd_set_error() memsets and memcpys through.
>
> amdxdna_drm_va_tbl takes a dmabuf_fd, so such a BO can be any exporter's
> buffer. amdgpu cannot reach this: its .pin forces GTT for a non peer to
> peer attachment like ours. An exporter on drm_gem_prime_dmabuf_ops has
> no .pin, and drm_gem_ttm_vmap() answers iomem for a VRAM resident
> object, so an NPU paired with nouveau or radeon does.
>
> Refuse the mapping. vmw_gem_vmap() does the same; unlike that one this
> path is reachable from an unprivileged ioctl, so it does not warn.
>
> Signed-off-by: Taimuraz Kaitmazov <taimuraz(a)kaitmazov.com>
> ---
> drivers/accel/amdxdna/amdxdna_gem.c | 10 ++++++++--
> 1 file changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/accel/amdxdna/amdxdna_gem.c b/drivers/accel/amdxdna/amdxdna_gem.c
> index 1f190b319bb..b66ec9e4828 100644
> --- a/drivers/accel/amdxdna/amdxdna_gem.c
> +++ b/drivers/accel/amdxdna/amdxdna_gem.c
> @@ -683,10 +683,16 @@ static int amdxdna_gem_obj_vmap(struct drm_gem_object *obj, struct iosys_map *ma
>
> dma_resv_assert_held(obj->resv);
>
> - if (is_import_bo(abo))
> + if (is_import_bo(abo)) {
> ret = dma_buf_vmap(abo->dma_buf, map);
> - else
> + /* Callers use mem.kva as an ordinary kernel address. */
> + if (!ret && map->is_iomem) {
> + dma_buf_vunmap(abo->dma_buf, map);
> + return -EOPNOTSUPP;
> + }
Thanks for the fix. The 'is_iomem' check should be moved to
amdxdna_gem_vmap() to cover all the cases.
Lizhi
> + } else {
> ret = drm_gem_shmem_object_vmap(obj, map);
> + }
> if (ret)
> return ret;
> if (!map->vaddr)
I've gone ahead, added one more rb and pushed the result to drm-misc-fixes.
Thanks for the help,
Christian.
On 8/17/26 07:04, Baineng Shou wrote:
> Several drivers call dma_buf_fd() — which internally calls fd_install()
> — before copy_to_user() returns the fd number to userspace. If
> copy_to_user() fails, the fd is already published in the caller's fd
> table but the ioctl returns an error, so userspace never learns the fd
> number. Worse, the window between fd_install() and copy_to_user()
> allows other threads to observe and manipulate the fd (dup, close,
> SCM_RIGHTS), making any "close it on the failure path" fix unsafe.
>
> The fix is to split the allocation into three steps: reserve an fd with
> get_unused_fd_flags() (not yet visible to other threads), do
> copy_to_user(), and only then publish the fd with fd_install() via the
> new dma_buf_fd_install() helper. On copy_to_user() failure,
> put_unused_fd() + dma_buf_put() cleanly unwind with no user-visible
> side effects.
>
> Patch 1 introduces dma_buf_fd_install() in dma-buf.c (wrapping
> fd_install() together with the DMA_BUF_TRACE call to preserve export
> tracing) and applies the fix to dma-heap.
>
> Patch 2 applies the same fix to fastrpc, which even had a comment
> acknowledging the problem could not be fixed before.
>
> Patch 3 replaces the bare fd_install() in drm_gem_prime_handle_to_fd()
> with dma_buf_fd_install() to restore tracepoint coverage for DRM PRIME
> exports (suggested by Christian König).
>
> Patch 4 adds a selftest to tools/testing/selftests/dmabuf-heaps/ that
> reproduces the fd-leak scenario (mprotect flip before the ioctl) and
> verifies the fd count is unchanged after a failed ioctl (suggested by
> Sumit Semwal).
>
> v1: https://lore.kernel.org/dri-devel/20260703080922.1838362-1-shoubaineng@gmai…
> v2: https://lore.kernel.org/dri-devel/20260710105740.3080070-1-shoubaineng@gmai…
> v3: https://lore.kernel.org/dri-devel/20260714114654.3885457-1-shoubaineng@gmai…
> v5: https://lore.kernel.org/dri-devel/20260730062645.233148-1-shoubaineng@gmail…
> v6: https://lore.kernel.org/dri-devel/20260807101140.1357218-1-shoubaineng@gmai…
>
> Changes in v7:
> - Add Reviewed-by: T.J. Mercier to patch 4 (selftest).
> - Add Acked-by: Sumit Semwal to the whole series.
>
> Changes in v6:
> - Rework the selftest (patch 4) per review: extract a count_open_fds()
> helper, fix the copy_from_user() comment, fail (not skip) when the
> ioctl does not return -1, drop the bogus mprotect-race mention, and
> reword the result message.
>
> Changes in v5:
> - Add selftest (patch 4) reproducing the fd-leak scenario (Sumit Semwal)
>
> Changes in v4:
> - Add patch 3: drm/prime: use dma_buf_fd_install() (Christian König)
> - Add Acked-by: Christian König to patches 1 and 2
>
> Changes in v3:
> - Split into two patches (dma-heap + fastrpc separately)
> - Add dma_buf_fd_install() to preserve trace_dma_buf_fd tracepoint
> - Add fastrpc fix using the new helper (T.J. Mercier)
>
> Baineng Shou (4):
> dma-buf: dma-heap: don't publish fd before copy_to_user() succeeds
> misc: fastrpc: don't publish fd before copy_to_user() succeeds
> drm/prime: use dma_buf_fd_install() to preserve export tracing
> selftests: dmabuf-heaps: add fd-leak-on-EFAULT regression test
>
> drivers/dma-buf/dma-buf.c | 20 ++++
> drivers/dma-buf/dma-heap.c | 80 ++++++-------
> drivers/gpu/drm/drm_prime.c | 2 +-
> drivers/misc/fastrpc.c | 16 +--
> include/linux/dma-buf.h | 1 +
> .../selftests/dmabuf-heaps/dmabuf-heap.c | 113 +++++++++++++++++-
> 6 files changed, 180 insertions(+), 52 deletions(-)
>
Hi,
On 8/23/26 08:02, Junrui Luo wrote:
> Hi Christian, Alex,
>
> Sorry for the ping. No need to look at the patch itself.
>
> I would just be grateful for a quick word on whether the issue it describes
> is a real one. If not, I will drop it; if it is, should I send a v2?
as far as I can see it is completely nonsense what you try to do here.
The fence_drv references an amdgpu_userq object holds are the ones which the queue potentially waits on.
When the queue is freed up those references must be dropped, but that shouldn't affect fence_drv->fences in any way possible.
What exactly is the leak you are seeing?
Regards,
Christian.
>
> Thanks for your time,
> Junrui Luo