驱动程序之_2_块设备_2_ll_rw_block分析
层次结构
内核目录下有fs文件夹,里面放有各种文件系统以及它们公共的接口,ll_rw_block就位于fs/buffer.c中
以读为例
在ll_rw_block中提取bh呈递
void ll_rw_block(int rw, int nr, struct buffer_head *bhs[])
{
/*******************************************/
struct buffer_head *bh = bhs[i];
/*******************************************/
if (rw == WRITE || rw == SWRITE) {
}
else{
submit_bh(rw, bh);
}
/*******************************************/
}
在submit_bh中构造bio呈递
int submit_bh(int rw, struct buffer_head * bh)
{
/*******************************************/
struct bio *bio;
/*******************************************/
submit_bio(rw, bio);
/*******************************************/
}
在submit_bio中,使用bio构造请求
void submit_bio(int rw, struct bio *bio)
{
/*******************************************/
generic_make_request(bio);
/*******************************************/
}
void generic_make_request(struct bio *bio)
{
/*******************************************/
__generic_make_request(bio);
/*******************************************/
}
在__generic_make_request中找到队列,以此构造请求
static inline void __generic_make_request(struct bio *bio)
{
/*******************************************/
q = bdev_get_queue(bio->bi_bdev);
/*******************************************/
ret = q->make_request_fn(q, bio);
/*******************************************/
}
在blk_queue_make_request中设置队列
void blk_queue_make_request(request_queue_t * q, make_request_fn * mfn)
{
/*******************************************/
q->make_request_fn = mfn;
/*******************************************/
}
在blk_init_queue_node中调用blk_queue_make_request
request_queue_t * blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id)
{
/*******************************************/
blk_queue_make_request(q, __make_request);
/*******************************************/
}
在__make_request中使用电梯调度算法尝试合并bio
如果合并不成功,就分配队列节点,添加到队列
static int __make_request(request_queue_t *q, struct bio *bio)
{
/*******************************************/
el_ret = elv_merge(q, &req, bio);
/*******************************************/
req = get_request_wait(q, rw_flags, bio);
/*******************************************/
add_request(q, req);
/*******************************************/
}
电梯调度算法中,将一个方向(读写)的数据节点处理一次(尽最大可能),处理完毕后再反向处理