linux内核md源代码解读 九 阵列raid5同步函数sync_reque

欢迎使用ueditor!

我们再来回顾一下整个场景:

1)在运行阵列的时候调用md_wakeup_thread唤醒主线程

2)主线程调用md_check_recovery检查同步
3)md_check_recovery函数中检查需要同步调用md_register_thread创建同步线程

4)同步线程调用md_do_sync函数处理同步过程

5)md_do_sync做同步过程的管理,一步步推同步点,记录同步完成点,调用sync_request进行各种阵列级别的同步

6)sync_request做同步数据流的派发工作

对于raid5阵列来说,同步是按struct stripe_head为基本单位进行派发的。打个比方,我们现在要把一个土豆炸成薯片,这时首先要把土豆切成片,再把土豆片放到油锅里炸,炸开了再捞起来装盒。那么md_do_sync的作用就相当于把土豆切片,这个切片的大小也就是STRIPE_SECTORS大小了。sync_request接收到这个土豆片之后不能立即下锅,要用struct stripe_head把它包装一下,这就类似要在土豆片外面刷一层调料。然后再调用handle_stripe进行处理并最终下发到磁盘,这就类似于把土豆片放在锅里油炸加工的过程。最后调用bitmap_cond_end_sync保存同步完成记录,这就类似回收土豆片并盒装。

这里还有一个细节,就是为了周期性保存同步结果,每隔几秒钟都会等待所有同步请求返回再记录下来。这就类似于这个炸土豆的锅很小,一次只能放20片土豆,一开始我们不停的放薯片,等放满20片,我们就停下来直接到所有土豆都熟了然后一次性打捞上来,然后再放20片,重复上面的过程。

理解上以上的处理机制,再看代码就非常容易了。

4453 static inline sector_t sync_request(struct mddev *mddev, sector_t sector_nr, int *skipped, int go_faster)
4454 {
4455         struct r5conf *conf = mddev->private;
4456         struct stripe_head *sh;
4457         sector_t max_sector = mddev->dev_sectors;
4458         sector_t sync_blocks;
4459         int still_degraded = 0;
4460         int i;
4461
4462         if (sector_nr >= max_sector) {
4463                 /* just being told to finish up .. nothing much to do */
4464
4465                 if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) {
4466                         end_reshape(conf);
4467                         return 0;
4468                 }
4469
4470                 if (mddev->curr_resync < max_sector) /* aborted */
4471                         bitmap_end_sync(mddev->bitmap, mddev->curr_resync,
4472                                         &sync_blocks, 1);
4473                 else /* completed sync */
4474                         conf->fullsync = 0;
4475                 bitmap_close_sync(mddev->bitmap);
4476
4477                 return 0;
4478         }

这一部分是处理同步完成的,同步完成有两种情况,一种是正常完成的,另一种是被中断的。

4462行,同步完成。

4470行,同步中断,通知bitmap最后一次同步是abort

4474行,同步成功完成,更新fullsync为0,fullsync表示阵列要强制完全同步。

4475行,通知bitmap同步完成。

虽然这部分代码是放在函数比较靠前的位置,但是这部分代码是在md_do_sync退出同步循环之后的7521行的sync_request调用到的。接下来这部分才是md_do_sync循环中sync_request会执行到的部分:

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索struct
, 线程
, 函数
, ueditor
, 同步
, 阵列
, 土豆
, 代码同步
, sync ocket
, sync
, nvoke sync
同步调用
raid磁盘阵列、raid阵列、raid磁盘阵列教程、raid阵列卡、磁盘阵列raid5,以便于您获取更多的相关知识。

时间: 2024-11-13 00:03:50

linux内核md源代码解读 九 阵列raid5同步函数sync_reque的相关文章

linux内核md源代码解读 八 阵列同步二:同步过程

在上一小节里讲到启动同步线程: 7824 mddev->sync_thread = md_register_thread(md_do_sync, 7825 mddev, 7826 "resync"); md_register_thread函数如下: 6697 struct md_thread *md_register_thread(void (*run) (struct mddev *), struct mddev *mddev, 6698 const char *name) 6

linux内核md源代码解读 三 阵列创建的过程

这一节我们阅读阵列的创建过程. 按照常理出牌,我们到ioctl中找阵列创建命令,md对应的ioctl函数是md_ioctl,当找对应的cmd命令字时,却完全没有类似CREATE_ARRAY的命令,那么就说明md设备并不是通过ioctl函数来创建的.其实如果我们仔细阅读一下md_ioctl函数的原型就会发现其实创建md设备根本就不在这个地方,函数原型如下: 6303 static int md_ioctl(struct block_device *bdev, fmode_t mode, 6304

linux内核md源代码解读 七 阵列同步一 :介绍阵列同步

阵列同步在md_do_sync,那么入口在哪里呢?就是说阵列同步触发点在哪里呢?听说过md_check_recovery吧,但这还不是同步的入口点.那raid5d函数是入口点吧?如果要认真分析起来还不算是. 真正的同步入口点在do_md_run函数,就是在运行阵列run函数之后,有这么一行: 5171         md_wakeup_thread(mddev->thread); 是这一行把raid5d唤醒的,raid5d函数如下: 4823 static void raid5d(struct

linux内核md源代码解读 二 md模块初始化

在编译完成linux内核源代码的时候,drivers/md目录下会生成多个ko文件,那么这些内核模块哪一个先加载,哪一个后加载的呢?例如md-mod.ko, raid5.ko, raid10.ko,这些模块是一起加载的呢,还是有先后顺序呢?如果熟悉linux内核编程的话,知道有一个request_module函数,这个函数用于请求加载一个模块,但这个函数并不能说明一个模块对另一个模块的依赖关系.准确的信息还是来自于Kconfig,这里只抽取Kconfig中相关的部分: config BLK_DE

linux内核md源代码解读 十 raid5数据流之同步数据流程

上一节讲到在raid5的同步函数sync_request中炸土豆片是通过handle_stripe来进行的.从最初的创建阵列,到申请各种资源,建立每个阵列的personality,所有的一切都是为了迎接数据流而作的准备.就像我们寒窗苦读就是为了上大学一样.数据流的过程就像大学校园一样丰富多彩并且富有挑战性,但只要跨过了这道坎,内核代码将不再神秘,剩下的问题只是时间而已. 首先看handle_stripe究竟把我们的土豆片带往何处: 3379 static void handle_stripe(s

linux内核md源代码解读 十三 raid5重试读

上节我们讲到条块内读失败,在回调函数raid5_align_endio中将请求加入阵列重试链表,在唤醒raid5d线程之后,raid5d线程将该请求调用retry_aligned_read函数进行重试读: 4539static int retry_aligned_read(struct r5conf *conf, struct bio *raid_bio) 4540{ 4541 /* We may not be able to submit a whole bio at once as ther

linux内核md源代码解读 五 介绍raidd5阵列的运行

如果看懂了raid1阵列的run函数,那么看raid5阵列run就非常轻松了,因为两者要做的事情都是大同小异. raid5的run函数很长,但很大一部分跟创建运行是没有关系的,特别是有一段跟reshape相关的,大多数系统都不关注该功能,因此可以直接跳过.经过删减之后的run函数如下: 5307 static int run(struct mddev *mddev) 5308 { 5309 struct r5conf *conf; 5310 int working_disks = 0; 5311

linux内核md源代码解读 一

最近花了一段时间认真地学习了一下md代码,并且在原代码的基础上开发了一系列的新功能,这些新功能让md更完善.更适合于企业大容量存储,通过增加阵列缓存和bitmap优化大大提升了存储速度,提高了数据的可靠性,在任何掉电的情况下保证数据一致性,超级块异常情况下完全不影响阵列使用,完全控制了踢盘问题,简化了用户操作.简单地概括一下,就是让存储不再有门槛.说了这么多,其实想表达的意思就是md的学习之路并非十分顺利,特此写此博文与所有兄弟姐妹们共享一下我的学习经验,如果您看完之后能有所收获,那就不枉费我下

linux内核md源代码解读 十二 raid读写

我们都知道,对一个linux块设备来说,都有一个对应的请求队列.注册在这个请求队列上的请求就是该块设备的请求入口.对于raid来说,分配struct mddev时就已经设置好了,在函数md_alloc中有这样的代码: 4846 blk_queue_make_request(mddev->queue, md_make_request); 4847 blk_set_stacking_limits(&mddev->queue->limits); 虽然全国的PM一直保持着稳健的增长,但丝