[445713.507663] Pid: , comm: -IFileSender Tainted: G    B      ENX 3.0.-0.47.-default # ZTE Grantley/S1008
[445713.507671] RIP: :[<ffffffff810fb2cb>] [<ffffffff810fb2cb>] find_get_pages_contig+0x5b/0x110
[445713.507678] RSP: :ffff883edfc2fab8 EFLAGS:
[445713.507679] RAX: ffff881f68ef68d0 RBX: RCX:
[445713.507681] RDX: RSI: ffffea000a9164e8 RDI: ffffea000a9164e0
[445713.507682] RBP: R08: R09: ffff883edfc2fa78
[445713.507683] R10: R11: 000000000000003f R12: ffffffff8146ffee
[445713.507684] R13: 000000000006cc46 R14: 00000000000007fe R15: ffffe8e001baa620
[445713.507686] FS: 00007f06f82a9700() GS:ffff88207fda0000() knlGS:
[445713.507688] CS: DS: ES: CR0:
[445713.507689] CR2: 00007fd39233d810 CR3: 0000003ec0289000 CR4: 00000000001407e0
[445713.507690] DR0: DR1: DR2:
[445713.507691] DR3: DR6: 00000000ffff0ff0 DR7:
[445713.507693] Process -IFileSender (pid: , threadinfo ffff883edfc2e000, task ffff883edfc2c480)
[445713.507694] Stack:
[445713.507700] 000000059715f240 ffff881f6a1bd2e8 0000000000003ffb
[445713.507704] ffff881dab7a5180 0000000000004c04
[445713.507706] ffff883edfc2fdf8 ffffffff811898f1 ffff881d69cf4c40 ffff881dab7a5180
[445713.507709] Call Trace:
[445713.507718] [<ffffffff811898f1>] __generic_file_splice_read+0x111/0x4c0
[445713.507722] [<ffffffff81189ceb>] generic_file_splice_read+0x4b/0x90
[445713.507767] [<ffffffffa05fec5a>] xfs_file_splice_read+0x14a/0x200 [xfs]
[445713.507832] [<ffffffff81188c6c>] splice_direct_to_actor+0xcc/0x1d0
[445713.507837] [<ffffffffa070a9ab>] do_sendfile+0x1db/0x270 [witdriver]
[445713.507844] [<ffffffffa0716b3a>] my_sendfile+0x2da/0x530 [witdriver]
[445713.507863] [<ffffffff8146f5f2>] system_call_fastpath+0x16/0x1b
[445713.507870] [<00007f07326683c9>] 0x7f07326683c8

获取页面超时,反汇编响应的代码,确定了是在进行page计数增加。

        if (!page_cache_get_speculative(page))
goto repeat;

根据代码逻辑,page的计数不对,本来page的计数为0是一个瞬间状态,结果却一直在循环。

查看crash之前的打印,找到对应的日志为:

kernel: [111747.127259] BUG: Bad page state in process -IFileSender  pfn:2375c8e
kernel: [111747.127259] BUG: Bad page state in process -IFileSender pfn:2375c8e
kernel: [111747.127263] page:ffffea007c1c3f10 count: mapcount: mapping:ffff882b63e766e0 index:0x3ffc
kernel: [111747.127263] page:ffffea007c1c3f10 count: mapcount: mapping:ffff882b63e766e0 index:0x3ffc
kernel: [111747.127265] page flags: 0x60000000080010(uptodate|mappedtodisk)
kernel: [111747.127265] page flags: 0x60000000080010(uptodate|mappedtodisk)
kernel: [111747.127269] Pid: , comm: -IFileSender Tainted: G ENX 3.0.-0.47.-default #
kernel: [111747.127269] Pid: , comm: -IFileSender Tainted: G ENX 3.0.-0.47.-default #
kernel: [111747.127271] Call Trace:
kernel: [111747.127271] Call Trace:
kernel: [111747.127284] [<ffffffff81004b95>] dump_trace+0x75/0x300
kernel: [111747.127284] [<ffffffff81004b95>] dump_trace+0x75/0x300
kernel: [111747.127290] [<ffffffff81464663>] dump_stack+0x69/0x6f
kernel: [111747.127290] [<ffffffff81464663>] dump_stack+0x69/0x6f
kernel: [111747.127296] [<ffffffff81100da1>] bad_page+0xb1/0x120
kernel: [111747.127296] [<ffffffff81100da1>] bad_page+0xb1/0x120
kernel: [111747.127300] [<ffffffff81101306>] free_pages_prepare+0xe6/0x110
kernel: [111747.127300] [<ffffffff81101306>] free_pages_prepare+0xe6/0x110
kernel: [111747.127304] [<ffffffff81104d69>] free_hot_cold_page+0x49/0x1f0
kernel: [111747.127304] [<ffffffff81104d69>] free_hot_cold_page+0x49/0x1f0
kernel: [111747.127311] [<ffffffffa0621224>] wit_free_shinfo_pages+0x34/0x50 [witdriver]
kernel: [111747.127311] [<ffffffffa0621224>] wit_free_shinfo_pages+0x34/0x50 [witdriver]
kernel: [111747.127331] [<ffffffffa0631306>] my_writev+0x2b6/0x6e0 [witdriver]
kernel: [111747.127331] [<ffffffffa0631306>] my_writev+0x2b6/0x6e0 [witdriver]
kernel: [111747.127341] [<ffffffff8146f5f2>] system_call_fastpath+0x16/0x1b
kernel: [111747.127341] [<ffffffff8146f5f2>] system_call_fastpath+0x16/0x1b
kernel: [111747.127361] [<00007f2018ce33c9>] 0x7f2018ce33c8
kernel: [111747.127361] [<00007f2018ce33c9>] 0x7f2018ce33c8

从这个打印,知道了我们当时流程释放页的时候,page的计数为0了,此时的mapping指针还在,说明了不该释放的页给释放了。

这种计数问题本来很头疼,偶然间看到page的index 为:

kernel: [111747.127263] page:ffffea007c1c3f10 count: mapcount: mapping:ffff882b63e766e0 index:0x3ffc------------这个index

查看了其他类似的打印发现这个index都靠近0x4000,而这个0x4000是我们一种业务文件的固定大小。

再查找对应的业务日志,发现当时sendfile调用失败,然后使用writev方式发送文件,而writev的时候,又出现了调用方传送的参数不对的情况,导致我们内核模块在释放内存的时候,

将发送失败那几页page释放多执行了一次。从而使得page计数被减成0了。

void put_page(struct page *page)
{
if (unlikely(PageCompound(page)))
put_compound_page(page);
else if (put_page_testzero(page))//原子计数减,然后判断是否为0,为0则继续释放
__put_single_page(page);
}

这个page因为还在被inode的radix树管理,所以那边读文件找page的时候,发现计数为0,则循环等待,否则加1,这样的话,导致了一个死循环,因为这个计数本来不应该长时间为0,是被

我们释放计数错了才导致为0的。

void free_hot_cold_page(struct page *page, int cold)
{
struct zone *zone = page_zone(page);
struct per_cpu_pages *pcp;
unsigned long flags;
int migratetype;
int wasMlocked = __TestClearPageMlocked(page); #ifdef CONFIG_XEN
WARN_ON(PageForeign(page) && wasMlocked);
#endif
if (!free_pages_prepare(page, ))
return;

最终由于mapping指针不为NULL而在bad_page 的流程中打印警告。

不过这种page会不会used after free呢?不会的,因为page的计数虽然为0,但是并没有放到管理单元中去,假设以后再也不访问这个page,则只会泄露。

这种循环,会因为定时器中断而中断,最终系统hung住:

 kernel: [217186.608729]  [<ffffffff8102735a>] arch_trigger_all_cpu_backtrace+0x5a/0xa0
kernel: [217186.608729] [<ffffffff8102735a>] arch_trigger_all_cpu_backtrace+0x5a/0xa0---------------等回调,
kernel: [217186.608734] [<ffffffff810d0021>] check_cpu_stall+0xe1/0x140
kernel: [217186.608734] [<ffffffff810d0021>] check_cpu_stall+0xe1/0x140
kernel: [217186.608738] [<ffffffff810d00a9>] __rcu_pending+0x29/0x180
kernel: [217186.608738] [<ffffffff810d00a9>] __rcu_pending+0x29/0x180
kernel: [217186.608742] [<ffffffff810d025f>] rcu_check_callbacks+0x5f/0x110
kernel: [217186.608742] [<ffffffff810d025f>] rcu_check_callbacks+0x5f/0x110
kernel: [217186.608748] [<ffffffff81071dff>] update_process_times+0x3f/0x80
kernel: [217186.608748] [<ffffffff81071dff>] update_process_times+0x3f/0x80--------------------------定时中断,更新进程时间等
kernel: [217186.608752] [<ffffffff8109615b>] tick_sched_timer+0x5b/0xc0
kernel: [217186.608752] [<ffffffff8109615b>] tick_sched_timer+0x5b/0xc0
kernel: [217186.608757] [<ffffffff81088a4e>] __run_hrtimer+0xbe/0x1a0
kernel: [217186.608757] [<ffffffff81088a4e>] __run_hrtimer+0xbe/0x1a0
kernel: [217186.608762] [<ffffffff81088d6d>] hrtimer_interrupt+0xed/0x2a0
kernel: [217186.608762] [<ffffffff81088d6d>] hrtimer_interrupt+0xed/0x2a0
kernel: [217186.608767] [<ffffffff81026da3>] smp_apic_timer_interrupt+0x63/0xa0
kernel: [217186.608767] [<ffffffff81026da3>] smp_apic_timer_interrupt+0x63/0xa0
kernel: [217186.608771] [<ffffffff8146fff3>] apic_timer_interrupt+0x13/0x20
kernel: [217186.608771] [<ffffffff8146fff3>] apic_timer_interrupt+0x13/0x20--------------被中断
kernel: [217186.608777] [<ffffffff810fb2c3>] find_get_pages_contig+0x53/0x110
kernel: [217186.608777] [<ffffffff810fb2c3>] find_get_pages_contig+0x53/0x110
kernel: [217186.608782] [<ffffffff811898f1>] __generic_file_splice_read+0x111/0x4c0
kernel: [217186.608782] [<ffffffff811898f1>] __generic_file_splice_read+0x111/0x4c0
kernel: [217186.608786] [<ffffffff81189ceb>] generic_file_splice_read+0x4b/0x90
kernel: [217186.608786] [<ffffffff81189ceb>] generic_file_splice_read+0x4b/0x90
kernel: [217186.608805] [<ffffffffa0be6c5a>] xfs_file_splice_read+0x14a/0x200 [xfs]
kernel: [217186.608805] [<ffffffffa0be6c5a>] xfs_file_splice_read+0x14a/0x200 [xfs]
kernel: [217186.608868] [<ffffffff81188c6c>] splice_direct_to_actor+0xcc/0x1d0
kernel: [217186.608868] [<ffffffff81188c6c>] splice_direct_to_actor+0xcc/0x1d0
kernel: [217186.608874] [<ffffffffa0620a8b>] do_sendfile+0x1db/0x270 [witdriver]
kernel: [217186.608874] [<ffffffffa0620a8b>] do_sendfile+0x1db/0x270 [witdriver]
kernel: [217186.608881] [<ffffffffa0630df0>] my_sendfile+0x2e0/0x540 [witdriver]
kernel: [217186.608881] [<ffffffffa0630df0>] my_sendfile+0x2e0/0x540 [witdriver]
kernel: [217186.608892] [<ffffffff8146f5f2>] system_call_fastpath+0x16/0x1b
kernel: [217186.608892] [<ffffffff8146f5f2>] system_call_fastpath+0x16/0x1b
kernel: [217186.608898] [<00007f2018ce33c9>] 0x7f2018ce33c8
kernel: [217186.608898] [<00007f2018ce33c9>] 0x7f2018ce33c8

linux 内核假死循环导致的问题的更多相关文章

  1. linux内核过高导致vm打开出错修复脚本

    #!/bin/bashVMWARE_VERSION=workstation-15.1.0TMP_FOLDER=/tmp/patch-vmwarerm -fdr $TMP_FOLDERmkdir -p ...

  2. mysql 5.7.15 vs mysql 5.6.31性能测试以及不同linux内核性能比较

    最近,将部分开发和测试环境的mysql升级到5.7之后,今天抽时间测试了下5.6和5.7 PK查询的性能,使用mysqlslap进行测试,测试结果发现在低配下,percona 5.6.31大约比5.7 ...

  3. Linux内核分析:页回收导致的cpu load瞬间飙高的问题分析与思考--------------蘑菇街技术博客

    http://mogu.io/156-156 摘要 本文一是为了讨论在Linux系统出现问题时我们能够借助哪些工具去协助分析,二是讨论出现问题时大致的可能点以及思路,三是希望能给应用层开发团队介绍一些 ...

  4. Linux内核升级导致无法启动,Kernel panic - not syncing Unable to mount root fs on unknown block(0,0)

    问题原因:内核的某次升级,导致系统无法启动. 首先进入recovery模式:引导界面选择-->Ubuntu高级-->出现的选项中选择能够启动的recovery模式(几个内核版本分别试一下) ...

  5. 一个linux内核编译时遇到的perl语法导致的编译问题解决

    在编译linux内核时,遇到了一个比较诡异的问题.具体log如下: Can't locate strict.pm in @INC (you may need to install the strict ...

  6. 升级Linux内核导致vmware无法使用(vmnet模块无法编译)解决方式

    近期将ubuntu升级到了14.04,出现了vmware无法启动的情况. 详细表现为:每次启动的时候都会弹出一个VMWare Kernel Module Updater的对话框,要求依据当前内核版本号 ...

  7. 【漏洞预警】Intel爆CPU设计问题,导致win和Linux内核重设计(附测试poc)

    目前研究人员正抓紧检查 Linux 内核的安全问题,与此同时,微软也预计将在本月补丁日公开介绍 Windows 操作系统的相关变更. 而 Linux 和 Windows 系统的这些更新势必会对 Int ...

  8. Linux内核同步

    Linux内核剖析 之 内核同步 主要内容 1.内核请求何时以交错(interleave)的方式执行以及交错程度如何. 2.内核所实现的基本同步机制. 3.通常情况下如何使用内核提供的同步机制. 内核 ...

  9. 浅析Linux内核同步机制

    非常早之前就接触过同步这个概念了,可是一直都非常模糊.没有深入地学习了解过,最近有时间了,就花时间研习了一下<linux内核标准教程>和<深入linux设备驱动程序内核机制>这 ...

随机推荐

  1. [UE4]纯函数的执行时机

    一.纯函数是在需要的时候被调用 二.纯函数内不应当修改任何数据 三.如果同一个函数需要多个得到多个纯函数的返回值,则多个纯函数的调用顺序不是固定的,并且一个纯函数的调用顺序也不应当影响下一个纯函数的返 ...

  2. [UE4]UMG和关卡坐标变换、旋转小地图

    一.优化上一节的蓝图,新建一个函数addFlagToCanvas(动态添加图标到Canvas) 二. 分析地图坐标系和UMG坐标系 要根据实际情况分析关卡坐标系. UserWidget中的坐标系 三. ...

  3. Mybatis 系列3-结合源码解析properties节点和environments节点

    [Mybatis 系列10-结合源码解析mybatis 执行流程] [Mybatis 系列9-强大的动态sql 语句] [Mybatis 系列8-结合源码解析select.resultMap的用法] ...

  4. Java GC2

    虚拟机中共划分为3个代:年轻代,老年代,持久代:其中持久代主要存放Java类的类信息,与垃圾收集要收集的Java对象关系不大,年轻代和老年代的划分是对垃圾收集影响较大的 年轻代: HotSpot JV ...

  5. 有关于Integer的一些小问题

    先看一小段源码: Integer a1=; Integer a2=; Integer b1=); Integer b2=); Integer c1=; Integer c2=; System.out. ...

  6. c#语言函数

    class Program {访问修饰符 函数名(参数1,参数2){   函数体   return 返回值} 无参数,无返回值 public static void abc()             ...

  7. 深入理解Apache Flink

    Apache Flink(下简称Flink)项目是大数据处理领域最近冉冉升起的一颗新星,其不同于其他大数据项目的诸多特性吸引了越来越多人的关注.本文将深入分析Flink的一些关键技术与特性,希望能够帮 ...

  8. 01-spark基础

    1.定义 Spark是一个由scala语言编写的实时计算系统 Spark支持的API包括Scala.Python.Java .R 2.功能 Spark Core: 将分布式数据抽象为弹性分布式数据集( ...

  9. WPF 各种绑定写法以及用法

    一:{Binding ElementName=grid0, Path=Height} ElementName=grid0:查找到名为grid0的控件. , Path=Height:获取名为grid0的 ...

  10. WPF DataGrid多表头/列头,多行头,合并单元格,一列占据多行

    先上效果图: 思路说明:这是两个DataGrid,没有嵌套,位置和高度保持一致,在加上ScrollViewer滚动条,这就像是在一个DataGrid中. 缺点: 因为最外层有透明的Border,所以没 ...