安庆

导航

rcu使用遇到问题汇总

 

1.3.10内核,在项目中遇到一种情况,我们根据sk指针hash到一个cpu上,然后访问该cpu对应分配的一个数据区。

然后系统会偶尔crash掉,crash掉有两种情况,一种是cred的rcu回收时出现计数bugon,一种是hung,

hung的这种一般是由于由一个持有mutex的进程在rttable的resize过程中synchronize_rcu() 出现等待gp,而另外一个进程也需要这把mutex的锁。

继续排查发现等待gp是因为synchronize_rcu() 自身的这个rcu没有及时处理,导致没有调用wakeup,

这种rcu还在对应的链中,也就是rcu出现累积,有的是几十万个rcu没有执行,有的甚至上千万个。在开启rcuo内核线程的代码中(RCU_NOCB),可以看到对应的线程

处于一种不干活的状态,

tatic int rcu_nocb_kthread(void *arg)
{
    。。。
        while (list) {
            next = list->next;
            /* Wait for enqueuing to complete, if needed. */
            while (next == NULL && &list->next != tail) {----------什么情况下会在这里循环
                schedule_timeout_interruptible(1);
                next = list->next;
            }
            debug_rcu_head_unqueue(list);
            local_bh_disable();
            if (__rcu_reclaim(rdp->rsp->name, list))
                cl++;
            c++;
            local_bh_enable();
            list = next;
        }
。。。。
}

很显然,原本的第二个while,应该只是一个无锁设计,也就是临时状态,但是从crash文件看,这里形成死循环了。

这种死循环,导致了后面的 __rcu_reclaim 并没有执行,从而导致rcu积压。

回过头来看,while循环的原因是因为,rcu_head的next指向NULL,同时它又不是最后一个rcu。

也就是rcu的串被破坏了,破坏的原因不是因为踩内存,而是因为,我们由一个流程有问题,导致同一个rcu_head被call_rcu了两次。

后面的问题我想大家也容易分析了,不过我们还遇到了两种情况,一种是,在同一个cpu上,同一个rcu_head被call_rcu了两次,

另外一种,是在两个cpu上分别执行,形成了环。

 2.在suse 11 sp3上,遇到一种rcu链被破坏的情况,rcu的func指针指向莫名的数据段地址,导致oops,另外一个crash是出现的put_cred的bugon,因为计数不对。两种

crash都是因为rcu的链被异常破坏,如果是1这种情况的破坏是因为自己代码没写好,那么2这种其实是因为xfs的一个bug,排查耗了很多时间,

如果你排查过程中遇到rcu的qlen为负值(也就是不该执行的rcu执行了,会导致rcu_data的关于qlen的计数会错的),并且开启了slab或者slub的debug的话,

最还还需要开启CONGFIG_PAGEALLOC和STACKOVERFLOW的开关,kmem -s 看到slab一片正常的时候,你需要怀疑,是不是xfs的bug,因为,我踩坑了。

 

posted on 2019-09-28 08:54  _备忘录  阅读(1381)  评论(1编辑  收藏  举报