在系统使用过程中,内核dmesg有nvme: I/O QID timeout,completion polled信息报出。
先看报Warning的代码:
static enum blk_eh_timer_return nvme_timeout(struct request *req, bool reserved)
{
... ...
if (__nvme_poll(nvmeq, req->tag)) {
??????????????? dev_warn(dev->ctrl.device,
???????????????????????? "I/O %d QID %d timeout, completion polled\n",
???????????????????????? req->tag, nvmeq->qid);
??????????????? return BLK_EH_DONE;
}
... ...
}
可以看出Warning是在IO的timeout处理函数报出的,其原因是:系统在下发一个IO后长时间没有收到IO回复,此时会触发一个timeout来处理,但是timeout在处理过程中发现这个IO实际上回来了(也就是处于NVMe的nvmeq中),但是系统一直没有处理这个IO,没有处理的原因是系统漏掉了这个中断。具体步骤如下:
从上面具体步骤分析可以看出,漏中断报这个Waring不会导致IO丢失,但是会导致IO的延迟加大。
通过构建测试环境发现在ARM64下(鲲鹏、飞腾都有测试),在调用set_irq_affinity后会有很小很小的概率miss中断,此外,通过核外的/proc/irq/smp_affinity接口也可以复现(写一个脚本不停地改中断的亲和性,再用dd写盘,就有一定的概率出现),此问题应该是ARM64 gic-v3的硬件缺陷(测试发现社区5.6内核都能复现出来),目前最新的麒麟内核修复了这一问题。