# I/O 스케줄러: 다음 요청을 어떤 기준으로 고르는가

v6.6 / block/mq-deadline.c

여러 프로세스가 동시에 I/O를 내면 장치가 처리할 순서를 정해야 합니다. mq-deadline은 우선순위뿐 아니라 오래 기다린 요청도 고려합니다. dd_dispatch_request는 다음 요청 하나를 고르는 상위 흐름이며, 실제 읽기·쓰기 선택과 섹터 순서 비교는 하위 함수로 이어집니다.

## dd_dispatch_request

```c

static struct request *dd_dispatch_request(struct blk_mq_hw_ctx *hctx)
{
	struct deadline_data *dd = hctx->queue->elevator->elevator_data;
	const unsigned long now = jiffies;
	struct request *rq;
	enum dd_prio prio;

	spin_lock(&dd->lock);
	rq = dd_dispatch_prio_aged_requests(dd, now);
	if (rq)
		goto unlock;

	/*
	 * Next, dispatch requests in priority order. Ignore lower priority
	 * requests if any higher priority requests are pending.
	 */
	for (prio = 0; prio <= DD_PRIO_MAX; prio++) {
		rq = __dd_dispatch_request(dd, &dd->per_prio[prio], now);
		if (rq || dd_queued(dd, prio))
			break;
	}

unlock:
	spin_unlock(&dd->lock);

	return rq;
}

```

### 596행

```c

static struct request *dd_dispatch_request(struct blk_mq_hw_ctx *hctx)

```

해당 하드웨어 큐가 다음에 발행할 request 하나를 요청하는 진입점입니다.

### 598행

```c

	struct deadline_data *dd = hctx->queue->elevator->elevator_data;

```

하드웨어 큐에서 공통 큐와 elevator를 따라가 mq-deadline의 정책 상태를 얻습니다.

### 599행

```c

	const unsigned long now = jiffies;

```

이번 선택 동안 사용할 현재 틱 값을 한 번 읽습니다.

### 600행

```c

	struct request *rq;

```

최종 선택한 request를 담을 포인터입니다. 후보가 없으면 NULL이 될 수 있습니다.

### 601행

```c

	enum dd_prio prio;

```

우선순위 그룹을 순회할 변수를 선언합니다.

### 603행

```c

	spin_lock(&dd->lock);

```

공유하는 스케줄러 목록과 계수를 안전하게 다루도록 잠급니다.

### 604행

```c

	rq = dd_dispatch_prio_aged_requests(dd, now);

```

너무 오래 기다린 다른 우선순위의 요청이 있는지 먼저 살펴 기아를 완화합니다.

### 605행

```c

	if (rq)

```

이 검사에서 실제 후보를 얻었는지 확인합니다.

### 606행

```c

		goto unlock;

```

얻은 후보를 유지한 채 공통 반환 절차로 갑니다.

### 612행

```c

	for (prio = 0; prio <= DD_PRIO_MAX; prio++) {

```

우선순위 값 0부터 마지막 그룹까지 차례로 살펴봅니다. 숫자가 메모리 주소를 뜻하는 것은 아닙니다.

### 613행

```c

		rq = __dd_dispatch_request(dd, &dd->per_prio[prio], now);

```

해당 우선순위 내부의 읽기·쓰기와 순서 정책으로 발행할 후보를 선택합니다.

### 614행

```c

		if (rq || dd_queued(dd, prio))

```

후보를 찾았거나 해당 높은 우선순위에 아직 대기 작업이 있으면 아래 그룹으로 내려가지 않습니다.

### 615행

```c

			break;

```

우선순위 순회를 끝냅니다.

### 618행

```c

unlock:

```

성공과 후보 없음 모두 잠금을 풀기 위해 모이는 위치입니다.

### 619행

```c

	spin_unlock(&dd->lock);

```

선택 중 보호한 스케줄러 상태의 잠금을 해제합니다.

### 621행

```c

	return rq;

```

선택한 request를 반환합니다. NULL이면 이 호출에서 발행할 후보가 없습니다.

