dma-debug: fix locking bug in check_unmap()
In check_unmap() it is possible to get into a dead-locked state if dma_mapping_error is called. The problem is that the bucket is locked in check_unmap, and locked again by debug_dma_mapping_error which is called by dma_mapping_error. To resolve that we must release the lock on the bucket before making the call to dma_mapping_error. [akpm@linux-foundation.org: restore 80-col trickery to be consistent with the rest of the file] Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com> Cc: Joerg Roedel <joro@8bytes.org> Reviewed-by: Shuah Khan <shuah.khan@hp.com> Tested-by: Shuah Khan <shuah.khan@hp.com> Cc: Jakub Kicinski <kubakici@wp.pl> Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Родитель
0ef1594c01
Коммит
8d640a51ec
|
@ -862,17 +862,21 @@ static void check_unmap(struct dma_debug_entry *ref)
|
|||
entry = bucket_find_exact(bucket, ref);
|
||||
|
||||
if (!entry) {
|
||||
/* must drop lock before calling dma_mapping_error */
|
||||
put_hash_bucket(bucket, &flags);
|
||||
|
||||
if (dma_mapping_error(ref->dev, ref->dev_addr)) {
|
||||
err_printk(ref->dev, NULL,
|
||||
"DMA-API: device driver tries "
|
||||
"to free an invalid DMA memory address\n");
|
||||
return;
|
||||
"DMA-API: device driver tries to free an "
|
||||
"invalid DMA memory address\n");
|
||||
} else {
|
||||
err_printk(ref->dev, NULL,
|
||||
"DMA-API: device driver tries to free DMA "
|
||||
"memory it has not allocated [device "
|
||||
"address=0x%016llx] [size=%llu bytes]\n",
|
||||
ref->dev_addr, ref->size);
|
||||
}
|
||||
err_printk(ref->dev, NULL, "DMA-API: device driver tries "
|
||||
"to free DMA memory it has not allocated "
|
||||
"[device address=0x%016llx] [size=%llu bytes]\n",
|
||||
ref->dev_addr, ref->size);
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ref->size != entry->size) {
|
||||
|
@ -936,7 +940,6 @@ static void check_unmap(struct dma_debug_entry *ref)
|
|||
hash_bucket_del(entry);
|
||||
dma_entry_free(entry);
|
||||
|
||||
out:
|
||||
put_hash_bucket(bucket, &flags);
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче