在自有模块的处理中,我们设计了一个内核线程去做gc,

但同时,我们又用到了rcu,rcu中也会去抢gc的锁,由于该锁用的spin_lock,而不是spin_lock_bh,并没有关软中断,所以在rcu上下文中拿不到锁,造成死锁。

[106251.128106] NMI watchdog: BUG: soft lockup - CPU# stuck for 23s! [kflow_gcd:]
[106251.129425] Modules linked in: newsendfile(OE) witdriver(OE) mysendmsg(OE) xfs libcrc32c fuse tipc(OE) ossmod(OE) iptable_filter mptctl mptbase bonding dm_mirror dm_region_hash dm_log dm_mod iTCO_wdt iTCO_vendor_support skx_edac edac_core intel_powerclamp coretemp intel_rapl iosf_mbi kvm_intel kvm irqbypass crc32_pclmul ghash_clmulni_intel aesni_intel lrw gf128mul glue_helper ablk_helper cryptd pcspkr ses enclosure joydev sg mei_me mei shpchp i2c_i801 lpc_ich wmi ipmi_si ipmi_devintf ipmi_msghandler nfit libnvdimm acpi_pad acpi_cpufreq acpi_power_meter tcp_bbr sch_fq binfmt_misc ip_tables ext4 mbcache jbd2 raid1 sd_mod crc_t10dif crct10dif_generic ast i2c_algo_bit drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops ttm crct10dif_pclmul crct10dif_common crc32c_intel drm ahci libahci libata
[106251.129481] ixgbe(OE) i40e(OE) mpt3sas(OE) ptp raid_class pps_core scsi_transport_sas i2c_core dca [last unloaded: witdriver]
[106251.129492] CPU: PID: Comm: kflow_gcd Tainted: G W OEL ------------ 3.10.-693.21..el7.x86_64 #
[106251.129493] Hardware name: ZTE ZXCDN/SC621DI-16F, BIOS .0b //
[106251.129496] task: ffff8839a2e70000 ti: ffff884f3fb34000 task.ti: ffff884f3fb34000
[106251.129498] RIP: :[<ffffffff811005ce>] [<ffffffff811005ce>] native_queued_spin_lock_slowpath+0x1ce/0x200
[106251.129508] RSP: :ffff885fbdf43dd0 EFLAGS:
[106251.129510] RAX: RBX: 000000000000060c RCX:
[106251.129512] RDX: RSI: RDI: ffff885fbdf59b60
[106251.129513] RBP: ffff885fbdf43dd0 R08: R09:
[106251.129515] R10: ffff88607fbc84a0 R11: ffffea00fba2ae00 R12: ffff885fbdf43d48
[106251.129517] R13: ffffffff816c6732 R14: ffff885fbdf43dd0 R15: ffff8852e87ccf40
[106251.129519] FS: () GS:ffff885fbdf40000() knlGS:
[106251.129521] CS: DS: ES: CR0:
[106251.129523] CR2: 00007f582cb9816c CR3: 0000000001a0a000 CR4: 00000000003607e0
[106251.129525] DR0: DR1: DR2:
[106251.129527] DR3: DR6: 00000000fffe0ff0 DR7:
[106251.129528] Call Trace:
[106251.129530] <IRQ> [106251.129539] [<ffffffff816adeee>] queued_spin_lock_slowpath+0xb/0xf
[106251.129546] [<ffffffff816bb080>] _raw_spin_lock+0x20/0x30
[106251.129555] [<ffffffffc055a3e5>] wit_inode_replace+0x3b5/0x400 [witdriver]
[106251.129561] [<ffffffff8119243f>] ? free_pages.part.+0x3f/0x50
[106251.129567] [<ffffffffc055a534>] free_wit_flow+0x104/0x150 [witdriver]----------------rcu中调用
[106251.129571] [<ffffffffc055a592>] release_wit_flow+0x12/0x20 [witdriver]
[106251.129577] [<ffffffff81140340>] rcu_process_callbacks+0x1e0/0x580
[106251.129583] [<ffffffff8109404d>] __do_softirq+0xfd/0x290
[106251.129588] [<ffffffff816c8afc>] call_softirq+0x1c/0x30
[106251.129594] [<ffffffff8102d435>] do_softirq+0x65/0xa0
[106251.129597] [<ffffffff81094495>] irq_exit+0x175/0x180
[106251.129600] [<ffffffff816c9e88>] smp_apic_timer_interrupt+0x48/0x60
[106251.129603] [<ffffffff816c6732>] apic_timer_interrupt+0x162/0x170
[106251.129604] <EOI> [106251.129613] [<ffffffff81347655>] ? __list_del_entry+0x35/0xd0
[106251.129615] [<ffffffff813476fd>] list_del+0xd/0x30
[106251.129620] [<ffffffffc055fdea>] prune_wait_free_list+0x9a/0x1c0 [witdriver]----------sys中调用
[106251.129624] [<ffffffffc055ff65>] kflow_gcd_fn+0x55/0x1e0 [witdriver]
[106251.129628] [<ffffffffc055ff10>] ? prune_wait_free_list+0x1c0/0x1c0 [witdriver]
[106251.129634] [<ffffffff810b5241>] kthread+0xd1/0xe0
[106251.129637] [<ffffffff810b5170>] ? insert_kthread_work+0x40/0x40
[106251.129641] [<ffffffff816c5577>] ret_from_fork+0x77/0xb0
[106251.129644] [<ffffffff810b5170>] ? insert_kthread_work+0x40/0x40
void wit_unref_flow(void *flow)
{
struct wit_fq_flow *f = (struct wit_fq_flow*)flow;
if ( !witdriver_init_done || !f ) return;
if ( atomic_dec_and_test(&(f->users)) )
{
call_rcu(&f->rcu_head, release_wit_flow);
}
}

由于call_rcu其实是在软中断中完成的,

crash> irq -b
SOFTIRQ_VEC ACTION
[] ffffffff81092e40 <tasklet_hi_action>
[] ffffffff8109bcf0 <run_timer_softirq>
[] ffffffff81590d60 <net_tx_action>
[] ffffffff81592b80 <net_rx_action>
[] ffffffff81308250 <blk_done_softirq>
[] ffffffff81358f00 <irq_poll_softirq>
[] ffffffff81092d00 <tasklet_action>
[] ffffffff810d6610 <run_rebalance_domains>
[] ffffffff8113ea70 <rcu_process_callbacks>

release_wit_flow 会和gc流程抢一把锁,当gc流程拿了锁又被中断之后,执行到rcu的流程,执行 release_wit_flow 去抢锁,造成死锁。

所以需要加bh。

需要注意的是,这个软中断打印,很明显缺少[8],这个8对应的是啥呢?

crash> p softirq_to_name
softirq_to_name = $ =
{0xffffffff8195816a "HI", 0xffffffff818f79c0 "TIMER", 0xffffffff81914a4c "NET_TX", 0xffffffff81914a53 "NET_RX", 0xffffffff819547d4 "BLOCK", 0xffffffff81914a8a "BLOCK_IOPOLL", 0xffffffff81914a63 "TASKLET", 0xffffffff81914a6b "SCHED", 0xffffffff81914a71 "HRTIMER", 0xffffffff81914a79 "RCU"}

看起来【8】对应的是 HRTIMER ,而 HRTIMER 其实是在硬中断中实现的,而不是在软中断中实现的,所以这个看起来应该是废弃了。

hrtimers - High-resolution kernel timers,在rh的3.10内核中,高精度定时器是通过硬中断来实现的,
void __init hrtimers_init(void)
{
hrtimer_cpu_notify(&hrtimers_nb, (unsigned long)CPU_UP_PREPARE,
(void *)(long)smp_processor_id());
register_cpu_notifier(&hrtimers_nb);
}
对应的中断处理堆栈可以参考如下:
[ 6401.459859] [<ffffffff816b9d53>] _raw_spin_lock_bh+0x33/0x40
[ 6401.466087] [<ffffffffc0358971>] wit_hrtimer_pool_notify+0x181/0x3c0 [witdriver]-----这个是我们的timer的func
[ 6401.474060] [<ffffffffc03587f0>] ? wit_send_tasklet+0x590/0x590 [witdriver]
[ 6401.481600] [<ffffffff810b9096>] __hrtimer_run_queues+0xd6/0x260
[ 6401.488187] [<ffffffff810b962f>] hrtimer_interrupt+0xaf/0x1d0
[ 6401.494566] [<ffffffff8105467b>] local_apic_timer_interrupt+0x3b/0x60
[ 6401.501625] [<ffffffff816c8e83>] smp_apic_timer_interrupt+0x43/0x60
[ 6401.508511] [<ffffffff816c5732>] apic_timer_interrupt+0x162/0x170

一个rcu回调导致的简单死锁的更多相关文章

  1. Update导致SQL Server死锁的典型方法(转载)

    此文为转载文章,描述的很好,没有验证过. 最近遇到了一个看上去很奇怪,分析起来很有意思的死锁问题.这个死锁看上去难以理解.而分析过程中,又使用了很多分析SQL Server死锁的典型方法.记录下来整个 ...

  2. 写一个ajax程序就是如此简单

    写一个ajax程序就是如此简单 ajax介绍: 1:AJAX全称为Asynchronous JavaScript and XML(异步JavaScript和XML),指一种创建交互式网页应用的网页开发 ...

  3. ZeroMQ接口函数之 :zmq_socket_monitor - 注册一个监控回调函数

    ZeroMQ 官方地址 :http://api.zeromq.org/4-2:zmq-socket-monitor zmq_socket_monitor(3) ØMQ Manual - ØMQ/4.1 ...

  4. 从一个弱引用导致的奔溃 谈 weak assign strong的应用场景【iOS开发教程】

    从一个弱引用导致的奔溃 谈 weak assign strong的应用场景 .h中的定义方法一: @property (nonatomic, assign) NSArray *dataSource; ...

  5. SqlServer 一个查询语句导致tempdb增大55G(转载)

    SqlServer 一个查询语句导致tempdb增大55G 今天操作着服务器,突然右下角提示“C盘空间不足”! 吓一跳!~ 看看C盘,还有7M!!!这么大的C盘空间怎么会没了呢?搞不好等下服务器会动不 ...

  6. 一个mybatis错误导致无法启动项目的问题

    今天遇到Mybatis一个问题,导致项目一直起不来,查了很久发现是MapperXML的错,问题表现为: 系统始终起不来,但也不报错,始终卡到如下信息位置: 信息: Initializing Sprin ...

  7. java的一个简单死锁的例子

    package com.deadlock; /* * 演示死锁:(由毕向东视频所得) * 一种解释:Thread—0拿到lock1锁,Thread—1拿到lock2锁,Thread—0想要lock2锁 ...

  8. Mysql查询语句使用select.. for update导致的数据库死锁分析

    近期有一个业务需求,多台机器需要同时从Mysql一个表里查询数据并做后续业务逻辑,为了防止多台机器同时拿到一样的数据,每台机器需要在获取时锁住获取数据的数据段,保证多台机器不拿到相同的数据. 我们My ...

  9. bLock 回调 就是这么简单!

    转载自:http://blog.csdn.net/mobanchengshuang/article/details/11751671 我们在开发中常常会用到函数回调,你可以用通知来替代回调,但是大多数 ...

随机推荐

  1. cordova 常用操作

    #创建插件 plugman create --name MyMath --plugin_id SimpleMath --plugin_version #进入插件目录 cd MyMath #plugin ...

  2. 第8章 传输层(1)_TCP/UDP协议的应用场景

    1. 传输层的两个协议 1.1 TCP和UDP协议的应用场景 (1)TCP协议:如果要传输的内容比较多,需要将发送的内容分成多个数据包发送.这就要求在传输层用TCP协议,在发送方和接收方建立连接,实现 ...

  3. 第1章 计算机网络和协议(3)_TCP/IP协议

    3. TCP/IP协议 3.1 TCP/IP协议分层 3.2 TCP/IP通信过程 (1)应用层:浏览器和Web服务器是两个对等的实现,它们之间使用http协议进行通信. (2)传输层:网页传输之前, ...

  4. [SDOI2013]泉(容斥)

    /* 容斥加上哈希 首先我们可以2 ^ 6枚举相同情况, 然后对于这些确定的位置哈希一下统计方案数 这样我们就统计出了这些不同方案的情况, 然后容斥一下就好了 */ #include<cstdi ...

  5. SHOI2016方

    /* 上帝说 要方 是的 很方 计数问题的容斥思想 (首先要注意 正方形有斜着的QAQ) 考虑我们要求的合法正方形 ans 根据容斥 ans = 无限制方案书 - 一个点确定的方案数 + 两个点确定的 ...

  6. 测试oracle数据库连接

    1.ping 192.168.0.12.telnet 192.168.0.1 1521 按下ctrl+] 组合键出现命令回显才是端口连接成 3.tnsping 192.168.0.1:1521/db

  7. Apache服务器下phalcon项目报Mod-Rewrite is not enabled问题

    问题如图: 项目已经按照官网的教程修改了.htaccess文件,仍旧报此错误,判断可能是apache未添加mod_rewrite,通过查询资料,经以下两步解决此问题: 1.执行sudo a2enmod ...

  8. day19常用模块2

    常用模块21 shelve模块  也是一种序列化方式    使用方法        1.open     sl = shelve.open("shelvetest.txt")   ...

  9. jsfiddle修改个人头像

    找了半天终于知道修改jsfiddle头像的方法了~ JsFiddle将Gravatar - 全球认可的头像用于个人资料图片.必须在这里改变你的头像,它也会在jsFiddle中自动更新. 注意,两者的注 ...

  10. [转]IISExpress配置使其能通过IP访问方法

    转自http://www.cnblogs.com/liujh/p/4315927.html 环境说明: 本机IP:192.168.2.100:Web端口:11843 步骤一 打开[我的文档]\IISE ...