1.5.6 真实的I/O调度层处理
现在我们块设备也有了,队列也有了,要提交请求也就可以开始提交了。那就让我们回到generic_make_request来研究一下如何提交请求如何处理请求吧。我们看到,函数最后调用q->make_request_fn(q, bio)。对 make_request_fn 函数的调用可以认为是 IO调度层的入口,该函数用于向请求队列中添加请求。该函数是在创建请求队列时指定的,代码如下(blk_init_queue 函数中):
q->request_fn = rfn;
blk_queue_make_request(q, __make_request);
前面看到函数 blk_queue_make_request 将函数 __make_request 的地址赋予了请求队列 q 的 make_request_fn 成员:
void blk_queue_make_request(struct request_queue *q, make_request_fn *mfn) { q->nr_requests = BLKDEV_MAX_RQ; q->make_request_fn = mfn; …… |
那么,__make_request函数才是IO调度层的真实入口,来自block/ll_rw_blk.c:
2846static int __make_request(request_queue_t *q, struct bio *bio) 2847{ 2848 struct request *req; 2849 int el_ret, rw, nr_sectors, cur_nr_sectors, barrier, err, sync; 2850 unsigned short prio; 2851 sector_t sector; 2852 2853 sector = bio->bi_sector; 2854 nr_sectors = bio_sectors(bio); 2855 cur_nr_sectors = bio_cur_sectors(bio); 2856 prio = bio_prio(bio); 2857 2858 rw = bio_data_dir(bio); 2859 sync = bio_sync(bio); 2860 2861 /* 2862 * low level driver can indicate that it wants pages above a 2863 * certain limit bounced to low memory (ie for highmem, or even 2864 * ISA dma in theory) 2865 */ 2866 blk_queue_bounce(q, &bio); 2867 2868 spin_lock_prefetch(q->queue_lock); 2869 2870 barrier = bio_barrier(bio); 2871 if (unlikely(barrier) && (q->next_ordered == QUEUE_ORDERED_NONE)) { 2872 err = -EOPNOTSUPP; 2873 goto end_io; 2874 } 2875 2876 spin_lock_irq(q->queue_lock); 2877 2878 if (unlikely(barrier) || elv_queue_empty(q)) 2879 goto get_rq; 2880 2881 el_ret = elv_merge(q, &req, bio); 2882 switch (el_ret) { 2883 case ELEVATOR_BACK_MERGE: 2884 BUG_ON(!rq_mergeable(req)); 2885 2886 if (!q->back_merge_fn(q, req, bio)) 2887 break; 2888 2889 blk_add_trace_bio(q, bio, BLK_TA_BACKMERGE); 2890 2891 req->biotail->bi_next = bio; 2892 req->biotail = bio; 2893 req->nr_sectors = req->hard_nr_sectors += nr_sectors; 2894 req->ioprio = ioprio_best(req->ioprio, prio); 2895 drive_stat_acct(req, nr_sectors, 0); 2896 if (!attempt_back_merge(q, req)) 2897 elv_merged_request(q, req); 2898 goto out; 2899 2900 case ELEVATOR_FRONT_MERGE: 2901 BUG_ON(!rq_mergeable(req)); 2902 2903 if (!q->front_merge_fn(q, req, bio)) 2904 break; 2905 2906 blk_add_trace_bio(q, bio, BLK_TA_FRONTMERGE); 2907 2908 bio->bi_next = req->bio; 2909 req->bio = bio; 2910 2911 /* 2912 * may not be valid. if the low level driver said 2913 * it didn't need a bounce buffer then it better 2914 * not touch req->buffer either... 2915 */ 2916 req->buffer = bio_data(bio); 2917 req->current_nr_sectors = cur_nr_sectors; 2918 req->hard_cur_sectors = cur_nr_sectors; 2919 req->sector = req->hard_sector = sector; 2920 req->nr_sectors = req->hard_nr_sectors += nr_sectors; 2921 req->ioprio = ioprio_best(req->ioprio, prio); 2922 drive_stat_acct(req, nr_sectors, 0); 2923 if (!attempt_front_merge(q, req)) 2924 elv_merged_request(q, req); 2925 goto out; 2926</ |