aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ncpfs/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ncpfs/dir.c')
-rw-r--r--fs/ncpfs/dir.c88
1 files changed, 38 insertions, 50 deletions
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
index f22b12e7d337..28f136d4aaec 100644
--- a/fs/ncpfs/dir.c
+++ b/fs/ncpfs/dir.c
@@ -17,6 +17,7 @@
17#include <linux/kernel.h> 17#include <linux/kernel.h>
18#include <linux/vmalloc.h> 18#include <linux/vmalloc.h>
19#include <linux/mm.h> 19#include <linux/mm.h>
20#include <linux/namei.h>
20#include <asm/uaccess.h> 21#include <asm/uaccess.h>
21#include <asm/byteorder.h> 22#include <asm/byteorder.h>
22 23
@@ -74,9 +75,12 @@ const struct inode_operations ncp_dir_inode_operations =
74 * Dentry operations routines 75 * Dentry operations routines
75 */ 76 */
76static int ncp_lookup_validate(struct dentry *, struct nameidata *); 77static int ncp_lookup_validate(struct dentry *, struct nameidata *);
77static int ncp_hash_dentry(struct dentry *, struct qstr *); 78static int ncp_hash_dentry(const struct dentry *, const struct inode *,
78static int ncp_compare_dentry (struct dentry *, struct qstr *, struct qstr *); 79 struct qstr *);
79static int ncp_delete_dentry(struct dentry *); 80static int ncp_compare_dentry(const struct dentry *, const struct inode *,
81 const struct dentry *, const struct inode *,
82 unsigned int, const char *, const struct qstr *);
83static int ncp_delete_dentry(const struct dentry *);
80 84
81static const struct dentry_operations ncp_dentry_operations = 85static const struct dentry_operations ncp_dentry_operations =
82{ 86{
@@ -113,10 +117,10 @@ static inline int ncp_preserve_entry_case(struct inode *i, __u32 nscreator)
113 117
114#define ncp_preserve_case(i) (ncp_namespace(i) != NW_NS_DOS) 118#define ncp_preserve_case(i) (ncp_namespace(i) != NW_NS_DOS)
115 119
116static inline int ncp_case_sensitive(struct dentry *dentry) 120static inline int ncp_case_sensitive(const struct inode *i)
117{ 121{
118#ifdef CONFIG_NCPFS_NFS_NS 122#ifdef CONFIG_NCPFS_NFS_NS
119 return ncp_namespace(dentry->d_inode) == NW_NS_NFS; 123 return ncp_namespace(i) == NW_NS_NFS;
120#else 124#else
121 return 0; 125 return 0;
122#endif /* CONFIG_NCPFS_NFS_NS */ 126#endif /* CONFIG_NCPFS_NFS_NS */
@@ -127,14 +131,16 @@ static inline int ncp_case_sensitive(struct dentry *dentry)
127 * is case-sensitive. 131 * is case-sensitive.
128 */ 132 */
129static int 133static int
130ncp_hash_dentry(struct dentry *dentry, struct qstr *this) 134ncp_hash_dentry(const struct dentry *dentry, const struct inode *inode,
135 struct qstr *this)
131{ 136{
132 if (!ncp_case_sensitive(dentry)) { 137 if (!ncp_case_sensitive(inode)) {
138 struct super_block *sb = dentry->d_sb;
133 struct nls_table *t; 139 struct nls_table *t;
134 unsigned long hash; 140 unsigned long hash;
135 int i; 141 int i;
136 142
137 t = NCP_IO_TABLE(dentry); 143 t = NCP_IO_TABLE(sb);
138 hash = init_name_hash(); 144 hash = init_name_hash();
139 for (i=0; i<this->len ; i++) 145 for (i=0; i<this->len ; i++)
140 hash = partial_name_hash(ncp_tolower(t, this->name[i]), 146 hash = partial_name_hash(ncp_tolower(t, this->name[i]),
@@ -145,15 +151,17 @@ ncp_hash_dentry(struct dentry *dentry, struct qstr *this)
145} 151}
146 152
147static int 153static int
148ncp_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b) 154ncp_compare_dentry(const struct dentry *parent, const struct inode *pinode,
155 const struct dentry *dentry, const struct inode *inode,
156 unsigned int len, const char *str, const struct qstr *name)
149{ 157{
150 if (a->len != b->len) 158 if (len != name->len)
151 return 1; 159 return 1;
152 160
153 if (ncp_case_sensitive(dentry)) 161 if (ncp_case_sensitive(pinode))
154 return strncmp(a->name, b->name, a->len); 162 return strncmp(str, name->name, len);
155 163
156 return ncp_strnicmp(NCP_IO_TABLE(dentry), a->name, b->name, a->len); 164 return ncp_strnicmp(NCP_IO_TABLE(pinode->i_sb), str, name->name, len);
157} 165}
158 166
159/* 167/*
@@ -162,7 +170,7 @@ ncp_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b)
162 * Closing files can be safely postponed until iput() - it's done there anyway. 170 * Closing files can be safely postponed until iput() - it's done there anyway.
163 */ 171 */
164static int 172static int
165ncp_delete_dentry(struct dentry * dentry) 173ncp_delete_dentry(const struct dentry * dentry)
166{ 174{
167 struct inode *inode = dentry->d_inode; 175 struct inode *inode = dentry->d_inode;
168 176
@@ -301,6 +309,9 @@ ncp_lookup_validate(struct dentry *dentry, struct nameidata *nd)
301 int res, val = 0, len; 309 int res, val = 0, len;
302 __u8 __name[NCP_MAXPATHLEN + 1]; 310 __u8 __name[NCP_MAXPATHLEN + 1];
303 311
312 if (nd->flags & LOOKUP_RCU)
313 return -ECHILD;
314
304 parent = dget_parent(dentry); 315 parent = dget_parent(dentry);
305 dir = parent->d_inode; 316 dir = parent->d_inode;
306 317
@@ -384,21 +395,21 @@ ncp_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos)
384 } 395 }
385 396
386 /* If a pointer is invalid, we search the dentry. */ 397 /* If a pointer is invalid, we search the dentry. */
387 spin_lock(&dcache_lock); 398 spin_lock(&parent->d_lock);
388 next = parent->d_subdirs.next; 399 next = parent->d_subdirs.next;
389 while (next != &parent->d_subdirs) { 400 while (next != &parent->d_subdirs) {
390 dent = list_entry(next, struct dentry, d_u.d_child); 401 dent = list_entry(next, struct dentry, d_u.d_child);
391 if ((unsigned long)dent->d_fsdata == fpos) { 402 if ((unsigned long)dent->d_fsdata == fpos) {
392 if (dent->d_inode) 403 if (dent->d_inode)
393 dget_locked(dent); 404 dget(dent);
394 else 405 else
395 dent = NULL; 406 dent = NULL;
396 spin_unlock(&dcache_lock); 407 spin_unlock(&parent->d_lock);
397 goto out; 408 goto out;
398 } 409 }
399 next = next->next; 410 next = next->next;
400 } 411 }
401 spin_unlock(&dcache_lock); 412 spin_unlock(&parent->d_lock);
402 return NULL; 413 return NULL;
403 414
404out: 415out:
@@ -592,7 +603,7 @@ ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
592 qname.hash = full_name_hash(qname.name, qname.len); 603 qname.hash = full_name_hash(qname.name, qname.len);
593 604
594 if (dentry->d_op && dentry->d_op->d_hash) 605 if (dentry->d_op && dentry->d_op->d_hash)
595 if (dentry->d_op->d_hash(dentry, &qname) != 0) 606 if (dentry->d_op->d_hash(dentry, dentry->d_inode, &qname) != 0)
596 goto end_advance; 607 goto end_advance;
597 608
598 newdent = d_lookup(dentry, &qname); 609 newdent = d_lookup(dentry, &qname);
@@ -611,35 +622,12 @@ ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
611 shrink_dcache_parent(newdent); 622 shrink_dcache_parent(newdent);
612 623
613 /* 624 /*
614 * It is not as dangerous as it looks. NetWare's OS2 namespace is 625 * NetWare's OS2 namespace is case preserving yet case
615 * case preserving yet case insensitive. So we update dentry's name 626 * insensitive. So we update dentry's name as received from
616 * as received from server. We found dentry via d_lookup with our 627 * server. Parent dir's i_mutex is locked because we're in
617 * hash, so we know that hash does not change, and so replacing name 628 * readdir.
618 * should be reasonably safe.
619 */ 629 */
620 if (qname.len == newdent->d_name.len && 630 dentry_update_name_case(newdent, &qname);
621 memcmp(newdent->d_name.name, qname.name, newdent->d_name.len)) {
622 struct inode *inode = newdent->d_inode;
623
624 /*
625 * Inside ncpfs all uses of d_name are either for debugging,
626 * or on functions which acquire inode mutex (mknod, creat,
627 * lookup). So grab i_mutex here, to be sure. d_path
628 * uses dcache_lock when generating path, so we should too.
629 * And finally d_compare is protected by dentry's d_lock, so
630 * here we go.
631 */
632 if (inode)
633 mutex_lock(&inode->i_mutex);
634 spin_lock(&dcache_lock);
635 spin_lock(&newdent->d_lock);
636 memcpy((char *) newdent->d_name.name, qname.name,
637 newdent->d_name.len);
638 spin_unlock(&newdent->d_lock);
639 spin_unlock(&dcache_lock);
640 if (inode)
641 mutex_unlock(&inode->i_mutex);
642 }
643 } 631 }
644 632
645 if (!newdent->d_inode) { 633 if (!newdent->d_inode) {
@@ -649,7 +637,7 @@ ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
649 entry->ino = iunique(dir->i_sb, 2); 637 entry->ino = iunique(dir->i_sb, 2);
650 inode = ncp_iget(dir->i_sb, entry); 638 inode = ncp_iget(dir->i_sb, entry);
651 if (inode) { 639 if (inode) {
652 newdent->d_op = &ncp_dentry_operations; 640 d_set_d_op(newdent, &ncp_dentry_operations);
653 d_instantiate(newdent, inode); 641 d_instantiate(newdent, inode);
654 if (!hashed) 642 if (!hashed)
655 d_rehash(newdent); 643 d_rehash(newdent);
@@ -657,7 +645,7 @@ ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
657 } else { 645 } else {
658 struct inode *inode = newdent->d_inode; 646 struct inode *inode = newdent->d_inode;
659 647
660 mutex_lock(&inode->i_mutex); 648 mutex_lock_nested(&inode->i_mutex, I_MUTEX_CHILD);
661 ncp_update_inode2(inode, entry); 649 ncp_update_inode2(inode, entry);
662 mutex_unlock(&inode->i_mutex); 650 mutex_unlock(&inode->i_mutex);
663 } 651 }
@@ -905,7 +893,7 @@ static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, struc
905 if (inode) { 893 if (inode) {
906 ncp_new_dentry(dentry); 894 ncp_new_dentry(dentry);
907add_entry: 895add_entry:
908 dentry->d_op = &ncp_dentry_operations; 896 d_set_d_op(dentry, &ncp_dentry_operations);
909 d_add(dentry, inode); 897 d_add(dentry, inode);
910 error = 0; 898 error = 0;
911 } 899 }