diff options
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/cifsfs.h | 1 | ||||
-rw-r--r-- | fs/cifs/dir.c | 54 | ||||
-rw-r--r-- | fs/cifs/inode.c | 5 | ||||
-rw-r--r-- | fs/cifs/link.c | 5 | ||||
-rw-r--r-- | fs/cifs/readdir.c | 5 |
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 */ |
83 | extern struct dentry_operations cifs_dentry_ops; | 83 | extern struct dentry_operations cifs_dentry_ops; |
84 | extern struct dentry_operations cifs_ci_dentry_ops; | ||
84 | 85 | ||
85 | /* Functions related to symlinks */ | 86 | /* Functions related to symlinks */ |
86 | extern void *cifs_follow_link(struct dentry *direntry, struct nameidata *nd); | 87 | extern 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 | |||
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 | }; | ||
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; |