diff options
author | Nick Piggin <npiggin@kernel.dk> | 2011-01-07 01:49:27 -0500 |
---|---|---|
committer | Nick Piggin <npiggin@kernel.dk> | 2011-01-07 01:50:19 -0500 |
commit | 621e155a3591962420eacdd39f6f0aa29ceb221e (patch) | |
tree | 387a9fb396f1bf24514b712c294182e36ba51076 | |
parent | fb2d5b86aff355a27ebfc132d3c99f4a940cc3fe (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>
-rw-r--r-- | Documentation/filesystems/Locking | 4 | ||||
-rw-r--r-- | Documentation/filesystems/porting | 7 | ||||
-rw-r--r-- | Documentation/filesystems/vfs.txt | 26 | ||||
-rw-r--r-- | drivers/staging/smbfs/dir.c | 16 | ||||
-rw-r--r-- | fs/adfs/dir.c | 8 | ||||
-rw-r--r-- | fs/affs/namei.c | 46 | ||||
-rw-r--r-- | fs/cifs/dir.c | 12 | ||||
-rw-r--r-- | fs/dcache.c | 4 | ||||
-rw-r--r-- | fs/fat/namei_msdos.c | 14 | ||||
-rw-r--r-- | fs/fat/namei_vfat.c | 33 | ||||
-rw-r--r-- | fs/hfs/hfs_fs.h | 5 | ||||
-rw-r--r-- | fs/hfs/string.c | 14 | ||||
-rw-r--r-- | fs/hfsplus/hfsplus_fs.h | 5 | ||||
-rw-r--r-- | fs/hfsplus/unicode.c | 15 | ||||
-rw-r--r-- | fs/hpfs/dentry.c | 22 | ||||
-rw-r--r-- | fs/isofs/inode.c | 92 | ||||
-rw-r--r-- | fs/isofs/namei.c | 3 | ||||
-rw-r--r-- | fs/jfs/namei.c | 11 | ||||
-rw-r--r-- | fs/ncpfs/dir.c | 25 | ||||
-rw-r--r-- | fs/ncpfs/ncplib_kernel.h | 8 | ||||
-rw-r--r-- | fs/proc/proc_sysctl.c | 13 | ||||
-rw-r--r-- | include/linux/dcache.h | 12 | ||||
-rw-r--r-- | include/linux/ncp_fs.h | 4 |
23 files changed, 242 insertions, 157 deletions
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index 33fa3e5d38fd..9a76f8d8bf95 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking | |||
@@ -11,7 +11,9 @@ be able to use diff(1). | |||
11 | prototypes: | 11 | prototypes: |
12 | int (*d_revalidate)(struct dentry *, int); | 12 | int (*d_revalidate)(struct dentry *, int); |
13 | int (*d_hash) (struct dentry *, struct qstr *); | 13 | int (*d_hash) (struct dentry *, struct qstr *); |
14 | int (*d_compare) (struct dentry *, struct qstr *, struct qstr *); | 14 | int (*d_compare)(const struct dentry *, const struct inode *, |
15 | const struct dentry *, const struct inode *, | ||
16 | unsigned int, const char *, const struct qstr *); | ||
15 | int (*d_delete)(struct dentry *); | 17 | int (*d_delete)(struct dentry *); |
16 | void (*d_release)(struct dentry *); | 18 | void (*d_release)(struct dentry *); |
17 | void (*d_iput)(struct dentry *, struct inode *); | 19 | void (*d_iput)(struct dentry *, struct inode *); |
diff --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting index 9e71c9ad3108..d44511e20828 100644 --- a/Documentation/filesystems/porting +++ b/Documentation/filesystems/porting | |||
@@ -326,3 +326,10 @@ to it. | |||
326 | unreferenced dentries, and is now only called when the dentry refcount goes to | 326 | unreferenced dentries, and is now only called when the dentry refcount goes to |
327 | 0. Even on 0 refcount transition, it must be able to tolerate being called 0, | 327 | 0. Even on 0 refcount transition, it must be able to tolerate being called 0, |
328 | 1, or more times (eg. constant, idempotent). | 328 | 1, or more times (eg. constant, idempotent). |
329 | |||
330 | --- | ||
331 | [mandatory] | ||
332 | |||
333 | .d_compare() calling convention and locking rules are significantly | ||
334 | changed. Read updated documentation in Documentation/filesystems/vfs.txt (and | ||
335 | look at examples of other filesystems) for guidance. | ||
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index 95c0a93f056c..250681b8c7cc 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt | |||
@@ -848,7 +848,9 @@ defined: | |||
848 | struct dentry_operations { | 848 | struct dentry_operations { |
849 | int (*d_revalidate)(struct dentry *, struct nameidata *); | 849 | int (*d_revalidate)(struct dentry *, struct nameidata *); |
850 | int (*d_hash)(struct dentry *, struct qstr *); | 850 | int (*d_hash)(struct dentry *, struct qstr *); |
851 | int (*d_compare)(struct dentry *, struct qstr *, struct qstr *); | 851 | int (*d_compare)(const struct dentry *, const struct inode *, |
852 | const struct dentry *, const struct inode *, | ||
853 | unsigned int, const char *, const struct qstr *); | ||
852 | int (*d_delete)(const struct dentry *); | 854 | int (*d_delete)(const struct dentry *); |
853 | void (*d_release)(struct dentry *); | 855 | void (*d_release)(struct dentry *); |
854 | void (*d_iput)(struct dentry *, struct inode *); | 856 | void (*d_iput)(struct dentry *, struct inode *); |
@@ -860,9 +862,27 @@ struct dentry_operations { | |||
860 | dcache. Most filesystems leave this as NULL, because all their | 862 | dcache. Most filesystems leave this as NULL, because all their |
861 | dentries in the dcache are valid | 863 | dentries in the dcache are valid |
862 | 864 | ||
863 | d_hash: called when the VFS adds a dentry to the hash table | 865 | d_hash: called when the VFS adds a dentry to the hash table. The first |
866 | dentry passed to d_hash is the parent directory that the name is | ||
867 | to be hashed into. | ||
864 | 868 | ||
865 | d_compare: called when a dentry should be compared with another | 869 | d_compare: called to compare a dentry name with a given name. The first |
870 | dentry is the parent of the dentry to be compared, the second is | ||
871 | the parent's inode, then the dentry and inode (may be NULL) of the | ||
872 | child dentry. len and name string are properties of the dentry to be | ||
873 | compared. qstr is the name to compare it with. | ||
874 | |||
875 | Must be constant and idempotent, and should not take locks if | ||
876 | possible, and should not or store into the dentry or inodes. | ||
877 | Should not dereference pointers outside the dentry or inodes without | ||
878 | lots of care (eg. d_parent, d_inode, d_name should not be used). | ||
879 | |||
880 | However, our vfsmount is pinned, and RCU held, so the dentries and | ||
881 | inodes won't disappear, neither will our sb or filesystem module. | ||
882 | ->i_sb and ->d_sb may be used. | ||
883 | |||
884 | It is a tricky calling convention because it needs to be called under | ||
885 | "rcu-walk", ie. without any locks or references on things. | ||
866 | 886 | ||
867 | d_delete: called when the last reference to a dentry is dropped and the | 887 | d_delete: called when the last reference to a dentry is dropped and the |
868 | dcache is deciding whether or not to cache it. Return 1 to delete | 888 | dcache is deciding whether or not to cache it. Return 1 to delete |
diff --git a/drivers/staging/smbfs/dir.c b/drivers/staging/smbfs/dir.c index 2270d4822c2f..bd63229f43f2 100644 --- a/drivers/staging/smbfs/dir.c +++ b/drivers/staging/smbfs/dir.c | |||
@@ -275,7 +275,10 @@ smb_dir_open(struct inode *dir, struct file *file) | |||
275 | */ | 275 | */ |
276 | static int smb_lookup_validate(struct dentry *, struct nameidata *); | 276 | static int smb_lookup_validate(struct dentry *, struct nameidata *); |
277 | static int smb_hash_dentry(struct dentry *, struct qstr *); | 277 | static int smb_hash_dentry(struct dentry *, struct qstr *); |
278 | static int smb_compare_dentry(struct dentry *, struct qstr *, struct qstr *); | 278 | static int smb_compare_dentry(const struct dentry *, |
279 | const struct inode *, | ||
280 | const struct dentry *, const struct inode *, | ||
281 | unsigned int, const char *, const struct qstr *); | ||
279 | static int smb_delete_dentry(const struct dentry *); | 282 | static int smb_delete_dentry(const struct dentry *); |
280 | 283 | ||
281 | static const struct dentry_operations smbfs_dentry_operations = | 284 | static const struct dentry_operations smbfs_dentry_operations = |
@@ -347,14 +350,17 @@ smb_hash_dentry(struct dentry *dir, struct qstr *this) | |||
347 | } | 350 | } |
348 | 351 | ||
349 | static int | 352 | static int |
350 | smb_compare_dentry(struct dentry *dir, struct qstr *a, struct qstr *b) | 353 | smb_compare_dentry(const struct dentry *parent, |
354 | const struct inode *pinode, | ||
355 | const struct dentry *dentry, const struct inode *inode, | ||
356 | unsigned int len, const char *str, const struct qstr *name) | ||
351 | { | 357 | { |
352 | int i, result = 1; | 358 | int i, result = 1; |
353 | 359 | ||
354 | if (a->len != b->len) | 360 | if (len != name->len) |
355 | goto out; | 361 | goto out; |
356 | for (i=0; i < a->len; i++) { | 362 | for (i=0; i < len; i++) { |
357 | if (tolower(a->name[i]) != tolower(b->name[i])) | 363 | if (tolower(str[i]) != tolower(name->name[i])) |
358 | goto out; | 364 | goto out; |
359 | } | 365 | } |
360 | result = 0; | 366 | result = 0; |
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 | */ |
239 | static int | 239 | static int |
240 | adfs_compare(struct dentry *parent, struct qstr *entry, struct qstr *name) | 240 | adfs_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 | ||
15 | static int affs_toupper(int ch); | 15 | static int affs_toupper(int ch); |
16 | static int affs_hash_dentry(struct dentry *, struct qstr *); | 16 | static int affs_hash_dentry(struct dentry *, struct qstr *); |
17 | static int affs_compare_dentry(struct dentry *, struct qstr *, struct qstr *); | 17 | static 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); | ||
18 | static int affs_intl_toupper(int ch); | 21 | static int affs_intl_toupper(int ch); |
19 | static int affs_intl_hash_dentry(struct dentry *, struct qstr *); | 22 | static int affs_intl_hash_dentry(struct dentry *, struct qstr *); |
20 | static int affs_intl_compare_dentry(struct dentry *, struct qstr *, struct qstr *); | 23 | static 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 | ||
22 | const struct dentry_operations affs_dentry_operations = { | 28 | const 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 | ||
91 | static inline int | 97 | static 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 | ||
123 | static int | 129 | static int |
124 | affs_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b) | 130 | affs_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 | } |
128 | static int | 136 | static int |
129 | affs_intl_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b) | 137 | affs_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 | ||
718 | static int cifs_ci_compare(struct dentry *dentry, struct qstr *a, | 718 | static 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 | */ |
167 | static int msdos_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b) | 167 | static 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 | ||
183 | old_compare: | 185 | old_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 */ |
88 | static unsigned int vfat_striptail_len(struct qstr *qstr) | 88 | static 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 | ||
95 | static 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 | */ |
136 | static int vfat_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b) | 139 | static 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 | */ |
154 | static int vfat_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b) | 159 | static 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; | |||
216 | extern int hfs_hash_dentry(struct dentry *, struct qstr *); | 216 | extern int hfs_hash_dentry(struct dentry *, struct qstr *); |
217 | extern int hfs_strcmp(const unsigned char *, unsigned int, | 217 | extern int hfs_strcmp(const unsigned char *, unsigned int, |
218 | const unsigned char *, unsigned int); | 218 | const unsigned char *, unsigned int); |
219 | extern int hfs_compare_dentry(struct dentry *, struct qstr *, struct qstr *); | 219 | extern 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 */ |
222 | extern void hfs_asc2mac(struct super_block *, struct hfs_name *, struct qstr *); | 225 | extern 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 | */ |
95 | int hfs_compare_dentry(struct dentry *dentry, struct qstr *s1, struct qstr *s2) | 95 | int 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 *) | |||
380 | int hfsplus_uni2asc(struct super_block *, const struct hfsplus_unistr *, char *, int *); | 380 | int hfsplus_uni2asc(struct super_block *, const struct hfsplus_unistr *, char *, int *); |
381 | int hfsplus_asc2uni(struct super_block *, struct hfsplus_unistr *, const char *, int); | 381 | int hfsplus_asc2uni(struct super_block *, struct hfsplus_unistr *, const char *, int); |
382 | int hfsplus_hash_dentry(struct dentry *dentry, struct qstr *str); | 382 | int hfsplus_hash_dentry(struct dentry *dentry, struct qstr *str); |
383 | int hfsplus_compare_dentry(struct dentry *dentry, struct qstr *s1, struct qstr *s2); | 383 | int 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 */ |
386 | int hfsplus_read_wrapper(struct super_block *); | 389 | int 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 | */ |
366 | int hfsplus_compare_dentry(struct dentry *dentry, struct qstr *s1, struct qstr *s2) | 366 | int 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 | ||
37 | static int hpfs_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b) | 37 | static 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 | ||
29 | static int isofs_hashi(struct dentry *parent, struct qstr *qstr); | 29 | static int isofs_hashi(struct dentry *parent, struct qstr *qstr); |
30 | static int isofs_hash(struct dentry *parent, struct qstr *qstr); | 30 | static int isofs_hash(struct dentry *parent, struct qstr *qstr); |
31 | static int isofs_dentry_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b); | 31 | static int isofs_dentry_cmpi(const struct dentry *parent, |
32 | static 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); | ||
35 | static 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 |
35 | static int isofs_hashi_ms(struct dentry *parent, struct qstr *qstr); | 41 | static int isofs_hashi_ms(struct dentry *parent, struct qstr *qstr); |
36 | static int isofs_hash_ms(struct dentry *parent, struct qstr *qstr); | 42 | static int isofs_hash_ms(struct dentry *parent, struct qstr *qstr); |
37 | static int isofs_dentry_cmpi_ms(struct dentry *dentry, struct qstr *a, struct qstr *b); | 43 | static int isofs_dentry_cmpi_ms(const struct dentry *parent, |
38 | static 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); | ||
47 | static 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 | ||
41 | static void isofs_put_super(struct super_block *sb) | 53 | static 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 | */ |
211 | static int isofs_dentry_cmpi_common(struct dentry *dentry, struct qstr *a, | 223 | static 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 | */ | ||
235 | static 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 | ||
268 | static int | 262 | static int |
269 | isofs_dentry_cmp(struct dentry *dentry,struct qstr *a,struct qstr *b) | 263 | isofs_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 | ||
274 | static int | 270 | static int |
275 | isofs_dentry_cmpi(struct dentry *dentry,struct qstr *a,struct qstr *b) | 271 | isofs_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 | ||
293 | static int | 291 | static int |
294 | isofs_dentry_cmp_ms(struct dentry *dentry,struct qstr *a,struct qstr *b) | 292 | isofs_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 | ||
299 | static int | 299 | static int |
300 | isofs_dentry_cmpi_ms(struct dentry *dentry,struct qstr *a,struct qstr *b) | 300 | isofs_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 | ||
1590 | static int jfs_ci_compare(struct dentry *dir, struct qstr *a, struct qstr *b) | 1590 | static 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 | */ |
76 | static int ncp_lookup_validate(struct dentry *, struct nameidata *); | 76 | static int ncp_lookup_validate(struct dentry *, struct nameidata *); |
77 | static int ncp_hash_dentry(struct dentry *, struct qstr *); | 77 | static int ncp_hash_dentry(struct dentry *, struct qstr *); |
78 | static int ncp_compare_dentry (struct dentry *, struct qstr *, struct qstr *); | 78 | static 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 *); | ||
79 | static int ncp_delete_dentry(const struct dentry *); | 81 | static int ncp_delete_dentry(const struct dentry *); |
80 | 82 | ||
81 | static const struct dentry_operations ncp_dentry_operations = | 83 | static 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 | ||
116 | static inline int ncp_case_sensitive(struct dentry *dentry) | 118 | static 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) | |||
129 | static int | 131 | static int |
130 | ncp_hash_dentry(struct dentry *dentry, struct qstr *this) | 132 | ncp_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 | ||
147 | static int | 150 | static int |
148 | ncp_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b) | 151 | ncp_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 *, | |||
150 | int ncp__vol2io(unsigned char *, unsigned int *, | 150 | int 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 | ||
160 | static inline int ncp_strnicmp(struct nls_table *t, const unsigned char *s1, | 160 | static 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 | ||
400 | static int proc_sys_compare(struct dentry *dir, struct qstr *qstr, | 400 | static 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 | ||
411 | static const struct dentry_operations proc_sys_dentry_operations = { | 412 | static const struct dentry_operations proc_sys_dentry_operations = { |
diff --git a/include/linux/dcache.h b/include/linux/dcache.h index 6cdf4995c90a..75a072bf2a34 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h | |||
@@ -134,7 +134,9 @@ enum dentry_d_lock_class | |||
134 | struct dentry_operations { | 134 | struct dentry_operations { |
135 | int (*d_revalidate)(struct dentry *, struct nameidata *); | 135 | int (*d_revalidate)(struct dentry *, struct nameidata *); |
136 | int (*d_hash)(struct dentry *, struct qstr *); | 136 | int (*d_hash)(struct dentry *, struct qstr *); |
137 | int (*d_compare)(struct dentry *, struct qstr *, struct qstr *); | 137 | int (*d_compare)(const struct dentry *, const struct inode *, |
138 | const struct dentry *, const struct inode *, | ||
139 | unsigned int, const char *, const struct qstr *); | ||
138 | int (*d_delete)(const struct dentry *); | 140 | int (*d_delete)(const struct dentry *); |
139 | void (*d_release)(struct dentry *); | 141 | void (*d_release)(struct dentry *); |
140 | void (*d_iput)(struct dentry *, struct inode *); | 142 | void (*d_iput)(struct dentry *, struct inode *); |
@@ -145,12 +147,8 @@ struct dentry_operations { | |||
145 | * Locking rules for dentry_operations callbacks are to be found in | 147 | * Locking rules for dentry_operations callbacks are to be found in |
146 | * Documentation/filesystems/Locking. Keep it updated! | 148 | * Documentation/filesystems/Locking. Keep it updated! |
147 | * | 149 | * |
148 | * the dentry parameter passed to d_hash and d_compare is the parent | 150 | * FUrther descriptions are found in Documentation/filesystems/vfs.txt. |
149 | * directory of the entries to be compared. It is used in case these | 151 | * Keep it updated too! |
150 | * functions need any directory specific information for determining | ||
151 | * equivalency classes. Using the dentry itself might not work, as it | ||
152 | * might be a negative dentry which has no information associated with | ||
153 | * it. | ||
154 | */ | 152 | */ |
155 | 153 | ||
156 | /* d_flags entries */ | 154 | /* d_flags entries */ |
diff --git a/include/linux/ncp_fs.h b/include/linux/ncp_fs.h index ef663061d5ac..1c27f201c856 100644 --- a/include/linux/ncp_fs.h +++ b/include/linux/ncp_fs.h | |||
@@ -184,13 +184,13 @@ struct ncp_entry_info { | |||
184 | __u8 file_handle[6]; | 184 | __u8 file_handle[6]; |
185 | }; | 185 | }; |
186 | 186 | ||
187 | static inline struct ncp_server *NCP_SBP(struct super_block *sb) | 187 | static inline struct ncp_server *NCP_SBP(const struct super_block *sb) |
188 | { | 188 | { |
189 | return sb->s_fs_info; | 189 | return sb->s_fs_info; |
190 | } | 190 | } |
191 | 191 | ||
192 | #define NCP_SERVER(inode) NCP_SBP((inode)->i_sb) | 192 | #define NCP_SERVER(inode) NCP_SBP((inode)->i_sb) |
193 | static inline struct ncp_inode_info *NCP_FINFO(struct inode *inode) | 193 | static inline struct ncp_inode_info *NCP_FINFO(const struct inode *inode) |
194 | { | 194 | { |
195 | return container_of(inode, struct ncp_inode_info, vfs_inode); | 195 | return container_of(inode, struct ncp_inode_info, vfs_inode); |
196 | } | 196 | } |