我們都知道,對一個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函數: