接到一个问题,反馈D3.16XLARGE256(24块3T本地sata数据盘)机型,3.10内核,在初始化mkfs后mount -a,概率触发mount hung住,需要很长时间(半天左右)才能完成所有盘的挂载,需要排查根因。 本文记录复现场景分析的全过程,发现罪魁祸首源于一个mutex锁,而在高版本内核中对该锁的使用进行了优化,因此TencentOS 5.4内核可以根治这个问题。
复现
首先我们尝试复现问题。
复现方法
脚本mkfs:
代码语言:txt复制#!/bin/sh
count=`ls /dev/ | grep vd|cut -c 1-3|uniq -u |wc -l`
for ((i=1;i<=$count;i ))
do
mkdir /data$i
done
for j in `ls /dev/ | grep vd|cut -c 1-3|uniq -u`
do
echo 'y' | mkfs.ext4 /dev/$j &
done
一开始有怀疑和mount -a并行有关,于是脚本串行mount:
代码语言:txt复制i=1
for j in `ls /dev/ | grep -E '^vd' | cut -c 1-3 | grep -v 'vda'`
do
mount /dev/$j /data$i
(( i))
done
单机问题表现
mount D住(图分别为mount -a,和串行mount某个盘D住):
堆栈在ext4_register_li_request上:
大部分时间D住,但没D死,不然也执行不完:
发现还有一个D进程ext4lazyinit,直觉告诉我就是他导致的问题: 注:ext4lazyinit的机制一句话就可以概括——让mkfs格式化磁盘的io在真正有需要的时候(mount)再去执行
发现每个盘都有写io:
结束后,仍然能看到存在ext4lazyinit单独D住的现象,说明ext4lazyinit本身的执行也很慢:
OS角度
TencentOS Server 3.10内核 , 2 台环境【必现】。 升级到5.4内核问题解决。
使用5.4内核。没有问题。 系统变更到3.10内核,问题【必现】。再升级回5.4问题解决。
到这里,基本能看出来3.10必现,5.4没有问题。
但是两个内核也存在以下共同点: ext4lazyinit会跑很久,大部分时间在D; 机器各盘都会有持续的io;
问题现象角度
存在以下几种复现的情况:
mkfs->mount概率复现
mkfs->mount如果没复现->直接umount必现
mkfs->mount复现后->umount->再mount不复现
mkfs->mount复现后->umount->重新mkfs->再mount复现(或再umount复现)
疑惑
- 3.10 mount为什么会卡慢,为什么5.4不会
- 为什么不是mount必现
- 为什么mount不复现后umount可以复现
- ext4lazyinit慢是否正常,为什么慢 下面会尝试解答这些疑问。
分析
是谁拖慢了mount?
在复现的现场,多来几次live crash大法,答案显而易见,凶手呼之欲出。 截取其中一次分析为例:
代码语言:txt复制crash> ps -l | grep UN
[5241570371969] [UN] PID: 25036 TASK: ffff883ed30b8000 CPU: 0 COMMAND: "jbd2/vdl-8"
[5241560582065] [UN] PID: 24623 TASK: ffff881f8db1b3a0 CPU: 0 COMMAND: "ext4lazyinit"
[5241365143847] [UN] PID: 25759 TASK: ffff881f8c7019d0 CPU: 10 COMMAND: "mount"
crash> bt ffff881f8c7019d0 -z
PID: 25759 TASK: ffff881f8c7019d0 CPU: 10 COMMAND: "mount"
#0 [ffff881f7d807b70] __schedule () at ffffffff819d023e
#1 [ffff881f7d807bd8] schedule_preempt_disabled () at ffffffff819d1659
#2 [ffff881f7d807be8] __mutex_lock_slowpath (atomic_t * arg0= ffff881ea9af3658) at ffffffff819cf7c1
#3 [ffff881f7d807c48] mutex_lock (struct mutex * arg0= ffff881ea9af3658) at ffffffff819cf13f
#4 [ffff881f7d807c60] ext4_register_li_request (struct super_block * arg0= ffff883f5ee88000, ext4_group_t arg1= 0000000000000000) at ffffffff812586d4
#5 [ffff881f7d807ca8] ext4_fill_super (struct super_block * arg0= ffff883f5ee88000, void * arg1= 0000000000000000, int arg2= 0000000000000000) at ffffffff8125bf24
bt: invalid size request: -1 type: "read stack arg"
#6 [ffff881f7d807dc8] mount_bdev (struct file_system_type * arg0= ffffffff81f80880, int arg1= 0000000000000000, const char * arg2= ffffffff81f80880, void * arg3= 0000000000000000, int (*)(struct super_block * arg4= ffffffff812592d0, void * arg5= ffff883f620c5ba0, int) arg6= 0000000000000000) at ffffffff8118f8b8
#7 [ffff881f7d807e38] ext4_mount (struct file_system_type * arg0= ffffffff81f80880, int arg1= 0000000000000000, const char * arg2= ffffffff81f80880, void * arg3= 0000000000000000) at ffffffff8124f155
#8 [ffff881f7d807e48] mount_fs (struct file_system_type * arg0= ffffffff81f80880, int arg1= 0000000000000000, const char * arg2= ffff883f620c5ba0, void * arg3= 0000000000000000) at ffffffff81190255
#9 [ffff881f7d807e70] vfs_kern_mount (struct file_system_type * arg0= ffffffff81f80880, int arg1= 0000000000000000, const char * arg2= ffff883f620c5ba0, void * arg3= 0000000000000000) at ffffffff811aa84f
#10 [ffff881f7d807ea8] do_mount (const char * arg0= ffff883f620c5ba0, const char * arg1= ffff881f8f163020, const char * arg2= ffff883f5c8a3c98, unsigned long arg3= 00000000c0ed0000, void * arg4= 0000000000000000) at ffffffff811acced
#11 [ffff881f7d807f28] sys_mount () at ffffffff811ad616
#12 [ffff881f7d807f80] system_call_fastpath () at ffffffff81aab479
RIP: 00007f6230ac915a RSP: 00007ffe5419e0e8 RFLAGS: 00010246
RAX: 00000000000000a5 RBX: ffffffff81aab479 RCX: 0000000000000010
RDX: 00007f6233904600 RSI: 00007f6233902230 RDI: 00007f6233902140
RBP: 0000000000000000 R8: 0000000000000000 R9: 0000000000000010
R10: 00000000c0ed0000 R11: 0000000000000206 R12: 00007f6233902040
R13: 0000000000000000 R14: 00007f6233904600 R15: 00007f6233902140
ORIG_RAX: 00000000000000a5 CS: 0033 SS: 002b
crash> mutex ffff881ea9af3658
struct mutex {
count = {
counter = -1
},
wait_lock = {
{
rlock = {
raw_lock = {
lock = 0 '