hadoop与午睡

[原写于2012年6月]

这一阵子在折腾hadoop集群上linux kernel的优化,开始没机器,只好悲惨的用虚拟机来装,但是kvm虚拟机又不给力,虚拟机之间死活连不上,最后终于等到柯旻同学婚假归来,支援了我几台线下测试机,刘毅同学帮我搭了环境,终于可以见到活生生的hadoop运行状态。
接下来是两周的运行观察和调试。

目前为止最大的进展是揪出一个2.6.32(upstream也有)的一个pagevec引发的性能退化,见patch
然后,考虑到hadoop里,源数据一般只读一次,目标结果也只写一次,cache没什么用,所以我们很想试试新版带有cache抛弃功能(所谓的drop-behind )的hadoop,我看hadoop-0.23.1有此功能,于是想在测试集群里跑起来。
没想到hadoop-0.23.1比0.19变了那么多,配置文件的名字变了、配置项变了、连resource manager也变了,我在网上翻了不少文章,试了好多配置方法,hadoop的log报了不少WARN(无非都是某些配置项名字变了),好像这些WARN也不影响运行,但最后却只能在单机上跑任务....诸多毛病,我折腾了两个工作日外加一个周末,还是没能把最基本的terasort在多机上run起来....这五个白天看了不知道多少hadoop那无病呻吟却又提供不了多少帮助的log。

昨天(星期天)睡午觉,梦见早上起床要去上班,提起裤子准备穿,突然发现裤子上有妈妈绣的字:”WARN:此裤子颜色已经发旧,不要再穿“,我心想,不就是”WARN“嘛,又不是”ERROR“或者”FATAL“,于是我还是把裤子穿上了。等到醒来,不禁失笑。

今天早上,找到了吴威同学,还是专家有办法:别再搭郁闷的hadoop-0.23.1了,搭cdh3u4!吴威同学三下五除二把cdh搭好,我终于能跑上terasort测试了。

关于雅思的爱与恨

[原写于2012年6月]

前年我去考过一次雅思,口语的考官是个面无表情的瘦高个儿,老外,非常非常的面无表情,我回答了一堆东西,他每次都只问一个字:“Why?“...“Why?”...“Why?“,我当时真想抓起桌上的电子钟砸他脑袋上去——你他妈哪来那么多的Why!无奈考雅思就是求老外,我当然不敢动手。至今想起来,依然忿忿不平,唉,只要国内的食品略安全一点,我也用不着一把年纪了还背单词学英语(我读书时背得够累的了)、还得看这老外考官的脸色。

今天在组内群里发了娃的照片

涛哥: 你娃这么小就考雅思呵

我: 这你都看出来了

涛哥: 10天突破系列啊

我: 唉,10天是突破不了的,尤其是像我这样7年都在民企干,一点读、写、说、听英语的机会都没有的人

文卿: 请参加ext4 weekly conference call

我: 雅思口语是不会考文件系统的

文卿: 但是会考你跟人扯淡

我: 雅思口语一般是问 “你最近最爽的一次散步是在哪里,跟谁散的,你们聊了什么,为什么你觉得很爽” 一类的问题,然后接下来考官就一脸的木然,不停的问“why?。。why?。。。why?”

文卿: 我最爽的一次是在google compus跟Ted散的,聊了ext4,因为我和他握了爪,所以爽 :)

我: 如果我是雅思考官,我就会继续问:“Why you feel happy when catching Ted's claw?"

文卿: because he is a well-known man in ext4 community.

我: why you want to catch a ext4 fellow's claw?

文卿: His claw can make me happy.

我: Why his claw could make you happy?

文卿: that was a long time ago. When I was a frehman in my university, I firstly hear his name and blabla ....

我: ....看来你能通过口语考试,我反正是不行了

netoops启动时报 "XX is a slave device, aborting"

[原写于2012年6月]

为了监控上线的新内核,我们把google的netoops backport到了自己的内核,生产上如有kernel panic,会将panic的栈信息发送到日志服务器,方便调试和修复。
前天,洪川同学报告说以前线上的netoops都是把bond的slave网口作为发消息的dev,新上线2.6.32-220内核后,启动netoops失败,系统报:

”eth0 is a slave device, aborting."

找了一下从 2.6.32-131 到 2.6.32-220 的redhat的变动,发现了王聪同学的这个patch:

commit 0c1ad04aecb975f2a2014e1bc5a2fa23923ecbd9
Author: WANG Cong
Date: Thu Jun 9 00:28:13 2011 -0700

netpoll: prevent netpoll setup on slave devices

In commit 8d8fc29d02a33e4bd5f4fa47823c1fd386346093
(netpoll: disable netpoll when enslave a device), we automatically
disable netpoll when the underlying device is being enslaved,
we also need to prevent people from setuping netpoll on
devices that are already enslaved.

Signed-off-by: WANG Cong
Signed-off-by: David S. Miller

diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 2d7d6d4..42ea4b0 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -792,6 +792,12 @@ int netpoll_setup(struct netpoll *np)
return -ENODEV;
}

+ if (ndev->master) {
+ printk(KERN_ERR "%s: %s is a slave device, aborting.\n",
+ np->name, np->dev_name);
+ return -EBUSY;
+ }
+
if (!netif_running(ndev)) {
unsigned long atmost, atleast;

从此,netpoll就无法使用slave设备了(netoops用的就是netpoll),不过我奇怪为什么以前可以现在又不行了,所以发邮件问了王聪同学为何现在不能使用slave设备,回答是:

“因为slave设备没有IP地址,http://wangcong.org/blog/archives/1657”

而且王同学在redhat搞netconsole也遇到了同样的问题,只能改用master网口。我们的netoops也只能遵循同样的规则,改用 bond0做dev

BUG_ON exit_mmap

[原写于2012年6月]

上个月,生产服务器上报来了内核bug:

------------[ cut here ]------------
kernel BUG at mm/mmap.c:2352!
invalid opcode: 0000 [#1] SMP
last sysfs file: /sys/devices/system/cpu/cpu23/cache/index2/shared_cpu_map
CPU 13
....
[] mmput+0x65/0x100
[] exit_mm+0x105/0x140
[] do_exit+0x1ad/0x840
[] ? __sigqueue_free+0x40/0x50
[] do_group_exit+0x41/0xb0
[] get_signal_to_deliver+0x1e8/0x430
[] do_notify_resume+0xf4/0x8a0
[] ? security_task_kill+0x16/0x20
[] ? recalc_sigpending+0x32/0x80
[] ? sigprocmask+0x75/0xf0
[] ? sys_rt_sigprocmask+0x81/0x100
[] ? sigprocmask+0x75/0xf0
[] int_signal+0x12/0x17

原因就是 exit_mmap 函数最后一行的BUG_ON被触发了(我们用的是 2.6.32 内核)

void exit_mmap(struct mm_struct *mm)
{
....
BUG_ON(mm->nr_ptes > (FIRST_USER_ADDRESS+PMD_SIZE-1)>>PMD_SHIFT);
}

[ 这个 (FIRST_USER_ADDRESS+PMD_SIZE-1)>>PMD_SHIFT 其实就是0 ]

从代码直观能想到的就是进程在退出的时候pte没有释放对,或者nr_ptes计数漏了,导致最后一步nr_ptes没有变成0。
想归想,这个非常难重现。但是很快,好运来了,同事在开发cgroup的过程中无意中也触发了了这个BUG_ON,触发的方法是在 __mem_cgroup_uncharge_common 函数里加了一对 down_read/up_read (除了这一对,没有任何别的操作)。于是我开始想象:这一对 down_read/up_read 没有做任何与page或者pte相关的事情,却引起 nr_ptes计算出错,那八成是这一对锁的添加触发了原来的某个race condition,最终导致 nr_ptes 没有计算对。
于是,我沿着这条思路,顺着 exit_mmap 一路 trace_printk ,终于发现是在 page_remove_rmap() 前后nr_ptes开始不对,调用路线还挺深(花了不少力气才找到):

--> exit_mmap
--> unmap_vmas
--> unmap_page_range
--> zap_pud_range
--> zap_pmd_range
--> zap_pte_range
--> page_remove_rmap

为什么是 page_remove_rmap ? 又花了两天才发现,原来exit_mmap里用到了 tlb_gather_mmu/tlb_finish_mmu,就是把要清空页表项的page暂存在一个 struct mmu_gather 里,然后在tlb_finish_mmu时统一清空页表,以提高性能。2.6.32内核里的这个 struct mmu_gather 是per cpu变量(每个cpu一个),这就意味着在 tlb_gahter_mmu 和 tlb_finish_mmu 之间进程不能切换CPU,否则拿到的 struct mmu_gather就可能是另一个CPU上的变量,那就彻底不对了(upstream为了支持抢占,已经将mmu_gather改为 stack argument)。糟糕之处就在于,page_remove_rmap调用了mem_cgroup_uncharge_page进而调用了__mem_cgroup_uncharge_common,而我们在里面加了一个down_read,而down_read里有一句might_sleep(),结果,进程睡眠了,等他醒过来,可能已经身处另一个CPU,于是mmu_gather拿错了,于是nr_ptes不对了....(其实我挺好奇:为什么down_read里要加一句might_sleep?求高手解答)

花了三天辛辛苦苦的找,最后发现不是race condition,就是自己加的down_read造成的问题。
但是毕竟,生产报来的bug是没有这一更改的,那就是另有原因,还得查。

上周刘峥同学给了个链接 https://lkml.org/lkml/2012/2/15/322 ,看来redhat也遇到不少exit_mmap BUG_ON(),不过他们发现是Transparent Huge Page造成的,咱们报bug的生产服务器上并没有用到THP,还不是一个问题。不过,我总体感觉,进程退出的代码路径里,这个 BUG_ON(mm->nr_ptes > 0) 是最后一关,结果成了bug触发的汇集处,很多别处的甚至不是mm相关的代码错误都可能触发这个BUG_ON,比如这个 https://lkml.org/lkml/2012/5/25/553

后来,生产服务器从 2.6.32-131 升到 2.6.32-220 后,再没报过这个BUG_ON,至于终极的原因....可能是mm部分的bug fix,也可能是某个驱动的升级,这个,只有redhat知道了

木匠

[原写于2012年5月]

我的办公桌上有一个纠正坐姿的木架子(我有脖子前倾的坏习惯),是我爸做的,但是同事都以为是我做的(他们跟我爸不熟)。大家似乎都对这个自制的小木架非常感兴趣,很多第一次看见的同事都会详细询问一番,甚或赞美一番。

上个星期,coly和易统在讨论问题。

coly:google那边不仅自己定制内核,还自己定制硬件
易统:是的,他们有自己的硬件工程师,专门为公司的搜索应用定制主板、硬盘等
coly:嗯,还有自己的机械师,连机房的机架都是专门设计的
易统:。。。。那有什么了不起,(转身看着我)。。。。咱们有自己的木匠!

。。。。

我:有订单千万别忘了我喲

1 10 11 12 13 14