dma-debug: Make leak-like behaviour apparent

Now that we can dynamically allocate DMA debug entries to cope with
drivers maintaining excessively large numbers of live mappings, a driver
which *does* actually have a bug leaking mappings (and is not unloaded)
will no longer trigger the "DMA-API: debugging out of memory - disabling"
message until it gets to actual kernel OOM conditions, which means it
could go unnoticed for a while. To that end, let's inform the user each
time the pool has grown to a multiple of its initial size, which should
make it apparent that they either have a leak or might want to increase
the preallocation size.

Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Tested-by: Qian Cai <cai@lca.pw>
Signed-off-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
Robin Murphy 2018-12-10 14:00:30 +00:00 committed by Christoph Hellwig
parent 2b9d9ac02b
commit ceb51173b2
2 changed files with 18 additions and 1 deletions

View File

@ -747,7 +747,11 @@ driver afterwards. This filter can be disabled or changed later using debugfs.
When the code disables itself at runtime this is most likely because it ran When the code disables itself at runtime this is most likely because it ran
out of dma_debug_entries and was unable to allocate more on-demand. 65536 out of dma_debug_entries and was unable to allocate more on-demand. 65536
entries are preallocated at boot - if this is too low for you boot with entries are preallocated at boot - if this is too low for you boot with
'dma_debug_entries=<your_desired_number>' to overwrite the default. 'dma_debug_entries=<your_desired_number>' to overwrite the default. The
code will print to the kernel log each time it has dynamically allocated
as many entries as were initially preallocated. This is to indicate that a
larger preallocation size may be appropriate, or if it happens continually
that a driver may be leaking mappings.
:: ::

View File

@ -691,6 +691,18 @@ static struct dma_debug_entry *__dma_entry_alloc(void)
return entry; return entry;
} }
void __dma_entry_alloc_check_leak(void)
{
u32 tmp = nr_total_entries % nr_prealloc_entries;
/* Shout each time we tick over some multiple of the initial pool */
if (tmp < DMA_DEBUG_DYNAMIC_ENTRIES) {
pr_info("dma_debug_entry pool grown to %u (%u00%%)\n",
nr_total_entries,
(nr_total_entries / nr_prealloc_entries));
}
}
/* struct dma_entry allocator /* struct dma_entry allocator
* *
* The next two functions implement the allocator for * The next two functions implement the allocator for
@ -710,6 +722,7 @@ static struct dma_debug_entry *dma_entry_alloc(void)
pr_err("debugging out of memory - disabling\n"); pr_err("debugging out of memory - disabling\n");
return NULL; return NULL;
} }
__dma_entry_alloc_check_leak();
} }
entry = __dma_entry_alloc(); entry = __dma_entry_alloc();