Linux3.10.0块IO子系统流程(1)-- 上层提交请求

Linux通用块层提供给上层的接口函数是submit_bio。上层在构造好bio之后,调用submit_bio提交给通用块层处理。
 
submit_bio函数如下:
 
void submit_bio(int rw, struct bio *bio)
{
    bio->bi_rw |= rw;    //记录读写方式
    /*
     * 执行有数据传输的读写或屏障请求统计,暂不关心
     */
    if (bio_has_data(bio)) {
        unsigned int count;
        if (unlikely(rw & REQ_WRITE_SAME))
            count = bdev_logical_block_size(bio->bi_bdev) >> 9;
        else
            count = bio_sectors(bio);
        if (rw & WRITE) {
            count_vm_events(PGPGOUT, count);
        } else {
            task_io_account_read(bio->bi_size);
            count_vm_events(PGPGIN, count);
        }
        if (unlikely(block_dump)) {
            char b[BDEVNAME_SIZE];
            printk(KERN_DEBUG "%s(%d): %s block %Lu on %s (%u sectors)\n",
            current->comm, task_pid_nr(current),
                (rw & WRITE) ? "WRITE" : "READ",
                (unsigned long long)bio->bi_sector,
                bdevname(bio->bi_bdev, b),
                count);
        }
    }
    //执行真实的IO处理
    generic_make_request(bio);
}
void generic_make_request(struct bio *bio)
{
    struct bio_list bio_list_on_stack;
    if (!generic_make_request_checks(bio))
        return;

    if (current->bio_list) {
        bio_list_add(current->bio_list, bio);
        return;
    }

    BUG_ON(bio->bi_next);
    bio_list_init(&bio_list_on_stack);
    current->bio_list = &bio_list_on_stack;
    do {
        struct request_queue *q = bdev_get_queue(bio->bi_bdev);    //获取bio对应的请求队列
        q->make_request_fn(q, bio);                                //调用请求队列的回调函数来处理IO
        bio = bio_list_pop(current->bio_list);
    } while (bio);
    current->bio_list = NULL; /* deactivate */
}
在调用make_request_fn处理bio的时候,可能会产生新的bio,即make_request_fn会递归调用generic_make_request 最直观的例子就是“栈式块设备”。后续学习device mapper之后补上这段分析。

猜你喜欢

转载自www.cnblogs.com/luxiaodai/p/9254779.html
今日推荐