加入收藏 | 设为首页 | 会员中心 | 我要投稿 应用网_镇江站长网 (https://www.0511zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

linux内核md源代码解读 十二 raid读写 - Linux系统

发布时间:2014-03-24 10:21:10 所属栏目:Linux 来源:站长网
导读:我们都知道,对一个linux块设备来说,都有一个对应的请求队列。注册在这个请求队列上的请求就是该块设备的请求入口。对于raid来说,分配struct mddev时就已经设
我们都知道,对一个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一直保持着稳健的增长,但丝毫也阻挡不了我们看代码的慧眼,在成千上万行的代码里我们依然能够迅速地找出raid读写入口就是md_make_request。

328/* Rather than calling directly into the personality make_request function,  
329 * IO requests come here first so that we can check if the device is  
330 * being suspended pending a reconfiguration.  
331 * We hold a refcount over the call to ->make_request.  By the time that  
332 * call has finished, the bio has been linked into some internal structure  
333 * and so is visible to ->quiesce(), so we don't need the refcount any more.  
334 */

我们在调用make_request函数之前,先检查设备是否因为重配置而挂起。在调用make_request函数之前,我们增加设备的引用计数,在make_request调用完成时再递减。增加设备引用计数主要是为调用->quiesce()之前保证下发到设备的IO已经完成。

335static void md_make_request(struct request_queue *q, struct bio *bio)  
336{  
337     const int rw = bio_data_dir(bio);  
338     struct mddev *mddev = q->queuedata;  
339     int cpu;  
340     unsigned int sectors;  
341  
342     if (mddev == NULL || mddev->pers == NULL  
343         || !mddev->ready) {  
344          bio_io_error(bio);  
345          return;  
346     }  
347     smp_rmb(); /* Ensure implications of  'active' are visible */
348     rcu_read_lock();  
349     if (mddev->suspended) {  
350          DEFINE_WAIT(__wait);  
351          for (;;) {  
352               prepare_to_wait(&mddev->sb_wait, &__wait,  
353                         TASK_UNINTERRUPTIBLE);  
354               if (!mddev->suspended)  
355                    break;  
356               rcu_read_unlock();  
357               schedule();  
358               rcu_read_lock();  
359          }  
360          finish_wait(&mddev->sb_wait, &__wait);  
361     }  
362     atomic_inc(&mddev->active_io);  
363     rcu_read_unlock();  
364  
365     /* 
366     * save the sectors now since our bio can 
367     * go away inside make_request 
368     */
369     sectors = bio_sectors(bio);  
370     mddev->pers->make_request(mddev, bio);  
371  
372     cpu = part_stat_lock();  
373     part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]);  
374     part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw], sectors);  
375     part_stat_unlock();  
376  
377     if (atomic_dec_and_test(&mddev->active_io) && mddev->suspended)  
378          wake_up(&mddev->sb_wait);  
379}

337行,获取IO方向,用于设备信息统计

338行,获取阵列指针,该指针是在md_alloc中赋值的

342行,基本检查

348行,访问struct mddev信息加rcu读锁

349行,阵列suspend

350行,如果阵列suspend,即前面注释中讲的正在重配置,则加入sb_wait等待队列

360行,阵列完成suspend,从等待队列中移除

362行,递增阵列引用计数,在前面注释里有原因说明

370行,下发bio到阵列

372行,这个开始是信息统计

377行,递减阵列引用计数,如果正在重配置,则唤醒该进程

真正的数据通道命令也就370行这一句,其他的都是控制通道的。

对于raid5阵列,这个请求函数对应的是raid5.c中的make_request函数:

(编辑:应用网_镇江站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!