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