I/O 探针管理器

I/O 探测器管理器提供在 AIX® I/O 堆栈的各个层中跟踪 I/O 操作事件的功能。 使用 syscall 探针管理器跟踪读/写系统调用触发的应用程序 I/O 请求。 使用 I/O 探针管理器进一步探测 syscall 层。

使用 I/O 探针管理器分析用于隔离服务时间和排队延迟的块设备的 I/O 操作的响应时间。

以下层受支持:

  • 逻辑文件系统 (LFS)
  • 虚拟文件系统 (VFS)
  • 增强型日志文件系统 (JFS2)
  • 逻辑卷管理器 (Logical Volume Manager,LVM)
  • 小型计算机系统接口 (SCSI) 磁盘驱动程序
  • 通用块设备

I/O 探针管理器的主要用例如下所示:

  • 标识以下模式的设备 I/O 使用情况。 有效的设备可以是指定时间段的磁盘、逻辑卷、卷组或文件系统(类型或安装路径):
    • I / O 操作计数
    • I/O 操作大小
    • I/O 操作类型(读/写)
    • I/O 的循序或随机特性
  • 获取文件系统(类型或安装路径)、逻辑卷、卷组或磁盘的进程或线程方面的使用信息。
  • 获取各层间的 I/O 流的端到端映射(任何可能位置)。
  • 监视特定 I/O 资源使用情况。 例如:
    • 跟踪 /etc/password 文件的任何写操作。
    • 跟踪针对 hdisk0 设备的块 0 的读操作。
    • 在根卷组 (rootvg) 中打开新逻辑卷时进行跟踪。
  • 对于多路径 I/O (MPIO) 磁盘,请通过以下操作获取特定于路径的信息:
    • 获取路径方面的使用情况和响应时间信息。
    • 标识路径切换或路径故障。
  • 对于 I/O 错误,获取有关磁盘驱动器层中的错误的更多详细信息。

调查规范

必须按以下格式在 Vue 脚本中指定 I/O 探针:

@@io:sub_type:io_event:operation_type:filter[|filter …]
此规范由以冒号 (:) 分隔的五个元组组成。 第一个元组始终为 @@io

探针子类型

第二个元组表示探测器的子类型,该子类型指示包含探测器的 AIX I/O 堆栈层。 此元组可具有下列其中一个值:

表 1. 探针的第二元组
第二元组(子类型) 描述
磁盘 此探针针对磁盘驱动器事件启动。 目前,I/O 探针管理器仅支持 scsidisk 驱动器。
lvm 此探针针对逻辑卷管理器 (LVM) 事件启动。
bdev 此探针针对任何块 I/O 设备启动。 例如,磁盘、CD-ROM 和软盘都是块设备。 仅当没有其他子类型适用时,才使用此子类型。 例如,如果块设备并非磁盘、卷组或逻辑卷,那么此子类型适用。
jfs2 此探针针对 JFS2 文件系统事件启动。
vfs 此探针针对任何对文件执行的读/写操作启动。
注: 第二个元组的值不能为星号 (*)。

对于磁盘类型的第二元组,第三元组可具有以下值:

表 2。 磁盘第二元组:第三元组的值
子类型(第二元组) I/O 事件(第三元组) 描述
磁盘 条目 每当磁盘驱动器接收到要处理的 I/O 请求时,此探针启动。
iostart 磁盘驱动器从其就绪队列选择 I/O 请求并将其向下发送至下层(例如,适配器驱动器)时,此探针启动。 针对磁盘驱动器的单个原始 I/O 请求可向下层发送多个命令请求(某些请求可能是与驱动器相关的任务管理命令请求)。 但是,有时驱动器可以将多个原始请求组合到一起并向下层发送单个请求。
iodone 下层(例如,适配器驱动器)将 I/O 请求(成功或失败)返回给磁盘驱动器时,此探针启动。
exit 磁盘驱动器将 I/O 请求(成功或失败)返回给其上层时,此探针启动。
注: 以下内置值的成员在针对探测器子类型提及的探测器中可用: __iobuf__diskinfo__diskcmd (仅在 disk:iostartdisk:iodone中) , 和 __iopath (仅在 disk:iostartdisk:iodone中)。

对于每个入口,将定义相应的出口探针,两个探针点上具有相同 __iobuf->bufid 值。 入口事件可后跟多个 iostart 事件,但至少其中一个事件必须具有相同 __iobuf->bufid 值。 每个 iostart 事件具有匹配 iodone 事件,该 iodone 事件有相同 __iobuf->child_bufid 值。

对于 LVM 类型的第二元组,第三元组可具有以下值:

表 3。 LVM 第二元组:第三元组的值
子类型(第二元组) I/O 事件(第三元组) 描述
lvm 条目 每当 LVM 层接收到要处理的 I/O 请求时,此探针启动。
iostart LVM 从其就绪队列选择 I/O 请求并将其向下发送至下层(通常为磁盘驱动器)时,此探针启动。
iodone 下层(例如,磁盘驱动器)将 I/O 请求(成功或失败)返回给 LVM 时,此探针启动。
exit LVM 将 I/O 请求(成功或失败)返回给其上层时,此探针启动。
注: 针对 LVM 提及的探测器中提供了以下内置值的成员: __iobuf__lvol__volgrp。 每个入口都有对应出口探针,该出口探针的两个探针点上具有相同 __iobuf->bufid 值。

入口事件可后跟多个 iostart 事件,但至少其中一个事件具有相同 __iobuf->bufid 值。 每个 iostart 事件具有匹配 iodone 事件,该 iodone 事件有相同 __iobuf->child_bufid 值。

对于通用块设备探针,第三元组可具有以下值:

表 4。 通用块设备第二元组:第三元组的值
子类型(第二元组) I/O 事件(第三元组) 描述
bdev iostart 任何块 I/O(例如,磁盘、逻辑卷和 CD-ROM)设备启动时,此探针被触发。 当任何代码调用 AIX devstrat 内核服务时会发生此情况。
iodone 当发生块 I/O 请求完成时,当任何代码调用 AIX iodone 内核服务时,将会触发此探测器。
注: 以下内置值的成员在 bdev 中提及的探测器中可用: __iobuf。 每个 iostart 事件具有匹配 iodone 事件,该 iodone 事件有相同 __iobuf->bufid 值。

对于 JFS2 文件系统探针,第三元组可具有以下值:

表 5。 JFS2 第二元组:第三元组的值
子类型(第二元组) I/O 事件(第三元组) 描述
jfs2 buf_map 逻辑文件扩展数据块映射至 I/O 缓冲区并发送至底层逻辑卷时,此探针启动。
注: 以下内置值的成员在针对 JFS2 文件系统探测器提及的探测器中可用: __j2info

对于虚拟文件系统 (VFS) 探针,第三元组可具有以下值:

表 6。 VFS 第二元组:第三元组的值
子类型(第二元组) I/O 事件(第三元组) 描述
vfs 条目 任何对文件执行的读/写操作启动时,此探针启动。
exit 任何对文件执行的读/写操作完成(无论成功还是失败)时,此探针启动。
注: 以下内置的成员在 VFS 探测器中提到的探测器中可用: __file

对于同一个线程,每个入口后跟一个出口事件,该出口事件具有相同 __file->inode_id值。

探测器操作类型

第四元组指示该探针指定的 I/O 操作的类型。 第四元组可具有下列其中一个值:

表 7。 I/O 操作的第四元组
第四元组 描述
此探针仅针对读操作启动。
写入 此探针仅针对写操作启动。
* 此探针针对读操作和写操作启动。

探针过滤器

第五元组是一个过滤器元组,可根据要求帮助过滤更具体的探针。 可能的值依赖于子类型。 可指定多个值并使用 | 字符分隔,如果探针与其中任何过滤器匹配,那么该探针启动。 如果第五元组的值为 *,那么不会进行任何过滤,其他元组匹配时,该探针启动。 如果指定了多个选择器,并且其中一个选择器为 *,那么相当于整个元组值为 *。

对于磁盘探针,第五元组可具有以下值:

表 8。 磁盘过滤器元组
过滤器(第五元组) 描述
磁盘名称。 例如,hdisk0 此探针操作仅针对特定磁盘运行。
磁盘类型。 允许的符号:FC、ISCSI、VSCSI 和 SAS 此探针操作仅针对具有匹配类型的磁盘运行。 这些符号的含义如下所示:
  • FC:光纤通道磁盘
  • ISCSI:iSCSI 磁盘
  • VSCSI:虚拟 SCSI 磁盘(在 VIOS 客户机上)
  • SAS:串行连接 SCSI 磁盘
注: 可以将磁盘名称和磁盘类型组合为过滤器。 例如,以下探针针对 hdisk0 或任何其他 FC 磁盘(发生磁盘入口事件时,针对读操作和写操作类型)启动:
@@io:disk:entry:*:hdisk0|FC

对于逻辑卷管理器 (LVM) 探针,第五元组可具有以下值:

表 9。 LVM 过滤器元组
过滤器(第五元组) 描述
逻辑卷名称,例如,hd5, lg_dumplv 此探针操作仅针对特定逻辑卷运行。
卷组名称,例如,rootvg 此探针操作仅针对属于特定逻辑卷组的逻辑卷运行。

发生 iostart 事件时,仅针对写操作:以下探针针对属于根卷组 (rootvg) 或测试卷组 (testvg) 的任何逻辑卷启动。

@@io:lvm:iostart:write:rootvg|testvg

对于通用块设备探针,第五元组可具有以下值:
表 10. 通用块设备过滤器元组
过滤器(第五元组) 描述
块设备名,例如:hdisk0, hd5, cd0 此探针操作仅针对特定块设备运行。

对于通用块设备探针,考虑以下示例:

@@io:bdev:iostart:*:cd0

@@io:bdev:iodone:read:hdisk3|hdisk5

对于 JFS2 文件系统探针,第五元组可具有以下值:

表 11. JFS2 过滤器元组
过滤器(第五元组) 描述
文件系统安装路径,例如:/usr 此探针操作仅针对具有特定安装路径的文件系统运行。 它必须是一个JFS2文件系统,否则ProbeVue 将拒绝该探针规范。

对于 JFS2 文件系统探针,考虑以下示例:

@@io:jfs2:buf_map:*:/usr|/tmp

对于虚拟文件系统 (VFS) 探针,第五元组可具有以下值:

表 12. VFS 过滤器元组
过滤器(第五元组) 描述
文件系统安装路径。 例如,/tmp 此探针操作仅针对属于该文件系统的文件运行。
文件系统类型。 允许的符号为 JFS2, NAMEFS, NFS, JFS, CDROM, PROCFS, SFS, CACHEFS, NFS3, AUTOFS, POOLFS, VXFS, VXODM, UDF, NFS4, RFS4, CIFS, PMEMFS, AHAFS, STNFS, ASMFS 此探针操作仅针对特定文件系统的文件运行。 这些符号对应于导出的头文件 sys/vmount.h中定义的 AIX 文件系统。

对于虚拟文件系统 (VFS) 探针,考虑以下示例:

@@io:vfs:entry:read:JFS2

@@io:vfs:exit:*:/usr|JFS

Vue 脚本的 I/O 探针相关内置变量

__iobuf 内置变量

可以使用特殊 __iobuf 内置变量来访问有关当前 I/O 操作中使用的 I/O 缓冲区的各种信息。 可在以下子类型的探针中访问:disklvmbdev。 其成员元素可通过使用 __iobuf->member 语法访问。

注: 每当无法获取实际值时,都会返回标记为 Invalid Value 的值。 返回此值的原因为下列其中一项:
  • 需要缺页故障上下文,但当前 probevctrl 可调整值 num_pagefaults 为 0 或不足。
  • 包含此值的内存位置已调出页面。
  • 任何其他严重系统错误,例如,指针无效或内存已损坏。

__iobuf 内置变量具有下列成员:

表 13. __iobuf 内置变量成员
成员名 类型 描述 无效值
blknum unsigned long long I/O 请求的开始块号。 0xFFFFFFFFFFFFFFFF
bcount unsigned long long I/O 操作中的所请求字节数。 0xFFFFFFFFFFFFFFFF
bflags unsigned long long 与 I/O 操作相关联的标记。 提供了以下符号: B_READ, B_ASYNC, B_ERROR。 这些符号可与 bflags 值配合使用来查看是否设置了此项。 例如,如果 (__iobuf->bflags & B_READ) 为 true,那么它是读操作。
注: 没有 B_WRITE 标志。 如果未设置 B_READ 标记,那么它被视为写操作。
0
devnum unsigned long long 与 I/O 操作相关联的目标设备的设备号。 设备主号码和副号码嵌入在其中。 0
major_num 整数 I/O 操作的目标设备的主号码。 -1
minor_num 整数 I/O 操作的目标设备的副号码。 -1
错误 整数 如果 I/O 操作中发生任何错误,那么此值是错误号。 此值是在已导出 errno.h 头文件中定义的。 -1
residue unsigned long long 原始请求中可能未读取或写入的余下字节数。 在 I/O 完成事件中,此值在理想状态下为零。 但是,对于读操作,非零值可能意味着您尝试读取的字节数大于可用字节数,这是可接受的。 仅当错误值为非零时,才会考虑此值。 0xFFFFFFFFFFFFFFFF
bufid unsigned long long 指定与 I/O 请求相关联的唯一编号。 正在进行 I/O 时,bufid 值在特定子类型的所有事件中唯一标识该 I/O 请求。 例如,在 disk: entrydisk: iostartdisk: iodonedisk:exit 中。 如果 __iobuf->bufid 匹配,那么它在各个阶段是相同 I/O 请求。 0
parent_bufid unsigned long long 如果值不为 0,那么此值提供与此 I/O 请求相关联的上层缓冲区的 bufid。 现在可将当前 I/O 操作与上层 I/O 请求链接到一起。 例如,在磁盘 I/O 请求中,可确定对应 LVM I/O。
注: 未在所有代码路径中设置 parent_bufid 字段,因此它并非总是有用的。 在两个相邻层之间使用 child_bufid 字段链接 I/O 请求。
0
child_bufid unsigned long long 如果值不为 0,那么此值提供发送至下层的新 I/O 请求的 bufid。 要记录的最佳事件为 disk:iostartlvm:iostartbdev:iostart。 通过将 __iobuf->bufid 值与此 child_bufid 值匹配,可在相邻下层中标识该 I/O。 例如,在 lvm:iostart 中,您可记录 __iobuf->child_buf 值。 然后,在 disk:entry 中,您可将其与 __iobuf->bufid 匹配以标识对应 I/O 请求。 0

__file 内置变量

可以使用 __file 特殊内置变量来获取有关文件操作的各种信息。 它在子类型为 VFS 的探针中可用。 可使用 __file->member 语法访问其成员元素。

注: 每当无法获取实际值时,都会返回标记为无效的值。 返回无效值的原因为下列其中一项:
  • 需要缺页故障上下文,但当前 probevctrl 可调整值 num_pagefaults 为 0 或不足。
  • 包含该值的内存位置已调出页面。
  • 任何其他严重系统错误,例如,指针无效或内存已损坏。

__file 内置变量具有下列成员:

表 14. __file 内置变量成员
成员名 类型 描述 无效值
f_type 整数 指定文件类型。 它可与下列其中一个内置常量值相匹配:
  • F_REG(常规文件)
  • F_DIR(目录)
  • F_BLK(块设备文件)
  • F_CHR(字符设备文件)
  • F_LNK(文件链接)
  • F_SOCK(套接字)
注: 该值可能与任何内置常量都不匹配,因为列表不包含每种可能的文件类型,而只包含最有用的文件类型。
-1
fs_type 整数 指定此文件所属的文件系统的类型。 它可与下列其中一个内置常量值相匹配:
  • FS_JFS2
  • FS_NAMEFS
  • FS_NFS
  • FS_JFS
  • FS_CDROM
  • FS_PROCFS
  • FS_SFS
  • FS_CACHEFS
  • FS_NFS3
  • FS_AUTOFS
  • FS_POOLFS
  • FS_VXFS
  • FS_VXODM
  • FS_UDF
  • FS_NFS4
  • FS_RFS4
  • FS_CIFS
  • FS_PMEMFS
  • FS_AHAFS
  • FS_STNFS
  • FS_ASMFS

内置常量与导出的 sys/vmount.h 头文件中定义的 AIX 文件系统类型相对应。

-1
mount_path 字符 * 指定关联文件系统的安装路径。 空字符串
devnum unsigned long long 指定文件的关联块设备的设备号。 主号码和副号码都嵌入其中。 如果没有相关联的块设备,那么它为 0。 0
major_num 整数 指定文件的关联块设备的主号码。 -1
minor_num 整数 指定文件的关联块设备的副号码。 -1
偏移量 unsigned long long 指定文件的当前读/写字节偏移量。 0xFFFFFFFFFFFFFFFF
rw_mode 整数 指定文件的读/写方式。 它与下列其中一个内置常量值相匹配:F_READ 或 F_WRITE。 -1
byte_count unsigned long long vfs: 入口事件中,byte_count 提供读/写请求的字节计数。 在 vfs: 出口事件中,它提供尚未完成的字节数。 例如,这两个事件中的此值之差确定操作中处理的字节数。 0xFFFFFFFFFFFFFFFF
fname 字符 * 指定文件名称(仅基本名称,不包含路径)。 空字符串
inode_id unsigned long long 指定与文件相关联的系统范围唯一编号。
注: 它与文件索引节点号不同。
0
路径 path_t(VUE 中的新数据类型) 指定完整文件路径。 可使用 printf() 和格式说明符 %p 显示此项。 空字符串作为文件路径
错误 整数 已导出 errno.h 头文件中定义的用于表示读/写操作失败的错误号。 如果没有错误,那么它为 0。 -1

__lvol 内置变量

可以使用 __lvol 特殊内置变量来获取有关 LVM 操作中的逻辑卷的各种信息。 它在子类型为 lvm 的探针中可用。 其成员元素可通过使用 __lvol->member 语法访问。
注: 每当无法获取实际值时,都会返回标记为 Invalid Value的值。 获取此无效值可能有以下原因:
  • 需要缺页故障上下文,但当前 probevctrl 可调整值 num_pagefaults 为 0 或不足。
  • 包含此值的内存位置已调出页面。
  • 任何其他严重系统错误,例如,指针无效或内存已损坏。
__lvol 内置变量具有以下成员:
表 15. __lvol 内置变量成员
成员名 类型 描述 无效值
名称 字符 * 逻辑卷的名称。 空字符串
devnum unsigned long long 逻辑卷的设备号。 主号码和副号码嵌入在其中。 0
major_num 整数 逻辑卷的主号码。 -1
minor_num 整数 逻辑卷的副号码。 -1
lv_options unsigned int 与逻辑卷相关的选项。 下列值定义为内置常量:
  • LV_RDONLY(只读逻辑卷)
  • LV_NOMWC(无镜像写一致性检查)
  • LV_ACTIVE_MWC(主动镜像写一致性)
  • LV_PASSIVE_MWC(被动镜像写一致性)
  • LV_SERIALIZE_IO(I/O 已序列化)
  • LV_DMPDEV(此 LV 是转储设备)

You can check whether one of these values is set by having condition such as __lvol->lv_options & LV_RDONLY.

注: 未定义所有可能的值,因此其他选项可能在该值中可用。
0xFFFFFFFF

__volgrp 内置变量

可以使用 __volgrp 特殊内置变量来获取有关 LVM 操作中的卷组的各种信息。 它在子类型为 lvm 的探针中可用。 其成员元素可通过使用 __volgrp->member 语法访问。
注: 每当无法获取实际值时,都会返回标记为 Invalid Value 的值。 该值可能由于以下原因而无效:
  • 需要缺页故障上下文,但当前 probevctrl 可调整值 num_pagefaults 为 0 或不足。
  • 包含此值的内存位置已调出页面。
  • 任何其他严重系统错误,例如,指针无效或内存已损坏。

__volgrp 内置变量具有以下成员:

表 16. __volgrp 内置变量成员
成员名 类型 描述 无效值
名称 字符 * 卷组的名称。 空字符串
devnum unsigned long long 卷组的设备号。 主号码和副号码嵌入在其中。 0
major_num 整数 卷组的主号码。 -1
minor_num 整数 卷组的副号码。
注: 对于卷组, AIX 始终将 0 指定为次要编号。
-1
num_open_lvs 整数 属于此卷组的已打开逻辑卷的数量。 -1

__diskinfo 内置变量

可以使用 __diskinfo 特殊内置变量来获取有关磁盘 I/O 操作中的磁盘的各种信息。 它在子类型为 disk 的探针中可用。 可使用 __diskinfo->member 语法访问其成员元素。
注: 每当无法获取实际值时,都会返回标记为 "无效值" 的值。 获取此无效值可能有以下原因:
  • 需要缺页故障上下文,但当前 probevctrl 可调整值 num_pagefaults 为 0 或不足。
  • 包含此值的内存位置已调出页面。
  • 任何其他严重系统错误,例如,指针无效或内存已损坏。
__diskinfo 内置变量具有以下成员:
表 17. __diskinfo 内置变量成员
成员名 类型 描述 无效值
名称 字符 * 磁盘的名称。 空字符串。
devnum unsigned long long 磁盘的设备号。 主号码和副号码嵌入在其中。 0
major_num 整数 磁盘的主号码。 -1
minor_num 整数 磁盘的副号码。 -1
lun_id unsigned long long 磁盘的逻辑单元号 (LUN)。 0xFFFFFFFFFFFFFFFF
transport_type 整数 磁盘的传输类型。 它可与下列其中一个内置常量值相匹配:
  • T_FC(光纤通道)
  • T_ISCSI (iSCSI)
  • T_VSCSI(虚拟 SCSI)
  • T_SAS(串行连接 SCSI)
-1
queue_depth 整数 磁盘的队列深度。 它指示磁盘驱动器可传递至下层(例如,适配器)的最大同步 I/O 请求数。 如果传入的 I/O 请求数超过 queue_depth,那么系统以不同方式处理该请求。 额外请求由磁盘驱动器在其等待队列中处理,直到下层响应至少一个未完成 I/O 请求。 -1
cmds_out 整数 指向下层(例如,适配器)的未完成 I/O 命令请求的数目。 -1
path_count 整数 磁盘的 MPIO 路径数(仅当磁盘支持 MPIO 时才使用,否则为 0)。 -1
reserve_policy 整数 磁盘的 SCSI 预留策略。 它与下列其中一个内置常量值相匹配:
  • DK_NO_RESERVE (no_reserve)
  • DK_SINGLE_PATH (single_path)
  • DK_PR_EXCLUSIVE (PR_exclusive)
  • DK_PR_SHARED (PR_shared)

请参阅 AIX MPIO 文档以了解有关预留策略的更多信息。

-1
scsi_flags 整数 磁盘的 SCSI 标记。 已定义下列内置标志值:
  • SC_AUTOSENSE_ENABLED(发生错误时,目标在响应中发送检测数据。 发起方不需要发送请求检测命令。)
  • SC_NACA_1_ENABLED(正常 ACA 已启用,如果它返回检查条件,那么目标进入 ACA 状态。)
  • SC_64BIT_IDS(64 位 SCSI 标识和逻辑单元号 (LUN))
  • SC_LUN_RESET_ENABLED(可发送 LUN 重置命令。)
  • SC_PRIORITY_SUP(设备支持 I/O 优先级。)
0
   
  • SC_CACHE_HINT_SUP(设备支持高速缓存提示。)
  • SC_QUEUE_UNTAGGED(设备支持未标记命令排队。)
注: 未定义所有标志值,因此存在的其他标志可能在该值中可用。
0

__diskcmd 内置变量

可以使用 __diskcmd 特殊内置变量来获取有关当前操作的 SCSI I/O 命令的各种信息。 它在子类型为 disk(但只适用于 iostartiodone 事件)的探针中可用。 可使用 __diskcmd->member 语法访问其成员元素。
注: 每当无法获取实际值时,都会返回标记为 "无效值" 的值。 获取此值可能有以下原因:
  • 需要缺页故障上下文,但当前 probevctrl 可调整值 num_pagefaults 为 0 或不足。
  • 包含此值的内存位置已调出页面。
  • 任何其他严重系统错误,例如,指针无效或内存已损坏。

__diskcmd 内置变量具有下列成员:

表 18. __diskcmd 内置变量成员
成员名 类型 描述
cmd_type 整数 该 SCSI 命令的类型(类型和子类型合并在一起)。 下列内置常量值可用作命令类型:
  • DK_BUF(正常 I/O 读/写)
  • DK_IOCTL (ioctl)
  • DK_REQSNS(请求检测)
  • DK_TGT_LUN_RST(目标或 LUN 重置)
  • DK_TUR(测试单元就绪)
  • DK_INQUIRY(查询)
  • DK_RESERVE(SCSI-2 RESERVE,6 字节版本)
  • DK_RELEASE(SCSI-2 RELEASE,6 字节版本)
  • DK_RESERVE_10(SCSI-2 RESERVE,10 字节版本)
  • DK_RELEASE_10(SCSI-2 RELEASE,10 字节版本)
  • DK_PR_RESERVE(SCSI-3 持久性预留量,RESERVE)
  • DK_PR_RELEASE(SCSI-3 持久性预留量,RELEASE)
  • DK_PR_CLEAR(SCSI-3 持久性预留量,CLEAR)
  • DK_PR_PREEMPT(SCSI-3 持久性预留量,PREEMPT)
  • DK_PR_PREEMPT_ABORT(SCSI-3 持久性预留量,PREEMPT AND ABORT)
  • DK_READCAP(READ CAPACITY,10 字节版本)
  • DK_READCAP16(READ CAPACITY,16 字节版本)
注: The built-in constants are bit position values and hence their presence must be checked by using ‘&’ operator (the ‘==’ operator must not be used). 例如:__diskcmd->cmd_type & DK_IOCTL
retry_count 整数 它指示是否在任何故障后重试 I/O 命令。
注: 1 的值表示它是第一次尝试。 任何更大值指示实际重试次数。
path_switch_count 整数 它指示针对此特定 I/O 操作更改路径(通常指示某种 I/O 路径故障,瞬态或永久)的次数。
status_validity 整数 发生任何错误时,此值指示它是 SCSI 错误还是适配器错误。 它可与下列其中一个内置常量值相匹配:SC_SCSI_ERROR 或 SC_ADAPTER_ERROR。 如果没有错误,那么它为 0。
scsi_status 整数 如果 status_validity 字段设置为 SC_SCSI_ERROR,那么此字段给出有关该错误的更多详细信息。 它可与其中一个内置常量值相匹配:
  • SC_GOOD_STATUS(任务成功完成)
  • SC_CHECK_CONDITION(某个错误,检测数据提供更多信息)
  • SC_BUSY_STATUS(LUN 繁忙,无法接受命令)
  • SC_RESERVATION_CONFLICT(违反现有 SCSI 预留。)
  • SC_COMMAND_TERMINATED(设备已结束该命令。)
  • SC_QUEUE_FULL(设备队列已满。)
  • SC_ACA_ACTIVE(该设备处于自动应急处理状态。)
  • SC_TASK_ABORTED(该设备已停止该命令。)
注: 未定义所有可能的值。 因此,SC_SCSI_ERROR 可能具有的值可能与任何内置值都不匹配。 您可以查找相应的 SCSI 命令响应代码。
adapter_status 整数 如果 status_validity 字段设置为 SC_ADAPTER_ERROR,那么此字段提供有关该错误的更多详细信息。 它可与下列其中一个内置常量值相匹配:
  • ADAP_HOST_IO_BUS_ERR(主机 I/O 总线错误)
  • ADAP_TRANSPORT_FAULT(传输层错误)
  • ADAP_CMD_TIMEOUT(I/O 命令已超时)
  • ADAP_NO_DEVICE_RESPONSE(设备未响应)
  • ADAP_HDW_FAILURE(适配器硬件故障)
  • ADAP_SFW_FAILURE(适配器微码故障)
  • ADAP_TRANSPORT_RESET(适配器检测到外部 SCSI 总线重置)
  • ADAP_TRANSPORT_BUSY(传输层繁忙)
  • ADAP_TRANSPORT_DEAD(传输层不起作用)
  • ADAP_TRANSPORT_MIGRATED(传输层已迁移)
  • ADAP_FUSE_OR_TERMINAL_PWR(适配器熔断或无效电子终止)

__iopath 内置变量

可以使用 __iopath 特殊内置变量来获取有关当前操作的 I/O 路径的各种信息。 它在子类型为 disk 的针对 iostartiodone 事件的探针中可用。 可使用 __iopath->member 语法访问其成员元素。
注: 每当无法获取实际值时,都会返回标记为 Invalid Value的值。 获取此无效值可能有以下原因:
  • 需要缺页故障上下文,但当前 probevctrl 可调整值 num_pagefaults 为 0 或不足。
  • 包含此值的内存位置已调出页面。
  • 任何其他严重系统错误,例如,指针无效或内存已损坏。

__iopath 具有以下成员:

表 19. __iopath 内置变量成员
成员名 类型 描述 无效值
path_id 整数 当前路径的标识(从 0 开始)。 -1
scsi_id unsigned long long 此路径上的目标的 SCSI 标识。 0xFFFFFFFFFFFFFFFF
lun_id unsigned long long 此路径上的逻辑单元号 (LUN)。 0xFFFFFFFFFFFFFFFF
ww_name unsigned long long 此路径上的目标端口的全球名称。 0
cmds_out 整数 此路径上未完成的 I/O 命令数。 -1

__j2info 内置变量

__j2info 是一个特殊内置变量,可以使用此变量来获取有关 JFS2 文件系统操作的各种信息。 它在子类型为 jfs2 的探针中可用。 其成员元素可通过使用 __j2info->member 语法访问。
注: 每当无法获取实际值时,都会返回标记为 Invalid Value 的值。 获取此无效值可能有以下原因:
  • 需要缺页故障上下文,但当前 probevctrl 可调整值 num_pagefaults 为 0 或不足。
  • 包含此值的内存位置已调出页面。
  • 任何其他严重系统错误,例如,指针无效或内存已损坏。

__j2info 具有以下成员:

表 20. __j2info 内置变量成员
成员名 类型 描述 无效值
inode_id unsigned long long 与当前操作的文件相关联的系统范围唯一编号。
注: 它与文件索引节点号不同。
0
f_type 整数 文件的类型。 __file->f_type 描述提供可能值。 -1
mount_path 字符 * 文件系统的安装路径。 空字符串。
devnum unsigned long long 文件系统的底层块设备的设备号。 主号码和副号码嵌入在其中。 0
major_num 整数 文件系统的底层块设备的主号码。 -1
minor_num 整数 文件系统的底层块设备的副号码。 -1
l_blknum unsigned long long 此文件操作的逻辑块号。 0xFFFFFFFFFFFFFFFF
l_bcount unsigned long long 此操作中的逻辑块之间所请求的字节数。 0xFFFFFFFFFFFFFFFF
child_bufid unsigned long long 发送至下层(例如,LVM)的 I/O 请求缓冲区的 bufid。 在该层中,它显示为 __iobuf->bufid 0
child_blknum unsigned long long 向下发送至下层(例如,LVM)的 I/O 请求缓冲区的块号。 在该层中,它显示为 __iobuf->blknum 0xFFFFFFFFFFFFFFFF
child_bcount unsigned long long 向下发送至下层(例如,LVM)的 I/O 请求缓冲区的字节数。 在该层中,它显示为 __iobuf->bcount 0xFFFFFFFFFFFFFFFF
child_bflags unsigned long long 发送至下层(例如,LVM)的 I/O 请求缓冲区的标记。 在该层中,它显示为 __iobuf->bflags 0

I/O 探针管理器的示例脚本

  1. 此脚本用于跟踪针对 /etc/passwd 文件的任何写操作:
    
    int write(int, char *, int);
    @@BEGIN  {
            target_inodeid = fpath_inodeid("/etc/passwd");
    }
    @@syscall:*:write:entry {
            if (fd_inodeid(__arg1) == target_inodeid) {
                    printf("write on /etc/passwd: timestamp=%A, pid=%lld, pname=[%s], uid=%lld\n",
                            timestamp(), __pid, __pname, __uid);
            }
    }
    If the scripts is in a VUE file, names etc_passwd.e. The script can be run as:
    # probevue etc_passwd.e
    In another terminal, if the user (root) runs:
    # mkuser user1
    Then probevue displays an output similar to the following example:
    write on /etc/passwd: timestamp=Mar/03/15 16:10:07, pid=14221508, pname=[mkuser], uid=0
    
    
  2. 此脚本用于查找某个时间段内某个磁盘(例如,hdisk0)的最长和最短 I/O 操作时间。 同时查找对应最长时间或最短时间的块号、所请求字节数、操作时间及操作类型(读或写)。
long long min_time, max_time;
@@BEGIN {
        min_time = max_time = 0;
}
@@io:disk:entry:*:hdisk0 {
        ts_entry[__iobuf->bufid] = (long long)timestamp();
}
@@io:disk:exit:*:hdisk0 {
        if (ts_entry[__iobuf->bufid]) { /* only if we recorded entry time */
                ts_now = timestamp();
                op_type = (__iobuf->bflags & B_READ) ? "READ" : "WRITE";
                dt = (long long)diff_time(ts_entry[__iobuf->bufid], ts_now, MICROSECONDS);
                if (min_time == 0 || dt < min_time) {
                        min_time = dt;
                        min_blknum = __iobuf->blknum;
                        min_bcount = __iobuf->bcount;
                        min_ts = ts_now;
                        min_optype = op_type;
                }
                if (max_time == 0 || dt > max_time) {
                        max_time = dt;
                        max_blknum = __iobuf->blknum;
                        max_bcount = __iobuf->bcount;
                        max_ts = ts_now;
                        max_optype = op_type;
                }
                ts_entry[__iobuf->bufid] = 0;
        }
}
@@END {
        printf("Maximum and minimum IO operation time for [hdisk0]:\n");
        printf("Max: %lld usec, block=%lld, byte count=%lld, operation=%s, time of operation=[%A]\n",
                max_time, max_blknum, max_bcount, max_optype, max_ts);
        printf("Min: %lld usec, block=%lld, byte count=%lld, operation=%s, time of operation=[%A]\n",
                min_time, min_blknum, min_bcount, min_optype, min_ts);
}

Let this script be in a VUE file named disk_min_max_time.e. It can be executed as:
# probevue disk_min_max_time.e
Let there be some IO activity on hdisk0 (dd command can be used). 
Then after a few minutes, if the above command is terminated (by pressing CTRL-C), then it will print output similar to:
^CMaximum and minimum IO operation time for [hdisk0]:
Max: 48174 usec, block=6927976, byte count=4096, operation=READ, time of operation=[Mar/04/15 03:31:07]
Min: 133 usec, block=6843288, byte count=4096, operation=READ, time of operation=[Mar/04/15 03:31:03]