diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index 538ca18efe0d8217725a05d873d566c61a8d4d87..08b499504f6325d3b016cb528a48ea71a757ea4d 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -1015,7 +1015,7 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
 	struct dentry *parent;
 	struct inode *inode;
 	struct key *key;
-	void *dir_version;
+	long dir_version, de_version;
 	int ret;
 
 	if (flags & LOOKUP_RCU)
@@ -1059,9 +1059,19 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
 		goto out_bad_parent;
 	}
 
-	dir_version = (void *) (unsigned long) dir->status.data_version;
-	if (dentry->d_fsdata == dir_version)
-		goto out_valid; /* the dir contents are unchanged */
+	/* We only need to invalidate a dentry if the server's copy changed
+	 * behind our back.  If we made the change, it's no problem.  Note that
+	 * on a 32-bit system, we only have 32 bits in the dentry to store the
+	 * version.
+	 */
+	dir_version = (long)dir->status.data_version;
+	de_version = (long)dentry->d_fsdata;
+	if (de_version == dir_version)
+		goto out_valid;
+
+	dir_version = (long)dir->invalid_before;
+	if (de_version - dir_version >= 0)
+		goto out_valid;
 
 	_debug("dir modified");
 	afs_stat_v(dir, n_reval);
@@ -1120,7 +1130,7 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
 	}
 
 out_valid:
-	dentry->d_fsdata = dir_version;
+	dentry->d_fsdata = (void *)dir_version;
 	dput(parent);
 	key_put(key);
 	_leave(" = 1 [valid]");
diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c
index ff87fc6bb27fbbc32dd25d2ff0c419307056684b..f7570d229dcc4d8f304913b23d59e0fcdcd3563f 100644
--- a/fs/afs/fsclient.c
+++ b/fs/afs/fsclient.c
@@ -100,6 +100,7 @@ void afs_update_inode_from_status(struct afs_vnode *vnode,
 			       (unsigned long long) status->data_version,
 			       vnode->fid.vid, vnode->fid.vnode,
 			       (unsigned long long) *expected_version);
+			vnode->invalid_before = status->data_version;
 			set_bit(AFS_VNODE_DIR_MODIFIED, &vnode->flags);
 			set_bit(AFS_VNODE_ZAP_DATA, &vnode->flags);
 		}
diff --git a/fs/afs/inode.c b/fs/afs/inode.c
index 2e32d475ec11f583eab1a7d6e55e61be8834532c..07f450513f3e95a389f1fd24fa39676df3c4018f 100644
--- a/fs/afs/inode.c
+++ b/fs/afs/inode.c
@@ -83,6 +83,7 @@ static int afs_inode_init_from_status(struct afs_vnode *vnode, struct key *key)
 
 	inode->i_blocks		= 0;
 	inode->i_mapping->a_ops	= &afs_fs_aops;
+	vnode->invalid_before	= vnode->status.data_version;
 
 	read_sequnlock_excl(&vnode->cb_lock);
 
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index ac3076c2a8e827d0e77df5ecf31c63b7d4ae4b0b..adf9b17d328c1b28d12b5e930b2ed763dcc6a1a9 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -479,6 +479,7 @@ struct afs_vnode {
 	struct afs_volume	*volume;	/* volume on which vnode resides */
 	struct afs_fid		fid;		/* the file identifier for this inode */
 	struct afs_file_status	status;		/* AFS status info for this file */
+	afs_dataversion_t	invalid_before;	/* Child dentries are invalid before this */
 #ifdef CONFIG_AFS_FSCACHE
 	struct fscache_cookie	*cache;		/* caching cookie */
 #endif