├── LICENSE ├── Makefile ├── README.md ├── README_en-us.md ├── debian ├── build.sh ├── control ├── postinst ├── preinst └── prerm ├── kernel ├── Makefile ├── kiodump.c ├── kiodump.conf └── kiodump.h ├── spec ├── distribution.spec ├── docker.spec └── iodump.spec └── user ├── Makefile ├── iodump.c └── iodump.h /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Alibaba Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | KERNELVER?=$(shell uname -r) 2 | 3 | default: 4 | make -C user 5 | make -C kernel 6 | clean: 7 | make -C user clean 8 | make -C kernel clean 9 | install: 10 | if [ $(id -u) -ne 0 ]; then { echo "root permission is required to install iodump";exit 0;} fi 11 | install -d /usr/lib/iodump/ 12 | install kernel/kiodump.ko /usr/lib/iodump/kiodump.ko 13 | install -d /usr/src/os_health/iodump/ 14 | install kernel/kiodump.conf /usr/src/os_health/iodump/kiodump.conf 15 | install user/iodump /usr/sbin/iodump 16 | ps h -C iodump -o pid && killall iodump || true 17 | if [ -e /sys/module/kiodump/parameters/enable ];then { echo N > /sys/module/kiodump/parameters/enable;} fi 18 | lsmod | grep -qw kiodump && modprobe -r kiodump || true 19 | if [ -e "/usr/lib/iodump/kiodump.ko" ];then \ 20 | install -d /lib/modules/$(KERNELVER)/extra/os_health/iodump/;\ 21 | install /usr/lib/iodump/kiodump.ko /lib/modules/$(KERNELVER)/extra/os_health/iodump/kiodump.ko;\ 22 | /sbin/depmod -aeF /boot/System.map-$(KERNELVER) $(KERNELVER) > /dev/null;\ 23 | modprobe kiodump;\ 24 | if [ $$? -ne 0 ];then { echo "kiodump.ko modprobe is failed, check the dmesg info.";exit 0;} fi;\ 25 | else\ 26 | echo "The /usr/lib/iodump/kiodump.ko file does not exist in the iodump rpm package";\ 27 | exit 0; \ 28 | fi 29 | if [ -d /etc/modules-load.d/ ];then { install /usr/src/os_health/iodump/kiodump.conf /etc/modules-load.d/kiodump.conf;} fi 30 | uninstall: 31 | if [ $(id -u) -ne 0 ]; then { echo "root permission is required to uninstall iodump";exit 0;} fi 32 | ps h -C iodump -o pid && killall iodump || true 33 | if [ -e /sys/module/kiodump/parameters/enable ];then { echo N > /sys/module/kiodump/parameters/enable;} fi 34 | lsmod | grep -qw kiodump && modprobe -r kiodump || true 35 | rm -f /lib/modules/$(KERNELVER)/extra/os_health/iodump/kiodump.ko 36 | /sbin/depmod -aeF /boot/System.map-$(KERNELVER) $(KERNELVER) > /dev/null 37 | rm -f /etc/modules-load.d/kiodump.conf 38 | rm -fr /usr/lib/iodump/ 39 | rm -fr /usr/src/os_health/iodump/ 40 | rm -f /usr/sbin/iodump 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## iops dump使用手册 2 | 3 | [English](README_en-us.md) | 中文 4 | 5 | ## 目录 6 | 7 | - 一、[工具介绍](#工具介绍) 8 | - 二、[工具特点](#工具特点) 9 | - 三、[工具安装](#工具安装) 10 | - 3.1、[rpm包打包方法1](#rpm包打包方法1) 11 | - 3.2、[rpm包打包方法2](#rpm包打包方法2) 12 | - 3.3、[rpm包打包方法3](#rpm包打包方法3) 13 | - 3.4、[deb包打包方法](#deb包打包方法) 14 | - 3.5、[源代码编译安装](#源代码编译安装) 15 | - 四、[使用说明](#使用说明) 16 | - 4.1、[基本使用](#基本使用) 17 | - 4.2、[参数说明](#参数说明) 18 | - 4.3、[长期测试](#长期测试) 19 | - 五、[输出说明](#输出说明) 20 | - 六、[结果有效性](#结果有效性) 21 | - 6.1、[数据有效性](#数据有效性) 22 | - 6.2、[跟踪点的正确选择](#跟踪点的正确选择) 23 | - 6.3、[再谈数据有效性](#再谈数据有效性) 24 | - 七、[使用案例](#使用案例) 25 | - 7.1、[诊断磁盘io打满](#诊断磁盘io打满) 26 | - 7.2、[内存颠簸型磁盘io打满](#内存颠簸型磁盘io打满) 27 | - 7.3、[诊断元数据io](#诊断元数据io) 28 | - 7.4、[写类型的元数据io](#写类型的元数据io) 29 | - 7.5、[获取元数据io的文件信息](#获取元数据io的文件信息) 30 | - 7.6、[读类型的元数据io](#读类型的元数据io) 31 | - 7.7、[写系统调用触发元数据读io](#写系统调用触发元数据读io) 32 | - 7.8、[存储io的双峰模式](#存储io的双峰模式) 33 | - 八、[性能开销](#性能开销) 34 | - 九、[许可证](#许可证) 35 | - 十、[技术交流](#技术交流) 36 | 37 | 38 | 39 | 40 | 41 | ## 一、工具介绍 42 | 43 |   iops dump工具是利用内核tracepoint静态探针点技术实现的一个io问题排查工具。通过iops dump工具,我们可以获取每一个IOPS(w/s和r/s)的详细信息,不仅包括IO请求的size大小,还包括IO请求的扇区地址,同时还包含IO请求的发生时间、读写的文件全路径、产生IO请求的进程、产生IO请求的系统调用和扩展IO类型等信息。这其中最具有特色的就是读写的文件全路径功能。为了便于向大家介绍iops dump工具,下文将我们简称其为iodump。 44 | 45 | 46 | 47 | ## 二、工具特点 48 | 49 |   当我们要排查操作系统磁盘IO问题时,可以使用iostat扩展命令进行具体分析。当iostat工具显示此时磁盘IO并发很高,磁盘使用率接近饱和时,还需要依赖更多的工具进一步查看影响磁盘IO使用率高的进程信息和读写文件信息。 50 | 51 |   常见的工具或者方法有iotop、blktrace、ftrace和block_dump等。实际使用中,它们都有各种不足: 52 | - iotop工具,可以细化到进程带宽信息,但缺乏进程级的IOPS信息,也没有对应的磁盘分区信息。 53 | - blktrace工具,功能强大,但使用较复杂。获取sector信息后,进一步通过debugfs等其他方式解析文件路径也比较低效。 54 | - ftrace工具,当跟踪块设备层静态探针点时,功能和blktrace工具类似,也需要通过debugfs等工具进一步解析文件路径。当跟踪文件系统层探针点函数时,无法精确对应IOPS数量。 55 | - block_dump工具,也同样存在以上ftrace工具的2个不足。 56 | 57 |   **相比其他磁盘io类工具,iodump有如下几个特色优势** : 58 | 1. 支持自定义选择blk层探针点函数。 59 | 2. 支持自定义输出字段信息,包括时间、进程名、进程ID、IO大小、扇区地址、磁盘分区、读写类型、扩展IO类型、IO来源、Inode号,文件全路径。 60 | 3. 当采集进程异常退出后,支持内核态自动关闭探针。 61 | 4. 支持从2.6.32以上的各内核版本。 62 | 5. 当IOPS高时,支持抽样输出。 63 | 64 |   iodump功能虽然强大,但iodump本质上采用的是加载内核模块方式实现,可能会引起操作系统crash,请在重要的生产环境使用前,提前进行充分测试。从计算平台的实际使用情况,未发生生产环境宕机。 65 | 66 | 67 | 68 | ## 三、工具安装 69 | 70 |   工具的安装,有如下几种方法: 71 | 72 | 73 | 74 | ### 3.1、rpm包打包方法1 75 | 76 |   rpm包的打包方法如下,本方法适用于AnolisOS and CentOS等操作系统环境。 77 | 78 | ```bash 79 | $ yum install rpm-build rpmdevtools git 80 | $ cd /tmp/ # work dir 81 | $ git clone https://gitee.com/anolis/iodump.git 82 | $ rpmdev-setuptree 83 | $ tar -zcvf ~/rpmbuild/SOURCES/iodump-$(cat iodump/spec/iodump.spec |grep Version |awk '{print $2}').tar.gz iodump 84 | $ cp iodump/spec/iodump.spec ~/rpmbuild/SPECS/ 85 | $ rpmbuild -bb ~/rpmbuild/SPECS/iodump.spec 86 | $ cd ~/rpmbuild/RPMS/x86_64/ 87 | $ sudo rpm -ivh $(ls) 88 | $ sudo rpm -e iodump-$(uname -r) # remove package 89 | ``` 90 | 91 |   iodump工具本质上是内核驱动模块,在一个特定内核版本上生成的rpm包在另外一个不同的内核版本上是不能正常工作的。在这里我们将内核版本信息加入到rpm包的name部分,用以识别不同内核版本的rpm包。这里我们推荐使用如下rpm的查询命令区分一个rpm包的name、version、release和arch四个部分的内容。我们使用连续的3横线来区隔不同的部分,结果一目了然。 92 | 93 | ```bash 94 | $ rpm -qp iodump-4.19.91-24.8-1.0.1-1.an8.x86_64.rpm --queryformat="%{name}---%{version}---%{release}---%{arch}\n" 95 | iodump-4.19.91-24.8---1.0.1---1.an8---x86_64 96 | ``` 97 | 98 |   使用这个方法打rpm,默认会依赖当前机器上默认第一个kernel-devel包。如果想指定版本的kernel-devel包,可以使用如下rpmbuild命令通过宏参数传入内核版本信息。 99 | 100 | ```bash 101 | $ rpmbuild -bb ~/rpmbuild/SPECS/iodump.spec --define "%kver $(uname -r)" 102 | $ rpmbuild -bb ~/rpmbuild/SPECS/iodump.spec --define "%kver 4.19.91-24.8.an8.x86_64" 103 | ``` 104 | 105 | 106 | 107 | ### 3.2、rpm包打包方法2 108 | 109 |   有些情况下,在一个发行版下面,迭代了很多版本的内核,本方法适用于这种场景。 110 | 111 |   这里以Anolis 8为例,有Anolis8.2、8.4和8.6等多个小的发行版本,每个小版本也分别对应了不同的内核版本。 112 | 113 | > Release     Kernel Version 114 | 115 | > 8.2 ANCK 64位  4.19.91-25.8.an8.x86_64 116 | 117 | > 8.4 ANCK 64位  4.19.91-26.an8.x86_64 118 | 119 | > 8.6 ANCK 64位  4.19.91-26.1.an8.x86_64 120 | 121 |   此时,新版本的gcc版本通常也更新,会对低版本向下兼容。因此,我们选择最新版本Anolis8.6作为打包机。并且安装上所有需要支持的内核版本对应的kernel-devel的rpm包。 122 | 123 | > Release     Kernel-devel 124 | 125 | > 8.2 ANCK 64位  kernel-devel-4.19.91-25.8.an8.x86_64 126 | 127 | > 8.4 ANCK 64位  kernel-devel-4.19.91-26.an8.x86_64 128 | 129 | > 8.6 ANCK 64位  kernel-devel-4.19.91-26.1.an8.x86_64 130 | 131 |   相关版本的kernel-devel包,我们推荐在阿里巴巴开源镜像站进行搜索查找并下载。 132 | 133 | > https://developer.aliyun.com/packageSearch 134 | 135 |   具体打包方案如下: 136 | 137 | ```bash 138 | $ rpm -ivh --force kernel-devel-4.19.91-25.8.an8.x86_64.rpm kernel-devel-4.19.91-26.an8.x86_64.rpm 139 | $ yum install rpm-build rpmdevtools git 140 | $ cd /tmp/ # work dir 141 | $ git clone https://gitee.com/anolis/iodump.git 142 | $ rpmdev-setuptree 143 | $ tar -zcvf ~/rpmbuild/SOURCES/iodump-$(cat iodump/spec/distribution.spec |grep Version |awk '{print $2}').tar.gz iodump 144 | $ cp iodump/spec/distribution.spec ~/rpmbuild/SPECS/ 145 | $ rpmbuild -bb ~/rpmbuild/SPECS/distribution.spec 146 | $ cd ~/rpmbuild/RPMS/x86_64/ 147 | $ rpm -qpl $(ls) | grep kiodump # display all version kiodump 148 | $ sudo rpm -ivh $(ls) 149 | $ sudo rpm -e iodump # remove package 150 | ``` 151 | 152 | 153 | 154 | ### 3.3、rpm包打包方法3 155 | 156 |   在一些大型互联网公司,会在低版本发行版上使用较高版本内核的情况。比如centos7的原装内核版本是3.10,但是为了支持业务需求,在centos7的发行版上将内核升级为更高版本,如4.18内核。本方法适用于这种场景 157 | 158 |   这里以centos7为例,假设这里当前某公司同时使用了6个版本的内核,分别是3.10.0-1062、3.10.0-1127、3.10.0-1160、4.18.0-240、4.18.0-305和4.18.0-348。我们需要基于centos7发行版,制作2个docker镜像。 159 | 160 |   第一个docker镜像中包含3个3.10内核版本,需要安装如下软件包,命名为image-centos7。 161 | 162 | ```bash 163 | $ yum install rpm-build 164 | $ rpm -ivh --force kernel-devel-3.10.0-1062.el7.x86_64.rpm kernel-devel-3.10.0-1127.el7.x86_64.rpm kernel-devel-3.10.0-1160.el7.x86_64.rpm 165 | ``` 166 | 167 |   第二个docker镜像中包含3个4.18内核版本,需要安装如下软件包,命名为image-centos8。 168 | 169 | ```bash 170 | $ yum install rpm-build 171 | $ rpm -ivh --force kernel-devel-4.18.0-240.el8.x86_64.rpm kernel-devel-4.18.0-305.el8.x86_64.rpm kernel-devel-4.18.0-348.el8.x86_64.rpm 172 | $ rpm -Uvh gcc-8.5.0-4.el8_5.x86_64.rpm # 具体需要升级的gcc相关rpm包参考公司内部资料 173 | ``` 174 | 175 |   然后,具体打包方案如下: 176 | 177 | ```bash 178 | $ yum install rpmdevtools git docker 179 | $ rpmdev-setuptree 180 | $ cd ~/ 181 | $ git clone https://gitee.com/anolis/iodump.git 182 | $ tar -zcvf ~/rpmbuild/SOURCES/iodump-$(cat iodump/spec/docker.spec |grep Version |awk '{print $2}').tar.gz iodump 183 | $ cp iodump/spec/docker.spec ~/rpmbuild/SPECS/ 184 | $ docker run --net=host -u root -v ~/rpmbuild:/root/rpmbuild -w /root/rpmbuild -it image-centos8 /bin/bash -c "rpmbuild -bb /root/rpmbuild/SPECS/docker.spec" 185 | $ docker run --net=host -u root -v ~/rpmbuild:/root/rpmbuild -w /root/rpmbuild -it image-centos7 /bin/bash -c "rpmbuild -bb /root/rpmbuild/SPECS/docker.spec" 186 | $ rm -fr ~/rpmbuild/SPECS/kiodump/ # clear kiodump.ko 187 | $ cd ~/rpmbuild/RPMS/x86_64/ 188 | $ rpm -qpl iodump-*.an8.x86_64.rpm | grep kiodump # display all version kiodump 189 | $ sudo rpm -ivh iodump-*.an8.x86_64.rpm 190 | $ sudo rpm -e iodump # remove package 191 | ``` 192 | 193 | 194 | 195 | ### 3.4、deb包打包方法 196 | 197 |   deb包的打包方法如下,本方法适用于Ubuntu等操作系统环境。 198 | 199 | ```bash 200 | $ apt-get update 201 | $ apt install git 202 | $ cd ~/ 203 | $ git clone https://gitee.com/anolis/iodump.git 204 | $ cd iodump/debian 205 | $ ./build.sh 206 | $ dpkg -i iodump-4.4.0-87-generic_1.0.1-1_amd64.deb 207 | $ dpkg -r iodump-4.4.0-87-generic # remove package 208 | ``` 209 | 210 | 211 | 212 | ### 3.5、源代码编译安装 213 | 214 |   源代码安装方法。 215 | 216 | ```bash 217 | $ cd ~/ 218 | $ git clone https://gitee.com/anolis/iodump.git 219 | $ cd iodump 220 | $ make 221 | $ sudo make install 222 | $ sudo make uninstall # remove 223 | ``` 224 | 225 | 226 | 227 | ## 四、使用说明 228 | 229 | 230 | 231 | ### 4.1、基本使用 232 | 233 |   基本运命命令如下。并且运行时需要使用sudo进行提权。 234 | 235 | ```bash 236 | $ sudo iodump -p sda 237 | ``` 238 | 239 |   结束运行iodump,可以在运行过程中直接使用键盘的ctrl+c的组合,或在另外一个终端运行如下命令。 240 | 241 | ```bash 242 | $ sudo killall iodump 243 | $ sudo killall -9 iodump 244 | ``` 245 | 246 |   当向iodump进程发送SIGHUP、SIGINT和SIGTERM等信号时,用户态的iodump进程会在退出前向内核模块发送关闭内核跟踪的消息。但是,当向iodump进程发送-9,即SIGKILL信号时,用户态进程iodump将强制退出,无法向内核模块发送关闭内核跟踪的消息。此时,kiodump内核模块会在用户态iodump进程异常退出后,自动关闭内核跟踪开关。其它的blktrace等工具并没有此功能。 247 | 248 | 249 | 250 | ### 4.2、参数说明 251 | 252 |   为了完整的了解使用方法,我们可以查看帮助信息。 253 | 254 | ```bash 255 | $ iodump -h 256 | 257 | Usage: iodump [OPTIONS] 258 | 259 | Summary: this is a io tools. it can dump the details of struct request or struct bio. 260 | 261 | Options: 262 | -h Get the help information. 263 | -H Hiding header information. 264 | -a Set blk tracepoint action which is fully compatible with blktrace, default G, See Actions. 265 | -o Set the output field, such as datetime,comm,pid, See Formats. 266 | -p Set partition parameter, this option is necessary. 267 | -s Set saving output to the file. if not set, it will output to standard output. 268 | -t