Chinaunix

标题: 请教buffer_head的具体作用 [打印本页]

作者: humjb_1983    时间: 2014-05-07 11:27
标题: 请教buffer_head的具体作用
个人理解buffer通常是用在需要按块进行读写或者读写的页对应的磁盘块不连续时,才使用buffer page按块进行读写。通常的读写应该都是直接通过页缓存。
但是,不解的是在write的流程中,prepare_write的时候,看似对每个page都会分配对应的buffer_head,不知为何要这样做?还大侠们指点下buffer具体的应用场景?
作者: firkraag    时间: 2014-05-07 16:36
You do not need to write back the whole page if you can just write back the dirty part(block buffer whose buffer head with BH_Dirty flag), right?
作者: humjb_1983    时间: 2014-05-07 20:25
回复 2# firkraag
但是正常情况下,应该都是整页回写的哦(即使写的数量小于一页),除非通过submit_bh指定块进行写


   
作者: firkraag    时间: 2014-05-08 10:28
If the page is mapped, it will write back the whole page. But if you use the 'write' systemcall and  just write a few bytes less than a page and the page is not mapped, then it will not need
to write back the whole page.
作者: humjb_1983    时间: 2014-05-08 12:41
ooo~
static int __block_prepare_write(struct inode *inode, struct page *page,
                unsigned from, unsigned to, get_block_t *get_block)
{
        unsigned block_start, block_end;
        sector_t block;
        int err = 0;
        unsigned blocksize, bbits;
        struct buffer_head *bh, *head, *wait[2], **wait_bh=wait;

        BUG_ON(!PageLocked(page));
        BUG_ON(from > PAGE_CACHE_SIZE);
        BUG_ON(to > PAGE_CACHE_SIZE);
        BUG_ON(from > to);

        blocksize = 1 << inode->i_blkbits;
        /**
         * 检查某页是否是一个缓冲区页(如果是则PG_Private标志置位)。
         * 如果没有设置该标志,则调用create_empty_buffers为页中所有的缓冲区分配缓冲区首部
         */
        if (!page_has_buffers(page))
                create_empty_buffers(page, blocksize, 0);
        head = page_buffers(page);

请问为什么这里,当page不是buffer page的时候,还要为其分配buffer_head呢?照理解,正常的write不需要使用buffer,也就不需要使用buffer_head吧?如果是这样的话,那write时所有的页都需要为其分配buffer_head了?为啥?
作者: firkraag    时间: 2014-05-09 13:58
I mean if you write to a part of a file which the corresponding page has not been loaded into the page cache and you may just write 2000 bytes. This time kernel can not find the page in the page cache,  it just allocates a page and don't load the content of the whole file page into the page(without PG_Uptodate), then add it to the page cache, it just loads the parts(BH_Mapped) which are affected by the writing action and the commitment will mark the corresponding parts of the page as dirty(BH_Dirty) and uptodated(BH_Uptodate). Of course, mark the page as dirty.
作者: humjb_1983    时间: 2014-05-10 12:05
firkraag 发表于 2014-05-09 13:58
I mean if you write to a part of a file which the corresponding page has not been loaded into the pa ...

感谢回复~

照兄台的意思,只有当写入的内容小于一页,同时该页还没有page cache时,才会使用buffer?
那为何在prepare_write的时候,看似对所有的cache页都分配了buffer_head呢?这也是我最大的疑问
作者: firkraag    时间: 2014-05-11 09:40
Even kernel can find the page in the page cache, if you write a part of the file, the block buffer is useful for just writing the dirty part back to the disk.  And the page you can find in the page cache may not have corresponding blocks allocated on the disk, if this happened, block buffer is needed. Although there is a flag 'PG_mappedtodisk' to indicated all corresponds blocks are allocated on the disk, they seems not to making use of it.
作者: humjb_1983    时间: 2014-05-12 18:33
firkraag 发表于 2014-05-11 09:40
Even kernel can find the page in the page cache, if you write a part of the file, the block buffer i ...

感谢解答,后面再研究下代码~~
作者: zhangku0    时间: 2018-07-31 10:46
本帖最后由 zhangku0 于 2018-07-31 11:07 编辑

最近在看这一块 也觉得这部分有些奇怪
我的理解是 写出到pagecache的时候 在写出数据的首尾的位置 未必是以块对齐  这样在此块信息无效的时候 就需要读入这些并非重写整个块的块内容(在读入块的时候就需要bufferhead了) 以便于一起flush到硬盘(可以想象 如果不读入这些额外内容  写入硬盘的单位又是块  就会导致块内部分内容缺失)  

但是这么理解奇怪的是 这样只需要首尾块所在的页产生bufferhead就可以  为啥所有页都变成这样呢

另外 写入页都生成了bufferhead 是不是说明 写入过的页 都是缓冲区页?





欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2