Raid1的源码的读、写、同步,在本系列博客中都已经分析完成。除了barrier机制要专门拿出来分析(下一篇会写)以外,有一些问题值得思考和注意,分析如下。

1、freeze_array是如何做的?

通过barrier挡住上层用户io请求,并且nr_waiting++计数。nr_pending表示未完成的请求数,nr_queue表示retrylist的r1_bio数量。conf->nr_pending == conf->nr_queued+1表示没有正常的处理请求了,满足这个条件的时候就进行read error的处理;不满足的话,就进行后面的两个处理,之后wait。后面的两个处理是:flush_pending_writes(conf);  raid1_unplug(conf->mddev->queue);第一句的意思是下发raid1层中未下发的所有写请求,第二句的意思是通知下层赶紧unplug下发请求。这里需要注意的是,读请求是在make_request中下发的,是用户上下文,并且nr_pending++也是在make_request中做的;而这里是daemon的上下文,所以只需要通知下层赶紧unplug就可以了。而写请求本来就是需要挂在pending list中由deamon来进行处理的,所以需要第一句下发raid1中还未下发的写请求。

假设一种情景,如果这时又有另外一个或者多个读出错,那么就是将其r1_bio挂到retry list上等待处理,deamon处理retry list链上的r1_bio是逐个进行处理,处理完一个之后才处理下一个,不会有并发产生。也就是说如果有两个读出错,那么需要等待前一个读出错处理流程完全做完之后,才可以做下一个。

另外需要说明的是,这里如果读出错的同一个磁盘位置,正好raid1有写请求还未下发,通知raid1层下发,那么就写了这个位置,当修复读出错位置完成之后,重发这个读请求,那么这次读请求其实是想读旧值,而其实这次读到的是新值,出现一致性问题。Raid1没有保证短时间内对同一个数据块同时读写的一致性,通常这是由上层文件系统层来保证的。

2、读均衡为什么能达到均衡,读均衡算法还有哪些缺陷?

因为当多个读并发的时候,可以尽可能均衡到各个盘中,提高并发读性能,即可以同时读,这样既利用每个盘的带宽提高了整体带宽,又均衡了每个盘的IO负载;而如果多个读是连续的,那么这几个读都落在一块盘上,因为不会发生磁头抖动,进而提高读性能。

但是缺陷还是有的:如果一个读IO很大,也只能选出一个盘作为读盘;更糟糕的是,如果连续多个读IO是顺序读,那么仍然落在一块盘上,导致顺序读性能受限于单盘性能;

解决办法我目前有两种思路:1、条带化,raid0就是这么干;2、bio切分,将大bio切分成小bio,并且限制每个盘的读IO的pending个数。

3in_sync的作用?

       在raid1中有两种in_sync,一种是mddev->in_sync,一种是rdev->flags的In_sync标志位。

mddev->In_sync标志位的作用,超级块中设计一个in_sync标志, 没有IO时,in_sync设置为1,并写回磁盘。 写操作遇到in_sync=1时,则先修改in_sync=0并写回 磁盘之后才执行。

rdev->flag的In_sync位为0,表示该盘不是active disk,不能工作,不可对其操作;In_sync位为1,表示该盘是active disk。

4R1BIO_Returned标志位的作用?

bio_endio之前要进行test_and_set_bit(R1BIO_Returned, &r1_bio->state)来判断是否已经endio了,如果已经endio了,就不再进行bio_endio。R1BIO_Returned标志位的作用就在于此,当设置了延迟写的时候,存在还没有真正将所有盘的写操作完成的时候endio的,所以在真正将所有盘都返回的时候调用raid_end_bio_io(),会出现已经设置R1BIO_Returned的情景,则不需要再endio了。

5IO_BLOCKED标志位的作用?

如果之前读失败的盘为只读状态,在守护进程处理读失败的时候,将r1_bio的该盘bio标记为IO_BLOCKED;接着调用read_balance函数,如果重新指定读盘成功,那么就重发read请求;如果重发的这次read请求还是失败了,同样还是会唤醒守护进程来处理读出错流程,这时又会调用到read_balance函数,而将之前的IO_BLOCKED传入进来,参与到这些流程中。也就是在只读盘上读失败之后,重发读请求,再次读失败的场景会使用到。

6make_request函数中的do_barriersdo_sync变量的作用?

  do_barriers标志接收到的bio的BIO_RW_BARRIER是否置位。如果接收到的上层bio->bi_rw的BIO_RW_BARRIER置位,则为1;BIO_RW_BARRIER不置位,则为0。

  do_barriers有两个用途:

    1、根据do_barriers来设置r1_bio->state的R1BIO_Barrier位;

    2、根据do_barriers来设置要下发的bio的BIO_RW_BARRIER位。

7r1_bioconf结构中都有retry_list,但是r1_bio中没有pending_bio_list,这是为什么?

因为retry_list是由list_head组织起来的链表,其中的每个元素是r1_bio,对于这种组织方式,需要在每个r1_bio中都有一个list_head的结构从而可以找到上一项和下一项,这是一个双向链表;

  而pending_bio_list是由bio组织起来的链表,其中的每个元素直接就是bio,直接用bio->bi_next就可以找到下一项了,这是一个单向链表。

8、为什么用户的read io是在make_request中下发的,而write io是在raid1d中下发的?

因为写io需要修改bitmap,在make_request中先标记一下DRITY位表示需要下刷,而放在deamon中,可以攒集一些write bio用来批量下刷。为了保证正确性,这些write bio在下刷之前要保证bitmap已经下刷到磁盘,所以在批量下刷写之前可以做到bitmap达到批量同步下刷,节省开销。

转载请注明出处:http://www.cnblogs.com/fangpei/

Raid1源代码分析--一些补充的更多相关文章

  1. Raid1源代码分析--开篇总述

    前段时间由于一些事情耽搁了,最近将raid1方面的各流程整理了一遍.网上和书上,能找到关于MD下的raid1的文档资料比较少.决定开始写一个系列的关于raid1的博客,之前写过的一篇读流程也会在之后加 ...

  2. Raid1源代码分析--同步流程

    同步的大流程是先读,后写.所以是分两个阶段,sync_request完成第一个阶段,sync_request_write完成第二个阶段.第一个阶段由MD发起(md_do_sync),第二个阶段由守护进 ...

  3. Raid1源代码分析--Barrier机制

    本想就此结束Raid1的专题博客,但是觉得Raid1中自己构建的一套barrier机制的设计非常巧妙,值得单独拿出来分析.它保证了同步流程和正常读写流程的并发性,也为设备冻结/解冻(freeze/un ...

  4. Raid1源代码分析--写流程

    正确写流程的总体步骤是,raid1接收上层的写bio,申请一个r1_bio结构,将其中的所有bios[]指向该bio.假设盘阵中有N块盘.然后克隆N份上层的bio结构,并分别将每个bios[]指向克隆 ...

  5. Raid1源代码分析--读流程(重新整理)

    五.Raid1读流程分析 两个月前,刚刚接触raid1,就阅读了raid1读流程的代码,那个时候写了一篇博客.现在回过头看看,那篇的错误很多,并且很多地方没有表述清楚.所以还是决定重新写一篇以更正之前 ...

  6. Raid1源代码分析--初始化流程

    初始化流程代码量比较少,也比较简单.主要是run函数.(我阅读的代码的linux内核版本是2.6.32.61) 四.初始化流程分析 run函数顾名思义,很简单这就是在RAID1开始运行时调用,进行一些 ...

  7. Raid1源代码分析--读流程

    这篇博文不足之处较多,重新整理了一下,链接:http://www.cnblogs.com/fangpei/p/3890873.html 我阅读的代码的linux内核版本是2.6.32.61.刚进实验室 ...

  8. 转:SDL2源代码分析

    1:初始化(SDL_Init()) SDL简介 有关SDL的简介在<最简单的视音频播放示例7:SDL2播放RGB/YUV>以及<最简单的视音频播放示例9:SDL2播放PCM>中 ...

  9. 转:RTMPDump源代码分析

    0: 主要函数调用分析 rtmpdump 是一个用来处理 RTMP 流媒体的开源工具包,支持 rtmp://, rtmpt://, rtmpe://, rtmpte://, and rtmps://. ...

随机推荐

  1. java 类加载过程

    1. 使用命令行查看类加载过程,在eclipse测试类的run configuration中配置-verbose:class或者-verbose,如下图所示: 运行结果如下所示: [Opened D: ...

  2. Java 编程的动态性,第 6 部分: 利用 Javassist 进行面向方面的更改--转载

    本系列的 第 4 部分和 第 5 部分讨论了如何用 Javassist 对二进制类进行局部更改.这次您将学习以一种更强大的方式使用该框架,从而充分利用 Javassist 对在字节码中查找所有特定方法 ...

  3. 开发中可能会用到的几个 jQuery 小提示和技巧 (转)

    转自:http://www.cnblogs.com/lhb25/p/useful-jquery-tips-and-tricks.html 今天,我们将分享一些很有用的技巧和窍门给 jQuery 开发人 ...

  4. [转] Makefile的条件执行

    条件语句可以根据一个变量的值来控制make执行或者忽略Makefile的特定部分.条件语句可以是两个不同变量.或者变量和常量值的比较.要注意的是:条件语句只能用于控制make实际执行的makefile ...

  5. java07循环结构

    public class WhileTest { // while循环结构 public static void main(String[] args) { System.out.println(&q ...

  6. CSS 样式属性锦集

    ul#nav > Li 只有一个大于号,是指应用了#nav这个ID的下一级元素的儿子辈Li 元素定义的内容符合这个CSS代码定义的样式,但是孙子辈Li元素定义的内容就不符合这个CSS代码样式了, ...

  7. congos 日期控件的简单使用

    congos 添加html的标签,然后写上js的代码,这段代码的功能是得到前一天的日期. <input type="button" value="查询" ...

  8. 制作ado开发辅助工具类SqlHelper

    public static class SqlHelper { //通过配置文件获取连接字符创 private static readonly string constr = Configuratio ...

  9. java分布式开发,什么是分布式开发

    就是同一个服务,把数据库的不同部分分开建立到不同的服务器上.以缓解数据库大量数据访问的压力.很多大公司的业务量比较大,每天的访问量都达到几百万上千万,甚至上亿的访问量,在访问量不是很大的情况下,是可以 ...

  10. java操作csv文件之javacsv.jar应用

    csv文件是分隔文件,如果使用java的io流来写,比较麻烦,这里为大家提供一个javacsv的jar包,这个很方便操作csv文件. 下载地址:https://pan.baidu.com/s/1i46 ...