# F2FS: 파일 조건에 맞는 직접 읽기와 캐시 읽기

v6.6 / fs/f2fs/file.c

F2FS는 플래시 저장장치를 고려해 세그먼트와 노드 구조로 파일 위치를 관리합니다. 읽기 진입점에서는 압축 구현이 준비됐는지 확인하고 파일과 요청 조건에 맞는 읽기 방식을 고릅니다. 아래는 v6.6의 f2fs_file_read_iter 전체입니다. 이후 버전에 추가된 LFS 모드의 진행 중 DIO 대기 분기는 이 코드에 없으므로 같은 동작으로 설명하지 않습니다.

## f2fs_file_read_iter

```c

static ssize_t f2fs_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
{
	struct inode *inode = file_inode(iocb->ki_filp);
	const loff_t pos = iocb->ki_pos;
	ssize_t ret;

	if (!f2fs_is_compress_backend_ready(inode))
		return -EOPNOTSUPP;

	if (trace_f2fs_dataread_start_enabled())
		f2fs_trace_rw_file_path(iocb->ki_filp, iocb->ki_pos,
					iov_iter_count(to), READ);

	if (f2fs_should_use_dio(inode, iocb, to)) {
		ret = f2fs_dio_read_iter(iocb, to);
	} else {
		ret = filemap_read(iocb, to, 0);
		if (ret > 0)
			f2fs_update_iostat(F2FS_I_SB(inode), inode,
						APP_BUFFERED_READ_IO, ret);
	}
	if (trace_f2fs_dataread_end_enabled())
		trace_f2fs_dataread_end(inode, pos, ret);
	return ret;
}

```

### 4436행

```c

static ssize_t f2fs_file_read_iter(struct kiocb *iocb, struct iov_iter *to)

```

F2FS 파일 읽기 요청과 목적지 반복자를 받습니다. 결과는 바이트 수 또는 음수 오류입니다.

### 4438행

```c

	struct inode *inode = file_inode(iocb->ki_filp);

```

파일에서 inode를 얻어 F2FS 속성과 동시 I/O 상태를 확인합니다.

### 4439행

```c

	const loff_t pos = iocb->ki_pos;

```

읽기 전 시작 위치를 보관합니다. 이후 위치가 이동해도 추적 기록에 원래 값을 쓸 수 있습니다.

### 4440행

```c

	ssize_t ret;

```

읽기 결과를 저장할 부호 있는 변수입니다. 음수 오류도 담아야 합니다.

### 4442행

```c

	if (!f2fs_is_compress_backend_ready(inode))

```

해당 파일을 읽는 데 필요한 압축 구현이 준비되어 있는지 확인합니다.

### 4443행

```c

		return -EOPNOTSUPP;

```

준비되지 않았다면 지원하지 않는 작업이라는 오류를 반환합니다.

### 4445행

```c

	if (trace_f2fs_dataread_start_enabled())

```

읽기 시작 추적 이벤트가 활성화됐을 때만 경로 추적 정보를 계산합니다.

### 4446행

```c

		f2fs_trace_rw_file_path(iocb->ki_filp, iocb->ki_pos,

```

파일과 현재 위치를 추적 함수에 전달합니다.

### 4447행

```c

					iov_iter_count(to), READ);

```

요청 바이트 수와 읽기 방향 READ도 함께 전달합니다.

### 4449행

```c

	if (f2fs_should_use_dio(inode, iocb, to)) {

```

inode와 이번 I/O 조건을 함께 검사하여 직접 I/O 경로를 사용할지 바로 분기합니다. 이 v6.6 함수에는 별도의 dio 지역변수나 LFS DIO 대기 분기가 없습니다.

### 4450행

```c

		ret = f2fs_dio_read_iter(iocb, to);

```

F2FS 직접 읽기를 수행해 결과를 ret에 저장합니다.

### 4451행

```c

	} else {

```

직접 I/O를 선택하지 않은 요청은 아래 캐시 읽기 경로로 갑니다.

### 4452행

```c

		ret = filemap_read(iocb, to, 0);

```

페이지 캐시를 이용하는 filemap 읽기에 요청을 넘깁니다.

### 4453행

```c

		if (ret > 0)

```

실제로 양수 바이트를 읽었을 때만 읽은 양을 통계에 더합니다.

### 4454행

```c

			f2fs_update_iostat(F2FS_I_SB(inode), inode,

```

F2FS 파일시스템과 inode를 통계 갱신 함수에 전달합니다.

### 4455행

```c

						APP_BUFFERED_READ_IO, ret);

```

애플리케이션 버퍼드 읽기 종류와 실제 읽은 바이트 수를 전달합니다.

### 4457행

```c

	if (trace_f2fs_dataread_end_enabled())

```

읽기 종료 추적 이벤트가 활성화되어 있는지 확인한 뒤에만 이벤트 호출을 실행합니다.

### 4458행

```c

		trace_f2fs_dataread_end(inode, pos, ret);

```

원래 시작 위치와 최종 결과로 읽기 종료 추적 이벤트를 남깁니다.

### 4459행

```c

	return ret;

```

실제 읽은 길이, 0 또는 오류를 호출자에게 반환합니다.

