首页 > 其他分享 >submit_bio

submit_bio

时间:2023-06-01 10:37:51浏览次数:32  
标签:bio request make req list bi submit


/**
 * submit_bio - submit a bio to the block device layer for I/O
 * @bio: The &struct bio which describes the I/O
 *
 * submit_bio() is very similar in purpose to generic_make_request(), and
 * uses that function to do most of the work. Both are fairly rough
 * interfaces; @bio must be presetup and ready for I/O.
 *
 */
blk_qc_t submit_bio(struct bio *bio)
{
	/*
	 * If it's a regular read/write or a barrier with data attached,
	 * go through the normal accounting stuff before submission.
	 */
	if (bio_has_data(bio)) {
		unsigned int count;


		if (unlikely(bio_op(bio) == REQ_OP_WRITE_SAME))
			count = bdev_logical_block_size(bio->bi_bdev) >> 9;
		else
			count = bio_sectors(bio);


		if (op_is_write(bio_op(bio))) {
			count_vm_events(PGPGOUT, count);
		} else {
			task_io_account_read(bio->bi_iter.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),
				op_is_write(bio_op(bio)) ? "WRITE" : "READ",
				(unsigned long long)bio->bi_iter.bi_sector,
				bdevname(bio->bi_bdev, b),
				count);
		}
	}


	return generic_make_request(bio);
}


/**
 * generic_make_request - hand a buffer to its device driver for I/O
 * @bio:  The bio describing the location in memory and on the device.
 *
 * generic_make_request() is used to make I/O requests of block
 * devices. It is passed a &struct bio, which describes the I/O that needs
 * to be done.
 *
 * generic_make_request() does not return any status.  The
 * success/failure status of the request, along with notification of
 * completion, is delivered asynchronously through the bio->bi_end_io
 * function described (one day) else where.
 *
 * The caller of generic_make_request must make sure that bi_io_vec
 * are set to describe the memory buffer, and that bi_dev and bi_sector are
 * set to describe the device address, and the
 * bi_end_io and optionally bi_private are set to describe how
 * completion notification should be signaled.
 *
 * generic_make_request and the drivers it calls may use bi_next if this
 * bio happens to be merged with someone else, and may resubmit the bio to
 * a lower device by calling into generic_make_request recursively, which
 * means the bio should NOT be touched after the call to ->make_request_fn.
 */
blk_qc_t generic_make_request(struct bio *bio)
{
	struct bio_list bio_list_on_stack;
	blk_qc_t ret = BLK_QC_T_NONE;


	if (!generic_make_request_checks(bio))
		goto out;

	/*
	 * We only want one ->make_request_fn to be active at a time, else
	 * stack usage with stacked devices could be a problem.  So use
	 * current->bio_list to keep a list of requests submited by a
	 * make_request_fn function.  current->bio_list is also used as a
	 * flag to say if generic_make_request is currently active in this
	 * task or not.  If it is NULL, then no make_request is active.  If
	 * it is non-NULL, then a make_request is active, and new requests
	 * should be added at the tail
	 */
	if (current->bio_list) {
		bio_list_add(current->bio_list, bio);
		goto out;
	}

	/* following loop may be a bit non-obvious, and so deserves some
	 * explanation.
	 * Before entering the loop, bio->bi_next is NULL (as all callers
	 * ensure that) so we have a list with a single bio.
	 * We pretend that we have just taken it off a longer list, so
	 * we assign bio_list to a pointer to the bio_list_on_stack,
	 * thus initialising the bio_list of new bios to be
	 * added.  ->make_request() may indeed add some more bios
	 * through a recursive call to generic_make_request.  If it
	 * did, we find a non-NULL value in bio_list and re-enter the loop
	 * from the top.  In this case we really did just take the bio
	 * of the top of the list (no pretending) and so remove it from
	 * bio_list, and call into ->make_request() again.
	 */
	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);

		if (likely(blk_queue_enter(q, false) == 0)) {
			ret = q->make_request_fn(q, bio);
			blk_queue_exit(q);
			bio = bio_list_pop(current->bio_list);
		} else {
			struct bio *bio_next = bio_list_pop(current->bio_list);
			bio_io_error(bio);
			bio = bio_next;
		}
	} while (bio);
	current->bio_list = NULL; /* deactivate */

out:
	return ret;
}



static blk_qc_t blk_queue_bio(struct request_queue *q, struct bio *bio)
{
	const bool sync = !!(bio->bi_opf & REQ_SYNC);
	struct blk_plug *plug;
	int el_ret, rw_flags = 0, where = ELEVATOR_INSERT_SORT;
	struct request *req;
	unsigned int request_count = 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);

       blk_queue_split(q, &bio, q->bio_split);


	if (bio_integrity_enabled(bio) && bio_integrity_prep(bio)) {
		bio->bi_error = -EIO;
		bio_endio(bio);
		return BLK_QC_T_NONE;
	}


	if (bio->bi_opf & (REQ_PREFLUSH | REQ_FUA)) {
		spin_lock_irq(q->queue_lock);
		where = ELEVATOR_INSERT_FLUSH;
		goto get_rq;
	}


	/*
	 * Check if we can merge with the plugged list before grabbing
	 * any locks.
	 */
	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);


	el_ret = elv_merge(q, &req, bio);
	if (el_ret == ELEVATOR_BACK_MERGE) {
		if (bio_attempt_back_merge(q, req, bio)) {
			elv_bio_merged(q, req, bio);
			if (!attempt_back_merge(q, req))
				elv_merged_request(q, req, el_ret);
			goto out_unlock;
		}
	} else if (el_ret == ELEVATOR_FRONT_MERGE) {
		if (bio_attempt_front_merge(q, req, bio)) {
			elv_bio_merged(q, req, bio);
			if (!attempt_front_merge(q, req))
				elv_merged_request(q, req, el_ret);
			goto out_unlock;
		}
	}


get_rq:
	/*
	 * 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.
	 */
	if (sync)
		rw_flags |= REQ_SYNC;


	/*
	 * Add in META/PRIO flags, if set, before we get to the IO scheduler
	 */
	rw_flags |= (bio->bi_opf & (REQ_META | REQ_PRIO));


	/*
	 * Grab a free request. This is might sleep but can not fail.
	 * Returns with the queue unlocked.
	 */
	req = get_request(q, bio_data_dir(bio), rw_flags, bio, GFP_NOIO);
	if (IS_ERR(req)) {
		bio->bi_error = PTR_ERR(req);
		bio_endio(bio);
		goto out_unlock;
	}


	/*
	 * 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.
	 */
	init_request_from_bio(req, bio);


	if (test_bit(QUEUE_FLAG_SAME_COMP, &q->queue_flags))
		req->cpu = raw_smp_processor_id();


	plug = current->plug;
	if (plug) {
		/*
		 * If this is the first request added after a plug, fire
		 * of a plug trace.
		 */
		if (!request_count)
			trace_block_plug(q);
		else {
			if (request_count >= BLK_MAX_REQUEST_COUNT) {
				blk_flush_plug_list(plug, false);
				trace_block_plug(q);
			}
		}
		list_add_tail(&req->queuelist, &plug->list);
		blk_account_io_start(req, true);
	} else {
		spin_lock_irq(q->queue_lock);
		add_acct_request(q, req, where);
		__blk_run_queue(q);
out_unlock:
		spin_unlock_irq(q->queue_lock);
	}


	return BLK_QC_T_NONE;
}












标签:bio,request,make,req,list,bi,submit
From: https://blog.51cto.com/u_11860992/6392683

相关文章

  • BioinformaticsMeeting以下是一些生物信息学领域的会议和期刊:
    #BioinformaticsMeeting生物信息学学术会议以下是一些生物信息学领域的会议和期刊: 会议:国际基因组学和基因组医学会议(InternationalConferenceonGenomicsandGenomicMedicine,ICGGM)ACMConferenceonBioinformatics,ComputationalBiology,andHealthInformatic......
  • BIO、NIO、AIO区别详解
    BIO:同步阻塞主线程发起io请求后,需要等待当前io操作完成,才能继续执行。NIO:同步非阻塞引入selector、channel、等概念,当主线程发起io请求后,轮询的查看系统是否准备好执行io操作,没有准备好则主线程不会阻塞会继续执行,准备好主线程会阻塞等待io操作完成。AIO:异步非阻塞主线程发起......
  • 中国生物科技公司【Advanced Biomed】申请纳斯达克IPO上市
    猛兽财经获悉,总部位于台湾台南的生物科技公司【AdvancedBiomed】近期已向美国证券交易委员会(SEC)提交招股书,申请在纳斯达克IPO上市,股票代码为(ADVB)。AdvancedBiomed计划通过此次纳斯达克IPO上市募集1.495亿美元的资金。公司业务总部位于台湾台南的AdvancedBiomed旨在开发一种专......
  • Docker Desktop 错误:必须在BIOS中启用 硬件辅助虚拟化和数据执行保护
    一、检查Hyper-V是否开启控制面板—》程序----》启用或关闭Windows功能二、重装DockerDesktopDocker的安装就不在赘述了,按照官网安装即可,需要注意的是win10家庭版的需要安装WSL2–即linux的虚拟机内核,官网也有详细安装步骤三、重新配置Hyper-V(生效)经过无数次重启,安......
  • java中的BIO NIO AIO有什么区别?
    BIO、NIO和AIO都是Java中用于处理网络编程的技术,它们的主要区别如下:BIO:BIO(BlockingIO)阻塞式IO,指I/O的读写操作是阻塞的。当读写操作发生时,线程被阻塞,一直等到I/O完成才返回。BIO是Java最早的网络编程API,也是最常用的API。BIO的实现简单,易于理解和使用,但是由于阻塞......
  • Ubuntu 18.04 (Bionic) 简单快速的安装mongodb
    按步骤走,不带脑子式安装(注意4.0版本mongodb官方已经不再支持,以下代码中可以修改mongodb版本号安装,目前最新版为6.0,如果懒得改直接用也可以,文章后边第三章第一条代码会直接升级为最新版本mongodb):1.导入包管理系统使用的公钥wget-qO-https://www.mongodb.org/static/pgp/serv......
  • python基础-进程池、submit同异步调用、shutdown参数、ProcessPoolExecutor进程池、进
    转载:(14条消息)python基础-进程池、submit同异步调用、shutdown参数、ProcessPoolExecutor进程池、进程池ftp_pythonsubmit_易辰_的博客-CSDN博客引入进程池在学习线程池之前,我们先看一个例子frommultiprocessingimportProcessimporttimedeftask(name):print(......
  • win10定时开关机(很多地方总结的定时开机不生效),要用主板bios设置才可以
    1.定时关机(可以使用windows中计划任务)1.此电脑右键-->管理-->系统工具-->任务计划程序库-->右侧创建基本任务2.名称:定时关机,触发器:每天,开始时间2023/05/1817:30:00,启动程序:浏览选择C:\Windows\System32\shutdown.exe,参数:-s 2.定时开机(系统中设置开机,肯定不行。......
  • 15、BIO、NIO、AIO 有什么区别?
    (1)同步阻塞BIO一个连接一个线程。JDK1.4之前,建立网络连接的时候采用BIO模式,先在启动服务端socket,然后启动客户端socket,对服务端通信,客户端发送请求后,先判断服务端是否有线程响应,如果没有则会一直等待或者遭到拒绝请求,如果有的话会等待请求结束后才继续执行。(2)同步非阻塞NIONIO......
  • Java网络编程----通过实现简易聊天工具来聊聊BIO
    IO模型即输入输出模型,我们今天主要来聊的是java网络编程中的IO模型---BIO模型。BIO即阻塞式IO,BlockingIOblocking[ˈblɒkɪŋ]v. 堵塞;阻塞;堵住(某人的路等);挡住(某人的视线等);妨碍;阻碍;那究竟什么是阻塞呢?这里的阻塞和多线程并发控制中,对未持有锁的线程进行同步阻......