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:
Christoph Hellwig 2009-01-05 19:10:37 +01:00 committed by Al Viro
parent 2b1c6bd77d
commit b6520c8193
1 changed files with 18 additions and 30 deletions

View File

@ -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: