From 2afd72f59c518da18853192ceeebead670ced5ea Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 9 Jan 2013 11:17:14 -0800 Subject: [PATCH] 3.7-stable patches added patches: cifs-don-t-compare-uniqueids-in-cifs_prime_dcache-unless-server-inode-numbers-are-in-use.patch cifs-rename-cifs_readdir_lookup-to-cifs_prime_dcache-and-make-it-void-return.patch --- ...less-server-inode-numbers-are-in-use.patch | 62 +++++++++ ...prime_dcache-and-make-it-void-return.patch | 120 ++++++++++++++++++ queue-3.7/series | 2 + 3 files changed, 184 insertions(+) create mode 100644 queue-3.7/cifs-don-t-compare-uniqueids-in-cifs_prime_dcache-unless-server-inode-numbers-are-in-use.patch create mode 100644 queue-3.7/cifs-rename-cifs_readdir_lookup-to-cifs_prime_dcache-and-make-it-void-return.patch diff --git a/queue-3.7/cifs-don-t-compare-uniqueids-in-cifs_prime_dcache-unless-server-inode-numbers-are-in-use.patch b/queue-3.7/cifs-don-t-compare-uniqueids-in-cifs_prime_dcache-unless-server-inode-numbers-are-in-use.patch new file mode 100644 index 00000000000..621f3142d0b --- /dev/null +++ b/queue-3.7/cifs-don-t-compare-uniqueids-in-cifs_prime_dcache-unless-server-inode-numbers-are-in-use.patch @@ -0,0 +1,62 @@ +From 2f2591a34db6c9361faa316c91a6e320cb4e6aee Mon Sep 17 00:00:00 2001 +From: Jeff Layton +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 + +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 +Signed-off-by: Jeff Layton +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman + +--- + 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); diff --git a/queue-3.7/cifs-rename-cifs_readdir_lookup-to-cifs_prime_dcache-and-make-it-void-return.patch b/queue-3.7/cifs-rename-cifs_readdir_lookup-to-cifs_prime_dcache-and-make-it-void-return.patch new file mode 100644 index 00000000000..dea57299f3c --- /dev/null +++ b/queue-3.7/cifs-rename-cifs_readdir_lookup-to-cifs_prime_dcache-and-make-it-void-return.patch @@ -0,0 +1,120 @@ +From eb1b3fa5cdb9c27bdec8f262acf757a06588eb2d Mon Sep 17 00:00:00 2001 +From: Jeff Layton +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 + +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 +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman + +--- + 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; + } + diff --git a/queue-3.7/series b/queue-3.7/series index 681637cd5e2..b8b529b8fa4 100644 --- a/queue-3.7/series +++ b/queue-3.7/series @@ -119,3 +119,5 @@ mm-limit-mmu_gather-batching-to-fix-soft-lockups-on-config_preempt.patch linux-kernel.h-fix-div_round_closest-with-unsigned-divisors.patch hid-add-apple-wireless-keyboard-2011-ansi-to-special-driver-list.patch can-do-not-call-dev_put-if-restart-timer-is-running-upon-close.patch +cifs-rename-cifs_readdir_lookup-to-cifs_prime_dcache-and-make-it-void-return.patch +cifs-don-t-compare-uniqueids-in-cifs_prime_dcache-unless-server-inode-numbers-are-in-use.patch -- 2.47.3