summaryrefslogtreecommitdiff
path: root/fs/cifs/dir.c
diff options
context:
space:
mode:
authorNick Piggin <npiggin@kernel.dk>2011-01-07 17:49:24 +1100
committerNick Piggin <npiggin@kernel.dk>2011-01-07 17:50:18 +1100
commit79eb4dde742fe2e9c9e301432b894a7410261ce7 (patch)
tree89150e92450fd10f7bd55348459d9f36be544ec0 /fs/cifs/dir.c
parentfe15ce446beb3a33583af81ffe6c9d01a75314ed (diff)
downloadlinux-3.10-79eb4dde742fe2e9c9e301432b894a7410261ce7.tar.gz
linux-3.10-79eb4dde742fe2e9c9e301432b894a7410261ce7.tar.bz2
linux-3.10-79eb4dde742fe2e9c9e301432b894a7410261ce7.zip
cifs: dont overwrite dentry name in d_revalidate
Use vfat's method for dealing with negative dentries to preserve case, rather than overwrite dentry name in d_revalidate, which is a bit ugly and also gets in the way of doing lock-free path walking. Signed-off-by: Nick Piggin <npiggin@kernel.dk>
Diffstat (limited to 'fs/cifs/dir.c')
-rw-r--r--fs/cifs/dir.c43
1 files changed, 24 insertions, 19 deletions
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 3840eddbfb7..521d841b1fd 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -656,22 +656,34 @@ lookup_out:
static int
cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
{
- int isValid = 1;
-
if (direntry->d_inode) {
if (cifs_revalidate_dentry(direntry))
return 0;
- } else {
- cFYI(1, "neg dentry 0x%p name = %s",
- direntry, direntry->d_name.name);
- if (time_after(jiffies, direntry->d_time + HZ) ||
- !lookupCacheEnabled) {
- d_drop(direntry);
- isValid = 0;
- }
+ else
+ return 1;
}
- return isValid;
+ /*
+ * This may be nfsd (or something), anyway, we can't see the
+ * intent of this. So, since this can be for creation, drop it.
+ */
+ if (!nd)
+ return 0;
+
+ /*
+ * Drop the negative dentry, in order to make sure to use the
+ * case sensitive name which is specified by user if this is
+ * for creation.
+ */
+ if (!(nd->flags & (LOOKUP_CONTINUE | LOOKUP_PARENT))) {
+ if (nd->flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))
+ return 0;
+ }
+
+ if (time_after(jiffies, direntry->d_time + HZ) || !lookupCacheEnabled)
+ return 0;
+
+ return 1;
}
/* static int cifs_d_delete(struct dentry *direntry)
@@ -709,15 +721,8 @@ static int cifs_ci_compare(struct dentry *dentry, struct qstr *a,
struct nls_table *codepage = CIFS_SB(dentry->d_inode->i_sb)->local_nls;
if ((a->len == b->len) &&
- (nls_strnicmp(codepage, a->name, b->name, a->len) == 0)) {
- /*
- * To preserve case, don't let an existing negative dentry's
- * case take precedence. If a is not a negative dentry, this
- * should have no side effects
- */
- memcpy((void *)a->name, b->name, a->len);
+ (nls_strnicmp(codepage, a->name, b->name, a->len) == 0))
return 0;
- }
return 1;
}