hadoop集群上捉到linux kernel bug一个 (答读者提问)

首先感谢大家对原文的关注,能和大家一起交流内核技术我非常的荣幸,这里试着回答大家的提问。


超然台上仙:有点不太理解请教一下, “看,这样写完一个文件后,每个page都被makr_page_accessed了两次,也就是说都成了AC TIVE。在2.6.18 kernel里,确实是这样;” 这说明这些page应该是active的,可是后面的修改, “fix这个问题的方案非常简单,就是不要让第14个page有特权,而是让它在被mark_page_a ccessed之前就一直呆在pagevec,别去全局lru链表。” 这样这些page不都成REFERENCED的了么

答:是的,按我的patch的方案,这14个page在被write了两遍以后,都是REFERENCED了。
可能有人要说,文件写了两遍,应该page都是ACTIVE呀。道理上说是这样,但是,pagevec的引入已经造成了“两遍写之后page都是REFERENCED”这个即成事实(当然,还有不均匀的问题),所以我第一次在社区发出这个patch的第一版时,就有人回信说干脆把pagevec去掉得了,但毕竟去pagevec牵扯太多,可能带来的副作用也不好评估,于是最后社区还是决定先收我这个patch,至少先把这14个page弄“平等”,大家都是REFERENCED总好过“前13个REFERENCED后一个ACTIVE“。
等以后哪位内核牛人决定了最终去掉pagevec,我这个patch也就没有存在的必要了。到了那个时候,再也没有不平等的page,而文件在连续的写过(或读过)两遍之后,page们就都是ACTIVE了。


超然台上仙:2.6.18 kernel也同样使用了pagevec,__grab_cache_page中代码意思与32版本是一样的,似乎与文中描述不符

答:你看得非常仔细,我去翻了一下code,发现在upstream的2.6.18内核里,generic_file_buffered_write的逻辑是:

__grab_cache_page()
prepare_write (对应2.6.32内核里的write_begin)
copy content into page
commit_write (对应2.6.32内核里的write_end)
mark_page_accessed(page)

在__grab_cache_page里确实是把page先放入了pagevec,所以,一样会出现page冷热不均的情况(我的patch里有复现这个问题的方法,大家可以试一试)。
但是,redhat的2.6.18是打了补丁的(我上文的2.6.18都是指redhat的),打过之后,__grab_cache_page变成了grab_cache_page_write_begin,这里面就没有用pagevec,而是直接加入全局lru链表了。很可能redhat已经发现了pagevec会带来副作用。
奇怪的是,redhat如果知道了pagevec引入的这个问题,为什么在新的rhel6里没有fix?....这个就不得而知了。


Bergwolf:帅锅,IIUC这个问题的根源是pagevec破坏了active page的公平性,以及readahead window遇到已经存在的page就停下。看了下你的patch,如果在page 14两次mark_page_accessed()之间,有别的page需要加入到LRU,那page 14还是会被置成active。可以想象的场景是,你的test case在多进程并发写的场景下,vm还是出现少量独立的active page的情况。

答:我才发现,确实如你所说!如果用户是用2K的buffer来write且用多进程,那么即使是我的patch也不能完全避免page冷热不均。只是在hadoop上大文件是一次写成,一个page不会被两次mark_page_accessed,也就不会触发而已。
Bergwolf同学果然洞察玄机,拜服了!


相关文章

分类

2 Comments

非常感谢博主耐心回答本人问题。
不过要指出所谓“zc19881024的来信”也是本人发的。。。

DongHao Author Profile Page said:

你的邮箱和法号也太不统一了,我马上改过来

留言:

关于文章

This page contains a single entry by DongHao published on 08 31, 2012 10:45 AM.

hadoop集群上捉到linux kernel bug一个 was the previous entry in this blog.

怎样用上ext4 bigalloc is the next entry in this blog.

Find recent content on the main index or look in the 存档 to find all content.