linux 3.10内核 xfs的一次io异常导致的hung crash_weixin_34023863的博客-程序员宝宝

技术标签: 操作系统  

8556395.925003] XFS (sdi): xfs_log_force: error -5 returned.
[8556407.425047] INFO: task umount:19286 blocked for more than 1200 seconds.----这个默认是120,该环境上是被人为设置1200
[8556407.425653] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[8556407.426050] umount          D ffff881fffdd47c0     0 19286  19283 0x00000080------------------------19286是pid,19283是ppid
[8556407.426056]  ffff883e39587d80 0000000000000082 ffff883e39587fd8 ffff883e39587fd8
[8556407.426066]  ffff883e39587fd8 00000000000147c0 ffff881fd3260000 ffff881f860fec80
[8556407.426072]  ffff883ed79e1a20 ffff881f860fecc0 ffff881f860fece8 ffff881f860fec90------------这12个64位的值为栈里的值
[8556407.426078] Call Trace:
[8556407.426092]  [<ffffffff8163e879>] schedule+0x29/0x70
[8556407.426137]  [<ffffffffa07c6cd1>] xfs_ail_push_all_sync+0xc1/0x110 [xfs]
[8556407.426143]  [<ffffffff810a7610>] ? wake_up_atomic_t+0x30/0x30
[8556407.426165]  [<ffffffffa07b1b98>] xfs_unmountfs+0x68/0x190 [xfs]
[8556407.426186]  [<ffffffffa07b267b>] ? xfs_mru_cache_destroy+0x6b/0x90 [xfs]
[8556407.426204]  [<ffffffffa07b4a52>] xfs_fs_put_super+0x32/0x90 [xfs]
[8556407.426211]  [<ffffffff811e3026>] generic_shutdown_super+0x56/0xe0-------已经执行完fsnotify_umount_inodes
[8556407.426215]  [<ffffffff811e3477>] kill_block_super+0x27/0x70
[8556407.426218]  [<ffffffff811e37b9>] deactivate_locked_super+0x49/0x60
[8556407.426222]  [<ffffffff811e3db6>] deactivate_super+0x46/0x60
[8556407.426229]  [<ffffffff81200d25>] mntput_no_expire+0xc5/0x120
[8556407.426234]  [<ffffffff812025cb>] SyS_umount+0x15b/0x5b0
[8556407.426239]  [<ffffffff81649909>] system_call_fastpath+0x16/0x1b
[8556407.426242] sending NMI to all CPUs:

对应的函数为:

/*
 * Push out all items in the AIL immediately and wait until the AIL is empty.
 */
void
xfs_ail_push_all_sync(
    struct xfs_ail  *ailp)
{
    struct xfs_log_item    *lip;
    DEFINE_WAIT(wait);

    spin_lock(&ailp->xa_lock);
    while ((lip = xfs_ail_max(ailp)) != NULL) {
        prepare_to_wait(&ailp->xa_empty, &wait, TASK_UNINTERRUPTIBLE);
        ailp->xa_target = lip->li_lsn;
        wake_up_process(ailp->xa_task);
        spin_unlock(&ailp->xa_lock);
        schedule();
        spin_lock(&ailp->xa_lock);
    }
    spin_unlock(&ailp->xa_lock);

    finish_wait(&ailp->xa_empty, &wait);
}

 排查的时候走了弯路,因为看的是:

crash> dis -l xfs_ail_push_all_sync+0xc1
/usr/src/debug/kernel-3.10.0-327.22.2.el7/linux-3.10.0-327.22.2.el7.x86_64/include/linux/spinlock.h: 293
0xffffffffa07c6cd1 <xfs_ail_push_all_sync+193>: mov    %r13,%rdi

所以想当然地认为在第一个 获取spinlock的地方,

spin_lock(&ailp->xa_lock);---------以为在这hung住
    while ((lip = xfs_ail_max(ailp)) != NULL) {
    

然后查找这把锁:

  crash>  struct super_block.s_fs_info ffff883f7fe67800
  s_fs_info = 0xffff883f7fe67000
crash> mod -s xfs
     MODULE       NAME                   SIZE  OBJECT FILE
ffffffffa0803d40  xfs                  939714  /lib/modules/3.10.0-327.22.2.el7.x86_64/kernel/fs/xfs/xfs.ko
crash> struct -xo  xfs_mount.m_ail 0xffff883f7fe67000
struct xfs_mount {
  [ffff883f7fe67010] struct xfs_ail *m_ail;
}

 struct   xfs_mount.m_ail 0xffff883f7fe67000
  m_ail = 0xffff881f860fec80


crash> struct -xo  xfs_ail.xa_lock 0xffff881f860fec80
struct xfs_ail {
  [ffff881f860fecc0] spinlock_t xa_lock;
}

而且这把锁的值是:

crash> struct   xfs_ail.xa_lock 0xffff881f860fec80
  xa_lock = {
    {
      rlock = {
        raw_lock = {
          {
            head_tail = 2406518640,
            tickets = {
              head = 36720,
              tail = 36720
            }
          }
        }
      }
    }
  }

我一看到这个是非0值,想当然认为是被持有了,为了验证我的想法,我甚至随便找了一把锁查看它的值,点背的时候,喝凉水都塞牙,我随手选择的锁是:

crash> p gc_lock
gc_lock = $1 = {
  {
    rlock = {
      raw_lock = {
        {
          head_tail = 0,
          tickets = {
            head = 0,
            tail = 0
          }
        }
      }
    }
  }
}

后来仔细看了在没有开启 CONFIG_QUEUED_SPINLOCKS 的情况下,锁的定义才是如此,否则的话,是如下:

#ifndef __GENKSYMS__
typedef struct qspinlock {
    atomic_t    val;
} arch_spinlock_t;
#else
typedef u32 __ticketpair_t;

typedef struct arch_spinlock {
    union {
        __ticketpair_t    head_tail;
        struct __raw_tickets {
            __ticket_t head, tail;
        } tickets;
    };
} arch_spinlock_t;
#endif

所以要么0,要么1的情况只适合于第一种定义,以前因为业务默认配置的config问题,查的锁相关的crash,大多是第一种定义,但是当时没注意到这个细节,只是简单扫了一眼,浪费我两个小时,所以下盘不稳总会摔。

查看running状态的都没有持有这把锁,(其实按照第二种定义,是正常的,因为此时本就没人持有这把锁,因为head和tail相等)比较奇怪,后来找同事讨论,同事认为是while循环没跳出,所以获取锁的那行是schedule下面那行,还没有执行。

想起来自己曾经写过的博客《https://www.cnblogs.com/10087622blog/p/9558024.html》,应该是如此

void
xfs_ail_push_all_sync(
    struct xfs_ail  *ailp)
{
    struct xfs_log_item    *lip;
    DEFINE_WAIT(wait);

    spin_lock(&ailp->xa_lock);
    while ((lip = xfs_ail_max(ailp)) != NULL) {
        prepare_to_wait(&ailp->xa_empty, &wait, TASK_UNINTERRUPTIBLE);
        ailp->xa_target = lip->li_lsn;
        wake_up_process(ailp->xa_task);
        spin_unlock(&ailp->xa_lock);
        schedule();--------------------这个和while循环一直跳不出去,
        spin_lock(&ailp->xa_lock);
    }
    spin_unlock(&ailp->xa_lock);

    finish_wait(&ailp->xa_empty, &wait);
}

跳不出去的原因跟io相关,也就是wake_up 相关的内核线程之后,内核线程还是没有完成对应的任务:

crash> struct xfs_ail.xa_task 0xffff881f860fec80
  xa_task = 0xffff883f8901dc00

crash> task_struct.pid 0xffff883f8901dc00
  pid = 42726

crash> set 42726
    PID: 42726
COMMAND: "xfsaild/sdi"
   TASK: ffff883f8901dc00  [THREAD_INFO: ffff881f3d828000]
    CPU: 17
  STATE: TASK_INTERRUPTIBLE
crash> bt
PID: 42726  TASK: ffff883f8901dc00  CPU: 17  COMMAND: "xfsaild/sdi"
 #0 [ffff881f3d82bcd0] __schedule at ffffffff8163df9b
 #1 [ffff881f3d82bd38] schedule at ffffffff8163e879
 #2 [ffff881f3d82bd48] schedule_timeout at ffffffff8163c295
 #3 [ffff881f3d82bdf8] xfsaild at ffffffffa07c6a4f [xfs]
 #4 [ffff881f3d82bec8] kthread at ffffffff810a661f
 #5 [ffff881f3d82bf50] ret_from_fork at ffffffff81649858

xfsaild 无法完成的原因也是因为IO异常:

附部分相关io异常的message日志:

kernel: sd 5:0:8:0: [sdi] CDB: Read(16) 88 00 00 00 00 00 03 4c b0 48 00 00 00 08 00 00
kernel: sd 5:0:8:0: [sdi] CDB: Read(16) 88 00 00 00 00 00 15 32 8a 50 00 00 03 30 00 00
kernel: blk_update_request: I/O error, dev sdi, sector 355634560
kernel: sd 5:0:8:0: rejecting I/O to offline device
kernel: XFS (sdi): metadata I/O error: block 0xee173de0 ("xfs_trans_read_buf_map") error 5 numblks 8
kernel: XFS (sdi): metadata I/O error: block 0x15da29d90 ("xfs_trans_read_buf_map") error 5 numblks 32
kernel: sd 5:0:8:0: rejecting I/O to offline device
kernel: XFS (sdi): xfs_imap_to_bp: xfs_trans_read_buf() returned error -5.
kernel: XFS (sdi): metadata I/O error: block 0xeca8a480 ("xfs_trans_read_buf_map") error 5 numblks 8
kernel: sd 5:0:8:0: rejecting I/O to offline device
kernel: sd 5:0:8:0: rejecting I/O to offline device

对应的bug解决可以参照:https://bugzilla.redhat.com/show_bug.cgi?id=1267042

转载于:https://www.cnblogs.com/10087622blog/p/10729687.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_34023863/article/details/93212961

智能推荐

Vue 组件间的样式污染_Wu.vue.js的博客-程序员宝宝_vue组件样式污染

1.多个组件的样式会互相影响原因:组件天生隔离,可是在 Vue 当中,运行的载体还是浏览器,所有的样式类还是会通过

强化学习算法:DQN系列详解_困比比的博客-程序员宝宝

文章目录SarsaQ-LearningDQNDouble DQNDueling DQNReferences:SarsaSarsa 的名称来源于下图所示的序列描述:给定一个状态SSS,个体通过行为策略产生一个行为AAA,即产生一个状态行为对(S,A)(S,A)(S,A),环境收到个体的行为后会返回即时奖励RRR以及后续状态S’S’S’;个体在状态S’S’S’ 时遵循当前的行为策略产生一个新行为A...

android中的资源_SANDKING2015的博客-程序员宝宝

一、概括地讲,android中的资源是指非代码部分,比如图片、MP3、字符串、xml文件等。在一个android工程中,和src源文件夹并列的有两个文件夹,分别叫做res和assets,都是用来保存资源文件的。不同点:1.res中的资源可以通过R资源类直接访问。这种方式比较常用。 res中有包含各种子文件夹,对资源进行分类: anim(xml动画文件)、drawable(图片),la...

请邮递员把这封信在六个月后送给我!_赫于富的博客-程序员宝宝

致六个月后自己- 你好,赫于富,现在应该是2月5号左右,你现在应该比六个月前有很大的进步吧? 英语你应该过四级了吧? mini story 10 个应该也完成了吧? 突破口语了吧? 可以自然的使用英语对话了吗?六个月前的你还正在进行mini stroy 第一个故事,还在不断的重复音标的学习,甚至还在怀疑现在的英语学习究竟有没有用,六个月前的你每天都6点早早的开始晨读,每天四个小...

C# 强制垃圾回收 GC_风干牛肉巴旦木的博客-程序员宝宝

在需要调用垃圾回收的地方调用ClearMemory()public static void ClearMemory(){ GC.Collect(); GC.WaitForPendingFinalizers(); if (Environment.OSVersion.Platform == PlatformID.Win32NT) { SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle, -1,

java变量判断代码自动生成_Java单测代码生成工具Evosuite_步步指南的博客-程序员宝宝

一、EvoSuite简介EvoSuite 是由 Sheffield 等大学联合开发的一种开源工具,用于自动生成测试用例集,生成的测试用例均符合 Junit的标准,可直接在 Junit 中运行。通过使用此自动测试工具能够在保证代码覆盖率的前提下极大地提高测试人员的开发效率。但是只能辅助测试,并不能完全取代人工,测试用例的正确与否还需人工判断。1.1 核心功能:对于指定类,生成 Junit4 类型的单...

随便推点

树莓派3B+安装配置samba_zhangjun62的博客-程序员宝宝

安装软件sudo apt-get install samba samba-common-bin修改配置文件sudo vim /etc/samba/smb.conf配置每个用户可以读写自己的home目录,在“[homes]”节中,把“read only = yes”改为“read only = no”重启samba服务sudo /etc/init.d/samba re...

如何修改Google Adsense广告位的宽高_ConstXiong的博客-程序员宝宝

在自己的博客网站放了 Google Adsense 的广告,但是样式和网站整体的风格都不太搭。1、希望设置正方形的广告位的宽度查了下文档可以修改 &lt;ins&gt; 节点的 style 参数,如我希望宽度设置位 div 宽度的 80% 降低广告位的透明度 在 div 中居中修改代码如下:&lt;script async src="https://pagead2.g...

大牛手把手带你!mysql详细教程_普通网友的博客-程序员宝宝

一、对Kafka的认识1.Kafka的基本概念2.安装与配置3.生产与消费4.服务端参数配置二、生产者1.客户端开发2.原理分析3.重要的生产者参数三、消费者1.消费者与消费组2.客户端开发四、主题与分区1.主题的管理2.初识KafkaAdminCilent3.分区的管理4.如何选择合适的分区数五、日志存储1.文件目录布局2.日志格式的演变3.日志索引4.日志清理5.磁盘存储六、深入服务端1.协议设计2.时间轮3.延时操作4.控制器

jQuery.validator 参数使用javascript方式调用属性_蟠龙有悔的博客-程序员宝宝

使用 validator 添加自定义方法 时候,刚好要用到 element 调用下它自身的属性,发现用 element.attr('xxx') 调用,浏览器会提示: TypeError: Object # has no method 'attr'  但是element并不是不可以调用函数的,试着用javascript方式调用下它的值:element.value ,然后加到弹窗里。浏览器刷新

pandas异常值检测与处理_lizz2276的博客-程序员宝宝_pandas处理异常值

1、异常值检测1.1、标准差法outlier&gt;x¯+nσ或outlier&lt;x¯−nσx¯ 为样本均值, σ 为样本标准差 当n=2时,满足条件的观测值就为异常值,当n=3时满足条件的观测就是极端异常值1.2、箱线图法outlier&gt;\Q3+nIQR或outlier&lt;\Q1−nIQR\Q3 为上四分位数(75%), \Q1 为下四分位数(25%), IQR 为上四分位与下四分位的差 当n=1.5时,满足条件的观测值就为异常值,当n=3时满足条件的观测就是极端异常值

【ELK】Elasticsearch 2.4 API调用小记_dazhuang32333的博客-程序员宝宝

官方文档地址:https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html1.1. 简介Elasticsearch的JAVA API运行在9300端口上,而通过9200端口则可以与它的RESTful API进行通信,它提供了许多API,如文档API、搜索API、索引API、集群API、状态查询...