aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/dir.c')
-rw-r--r--fs/cifs/dir.c54
1 files changed, 51 insertions, 3 deletions
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};