(WIP)SSD上的I/O电梯算法与HugePage设置可能导致的Crash(by quqi99)

作者:张华  发表于:2016-03-24
版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声明
( http://blog.csdn.net/quqi99 )

问题

虚机里的某个进程Hang住了,使用”cat /proc/diskstats”命令查看一个SSD硬盘上有很多请求列队。

hung_task_timeout_secs参数与D状态

进程等待IO时如果处于D状态,即TASK_UNINTERRUPTIBLE状态,处于这种状态的进程不处理信号,所以kill不掉,如果进程长期处于D状态,那么肯定不正常,原因可能有二:

  1. IO路径上的硬件出问题了,比如硬盘坏了(只有少数情况会导致长期D,通常会返回错误);
  2. 内核自己出问题了。

这种问题不好定位,而且一旦出现就通常不可恢复,kill不掉,通常只能重启恢复了。内核针对这种开发了一种hung task的检测机制,基本原理是:定时检测系统中处于D状态的进程,如果其处于D状态的时间超过了指定时间(默认120s,可以配置),则打印相关堆栈信息,也可以通过proc参数配置使其直接panic (也可能内核发生了其他错误触发crash,crash时间过长越过2分钟它自己的进程也会被hung task误检测出来为D状态)。
1)设置timeout时间:
   echo 120 > /proc/sys/kernel/hung_task_timeout_secs
2)设置hung task后是否触发panic
   echo 1 > /proc/sys/kernel/hung_task_panic

Hugepage与D状态

逻辑地址到线性地址的转换由分段来做,线性地址到物理地址的转换由分页来做。默认每页是4K,为了减少分页映射表的条目,可以增加页的尺寸,Hugepage因此得名。THP(Transparent Huge Pages)是一个使管理Huge Pages自动化的抽象层(由于实现方式问题,THP会造成内存锁影响性能,尤其是在程序不是专门为大内内存页开发的时候,因为khugepaged会在后台扫描所有进程占用的内存,在可能的情况下会把4K page交换为Huge Pages,在这个过程中需要分配内存锁影响性能)。在redhat6中由khugepaged进程在开机时自动启动,如果想关闭它的话可以:
1, echo "never" > /sys/kernel/mm/redhat_transparent_hugepage/enabled
   cat /sys/kernel/mm/redhat_transparent_hugepage/enabled 
   always madvise [never] 
2, or using cmdline, transparent_hugepage=never
never选项将清除TRANSPARENT_HUGEPAGE_FLAG和TRANSPARENT_HUGEPAGE_REQ_MADV_FLAG中的bit值,

内存锁与D状态

有进程为了使其不被转换到SWAP中降低效率会调用mlock来锁定内存,mlock会调用lru_add_drain_all对每个cpu下发work函数lru_add_drain_per_cpu回刷pagevec,然后调用flush_work等待完成,flush_work(kworker)又会调wait_for_completion,继尔调用do_wait_for_common将进程设置为D状态。

static long __sched
wait_for_common(struct completion *x, long timeout, int state)
{
return __wait_for_common(x, schedule_timeout, timeout, state);
}

static inline long __sched
__wait_for_common(struct completion *x,
 long (*action)(long), long timeout, int state)
{
might_sleep();

spin_lock_irq(&x->wait.lock);
timeout = do_wait_for_common(x, action, timeout, state);
spin_unlock_irq(&x->wait.lock);
return timeout;
}

do_wait_for_common(struct completion *x,
  long (*action)(long), long timeout, int state)
{
if (!x->done) {
DECLARE_WAITQUEUE(wait, current);

__add_wait_queue_tail_exclusive(&x->wait, &wait);
do {
if (signal_pending_state(state, current)) {
timeout = -ERESTARTSYS;
break;
}
__set_current_state(state);
spin_unlock_irq(&x->wait.lock);
timeout = action(timeout);
spin_lock_irq(&x->wait.lock);
} while (!x->done && timeout);
__remove_wait_queue(&x->wait, &wait);
if (!x->done)
return timeout;
}
x->done--;
return timeout ?: 1;
}

缺页时的D状态

其他进程缺页时也会进入D状态(缺页的都会是D状态), 缺页中断服务程序do_page_fault会调用down_read(&mm->mmap_sem)加读锁,然后再调__down_read, 再调rwsem_down_failed_common设置D状态:
    /* wait to be given the lock */
    for (;;) {
        //已经获取读锁,跳出死循环
        if (!waiter.task)
            break;
        schedule();  //否则,调度出去,放弃CPU
        //调度回来后重设状态
        set_task_state(tsk, TASK_UNINTERRUPTIBLE);
    }
    //获取锁后改成R状态
    tsk->state = TASK_RUNNING;

如何crash的

这个网页(http://www.oenhan.com/rwsem-realtime-task-hung)描述了一种crash的情况,上述的kworker进程进入了D状态,如果这时有另外一个实时进程H的优先级大于kworker的话,采用FIFO的调度模式,且H在大量业务的话那它会一直抢占CPU不释放,那样导致kworker一直得不到调度,直接导致kworker进程D状态触发hung_task_timeout_secs直接死掉。

同一个CPU核上进程有一个H2,而且H1和H2都是被cpu绑定到5核上,H2处理主要业务,H1辅助,H2实时优先级高,H1实时优先级低,当H2压力大占用100% CPU时,H1就得不到调度了。
高业务压力下,H2一直占用CPU,是R状态,H1得不到调度,是S状态。首先是khugepaged扫描时获取写锁,同时包含H2的多个H线程因缺页中断申请读锁,H2处于D状态被schedule让出CPU,H1也恰好缺页中断,获得CPU后申请读锁,排在H2后面,也是D状态。khugepaged释放写锁后,khugepaged先将所有等待读锁的进程拉入读写锁,并将其置成TASK_WAKING状态(参考__rwsem_do_wake函数)。H2先调度回来获取了读锁并完全占用了5核CPU,本来读锁支持并发,但H1此时没有了CPU可供使用,没有调度,一直在schedule打转,虽然进程没有调度,但H1已经被khugepaged拉到读写锁,占用了读锁,一直不释放,khugepaged申请写锁也不能完成,后续更多H缺页中断申请读锁也被阻塞住,D状态达到20s。至于后续能恢复,是因为H2再次因为缺页要申请读锁,排队到队列,进入D状态,schedule让出CPU,H1才能再次得到CPU,完成工作后释放读锁。

解决办法

虚机里的I/O路径是: Application -> File/Block in VM -> virtio-blk driver in VM -> virtio-backend driver in Host -> File/Block in Host -> SSD disk in Host

  • VM里面(File/Block in VM -> virtio-blk driver in VM), 因为跑在QEMU里,Guest机的I/O调度算法应该使用elevator=noop
  • Hypervisor端(virtio-blk driver in VM -> virtio-backend driver in Host), 两种I/O机制(io=‘native‘ or io=‘threads‘),五种缓存机制(writethrough, writeback, none, directsync, unsafe), 例:<driver name=‘qemu‘ type=‘raw‘ cache=‘writethrough‘ io=‘native‘/>
  • Host里面(File/Block in Host -> SSD disk in Host ),由于使用SSD, I/O调度算法应该使用elevator=noop

故需要在grub中添加cmdline启动参数及关闭khugepaged进程:transparent_hugepage=never elevator=noop , 另外,

附件一,如何确认I/O调度算法

[email protected]:~$ sudo lsblk -io KNAME,TYPE,SCHED
KNAME TYPE SCHED
sda   disk deadline
sda1  part deadline
sda2  part deadline
sda5  part deadline
sda6  part deadline
sda7  part deadline
sda8  part deadline
sda9  part deadline
sda10 part deadline
sdb   disk deadline

[email protected]:~$ cat /sys/block/sda/queue/scheduler 
noop [deadline] cfq
http://www.circlingcycle.com.au/Unix-sources/Linux-check-IO-scheduler-and-discard-support.pl.txt
[email protected]:~$  perl ./Linux-check-IO-scheduler-and-discard-support.pl 
INFO: File systems and raids
NAME    FSTYPE LABEL MOUNTPOINT
sda                  
├─sda1               [SWAP]
├─sda2               
├─sda5               /bak
├─sda6               /data1
├─sda7               /win
├─sda8               /data2
├─sda9               /
└─sda10              /images
sdb

INFO: Block devices
NAME    ALIGNMENT  MIN-IO OPT-IO PHY-SEC LOG-SEC ROTA SCHED    RQ-SIZE
sda             0    4096      0    4096     512    1 deadline     128
├─sda1          0    4096      0    4096     512    1 deadline     128
├─sda2       1024    4096      0    4096     512    1 deadline     128
├─sda5          0    4096      0    4096     512    1 deadline     128
├─sda6          0    4096      0    4096     512    1 deadline     128
├─sda7          0    4096      0    4096     512    1 deadline     128
├─sda8          0    4096      0    4096     512    1 deadline     128
├─sda9          0    4096      0    4096     512    1 deadline     128
└─sda10         0    4096      0    4096     512    1 deadline     128
sdb             0 1048576   2048     512     512    1 deadline     128

INFO: I/O elevator (scheduler) and discard support summary
INFO: Hard Disk sda configured with I/O scheduler "deadline" 
INFO: Hard Disk sdb configured with I/O scheduler "deadline" supports discard operation

时间: 2024-10-13 05:08:36

(WIP)SSD上的I/O电梯算法与HugePage设置可能导致的Crash(by quqi99)的相关文章

文件系统在NVMe SSD上的性能表现分析

文件系统是访问存储的一种常用方式,目前常用的文件系统都是针对磁盘的特性进行设计的.例如,为了解决磁盘随机小数据访问的问题,在文件系统层面引入了Page cache机制,利用内存缓存对这种访问进行加速.大多数业务都会存在数据局部性,因此,通过这种Page cache机制可以很好的提升文件系统的性能.另外,文件系统的数据布局也会考虑磁盘的特性,元数据聚合存放在一起,这样可以高效的实现元数据的存放,避免磁盘抖动.如下图描述,包括文件系统在内的存储软件栈在各个层次都会对磁盘抖动问题进行优化. 在NVMe

可以在SSD上建传统RAID吗?

当被问及"在SSD上能否建传统RAID"这个问题的时候,大家的第一反应应该是"可以建,但是需要Trim命令的支持".在网上也可以看到很多人拿SSD来建RAID,但基本上都会配置成RAID0或者RAID1.很少有人会去建RAID5,这是为什么呢? 答案很简单,在SSD基础上如果配置类似于RAID5这样的Parity-RAID,那么SSD的整体性能不能很好的发挥出来,更为重要的是Parity-RAID会影响SSD的寿命.一句话,Traditional RAID kill

SSD上如何进行数据保护?

来自存储老吴的博客--存储之道 闪存技术的发展使得其成本下降.容量增加,越来越多的企业级用户也都在考虑如何将闪存SSD技术应用到自己的环境中去,从而解决性能.功耗.体积等存储常见问题.前几年闪存技术主要在互联网领域得到了大量应用,其主要原因在于互联网需要面临大量的访问IO压力,传统的磁盘存储系统无法提供高IOPS的能力,所以,只能借助闪存的高性能来解决互联网发展过程中的难题.所以,今天闪存在互联网领域已经得到大量应用,并成为其标配. 在闪存应用的过程中,PCIe接口在存储上的应用起到了巨大的成功

SSD上安装win7

本来弄个SSD是个开心事,结果比较头疼的是只要选了AHCI模式就装不上系统,废话少说,直接上解决方案: 1.先选择IDE模式装Win7. 2.正常进入系统后,在运行里输入regedit,然后敲回车,进入注册表. 3.找到并单击下面的注册表子项: HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Msahci 4.将右窗格中的start的数值改为0(以前的键值是3),然后确定,退出注册表,重启电脑. 5.进入BIOS更改位AHCI模式,然后保

数据的加密传输——单片机上实现TEA加密解密算法(转)

源:数据的加密传输——单片机上实现TEA加密解密算法 各位大侠在做数据传输时,有没有考虑过把数据加密起来进行传输,若在串口或者无线中把所要传的数据加密起来,岂不是增加了通信的安全性.常用的加密解密算法比如DES.RSA等,受限于单片机的内存和运算速度,实现起来比较困难,但一种叫TEA的加密算法特别适合单片机使用. TEA(Tiny Encryption Algorithm)是一种简单高效的加密算法,以加密解密速度快,实现简单著称.算法很简单,TEA算法每一次可以操作64-bit(8-byte),

故障现象:Win7 访问共享时输入正确密码仍然提示密码错误,此帐号在其它机器上可以正常使用,排除帐号密码不对导致的问题。

解决方案一 安装win7的机器日期不对,调整后故障排除. 解决方案二 1.直接按下win+r键,输入secpol.msc,打开本地安全策略.2.找到"安全设置"的"本地策略"的"安全选项"3.在右边一栏找到"网络安全:LAN管理器身份验证级别",双击进入4.在默认状态选项下,英文版应该为"no defined",中文版为空.下拉那个默认选项,选择"仅发送NTLM响应"重启后故障排除. 故

『HTML5实现人工智能』小游戏《井字棋》发布,据说IQ上200才能赢【算法&amp;代码讲解+资源打包下载】

一,什么是TicTacToe(井字棋) 本游戏为在下用lufylegend开发的第二款小游戏.此游戏是大家想必大家小时候都玩过,因为玩它很简单,只需要一张草稿纸和一只笔就能开始游戏,所以广受儿童欢迎.可能我说了半天,对它名字不熟悉的朋友也不懂我在说神马.那没关系,我就引用Wiki(维基百科)的介绍作为大家对它名字的认识,顺便也勾起我们儿时的回忆: 井字棋,大陆.台湾又称为井字游戏.圈圈叉叉:另外也有打井游戏.OX棋的称呼,香港多称井字过三关.过三关,是种纸笔游戏.两个玩家,一个打圈(O),一个打

android上的缓存、缓存算法和缓存框架

1.使用缓存的目的 缓存是存取数据的临时地,因为取原始数据代价太大了,加了缓存,可以取得快些.缓存可以认为是原始数据的子集,它是从原始数据里复制出来的,并且为了能被取回,被加上了标志. 在android开发中,经常要访问网络数据比如大量网络图片,如果每次需要同一张图片都去网络获取,这代价显然太大了.可以考虑设置本地文件缓存和内存 缓存,存储从网络取得的数据:本地文件缓存空间并非是无限大的,容量越大读取效率越低,可设置一个折中缓存容量比如10M,如果缓存已满,我们需要采用合 适的替换策略换掉一个已

复杂度分析(上)如何分析统计算法的执行效率和资源消耗

一.什么是复杂度分析? 数据结构和算法解决是“如何让计算机更快时间.更省空间的解决问题”. 因此需从执行时间和占用空间两个维度来评估数据结构和算法的性能. 分别用时间复杂度和空间复杂度两个概念来描述性能问题,二者统称为复杂度. 复杂度描述的是算法执行时间(或占用空间)与数据规模的增长关系. 二.为什么要进行复杂度分析? 2.1 事后统计法 2.2.1 概念 通过运行代码跑,统计.监控,得到算法执行的时间和占用的内存大小. 2.2.2 劣势 测试结果非常依赖测试环境.测试环境中硬件的不同会对测试结