天天看點

驅動程式之_2_塊裝置_2_ll_rw_block分析

驅動程式之_2_塊裝置_2_ll_rw_block分析

層次結構

驅動程式之_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);
/*******************************************/	
}
           

電梯排程算法中,将一個方向(讀寫)的資料節點處理一次(盡最大可能),處理完畢後再反向處理