diff options
author | NeilBrown <neilb@suse.de> | 2006-03-27 04:14:59 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-03-27 11:44:41 -0500 |
commit | efc36aa5608f5717338747e152c23f2cfdb14697 (patch) | |
tree | ab444f6e6c88ed07a8d5a034777c10de50e663fd /net | |
parent | 3e7b19198003fc25b11838e709f17d4fa173b2d7 (diff) |
[PATCH] knfsd: Change the store of auth_domains to not be a 'cache'
The 'auth_domain's are simply handles on internal data structures. They do
not cache information from user-space, and forcing them into the mold of a
'cache' misrepresents their true nature and causes confusion.
Signed-off-by: Neil Brown <neilb@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'net')
-rw-r--r-- | net/sunrpc/auth_gss/svcauth_gss.c | 14 | ||||
-rw-r--r-- | net/sunrpc/sunrpc_syms.c | 4 | ||||
-rw-r--r-- | net/sunrpc/svcauth.c | 122 | ||||
-rw-r--r-- | net/sunrpc/svcauth_unix.c | 69 |
4 files changed, 72 insertions, 137 deletions
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 23632d84d8d7..6b073c2e6930 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c | |||
@@ -645,6 +645,8 @@ find_gss_auth_domain(struct gss_ctx *ctx, u32 svc) | |||
645 | return auth_domain_find(name); | 645 | return auth_domain_find(name); |
646 | } | 646 | } |
647 | 647 | ||
648 | static struct auth_ops svcauthops_gss; | ||
649 | |||
648 | int | 650 | int |
649 | svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name) | 651 | svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name) |
650 | { | 652 | { |
@@ -655,20 +657,18 @@ svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name) | |||
655 | new = kmalloc(sizeof(*new), GFP_KERNEL); | 657 | new = kmalloc(sizeof(*new), GFP_KERNEL); |
656 | if (!new) | 658 | if (!new) |
657 | goto out; | 659 | goto out; |
658 | cache_init(&new->h.h); | 660 | kref_init(&new->h.ref); |
659 | new->h.name = kmalloc(strlen(name) + 1, GFP_KERNEL); | 661 | new->h.name = kmalloc(strlen(name) + 1, GFP_KERNEL); |
660 | if (!new->h.name) | 662 | if (!new->h.name) |
661 | goto out_free_dom; | 663 | goto out_free_dom; |
662 | strcpy(new->h.name, name); | 664 | strcpy(new->h.name, name); |
663 | new->h.flavour = RPC_AUTH_GSS; | 665 | new->h.flavour = &svcauthops_gss; |
664 | new->pseudoflavor = pseudoflavor; | 666 | new->pseudoflavor = pseudoflavor; |
665 | new->h.h.expiry_time = NEVER; | ||
666 | 667 | ||
667 | test = auth_domain_lookup(&new->h, 1); | 668 | test = auth_domain_lookup(name, &new->h); |
668 | if (test == &new->h) { | 669 | if (test != &new->h) { /* XXX Duplicate registration? */ |
669 | BUG_ON(atomic_dec_and_test(&new->h.h.refcnt)); | ||
670 | } else { /* XXX Duplicate registration? */ | ||
671 | auth_domain_put(&new->h); | 670 | auth_domain_put(&new->h); |
671 | /* dangling ref-count... */ | ||
672 | goto out; | 672 | goto out; |
673 | } | 673 | } |
674 | return 0; | 674 | return 0; |
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c index 9f7373203592..40401196e7de 100644 --- a/net/sunrpc/sunrpc_syms.c +++ b/net/sunrpc/sunrpc_syms.c | |||
@@ -142,6 +142,7 @@ EXPORT_SYMBOL(nlm_debug); | |||
142 | 142 | ||
143 | extern int register_rpc_pipefs(void); | 143 | extern int register_rpc_pipefs(void); |
144 | extern void unregister_rpc_pipefs(void); | 144 | extern void unregister_rpc_pipefs(void); |
145 | extern struct cache_detail ip_map_cache; | ||
145 | 146 | ||
146 | static int __init | 147 | static int __init |
147 | init_sunrpc(void) | 148 | init_sunrpc(void) |
@@ -158,7 +159,6 @@ init_sunrpc(void) | |||
158 | #ifdef CONFIG_PROC_FS | 159 | #ifdef CONFIG_PROC_FS |
159 | rpc_proc_init(); | 160 | rpc_proc_init(); |
160 | #endif | 161 | #endif |
161 | cache_register(&auth_domain_cache); | ||
162 | cache_register(&ip_map_cache); | 162 | cache_register(&ip_map_cache); |
163 | out: | 163 | out: |
164 | return err; | 164 | return err; |
@@ -169,8 +169,6 @@ cleanup_sunrpc(void) | |||
169 | { | 169 | { |
170 | unregister_rpc_pipefs(); | 170 | unregister_rpc_pipefs(); |
171 | rpc_destroy_mempool(); | 171 | rpc_destroy_mempool(); |
172 | if (cache_unregister(&auth_domain_cache)) | ||
173 | printk(KERN_ERR "sunrpc: failed to unregister auth_domain cache\n"); | ||
174 | if (cache_unregister(&ip_map_cache)) | 172 | if (cache_unregister(&ip_map_cache)) |
175 | printk(KERN_ERR "sunrpc: failed to unregister ip_map cache\n"); | 173 | printk(KERN_ERR "sunrpc: failed to unregister ip_map cache\n"); |
176 | #ifdef RPC_DEBUG | 174 | #ifdef RPC_DEBUG |
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) | |||
106 | EXPORT_SYMBOL(svc_auth_unregister); | 106 | EXPORT_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 | ||
135 | static struct cache_head *auth_domain_table[DN_HASHMAX]; | 121 | static struct hlist_head auth_domain_table[DN_HASHMAX]; |
136 | 122 | static spinlock_t auth_domain_lock = SPIN_LOCK_UNLOCKED; | |
137 | static 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 | |||
145 | struct 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 | ||
153 | void auth_domain_put(struct auth_domain *dom) | 124 | void 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); | |
158 | static inline int auth_domain_hash(struct auth_domain *item) | 129 | } |
159 | { | ||
160 | return hash_str(item->name, DN_HASHBITS); | ||
161 | } | ||
162 | static 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 | ||
167 | struct auth_domain * | 132 | struct auth_domain * |
168 | auth_domain_lookup(struct auth_domain *item, int set) | 133 | auth_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 | } |
195 | out_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; | ||
203 | out_nada: | ||
204 | tmp = NULL; | ||
205 | out_noset: | ||
206 | read_unlock(&auth_domain_cache.hash_lock); | ||
207 | return tmp; | ||
208 | } | 156 | } |
209 | 157 | ||
210 | struct auth_domain *auth_domain_find(char *name) | 158 | struct 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 | } |
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index 3e6c694bbad1..17e8b2a3130c 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c | |||
@@ -27,41 +27,35 @@ struct unix_domain { | |||
27 | /* other stuff later */ | 27 | /* other stuff later */ |
28 | }; | 28 | }; |
29 | 29 | ||
30 | extern struct auth_ops svcauth_unix; | ||
31 | |||
30 | struct auth_domain *unix_domain_find(char *name) | 32 | struct auth_domain *unix_domain_find(char *name) |
31 | { | 33 | { |
32 | struct auth_domain *rv, ud; | 34 | struct auth_domain *rv; |
33 | struct unix_domain *new; | 35 | struct unix_domain *new = NULL; |
34 | 36 | ||
35 | ud.name = name; | 37 | rv = auth_domain_lookup(name, NULL); |
36 | 38 | while(1) { | |
37 | rv = auth_domain_lookup(&ud, 0); | 39 | if (rv != &new->h) { |
38 | 40 | if (new) auth_domain_put(&new->h); | |
39 | foundit: | 41 | return rv; |
40 | if (rv && rv->flavour != RPC_AUTH_UNIX) { | 42 | } |
41 | auth_domain_put(rv); | 43 | if (rv && rv->flavour != &svcauth_unix) { |
42 | return NULL; | 44 | auth_domain_put(rv); |
43 | } | 45 | return NULL; |
44 | if (rv) | 46 | } |
45 | return rv; | 47 | if (rv) |
46 | 48 | return rv; | |
47 | new = kmalloc(sizeof(*new), GFP_KERNEL); | 49 | |
48 | if (new == NULL) | 50 | new = kmalloc(sizeof(*new), GFP_KERNEL); |
49 | return NULL; | 51 | if (new == NULL) |
50 | cache_init(&new->h.h); | 52 | return NULL; |
51 | new->h.name = kstrdup(name, GFP_KERNEL); | 53 | kref_init(&new->h.ref); |
52 | new->h.flavour = RPC_AUTH_UNIX; | 54 | new->h.name = kstrdup(name, GFP_KERNEL); |
53 | new->addr_changes = 0; | 55 | new->h.flavour = &svcauth_unix; |
54 | new->h.h.expiry_time = NEVER; | 56 | new->addr_changes = 0; |
55 | 57 | rv = auth_domain_lookup(name, &new->h); | |
56 | rv = auth_domain_lookup(&new->h, 2); | ||
57 | if (rv == &new->h) { | ||
58 | if (atomic_dec_and_test(&new->h.h.refcnt)) BUG(); | ||
59 | } else { | ||
60 | auth_domain_put(&new->h); | ||
61 | goto foundit; | ||
62 | } | 58 | } |
63 | |||
64 | return rv; | ||
65 | } | 59 | } |
66 | 60 | ||
67 | static void svcauth_unix_domain_release(struct auth_domain *dom) | 61 | static void svcauth_unix_domain_release(struct auth_domain *dom) |
@@ -130,7 +124,7 @@ static inline void ip_map_init(struct ip_map *new, struct ip_map *item) | |||
130 | } | 124 | } |
131 | static inline void ip_map_update(struct ip_map *new, struct ip_map *item) | 125 | static inline void ip_map_update(struct ip_map *new, struct ip_map *item) |
132 | { | 126 | { |
133 | cache_get(&item->m_client->h.h); | 127 | kref_get(&item->m_client->h.ref); |
134 | new->m_client = item->m_client; | 128 | new->m_client = item->m_client; |
135 | new->m_add_change = item->m_add_change; | 129 | new->m_add_change = item->m_add_change; |
136 | } | 130 | } |
@@ -272,7 +266,7 @@ int auth_unix_add_addr(struct in_addr addr, struct auth_domain *dom) | |||
272 | struct unix_domain *udom; | 266 | struct unix_domain *udom; |
273 | struct ip_map ip, *ipmp; | 267 | struct ip_map ip, *ipmp; |
274 | 268 | ||
275 | if (dom->flavour != RPC_AUTH_UNIX) | 269 | if (dom->flavour != &svcauth_unix) |
276 | return -EINVAL; | 270 | return -EINVAL; |
277 | udom = container_of(dom, struct unix_domain, h); | 271 | udom = container_of(dom, struct unix_domain, h); |
278 | strcpy(ip.m_class, "nfsd"); | 272 | strcpy(ip.m_class, "nfsd"); |
@@ -295,7 +289,7 @@ int auth_unix_forget_old(struct auth_domain *dom) | |||
295 | { | 289 | { |
296 | struct unix_domain *udom; | 290 | struct unix_domain *udom; |
297 | 291 | ||
298 | if (dom->flavour != RPC_AUTH_UNIX) | 292 | if (dom->flavour != &svcauth_unix) |
299 | return -EINVAL; | 293 | return -EINVAL; |
300 | udom = container_of(dom, struct unix_domain, h); | 294 | udom = container_of(dom, struct unix_domain, h); |
301 | udom->addr_changes++; | 295 | udom->addr_changes++; |
@@ -323,7 +317,7 @@ struct auth_domain *auth_unix_lookup(struct in_addr addr) | |||
323 | rv = NULL; | 317 | rv = NULL; |
324 | } else { | 318 | } else { |
325 | rv = &ipm->m_client->h; | 319 | rv = &ipm->m_client->h; |
326 | cache_get(&rv->h); | 320 | kref_get(&rv->ref); |
327 | } | 321 | } |
328 | ip_map_put(&ipm->h, &ip_map_cache); | 322 | ip_map_put(&ipm->h, &ip_map_cache); |
329 | return rv; | 323 | return rv; |
@@ -332,7 +326,6 @@ struct auth_domain *auth_unix_lookup(struct in_addr addr) | |||
332 | void svcauth_unix_purge(void) | 326 | void svcauth_unix_purge(void) |
333 | { | 327 | { |
334 | cache_purge(&ip_map_cache); | 328 | cache_purge(&ip_map_cache); |
335 | cache_purge(&auth_domain_cache); | ||
336 | } | 329 | } |
337 | 330 | ||
338 | static int | 331 | static int |
@@ -361,7 +354,7 @@ svcauth_unix_set_client(struct svc_rqst *rqstp) | |||
361 | return SVC_DENIED; | 354 | return SVC_DENIED; |
362 | case 0: | 355 | case 0: |
363 | rqstp->rq_client = &ipm->m_client->h; | 356 | rqstp->rq_client = &ipm->m_client->h; |
364 | cache_get(&rqstp->rq_client->h); | 357 | kref_get(&rqstp->rq_client->ref); |
365 | ip_map_put(&ipm->h, &ip_map_cache); | 358 | ip_map_put(&ipm->h, &ip_map_cache); |
366 | break; | 359 | break; |
367 | } | 360 | } |