Linux kernel 磁盘IO上swiotlb_unmap_sg_attrs()中的空指针取消引用

Linux kernel 磁盘IO上swiotlb_unmap_sg_attrs()中的空指针取消引用,linux-kernel,linux-device-driver,device-driver,kernel-module,pci-e,Linux Kernel,Linux Device Driver,Device Driver,Kernel Module,Pci E,在使用PCIe块设备驱动程序读取或写入文件时,我遇到了一个我真的不理解的错误。我似乎遇到了一个问题,它似乎对sg指针进行了空解引用,但我不知道这是从哪里来的,因为我自己使用的唯一散点列表被分配为设备信息结构的一部分,并与驱动程序一样持续存在 这个问题有一个解决办法。在确切的细节上它往往会有一些变化,但在swiotlb_unmap_sq_attrs()中它总是崩溃 我想我可能有一个锁定问题,因为我不知道如何处理IO函数周围的锁定。当调用请求函数时,锁已经被保持,我在调用IO函数之前释放它,因为它们

在使用PCIe块设备驱动程序读取或写入文件时,我遇到了一个我真的不理解的错误。我似乎遇到了一个问题,它似乎对
sg
指针进行了空解引用,但我不知道这是从哪里来的,因为我自己使用的唯一
散点列表
被分配为设备信息结构的一部分,并与驱动程序一样持续存在

这个问题有一个解决办法。在确切的细节上它往往会有一些变化,但在
swiotlb_unmap_sq_attrs()
中它总是崩溃

我想我可能有一个锁定问题,因为我不知道如何处理IO函数周围的锁定。当调用
请求
函数时,锁已经被保持,我在调用IO函数之前释放它,因为它们需要一个(MSI)IRQ来完成。IRQ处理程序更新IO函数正在等待的“状态”值。当IO函数返回时,我将恢复锁并返回请求队列处理

崩溃发生在
blk\u fetch\u request()
的以下过程中:

if(!\u blk\u end\u请求(请求、恢复、字节)){
printk(内核错误“%s next request\n”,驱动程序名称);
req=blk_取数_请求(q);
}否则{
printk(内核错误“%s同一请求”,驱动程序名称);
}

其中,
字节
由请求处理程序更新为IO的总长度(每个分散-聚集段的总长度)。

结果表明,这是由于请求函数的重新进入。因为我在中间解锁以允许IRQs进入,可以再次调用<代码>请求< /C>函数,将锁(而原始请求处理程序在IO上等待),然后错误的处理程序得到IRQ,所有的东西都以失败的IO。 我解决这个问题的方法是在请求函数的开始处设置一个“busy”标志,在结束时清除它,如果设置了,则在函数的开始处立即返回:

static void mydev\u submit\u req(结构请求队列*q){
struct mydevice*dev=q->queuedata;
//我们已经在处理一个请求
//因此,可重入呼叫可能需要一段时间
//他们会回来的
如果(开发->有请求)
返回;
//我们现在拥有IO,新请求需要等待
//调用此函数时,将保持队列锁
//所以不需要一套原子装置
dev->has_request=1;
//此处为访问请求队列,同时保持队列锁
旋转解锁irq(q->队列锁定);
//在启用IRQ的情况下在此执行IO
//您无法在此访问队列或请求,请确保
//在释放锁之前,您已经获得了所需的信息
自旋锁(q->队列锁);
//您可以根据需要在这里结束请求,并保持锁定
//允许在返回后处理新请求
dev->has_request=0;
//当函数返回时,锁定被保持
}
但是,我仍然不确定为什么我总是从
swiotlb_unmap_sq_attrs()
获取堆栈跟踪