分类: LINUX
2013-10-22 13:57:16
原文地址:对dentry的理解 作者:Mars007
1.dentry与inode是多对一的(硬链接的情况),可以通过inode->i_dentry找到指向inode的所有dentry.
2.sys_open() 打开一个文件,如果文件不存在,dentry仍然会被创建且被加入到dcache中,但是dentry指向的inode为空(此时dentry为负状 态),path_walk()完毕后,dentry被加入到super_block的LRU链表中,等待销毁.
3.dentry有自己所属的文件系统,因此dentry建立的树状层次结构只在dentry所属的文件系统中生效.
4. 引用计数为0的dentry仍然会保留在dcache中,但是同时也会被加入到super_block的LRU未使用链表中,当需要释放内存时,压缩 dentry的slab回调函数shrink_dcache_memory()被调用,将LRU链表中最久未被使用的dentry从dentry缓存中删 除后,释放给slab分配器.
5.dentry被创建时其父dentry必然存在,且会增加父dentry的引用计数,dentry被销毁
时会减少其父dentry的引用计数,如果其父dentry的引用计数被递减后变为0,那么其父dentry会被销毁,依次向上,直到文件系统的root
dentry.
Q:文件系统中有一个文件foo,假设文件系统同时挂载到/mnt1/和/mnt2/,那么/mnt1/foo和/mnt2/foo对应的dentry是同一个dentry吗?
A:是的,一个块设备可以被挂载到多处,每次挂载都会创建vfsmount,但是VFS的super_block只有一个,dentry是属于文件系统的
而不是属于某个挂载点,唯一代表文件系统的是VFS的super_block,因此,dentry结构体中有到super_block的指针,但是没有到
vfsmount的指针,/mnt1/foo和/mnt2/foo是同一个文件系统下的同一个文件,他们对应的dentry也必然是相同的,理解了
dentry是属于文件系统的,就很容易理解为什么struct path的成员只有vfsmount和dentry了.
Q:得到dentry后,可以沿着dentry->d_parent往上一直到系统的根目录吗?
A:如果dentry是属于根文件系统的,则可以.否则,如果dentry属于新挂载的文件系统,则不能,因为通过dentry是无法得知文件系统的挂载
点的(如果文件系统只挂载了一次,通过dentry拿到文件系统的根dentry,找到vfsmount,获得挂载点也是一种办法).
Q:引用计数为0的dentry会同时存在于super_block的未使用链表和dcache中,当通过do_lookup()函数从dcache中找到dentry时只是增加dentry的引用计数,为什么不把它从super_block的链表中删除?
A:dentry的LRU实现使用了lazy
LRU,因为dentry的使用时间可能非常短(如stat一个文件),如果从dcahce中找到后,立即将dentry从LRU中移除,使用完毕后,马
上又要插入到LRU链表中,增加了链表操作的开销,由于LRU链表是受全局dcache_lock保护的,加剧对dcache_lock的争用.但是,这
样一来又有一个问题,dentry的引用计数从0->1,到1->0的过程中,dentry在LRU链表中的位置没有变化,且dput()
时,dentry已经在LRU链表中,DCACHE_REFERENCED标志不会置位,shrink_dcache_memory()被调用时,可能被
当作最久未使用dentry给释放掉,但是实际情况是,dentry刚刚才被使用,super_block的LRU链表明显没有达到效果?哥们的这个疑问
还真是一个问题,这个问题已由Nick Piggin在这个中解决.
Q:
调用unlink()删除文件时,经过sys_unlink()->do_unlinkat()->vfs_unlink()进入到
d_delete(),如果dentry还被其他进程使用(dentry->d_count>1),为什么d_delete()需要将
dentry从dcache中移除?
A:如果dentry被其他进程引用,在d_delete()中还不能将dentry转化为负状态,但是必须
将dentry(记为dentry1,dentry1对应的inode记为inode1)从dcache中移除,否则,后续在同一个目录下创建相同文件名
的文件时会从dcache中找到dentry1,导致引用inode1,出现新创建的文件就有数据的情况.