diff options
| author | Thomas Graf <tgraf@suug.ch> | 2015-01-02 17:00:16 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2015-01-03 14:32:56 -0500 |
| commit | 88d6ed15acff1cb44b1d1f3c0a393b7f7744957a (patch) | |
| tree | ee25a48f8ab11d06c062480c89ba1e96c8113e57 /include/linux | |
| parent | a4b18cda4c2676a4b4b59622b2e0394dc153e00b (diff) | |
rhashtable: Convert bucket iterators to take table and index
This patch is in preparation to introduce per bucket spinlocks. It
extends all iterator macros to take the bucket table and bucket
index. It also introduces a new rht_dereference_bucket() to
handle protected accesses to buckets.
It introduces a barrier() to the RCU iterators to the prevent
the compiler from caching the first element.
The lockdep verifier is introduced as stub which always succeeds
and properly implement in the next patch when the locks are
introduced.
Signed-off-by: Thomas Graf <tgraf@suug.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/linux')
| -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 */ |
