linux i o请求过程,Linux I/O Block--递交I/O请求

可以看到这里将bio的参考对象设置为了主设备,而不是分区,因此对应的扇区起始号也要计算为扇区的绝对值。

大多数的make_request_fn函数都可以直接定义为__make_request(),我们通过这个函数来分析递交bio的关键操作

static int __make_request(struct request_queue *q, struct bio *bio)

{

struct request *req;

int el_ret;

unsigned int bytes = bio->bi_size;

const unsigned short prio = bio_prio(bio);

const bool sync = bio_rw_flagged(bio, BIO_RW_SYNCIO);

const bool unplug = bio_rw_flagged(bio, BIO_RW_UNPLUG);

const unsigned int ff = bio->bi_rw & REQ_FAILFAST_MASK;

int rw_flags;

/*如果BIO_RW_BARRIER被置位(表示必须得让请求队列中的所有bio传递完毕才处理自己),

但是不支持hardbarrier,不能进行bio的提交*/

if (bio_rw_flagged(bio, BIO_RW_BARRIER) &&

(q->next_ordered == QUEUE_ORDERED_NONE)) {

bio_endio(bio, -EOPNOTSUPP);

return 0;

}

/*

* low level driver can indicate that it wants pages above a

* certain limit bounced to low memory (ie for highmem, or even

* ISA dma in theory)

*/

blk_queue_bounce(q, &bio);

spin_lock_irq(q->queue_lock);

//如果BIO_RW_BARRIER被置位或者请求队列为空,则情况比较简单,不用进行bio的合并,跳转到get_rq处处理

if (unlikely(bio_rw_flagged(bio, BIO_RW_BARRIER)) || elv_queue_empty(q))

goto get_rq;

/**请求队列不为空**/

/*elv_merge()试图寻找一个已存在的request,将bio并入其中*/

el_ret = elv_merge(q, &req, bio);

switch (el_ret) {

case ELEVATOR_BACK_MERGE:

BUG_ON(!rq_mergeable(req));

/*相关检查*/

if (!ll_back_merge_fn(q, req, bio))

break;

trace_block_bio_backmerge(q, bio);

if ((req->cmd_flags & REQ_FAILFAST_MASK) != ff)

blk_rq_set_mixed_merge(req);

/*这里将bio插入到request尾部*/

req->biotail->bi_next = bio;

req->biotail = bio;

req->__data_len += bytes;

req->ioprio = ioprio_best(req->ioprio, prio);

if (!blk_rq_cpu_valid(req))

req->cpu = bio->bi_comp_cpu;

drive_stat_acct(req, 0);

if (!attempt_back_merge(q, req))

elv_merged_request(q, req, el_ret);

goto out;

case ELEVATOR_FRONT_MERGE:

BUG_ON(!rq_mergeable(req));

if (!ll_front_merge_fn(q, req, bio))

break;

trace_block_bio_frontmerge(q, bio);

if ((req->cmd_flags & REQ_FAILFAST_MASK) != ff) {

blk_rq_set_mixed_merge(req);

req->cmd_flags &= ~REQ_FAILFAST_MASK;

req->cmd_flags |= ff;

}

/*这里将bio插入到request的头部*/

bio->bi_next = req->bio;

req->bio = bio;

/*

* may not be valid. if the low level driver said

* it didn't need a bounce buffer then it better

* not touch req->buffer either...

*/

req->buffer = bio_data(bio);

req->__sector = bio->bi_sector;

req->__data_len += bytes;

req->ioprio = ioprio_best(req->ioprio, prio);

if (!blk_rq_cpu_valid(req))

req->cpu = bio->bi_comp_cpu;

drive_stat_acct(req, 0);

if (!attempt_front_merge(q, req))

elv_merged_request(q, req, el_ret);

goto out;

/* ELV_NO_MERGE: elevator says don't/can't merge. */

default:

;

}

get_rq:/**下面的代码对应请求队列为空的情况,需要先分配一个request,再将bio插入***/

/*

* This sync check and mask will be re-done in init_request_from_bio(),

* but we need to set it earlier to expose the sync flag to the

* rq allocator and io schedulers.

*/

rw_flags = bio_data_dir(bio);//确定读写标识

if (sync)

rw_flags |= REQ_RW_SYNC;

/*

* Grab a free request. This is might sleep but can not fail.

* Returns with the queue unlocked.

*/

req = get_request_wait(q, rw_flags, bio);//分配一个新的request

/*

* After dropping the lock and possibly sleeping here, our request

* may now be mergeable after it had proven unmergeable (above).

* We don't worry about that case for efficiency. It won't happen

* often, and the elevators are able to handle it.

*/

//根据bio初始化新分配的request,并将bio插入到request中

init_request_from_bio(req, bio);

spin_lock_irq(q->queue_lock);

if (test_bit(QUEUE_FLAG_SAME_COMP, &q->queue_flags) ||

bio_flagged(bio, BIO_CPU_AFFINE))

req->cpu = blk_cpu_to_group(smp_processor_id());

if (queue_should_plug(q) && elv_queue_empty(q))

blk_plug_device(q);

add_request(q, req);//将request插入到请求队列

out:

if (unplug || !queue_should_plug(q))

__generic_unplug_device(q);

spin_unlock_irq(q->queue_lock);

return 0;

}0b1331709591d260c1c78e86d0c51c18.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值