📄 036_fs_dcache_c.html
字号:
void prune_dcache(int count)<BR>
{<BR>
spin_lock(&dcache_lock);<BR>
for (;;) {<BR>
struct dentry *dentry;<BR>
struct list_head *tmp;<BR>
<BR>
tmp =
dentry_unused.prev;<FONT color=#3333ff> /*遍历unused 链表*/</FONT><BR>
<BR>
if (tmp == &dentry_unused)<BR>
break;<BR>
list_del_init(tmp);<FONT color=#3333ff> /*先unshash*/</FONT><BR>
dentry = list_entry(tmp, struct
dentry, d_lru);<BR>
<BR>
/* If the dentry was recently
referenced, don't free it. */<BR>
if (dentry->d_flags &
DCACHE_REFERENCED) {
<FONT color=#3333ff>/*如果有lookup命中这个节点就还留用,继续加速查找已经删除的文件*/</FONT><BR>
dentry->d_flags &= ~DCACHE_REFERENCED;<BR>
list_add(&dentry->d_lru, &dentry_unused);<BR>
count--;<BR>
continue;<BR>
}<BR>
dentry_stat.nr_unused--;<BR>
<BR>
/* Unused dentry with a count? */<BR>
if
(atomic_read(&dentry->d_count)) <FONT color=#3333ff>/*引用计数应当为0,
印证了猜测.*/</FONT><BR>
BUG();<BR>
<BR>
prune_one_dentry(dentry);
<FONT color=#3333ff>/*全部的释放... 也有对parent节点的dput,这个函数就不罗列了*/</FONT><BR>
if (!--count)<BR>
break;<BR>
}<BR>
spin_unlock(&dcache_lock);<BR>
}<BR>
<BR>
prune dcache的过程就是在unused链表中找些东西释放给mm. 剩下的对parent节点的prune和对sb的prune不难理解,
不再罗列了.倒是select_parent的非递归算法可以看看.(这里就算了)<BR>
<BR>
初始化相关的部分,dcache_init,不再分析.<BR>
到此补充一张dentry的示意图:<BR>
<DIV id=nuz7 style="PADDING-RIGHT:0pt; PADDING-LEFT:0pt; PADDING-BOTTOM:1em; PADDING-TOP:1em; TEXT-ALIGN:left">
<IMG src=036_fs_dcache_c_images/dcbsxfpf_20vcx5trcf.gif style="WIDTH:632px; HEIGHT:528px">
</DIV>
<BR>
<BR>
顺便看看如何加入hash表吧:<BR>
static __inline__ void <FONT color=#3333ff><B>d_add</B></FONT>(struct
dentry * entry, struct inode * inode)<BR>
{<BR>
d_instantiate(entry, inode);
<FONT color=#3333ff>/*建立entry->d_alias,
inode->i_dentry关系*/</FONT><BR>
d_rehash(entry);
/<FONT color=#3333ff>*加入hash表*/</FONT><BR>
}<BR>
简单搜索可知这种 make postive的工作都交给了具体的文件系统去做了,如 ext2_lookup.
d_delete试图只是将删除的文件的inode和dentry的关系脱离,这里复习?一下.<BR>
<BR>
<BR>
说了这么多看dget_locked就知道为什么了:<BR>
/* This should be called _only_ with dcache_lock held */<BR>
<BR>
static inline struct dentry *
<FONT color=#009900><B>__dget_locked</B></FONT>(struct dentry *dentry)<BR>
{<BR>
atomic_inc(&dentry->d_count);<BR>
if (atomic_read(&dentry->d_count) == 1) {
<FONT color=#3333ff>/*我们inc后等于1, 代表他在lru队列,即unused队列*/</FONT><BR>
dentry_stat.nr_unused--;<BR>
list_del(&dentry->d_lru);
<FONT color=#3333ff>/*暂时吧他从lru搞出来,dpu又会回到这里来*/</FONT><BR>
INIT_LIST_HEAD(&dentry->d_lru);
/* make "list_empty()" work */<BR>
}<BR>
return dentry;<BR>
}<BR>
struct dentry * dget_locked(struct dentry *dentry)<BR>
{<BR>
return __dget_locked(dentry);<BR>
}<BR>
最后,反而d_lookup比较清新宜人,没啥令人难懂的操作.<BR>
struct dentry * <FONT color=#009900><B>d_lookup</B></FONT>(struct dentry *
parent, struct qstr * name)<BR>
<BR>
每次查完dcache,都要检查是不是要做revalidate操作,逻辑是:如果需要做,
组成了就好,做不成就释放invalidate这个dentry(unhash<BR>
然后 prune掉所有子目录):<BR>
if (dentry && dentry->d_op &&
dentry->d_op->d_revalidate) {<BR>
if
(!dentry->d_op->d_revalidate(dentry, flags) &&
!d_invalidate(dentry)) {<BR>
dput(dentry);<BR>
dentry = NULL;<BR>
}<BR>
}<BR>
比较典型的例子可能是NFS了,但是过于复杂了些. 看看<B>pid_base_revalidate</B>也就够了.<BR>
<FONT color=#3366ff>/**<BR>
* d_invalidate - invalidate a dentry<BR>
* @dentry: dentry to invalidate<BR>
*<BR>
* Try to invalidate the dentry if it turns out to be<BR>
* possible. If there are other dentries that can be<BR>
* reached through this one we can't delete it and we<BR>
* return -EBUSY. On success we return 0.<BR>
*<BR>
* no dcache lock.<BR>
*/<BR>
</FONT><BR>
int d_invalidate(struct dentry * dentry) /*invalidate, 使其彻底的失效*/<BR>
{<BR>
/*<BR>
* If it's already been dropped, return OK.<BR>
*/<BR>
spin_lock(&dcache_lock);<BR>
if (list_empty(&dentry->d_hash))
{<FONT color=#3366ff> /*已经无效了*/</FONT><BR>
spin_unlock(&dcache_lock);<BR>
return 0;<BR>
}<BR>
/*<BR>
* Check whether to do a partial shrink_dcache<BR>
* to get rid of unused child entries.<BR>
*/<BR>
if (!list_empty(&dentry->d_subdirs)) {
<FONT color=#3333ff>/*清除所有子目录,树*/</FONT><BR>
spin_unlock(&dcache_lock);<BR>
shrink_dcache_parent(dentry);<BR>
spin_lock(&dcache_lock);<BR>
}<BR>
<BR>
/*<BR>
* Somebody else still using it?<BR>
*<BR>
* If it's a directory, we can't drop it<BR>
* for fear of somebody re-populating it<BR>
* with children (even though dropping it<BR>
* would make it unreachable from the root,<BR>
* we might still populate it if it was a<BR>
* working directory or similar).<BR>
*/<BR>
if (atomic_read(&dentry->d_count) > 1) {<BR>
if (dentry->d_inode &&
S_ISDIR(dentry->d_inode->i_mode)) {<BR>
spin_unlock(&dcache_lock);<BR>
return -EBUSY;<BR>
}<BR>
}<BR>
<BR>
list_del_init(&dentry->d_hash);<FONT color=#3333ff>
/*这个操作就是使其无效的操作,,,,随后的dput会将其放入lru(如果ref==1)*/</FONT><BR>
spin_unlock(&dcache_lock);<BR>
return 0;<BR>
}<BR>
<BR>
<BR>
而 int d_validate(struct dentry *dentry, struct dentry
*dparent,)并不是d_invalid的对应者, 这个函数左看右看是验证一个没有引用的的指针是否有效....., ncp, smb使用,
估计做这两个文件系统的人才知道这个鬼东西到底是啥玩意.<BR>
<BR>
<BR>
struct dentry * d_find_alias(struct inode *inode)
:<FONT color=#ff0000>只有VFAT使用(2.4), 看来VFAT不支持dentry的alias(不能在其一个目录下安装多个设备?
还是另有隐情..... 待解问题....</FONT><BR>
void d_prune_aliases(struct inode *inode) 太具体了,这两个函数<BR>
<BR>
<BR>
<BR>
int is_subdir(struct dentry * new_dentry, struct dentry * old_dentry)<BR>
void <B>d_move</B>(struct dentry * dentry, struct dentry * target)
:虽然vfs_rename很复杂的,这里倒是尽是些力气活.<BR>
char * <B>__d_path</B>(struct dentry *dentry, struct vfsmount *vfsmnt,
<FONT color=#3333ff>/*从一个dentry需找其父节点的时候,要知道<BR>
mnt才能在这其中做出选择, 从follow_dot_dot我们能学到这个概念, 倒是再细细品味吧*/</FONT><BR>
struct dentry *root, struct vfsmount
*rootmnt,<BR>
char *buffer, int buflen)<BR>
asmlinkage long <B>sys_getcwd</B>(char *buf, unsigned long size)
刚好是__d_path的一个应用.<BR>
void d_genocide(struct dentry *root) : 非递归遍历树,呵呵...<BR>
int is_subdir(struct dentry * new_dentry, struct dentry * old_dentry) :呵呵<BR>
ino_t find_inode_number(struct dentry *dir, struct qstr *name)<B><BR>
</B>int have_submounts(struct dentry *parent) :有任何子目录是安装点就返回真,树的遍历...<BR>
<BR>
这里最后给出一个图,表明dentry 和mnt 所组成的一幅全景图,并且还是一个dentry下面安装多个文件系统的例子:体会下<BR>
上面的这句话:<BR>
<FONT color=#3333ff>/*从一个dentry需找其父节点的时候,要知道mnt才能在这其中做出选择,
从follow_dot_dot我们能学到这个。。。*/<BR>
<DIV id=fcni style="PADDING-RIGHT:0pt; PADDING-LEFT:0pt; PADDING-BOTTOM:1em; PADDING-TOP:1em; TEXT-ALIGN:left">
<IMG src=036_fs_dcache_c_images/dcbsxfpf_25gzfbcmd9.jpg style="WIDTH:436px; HEIGHT:635px">
</DIV>
<BR>
</FONT><B><BR>
</B><BR>
</TD>
</TR>
<TR>
<TD vAlign=top>
<BR>
</TD>
</TR>
<TR>
<TD vAlign=top>
<BR>
</TD>
</TR>
<TR>
<TD vAlign=top>
<BR>
</TD>
</TR>
</TBODY>
</TABLE></body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -