flashcache中内存与磁盘,磁盘与磁盘的io
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);
}
#endif
int
flashcache_dm_io_async_vm(struct cache_c *dmc, unsigned int num_regions,
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
struct io_region *where,
#else
struct dm_io_region *where,
#endif
int rw,
void *data, io_notify_fn fn, void *context)
{
unsigned long error_bits = ;
int error;
struct dm_io_request io_req = {
.bi_rw = rw,
.mem.type = DM_IO_VMA,
.mem.ptr.vma = data,
.mem.offset = ,
.notify.fn = fn,
.notify.context = context,
.client = flashcache_io_client,
}; error = dm_io(&io_req, , where, &error_bits);
if (error)
return error;
if (error_bits)
return error_bits;
return ;
}
#endif
上面两个函数都使用struct dm_io_request 来包装了请求,其中的只有两种请求的类型是不一样的,第一个函数对应的是DM_IO_BVEC,第二个函数是DM_IO_VMA。
其实我开始一直不明白,为什么要使用这两个函数让硬盘与内存打交道,不过后来看了dm_io发现其中的io服务类型有多种不同类型,这两个函数的调用分别对应不同的io类型。下面先看一下dm_io相关的数据结构。
dm_io
dm-io为device mapper提供同步或者异步的io服务。
使用dm-io必须设置dm_io_region结构(2.6.26版本以前叫io_region),该结构定义了io操作的区域,读一般针对一个dm_io_region区,而写可以针对一组dm_io_region区。
struct dm_io_region {
struct block_device *bdev;
sector_t sector;
sector_t count; /* If this is zero the region is ignored. */
};
struct io_region {
struct block_device *bdev;
sector_t sector;
sector_t count;
};
dm-io一共有四种dm_io_mem_type类型(老一点的内核版本只有前面三种,Flashcache主要使用DM_IO_BVEC):
enum dm_io_mem_type {
DM_IO_PAGE_LIST,/* Page list */
DM_IO_BVEC, /* Bio vector */
DM_IO_VMA, /* Virtual memory area */
DM_IO_KMEM, /* Kernel memory */
}; struct dm_io_memory {
enum dm_io_mem_type type;
union {
struct page_list *pl;
struct bio_vec *bvec;
void *vma;
void *addr;
} ptr; unsigned 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);
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);
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);
当用户完成了使用I/O服务,他们将调用dm_io_put(),并指定和给dm_io_get()的相同数量的页面。
dm-io通过dm_io_request结构来封装请求的类型,如果设置了dm_io_notify.fn则是异步IO,否则是同步IO。
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服务前前需要通过dm_io_client_create函数(在2.6.22版本前是dm_io_get)先创建dm_io_client结构,为dm-io的执行过程中分配内存池。使用dm-io服务完毕后,则需要调用dm_io_client_destroy函数(在2.6.22版本前是dm_io_put)释放内存池。
struct dm_io_client {
mempool_t *pool;
struct bio_set *bios;
};
dm-io函数执行具体的io请求。
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);
}
对于第二种情况,磁盘跟磁盘之前的交互。这种情况只用于将ssd中脏块写入disk中。
int dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from,
unsigned int num_dests, struct dm_io_region *dests,
unsigned int flags, dm_kcopyd_notify_fn fn, void *context)
第一个参数dm_kcopyd_client,在使用kcopyd异步拷贝服务时,必须先创建一个对应的client,首先要分配“kcopyd客户端”结构,调用函数如下:
kcopyd_client_create(FLASHCACHE_COPY_PAGES, &flashcache_kcp_client);
创建dm_kcopyd_client结构。
struct block_device *bdev;
sector_t sector;
sector_t count; /* If this is zero the region is ignored. */
};
flashcache中内存与磁盘,磁盘与磁盘的io的更多相关文章
- CentOS查看CPU、内存、网络流量和磁盘 I/O
安装 yum install -y sysstat sar -d 1 1 rrqm/s: 每秒进行 merge 的读操作数目.即 delta(rmerge)/swrqm/s: 每秒进行 merge 的 ...
- CentOS查看CPU、内存、网络流量和磁盘 I/O【详细】
安装 yum install -y sysstat sar -d 1 1 rrqm/s: 每秒进行 merge 的读操作数目.即 delta(rmerge)/swrqm/s: 每秒进行 merge 的 ...
- linux硬件资源问题排查:cpu负载、内存使用情况、磁盘空间、磁盘IO
在使用过程中之前正常的功能,突然无法使用,性能变慢,通常都是资源消耗问题,资源消耗可以从以下几个方面去排查.对于已经安装硬件资源监控软件(zabbix)的环境,直接使用硬件资源监控软件(zabbix) ...
- 请确认 <Import> 声明中的路径正确,且磁盘上存在该文件。
在网上下了个源码打开报错. 请确认 <Import> 声明中的路径正确,且磁盘上存在该文件. 一查,原来是路径错误. 解决办法:将项目文件(.csproj)用记事本打开,然后找到<I ...
- 升级CUDA版本导致VS2010错误:未找到导入的项目XXX,请确认<Import>声明中的路径正确,且磁盘上存在该文件
转自:http://www.cnblogs.com/yeahgis/p/3853420.html VS2010错误:未找到导入的项目XXX,请确认<Import>声明中的路径正确,且磁盘上 ...
- Linux学习(十四)磁盘格式化、磁盘挂载、手动增加swap空间
一.磁盘格式化 分好去的磁盘需要格式化之后才可以使用.磁盘分区一般用mke2fs命令或者mkfs.filesystemtype.这个filesystemtype分为ext4,ext3,xfs等等.xf ...
- Linux学习之CentOS(十二)------磁盘管理之 磁盘的分区、格式化、挂载(转)
磁盘分区.格式化.挂载磁盘分区 新增分区 查询分区 删除分区磁盘格式化 mkfs mke2fs磁盘挂载与卸载 mount umount 磁盘的分区.格式化.挂 ...
- (转)GPT磁盘与MBR磁盘区别
摘要: Windows 2008磁盘管理器中,在磁盘标签处右击鼠标,随磁盘属性的不同会出现“转换到动态磁盘”,“转换到基本磁盘”“转换成GPT磁盘”,“转换成MBR磁盘”等选项,在此做简单介绍.部 ...
- Linux磁盘系统——管理磁盘的命令
Linux磁盘系统——管理磁盘的命令 摘要:本文主要学习了Linux系统中管理磁盘的命令,包括查看磁盘使用情况.磁盘挂载相关.磁盘分区相关.磁盘格式化等操作. df命令 df命令用于显示Linux系统 ...
随机推荐
- Spring Data MongoDB 分页查询
在上篇文章 Spring Data MongoDB 环境搭建 基础上进行分页查询 定义公用分页参数类,实现 Pageable 接口 import java.io.Serializable; impor ...
- 利用Ogr将Kml转为Shape【1】
最近在研究Kml怎么转化为Shape文件,因为客户中很多在原来采集了一部分数据都是在google Earth中,而我们的应用中特别需要这份数据,所以打算先在GE中把这份数据导出为Kml或Kmz文件,然 ...
- spring 与mybatis 整合总结
刚看完同学给我的代码,我忍不住爆粗.去TMD,写得像坨屎,恶心,乱七八糟,这让我怎么交差??一行代码注释都没有,还很自以为是的傲慢.“这都不懂?这就是Mybatis啊,有很多种方法实现.....” 操 ...
- 微服务架构之spring cloud eureka
Spring Cloud Eureka是spring cloud的核心组件,负责服务治理功能,起到中心枢纽作用,其它组件都依赖eureka来获取服务,然后再根据项目需求实现自己的业务,eureka在整 ...
- SpringBoot整合mybatis踩坑
springboot整合mybaits过程中,调用接口时报错:org.apache.ibatis.binding.BindingException: Invalid bound statement ( ...
- Sql server 查询数据库中包含某字段的所有的表
我们有时候会需要查询数据库中包含某字段的所有的表,去进行update,这时就可以用下面的SQL来实现: select object_name(id) objName,Name as colName f ...
- jQuery 小案例
用jquery实现 百度换肤的模式; <!DOCTYPE html> <html lang="en"> <head> <meta cha ...
- 服务器编程入门(13) Linux套接字设置超时的三种方法
摘要: 本文介绍在套接字的I/O操作上设置超时的三种方法. 图片可能有点宽,看不到的童鞋可以点击图片查看完整图片.. 1 调用alarm 使用SIGALRM为connect设置超时 设置方法: ...
- python的文件对象(1)
1 首先要明确的是,文件只是连续的字节. 数据的传输经常会用到字节流,无论字节流是由单个字节还是大块数据组成. 2 打开文件之门的钥匙--open() open()内建函数成功打开文件后会返回一个 ...
- ASP.NET Core 返回文件、用户下载文件,从网站下载文件,动态下载文件
ASP.NET Core 中,可以在静态目录添加文件,直接访问就可以下载.但是这种方法可能不安全,也不够灵活. 我们可以在 Controller 控制器中 添加 一个 Action,通过此Action ...