작성한 커널 코드를 정리하던 중에 디버깅용으로 작성한 코드 중 SQ의 쌓인 entry 개수를 측정하는 함수가 있었다.
여기서는 이와 관련된 것을 정리하겠다.
SQ의 entry가 증가하는 경우는
__nvme_submit_cmd()와 __nvme_submit_cmd_extra()를 참조하면 된다.
해당 함수에서 size를 1 증가시키는 코드의 주석을 해제하면 된다.
static void __nvme_submit_cmd(struct nvme_queue *nvmeq,
struct nvme_command *cmd)
{
u16 tail = nvmeq->sq_tail;
if (nvmeq->sq_cmds_io)
memcpy_toio(&nvmeq->sq_cmds_io[tail], cmd, sizeof(*cmd));
else
memcpy(&nvmeq->sq_cmds[tail], cmd, sizeof(*cmd));
if (++tail == nvmeq->q_depth)
tail = 0;
if (nvme_dbbuf_update_and_check_event(tail, nvmeq->dbbuf_sq_db,
nvmeq->dbbuf_sq_ei))
writel(tail, nvmeq->q_db);
//if (nvmeq->qid)
//nvmeq->size += 1;
nvmeq->sq_tail = tail;
관리자 큐를 제외한 IO를 위한 SQ일 때에 만 동작한다.
더 중요한 건 entry를 감소시킬 때이다.
static void nvme_process_cq(struct nvme_queue *nvmeq)
{
struct nvme_completion cqe;
int consumed = 0;
while (nvme_read_cqe(nvmeq, &cqe)) {
nvme_handle_cqe(nvmeq, &cqe);
consumed++;
//if (nvmeq->cqe_seen && cqe.sq_id)
//nvme_queue_size_update(nvmeq, cqe.sq_id);
}
if (consumed)
nvme_ring_cq_doorbell(nvmeq);
}
위 함수는 io가 끝났을 때 인터럽트 문맥에서 호출되는 함수이다.
여기서 주석처리된 부분에 대한 설명을 하자면,
io가 처리되었고 관리자 큐가 아닌 경우면 sq의 entry개수를 줄이는 함수를 호출한다.
static inline void nvme_queue_size_update(struct nvme_queue * nvmeq, u16 sq_id)
{
int max = nvmeq->dev->online_queues - 1;
sq_id -= 1;
if (sq_id < max)
nvmeq->size -= 1;
else
nvmeq->extra_list[(sq_id / max) - 1]->size -= 1;
/*if (size)
{
--(*size);
printk("extra, %s, qid(%d), size: %d\n", current->comm, sq_id, *size);
}*/
}
max는 원래 커널이 생성하는 IO를 위한 SQ개수를 의미한다.
코어가 6개인 경우 그 개수는 6이나 online_queues는 관리자 큐 개수로 인해 7이 된다.
그래서 1을 빼는 것이다.
그리고 qid를 적절히 보정 한 후 해당 SQ에 접근해서 size를 1감소시키는데,
[01] [02] [03] [04] [05] [06]
[07] [08] [09] [10] [11] [12]
[13] [14] [15] [16] [17] [18]
첫번째 행에 있는 것들은 원래 커널이 만들어내는 큐들의 id이다.
그리고 각 열은 1번 코어가 갖고 있는 SQ의 id들을 나타낸다.
그리고 __nvme_submit_cmd_extra()에 의해 증가된 size를 줄이기 위해서는
extra_list에 각 sq_id에 적합한 인덱스를 통해 접근해야 된다.
그런데 (12 / 6) - 1을 해주면 그 인덱스가 1이 나온다. 잘못된 sq에 접근하고 있는 것 이다.
그래서 이러한 점을 막기 위해 값을 보정하여 계산한다.
아래와 같은 형식으로 만드는 것이다.
[00] [01] [02] [03] [04] [05]
[06] [07] [08] [09] [10] [11]
[12] [13] [14] [15] [16] [17]
'리눅스 커널 > 블록 멀티 큐' 카테고리의 다른 글
nvme 디바이스 레이어에서 read/write 연산 횟수 계산 방법 (0) | 2021.10.27 |
---|---|
Limited sq entry implementation (0) | 2021.10.27 |
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 |