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 <Trond.Myklebust@netapp.com>
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 @@
  * 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 @@
 	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 @@
 		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 @@
 	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 @@
 		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 @@
 	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? */