]> err.no Git - linux-2.6/blobdiff - fs/nfs/dir.c
NFS: Be strict about dentry revalidation when doing exclusive create
[linux-2.6] / fs / nfs / dir.c
index cf80cf234e27ddc58be4d2dd2ea25921897c1aa4..c2207e3f26344f3b4ef86da47116263d0d65aaf7 100644 (file)
@@ -211,9 +211,7 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
        unlock_page(page);
        return 0;
  error:
-       SetPageError(page);
        unlock_page(page);
-       nfs_zap_caches(inode);
        desc->error = error;
        return -EIO;
 }
@@ -656,11 +654,6 @@ static int nfs_check_verifier(struct inode *dir, struct dentry *dentry)
        return 1;
 }
 
-static inline void nfs_set_verifier(struct dentry * dentry, unsigned long verf)
-{
-       dentry->d_time = verf;
-}
-
 /*
  * Return the intent data that applies to this particular path component
  *
@@ -675,6 +668,19 @@ static inline unsigned int nfs_lookup_check_intent(struct nameidata *nd, unsigne
        return nd->flags & mask;
 }
 
+/*
+ * Use intent information to check whether or not we're going to do
+ * an O_EXCL create using this path component.
+ */
+static int nfs_is_exclusive_create(struct inode *dir, struct nameidata *nd)
+{
+       if (NFS_PROTO(dir)->version == 2)
+               return 0;
+       if (nd == NULL || nfs_lookup_check_intent(nd, LOOKUP_CREATE) == 0)
+               return 0;
+       return (nd->intent.open.flags & O_EXCL) != 0;
+}
+
 /*
  * Inode and filehandle revalidation for lookups.
  *
@@ -761,7 +767,7 @@ static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
        }
 
        /* Force a full look up iff the parent directory has changed */
-       if (nfs_check_verifier(dir, dentry)) {
+       if (!nfs_is_exclusive_create(dir, nd) && nfs_check_verifier(dir, dentry)) {
                if (nfs_lookup_verify_inode(inode, nd))
                        goto out_zap_parent;
                goto out_valid;
@@ -855,30 +861,6 @@ struct dentry_operations nfs_dentry_operations = {
        .d_iput         = nfs_dentry_iput,
 };
 
-/*
- * Use intent information to check whether or not we're going to do
- * an O_EXCL create using this path component.
- */
-static inline
-int nfs_is_exclusive_create(struct inode *dir, struct nameidata *nd)
-{
-       if (NFS_PROTO(dir)->version == 2)
-               return 0;
-       if (nd == NULL || nfs_lookup_check_intent(nd, LOOKUP_CREATE) == 0)
-               return 0;
-       return (nd->intent.open.flags & O_EXCL) != 0;
-}
-
-static inline int nfs_reval_fsid(struct inode *dir, const struct nfs_fattr *fattr)
-{
-       struct nfs_server *server = NFS_SERVER(dir);
-
-       if (!nfs_fsid_equal(&server->fsid, &fattr->fsid))
-               /* Revalidate fsid using the parent directory */
-               return __nfs_revalidate_inode(server, dir);
-       return 0;
-}
-
 static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
 {
        struct dentry *res;
@@ -917,11 +899,6 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru
                res = ERR_PTR(error);
                goto out_unlock;
        }
-       error = nfs_reval_fsid(dir, &fattr);
-       if (error < 0) {
-               res = ERR_PTR(error);
-               goto out_unlock;
-       }
        inode = nfs_fhget(dentry->d_sb, &fhandle, &fattr);
        res = (struct dentry *)inode;
        if (IS_ERR(res))
@@ -994,14 +971,6 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
 
        /* Open the file on the server */
        lock_kernel();
-       /* Revalidate parent directory attribute cache */
-       error = nfs_revalidate_inode(NFS_SERVER(dir), dir);
-       if (error < 0) {
-               res = ERR_PTR(error);
-               unlock_kernel();
-               goto out;
-       }
-
        res = nfs4_atomic_open(dir, dentry, nd);
        unlock_kernel();
        if (IS_ERR(res)) {
@@ -1024,7 +993,6 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
                }
        } else if (res != NULL)
                dentry = res;
-       nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
 out:
        return res;
 no_open:
@@ -1045,8 +1013,12 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
        /* We can't create new files in nfs_open_revalidate(), so we
         * optimize away revalidation of negative dentries.
         */
-       if (inode == NULL)
+       if (inode == NULL) {
+               if (!nfs_neg_need_reval(dir, dentry, nd))
+                       ret = 1;
                goto out;
+       }
+
        /* NFS only supports OPEN on regular files */
        if (!S_ISREG(inode->i_mode))
                goto no_open;
@@ -1064,8 +1036,6 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
         */
        lock_kernel();
        ret = nfs4_open_revalidate(dir, dentry, openflags, nd);
-       if (ret == 1)
-               nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
        unlock_kernel();
 out:
        dput(parent);