发布时间:2014-09-05 17:07:30作者:知识屋
MD在处理读写错误时是不一样的。写数据发生错误时处理较简单,读发生错误时会比较麻烦,它会把读不出来的数据通过计算出来,然后在重新写回磁盘上。首先先看看如何处理写错误的。
1、写数据时发生错误
如果写发生错误,那么回调函数raid5_end_write_request()中bio的BIO_UPTODATE位无效,调用md_error函数将相应的rdev置为Faulty,清除掉In_sync标志,degreded++。唤醒raid5守护进程,如果有spare盘,则进行recovery。这个过程以后再说。设置该条带STRIPE_HANDLE位,继续处理该条带。
在handle_stripe5函数中,首先会统计失效盘的个数failed。对于raid5来说,它是允许一个盘失效的。如果failed>1的话,那么阵列也就失效了。在handle_stripe5中会看到相应的处理-----即满足if (failed > 1 && to_read+to_write+written),对条带中的所有命令均返回失败。
如果只有一个盘失效的话,并且该失效rdev上有非满块的写请求,那么必须读出其他盘上的数据。为什么这样做呢?其实仔细想想就知道了。因为在写数据时要计算校验盘的数据,要保证校验盘数据的正确性,对于失效盘上的非满块写,我们必须知道它的缓冲区中原来的数据,然后再将一部分数据更新到缓冲区中。这样才能保证在写数据的过程中失效盘中缓冲区数据是正确的。而失效盘上的数据需要根据其它盘上的数据计算得到,故要先读取其他盘上的数据。
如果不是非满块写的话,那么我们没必要预读出其他未失效盘上的数据。这时会走到判断做rmw还是rcw的流程中。而对于有失效盘的情况,做rmw显示是不切合实际的。因为做rmw首先要读取有写请求的盘上的数据,而失效盘上的数据又要通过预读其他盘上的数据计算而来,所以这里直接将rmw值置为2*disks。rcw值也为2*disks,这样做的目的是选择rcw做写数据方式。
之后对于非满块写会根据compute_block()计算出失效盘的数据,而满块写则根据rcw方式读出了相应的数据,这时数据都已经准备好了,满足了
if (locked == 0 && (rcw == 0 ||rmw == 0) &&
!test_bit(STRIPE_BIT_DELAY, &sh->state))
判定式,然后compute_parity5计算校验盘信息,将数据写到磁盘上。这里可能会有个疑问,失效盘数据怎么写上去啊?在handle_stripe的末尾,会有如下判断
rcu_read_lock();
rdev = rcu_dereference(conf->disks[i].rdev);
if (rdev && test_bit(Faulty, &rdev->flags))
rdev = NULL;
if (rdev)
atomic_inc(&rdev->nr_pending);
rcu_read_unlock();
这个rcu锁很重要,有兴趣的人可以研究研究。这段代码就会根据rdev的状态设置rdev指针值,如果它是NULL的话就不会下发具体的命令到物理磁盘上。这样写数据发生错误的时候就处理完毕了,下面我们来看看读发生错误的时候。
2、读数据发生错误
和写发生错误一样,读发生错误首先也会在raid5_end_read_request()函数中体现,只不过会重试命令。重试命令之前会做一些检查,比如阵列已经处于降级状态,那么我们没有重试该命令了,这时阵列已经坏了。又比如该设备的发生太多的读取错误,则也不做重试。如果不做重试,则会调用md_error。否则将rdev的状态置为R5_ReadError,重新处理这个条带。
在handle_stripe5函数中,如果是失效盘上有读请求,依旧还是要通过读出其他盘上的数据来计算出该失效盘上的数据。当其他盘数据都读出来的时候,调用compute_block()计算失效盘上的数据,之后便满足
if (failed == 1 && ! conf->mddev->ro &&
test_bit(R5_ReadError, &sh->dev[failed_num].flags)
&& !test_bit(R5_LOCKED, &sh->dev[failed_num].flags)
&& test_bit(R5_UPTODATE, &sh->dev[failed_num].flags)
)
判定式,将rdev状态位R5_ReWrite置为有效,将失效盘数据重新写回磁盘上。
如果rewrite成功,则将数据重新写回磁盘成功,否则想处理写请求失败的情况下处理。
linux一键安装web环境全攻略 在linux系统中怎么一键安装web环境方法
Linux网络基本网络配置方法介绍 如何配置Linux系统的网络方法
Linux下DNS服务器搭建详解 Linux下搭建DNS服务器和配置文件
对Linux进行详细的性能监控的方法 Linux 系统性能监控命令详解
linux系统root密码忘了怎么办 linux忘记root密码后找回密码的方法
Linux基本命令有哪些 Linux系统常用操作命令有哪些
Linux必学的网络操作命令 linux网络操作相关命令汇总
linux系统从入侵到提权的详细过程 linux入侵提权服务器方法技巧
linux系统怎么用命令切换用户登录 Linux切换用户的命令是什么
在linux中添加普通新用户登录 如何在Linux中添加一个新的用户
2012-07-10
CentOS 6.3安装(详细图解教程)
Linux怎么查看网卡驱动?Linux下查看网卡的驱动程序
centos修改主机名命令
Ubuntu或UbuntuKyKin14.04Unity桌面风格与Gnome桌面风格的切换
FEDORA 17中设置TIGERVNC远程访问
StartOS 5.0相关介绍,新型的Linux系统!
解决vSphere Client登录linux版vCenter失败
LINUX最新提权 Exploits Linux Kernel <= 2.6.37
nginx在网站中的7层转发功能