dma-mapping: don't trace the DMA address when the allocation fails
Subsystems (2)
PATCH v2 1/1 dma-mapping: don't trace the DMA address when the allocation fails
dma_alloc_attrs() passes *dma_handle to trace_dma_alloc() without checking whether the allocation succeeded. No backend writes it on
failure: dma_direct_alloc(), iommu_dma_alloc() and the dma_map_ops instances assign it only on the path that returns a buffer. Callers usually pass an uninitialized automatic variable, so a failed allocation records whatever the stack held, next to the virt_addr=(null) that marks the record as an error:
dma_alloc: dmatrace dir=BIDIRECTIONAL dma_addr=deadbeefdeadbeef size=1099511627776 virt_addr=0000000000000000
The device coherent pool path reaches the same call: a non-zero return from dma_alloc_from_dev_coherent() means the request was handled, not that it succeeded, so cpu_addr is NULL and dma_handle is untouched once the pool runs out.
For an allocation event a NULL virt_addr already means the request failed, so the address field carries nothing. Report 0 for it in the event class rather than at each call site, which covers dma_alloc_pages() and dma_alloc_sgt_err() as well.
---
v2:
- report 0 in the event class instead of splitting the two call sites,
as suggested by Marek. kernel/dma/mapping.c is untouched now, so debug_dma_alloc_coherent() keeps being called for a failed allocation
and decides for itself what to do with it.
- tested on x86_64 rather than compile-tested only.
v1: https://lore.kernel.org/linux-iommu/[email protected]/
Tested with a module that puts a known value in the caller's handle and then asks for 1 TiB from a 32-bit capable device, with the dma_alloc event enabled. Before, the record carries the caller's stale value; after, it carries 0:
-dma_addr=deadbeefdeadbeef size=1099511627776 virt_addr=0000000000000000 +dma_addr=0 size=1099511627776 virt_addr=0000000000000000
A PAGE_SIZE request from the same device, as a control, reports its real address on both kernels, matching the handle the caller got back.
This changes what the record contains, not what the caller does:*dma_handle is still read to build the tracepoint arguments, since those are evaluated before the static branch.
include/trace/events/dma.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
include/trace/events/dma.h +1 -1
@@ -134,7 +134,7 @@ DECLARE_EVENT_CLASS(dma_alloc_class,TP_fast_assign ( __assign_str(device); __entry->virt_addr = virt_addr; - __entry->dma_addr = dma_addr; + __entry->dma_addr = virt_addr ? dma_addr :0 ; __entry->size = size; __entry->flags = flags; __entry->dir = dir;
base-commit: cee9395acd8043be0644b25c34bfa86623f2b935
Signature · 1 line
2.53.0
Quoted 66 lines · Donggeun Yoo
dma_alloc_attrs()passes*dma_handletotrace_dma_alloc()without checking whether the allocation succeeded. No backend writes it on
failure:dma_direct_alloc(),iommu_dma_alloc()and thedma_map_opsinstances assign it only on the path that returns a buffer. Callers usually pass an uninitialized automatic variable, so a failed allocation records whatever the stack held, next to the virt_addr=(null) that marks the record as an error:
dma_alloc: dmatrace dir=BIDIRECTIONAL dma_addr=deadbeefdeadbeef size=1099511627776 virt_addr=0000000000000000The device coherent pool path reaches the same call: a non-zero return from
dma_alloc_from_dev_coherent()means the request was handled, not that it succeeded, socpu_addris NULL anddma_handleis untouched once the pool runs out.For an allocation event a NULL
virt_addralready means the request failed, so the address field carries nothing. Report 0 for it in the event class rather than at each call site, which coversdma_alloc_pages()anddma_alloc_sgt_err()as well.Fixes 038eb433dc14 ("dma-mapping: add tracing for dma-mapping API calls")Fixes 68b6dbf1f441 ("dma-mapping: trace more error paths")Suggested-by Marek Szyprowski <[email protected]>Signed-off-by Donggeun Yoo <[email protected]>---
v2:
- report 0 in the event class instead of splitting the two call sites,
as suggested by Marek.kernel/dma/mapping.cis untouched now, sodebug_dma_alloc_coherent()keeps being called for a failed allocation
and decides for itself what to do with it.
- tested onx86_64rather than compile-tested only.
v1: https://lore.kernel.org/linux-iommu/[email protected]/Tested with a module that puts a known value in the caller's handle and then asks for 1 TiB from a 32-bit capable device, with the
dma_allocevent enabled. Before, the record carries the caller's stale value; after, it carries 0:-dma_addr=deadbeefdeadbeef size=1099511627776 virt_addr=0000000000000000 +dma_addr=0 size=1099511627776 virt_addr=0000000000000000
A
PAGE_SIZErequest from the same device, as a control, reports its real address on both kernels, matching the handle the caller got back.This changes what the record contains, not what the caller does:
*dma_handleis still read to build the tracepoint arguments, since those are evaluated before the static branch.include/trace/events/dma.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)include/trace/events/dma.h +1
-1@@ -134,7 +134,7 @@ DECLARE_EVENT_CLASS(dma_alloc_class,TP_fast_assign ( __assign_str(device); __entry->virt_addr = virt_addr; - __entry->dma_addr = dma_addr; + __entry->dma_addr = virt_addr ? dma_addr :0 ; __entry->size = size; __entry->flags = flags; __entry->dir = dir;
Quoted 1 line
base-commit:
cee9395acd8043be0644b25c34bfa86623f2b935
Quoted 21 lines · Donggeun Yoo
dma_alloc_attrs()passes*dma_handletotrace_dma_alloc()without checking whether the allocation succeeded. No backend writes it on
failure:dma_direct_alloc(),iommu_dma_alloc()and thedma_map_opsinstances assign it only on the path that returns a buffer. Callers usually pass an uninitialized automatic variable, so a failed allocation records whatever the stack held, next to the virt_addr=(null) that marks the record as an error:
dma_alloc: dmatrace dir=BIDIRECTIONAL dma_addr=deadbeefdeadbeef size=1099511627776 virt_addr=0000000000000000The device coherent pool path reaches the same call: a non-zero return from
dma_alloc_from_dev_coherent()means the request was handled, not that it succeeded, socpu_addris NULL anddma_handleis untouched once the pool runs out.For an allocation event a NULL
virt_addralready means the request failed, so the address field carries nothing. Report 0 for it in the event class rather than at each call site, which coversdma_alloc_pages()anddma_alloc_sgt_err()as well.
Quoted 4 lines
Fixes 038eb433dc14 ("dma-mapping: add tracing for dma-mapping API calls")Fixes 68b6dbf1f441 ("dma-mapping: trace more error paths")Suggested-by Marek Szyprowski <[email protected]>Signed-off-by Donggeun Yoo <[email protected]>
Applied to dma-mapping-fixes, thanks!
Quoted 41 lines
---
v2:
- report 0 in the event class instead of splitting the two call sites,
as suggested by Marek.kernel/dma/mapping.cis untouched now, sodebug_dma_alloc_coherent()keeps being called for a failed allocation
and decides for itself what to do with it.
- tested onx86_64rather than compile-tested only.
v1: https://lore.kernel.org/linux-iommu/[email protected]/Tested with a module that puts a known value in the caller's handle and then asks for 1 TiB from a 32-bit capable device, with the
dma_allocevent enabled. Before, the record carries the caller's stale value; after, it carries 0:-dma_addr=deadbeefdeadbeef size=1099511627776 virt_addr=0000000000000000 +dma_addr=0 size=1099511627776 virt_addr=0000000000000000
A
PAGE_SIZErequest from the same device, as a control, reports its real address on both kernels, matching the handle the caller got back.This changes what the record contains, not what the caller does:
*dma_handleis still read to build the tracepoint arguments, since those are evaluated before the static branch.include/trace/events/dma.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)include/trace/events/dma.h +1
-1@@ -134,7 +134,7 @@ DECLARE_EVENT_CLASS(dma_alloc_class,TP_fast_assign ( __assign_str(device); __entry->virt_addr = virt_addr; - __entry->dma_addr = dma_addr; + __entry->dma_addr = virt_addr ? dma_addr :0 ; __entry->size = size; __entry->flags = flags; __entry->dir = dir;
Quoted 1 line
base-commit:
cee9395acd8043be0644b25c34bfa86623f2b935
Best regards
Signature · 2 lines
Marek Szyprowski, PhD Samsung R&D Institute Poland