aboutsummaryrefslogtreecommitdiffstats
path: root/net/netlabel/netlabel_domainhash.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/netlabel/netlabel_domainhash.c')
-rw-r--r--net/netlabel/netlabel_domainhash.c28
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 */
55static DEFINE_SPINLOCK(netlbl_domhsh_lock); 55static 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))
56static struct netlbl_domhsh_tbl *netlbl_domhsh = NULL; 59static struct netlbl_domhsh_tbl *netlbl_domhsh = NULL;
57static struct netlbl_dom_map *netlbl_domhsh_def = NULL; 60static 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 */
112static u32 netlbl_domhsh_hash(const char *key) 116static 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 */
136static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain) 141static 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 */
166static struct netlbl_dom_map *netlbl_domhsh_search_def(const char *domain) 171static 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);