/*
* This is dput
*
* This is complicated by the fact that we do not want to put
* dentries that are no longer on any hash chain on the unused
* list: we'd much rather just get rid of them immediately.
*
* However, that implies that we have to traverse the dentry
* tree upwards to the parents which might _also_ now be
* scheduled for deletion (it may have been only waiting for
* its last child to go away).
*
* This tail recursion is done by hand as we don't want to depend
* on the compiler to always get this right (gcc generally doesn't).
* Real recursion would eat up our stack space.
*/
/*
* dput - release a dentry
* @dentry: dentry to release
*
* Release a dentry. This will drop the usage count and if appropriate
* call the dentry unlink method as well as removing it from the queues and
* releasing its resources. If the parent dentries were scheduled for release
* they too may now get deleted.
*/
/*
*dput()产生的原因:由于不想在不再使用的列表上放置已不在哈希链上的目录文件,我们更愿意立即删除它们。
*同时也意味要向上遍历预备删除的父母目录节点(这些父母节点只等待最后的孩子节点被删除/释放)
*因为不指望编译器的正确编译,该递归是手工完成的,真实的递归会占用堆栈空间。
*/
/*
* dput - release a dentry 释放一个目录
* @dentry: dentry to release *
* Release a dentry. This will drop the usage count and if appropriate
* call the dentry unlink method as well as removing it from the queues and
* releasing its resources. If the parent dentries were scheduled for release
* they too may now get deleted. 如果父母目录节点预备释放的话可能会一起删除
*/
void dput(struct dentry *dentry)
{
if (unlikely(!dentry))
return;
repeat:
might_sleep();
rcu_read_lock();
if (likely(fast_dput(dentry))) {
rcu_read_unlock();
return;
}
/* Slow case: now with the dentry lock held */
rcu_read_unlock();
if (likely(retain_dentry(dentry))) {
spin_unlock(&dentry->d_lock);
return;
}
dentry = dentry_kill(dentry);
if (dentry) {
cond_resched();
goto repeat;
}
}
dput()内核源码:https://elixir.bootlin.com/linux/latest/source/fs/dcache.c#L828