aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
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
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')
-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;