int dm_io_async_bvec(unsigned int num_regions,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
struct dm_io_region *where,
#else
struct io_region *where,
#endif
int rw,
struct bio_vec *bvec, io_notify_fn fn,
void *context)
{
struct dm_io_request iorq;
iorq.bi_rw = rw;
iorq.mem.type = DM_IO_BVEC;
iorq.mem.ptr.bvec = bvec;
iorq.notify.fn = fn;
iorq.notify.context = context;
iorq.client = flashcache_io_client;
return dm_io(&iorq, num_regions, where, NULL);
}
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.
但是不同的内核版本io_region 结构体的表示不同。
2.6.26以后的版本用dm_io_region表示如下:
[cpp]
struct dm_io_region {
struct block_device *bdev;
sector_t sector;
sector_t count; /* If this is zero the region is ignored. */
};
2.6.26之前的版本用io_region表示如下:
[cpp]
struct io_region {
struct block_device *bdev;
sector_t sector;
sector_t count;
};
虽然形式不同,但是里面的内容是一样的,都含有一个指向block_device的指针,以及区域的起始扇区和区域的大小。
bio_vec结构体如下:
[cpp]
struct bio_vec {
struct page *bv_page; //指向段的页框中页描述符的指针
unsigned int bv_len;
//段的字节长度
unsigned int bv_offset; //页框中段数据的偏移量
};
io_notify_fn是一个回调函数指针的类型,其定义如下:
[cpp]
typedef void (*io_notify_fn)(unsigned long error, void *context);
The "error" parameter in this callback,, 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.
dm_io_request结构体如下:(通过dm_io_request结构来封装请求的类型,如果设置了dm_io_notify.fn则是异步IO,否则是同步IO。)
[cpp]
struct dm_io_request {
int bi_rw; /* READ|WRITE - not READA */
struct dm_io_memory mem; /* Memory to use for io */
struct dm_io_notify notify; /* Synchronous if notify.fn is NULL */
struct dm_io_client *client; /* Client memory handler */
};
从上面的分析可以看出,dm_io_async_bvec通过io_notify_fn fn来确定是同步操作还是异步操作,通过bio_vec *bvec确定dm_io的服务类型,dm_io有3种服务类型:
[cpp]
//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);
[cpp]
//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_b