diff options
author | David S. Miller <davem@davemloft.net> | 2010-09-09 02:49:04 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-09-09 02:49:04 -0400 |
commit | e199e6136ce6b151e6638ae93dca60748424d900 (patch) | |
tree | 0d66e0b5d227c36b005e4f5537f4bbcfc6ed4904 /net | |
parent | 972c40b5bee429c84ba727f8ac0a08292bc5dc3d (diff) | |
parent | d56557af19867edb8c0e96f8e26399698a08857f (diff) |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'net')
-rw-r--r-- | net/Kconfig | 1 | ||||
-rw-r--r-- | net/Makefile | 1 | ||||
-rw-r--r-- | net/dns_resolver/Kconfig | 27 | ||||
-rw-r--r-- | net/dns_resolver/Makefile | 7 | ||||
-rw-r--r-- | net/dns_resolver/dns_key.c | 293 | ||||
-rw-r--r-- | net/dns_resolver/dns_query.c | 165 | ||||
-rw-r--r-- | net/dns_resolver/internal.h | 44 | ||||
-rw-r--r-- | net/mac80211/rate.c | 2 | ||||
-rw-r--r-- | net/rxrpc/ar-internal.h | 16 | ||||
-rw-r--r-- | net/sunrpc/Kconfig | 9 | ||||
-rw-r--r-- | net/sunrpc/auth.c | 162 | ||||
-rw-r--r-- | net/sunrpc/auth_generic.c | 23 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/auth_gss.c | 29 | ||||
-rw-r--r-- | net/sunrpc/auth_null.c | 2 | ||||
-rw-r--r-- | net/sunrpc/auth_unix.c | 21 | ||||
-rw-r--r-- | net/sunrpc/cache.c | 8 | ||||
-rw-r--r-- | net/sunrpc/clnt.c | 182 | ||||
-rw-r--r-- | net/sunrpc/sched.c | 104 | ||||
-rw-r--r-- | net/sunrpc/sunrpc_syms.c | 16 | ||||
-rw-r--r-- | net/sunrpc/xprt.c | 3 | ||||
-rw-r--r-- | net/sunrpc/xprtrdma/rpc_rdma.c | 2 | ||||
-rw-r--r-- | net/sunrpc/xprtrdma/verbs.c | 22 | ||||
-rw-r--r-- | net/sunrpc/xprtsock.c | 54 |
23 files changed, 919 insertions, 274 deletions
diff --git a/net/Kconfig b/net/Kconfig index e24fa0873f32..e330594d3709 100644 --- a/net/Kconfig +++ b/net/Kconfig | |||
@@ -213,6 +213,7 @@ source "net/phonet/Kconfig" | |||
213 | source "net/ieee802154/Kconfig" | 213 | source "net/ieee802154/Kconfig" |
214 | source "net/sched/Kconfig" | 214 | source "net/sched/Kconfig" |
215 | source "net/dcb/Kconfig" | 215 | source "net/dcb/Kconfig" |
216 | source "net/dns_resolver/Kconfig" | ||
216 | 217 | ||
217 | config RPS | 218 | config RPS |
218 | boolean | 219 | boolean |
diff --git a/net/Makefile b/net/Makefile index 41d420070a38..ea60fbce9b1b 100644 --- a/net/Makefile +++ b/net/Makefile | |||
@@ -67,3 +67,4 @@ ifeq ($(CONFIG_NET),y) | |||
67 | obj-$(CONFIG_SYSCTL) += sysctl_net.o | 67 | obj-$(CONFIG_SYSCTL) += sysctl_net.o |
68 | endif | 68 | endif |
69 | obj-$(CONFIG_WIMAX) += wimax/ | 69 | obj-$(CONFIG_WIMAX) += wimax/ |
70 | obj-$(CONFIG_DNS_RESOLVER) += dns_resolver/ | ||
diff --git a/net/dns_resolver/Kconfig b/net/dns_resolver/Kconfig new file mode 100644 index 000000000000..50d49f7e0472 --- /dev/null +++ b/net/dns_resolver/Kconfig | |||
@@ -0,0 +1,27 @@ | |||
1 | # | ||
2 | # Configuration for DNS Resolver | ||
3 | # | ||
4 | config DNS_RESOLVER | ||
5 | tristate "DNS Resolver support" | ||
6 | depends on NET && KEYS | ||
7 | help | ||
8 | Saying Y here will include support for the DNS Resolver key type | ||
9 | which can be used to make upcalls to perform DNS lookups in | ||
10 | userspace. | ||
11 | |||
12 | DNS Resolver is used to query DNS server for information. Examples | ||
13 | being resolving a UNC hostname element to an IP address for CIFS or | ||
14 | performing a DNS query for AFSDB records so that AFS can locate a | ||
15 | cell's volume location database servers. | ||
16 | |||
17 | DNS Resolver is used by the CIFS and AFS modules, and would support | ||
18 | SMB2 later. DNS Resolver is supported by the userspace upcall | ||
19 | helper "/sbin/dns.resolver" via /etc/request-key.conf. | ||
20 | |||
21 | See <file:Documentation/networking/dns_resolver.txt> for further | ||
22 | information. | ||
23 | |||
24 | To compile this as a module, choose M here: the module will be called | ||
25 | dnsresolver. | ||
26 | |||
27 | If unsure, say N. | ||
diff --git a/net/dns_resolver/Makefile b/net/dns_resolver/Makefile new file mode 100644 index 000000000000..c0ef4e71dc49 --- /dev/null +++ b/net/dns_resolver/Makefile | |||
@@ -0,0 +1,7 @@ | |||
1 | # | ||
2 | # Makefile for the Linux DNS Resolver. | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_DNS_RESOLVER) += dns_resolver.o | ||
6 | |||
7 | dns_resolver-objs := dns_key.o dns_query.o | ||
diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c new file mode 100644 index 000000000000..739435a6af39 --- /dev/null +++ b/net/dns_resolver/dns_key.c | |||
@@ -0,0 +1,293 @@ | |||
1 | /* Key type used to cache DNS lookups made by the kernel | ||
2 | * | ||
3 | * See Documentation/networking/dns_resolver.txt | ||
4 | * | ||
5 | * Copyright (c) 2007 Igor Mammedov | ||
6 | * Author(s): Igor Mammedov (niallain@gmail.com) | ||
7 | * Steve French (sfrench@us.ibm.com) | ||
8 | * Wang Lei (wang840925@gmail.com) | ||
9 | * David Howells (dhowells@redhat.com) | ||
10 | * | ||
11 | * This library is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU Lesser General Public License as published | ||
13 | * by the Free Software Foundation; either version 2.1 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This library is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See | ||
19 | * the GNU Lesser General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU Lesser General Public License | ||
22 | * along with this library; if not, write to the Free Software | ||
23 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
24 | */ | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/moduleparam.h> | ||
27 | #include <linux/slab.h> | ||
28 | #include <linux/string.h> | ||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/keyctl.h> | ||
31 | #include <linux/err.h> | ||
32 | #include <linux/seq_file.h> | ||
33 | #include <keys/dns_resolver-type.h> | ||
34 | #include <keys/user-type.h> | ||
35 | #include "internal.h" | ||
36 | |||
37 | MODULE_DESCRIPTION("DNS Resolver"); | ||
38 | MODULE_AUTHOR("Wang Lei"); | ||
39 | MODULE_LICENSE("GPL"); | ||
40 | |||
41 | unsigned dns_resolver_debug; | ||
42 | module_param_named(debug, dns_resolver_debug, uint, S_IWUSR | S_IRUGO); | ||
43 | MODULE_PARM_DESC(debug, "DNS Resolver debugging mask"); | ||
44 | |||
45 | const struct cred *dns_resolver_cache; | ||
46 | |||
47 | #define DNS_ERRORNO_OPTION "dnserror" | ||
48 | |||
49 | /* | ||
50 | * Instantiate a user defined key for dns_resolver. | ||
51 | * | ||
52 | * The data must be a NUL-terminated string, with the NUL char accounted in | ||
53 | * datalen. | ||
54 | * | ||
55 | * If the data contains a '#' characters, then we take the clause after each | ||
56 | * one to be an option of the form 'key=value'. The actual data of interest is | ||
57 | * the string leading up to the first '#'. For instance: | ||
58 | * | ||
59 | * "ip1,ip2,...#foo=bar" | ||
60 | */ | ||
61 | static int | ||
62 | dns_resolver_instantiate(struct key *key, const void *_data, size_t datalen) | ||
63 | { | ||
64 | struct user_key_payload *upayload; | ||
65 | unsigned long derrno; | ||
66 | int ret; | ||
67 | size_t result_len = 0; | ||
68 | const char *data = _data, *end, *opt; | ||
69 | |||
70 | kenter("%%%d,%s,'%s',%zu", | ||
71 | key->serial, key->description, data, datalen); | ||
72 | |||
73 | if (datalen <= 1 || !data || data[datalen - 1] != '\0') | ||
74 | return -EINVAL; | ||
75 | datalen--; | ||
76 | |||
77 | /* deal with any options embedded in the data */ | ||
78 | end = data + datalen; | ||
79 | opt = memchr(data, '#', datalen); | ||
80 | if (!opt) { | ||
81 | /* no options: the entire data is the result */ | ||
82 | kdebug("no options"); | ||
83 | result_len = datalen; | ||
84 | } else { | ||
85 | const char *next_opt; | ||
86 | |||
87 | result_len = opt - data; | ||
88 | opt++; | ||
89 | kdebug("options: '%s'", opt); | ||
90 | do { | ||
91 | const char *eq; | ||
92 | int opt_len, opt_nlen, opt_vlen, tmp; | ||
93 | |||
94 | next_opt = memchr(opt, '#', end - opt) ?: end; | ||
95 | opt_len = next_opt - opt; | ||
96 | if (!opt_len) { | ||
97 | printk(KERN_WARNING | ||
98 | "Empty option to dns_resolver key %d\n", | ||
99 | key->serial); | ||
100 | return -EINVAL; | ||
101 | } | ||
102 | |||
103 | eq = memchr(opt, '=', opt_len) ?: end; | ||
104 | opt_nlen = eq - opt; | ||
105 | eq++; | ||
106 | opt_vlen = next_opt - eq; /* will be -1 if no value */ | ||
107 | |||
108 | tmp = opt_vlen >= 0 ? opt_vlen : 0; | ||
109 | kdebug("option '%*.*s' val '%*.*s'", | ||
110 | opt_nlen, opt_nlen, opt, tmp, tmp, eq); | ||
111 | |||
112 | /* see if it's an error number representing a DNS error | ||
113 | * that's to be recorded as the result in this key */ | ||
114 | if (opt_nlen == sizeof(DNS_ERRORNO_OPTION) - 1 && | ||
115 | memcmp(opt, DNS_ERRORNO_OPTION, opt_nlen) == 0) { | ||
116 | kdebug("dns error number option"); | ||
117 | if (opt_vlen <= 0) | ||
118 | goto bad_option_value; | ||
119 | |||
120 | ret = strict_strtoul(eq, 10, &derrno); | ||
121 | if (ret < 0) | ||
122 | goto bad_option_value; | ||
123 | |||
124 | if (derrno < 1 || derrno > 511) | ||
125 | goto bad_option_value; | ||
126 | |||
127 | kdebug("dns error no. = %lu", derrno); | ||
128 | key->type_data.x[0] = -derrno; | ||
129 | continue; | ||
130 | } | ||
131 | |||
132 | bad_option_value: | ||
133 | printk(KERN_WARNING | ||
134 | "Option '%*.*s' to dns_resolver key %d:" | ||
135 | " bad/missing value\n", | ||
136 | opt_nlen, opt_nlen, opt, key->serial); | ||
137 | return -EINVAL; | ||
138 | } while (opt = next_opt + 1, opt < end); | ||
139 | } | ||
140 | |||
141 | /* don't cache the result if we're caching an error saying there's no | ||
142 | * result */ | ||
143 | if (key->type_data.x[0]) { | ||
144 | kleave(" = 0 [h_error %ld]", key->type_data.x[0]); | ||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | kdebug("store result"); | ||
149 | ret = key_payload_reserve(key, result_len); | ||
150 | if (ret < 0) | ||
151 | return -EINVAL; | ||
152 | |||
153 | upayload = kmalloc(sizeof(*upayload) + result_len + 1, GFP_KERNEL); | ||
154 | if (!upayload) { | ||
155 | kleave(" = -ENOMEM"); | ||
156 | return -ENOMEM; | ||
157 | } | ||
158 | |||
159 | upayload->datalen = result_len; | ||
160 | memcpy(upayload->data, data, result_len); | ||
161 | upayload->data[result_len] = '\0'; | ||
162 | rcu_assign_pointer(key->payload.data, upayload); | ||
163 | |||
164 | kleave(" = 0"); | ||
165 | return 0; | ||
166 | } | ||
167 | |||
168 | /* | ||
169 | * The description is of the form "[<type>:]<domain_name>" | ||
170 | * | ||
171 | * The domain name may be a simple name or an absolute domain name (which | ||
172 | * should end with a period). The domain name is case-independent. | ||
173 | */ | ||
174 | static int | ||
175 | dns_resolver_match(const struct key *key, const void *description) | ||
176 | { | ||
177 | int slen, dlen, ret = 0; | ||
178 | const char *src = key->description, *dsp = description; | ||
179 | |||
180 | kenter("%s,%s", src, dsp); | ||
181 | |||
182 | if (!src || !dsp) | ||
183 | goto no_match; | ||
184 | |||
185 | if (strcasecmp(src, dsp) == 0) | ||
186 | goto matched; | ||
187 | |||
188 | slen = strlen(src); | ||
189 | dlen = strlen(dsp); | ||
190 | if (slen <= 0 || dlen <= 0) | ||
191 | goto no_match; | ||
192 | if (src[slen - 1] == '.') | ||
193 | slen--; | ||
194 | if (dsp[dlen - 1] == '.') | ||
195 | dlen--; | ||
196 | if (slen != dlen || strncasecmp(src, dsp, slen) != 0) | ||
197 | goto no_match; | ||
198 | |||
199 | matched: | ||
200 | ret = 1; | ||
201 | no_match: | ||
202 | kleave(" = %d", ret); | ||
203 | return ret; | ||
204 | } | ||
205 | |||
206 | /* | ||
207 | * Describe a DNS key | ||
208 | */ | ||
209 | static void dns_resolver_describe(const struct key *key, struct seq_file *m) | ||
210 | { | ||
211 | int err = key->type_data.x[0]; | ||
212 | |||
213 | seq_puts(m, key->description); | ||
214 | if (err) | ||
215 | seq_printf(m, ": %d", err); | ||
216 | else | ||
217 | seq_printf(m, ": %u", key->datalen); | ||
218 | } | ||
219 | |||
220 | struct key_type key_type_dns_resolver = { | ||
221 | .name = "dns_resolver", | ||
222 | .instantiate = dns_resolver_instantiate, | ||
223 | .match = dns_resolver_match, | ||
224 | .revoke = user_revoke, | ||
225 | .destroy = user_destroy, | ||
226 | .describe = dns_resolver_describe, | ||
227 | .read = user_read, | ||
228 | }; | ||
229 | |||
230 | static int __init init_dns_resolver(void) | ||
231 | { | ||
232 | struct cred *cred; | ||
233 | struct key *keyring; | ||
234 | int ret; | ||
235 | |||
236 | printk(KERN_NOTICE "Registering the %s key type\n", | ||
237 | key_type_dns_resolver.name); | ||
238 | |||
239 | /* create an override credential set with a special thread keyring in | ||
240 | * which DNS requests are cached | ||
241 | * | ||
242 | * this is used to prevent malicious redirections from being installed | ||
243 | * with add_key(). | ||
244 | */ | ||
245 | cred = prepare_kernel_cred(NULL); | ||
246 | if (!cred) | ||
247 | return -ENOMEM; | ||
248 | |||
249 | keyring = key_alloc(&key_type_keyring, ".dns_resolver", 0, 0, cred, | ||
250 | (KEY_POS_ALL & ~KEY_POS_SETATTR) | | ||
251 | KEY_USR_VIEW | KEY_USR_READ, | ||
252 | KEY_ALLOC_NOT_IN_QUOTA); | ||
253 | if (IS_ERR(keyring)) { | ||
254 | ret = PTR_ERR(keyring); | ||
255 | goto failed_put_cred; | ||
256 | } | ||
257 | |||
258 | ret = key_instantiate_and_link(keyring, NULL, 0, NULL, NULL); | ||
259 | if (ret < 0) | ||
260 | goto failed_put_key; | ||
261 | |||
262 | ret = register_key_type(&key_type_dns_resolver); | ||
263 | if (ret < 0) | ||
264 | goto failed_put_key; | ||
265 | |||
266 | /* instruct request_key() to use this special keyring as a cache for | ||
267 | * the results it looks up */ | ||
268 | cred->thread_keyring = keyring; | ||
269 | cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; | ||
270 | dns_resolver_cache = cred; | ||
271 | |||
272 | kdebug("DNS resolver keyring: %d\n", key_serial(keyring)); | ||
273 | return 0; | ||
274 | |||
275 | failed_put_key: | ||
276 | key_put(keyring); | ||
277 | failed_put_cred: | ||
278 | put_cred(cred); | ||
279 | return ret; | ||
280 | } | ||
281 | |||
282 | static void __exit exit_dns_resolver(void) | ||
283 | { | ||
284 | key_revoke(dns_resolver_cache->thread_keyring); | ||
285 | unregister_key_type(&key_type_dns_resolver); | ||
286 | put_cred(dns_resolver_cache); | ||
287 | printk(KERN_NOTICE "Unregistered %s key type\n", | ||
288 | key_type_dns_resolver.name); | ||
289 | } | ||
290 | |||
291 | module_init(init_dns_resolver) | ||
292 | module_exit(exit_dns_resolver) | ||
293 | MODULE_LICENSE("GPL"); | ||
diff --git a/net/dns_resolver/dns_query.c b/net/dns_resolver/dns_query.c new file mode 100644 index 000000000000..c32be292c7e3 --- /dev/null +++ b/net/dns_resolver/dns_query.c | |||
@@ -0,0 +1,165 @@ | |||
1 | /* Upcall routine, designed to work as a key type and working through | ||
2 | * /sbin/request-key to contact userspace when handling DNS queries. | ||
3 | * | ||
4 | * See Documentation/networking/dns_resolver.txt | ||
5 | * | ||
6 | * Copyright (c) 2007 Igor Mammedov | ||
7 | * Author(s): Igor Mammedov (niallain@gmail.com) | ||
8 | * Steve French (sfrench@us.ibm.com) | ||
9 | * Wang Lei (wang840925@gmail.com) | ||
10 | * David Howells (dhowells@redhat.com) | ||
11 | * | ||
12 | * The upcall wrapper used to make an arbitrary DNS query. | ||
13 | * | ||
14 | * This function requires the appropriate userspace tool dns.upcall to be | ||
15 | * installed and something like the following lines should be added to the | ||
16 | * /etc/request-key.conf file: | ||
17 | * | ||
18 | * create dns_resolver * * /sbin/dns.upcall %k | ||
19 | * | ||
20 | * For example to use this module to query AFSDB RR: | ||
21 | * | ||
22 | * create dns_resolver afsdb:* * /sbin/dns.afsdb %k | ||
23 | * | ||
24 | * This library is free software; you can redistribute it and/or modify | ||
25 | * it under the terms of the GNU Lesser General Public License as published | ||
26 | * by the Free Software Foundation; either version 2.1 of the License, or | ||
27 | * (at your option) any later version. | ||
28 | * | ||
29 | * This library is distributed in the hope that it will be useful, | ||
30 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
31 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See | ||
32 | * the GNU Lesser General Public License for more details. | ||
33 | * | ||
34 | * You should have received a copy of the GNU Lesser General Public License | ||
35 | * along with this library; if not, write to the Free Software | ||
36 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
37 | */ | ||
38 | |||
39 | #include <linux/module.h> | ||
40 | #include <linux/slab.h> | ||
41 | #include <linux/dns_resolver.h> | ||
42 | #include <linux/err.h> | ||
43 | #include <keys/dns_resolver-type.h> | ||
44 | #include <keys/user-type.h> | ||
45 | |||
46 | #include "internal.h" | ||
47 | |||
48 | /** | ||
49 | * dns_query - Query the DNS | ||
50 | * @type: Query type (or NULL for straight host->IP lookup) | ||
51 | * @name: Name to look up | ||
52 | * @namelen: Length of name | ||
53 | * @options: Request options (or NULL if no options) | ||
54 | * @_result: Where to place the returned data. | ||
55 | * @_expiry: Where to store the result expiry time (or NULL) | ||
56 | * | ||
57 | * The data will be returned in the pointer at *result, and the caller is | ||
58 | * responsible for freeing it. | ||
59 | * | ||
60 | * The description should be of the form "[<query_type>:]<domain_name>", and | ||
61 | * the options need to be appropriate for the query type requested. If no | ||
62 | * query_type is given, then the query is a straight hostname to IP address | ||
63 | * lookup. | ||
64 | * | ||
65 | * The DNS resolution lookup is performed by upcalling to userspace by way of | ||
66 | * requesting a key of type dns_resolver. | ||
67 | * | ||
68 | * Returns the size of the result on success, -ve error code otherwise. | ||
69 | */ | ||
70 | int dns_query(const char *type, const char *name, size_t namelen, | ||
71 | const char *options, char **_result, time_t *_expiry) | ||
72 | { | ||
73 | struct key *rkey; | ||
74 | struct user_key_payload *upayload; | ||
75 | const struct cred *saved_cred; | ||
76 | size_t typelen, desclen; | ||
77 | char *desc, *cp; | ||
78 | int ret, len; | ||
79 | |||
80 | kenter("%s,%*.*s,%zu,%s", | ||
81 | type, (int)namelen, (int)namelen, name, namelen, options); | ||
82 | |||
83 | if (!name || namelen == 0 || !_result) | ||
84 | return -EINVAL; | ||
85 | |||
86 | /* construct the query key description as "[<type>:]<name>" */ | ||
87 | typelen = 0; | ||
88 | desclen = 0; | ||
89 | if (type) { | ||
90 | typelen = strlen(type); | ||
91 | if (typelen < 1) | ||
92 | return -EINVAL; | ||
93 | desclen += typelen + 1; | ||
94 | } | ||
95 | |||
96 | if (!namelen) | ||
97 | namelen = strlen(name); | ||
98 | if (namelen < 3) | ||
99 | return -EINVAL; | ||
100 | desclen += namelen + 1; | ||
101 | |||
102 | desc = kmalloc(desclen, GFP_KERNEL); | ||
103 | if (!desc) | ||
104 | return -ENOMEM; | ||
105 | |||
106 | cp = desc; | ||
107 | if (type) { | ||
108 | memcpy(cp, type, typelen); | ||
109 | cp += typelen; | ||
110 | *cp++ = ':'; | ||
111 | } | ||
112 | memcpy(cp, name, namelen); | ||
113 | cp += namelen; | ||
114 | *cp = '\0'; | ||
115 | |||
116 | if (!options) | ||
117 | options = ""; | ||
118 | kdebug("call request_key(,%s,%s)", desc, options); | ||
119 | |||
120 | /* make the upcall, using special credentials to prevent the use of | ||
121 | * add_key() to preinstall malicious redirections | ||
122 | */ | ||
123 | saved_cred = override_creds(dns_resolver_cache); | ||
124 | rkey = request_key(&key_type_dns_resolver, desc, options); | ||
125 | revert_creds(saved_cred); | ||
126 | kfree(desc); | ||
127 | if (IS_ERR(rkey)) { | ||
128 | ret = PTR_ERR(rkey); | ||
129 | goto out; | ||
130 | } | ||
131 | |||
132 | down_read(&rkey->sem); | ||
133 | rkey->perm |= KEY_USR_VIEW; | ||
134 | |||
135 | ret = key_validate(rkey); | ||
136 | if (ret < 0) | ||
137 | goto put; | ||
138 | |||
139 | /* If the DNS server gave an error, return that to the caller */ | ||
140 | ret = rkey->type_data.x[0]; | ||
141 | if (ret) | ||
142 | goto put; | ||
143 | |||
144 | upayload = rcu_dereference_protected(rkey->payload.data, | ||
145 | lockdep_is_held(&rkey->sem)); | ||
146 | len = upayload->datalen; | ||
147 | |||
148 | ret = -ENOMEM; | ||
149 | *_result = kmalloc(len + 1, GFP_KERNEL); | ||
150 | if (!*_result) | ||
151 | goto put; | ||
152 | |||
153 | memcpy(*_result, upayload->data, len + 1); | ||
154 | if (_expiry) | ||
155 | *_expiry = rkey->expiry; | ||
156 | |||
157 | ret = len; | ||
158 | put: | ||
159 | up_read(&rkey->sem); | ||
160 | key_put(rkey); | ||
161 | out: | ||
162 | kleave(" = %d", ret); | ||
163 | return ret; | ||
164 | } | ||
165 | EXPORT_SYMBOL(dns_query); | ||
diff --git a/net/dns_resolver/internal.h b/net/dns_resolver/internal.h new file mode 100644 index 000000000000..189ca9e9b785 --- /dev/null +++ b/net/dns_resolver/internal.h | |||
@@ -0,0 +1,44 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 Wang Lei | ||
3 | * Author(s): Wang Lei (wang840925@gmail.com). All Rights Reserved. | ||
4 | * | ||
5 | * Internal DNS Rsolver stuff | ||
6 | * | ||
7 | * This library is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU Lesser General Public License as published | ||
9 | * by the Free Software Foundation; either version 2.1 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This library is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See | ||
15 | * the GNU Lesser General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU Lesser General Public License | ||
18 | * along with this library; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | #include <linux/compiler.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/sched.h> | ||
25 | |||
26 | /* | ||
27 | * dns_key.c | ||
28 | */ | ||
29 | extern const struct cred *dns_resolver_cache; | ||
30 | |||
31 | /* | ||
32 | * debug tracing | ||
33 | */ | ||
34 | extern unsigned dns_resolver_debug; | ||
35 | |||
36 | #define kdebug(FMT, ...) \ | ||
37 | do { \ | ||
38 | if (unlikely(dns_resolver_debug)) \ | ||
39 | printk(KERN_DEBUG "[%-6.6s] "FMT"\n", \ | ||
40 | current->comm, ##__VA_ARGS__); \ | ||
41 | } while (0) | ||
42 | |||
43 | #define kenter(FMT, ...) kdebug("==> %s("FMT")", __func__, ##__VA_ARGS__) | ||
44 | #define kleave(FMT, ...) kdebug("<== %s()"FMT"", __func__, ##__VA_ARGS__) | ||
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 6d0bd198af19..be04d46110fe 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
@@ -103,6 +103,7 @@ ieee80211_rate_control_ops_get(const char *name) | |||
103 | struct rate_control_ops *ops; | 103 | struct rate_control_ops *ops; |
104 | const char *alg_name; | 104 | const char *alg_name; |
105 | 105 | ||
106 | kparam_block_sysfs_write(ieee80211_default_rc_algo); | ||
106 | if (!name) | 107 | if (!name) |
107 | alg_name = ieee80211_default_rc_algo; | 108 | alg_name = ieee80211_default_rc_algo; |
108 | else | 109 | else |
@@ -120,6 +121,7 @@ ieee80211_rate_control_ops_get(const char *name) | |||
120 | /* try built-in one if specific alg requested but not found */ | 121 | /* try built-in one if specific alg requested but not found */ |
121 | if (!ops && strlen(CONFIG_MAC80211_RC_DEFAULT)) | 122 | if (!ops && strlen(CONFIG_MAC80211_RC_DEFAULT)) |
122 | ops = ieee80211_try_rate_control_ops_get(CONFIG_MAC80211_RC_DEFAULT); | 123 | ops = ieee80211_try_rate_control_ops_get(CONFIG_MAC80211_RC_DEFAULT); |
124 | kparam_unblock_sysfs_write(ieee80211_default_rc_algo); | ||
123 | 125 | ||
124 | return ops; | 126 | return ops; |
125 | } | 127 | } |
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h index 7043b294bb67..8e22bd345e71 100644 --- a/net/rxrpc/ar-internal.h +++ b/net/rxrpc/ar-internal.h | |||
@@ -597,12 +597,6 @@ extern unsigned rxrpc_debug; | |||
597 | #define dbgprintk(FMT,...) \ | 597 | #define dbgprintk(FMT,...) \ |
598 | printk("[%-6.6s] "FMT"\n", current->comm ,##__VA_ARGS__) | 598 | printk("[%-6.6s] "FMT"\n", current->comm ,##__VA_ARGS__) |
599 | 599 | ||
600 | /* make sure we maintain the format strings, even when debugging is disabled */ | ||
601 | static inline __attribute__((format(printf,1,2))) | ||
602 | void _dbprintk(const char *fmt, ...) | ||
603 | { | ||
604 | } | ||
605 | |||
606 | #define kenter(FMT,...) dbgprintk("==> %s("FMT")",__func__ ,##__VA_ARGS__) | 600 | #define kenter(FMT,...) dbgprintk("==> %s("FMT")",__func__ ,##__VA_ARGS__) |
607 | #define kleave(FMT,...) dbgprintk("<== %s()"FMT"",__func__ ,##__VA_ARGS__) | 601 | #define kleave(FMT,...) dbgprintk("<== %s()"FMT"",__func__ ,##__VA_ARGS__) |
608 | #define kdebug(FMT,...) dbgprintk(" "FMT ,##__VA_ARGS__) | 602 | #define kdebug(FMT,...) dbgprintk(" "FMT ,##__VA_ARGS__) |
@@ -655,11 +649,11 @@ do { \ | |||
655 | } while (0) | 649 | } while (0) |
656 | 650 | ||
657 | #else | 651 | #else |
658 | #define _enter(FMT,...) _dbprintk("==> %s("FMT")",__func__ ,##__VA_ARGS__) | 652 | #define _enter(FMT,...) no_printk("==> %s("FMT")",__func__ ,##__VA_ARGS__) |
659 | #define _leave(FMT,...) _dbprintk("<== %s()"FMT"",__func__ ,##__VA_ARGS__) | 653 | #define _leave(FMT,...) no_printk("<== %s()"FMT"",__func__ ,##__VA_ARGS__) |
660 | #define _debug(FMT,...) _dbprintk(" "FMT ,##__VA_ARGS__) | 654 | #define _debug(FMT,...) no_printk(" "FMT ,##__VA_ARGS__) |
661 | #define _proto(FMT,...) _dbprintk("### "FMT ,##__VA_ARGS__) | 655 | #define _proto(FMT,...) no_printk("### "FMT ,##__VA_ARGS__) |
662 | #define _net(FMT,...) _dbprintk("@@@ "FMT ,##__VA_ARGS__) | 656 | #define _net(FMT,...) no_printk("@@@ "FMT ,##__VA_ARGS__) |
663 | #endif | 657 | #endif |
664 | 658 | ||
665 | /* | 659 | /* |
diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig index 443c161eb8bd..3376d7657185 100644 --- a/net/sunrpc/Kconfig +++ b/net/sunrpc/Kconfig | |||
@@ -18,10 +18,11 @@ config SUNRPC_XPRT_RDMA | |||
18 | If unsure, say N. | 18 | If unsure, say N. |
19 | 19 | ||
20 | config RPCSEC_GSS_KRB5 | 20 | config RPCSEC_GSS_KRB5 |
21 | tristate "Secure RPC: Kerberos V mechanism (EXPERIMENTAL)" | 21 | tristate |
22 | depends on SUNRPC && EXPERIMENTAL | 22 | depends on SUNRPC && CRYPTO |
23 | prompt "Secure RPC: Kerberos V mechanism" if !(NFS_V4 || NFSD_V4) | ||
24 | default y | ||
23 | select SUNRPC_GSS | 25 | select SUNRPC_GSS |
24 | select CRYPTO | ||
25 | select CRYPTO_MD5 | 26 | select CRYPTO_MD5 |
26 | select CRYPTO_DES | 27 | select CRYPTO_DES |
27 | select CRYPTO_CBC | 28 | select CRYPTO_CBC |
@@ -34,7 +35,7 @@ config RPCSEC_GSS_KRB5 | |||
34 | available from http://linux-nfs.org/. In addition, user-space | 35 | available from http://linux-nfs.org/. In addition, user-space |
35 | Kerberos support should be installed. | 36 | Kerberos support should be installed. |
36 | 37 | ||
37 | If unsure, say N. | 38 | If unsure, say Y. |
38 | 39 | ||
39 | config RPCSEC_GSS_SPKM3 | 40 | config RPCSEC_GSS_SPKM3 |
40 | tristate "Secure RPC: SPKM3 mechanism (EXPERIMENTAL)" | 41 | tristate "Secure RPC: SPKM3 mechanism (EXPERIMENTAL)" |
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index 8dc47f1d0001..36cb66022a27 100644 --- a/net/sunrpc/auth.c +++ b/net/sunrpc/auth.c | |||
@@ -19,6 +19,15 @@ | |||
19 | # define RPCDBG_FACILITY RPCDBG_AUTH | 19 | # define RPCDBG_FACILITY RPCDBG_AUTH |
20 | #endif | 20 | #endif |
21 | 21 | ||
22 | #define RPC_CREDCACHE_DEFAULT_HASHBITS (4) | ||
23 | struct rpc_cred_cache { | ||
24 | struct hlist_head *hashtable; | ||
25 | unsigned int hashbits; | ||
26 | spinlock_t lock; | ||
27 | }; | ||
28 | |||
29 | static unsigned int auth_hashbits = RPC_CREDCACHE_DEFAULT_HASHBITS; | ||
30 | |||
22 | static DEFINE_SPINLOCK(rpc_authflavor_lock); | 31 | static DEFINE_SPINLOCK(rpc_authflavor_lock); |
23 | static const struct rpc_authops *auth_flavors[RPC_AUTH_MAXFLAVOR] = { | 32 | static const struct rpc_authops *auth_flavors[RPC_AUTH_MAXFLAVOR] = { |
24 | &authnull_ops, /* AUTH_NULL */ | 33 | &authnull_ops, /* AUTH_NULL */ |
@@ -29,6 +38,47 @@ static const struct rpc_authops *auth_flavors[RPC_AUTH_MAXFLAVOR] = { | |||
29 | static LIST_HEAD(cred_unused); | 38 | static LIST_HEAD(cred_unused); |
30 | static unsigned long number_cred_unused; | 39 | static unsigned long number_cred_unused; |
31 | 40 | ||
41 | #define MAX_HASHTABLE_BITS (10) | ||
42 | static int param_set_hashtbl_sz(const char *val, const struct kernel_param *kp) | ||
43 | { | ||
44 | unsigned long num; | ||
45 | unsigned int nbits; | ||
46 | int ret; | ||
47 | |||
48 | if (!val) | ||
49 | goto out_inval; | ||
50 | ret = strict_strtoul(val, 0, &num); | ||
51 | if (ret == -EINVAL) | ||
52 | goto out_inval; | ||
53 | nbits = fls(num); | ||
54 | if (num > (1U << nbits)) | ||
55 | nbits++; | ||
56 | if (nbits > MAX_HASHTABLE_BITS || nbits < 2) | ||
57 | goto out_inval; | ||
58 | *(unsigned int *)kp->arg = nbits; | ||
59 | return 0; | ||
60 | out_inval: | ||
61 | return -EINVAL; | ||
62 | } | ||
63 | |||
64 | static int param_get_hashtbl_sz(char *buffer, const struct kernel_param *kp) | ||
65 | { | ||
66 | unsigned int nbits; | ||
67 | |||
68 | nbits = *(unsigned int *)kp->arg; | ||
69 | return sprintf(buffer, "%u", 1U << nbits); | ||
70 | } | ||
71 | |||
72 | #define param_check_hashtbl_sz(name, p) __param_check(name, p, unsigned int); | ||
73 | |||
74 | static struct kernel_param_ops param_ops_hashtbl_sz = { | ||
75 | .set = param_set_hashtbl_sz, | ||
76 | .get = param_get_hashtbl_sz, | ||
77 | }; | ||
78 | |||
79 | module_param_named(auth_hashtable_size, auth_hashbits, hashtbl_sz, 0644); | ||
80 | MODULE_PARM_DESC(auth_hashtable_size, "RPC credential cache hashtable size"); | ||
81 | |||
32 | static u32 | 82 | static u32 |
33 | pseudoflavor_to_flavor(u32 flavor) { | 83 | pseudoflavor_to_flavor(u32 flavor) { |
34 | if (flavor >= RPC_AUTH_MAXFLAVOR) | 84 | if (flavor >= RPC_AUTH_MAXFLAVOR) |
@@ -145,16 +195,23 @@ int | |||
145 | rpcauth_init_credcache(struct rpc_auth *auth) | 195 | rpcauth_init_credcache(struct rpc_auth *auth) |
146 | { | 196 | { |
147 | struct rpc_cred_cache *new; | 197 | struct rpc_cred_cache *new; |
148 | int i; | 198 | unsigned int hashsize; |
149 | 199 | ||
150 | new = kmalloc(sizeof(*new), GFP_KERNEL); | 200 | new = kmalloc(sizeof(*new), GFP_KERNEL); |
151 | if (!new) | 201 | if (!new) |
152 | return -ENOMEM; | 202 | goto out_nocache; |
153 | for (i = 0; i < RPC_CREDCACHE_NR; i++) | 203 | new->hashbits = auth_hashbits; |
154 | INIT_HLIST_HEAD(&new->hashtable[i]); | 204 | hashsize = 1U << new->hashbits; |
205 | new->hashtable = kcalloc(hashsize, sizeof(new->hashtable[0]), GFP_KERNEL); | ||
206 | if (!new->hashtable) | ||
207 | goto out_nohashtbl; | ||
155 | spin_lock_init(&new->lock); | 208 | spin_lock_init(&new->lock); |
156 | auth->au_credcache = new; | 209 | auth->au_credcache = new; |
157 | return 0; | 210 | return 0; |
211 | out_nohashtbl: | ||
212 | kfree(new); | ||
213 | out_nocache: | ||
214 | return -ENOMEM; | ||
158 | } | 215 | } |
159 | EXPORT_SYMBOL_GPL(rpcauth_init_credcache); | 216 | EXPORT_SYMBOL_GPL(rpcauth_init_credcache); |
160 | 217 | ||
@@ -183,11 +240,12 @@ rpcauth_clear_credcache(struct rpc_cred_cache *cache) | |||
183 | LIST_HEAD(free); | 240 | LIST_HEAD(free); |
184 | struct hlist_head *head; | 241 | struct hlist_head *head; |
185 | struct rpc_cred *cred; | 242 | struct rpc_cred *cred; |
243 | unsigned int hashsize = 1U << cache->hashbits; | ||
186 | int i; | 244 | int i; |
187 | 245 | ||
188 | spin_lock(&rpc_credcache_lock); | 246 | spin_lock(&rpc_credcache_lock); |
189 | spin_lock(&cache->lock); | 247 | spin_lock(&cache->lock); |
190 | for (i = 0; i < RPC_CREDCACHE_NR; i++) { | 248 | for (i = 0; i < hashsize; i++) { |
191 | head = &cache->hashtable[i]; | 249 | head = &cache->hashtable[i]; |
192 | while (!hlist_empty(head)) { | 250 | while (!hlist_empty(head)) { |
193 | cred = hlist_entry(head->first, struct rpc_cred, cr_hash); | 251 | cred = hlist_entry(head->first, struct rpc_cred, cr_hash); |
@@ -216,6 +274,7 @@ rpcauth_destroy_credcache(struct rpc_auth *auth) | |||
216 | if (cache) { | 274 | if (cache) { |
217 | auth->au_credcache = NULL; | 275 | auth->au_credcache = NULL; |
218 | rpcauth_clear_credcache(cache); | 276 | rpcauth_clear_credcache(cache); |
277 | kfree(cache->hashtable); | ||
219 | kfree(cache); | 278 | kfree(cache); |
220 | } | 279 | } |
221 | } | 280 | } |
@@ -297,7 +356,7 @@ rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred, | |||
297 | *entry, *new; | 356 | *entry, *new; |
298 | unsigned int nr; | 357 | unsigned int nr; |
299 | 358 | ||
300 | nr = hash_long(acred->uid, RPC_CREDCACHE_HASHBITS); | 359 | nr = hash_long(acred->uid, cache->hashbits); |
301 | 360 | ||
302 | rcu_read_lock(); | 361 | rcu_read_lock(); |
303 | hlist_for_each_entry_rcu(entry, pos, &cache->hashtable[nr], cr_hash) { | 362 | hlist_for_each_entry_rcu(entry, pos, &cache->hashtable[nr], cr_hash) { |
@@ -390,16 +449,16 @@ rpcauth_init_cred(struct rpc_cred *cred, const struct auth_cred *acred, | |||
390 | } | 449 | } |
391 | EXPORT_SYMBOL_GPL(rpcauth_init_cred); | 450 | EXPORT_SYMBOL_GPL(rpcauth_init_cred); |
392 | 451 | ||
393 | void | 452 | struct rpc_cred * |
394 | rpcauth_generic_bind_cred(struct rpc_task *task, struct rpc_cred *cred, int lookupflags) | 453 | rpcauth_generic_bind_cred(struct rpc_task *task, struct rpc_cred *cred, int lookupflags) |
395 | { | 454 | { |
396 | task->tk_msg.rpc_cred = get_rpccred(cred); | ||
397 | dprintk("RPC: %5u holding %s cred %p\n", task->tk_pid, | 455 | dprintk("RPC: %5u holding %s cred %p\n", task->tk_pid, |
398 | cred->cr_auth->au_ops->au_name, cred); | 456 | cred->cr_auth->au_ops->au_name, cred); |
457 | return get_rpccred(cred); | ||
399 | } | 458 | } |
400 | EXPORT_SYMBOL_GPL(rpcauth_generic_bind_cred); | 459 | EXPORT_SYMBOL_GPL(rpcauth_generic_bind_cred); |
401 | 460 | ||
402 | static void | 461 | static struct rpc_cred * |
403 | rpcauth_bind_root_cred(struct rpc_task *task, int lookupflags) | 462 | rpcauth_bind_root_cred(struct rpc_task *task, int lookupflags) |
404 | { | 463 | { |
405 | struct rpc_auth *auth = task->tk_client->cl_auth; | 464 | struct rpc_auth *auth = task->tk_client->cl_auth; |
@@ -407,45 +466,43 @@ rpcauth_bind_root_cred(struct rpc_task *task, int lookupflags) | |||
407 | .uid = 0, | 466 | .uid = 0, |
408 | .gid = 0, | 467 | .gid = 0, |
409 | }; | 468 | }; |
410 | struct rpc_cred *ret; | ||
411 | 469 | ||
412 | dprintk("RPC: %5u looking up %s cred\n", | 470 | dprintk("RPC: %5u looking up %s cred\n", |
413 | task->tk_pid, task->tk_client->cl_auth->au_ops->au_name); | 471 | task->tk_pid, task->tk_client->cl_auth->au_ops->au_name); |
414 | ret = auth->au_ops->lookup_cred(auth, &acred, lookupflags); | 472 | return auth->au_ops->lookup_cred(auth, &acred, lookupflags); |
415 | if (!IS_ERR(ret)) | ||
416 | task->tk_msg.rpc_cred = ret; | ||
417 | else | ||
418 | task->tk_status = PTR_ERR(ret); | ||
419 | } | 473 | } |
420 | 474 | ||
421 | static void | 475 | static struct rpc_cred * |
422 | rpcauth_bind_new_cred(struct rpc_task *task, int lookupflags) | 476 | rpcauth_bind_new_cred(struct rpc_task *task, int lookupflags) |
423 | { | 477 | { |
424 | struct rpc_auth *auth = task->tk_client->cl_auth; | 478 | struct rpc_auth *auth = task->tk_client->cl_auth; |
425 | struct rpc_cred *ret; | ||
426 | 479 | ||
427 | dprintk("RPC: %5u looking up %s cred\n", | 480 | dprintk("RPC: %5u looking up %s cred\n", |
428 | task->tk_pid, auth->au_ops->au_name); | 481 | task->tk_pid, auth->au_ops->au_name); |
429 | ret = rpcauth_lookupcred(auth, lookupflags); | 482 | return rpcauth_lookupcred(auth, lookupflags); |
430 | if (!IS_ERR(ret)) | ||
431 | task->tk_msg.rpc_cred = ret; | ||
432 | else | ||
433 | task->tk_status = PTR_ERR(ret); | ||
434 | } | 483 | } |
435 | 484 | ||
436 | void | 485 | static int |
437 | rpcauth_bindcred(struct rpc_task *task, struct rpc_cred *cred, int flags) | 486 | rpcauth_bindcred(struct rpc_task *task, struct rpc_cred *cred, int flags) |
438 | { | 487 | { |
488 | struct rpc_rqst *req = task->tk_rqstp; | ||
489 | struct rpc_cred *new; | ||
439 | int lookupflags = 0; | 490 | int lookupflags = 0; |
440 | 491 | ||
441 | if (flags & RPC_TASK_ASYNC) | 492 | if (flags & RPC_TASK_ASYNC) |
442 | lookupflags |= RPCAUTH_LOOKUP_NEW; | 493 | lookupflags |= RPCAUTH_LOOKUP_NEW; |
443 | if (cred != NULL) | 494 | if (cred != NULL) |
444 | cred->cr_ops->crbind(task, cred, lookupflags); | 495 | new = cred->cr_ops->crbind(task, cred, lookupflags); |
445 | else if (flags & RPC_TASK_ROOTCREDS) | 496 | else if (flags & RPC_TASK_ROOTCREDS) |
446 | rpcauth_bind_root_cred(task, lookupflags); | 497 | new = rpcauth_bind_root_cred(task, lookupflags); |
447 | else | 498 | else |
448 | rpcauth_bind_new_cred(task, lookupflags); | 499 | new = rpcauth_bind_new_cred(task, lookupflags); |
500 | if (IS_ERR(new)) | ||
501 | return PTR_ERR(new); | ||
502 | if (req->rq_cred != NULL) | ||
503 | put_rpccred(req->rq_cred); | ||
504 | req->rq_cred = new; | ||
505 | return 0; | ||
449 | } | 506 | } |
450 | 507 | ||
451 | void | 508 | void |
@@ -484,22 +541,10 @@ out_nodestroy: | |||
484 | } | 541 | } |
485 | EXPORT_SYMBOL_GPL(put_rpccred); | 542 | EXPORT_SYMBOL_GPL(put_rpccred); |
486 | 543 | ||
487 | void | ||
488 | rpcauth_unbindcred(struct rpc_task *task) | ||
489 | { | ||
490 | struct rpc_cred *cred = task->tk_msg.rpc_cred; | ||
491 | |||
492 | dprintk("RPC: %5u releasing %s cred %p\n", | ||
493 | task->tk_pid, cred->cr_auth->au_ops->au_name, cred); | ||
494 | |||
495 | put_rpccred(cred); | ||
496 | task->tk_msg.rpc_cred = NULL; | ||
497 | } | ||
498 | |||
499 | __be32 * | 544 | __be32 * |
500 | rpcauth_marshcred(struct rpc_task *task, __be32 *p) | 545 | rpcauth_marshcred(struct rpc_task *task, __be32 *p) |
501 | { | 546 | { |
502 | struct rpc_cred *cred = task->tk_msg.rpc_cred; | 547 | struct rpc_cred *cred = task->tk_rqstp->rq_cred; |
503 | 548 | ||
504 | dprintk("RPC: %5u marshaling %s cred %p\n", | 549 | dprintk("RPC: %5u marshaling %s cred %p\n", |
505 | task->tk_pid, cred->cr_auth->au_ops->au_name, cred); | 550 | task->tk_pid, cred->cr_auth->au_ops->au_name, cred); |
@@ -510,7 +555,7 @@ rpcauth_marshcred(struct rpc_task *task, __be32 *p) | |||
510 | __be32 * | 555 | __be32 * |
511 | rpcauth_checkverf(struct rpc_task *task, __be32 *p) | 556 | rpcauth_checkverf(struct rpc_task *task, __be32 *p) |
512 | { | 557 | { |
513 | struct rpc_cred *cred = task->tk_msg.rpc_cred; | 558 | struct rpc_cred *cred = task->tk_rqstp->rq_cred; |
514 | 559 | ||
515 | dprintk("RPC: %5u validating %s cred %p\n", | 560 | dprintk("RPC: %5u validating %s cred %p\n", |
516 | task->tk_pid, cred->cr_auth->au_ops->au_name, cred); | 561 | task->tk_pid, cred->cr_auth->au_ops->au_name, cred); |
@@ -522,7 +567,7 @@ int | |||
522 | rpcauth_wrap_req(struct rpc_task *task, kxdrproc_t encode, void *rqstp, | 567 | rpcauth_wrap_req(struct rpc_task *task, kxdrproc_t encode, void *rqstp, |
523 | __be32 *data, void *obj) | 568 | __be32 *data, void *obj) |
524 | { | 569 | { |
525 | struct rpc_cred *cred = task->tk_msg.rpc_cred; | 570 | struct rpc_cred *cred = task->tk_rqstp->rq_cred; |
526 | 571 | ||
527 | dprintk("RPC: %5u using %s cred %p to wrap rpc data\n", | 572 | dprintk("RPC: %5u using %s cred %p to wrap rpc data\n", |
528 | task->tk_pid, cred->cr_ops->cr_name, cred); | 573 | task->tk_pid, cred->cr_ops->cr_name, cred); |
@@ -536,7 +581,7 @@ int | |||
536 | rpcauth_unwrap_resp(struct rpc_task *task, kxdrproc_t decode, void *rqstp, | 581 | rpcauth_unwrap_resp(struct rpc_task *task, kxdrproc_t decode, void *rqstp, |
537 | __be32 *data, void *obj) | 582 | __be32 *data, void *obj) |
538 | { | 583 | { |
539 | struct rpc_cred *cred = task->tk_msg.rpc_cred; | 584 | struct rpc_cred *cred = task->tk_rqstp->rq_cred; |
540 | 585 | ||
541 | dprintk("RPC: %5u using %s cred %p to unwrap rpc data\n", | 586 | dprintk("RPC: %5u using %s cred %p to unwrap rpc data\n", |
542 | task->tk_pid, cred->cr_ops->cr_name, cred); | 587 | task->tk_pid, cred->cr_ops->cr_name, cred); |
@@ -550,13 +595,21 @@ rpcauth_unwrap_resp(struct rpc_task *task, kxdrproc_t decode, void *rqstp, | |||
550 | int | 595 | int |
551 | rpcauth_refreshcred(struct rpc_task *task) | 596 | rpcauth_refreshcred(struct rpc_task *task) |
552 | { | 597 | { |
553 | struct rpc_cred *cred = task->tk_msg.rpc_cred; | 598 | struct rpc_cred *cred = task->tk_rqstp->rq_cred; |
554 | int err; | 599 | int err; |
555 | 600 | ||
601 | cred = task->tk_rqstp->rq_cred; | ||
602 | if (cred == NULL) { | ||
603 | err = rpcauth_bindcred(task, task->tk_msg.rpc_cred, task->tk_flags); | ||
604 | if (err < 0) | ||
605 | goto out; | ||
606 | cred = task->tk_rqstp->rq_cred; | ||
607 | }; | ||
556 | dprintk("RPC: %5u refreshing %s cred %p\n", | 608 | dprintk("RPC: %5u refreshing %s cred %p\n", |
557 | task->tk_pid, cred->cr_auth->au_ops->au_name, cred); | 609 | task->tk_pid, cred->cr_auth->au_ops->au_name, cred); |
558 | 610 | ||
559 | err = cred->cr_ops->crrefresh(task); | 611 | err = cred->cr_ops->crrefresh(task); |
612 | out: | ||
560 | if (err < 0) | 613 | if (err < 0) |
561 | task->tk_status = err; | 614 | task->tk_status = err; |
562 | return err; | 615 | return err; |
@@ -565,7 +618,7 @@ rpcauth_refreshcred(struct rpc_task *task) | |||
565 | void | 618 | void |
566 | rpcauth_invalcred(struct rpc_task *task) | 619 | rpcauth_invalcred(struct rpc_task *task) |
567 | { | 620 | { |
568 | struct rpc_cred *cred = task->tk_msg.rpc_cred; | 621 | struct rpc_cred *cred = task->tk_rqstp->rq_cred; |
569 | 622 | ||
570 | dprintk("RPC: %5u invalidating %s cred %p\n", | 623 | dprintk("RPC: %5u invalidating %s cred %p\n", |
571 | task->tk_pid, cred->cr_auth->au_ops->au_name, cred); | 624 | task->tk_pid, cred->cr_auth->au_ops->au_name, cred); |
@@ -576,7 +629,7 @@ rpcauth_invalcred(struct rpc_task *task) | |||
576 | int | 629 | int |
577 | rpcauth_uptodatecred(struct rpc_task *task) | 630 | rpcauth_uptodatecred(struct rpc_task *task) |
578 | { | 631 | { |
579 | struct rpc_cred *cred = task->tk_msg.rpc_cred; | 632 | struct rpc_cred *cred = task->tk_rqstp->rq_cred; |
580 | 633 | ||
581 | return cred == NULL || | 634 | return cred == NULL || |
582 | test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) != 0; | 635 | test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) != 0; |
@@ -587,14 +640,27 @@ static struct shrinker rpc_cred_shrinker = { | |||
587 | .seeks = DEFAULT_SEEKS, | 640 | .seeks = DEFAULT_SEEKS, |
588 | }; | 641 | }; |
589 | 642 | ||
590 | void __init rpcauth_init_module(void) | 643 | int __init rpcauth_init_module(void) |
591 | { | 644 | { |
592 | rpc_init_authunix(); | 645 | int err; |
593 | rpc_init_generic_auth(); | 646 | |
647 | err = rpc_init_authunix(); | ||
648 | if (err < 0) | ||
649 | goto out1; | ||
650 | err = rpc_init_generic_auth(); | ||
651 | if (err < 0) | ||
652 | goto out2; | ||
594 | register_shrinker(&rpc_cred_shrinker); | 653 | register_shrinker(&rpc_cred_shrinker); |
654 | return 0; | ||
655 | out2: | ||
656 | rpc_destroy_authunix(); | ||
657 | out1: | ||
658 | return err; | ||
595 | } | 659 | } |
596 | 660 | ||
597 | void __exit rpcauth_remove_module(void) | 661 | void __exit rpcauth_remove_module(void) |
598 | { | 662 | { |
663 | rpc_destroy_authunix(); | ||
664 | rpc_destroy_generic_auth(); | ||
599 | unregister_shrinker(&rpc_cred_shrinker); | 665 | unregister_shrinker(&rpc_cred_shrinker); |
600 | } | 666 | } |
diff --git a/net/sunrpc/auth_generic.c b/net/sunrpc/auth_generic.c index 8f623b0f03dd..43162bb3b78f 100644 --- a/net/sunrpc/auth_generic.c +++ b/net/sunrpc/auth_generic.c | |||
@@ -27,7 +27,6 @@ struct generic_cred { | |||
27 | }; | 27 | }; |
28 | 28 | ||
29 | static struct rpc_auth generic_auth; | 29 | static struct rpc_auth generic_auth; |
30 | static struct rpc_cred_cache generic_cred_cache; | ||
31 | static const struct rpc_credops generic_credops; | 30 | static const struct rpc_credops generic_credops; |
32 | 31 | ||
33 | /* | 32 | /* |
@@ -55,18 +54,13 @@ struct rpc_cred *rpc_lookup_machine_cred(void) | |||
55 | } | 54 | } |
56 | EXPORT_SYMBOL_GPL(rpc_lookup_machine_cred); | 55 | EXPORT_SYMBOL_GPL(rpc_lookup_machine_cred); |
57 | 56 | ||
58 | static void | 57 | static struct rpc_cred *generic_bind_cred(struct rpc_task *task, |
59 | generic_bind_cred(struct rpc_task *task, struct rpc_cred *cred, int lookupflags) | 58 | struct rpc_cred *cred, int lookupflags) |
60 | { | 59 | { |
61 | struct rpc_auth *auth = task->tk_client->cl_auth; | 60 | struct rpc_auth *auth = task->tk_client->cl_auth; |
62 | struct auth_cred *acred = &container_of(cred, struct generic_cred, gc_base)->acred; | 61 | struct auth_cred *acred = &container_of(cred, struct generic_cred, gc_base)->acred; |
63 | struct rpc_cred *ret; | ||
64 | 62 | ||
65 | ret = auth->au_ops->lookup_cred(auth, acred, lookupflags); | 63 | return auth->au_ops->lookup_cred(auth, acred, lookupflags); |
66 | if (!IS_ERR(ret)) | ||
67 | task->tk_msg.rpc_cred = ret; | ||
68 | else | ||
69 | task->tk_status = PTR_ERR(ret); | ||
70 | } | 64 | } |
71 | 65 | ||
72 | /* | 66 | /* |
@@ -159,20 +153,16 @@ out_nomatch: | |||
159 | return 0; | 153 | return 0; |
160 | } | 154 | } |
161 | 155 | ||
162 | void __init rpc_init_generic_auth(void) | 156 | int __init rpc_init_generic_auth(void) |
163 | { | 157 | { |
164 | spin_lock_init(&generic_cred_cache.lock); | 158 | return rpcauth_init_credcache(&generic_auth); |
165 | } | 159 | } |
166 | 160 | ||
167 | void __exit rpc_destroy_generic_auth(void) | 161 | void __exit rpc_destroy_generic_auth(void) |
168 | { | 162 | { |
169 | rpcauth_clear_credcache(&generic_cred_cache); | 163 | rpcauth_destroy_credcache(&generic_auth); |
170 | } | 164 | } |
171 | 165 | ||
172 | static struct rpc_cred_cache generic_cred_cache = { | ||
173 | {{ NULL, },}, | ||
174 | }; | ||
175 | |||
176 | static const struct rpc_authops generic_auth_ops = { | 166 | static const struct rpc_authops generic_auth_ops = { |
177 | .owner = THIS_MODULE, | 167 | .owner = THIS_MODULE, |
178 | .au_name = "Generic", | 168 | .au_name = "Generic", |
@@ -183,7 +173,6 @@ static const struct rpc_authops generic_auth_ops = { | |||
183 | static struct rpc_auth generic_auth = { | 173 | static struct rpc_auth generic_auth = { |
184 | .au_ops = &generic_auth_ops, | 174 | .au_ops = &generic_auth_ops, |
185 | .au_count = ATOMIC_INIT(0), | 175 | .au_count = ATOMIC_INIT(0), |
186 | .au_credcache = &generic_cred_cache, | ||
187 | }; | 176 | }; |
188 | 177 | ||
189 | static const struct rpc_credops generic_credops = { | 178 | static const struct rpc_credops generic_credops = { |
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 8da2a0e68574..dcfc66bab2bb 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -373,7 +373,7 @@ gss_handle_downcall_result(struct gss_cred *gss_cred, struct gss_upcall_msg *gss | |||
373 | static void | 373 | static void |
374 | gss_upcall_callback(struct rpc_task *task) | 374 | gss_upcall_callback(struct rpc_task *task) |
375 | { | 375 | { |
376 | struct gss_cred *gss_cred = container_of(task->tk_msg.rpc_cred, | 376 | struct gss_cred *gss_cred = container_of(task->tk_rqstp->rq_cred, |
377 | struct gss_cred, gc_base); | 377 | struct gss_cred, gc_base); |
378 | struct gss_upcall_msg *gss_msg = gss_cred->gc_upcall; | 378 | struct gss_upcall_msg *gss_msg = gss_cred->gc_upcall; |
379 | struct inode *inode = &gss_msg->inode->vfs_inode; | 379 | struct inode *inode = &gss_msg->inode->vfs_inode; |
@@ -502,7 +502,7 @@ static void warn_gssd(void) | |||
502 | static inline int | 502 | static inline int |
503 | gss_refresh_upcall(struct rpc_task *task) | 503 | gss_refresh_upcall(struct rpc_task *task) |
504 | { | 504 | { |
505 | struct rpc_cred *cred = task->tk_msg.rpc_cred; | 505 | struct rpc_cred *cred = task->tk_rqstp->rq_cred; |
506 | struct gss_auth *gss_auth = container_of(cred->cr_auth, | 506 | struct gss_auth *gss_auth = container_of(cred->cr_auth, |
507 | struct gss_auth, rpc_auth); | 507 | struct gss_auth, rpc_auth); |
508 | struct gss_cred *gss_cred = container_of(cred, | 508 | struct gss_cred *gss_cred = container_of(cred, |
@@ -928,6 +928,7 @@ gss_do_free_ctx(struct gss_cl_ctx *ctx) | |||
928 | { | 928 | { |
929 | dprintk("RPC: gss_free_ctx\n"); | 929 | dprintk("RPC: gss_free_ctx\n"); |
930 | 930 | ||
931 | gss_delete_sec_context(&ctx->gc_gss_ctx); | ||
931 | kfree(ctx->gc_wire_ctx.data); | 932 | kfree(ctx->gc_wire_ctx.data); |
932 | kfree(ctx); | 933 | kfree(ctx); |
933 | } | 934 | } |
@@ -942,13 +943,7 @@ gss_free_ctx_callback(struct rcu_head *head) | |||
942 | static void | 943 | static void |
943 | gss_free_ctx(struct gss_cl_ctx *ctx) | 944 | gss_free_ctx(struct gss_cl_ctx *ctx) |
944 | { | 945 | { |
945 | struct gss_ctx *gc_gss_ctx; | ||
946 | |||
947 | gc_gss_ctx = rcu_dereference(ctx->gc_gss_ctx); | ||
948 | rcu_assign_pointer(ctx->gc_gss_ctx, NULL); | ||
949 | call_rcu(&ctx->gc_rcu, gss_free_ctx_callback); | 946 | call_rcu(&ctx->gc_rcu, gss_free_ctx_callback); |
950 | if (gc_gss_ctx) | ||
951 | gss_delete_sec_context(&gc_gss_ctx); | ||
952 | } | 947 | } |
953 | 948 | ||
954 | static void | 949 | static void |
@@ -1064,12 +1059,12 @@ out: | |||
1064 | static __be32 * | 1059 | static __be32 * |
1065 | gss_marshal(struct rpc_task *task, __be32 *p) | 1060 | gss_marshal(struct rpc_task *task, __be32 *p) |
1066 | { | 1061 | { |
1067 | struct rpc_cred *cred = task->tk_msg.rpc_cred; | 1062 | struct rpc_rqst *req = task->tk_rqstp; |
1063 | struct rpc_cred *cred = req->rq_cred; | ||
1068 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, | 1064 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, |
1069 | gc_base); | 1065 | gc_base); |
1070 | struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); | 1066 | struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); |
1071 | __be32 *cred_len; | 1067 | __be32 *cred_len; |
1072 | struct rpc_rqst *req = task->tk_rqstp; | ||
1073 | u32 maj_stat = 0; | 1068 | u32 maj_stat = 0; |
1074 | struct xdr_netobj mic; | 1069 | struct xdr_netobj mic; |
1075 | struct kvec iov; | 1070 | struct kvec iov; |
@@ -1119,7 +1114,7 @@ out_put_ctx: | |||
1119 | 1114 | ||
1120 | static int gss_renew_cred(struct rpc_task *task) | 1115 | static int gss_renew_cred(struct rpc_task *task) |
1121 | { | 1116 | { |
1122 | struct rpc_cred *oldcred = task->tk_msg.rpc_cred; | 1117 | struct rpc_cred *oldcred = task->tk_rqstp->rq_cred; |
1123 | struct gss_cred *gss_cred = container_of(oldcred, | 1118 | struct gss_cred *gss_cred = container_of(oldcred, |
1124 | struct gss_cred, | 1119 | struct gss_cred, |
1125 | gc_base); | 1120 | gc_base); |
@@ -1133,7 +1128,7 @@ static int gss_renew_cred(struct rpc_task *task) | |||
1133 | new = gss_lookup_cred(auth, &acred, RPCAUTH_LOOKUP_NEW); | 1128 | new = gss_lookup_cred(auth, &acred, RPCAUTH_LOOKUP_NEW); |
1134 | if (IS_ERR(new)) | 1129 | if (IS_ERR(new)) |
1135 | return PTR_ERR(new); | 1130 | return PTR_ERR(new); |
1136 | task->tk_msg.rpc_cred = new; | 1131 | task->tk_rqstp->rq_cred = new; |
1137 | put_rpccred(oldcred); | 1132 | put_rpccred(oldcred); |
1138 | return 0; | 1133 | return 0; |
1139 | } | 1134 | } |
@@ -1161,7 +1156,7 @@ static int gss_cred_is_negative_entry(struct rpc_cred *cred) | |||
1161 | static int | 1156 | static int |
1162 | gss_refresh(struct rpc_task *task) | 1157 | gss_refresh(struct rpc_task *task) |
1163 | { | 1158 | { |
1164 | struct rpc_cred *cred = task->tk_msg.rpc_cred; | 1159 | struct rpc_cred *cred = task->tk_rqstp->rq_cred; |
1165 | int ret = 0; | 1160 | int ret = 0; |
1166 | 1161 | ||
1167 | if (gss_cred_is_negative_entry(cred)) | 1162 | if (gss_cred_is_negative_entry(cred)) |
@@ -1172,7 +1167,7 @@ gss_refresh(struct rpc_task *task) | |||
1172 | ret = gss_renew_cred(task); | 1167 | ret = gss_renew_cred(task); |
1173 | if (ret < 0) | 1168 | if (ret < 0) |
1174 | goto out; | 1169 | goto out; |
1175 | cred = task->tk_msg.rpc_cred; | 1170 | cred = task->tk_rqstp->rq_cred; |
1176 | } | 1171 | } |
1177 | 1172 | ||
1178 | if (test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags)) | 1173 | if (test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags)) |
@@ -1191,7 +1186,7 @@ gss_refresh_null(struct rpc_task *task) | |||
1191 | static __be32 * | 1186 | static __be32 * |
1192 | gss_validate(struct rpc_task *task, __be32 *p) | 1187 | gss_validate(struct rpc_task *task, __be32 *p) |
1193 | { | 1188 | { |
1194 | struct rpc_cred *cred = task->tk_msg.rpc_cred; | 1189 | struct rpc_cred *cred = task->tk_rqstp->rq_cred; |
1195 | struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); | 1190 | struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); |
1196 | __be32 seq; | 1191 | __be32 seq; |
1197 | struct kvec iov; | 1192 | struct kvec iov; |
@@ -1400,7 +1395,7 @@ static int | |||
1400 | gss_wrap_req(struct rpc_task *task, | 1395 | gss_wrap_req(struct rpc_task *task, |
1401 | kxdrproc_t encode, void *rqstp, __be32 *p, void *obj) | 1396 | kxdrproc_t encode, void *rqstp, __be32 *p, void *obj) |
1402 | { | 1397 | { |
1403 | struct rpc_cred *cred = task->tk_msg.rpc_cred; | 1398 | struct rpc_cred *cred = task->tk_rqstp->rq_cred; |
1404 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, | 1399 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, |
1405 | gc_base); | 1400 | gc_base); |
1406 | struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); | 1401 | struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); |
@@ -1503,7 +1498,7 @@ static int | |||
1503 | gss_unwrap_resp(struct rpc_task *task, | 1498 | gss_unwrap_resp(struct rpc_task *task, |
1504 | kxdrproc_t decode, void *rqstp, __be32 *p, void *obj) | 1499 | kxdrproc_t decode, void *rqstp, __be32 *p, void *obj) |
1505 | { | 1500 | { |
1506 | struct rpc_cred *cred = task->tk_msg.rpc_cred; | 1501 | struct rpc_cred *cred = task->tk_rqstp->rq_cred; |
1507 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, | 1502 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, |
1508 | gc_base); | 1503 | gc_base); |
1509 | struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); | 1504 | struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); |
diff --git a/net/sunrpc/auth_null.c b/net/sunrpc/auth_null.c index 1db618f56ecb..a5c36c01707b 100644 --- a/net/sunrpc/auth_null.c +++ b/net/sunrpc/auth_null.c | |||
@@ -75,7 +75,7 @@ nul_marshal(struct rpc_task *task, __be32 *p) | |||
75 | static int | 75 | static int |
76 | nul_refresh(struct rpc_task *task) | 76 | nul_refresh(struct rpc_task *task) |
77 | { | 77 | { |
78 | set_bit(RPCAUTH_CRED_UPTODATE, &task->tk_msg.rpc_cred->cr_flags); | 78 | set_bit(RPCAUTH_CRED_UPTODATE, &task->tk_rqstp->rq_cred->cr_flags); |
79 | return 0; | 79 | return 0; |
80 | } | 80 | } |
81 | 81 | ||
diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c index aac2f8b4ee21..4cb70dc6e7ad 100644 --- a/net/sunrpc/auth_unix.c +++ b/net/sunrpc/auth_unix.c | |||
@@ -29,7 +29,6 @@ struct unx_cred { | |||
29 | #endif | 29 | #endif |
30 | 30 | ||
31 | static struct rpc_auth unix_auth; | 31 | static struct rpc_auth unix_auth; |
32 | static struct rpc_cred_cache unix_cred_cache; | ||
33 | static const struct rpc_credops unix_credops; | 32 | static const struct rpc_credops unix_credops; |
34 | 33 | ||
35 | static struct rpc_auth * | 34 | static struct rpc_auth * |
@@ -141,7 +140,7 @@ static __be32 * | |||
141 | unx_marshal(struct rpc_task *task, __be32 *p) | 140 | unx_marshal(struct rpc_task *task, __be32 *p) |
142 | { | 141 | { |
143 | struct rpc_clnt *clnt = task->tk_client; | 142 | struct rpc_clnt *clnt = task->tk_client; |
144 | struct unx_cred *cred = container_of(task->tk_msg.rpc_cred, struct unx_cred, uc_base); | 143 | struct unx_cred *cred = container_of(task->tk_rqstp->rq_cred, struct unx_cred, uc_base); |
145 | __be32 *base, *hold; | 144 | __be32 *base, *hold; |
146 | int i; | 145 | int i; |
147 | 146 | ||
@@ -174,7 +173,7 @@ unx_marshal(struct rpc_task *task, __be32 *p) | |||
174 | static int | 173 | static int |
175 | unx_refresh(struct rpc_task *task) | 174 | unx_refresh(struct rpc_task *task) |
176 | { | 175 | { |
177 | set_bit(RPCAUTH_CRED_UPTODATE, &task->tk_msg.rpc_cred->cr_flags); | 176 | set_bit(RPCAUTH_CRED_UPTODATE, &task->tk_rqstp->rq_cred->cr_flags); |
178 | return 0; | 177 | return 0; |
179 | } | 178 | } |
180 | 179 | ||
@@ -197,15 +196,20 @@ unx_validate(struct rpc_task *task, __be32 *p) | |||
197 | printk("RPC: giant verf size: %u\n", size); | 196 | printk("RPC: giant verf size: %u\n", size); |
198 | return NULL; | 197 | return NULL; |
199 | } | 198 | } |
200 | task->tk_msg.rpc_cred->cr_auth->au_rslack = (size >> 2) + 2; | 199 | task->tk_rqstp->rq_cred->cr_auth->au_rslack = (size >> 2) + 2; |
201 | p += (size >> 2); | 200 | p += (size >> 2); |
202 | 201 | ||
203 | return p; | 202 | return p; |
204 | } | 203 | } |
205 | 204 | ||
206 | void __init rpc_init_authunix(void) | 205 | int __init rpc_init_authunix(void) |
207 | { | 206 | { |
208 | spin_lock_init(&unix_cred_cache.lock); | 207 | return rpcauth_init_credcache(&unix_auth); |
208 | } | ||
209 | |||
210 | void rpc_destroy_authunix(void) | ||
211 | { | ||
212 | rpcauth_destroy_credcache(&unix_auth); | ||
209 | } | 213 | } |
210 | 214 | ||
211 | const struct rpc_authops authunix_ops = { | 215 | const struct rpc_authops authunix_ops = { |
@@ -219,17 +223,12 @@ const struct rpc_authops authunix_ops = { | |||
219 | }; | 223 | }; |
220 | 224 | ||
221 | static | 225 | static |
222 | struct rpc_cred_cache unix_cred_cache = { | ||
223 | }; | ||
224 | |||
225 | static | ||
226 | struct rpc_auth unix_auth = { | 226 | struct rpc_auth unix_auth = { |
227 | .au_cslack = UNX_WRITESLACK, | 227 | .au_cslack = UNX_WRITESLACK, |
228 | .au_rslack = 2, /* assume AUTH_NULL verf */ | 228 | .au_rslack = 2, /* assume AUTH_NULL verf */ |
229 | .au_ops = &authunix_ops, | 229 | .au_ops = &authunix_ops, |
230 | .au_flavor = RPC_AUTH_UNIX, | 230 | .au_flavor = RPC_AUTH_UNIX, |
231 | .au_count = ATOMIC_INIT(0), | 231 | .au_count = ATOMIC_INIT(0), |
232 | .au_credcache = &unix_cred_cache, | ||
233 | }; | 232 | }; |
234 | 233 | ||
235 | static | 234 | static |
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 58de76c8540c..2b06410e584e 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #include <linux/sunrpc/cache.h> | 34 | #include <linux/sunrpc/cache.h> |
35 | #include <linux/sunrpc/stats.h> | 35 | #include <linux/sunrpc/stats.h> |
36 | #include <linux/sunrpc/rpc_pipe_fs.h> | 36 | #include <linux/sunrpc/rpc_pipe_fs.h> |
37 | #include <linux/smp_lock.h> | ||
38 | 37 | ||
39 | #define RPCDBG_FACILITY RPCDBG_CACHE | 38 | #define RPCDBG_FACILITY RPCDBG_CACHE |
40 | 39 | ||
@@ -320,7 +319,7 @@ static struct cache_detail *current_detail; | |||
320 | static int current_index; | 319 | static int current_index; |
321 | 320 | ||
322 | static void do_cache_clean(struct work_struct *work); | 321 | static void do_cache_clean(struct work_struct *work); |
323 | static DECLARE_DELAYED_WORK(cache_cleaner, do_cache_clean); | 322 | static struct delayed_work cache_cleaner; |
324 | 323 | ||
325 | static void sunrpc_init_cache_detail(struct cache_detail *cd) | 324 | static void sunrpc_init_cache_detail(struct cache_detail *cd) |
326 | { | 325 | { |
@@ -1504,6 +1503,11 @@ static int create_cache_proc_entries(struct cache_detail *cd) | |||
1504 | } | 1503 | } |
1505 | #endif | 1504 | #endif |
1506 | 1505 | ||
1506 | void __init cache_initialize(void) | ||
1507 | { | ||
1508 | INIT_DELAYED_WORK_DEFERRABLE(&cache_cleaner, do_cache_clean); | ||
1509 | } | ||
1510 | |||
1507 | int cache_register(struct cache_detail *cd) | 1511 | int cache_register(struct cache_detail *cd) |
1508 | { | 1512 | { |
1509 | int ret; | 1513 | int ret; |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 756fc324db9e..2388d83b68ff 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -414,6 +414,35 @@ out_no_clnt: | |||
414 | EXPORT_SYMBOL_GPL(rpc_clone_client); | 414 | EXPORT_SYMBOL_GPL(rpc_clone_client); |
415 | 415 | ||
416 | /* | 416 | /* |
417 | * Kill all tasks for the given client. | ||
418 | * XXX: kill their descendants as well? | ||
419 | */ | ||
420 | void rpc_killall_tasks(struct rpc_clnt *clnt) | ||
421 | { | ||
422 | struct rpc_task *rovr; | ||
423 | |||
424 | |||
425 | if (list_empty(&clnt->cl_tasks)) | ||
426 | return; | ||
427 | dprintk("RPC: killing all tasks for client %p\n", clnt); | ||
428 | /* | ||
429 | * Spin lock all_tasks to prevent changes... | ||
430 | */ | ||
431 | spin_lock(&clnt->cl_lock); | ||
432 | list_for_each_entry(rovr, &clnt->cl_tasks, tk_task) { | ||
433 | if (!RPC_IS_ACTIVATED(rovr)) | ||
434 | continue; | ||
435 | if (!(rovr->tk_flags & RPC_TASK_KILLED)) { | ||
436 | rovr->tk_flags |= RPC_TASK_KILLED; | ||
437 | rpc_exit(rovr, -EIO); | ||
438 | rpc_wake_up_queued_task(rovr->tk_waitqueue, rovr); | ||
439 | } | ||
440 | } | ||
441 | spin_unlock(&clnt->cl_lock); | ||
442 | } | ||
443 | EXPORT_SYMBOL_GPL(rpc_killall_tasks); | ||
444 | |||
445 | /* | ||
417 | * Properly shut down an RPC client, terminating all outstanding | 446 | * Properly shut down an RPC client, terminating all outstanding |
418 | * requests. | 447 | * requests. |
419 | */ | 448 | */ |
@@ -538,6 +567,49 @@ out: | |||
538 | } | 567 | } |
539 | EXPORT_SYMBOL_GPL(rpc_bind_new_program); | 568 | EXPORT_SYMBOL_GPL(rpc_bind_new_program); |
540 | 569 | ||
570 | void rpc_task_release_client(struct rpc_task *task) | ||
571 | { | ||
572 | struct rpc_clnt *clnt = task->tk_client; | ||
573 | |||
574 | if (clnt != NULL) { | ||
575 | /* Remove from client task list */ | ||
576 | spin_lock(&clnt->cl_lock); | ||
577 | list_del(&task->tk_task); | ||
578 | spin_unlock(&clnt->cl_lock); | ||
579 | task->tk_client = NULL; | ||
580 | |||
581 | rpc_release_client(clnt); | ||
582 | } | ||
583 | } | ||
584 | |||
585 | static | ||
586 | void rpc_task_set_client(struct rpc_task *task, struct rpc_clnt *clnt) | ||
587 | { | ||
588 | if (clnt != NULL) { | ||
589 | rpc_task_release_client(task); | ||
590 | task->tk_client = clnt; | ||
591 | kref_get(&clnt->cl_kref); | ||
592 | if (clnt->cl_softrtry) | ||
593 | task->tk_flags |= RPC_TASK_SOFT; | ||
594 | /* Add to the client's list of all tasks */ | ||
595 | spin_lock(&clnt->cl_lock); | ||
596 | list_add_tail(&task->tk_task, &clnt->cl_tasks); | ||
597 | spin_unlock(&clnt->cl_lock); | ||
598 | } | ||
599 | } | ||
600 | |||
601 | static void | ||
602 | rpc_task_set_rpc_message(struct rpc_task *task, const struct rpc_message *msg) | ||
603 | { | ||
604 | if (msg != NULL) { | ||
605 | task->tk_msg.rpc_proc = msg->rpc_proc; | ||
606 | task->tk_msg.rpc_argp = msg->rpc_argp; | ||
607 | task->tk_msg.rpc_resp = msg->rpc_resp; | ||
608 | if (msg->rpc_cred != NULL) | ||
609 | task->tk_msg.rpc_cred = get_rpccred(msg->rpc_cred); | ||
610 | } | ||
611 | } | ||
612 | |||
541 | /* | 613 | /* |
542 | * Default callback for async RPC calls | 614 | * Default callback for async RPC calls |
543 | */ | 615 | */ |
@@ -562,6 +634,18 @@ struct rpc_task *rpc_run_task(const struct rpc_task_setup *task_setup_data) | |||
562 | if (IS_ERR(task)) | 634 | if (IS_ERR(task)) |
563 | goto out; | 635 | goto out; |
564 | 636 | ||
637 | rpc_task_set_client(task, task_setup_data->rpc_client); | ||
638 | rpc_task_set_rpc_message(task, task_setup_data->rpc_message); | ||
639 | |||
640 | if (task->tk_status != 0) { | ||
641 | int ret = task->tk_status; | ||
642 | rpc_put_task(task); | ||
643 | return ERR_PTR(ret); | ||
644 | } | ||
645 | |||
646 | if (task->tk_action == NULL) | ||
647 | rpc_call_start(task); | ||
648 | |||
565 | atomic_inc(&task->tk_count); | 649 | atomic_inc(&task->tk_count); |
566 | rpc_execute(task); | 650 | rpc_execute(task); |
567 | out: | 651 | out: |
@@ -756,12 +840,13 @@ EXPORT_SYMBOL_GPL(rpc_force_rebind); | |||
756 | * Restart an (async) RPC call from the call_prepare state. | 840 | * Restart an (async) RPC call from the call_prepare state. |
757 | * Usually called from within the exit handler. | 841 | * Usually called from within the exit handler. |
758 | */ | 842 | */ |
759 | void | 843 | int |
760 | rpc_restart_call_prepare(struct rpc_task *task) | 844 | rpc_restart_call_prepare(struct rpc_task *task) |
761 | { | 845 | { |
762 | if (RPC_ASSASSINATED(task)) | 846 | if (RPC_ASSASSINATED(task)) |
763 | return; | 847 | return 0; |
764 | task->tk_action = rpc_prepare_task; | 848 | task->tk_action = rpc_prepare_task; |
849 | return 1; | ||
765 | } | 850 | } |
766 | EXPORT_SYMBOL_GPL(rpc_restart_call_prepare); | 851 | EXPORT_SYMBOL_GPL(rpc_restart_call_prepare); |
767 | 852 | ||
@@ -769,13 +854,13 @@ EXPORT_SYMBOL_GPL(rpc_restart_call_prepare); | |||
769 | * Restart an (async) RPC call. Usually called from within the | 854 | * Restart an (async) RPC call. Usually called from within the |
770 | * exit handler. | 855 | * exit handler. |
771 | */ | 856 | */ |
772 | void | 857 | int |
773 | rpc_restart_call(struct rpc_task *task) | 858 | rpc_restart_call(struct rpc_task *task) |
774 | { | 859 | { |
775 | if (RPC_ASSASSINATED(task)) | 860 | if (RPC_ASSASSINATED(task)) |
776 | return; | 861 | return 0; |
777 | |||
778 | task->tk_action = call_start; | 862 | task->tk_action = call_start; |
863 | return 1; | ||
779 | } | 864 | } |
780 | EXPORT_SYMBOL_GPL(rpc_restart_call); | 865 | EXPORT_SYMBOL_GPL(rpc_restart_call); |
781 | 866 | ||
@@ -824,11 +909,6 @@ call_reserve(struct rpc_task *task) | |||
824 | { | 909 | { |
825 | dprint_status(task); | 910 | dprint_status(task); |
826 | 911 | ||
827 | if (!rpcauth_uptodatecred(task)) { | ||
828 | task->tk_action = call_refresh; | ||
829 | return; | ||
830 | } | ||
831 | |||
832 | task->tk_status = 0; | 912 | task->tk_status = 0; |
833 | task->tk_action = call_reserveresult; | 913 | task->tk_action = call_reserveresult; |
834 | xprt_reserve(task); | 914 | xprt_reserve(task); |
@@ -892,7 +972,7 @@ call_reserveresult(struct rpc_task *task) | |||
892 | static void | 972 | static void |
893 | call_allocate(struct rpc_task *task) | 973 | call_allocate(struct rpc_task *task) |
894 | { | 974 | { |
895 | unsigned int slack = task->tk_msg.rpc_cred->cr_auth->au_cslack; | 975 | unsigned int slack = task->tk_client->cl_auth->au_cslack; |
896 | struct rpc_rqst *req = task->tk_rqstp; | 976 | struct rpc_rqst *req = task->tk_rqstp; |
897 | struct rpc_xprt *xprt = task->tk_xprt; | 977 | struct rpc_xprt *xprt = task->tk_xprt; |
898 | struct rpc_procinfo *proc = task->tk_msg.rpc_proc; | 978 | struct rpc_procinfo *proc = task->tk_msg.rpc_proc; |
@@ -900,7 +980,7 @@ call_allocate(struct rpc_task *task) | |||
900 | dprint_status(task); | 980 | dprint_status(task); |
901 | 981 | ||
902 | task->tk_status = 0; | 982 | task->tk_status = 0; |
903 | task->tk_action = call_bind; | 983 | task->tk_action = call_refresh; |
904 | 984 | ||
905 | if (req->rq_buffer) | 985 | if (req->rq_buffer) |
906 | return; | 986 | return; |
@@ -937,6 +1017,47 @@ call_allocate(struct rpc_task *task) | |||
937 | rpc_exit(task, -ERESTARTSYS); | 1017 | rpc_exit(task, -ERESTARTSYS); |
938 | } | 1018 | } |
939 | 1019 | ||
1020 | /* | ||
1021 | * 2a. Bind and/or refresh the credentials | ||
1022 | */ | ||
1023 | static void | ||
1024 | call_refresh(struct rpc_task *task) | ||
1025 | { | ||
1026 | dprint_status(task); | ||
1027 | |||
1028 | task->tk_action = call_refreshresult; | ||
1029 | task->tk_status = 0; | ||
1030 | task->tk_client->cl_stats->rpcauthrefresh++; | ||
1031 | rpcauth_refreshcred(task); | ||
1032 | } | ||
1033 | |||
1034 | /* | ||
1035 | * 2b. Process the results of a credential refresh | ||
1036 | */ | ||
1037 | static void | ||
1038 | call_refreshresult(struct rpc_task *task) | ||
1039 | { | ||
1040 | int status = task->tk_status; | ||
1041 | |||
1042 | dprint_status(task); | ||
1043 | |||
1044 | task->tk_status = 0; | ||
1045 | task->tk_action = call_bind; | ||
1046 | if (status >= 0 && rpcauth_uptodatecred(task)) | ||
1047 | return; | ||
1048 | switch (status) { | ||
1049 | case -EACCES: | ||
1050 | rpc_exit(task, -EACCES); | ||
1051 | return; | ||
1052 | case -ENOMEM: | ||
1053 | rpc_exit(task, -ENOMEM); | ||
1054 | return; | ||
1055 | case -ETIMEDOUT: | ||
1056 | rpc_delay(task, 3*HZ); | ||
1057 | } | ||
1058 | task->tk_action = call_refresh; | ||
1059 | } | ||
1060 | |||
940 | static inline int | 1061 | static inline int |
941 | rpc_task_need_encode(struct rpc_task *task) | 1062 | rpc_task_need_encode(struct rpc_task *task) |
942 | { | 1063 | { |
@@ -1472,43 +1593,6 @@ out_retry: | |||
1472 | } | 1593 | } |
1473 | } | 1594 | } |
1474 | 1595 | ||
1475 | /* | ||
1476 | * 8. Refresh the credentials if rejected by the server | ||
1477 | */ | ||
1478 | static void | ||
1479 | call_refresh(struct rpc_task *task) | ||
1480 | { | ||
1481 | dprint_status(task); | ||
1482 | |||
1483 | task->tk_action = call_refreshresult; | ||
1484 | task->tk_status = 0; | ||
1485 | task->tk_client->cl_stats->rpcauthrefresh++; | ||
1486 | rpcauth_refreshcred(task); | ||
1487 | } | ||
1488 | |||
1489 | /* | ||
1490 | * 8a. Process the results of a credential refresh | ||
1491 | */ | ||
1492 | static void | ||
1493 | call_refreshresult(struct rpc_task *task) | ||
1494 | { | ||
1495 | int status = task->tk_status; | ||
1496 | |||
1497 | dprint_status(task); | ||
1498 | |||
1499 | task->tk_status = 0; | ||
1500 | task->tk_action = call_reserve; | ||
1501 | if (status >= 0 && rpcauth_uptodatecred(task)) | ||
1502 | return; | ||
1503 | if (status == -EACCES) { | ||
1504 | rpc_exit(task, -EACCES); | ||
1505 | return; | ||
1506 | } | ||
1507 | task->tk_action = call_refresh; | ||
1508 | if (status != -ETIMEDOUT) | ||
1509 | rpc_delay(task, 3*HZ); | ||
1510 | } | ||
1511 | |||
1512 | static __be32 * | 1596 | static __be32 * |
1513 | rpc_encode_header(struct rpc_task *task) | 1597 | rpc_encode_header(struct rpc_task *task) |
1514 | { | 1598 | { |
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 4a843b883b89..cace6049e4a5 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c | |||
@@ -246,17 +246,8 @@ static inline void rpc_task_set_debuginfo(struct rpc_task *task) | |||
246 | 246 | ||
247 | static void rpc_set_active(struct rpc_task *task) | 247 | static void rpc_set_active(struct rpc_task *task) |
248 | { | 248 | { |
249 | struct rpc_clnt *clnt; | ||
250 | if (test_and_set_bit(RPC_TASK_ACTIVE, &task->tk_runstate) != 0) | ||
251 | return; | ||
252 | rpc_task_set_debuginfo(task); | 249 | rpc_task_set_debuginfo(task); |
253 | /* Add to global list of all tasks */ | 250 | set_bit(RPC_TASK_ACTIVE, &task->tk_runstate); |
254 | clnt = task->tk_client; | ||
255 | if (clnt != NULL) { | ||
256 | spin_lock(&clnt->cl_lock); | ||
257 | list_add_tail(&task->tk_task, &clnt->cl_tasks); | ||
258 | spin_unlock(&clnt->cl_lock); | ||
259 | } | ||
260 | } | 251 | } |
261 | 252 | ||
262 | /* | 253 | /* |
@@ -319,11 +310,6 @@ static void __rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task, | |||
319 | dprintk("RPC: %5u sleep_on(queue \"%s\" time %lu)\n", | 310 | dprintk("RPC: %5u sleep_on(queue \"%s\" time %lu)\n", |
320 | task->tk_pid, rpc_qname(q), jiffies); | 311 | task->tk_pid, rpc_qname(q), jiffies); |
321 | 312 | ||
322 | if (!RPC_IS_ASYNC(task) && !RPC_IS_ACTIVATED(task)) { | ||
323 | printk(KERN_ERR "RPC: Inactive synchronous task put to sleep!\n"); | ||
324 | return; | ||
325 | } | ||
326 | |||
327 | __rpc_add_wait_queue(q, task); | 313 | __rpc_add_wait_queue(q, task); |
328 | 314 | ||
329 | BUG_ON(task->tk_callback != NULL); | 315 | BUG_ON(task->tk_callback != NULL); |
@@ -334,8 +320,8 @@ static void __rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task, | |||
334 | void rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task, | 320 | void rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task, |
335 | rpc_action action) | 321 | rpc_action action) |
336 | { | 322 | { |
337 | /* Mark the task as being activated if so needed */ | 323 | /* We shouldn't ever put an inactive task to sleep */ |
338 | rpc_set_active(task); | 324 | BUG_ON(!RPC_IS_ACTIVATED(task)); |
339 | 325 | ||
340 | /* | 326 | /* |
341 | * Protect the queue operations. | 327 | * Protect the queue operations. |
@@ -406,14 +392,6 @@ void rpc_wake_up_queued_task(struct rpc_wait_queue *queue, struct rpc_task *task | |||
406 | EXPORT_SYMBOL_GPL(rpc_wake_up_queued_task); | 392 | EXPORT_SYMBOL_GPL(rpc_wake_up_queued_task); |
407 | 393 | ||
408 | /* | 394 | /* |
409 | * Wake up the specified task | ||
410 | */ | ||
411 | static void rpc_wake_up_task(struct rpc_task *task) | ||
412 | { | ||
413 | rpc_wake_up_queued_task(task->tk_waitqueue, task); | ||
414 | } | ||
415 | |||
416 | /* | ||
417 | * Wake up the next task on a priority queue. | 395 | * Wake up the next task on a priority queue. |
418 | */ | 396 | */ |
419 | static struct rpc_task * __rpc_wake_up_next_priority(struct rpc_wait_queue *queue) | 397 | static struct rpc_task * __rpc_wake_up_next_priority(struct rpc_wait_queue *queue) |
@@ -600,7 +578,15 @@ void rpc_exit_task(struct rpc_task *task) | |||
600 | } | 578 | } |
601 | } | 579 | } |
602 | } | 580 | } |
603 | EXPORT_SYMBOL_GPL(rpc_exit_task); | 581 | |
582 | void rpc_exit(struct rpc_task *task, int status) | ||
583 | { | ||
584 | task->tk_status = status; | ||
585 | task->tk_action = rpc_exit_task; | ||
586 | if (RPC_IS_QUEUED(task)) | ||
587 | rpc_wake_up_queued_task(task->tk_waitqueue, task); | ||
588 | } | ||
589 | EXPORT_SYMBOL_GPL(rpc_exit); | ||
604 | 590 | ||
605 | void rpc_release_calldata(const struct rpc_call_ops *ops, void *calldata) | 591 | void rpc_release_calldata(const struct rpc_call_ops *ops, void *calldata) |
606 | { | 592 | { |
@@ -690,7 +676,6 @@ static void __rpc_execute(struct rpc_task *task) | |||
690 | dprintk("RPC: %5u got signal\n", task->tk_pid); | 676 | dprintk("RPC: %5u got signal\n", task->tk_pid); |
691 | task->tk_flags |= RPC_TASK_KILLED; | 677 | task->tk_flags |= RPC_TASK_KILLED; |
692 | rpc_exit(task, -ERESTARTSYS); | 678 | rpc_exit(task, -ERESTARTSYS); |
693 | rpc_wake_up_task(task); | ||
694 | } | 679 | } |
695 | rpc_set_running(task); | 680 | rpc_set_running(task); |
696 | dprintk("RPC: %5u sync task resuming\n", task->tk_pid); | 681 | dprintk("RPC: %5u sync task resuming\n", task->tk_pid); |
@@ -714,8 +699,9 @@ static void __rpc_execute(struct rpc_task *task) | |||
714 | void rpc_execute(struct rpc_task *task) | 699 | void rpc_execute(struct rpc_task *task) |
715 | { | 700 | { |
716 | rpc_set_active(task); | 701 | rpc_set_active(task); |
717 | rpc_set_running(task); | 702 | rpc_make_runnable(task); |
718 | __rpc_execute(task); | 703 | if (!RPC_IS_ASYNC(task)) |
704 | __rpc_execute(task); | ||
719 | } | 705 | } |
720 | 706 | ||
721 | static void rpc_async_schedule(struct work_struct *work) | 707 | static void rpc_async_schedule(struct work_struct *work) |
@@ -808,26 +794,9 @@ static void rpc_init_task(struct rpc_task *task, const struct rpc_task_setup *ta | |||
808 | /* Initialize workqueue for async tasks */ | 794 | /* Initialize workqueue for async tasks */ |
809 | task->tk_workqueue = task_setup_data->workqueue; | 795 | task->tk_workqueue = task_setup_data->workqueue; |
810 | 796 | ||
811 | task->tk_client = task_setup_data->rpc_client; | ||
812 | if (task->tk_client != NULL) { | ||
813 | kref_get(&task->tk_client->cl_kref); | ||
814 | if (task->tk_client->cl_softrtry) | ||
815 | task->tk_flags |= RPC_TASK_SOFT; | ||
816 | } | ||
817 | |||
818 | if (task->tk_ops->rpc_call_prepare != NULL) | 797 | if (task->tk_ops->rpc_call_prepare != NULL) |
819 | task->tk_action = rpc_prepare_task; | 798 | task->tk_action = rpc_prepare_task; |
820 | 799 | ||
821 | if (task_setup_data->rpc_message != NULL) { | ||
822 | task->tk_msg.rpc_proc = task_setup_data->rpc_message->rpc_proc; | ||
823 | task->tk_msg.rpc_argp = task_setup_data->rpc_message->rpc_argp; | ||
824 | task->tk_msg.rpc_resp = task_setup_data->rpc_message->rpc_resp; | ||
825 | /* Bind the user cred */ | ||
826 | rpcauth_bindcred(task, task_setup_data->rpc_message->rpc_cred, task_setup_data->flags); | ||
827 | if (task->tk_action == NULL) | ||
828 | rpc_call_start(task); | ||
829 | } | ||
830 | |||
831 | /* starting timestamp */ | 800 | /* starting timestamp */ |
832 | task->tk_start = ktime_get(); | 801 | task->tk_start = ktime_get(); |
833 | 802 | ||
@@ -896,11 +865,8 @@ void rpc_put_task(struct rpc_task *task) | |||
896 | if (task->tk_rqstp) | 865 | if (task->tk_rqstp) |
897 | xprt_release(task); | 866 | xprt_release(task); |
898 | if (task->tk_msg.rpc_cred) | 867 | if (task->tk_msg.rpc_cred) |
899 | rpcauth_unbindcred(task); | 868 | put_rpccred(task->tk_msg.rpc_cred); |
900 | if (task->tk_client) { | 869 | rpc_task_release_client(task); |
901 | rpc_release_client(task->tk_client); | ||
902 | task->tk_client = NULL; | ||
903 | } | ||
904 | if (task->tk_workqueue != NULL) { | 870 | if (task->tk_workqueue != NULL) { |
905 | INIT_WORK(&task->u.tk_work, rpc_async_release); | 871 | INIT_WORK(&task->u.tk_work, rpc_async_release); |
906 | queue_work(task->tk_workqueue, &task->u.tk_work); | 872 | queue_work(task->tk_workqueue, &task->u.tk_work); |
@@ -913,13 +879,6 @@ static void rpc_release_task(struct rpc_task *task) | |||
913 | { | 879 | { |
914 | dprintk("RPC: %5u release task\n", task->tk_pid); | 880 | dprintk("RPC: %5u release task\n", task->tk_pid); |
915 | 881 | ||
916 | if (!list_empty(&task->tk_task)) { | ||
917 | struct rpc_clnt *clnt = task->tk_client; | ||
918 | /* Remove from client task list */ | ||
919 | spin_lock(&clnt->cl_lock); | ||
920 | list_del(&task->tk_task); | ||
921 | spin_unlock(&clnt->cl_lock); | ||
922 | } | ||
923 | BUG_ON (RPC_IS_QUEUED(task)); | 882 | BUG_ON (RPC_IS_QUEUED(task)); |
924 | 883 | ||
925 | /* Wake up anyone who is waiting for task completion */ | 884 | /* Wake up anyone who is waiting for task completion */ |
@@ -928,35 +887,6 @@ static void rpc_release_task(struct rpc_task *task) | |||
928 | rpc_put_task(task); | 887 | rpc_put_task(task); |
929 | } | 888 | } |
930 | 889 | ||
931 | /* | ||
932 | * Kill all tasks for the given client. | ||
933 | * XXX: kill their descendants as well? | ||
934 | */ | ||
935 | void rpc_killall_tasks(struct rpc_clnt *clnt) | ||
936 | { | ||
937 | struct rpc_task *rovr; | ||
938 | |||
939 | |||
940 | if (list_empty(&clnt->cl_tasks)) | ||
941 | return; | ||
942 | dprintk("RPC: killing all tasks for client %p\n", clnt); | ||
943 | /* | ||
944 | * Spin lock all_tasks to prevent changes... | ||
945 | */ | ||
946 | spin_lock(&clnt->cl_lock); | ||
947 | list_for_each_entry(rovr, &clnt->cl_tasks, tk_task) { | ||
948 | if (! RPC_IS_ACTIVATED(rovr)) | ||
949 | continue; | ||
950 | if (!(rovr->tk_flags & RPC_TASK_KILLED)) { | ||
951 | rovr->tk_flags |= RPC_TASK_KILLED; | ||
952 | rpc_exit(rovr, -EIO); | ||
953 | rpc_wake_up_task(rovr); | ||
954 | } | ||
955 | } | ||
956 | spin_unlock(&clnt->cl_lock); | ||
957 | } | ||
958 | EXPORT_SYMBOL_GPL(rpc_killall_tasks); | ||
959 | |||
960 | int rpciod_up(void) | 890 | int rpciod_up(void) |
961 | { | 891 | { |
962 | return try_module_get(THIS_MODULE) ? 0 : -EINVAL; | 892 | return try_module_get(THIS_MODULE) ? 0 : -EINVAL; |
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c index f438347d817b..c0d085013a2b 100644 --- a/net/sunrpc/sunrpc_syms.c +++ b/net/sunrpc/sunrpc_syms.c | |||
@@ -33,21 +33,27 @@ init_sunrpc(void) | |||
33 | if (err) | 33 | if (err) |
34 | goto out; | 34 | goto out; |
35 | err = rpc_init_mempool(); | 35 | err = rpc_init_mempool(); |
36 | if (err) { | 36 | if (err) |
37 | unregister_rpc_pipefs(); | 37 | goto out2; |
38 | goto out; | 38 | err = rpcauth_init_module(); |
39 | } | 39 | if (err) |
40 | goto out3; | ||
40 | #ifdef RPC_DEBUG | 41 | #ifdef RPC_DEBUG |
41 | rpc_register_sysctl(); | 42 | rpc_register_sysctl(); |
42 | #endif | 43 | #endif |
43 | #ifdef CONFIG_PROC_FS | 44 | #ifdef CONFIG_PROC_FS |
44 | rpc_proc_init(); | 45 | rpc_proc_init(); |
45 | #endif | 46 | #endif |
47 | cache_initialize(); | ||
46 | cache_register(&ip_map_cache); | 48 | cache_register(&ip_map_cache); |
47 | cache_register(&unix_gid_cache); | 49 | cache_register(&unix_gid_cache); |
48 | svc_init_xprt_sock(); /* svc sock transport */ | 50 | svc_init_xprt_sock(); /* svc sock transport */ |
49 | init_socket_xprt(); /* clnt sock transport */ | 51 | init_socket_xprt(); /* clnt sock transport */ |
50 | rpcauth_init_module(); | 52 | return 0; |
53 | out3: | ||
54 | rpc_destroy_mempool(); | ||
55 | out2: | ||
56 | unregister_rpc_pipefs(); | ||
51 | out: | 57 | out: |
52 | return err; | 58 | return err; |
53 | } | 59 | } |
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index dcd0132396ba..970fb00f388c 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
@@ -1032,6 +1032,8 @@ void xprt_release(struct rpc_task *task) | |||
1032 | spin_unlock_bh(&xprt->transport_lock); | 1032 | spin_unlock_bh(&xprt->transport_lock); |
1033 | if (req->rq_buffer) | 1033 | if (req->rq_buffer) |
1034 | xprt->ops->buf_free(req->rq_buffer); | 1034 | xprt->ops->buf_free(req->rq_buffer); |
1035 | if (req->rq_cred != NULL) | ||
1036 | put_rpccred(req->rq_cred); | ||
1035 | task->tk_rqstp = NULL; | 1037 | task->tk_rqstp = NULL; |
1036 | if (req->rq_release_snd_buf) | 1038 | if (req->rq_release_snd_buf) |
1037 | req->rq_release_snd_buf(req); | 1039 | req->rq_release_snd_buf(req); |
@@ -1129,6 +1131,7 @@ static void xprt_destroy(struct kref *kref) | |||
1129 | rpc_destroy_wait_queue(&xprt->sending); | 1131 | rpc_destroy_wait_queue(&xprt->sending); |
1130 | rpc_destroy_wait_queue(&xprt->resend); | 1132 | rpc_destroy_wait_queue(&xprt->resend); |
1131 | rpc_destroy_wait_queue(&xprt->backlog); | 1133 | rpc_destroy_wait_queue(&xprt->backlog); |
1134 | cancel_work_sync(&xprt->task_cleanup); | ||
1132 | /* | 1135 | /* |
1133 | * Tear down transport state and free the rpc_xprt | 1136 | * Tear down transport state and free the rpc_xprt |
1134 | */ | 1137 | */ |
diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c index e5e28d1946a4..2ac3f6e8adff 100644 --- a/net/sunrpc/xprtrdma/rpc_rdma.c +++ b/net/sunrpc/xprtrdma/rpc_rdma.c | |||
@@ -249,6 +249,8 @@ rpcrdma_create_chunks(struct rpc_rqst *rqst, struct xdr_buf *target, | |||
249 | req->rl_nchunks = nchunks; | 249 | req->rl_nchunks = nchunks; |
250 | 250 | ||
251 | BUG_ON(nchunks == 0); | 251 | BUG_ON(nchunks == 0); |
252 | BUG_ON((r_xprt->rx_ia.ri_memreg_strategy == RPCRDMA_FRMR) | ||
253 | && (nchunks > 3)); | ||
252 | 254 | ||
253 | /* | 255 | /* |
254 | * finish off header. If write, marshal discrim and nchunks. | 256 | * finish off header. If write, marshal discrim and nchunks. |
diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c index 27015c6d8eb5..5f4c7b3bc711 100644 --- a/net/sunrpc/xprtrdma/verbs.c +++ b/net/sunrpc/xprtrdma/verbs.c | |||
@@ -650,10 +650,22 @@ rpcrdma_ep_create(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia, | |||
650 | ep->rep_attr.cap.max_send_wr = cdata->max_requests; | 650 | ep->rep_attr.cap.max_send_wr = cdata->max_requests; |
651 | switch (ia->ri_memreg_strategy) { | 651 | switch (ia->ri_memreg_strategy) { |
652 | case RPCRDMA_FRMR: | 652 | case RPCRDMA_FRMR: |
653 | /* Add room for frmr register and invalidate WRs */ | 653 | /* Add room for frmr register and invalidate WRs. |
654 | ep->rep_attr.cap.max_send_wr *= 3; | 654 | * 1. FRMR reg WR for head |
655 | if (ep->rep_attr.cap.max_send_wr > devattr.max_qp_wr) | 655 | * 2. FRMR invalidate WR for head |
656 | return -EINVAL; | 656 | * 3. FRMR reg WR for pagelist |
657 | * 4. FRMR invalidate WR for pagelist | ||
658 | * 5. FRMR reg WR for tail | ||
659 | * 6. FRMR invalidate WR for tail | ||
660 | * 7. The RDMA_SEND WR | ||
661 | */ | ||
662 | ep->rep_attr.cap.max_send_wr *= 7; | ||
663 | if (ep->rep_attr.cap.max_send_wr > devattr.max_qp_wr) { | ||
664 | cdata->max_requests = devattr.max_qp_wr / 7; | ||
665 | if (!cdata->max_requests) | ||
666 | return -EINVAL; | ||
667 | ep->rep_attr.cap.max_send_wr = cdata->max_requests * 7; | ||
668 | } | ||
657 | break; | 669 | break; |
658 | case RPCRDMA_MEMWINDOWS_ASYNC: | 670 | case RPCRDMA_MEMWINDOWS_ASYNC: |
659 | case RPCRDMA_MEMWINDOWS: | 671 | case RPCRDMA_MEMWINDOWS: |
@@ -1490,7 +1502,7 @@ rpcrdma_register_frmr_external(struct rpcrdma_mr_seg *seg, | |||
1490 | memset(&frmr_wr, 0, sizeof frmr_wr); | 1502 | memset(&frmr_wr, 0, sizeof frmr_wr); |
1491 | frmr_wr.opcode = IB_WR_FAST_REG_MR; | 1503 | frmr_wr.opcode = IB_WR_FAST_REG_MR; |
1492 | frmr_wr.send_flags = 0; /* unsignaled */ | 1504 | frmr_wr.send_flags = 0; /* unsignaled */ |
1493 | frmr_wr.wr.fast_reg.iova_start = (unsigned long)seg1->mr_dma; | 1505 | frmr_wr.wr.fast_reg.iova_start = seg1->mr_dma; |
1494 | frmr_wr.wr.fast_reg.page_list = seg1->mr_chunk.rl_mw->r.frmr.fr_pgl; | 1506 | frmr_wr.wr.fast_reg.page_list = seg1->mr_chunk.rl_mw->r.frmr.fr_pgl; |
1495 | frmr_wr.wr.fast_reg.page_list_len = i; | 1507 | frmr_wr.wr.fast_reg.page_list_len = i; |
1496 | frmr_wr.wr.fast_reg.page_shift = PAGE_SHIFT; | 1508 | frmr_wr.wr.fast_reg.page_shift = PAGE_SHIFT; |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 7ca65c7005ea..b6309db56226 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -1305,10 +1305,11 @@ static void xs_tcp_state_change(struct sock *sk) | |||
1305 | if (!(xprt = xprt_from_sock(sk))) | 1305 | if (!(xprt = xprt_from_sock(sk))) |
1306 | goto out; | 1306 | goto out; |
1307 | dprintk("RPC: xs_tcp_state_change client %p...\n", xprt); | 1307 | dprintk("RPC: xs_tcp_state_change client %p...\n", xprt); |
1308 | dprintk("RPC: state %x conn %d dead %d zapped %d\n", | 1308 | dprintk("RPC: state %x conn %d dead %d zapped %d sk_shutdown %d\n", |
1309 | sk->sk_state, xprt_connected(xprt), | 1309 | sk->sk_state, xprt_connected(xprt), |
1310 | sock_flag(sk, SOCK_DEAD), | 1310 | sock_flag(sk, SOCK_DEAD), |
1311 | sock_flag(sk, SOCK_ZAPPED)); | 1311 | sock_flag(sk, SOCK_ZAPPED), |
1312 | sk->sk_shutdown); | ||
1312 | 1313 | ||
1313 | switch (sk->sk_state) { | 1314 | switch (sk->sk_state) { |
1314 | case TCP_ESTABLISHED: | 1315 | case TCP_ESTABLISHED: |
@@ -1779,10 +1780,25 @@ static void xs_tcp_reuse_connection(struct rpc_xprt *xprt, struct sock_xprt *tra | |||
1779 | { | 1780 | { |
1780 | unsigned int state = transport->inet->sk_state; | 1781 | unsigned int state = transport->inet->sk_state; |
1781 | 1782 | ||
1782 | if (state == TCP_CLOSE && transport->sock->state == SS_UNCONNECTED) | 1783 | if (state == TCP_CLOSE && transport->sock->state == SS_UNCONNECTED) { |
1783 | return; | 1784 | /* we don't need to abort the connection if the socket |
1784 | if ((1 << state) & (TCPF_ESTABLISHED|TCPF_SYN_SENT)) | 1785 | * hasn't undergone a shutdown |
1785 | return; | 1786 | */ |
1787 | if (transport->inet->sk_shutdown == 0) | ||
1788 | return; | ||
1789 | dprintk("RPC: %s: TCP_CLOSEd and sk_shutdown set to %d\n", | ||
1790 | __func__, transport->inet->sk_shutdown); | ||
1791 | } | ||
1792 | if ((1 << state) & (TCPF_ESTABLISHED|TCPF_SYN_SENT)) { | ||
1793 | /* we don't need to abort the connection if the socket | ||
1794 | * hasn't undergone a shutdown | ||
1795 | */ | ||
1796 | if (transport->inet->sk_shutdown == 0) | ||
1797 | return; | ||
1798 | dprintk("RPC: %s: ESTABLISHED/SYN_SENT " | ||
1799 | "sk_shutdown set to %d\n", | ||
1800 | __func__, transport->inet->sk_shutdown); | ||
1801 | } | ||
1786 | xs_abort_connection(xprt, transport); | 1802 | xs_abort_connection(xprt, transport); |
1787 | } | 1803 | } |
1788 | 1804 | ||
@@ -2577,7 +2593,8 @@ void cleanup_socket_xprt(void) | |||
2577 | xprt_unregister_transport(&xs_bc_tcp_transport); | 2593 | xprt_unregister_transport(&xs_bc_tcp_transport); |
2578 | } | 2594 | } |
2579 | 2595 | ||
2580 | static int param_set_uint_minmax(const char *val, struct kernel_param *kp, | 2596 | static int param_set_uint_minmax(const char *val, |
2597 | const struct kernel_param *kp, | ||
2581 | unsigned int min, unsigned int max) | 2598 | unsigned int min, unsigned int max) |
2582 | { | 2599 | { |
2583 | unsigned long num; | 2600 | unsigned long num; |
@@ -2592,34 +2609,37 @@ static int param_set_uint_minmax(const char *val, struct kernel_param *kp, | |||
2592 | return 0; | 2609 | return 0; |
2593 | } | 2610 | } |
2594 | 2611 | ||
2595 | static int param_set_portnr(const char *val, struct kernel_param *kp) | 2612 | static int param_set_portnr(const char *val, const struct kernel_param *kp) |
2596 | { | 2613 | { |
2597 | return param_set_uint_minmax(val, kp, | 2614 | return param_set_uint_minmax(val, kp, |
2598 | RPC_MIN_RESVPORT, | 2615 | RPC_MIN_RESVPORT, |
2599 | RPC_MAX_RESVPORT); | 2616 | RPC_MAX_RESVPORT); |
2600 | } | 2617 | } |
2601 | 2618 | ||
2602 | static int param_get_portnr(char *buffer, struct kernel_param *kp) | 2619 | static struct kernel_param_ops param_ops_portnr = { |
2603 | { | 2620 | .set = param_set_portnr, |
2604 | return param_get_uint(buffer, kp); | 2621 | .get = param_get_uint, |
2605 | } | 2622 | }; |
2623 | |||
2606 | #define param_check_portnr(name, p) \ | 2624 | #define param_check_portnr(name, p) \ |
2607 | __param_check(name, p, unsigned int); | 2625 | __param_check(name, p, unsigned int); |
2608 | 2626 | ||
2609 | module_param_named(min_resvport, xprt_min_resvport, portnr, 0644); | 2627 | module_param_named(min_resvport, xprt_min_resvport, portnr, 0644); |
2610 | module_param_named(max_resvport, xprt_max_resvport, portnr, 0644); | 2628 | module_param_named(max_resvport, xprt_max_resvport, portnr, 0644); |
2611 | 2629 | ||
2612 | static int param_set_slot_table_size(const char *val, struct kernel_param *kp) | 2630 | static int param_set_slot_table_size(const char *val, |
2631 | const struct kernel_param *kp) | ||
2613 | { | 2632 | { |
2614 | return param_set_uint_minmax(val, kp, | 2633 | return param_set_uint_minmax(val, kp, |
2615 | RPC_MIN_SLOT_TABLE, | 2634 | RPC_MIN_SLOT_TABLE, |
2616 | RPC_MAX_SLOT_TABLE); | 2635 | RPC_MAX_SLOT_TABLE); |
2617 | } | 2636 | } |
2618 | 2637 | ||
2619 | static int param_get_slot_table_size(char *buffer, struct kernel_param *kp) | 2638 | static struct kernel_param_ops param_ops_slot_table_size = { |
2620 | { | 2639 | .set = param_set_slot_table_size, |
2621 | return param_get_uint(buffer, kp); | 2640 | .get = param_get_uint, |
2622 | } | 2641 | }; |
2642 | |||
2623 | #define param_check_slot_table_size(name, p) \ | 2643 | #define param_check_slot_table_size(name, p) \ |
2624 | __param_check(name, p, unsigned int); | 2644 | __param_check(name, p, unsigned int); |
2625 | 2645 | ||