续上篇。
IO完成的中断处理事件
irq 的事件处理函数是 nvme_handle_event。 这部分其实是可以优化的,通过 polling,去掉事件通知。 完成的处理逻辑是:
\1. 遍历所有的 Queue,包括 admin queue 和 IO queue;
\2. 检查 queue 的每一个 completion queue 的 entry,直到遇到没有完成的退出;
\3. cq 的 head ++;
\4. 根据 entry 的 cid 从 reqs 中取得 req;
\5. 调用 req 的 done 回调函数;
\6. q->inflight--;
\7. 通知硬件,可以回收 completion queue 的 entry 了。 *q->cq.doorbell = cpu_to_le32(q->cq.head);
297static bool nvme_process_completion(BDRVNVMeState *s, NVMeQueuePair *q) 298{ ... 305 if (q->busy || s->plugged) { 306 trace_nvme_process_completion_queue_busy(s, q->index); 307 return false; 308 } 309 q->busy = true; 310 assert(q->inflight >= 0); 311 while (q->inflight) { 312 int16_t cid; 313 c = (NvmeCqe *)&q->cq.queue[q->cq.head *