--- /dev/null
+From 2f2591a34db6c9361faa316c91a6e320cb4e6aee Mon Sep 17 00:00:00 2001
+From: Jeff Layton <jlayton@redhat.com>
+Date: Tue, 18 Dec 2012 06:35:10 -0500
+Subject: cifs: don't compare uniqueids in cifs_prime_dcache unless server inode numbers are in use
+
+From: Jeff Layton <jlayton@redhat.com>
+
+commit 2f2591a34db6c9361faa316c91a6e320cb4e6aee upstream.
+
+Oliver reported that commit cd60042c caused his cifs mounts to
+continually thrash through new inodes on readdir. His servers are not
+sending inode numbers (or he's not using them), and the new test in
+that function doesn't account for that sort of setup correctly.
+
+If we're not using server inode numbers, then assume that the inode
+attached to the dentry hasn't changed. Go ahead and update the
+attributes in place, but keep the same inode number.
+
+Reported-and-Tested-by: Oliver Mössinger <Oliver.Moessinger@ichaus.de>
+Signed-off-by: Jeff Layton <jlayton@redhat.com>
+Signed-off-by: Steve French <sfrench@us.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/readdir.c | 19 +++++++++++++++----
+ 1 file changed, 15 insertions(+), 4 deletions(-)
+
+--- a/fs/cifs/readdir.c
++++ b/fs/cifs/readdir.c
+@@ -78,6 +78,7 @@ cifs_prime_dcache(struct dentry *parent,
+ struct dentry *dentry, *alias;
+ struct inode *inode;
+ struct super_block *sb = parent->d_inode->i_sb;
++ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+
+ cFYI(1, "%s: for %s", __func__, name->name);
+
+@@ -91,10 +92,20 @@ cifs_prime_dcache(struct dentry *parent,
+ int err;
+
+ inode = dentry->d_inode;
+- /* update inode in place if i_ino didn't change */
+- if (inode && CIFS_I(inode)->uniqueid == fattr->cf_uniqueid) {
+- cifs_fattr_to_inode(inode, fattr);
+- goto out;
++ if (inode) {
++ /*
++ * If we're generating inode numbers, then we don't
++ * want to clobber the existing one with the one that
++ * the readdir code created.
++ */
++ if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM))
++ fattr->cf_uniqueid = CIFS_I(inode)->uniqueid;
++
++ /* update inode in place if i_ino didn't change */
++ if (CIFS_I(inode)->uniqueid == fattr->cf_uniqueid) {
++ cifs_fattr_to_inode(inode, fattr);
++ goto out;
++ }
+ }
+ err = d_invalidate(dentry);
+ dput(dentry);
--- /dev/null
+From eb1b3fa5cdb9c27bdec8f262acf757a06588eb2d Mon Sep 17 00:00:00 2001
+From: Jeff Layton <jlayton@redhat.com>
+Date: Mon, 3 Dec 2012 06:05:37 -0500
+Subject: cifs: rename cifs_readdir_lookup to cifs_prime_dcache and make it void return
+
+From: Jeff Layton <jlayton@redhat.com>
+
+commit eb1b3fa5cdb9c27bdec8f262acf757a06588eb2d upstream.
+
+The caller doesn't do anything with the dentry, so there's no point in
+holding a reference to it on return. Also cifs_prime_dcache better
+describes the actual purpose of the function.
+
+Signed-off-by: Jeff Layton <jlayton@redhat.com>
+Signed-off-by: Steve French <smfrench@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/readdir.c | 42 ++++++++++++++++++------------------------
+ 1 file changed, 18 insertions(+), 24 deletions(-)
+
+--- a/fs/cifs/readdir.c
++++ b/fs/cifs/readdir.c
+@@ -66,18 +66,20 @@ static inline void dump_cifs_file_struct
+ #endif /* DEBUG2 */
+
+ /*
++ * Attempt to preload the dcache with the results from the FIND_FIRST/NEXT
++ *
+ * Find the dentry that matches "name". If there isn't one, create one. If it's
+ * a negative dentry or the uniqueid changed, then drop it and recreate it.
+ */
+-static struct dentry *
+-cifs_readdir_lookup(struct dentry *parent, struct qstr *name,
++static void
++cifs_prime_dcache(struct dentry *parent, struct qstr *name,
+ struct cifs_fattr *fattr)
+ {
+ struct dentry *dentry, *alias;
+ struct inode *inode;
+ struct super_block *sb = parent->d_inode->i_sb;
+
+- cFYI(1, "For %s", name->name);
++ cFYI(1, "%s: for %s", __func__, name->name);
+
+ if (parent->d_op && parent->d_op->d_hash)
+ parent->d_op->d_hash(parent, parent->d_inode, name);
+@@ -87,37 +89,32 @@ cifs_readdir_lookup(struct dentry *paren
+ dentry = d_lookup(parent, name);
+ if (dentry) {
+ int err;
++
+ inode = dentry->d_inode;
+ /* update inode in place if i_ino didn't change */
+ if (inode && CIFS_I(inode)->uniqueid == fattr->cf_uniqueid) {
+ cifs_fattr_to_inode(inode, fattr);
+- return dentry;
++ goto out;
+ }
+ err = d_invalidate(dentry);
+ dput(dentry);
+ if (err)
+- return NULL;
++ return;
+ }
+
+ dentry = d_alloc(parent, name);
+- if (dentry == NULL)
+- return NULL;
++ if (!dentry)
++ return;
+
+ inode = cifs_iget(sb, fattr);
+- if (!inode) {
+- dput(dentry);
+- return NULL;
+- }
++ if (!inode)
++ goto out;
+
+ alias = d_materialise_unique(dentry, inode);
+- if (alias != NULL) {
+- dput(dentry);
+- if (IS_ERR(alias))
+- return NULL;
+- dentry = alias;
+- }
+-
+- return dentry;
++ if (alias && !IS_ERR(alias))
++ dput(alias);
++out:
++ dput(dentry);
+ }
+
+ static void
+@@ -652,7 +649,6 @@ static int cifs_filldir(char *find_entry
+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+ struct cifs_dirent de = { NULL, };
+ struct cifs_fattr fattr;
+- struct dentry *dentry;
+ struct qstr name;
+ int rc = 0;
+ ino_t ino;
+@@ -723,13 +719,11 @@ static int cifs_filldir(char *find_entry
+ */
+ fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
+
+- ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid);
+- dentry = cifs_readdir_lookup(file->f_dentry, &name, &fattr);
++ cifs_prime_dcache(file->f_dentry, &name, &fattr);
+
++ ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid);
+ rc = filldir(dirent, name.name, name.len, file->f_pos, ino,
+ fattr.cf_dtype);
+-
+- dput(dentry);
+ return rc;
+ }
+