Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=c79ba787c11e767ffaf8d723923afda99ba6c63c
Commit:     c79ba787c11e767ffaf8d723923afda99ba6c63c
Parent:     ef75c7974b383769ae5741cf930b8aa4dcaef395
Author:     Trond Myklebust <[EMAIL PROTECTED]>
AuthorDate: Wed Jan 31 08:16:24 2007 -0500
Committer:  Trond Myklebust <[EMAIL PROTECTED]>
CommitDate: Sat Feb 3 15:35:05 2007 -0800

    NFS: Dont clobber more uptodate values in nfs_set_verifier()
    
    nfs_lookup_revalidate and friends are not serialised, so it is currently
    quite possible for the dentry to be revalidated, and then have the
    updated verifier replaced with an older value by another process.
    
    Signed-off-by: Trond Myklebust <[EMAIL PROTECTED]>
---
 fs/nfs/dir.c |   19 ++++++++++++++-----
 1 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 062e108..37c1dd6 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -637,7 +637,7 @@ int nfs_fsync_dir(struct file *filp, struct dentry *dentry, 
int datasync)
  * In the case it has, we assume that the dentries are untrustworthy
  * and may need to be looked up again.
  */
-static inline int nfs_check_verifier(struct inode *dir, struct dentry *dentry)
+static int nfs_check_verifier(struct inode *dir, struct dentry *dentry)
 {
        if (IS_ROOT(dentry))
                return 1;
@@ -652,6 +652,12 @@ static inline void nfs_set_verifier(struct dentry * 
dentry, unsigned long verf)
        dentry->d_fsdata = (void *)verf;
 }
 
+static void nfs_refresh_verifier(struct dentry * dentry, unsigned long verf)
+{
+       if (time_after(verf, (unsigned long)dentry->d_fsdata))
+               nfs_set_verifier(dentry, verf);
+}
+
 /*
  * Whenever an NFS operation succeeds, we know that the dentry
  * is valid, so we update the revalidation timestamp.
@@ -785,7 +791,7 @@ static int nfs_lookup_revalidate(struct dentry * dentry, 
struct nameidata *nd)
                goto out_bad;
 
        nfs_renew_times(dentry);
-       nfs_set_verifier(dentry, verifier);
+       nfs_refresh_verifier(dentry, verifier);
  out_valid:
        unlock_kernel();
        dput(parent);
@@ -1085,7 +1091,7 @@ static int nfs_open_revalidate(struct dentry *dentry, 
struct nameidata *nd)
        verifier = nfs_save_change_attribute(dir);
        ret = nfs4_open_revalidate(dir, dentry, openflags, nd);
        if (!ret)
-               nfs_set_verifier(dentry, verifier);
+               nfs_refresh_verifier(dentry, verifier);
        unlock_kernel();
 out:
        dput(parent);
@@ -1159,10 +1165,13 @@ static struct dentry 
*nfs_readdir_lookup(nfs_readdir_descriptor_t *desc)
                dentry = alias;
        }
 
-out_renew:
        nfs_renew_times(dentry);
        nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
        return dentry;
+out_renew:
+       nfs_renew_times(dentry);
+       nfs_refresh_verifier(dentry, nfs_save_change_attribute(dir));
+       return dentry;
 }
 
 /*
@@ -1700,7 +1709,7 @@ out:
        if (!error) {
                d_move(old_dentry, new_dentry);
                nfs_renew_times(new_dentry);
-               nfs_set_verifier(new_dentry, 
nfs_save_change_attribute(new_dir));
+               nfs_refresh_verifier(new_dentry, 
nfs_save_change_attribute(new_dir));
        }
 
        /* new dentry created? */
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to