aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/cifs/cifsfs.h1
-rw-r--r--fs/cifs/dir.c54
-rw-r--r--fs/cifs/inode.c5
-rw-r--r--fs/cifs/link.c5
-rw-r--r--fs/cifs/readdir.c5
5 files changed, 64 insertions, 6 deletions
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index d5fb3441555f..bb3404a99e5f 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -81,6 +81,7 @@ extern int cifs_dir_notify(struct file *, unsigned long arg);
81 81
82/* Functions related to dir entries */ 82/* Functions related to dir entries */
83extern struct dentry_operations cifs_dentry_ops; 83extern struct dentry_operations cifs_dentry_ops;
84extern struct dentry_operations cifs_ci_dentry_ops;
84 85
85/* Functions related to symlinks */ 86/* Functions related to symlinks */
86extern void *cifs_follow_link(struct dentry *direntry, struct nameidata *nd); 87extern void *cifs_follow_link(struct dentry *direntry, struct nameidata *nd);
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index c619d45060ce..5311c50734b0 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -230,7 +230,10 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
230 ("Create worked but get_inode_info failed rc = %d", 230 ("Create worked but get_inode_info failed rc = %d",
231 rc)); 231 rc));
232 } else { 232 } else {
233 direntry->d_op = &cifs_dentry_ops; 233 if (pTcon->nocase)
234 direntry->d_op = &cifs_ci_dentry_ops;
235 else
236 direntry->d_op = &cifs_dentry_ops;
234 d_instantiate(direntry, newinode); 237 d_instantiate(direntry, newinode);
235 } 238 }
236 if((nd->flags & LOOKUP_OPEN) == FALSE) { 239 if((nd->flags & LOOKUP_OPEN) == FALSE) {
@@ -322,7 +325,10 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t dev
322 if(!rc) { 325 if(!rc) {
323 rc = cifs_get_inode_info_unix(&newinode, full_path, 326 rc = cifs_get_inode_info_unix(&newinode, full_path,
324 inode->i_sb,xid); 327 inode->i_sb,xid);
325 direntry->d_op = &cifs_dentry_ops; 328 if (pTcon->nocase)
329 direntry->d_op = &cifs_ci_dentry_ops;
330 else
331 direntry->d_op = &cifs_dentry_ops;
326 if(rc == 0) 332 if(rc == 0)
327 d_instantiate(direntry, newinode); 333 d_instantiate(direntry, newinode);
328 } 334 }
@@ -418,7 +424,10 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
418 parent_dir_inode->i_sb,xid); 424 parent_dir_inode->i_sb,xid);
419 425
420 if ((rc == 0) && (newInode != NULL)) { 426 if ((rc == 0) && (newInode != NULL)) {
421 direntry->d_op = &cifs_dentry_ops; 427 if (pTcon->nocase)
428 direntry->d_op = &cifs_ci_dentry_ops;
429 else
430 direntry->d_op = &cifs_dentry_ops;
422 d_add(direntry, newInode); 431 d_add(direntry, newInode);
423 432
424 /* since paths are not looked up by component - the parent directories are presumed to be good here */ 433 /* since paths are not looked up by component - the parent directories are presumed to be good here */
@@ -477,3 +486,42 @@ struct dentry_operations cifs_dentry_ops = {
477/* d_delete: cifs_d_delete, *//* not needed except for debugging */ 486/* d_delete: cifs_d_delete, *//* not needed except for debugging */
478 /* no need for d_hash, d_compare, d_release, d_iput ... yet. BB confirm this BB */ 487 /* no need for d_hash, d_compare, d_release, d_iput ... yet. BB confirm this BB */
479}; 488};
489
490static int cifs_ci_hash(struct dentry *dentry, struct qstr *q)
491{
492 struct nls_table *codepage = CIFS_SB(dentry->d_inode->i_sb)->local_nls;
493 unsigned long hash;
494 int i;
495
496 hash = init_name_hash();
497 for (i = 0; i < q->len; i++)
498 hash = partial_name_hash(nls_tolower(codepage, q->name[i]),
499 hash);
500 q->hash = end_name_hash(hash);
501
502 return 0;
503}
504
505static int cifs_ci_compare(struct dentry *dentry, struct qstr *a,
506 struct qstr *b)
507{
508 struct nls_table *codepage = CIFS_SB(dentry->d_inode->i_sb)->local_nls;
509
510 if ((a->len == b->len) &&
511 (nls_strnicmp(codepage, a->name, b->name, a->len) == 0)) {
512 /*
513 * To preserve case, don't let an existing negative dentry's
514 * case take precedence. If a is not a negative dentry, this
515 * should have no side effects
516 */
517 memcpy((unsigned char *)a->name, b->name, a->len);
518 return 0;
519 }
520 return 1;
521}
522
523struct dentry_operations cifs_ci_dentry_ops = {
524 .d_revalidate = cifs_d_revalidate,
525 .d_hash = cifs_ci_hash,
526 .d_compare = cifs_ci_compare,
527};
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index ed3e9207d92e..2d50b3507d13 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -591,7 +591,10 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
591 rc = cifs_get_inode_info(&newinode, full_path, NULL, 591 rc = cifs_get_inode_info(&newinode, full_path, NULL,
592 inode->i_sb,xid); 592 inode->i_sb,xid);
593 593
594 direntry->d_op = &cifs_dentry_ops; 594 if (pTcon->nocase)
595 direntry->d_op = &cifs_ci_dentry_ops;
596 else
597 direntry->d_op = &cifs_dentry_ops;
595 d_instantiate(direntry, newinode); 598 d_instantiate(direntry, newinode);
596 if (direntry->d_inode) 599 if (direntry->d_inode)
597 direntry->d_inode->i_nlink = 2; 600 direntry->d_inode->i_nlink = 2;
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index da420e8c3298..b8ec6646456a 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -199,7 +199,10 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
199 ("Create symlink worked but get_inode_info failed with rc = %d ", 199 ("Create symlink worked but get_inode_info failed with rc = %d ",
200 rc)); 200 rc));
201 } else { 201 } else {
202 direntry->d_op = &cifs_dentry_ops; 202 if (pTcon->nocase)
203 direntry->d_op = &cifs_ci_dentry_ops;
204 else
205 direntry->d_op = &cifs_dentry_ops;
203 d_instantiate(direntry, newinode); 206 d_instantiate(direntry, newinode);
204 } 207 }
205 } 208 }
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index ef5eb804ce82..f769292e2a93 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -91,7 +91,10 @@ static int construct_dentry(struct qstr *qstring, struct file *file,
91 } 91 }
92 92
93 *ptmp_inode = new_inode(file->f_dentry->d_sb); 93 *ptmp_inode = new_inode(file->f_dentry->d_sb);
94 tmp_dentry->d_op = &cifs_dentry_ops; 94 if (pTcon->nocase)
95 tmp_dentry->d_op = &cifs_ci_dentry_ops;
96 else
97 tmp_dentry->d_op = &cifs_dentry_ops;
95 if(*ptmp_inode == NULL) 98 if(*ptmp_inode == NULL)
96 return rc; 99 return rc;
97 rc = 1; 100 rc = 1;