aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/svcauth.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sunrpc/svcauth.c')
-rw-r--r--net/sunrpc/svcauth.c122
1 files changed, 33 insertions, 89 deletions
diff --git a/net/sunrpc/svcauth.c b/net/sunrpc/svcauth.c
index dda4f0c63511..5b28c6176806 100644
--- a/net/sunrpc/svcauth.c
+++ b/net/sunrpc/svcauth.c
@@ -106,112 +106,56 @@ svc_auth_unregister(rpc_authflavor_t flavor)
106EXPORT_SYMBOL(svc_auth_unregister); 106EXPORT_SYMBOL(svc_auth_unregister);
107 107
108/************************************************** 108/**************************************************
109 * cache for domain name to auth_domain 109 * 'auth_domains' are stored in a hash table indexed by name.
110 * Entries are only added by flavours which will normally 110 * When the last reference to an 'auth_domain' is dropped,
111 * have a structure that 'inherits' from auth_domain. 111 * the object is unhashed and freed.
112 * e.g. when an IP -> domainname is given to auth_unix, 112 * If auth_domain_lookup fails to find an entry, it will return
113 * and the domain name doesn't exist, it will create a 113 * it's second argument 'new'. If this is non-null, it will
114 * auth_unix_domain and add it to this hash table. 114 * have been atomically linked into the table.
115 * If it finds the name does exist, but isn't AUTH_UNIX,
116 * it will complain.
117 */ 115 */
118 116
119/*
120 * Auth auth_domain cache is somewhat different to other caches,
121 * largely because the entries are possibly of different types:
122 * each auth flavour has it's own type.
123 * One consequence of this that DefineCacheLookup cannot
124 * allocate a new structure as it cannot know the size.
125 * Notice that the "INIT" code fragment is quite different
126 * from other caches. When auth_domain_lookup might be
127 * creating a new domain, the new domain is passed in
128 * complete and it is used as-is rather than being copied into
129 * another structure.
130 */
131#define DN_HASHBITS 6 117#define DN_HASHBITS 6
132#define DN_HASHMAX (1<<DN_HASHBITS) 118#define DN_HASHMAX (1<<DN_HASHBITS)
133#define DN_HASHMASK (DN_HASHMAX-1) 119#define DN_HASHMASK (DN_HASHMAX-1)
134 120
135static struct cache_head *auth_domain_table[DN_HASHMAX]; 121static struct hlist_head auth_domain_table[DN_HASHMAX];
136 122static spinlock_t auth_domain_lock = SPIN_LOCK_UNLOCKED;
137static void auth_domain_drop(struct cache_head *item, struct cache_detail *cd)
138{
139 struct auth_domain *dom = container_of(item, struct auth_domain, h);
140 if (cache_put(item,cd))
141 authtab[dom->flavour]->domain_release(dom);
142}
143
144
145struct cache_detail auth_domain_cache = {
146 .owner = THIS_MODULE,
147 .hash_size = DN_HASHMAX,
148 .hash_table = auth_domain_table,
149 .name = "auth.domain",
150 .cache_put = auth_domain_drop,
151};
152 123
153void auth_domain_put(struct auth_domain *dom) 124void auth_domain_put(struct auth_domain *dom)
154{ 125{
155 auth_domain_drop(&dom->h, &auth_domain_cache); 126 if (atomic_dec_and_lock(&dom->ref.refcount, &auth_domain_lock)) {
156} 127 hlist_del(&dom->hash);
157 128 dom->flavour->domain_release(dom);
158static inline int auth_domain_hash(struct auth_domain *item) 129 }
159{
160 return hash_str(item->name, DN_HASHBITS);
161}
162static inline int auth_domain_match(struct auth_domain *tmp, struct auth_domain *item)
163{
164 return strcmp(tmp->name, item->name) == 0;
165} 130}
166 131
167struct auth_domain * 132struct auth_domain *
168auth_domain_lookup(struct auth_domain *item, int set) 133auth_domain_lookup(char *name, struct auth_domain *new)
169{ 134{
170 struct auth_domain *tmp = NULL; 135 struct auth_domain *hp;
171 struct cache_head **hp, **head; 136 struct hlist_head *head;
172 head = &auth_domain_cache.hash_table[auth_domain_hash(item)]; 137 struct hlist_node *np;
173 138
174 if (set) 139 head = &auth_domain_table[hash_str(name, DN_HASHBITS)];
175 write_lock(&auth_domain_cache.hash_lock); 140
176 else 141 spin_lock(&auth_domain_lock);
177 read_lock(&auth_domain_cache.hash_lock); 142
178 for (hp=head; *hp != NULL; hp = &tmp->h.next) { 143 hlist_for_each_entry(hp, np, head, hash) {
179 tmp = container_of(*hp, struct auth_domain, h); 144 if (strcmp(hp->name, name)==0) {
180 if (!auth_domain_match(tmp, item)) 145 kref_get(&hp->ref);
181 continue; 146 spin_unlock(&auth_domain_lock);
182 if (!set) { 147 return hp;
183 cache_get(&tmp->h);
184 goto out_noset;
185 } 148 }
186 *hp = tmp->h.next;
187 tmp->h.next = NULL;
188 auth_domain_drop(&tmp->h, &auth_domain_cache);
189 goto out_set;
190 } 149 }
191 /* Didn't find anything */ 150 if (new) {
192 if (!set) 151 hlist_add_head(&new->hash, head);
193 goto out_nada; 152 kref_get(&new->ref);
194 auth_domain_cache.entries++; 153 }
195out_set: 154 spin_unlock(&auth_domain_lock);
196 item->h.next = *head; 155 return new;
197 *head = &item->h;
198 cache_get(&item->h);
199 write_unlock(&auth_domain_cache.hash_lock);
200 cache_fresh(&auth_domain_cache, &item->h, item->h.expiry_time);
201 cache_get(&item->h);
202 return item;
203out_nada:
204 tmp = NULL;
205out_noset:
206 read_unlock(&auth_domain_cache.hash_lock);
207 return tmp;
208} 156}
209 157
210struct auth_domain *auth_domain_find(char *name) 158struct auth_domain *auth_domain_find(char *name)
211{ 159{
212 struct auth_domain *rv, ad; 160 return auth_domain_lookup(name, NULL);
213
214 ad.name = name;
215 rv = auth_domain_lookup(&ad, 0);
216 return rv;
217} 161}