I/O barrier请求用来保证I/O请求的顺序。其主要是针对那些需要保证顺序的写请求,比如日志的checkpoint。在请求队列中,那些排在barrier请求前的请求,必须在barrier请求开始之前完成。(这里所说的完成指数据写入物理介质,而不是保存在OS或者设备缓存中)。而那些排在barrier请求后的请求,只有在barrier请求完成后才能开始(这儿所说的完成,同样是指barrier请求的捎带数据写入物理介质)。

总的来说, I/O barrier请求拥有一下两个性质:

1.请求顺序

非barrier请求不能跨越barrier请求。barrier请求之前的请求必须先于barrier请求进行处理,barrier请求之后的请求必须在barrier请求完成后进行处理。

根据磁盘驱动器的特性,以上条件可以用以下三种方式来实现:

i.对于设备队列深度大于1(TCQ设备)并且支持ordered

tag的设备,块设备层只需要发送一个标为ordered的请求来作为barrier,底层驱动,控制器和磁盘驱动器负责确保请求的顺序。现在,大多数SCSI控制器/磁盘驱动器都应该支持这个特性。

ii. 对于设备队列深度大于1但是不支持ordered

tag的设备,块设备层确保barrier请求往设备分发前,之前的请求将先被处理完。块设备层也会延迟barrier请求之后的请求,直到barrier请求完成。老的SCSI控制器/磁盘驱动器以及SATA磁盘驱动器属于这类设备。

iii.

对于设备队列深度为1的设备,这种设备相当于ii类设备的特例。只要保证分发的顺序就够了(保证i/o调度器不打乱顺序)。较老的SCSI控制器/磁盘驱动器和IDE驱动器属于这类设备。

2. 强制刷新数据到物理介质

使用I/O

barrier的原因主要是保护文件系统的完整性。意外掉电或者其他事件使得磁盘驱动器无法正常工作,将造成磁盘缓存中数据的丢失。所以,I/Obarrier需要保证i/o请求真正被顺序写入了非易失性介质上。

这儿有四种情况:

i.无write-back缓冲,保证请求自身的顺序就足够了。

ii.有write-back缓存但没有刷新缓存的操作。这种情况下,无法保证物理介质的写入顺序。这种类型的设备不能支持I/Obarrier。

iii.有write-bach缓存,有刷新缓存的操作但无FUA(forced unit

access),这种情况下,我们需要两次缓存刷新操作:分别在barrier请求前后。

iv.有write-back缓存,刷新缓存操作和FUA。这是,我们只需要一次刷新操作来确保barrier请求之前的请求被写入物理介质。而barrier请求之后的刷新操作可以省略。因为我们可以指定barrier请求为FUA写,这样确保了barrier请求自身能被真正地写入物理介质。从而避免了第二次刷新。

怎样在驱动中支持barrier请求

---------------------------

所有barrier的处理都是在通用块层内部进行的。所有底层驱动需要实现自己的prepare_flush_fn函数,并且使用以下两个函数之一来说明自己支持哪种barrier类型以及怎样准备用于刷新缓存的请求。注意,“ordered”用来说明处理barrier请求的整个过程顺序,包括请求的分发和缓存的刷新。

typedef void (prepare_flush_fn)(struct request_queue *q, struct request *rq);

int blk_queue_ordered(struct request_queue *q, unsigned ordered,

prepare_flush_fn *prepare_flush_fn);

@q   : the queue in question

@ordered  : the ordered mode the driver/device supports

@prepare_flush_fn : this function should prepare @rq such that it

flushes cache to physical medium when executed

比如,SCSI磁盘驱动的prepare_flush_fn如下:

static void sd_prepare_flush(struct request_queue *q, struct request *rq)

{

memset(rq->cmd, 0, sizeof(rq->cmd));

rq->cmd_type = REQ_TYPE_BLOCK_PC;

rq->timeout = SD_TIMEOUT;

rq->cmd[0] = SYNCHRONIZE_CACHE;

rq->cmd_len = 10;

}

当前Linux中,支持以下7中顺序模式。以下表格显示了根据不同设备/驱动的特点需要采用哪种模式。在表格的最左边,QUEUE_ORDERED_前缀被省略了,以节约空间。

表格后面是各种模式的解释。注意,在QUEUE_ORDERED_DRAIN*中的描述使用了“=>”,而在QUEUE_ORDERED_TAG*的描述中使用了“->”。前者表示,前面的步骤必须在后面的步骤开始之前完成。而后者表示后面的步骤只要在前面步骤开始后就可以开始。

write-back cache ordered tag flush  FUA

-----------------------------------------------------------------------

NONE  yes/no  N/A  no  N/A

DRAIN  no  no  N/A  N/A

DRAIN_FLUSH yes  no  yes  no

DRAIN_FUA yes  no  yes  yes

TAG  no  yes  N/A  N/A

TAG_FLUSH yes  yes  yes  no

TAG_FUA  yes  yes  yes  yes

QUEUE_ORDERED_NONE

I/O barrier不需要或者不被支持

Sequence: N/A

QUEUE_ORDERED_DRAIN

请求以请求队列中分发的顺序进行排序,不需要刷新缓存操作。

Sequence: drain => barrier

QUEUE_ORDERED_DRAIN_FLUSH

请求以请求队列中分发的顺序进行排序,需要在barrier请求前和之后刷新缓存。

Sequence: drain => preflush => barrier => postflush

QUEUE_ORDERED_DRAIN_FUA

请求以请求队列中分发的顺序进行排序,之需要在barrier请求前刷新缓存。在barrier请求上使用FUA,省略barrier请求之后的刷新。

Sequence: drain => preflush => barrier

QUEUE_ORDERED_TAG

请求被ordered tag排序,不需要刷新缓存。

Sequence: barrier

QUEUE_ORDERED_TAG_FLUSH

请求被ordered tag排序,在barrier请求之前和之后,需要刷新缓存。

Sequence: preflush -> barrier -> postflush

QUEUE_ORDERED_TAG_FUA

请求被ordered

tag排序,在barrier请求之前需要刷新缓存。在barrier请求上使用FUA,省略barrier请求之后的刷新。

Sequence: preflush -> barrier

----------------

*SCSI层当前不能使用TAG ordering,即使磁盘驱动器,控制器和驱动支持这个特性。其主要原因是SCSI中间层的请求分发函数不是原子的。在分发请求时,它会释放请求队列的锁,转而获取SCSI host的锁。这样,就可能发生请求相对位置改变的情况。一但这个问题解决了,TAG ordering将会启用。

*当前,无论那种顺序模式被使用,某一时刻,只能有一个barrier请求被处理。所有I/O barrier都会被通用块层扣留起来,直到前面的I/O barrier处理完成。这和DRAIN顺序的设备没有什么不同。但是,对于TAG 顺序的设备,由于其命令时延较长,如果I/O barrier分发频

繁,传递多个I/O barrier到底层可能会有帮助。

*完成顺序。顺序的请求被顺序的分发,但不要求顺序完成。Barrier实现可以处理乱序完成的请求。也就是说,请求必须被顺序处理,但是硬件/软件完成路径允许以乱序进行通知。比如,当前SCSI中间层就没在错误处理时预设完成顺序。

*重新入队顺序。底层驱动可以自由重新入队任何请求。由于barrier序列在重新入队时必须保持顺序,通用电梯程序中保证插入的请求符合barrier顺序。参见blk_ordered_req_seq() 和 ELEVATOR_INSERT_REQUEUE handling in __elv_add_request()。

注意,在完成一个顺序序列后面的请求时,块设备不能重新入队之前的请求。当前,没有针对这种错误的检查。

*错误处理。当前,当在一个顺序序列中的请求发生错误时,通用块层会把错误报告给上层。不幸的是,这样做往往还不够。比如有如下的请求,使用QUEUE_ORDERED_TAG_FLUSH顺序模式。

[0] [1] [2] [3] [pre] [barrier] [post] < [4] [5] [6] ... >

still in elevator

假设[2],[3]是用来更新文件系统metadata的写请求(日志等)。[barrier]用来标识这些更新是有效的。考虑以下序列:

i.请求[0]~[post] 离开了请求队列,进入底层驱动。

ii. 过了一会儿,不幸发生了,磁盘驱动器出现故障,[2]失败。注意,此时[0],[1],和[3]都已经完成了。但是[pre]还没有完成,因为磁盘驱动器必须按照顺序来处理它。它在也会失败。

iii.此时,错误处理介入。它确定错误不能恢复,[2]操作失败,并重启操作。

iv.[pre][barrier][post]得到处理

v.掉电

问题在于,barrier请求本来认为文件系统更新请求[2]和[3]会被安全地写入物理介质。如果机器在barrier被写入后crash掉。文件系统的恢复代码可以依靠它。不幸的是,这种情况不再成立。也就是说,I/O barrier的成功,必须依赖前面某些请求的成功,这究竟是那些请求,只有上面的文件系统才知道。

要解决这个问题,可以通过实现一种方式,来告诉通用块层哪些请求影响之后的barrier请求,使底层驱动只有在得到通用块层通知后才进行错误处理。

barrier linux,Linux Barrier I/O相关推荐

  1. barrier linux,Linux Barrier I/O 实现分析笔记

    一直以来,I/O顺序问题一直困扰着我.其实这个问题是一个比较综合的问题,它涉及的层次比较多,从VFS page cache到I/O调度算法,从i/o子系统到存储外设.而Linux I/O barrie ...

  2. barrier linux,Linux系统上启用barrier?

    大多数当前流行的Linux文件系统,包括EXT3和EXT4,都将文件系统barrier作为一个增强的安全特性.它保护数据不被写入日记.但是,在许多情况下,我们并不清楚这些barrier是否有用.本文就 ...

  3. 九十分钟极速入门Linux——Linux Guide for Developments 学习笔记

    转载自: 九十分钟极速入门Linux--Linux Guide for Developments 学习笔记 http://mp.weixin.qq.com/s?__biz=MzAwNTMxMzg1MA ...

  4. [Linux]Linux下安装和配置solr/tomcat/IK分词器 详细实例二.

    为了更好的排版, 所以将IK分词器的安装重启了一篇博文,  大家可以接上solr的安装一同查看. [Linux]Linux下安装和配置solr/tomcat/IK分词器 详细实例一: http://w ...

  5. krc 编辑 linux,Linux网络编程

    6 berkeley - 145 - struct in_addr { unsigned long s_addr; }; ina struct sockaddr_in struct in_addr i ...

  6. 简单了解linux,linux简单了解

    今天主要了解下linux linux目录结构包含: /:代表根目录 bin(binaries):存放二进制可执行文件 sbin(super user binaries):存放二进制可执行文件,只有ro ...

  7. linux barrier,如何决定何时启用Linux文件系统barrier功能?

    大多数当前流行的Linux文件系统,包括EXT3和EXT4,都将文件系统barrier作为一个增强的安全特性.它保护数据不被写入日记.但是,在许多情况下,我们并不清楚这些barrier是否有用.本文就 ...

  8. linux puppy 安装软件,puppy linux(linux操作系统)V5.7.2 官方版

    puppy linux(linux操作系统)是一款十分优秀的全新linux发行系统.平常linux操作系统太过简陋,puppy linux集合了大量所需功能.但它自带了大量的描扫仪.打印机.数码相机的 ...

  9. 什么是Linux?Linux主要用在那?为什么有Linux?

    一,什么是Linux Linux,是一个开放式系统,任何人可以根据它的源码改编,做成你想要的样子(反正就是非常开放) 为什么要开发Linux 这个说来话长,就是一位Windows程序袁,因为不满足Wi ...

最新文章

  1. 网络编程中的注意问题
  2. 【新技术】CentOS系统下docker的安装配置及使用详解
  3. boost::reverse_copy相关的测试程序
  4. 联想服务器支持esxi版本,联想中国(Lenovo China)_服务频道_服务政策
  5. LeetCode 20. 有效的括号 golang(三)
  6. 海量数据库解决方案2011030101
  7. java get set 注解_java技能提升,用Lombok甩掉get和set,让代码变得更简洁
  8. 2017.9.14 星际竞速 失败总结
  9. mysql 5.6 ddl 锁表_MySQL数据库之MySQL5.6 Online DDL 是否锁表、rebuild表、inplace的说明...
  10. 搭建servlet+jsp环境
  11. NumPy库---数组进阶操作
  12. CREO产品柔性建模 参数化 模具 TOP DOWN设计
  13. 人月到底有多少神话色彩
  14. python matplotlib cannot import name ‘artist‘ from ‘matplotlib‘
  15. mysql安装apply_MySQL安装过程中出现“APPLY security settings错误”的解决方式
  16. SUMIF 和 SUMIFS
  17. PWM调光频率0.1-20KHz以内,共阳极控制高辉无频闪LED车灯调光电源驱动芯片方案FP7125/FP7122/FP7123
  18. 用 顶部tab栏 做排班表
  19. MySQL之账号管理、建库以及四大引擎
  20. 中国一些著名网站的主题颜色

热门文章

  1. x2检验(chi-square test)/ 卡方检验
  2. 高一数学知识点复习:命题及其关系、充分条件
  3. 在b站上跟着沐神学习深度学习
  4. Github:this exceeds GitHub‘s file size limit of 100.00 MB
  5. PERCENT(SQL)
  6. 【学习笔记】到底是谁先开枪?——网络游戏同步机制初探
  7. 计算机网络谢希仁课后习题
  8. 性格色彩测试android程序开发之七--测试题模块dialog的实现
  9. VINS-FUSION GPS融合坐标转换细节分析
  10. Ubuntu16.04LTS学习笔记