1,blktrace:跟踪IO请求的工具.Linux系统发起的IO请求都可以通过blktrace捕获并分析.
debugfs是ext2, ext3, ext4文件系统提供的文件系统访问工具,通过它我们可以不通过mount文件系统而直接访问文件系统的内容,
它是e2fsprogs的一部分,默认应该都是安装的,详细的说明可以通过man debugfs得到。
2. 通过blktrace抓取对应盘的数据:
blktrace /dev/sdb -o test1 //输出文件名为:test1.blktrace.n(blktrace中,每个逻辑cpu都有一个线程,产生一个文件,故会产生cpu数目个文件)
blktrace是需要debugfs支持的,如果系统提示debugfs没有mount,需要先mount上
mount -t debugfs none /sys/kernel/debug 再执行blktrace命令.
3. 将blktrace抓出来的二进制文件转成文本格式。
blkparse sdb.blktrace.* > 1.log
blktrace /dev/sda -o - | blkparse -i – //直接在终端边临视边显示(-代表终端)
4. 开始分析日志
grep ‘ A ‘ 1.log|head -n 5
8,16 0 39 0.001242727 2872 A WS 420143 + 8 <- (8,17) 420080
8,16 0 52 0.001361766 2872 A WS 420151 + 8 <- (8,17) 420088
8,16 0 65 0.001440210 2872 A WS 420159 + 8 <- (8,17) 420096
8,16 0 78 0.001518207 2872 A WS 420167 + 8 <- (8,17) 420104
8,16 0 91 0.001596083 2872 A WS 420175 + 8 <- (8,17) 420112
为啥要grep ‘ A ‘呢?因为这条信息是上层一个读写请求进入到Linux IO协议栈的第一步,只有在这里我们可以看到清晰的请求原始信息。比如
8,16 0 39 0.001242727 2872 A WS 420143 + 8 <- (8,17) 420080
这条说明是设备(8,17)也就是sdb1上产生的扇区为420080的写请求(读请求的话会在WS对应的位置出现‘R’),长度是8,它被映射到(8,16)上位置为420143。这个IO请求的完整生命周期是这样的:
8,16 0 39 0.001242727 2872 A WS 420143 + 8 <- (8,17) 420080
8,16 0 41 0.001244984 2872 G WS 420143 + 8 [dd]
8,16 0 43 0.001246609 2872 I WS 420143 + 8 [dd]
8,16 0 45 0.001255064 2872 D WS 420143 + 8 [dd]
8,16 0 46 0.001325168 0 C WS 420143 + 8 [0]
可以看到从’ A ‘的下一条开始都是以整个设备的扇区号为标识的,不方便我们找到对应的分区。
4.1. 下面就开始通过debugfs来分析这条读写请求的来源了。
(8, 17)是sdb1, 420080是扇区号(IO层的基本单位是扇区sector,大小是512bytes),而文件系统层是通过块block来管理的,
一般的ext3,ext4的块block大小是4096[1],由此可得这个请求对应到文件系统的块block号是420080/8=52510,
4.2,debugfs提供了命令icheck可以通过block号找到它对应的文件的inode。
4.3. 通过inode number找到对应的文件名
注1. 块大小实际上也能够通过debugfs来得到。
debugfs -R ‘stats’ /dev/sdb1|grep “Block size”
注2. 有的同学找到的inode number是8,然后却无法找到对应的文件名。
这是因为8是ext3/4文件系统中的日志文件的inode,它是隐藏文件,所以无法找到,可以再试试其他的block号哦!
注3.日志详细格式说明:
8,16 1 8604 0.122819912 332 A R 1411761232 + 8 <- (9,1) 4234498128
8,16 1 8605 0.122820070 332 Q R 1411761232 + 8 [md1_resync]
8,16 1 8606 0.122820211 332 M R 1411761232 + 8 [md1_resync]
8,16 1 8607 0.122827646 332 A R 1411761240 + 8 <- (9,1) 4234498136
1,主次设备号
2,cpu id
3, blkparse自己产生的一个序号
4,秒.纳秒
5,进程ID
6,表示IO动作Action:
debugfs是ext2, ext3, ext4文件系统提供的文件系统访问工具,通过它我们可以不通过mount文件系统而直接访问文件系统的内容,
它是e2fsprogs的一部分,默认应该都是安装的,详细的说明可以通过man debugfs得到。
2. 通过blktrace抓取对应盘的数据:
blktrace /dev/sdb -o test1 //输出文件名为:test1.blktrace.n(blktrace中,每个逻辑cpu都有一个线程,产生一个文件,故会产生cpu数目个文件)
blktrace是需要debugfs支持的,如果系统提示debugfs没有mount,需要先mount上
mount -t debugfs none /sys/kernel/debug 再执行blktrace命令.
3. 将blktrace抓出来的二进制文件转成文本格式。
blkparse sdb.blktrace.* > 1.log
blktrace /dev/sda -o - | blkparse -i – //直接在终端边临视边显示(-代表终端)
4. 开始分析日志
grep ‘ A ‘ 1.log|head -n 5
8,16 0 39 0.001242727 2872 A WS 420143 + 8 <- (8,17) 420080
8,16 0 52 0.001361766 2872 A WS 420151 + 8 <- (8,17) 420088
8,16 0 65 0.001440210 2872 A WS 420159 + 8 <- (8,17) 420096
8,16 0 78 0.001518207 2872 A WS 420167 + 8 <- (8,17) 420104
8,16 0 91 0.001596083 2872 A WS 420175 + 8 <- (8,17) 420112
为啥要grep ‘ A ‘呢?因为这条信息是上层一个读写请求进入到Linux IO协议栈的第一步,只有在这里我们可以看到清晰的请求原始信息。比如
8,16 0 39 0.001242727 2872 A WS 420143 + 8 <- (8,17) 420080
这条说明是设备(8,17)也就是sdb1上产生的扇区为420080的写请求(读请求的话会在WS对应的位置出现‘R’),长度是8,它被映射到(8,16)上位置为420143。这个IO请求的完整生命周期是这样的:
8,16 0 39 0.001242727 2872 A WS 420143 + 8 <- (8,17) 420080
8,16 0 41 0.001244984 2872 G WS 420143 + 8 [dd]
8,16 0 43 0.001246609 2872 I WS 420143 + 8 [dd]
8,16 0 45 0.001255064 2872 D WS 420143 + 8 [dd]
8,16 0 46 0.001325168 0 C WS 420143 + 8 [0]
可以看到从’ A ‘的下一条开始都是以整个设备的扇区号为标识的,不方便我们找到对应的分区。
4.1. 下面就开始通过debugfs来分析这条读写请求的来源了。
(8, 17)是sdb1, 420080是扇区号(IO层的基本单位是扇区sector,大小是512bytes),而文件系统层是通过块block来管理的,
一般的ext3,ext4的块block大小是4096[1],由此可得这个请求对应到文件系统的块block号是420080/8=52510,
4.2,debugfs提供了命令icheck可以通过block号找到它对应的文件的inode。
#debugfs -R ‘icheck 52510′ /dev/sdb1
debugfs 1.43-WIP (1-Aug-2012)
Block Inode number
52510 12
4.3. 通过inode number找到对应的文件名
#debugfs -R ‘ncheck 12′ /dev/sdb1大家可以看到,我们现在已经成功找到了test_file这个文件啦,至此块设备层和文件系统层的分析工作已经结束了,下面就可以结合应用看看为啥会对这个文件有如此频繁的读写操作了!
debugfs 1.43-WIP (1-Aug-2012)
Inode Pathname
12 //testfile
注1. 块大小实际上也能够通过debugfs来得到。
debugfs -R ‘stats’ /dev/sdb1|grep “Block size”
注2. 有的同学找到的inode number是8,然后却无法找到对应的文件名。
这是因为8是ext3/4文件系统中的日志文件的inode,它是隐藏文件,所以无法找到,可以再试试其他的block号哦!
注3.日志详细格式说明:
8,16 1 8604 0.122819912 332 A R 1411761232 + 8 <- (9,1) 4234498128
8,16 1 8605 0.122820070 332 Q R 1411761232 + 8 [md1_resync]
8,16 1 8606 0.122820211 332 M R 1411761232 + 8 [md1_resync]
8,16 1 8607 0.122827646 332 A R 1411761240 + 8 <- (9,1) 4234498136
1,主次设备号
2,cpu id
3, blkparse自己产生的一个序号
4,秒.纳秒
5,进程ID
6,表示IO动作Action:
A:表示IO被重新映射到不同的设备。7,表示IO的命令:
B: IO反弹(io bounced)
C: IO完成。(io completion)
D: IO发送给驱动(io issued to driver)
F: 在队列中请求合并前的IO(io front merged with request on queue)
G: 获取请求(get request)
I: IO插入到请求队列(io inserted onto request queue)
M: 在队列中请求合并后的IO(io back merged with request on queue)
P: 阻塞请求(Plug request)
Q: IO已被请求队列处理(io handled by request queue code)
S: 请求睡眠(sleep request)
T: 拔下由于超时(unplug due to timeout)
U: 分发请求(unplug request)
X: 分拆IO(split)
W:写命令
R:读命令
D:忽略块命令
S:同步命令
B:barrier(屏障)命令
8,起始扇区号+扇区个数[<-(映射设备的主次设备号)起始扇区号]
[程序名]