內核包含的文(wen)件(jian)(jian)系統(tong)非常豐(feng)富,無法全部列舉(ju),本(ben)文(wen)主要討(tao)論的是網絡(luo)文(wen)件(jian)(jian)系統(tong),具體是 NFS 、CIFS 、9P 和 CEPH 這 4 個(ge)文(wen)件(jian)(jian)系統(tong)。
第1,關(guan)于 NFS 的調試開關(guan)。
原理:NFS 的調(diao)試打印(yin)沿用(yong)了(le)(le) sunrpc 實現的 dprintk() 接口,該接口調(diao)用(yong) printk() ,借助一些標(biao)志(zhi)位進行細粒度的調(diao)試控制(zhi),這(zhe)些標(biao)志(zhi)位保(bao)存在一個(ge)靜態變(bian)(bian)量里,該變(bian)(bian)量通(tong)過 procfs 接口暴露給用(yong)戶態進行修改。NFS 就是在此之上,新增了(le)(le) nfs_debug 變(bian)(bian)量作為(wei)調(diao)試開關,該變(bian)(bian)量支(zhi)持保(bao)存的標(biao)志(zhi)參見 include/uapi/linux/nfs_fs.h ,宏定義(yi)都(dou)是 NFSDBG_XXX 這(zhe)種格式(shi),呈現給用(yong)戶態的 proc 文件是 /proc/sys/sunrpc/nfs_debug。
使用(yong): 首先(xian)看(kan)調(diao)用(yong) dprintk() 的(de) C 源文件如(ru)何定義 NFSDBG_FACILITY ,例如(ru) fs/nfs/blocklayout/blocklayout.c 對(dui) NFSDBG_FACILITY 的(de)定義是(shi) NFSDBG_PNFS_LD ,然后看(kan) NFSDBG_PNFS_LD 的(de)定義,可見(jian)是(shi) 0x2000 ,那么就使用(yong)以下命(ming)令開啟調(diao)試打印,即
echo 0x2000 > /proc/sys/sunrpc/nfs_debug
第2,關于 CIFS 的調試開關。
原(yuan)理:CIFS 封(feng)裝了自(zi)己的調(diao)試(shi)打印接口,即 cifs_dbg() 接口。它基于(yu) pr_debug() 接口實(shi)現,并由 cifsFYI 變(bian)量作(zuo)為總開關。這個變(bian)量呈(cheng)現給(gei)用戶態(tai)的 proc 文件(jian)是 /proc/fs/cifs/cifsFYI 。
使用:
使用前需確認內(nei)核是否(fou)支(zhi)持(chi) pr_debug() ,執行以(yi)下(xia)命令(ling)確認,即(ji)
grep DYNAMIC_DEBUG /boot/config-`uname -r`
如果看(kan)到 CONFIG_DYNAMIC_DEBUG=y ,則可(ke)以(yi)(yi)繼續執行以(yi)(yi)下操作。
然后確認系統是否掛(gua)載 debugfs 以及掛(gua)載路徑(jing),執(zhi)行以下命令確認,即(ji)
mount | grep debugfs
通(tong)常會(hui)看到以(yi)下輸出:
debugfs on /sys/kernel/debug type debugfs (rw,nosuid,nodev,noexec,relatime)
說明(ming)系(xi)統已掛載 debugfs 到 /sys/kernel/debug 目錄。
然后打(da)開(kai) CIFS 的調試總開(kai)關,執行
echo 1 > /proc/fs/cifs/cifsFYI
接(jie)下來(lai)就看 cifs_dbg() 接(jie)口所在的(de) C 源文(wen)件和行號,假(jia)設在 fs/cifs/transport.c 第 68 行調用(yong)了 cifs_dbg() 接(jie)口,那么執(zhi)行以(yi)下命令(ling),即
echo "file fs/cifs/transport.c line 68 +p" > /sys/kernel/debug/dynamic_debug/control
最后為(wei)了看到輸出內容,還(huan)要調整內核(he)日志級(ji)別(原(yuan)理(li)參(can)考本專(zhuan)欄的(de) 控制(zhi)內核(he)日志打印 ),執行以下命令(ling):
echo 8 4 1 7 > /proc/sys/kernel/printk
或者
dmesg -n 8
至此就開啟 CIFS 的調試開關了。
第3,關于 CEPH 的(de)調試開關。
原理(li):CEPH 封裝的調試打(da)印接口是 dout() ,與 CIFS 類似,也是調用 pr_debug() 接口。
使用:
使用前(qian)也(ye)需要確認前(qian)置條(tiao)件(jian),參見上(shang)述 CIFS 的(de)說明。
接下來看(kan) dout() 接口所在的 C 源文件和行號,假設在 fs/ceph/inode.c 第(di) 768 行調用了(le) dout() 接口,那(nei)么執(zhi)行以下命令,即
echo "file fs/ceph/inode.c line 768 +p" > /sys/kernel/debug/dynamic_debug/control
最后調整內核日志級別,執(zhi)行 dmesg -n 8 即可。
第4,關于 9P 的調試(shi)開(kai)關。
原(yuan)理:9P 封(feng)裝的(de)(de)調試(shi)打印接口是(shi) p9_debug() ,底層(ceng)調用(yong)的(de)(de)是(shi) pr_notice() 。p9_debug() 用(yong) p9_debug_level 變(bian)(bian)量作為調試(shi)開關,其(qi)中通過不同(tong)標志(zhi)位進行細(xi)粒度的(de)(de)打印控制(zhi)。 p9_debug_level 變(bian)(bian)量由掛載選(xuan)項 debug 來控制(zhi),它(ta)支持保存的(de)(de)標志(zhi)位參見 include/net/9p/9p.h 定義的(de)(de) p9_debug_flags 枚舉,其(qi)中的(de)(de)枚舉都(dou)是(shi) P9_DEBUG_XXX 這(zhe)種(zhong)格式。
使用(yong):在虛(xu)擬機里掛載 9P 時指(zhi)定 debug 參數,假設(she)要(yao)開啟 P9_DEBUG_SLABS 標(biao)志,枚舉(ju)值是 (1<<7) = 128 ,那么執行
mount -t 9p -o trans=virtio,debug=128,nfcp host9ptest /mnt/9ptest -oversion=9p2000.L
總結:
上述文件系統的(de)(de)調試打(da)印(yin)接口都是(shi)(shi)基于內核已有的(de)(de)日志接口進行封裝(zhuang),封裝(zhuang)的(de)(de)目的(de)(de)是(shi)(shi)方便(bian)新增一些標志位進行細粒度(du)的(de)(de)控制,這些標志位保存在某個變量(liang)里。修改(gai)這個變量(liang)的(de)(de)方式可(ke)以(yi)是(shi)(shi)通(tong)(tong)過(guo) proc 文件修改(gai),也可(ke)以(yi)是(shi)(shi)通(tong)(tong)過(guo)掛載(zai)選(xuan)項指定。