diff options
Diffstat (limited to 'fs/cifs/dir.c')
-rw-r--r-- | fs/cifs/dir.c | 54 |
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 | |||
490 | static 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 | |||
505 | static 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 | |||
523 | struct 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 | }; | ||