요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
완료와 오류
dm-io.rst:58-67비동기 callback과 multi-region write의 region별 error bitset을 정리합니다.
Mempool 생명주기
dm-io.rst:68-75`dm_io_get()`과 `dm_io_put()`으로 동시 I/O page 수요를 예약하고 반환합니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
=====
dm-io
=====
Dm-io provides synchronous and asynchronous I/O services. There are three
types of I/O services available, and each type has a sync and an async
version.
The user must set up an io_region structure to describe the desired location
of the I/O. Each io_region indicates a block-device along with the starting
sector and size of the region::
struct io_region {
struct block_device *bdev;
sector_t sector;
sector_t count;
};
Dm-io can read from one io_region or write to one or more io_regions. Writes
to multiple regions are specified by an array of io_region structures.
The first I/O service type takes a list of memory pages as the data buffer for
the I/O, along with an offset into the first page::
struct page_list {
struct page_list *next;
struct page *page;
};
int dm_io_sync(unsigned int num_regions, struct io_region *where, int rw,
struct page_list *pl, unsigned int offset,
unsigned long *error_bits);
int dm_io_async(unsigned int num_regions, struct io_region *where, int rw,
struct page_list *pl, unsigned int offset,
io_notify_fn fn, void *context);
The second I/O service type takes an array of bio vectors as the data buffer
for the I/O. This service can be handy if the caller has a pre-assembled bio,
but wants to direct different portions of the bio to different devices::
int dm_io_sync_bvec(unsigned int num_regions, struct io_region *where,
int rw, struct bio_vec *bvec,
unsigned long *error_bits);
int dm_io_async_bvec(unsigned int num_regions, struct io_region *where,
int rw, struct bio_vec *bvec,
io_notify_fn fn, void *context);
The third I/O service type takes a pointer to a vmalloc'd memory buffer as the
data buffer for the I/O. This service can be handy if the caller needs to do
I/O to a large region but doesn't want to allocate a large number of individual
memory pages::
int dm_io_sync_vm(unsigned int num_regions, struct io_region *where, int rw,
void *data, unsigned long *error_bits);
int dm_io_async_vm(unsigned int num_regions, struct io_region *where, int rw,
void *data, io_notify_fn fn, void *context);
Callers of the asynchronous I/O services must include the name of a completion
callback routine and a pointer to some context data for the I/O::
typedef void (*io_notify_fn)(unsigned long error, void *context);
The "error" parameter in this callback, as well as the `*error` parameter in
all of the synchronous versions, is a bitset (instead of a simple error value).
In the case of an write-I/O to multiple regions, this bitset allows dm-io to
indicate success or failure on each individual region.
Before using any of the dm-io services, the user should call dm_io_get()
and specify the number of pages they expect to perform I/O on concurrently.
Dm-io will attempt to resize its mempool to make sure enough pages are
always available in order to avoid unnecessary waiting while performing I/O.
When the user is finished using the dm-io services, they should call
dm_io_put() and specify the same number of pages that were given on the
dm_io_get() call.
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
동기·비동기 I/O와 io_region
1-20`dm-io`는 동기 및 비동기 I/O 서비스를 제공합니다. 세 가지 data-buffer 유형이 있으며, 각 유형마다 sync 버전과 async 버전이 있습니다.
Buffer 표현 세 종류를 실행 방식 두 종류와 조합합니다.
호출자는 I/O 위치를 기술하는 `io_region` 구조체를 준비해야 합니다. 각 region은 block device, 시작 sector, region 크기를 지정합니다.
struct io_region {
struct block_device *bdev;
sector_t sector;
sector_t count;
};
`dm-io`는 하나의 `io_region`에서 읽거나 하나 이상의 region에 쓸 수 있습니다. 여러 region으로 쓰려면 `io_region` 구조체 배열을 전달합니다.
Read는 단일 source region을 사용하고 multi-write는 region 배열의 각 destination에 결과를 전달합니다.
Page list 기반 서비스
21-36첫 번째 서비스 유형은 memory page의 연결 목록을 I/O data buffer로 받고 첫 page 안의 offset도 함께 받습니다.
struct page_list {
struct page_list *next;
struct page *page;
};
int dm_io_sync(unsigned int num_regions, struct io_region *where, int rw,
struct page_list *pl, unsigned int offset,
unsigned long *error_bits);
int dm_io_async(unsigned int num_regions, struct io_region *where, int rw,
struct page_list *pl, unsigned int offset,
io_notify_fn fn, void *context);
`struct page_list`는 다음 node와 현재 `struct page`를 가리킵니다. 동기 `dm_io_sync()`는 region별 결과를 `error_bits`에 반환하고, 비동기 `dm_io_async()`는 완료 callback `fn`과 `context`를 받습니다.
Bio vector 배열 기반 서비스
37-47두 번째 서비스 유형은 bio vector 배열을 data buffer로 받습니다. 호출자가 이미 조립한 bio를 가지고 있으면서 bio의 서로 다른 부분을 서로 다른 장치로 보내려 할 때 유용합니다.
int dm_io_sync_bvec(unsigned int num_regions, struct io_region *where,
int rw, struct bio_vec *bvec,
unsigned long *error_bits);
int dm_io_async_bvec(unsigned int num_regions, struct io_region *where,
int rw, struct bio_vec *bvec,
io_notify_fn fn, void *context);
호출자가 이미 가진 memory 표현에 맞는 API를 선택합니다.
Vmalloc buffer 기반 서비스
48-57세 번째 서비스 유형은 `vmalloc()`으로 할당한 memory buffer 포인터를 I/O data buffer로 받습니다. 큰 영역에 I/O해야 하지만 많은 개별 memory page를 할당하고 싶지 않을 때 유용합니다.
int dm_io_sync_vm(unsigned int num_regions, struct io_region *where, int rw,
void *data, unsigned long *error_bits);
int dm_io_async_vm(unsigned int num_regions, struct io_region *where, int rw,
void *data, io_notify_fn fn, void *context);
동기 `dm_io_sync_vm()`은 `error_bits`를 반환하고, 비동기 `dm_io_async_vm()`은 callback과 context를 통해 완료를 통지합니다.
비동기 callback과 region별 error bitset
58-67비동기 I/O 서비스 호출자는 완료 callback routine의 이름과 해당 I/O를 위한 context data 포인터를 제공해야 합니다.
typedef void (*io_notify_fn)(unsigned long error, void *context);
Callback의 `error` 매개변수와 모든 동기 버전의 `*error` 매개변수는 단순 오류 값이 아니라 bitset입니다. 여러 region으로 write할 때 이 bitset으로 각 region의 성공 또는 실패를 개별 표시할 수 있습니다.
하나의 callback 호출이 multi-region 결과와 caller context를 함께 전달합니다.
dm_io_get과 dm_io_put 생명주기
68-75`dm-io` 서비스를 사용하기 전에 호출자는 `dm_io_get()`을 호출하고 동시에 I/O할 것으로 예상하는 page 수를 지정해야 합니다.
`dm-io`는 I/O 수행 중 불필요한 대기를 피할 만큼 page가 항상 준비되도록 mempool 크기 조정을 시도합니다.
서비스 사용을 마치면 `dm_io_put()`을 호출하고 앞서 `dm_io_get()`에 전달한 것과 같은 page 수를 지정해야 합니다.
예약과 해제에 같은 page 수를 사용해 공유 mempool 수요를 정확히 회계합니다.
Region과 buffer API
dm-io.rst:1-57`io_region` 위치 표현과 세 buffer 유형의 sync·async 함수 원형을 설명합니다.