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         int dirty_parity_disks = 0;
5312         struct md_rdev *rdev;
5313         sector_t reshape_offset = 0;
5314         int i;
5315         long long min_offset_diff = 0;
5316         int first = 1;
...
5426         if (mddev->private == NULL)
5427                 conf = setup_conf(mddev);
5428         else
5429                 conf = mddev->private;
5430
5431         if (IS_ERR(conf))
5432                 return PTR_ERR(conf);
5433
5434         conf->min_offset_diff = min_offset_diff;
5435         mddev->thread = conf->thread;
5436         conf->thread = NULL;
5437         mddev->private = conf;
...
5491         /*
5492          * 0 for a fully functional array, 1 or 2 for a degraded array.
5493          */
5494         mddev->degraded = calc_degraded(conf);
...
5503         /* device size must be a multiple of chunk size */
5504         mddev->dev_sectors &= ~(mddev->chunk_sectors - 1);
5505         mddev->resync_max_sectors = mddev->dev_sectors;
...
5556         md_set_array_sectors(mddev, raid5_size(mddev, 0, 0));
5557
5558         if (mddev->queue) {
...
5628         }
5629
5630         return 0;

是不是感觉超级简单呢,就像有些事情表面上看起来很复杂,但只要认真地去分析之后发现其实是有规律可循的。就像这个run函数,做的事情与raid1的run是相同的,就是建立读写的上下文环境。

5427行,创建struct r5conf,跟进函数:

5131 static struct r5conf *setup_conf(struct mddev *mddev)
5132 {
5133         struct r5conf *conf;
5134         int raid_disk, memory, max_disks;
5135         struct md_rdev *rdev;
5136         struct disk_info *disk;
5137         char pers_name[6];
5138
5139         if (mddev->new_level != 5
5140             && mddev->new_level != 4
5141             && mddev->new_level != 6) {
5142                 printk(KERN_ERR "md/raid:%s: raid level not set to 4/5/6 (%d)\n",
5143                        mdname(mddev), mddev->new_level);
5144                 return ERR_PTR(-EIO);
5145         }
5146         if ((mddev->new_level == 5
5147              && !algorithm_valid_raid5(mddev->new_layout)) ||
5148             (mddev->new_level == 6
5149              && !algorithm_valid_raid6(mddev->new_layout))) {
5150                 printk(KERN_ERR "md/raid:%s: layout %d not supported\n",
5151                        mdname(mddev), mddev->new_layout);
5152                 return ERR_PTR(-EIO);
5153         }
5154         if (mddev->new_level == 6 && mddev->raid_disks < 4) {
5155                 printk(KERN_ERR "md/raid:%s: not enough configured devices (%d, minimum 4)\n",
5156                        mdname(mddev), mddev->raid_disks);
5157                 return ERR_PTR(-EINVAL);
5158         }
5159
5160         if (!mddev->new_chunk_sectors ||
5161             (mddev->new_chunk_sectors << 9) % PAGE_SIZE ||
5162             !is_power_of_2(mddev->new_chunk_sectors)) {
5163                 printk(KERN_ERR "md/raid:%s: invalid chunk size %d\n",
5164                        mdname(mddev), mddev->new_chunk_sectors << 9);
5165                 return ERR_PTR(-EINVAL);
5166         }
5167
5168         conf = kzalloc(sizeof(struct r5conf), GFP_KERNEL);
5169         if (conf == NULL)
5170                 goto abort;
5171         spin_lock_init(&conf->device_lock);
5172         init_waitqueue_head(&conf->wait_for_stripe);
5173         init_waitqueue_head(&conf->wait_for_overlap);
5174         INIT_LIST_HEAD(&conf->handle_list);
5175         INIT_LIST_HEAD(&conf->hold_list);
5176         INIT_LIST_HEAD(&conf->delayed_list);
5177         INIT_LIST_HEAD(&conf->bitmap_list);
5178         INIT_LIST_HEAD(&conf->inactive_list);
5179         atomic_set(&conf->active_stripes, 0);
5180         atomic_set(&conf->preread_active_stripes, 0);
5181         atomic_set(&conf->active_aligned_reads, 0);
5182         conf->bypass_threshold = BYPASS_THRESHOLD;
5183         conf->recovery_disabled = mddev->recovery_disabled - 1;
5184
5185         conf->raid_disks = mddev->raid_disks;
5186         if (mddev->reshape_position == MaxSector)
5187                 conf->previous_raid_disks = mddev->raid_disks;
5188         else
5189                 conf->previous_raid_disks = mddev->raid_disks - mddev->delta_disks;
5190         max_disks = max(conf->raid_disks, conf->previous_raid_disks);
5191         conf->scribble_len = scribble_len(max_disks);
5192
5193         conf->disks = kzalloc(max_disks * sizeof(struct disk_info),
5194                               GFP_KERNEL);
5195         if (!conf->disks)
5196                 goto abort;
5197
5198         conf->mddev = mddev;
5199
5200         if ((conf->stripe_hashtbl = kzalloc(PAGE_SIZE, GFP_KERNEL)) == NULL)
5201                 goto abort;
5202
5203         conf->level = mddev->new_level;
5204         if (raid5_alloc_percpu(conf) != 0)
5205                 goto abort;
5206
5207         pr_debug("raid456: run(%s) called.\n", mdname(mddev));
5208
5209         rdev_for_each(rdev, mddev) {
5210                 raid_disk = rdev->raid_disk;
5211                 if (raid_disk >= max_disks
5212                     || raid_disk < 0)
5213                         continue;
5214                 disk = conf->disks + raid_disk;
5215
5216                 if (test_bit(Replacement, &rdev->flags)) {
5217                         if (disk->replacement)
5218                                 goto abort;
5219                         disk->replacement = rdev;
5220                 } else {
5221                         if (disk->rdev)
5222                                 goto abort;
5223                         disk->rdev = rdev;
5224                 }
5225
5226                 if (test_bit(In_sync, &rdev->flags)) {
5227                         char b[BDEVNAME_SIZE];
5228                         printk(KERN_INFO "md/raid:%s: device %s operational as raid"
5229                                " disk %d\n",
5230                                mdname(mddev), bdevname(rdev->bdev, b), raid_disk);
5231                 } else if (rdev->saved_raid_disk != raid_disk)
5232                         /* Cannot rely on bitmap to complete recovery */
5233                         conf->fullsync = 1;
5234         }
5235
5236         conf->chunk_sectors = mddev->new_chunk_sectors;
5237         conf->level = mddev->new_level;
5238         if (conf->level == 6)
5239                 conf->max_degraded = 2;
5240         else
5241                 conf->max_degraded = 1;
5242         conf->algorithm = mddev->new_layout;
5243         conf->max_nr_stripes = NR_STRIPES;
5244         conf->reshape_progress = mddev->reshape_position;
5245         if (conf->reshape_progress != MaxSector) {
5246                 conf->prev_chunk_sectors = mddev->chunk_sectors;
5247                 conf->prev_algo = mddev->layout;
5248         }
5249
5250         memory = conf->max_nr_stripes * (sizeof(struct stripe_head) +
5251                  max_disks * ((sizeof(struct bio) + PAGE_SIZE))) / 1024;
5252         if (grow_stripes(conf, conf->max_nr_stripes)) {
5253                 printk(KERN_ERR  

5254                        "md/raid:%s: couldn't allocate %dkB for buffers\n",
5255                        mdname(mddev), memory);
5256                 goto abort;
5257         } else
5258                 printk(KERN_INFO "md/raid:%s: allocated %dkB\n",
5259                        mdname(mddev), memory);
5260
5261         sprintf(pers_name, "raid%d", mddev->new_level);
5262         conf->thread = md_register_thread(raid5d, mddev, pers_name);
5263         if (!conf->thread) {
5264                 printk(KERN_ERR
5265                        "md/raid:%s: couldn't allocate thread.\n",
5266                        mdname(mddev));
5267                 goto abort;
5268         }
5269
5270         return conf;

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索struct
, conf
, is_err
, if
, raid
printk
raid磁盘阵列、raid阵列、raid磁盘阵列教程、raid阵列卡、磁盘阵列raid5,以便于您获取更多的相关知识。

时间: 2024-08-03 01:40:33

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

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

raid10的run函数与raid5的run函数最大区别在于setup_conf,那就直接深入核心: 3540 static struct r10conf *setup_conf(struct mddev *mddev) 3541 { 3542 struct r10conf *conf = NULL; 3543 int err = -EINVAL; 3544 struct geom geo; 3545 int copies; 3546 3547 copies = setup_geo(&geo,

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源代码解读 八 阵列同步二:同步过程

在上一小节里讲到启动同步线程: 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模块初始化

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

linux内核md源代码解读 一

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

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源代码解读 十二 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一直保持着稳健的增长,但丝

linux内核md源代码解读 十一 raid5d

正是有了上一篇的读写基础,我们才开始看raid5d的代码.raid5d不是读写的入口,也不是读写处理的地方,只是简简单单的中转站或者叫做交通枢纽.这个枢纽具有制高点的作用,就像美国在新加坡的基地,直接就控制了太平洋和印度洋的交通枢纽. 4626 /* 4627 * This is our raid5 kernel thread. 4628 * 4629 * We scan the hash table for stripes which can be handled now. 4630 * Du