文件系统损坏通常导致进程(或系统)挂起也就不足为奇了。

但是有时,看起来干净的文件系统仍可能导致进程挂起。

在本文中,我们介绍了创建具有空扩展属性(EA)条目的,启用访问控制列表(ACL)的增强型日记文件系统(JFS2)索引节点的方法,并研究了它如何导致进程挂起。 本文还概述了解决此类JFS2索引节点导致的进程挂起的方法。

设置AIXC ACL的扩展权限

AIXC ACL包括基本权限和扩展权限。 基本权限是分配给文件所有者,文件组和其他用户的传统文件访问模式。 扩展权限通过允许,拒绝或指定特定个人,组或用户和组组合的访问模式来修改(所有者,组或其他人的)基本文件权限。

要为/ testfs / foo文件启用ACL并向用户添加特定权限,我们可以使用acledit命令:

# export EDITOR=/usr/bin/vi; acledit /testfs/foo

然后,我们可以使用vi命令将扩展权限更改为enabled并添加特定权限:

** ACL_type   AIXC*attributes:base permissionsowner(root):  rw-group(system):  r--others:  r--extended permissionsenabledpermit   rwx     u:binShould the modified ACL be applied? (yes) or (no) yes

我们可以运行aclget 检查文件的ACL。

inode中的扩展属性描述符

许多应用程序要求具有将可变长度控制信息与文件系统对象相关联的能力。 这些对象称为扩展属性或EA。 di_ea节点di_ea的EA描述符描述了di_ea节点是否为其存储了任何EA。 如果索引节点确实具有与其关联的EA,则EA描述符还将描述与索引节点关联的索引节点扩展。 EA描述符在j2_types.head_t定义:

typedef struct {uint8   flag;      /* 1: flags */uint8   nEntry;    /* 1: */uint8   len;       /* 1: length in unit of fsblksize */uint8   addr1;     /* 1: address in unit of fsblksize */uint32  addr2;     /* 4: address in unit of fsblksize */uint16  type;      /* 2: ea type */int16   nblocks;   /* 2: nBlocks for outline pages */int32   rsrvd;     /* 4: */} ead_t; /* 16 */

创建一个具有空EA条目的启用ACL的JFS2索引节点

启用ACL后,inode的di_ea.nEntry通常不会为零。 为了进行测试,我们需要为启用了ACL的inode故意将di_ea.nEntry设置为0。 我们有几种方法可以完成它。

使用fsdb修改inode

首先,我们创建一个测试文件:

# echo "a test file" > /testfs/foo
# sync

然后,我们获得索引节点编号:

# ls -i /testfs/foo
3 /testfs/foo

在卸载文件系统后,可以使用fsdb修改磁盘上的inode:

# umount /testfs
# fsdb /testfsFile System:                    /testfs
File System Size:               2620952 (512 byte blocks)
Aggregate Block Size:           4096
Allocation Group Size:          8192   (aggregate blocks)
> i 3
Inode 3 at block 33, offset 0x600:
……
[5] di_nlink:  1                     [22] di_ixpxd.addr2:    0x00000021
[6] di_mode:  0x000081a4                   di_ixpxd.address:  330100644 -rw-r--r--    [24] di_uid:            0
……
[13] di_ea.flag:   0x00              [30] di_ea.len:          0EAv1                             [31] di_ea.addr1:        0x00
[15] di_ea.nEntry: 0x00              [32] di_ea.addr2:       0x00000000
[16] di_ea.type:   0x0000                  di_ea.address:     0[34] di_ea.nblocks:     0
change_inode: [m]odify, [e]a, [t]ree, or e[x]it > m 6 0x020081a4
change_inode: [m]odify, [e]a, [t]ree, or e[x]it > m 16 2
Inode 3 at block 33, offset 0x600:
……
Inode 3 at block 33, offset 0x600:
……
[5] di_nlink:  1                     [22] di_ixpxd.addr2:    0x00000021
[6] di_mode:  0x020081a4                   di_ixpxd.address:  330100644 -rw-r--r--    [24] di_uid:            0
……
[13] di_ea.flag:   0x00              [30] di_ea.len:          0EAv1                             [31] di_ea.addr1:        0x00
[15] di_ea.nEntry: 0x00              [32] di_ea.addr2:       0x00000000
[16] di_ea.type:   0x0002                 di_ea.address:     0[34] di_ea.nblocks:     0change_inode: [m]odify, [e]a, [t]ree, or e[x]it > x
> q

现在,我们运行fscck命令来检查/ testfs:

# fsck -yvv /testfsThe current volume is: /dev/fslv00
Primary superblock is valid.Superblock s_state = 0x0 mode = 0x3
*** Phase 1 - Initial inode scan
*** Phase 2 - Process remaining directories
*** Phase 3 - Process remaining files
*** Phase 4 - Check and repair inode allocation map
*** Phase 5 - Check and repair block allocation map
File system is clean.

输出显示fsck命令无法检测到具有空EA条目的启用ACL的JFS2索引节点。

使用kdb修改inode

在IBM®AIX®6.1和AIX 7.1中,可以在安装文件系统时使用kdb命令修改内存中的inode。

(0)> i2 -i 3
ADDRESS           DEVICE           I_NUM/FS    COUNT   TYPE    FLAG
F1000A00588F6880 8000000A0000000C       3/16    00000   VREG
……
On-disk Persistent Inode @ 0xF1000A00588F6A20:
uid..........0x00000000  gid..........0x00000000
mode......0x000081A4  mode.........-rw-r--r---  mode.........0100644
……
ea.flag......0x00000000  ea.address...0x0000000000000000
ea.addr1.....0x00000000  ea.addr2.....0x00000000
ea.nEntry....0x00000000  ea.len.........0x00000000
ea.type.......0x00000000(0)> mw 0xF1000A00588F6A20+0x3C
F1000A00588F6A5C:  000081A4  = 020081a4
F1000A00588F6A60:  00000000  = .(0)> mw0xF1000A00588F6A20+0x88
F1000A00588F6AA8:  00000000  = 00020000
F1000A00588F6AAC:  00000000  = .

再次检查inode以确认更改:

(0)> i2 F1000A00588F6880
……
On-disk Persistent Inode @ 0xF1000A00588F6A20:
uid..........0x00000000  gid..........0x00000000
mode......0x020081A4  mode.........-rw-r--r---  mode.........0100644
……
ea.flag......0x00000000   ea.address...0x0000000000000000
ea.addr1.....0x00000000  ea.addr2.....0x00000000
ea.nEntry....0x00000000  ea.len.........0x00000000
ea.type.......0x00000002
typeNames....
AIXACL

故障排除过程挂起

当进程打开使用上述方法创建的索引节点时,该进程可能会挂起:

# more foo
# ps ax|grep more25100524  pts/3 A     0:25 more foo

当更多进程尝试打开该文件并且挂起进程无法终止时,处理器系统时间将急剧增加:

# kill -9 25100524
# ps ax|grep more25100524  pts/3 A     0:57 more foo

仅当线程从内核模式返回时才传递信号。 因此,我们需要检查线程当前在内核模式下运行的功能以及为什么它无法返回用户模式。 在这种情况下, Tracekdb是非常有用的命令。

使用kdb检查挂起过程

# kdb(0)> th * |grep more
pvthread+006200   98*more     RUN   062027 06D    0         0
pvthread+00EB00  235!more     RUN   0EB039 078    2         0
pvthread+015800  344!more     RUN   158047 06C    7         0  (0)> f 344
pvthread+015800 STACK:
Use current context [F00000002FF47600] of cpu 7
[00009518].simple_lock+000018 ()
[00274808]iPut+000054 (??, ??)
[20646678]20646678 ()
[DEADBEEB]DEADBEEB ()
[0044FE64]openpnp+000788 (??, ??, ??, ??, ??)
[0044FF9C]openpath+0000BC (??, ??, ??, ??, ??, ??, ??)
[0045027C]copen+000218 (??, ??, ??, ??, ??)
[0044F678]kopen+00001C (??, ??, ??)(0)> f 344
pvthread+015800 STACK:
Use current context [F00000002FF47600] of cpu 7
[0000B598].fetch_and_addlp+000018 ()
[003DAEEC]lookuppn+0000D8 (??, ??, ??, ??, ??, ??, ??, ??)
[0044FE64]openpnp+000788 (??, ??, ??, ??, ??)
[0044FF9C]openpath+0000BC (??, ??, ??, ??, ??, ??, ??)
[0045027C]copen+000218 (??, ??, ??, ??, ??)
[0044F678]kopen+00001C (??, ??, ??)

kdb命令显示了挂起线程的内核堆栈在不同的时间是不同的,但是一直在调用openpath()openpnp()函数。

这意味着挂起线程没有在Hibernate某些资源,而是进入了openpath()openpnp()内核函数之间的无限循环。 这也解释了为什么挂起过程会消耗大量的处理器系统时间。

跟踪日志和报告

跟踪可用于获取有关挂起过程的更多详细信息。

# trace -anl -C all -T20M -L40M -o trace.raw; sleep 5; trcstop
# ps ax|grep more286908  pts/5 A    13:07 more foo323740  pts/8 A    12:26 more foo# trcrpt -C all -O 'exec=on,pid=on,tid=on,cpu=on' -o trace.log -p 323740 trace.raw

trace.log重复以下块:

107 more  3  323740 1401077  4.450242983 0  lookuppn: foo
4DF more  3  323740 1401077  4.450244140  1 JFS2 iget: vp = F100010038159FE8,
count = 0017, ino = 0002, dev = 000000A0000000B 4DB more  3  323740 1401077  4.450244521  0  vnop_hold(vp = F100010038159FE8,
getcaller = 3DB1B8) = 00004DF more  3  323740 1401077  4.450246527   2  JFS2 iget: vp = F100010038169FE8,
count = 0006, ino = 0003, dev = 000000A0000000B107 more  3  323740 1401077  4.450247078    0
vnop_lookup(dvp = F100010038159FE8, flag = 000A) = 0000, *vpp = 100010038169FE8107 more  3  323740 1401077  4.450247558    0
lookuppn exit: 'foo' = vnode F100010038169FE815B more  3  323740 1401077  4.450248828    1
vnop_open(vp = F100010038169FE8, flags = 4000001, ext = 0000) = 0002

显然,线程首先调用了lookuppn()函数并找到了foo文件出口,但是当vnop_open()尝试打开foo时,它返回了02 (ENOENT)错误代码。 然后,它不断重复调用lookuppn()vnop_open()函数,从而导致进程挂起。

如何解决问题

当挂起进程无法终止时,我们通常必须重新启动系统。 但是对于重要的生产系统,重启不是首选。 当我们知道挂起的根本原因时,有时可以无需重新启动即可解决它。 在此特定示例中,我们已经知道挂起是由空白EA条目引起的。 因此,我们可以通过禁用ACL退出无限循环。

使用kdb禁用ACL

在AIX 6.1和7.1中,可以使用kdb修改内存中的inode以禁用ACL。

(0)> i2 F1000A0034496880On-disk Persistent Inode @ 0xF1000A0034496A20:
uid..........0x00000000   gid..........0x00000000
mode...... 0x020081A4  mode.........-rw-r--r---  mode.........0100644
……
ea.flag....... 0x00000000   ea.address...0x0000000000000000
ea.addr1.....0x00000000   ea.addr2.....0x00000000
ea.nEntry....0x00000000   ea.len.........0x00000000
ea.type........0x00000002
typeNames....
AIXACL  (0)> mw 0xF1000A0034496A20+0x3c
F1000A0034496A5C:  020081A4  = 000081A4
F1000A0034496A60:  00000000  = .(0)> mw 0xF1000A0034496A20+0x88
F1000A0034496AA8:  00020000  = 0
F1000A0034496AAC:  00000000  = .(0)> q

现在,所有挂起进程将继续运行,或者如果之前挂起了kill信号,则将挂起。

编写程序以禁用ACL

在AIX 5.3中,我们编写了一个修复程序,因为kdb无法修改内存。 (请参见下载部分。)

该修订程序也适用于AIX 6.1和AIX 7.1。

首先,我们使用kdb获取on-disk persistent inode的内存地址。 然后,我们通过/dev/kmem接口读取,修改和写回ea.typedi_mode

/* on-disk inode */dinode_t dip;/* on-disk inode address got from kdb */unsigned long long ip=0xF1000A005D84F620;open("/dev/kmem", O_RDWR, 0);kread(ip, (char *)&dip, sizeof(dinode_t));/* clear S_IXACL */if(dip.di_mode == 0x20081a4)dip.di_mode = 0x81a4;  /* clear ea.type  */  if(dip.di_ea.type == 0x02)dip.di_ea.type = 0;  kwrite(ip, (char *)&dip, sizeof(dinode_t));

运行修订程序后,所有挂起进程将继续运行,或者如果之前已挂起kill信号,则将挂起所有挂起进程。

结论

当进程打开带有空EA条目的启用ACL的文件时,进程将挂起。 IBM最近提供了可以避免此问题的授权程序分析师报告(APAR)IV34969。 如果不幸的是,您的AIX系统在申请IV34969之前遇到了此问题,并且您不想重新启动系统,则可以应用本文介绍的方法作为解决方法。


翻译自: https://www.ibm.com/developerworks/aix/library/au-aix-jfs2-inode/index.html

jfs jfs2_故障诊断过程因JFS2 inode带有空扩展属性条目而挂起相关推荐

  1. 消息 15135,级别 16,状态 8,过程 sp_addextendedproperty,对象无效。不允许有扩展属性,或对象不存在。...

    不知道网上为啥有那么多复制粘贴的文章,写点原创不好吗?堂而皇之的贴别人的文章有意思吗? 消息 15135,级别 16,状态 8,过程 sp_addextendedproperty,对象无效.不允许有扩 ...

  2. java xml中的冒号_Java jdom解析xml文件带冒号的属性

    Java jdom解析xml文件带冒号的属性 如果xml文件解析带了冒号的属性,一般都是要特别处理,这里是命名空间,N年前遇到过一次忘记记录,后来也忘了,这次再记录下. 解决了,记录下,分享给大家,百 ...

  3. SQLServer错误:过程 sp_addextendedproperty,第 xxx 行对象无效。'dbo.xxx.xxx' 不允许有扩展属性,或对象不存在。...

    上传数据库到虚拟主机,在执行SQL脚本的时候出现以下的错误: 消息 15135,级别 16,状态 8,过程 sp_addextendedproperty,第 37 行 对象无效.'dbo.Messag ...

  4. domdocument php 扩展_php使用自带dom扩展进行元素匹配的原理解析

    DOMDocument php提供了非常好用的解析html和xml文档的扩展库DOM,使用这个库可以非常高效的进行html和xml文档的解析,它的原理就是通过寻找首尾匹配对来进行文档的解析. 从上面的 ...

  5. Bootstrap CSS 编码规范之带前缀的属性

    带前缀的属性 当使用特定厂商的带有前缀的属性时,通过缩进的方式,让每个属性的值在垂直方向对齐,这样便于多行编辑. /* Prefixed properties */ .selector {   -we ...

  6. 有时间属性,有过程的是软件,有空间属性,有结构的是硬件

    有时间属性,有过程的是软件,有空间属性,有结构的是硬件 转载于:https://www.cnblogs.com/jcode/p/6101870.html

  7. [Ant自动打包]ant执行命令的详细参数和Ant自带的系统属性

    转自:http://hi.baidu.com/yuanzhifeng/item/75d03d11e9b2010eb88a1a6d?qq-pf-to=pcqq.c2c ant学习笔记之(ant执行命令的 ...

  8. FME-CAD专题之-生成带扩展属性的CAD文件

    前几天一位老用户遇到了关于从数据库中提取生成CAD文件时如何将属性带出的问题.在这里我们提供了两种方式将GIS数据转换为带扩展属性的CAD文件. 示例数据是一个ArcGIS的mdb格式地形图数据,包含 ...

  9. Java jdom解析xml文件带冒号的属性

    Java jdom解析xml文件带冒号的属性 转载请标明出处: https://dujinyang.blog.csdn.net/article/details/99644824 本文出自:[奥特曼超人 ...

最新文章

  1. 【性能优化】小伙伴问我性能指标监控怎么做,这次我安排上了!!
  2. 安装惠普笔记本XP三种方法
  3. java知识理论_JAVA理论知识 - OSC_rnoszD的个人空间 - OSCHINA - 中文开源技术交流社区...
  4. SCCM2007系列教程之十操作系统部署(二)
  5. linux盘符改名字,Linux 下powerpath共享磁盘名称不一致处理方法
  6. 2021年第二届“华数杯”全国大学生数学建模竞赛
  7. 恰当地利用中间结果集
  8. Laravel Facades的实现原理
  9. MaterialPropertyBlock的使用
  10. 【Unity】UGUI无法修改UI元素的Pivot锚点位置
  11. IE调试网页之二:F12 开发人员工具入门 (Windows)
  12. 22_粗粒度权限控制
  13. HP34401a实现高精度温度测量
  14. JavaEE与云服务知识概括
  15. 电子爱好者必备,强烈推荐这些常用工具
  16. 毕业论文-----有关目录的全部问题
  17. ubuntu修改用户名和home对应的目录名
  18. 获取当前所在地的天气
  19. 经典智力面试题[转载]
  20. (转)如何使用Psyco为你的Python程序提速。

热门文章

  1. 线性表操作(线性表)
  2. python 中正无穷,负无穷的表示
  3. OK6410A 开发板 (三) 3 u-boot-2021.01 boot 解析概览
  4. 应用运筹学基础:线性规划 (1) - 极点与基可行解
  5. 【零基础 快速学Java】韩顺平 p104-147 流程控制:顺序、分支、循环、跳转 控制语句 (if、for、while、dowhile、break、continue、return)
  6. 高质量的原创对于搜索引擎来说是非常的友好的
  7. 【传智播客郑州校区分享】AndroidAnnotations框架详解
  8. ios让您的today变得更加有节奏,新出品Today:日历、提醒、习惯养成、倒计时
  9. 【C语言】switch语句的理解
  10. 8种开源的ETL工具