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