在客戶使用我們產(chǎn)品后鹏氧,發(fā)現(xiàn)一個(gè)問題:在刪除了文件后池户,磁盤空間卻沒有釋放离例。是有進(jìn)程在打開這個(gè)文件换团,還是其他情況?我們一起來看看一下兩個(gè)場(chǎng)景
一. 場(chǎng)景一:進(jìn)程打開此文件
當(dāng)一個(gè)文件正在被一個(gè)進(jìn)程使用時(shí)宫蛆,用戶刪除此文件艘包,文件只會(huì)從目錄結(jié)構(gòu)中刪除,但并沒有從磁盤刪除耀盗。當(dāng)使用這個(gè)文件的進(jìn)程結(jié)束后想虎,文件才會(huì)真正的從磁盤刪除,釋放占有的空間袍冷。
我們發(fā)現(xiàn)剩余磁盤空間比較少時(shí),回去刪除一些大的臨時(shí)文件或者log文件猫牡,如果刪除之后會(huì)發(fā)現(xiàn)磁盤空間并未減少胡诗,那么可以通過“l(fā)sof”命令去查看正在使用該文件的進(jìn)程,然后再重啟該進(jìn)程或者服務(wù)淌友。
【例子】
現(xiàn)在發(fā)現(xiàn)磁盤空間的占用了99%煌恢,剩余空間只剩下522M。
SUSE11X64-001:/test # df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda2 29G 27G 522M 99% /
devtmpfs 972M 116K 972M 1% /dev
tmpfs 972M 0 972M 0% /dev/shm
找到一個(gè)文件"vmcore"占用了接近900M空間震庭,但這個(gè)文件不需要再使用了瑰抵,于是采用“rm”命令刪除此文件,可是刪除后器联,發(fā)現(xiàn)磁盤空間并沒有真正的減少二汛。
SUSE11X64-001:/test # rm vmcore
SUSE11X64-001:/test # df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda2 29G 27G 522M 99% /
devtmpfs 972M 116K 972M 1% /dev
tmpfs 972M 0 972M 0% /dev/shm
//10.204.16.2/home/splx/iceking 6.3T 1.6T 4.7T 25% /mnt/iceking
也就是說很有可能有其他進(jìn)程正在使用這個(gè)文件,使用“l(fā)sof”命令去查看正在使用該文件的進(jìn)程拨拓。
SUSE11X64-001:/test # lsof | grep vmcore
a.out 2610 root 3r REG 8,2 941331144 1643779 /test/vmcore (deleted)
進(jìn)程號(hào)為2610(進(jìn)程名為"a.out")的進(jìn)程肴颊,正在使用vmcore文件,也可以看到其后有“deleted”:其表示正在使用的文件被刪除渣磷,但并沒有真正從磁盤上移除婿着。
現(xiàn)在我們刪除這個(gè)進(jìn)程,并查看磁盤空間此時(shí)占用率降低為95%醋界,剩余空間增加到1.4G竟宋。
SUSE11X64-001:/test # df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda2 29G 26G 1.4G 95% /
devtmpfs 972M 116K 972M 1% /dev
tmpfs 972M 0 972M 0% /dev/shm
二. 場(chǎng)景二:內(nèi)核模塊Bug
在文件系統(tǒng)處理文件需要的信息都存放在索引節(jié)點(diǎn)(inode)中,如果在刪除文件的時(shí)候索引節(jié)點(diǎn)的引用計(jì)數(shù)不為0(表示文件正在被使用)形纺,則不會(huì)在磁盤中真正的刪除文件丘侠,從而保證正在使用此文件的進(jìn)程能夠正常的處理文件。
首先我們一起來看一下內(nèi)核中關(guān)于文件系統(tǒng)的一些關(guān)鍵數(shù)據(jù)結(jié)構(gòu)的關(guān)聯(lián)逐样,當(dāng)一個(gè)進(jìn)程打開一個(gè)文件后婉陷,便會(huì)在內(nèi)核中創(chuàng)建一個(gè)file對(duì)象帚称,這個(gè)對(duì)象主要描述了進(jìn)程如何與文件進(jìn)行交互。file對(duì)象中將指向一個(gè)dentry結(jié)構(gòu)(目錄項(xiàng))秽澳,目錄項(xiàng)中描述了目錄項(xiàng)名稱闯睹,父目錄項(xiàng)信息,子目錄項(xiàng)信息等担神。而dentry中的d_inode所指向的inode節(jié)點(diǎn)中則包含了實(shí)際的文件存儲(chǔ)在磁盤上的信息楼吃。
當(dāng)多個(gè)進(jìn)程打開同一個(gè)文件時(shí),內(nèi)核中變會(huì)創(chuàng)建相應(yīng)的file對(duì)象妄讯,但是他們都公用同一個(gè)dentry孩锡,只不過每一次打開文件dentry的引用計(jì)數(shù)d_count加1。并且對(duì)于打開的同一個(gè)文件而言亥贸,inode也是唯一的躬窜,inode的引用計(jì)數(shù)i_count一般為文件硬鏈接的數(shù)目】恢茫看過一些中文博客荣挨,說“同一個(gè)文件,每打開一次朴摊,則inode中引用計(jì)數(shù)i_count則加1”默垄,這種說法通過我的驗(yàn)證結(jié)果是錯(cuò)誤的。實(shí)驗(yàn)結(jié)果是:對(duì)于同一個(gè)文件甚纲,每打開一次口锭,則inode中的引用計(jì)數(shù)不變,但相應(yīng)的dentry引用計(jì)數(shù)加1.
這次客戶在刪除文件后介杆,磁盤空間沒有釋放鹃操,通過"lsof"命令也沒有找到正在占用此文件的進(jìn)程。于是再次懷疑這是由于產(chǎn)品的內(nèi)核模塊早成的春哨。后經(jīng)分析得到:在上一篇博文《Linux Kernel模塊內(nèi)存泄露查找 (2)》中解釋過由于在產(chǎn)品內(nèi)核模塊中组民,對(duì)dentry引用,并使用完之后并沒有對(duì)其引用計(jì)數(shù)減1悲靴,從而造成內(nèi)存泄露臭胜。在這種情況下,dentry不會(huì)被釋放癞尚,則inode也就一直被引用著耸三,從而也導(dǎo)致了即使刪除文件,也不會(huì)從磁盤刪除浇揩。
而且針對(duì)以上的問題和分析仪壮,如果不能及時(shí)給客戶修這個(gè)問題,那也只能讓其重新啟動(dòng)OS胳徽,空閑的磁盤空間才會(huì)釋放出來积锅。