dm_io_async_bvec()函数分析(二)
its);
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);
[cpp]
//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);
dm_io_async_bvec通过dm_io_request封装请求之后,确定了请求的各种类型,然后由dm_io()函数来完成操作。dm_io函数如下:
[cpp]
int dm_io(struct dm_io_request *io_req, unsigned num_regions,
struct dm_io_region *where, unsigned long *sync_error_bits)
{
int r;
struct dpages dp;
r = dp_init(io_req, &dp);
if (r)
return r;
if (!io_req->notify.fn)
return sync_io(io_req->client, num_regions, where,
io_req->bi_rw, &dp, sync_error_bits);
return async_io(io_req->client, num_regions, where, io_req->bi_rw,
&dp, io_req->notify.fn, io_req->notify.context);
}
dpages结构体如下:
[cpp]
struct dpages {
void (*get_page)(struct dpages *dp,
struct page **p, unsigned long *len, unsigned *offset);//是一种函数指针的形式,根据参数获取某一区域,区域类型由上下文确定
void (*next_page)(struct dpages *dp);//同样是函数指针的形式,根据参数获取某一区域的下一区域
unsigned context_u;
void *context_ptr;//私有数据成员,可根据上下文确定其类型,也即上面的区域类型
};
dpages结构体provide an abstraction for getting a new destination page for io.
dp_init()函数如下:
[cpp]
{
/* Set up dpages based on memory type */
switch (io_req->mem.type) {
case DM_IO_PAGE_LIST:
list_dp_init(dp, io_req->mem.ptr.pl, io_req->mem.offset);
break;
case DM_IO_BVEC: //可以看到我们的io_req->mem.type是此种类型
bvec_dp_init(dp, io_req->mem.ptr.bvec);
break;
case DM_IO_VMA:
vm_dp_init(dp, io_req->mem.ptr.vma);
break;
case DM_IO_KMEM:
km_dp_init(dp, io_req->mem.ptr.addr);
break;
default:
return -EINVAL;
}
return 0;
}
b
vce_dp_init()函数如下:
[cpp]
static void bvec_dp_init(struct dpages *dp, struct bio_vec *bvec)
{
dp->get_page = bvec_get_page;//获取某一个bio_vec
dp->next_page = bvec_next_page;//获取下一个bio_vec
dp->context_ptr = bvec;//确定区域类型为bio_vec
}
bvec_get_page()函数如下:
[cpp]
static void bvec_get_page(struct dpages *dp,
struct page **p, unsigned long *len, unsigned *offset)
{
struct bio_vec *bvec = (struct bio_vec *) dp->context_ptr;
*p = bvec->bv_page;
*len = bvec->bv_len;
*offset = bvec->bv_offset;
}
bvec_next_page()函数如下:
[cpp]
static void bvec_next_page(struct dpages *dp)
{
struct bio_vec *bvec = (struct bio_vec *) dp->context_ptr;
dp->context_ptr = bvec + 1;
}
处理完dm_io的服务类型之后,然后根据io_req->notify.fn是否设置,来确定dm_io的操作类型是同步的还是异步的。
同步操作调用sync_io