linux - put_page 和 pci unmap_sg 之间的竞争条件

标签 linux linux-kernel linux-device-driver

我正在研究包含 dma 的设备驱动程序。如果我只使用 get_user_pages_fastput_page 一切正常。一旦我添加对 pci_(un)map_sg 的调用,它似乎就变得活泼了。

测试程序完成后,我有时会遇到BUG,但我并不总是会遇到BUG

BUG是这样写的:

[ 7202.183324] BUG: Bad page state in process dma  pfn:f20ea8
[ 7202.183327] page:ffffea003c83aa00 count:0 mapcount:-30705 mapping:          (null) index:0xc0054000d3431e41
[ 7202.183329] page flags: 0x2ffff000008000c(referenced|uptodate|swapbacked)

并且有如下痕迹:

[ 7202.183442] Call Trace:
[ 7202.183447]  [<ffffffff8171e0be>] dump_stack+0x45/0x56
[ 7202.183453]  [<ffffffff8171aa88>] bad_page.part.61+0xcf/0xe8
[ 7202.183459]  [<ffffffff81155ce8>] free_pages_prepare+0x148/0x160
[ 7202.183463]  [<ffffffff81156651>] free_hot_cold_page+0x31/0x150
[ 7202.183467]  [<ffffffff811567b6>] free_hot_cold_page_list+0x46/0xa0
[ 7202.183473]  [<ffffffff8115c210>] release_pages+0x80/0x210
[ 7202.183478]  [<ffffffff8118b725>] free_pages_and_swap_cache+0x95/0xb0
[ 7202.183483]  [<ffffffff81174c5c>] tlb_flush_mmu.part.56+0x4c/0x90
[ 7202.183486]  [<ffffffff811757d5>] tlb_finish_mmu+0x55/0x60
[ 7202.183491]  [<ffffffff81180c0b>] exit_mmap+0xcb/0x170
[ 7202.183497]  [<ffffffff810646cc>] mmput+0x5c/0x120
[ 7202.183502]  [<ffffffff81069b1c>] do_exit+0x26c/0xa50
[ 7202.183506]  [<ffffffff811bef1e>] ? ____fput+0xe/0x10
[ 7202.183511]  [<ffffffff8106a37f>] do_group_exit+0x3f/0xa0
[ 7202.183515]  [<ffffffff8106a3f4>] SyS_exit_group+0x14/0x20
[ 7202.183520]  [<ffffffff8172ec2d>] system_call_fastpath+0x1a/0x1f

是否有任何我必须为任何功能持有的额外锁(没有针对 pci-dma api 的提示,并且我在其他驱动程序中看到 put_page 的地方附近没有锁它)。还有其他地方我可能会出错吗?

我目前将相同的指针传递给 pci_unmap_sg 作为我用于 pci_map_sg 的指针,在查看其他驱动程序并使用实际页数而不是从映射返回的用于取消映射的计数。

我想我缺少一些锁定或同步,如 this post可能会暗示,但是我对 linux 内存子系统的理解很难理解。

另外 [release_pages](http://lxr.free-electrons.com/source/mm/swap.c#L899) 似乎是一个替代方案,但是我看到 spin_unlock_irqrestore (&zone->lru_lock, flags); 在没有事先锁定的 View 路径中,我需要在调用它之前保持锁定吗?

最佳答案

我错误地初始化了分散/聚集列表,我认为调用 sg_set_page 就足够了,但是需要初始调用 sg_init_table

因为我发现很多驱动程序没有这样做,而且 ldd3 没有在任何地方提到 sg_init_table,所以我想如果我把它留在这里可能会有帮助。

关于linux - put_page 和 pci unmap_sg 之间的竞争条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28202313/

相关文章:

java - 使用 JDBC 时更改 DB2 的 session 用户

linux - snmp 服务无法在 Linux 中正确运行我的程序

c - 轮询立即从司机那里退出

memory-management - arm 架构上的 dma_map_single 内部结构

linux - 什么驱动程序取代了 ldusb ? (写一个真正的 Linux 驱动程序教程)

c - 在 Windows、Mac 和 Linux 上使用的 C 库应该放在哪里

C++ 重新分配() : invalid pointer

linux - madvise() 中 MADV_USERFAULT 标志的状态是什么?

c - 如何使用 perf_event_open 以恒定速率采样?

Linux在特定的物理地址分配内存