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