cleanup d_add_ci
Make sure that comments describe what's going on and not how, and always use __d_instantiate instead of two separate branches, one with d_instantiate and one with __d_instantiate. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
2b1c6bd77d
commit
b6520c8193
48
fs/dcache.c
48
fs/dcache.c
|
@ -1247,15 +1247,18 @@ struct dentry *d_add_ci(struct dentry *dentry, struct inode *inode,
|
||||||
struct dentry *found;
|
struct dentry *found;
|
||||||
struct dentry *new;
|
struct dentry *new;
|
||||||
|
|
||||||
/* Does a dentry matching the name exist already? */
|
/*
|
||||||
|
* First check if a dentry matching the name already exists,
|
||||||
|
* if not go ahead and create it now.
|
||||||
|
*/
|
||||||
found = d_hash_and_lookup(dentry->d_parent, name);
|
found = d_hash_and_lookup(dentry->d_parent, name);
|
||||||
/* If not, create it now and return */
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
new = d_alloc(dentry->d_parent, name);
|
new = d_alloc(dentry->d_parent, name);
|
||||||
if (!new) {
|
if (!new) {
|
||||||
error = -ENOMEM;
|
error = -ENOMEM;
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
found = d_splice_alias(inode, new);
|
found = d_splice_alias(inode, new);
|
||||||
if (found) {
|
if (found) {
|
||||||
dput(new);
|
dput(new);
|
||||||
|
@ -1263,61 +1266,46 @@ struct dentry *d_add_ci(struct dentry *dentry, struct inode *inode,
|
||||||
}
|
}
|
||||||
return new;
|
return new;
|
||||||
}
|
}
|
||||||
/* Matching dentry exists, check if it is negative. */
|
|
||||||
|
/*
|
||||||
|
* If a matching dentry exists, and it's not negative use it.
|
||||||
|
*
|
||||||
|
* Decrement the reference count to balance the iget() done
|
||||||
|
* earlier on.
|
||||||
|
*/
|
||||||
if (found->d_inode) {
|
if (found->d_inode) {
|
||||||
if (unlikely(found->d_inode != inode)) {
|
if (unlikely(found->d_inode != inode)) {
|
||||||
/* This can't happen because bad inodes are unhashed. */
|
/* This can't happen because bad inodes are unhashed. */
|
||||||
BUG_ON(!is_bad_inode(inode));
|
BUG_ON(!is_bad_inode(inode));
|
||||||
BUG_ON(!is_bad_inode(found->d_inode));
|
BUG_ON(!is_bad_inode(found->d_inode));
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* Already have the inode and the dentry attached, decrement
|
|
||||||
* the reference count to balance the iget() done
|
|
||||||
* earlier on. We found the dentry using d_lookup() so it
|
|
||||||
* cannot be disconnected and thus we do not need to worry
|
|
||||||
* about any NFS/disconnectedness issues here.
|
|
||||||
*/
|
|
||||||
iput(inode);
|
iput(inode);
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Negative dentry: instantiate it unless the inode is a directory and
|
* Negative dentry: instantiate it unless the inode is a directory and
|
||||||
* has a 'disconnected' dentry (i.e. IS_ROOT and DCACHE_DISCONNECTED),
|
* already has a dentry.
|
||||||
* in which case d_move() that in place of the found dentry.
|
|
||||||
*/
|
*/
|
||||||
if (!S_ISDIR(inode->i_mode)) {
|
|
||||||
/* Not a directory; everything is easy. */
|
|
||||||
d_instantiate(found, inode);
|
|
||||||
return found;
|
|
||||||
}
|
|
||||||
spin_lock(&dcache_lock);
|
spin_lock(&dcache_lock);
|
||||||
if (list_empty(&inode->i_dentry)) {
|
if (!S_ISDIR(inode->i_mode) || list_empty(&inode->i_dentry)) {
|
||||||
/*
|
|
||||||
* Directory without a 'disconnected' dentry; we need to do
|
|
||||||
* d_instantiate() by hand because it takes dcache_lock which
|
|
||||||
* we already hold.
|
|
||||||
*/
|
|
||||||
__d_instantiate(found, inode);
|
__d_instantiate(found, inode);
|
||||||
spin_unlock(&dcache_lock);
|
spin_unlock(&dcache_lock);
|
||||||
security_d_instantiate(found, inode);
|
security_d_instantiate(found, inode);
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Directory with a 'disconnected' dentry; get a reference to the
|
* In case a directory already has a (disconnected) entry grab a
|
||||||
* 'disconnected' dentry.
|
* reference to it, move it in place and use it.
|
||||||
*/
|
*/
|
||||||
new = list_entry(inode->i_dentry.next, struct dentry, d_alias);
|
new = list_entry(inode->i_dentry.next, struct dentry, d_alias);
|
||||||
dget_locked(new);
|
dget_locked(new);
|
||||||
spin_unlock(&dcache_lock);
|
spin_unlock(&dcache_lock);
|
||||||
/* Do security vodoo. */
|
|
||||||
security_d_instantiate(found, inode);
|
security_d_instantiate(found, inode);
|
||||||
/* Move new in place of found. */
|
|
||||||
d_move(new, found);
|
d_move(new, found);
|
||||||
/* Balance the iget() we did above. */
|
|
||||||
iput(inode);
|
iput(inode);
|
||||||
/* Throw away found. */
|
|
||||||
dput(found);
|
dput(found);
|
||||||
/* Use new as the actual dentry. */
|
|
||||||
return new;
|
return new;
|
||||||
|
|
||||||
err_out:
|
err_out:
|
||||||
|
|
Loading…
Reference in New Issue