blk_queue_bio函数学习

blk_queue_bio函数学习

//块设备排入bio请求函数 
//该接口作为通用的块设备处理bio请求的方式,主要思路是尽可能的将bio合并request中或者生成新的request。 

static blk_qc_t blk_queue_bio(struct request_queue *q, struct bio *bio)
{
    
    //(1)首先尝试在plug链表中寻找能够与该bio合并的request,
    //如果能够合并则合并后返回;
    //如果不能合并入plug队列则继续去调度队列中寻找合并机会
    if (!blk_queue_nomerges(q)) {
		if (blk_attempt_plug_merge(q, bio, &request_count, NULL))
			return BLK_QC_T_NONE;
	} else
		request_count = blk_plug_queued_count(q);
    spin_lock_irq(q->queue_lock);
  
    //(2)第二步尝试将bio合并到调度队列的request中去
	switch (elv_merge(q, &req, bio)) {//寻找能够合并的request并返回合并类型是向前合并还是向后合并
	case ELEVATOR_BACK_MERGE://向后合并
		if (!bio_attempt_back_merge(q, req, bio))
			break;
		elv_bio_merged(q, req, bio);
		free = attempt_back_merge(q, req);
		if (free)
			__blk_put_request(q, free);
		else
			elv_merged_request(q, req, ELEVATOR_BACK_MERGE);
		goto out_unlock;
	case ELEVATOR_FRONT_MERGE://向前合并
		if (!bio_attempt_front_merge(q, req, bio))
			break;
		elv_bio_merged(q, req, bio);
		free = attempt_front_merge(q, req);
		if (free)
			__blk_put_request(q, free);
		else
			elv_merged_request(q, req, ELEVATOR_FRONT_MERGE);
		goto out_unlock;
	default:
		break;
	}
    //(3)如果bio在上面两种合并过程中均未找到能够合并的request,那么只能新申请一个空的request并将其初始化,将bio放在新申请的request中随后放入plug队列;
    ....
    //此处省略了申请新的request代码
    
	plug = current->plug;
    //判断是否启动了蓄流机制,如果启用则将新建立的request加入到plug list中;
	if (plug) {
		/*
		 * If this is the first request added after a plug, fire
		 * of a plug trace.
		 *
		 * @request_count may become stale because of schedule
		 * out, so check plug list again.
		 */
		if (!request_count || list_empty(&plug->list))
			trace_block_plug(q);
		else {
			struct request *last = list_entry_rq(plug->list.prev);
			if (request_count >= BLK_MAX_REQUEST_COUNT ||
			    blk_rq_bytes(last) >= BLK_PLUG_FLUSH_SIZE) {
                //判断plug lsit中的request数量是否满了,满了的话就启动泄流;
                blk_flush_plug_list(plug, false);
				trace_block_plug(q);
			}
		}
		list_add_tail(&req->queuelist, &plug->list);
		blk_account_io_start(req, true);
	} else {
        //如果没有开启plug机制,则将request直接加入到调度队列
        spin_lock_irq(q->queue_lock);
		add_acct_request(q, req, where);//默认where=ELEVATOR_INSERT_SORT
		__blk_run_queue(q);//最差的一种情况,无法合并,也没有开启plug,那么加入到调度器后,有一次通知驱动执行request_fn函数从派发队列中拿取一个request进行处理 
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值