# 요청 큐: 대기 중인 작업이 장치에서 진행 중인 작업이 될 때

v6.6 / block/blk-mq.c

파일시스템이 만든 bio는 장치가 처리할 request로 묶일 수 있습니다. request_queue는 그 장치의 요청 처리 규칙을 제공하며 blk-mq는 소프트웨어 쪽 요청을 하드웨어 큐로 연결합니다. 여기서는 드라이버가 요청을 시작할 때 부르는 blk_mq_start_request를 통해 태그, 시간 제한, 진행 상태가 왜 필요한지 살펴봅니다.

## blk_mq_start_request

```c

void blk_mq_start_request(struct request *rq)
{
	struct request_queue *q = rq->q;

	trace_block_rq_issue(rq);

	if (test_bit(QUEUE_FLAG_STATS, &q->queue_flags)) {
		rq->io_start_time_ns = ktime_get_ns();
		rq->stats_sectors = blk_rq_sectors(rq);
		rq->rq_flags |= RQF_STATS;
		rq_qos_issue(q, rq);
	}

	WARN_ON_ONCE(blk_mq_rq_state(rq) != MQ_RQ_IDLE);

	blk_add_timer(rq);
	WRITE_ONCE(rq->state, MQ_RQ_IN_FLIGHT);

#ifdef CONFIG_BLK_DEV_INTEGRITY
	if (blk_integrity_rq(rq) && req_op(rq) == REQ_OP_WRITE)
		q->integrity.profile->prepare_fn(rq);
#endif
	if (rq->bio && rq->bio->bi_opf & REQ_POLLED)
	        WRITE_ONCE(rq->bio->bi_cookie, rq->mq_hctx->queue_num);
}

```

### 1245행

```c

void blk_mq_start_request(struct request *rq)

```

시작할 request를 받습니다. 드라이버가 장치 처리를 시작하는 경계에서 호출합니다.

### 1247행

```c

	struct request_queue *q = rq->q;

```

요청이 소속된 request_queue를 지역변수로 꺼내 통계와 서비스 품질 처리를 연결합니다.

### 1249행

```c

	trace_block_rq_issue(rq);

```

요청 발행 추적 이벤트를 남깁니다. 이 기록은 완료 이벤트와 구분됩니다.

### 1251행

```c

	if (test_bit(QUEUE_FLAG_STATS, &q->queue_flags)) {

```

큐의 통계 수집 플래그가 켜졌는지 검사합니다. 이 v6.6 본문에는 통과 명령을 제외하는 추가 조건이 없습니다.

### 1252행

```c

		rq->io_start_time_ns = ktime_get_ns();

```

ktime_get_ns로 단조 증가 시간의 나노초 값을 얻어 요청 시작 시각으로 저장합니다.

### 1253행

```c

		rq->stats_sectors = blk_rq_sectors(rq);

```

통계에 사용할 요청 크기를 섹터 수로 저장합니다.

### 1254행

```c

		rq->rq_flags |= RQF_STATS;

```

이 요청에 통계 자료가 준비됐다는 RQF_STATS 비트를 켭니다.

### 1255행

```c

		rq_qos_issue(q, rq);

```

큐의 서비스 품질 제어 계층에 요청이 발행됐음을 알립니다.

### 1258행

```c

	WARN_ON_ONCE(blk_mq_rq_state(rq) != MQ_RQ_IDLE);

```

시작 전에 IDLE이어야 한다는 상태 규칙이 깨졌으면 한 번 경고합니다. 경고가 요청을 자동으로 취소하는 것은 아닙니다.

### 1260행

```c

	blk_add_timer(rq);

```

요청의 시간 제한을 감시할 타이머를 준비합니다.

### 1261행

```c

	WRITE_ONCE(rq->state, MQ_RQ_IN_FLIGHT);

```

상태를 MQ_RQ_IN_FLIGHT로 기록합니다. WRITE_ONCE는 이 필드 접근이 임의로 합쳐지거나 나뉘는 것을 제한합니다.

### 1263행

```c

#ifdef CONFIG_BLK_DEV_INTEGRITY

```

데이터와 함께 보호 정보도 전달하는 장치를 위해 블록 계층의 무결성 처리를 포함하는 설정입니다. v6.6의 이 구간은 쓰기 요청에 필요한 보호 정보 준비를 수행하며, 이 설정만으로 모든 저장장치가 무결성 정보를 사용하지는 않습니다. 이 선택은 전처리 단계에서 이루어지며, CPU가 실행 중 이 줄의 조건을 검사하지 않습니다.

### 1264행

```c

	if (blk_integrity_rq(rq) && req_op(rq) == REQ_OP_WRITE)

```

무결성 보호 대상이면서 쓰기 요청인지 함께 검사합니다.

### 1265행

```c

		q->integrity.profile->prepare_fn(rq);

```

큐의 무결성 프로파일이 제공한 prepare_fn에 쓰기 요청을 넘겨 무결성 정보를 준비합니다.

### 1266행

```c

#endif

```

무결성 기능에 따른 조건부 코드는 여기서 끝납니다.

### 1267행

```c

	if (rq->bio && rq->bio->bi_opf & REQ_POLLED)

```

연결된 bio가 있으며 REQ_POLLED가 켜진 요청인지 확인합니다.

### 1268행

```c

	        WRITE_ONCE(rq->bio->bi_cookie, rq->mq_hctx->queue_num);

```

폴링할 하드웨어 큐 번호를 bio의 cookie에 기록합니다. cookie는 저장장치 주소가 아닙니다.

