storage R&D guy.
全部博文(1000)
分类: LINUX
2016-11-01 14:27:45
原文地址:page和buffer标志位的一些总结 作者:mars007
1.如果buffer被置为脏buffer,那么page的脏页标志需要被置位,此时,page中其他buffer的DIRTY标志不受影响
mark_buffer_dirty()
if (!test_set_buffer_dirty(bh))
__set_page_dirty()
TestSetPageDirty(page)
radix_tree_tag_set(PAGECACHE_TAG_DIRTY)
2.如果page整页被置为脏页,那么page对应的buffer也会全部被置为脏buffer
set_page_dirty()
set_page_dirty()
__set_page_dirty_buffers
if (page_has_buffers(page)) {
do {
set_buffer_dirty(bh);
bh = bh->b_this_page;
} while (bh != head);
}
__set_page_dirty()
TestSetPageDirty(page)
radix_tree_tag_set(PAGECACHE_TAG_DIRTY)
3.如果使用__bread()同步读取buffer,成功后,此buffer的UPTODATE标志会置位,但是不会碰对应page的UPTODATE标志
__bread()
__bread_slow
bh->b_end_io = end_buffer_read_sync;
submit_bh(READ, bh);
wait_on_buffer(bh);
end_buffer_read_sync()
__end_buffer_read_notouch()
if (uptodate) {
set_buffer_uptodate(bh);
} else {
clear_buffer_uptodate(bh);
}
unlock_buffer(bh);
4.异步读取buffer时,成功后,buffer的UPTODATE标志会置位,如果发现page中所有buffer的UPTODATE标志都已置位,会同时置位page的UPTODATE标志
end_buffer_async_read()
set_buffer_uptodate(bh);
if (所有的buffer都是uptodate的 && !PageError(page))
SetPageUptodate(page);
5.脏页回写时,只回写page中已映射的脏buffer
__block_write_full_page()
do {
if (test_clear_buffer_dirty(bh)) {
submit_bh(WRITE, bh);
} while ((bh = bh->b_this_page) != head);
6.buffer_dirty(bh)=1并不表示buffer_mapped(bh)=1
出现buffer_dirty(bh)=1 && buffer_mapped(bh)=0的一种情况是:mmap()到有空洞块的页或EOF页,用户态程序写page,触发缺页
调用set_page_dirty_balance()->set_page_dirty()->__set_page_dirty_buffers(),将page所有的buffer都置为脏块,__block_write_full_page()
中会处理这种情况.