第10章文件系统读写--3

当要读的页在page cache中数据不是最新的或者在页在page cache不存在时,则需要从磁盘读数据。通过接下来的readpage函数来实现从磁盘读文件,readpage函数由具体的文件系统提供。比如ext2文件系统所对应的为:ext2_readpage().

文件系统的读写请求,最终要转换成对块设备的读写请求。这涉及几个问题:

1、文件对用户呈现一个连续的读写接口,但文件在真正的物理设备上的存储可能不是连续的,如果不是连续的,对文件的读写就不能用同一个I/O完成,而是需要拆分。

2、硬盘的读写最小单元通常是扇区,通常一个扇区是512字节,而文件的最小单元是块,一个块可以由多个扇区组成。组成块的扇区物理地址是连续的,而块与块之间可以不连续。

3、内核通过submit_bio来提交一个I/O给底层。同时内核又提供一个submit_bh来提交块。(submit_bh最终也是通过submit_bio来实现的)

static int ext2_readpage(struct file *file, struct page *page)
{                                                             
____return mpage_readpage(page, ext2_get_block);              
}                                                             
int mpage_readpage(struct page *page, get_block_t get_block) 
{                                                            
____struct bio *bio = NULL;                                  
____sector_t last_block_in_bio = 0;                          
____struct buffer_head map_bh;                               
____unsigned long first_logical_block = 0;                   
                                                             
____clear_buffer_mapped(&map_bh);                            
____bio = do_mpage_readpage(bio, page, 1, &last_block_in_bio,
____________&map_bh, &first_logical_block, get_block);       
____if (bio)                                                 
________mpage_bio_submit(READ, bio);                         
____return 0;                                                
}                                                            

mpage_readpage->do_mpage_readpage->mpage_bio_submit最终提交bio给下一层。在提交bio过程中会注册,bio->bi_end_io = mpage_end_io_read供中断处理函数在中断处理过程中调用。

static struct bio *mpage_bio_submit(int rw, struct bio *bio)
{
____bio->bi_end_io = mpage_end_io_read;
____if (rw == WRITE)
________bio->bi_end_io = mpage_end_io_write;
____submit_bio(rw, bio);
____return NULL;
}

mpage_end_io_read这个回调函数会遍历bio结构的每个向量,看相关页面是否获得最新的数据。如果成功,则设置页面状态为最新,同时解锁页面。解锁页面将唤醒之前等待的页面更新进程;如果数据未更新,则设置页面错误,解锁页面,唤醒等待页面更新的进程。

static int mpage_end_io_read(struct bio *bio, unsigned int bytes_done, int err)
{                                                                              
____const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);               
____struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;                  
                                                                               
____if (bio->bi_size)                                                          
________return 1;                                                              
                                                                               
____do {                                                                       
________struct page *page = bvec->bv_page;                                     
                                                                               
________if (--bvec >= bio->bi_io_vec)                                          
____________prefetchw(&bvec->bv_page->flags);                                  
                                                                               
________if (uptodate) {                                                        
____________SetPageUptodate(page);                                             
________} else {                                                               
____________ClearPageUptodate(page);                                           
____________SetPageError(page);                                                
________}                                                                      
________unlock_page(page);                                                     
____} while (bvec >= bio->bi_io_vec);                                          
____bio_put(bio);                                                              
____return 0;                                                                  
}                                                                              

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值