aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/Kconfig1
-rw-r--r--net/Makefile1
-rw-r--r--net/dns_resolver/Kconfig27
-rw-r--r--net/dns_resolver/Makefile7
-rw-r--r--net/dns_resolver/dns_key.c293
-rw-r--r--net/dns_resolver/dns_query.c165
-rw-r--r--net/dns_resolver/internal.h44
-rw-r--r--net/mac80211/rate.c2
-rw-r--r--net/rxrpc/ar-internal.h16
-rw-r--r--net/sunrpc/Kconfig9
-rw-r--r--net/sunrpc/auth.c162
-rw-r--r--net/sunrpc/auth_generic.c23
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c29
-rw-r--r--net/sunrpc/auth_null.c2
-rw-r--r--net/sunrpc/auth_unix.c21
-rw-r--r--net/sunrpc/cache.c8
-rw-r--r--net/sunrpc/clnt.c182
-rw-r--r--net/sunrpc/sched.c104
-rw-r--r--net/sunrpc/sunrpc_syms.c16
-rw-r--r--net/sunrpc/xprt.c3
-rw-r--r--net/sunrpc/xprtrdma/rpc_rdma.c2
-rw-r--r--net/sunrpc/xprtrdma/verbs.c22
-rw-r--r--net/sunrpc/xprtsock.c54
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"
213source "net/ieee802154/Kconfig" 213source "net/ieee802154/Kconfig"
214source "net/sched/Kconfig" 214source "net/sched/Kconfig"
215source "net/dcb/Kconfig" 215source "net/dcb/Kconfig"
216source "net/dns_resolver/Kconfig"
216 217
217config RPS 218config 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)
67obj-$(CONFIG_SYSCTL) += sysctl_net.o 67obj-$(CONFIG_SYSCTL) += sysctl_net.o
68endif 68endif
69obj-$(CONFIG_WIMAX) += wimax/ 69obj-$(CONFIG_WIMAX) += wimax/
70obj-$(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#
4config 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
5obj-$(CONFIG_DNS_RESOLVER) += dns_resolver.o
6
7dns_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
37MODULE_DESCRIPTION("DNS Resolver");
38MODULE_AUTHOR("Wang Lei");
39MODULE_LICENSE("GPL");
40
41unsigned dns_resolver_debug;
42module_param_named(debug, dns_resolver_debug, uint, S_IWUSR | S_IRUGO);
43MODULE_PARM_DESC(debug, "DNS Resolver debugging mask");
44
45const 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 */
61static int
62dns_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 */
174static int
175dns_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
199matched:
200 ret = 1;
201no_match:
202 kleave(" = %d", ret);
203 return ret;
204}
205
206/*
207 * Describe a DNS key
208 */
209static 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
220struct 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
230static 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
275failed_put_key:
276 key_put(keyring);
277failed_put_cred:
278 put_cred(cred);
279 return ret;
280}
281
282static 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
291module_init(init_dns_resolver)
292module_exit(exit_dns_resolver)
293MODULE_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 */
70int 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;
158put:
159 up_read(&rkey->sem);
160 key_put(rkey);
161out:
162 kleave(" = %d", ret);
163 return ret;
164}
165EXPORT_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 */
29extern const struct cred *dns_resolver_cache;
30
31/*
32 * debug tracing
33 */
34extern unsigned dns_resolver_debug;
35
36#define kdebug(FMT, ...) \
37do { \
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 */
601static inline __attribute__((format(printf,1,2)))
602void _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
20config RPCSEC_GSS_KRB5 20config 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
39config RPCSEC_GSS_SPKM3 40config 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)
23struct rpc_cred_cache {
24 struct hlist_head *hashtable;
25 unsigned int hashbits;
26 spinlock_t lock;
27};
28
29static unsigned int auth_hashbits = RPC_CREDCACHE_DEFAULT_HASHBITS;
30
22static DEFINE_SPINLOCK(rpc_authflavor_lock); 31static DEFINE_SPINLOCK(rpc_authflavor_lock);
23static const struct rpc_authops *auth_flavors[RPC_AUTH_MAXFLAVOR] = { 32static 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] = {
29static LIST_HEAD(cred_unused); 38static LIST_HEAD(cred_unused);
30static unsigned long number_cred_unused; 39static unsigned long number_cred_unused;
31 40
41#define MAX_HASHTABLE_BITS (10)
42static 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;
60out_inval:
61 return -EINVAL;
62}
63
64static 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
74static struct kernel_param_ops param_ops_hashtbl_sz = {
75 .set = param_set_hashtbl_sz,
76 .get = param_get_hashtbl_sz,
77};
78
79module_param_named(auth_hashtable_size, auth_hashbits, hashtbl_sz, 0644);
80MODULE_PARM_DESC(auth_hashtable_size, "RPC credential cache hashtable size");
81
32static u32 82static u32
33pseudoflavor_to_flavor(u32 flavor) { 83pseudoflavor_to_flavor(u32 flavor) {
34 if (flavor >= RPC_AUTH_MAXFLAVOR) 84 if (flavor >= RPC_AUTH_MAXFLAVOR)
@@ -145,16 +195,23 @@ int
145rpcauth_init_credcache(struct rpc_auth *auth) 195rpcauth_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;
211out_nohashtbl:
212 kfree(new);
213out_nocache:
214 return -ENOMEM;
158} 215}
159EXPORT_SYMBOL_GPL(rpcauth_init_credcache); 216EXPORT_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}
391EXPORT_SYMBOL_GPL(rpcauth_init_cred); 450EXPORT_SYMBOL_GPL(rpcauth_init_cred);
392 451
393void 452struct rpc_cred *
394rpcauth_generic_bind_cred(struct rpc_task *task, struct rpc_cred *cred, int lookupflags) 453rpcauth_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}
400EXPORT_SYMBOL_GPL(rpcauth_generic_bind_cred); 459EXPORT_SYMBOL_GPL(rpcauth_generic_bind_cred);
401 460
402static void 461static struct rpc_cred *
403rpcauth_bind_root_cred(struct rpc_task *task, int lookupflags) 462rpcauth_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
421static void 475static struct rpc_cred *
422rpcauth_bind_new_cred(struct rpc_task *task, int lookupflags) 476rpcauth_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
436void 485static int
437rpcauth_bindcred(struct rpc_task *task, struct rpc_cred *cred, int flags) 486rpcauth_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
451void 508void
@@ -484,22 +541,10 @@ out_nodestroy:
484} 541}
485EXPORT_SYMBOL_GPL(put_rpccred); 542EXPORT_SYMBOL_GPL(put_rpccred);
486 543
487void
488rpcauth_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 *
500rpcauth_marshcred(struct rpc_task *task, __be32 *p) 545rpcauth_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 *
511rpcauth_checkverf(struct rpc_task *task, __be32 *p) 556rpcauth_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
522rpcauth_wrap_req(struct rpc_task *task, kxdrproc_t encode, void *rqstp, 567rpcauth_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
536rpcauth_unwrap_resp(struct rpc_task *task, kxdrproc_t decode, void *rqstp, 581rpcauth_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,
550int 595int
551rpcauth_refreshcred(struct rpc_task *task) 596rpcauth_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);
612out:
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)
565void 618void
566rpcauth_invalcred(struct rpc_task *task) 619rpcauth_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)
576int 629int
577rpcauth_uptodatecred(struct rpc_task *task) 630rpcauth_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
590void __init rpcauth_init_module(void) 643int __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;
655out2:
656 rpc_destroy_authunix();
657out1:
658 return err;
595} 659}
596 660
597void __exit rpcauth_remove_module(void) 661void __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
29static struct rpc_auth generic_auth; 29static struct rpc_auth generic_auth;
30static struct rpc_cred_cache generic_cred_cache;
31static const struct rpc_credops generic_credops; 30static const struct rpc_credops generic_credops;
32 31
33/* 32/*
@@ -55,18 +54,13 @@ struct rpc_cred *rpc_lookup_machine_cred(void)
55} 54}
56EXPORT_SYMBOL_GPL(rpc_lookup_machine_cred); 55EXPORT_SYMBOL_GPL(rpc_lookup_machine_cred);
57 56
58static void 57static struct rpc_cred *generic_bind_cred(struct rpc_task *task,
59generic_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
162void __init rpc_init_generic_auth(void) 156int __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
167void __exit rpc_destroy_generic_auth(void) 161void __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
172static struct rpc_cred_cache generic_cred_cache = {
173 {{ NULL, },},
174};
175
176static const struct rpc_authops generic_auth_ops = { 166static 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 = {
183static struct rpc_auth generic_auth = { 173static 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
189static const struct rpc_credops generic_credops = { 178static 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
373static void 373static void
374gss_upcall_callback(struct rpc_task *task) 374gss_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)
502static inline int 502static inline int
503gss_refresh_upcall(struct rpc_task *task) 503gss_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)
942static void 943static void
943gss_free_ctx(struct gss_cl_ctx *ctx) 944gss_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
954static void 949static void
@@ -1064,12 +1059,12 @@ out:
1064static __be32 * 1059static __be32 *
1065gss_marshal(struct rpc_task *task, __be32 *p) 1060gss_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
1120static int gss_renew_cred(struct rpc_task *task) 1115static 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)
1161static int 1156static int
1162gss_refresh(struct rpc_task *task) 1157gss_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)
1191static __be32 * 1186static __be32 *
1192gss_validate(struct rpc_task *task, __be32 *p) 1187gss_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
1400gss_wrap_req(struct rpc_task *task, 1395gss_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
1503gss_unwrap_resp(struct rpc_task *task, 1498gss_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)
75static int 75static int
76nul_refresh(struct rpc_task *task) 76nul_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
31static struct rpc_auth unix_auth; 31static struct rpc_auth unix_auth;
32static struct rpc_cred_cache unix_cred_cache;
33static const struct rpc_credops unix_credops; 32static const struct rpc_credops unix_credops;
34 33
35static struct rpc_auth * 34static struct rpc_auth *
@@ -141,7 +140,7 @@ static __be32 *
141unx_marshal(struct rpc_task *task, __be32 *p) 140unx_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)
174static int 173static int
175unx_refresh(struct rpc_task *task) 174unx_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
206void __init rpc_init_authunix(void) 205int __init rpc_init_authunix(void)
207{ 206{
208 spin_lock_init(&unix_cred_cache.lock); 207 return rpcauth_init_credcache(&unix_auth);
208}
209
210void rpc_destroy_authunix(void)
211{
212 rpcauth_destroy_credcache(&unix_auth);
209} 213}
210 214
211const struct rpc_authops authunix_ops = { 215const struct rpc_authops authunix_ops = {
@@ -219,17 +223,12 @@ const struct rpc_authops authunix_ops = {
219}; 223};
220 224
221static 225static
222struct rpc_cred_cache unix_cred_cache = {
223};
224
225static
226struct rpc_auth unix_auth = { 226struct 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
235static 234static
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;
320static int current_index; 319static int current_index;
321 320
322static void do_cache_clean(struct work_struct *work); 321static void do_cache_clean(struct work_struct *work);
323static DECLARE_DELAYED_WORK(cache_cleaner, do_cache_clean); 322static struct delayed_work cache_cleaner;
324 323
325static void sunrpc_init_cache_detail(struct cache_detail *cd) 324static 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
1506void __init cache_initialize(void)
1507{
1508 INIT_DELAYED_WORK_DEFERRABLE(&cache_cleaner, do_cache_clean);
1509}
1510
1507int cache_register(struct cache_detail *cd) 1511int 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:
414EXPORT_SYMBOL_GPL(rpc_clone_client); 414EXPORT_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 */
420void 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}
443EXPORT_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}
539EXPORT_SYMBOL_GPL(rpc_bind_new_program); 568EXPORT_SYMBOL_GPL(rpc_bind_new_program);
540 569
570void 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
585static
586void 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
601static void
602rpc_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);
567out: 651out:
@@ -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 */
759void 843int
760rpc_restart_call_prepare(struct rpc_task *task) 844rpc_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}
766EXPORT_SYMBOL_GPL(rpc_restart_call_prepare); 851EXPORT_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 */
772void 857int
773rpc_restart_call(struct rpc_task *task) 858rpc_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}
780EXPORT_SYMBOL_GPL(rpc_restart_call); 865EXPORT_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)
892static void 972static void
893call_allocate(struct rpc_task *task) 973call_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 */
1023static void
1024call_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 */
1037static void
1038call_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
940static inline int 1061static inline int
941rpc_task_need_encode(struct rpc_task *task) 1062rpc_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 */
1478static void
1479call_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 */
1492static void
1493call_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
1512static __be32 * 1596static __be32 *
1513rpc_encode_header(struct rpc_task *task) 1597rpc_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
247static void rpc_set_active(struct rpc_task *task) 247static 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,
334void rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task, 320void 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
406EXPORT_SYMBOL_GPL(rpc_wake_up_queued_task); 392EXPORT_SYMBOL_GPL(rpc_wake_up_queued_task);
407 393
408/* 394/*
409 * Wake up the specified task
410 */
411static 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 */
419static struct rpc_task * __rpc_wake_up_next_priority(struct rpc_wait_queue *queue) 397static 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}
603EXPORT_SYMBOL_GPL(rpc_exit_task); 581
582void 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}
589EXPORT_SYMBOL_GPL(rpc_exit);
604 590
605void rpc_release_calldata(const struct rpc_call_ops *ops, void *calldata) 591void 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)
714void rpc_execute(struct rpc_task *task) 699void 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
721static void rpc_async_schedule(struct work_struct *work) 707static 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 */
935void 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}
958EXPORT_SYMBOL_GPL(rpc_killall_tasks);
959
960int rpciod_up(void) 890int 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;
53out3:
54 rpc_destroy_mempool();
55out2:
56 unregister_rpc_pipefs();
51out: 57out:
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
2580static int param_set_uint_minmax(const char *val, struct kernel_param *kp, 2596static 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
2595static int param_set_portnr(const char *val, struct kernel_param *kp) 2612static 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
2602static int param_get_portnr(char *buffer, struct kernel_param *kp) 2619static 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
2609module_param_named(min_resvport, xprt_min_resvport, portnr, 0644); 2627module_param_named(min_resvport, xprt_min_resvport, portnr, 0644);
2610module_param_named(max_resvport, xprt_max_resvport, portnr, 0644); 2628module_param_named(max_resvport, xprt_max_resvport, portnr, 0644);
2611 2629
2612static int param_set_slot_table_size(const char *val, struct kernel_param *kp) 2630static 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
2619static int param_get_slot_table_size(char *buffer, struct kernel_param *kp) 2638static 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