struct nvme_queue {
...
//int ssize;
int szs[2]; //READ: 0, WRITE: 1
int ops[1024]; //sq의 depth에 맞게 설정. 포인터로 선언해서 동적할당하기를 권장
};
static blk_status_t nvme_queue_rq(struct blk_mq_hw_ctx *hctx,
const struct blk_mq_queue_data *bd)
{
...
if (nvmeq->qid > 0) //io를 위한 sq에 대해서,
{
nvmeq->ops[nvmeq->sq_tail] = rq_data_dir(req);
nvmeq->szs[rq_data_dir(req)] += 1;
printk("log, qid: %d, read: %d, write: %d, total: %d\n",
nvmeq->qid, nvmeq->szs[0], nvmeq->szs[1], nvmeq->szs[0] + nvmeq->szs[1]);
}
__nvme_submit_cmd(nvmeq, &cmnd);
nvme_process_cq(nvmeq);
spin_unlock_irq(&nvmeq->q_lock);
return BLK_STS_OK;
out_cleanup_iod:
nvme_free_iod(dev, req);
out_free_cmd:
nvme_cleanup_cmd(req);
return ret;
}
static inline bool nvme_read_cqe(struct nvme_queue *nvmeq,
struct nvme_completion *cqe)
{
if (nvme_cqe_valid(nvmeq, nvmeq->cq_head, nvmeq->cq_phase)) {
*cqe = nvmeq->cqes[nvmeq->cq_head];
if (nvmeq->qid > 0) //io를 위한 sq에 대해서
nvmeq->szs[nvmeq->ops[nvmeq->cq_head]] -= 1; //dec
if (++nvmeq->cq_head == nvmeq->q_depth) {
nvmeq->cq_head = 0;
nvmeq->cq_phase = !nvmeq->cq_phase;
}
return true;
}
return false;
}
sq가 원형큐라는 점을 이용했다.
현재 tail위치에 연산 정보를 기록한다. READ == 0, WRITE == 1이다.
그리고 이 값을 인덱스로 하여 read와 write 개수를 증가시킨다.
io가 끝나면 head의 위치부터 확인하게 된다.
그래서 이 head값을 토대로 큐잉시 저장해두었던 연산 정보를 읽어와서 해당 인덱스의 위치한 값을 하나 감소시킨다.
'리눅스 커널 > 블록 멀티 큐' 카테고리의 다른 글
Limited sq entry implementation (0) | 2021.10.27 |
---|---|
NVMe device driver code tuning & comments - 5 (0) | 2021.10.26 |
NVMe device driver code tuning & comments - 4 (0) | 2021.10.26 |
NVMe device driver code tuning & comments - 3 (0) | 2021.10.26 |
NVMe device driver code tuning & comments - 2 (0) | 2021.10.26 |