aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/dir.c
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2005-08-22 23:09:43 -0400
committerSteve French <sfrench@us.ibm.com>2005-08-22 23:09:43 -0400
commitb92327fe6b25d60004b79df9e3c19091c03118ba (patch)
tree064479872cf0cc83d08f9c719edfd9769b01b9a3 /fs/cifs/dir.c
parenta5a2b489bae8f66559a531df99a26eb16b42299e (diff)
[CIFS] Finish up of case-insensitive dentry handling for cifs. This
will eventually (or should eventually) be common code for jfs, smbfs, etc. but in the meantime is small enough and necessary when mounting case insensitive to Windows (nocase). Signed-off-by: Shaggy (shaggy@austin.ibm.com) Signed-off-by: Steve French (sfrench@us.ibm.com)
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};