diff options
Diffstat (limited to 'include/linux/rhashtable.h')
-rw-r--r-- | include/linux/rhashtable.h | 173 |
1 files changed, 116 insertions, 57 deletions
diff --git a/include/linux/rhashtable.h b/include/linux/rhashtable.h index 1b51221c6bbd..b54e24a08806 100644 --- a/include/linux/rhashtable.h +++ b/include/linux/rhashtable.h | |||
@@ -87,11 +87,18 @@ struct rhashtable { | |||
87 | 87 | ||
88 | #ifdef CONFIG_PROVE_LOCKING | 88 | #ifdef CONFIG_PROVE_LOCKING |
89 | int lockdep_rht_mutex_is_held(const struct rhashtable *ht); | 89 | int lockdep_rht_mutex_is_held(const struct rhashtable *ht); |
90 | int lockdep_rht_bucket_is_held(const struct bucket_table *tbl, u32 hash); | ||
90 | #else | 91 | #else |
91 | static inline int lockdep_rht_mutex_is_held(const struct rhashtable *ht) | 92 | static inline int lockdep_rht_mutex_is_held(const struct rhashtable *ht) |
92 | { | 93 | { |
93 | return 1; | 94 | return 1; |
94 | } | 95 | } |
96 | |||
97 | static inline int lockdep_rht_bucket_is_held(const struct bucket_table *tbl, | ||
98 | u32 hash) | ||
99 | { | ||
100 | return 1; | ||
101 | } | ||
95 | #endif /* CONFIG_PROVE_LOCKING */ | 102 | #endif /* CONFIG_PROVE_LOCKING */ |
96 | 103 | ||
97 | int rhashtable_init(struct rhashtable *ht, struct rhashtable_params *params); | 104 | int rhashtable_init(struct rhashtable *ht, struct rhashtable_params *params); |
@@ -119,92 +126,144 @@ void rhashtable_destroy(const struct rhashtable *ht); | |||
119 | #define rht_dereference_rcu(p, ht) \ | 126 | #define rht_dereference_rcu(p, ht) \ |
120 | rcu_dereference_check(p, lockdep_rht_mutex_is_held(ht)) | 127 | rcu_dereference_check(p, lockdep_rht_mutex_is_held(ht)) |
121 | 128 | ||
122 | #define rht_entry(ptr, type, member) container_of(ptr, type, member) | 129 | #define rht_dereference_bucket(p, tbl, hash) \ |
123 | #define rht_entry_safe(ptr, type, member) \ | 130 | rcu_dereference_protected(p, lockdep_rht_bucket_is_held(tbl, hash)) |
124 | ({ \ | ||
125 | typeof(ptr) __ptr = (ptr); \ | ||
126 | __ptr ? rht_entry(__ptr, type, member) : NULL; \ | ||
127 | }) | ||
128 | 131 | ||
129 | #define rht_next_entry_safe(pos, ht, member) \ | 132 | #define rht_dereference_bucket_rcu(p, tbl, hash) \ |
130 | ({ \ | 133 | rcu_dereference_check(p, lockdep_rht_bucket_is_held(tbl, hash)) |
131 | pos ? rht_entry_safe(rht_dereference((pos)->member.next, ht), \ | 134 | |
132 | typeof(*(pos)), member) : NULL; \ | 135 | #define rht_entry(tpos, pos, member) \ |
133 | }) | 136 | ({ tpos = container_of(pos, typeof(*tpos), member); 1; }) |
134 | 137 | ||
135 | /** | 138 | /** |
136 | * rht_for_each - iterate over hash chain | 139 | * rht_for_each_continue - continue iterating over hash chain |
137 | * @pos: &struct rhash_head to use as a loop cursor. | 140 | * @pos: the &struct rhash_head to use as a loop cursor. |
138 | * @head: head of the hash chain (struct rhash_head *) | 141 | * @head: the previous &struct rhash_head to continue from |
139 | * @ht: pointer to your struct rhashtable | 142 | * @tbl: the &struct bucket_table |
143 | * @hash: the hash value / bucket index | ||
140 | */ | 144 | */ |
141 | #define rht_for_each(pos, head, ht) \ | 145 | #define rht_for_each_continue(pos, head, tbl, hash) \ |
142 | for (pos = rht_dereference(head, ht); \ | 146 | for (pos = rht_dereference_bucket(head, tbl, hash); \ |
143 | pos; \ | 147 | pos; \ |
144 | pos = rht_dereference((pos)->next, ht)) | 148 | pos = rht_dereference_bucket((pos)->next, tbl, hash)) |
149 | |||
150 | /** | ||
151 | * rht_for_each - iterate over hash chain | ||
152 | * @pos: the &struct rhash_head to use as a loop cursor. | ||
153 | * @tbl: the &struct bucket_table | ||
154 | * @hash: the hash value / bucket index | ||
155 | */ | ||
156 | #define rht_for_each(pos, tbl, hash) \ | ||
157 | rht_for_each_continue(pos, (tbl)->buckets[hash], tbl, hash) | ||
158 | |||
159 | /** | ||
160 | * rht_for_each_entry_continue - continue iterating over hash chain | ||
161 | * @tpos: the type * to use as a loop cursor. | ||
162 | * @pos: the &struct rhash_head to use as a loop cursor. | ||
163 | * @head: the previous &struct rhash_head to continue from | ||
164 | * @tbl: the &struct bucket_table | ||
165 | * @hash: the hash value / bucket index | ||
166 | * @member: name of the &struct rhash_head within the hashable struct. | ||
167 | */ | ||
168 | #define rht_for_each_entry_continue(tpos, pos, head, tbl, hash, member) \ | ||
169 | for (pos = rht_dereference_bucket(head, tbl, hash); \ | ||
170 | pos && rht_entry(tpos, pos, member); \ | ||
171 | pos = rht_dereference_bucket((pos)->next, tbl, hash)) | ||
145 | 172 | ||
146 | /** | 173 | /** |
147 | * rht_for_each_entry - iterate over hash chain of given type | 174 | * rht_for_each_entry - iterate over hash chain of given type |
148 | * @pos: type * to use as a loop cursor. | 175 | * @tpos: the type * to use as a loop cursor. |
149 | * @head: head of the hash chain (struct rhash_head *) | 176 | * @pos: the &struct rhash_head to use as a loop cursor. |
150 | * @ht: pointer to your struct rhashtable | 177 | * @tbl: the &struct bucket_table |
151 | * @member: name of the rhash_head within the hashable struct. | 178 | * @hash: the hash value / bucket index |
179 | * @member: name of the &struct rhash_head within the hashable struct. | ||
152 | */ | 180 | */ |
153 | #define rht_for_each_entry(pos, head, ht, member) \ | 181 | #define rht_for_each_entry(tpos, pos, tbl, hash, member) \ |
154 | for (pos = rht_entry_safe(rht_dereference(head, ht), \ | 182 | rht_for_each_entry_continue(tpos, pos, (tbl)->buckets[hash], \ |
155 | typeof(*(pos)), member); \ | 183 | tbl, hash, member) |
156 | pos; \ | ||
157 | pos = rht_next_entry_safe(pos, ht, member)) | ||
158 | 184 | ||
159 | /** | 185 | /** |
160 | * rht_for_each_entry_safe - safely iterate over hash chain of given type | 186 | * rht_for_each_entry_safe - safely iterate over hash chain of given type |
161 | * @pos: type * to use as a loop cursor. | 187 | * @tpos: the type * to use as a loop cursor. |
162 | * @n: type * to use for temporary next object storage | 188 | * @pos: the &struct rhash_head to use as a loop cursor. |
163 | * @head: head of the hash chain (struct rhash_head *) | 189 | * @next: the &struct rhash_head to use as next in loop cursor. |
164 | * @ht: pointer to your struct rhashtable | 190 | * @tbl: the &struct bucket_table |
165 | * @member: name of the rhash_head within the hashable struct. | 191 | * @hash: the hash value / bucket index |
192 | * @member: name of the &struct rhash_head within the hashable struct. | ||
166 | * | 193 | * |
167 | * This hash chain list-traversal primitive allows for the looped code to | 194 | * This hash chain list-traversal primitive allows for the looped code to |
168 | * remove the loop cursor from the list. | 195 | * remove the loop cursor from the list. |
169 | */ | 196 | */ |
170 | #define rht_for_each_entry_safe(pos, n, head, ht, member) \ | 197 | #define rht_for_each_entry_safe(tpos, pos, next, tbl, hash, member) \ |
171 | for (pos = rht_entry_safe(rht_dereference(head, ht), \ | 198 | for (pos = rht_dereference_bucket((tbl)->buckets[hash], tbl, hash), \ |
172 | typeof(*(pos)), member), \ | 199 | next = pos ? rht_dereference_bucket(pos->next, tbl, hash) \ |
173 | n = rht_next_entry_safe(pos, ht, member); \ | 200 | : NULL; \ |
174 | pos; \ | 201 | pos && rht_entry(tpos, pos, member); \ |
175 | pos = n, \ | 202 | pos = next) |
176 | n = rht_next_entry_safe(pos, ht, member)) | 203 | |
204 | /** | ||
205 | * rht_for_each_rcu_continue - continue iterating over rcu hash chain | ||
206 | * @pos: the &struct rhash_head to use as a loop cursor. | ||
207 | * @head: the previous &struct rhash_head to continue from | ||
208 | * @tbl: the &struct bucket_table | ||
209 | * @hash: the hash value / bucket index | ||
210 | * | ||
211 | * This hash chain list-traversal primitive may safely run concurrently with | ||
212 | * the _rcu mutation primitives such as rhashtable_insert() as long as the | ||
213 | * traversal is guarded by rcu_read_lock(). | ||
214 | */ | ||
215 | #define rht_for_each_rcu_continue(pos, head, tbl, hash) \ | ||
216 | for (({barrier(); }), \ | ||
217 | pos = rht_dereference_bucket_rcu(head, tbl, hash); \ | ||
218 | pos; \ | ||
219 | pos = rcu_dereference_raw(pos->next)) | ||
177 | 220 | ||
178 | /** | 221 | /** |
179 | * rht_for_each_rcu - iterate over rcu hash chain | 222 | * rht_for_each_rcu - iterate over rcu hash chain |
180 | * @pos: &struct rhash_head to use as a loop cursor. | 223 | * @pos: the &struct rhash_head to use as a loop cursor. |
181 | * @head: head of the hash chain (struct rhash_head *) | 224 | * @tbl: the &struct bucket_table |
182 | * @ht: pointer to your struct rhashtable | 225 | * @hash: the hash value / bucket index |
183 | * | 226 | * |
184 | * This hash chain list-traversal primitive may safely run concurrently with | 227 | * This hash chain list-traversal primitive may safely run concurrently with |
185 | * the _rcu fkht mutation primitives such as rht_insert() as long as the | 228 | * the _rcu mutation primitives such as rhashtable_insert() as long as the |
186 | * traversal is guarded by rcu_read_lock(). | 229 | * traversal is guarded by rcu_read_lock(). |
187 | */ | 230 | */ |
188 | #define rht_for_each_rcu(pos, head, ht) \ | 231 | #define rht_for_each_rcu(pos, tbl, hash) \ |
189 | for (pos = rht_dereference_rcu(head, ht); \ | 232 | rht_for_each_rcu_continue(pos, (tbl)->buckets[hash], tbl, hash) |
190 | pos; \ | 233 | |
191 | pos = rht_dereference_rcu((pos)->next, ht)) | 234 | /** |
235 | * rht_for_each_entry_rcu_continue - continue iterating over rcu hash chain | ||
236 | * @tpos: the type * to use as a loop cursor. | ||
237 | * @pos: the &struct rhash_head to use as a loop cursor. | ||
238 | * @head: the previous &struct rhash_head to continue from | ||
239 | * @tbl: the &struct bucket_table | ||
240 | * @hash: the hash value / bucket index | ||
241 | * @member: name of the &struct rhash_head within the hashable struct. | ||
242 | * | ||
243 | * This hash chain list-traversal primitive may safely run concurrently with | ||
244 | * the _rcu mutation primitives such as rhashtable_insert() as long as the | ||
245 | * traversal is guarded by rcu_read_lock(). | ||
246 | */ | ||
247 | #define rht_for_each_entry_rcu_continue(tpos, pos, head, tbl, hash, member) \ | ||
248 | for (({barrier(); }), \ | ||
249 | pos = rht_dereference_bucket_rcu(head, tbl, hash); \ | ||
250 | pos && rht_entry(tpos, pos, member); \ | ||
251 | pos = rht_dereference_bucket_rcu(pos->next, tbl, hash)) | ||
192 | 252 | ||
193 | /** | 253 | /** |
194 | * rht_for_each_entry_rcu - iterate over rcu hash chain of given type | 254 | * rht_for_each_entry_rcu - iterate over rcu hash chain of given type |
195 | * @pos: type * to use as a loop cursor. | 255 | * @tpos: the type * to use as a loop cursor. |
196 | * @head: head of the hash chain (struct rhash_head *) | 256 | * @pos: the &struct rhash_head to use as a loop cursor. |
197 | * @member: name of the rhash_head within the hashable struct. | 257 | * @tbl: the &struct bucket_table |
258 | * @hash: the hash value / bucket index | ||
259 | * @member: name of the &struct rhash_head within the hashable struct. | ||
198 | * | 260 | * |
199 | * This hash chain list-traversal primitive may safely run concurrently with | 261 | * This hash chain list-traversal primitive may safely run concurrently with |
200 | * the _rcu fkht mutation primitives such as rht_insert() as long as the | 262 | * the _rcu mutation primitives such as rhashtable_insert() as long as the |
201 | * traversal is guarded by rcu_read_lock(). | 263 | * traversal is guarded by rcu_read_lock(). |
202 | */ | 264 | */ |
203 | #define rht_for_each_entry_rcu(pos, head, member) \ | 265 | #define rht_for_each_entry_rcu(tpos, pos, tbl, hash, member) \ |
204 | for (pos = rht_entry_safe(rcu_dereference_raw(head), \ | 266 | rht_for_each_entry_rcu_continue(tpos, pos, (tbl)->buckets[hash],\ |
205 | typeof(*(pos)), member); \ | 267 | tbl, hash, member) |
206 | pos; \ | ||
207 | pos = rht_entry_safe(rcu_dereference_raw((pos)->member.next), \ | ||
208 | typeof(*(pos)), member)) | ||
209 | 268 | ||
210 | #endif /* _LINUX_RHASHTABLE_H */ | 269 | #endif /* _LINUX_RHASHTABLE_H */ |