diff options
Diffstat (limited to 'net/netlabel/netlabel_domainhash.c')
-rw-r--r-- | net/netlabel/netlabel_domainhash.c | 28 |
1 files changed, 18 insertions, 10 deletions
diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c index 0bfeaab88ef5..06ab41b6b57a 100644 --- a/net/netlabel/netlabel_domainhash.c +++ b/net/netlabel/netlabel_domainhash.c | |||
@@ -50,9 +50,12 @@ struct netlbl_domhsh_tbl { | |||
50 | }; | 50 | }; |
51 | 51 | ||
52 | /* Domain hash table */ | 52 | /* Domain hash table */ |
53 | /* XXX - updates should be so rare that having one spinlock for the entire | 53 | /* updates should be so rare that having one spinlock for the entire hash table |
54 | * hash table should be okay */ | 54 | * should be okay */ |
55 | static DEFINE_SPINLOCK(netlbl_domhsh_lock); | 55 | static DEFINE_SPINLOCK(netlbl_domhsh_lock); |
56 | #define netlbl_domhsh_rcu_deref(p) \ | ||
57 | rcu_dereference_check(p, rcu_read_lock_held() || \ | ||
58 | lockdep_is_held(&netlbl_domhsh_lock)) | ||
56 | static struct netlbl_domhsh_tbl *netlbl_domhsh = NULL; | 59 | static struct netlbl_domhsh_tbl *netlbl_domhsh = NULL; |
57 | static struct netlbl_dom_map *netlbl_domhsh_def = NULL; | 60 | static struct netlbl_dom_map *netlbl_domhsh_def = NULL; |
58 | 61 | ||
@@ -106,7 +109,8 @@ static void netlbl_domhsh_free_entry(struct rcu_head *entry) | |||
106 | * Description: | 109 | * Description: |
107 | * This is the hashing function for the domain hash table, it returns the | 110 | * This is the hashing function for the domain hash table, it returns the |
108 | * correct bucket number for the domain. The caller is responsibile for | 111 | * correct bucket number for the domain. The caller is responsibile for |
109 | * calling the rcu_read_[un]lock() functions. | 112 | * ensuring that the hash table is protected with either a RCU read lock or the |
113 | * hash table lock. | ||
110 | * | 114 | * |
111 | */ | 115 | */ |
112 | static u32 netlbl_domhsh_hash(const char *key) | 116 | static u32 netlbl_domhsh_hash(const char *key) |
@@ -120,7 +124,7 @@ static u32 netlbl_domhsh_hash(const char *key) | |||
120 | 124 | ||
121 | for (iter = 0, val = 0, len = strlen(key); iter < len; iter++) | 125 | for (iter = 0, val = 0, len = strlen(key); iter < len; iter++) |
122 | val = (val << 4 | (val >> (8 * sizeof(u32) - 4))) ^ key[iter]; | 126 | val = (val << 4 | (val >> (8 * sizeof(u32) - 4))) ^ key[iter]; |
123 | return val & (rcu_dereference(netlbl_domhsh)->size - 1); | 127 | return val & (netlbl_domhsh_rcu_deref(netlbl_domhsh)->size - 1); |
124 | } | 128 | } |
125 | 129 | ||
126 | /** | 130 | /** |
@@ -130,7 +134,8 @@ static u32 netlbl_domhsh_hash(const char *key) | |||
130 | * Description: | 134 | * Description: |
131 | * Searches the domain hash table and returns a pointer to the hash table | 135 | * Searches the domain hash table and returns a pointer to the hash table |
132 | * entry if found, otherwise NULL is returned. The caller is responsibile for | 136 | * entry if found, otherwise NULL is returned. The caller is responsibile for |
133 | * the rcu hash table locks (i.e. the caller much call rcu_read_[un]lock()). | 137 | * ensuring that the hash table is protected with either a RCU read lock or the |
138 | * hash table lock. | ||
134 | * | 139 | * |
135 | */ | 140 | */ |
136 | static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain) | 141 | static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain) |
@@ -141,7 +146,7 @@ static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain) | |||
141 | 146 | ||
142 | if (domain != NULL) { | 147 | if (domain != NULL) { |
143 | bkt = netlbl_domhsh_hash(domain); | 148 | bkt = netlbl_domhsh_hash(domain); |
144 | bkt_list = &rcu_dereference(netlbl_domhsh)->tbl[bkt]; | 149 | bkt_list = &netlbl_domhsh_rcu_deref(netlbl_domhsh)->tbl[bkt]; |
145 | list_for_each_entry_rcu(iter, bkt_list, list) | 150 | list_for_each_entry_rcu(iter, bkt_list, list) |
146 | if (iter->valid && strcmp(iter->domain, domain) == 0) | 151 | if (iter->valid && strcmp(iter->domain, domain) == 0) |
147 | return iter; | 152 | return iter; |
@@ -159,8 +164,8 @@ static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain) | |||
159 | * Searches the domain hash table and returns a pointer to the hash table | 164 | * Searches the domain hash table and returns a pointer to the hash table |
160 | * entry if an exact match is found, if an exact match is not present in the | 165 | * entry if an exact match is found, if an exact match is not present in the |
161 | * hash table then the default entry is returned if valid otherwise NULL is | 166 | * hash table then the default entry is returned if valid otherwise NULL is |
162 | * returned. The caller is responsibile for the rcu hash table locks | 167 | * returned. The caller is responsibile ensuring that the hash table is |
163 | * (i.e. the caller much call rcu_read_[un]lock()). | 168 | * protected with either a RCU read lock or the hash table lock. |
164 | * | 169 | * |
165 | */ | 170 | */ |
166 | static struct netlbl_dom_map *netlbl_domhsh_search_def(const char *domain) | 171 | static struct netlbl_dom_map *netlbl_domhsh_search_def(const char *domain) |
@@ -169,7 +174,7 @@ static struct netlbl_dom_map *netlbl_domhsh_search_def(const char *domain) | |||
169 | 174 | ||
170 | entry = netlbl_domhsh_search(domain); | 175 | entry = netlbl_domhsh_search(domain); |
171 | if (entry == NULL) { | 176 | if (entry == NULL) { |
172 | entry = rcu_dereference(netlbl_domhsh_def); | 177 | entry = netlbl_domhsh_rcu_deref(netlbl_domhsh_def); |
173 | if (entry != NULL && !entry->valid) | 178 | if (entry != NULL && !entry->valid) |
174 | entry = NULL; | 179 | entry = NULL; |
175 | } | 180 | } |
@@ -306,8 +311,11 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry, | |||
306 | struct netlbl_af6list *tmp6; | 311 | struct netlbl_af6list *tmp6; |
307 | #endif /* IPv6 */ | 312 | #endif /* IPv6 */ |
308 | 313 | ||
314 | /* XXX - we can remove this RCU read lock as the spinlock protects the | ||
315 | * entire function, but before we do we need to fixup the | ||
316 | * netlbl_af[4,6]list RCU functions to do "the right thing" with | ||
317 | * respect to rcu_dereference() when only a spinlock is held. */ | ||
309 | rcu_read_lock(); | 318 | rcu_read_lock(); |
310 | |||
311 | spin_lock(&netlbl_domhsh_lock); | 319 | spin_lock(&netlbl_domhsh_lock); |
312 | if (entry->domain != NULL) | 320 | if (entry->domain != NULL) |
313 | entry_old = netlbl_domhsh_search(entry->domain); | 321 | entry_old = netlbl_domhsh_search(entry->domain); |