make nfs_atomic_open() call d_drop() on all ->open_context() errors.
[cascardo/linux.git] / fs / nfs / dir.c
index aaf7bd0..d8015a0 100644 (file)
@@ -424,12 +424,17 @@ static int xdr_decode(nfs_readdir_descriptor_t *desc,
 static
 int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry)
 {
+       struct inode *inode;
        struct nfs_inode *nfsi;
 
        if (d_really_is_negative(dentry))
                return 0;
 
-       nfsi = NFS_I(d_inode(dentry));
+       inode = d_inode(dentry);
+       if (is_bad_inode(inode) || NFS_STALE(inode))
+               return 0;
+
+       nfsi = NFS_I(inode);
        if (entry->fattr->fileid == nfsi->fileid)
                return 1;
        if (nfs_compare_fh(entry->fh, &nfsi->fh) == 0)
@@ -1363,7 +1368,6 @@ EXPORT_SYMBOL_GPL(nfs_dentry_operations);
 struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags)
 {
        struct dentry *res;
-       struct dentry *parent;
        struct inode *inode = NULL;
        struct nfs_fh *fhandle = NULL;
        struct nfs_fattr *fattr = NULL;
@@ -1393,7 +1397,6 @@ struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned in
        if (IS_ERR(label))
                goto out;
 
-       parent = dentry->d_parent;
        /* Protect against concurrent sillydeletes */
        trace_nfs_lookup_enter(dir, dentry, flags);
        error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label);
@@ -1536,9 +1539,9 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry,
                err = PTR_ERR(inode);
                trace_nfs_atomic_open_exit(dir, ctx, open_flags, err);
                put_nfs_open_context(ctx);
+               d_drop(dentry);
                switch (err) {
                case -ENOENT:
-                       d_drop(dentry);
                        d_add(dentry, NULL);
                        nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
                        break;