aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorNick Piggin <npiggin@kernel.dk>2011-01-07 01:49:27 -0500
committerNick Piggin <npiggin@kernel.dk>2011-01-07 01:50:19 -0500
commit621e155a3591962420eacdd39f6f0aa29ceb221e (patch)
tree387a9fb396f1bf24514b712c294182e36ba51076 /fs
parentfb2d5b86aff355a27ebfc132d3c99f4a940cc3fe (diff)
fs: change d_compare for rcu-walk
Change d_compare so it may be called from lock-free RCU lookups. This does put significant restrictions on what may be done from the callback, however there don't seem to have been any problems with in-tree fses. If some strange use case pops up that _really_ cannot cope with the rcu-walk rules, we can just add new rcu-unaware callbacks, which would cause name lookup to drop out of rcu-walk mode. For in-tree filesystems, this is just a mechanical change. Signed-off-by: Nick Piggin <npiggin@kernel.dk>
Diffstat (limited to 'fs')
-rw-r--r--fs/adfs/dir.c8
-rw-r--r--fs/affs/namei.c46
-rw-r--r--fs/cifs/dir.c12
-rw-r--r--fs/dcache.c4
-rw-r--r--fs/fat/namei_msdos.c14
-rw-r--r--fs/fat/namei_vfat.c33
-rw-r--r--fs/hfs/hfs_fs.h5
-rw-r--r--fs/hfs/string.c14
-rw-r--r--fs/hfsplus/hfsplus_fs.h5
-rw-r--r--fs/hfsplus/unicode.c15
-rw-r--r--fs/hpfs/dentry.c22
-rw-r--r--fs/isofs/inode.c92
-rw-r--r--fs/isofs/namei.c3
-rw-r--r--fs/jfs/namei.c11
-rw-r--r--fs/ncpfs/dir.c25
-rw-r--r--fs/ncpfs/ncplib_kernel.h8
-rw-r--r--fs/proc/proc_sysctl.c13
17 files changed, 191 insertions, 139 deletions
diff --git a/fs/adfs/dir.c b/fs/adfs/dir.c
index f4287e4de744..c8ed66162bd4 100644
--- a/fs/adfs/dir.c
+++ b/fs/adfs/dir.c
@@ -237,17 +237,19 @@ adfs_hash(struct dentry *parent, struct qstr *qstr)
237 * requirements of the underlying filesystem. 237 * requirements of the underlying filesystem.
238 */ 238 */
239static int 239static int
240adfs_compare(struct dentry *parent, struct qstr *entry, struct qstr *name) 240adfs_compare(const struct dentry *parent, const struct inode *pinode,
241 const struct dentry *dentry, const struct inode *inode,
242 unsigned int len, const char *str, const struct qstr *name)
241{ 243{
242 int i; 244 int i;
243 245
244 if (entry->len != name->len) 246 if (len != name->len)
245 return 1; 247 return 1;
246 248
247 for (i = 0; i < name->len; i++) { 249 for (i = 0; i < name->len; i++) {
248 char a, b; 250 char a, b;
249 251
250 a = entry->name[i]; 252 a = str[i];
251 b = name->name[i]; 253 b = name->name[i];
252 254
253 if (a >= 'A' && a <= 'Z') 255 if (a >= 'A' && a <= 'Z')
diff --git a/fs/affs/namei.c b/fs/affs/namei.c
index 914d1c0bc07a..547d5deb0d42 100644
--- a/fs/affs/namei.c
+++ b/fs/affs/namei.c
@@ -14,10 +14,16 @@ typedef int (*toupper_t)(int);
14 14
15static int affs_toupper(int ch); 15static int affs_toupper(int ch);
16static int affs_hash_dentry(struct dentry *, struct qstr *); 16static int affs_hash_dentry(struct dentry *, struct qstr *);
17static int affs_compare_dentry(struct dentry *, struct qstr *, struct qstr *); 17static int affs_compare_dentry(const struct dentry *parent,
18 const struct inode *pinode,
19 const struct dentry *dentry, const struct inode *inode,
20 unsigned int len, const char *str, const struct qstr *name);
18static int affs_intl_toupper(int ch); 21static int affs_intl_toupper(int ch);
19static int affs_intl_hash_dentry(struct dentry *, struct qstr *); 22static int affs_intl_hash_dentry(struct dentry *, struct qstr *);
20static int affs_intl_compare_dentry(struct dentry *, struct qstr *, struct qstr *); 23static int affs_intl_compare_dentry(const struct dentry *parent,
24 const struct inode *pinode,
25 const struct dentry *dentry, const struct inode *inode,
26 unsigned int len, const char *str, const struct qstr *name);
21 27
22const struct dentry_operations affs_dentry_operations = { 28const struct dentry_operations affs_dentry_operations = {
23 .d_hash = affs_hash_dentry, 29 .d_hash = affs_hash_dentry,
@@ -88,29 +94,29 @@ affs_intl_hash_dentry(struct dentry *dentry, struct qstr *qstr)
88 return __affs_hash_dentry(dentry, qstr, affs_intl_toupper); 94 return __affs_hash_dentry(dentry, qstr, affs_intl_toupper);
89} 95}
90 96
91static inline int 97static inline int __affs_compare_dentry(unsigned int len,
92__affs_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b, toupper_t toupper) 98 const char *str, const struct qstr *name, toupper_t toupper)
93{ 99{
94 const u8 *aname = a->name; 100 const u8 *aname = str;
95 const u8 *bname = b->name; 101 const u8 *bname = name->name;
96 int len;
97 102
98 /* 'a' is the qstr of an already existing dentry, so the name 103 /*
99 * must be valid. 'b' must be validated first. 104 * 'str' is the name of an already existing dentry, so the name
105 * must be valid. 'name' must be validated first.
100 */ 106 */
101 107
102 if (affs_check_name(b->name,b->len)) 108 if (affs_check_name(name->name, name->len))
103 return 1; 109 return 1;
104 110
105 /* If the names are longer than the allowed 30 chars, 111 /*
112 * If the names are longer than the allowed 30 chars,
106 * the excess is ignored, so their length may differ. 113 * the excess is ignored, so their length may differ.
107 */ 114 */
108 len = a->len;
109 if (len >= 30) { 115 if (len >= 30) {
110 if (b->len < 30) 116 if (name->len < 30)
111 return 1; 117 return 1;
112 len = 30; 118 len = 30;
113 } else if (len != b->len) 119 } else if (len != name->len)
114 return 1; 120 return 1;
115 121
116 for (; len > 0; len--) 122 for (; len > 0; len--)
@@ -121,14 +127,18 @@ __affs_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b, tou
121} 127}
122 128
123static int 129static int
124affs_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b) 130affs_compare_dentry(const struct dentry *parent, const struct inode *pinode,
131 const struct dentry *dentry, const struct inode *inode,
132 unsigned int len, const char *str, const struct qstr *name)
125{ 133{
126 return __affs_compare_dentry(dentry, a, b, affs_toupper); 134 return __affs_compare_dentry(len, str, name, affs_toupper);
127} 135}
128static int 136static int
129affs_intl_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b) 137affs_intl_compare_dentry(const struct dentry *parent,const struct inode *pinode,
138 const struct dentry *dentry, const struct inode *inode,
139 unsigned int len, const char *str, const struct qstr *name)
130{ 140{
131 return __affs_compare_dentry(dentry, a, b, affs_intl_toupper); 141 return __affs_compare_dentry(len, str, name, affs_intl_toupper);
132} 142}
133 143
134/* 144/*
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 521d841b1fd1..c60133f0d8e4 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -715,13 +715,15 @@ static int cifs_ci_hash(struct dentry *dentry, struct qstr *q)
715 return 0; 715 return 0;
716} 716}
717 717
718static int cifs_ci_compare(struct dentry *dentry, struct qstr *a, 718static int cifs_ci_compare(const struct dentry *parent,
719 struct qstr *b) 719 const struct inode *pinode,
720 const struct dentry *dentry, const struct inode *inode,
721 unsigned int len, const char *str, const struct qstr *name)
720{ 722{
721 struct nls_table *codepage = CIFS_SB(dentry->d_inode->i_sb)->local_nls; 723 struct nls_table *codepage = CIFS_SB(pinode->i_sb)->local_nls;
722 724
723 if ((a->len == b->len) && 725 if ((name->len == len) &&
724 (nls_strnicmp(codepage, a->name, b->name, a->len) == 0)) 726 (nls_strnicmp(codepage, name->name, str, len) == 0))
725 return 0; 727 return 0;
726 return 1; 728 return 1;
727} 729}
diff --git a/fs/dcache.c b/fs/dcache.c
index 814e5f491e9c..7075555fbb04 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1437,7 +1437,9 @@ struct dentry * __d_lookup(struct dentry * parent, struct qstr * name)
1437 */ 1437 */
1438 qstr = &dentry->d_name; 1438 qstr = &dentry->d_name;
1439 if (parent->d_op && parent->d_op->d_compare) { 1439 if (parent->d_op && parent->d_op->d_compare) {
1440 if (parent->d_op->d_compare(parent, qstr, name)) 1440 if (parent->d_op->d_compare(parent, parent->d_inode,
1441 dentry, dentry->d_inode,
1442 qstr->len, qstr->name, name))
1441 goto next; 1443 goto next;
1442 } else { 1444 } else {
1443 if (qstr->len != len) 1445 if (qstr->len != len)
diff --git a/fs/fat/namei_msdos.c b/fs/fat/namei_msdos.c
index 3345aabd1dd7..99d3c7ac973c 100644
--- a/fs/fat/namei_msdos.c
+++ b/fs/fat/namei_msdos.c
@@ -164,16 +164,18 @@ static int msdos_hash(struct dentry *dentry, struct qstr *qstr)
164 * Compare two msdos names. If either of the names are invalid, 164 * Compare two msdos names. If either of the names are invalid,
165 * we fall back to doing the standard name comparison. 165 * we fall back to doing the standard name comparison.
166 */ 166 */
167static int msdos_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b) 167static int msdos_cmp(const struct dentry *parent, const struct inode *pinode,
168 const struct dentry *dentry, const struct inode *inode,
169 unsigned int len, const char *str, const struct qstr *name)
168{ 170{
169 struct fat_mount_options *options = &MSDOS_SB(dentry->d_sb)->options; 171 struct fat_mount_options *options = &MSDOS_SB(parent->d_sb)->options;
170 unsigned char a_msdos_name[MSDOS_NAME], b_msdos_name[MSDOS_NAME]; 172 unsigned char a_msdos_name[MSDOS_NAME], b_msdos_name[MSDOS_NAME];
171 int error; 173 int error;
172 174
173 error = msdos_format_name(a->name, a->len, a_msdos_name, options); 175 error = msdos_format_name(name->name, name->len, a_msdos_name, options);
174 if (error) 176 if (error)
175 goto old_compare; 177 goto old_compare;
176 error = msdos_format_name(b->name, b->len, b_msdos_name, options); 178 error = msdos_format_name(str, len, b_msdos_name, options);
177 if (error) 179 if (error)
178 goto old_compare; 180 goto old_compare;
179 error = memcmp(a_msdos_name, b_msdos_name, MSDOS_NAME); 181 error = memcmp(a_msdos_name, b_msdos_name, MSDOS_NAME);
@@ -182,8 +184,8 @@ out:
182 184
183old_compare: 185old_compare:
184 error = 1; 186 error = 1;
185 if (a->len == b->len) 187 if (name->len == len)
186 error = memcmp(a->name, b->name, a->len); 188 error = memcmp(name->name, str, len);
187 goto out; 189 goto out;
188} 190}
189 191
diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c
index b936703b8924..95e00ab84c3f 100644
--- a/fs/fat/namei_vfat.c
+++ b/fs/fat/namei_vfat.c
@@ -85,15 +85,18 @@ static int vfat_revalidate_ci(struct dentry *dentry, struct nameidata *nd)
85} 85}
86 86
87/* returns the length of a struct qstr, ignoring trailing dots */ 87/* returns the length of a struct qstr, ignoring trailing dots */
88static unsigned int vfat_striptail_len(struct qstr *qstr) 88static unsigned int __vfat_striptail_len(unsigned int len, const char *name)
89{ 89{
90 unsigned int len = qstr->len; 90 while (len && name[len - 1] == '.')
91
92 while (len && qstr->name[len - 1] == '.')
93 len--; 91 len--;
94 return len; 92 return len;
95} 93}
96 94
95static unsigned int vfat_striptail_len(const struct qstr *qstr)
96{
97 return __vfat_striptail_len(qstr->len, qstr->name);
98}
99
97/* 100/*
98 * Compute the hash for the vfat name corresponding to the dentry. 101 * Compute the hash for the vfat name corresponding to the dentry.
99 * Note: if the name is invalid, we leave the hash code unchanged so 102 * Note: if the name is invalid, we leave the hash code unchanged so
@@ -133,16 +136,18 @@ static int vfat_hashi(struct dentry *dentry, struct qstr *qstr)
133/* 136/*
134 * Case insensitive compare of two vfat names. 137 * Case insensitive compare of two vfat names.
135 */ 138 */
136static int vfat_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b) 139static int vfat_cmpi(const struct dentry *parent, const struct inode *pinode,
140 const struct dentry *dentry, const struct inode *inode,
141 unsigned int len, const char *str, const struct qstr *name)
137{ 142{
138 struct nls_table *t = MSDOS_SB(dentry->d_inode->i_sb)->nls_io; 143 struct nls_table *t = MSDOS_SB(parent->d_sb)->nls_io;
139 unsigned int alen, blen; 144 unsigned int alen, blen;
140 145
141 /* A filename cannot end in '.' or we treat it like it has none */ 146 /* A filename cannot end in '.' or we treat it like it has none */
142 alen = vfat_striptail_len(a); 147 alen = vfat_striptail_len(name);
143 blen = vfat_striptail_len(b); 148 blen = __vfat_striptail_len(len, str);
144 if (alen == blen) { 149 if (alen == blen) {
145 if (nls_strnicmp(t, a->name, b->name, alen) == 0) 150 if (nls_strnicmp(t, name->name, str, alen) == 0)
146 return 0; 151 return 0;
147 } 152 }
148 return 1; 153 return 1;
@@ -151,15 +156,17 @@ static int vfat_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b)
151/* 156/*
152 * Case sensitive compare of two vfat names. 157 * Case sensitive compare of two vfat names.
153 */ 158 */
154static int vfat_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b) 159static int vfat_cmp(const struct dentry *parent, const struct inode *pinode,
160 const struct dentry *dentry, const struct inode *inode,
161 unsigned int len, const char *str, const struct qstr *name)
155{ 162{
156 unsigned int alen, blen; 163 unsigned int alen, blen;
157 164
158 /* A filename cannot end in '.' or we treat it like it has none */ 165 /* A filename cannot end in '.' or we treat it like it has none */
159 alen = vfat_striptail_len(a); 166 alen = vfat_striptail_len(name);
160 blen = vfat_striptail_len(b); 167 blen = __vfat_striptail_len(len, str);
161 if (alen == blen) { 168 if (alen == blen) {
162 if (strncmp(a->name, b->name, alen) == 0) 169 if (strncmp(name->name, str, alen) == 0)
163 return 0; 170 return 0;
164 } 171 }
165 return 1; 172 return 1;
diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h
index c8cffb81e849..8cd876f0e961 100644
--- a/fs/hfs/hfs_fs.h
+++ b/fs/hfs/hfs_fs.h
@@ -216,7 +216,10 @@ extern const struct dentry_operations hfs_dentry_operations;
216extern int hfs_hash_dentry(struct dentry *, struct qstr *); 216extern int hfs_hash_dentry(struct dentry *, struct qstr *);
217extern int hfs_strcmp(const unsigned char *, unsigned int, 217extern int hfs_strcmp(const unsigned char *, unsigned int,
218 const unsigned char *, unsigned int); 218 const unsigned char *, unsigned int);
219extern int hfs_compare_dentry(struct dentry *, struct qstr *, struct qstr *); 219extern int hfs_compare_dentry(const struct dentry *parent,
220 const struct inode *pinode,
221 const struct dentry *dentry, const struct inode *inode,
222 unsigned int len, const char *str, const struct qstr *name);
220 223
221/* trans.c */ 224/* trans.c */
222extern void hfs_asc2mac(struct super_block *, struct hfs_name *, struct qstr *); 225extern void hfs_asc2mac(struct super_block *, struct hfs_name *, struct qstr *);
diff --git a/fs/hfs/string.c b/fs/hfs/string.c
index 927a5af79428..aaf90d0d6940 100644
--- a/fs/hfs/string.c
+++ b/fs/hfs/string.c
@@ -92,21 +92,21 @@ int hfs_strcmp(const unsigned char *s1, unsigned int len1,
92 * Test for equality of two strings in the HFS filename character ordering. 92 * Test for equality of two strings in the HFS filename character ordering.
93 * return 1 on failure and 0 on success 93 * return 1 on failure and 0 on success
94 */ 94 */
95int hfs_compare_dentry(struct dentry *dentry, struct qstr *s1, struct qstr *s2) 95int hfs_compare_dentry(const struct dentry *parent, const struct inode *pinode,
96 const struct dentry *dentry, const struct inode *inode,
97 unsigned int len, const char *str, const struct qstr *name)
96{ 98{
97 const unsigned char *n1, *n2; 99 const unsigned char *n1, *n2;
98 int len;
99 100
100 len = s1->len;
101 if (len >= HFS_NAMELEN) { 101 if (len >= HFS_NAMELEN) {
102 if (s2->len < HFS_NAMELEN) 102 if (name->len < HFS_NAMELEN)
103 return 1; 103 return 1;
104 len = HFS_NAMELEN; 104 len = HFS_NAMELEN;
105 } else if (len != s2->len) 105 } else if (len != name->len)
106 return 1; 106 return 1;
107 107
108 n1 = s1->name; 108 n1 = str;
109 n2 = s2->name; 109 n2 = name->name;
110 while (len--) { 110 while (len--) {
111 if (caseorder[*n1++] != caseorder[*n2++]) 111 if (caseorder[*n1++] != caseorder[*n2++])
112 return 1; 112 return 1;
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index cb3653efb57a..7aa96eefe483 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -380,7 +380,10 @@ int hfsplus_strcmp(const struct hfsplus_unistr *, const struct hfsplus_unistr *)
380int hfsplus_uni2asc(struct super_block *, const struct hfsplus_unistr *, char *, int *); 380int hfsplus_uni2asc(struct super_block *, const struct hfsplus_unistr *, char *, int *);
381int hfsplus_asc2uni(struct super_block *, struct hfsplus_unistr *, const char *, int); 381int hfsplus_asc2uni(struct super_block *, struct hfsplus_unistr *, const char *, int);
382int hfsplus_hash_dentry(struct dentry *dentry, struct qstr *str); 382int hfsplus_hash_dentry(struct dentry *dentry, struct qstr *str);
383int hfsplus_compare_dentry(struct dentry *dentry, struct qstr *s1, struct qstr *s2); 383int hfsplus_compare_dentry(const struct dentry *parent,
384 const struct inode *pinode,
385 const struct dentry *dentry, const struct inode *inode,
386 unsigned int len, const char *str, const struct qstr *name);
384 387
385/* wrapper.c */ 388/* wrapper.c */
386int hfsplus_read_wrapper(struct super_block *); 389int hfsplus_read_wrapper(struct super_block *);
diff --git a/fs/hfsplus/unicode.c b/fs/hfsplus/unicode.c
index b66d67de882c..b178c997efa8 100644
--- a/fs/hfsplus/unicode.c
+++ b/fs/hfsplus/unicode.c
@@ -363,9 +363,12 @@ int hfsplus_hash_dentry(struct dentry *dentry, struct qstr *str)
363 * Composed unicode characters are decomposed and case-folding is performed 363 * Composed unicode characters are decomposed and case-folding is performed
364 * if the appropriate bits are (un)set on the superblock. 364 * if the appropriate bits are (un)set on the superblock.
365 */ 365 */
366int hfsplus_compare_dentry(struct dentry *dentry, struct qstr *s1, struct qstr *s2) 366int hfsplus_compare_dentry(const struct dentry *parent,
367 const struct inode *pinode,
368 const struct dentry *dentry, const struct inode *inode,
369 unsigned int len, const char *str, const struct qstr *name)
367{ 370{
368 struct super_block *sb = dentry->d_sb; 371 struct super_block *sb = parent->d_sb;
369 int casefold, decompose, size; 372 int casefold, decompose, size;
370 int dsize1, dsize2, len1, len2; 373 int dsize1, dsize2, len1, len2;
371 const u16 *dstr1, *dstr2; 374 const u16 *dstr1, *dstr2;
@@ -375,10 +378,10 @@ int hfsplus_compare_dentry(struct dentry *dentry, struct qstr *s1, struct qstr *
375 378
376 casefold = test_bit(HFSPLUS_SB_CASEFOLD, &HFSPLUS_SB(sb)->flags); 379 casefold = test_bit(HFSPLUS_SB_CASEFOLD, &HFSPLUS_SB(sb)->flags);
377 decompose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags); 380 decompose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags);
378 astr1 = s1->name; 381 astr1 = str;
379 len1 = s1->len; 382 len1 = len;
380 astr2 = s2->name; 383 astr2 = name->name;
381 len2 = s2->len; 384 len2 = name->len;
382 dsize1 = dsize2 = 0; 385 dsize1 = dsize2 = 0;
383 dstr1 = dstr2 = NULL; 386 dstr1 = dstr2 = NULL;
384 387
diff --git a/fs/hpfs/dentry.c b/fs/hpfs/dentry.c
index 67d9d36b3d5f..dd9b1e74a734 100644
--- a/fs/hpfs/dentry.c
+++ b/fs/hpfs/dentry.c
@@ -34,19 +34,25 @@ static int hpfs_hash_dentry(struct dentry *dentry, struct qstr *qstr)
34 return 0; 34 return 0;
35} 35}
36 36
37static int hpfs_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b) 37static int hpfs_compare_dentry(const struct dentry *parent,
38 const struct inode *pinode,
39 const struct dentry *dentry, const struct inode *inode,
40 unsigned int len, const char *str, const struct qstr *name)
38{ 41{
39 unsigned al=a->len; 42 unsigned al = len;
40 unsigned bl=b->len; 43 unsigned bl = name->len;
41 hpfs_adjust_length(a->name, &al); 44
45 hpfs_adjust_length(str, &al);
42 /*hpfs_adjust_length(b->name, &bl);*/ 46 /*hpfs_adjust_length(b->name, &bl);*/
43 /* 'a' is the qstr of an already existing dentry, so the name 47
44 * must be valid. 'b' must be validated first. 48 /*
49 * 'str' is the nane of an already existing dentry, so the name
50 * must be valid. 'name' must be validated first.
45 */ 51 */
46 52
47 if (hpfs_chk_name(b->name, &bl)) 53 if (hpfs_chk_name(name->name, &bl))
48 return 1; 54 return 1;
49 if (hpfs_compare_names(dentry->d_sb, a->name, al, b->name, bl, 0)) 55 if (hpfs_compare_names(parent->d_sb, str, al, name->name, bl, 0))
50 return 1; 56 return 1;
51 return 0; 57 return 0;
52} 58}
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index bfdeb82a53be..7b0fbc61af81 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -28,14 +28,26 @@
28 28
29static int isofs_hashi(struct dentry *parent, struct qstr *qstr); 29static int isofs_hashi(struct dentry *parent, struct qstr *qstr);
30static int isofs_hash(struct dentry *parent, struct qstr *qstr); 30static int isofs_hash(struct dentry *parent, struct qstr *qstr);
31static int isofs_dentry_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b); 31static int isofs_dentry_cmpi(const struct dentry *parent,
32static int isofs_dentry_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b); 32 const struct inode *pinode,
33 const struct dentry *dentry, const struct inode *inode,
34 unsigned int len, const char *str, const struct qstr *name);
35static int isofs_dentry_cmp(const struct dentry *parent,
36 const struct inode *pinode,
37 const struct dentry *dentry, const struct inode *inode,
38 unsigned int len, const char *str, const struct qstr *name);
33 39
34#ifdef CONFIG_JOLIET 40#ifdef CONFIG_JOLIET
35static int isofs_hashi_ms(struct dentry *parent, struct qstr *qstr); 41static int isofs_hashi_ms(struct dentry *parent, struct qstr *qstr);
36static int isofs_hash_ms(struct dentry *parent, struct qstr *qstr); 42static int isofs_hash_ms(struct dentry *parent, struct qstr *qstr);
37static int isofs_dentry_cmpi_ms(struct dentry *dentry, struct qstr *a, struct qstr *b); 43static int isofs_dentry_cmpi_ms(const struct dentry *parent,
38static int isofs_dentry_cmp_ms(struct dentry *dentry, struct qstr *a, struct qstr *b); 44 const struct inode *pinode,
45 const struct dentry *dentry, const struct inode *inode,
46 unsigned int len, const char *str, const struct qstr *name);
47static int isofs_dentry_cmp_ms(const struct dentry *parent,
48 const struct inode *pinode,
49 const struct dentry *dentry, const struct inode *inode,
50 unsigned int len, const char *str, const struct qstr *name);
39#endif 51#endif
40 52
41static void isofs_put_super(struct super_block *sb) 53static void isofs_put_super(struct super_block *sb)
@@ -206,49 +218,31 @@ isofs_hashi_common(struct dentry *dentry, struct qstr *qstr, int ms)
206} 218}
207 219
208/* 220/*
209 * Case insensitive compare of two isofs names. 221 * Compare of two isofs names.
210 */ 222 */
211static int isofs_dentry_cmpi_common(struct dentry *dentry, struct qstr *a, 223static int isofs_dentry_cmp_common(
212 struct qstr *b, int ms) 224 unsigned int len, const char *str,
225 const struct qstr *name, int ms, int ci)
213{ 226{
214 int alen, blen; 227 int alen, blen;
215 228
216 /* A filename cannot end in '.' or we treat it like it has none */ 229 /* A filename cannot end in '.' or we treat it like it has none */
217 alen = a->len; 230 alen = name->len;
218 blen = b->len; 231 blen = len;
219 if (ms) { 232 if (ms) {
220 while (alen && a->name[alen-1] == '.') 233 while (alen && name->name[alen-1] == '.')
221 alen--; 234 alen--;
222 while (blen && b->name[blen-1] == '.') 235 while (blen && str[blen-1] == '.')
223 blen--; 236 blen--;
224 } 237 }
225 if (alen == blen) { 238 if (alen == blen) {
226 if (strnicmp(a->name, b->name, alen) == 0) 239 if (ci) {
227 return 0; 240 if (strnicmp(name->name, str, alen) == 0)
228 } 241 return 0;
229 return 1; 242 } else {
230} 243 if (strncmp(name->name, str, alen) == 0)
231 244 return 0;
232/* 245 }
233 * Case sensitive compare of two isofs names.
234 */
235static int isofs_dentry_cmp_common(struct dentry *dentry, struct qstr *a,
236 struct qstr *b, int ms)
237{
238 int alen, blen;
239
240 /* A filename cannot end in '.' or we treat it like it has none */
241 alen = a->len;
242 blen = b->len;
243 if (ms) {
244 while (alen && a->name[alen-1] == '.')
245 alen--;
246 while (blen && b->name[blen-1] == '.')
247 blen--;
248 }
249 if (alen == blen) {
250 if (strncmp(a->name, b->name, alen) == 0)
251 return 0;
252 } 246 }
253 return 1; 247 return 1;
254} 248}
@@ -266,15 +260,19 @@ isofs_hashi(struct dentry *dentry, struct qstr *qstr)
266} 260}
267 261
268static int 262static int
269isofs_dentry_cmp(struct dentry *dentry,struct qstr *a,struct qstr *b) 263isofs_dentry_cmp(const struct dentry *parent, const struct inode *pinode,
264 const struct dentry *dentry, const struct inode *inode,
265 unsigned int len, const char *str, const struct qstr *name)
270{ 266{
271 return isofs_dentry_cmp_common(dentry, a, b, 0); 267 return isofs_dentry_cmp_common(len, str, name, 0, 0);
272} 268}
273 269
274static int 270static int
275isofs_dentry_cmpi(struct dentry *dentry,struct qstr *a,struct qstr *b) 271isofs_dentry_cmpi(const struct dentry *parent, const struct inode *pinode,
272 const struct dentry *dentry, const struct inode *inode,
273 unsigned int len, const char *str, const struct qstr *name)
276{ 274{
277 return isofs_dentry_cmpi_common(dentry, a, b, 0); 275 return isofs_dentry_cmp_common(len, str, name, 0, 1);
278} 276}
279 277
280#ifdef CONFIG_JOLIET 278#ifdef CONFIG_JOLIET
@@ -291,15 +289,19 @@ isofs_hashi_ms(struct dentry *dentry, struct qstr *qstr)
291} 289}
292 290
293static int 291static int
294isofs_dentry_cmp_ms(struct dentry *dentry,struct qstr *a,struct qstr *b) 292isofs_dentry_cmp_ms(const struct dentry *parent, const struct inode *pinode,
293 const struct dentry *dentry, const struct inode *inode,
294 unsigned int len, const char *str, const struct qstr *name)
295{ 295{
296 return isofs_dentry_cmp_common(dentry, a, b, 1); 296 return isofs_dentry_cmp_common(len, str, name, 1, 0);
297} 297}
298 298
299static int 299static int
300isofs_dentry_cmpi_ms(struct dentry *dentry,struct qstr *a,struct qstr *b) 300isofs_dentry_cmpi_ms(const struct dentry *parent, const struct inode *pinode,
301 const struct dentry *dentry, const struct inode *inode,
302 unsigned int len, const char *str, const struct qstr *name)
301{ 303{
302 return isofs_dentry_cmpi_common(dentry, a, b, 1); 304 return isofs_dentry_cmp_common(len, str, name, 1, 1);
303} 305}
304#endif 306#endif
305 307
diff --git a/fs/isofs/namei.c b/fs/isofs/namei.c
index 0d23abfd4280..715f7d318046 100644
--- a/fs/isofs/namei.c
+++ b/fs/isofs/namei.c
@@ -37,7 +37,8 @@ isofs_cmp(struct dentry *dentry, const char *compare, int dlen)
37 37
38 qstr.name = compare; 38 qstr.name = compare;
39 qstr.len = dlen; 39 qstr.len = dlen;
40 return dentry->d_op->d_compare(dentry, &dentry->d_name, &qstr); 40 return dentry->d_op->d_compare(NULL, NULL, NULL, NULL,
41 dentry->d_name.len, dentry->d_name.name, &qstr);
41} 42}
42 43
43/* 44/*
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index 2da1546161fa..92129016cd79 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -1587,14 +1587,17 @@ static int jfs_ci_hash(struct dentry *dir, struct qstr *this)
1587 return 0; 1587 return 0;
1588} 1588}
1589 1589
1590static int jfs_ci_compare(struct dentry *dir, struct qstr *a, struct qstr *b) 1590static int jfs_ci_compare(const struct dentry *parent,
1591 const struct inode *pinode,
1592 const struct dentry *dentry, const struct inode *inode,
1593 unsigned int len, const char *str, const struct qstr *name)
1591{ 1594{
1592 int i, result = 1; 1595 int i, result = 1;
1593 1596
1594 if (a->len != b->len) 1597 if (len != name->len)
1595 goto out; 1598 goto out;
1596 for (i=0; i < a->len; i++) { 1599 for (i=0; i < len; i++) {
1597 if (tolower(a->name[i]) != tolower(b->name[i])) 1600 if (tolower(str[i]) != tolower(name->name[i]))
1598 goto out; 1601 goto out;
1599 } 1602 }
1600 result = 0; 1603 result = 0;
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
index e80ea4e37c48..3bcc68aed416 100644
--- a/fs/ncpfs/dir.c
+++ b/fs/ncpfs/dir.c
@@ -75,7 +75,9 @@ const struct inode_operations ncp_dir_inode_operations =
75 */ 75 */
76static int ncp_lookup_validate(struct dentry *, struct nameidata *); 76static int ncp_lookup_validate(struct dentry *, struct nameidata *);
77static int ncp_hash_dentry(struct dentry *, struct qstr *); 77static int ncp_hash_dentry(struct dentry *, struct qstr *);
78static int ncp_compare_dentry (struct dentry *, struct qstr *, struct qstr *); 78static int ncp_compare_dentry(const struct dentry *, const struct inode *,
79 const struct dentry *, const struct inode *,
80 unsigned int, const char *, const struct qstr *);
79static int ncp_delete_dentry(const struct dentry *); 81static int ncp_delete_dentry(const struct dentry *);
80 82
81static const struct dentry_operations ncp_dentry_operations = 83static const struct dentry_operations ncp_dentry_operations =
@@ -113,10 +115,10 @@ static inline int ncp_preserve_entry_case(struct inode *i, __u32 nscreator)
113 115
114#define ncp_preserve_case(i) (ncp_namespace(i) != NW_NS_DOS) 116#define ncp_preserve_case(i) (ncp_namespace(i) != NW_NS_DOS)
115 117
116static inline int ncp_case_sensitive(struct dentry *dentry) 118static inline int ncp_case_sensitive(const struct inode *i)
117{ 119{
118#ifdef CONFIG_NCPFS_NFS_NS 120#ifdef CONFIG_NCPFS_NFS_NS
119 return ncp_namespace(dentry->d_inode) == NW_NS_NFS; 121 return ncp_namespace(i) == NW_NS_NFS;
120#else 122#else
121 return 0; 123 return 0;
122#endif /* CONFIG_NCPFS_NFS_NS */ 124#endif /* CONFIG_NCPFS_NFS_NS */
@@ -129,12 +131,13 @@ static inline int ncp_case_sensitive(struct dentry *dentry)
129static int 131static int
130ncp_hash_dentry(struct dentry *dentry, struct qstr *this) 132ncp_hash_dentry(struct dentry *dentry, struct qstr *this)
131{ 133{
132 if (!ncp_case_sensitive(dentry)) { 134 if (!ncp_case_sensitive(dentry->d_inode)) {
135 struct super_block *sb = dentry->d_sb;
133 struct nls_table *t; 136 struct nls_table *t;
134 unsigned long hash; 137 unsigned long hash;
135 int i; 138 int i;
136 139
137 t = NCP_IO_TABLE(dentry); 140 t = NCP_IO_TABLE(sb);
138 hash = init_name_hash(); 141 hash = init_name_hash();
139 for (i=0; i<this->len ; i++) 142 for (i=0; i<this->len ; i++)
140 hash = partial_name_hash(ncp_tolower(t, this->name[i]), 143 hash = partial_name_hash(ncp_tolower(t, this->name[i]),
@@ -145,15 +148,17 @@ ncp_hash_dentry(struct dentry *dentry, struct qstr *this)
145} 148}
146 149
147static int 150static int
148ncp_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b) 151ncp_compare_dentry(const struct dentry *parent, const struct inode *pinode,
152 const struct dentry *dentry, const struct inode *inode,
153 unsigned int len, const char *str, const struct qstr *name)
149{ 154{
150 if (a->len != b->len) 155 if (len != name->len)
151 return 1; 156 return 1;
152 157
153 if (ncp_case_sensitive(dentry)) 158 if (ncp_case_sensitive(pinode))
154 return strncmp(a->name, b->name, a->len); 159 return strncmp(str, name->name, len);
155 160
156 return ncp_strnicmp(NCP_IO_TABLE(dentry), a->name, b->name, a->len); 161 return ncp_strnicmp(NCP_IO_TABLE(pinode->i_sb), str, name->name, len);
157} 162}
158 163
159/* 164/*
diff --git a/fs/ncpfs/ncplib_kernel.h b/fs/ncpfs/ncplib_kernel.h
index 3c57eca634ce..244d1b73fda7 100644
--- a/fs/ncpfs/ncplib_kernel.h
+++ b/fs/ncpfs/ncplib_kernel.h
@@ -135,7 +135,7 @@ int ncp__vol2io(struct ncp_server *, unsigned char *, unsigned int *,
135 const unsigned char *, unsigned int, int); 135 const unsigned char *, unsigned int, int);
136 136
137#define NCP_ESC ':' 137#define NCP_ESC ':'
138#define NCP_IO_TABLE(dentry) (NCP_SERVER((dentry)->d_inode)->nls_io) 138#define NCP_IO_TABLE(sb) (NCP_SBP(sb)->nls_io)
139#define ncp_tolower(t, c) nls_tolower(t, c) 139#define ncp_tolower(t, c) nls_tolower(t, c)
140#define ncp_toupper(t, c) nls_toupper(t, c) 140#define ncp_toupper(t, c) nls_toupper(t, c)
141#define ncp_strnicmp(t, s1, s2, len) \ 141#define ncp_strnicmp(t, s1, s2, len) \
@@ -150,15 +150,15 @@ int ncp__io2vol(unsigned char *, unsigned int *,
150int ncp__vol2io(unsigned char *, unsigned int *, 150int ncp__vol2io(unsigned char *, unsigned int *,
151 const unsigned char *, unsigned int, int); 151 const unsigned char *, unsigned int, int);
152 152
153#define NCP_IO_TABLE(dentry) NULL 153#define NCP_IO_TABLE(sb) NULL
154#define ncp_tolower(t, c) tolower(c) 154#define ncp_tolower(t, c) tolower(c)
155#define ncp_toupper(t, c) toupper(c) 155#define ncp_toupper(t, c) toupper(c)
156#define ncp_io2vol(S,m,i,n,k,U) ncp__io2vol(m,i,n,k,U) 156#define ncp_io2vol(S,m,i,n,k,U) ncp__io2vol(m,i,n,k,U)
157#define ncp_vol2io(S,m,i,n,k,U) ncp__vol2io(m,i,n,k,U) 157#define ncp_vol2io(S,m,i,n,k,U) ncp__vol2io(m,i,n,k,U)
158 158
159 159
160static inline int ncp_strnicmp(struct nls_table *t, const unsigned char *s1, 160static inline int ncp_strnicmp(const struct nls_table *t,
161 const unsigned char *s2, int len) 161 const unsigned char *s1, const unsigned char *s2, int len)
162{ 162{
163 while (len--) { 163 while (len--) {
164 if (tolower(*s1++) != tolower(*s2++)) 164 if (tolower(*s1++) != tolower(*s2++))
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index a256d770ea18..ae4b0fd9033f 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -397,15 +397,16 @@ static int proc_sys_delete(const struct dentry *dentry)
397 return !!PROC_I(dentry->d_inode)->sysctl->unregistering; 397 return !!PROC_I(dentry->d_inode)->sysctl->unregistering;
398} 398}
399 399
400static int proc_sys_compare(struct dentry *dir, struct qstr *qstr, 400static int proc_sys_compare(const struct dentry *parent,
401 struct qstr *name) 401 const struct inode *pinode,
402 const struct dentry *dentry, const struct inode *inode,
403 unsigned int len, const char *str, const struct qstr *name)
402{ 404{
403 struct dentry *dentry = container_of(qstr, struct dentry, d_name); 405 if (name->len != len)
404 if (qstr->len != name->len)
405 return 1; 406 return 1;
406 if (memcmp(qstr->name, name->name, name->len)) 407 if (memcmp(name->name, str, len))
407 return 1; 408 return 1;
408 return !sysctl_is_seen(PROC_I(dentry->d_inode)->sysctl); 409 return !sysctl_is_seen(PROC_I(inode)->sysctl);
409} 410}
410 411
411static const struct dentry_operations proc_sys_dentry_operations = { 412static const struct dentry_operations proc_sys_dentry_operations = {