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 /fs/affs | |
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>
Diffstat (limited to 'fs/affs')
-rw-r--r-- | fs/affs/namei.c | 46 |
1 files changed, 28 insertions, 18 deletions
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 | /* |