RAID-5(三)简单的读写

这是一篇关于RAID-5技术的博客,讲述了如何进行简单的读操作。内容可能较旧,但仍有其价值。作者决定将这篇原创文章从社交平台迁移至专业博客,以便更好地分享和帮助他人理解RAID-5的读写机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这些文章已经写了好几年了,可能已经过时了。在MSN space和QQzone几经辗转之后,我想也许这些技术文章还是放在搞技术的博客中更能帮助人。于是做了一个艰难的决定,把这些文章一篇篇搬过来!绝对是原创的。

 

一次简单的读处理


这一切都是从make_request开始的。make_request的其中一个参数就是bio,至于一个bio是怎么送到make_request中的,这与块设备驱动内容相关,具体内容可以查看LDD3和ULK3,你或者可以从block/ll_rw_blk.c的generic_make_request函数开始寻找答案。
在make_request中,我们首先需要知道这个bio是要读哪个stripe的哪个dev。这些信息从raid5_compute_sector函数中获得。这两个信息就被放在new_sector和dd_idx中,根据new_sector信息,我们调用get_active_stripe取出一个 stripe_head即sh来处理这次读请求,根据dd_idx信息,我们调用add_stripe_bio将bio放入相应的dev,也就是放入 sh->dev[dd_idx].toread链表。
到此,就可以将sh送入handle_stripe函数中作第一轮处理。既然说是一次简单的读请求,那么我们忽略掉部分复杂的处理。在 handle_stripe中,看到相应dev的toread链表有请求,而且这个dev状态为Empty,我们就会将本dev标记为Want,最后将这 个dev的req标记为读请求通过generic_make_request送交下层disk处理。还记得么,Empty状态,Want状态,req在前面已经介绍过了。请注意,在送到下层之前req的bi_rw标记为读以外还将其bi_end_io这个callback设为 raid5_end_read_request。就这样第一轮的handle_stripe结束,这个sh也被放入handle_list等待第二轮处理。在make_request中,可以看到这些动作都处在一个循环之中,关于这个循环的作用暂且先放一放。
下层完成读操作后,raid5_end_read_requset被调用,读成功的话,则这个dev状态转为Clean,而RAID-5的守护线程 raid5d被唤醒。在raid5d中handle_stripe再次被调用对这个sh做第二轮处理。这次handle_stripe一看到相应的dev已经为Clean状态,则将缓冲页中的数据copy到bio的相应页中,最终等整个bio的数据都完备了,则调用这个bio的bi_end_io来通知上层I/O完成。
如此这般,一次简单的读请求处理完毕。


一次简单的写处理
写处理相对于读则更加复杂,因为除了正常的数据以外还要计算及写入校验数据。
写处理也是从make_request开始的,前面读处理中描述的get_active_stripe和add_stripe_bio在写处理中也是一样的,唯一的区别是bio将被放入dev的towrite链表。接着sh被送入handle_stripe处理。
为了简化起见,我们假设这次sh中要处理只有一个写bio,而且这次写的内容覆盖了整个dev的缓冲区页。handle_stripe首先需要决定是要做 read-modify-write(rmw)还是reconstruct-write(rcw)。这两个概念以后会解释。根据我们的假设,这里rmw的 可能性更高,所以我按rmw来解释。于是如果这个有towrite的dev和parity的dev的状态仍为Empty,handle_stripe就会将它们状态转为Want。大家如果看代码,这里会看到只有在这个sh状态为STRIPE_PREREAD_ACTIVE才会将dev由Empty转为 Want,这是RAID-5中一个巧妙的地方,这里我们只是假设sh的状态已经符合条件。接下了这些dev的req被作为读请求送到下层设备,第一轮的 handle_stripe处理就此结束。
接下来,下层处理完毕,两个dev的状态转为Clean,raid5d被唤醒对这个sh进行第二轮处理。这一轮处理最重要的就是 compute_parity这个函数,此时compute_parity所做的事情跟我在RAID-5原理中的叙述一样。在 compute_parity中,bio的相应页的内容被copy到dev的缓冲页中,校验dev的页内数据也是最新的了,而且bio也从towrite 链转入written链。它们的状态被设为Dirty,并在最后它们的req作为写请求送到下层设备。
下层写完成之后,callback函数raid5_end_write_request被调用,dev的状态由Dirty转为Clean。raid5再次醒来对这个sh做第三轮处理。这一轮处理非常简单,看到数据dev和校验dev状态均为Clean,就可以调用bio的bi_end_io通知上层本次写请 求完成。

make_request是一切处理的源头,请看下一集:)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值