驅動程式之_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);
/*******************************************/
}
電梯排程算法中,将一個方向(讀寫)的資料節點處理一次(盡最大可能),處理完畢後再反向處理