通用块层学习2 从页高速缓存到通用块层bio的代码流程

submit_bh(int rw, struct buffer_head * bh)
	=>bio = bio_alloc(GFP_NOIO, 1);//申请1个bio
	//初始化bio
	=>bio->bi_sector = bh->b_blocknr * (bh->b_size >> 9);//需要数据传输的起始逻辑扇区号(相对于分区)
	bio->bi_bdev = bh->b_bdev;
	bio->bi_io_vec[0].bv_page = bh->b_page;
	bio->bi_io_vec[0].bv_len = bh->b_size;
	bio->bi_io_vec[0].bv_offset = bh_offset(bh);

	bio->bi_vcnt = 1;//第一个bio只有一个vec,后续加入到集合里面
	bio->bi_idx = 0;
	bio->bi_size = bh->b_size;//需要传输数据的大小

	bio->bi_end_io = end_bio_bh_io_sync;
	bio->bi_private = bh;

	=>bio_get(bio);
	=>submit_bio(rw, bio);//下发块驱动
		=>bio->bi_rw |= rw;
		=>generic_make_request(bio);
			=>if (current->bio_tail) {//如果已经有队列了,则插到队尾返回,防止嵌套
				/* make_request is active */
				*(current->bio_tail) = bio;
				bio->bi_next = NULL;
				current->bio_tail = &bio->bi_next;
				return;
			}
			=>do {
				==>current->bio_list = bio->bi_next;
				==>if (bio->bi_next == NULL)
					current->bio_tail = &current->bio_list;
				==>else
					bio->bi_next = NULL;
				==>__generic_make_request(bio);
					=>if (maxsector < nr_sectors || maxsector - nr_sectors < sector)
						handle_bad_sector(bio);
					=>do {
						==>q = bdev_get_queue(bio->bi_bdev);
						==>blk_partition_remap(bio);//bio的sector和b_size更新,相对于整个磁盘,因为卡驱动看不到分区
						==>ret = q->make_request_fn(q, bio);						
						//在函数void blk_queue_make_request(struct request_queue * q, make_request_fn * mfn)里面赋值,即blk_queue_make_request(q, __make_request);
								=>__make_request //switch各种调度算法
									=>blk_queue_bounce(q, &bio);//回弹区,拷贝高端内存区的bio
									=>elv_queue_empty(q)
									=>el_ret = elv_merge(q, &req, bio);//如果能够合并到已有的request,则合并,否则创建新的request
										==>switch (el_ret) {
											case ELEVATOR_BACK_MERGE:
												req->biotail->bi_next = bio;
												req->biotail = bio;
												req->nr_sectors = req->hard_nr_sectors += nr_sectors;
												req->ioprio = ioprio_best(req->ioprio, prio);
												drive_stat_acct(req, nr_sectors, 0);
												goto out;//能够合并则不创建新的request
											case ELEVATOR_FRONT_MERGE:
												bio->bi_next = req->bio;
												req->bio = bio;
												req->buffer = bio_data(bio);
												req->current_nr_sectors = bio_cur_sectors(bio);
												req->hard_cur_sectors = req->current_nr_sectors;
												req->sector = req->hard_sector = bio->bi_sector;
												req->nr_sectors = req->hard_nr_sectors += nr_sectors;
												req->ioprio = ioprio_best(req->ioprio, prio);
												drive_stat_acct(req, nr_sectors, 0);
												if (!attempt_front_merge(q, req))
													elv_merged_request(q, req, el_ret);
												goto out;//能够合并则不创建新的request
											default://不能合并则创建新的request		
									=>init_request_from_bio(req, bio);
										=>req->errors = 0;
										req->hard_sector = req->sector = bio->bi_sector;
										req->hard_nr_sectors = req->nr_sectors = bio_sectors(bio);
										req->current_nr_sectors = req->hard_cur_sectors = bio_cur_sectors(bio);
										req->nr_phys_segments = bio_phys_segments(req->q, bio);
										req->nr_hw_segments = bio_hw_segments(req->q, bio);
										req->buffer = bio_data(bio);	/* see ->buffer comment above */
										req->bio = req->biotail = bio;
										req->ioprio = bio_prio(bio);
										req->rq_disk = bio->bi_bdev->bd_disk;
										req->start_time = jiffies;
									=>blk_plug_device(q)//详见激活设备,定时唤醒块设备驱动处理  http://blog.csdn.net/shipinsky/article/details/79102293
									=>add_request(q, req);//将新的request加入到队列
								out://bio能合并的话,跳过request的创建
									=>if (sync)//如果紧急,则立即唤醒
										__generic_unplug_device(q);		
					} while (ret);
				==>bio = current->bio_list;//从队尾取插入的bio继续处理
			} while (bio);
			==>current->bio_tail = NULL;
	=>bio_put(bio);

参考
向通用块层提交IO请求
http://blog.chinaunix.net/uid-28897358-id-3776947.html

块设备层分析
http://www.360doc.com/content/16/0510/02/478627_557720637.shtml

linux块设备读写流程(一篇很难的块设备文件 没怎么看懂)
http://blog.csdn.net/mbh_1991/article/details/9455113

generic_make_request函数初探
https://blog.csdn.net/huoshanbaofa123/article/details/51163708

__make_request()函数分析
https://blog.csdn.net/hs794502825/article/details/8719034

generic_make_request的总结性分析
https://blog.csdn.net/guogaofeng1219/article/details/5545439

Linux 性能优化之 IO 子系统
http://blog.sina.com.cn/s/blog_416656f70102vwld.html

Linux性能调优之I/O调优
https://blog.csdn.net/chuxuan909/article/details/72550729

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值