← Documents Documentation/admin-guide/device-mapper/dm-io.rst GitHub 원문 ↗

Linux 6.18.37 · Administration / Device Mapper

dm-io

Page list, bio vector, vmalloc buffer를 사용하는 동기·비동기 device-mapper I/O API와 오류·mempool 규칙입니다.

Source pathDocumentation/admin-guide/device-mapper/dm-io.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

Region과 buffer API

dm-io.rst:1-57

`io_region` 위치 표현과 세 buffer 유형의 sync·async 함수 원형을 설명합니다.

완료와 오류

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 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 =====
2 dm-io
3 =====
4
5 Dm-io provides synchronous and asynchronous I/O services. There are three
6 types of I/O services available, and each type has a sync and an async
7 version.
8
9 The user must set up an io_region structure to describe the desired location
10 of the I/O. Each io_region indicates a block-device along with the starting
11 sector and size of the region::
12
13 struct io_region {
14 struct block_device *bdev;
15 sector_t sector;
16 sector_t count;
17 };
18
19 Dm-io can read from one io_region or write to one or more io_regions. Writes
20 to multiple regions are specified by an array of io_region structures.
21
22 The first I/O service type takes a list of memory pages as the data buffer for
23 the I/O, along with an offset into the first page::
24
25 struct page_list {
26 struct page_list *next;
27 struct page *page;
28 };
29
30 int dm_io_sync(unsigned int num_regions, struct io_region *where, int rw,
31 struct page_list *pl, unsigned int offset,
32 unsigned long *error_bits);
33 int dm_io_async(unsigned int num_regions, struct io_region *where, int rw,
34 struct page_list *pl, unsigned int offset,
35 io_notify_fn fn, void *context);
36
37 The second I/O service type takes an array of bio vectors as the data buffer
38 for the I/O. This service can be handy if the caller has a pre-assembled bio,
39 but wants to direct different portions of the bio to different devices::
40
41 int dm_io_sync_bvec(unsigned int num_regions, struct io_region *where,
42 int rw, struct bio_vec *bvec,
43 unsigned long *error_bits);
44 int dm_io_async_bvec(unsigned int num_regions, struct io_region *where,
45 int rw, struct bio_vec *bvec,
46 io_notify_fn fn, void *context);
47
48 The third I/O service type takes a pointer to a vmalloc'd memory buffer as the
49 data buffer for the I/O. This service can be handy if the caller needs to do
50 I/O to a large region but doesn't want to allocate a large number of individual
51 memory pages::
52
53 int dm_io_sync_vm(unsigned int num_regions, struct io_region *where, int rw,
54 void *data, unsigned long *error_bits);
55 int dm_io_async_vm(unsigned int num_regions, struct io_region *where, int rw,
56 void *data, io_notify_fn fn, void *context);
57
58 Callers of the asynchronous I/O services must include the name of a completion
59 callback routine and a pointer to some context data for the I/O::
60
61 typedef void (*io_notify_fn)(unsigned long error, void *context);
62
63 The "error" parameter in this callback, as well as the `*error` parameter in
64 all of the synchronous versions, is a bitset (instead of a simple error value).
65 In the case of an write-I/O to multiple regions, this bitset allows dm-io to
66 indicate success or failure on each individual region.
67
68 Before using any of the dm-io services, the user should call dm_io_get()
69 and specify the number of pages they expect to perform I/O on concurrently.
70 Dm-io will attempt to resize its mempool to make sure enough pages are
71 always available in order to avoid unnecessary waiting while performing I/O.
72
73 When the user is finished using the dm-io services, they should call
74 dm_io_put() and specify the same number of pages that were given on the
75 dm_io_get() call.
76

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

동기·비동기 I/O와 io_region

1-20

`dm-io`는 동기 및 비동기 I/O 서비스를 제공합니다. 세 가지 data-buffer 유형이 있으며, 각 유형마다 sync 버전과 async 버전이 있습니다.

dm-io 서비스 조합
Data buffer동기 API비동기 API
Page list`dm_io_sync()``dm_io_async()`
Bio vector array`dm_io_sync_bvec()``dm_io_async_bvec()`
Vmalloc buffer`dm_io_sync_vm()``dm_io_async_vm()`

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` 구조체 배열을 전달합니다.

io_region에 따른 I/O 방향
Read request하나의 `io_region`Data buffer
Write request`io_region[]`Region 0Region 1 ... N

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);
Buffer 유형별 사용 시점
유형입력적합한 상황
Page list`struct page_list *pl` + first-page offset개별 page가 연결 목록으로 준비됨
Bio vector`struct bio_vec *bvec`미리 조립한 bio의 부분을 여러 장치로 분배
Vmalloc`void *data`많은 개별 page 할당 없이 큰 연속 가상 buffer 사용

호출자가 이미 가진 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의 성공 또는 실패를 개별 표시할 수 있습니다.

비동기 완료와 오류 전달
Async I/O 제출여러 `io_region` 실행`io_notify_fn(error, context)`Error bit N으로 region N 결과 확인

하나의 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 수를 지정해야 합니다.

dm-io 자원 생명주기
`dm_io_get(expected_pages)`Mempool 크기 조정동기·비동기 I/O 수행`dm_io_put(expected_pages)`

예약과 해제에 같은 page 수를 사용해 공유 mempool 수요를 정확히 회계합니다.