long do_unlinkat(int dfd, const char __user *pathname)
{
struct dentry *dentry;
struct nameidata nd;
struct inode *inode = NULL;
error = user_path_parent(dfd, pathname, &nd, &name);
dentry = lookup_hash(&nd);
inode = dentry->d_inode;
if (inode)
atomic_inc(&inode->i_count);
error = mnt_want_write(nd.path.mnt);
error = vfs_unlink(nd.path.dentry->d_inode, dentry);
mnt_drop_write(nd.path.mnt);
dput(dentry);
if (inode)
iput(inode); /* truncate the inode here */
=>void iput(struct inode *inode)
{
if (inode) {
BUG_ON(inode->i_state == I_CLEAR);
if (atomic_dec_and_lock(&inode->i_count, &inode_lock))
iput_final(inode);
=>void iput_final(struct inode *inode)
{
const struct super_operations *op = inode->i_sb->s_op;
void (*drop)(struct inode *) = generic_drop_inode;
if (op && op->drop_inode)
drop = op->drop_inode;
drop(inode);
=>void generic_drop_inode(struct inode *inode)
{
if (!inode->i_nlink)
generic_delete_inode(inode);//Super.c (fs\ext2): .delete_inode = ext2_delete_inode,
=>void ext2_delete_inode (struct inode * inode)
{
if (!is_bad_inode(inode))
dquot_initialize(inode);
truncate_inode_pages(&inode->i_data, 0);
if (is_bad_inode(inode))
goto no_delete;
EXT2_I(inode)->i_dtime = get_seconds();
mark_inode_dirty(inode);
__ext2_write_inode(inode, inode_needs_sync(inode));
inode->i_size = 0;
if (inode->i_blocks)
ext2_truncate (inode);
ext2_free_inode (inode);//真正释放文件节点
return;
no_delete:
clear_inode(inode); /* We must guarantee clearing of inode... */
}
else
generic_forget_inode(inode);
}
}
}
}
path_put(&nd.path);
putname(name);
return error;
}