深入理解nvme hardware queue pair

hardware queue pair是什麼

hardware queue pair是我們理解nvme/spdk的牛鼻子,只有深入理解纔可能把nvme用好。

從nvme控制器寄存器的角度看

顧名思義,就是一些硬件寄存器組成的隊列。

空隊列

深入理解nvme hardware queue pair

滿隊列

深入理解nvme hardware queue pair

  • 問題:
    能否併發入隊、出隊?不行

submission hardware queue entry

每個entry如下表所示:

深入理解nvme hardware queue pair

  • 入隊:

host software 提交命令到tail entry, 通過操作submission hardware queue tail doorbell register;
深入理解nvme hardware queue pair

  • 出隊:
    hardware 依次取head entry 去處理

completion hardware hardware queue entry

每個entry的主要fileds 如下:

深入理解nvme hardware queue pair

  • 入隊
    hardware 處理完上面取到的nvme command之後,把對應的完成的信息放在completion queue head entry;

  • 出隊
    host software 被中斷或主動輪詢到上面有新的entry 添加之後,去completion queue tail 去取最近提交的命令的處理結果。

這個主要是操作completion queue doorbell 寄存器去實現:
深入理解nvme hardware queue pair

queue pair

nvme控制器內部有多個submission hardware queue,也有多個completion hardware queue。 提交、執行 NVME command的時候,需要使用上面兩種hardware queue中的entry,成對使用。

從nvme控制器架構的角度看

hardware queue pair 是抽取"nvme command"的水車。設計到NVME 指令的提交/執行和完成。

概覽

下面是一張經典的圖:
深入理解nvme hardware queue pair

NVME command提交

深入理解nvme hardware queue pair

NVME已完成命令的處理

深入理解nvme hardware queue pair

spdk對hardware queue pair的封裝

IO請求提交函數

  • spdk_nvme_ns_cmd_read
  1. 生產request
    _nvme_ns_cmd_rw(ns, qpair, &payload, ....)

  2. 提交請求
    nvme_qpair_submmit_request()

    2.1 nvme_transport_qpair_submit_request(qpair, request)
    2.1.1 nvme_pcie_qpair_submit_request (qpair, request)
    2.1.1.1 nvme_pcie_qpair_build_contig_request(qpair, req, tr);
    2.1.1.2 nvme_pcie_qpair_submit_tracker(qpair, tr)

nvme_pcie_qpair_submit_tracker(struct spdk_nvme_qpair *qpair, struct nvme_tracker *tr)
{
        struct nvme_request     *req;
        struct nvme_pcie_qpair  *pqpair = nvme_pcie_qpair(qpair);
        struct nvme_pcie_ctrlr  *pctrlr = nvme_pcie_ctrlr(qpair->ctrlr);

        req = tr->req;
        assert(req != NULL);
        req->timed_out = false;
        if (spdk_unlikely(pctrlr->ctrlr.timeout_enabled)) {
                req->submit_tick = spdk_get_ticks();
        } else {
                req->submit_tick = 0;
        }

        pqpair->tr[tr->cid].active = true;

        /* Copy the command from the tracker to the submission queue. */
        nvme_pcie_copy_command(&pqpair->cmd[pqpair->sq_tail], &req->cmd);

        if (spdk_unlikely(++pqpair->sq_tail == pqpair->num_entries)) {
                pqpair->sq_tail = 0;
        }

        if (spdk_unlikely(pqpair->sq_tail == pqpair->sq_head)) {
                SPDK_ERRLOG("sq_tail is passing sq_head!\n");
        }

        spdk_wmb();
        if (spdk_likely(nvme_pcie_qpair_update_mmio_required(qpair,
                        pqpair->sq_tail,
                        pqpair->sq_shadow_tdbl,
                        pqpair->sq_eventidx))) {
                g_thread_mmio_ctrlr = pctrlr;
                spdk_mmio_write_4(pqpair->sq_tdbl, pqpair->sq_tail); // <---
                g_thread_mmio_ctrlr = NULL;
        }
}

通過上面code path可以看到,spdk nvme 需要操作硬件寄存器,並且一路無鎖和原子操作。需要上層保護。

IO完成查詢函數

spdk_nvme_qpair_process_completions

同上類似操作對應的cq_hdbel,無鎖和原子操作,需要上層保護,防止併發修改doorbell 寄存器。

如何用好多個hardware queue pair

需要管理好實際應用中hardware queue pair和線程、處理器核的對應關係,避免多個線程同時訪問某個hardware queue。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章