본문 바로가기

리눅스 커널/블록 멀티 큐

blk_mq_init_queue

블록 레이어에서 사용할 request_queue 를 할당하기 위해 호출되는 함수이다.

 

관리자 큐를 위해 nvme_alloc_admin_tagset() 에서 호출되는 것과

io 큐를 위해 nvme_alloc_ns() 에서 호출된다.

 

아래 흐름은 io 큐를 위해 호출된 상황이므로 set 은 dev.tagset 이다. 관리자 용 tagset이 아닌 것이다.

blk_mq_init_queue(struct blk_mq_tag_set * set) from nvme_alloc_ns
	//
    ->uninit_q = blk_alloc_queue_node(GFP_KERNEL, set->numa_node);
    ->blk_mq_init_allocated_queue(set, uninit_q);
    	//
        ->q->mq_ops = set->ops;
        ->q->queue_ctx = alloc_percpu(struct blk_mq_ctx);
        ->q->queue_hw_ctx = kzalloc_node(nr_cpu_idx * sizeof(*(q->queue_hw_ctx)), ...);
        ->q->mq_map = set->mq_map;
        ->blk_mq_realloc_hw_ctxs(set, q)
        	//
            ->for (0 to set->nr_hw_queues)
            	//
                ->hctxs[i] = kzalloc_node(...);
                ->blk_mq_init_hctx(q, set, hctxs[i], i)
            		//
                    ->hctx->q = q;
                    ->hctx->tags = set->tags[hctx_idx];
                    ->hctx->ctxs = kmalloc_node(nr_cpu_ids * sizeof(void *), ...);
                    ->sbitmap_init_node(...);
                    ->hctx->nr_ctx = 0;
                    ->set->ops->init_hctx(hctx, set->driver_data, hctx_idx);
                    ->hctx->fq = blk_alloc_flush_queue(...);
        ->q->nr_queues = nr_cpu_ids;
        ->blk_queue_make_request(q, blk_mq_make_request);
        ->q->nr_requests = set->queue_depth;
        ->blk_queue_softirq_done(q, set->ops->complete);
        ->blk_mq_init_cpu_queues(q, set->nr_hw_queues);
        	//
            ->for_each_possible_cpu(i)
            	//
                ->__ctx = per_cpu_ptr(q->queue_ctx, i);
                ->__ctx->cpu = i;
                ->__ctx->queue = q;
                ->hctx = blk_mq_map_queue(q, i);
        ->blk_mq_add_queue_tag_set(set, q);
        	//
            ->q->tagset = set;
        ->blk_mq_map_swqueue(q);
        	//
            ->for_each_present_cpu(i)
            	//
                ->hctx_idx = q->mq_map[i];
                ->ctx = per_cpu_ptr(q->queue_ctx, i);
                ->hctx = blk_mq_map_queue(q, i);
                ->cpumask_set_cpu(i, hctx->cpumask);
                ->ctx->index_hw = hctx->nr_ctx;
                ->hctx->ctxs[hctx->nr_ctx++] = ctx;

1. request_queue 를 위한 메모리 할당.

2. sw 큐를 각 코어에 맞게 할당. percpu

3. hw 큐 포인터 배열을 위한 메모리 할당.

4. hw 큐를 위한 메모리 할당 및 초기화.

5. request_queue 의 make_request_fn 멤버를 blk_mq_make_request로 등록

6. sw 큐 초기화

7. 매핑 정보에 맞게 sw큐를 hw큐에 실제로 매핑함.



'리눅스 커널 > 블록 멀티 큐' 카테고리의 다른 글

NVMe device driver code tuning & comments - 1  (0) 2021.10.26
urgent queue 를 위한 tag 예약  (0) 2021.10.26
blk_mq_alloc_tag_set 흐름  (0) 2021.10.26
nvme command 관련 추가 내용  (0) 2021.10.26
nvme command  (0) 2021.10.26