diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /net/sunrpc | |
parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) |
Patched in Tegra support.
Diffstat (limited to 'net/sunrpc')
42 files changed, 1678 insertions, 2930 deletions
diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig index 03d03e37a7d..ffd243d0918 100644 --- a/net/sunrpc/Kconfig +++ b/net/sunrpc/Kconfig | |||
@@ -21,11 +21,6 @@ config SUNRPC_XPRT_RDMA | |||
21 | 21 | ||
22 | If unsure, say N. | 22 | If unsure, say N. |
23 | 23 | ||
24 | config SUNRPC_SWAP | ||
25 | bool | ||
26 | depends on SUNRPC | ||
27 | select NETVM | ||
28 | |||
29 | config RPCSEC_GSS_KRB5 | 24 | config RPCSEC_GSS_KRB5 |
30 | tristate "Secure RPC: Kerberos V mechanism" | 25 | tristate "Secure RPC: Kerberos V mechanism" |
31 | depends on SUNRPC && CRYPTO | 26 | depends on SUNRPC && CRYPTO |
@@ -44,16 +39,3 @@ config RPCSEC_GSS_KRB5 | |||
44 | Kerberos support should be installed. | 39 | Kerberos support should be installed. |
45 | 40 | ||
46 | If unsure, say Y. | 41 | If unsure, say Y. |
47 | |||
48 | config SUNRPC_DEBUG | ||
49 | bool "RPC: Enable dprintk debugging" | ||
50 | depends on SUNRPC && SYSCTL | ||
51 | help | ||
52 | This option enables a sysctl-based debugging interface | ||
53 | that is be used by the 'rpcdebug' utility to turn on or off | ||
54 | logging of different aspects of the kernel RPC activity. | ||
55 | |||
56 | Disabling this option will make your kernel slightly smaller, | ||
57 | but makes troubleshooting NFS issues significantly harder. | ||
58 | |||
59 | If unsure, say Y. | ||
diff --git a/net/sunrpc/addr.c b/net/sunrpc/addr.c index d11418f97f1..4195233c491 100644 --- a/net/sunrpc/addr.c +++ b/net/sunrpc/addr.c | |||
@@ -19,9 +19,8 @@ | |||
19 | #include <net/ipv6.h> | 19 | #include <net/ipv6.h> |
20 | #include <linux/sunrpc/clnt.h> | 20 | #include <linux/sunrpc/clnt.h> |
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/export.h> | ||
23 | 22 | ||
24 | #if IS_ENABLED(CONFIG_IPV6) | 23 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
25 | 24 | ||
26 | static size_t rpc_ntop6_noscopeid(const struct sockaddr *sap, | 25 | static size_t rpc_ntop6_noscopeid(const struct sockaddr *sap, |
27 | char *buf, const int buflen) | 26 | char *buf, const int buflen) |
@@ -91,7 +90,7 @@ static size_t rpc_ntop6(const struct sockaddr *sap, | |||
91 | return len; | 90 | return len; |
92 | } | 91 | } |
93 | 92 | ||
94 | #else /* !IS_ENABLED(CONFIG_IPV6) */ | 93 | #else /* !(defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)) */ |
95 | 94 | ||
96 | static size_t rpc_ntop6_noscopeid(const struct sockaddr *sap, | 95 | static size_t rpc_ntop6_noscopeid(const struct sockaddr *sap, |
97 | char *buf, const int buflen) | 96 | char *buf, const int buflen) |
@@ -105,7 +104,7 @@ static size_t rpc_ntop6(const struct sockaddr *sap, | |||
105 | return 0; | 104 | return 0; |
106 | } | 105 | } |
107 | 106 | ||
108 | #endif /* !IS_ENABLED(CONFIG_IPV6) */ | 107 | #endif /* !(defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)) */ |
109 | 108 | ||
110 | static int rpc_ntop4(const struct sockaddr *sap, | 109 | static int rpc_ntop4(const struct sockaddr *sap, |
111 | char *buf, const size_t buflen) | 110 | char *buf, const size_t buflen) |
@@ -155,10 +154,9 @@ static size_t rpc_pton4(const char *buf, const size_t buflen, | |||
155 | return sizeof(struct sockaddr_in); | 154 | return sizeof(struct sockaddr_in); |
156 | } | 155 | } |
157 | 156 | ||
158 | #if IS_ENABLED(CONFIG_IPV6) | 157 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
159 | static int rpc_parse_scope_id(struct net *net, const char *buf, | 158 | static int rpc_parse_scope_id(const char *buf, const size_t buflen, |
160 | const size_t buflen, const char *delim, | 159 | const char *delim, struct sockaddr_in6 *sin6) |
161 | struct sockaddr_in6 *sin6) | ||
162 | { | 160 | { |
163 | char *p; | 161 | char *p; |
164 | size_t len; | 162 | size_t len; |
@@ -178,7 +176,7 @@ static int rpc_parse_scope_id(struct net *net, const char *buf, | |||
178 | unsigned long scope_id = 0; | 176 | unsigned long scope_id = 0; |
179 | struct net_device *dev; | 177 | struct net_device *dev; |
180 | 178 | ||
181 | dev = dev_get_by_name(net, p); | 179 | dev = dev_get_by_name(&init_net, p); |
182 | if (dev != NULL) { | 180 | if (dev != NULL) { |
183 | scope_id = dev->ifindex; | 181 | scope_id = dev->ifindex; |
184 | dev_put(dev); | 182 | dev_put(dev); |
@@ -198,7 +196,7 @@ static int rpc_parse_scope_id(struct net *net, const char *buf, | |||
198 | return 0; | 196 | return 0; |
199 | } | 197 | } |
200 | 198 | ||
201 | static size_t rpc_pton6(struct net *net, const char *buf, const size_t buflen, | 199 | static size_t rpc_pton6(const char *buf, const size_t buflen, |
202 | struct sockaddr *sap, const size_t salen) | 200 | struct sockaddr *sap, const size_t salen) |
203 | { | 201 | { |
204 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap; | 202 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap; |
@@ -214,14 +212,14 @@ static size_t rpc_pton6(struct net *net, const char *buf, const size_t buflen, | |||
214 | if (in6_pton(buf, buflen, addr, IPV6_SCOPE_DELIMITER, &delim) == 0) | 212 | if (in6_pton(buf, buflen, addr, IPV6_SCOPE_DELIMITER, &delim) == 0) |
215 | return 0; | 213 | return 0; |
216 | 214 | ||
217 | if (!rpc_parse_scope_id(net, buf, buflen, delim, sin6)) | 215 | if (!rpc_parse_scope_id(buf, buflen, delim, sin6)) |
218 | return 0; | 216 | return 0; |
219 | 217 | ||
220 | sin6->sin6_family = AF_INET6; | 218 | sin6->sin6_family = AF_INET6; |
221 | return sizeof(struct sockaddr_in6); | 219 | return sizeof(struct sockaddr_in6); |
222 | } | 220 | } |
223 | #else | 221 | #else |
224 | static size_t rpc_pton6(struct net *net, const char *buf, const size_t buflen, | 222 | static size_t rpc_pton6(const char *buf, const size_t buflen, |
225 | struct sockaddr *sap, const size_t salen) | 223 | struct sockaddr *sap, const size_t salen) |
226 | { | 224 | { |
227 | return 0; | 225 | return 0; |
@@ -230,7 +228,6 @@ static size_t rpc_pton6(struct net *net, const char *buf, const size_t buflen, | |||
230 | 228 | ||
231 | /** | 229 | /** |
232 | * rpc_pton - Construct a sockaddr in @sap | 230 | * rpc_pton - Construct a sockaddr in @sap |
233 | * @net: applicable network namespace | ||
234 | * @buf: C string containing presentation format IP address | 231 | * @buf: C string containing presentation format IP address |
235 | * @buflen: length of presentation address in bytes | 232 | * @buflen: length of presentation address in bytes |
236 | * @sap: buffer into which to plant socket address | 233 | * @sap: buffer into which to plant socket address |
@@ -243,14 +240,14 @@ static size_t rpc_pton6(struct net *net, const char *buf, const size_t buflen, | |||
243 | * socket address, if successful. Returns zero if an error | 240 | * socket address, if successful. Returns zero if an error |
244 | * occurred. | 241 | * occurred. |
245 | */ | 242 | */ |
246 | size_t rpc_pton(struct net *net, const char *buf, const size_t buflen, | 243 | size_t rpc_pton(const char *buf, const size_t buflen, |
247 | struct sockaddr *sap, const size_t salen) | 244 | struct sockaddr *sap, const size_t salen) |
248 | { | 245 | { |
249 | unsigned int i; | 246 | unsigned int i; |
250 | 247 | ||
251 | for (i = 0; i < buflen; i++) | 248 | for (i = 0; i < buflen; i++) |
252 | if (buf[i] == ':') | 249 | if (buf[i] == ':') |
253 | return rpc_pton6(net, buf, buflen, sap, salen); | 250 | return rpc_pton6(buf, buflen, sap, salen); |
254 | return rpc_pton4(buf, buflen, sap, salen); | 251 | return rpc_pton4(buf, buflen, sap, salen); |
255 | } | 252 | } |
256 | EXPORT_SYMBOL_GPL(rpc_pton); | 253 | EXPORT_SYMBOL_GPL(rpc_pton); |
@@ -258,13 +255,12 @@ EXPORT_SYMBOL_GPL(rpc_pton); | |||
258 | /** | 255 | /** |
259 | * rpc_sockaddr2uaddr - Construct a universal address string from @sap. | 256 | * rpc_sockaddr2uaddr - Construct a universal address string from @sap. |
260 | * @sap: socket address | 257 | * @sap: socket address |
261 | * @gfp_flags: allocation mode | ||
262 | * | 258 | * |
263 | * Returns a %NUL-terminated string in dynamically allocated memory; | 259 | * Returns a %NUL-terminated string in dynamically allocated memory; |
264 | * otherwise NULL is returned if an error occurred. Caller must | 260 | * otherwise NULL is returned if an error occurred. Caller must |
265 | * free the returned string. | 261 | * free the returned string. |
266 | */ | 262 | */ |
267 | char *rpc_sockaddr2uaddr(const struct sockaddr *sap, gfp_t gfp_flags) | 263 | char *rpc_sockaddr2uaddr(const struct sockaddr *sap) |
268 | { | 264 | { |
269 | char portbuf[RPCBIND_MAXUADDRPLEN]; | 265 | char portbuf[RPCBIND_MAXUADDRPLEN]; |
270 | char addrbuf[RPCBIND_MAXUADDRLEN]; | 266 | char addrbuf[RPCBIND_MAXUADDRLEN]; |
@@ -292,12 +288,12 @@ char *rpc_sockaddr2uaddr(const struct sockaddr *sap, gfp_t gfp_flags) | |||
292 | if (strlcat(addrbuf, portbuf, sizeof(addrbuf)) > sizeof(addrbuf)) | 288 | if (strlcat(addrbuf, portbuf, sizeof(addrbuf)) > sizeof(addrbuf)) |
293 | return NULL; | 289 | return NULL; |
294 | 290 | ||
295 | return kstrdup(addrbuf, gfp_flags); | 291 | return kstrdup(addrbuf, GFP_KERNEL); |
296 | } | 292 | } |
293 | EXPORT_SYMBOL_GPL(rpc_sockaddr2uaddr); | ||
297 | 294 | ||
298 | /** | 295 | /** |
299 | * rpc_uaddr2sockaddr - convert a universal address to a socket address. | 296 | * rpc_uaddr2sockaddr - convert a universal address to a socket address. |
300 | * @net: applicable network namespace | ||
301 | * @uaddr: C string containing universal address to convert | 297 | * @uaddr: C string containing universal address to convert |
302 | * @uaddr_len: length of universal address string | 298 | * @uaddr_len: length of universal address string |
303 | * @sap: buffer into which to plant socket address | 299 | * @sap: buffer into which to plant socket address |
@@ -309,9 +305,8 @@ char *rpc_sockaddr2uaddr(const struct sockaddr *sap, gfp_t gfp_flags) | |||
309 | * Returns the size of the socket address if successful; otherwise | 305 | * Returns the size of the socket address if successful; otherwise |
310 | * zero is returned. | 306 | * zero is returned. |
311 | */ | 307 | */ |
312 | size_t rpc_uaddr2sockaddr(struct net *net, const char *uaddr, | 308 | size_t rpc_uaddr2sockaddr(const char *uaddr, const size_t uaddr_len, |
313 | const size_t uaddr_len, struct sockaddr *sap, | 309 | struct sockaddr *sap, const size_t salen) |
314 | const size_t salen) | ||
315 | { | 310 | { |
316 | char *c, buf[RPCBIND_MAXUADDRLEN + sizeof('\0')]; | 311 | char *c, buf[RPCBIND_MAXUADDRLEN + sizeof('\0')]; |
317 | unsigned long portlo, porthi; | 312 | unsigned long portlo, porthi; |
@@ -343,7 +338,7 @@ size_t rpc_uaddr2sockaddr(struct net *net, const char *uaddr, | |||
343 | port = (unsigned short)((porthi << 8) | portlo); | 338 | port = (unsigned short)((porthi << 8) | portlo); |
344 | 339 | ||
345 | *c = '\0'; | 340 | *c = '\0'; |
346 | if (rpc_pton(net, buf, strlen(buf), sap, salen) == 0) | 341 | if (rpc_pton(buf, strlen(buf), sap, salen) == 0) |
347 | return 0; | 342 | return 0; |
348 | 343 | ||
349 | switch (sap->sa_family) { | 344 | switch (sap->sa_family) { |
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index b5c067bccc4..727e506cacd 100644 --- a/net/sunrpc/auth.c +++ b/net/sunrpc/auth.c | |||
@@ -13,7 +13,6 @@ | |||
13 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
14 | #include <linux/hash.h> | 14 | #include <linux/hash.h> |
15 | #include <linux/sunrpc/clnt.h> | 15 | #include <linux/sunrpc/clnt.h> |
16 | #include <linux/sunrpc/gss_api.h> | ||
17 | #include <linux/spinlock.h> | 16 | #include <linux/spinlock.h> |
18 | 17 | ||
19 | #ifdef RPC_DEBUG | 18 | #ifdef RPC_DEBUG |
@@ -123,59 +122,6 @@ rpcauth_unregister(const struct rpc_authops *ops) | |||
123 | } | 122 | } |
124 | EXPORT_SYMBOL_GPL(rpcauth_unregister); | 123 | EXPORT_SYMBOL_GPL(rpcauth_unregister); |
125 | 124 | ||
126 | /** | ||
127 | * rpcauth_list_flavors - discover registered flavors and pseudoflavors | ||
128 | * @array: array to fill in | ||
129 | * @size: size of "array" | ||
130 | * | ||
131 | * Returns the number of array items filled in, or a negative errno. | ||
132 | * | ||
133 | * The returned array is not sorted by any policy. Callers should not | ||
134 | * rely on the order of the items in the returned array. | ||
135 | */ | ||
136 | int | ||
137 | rpcauth_list_flavors(rpc_authflavor_t *array, int size) | ||
138 | { | ||
139 | rpc_authflavor_t flavor; | ||
140 | int result = 0; | ||
141 | |||
142 | spin_lock(&rpc_authflavor_lock); | ||
143 | for (flavor = 0; flavor < RPC_AUTH_MAXFLAVOR; flavor++) { | ||
144 | const struct rpc_authops *ops = auth_flavors[flavor]; | ||
145 | rpc_authflavor_t pseudos[4]; | ||
146 | int i, len; | ||
147 | |||
148 | if (result >= size) { | ||
149 | result = -ENOMEM; | ||
150 | break; | ||
151 | } | ||
152 | |||
153 | if (ops == NULL) | ||
154 | continue; | ||
155 | if (ops->list_pseudoflavors == NULL) { | ||
156 | array[result++] = ops->au_flavor; | ||
157 | continue; | ||
158 | } | ||
159 | len = ops->list_pseudoflavors(pseudos, ARRAY_SIZE(pseudos)); | ||
160 | if (len < 0) { | ||
161 | result = len; | ||
162 | break; | ||
163 | } | ||
164 | for (i = 0; i < len; i++) { | ||
165 | if (result >= size) { | ||
166 | result = -ENOMEM; | ||
167 | break; | ||
168 | } | ||
169 | array[result++] = pseudos[i]; | ||
170 | } | ||
171 | } | ||
172 | spin_unlock(&rpc_authflavor_lock); | ||
173 | |||
174 | dprintk("RPC: %s returns %d\n", __func__, result); | ||
175 | return result; | ||
176 | } | ||
177 | EXPORT_SYMBOL_GPL(rpcauth_list_flavors); | ||
178 | |||
179 | struct rpc_auth * | 125 | struct rpc_auth * |
180 | rpcauth_create(rpc_authflavor_t pseudoflavor, struct rpc_clnt *clnt) | 126 | rpcauth_create(rpc_authflavor_t pseudoflavor, struct rpc_clnt *clnt) |
181 | { | 127 | { |
diff --git a/net/sunrpc/auth_generic.c b/net/sunrpc/auth_generic.c index 6ed6f201b02..e010a015d99 100644 --- a/net/sunrpc/auth_generic.c +++ b/net/sunrpc/auth_generic.c | |||
@@ -41,17 +41,15 @@ EXPORT_SYMBOL_GPL(rpc_lookup_cred); | |||
41 | /* | 41 | /* |
42 | * Public call interface for looking up machine creds. | 42 | * Public call interface for looking up machine creds. |
43 | */ | 43 | */ |
44 | struct rpc_cred *rpc_lookup_machine_cred(const char *service_name) | 44 | struct rpc_cred *rpc_lookup_machine_cred(void) |
45 | { | 45 | { |
46 | struct auth_cred acred = { | 46 | struct auth_cred acred = { |
47 | .uid = RPC_MACHINE_CRED_USERID, | 47 | .uid = RPC_MACHINE_CRED_USERID, |
48 | .gid = RPC_MACHINE_CRED_GROUPID, | 48 | .gid = RPC_MACHINE_CRED_GROUPID, |
49 | .principal = service_name, | ||
50 | .machine_cred = 1, | 49 | .machine_cred = 1, |
51 | }; | 50 | }; |
52 | 51 | ||
53 | dprintk("RPC: looking up machine cred for service %s\n", | 52 | dprintk("RPC: looking up machine cred\n"); |
54 | service_name); | ||
55 | return generic_auth.au_ops->lookup_cred(&generic_auth, &acred, 0); | 53 | return generic_auth.au_ops->lookup_cred(&generic_auth, &acred, 0); |
56 | } | 54 | } |
57 | EXPORT_SYMBOL_GPL(rpc_lookup_machine_cred); | 55 | EXPORT_SYMBOL_GPL(rpc_lookup_machine_cred); |
@@ -92,7 +90,6 @@ generic_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) | |||
92 | if (gcred->acred.group_info != NULL) | 90 | if (gcred->acred.group_info != NULL) |
93 | get_group_info(gcred->acred.group_info); | 91 | get_group_info(gcred->acred.group_info); |
94 | gcred->acred.machine_cred = acred->machine_cred; | 92 | gcred->acred.machine_cred = acred->machine_cred; |
95 | gcred->acred.principal = acred->principal; | ||
96 | 93 | ||
97 | dprintk("RPC: allocated %s cred %p for uid %d gid %d\n", | 94 | dprintk("RPC: allocated %s cred %p for uid %d gid %d\n", |
98 | gcred->acred.machine_cred ? "machine" : "generic", | 95 | gcred->acred.machine_cred ? "machine" : "generic", |
@@ -124,17 +121,6 @@ generic_destroy_cred(struct rpc_cred *cred) | |||
124 | call_rcu(&cred->cr_rcu, generic_free_cred_callback); | 121 | call_rcu(&cred->cr_rcu, generic_free_cred_callback); |
125 | } | 122 | } |
126 | 123 | ||
127 | static int | ||
128 | machine_cred_match(struct auth_cred *acred, struct generic_cred *gcred, int flags) | ||
129 | { | ||
130 | if (!gcred->acred.machine_cred || | ||
131 | gcred->acred.principal != acred->principal || | ||
132 | gcred->acred.uid != acred->uid || | ||
133 | gcred->acred.gid != acred->gid) | ||
134 | return 0; | ||
135 | return 1; | ||
136 | } | ||
137 | |||
138 | /* | 124 | /* |
139 | * Match credentials against current process creds. | 125 | * Match credentials against current process creds. |
140 | */ | 126 | */ |
@@ -144,12 +130,9 @@ generic_match(struct auth_cred *acred, struct rpc_cred *cred, int flags) | |||
144 | struct generic_cred *gcred = container_of(cred, struct generic_cred, gc_base); | 130 | struct generic_cred *gcred = container_of(cred, struct generic_cred, gc_base); |
145 | int i; | 131 | int i; |
146 | 132 | ||
147 | if (acred->machine_cred) | ||
148 | return machine_cred_match(acred, gcred, flags); | ||
149 | |||
150 | if (gcred->acred.uid != acred->uid || | 133 | if (gcred->acred.uid != acred->uid || |
151 | gcred->acred.gid != acred->gid || | 134 | gcred->acred.gid != acred->gid || |
152 | gcred->acred.machine_cred != 0) | 135 | gcred->acred.machine_cred != acred->machine_cred) |
153 | goto out_nomatch; | 136 | goto out_nomatch; |
154 | 137 | ||
155 | /* Optimisation in the case where pointers are identical... */ | 138 | /* Optimisation in the case where pointers are identical... */ |
@@ -160,8 +143,8 @@ generic_match(struct auth_cred *acred, struct rpc_cred *cred, int flags) | |||
160 | if (gcred->acred.group_info->ngroups != acred->group_info->ngroups) | 143 | if (gcred->acred.group_info->ngroups != acred->group_info->ngroups) |
161 | goto out_nomatch; | 144 | goto out_nomatch; |
162 | for (i = 0; i < gcred->acred.group_info->ngroups; i++) { | 145 | for (i = 0; i < gcred->acred.group_info->ngroups; i++) { |
163 | if (!gid_eq(GROUP_AT(gcred->acred.group_info, i), | 146 | if (GROUP_AT(gcred->acred.group_info, i) != |
164 | GROUP_AT(acred->group_info, i))) | 147 | GROUP_AT(acred->group_info, i)) |
165 | goto out_nomatch; | 148 | goto out_nomatch; |
166 | } | 149 | } |
167 | out_match: | 150 | out_match: |
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 6e5c824b040..e9b76939268 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -81,7 +81,7 @@ struct gss_auth { | |||
81 | * mechanism (for example, "krb5") and exists for | 81 | * mechanism (for example, "krb5") and exists for |
82 | * backwards-compatibility with older gssd's. | 82 | * backwards-compatibility with older gssd's. |
83 | */ | 83 | */ |
84 | struct rpc_pipe *pipe[2]; | 84 | struct dentry *dentry[2]; |
85 | }; | 85 | }; |
86 | 86 | ||
87 | /* pipe_version >= 0 if and only if someone has a pipe open. */ | 87 | /* pipe_version >= 0 if and only if someone has a pipe open. */ |
@@ -112,7 +112,7 @@ gss_put_ctx(struct gss_cl_ctx *ctx) | |||
112 | /* gss_cred_set_ctx: | 112 | /* gss_cred_set_ctx: |
113 | * called by gss_upcall_callback and gss_create_upcall in order | 113 | * called by gss_upcall_callback and gss_create_upcall in order |
114 | * to set the gss context. The actual exchange of an old context | 114 | * to set the gss context. The actual exchange of an old context |
115 | * and a new one is protected by the pipe->lock. | 115 | * and a new one is protected by the inode->i_lock. |
116 | */ | 116 | */ |
117 | static void | 117 | static void |
118 | gss_cred_set_ctx(struct rpc_cred *cred, struct gss_cl_ctx *ctx) | 118 | gss_cred_set_ctx(struct rpc_cred *cred, struct gss_cl_ctx *ctx) |
@@ -192,23 +192,17 @@ gss_fill_context(const void *p, const void *end, struct gss_cl_ctx *ctx, struct | |||
192 | const void *q; | 192 | const void *q; |
193 | unsigned int seclen; | 193 | unsigned int seclen; |
194 | unsigned int timeout; | 194 | unsigned int timeout; |
195 | unsigned long now = jiffies; | ||
196 | u32 window_size; | 195 | u32 window_size; |
197 | int ret; | 196 | int ret; |
198 | 197 | ||
199 | /* First unsigned int gives the remaining lifetime in seconds of the | 198 | /* First unsigned int gives the lifetime (in seconds) of the cred */ |
200 | * credential - e.g. the remaining TGT lifetime for Kerberos or | ||
201 | * the -t value passed to GSSD. | ||
202 | */ | ||
203 | p = simple_get_bytes(p, end, &timeout, sizeof(timeout)); | 199 | p = simple_get_bytes(p, end, &timeout, sizeof(timeout)); |
204 | if (IS_ERR(p)) | 200 | if (IS_ERR(p)) |
205 | goto err; | 201 | goto err; |
206 | if (timeout == 0) | 202 | if (timeout == 0) |
207 | timeout = GSSD_MIN_TIMEOUT; | 203 | timeout = GSSD_MIN_TIMEOUT; |
208 | ctx->gc_expiry = now + ((unsigned long)timeout * HZ); | 204 | ctx->gc_expiry = jiffies + (unsigned long)timeout * HZ * 3 / 4; |
209 | /* Sequence number window. Determines the maximum number of | 205 | /* Sequence number window. Determines the maximum number of simultaneous requests */ |
210 | * simultaneous requests | ||
211 | */ | ||
212 | p = simple_get_bytes(p, end, &window_size, sizeof(window_size)); | 206 | p = simple_get_bytes(p, end, &window_size, sizeof(window_size)); |
213 | if (IS_ERR(p)) | 207 | if (IS_ERR(p)) |
214 | goto err; | 208 | goto err; |
@@ -243,12 +237,9 @@ gss_fill_context(const void *p, const void *end, struct gss_cl_ctx *ctx, struct | |||
243 | p = ERR_PTR(ret); | 237 | p = ERR_PTR(ret); |
244 | goto err; | 238 | goto err; |
245 | } | 239 | } |
246 | dprintk("RPC: %s Success. gc_expiry %lu now %lu timeout %u\n", | ||
247 | __func__, ctx->gc_expiry, now, timeout); | ||
248 | return q; | 240 | return q; |
249 | err: | 241 | err: |
250 | dprintk("RPC: %s returns %ld gc_expiry %lu now %lu timeout %u\n", | 242 | dprintk("RPC: gss_fill_context returning %ld\n", -PTR_ERR(p)); |
251 | __func__, -PTR_ERR(p), ctx->gc_expiry, now, timeout); | ||
252 | return p; | 243 | return p; |
253 | } | 244 | } |
254 | 245 | ||
@@ -260,7 +251,7 @@ struct gss_upcall_msg { | |||
260 | struct rpc_pipe_msg msg; | 251 | struct rpc_pipe_msg msg; |
261 | struct list_head list; | 252 | struct list_head list; |
262 | struct gss_auth *auth; | 253 | struct gss_auth *auth; |
263 | struct rpc_pipe *pipe; | 254 | struct rpc_inode *inode; |
264 | struct rpc_wait_queue rpc_waitqueue; | 255 | struct rpc_wait_queue rpc_waitqueue; |
265 | wait_queue_head_t waitqueue; | 256 | wait_queue_head_t waitqueue; |
266 | struct gss_cl_ctx *ctx; | 257 | struct gss_cl_ctx *ctx; |
@@ -303,17 +294,17 @@ gss_release_msg(struct gss_upcall_msg *gss_msg) | |||
303 | } | 294 | } |
304 | 295 | ||
305 | static struct gss_upcall_msg * | 296 | static struct gss_upcall_msg * |
306 | __gss_find_upcall(struct rpc_pipe *pipe, uid_t uid) | 297 | __gss_find_upcall(struct rpc_inode *rpci, uid_t uid) |
307 | { | 298 | { |
308 | struct gss_upcall_msg *pos; | 299 | struct gss_upcall_msg *pos; |
309 | list_for_each_entry(pos, &pipe->in_downcall, list) { | 300 | list_for_each_entry(pos, &rpci->in_downcall, list) { |
310 | if (pos->uid != uid) | 301 | if (pos->uid != uid) |
311 | continue; | 302 | continue; |
312 | atomic_inc(&pos->count); | 303 | atomic_inc(&pos->count); |
313 | dprintk("RPC: %s found msg %p\n", __func__, pos); | 304 | dprintk("RPC: gss_find_upcall found msg %p\n", pos); |
314 | return pos; | 305 | return pos; |
315 | } | 306 | } |
316 | dprintk("RPC: %s found nothing\n", __func__); | 307 | dprintk("RPC: gss_find_upcall found nothing\n"); |
317 | return NULL; | 308 | return NULL; |
318 | } | 309 | } |
319 | 310 | ||
@@ -324,17 +315,18 @@ __gss_find_upcall(struct rpc_pipe *pipe, uid_t uid) | |||
324 | static inline struct gss_upcall_msg * | 315 | static inline struct gss_upcall_msg * |
325 | gss_add_msg(struct gss_upcall_msg *gss_msg) | 316 | gss_add_msg(struct gss_upcall_msg *gss_msg) |
326 | { | 317 | { |
327 | struct rpc_pipe *pipe = gss_msg->pipe; | 318 | struct rpc_inode *rpci = gss_msg->inode; |
319 | struct inode *inode = &rpci->vfs_inode; | ||
328 | struct gss_upcall_msg *old; | 320 | struct gss_upcall_msg *old; |
329 | 321 | ||
330 | spin_lock(&pipe->lock); | 322 | spin_lock(&inode->i_lock); |
331 | old = __gss_find_upcall(pipe, gss_msg->uid); | 323 | old = __gss_find_upcall(rpci, gss_msg->uid); |
332 | if (old == NULL) { | 324 | if (old == NULL) { |
333 | atomic_inc(&gss_msg->count); | 325 | atomic_inc(&gss_msg->count); |
334 | list_add(&gss_msg->list, &pipe->in_downcall); | 326 | list_add(&gss_msg->list, &rpci->in_downcall); |
335 | } else | 327 | } else |
336 | gss_msg = old; | 328 | gss_msg = old; |
337 | spin_unlock(&pipe->lock); | 329 | spin_unlock(&inode->i_lock); |
338 | return gss_msg; | 330 | return gss_msg; |
339 | } | 331 | } |
340 | 332 | ||
@@ -350,14 +342,14 @@ __gss_unhash_msg(struct gss_upcall_msg *gss_msg) | |||
350 | static void | 342 | static void |
351 | gss_unhash_msg(struct gss_upcall_msg *gss_msg) | 343 | gss_unhash_msg(struct gss_upcall_msg *gss_msg) |
352 | { | 344 | { |
353 | struct rpc_pipe *pipe = gss_msg->pipe; | 345 | struct inode *inode = &gss_msg->inode->vfs_inode; |
354 | 346 | ||
355 | if (list_empty(&gss_msg->list)) | 347 | if (list_empty(&gss_msg->list)) |
356 | return; | 348 | return; |
357 | spin_lock(&pipe->lock); | 349 | spin_lock(&inode->i_lock); |
358 | if (!list_empty(&gss_msg->list)) | 350 | if (!list_empty(&gss_msg->list)) |
359 | __gss_unhash_msg(gss_msg); | 351 | __gss_unhash_msg(gss_msg); |
360 | spin_unlock(&pipe->lock); | 352 | spin_unlock(&inode->i_lock); |
361 | } | 353 | } |
362 | 354 | ||
363 | static void | 355 | static void |
@@ -384,11 +376,11 @@ gss_upcall_callback(struct rpc_task *task) | |||
384 | struct gss_cred *gss_cred = container_of(task->tk_rqstp->rq_cred, | 376 | struct gss_cred *gss_cred = container_of(task->tk_rqstp->rq_cred, |
385 | struct gss_cred, gc_base); | 377 | struct gss_cred, gc_base); |
386 | struct gss_upcall_msg *gss_msg = gss_cred->gc_upcall; | 378 | struct gss_upcall_msg *gss_msg = gss_cred->gc_upcall; |
387 | struct rpc_pipe *pipe = gss_msg->pipe; | 379 | struct inode *inode = &gss_msg->inode->vfs_inode; |
388 | 380 | ||
389 | spin_lock(&pipe->lock); | 381 | spin_lock(&inode->i_lock); |
390 | gss_handle_downcall_result(gss_cred, gss_msg); | 382 | gss_handle_downcall_result(gss_cred, gss_msg); |
391 | spin_unlock(&pipe->lock); | 383 | spin_unlock(&inode->i_lock); |
392 | task->tk_status = gss_msg->msg.errno; | 384 | task->tk_status = gss_msg->msg.errno; |
393 | gss_release_msg(gss_msg); | 385 | gss_release_msg(gss_msg); |
394 | } | 386 | } |
@@ -400,8 +392,7 @@ static void gss_encode_v0_msg(struct gss_upcall_msg *gss_msg) | |||
400 | } | 392 | } |
401 | 393 | ||
402 | static void gss_encode_v1_msg(struct gss_upcall_msg *gss_msg, | 394 | static void gss_encode_v1_msg(struct gss_upcall_msg *gss_msg, |
403 | struct rpc_clnt *clnt, | 395 | struct rpc_clnt *clnt, int machine_cred) |
404 | const char *service_name) | ||
405 | { | 396 | { |
406 | struct gss_api_mech *mech = gss_msg->auth->mech; | 397 | struct gss_api_mech *mech = gss_msg->auth->mech; |
407 | char *p = gss_msg->databuf; | 398 | char *p = gss_msg->databuf; |
@@ -416,8 +407,12 @@ static void gss_encode_v1_msg(struct gss_upcall_msg *gss_msg, | |||
416 | p += len; | 407 | p += len; |
417 | gss_msg->msg.len += len; | 408 | gss_msg->msg.len += len; |
418 | } | 409 | } |
419 | if (service_name != NULL) { | 410 | if (machine_cred) { |
420 | len = sprintf(p, "service=%s ", service_name); | 411 | len = sprintf(p, "service=* "); |
412 | p += len; | ||
413 | gss_msg->msg.len += len; | ||
414 | } else if (!strcmp(clnt->cl_program->name, "nfs4_cb")) { | ||
415 | len = sprintf(p, "service=nfs "); | ||
421 | p += len; | 416 | p += len; |
422 | gss_msg->msg.len += len; | 417 | gss_msg->msg.len += len; |
423 | } | 418 | } |
@@ -434,18 +429,17 @@ static void gss_encode_v1_msg(struct gss_upcall_msg *gss_msg, | |||
434 | } | 429 | } |
435 | 430 | ||
436 | static void gss_encode_msg(struct gss_upcall_msg *gss_msg, | 431 | static void gss_encode_msg(struct gss_upcall_msg *gss_msg, |
437 | struct rpc_clnt *clnt, | 432 | struct rpc_clnt *clnt, int machine_cred) |
438 | const char *service_name) | ||
439 | { | 433 | { |
440 | if (pipe_version == 0) | 434 | if (pipe_version == 0) |
441 | gss_encode_v0_msg(gss_msg); | 435 | gss_encode_v0_msg(gss_msg); |
442 | else /* pipe_version == 1 */ | 436 | else /* pipe_version == 1 */ |
443 | gss_encode_v1_msg(gss_msg, clnt, service_name); | 437 | gss_encode_v1_msg(gss_msg, clnt, machine_cred); |
444 | } | 438 | } |
445 | 439 | ||
446 | static struct gss_upcall_msg * | 440 | static inline struct gss_upcall_msg * |
447 | gss_alloc_msg(struct gss_auth *gss_auth, struct rpc_clnt *clnt, | 441 | gss_alloc_msg(struct gss_auth *gss_auth, uid_t uid, struct rpc_clnt *clnt, |
448 | uid_t uid, const char *service_name) | 442 | int machine_cred) |
449 | { | 443 | { |
450 | struct gss_upcall_msg *gss_msg; | 444 | struct gss_upcall_msg *gss_msg; |
451 | int vers; | 445 | int vers; |
@@ -458,14 +452,14 @@ gss_alloc_msg(struct gss_auth *gss_auth, struct rpc_clnt *clnt, | |||
458 | kfree(gss_msg); | 452 | kfree(gss_msg); |
459 | return ERR_PTR(vers); | 453 | return ERR_PTR(vers); |
460 | } | 454 | } |
461 | gss_msg->pipe = gss_auth->pipe[vers]; | 455 | gss_msg->inode = RPC_I(gss_auth->dentry[vers]->d_inode); |
462 | INIT_LIST_HEAD(&gss_msg->list); | 456 | INIT_LIST_HEAD(&gss_msg->list); |
463 | rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq"); | 457 | rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq"); |
464 | init_waitqueue_head(&gss_msg->waitqueue); | 458 | init_waitqueue_head(&gss_msg->waitqueue); |
465 | atomic_set(&gss_msg->count, 1); | 459 | atomic_set(&gss_msg->count, 1); |
466 | gss_msg->uid = uid; | 460 | gss_msg->uid = uid; |
467 | gss_msg->auth = gss_auth; | 461 | gss_msg->auth = gss_auth; |
468 | gss_encode_msg(gss_msg, clnt, service_name); | 462 | gss_encode_msg(gss_msg, clnt, machine_cred); |
469 | return gss_msg; | 463 | return gss_msg; |
470 | } | 464 | } |
471 | 465 | ||
@@ -477,12 +471,13 @@ gss_setup_upcall(struct rpc_clnt *clnt, struct gss_auth *gss_auth, struct rpc_cr | |||
477 | struct gss_upcall_msg *gss_new, *gss_msg; | 471 | struct gss_upcall_msg *gss_new, *gss_msg; |
478 | uid_t uid = cred->cr_uid; | 472 | uid_t uid = cred->cr_uid; |
479 | 473 | ||
480 | gss_new = gss_alloc_msg(gss_auth, clnt, uid, gss_cred->gc_principal); | 474 | gss_new = gss_alloc_msg(gss_auth, uid, clnt, gss_cred->gc_machine_cred); |
481 | if (IS_ERR(gss_new)) | 475 | if (IS_ERR(gss_new)) |
482 | return gss_new; | 476 | return gss_new; |
483 | gss_msg = gss_add_msg(gss_new); | 477 | gss_msg = gss_add_msg(gss_new); |
484 | if (gss_msg == gss_new) { | 478 | if (gss_msg == gss_new) { |
485 | int res = rpc_queue_upcall(gss_new->pipe, &gss_new->msg); | 479 | struct inode *inode = &gss_new->inode->vfs_inode; |
480 | int res = rpc_queue_upcall(inode, &gss_new->msg); | ||
486 | if (res) { | 481 | if (res) { |
487 | gss_unhash_msg(gss_new); | 482 | gss_unhash_msg(gss_new); |
488 | gss_msg = ERR_PTR(res); | 483 | gss_msg = ERR_PTR(res); |
@@ -513,11 +508,11 @@ gss_refresh_upcall(struct rpc_task *task) | |||
513 | struct gss_cred *gss_cred = container_of(cred, | 508 | struct gss_cred *gss_cred = container_of(cred, |
514 | struct gss_cred, gc_base); | 509 | struct gss_cred, gc_base); |
515 | struct gss_upcall_msg *gss_msg; | 510 | struct gss_upcall_msg *gss_msg; |
516 | struct rpc_pipe *pipe; | 511 | struct inode *inode; |
517 | int err = 0; | 512 | int err = 0; |
518 | 513 | ||
519 | dprintk("RPC: %5u %s for uid %u\n", | 514 | dprintk("RPC: %5u gss_refresh_upcall for uid %u\n", task->tk_pid, |
520 | task->tk_pid, __func__, cred->cr_uid); | 515 | cred->cr_uid); |
521 | gss_msg = gss_setup_upcall(task->tk_client, gss_auth, cred); | 516 | gss_msg = gss_setup_upcall(task->tk_client, gss_auth, cred); |
522 | if (PTR_ERR(gss_msg) == -EAGAIN) { | 517 | if (PTR_ERR(gss_msg) == -EAGAIN) { |
523 | /* XXX: warning on the first, under the assumption we | 518 | /* XXX: warning on the first, under the assumption we |
@@ -531,8 +526,8 @@ gss_refresh_upcall(struct rpc_task *task) | |||
531 | err = PTR_ERR(gss_msg); | 526 | err = PTR_ERR(gss_msg); |
532 | goto out; | 527 | goto out; |
533 | } | 528 | } |
534 | pipe = gss_msg->pipe; | 529 | inode = &gss_msg->inode->vfs_inode; |
535 | spin_lock(&pipe->lock); | 530 | spin_lock(&inode->i_lock); |
536 | if (gss_cred->gc_upcall != NULL) | 531 | if (gss_cred->gc_upcall != NULL) |
537 | rpc_sleep_on(&gss_cred->gc_upcall->rpc_waitqueue, task, NULL); | 532 | rpc_sleep_on(&gss_cred->gc_upcall->rpc_waitqueue, task, NULL); |
538 | else if (gss_msg->ctx == NULL && gss_msg->msg.errno >= 0) { | 533 | else if (gss_msg->ctx == NULL && gss_msg->msg.errno >= 0) { |
@@ -545,24 +540,24 @@ gss_refresh_upcall(struct rpc_task *task) | |||
545 | gss_handle_downcall_result(gss_cred, gss_msg); | 540 | gss_handle_downcall_result(gss_cred, gss_msg); |
546 | err = gss_msg->msg.errno; | 541 | err = gss_msg->msg.errno; |
547 | } | 542 | } |
548 | spin_unlock(&pipe->lock); | 543 | spin_unlock(&inode->i_lock); |
549 | gss_release_msg(gss_msg); | 544 | gss_release_msg(gss_msg); |
550 | out: | 545 | out: |
551 | dprintk("RPC: %5u %s for uid %u result %d\n", | 546 | dprintk("RPC: %5u gss_refresh_upcall for uid %u result %d\n", |
552 | task->tk_pid, __func__, cred->cr_uid, err); | 547 | task->tk_pid, cred->cr_uid, err); |
553 | return err; | 548 | return err; |
554 | } | 549 | } |
555 | 550 | ||
556 | static inline int | 551 | static inline int |
557 | gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred) | 552 | gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred) |
558 | { | 553 | { |
559 | struct rpc_pipe *pipe; | 554 | struct inode *inode; |
560 | struct rpc_cred *cred = &gss_cred->gc_base; | 555 | struct rpc_cred *cred = &gss_cred->gc_base; |
561 | struct gss_upcall_msg *gss_msg; | 556 | struct gss_upcall_msg *gss_msg; |
562 | DEFINE_WAIT(wait); | 557 | DEFINE_WAIT(wait); |
563 | int err = 0; | 558 | int err = 0; |
564 | 559 | ||
565 | dprintk("RPC: %s for uid %u\n", __func__, cred->cr_uid); | 560 | dprintk("RPC: gss_upcall for uid %u\n", cred->cr_uid); |
566 | retry: | 561 | retry: |
567 | gss_msg = gss_setup_upcall(gss_auth->client, gss_auth, cred); | 562 | gss_msg = gss_setup_upcall(gss_auth->client, gss_auth, cred); |
568 | if (PTR_ERR(gss_msg) == -EAGAIN) { | 563 | if (PTR_ERR(gss_msg) == -EAGAIN) { |
@@ -580,14 +575,14 @@ retry: | |||
580 | err = PTR_ERR(gss_msg); | 575 | err = PTR_ERR(gss_msg); |
581 | goto out; | 576 | goto out; |
582 | } | 577 | } |
583 | pipe = gss_msg->pipe; | 578 | inode = &gss_msg->inode->vfs_inode; |
584 | for (;;) { | 579 | for (;;) { |
585 | prepare_to_wait(&gss_msg->waitqueue, &wait, TASK_KILLABLE); | 580 | prepare_to_wait(&gss_msg->waitqueue, &wait, TASK_KILLABLE); |
586 | spin_lock(&pipe->lock); | 581 | spin_lock(&inode->i_lock); |
587 | if (gss_msg->ctx != NULL || gss_msg->msg.errno < 0) { | 582 | if (gss_msg->ctx != NULL || gss_msg->msg.errno < 0) { |
588 | break; | 583 | break; |
589 | } | 584 | } |
590 | spin_unlock(&pipe->lock); | 585 | spin_unlock(&inode->i_lock); |
591 | if (fatal_signal_pending(current)) { | 586 | if (fatal_signal_pending(current)) { |
592 | err = -ERESTARTSYS; | 587 | err = -ERESTARTSYS; |
593 | goto out_intr; | 588 | goto out_intr; |
@@ -598,13 +593,13 @@ retry: | |||
598 | gss_cred_set_ctx(cred, gss_msg->ctx); | 593 | gss_cred_set_ctx(cred, gss_msg->ctx); |
599 | else | 594 | else |
600 | err = gss_msg->msg.errno; | 595 | err = gss_msg->msg.errno; |
601 | spin_unlock(&pipe->lock); | 596 | spin_unlock(&inode->i_lock); |
602 | out_intr: | 597 | out_intr: |
603 | finish_wait(&gss_msg->waitqueue, &wait); | 598 | finish_wait(&gss_msg->waitqueue, &wait); |
604 | gss_release_msg(gss_msg); | 599 | gss_release_msg(gss_msg); |
605 | out: | 600 | out: |
606 | dprintk("RPC: %s for uid %u result %d\n", | 601 | dprintk("RPC: gss_create_upcall for uid %u result %d\n", |
607 | __func__, cred->cr_uid, err); | 602 | cred->cr_uid, err); |
608 | return err; | 603 | return err; |
609 | } | 604 | } |
610 | 605 | ||
@@ -616,7 +611,7 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) | |||
616 | const void *p, *end; | 611 | const void *p, *end; |
617 | void *buf; | 612 | void *buf; |
618 | struct gss_upcall_msg *gss_msg; | 613 | struct gss_upcall_msg *gss_msg; |
619 | struct rpc_pipe *pipe = RPC_I(filp->f_dentry->d_inode)->pipe; | 614 | struct inode *inode = filp->f_path.dentry->d_inode; |
620 | struct gss_cl_ctx *ctx; | 615 | struct gss_cl_ctx *ctx; |
621 | uid_t uid; | 616 | uid_t uid; |
622 | ssize_t err = -EFBIG; | 617 | ssize_t err = -EFBIG; |
@@ -646,14 +641,14 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) | |||
646 | 641 | ||
647 | err = -ENOENT; | 642 | err = -ENOENT; |
648 | /* Find a matching upcall */ | 643 | /* Find a matching upcall */ |
649 | spin_lock(&pipe->lock); | 644 | spin_lock(&inode->i_lock); |
650 | gss_msg = __gss_find_upcall(pipe, uid); | 645 | gss_msg = __gss_find_upcall(RPC_I(inode), uid); |
651 | if (gss_msg == NULL) { | 646 | if (gss_msg == NULL) { |
652 | spin_unlock(&pipe->lock); | 647 | spin_unlock(&inode->i_lock); |
653 | goto err_put_ctx; | 648 | goto err_put_ctx; |
654 | } | 649 | } |
655 | list_del_init(&gss_msg->list); | 650 | list_del_init(&gss_msg->list); |
656 | spin_unlock(&pipe->lock); | 651 | spin_unlock(&inode->i_lock); |
657 | 652 | ||
658 | p = gss_fill_context(p, end, ctx, gss_msg->auth->mech); | 653 | p = gss_fill_context(p, end, ctx, gss_msg->auth->mech); |
659 | if (IS_ERR(p)) { | 654 | if (IS_ERR(p)) { |
@@ -681,16 +676,16 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) | |||
681 | err = mlen; | 676 | err = mlen; |
682 | 677 | ||
683 | err_release_msg: | 678 | err_release_msg: |
684 | spin_lock(&pipe->lock); | 679 | spin_lock(&inode->i_lock); |
685 | __gss_unhash_msg(gss_msg); | 680 | __gss_unhash_msg(gss_msg); |
686 | spin_unlock(&pipe->lock); | 681 | spin_unlock(&inode->i_lock); |
687 | gss_release_msg(gss_msg); | 682 | gss_release_msg(gss_msg); |
688 | err_put_ctx: | 683 | err_put_ctx: |
689 | gss_put_ctx(ctx); | 684 | gss_put_ctx(ctx); |
690 | err: | 685 | err: |
691 | kfree(buf); | 686 | kfree(buf); |
692 | out: | 687 | out: |
693 | dprintk("RPC: %s returning %Zd\n", __func__, err); | 688 | dprintk("RPC: gss_pipe_downcall returning %Zd\n", err); |
694 | return err; | 689 | return err; |
695 | } | 690 | } |
696 | 691 | ||
@@ -729,23 +724,23 @@ static int gss_pipe_open_v1(struct inode *inode) | |||
729 | static void | 724 | static void |
730 | gss_pipe_release(struct inode *inode) | 725 | gss_pipe_release(struct inode *inode) |
731 | { | 726 | { |
732 | struct rpc_pipe *pipe = RPC_I(inode)->pipe; | 727 | struct rpc_inode *rpci = RPC_I(inode); |
733 | struct gss_upcall_msg *gss_msg; | 728 | struct gss_upcall_msg *gss_msg; |
734 | 729 | ||
735 | restart: | 730 | restart: |
736 | spin_lock(&pipe->lock); | 731 | spin_lock(&inode->i_lock); |
737 | list_for_each_entry(gss_msg, &pipe->in_downcall, list) { | 732 | list_for_each_entry(gss_msg, &rpci->in_downcall, list) { |
738 | 733 | ||
739 | if (!list_empty(&gss_msg->msg.list)) | 734 | if (!list_empty(&gss_msg->msg.list)) |
740 | continue; | 735 | continue; |
741 | gss_msg->msg.errno = -EPIPE; | 736 | gss_msg->msg.errno = -EPIPE; |
742 | atomic_inc(&gss_msg->count); | 737 | atomic_inc(&gss_msg->count); |
743 | __gss_unhash_msg(gss_msg); | 738 | __gss_unhash_msg(gss_msg); |
744 | spin_unlock(&pipe->lock); | 739 | spin_unlock(&inode->i_lock); |
745 | gss_release_msg(gss_msg); | 740 | gss_release_msg(gss_msg); |
746 | goto restart; | 741 | goto restart; |
747 | } | 742 | } |
748 | spin_unlock(&pipe->lock); | 743 | spin_unlock(&inode->i_lock); |
749 | 744 | ||
750 | put_pipe_version(); | 745 | put_pipe_version(); |
751 | } | 746 | } |
@@ -756,8 +751,8 @@ gss_pipe_destroy_msg(struct rpc_pipe_msg *msg) | |||
756 | struct gss_upcall_msg *gss_msg = container_of(msg, struct gss_upcall_msg, msg); | 751 | struct gss_upcall_msg *gss_msg = container_of(msg, struct gss_upcall_msg, msg); |
757 | 752 | ||
758 | if (msg->errno < 0) { | 753 | if (msg->errno < 0) { |
759 | dprintk("RPC: %s releasing msg %p\n", | 754 | dprintk("RPC: gss_pipe_destroy_msg releasing msg %p\n", |
760 | __func__, gss_msg); | 755 | gss_msg); |
761 | atomic_inc(&gss_msg->count); | 756 | atomic_inc(&gss_msg->count); |
762 | gss_unhash_msg(gss_msg); | 757 | gss_unhash_msg(gss_msg); |
763 | if (msg->errno == -ETIMEDOUT) | 758 | if (msg->errno == -ETIMEDOUT) |
@@ -766,75 +761,6 @@ gss_pipe_destroy_msg(struct rpc_pipe_msg *msg) | |||
766 | } | 761 | } |
767 | } | 762 | } |
768 | 763 | ||
769 | static void gss_pipes_dentries_destroy(struct rpc_auth *auth) | ||
770 | { | ||
771 | struct gss_auth *gss_auth; | ||
772 | |||
773 | gss_auth = container_of(auth, struct gss_auth, rpc_auth); | ||
774 | if (gss_auth->pipe[0]->dentry) | ||
775 | rpc_unlink(gss_auth->pipe[0]->dentry); | ||
776 | if (gss_auth->pipe[1]->dentry) | ||
777 | rpc_unlink(gss_auth->pipe[1]->dentry); | ||
778 | } | ||
779 | |||
780 | static int gss_pipes_dentries_create(struct rpc_auth *auth) | ||
781 | { | ||
782 | int err; | ||
783 | struct gss_auth *gss_auth; | ||
784 | struct rpc_clnt *clnt; | ||
785 | |||
786 | gss_auth = container_of(auth, struct gss_auth, rpc_auth); | ||
787 | clnt = gss_auth->client; | ||
788 | |||
789 | gss_auth->pipe[1]->dentry = rpc_mkpipe_dentry(clnt->cl_dentry, | ||
790 | "gssd", | ||
791 | clnt, gss_auth->pipe[1]); | ||
792 | if (IS_ERR(gss_auth->pipe[1]->dentry)) | ||
793 | return PTR_ERR(gss_auth->pipe[1]->dentry); | ||
794 | gss_auth->pipe[0]->dentry = rpc_mkpipe_dentry(clnt->cl_dentry, | ||
795 | gss_auth->mech->gm_name, | ||
796 | clnt, gss_auth->pipe[0]); | ||
797 | if (IS_ERR(gss_auth->pipe[0]->dentry)) { | ||
798 | err = PTR_ERR(gss_auth->pipe[0]->dentry); | ||
799 | goto err_unlink_pipe_1; | ||
800 | } | ||
801 | return 0; | ||
802 | |||
803 | err_unlink_pipe_1: | ||
804 | rpc_unlink(gss_auth->pipe[1]->dentry); | ||
805 | return err; | ||
806 | } | ||
807 | |||
808 | static void gss_pipes_dentries_destroy_net(struct rpc_clnt *clnt, | ||
809 | struct rpc_auth *auth) | ||
810 | { | ||
811 | struct net *net = rpc_net_ns(clnt); | ||
812 | struct super_block *sb; | ||
813 | |||
814 | sb = rpc_get_sb_net(net); | ||
815 | if (sb) { | ||
816 | if (clnt->cl_dentry) | ||
817 | gss_pipes_dentries_destroy(auth); | ||
818 | rpc_put_sb_net(net); | ||
819 | } | ||
820 | } | ||
821 | |||
822 | static int gss_pipes_dentries_create_net(struct rpc_clnt *clnt, | ||
823 | struct rpc_auth *auth) | ||
824 | { | ||
825 | struct net *net = rpc_net_ns(clnt); | ||
826 | struct super_block *sb; | ||
827 | int err = 0; | ||
828 | |||
829 | sb = rpc_get_sb_net(net); | ||
830 | if (sb) { | ||
831 | if (clnt->cl_dentry) | ||
832 | err = gss_pipes_dentries_create(auth); | ||
833 | rpc_put_sb_net(net); | ||
834 | } | ||
835 | return err; | ||
836 | } | ||
837 | |||
838 | /* | 764 | /* |
839 | * NOTE: we have the opportunity to use different | 765 | * NOTE: we have the opportunity to use different |
840 | * parameters based on the input flavor (which must be a pseudoflavor) | 766 | * parameters based on the input flavor (which must be a pseudoflavor) |
@@ -877,33 +803,32 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor) | |||
877 | * that we supported only the old pipe. So we instead create | 803 | * that we supported only the old pipe. So we instead create |
878 | * the new pipe first. | 804 | * the new pipe first. |
879 | */ | 805 | */ |
880 | gss_auth->pipe[1] = rpc_mkpipe_data(&gss_upcall_ops_v1, | 806 | gss_auth->dentry[1] = rpc_mkpipe(clnt->cl_path.dentry, |
881 | RPC_PIPE_WAIT_FOR_OPEN); | 807 | "gssd", |
882 | if (IS_ERR(gss_auth->pipe[1])) { | 808 | clnt, &gss_upcall_ops_v1, |
883 | err = PTR_ERR(gss_auth->pipe[1]); | 809 | RPC_PIPE_WAIT_FOR_OPEN); |
810 | if (IS_ERR(gss_auth->dentry[1])) { | ||
811 | err = PTR_ERR(gss_auth->dentry[1]); | ||
884 | goto err_put_mech; | 812 | goto err_put_mech; |
885 | } | 813 | } |
886 | 814 | ||
887 | gss_auth->pipe[0] = rpc_mkpipe_data(&gss_upcall_ops_v0, | 815 | gss_auth->dentry[0] = rpc_mkpipe(clnt->cl_path.dentry, |
888 | RPC_PIPE_WAIT_FOR_OPEN); | 816 | gss_auth->mech->gm_name, |
889 | if (IS_ERR(gss_auth->pipe[0])) { | 817 | clnt, &gss_upcall_ops_v0, |
890 | err = PTR_ERR(gss_auth->pipe[0]); | 818 | RPC_PIPE_WAIT_FOR_OPEN); |
891 | goto err_destroy_pipe_1; | 819 | if (IS_ERR(gss_auth->dentry[0])) { |
820 | err = PTR_ERR(gss_auth->dentry[0]); | ||
821 | goto err_unlink_pipe_1; | ||
892 | } | 822 | } |
893 | err = gss_pipes_dentries_create_net(clnt, auth); | ||
894 | if (err) | ||
895 | goto err_destroy_pipe_0; | ||
896 | err = rpcauth_init_credcache(auth); | 823 | err = rpcauth_init_credcache(auth); |
897 | if (err) | 824 | if (err) |
898 | goto err_unlink_pipes; | 825 | goto err_unlink_pipe_0; |
899 | 826 | ||
900 | return auth; | 827 | return auth; |
901 | err_unlink_pipes: | 828 | err_unlink_pipe_0: |
902 | gss_pipes_dentries_destroy_net(clnt, auth); | 829 | rpc_unlink(gss_auth->dentry[0]); |
903 | err_destroy_pipe_0: | 830 | err_unlink_pipe_1: |
904 | rpc_destroy_pipe_data(gss_auth->pipe[0]); | 831 | rpc_unlink(gss_auth->dentry[1]); |
905 | err_destroy_pipe_1: | ||
906 | rpc_destroy_pipe_data(gss_auth->pipe[1]); | ||
907 | err_put_mech: | 832 | err_put_mech: |
908 | gss_mech_put(gss_auth->mech); | 833 | gss_mech_put(gss_auth->mech); |
909 | err_free: | 834 | err_free: |
@@ -916,9 +841,8 @@ out_dec: | |||
916 | static void | 841 | static void |
917 | gss_free(struct gss_auth *gss_auth) | 842 | gss_free(struct gss_auth *gss_auth) |
918 | { | 843 | { |
919 | gss_pipes_dentries_destroy_net(gss_auth->client, &gss_auth->rpc_auth); | 844 | rpc_unlink(gss_auth->dentry[1]); |
920 | rpc_destroy_pipe_data(gss_auth->pipe[0]); | 845 | rpc_unlink(gss_auth->dentry[0]); |
921 | rpc_destroy_pipe_data(gss_auth->pipe[1]); | ||
922 | gss_mech_put(gss_auth->mech); | 846 | gss_mech_put(gss_auth->mech); |
923 | 847 | ||
924 | kfree(gss_auth); | 848 | kfree(gss_auth); |
@@ -985,7 +909,7 @@ gss_destroying_context(struct rpc_cred *cred) | |||
985 | static void | 909 | static void |
986 | gss_do_free_ctx(struct gss_cl_ctx *ctx) | 910 | gss_do_free_ctx(struct gss_cl_ctx *ctx) |
987 | { | 911 | { |
988 | dprintk("RPC: %s\n", __func__); | 912 | dprintk("RPC: gss_free_ctx\n"); |
989 | 913 | ||
990 | gss_delete_sec_context(&ctx->gc_gss_ctx); | 914 | gss_delete_sec_context(&ctx->gc_gss_ctx); |
991 | kfree(ctx->gc_wire_ctx.data); | 915 | kfree(ctx->gc_wire_ctx.data); |
@@ -1008,7 +932,7 @@ gss_free_ctx(struct gss_cl_ctx *ctx) | |||
1008 | static void | 932 | static void |
1009 | gss_free_cred(struct gss_cred *gss_cred) | 933 | gss_free_cred(struct gss_cred *gss_cred) |
1010 | { | 934 | { |
1011 | dprintk("RPC: %s cred=%p\n", __func__, gss_cred); | 935 | dprintk("RPC: gss_free_cred %p\n", gss_cred); |
1012 | kfree(gss_cred); | 936 | kfree(gss_cred); |
1013 | } | 937 | } |
1014 | 938 | ||
@@ -1026,7 +950,7 @@ gss_destroy_nullcred(struct rpc_cred *cred) | |||
1026 | struct gss_auth *gss_auth = container_of(cred->cr_auth, struct gss_auth, rpc_auth); | 950 | struct gss_auth *gss_auth = container_of(cred->cr_auth, struct gss_auth, rpc_auth); |
1027 | struct gss_cl_ctx *ctx = gss_cred->gc_ctx; | 951 | struct gss_cl_ctx *ctx = gss_cred->gc_ctx; |
1028 | 952 | ||
1029 | RCU_INIT_POINTER(gss_cred->gc_ctx, NULL); | 953 | rcu_assign_pointer(gss_cred->gc_ctx, NULL); |
1030 | call_rcu(&cred->cr_rcu, gss_free_cred_callback); | 954 | call_rcu(&cred->cr_rcu, gss_free_cred_callback); |
1031 | if (ctx) | 955 | if (ctx) |
1032 | gss_put_ctx(ctx); | 956 | gss_put_ctx(ctx); |
@@ -1058,8 +982,8 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) | |||
1058 | struct gss_cred *cred = NULL; | 982 | struct gss_cred *cred = NULL; |
1059 | int err = -ENOMEM; | 983 | int err = -ENOMEM; |
1060 | 984 | ||
1061 | dprintk("RPC: %s for uid %d, flavor %d\n", | 985 | dprintk("RPC: gss_create_cred for uid %d, flavor %d\n", |
1062 | __func__, acred->uid, auth->au_flavor); | 986 | acred->uid, auth->au_flavor); |
1063 | 987 | ||
1064 | if (!(cred = kzalloc(sizeof(*cred), GFP_NOFS))) | 988 | if (!(cred = kzalloc(sizeof(*cred), GFP_NOFS))) |
1065 | goto out_err; | 989 | goto out_err; |
@@ -1071,14 +995,12 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) | |||
1071 | */ | 995 | */ |
1072 | cred->gc_base.cr_flags = 1UL << RPCAUTH_CRED_NEW; | 996 | cred->gc_base.cr_flags = 1UL << RPCAUTH_CRED_NEW; |
1073 | cred->gc_service = gss_auth->service; | 997 | cred->gc_service = gss_auth->service; |
1074 | cred->gc_principal = NULL; | 998 | cred->gc_machine_cred = acred->machine_cred; |
1075 | if (acred->machine_cred) | ||
1076 | cred->gc_principal = acred->principal; | ||
1077 | kref_get(&gss_auth->kref); | 999 | kref_get(&gss_auth->kref); |
1078 | return &cred->gc_base; | 1000 | return &cred->gc_base; |
1079 | 1001 | ||
1080 | out_err: | 1002 | out_err: |
1081 | dprintk("RPC: %s failed with error %d\n", __func__, err); | 1003 | dprintk("RPC: gss_create_cred failed with error %d\n", err); |
1082 | return ERR_PTR(err); | 1004 | return ERR_PTR(err); |
1083 | } | 1005 | } |
1084 | 1006 | ||
@@ -1108,12 +1030,7 @@ gss_match(struct auth_cred *acred, struct rpc_cred *rc, int flags) | |||
1108 | if (!test_bit(RPCAUTH_CRED_UPTODATE, &rc->cr_flags)) | 1030 | if (!test_bit(RPCAUTH_CRED_UPTODATE, &rc->cr_flags)) |
1109 | return 0; | 1031 | return 0; |
1110 | out: | 1032 | out: |
1111 | if (acred->principal != NULL) { | 1033 | if (acred->machine_cred != gss_cred->gc_machine_cred) |
1112 | if (gss_cred->gc_principal == NULL) | ||
1113 | return 0; | ||
1114 | return strcmp(acred->principal, gss_cred->gc_principal) == 0; | ||
1115 | } | ||
1116 | if (gss_cred->gc_principal != NULL) | ||
1117 | return 0; | 1034 | return 0; |
1118 | return rc->cr_uid == acred->uid; | 1035 | return rc->cr_uid == acred->uid; |
1119 | } | 1036 | } |
@@ -1136,7 +1053,7 @@ gss_marshal(struct rpc_task *task, __be32 *p) | |||
1136 | struct kvec iov; | 1053 | struct kvec iov; |
1137 | struct xdr_buf verf_buf; | 1054 | struct xdr_buf verf_buf; |
1138 | 1055 | ||
1139 | dprintk("RPC: %5u %s\n", task->tk_pid, __func__); | 1056 | dprintk("RPC: %5u gss_marshal\n", task->tk_pid); |
1140 | 1057 | ||
1141 | *p++ = htonl(RPC_AUTH_GSS); | 1058 | *p++ = htonl(RPC_AUTH_GSS); |
1142 | cred_len = p++; | 1059 | cred_len = p++; |
@@ -1187,8 +1104,7 @@ static int gss_renew_cred(struct rpc_task *task) | |||
1187 | struct rpc_auth *auth = oldcred->cr_auth; | 1104 | struct rpc_auth *auth = oldcred->cr_auth; |
1188 | struct auth_cred acred = { | 1105 | struct auth_cred acred = { |
1189 | .uid = oldcred->cr_uid, | 1106 | .uid = oldcred->cr_uid, |
1190 | .principal = gss_cred->gc_principal, | 1107 | .machine_cred = gss_cred->gc_machine_cred, |
1191 | .machine_cred = (gss_cred->gc_principal != NULL ? 1 : 0), | ||
1192 | }; | 1108 | }; |
1193 | struct rpc_cred *new; | 1109 | struct rpc_cred *new; |
1194 | 1110 | ||
@@ -1262,7 +1178,7 @@ gss_validate(struct rpc_task *task, __be32 *p) | |||
1262 | u32 flav,len; | 1178 | u32 flav,len; |
1263 | u32 maj_stat; | 1179 | u32 maj_stat; |
1264 | 1180 | ||
1265 | dprintk("RPC: %5u %s\n", task->tk_pid, __func__); | 1181 | dprintk("RPC: %5u gss_validate\n", task->tk_pid); |
1266 | 1182 | ||
1267 | flav = ntohl(*p++); | 1183 | flav = ntohl(*p++); |
1268 | if ((len = ntohl(*p++)) > RPC_MAX_AUTH_SIZE) | 1184 | if ((len = ntohl(*p++)) > RPC_MAX_AUTH_SIZE) |
@@ -1280,20 +1196,20 @@ gss_validate(struct rpc_task *task, __be32 *p) | |||
1280 | if (maj_stat == GSS_S_CONTEXT_EXPIRED) | 1196 | if (maj_stat == GSS_S_CONTEXT_EXPIRED) |
1281 | clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); | 1197 | clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); |
1282 | if (maj_stat) { | 1198 | if (maj_stat) { |
1283 | dprintk("RPC: %5u %s: gss_verify_mic returned error 0x%08x\n", | 1199 | dprintk("RPC: %5u gss_validate: gss_verify_mic returned " |
1284 | task->tk_pid, __func__, maj_stat); | 1200 | "error 0x%08x\n", task->tk_pid, maj_stat); |
1285 | goto out_bad; | 1201 | goto out_bad; |
1286 | } | 1202 | } |
1287 | /* We leave it to unwrap to calculate au_rslack. For now we just | 1203 | /* We leave it to unwrap to calculate au_rslack. For now we just |
1288 | * calculate the length of the verifier: */ | 1204 | * calculate the length of the verifier: */ |
1289 | cred->cr_auth->au_verfsize = XDR_QUADLEN(len) + 2; | 1205 | cred->cr_auth->au_verfsize = XDR_QUADLEN(len) + 2; |
1290 | gss_put_ctx(ctx); | 1206 | gss_put_ctx(ctx); |
1291 | dprintk("RPC: %5u %s: gss_verify_mic succeeded.\n", | 1207 | dprintk("RPC: %5u gss_validate: gss_verify_mic succeeded.\n", |
1292 | task->tk_pid, __func__); | 1208 | task->tk_pid); |
1293 | return p + XDR_QUADLEN(len); | 1209 | return p + XDR_QUADLEN(len); |
1294 | out_bad: | 1210 | out_bad: |
1295 | gss_put_ctx(ctx); | 1211 | gss_put_ctx(ctx); |
1296 | dprintk("RPC: %5u %s failed.\n", task->tk_pid, __func__); | 1212 | dprintk("RPC: %5u gss_validate failed.\n", task->tk_pid); |
1297 | return NULL; | 1213 | return NULL; |
1298 | } | 1214 | } |
1299 | 1215 | ||
@@ -1475,7 +1391,7 @@ gss_wrap_req(struct rpc_task *task, | |||
1475 | struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); | 1391 | struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); |
1476 | int status = -EIO; | 1392 | int status = -EIO; |
1477 | 1393 | ||
1478 | dprintk("RPC: %5u %s\n", task->tk_pid, __func__); | 1394 | dprintk("RPC: %5u gss_wrap_req\n", task->tk_pid); |
1479 | if (ctx->gc_proc != RPC_GSS_PROC_DATA) { | 1395 | if (ctx->gc_proc != RPC_GSS_PROC_DATA) { |
1480 | /* The spec seems a little ambiguous here, but I think that not | 1396 | /* The spec seems a little ambiguous here, but I think that not |
1481 | * wrapping context destruction requests makes the most sense. | 1397 | * wrapping context destruction requests makes the most sense. |
@@ -1498,7 +1414,7 @@ gss_wrap_req(struct rpc_task *task, | |||
1498 | } | 1414 | } |
1499 | out: | 1415 | out: |
1500 | gss_put_ctx(ctx); | 1416 | gss_put_ctx(ctx); |
1501 | dprintk("RPC: %5u %s returning %d\n", task->tk_pid, __func__, status); | 1417 | dprintk("RPC: %5u gss_wrap_req returning %d\n", task->tk_pid, status); |
1502 | return status; | 1418 | return status; |
1503 | } | 1419 | } |
1504 | 1420 | ||
@@ -1613,8 +1529,8 @@ out_decode: | |||
1613 | status = gss_unwrap_req_decode(decode, rqstp, p, obj); | 1529 | status = gss_unwrap_req_decode(decode, rqstp, p, obj); |
1614 | out: | 1530 | out: |
1615 | gss_put_ctx(ctx); | 1531 | gss_put_ctx(ctx); |
1616 | dprintk("RPC: %5u %s returning %d\n", | 1532 | dprintk("RPC: %5u gss_unwrap_resp returning %d\n", task->tk_pid, |
1617 | task->tk_pid, __func__, status); | 1533 | status); |
1618 | return status; | 1534 | return status; |
1619 | } | 1535 | } |
1620 | 1536 | ||
@@ -1625,10 +1541,7 @@ static const struct rpc_authops authgss_ops = { | |||
1625 | .create = gss_create, | 1541 | .create = gss_create, |
1626 | .destroy = gss_destroy, | 1542 | .destroy = gss_destroy, |
1627 | .lookup_cred = gss_lookup_cred, | 1543 | .lookup_cred = gss_lookup_cred, |
1628 | .crcreate = gss_create_cred, | 1544 | .crcreate = gss_create_cred |
1629 | .pipes_create = gss_pipes_dentries_create, | ||
1630 | .pipes_destroy = gss_pipes_dentries_destroy, | ||
1631 | .list_pseudoflavors = gss_mech_list_pseudoflavors, | ||
1632 | }; | 1545 | }; |
1633 | 1546 | ||
1634 | static const struct rpc_credops gss_credops = { | 1547 | static const struct rpc_credops gss_credops = { |
@@ -1672,21 +1585,6 @@ static const struct rpc_pipe_ops gss_upcall_ops_v1 = { | |||
1672 | .release_pipe = gss_pipe_release, | 1585 | .release_pipe = gss_pipe_release, |
1673 | }; | 1586 | }; |
1674 | 1587 | ||
1675 | static __net_init int rpcsec_gss_init_net(struct net *net) | ||
1676 | { | ||
1677 | return gss_svc_init_net(net); | ||
1678 | } | ||
1679 | |||
1680 | static __net_exit void rpcsec_gss_exit_net(struct net *net) | ||
1681 | { | ||
1682 | gss_svc_shutdown_net(net); | ||
1683 | } | ||
1684 | |||
1685 | static struct pernet_operations rpcsec_gss_net_ops = { | ||
1686 | .init = rpcsec_gss_init_net, | ||
1687 | .exit = rpcsec_gss_exit_net, | ||
1688 | }; | ||
1689 | |||
1690 | /* | 1588 | /* |
1691 | * Initialize RPCSEC_GSS module | 1589 | * Initialize RPCSEC_GSS module |
1692 | */ | 1590 | */ |
@@ -1700,13 +1598,8 @@ static int __init init_rpcsec_gss(void) | |||
1700 | err = gss_svc_init(); | 1598 | err = gss_svc_init(); |
1701 | if (err) | 1599 | if (err) |
1702 | goto out_unregister; | 1600 | goto out_unregister; |
1703 | err = register_pernet_subsys(&rpcsec_gss_net_ops); | ||
1704 | if (err) | ||
1705 | goto out_svc_exit; | ||
1706 | rpc_init_wait_queue(&pipe_version_rpc_waitqueue, "gss pipe version"); | 1601 | rpc_init_wait_queue(&pipe_version_rpc_waitqueue, "gss pipe version"); |
1707 | return 0; | 1602 | return 0; |
1708 | out_svc_exit: | ||
1709 | gss_svc_shutdown(); | ||
1710 | out_unregister: | 1603 | out_unregister: |
1711 | rpcauth_unregister(&authgss_ops); | 1604 | rpcauth_unregister(&authgss_ops); |
1712 | out: | 1605 | out: |
@@ -1715,7 +1608,6 @@ out: | |||
1715 | 1608 | ||
1716 | static void __exit exit_rpcsec_gss(void) | 1609 | static void __exit exit_rpcsec_gss(void) |
1717 | { | 1610 | { |
1718 | unregister_pernet_subsys(&rpcsec_gss_net_ops); | ||
1719 | gss_svc_shutdown(); | 1611 | gss_svc_shutdown(); |
1720 | rpcauth_unregister(&authgss_ops); | 1612 | rpcauth_unregister(&authgss_ops); |
1721 | rcu_barrier(); /* Wait for completion of call_rcu()'s */ | 1613 | rcu_barrier(); /* Wait for completion of call_rcu()'s */ |
diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c index 0f43e894bc0..9576f35ab70 100644 --- a/net/sunrpc/auth_gss/gss_krb5_crypto.c +++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c | |||
@@ -600,14 +600,11 @@ gss_krb5_cts_crypt(struct crypto_blkcipher *cipher, struct xdr_buf *buf, | |||
600 | u32 ret; | 600 | u32 ret; |
601 | struct scatterlist sg[1]; | 601 | struct scatterlist sg[1]; |
602 | struct blkcipher_desc desc = { .tfm = cipher, .info = iv }; | 602 | struct blkcipher_desc desc = { .tfm = cipher, .info = iv }; |
603 | u8 data[GSS_KRB5_MAX_BLOCKSIZE * 2]; | 603 | u8 data[crypto_blkcipher_blocksize(cipher) * 2]; |
604 | struct page **save_pages; | 604 | struct page **save_pages; |
605 | u32 len = buf->len - offset; | 605 | u32 len = buf->len - offset; |
606 | 606 | ||
607 | if (len > ARRAY_SIZE(data)) { | 607 | BUG_ON(len > crypto_blkcipher_blocksize(cipher) * 2); |
608 | WARN_ON(0); | ||
609 | return -ENOMEM; | ||
610 | } | ||
611 | 608 | ||
612 | /* | 609 | /* |
613 | * For encryption, we want to read from the cleartext | 610 | * For encryption, we want to read from the cleartext |
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index d3611f11a8d..8c67890de42 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c | |||
@@ -344,7 +344,7 @@ out_err: | |||
344 | return PTR_ERR(p); | 344 | return PTR_ERR(p); |
345 | } | 345 | } |
346 | 346 | ||
347 | static struct crypto_blkcipher * | 347 | struct crypto_blkcipher * |
348 | context_v2_alloc_cipher(struct krb5_ctx *ctx, const char *cname, u8 *key) | 348 | context_v2_alloc_cipher(struct krb5_ctx *ctx, const char *cname, u8 *key) |
349 | { | 349 | { |
350 | struct crypto_blkcipher *cp; | 350 | struct crypto_blkcipher *cp; |
@@ -624,7 +624,7 @@ gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx, | |||
624 | ctx->seq_send = ctx->seq_send64; | 624 | ctx->seq_send = ctx->seq_send64; |
625 | if (ctx->seq_send64 != ctx->seq_send) { | 625 | if (ctx->seq_send64 != ctx->seq_send) { |
626 | dprintk("%s: seq_send64 %lx, seq_send %x overflow?\n", __func__, | 626 | dprintk("%s: seq_send64 %lx, seq_send %x overflow?\n", __func__, |
627 | (unsigned long)ctx->seq_send64, ctx->seq_send); | 627 | (long unsigned)ctx->seq_send64, ctx->seq_send); |
628 | p = ERR_PTR(-EINVAL); | 628 | p = ERR_PTR(-EINVAL); |
629 | goto out_err; | 629 | goto out_err; |
630 | } | 630 | } |
diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c index 62ae3273186..d7941eab779 100644 --- a/net/sunrpc/auth_gss/gss_krb5_seal.c +++ b/net/sunrpc/auth_gss/gss_krb5_seal.c | |||
@@ -159,7 +159,7 @@ gss_get_mic_v1(struct krb5_ctx *ctx, struct xdr_buf *text, | |||
159 | return (ctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE; | 159 | return (ctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE; |
160 | } | 160 | } |
161 | 161 | ||
162 | static u32 | 162 | u32 |
163 | gss_get_mic_v2(struct krb5_ctx *ctx, struct xdr_buf *text, | 163 | gss_get_mic_v2(struct krb5_ctx *ctx, struct xdr_buf *text, |
164 | struct xdr_netobj *token) | 164 | struct xdr_netobj *token) |
165 | { | 165 | { |
diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c index 107c4528654..2763e3e48db 100644 --- a/net/sunrpc/auth_gss/gss_krb5_wrap.c +++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c | |||
@@ -82,9 +82,9 @@ gss_krb5_remove_padding(struct xdr_buf *buf, int blocksize) | |||
82 | >>PAGE_CACHE_SHIFT; | 82 | >>PAGE_CACHE_SHIFT; |
83 | unsigned int offset = (buf->page_base + len - 1) | 83 | unsigned int offset = (buf->page_base + len - 1) |
84 | & (PAGE_CACHE_SIZE - 1); | 84 | & (PAGE_CACHE_SIZE - 1); |
85 | ptr = kmap_atomic(buf->pages[last]); | 85 | ptr = kmap_atomic(buf->pages[last], KM_USER0); |
86 | pad = *(ptr + offset); | 86 | pad = *(ptr + offset); |
87 | kunmap_atomic(ptr); | 87 | kunmap_atomic(ptr, KM_USER0); |
88 | goto out; | 88 | goto out; |
89 | } else | 89 | } else |
90 | len -= buf->page_len; | 90 | len -= buf->page_len; |
@@ -381,53 +381,21 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf) | |||
381 | } | 381 | } |
382 | 382 | ||
383 | /* | 383 | /* |
384 | * We can shift data by up to LOCAL_BUF_LEN bytes in a pass. If we need | 384 | * We cannot currently handle tokens with rotated data. We need a |
385 | * to do more than that, we shift repeatedly. Kevin Coffman reports | 385 | * generalized routine to rotate the data in place. It is anticipated |
386 | * seeing 28 bytes as the value used by Microsoft clients and servers | 386 | * that we won't encounter rotated data in the general case. |
387 | * with AES, so this constant is chosen to allow handling 28 in one pass | ||
388 | * without using too much stack space. | ||
389 | * | ||
390 | * If that proves to a problem perhaps we could use a more clever | ||
391 | * algorithm. | ||
392 | */ | 387 | */ |
393 | #define LOCAL_BUF_LEN 32u | 388 | static u32 |
394 | 389 | rotate_left(struct krb5_ctx *kctx, u32 offset, struct xdr_buf *buf, u16 rrc) | |
395 | static void rotate_buf_a_little(struct xdr_buf *buf, unsigned int shift) | ||
396 | { | ||
397 | char head[LOCAL_BUF_LEN]; | ||
398 | char tmp[LOCAL_BUF_LEN]; | ||
399 | unsigned int this_len, i; | ||
400 | |||
401 | BUG_ON(shift > LOCAL_BUF_LEN); | ||
402 | |||
403 | read_bytes_from_xdr_buf(buf, 0, head, shift); | ||
404 | for (i = 0; i + shift < buf->len; i += LOCAL_BUF_LEN) { | ||
405 | this_len = min(LOCAL_BUF_LEN, buf->len - (i + shift)); | ||
406 | read_bytes_from_xdr_buf(buf, i+shift, tmp, this_len); | ||
407 | write_bytes_to_xdr_buf(buf, i, tmp, this_len); | ||
408 | } | ||
409 | write_bytes_to_xdr_buf(buf, buf->len - shift, head, shift); | ||
410 | } | ||
411 | |||
412 | static void _rotate_left(struct xdr_buf *buf, unsigned int shift) | ||
413 | { | 390 | { |
414 | int shifted = 0; | 391 | unsigned int realrrc = rrc % (buf->len - offset - GSS_KRB5_TOK_HDR_LEN); |
415 | int this_shift; | ||
416 | |||
417 | shift %= buf->len; | ||
418 | while (shifted < shift) { | ||
419 | this_shift = min(shift - shifted, LOCAL_BUF_LEN); | ||
420 | rotate_buf_a_little(buf, this_shift); | ||
421 | shifted += this_shift; | ||
422 | } | ||
423 | } | ||
424 | 392 | ||
425 | static void rotate_left(u32 base, struct xdr_buf *buf, unsigned int shift) | 393 | if (realrrc == 0) |
426 | { | 394 | return 0; |
427 | struct xdr_buf subbuf; | ||
428 | 395 | ||
429 | xdr_buf_subsegment(buf, &subbuf, base, buf->len - base); | 396 | dprintk("%s: cannot process token with rotated data: " |
430 | _rotate_left(&subbuf, shift); | 397 | "rrc %u, realrrc %u\n", __func__, rrc, realrrc); |
398 | return 1; | ||
431 | } | 399 | } |
432 | 400 | ||
433 | static u32 | 401 | static u32 |
@@ -527,8 +495,11 @@ gss_unwrap_kerberos_v2(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf) | |||
527 | 495 | ||
528 | seqnum = be64_to_cpup((__be64 *)(ptr + 8)); | 496 | seqnum = be64_to_cpup((__be64 *)(ptr + 8)); |
529 | 497 | ||
530 | if (rrc != 0) | 498 | if (rrc != 0) { |
531 | rotate_left(offset + 16, buf, rrc); | 499 | err = rotate_left(kctx, offset, buf, rrc); |
500 | if (err) | ||
501 | return GSS_S_FAILURE; | ||
502 | } | ||
532 | 503 | ||
533 | err = (*kctx->gk5e->decrypt_v2)(kctx, offset, buf, | 504 | err = (*kctx->gk5e->decrypt_v2)(kctx, offset, buf, |
534 | &headskip, &tailskip); | 505 | &headskip, &tailskip); |
diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c index b174fcd9ff4..ca8cad8251c 100644 --- a/net/sunrpc/auth_gss/gss_mech_switch.c +++ b/net/sunrpc/auth_gss/gss_mech_switch.c | |||
@@ -239,35 +239,22 @@ gss_mech_get_by_pseudoflavor(u32 pseudoflavor) | |||
239 | 239 | ||
240 | EXPORT_SYMBOL_GPL(gss_mech_get_by_pseudoflavor); | 240 | EXPORT_SYMBOL_GPL(gss_mech_get_by_pseudoflavor); |
241 | 241 | ||
242 | /** | 242 | int gss_mech_list_pseudoflavors(rpc_authflavor_t *array_ptr) |
243 | * gss_mech_list_pseudoflavors - Discover registered GSS pseudoflavors | ||
244 | * @array: array to fill in | ||
245 | * @size: size of "array" | ||
246 | * | ||
247 | * Returns the number of array items filled in, or a negative errno. | ||
248 | * | ||
249 | * The returned array is not sorted by any policy. Callers should not | ||
250 | * rely on the order of the items in the returned array. | ||
251 | */ | ||
252 | int gss_mech_list_pseudoflavors(rpc_authflavor_t *array_ptr, int size) | ||
253 | { | 243 | { |
254 | struct gss_api_mech *pos = NULL; | 244 | struct gss_api_mech *pos = NULL; |
255 | int j, i = 0; | 245 | int i = 0; |
256 | 246 | ||
257 | spin_lock(®istered_mechs_lock); | 247 | spin_lock(®istered_mechs_lock); |
258 | list_for_each_entry(pos, ®istered_mechs, gm_list) { | 248 | list_for_each_entry(pos, ®istered_mechs, gm_list) { |
259 | for (j = 0; j < pos->gm_pf_num; j++) { | 249 | array_ptr[i] = pos->gm_pfs->pseudoflavor; |
260 | if (i >= size) { | 250 | i++; |
261 | spin_unlock(®istered_mechs_lock); | ||
262 | return -ENOMEM; | ||
263 | } | ||
264 | array_ptr[i++] = pos->gm_pfs[j].pseudoflavor; | ||
265 | } | ||
266 | } | 251 | } |
267 | spin_unlock(®istered_mechs_lock); | 252 | spin_unlock(®istered_mechs_lock); |
268 | return i; | 253 | return i; |
269 | } | 254 | } |
270 | 255 | ||
256 | EXPORT_SYMBOL_GPL(gss_mech_list_pseudoflavors); | ||
257 | |||
271 | u32 | 258 | u32 |
272 | gss_svc_to_pseudoflavor(struct gss_api_mech *gm, u32 service) | 259 | gss_svc_to_pseudoflavor(struct gss_api_mech *gm, u32 service) |
273 | { | 260 | { |
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 73e95738660..8d0f7d3c71c 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c | |||
@@ -41,7 +41,6 @@ | |||
41 | #include <linux/types.h> | 41 | #include <linux/types.h> |
42 | #include <linux/module.h> | 42 | #include <linux/module.h> |
43 | #include <linux/pagemap.h> | 43 | #include <linux/pagemap.h> |
44 | #include <linux/user_namespace.h> | ||
45 | 44 | ||
46 | #include <linux/sunrpc/auth_gss.h> | 45 | #include <linux/sunrpc/auth_gss.h> |
47 | #include <linux/sunrpc/gss_err.h> | 46 | #include <linux/sunrpc/gss_err.h> |
@@ -49,8 +48,6 @@ | |||
49 | #include <linux/sunrpc/svcauth_gss.h> | 48 | #include <linux/sunrpc/svcauth_gss.h> |
50 | #include <linux/sunrpc/cache.h> | 49 | #include <linux/sunrpc/cache.h> |
51 | 50 | ||
52 | #include "../netns.h" | ||
53 | |||
54 | #ifdef RPC_DEBUG | 51 | #ifdef RPC_DEBUG |
55 | # define RPCDBG_FACILITY RPCDBG_AUTH | 52 | # define RPCDBG_FACILITY RPCDBG_AUTH |
56 | #endif | 53 | #endif |
@@ -78,8 +75,10 @@ struct rsi { | |||
78 | int major_status, minor_status; | 75 | int major_status, minor_status; |
79 | }; | 76 | }; |
80 | 77 | ||
81 | static struct rsi *rsi_update(struct cache_detail *cd, struct rsi *new, struct rsi *old); | 78 | static struct cache_head *rsi_table[RSI_HASHMAX]; |
82 | static struct rsi *rsi_lookup(struct cache_detail *cd, struct rsi *item); | 79 | static struct cache_detail rsi_cache; |
80 | static struct rsi *rsi_update(struct rsi *new, struct rsi *old); | ||
81 | static struct rsi *rsi_lookup(struct rsi *item); | ||
83 | 82 | ||
84 | static void rsi_free(struct rsi *rsii) | 83 | static void rsi_free(struct rsi *rsii) |
85 | { | 84 | { |
@@ -217,7 +216,7 @@ static int rsi_parse(struct cache_detail *cd, | |||
217 | if (dup_to_netobj(&rsii.in_token, buf, len)) | 216 | if (dup_to_netobj(&rsii.in_token, buf, len)) |
218 | goto out; | 217 | goto out; |
219 | 218 | ||
220 | rsip = rsi_lookup(cd, &rsii); | 219 | rsip = rsi_lookup(&rsii); |
221 | if (!rsip) | 220 | if (!rsip) |
222 | goto out; | 221 | goto out; |
223 | 222 | ||
@@ -259,20 +258,21 @@ static int rsi_parse(struct cache_detail *cd, | |||
259 | if (dup_to_netobj(&rsii.out_token, buf, len)) | 258 | if (dup_to_netobj(&rsii.out_token, buf, len)) |
260 | goto out; | 259 | goto out; |
261 | rsii.h.expiry_time = expiry; | 260 | rsii.h.expiry_time = expiry; |
262 | rsip = rsi_update(cd, &rsii, rsip); | 261 | rsip = rsi_update(&rsii, rsip); |
263 | status = 0; | 262 | status = 0; |
264 | out: | 263 | out: |
265 | rsi_free(&rsii); | 264 | rsi_free(&rsii); |
266 | if (rsip) | 265 | if (rsip) |
267 | cache_put(&rsip->h, cd); | 266 | cache_put(&rsip->h, &rsi_cache); |
268 | else | 267 | else |
269 | status = -ENOMEM; | 268 | status = -ENOMEM; |
270 | return status; | 269 | return status; |
271 | } | 270 | } |
272 | 271 | ||
273 | static struct cache_detail rsi_cache_template = { | 272 | static struct cache_detail rsi_cache = { |
274 | .owner = THIS_MODULE, | 273 | .owner = THIS_MODULE, |
275 | .hash_size = RSI_HASHMAX, | 274 | .hash_size = RSI_HASHMAX, |
275 | .hash_table = rsi_table, | ||
276 | .name = "auth.rpcsec.init", | 276 | .name = "auth.rpcsec.init", |
277 | .cache_put = rsi_put, | 277 | .cache_put = rsi_put, |
278 | .cache_upcall = rsi_upcall, | 278 | .cache_upcall = rsi_upcall, |
@@ -283,24 +283,24 @@ static struct cache_detail rsi_cache_template = { | |||
283 | .alloc = rsi_alloc, | 283 | .alloc = rsi_alloc, |
284 | }; | 284 | }; |
285 | 285 | ||
286 | static struct rsi *rsi_lookup(struct cache_detail *cd, struct rsi *item) | 286 | static struct rsi *rsi_lookup(struct rsi *item) |
287 | { | 287 | { |
288 | struct cache_head *ch; | 288 | struct cache_head *ch; |
289 | int hash = rsi_hash(item); | 289 | int hash = rsi_hash(item); |
290 | 290 | ||
291 | ch = sunrpc_cache_lookup(cd, &item->h, hash); | 291 | ch = sunrpc_cache_lookup(&rsi_cache, &item->h, hash); |
292 | if (ch) | 292 | if (ch) |
293 | return container_of(ch, struct rsi, h); | 293 | return container_of(ch, struct rsi, h); |
294 | else | 294 | else |
295 | return NULL; | 295 | return NULL; |
296 | } | 296 | } |
297 | 297 | ||
298 | static struct rsi *rsi_update(struct cache_detail *cd, struct rsi *new, struct rsi *old) | 298 | static struct rsi *rsi_update(struct rsi *new, struct rsi *old) |
299 | { | 299 | { |
300 | struct cache_head *ch; | 300 | struct cache_head *ch; |
301 | int hash = rsi_hash(new); | 301 | int hash = rsi_hash(new); |
302 | 302 | ||
303 | ch = sunrpc_cache_update(cd, &new->h, | 303 | ch = sunrpc_cache_update(&rsi_cache, &new->h, |
304 | &old->h, hash); | 304 | &old->h, hash); |
305 | if (ch) | 305 | if (ch) |
306 | return container_of(ch, struct rsi, h); | 306 | return container_of(ch, struct rsi, h); |
@@ -336,17 +336,22 @@ struct rsc { | |||
336 | struct svc_cred cred; | 336 | struct svc_cred cred; |
337 | struct gss_svc_seq_data seqdata; | 337 | struct gss_svc_seq_data seqdata; |
338 | struct gss_ctx *mechctx; | 338 | struct gss_ctx *mechctx; |
339 | char *client_name; | ||
339 | }; | 340 | }; |
340 | 341 | ||
341 | static struct rsc *rsc_update(struct cache_detail *cd, struct rsc *new, struct rsc *old); | 342 | static struct cache_head *rsc_table[RSC_HASHMAX]; |
342 | static struct rsc *rsc_lookup(struct cache_detail *cd, struct rsc *item); | 343 | static struct cache_detail rsc_cache; |
344 | static struct rsc *rsc_update(struct rsc *new, struct rsc *old); | ||
345 | static struct rsc *rsc_lookup(struct rsc *item); | ||
343 | 346 | ||
344 | static void rsc_free(struct rsc *rsci) | 347 | static void rsc_free(struct rsc *rsci) |
345 | { | 348 | { |
346 | kfree(rsci->handle.data); | 349 | kfree(rsci->handle.data); |
347 | if (rsci->mechctx) | 350 | if (rsci->mechctx) |
348 | gss_delete_sec_context(&rsci->mechctx); | 351 | gss_delete_sec_context(&rsci->mechctx); |
349 | free_svc_cred(&rsci->cred); | 352 | if (rsci->cred.cr_group_info) |
353 | put_group_info(rsci->cred.cr_group_info); | ||
354 | kfree(rsci->client_name); | ||
350 | } | 355 | } |
351 | 356 | ||
352 | static void rsc_put(struct kref *ref) | 357 | static void rsc_put(struct kref *ref) |
@@ -384,7 +389,7 @@ rsc_init(struct cache_head *cnew, struct cache_head *ctmp) | |||
384 | tmp->handle.data = NULL; | 389 | tmp->handle.data = NULL; |
385 | new->mechctx = NULL; | 390 | new->mechctx = NULL; |
386 | new->cred.cr_group_info = NULL; | 391 | new->cred.cr_group_info = NULL; |
387 | new->cred.cr_principal = NULL; | 392 | new->client_name = NULL; |
388 | } | 393 | } |
389 | 394 | ||
390 | static void | 395 | static void |
@@ -399,8 +404,8 @@ update_rsc(struct cache_head *cnew, struct cache_head *ctmp) | |||
399 | spin_lock_init(&new->seqdata.sd_lock); | 404 | spin_lock_init(&new->seqdata.sd_lock); |
400 | new->cred = tmp->cred; | 405 | new->cred = tmp->cred; |
401 | tmp->cred.cr_group_info = NULL; | 406 | tmp->cred.cr_group_info = NULL; |
402 | new->cred.cr_principal = tmp->cred.cr_principal; | 407 | new->client_name = tmp->client_name; |
403 | tmp->cred.cr_principal = NULL; | 408 | tmp->client_name = NULL; |
404 | } | 409 | } |
405 | 410 | ||
406 | static struct cache_head * | 411 | static struct cache_head * |
@@ -439,7 +444,7 @@ static int rsc_parse(struct cache_detail *cd, | |||
439 | if (expiry == 0) | 444 | if (expiry == 0) |
440 | goto out; | 445 | goto out; |
441 | 446 | ||
442 | rscp = rsc_lookup(cd, &rsci); | 447 | rscp = rsc_lookup(&rsci); |
443 | if (!rscp) | 448 | if (!rscp) |
444 | goto out; | 449 | goto out; |
445 | 450 | ||
@@ -468,13 +473,9 @@ static int rsc_parse(struct cache_detail *cd, | |||
468 | status = -EINVAL; | 473 | status = -EINVAL; |
469 | for (i=0; i<N; i++) { | 474 | for (i=0; i<N; i++) { |
470 | gid_t gid; | 475 | gid_t gid; |
471 | kgid_t kgid; | ||
472 | if (get_int(&mesg, &gid)) | 476 | if (get_int(&mesg, &gid)) |
473 | goto out; | 477 | goto out; |
474 | kgid = make_kgid(&init_user_ns, gid); | 478 | GROUP_AT(rsci.cred.cr_group_info, i) = gid; |
475 | if (!gid_valid(kgid)) | ||
476 | goto out; | ||
477 | GROUP_AT(rsci.cred.cr_group_info, i) = kgid; | ||
478 | } | 479 | } |
479 | 480 | ||
480 | /* mech name */ | 481 | /* mech name */ |
@@ -498,28 +499,29 @@ static int rsc_parse(struct cache_detail *cd, | |||
498 | /* get client name */ | 499 | /* get client name */ |
499 | len = qword_get(&mesg, buf, mlen); | 500 | len = qword_get(&mesg, buf, mlen); |
500 | if (len > 0) { | 501 | if (len > 0) { |
501 | rsci.cred.cr_principal = kstrdup(buf, GFP_KERNEL); | 502 | rsci.client_name = kstrdup(buf, GFP_KERNEL); |
502 | if (!rsci.cred.cr_principal) | 503 | if (!rsci.client_name) |
503 | goto out; | 504 | goto out; |
504 | } | 505 | } |
505 | 506 | ||
506 | } | 507 | } |
507 | rsci.h.expiry_time = expiry; | 508 | rsci.h.expiry_time = expiry; |
508 | rscp = rsc_update(cd, &rsci, rscp); | 509 | rscp = rsc_update(&rsci, rscp); |
509 | status = 0; | 510 | status = 0; |
510 | out: | 511 | out: |
511 | gss_mech_put(gm); | 512 | gss_mech_put(gm); |
512 | rsc_free(&rsci); | 513 | rsc_free(&rsci); |
513 | if (rscp) | 514 | if (rscp) |
514 | cache_put(&rscp->h, cd); | 515 | cache_put(&rscp->h, &rsc_cache); |
515 | else | 516 | else |
516 | status = -ENOMEM; | 517 | status = -ENOMEM; |
517 | return status; | 518 | return status; |
518 | } | 519 | } |
519 | 520 | ||
520 | static struct cache_detail rsc_cache_template = { | 521 | static struct cache_detail rsc_cache = { |
521 | .owner = THIS_MODULE, | 522 | .owner = THIS_MODULE, |
522 | .hash_size = RSC_HASHMAX, | 523 | .hash_size = RSC_HASHMAX, |
524 | .hash_table = rsc_table, | ||
523 | .name = "auth.rpcsec.context", | 525 | .name = "auth.rpcsec.context", |
524 | .cache_put = rsc_put, | 526 | .cache_put = rsc_put, |
525 | .cache_parse = rsc_parse, | 527 | .cache_parse = rsc_parse, |
@@ -529,24 +531,24 @@ static struct cache_detail rsc_cache_template = { | |||
529 | .alloc = rsc_alloc, | 531 | .alloc = rsc_alloc, |
530 | }; | 532 | }; |
531 | 533 | ||
532 | static struct rsc *rsc_lookup(struct cache_detail *cd, struct rsc *item) | 534 | static struct rsc *rsc_lookup(struct rsc *item) |
533 | { | 535 | { |
534 | struct cache_head *ch; | 536 | struct cache_head *ch; |
535 | int hash = rsc_hash(item); | 537 | int hash = rsc_hash(item); |
536 | 538 | ||
537 | ch = sunrpc_cache_lookup(cd, &item->h, hash); | 539 | ch = sunrpc_cache_lookup(&rsc_cache, &item->h, hash); |
538 | if (ch) | 540 | if (ch) |
539 | return container_of(ch, struct rsc, h); | 541 | return container_of(ch, struct rsc, h); |
540 | else | 542 | else |
541 | return NULL; | 543 | return NULL; |
542 | } | 544 | } |
543 | 545 | ||
544 | static struct rsc *rsc_update(struct cache_detail *cd, struct rsc *new, struct rsc *old) | 546 | static struct rsc *rsc_update(struct rsc *new, struct rsc *old) |
545 | { | 547 | { |
546 | struct cache_head *ch; | 548 | struct cache_head *ch; |
547 | int hash = rsc_hash(new); | 549 | int hash = rsc_hash(new); |
548 | 550 | ||
549 | ch = sunrpc_cache_update(cd, &new->h, | 551 | ch = sunrpc_cache_update(&rsc_cache, &new->h, |
550 | &old->h, hash); | 552 | &old->h, hash); |
551 | if (ch) | 553 | if (ch) |
552 | return container_of(ch, struct rsc, h); | 554 | return container_of(ch, struct rsc, h); |
@@ -556,7 +558,7 @@ static struct rsc *rsc_update(struct cache_detail *cd, struct rsc *new, struct r | |||
556 | 558 | ||
557 | 559 | ||
558 | static struct rsc * | 560 | static struct rsc * |
559 | gss_svc_searchbyctx(struct cache_detail *cd, struct xdr_netobj *handle) | 561 | gss_svc_searchbyctx(struct xdr_netobj *handle) |
560 | { | 562 | { |
561 | struct rsc rsci; | 563 | struct rsc rsci; |
562 | struct rsc *found; | 564 | struct rsc *found; |
@@ -564,11 +566,11 @@ gss_svc_searchbyctx(struct cache_detail *cd, struct xdr_netobj *handle) | |||
564 | memset(&rsci, 0, sizeof(rsci)); | 566 | memset(&rsci, 0, sizeof(rsci)); |
565 | if (dup_to_netobj(&rsci.handle, handle->data, handle->len)) | 567 | if (dup_to_netobj(&rsci.handle, handle->data, handle->len)) |
566 | return NULL; | 568 | return NULL; |
567 | found = rsc_lookup(cd, &rsci); | 569 | found = rsc_lookup(&rsci); |
568 | rsc_free(&rsci); | 570 | rsc_free(&rsci); |
569 | if (!found) | 571 | if (!found) |
570 | return NULL; | 572 | return NULL; |
571 | if (cache_check(cd, &found->h, NULL)) | 573 | if (cache_check(&rsc_cache, &found->h, NULL)) |
572 | return NULL; | 574 | return NULL; |
573 | return found; | 575 | return found; |
574 | } | 576 | } |
@@ -929,6 +931,16 @@ struct gss_svc_data { | |||
929 | struct rsc *rsci; | 931 | struct rsc *rsci; |
930 | }; | 932 | }; |
931 | 933 | ||
934 | char *svc_gss_principal(struct svc_rqst *rqstp) | ||
935 | { | ||
936 | struct gss_svc_data *gd = (struct gss_svc_data *)rqstp->rq_auth_data; | ||
937 | |||
938 | if (gd && gd->rsci) | ||
939 | return gd->rsci->client_name; | ||
940 | return NULL; | ||
941 | } | ||
942 | EXPORT_SYMBOL_GPL(svc_gss_principal); | ||
943 | |||
932 | static int | 944 | static int |
933 | svcauth_gss_set_client(struct svc_rqst *rqstp) | 945 | svcauth_gss_set_client(struct svc_rqst *rqstp) |
934 | { | 946 | { |
@@ -956,31 +968,38 @@ svcauth_gss_set_client(struct svc_rqst *rqstp) | |||
956 | } | 968 | } |
957 | 969 | ||
958 | static inline int | 970 | static inline int |
959 | gss_write_init_verf(struct cache_detail *cd, struct svc_rqst *rqstp, | 971 | gss_write_init_verf(struct svc_rqst *rqstp, struct rsi *rsip) |
960 | struct xdr_netobj *out_handle, int *major_status) | ||
961 | { | 972 | { |
962 | struct rsc *rsci; | 973 | struct rsc *rsci; |
963 | int rc; | 974 | int rc; |
964 | 975 | ||
965 | if (*major_status != GSS_S_COMPLETE) | 976 | if (rsip->major_status != GSS_S_COMPLETE) |
966 | return gss_write_null_verf(rqstp); | 977 | return gss_write_null_verf(rqstp); |
967 | rsci = gss_svc_searchbyctx(cd, out_handle); | 978 | rsci = gss_svc_searchbyctx(&rsip->out_handle); |
968 | if (rsci == NULL) { | 979 | if (rsci == NULL) { |
969 | *major_status = GSS_S_NO_CONTEXT; | 980 | rsip->major_status = GSS_S_NO_CONTEXT; |
970 | return gss_write_null_verf(rqstp); | 981 | return gss_write_null_verf(rqstp); |
971 | } | 982 | } |
972 | rc = gss_write_verf(rqstp, rsci->mechctx, GSS_SEQ_WIN); | 983 | rc = gss_write_verf(rqstp, rsci->mechctx, GSS_SEQ_WIN); |
973 | cache_put(&rsci->h, cd); | 984 | cache_put(&rsci->h, &rsc_cache); |
974 | return rc; | 985 | return rc; |
975 | } | 986 | } |
976 | 987 | ||
977 | static inline int | 988 | /* |
978 | gss_read_verf(struct rpc_gss_wire_cred *gc, | 989 | * Having read the cred already and found we're in the context |
979 | struct kvec *argv, __be32 *authp, | 990 | * initiation case, read the verifier and initiate (or check the results |
980 | struct xdr_netobj *in_handle, | 991 | * of) upcalls to userspace for help with context initiation. If |
981 | struct xdr_netobj *in_token) | 992 | * the upcall results are available, write the verifier and result. |
993 | * Otherwise, drop the request pending an answer to the upcall. | ||
994 | */ | ||
995 | static int svcauth_gss_handle_init(struct svc_rqst *rqstp, | ||
996 | struct rpc_gss_wire_cred *gc, __be32 *authp) | ||
982 | { | 997 | { |
998 | struct kvec *argv = &rqstp->rq_arg.head[0]; | ||
999 | struct kvec *resv = &rqstp->rq_res.head[0]; | ||
983 | struct xdr_netobj tmpobj; | 1000 | struct xdr_netobj tmpobj; |
1001 | struct rsi *rsip, rsikey; | ||
1002 | int ret; | ||
984 | 1003 | ||
985 | /* Read the verifier; should be NULL: */ | 1004 | /* Read the verifier; should be NULL: */ |
986 | *authp = rpc_autherr_badverf; | 1005 | *authp = rpc_autherr_badverf; |
@@ -990,89 +1009,53 @@ gss_read_verf(struct rpc_gss_wire_cred *gc, | |||
990 | return SVC_DENIED; | 1009 | return SVC_DENIED; |
991 | if (svc_getnl(argv) != 0) | 1010 | if (svc_getnl(argv) != 0) |
992 | return SVC_DENIED; | 1011 | return SVC_DENIED; |
1012 | |||
993 | /* Martial context handle and token for upcall: */ | 1013 | /* Martial context handle and token for upcall: */ |
994 | *authp = rpc_autherr_badcred; | 1014 | *authp = rpc_autherr_badcred; |
995 | if (gc->gc_proc == RPC_GSS_PROC_INIT && gc->gc_ctx.len != 0) | 1015 | if (gc->gc_proc == RPC_GSS_PROC_INIT && gc->gc_ctx.len != 0) |
996 | return SVC_DENIED; | 1016 | return SVC_DENIED; |
997 | if (dup_netobj(in_handle, &gc->gc_ctx)) | 1017 | memset(&rsikey, 0, sizeof(rsikey)); |
1018 | if (dup_netobj(&rsikey.in_handle, &gc->gc_ctx)) | ||
998 | return SVC_CLOSE; | 1019 | return SVC_CLOSE; |
999 | *authp = rpc_autherr_badverf; | 1020 | *authp = rpc_autherr_badverf; |
1000 | if (svc_safe_getnetobj(argv, &tmpobj)) { | 1021 | if (svc_safe_getnetobj(argv, &tmpobj)) { |
1001 | kfree(in_handle->data); | 1022 | kfree(rsikey.in_handle.data); |
1002 | return SVC_DENIED; | 1023 | return SVC_DENIED; |
1003 | } | 1024 | } |
1004 | if (dup_netobj(in_token, &tmpobj)) { | 1025 | if (dup_netobj(&rsikey.in_token, &tmpobj)) { |
1005 | kfree(in_handle->data); | 1026 | kfree(rsikey.in_handle.data); |
1006 | return SVC_CLOSE; | 1027 | return SVC_CLOSE; |
1007 | } | 1028 | } |
1008 | 1029 | ||
1009 | return 0; | ||
1010 | } | ||
1011 | |||
1012 | static inline int | ||
1013 | gss_write_resv(struct kvec *resv, size_t size_limit, | ||
1014 | struct xdr_netobj *out_handle, struct xdr_netobj *out_token, | ||
1015 | int major_status, int minor_status) | ||
1016 | { | ||
1017 | if (resv->iov_len + 4 > size_limit) | ||
1018 | return -1; | ||
1019 | svc_putnl(resv, RPC_SUCCESS); | ||
1020 | if (svc_safe_putnetobj(resv, out_handle)) | ||
1021 | return -1; | ||
1022 | if (resv->iov_len + 3 * 4 > size_limit) | ||
1023 | return -1; | ||
1024 | svc_putnl(resv, major_status); | ||
1025 | svc_putnl(resv, minor_status); | ||
1026 | svc_putnl(resv, GSS_SEQ_WIN); | ||
1027 | if (svc_safe_putnetobj(resv, out_token)) | ||
1028 | return -1; | ||
1029 | return 0; | ||
1030 | } | ||
1031 | |||
1032 | /* | ||
1033 | * Having read the cred already and found we're in the context | ||
1034 | * initiation case, read the verifier and initiate (or check the results | ||
1035 | * of) upcalls to userspace for help with context initiation. If | ||
1036 | * the upcall results are available, write the verifier and result. | ||
1037 | * Otherwise, drop the request pending an answer to the upcall. | ||
1038 | */ | ||
1039 | static int svcauth_gss_handle_init(struct svc_rqst *rqstp, | ||
1040 | struct rpc_gss_wire_cred *gc, __be32 *authp) | ||
1041 | { | ||
1042 | struct kvec *argv = &rqstp->rq_arg.head[0]; | ||
1043 | struct kvec *resv = &rqstp->rq_res.head[0]; | ||
1044 | struct rsi *rsip, rsikey; | ||
1045 | int ret; | ||
1046 | struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, sunrpc_net_id); | ||
1047 | |||
1048 | memset(&rsikey, 0, sizeof(rsikey)); | ||
1049 | ret = gss_read_verf(gc, argv, authp, | ||
1050 | &rsikey.in_handle, &rsikey.in_token); | ||
1051 | if (ret) | ||
1052 | return ret; | ||
1053 | |||
1054 | /* Perform upcall, or find upcall result: */ | 1030 | /* Perform upcall, or find upcall result: */ |
1055 | rsip = rsi_lookup(sn->rsi_cache, &rsikey); | 1031 | rsip = rsi_lookup(&rsikey); |
1056 | rsi_free(&rsikey); | 1032 | rsi_free(&rsikey); |
1057 | if (!rsip) | 1033 | if (!rsip) |
1058 | return SVC_CLOSE; | 1034 | return SVC_CLOSE; |
1059 | if (cache_check(sn->rsi_cache, &rsip->h, &rqstp->rq_chandle) < 0) | 1035 | if (cache_check(&rsi_cache, &rsip->h, &rqstp->rq_chandle) < 0) |
1060 | /* No upcall result: */ | 1036 | /* No upcall result: */ |
1061 | return SVC_CLOSE; | 1037 | return SVC_CLOSE; |
1062 | 1038 | ||
1063 | ret = SVC_CLOSE; | 1039 | ret = SVC_CLOSE; |
1064 | /* Got an answer to the upcall; use it: */ | 1040 | /* Got an answer to the upcall; use it: */ |
1065 | if (gss_write_init_verf(sn->rsc_cache, rqstp, | 1041 | if (gss_write_init_verf(rqstp, rsip)) |
1066 | &rsip->out_handle, &rsip->major_status)) | 1042 | goto out; |
1043 | if (resv->iov_len + 4 > PAGE_SIZE) | ||
1044 | goto out; | ||
1045 | svc_putnl(resv, RPC_SUCCESS); | ||
1046 | if (svc_safe_putnetobj(resv, &rsip->out_handle)) | ||
1067 | goto out; | 1047 | goto out; |
1068 | if (gss_write_resv(resv, PAGE_SIZE, | 1048 | if (resv->iov_len + 3 * 4 > PAGE_SIZE) |
1069 | &rsip->out_handle, &rsip->out_token, | 1049 | goto out; |
1070 | rsip->major_status, rsip->minor_status)) | 1050 | svc_putnl(resv, rsip->major_status); |
1051 | svc_putnl(resv, rsip->minor_status); | ||
1052 | svc_putnl(resv, GSS_SEQ_WIN); | ||
1053 | if (svc_safe_putnetobj(resv, &rsip->out_token)) | ||
1071 | goto out; | 1054 | goto out; |
1072 | 1055 | ||
1073 | ret = SVC_COMPLETE; | 1056 | ret = SVC_COMPLETE; |
1074 | out: | 1057 | out: |
1075 | cache_put(&rsip->h, sn->rsi_cache); | 1058 | cache_put(&rsip->h, &rsi_cache); |
1076 | return ret; | 1059 | return ret; |
1077 | } | 1060 | } |
1078 | 1061 | ||
@@ -1096,7 +1079,6 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
1096 | __be32 *rpcstart; | 1079 | __be32 *rpcstart; |
1097 | __be32 *reject_stat = resv->iov_base + resv->iov_len; | 1080 | __be32 *reject_stat = resv->iov_base + resv->iov_len; |
1098 | int ret; | 1081 | int ret; |
1099 | struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, sunrpc_net_id); | ||
1100 | 1082 | ||
1101 | dprintk("RPC: svcauth_gss: argv->iov_len = %zd\n", | 1083 | dprintk("RPC: svcauth_gss: argv->iov_len = %zd\n", |
1102 | argv->iov_len); | 1084 | argv->iov_len); |
@@ -1147,7 +1129,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
1147 | case RPC_GSS_PROC_DESTROY: | 1129 | case RPC_GSS_PROC_DESTROY: |
1148 | /* Look up the context, and check the verifier: */ | 1130 | /* Look up the context, and check the verifier: */ |
1149 | *authp = rpcsec_gsserr_credproblem; | 1131 | *authp = rpcsec_gsserr_credproblem; |
1150 | rsci = gss_svc_searchbyctx(sn->rsc_cache, &gc->gc_ctx); | 1132 | rsci = gss_svc_searchbyctx(&gc->gc_ctx); |
1151 | if (!rsci) | 1133 | if (!rsci) |
1152 | goto auth_err; | 1134 | goto auth_err; |
1153 | switch (gss_verify_header(rqstp, rsci, rpcstart, gc, authp)) { | 1135 | switch (gss_verify_header(rqstp, rsci, rpcstart, gc, authp)) { |
@@ -1207,7 +1189,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
1207 | } | 1189 | } |
1208 | svcdata->rsci = rsci; | 1190 | svcdata->rsci = rsci; |
1209 | cache_get(&rsci->h); | 1191 | cache_get(&rsci->h); |
1210 | rqstp->rq_cred.cr_flavor = gss_svc_to_pseudoflavor( | 1192 | rqstp->rq_flavor = gss_svc_to_pseudoflavor( |
1211 | rsci->mechctx->mech_type, gc->gc_svc); | 1193 | rsci->mechctx->mech_type, gc->gc_svc); |
1212 | ret = SVC_OK; | 1194 | ret = SVC_OK; |
1213 | goto out; | 1195 | goto out; |
@@ -1227,7 +1209,7 @@ drop: | |||
1227 | ret = SVC_DROP; | 1209 | ret = SVC_DROP; |
1228 | out: | 1210 | out: |
1229 | if (rsci) | 1211 | if (rsci) |
1230 | cache_put(&rsci->h, sn->rsc_cache); | 1212 | cache_put(&rsci->h, &rsc_cache); |
1231 | return ret; | 1213 | return ret; |
1232 | } | 1214 | } |
1233 | 1215 | ||
@@ -1380,7 +1362,6 @@ svcauth_gss_release(struct svc_rqst *rqstp) | |||
1380 | struct rpc_gss_wire_cred *gc = &gsd->clcred; | 1362 | struct rpc_gss_wire_cred *gc = &gsd->clcred; |
1381 | struct xdr_buf *resbuf = &rqstp->rq_res; | 1363 | struct xdr_buf *resbuf = &rqstp->rq_res; |
1382 | int stat = -EINVAL; | 1364 | int stat = -EINVAL; |
1383 | struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, sunrpc_net_id); | ||
1384 | 1365 | ||
1385 | if (gc->gc_proc != RPC_GSS_PROC_DATA) | 1366 | if (gc->gc_proc != RPC_GSS_PROC_DATA) |
1386 | goto out; | 1367 | goto out; |
@@ -1423,7 +1404,7 @@ out_err: | |||
1423 | put_group_info(rqstp->rq_cred.cr_group_info); | 1404 | put_group_info(rqstp->rq_cred.cr_group_info); |
1424 | rqstp->rq_cred.cr_group_info = NULL; | 1405 | rqstp->rq_cred.cr_group_info = NULL; |
1425 | if (gsd->rsci) | 1406 | if (gsd->rsci) |
1426 | cache_put(&gsd->rsci->h, sn->rsc_cache); | 1407 | cache_put(&gsd->rsci->h, &rsc_cache); |
1427 | gsd->rsci = NULL; | 1408 | gsd->rsci = NULL; |
1428 | 1409 | ||
1429 | return stat; | 1410 | return stat; |
@@ -1448,96 +1429,30 @@ static struct auth_ops svcauthops_gss = { | |||
1448 | .set_client = svcauth_gss_set_client, | 1429 | .set_client = svcauth_gss_set_client, |
1449 | }; | 1430 | }; |
1450 | 1431 | ||
1451 | static int rsi_cache_create_net(struct net *net) | ||
1452 | { | ||
1453 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
1454 | struct cache_detail *cd; | ||
1455 | int err; | ||
1456 | |||
1457 | cd = cache_create_net(&rsi_cache_template, net); | ||
1458 | if (IS_ERR(cd)) | ||
1459 | return PTR_ERR(cd); | ||
1460 | err = cache_register_net(cd, net); | ||
1461 | if (err) { | ||
1462 | cache_destroy_net(cd, net); | ||
1463 | return err; | ||
1464 | } | ||
1465 | sn->rsi_cache = cd; | ||
1466 | return 0; | ||
1467 | } | ||
1468 | |||
1469 | static void rsi_cache_destroy_net(struct net *net) | ||
1470 | { | ||
1471 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
1472 | struct cache_detail *cd = sn->rsi_cache; | ||
1473 | |||
1474 | sn->rsi_cache = NULL; | ||
1475 | cache_purge(cd); | ||
1476 | cache_unregister_net(cd, net); | ||
1477 | cache_destroy_net(cd, net); | ||
1478 | } | ||
1479 | |||
1480 | static int rsc_cache_create_net(struct net *net) | ||
1481 | { | ||
1482 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
1483 | struct cache_detail *cd; | ||
1484 | int err; | ||
1485 | |||
1486 | cd = cache_create_net(&rsc_cache_template, net); | ||
1487 | if (IS_ERR(cd)) | ||
1488 | return PTR_ERR(cd); | ||
1489 | err = cache_register_net(cd, net); | ||
1490 | if (err) { | ||
1491 | cache_destroy_net(cd, net); | ||
1492 | return err; | ||
1493 | } | ||
1494 | sn->rsc_cache = cd; | ||
1495 | return 0; | ||
1496 | } | ||
1497 | |||
1498 | static void rsc_cache_destroy_net(struct net *net) | ||
1499 | { | ||
1500 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
1501 | struct cache_detail *cd = sn->rsc_cache; | ||
1502 | |||
1503 | sn->rsc_cache = NULL; | ||
1504 | cache_purge(cd); | ||
1505 | cache_unregister_net(cd, net); | ||
1506 | cache_destroy_net(cd, net); | ||
1507 | } | ||
1508 | |||
1509 | int | 1432 | int |
1510 | gss_svc_init_net(struct net *net) | 1433 | gss_svc_init(void) |
1511 | { | 1434 | { |
1512 | int rv; | 1435 | int rv = svc_auth_register(RPC_AUTH_GSS, &svcauthops_gss); |
1513 | |||
1514 | rv = rsc_cache_create_net(net); | ||
1515 | if (rv) | 1436 | if (rv) |
1516 | return rv; | 1437 | return rv; |
1517 | rv = rsi_cache_create_net(net); | 1438 | rv = cache_register(&rsc_cache); |
1518 | if (rv) | 1439 | if (rv) |
1519 | goto out1; | 1440 | goto out1; |
1441 | rv = cache_register(&rsi_cache); | ||
1442 | if (rv) | ||
1443 | goto out2; | ||
1520 | return 0; | 1444 | return 0; |
1445 | out2: | ||
1446 | cache_unregister(&rsc_cache); | ||
1521 | out1: | 1447 | out1: |
1522 | rsc_cache_destroy_net(net); | 1448 | svc_auth_unregister(RPC_AUTH_GSS); |
1523 | return rv; | 1449 | return rv; |
1524 | } | 1450 | } |
1525 | 1451 | ||
1526 | void | 1452 | void |
1527 | gss_svc_shutdown_net(struct net *net) | ||
1528 | { | ||
1529 | rsi_cache_destroy_net(net); | ||
1530 | rsc_cache_destroy_net(net); | ||
1531 | } | ||
1532 | |||
1533 | int | ||
1534 | gss_svc_init(void) | ||
1535 | { | ||
1536 | return svc_auth_register(RPC_AUTH_GSS, &svcauthops_gss); | ||
1537 | } | ||
1538 | |||
1539 | void | ||
1540 | gss_svc_shutdown(void) | 1453 | gss_svc_shutdown(void) |
1541 | { | 1454 | { |
1455 | cache_unregister(&rsc_cache); | ||
1456 | cache_unregister(&rsi_cache); | ||
1542 | svc_auth_unregister(RPC_AUTH_GSS); | 1457 | svc_auth_unregister(RPC_AUTH_GSS); |
1543 | } | 1458 | } |
diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c index 52c5abdee21..e50502d8ceb 100644 --- a/net/sunrpc/auth_unix.c +++ b/net/sunrpc/auth_unix.c | |||
@@ -12,7 +12,6 @@ | |||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/sunrpc/clnt.h> | 13 | #include <linux/sunrpc/clnt.h> |
14 | #include <linux/sunrpc/auth.h> | 14 | #include <linux/sunrpc/auth.h> |
15 | #include <linux/user_namespace.h> | ||
16 | 15 | ||
17 | #define NFS_NGROUPS 16 | 16 | #define NFS_NGROUPS 16 |
18 | 17 | ||
@@ -79,11 +78,8 @@ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) | |||
79 | groups = NFS_NGROUPS; | 78 | groups = NFS_NGROUPS; |
80 | 79 | ||
81 | cred->uc_gid = acred->gid; | 80 | cred->uc_gid = acred->gid; |
82 | for (i = 0; i < groups; i++) { | 81 | for (i = 0; i < groups; i++) |
83 | gid_t gid; | 82 | cred->uc_gids[i] = GROUP_AT(acred->group_info, i); |
84 | gid = from_kgid(&init_user_ns, GROUP_AT(acred->group_info, i)); | ||
85 | cred->uc_gids[i] = gid; | ||
86 | } | ||
87 | if (i < NFS_NGROUPS) | 83 | if (i < NFS_NGROUPS) |
88 | cred->uc_gids[i] = NOGROUP; | 84 | cred->uc_gids[i] = NOGROUP; |
89 | 85 | ||
@@ -130,12 +126,9 @@ unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int flags) | |||
130 | groups = acred->group_info->ngroups; | 126 | groups = acred->group_info->ngroups; |
131 | if (groups > NFS_NGROUPS) | 127 | if (groups > NFS_NGROUPS) |
132 | groups = NFS_NGROUPS; | 128 | groups = NFS_NGROUPS; |
133 | for (i = 0; i < groups ; i++) { | 129 | for (i = 0; i < groups ; i++) |
134 | gid_t gid; | 130 | if (cred->uc_gids[i] != GROUP_AT(acred->group_info, i)) |
135 | gid = from_kgid(&init_user_ns, GROUP_AT(acred->group_info, i)); | ||
136 | if (cred->uc_gids[i] != gid) | ||
137 | return 0; | 131 | return 0; |
138 | } | ||
139 | if (groups < NFS_NGROUPS && | 132 | if (groups < NFS_NGROUPS && |
140 | cred->uc_gids[groups] != NOGROUP) | 133 | cred->uc_gids[groups] != NOGROUP) |
141 | return 0; | 134 | return 0; |
diff --git a/net/sunrpc/backchannel_rqst.c b/net/sunrpc/backchannel_rqst.c index 890a29912d5..91eaa26e4c4 100644 --- a/net/sunrpc/backchannel_rqst.c +++ b/net/sunrpc/backchannel_rqst.c | |||
@@ -24,8 +24,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
24 | #include <linux/tcp.h> | 24 | #include <linux/tcp.h> |
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/sunrpc/xprt.h> | 26 | #include <linux/sunrpc/xprt.h> |
27 | #include <linux/export.h> | ||
28 | #include <linux/sunrpc/bc_xprt.h> | ||
29 | 27 | ||
30 | #ifdef RPC_DEBUG | 28 | #ifdef RPC_DEBUG |
31 | #define RPCDBG_FACILITY RPCDBG_TRANS | 29 | #define RPCDBG_FACILITY RPCDBG_TRANS |
@@ -59,7 +57,7 @@ static void xprt_free_allocation(struct rpc_rqst *req) | |||
59 | struct xdr_buf *xbufp; | 57 | struct xdr_buf *xbufp; |
60 | 58 | ||
61 | dprintk("RPC: free allocations for req= %p\n", req); | 59 | dprintk("RPC: free allocations for req= %p\n", req); |
62 | WARN_ON_ONCE(test_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state)); | 60 | BUG_ON(test_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state)); |
63 | xbufp = &req->rq_private_buf; | 61 | xbufp = &req->rq_private_buf; |
64 | free_page((unsigned long)xbufp->head[0].iov_base); | 62 | free_page((unsigned long)xbufp->head[0].iov_base); |
65 | xbufp = &req->rq_snd_buf; | 63 | xbufp = &req->rq_snd_buf; |
@@ -172,18 +170,17 @@ out_free: | |||
172 | xprt_free_allocation(req); | 170 | xprt_free_allocation(req); |
173 | 171 | ||
174 | dprintk("RPC: setup backchannel transport failed\n"); | 172 | dprintk("RPC: setup backchannel transport failed\n"); |
175 | return -ENOMEM; | 173 | return -1; |
176 | } | 174 | } |
177 | EXPORT_SYMBOL_GPL(xprt_setup_backchannel); | 175 | EXPORT_SYMBOL_GPL(xprt_setup_backchannel); |
178 | 176 | ||
179 | /** | 177 | /* |
180 | * xprt_destroy_backchannel - Destroys the backchannel preallocated structures. | 178 | * Destroys the backchannel preallocated structures. |
181 | * @xprt: the transport holding the preallocated strucures | ||
182 | * @max_reqs the maximum number of preallocated structures to destroy | ||
183 | * | ||
184 | * Since these structures may have been allocated by multiple calls | 179 | * Since these structures may have been allocated by multiple calls |
185 | * to xprt_setup_backchannel, we only destroy up to the maximum number | 180 | * to xprt_setup_backchannel, we only destroy up to the maximum number |
186 | * of reqs specified by the caller. | 181 | * of reqs specified by the caller. |
182 | * @xprt: the transport holding the preallocated strucures | ||
183 | * @max_reqs the maximum number of preallocated structures to destroy | ||
187 | */ | 184 | */ |
188 | void xprt_destroy_backchannel(struct rpc_xprt *xprt, unsigned int max_reqs) | 185 | void xprt_destroy_backchannel(struct rpc_xprt *xprt, unsigned int max_reqs) |
189 | { | 186 | { |
@@ -191,9 +188,7 @@ void xprt_destroy_backchannel(struct rpc_xprt *xprt, unsigned int max_reqs) | |||
191 | 188 | ||
192 | dprintk("RPC: destroy backchannel transport\n"); | 189 | dprintk("RPC: destroy backchannel transport\n"); |
193 | 190 | ||
194 | if (max_reqs == 0) | 191 | BUG_ON(max_reqs == 0); |
195 | goto out; | ||
196 | |||
197 | spin_lock_bh(&xprt->bc_pa_lock); | 192 | spin_lock_bh(&xprt->bc_pa_lock); |
198 | xprt_dec_alloc_count(xprt, max_reqs); | 193 | xprt_dec_alloc_count(xprt, max_reqs); |
199 | list_for_each_entry_safe(req, tmp, &xprt->bc_pa_list, rq_bc_pa_list) { | 194 | list_for_each_entry_safe(req, tmp, &xprt->bc_pa_list, rq_bc_pa_list) { |
@@ -204,7 +199,6 @@ void xprt_destroy_backchannel(struct rpc_xprt *xprt, unsigned int max_reqs) | |||
204 | } | 199 | } |
205 | spin_unlock_bh(&xprt->bc_pa_lock); | 200 | spin_unlock_bh(&xprt->bc_pa_lock); |
206 | 201 | ||
207 | out: | ||
208 | dprintk("RPC: backchannel list empty= %s\n", | 202 | dprintk("RPC: backchannel list empty= %s\n", |
209 | list_empty(&xprt->bc_pa_list) ? "true" : "false"); | 203 | list_empty(&xprt->bc_pa_list) ? "true" : "false"); |
210 | } | 204 | } |
@@ -258,7 +252,7 @@ void xprt_free_bc_request(struct rpc_rqst *req) | |||
258 | dprintk("RPC: free backchannel req=%p\n", req); | 252 | dprintk("RPC: free backchannel req=%p\n", req); |
259 | 253 | ||
260 | smp_mb__before_clear_bit(); | 254 | smp_mb__before_clear_bit(); |
261 | WARN_ON_ONCE(!test_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state)); | 255 | BUG_ON(!test_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state)); |
262 | clear_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state); | 256 | clear_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state); |
263 | smp_mb__after_clear_bit(); | 257 | smp_mb__after_clear_bit(); |
264 | 258 | ||
diff --git a/net/sunrpc/bc_svc.c b/net/sunrpc/bc_svc.c index 15c7a8a1c24..0b2eb388cbd 100644 --- a/net/sunrpc/bc_svc.c +++ b/net/sunrpc/bc_svc.c | |||
@@ -53,7 +53,7 @@ int bc_send(struct rpc_rqst *req) | |||
53 | if (IS_ERR(task)) | 53 | if (IS_ERR(task)) |
54 | ret = PTR_ERR(task); | 54 | ret = PTR_ERR(task); |
55 | else { | 55 | else { |
56 | WARN_ON_ONCE(atomic_read(&task->tk_count) != 1); | 56 | BUG_ON(atomic_read(&task->tk_count) != 1); |
57 | ret = task->tk_status; | 57 | ret = task->tk_status; |
58 | rpc_put_task(task); | 58 | rpc_put_task(task); |
59 | } | 59 | } |
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 9afa4393c21..72ad836e4fe 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c | |||
@@ -344,7 +344,7 @@ static int current_index; | |||
344 | static void do_cache_clean(struct work_struct *work); | 344 | static void do_cache_clean(struct work_struct *work); |
345 | static struct delayed_work cache_cleaner; | 345 | static struct delayed_work cache_cleaner; |
346 | 346 | ||
347 | void sunrpc_init_cache_detail(struct cache_detail *cd) | 347 | static void sunrpc_init_cache_detail(struct cache_detail *cd) |
348 | { | 348 | { |
349 | rwlock_init(&cd->hash_lock); | 349 | rwlock_init(&cd->hash_lock); |
350 | INIT_LIST_HEAD(&cd->queue); | 350 | INIT_LIST_HEAD(&cd->queue); |
@@ -360,9 +360,8 @@ void sunrpc_init_cache_detail(struct cache_detail *cd) | |||
360 | /* start the cleaning process */ | 360 | /* start the cleaning process */ |
361 | schedule_delayed_work(&cache_cleaner, 0); | 361 | schedule_delayed_work(&cache_cleaner, 0); |
362 | } | 362 | } |
363 | EXPORT_SYMBOL_GPL(sunrpc_init_cache_detail); | ||
364 | 363 | ||
365 | void sunrpc_destroy_cache_detail(struct cache_detail *cd) | 364 | static void sunrpc_destroy_cache_detail(struct cache_detail *cd) |
366 | { | 365 | { |
367 | cache_purge(cd); | 366 | cache_purge(cd); |
368 | spin_lock(&cache_list_lock); | 367 | spin_lock(&cache_list_lock); |
@@ -385,7 +384,6 @@ void sunrpc_destroy_cache_detail(struct cache_detail *cd) | |||
385 | out: | 384 | out: |
386 | printk(KERN_ERR "nfsd: failed to unregister %s cache\n", cd->name); | 385 | printk(KERN_ERR "nfsd: failed to unregister %s cache\n", cd->name); |
387 | } | 386 | } |
388 | EXPORT_SYMBOL_GPL(sunrpc_destroy_cache_detail); | ||
389 | 387 | ||
390 | /* clean cache tries to find something to clean | 388 | /* clean cache tries to find something to clean |
391 | * and cleans it. | 389 | * and cleans it. |
@@ -775,11 +773,11 @@ static ssize_t cache_read(struct file *filp, char __user *buf, size_t count, | |||
775 | if (rp->q.list.next == &cd->queue) { | 773 | if (rp->q.list.next == &cd->queue) { |
776 | spin_unlock(&queue_lock); | 774 | spin_unlock(&queue_lock); |
777 | mutex_unlock(&inode->i_mutex); | 775 | mutex_unlock(&inode->i_mutex); |
778 | WARN_ON_ONCE(rp->offset); | 776 | BUG_ON(rp->offset); |
779 | return 0; | 777 | return 0; |
780 | } | 778 | } |
781 | rq = container_of(rp->q.list.next, struct cache_request, q.list); | 779 | rq = container_of(rp->q.list.next, struct cache_request, q.list); |
782 | WARN_ON_ONCE(rq->q.reader); | 780 | BUG_ON(rq->q.reader); |
783 | if (rp->offset == 0) | 781 | if (rp->offset == 0) |
784 | rq->readers++; | 782 | rq->readers++; |
785 | spin_unlock(&queue_lock); | 783 | spin_unlock(&queue_lock); |
@@ -830,8 +828,6 @@ static ssize_t cache_do_downcall(char *kaddr, const char __user *buf, | |||
830 | { | 828 | { |
831 | ssize_t ret; | 829 | ssize_t ret; |
832 | 830 | ||
833 | if (count == 0) | ||
834 | return -EINVAL; | ||
835 | if (copy_from_user(kaddr, buf, count)) | 831 | if (copy_from_user(kaddr, buf, count)) |
836 | return -EFAULT; | 832 | return -EFAULT; |
837 | kaddr[count] = '\0'; | 833 | kaddr[count] = '\0'; |
@@ -1273,7 +1269,7 @@ static void *c_start(struct seq_file *m, loff_t *pos) | |||
1273 | __acquires(cd->hash_lock) | 1269 | __acquires(cd->hash_lock) |
1274 | { | 1270 | { |
1275 | loff_t n = *pos; | 1271 | loff_t n = *pos; |
1276 | unsigned int hash, entry; | 1272 | unsigned hash, entry; |
1277 | struct cache_head *ch; | 1273 | struct cache_head *ch; |
1278 | struct cache_detail *cd = ((struct handle*)m->private)->cd; | 1274 | struct cache_detail *cd = ((struct handle*)m->private)->cd; |
1279 | 1275 | ||
@@ -1349,11 +1345,8 @@ static int c_show(struct seq_file *m, void *p) | |||
1349 | if (cache_check(cd, cp, NULL)) | 1345 | if (cache_check(cd, cp, NULL)) |
1350 | /* cache_check does a cache_put on failure */ | 1346 | /* cache_check does a cache_put on failure */ |
1351 | seq_printf(m, "# "); | 1347 | seq_printf(m, "# "); |
1352 | else { | 1348 | else |
1353 | if (cache_is_expired(cd, cp)) | ||
1354 | seq_printf(m, "# "); | ||
1355 | cache_put(cp, cd); | 1349 | cache_put(cp, cd); |
1356 | } | ||
1357 | 1350 | ||
1358 | return cd->cache_show(m, cd, cp); | 1351 | return cd->cache_show(m, cd, cp); |
1359 | } | 1352 | } |
@@ -1409,11 +1402,11 @@ static ssize_t read_flush(struct file *file, char __user *buf, | |||
1409 | size_t count, loff_t *ppos, | 1402 | size_t count, loff_t *ppos, |
1410 | struct cache_detail *cd) | 1403 | struct cache_detail *cd) |
1411 | { | 1404 | { |
1412 | char tbuf[22]; | 1405 | char tbuf[20]; |
1413 | unsigned long p = *ppos; | 1406 | unsigned long p = *ppos; |
1414 | size_t len; | 1407 | size_t len; |
1415 | 1408 | ||
1416 | snprintf(tbuf, sizeof(tbuf), "%lu\n", convert_to_wallclock(cd->flush_time)); | 1409 | sprintf(tbuf, "%lu\n", convert_to_wallclock(cd->flush_time)); |
1417 | len = strlen(tbuf); | 1410 | len = strlen(tbuf); |
1418 | if (p >= len) | 1411 | if (p >= len) |
1419 | return 0; | 1412 | return 0; |
@@ -1635,7 +1628,7 @@ static int create_cache_proc_entries(struct cache_detail *cd, struct net *net) | |||
1635 | 1628 | ||
1636 | void __init cache_initialize(void) | 1629 | void __init cache_initialize(void) |
1637 | { | 1630 | { |
1638 | INIT_DEFERRABLE_WORK(&cache_cleaner, do_cache_clean); | 1631 | INIT_DELAYED_WORK_DEFERRABLE(&cache_cleaner, do_cache_clean); |
1639 | } | 1632 | } |
1640 | 1633 | ||
1641 | int cache_register_net(struct cache_detail *cd, struct net *net) | 1634 | int cache_register_net(struct cache_detail *cd, struct net *net) |
@@ -1648,40 +1641,24 @@ int cache_register_net(struct cache_detail *cd, struct net *net) | |||
1648 | sunrpc_destroy_cache_detail(cd); | 1641 | sunrpc_destroy_cache_detail(cd); |
1649 | return ret; | 1642 | return ret; |
1650 | } | 1643 | } |
1651 | EXPORT_SYMBOL_GPL(cache_register_net); | ||
1652 | 1644 | ||
1653 | void cache_unregister_net(struct cache_detail *cd, struct net *net) | 1645 | int cache_register(struct cache_detail *cd) |
1654 | { | 1646 | { |
1655 | remove_cache_proc_entries(cd, net); | 1647 | return cache_register_net(cd, &init_net); |
1656 | sunrpc_destroy_cache_detail(cd); | ||
1657 | } | 1648 | } |
1658 | EXPORT_SYMBOL_GPL(cache_unregister_net); | 1649 | EXPORT_SYMBOL_GPL(cache_register); |
1659 | 1650 | ||
1660 | struct cache_detail *cache_create_net(struct cache_detail *tmpl, struct net *net) | 1651 | void cache_unregister_net(struct cache_detail *cd, struct net *net) |
1661 | { | 1652 | { |
1662 | struct cache_detail *cd; | 1653 | remove_cache_proc_entries(cd, net); |
1663 | 1654 | sunrpc_destroy_cache_detail(cd); | |
1664 | cd = kmemdup(tmpl, sizeof(struct cache_detail), GFP_KERNEL); | ||
1665 | if (cd == NULL) | ||
1666 | return ERR_PTR(-ENOMEM); | ||
1667 | |||
1668 | cd->hash_table = kzalloc(cd->hash_size * sizeof(struct cache_head *), | ||
1669 | GFP_KERNEL); | ||
1670 | if (cd->hash_table == NULL) { | ||
1671 | kfree(cd); | ||
1672 | return ERR_PTR(-ENOMEM); | ||
1673 | } | ||
1674 | cd->net = net; | ||
1675 | return cd; | ||
1676 | } | 1655 | } |
1677 | EXPORT_SYMBOL_GPL(cache_create_net); | ||
1678 | 1656 | ||
1679 | void cache_destroy_net(struct cache_detail *cd, struct net *net) | 1657 | void cache_unregister(struct cache_detail *cd) |
1680 | { | 1658 | { |
1681 | kfree(cd->hash_table); | 1659 | cache_unregister_net(cd, &init_net); |
1682 | kfree(cd); | ||
1683 | } | 1660 | } |
1684 | EXPORT_SYMBOL_GPL(cache_destroy_net); | 1661 | EXPORT_SYMBOL_GPL(cache_unregister); |
1685 | 1662 | ||
1686 | static ssize_t cache_read_pipefs(struct file *filp, char __user *buf, | 1663 | static ssize_t cache_read_pipefs(struct file *filp, char __user *buf, |
1687 | size_t count, loff_t *ppos) | 1664 | size_t count, loff_t *ppos) |
@@ -1801,21 +1778,24 @@ const struct file_operations cache_flush_operations_pipefs = { | |||
1801 | }; | 1778 | }; |
1802 | 1779 | ||
1803 | int sunrpc_cache_register_pipefs(struct dentry *parent, | 1780 | int sunrpc_cache_register_pipefs(struct dentry *parent, |
1804 | const char *name, umode_t umode, | 1781 | const char *name, mode_t umode, |
1805 | struct cache_detail *cd) | 1782 | struct cache_detail *cd) |
1806 | { | 1783 | { |
1807 | struct qstr q; | 1784 | struct qstr q; |
1808 | struct dentry *dir; | 1785 | struct dentry *dir; |
1809 | int ret = 0; | 1786 | int ret = 0; |
1810 | 1787 | ||
1788 | sunrpc_init_cache_detail(cd); | ||
1811 | q.name = name; | 1789 | q.name = name; |
1812 | q.len = strlen(name); | 1790 | q.len = strlen(name); |
1813 | q.hash = full_name_hash(q.name, q.len); | 1791 | q.hash = full_name_hash(q.name, q.len); |
1814 | dir = rpc_create_cache_dir(parent, &q, umode, cd); | 1792 | dir = rpc_create_cache_dir(parent, &q, umode, cd); |
1815 | if (!IS_ERR(dir)) | 1793 | if (!IS_ERR(dir)) |
1816 | cd->u.pipefs.dir = dir; | 1794 | cd->u.pipefs.dir = dir; |
1817 | else | 1795 | else { |
1796 | sunrpc_destroy_cache_detail(cd); | ||
1818 | ret = PTR_ERR(dir); | 1797 | ret = PTR_ERR(dir); |
1798 | } | ||
1819 | return ret; | 1799 | return ret; |
1820 | } | 1800 | } |
1821 | EXPORT_SYMBOL_GPL(sunrpc_cache_register_pipefs); | 1801 | EXPORT_SYMBOL_GPL(sunrpc_cache_register_pipefs); |
@@ -1824,6 +1804,7 @@ void sunrpc_cache_unregister_pipefs(struct cache_detail *cd) | |||
1824 | { | 1804 | { |
1825 | rpc_remove_cache_dir(cd->u.pipefs.dir); | 1805 | rpc_remove_cache_dir(cd->u.pipefs.dir); |
1826 | cd->u.pipefs.dir = NULL; | 1806 | cd->u.pipefs.dir = NULL; |
1807 | sunrpc_destroy_cache_detail(cd); | ||
1827 | } | 1808 | } |
1828 | EXPORT_SYMBOL_GPL(sunrpc_cache_unregister_pipefs); | 1809 | EXPORT_SYMBOL_GPL(sunrpc_cache_unregister_pipefs); |
1829 | 1810 | ||
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 507b5e84fbd..c5347d29cfb 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -17,6 +17,7 @@ | |||
17 | * Copyright (C) 1995,1996 Olaf Kirch <okir@monad.swb.de> | 17 | * Copyright (C) 1995,1996 Olaf Kirch <okir@monad.swb.de> |
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <asm/system.h> | ||
20 | 21 | ||
21 | #include <linux/module.h> | 22 | #include <linux/module.h> |
22 | #include <linux/types.h> | 23 | #include <linux/types.h> |
@@ -30,16 +31,13 @@ | |||
30 | #include <linux/in.h> | 31 | #include <linux/in.h> |
31 | #include <linux/in6.h> | 32 | #include <linux/in6.h> |
32 | #include <linux/un.h> | 33 | #include <linux/un.h> |
33 | #include <linux/rcupdate.h> | ||
34 | 34 | ||
35 | #include <linux/sunrpc/clnt.h> | 35 | #include <linux/sunrpc/clnt.h> |
36 | #include <linux/sunrpc/rpc_pipe_fs.h> | 36 | #include <linux/sunrpc/rpc_pipe_fs.h> |
37 | #include <linux/sunrpc/metrics.h> | 37 | #include <linux/sunrpc/metrics.h> |
38 | #include <linux/sunrpc/bc_xprt.h> | 38 | #include <linux/sunrpc/bc_xprt.h> |
39 | #include <trace/events/sunrpc.h> | ||
40 | 39 | ||
41 | #include "sunrpc.h" | 40 | #include "sunrpc.h" |
42 | #include "netns.h" | ||
43 | 41 | ||
44 | #ifdef RPC_DEBUG | 42 | #ifdef RPC_DEBUG |
45 | # define RPCDBG_FACILITY RPCDBG_CALL | 43 | # define RPCDBG_FACILITY RPCDBG_CALL |
@@ -52,6 +50,8 @@ | |||
52 | /* | 50 | /* |
53 | * All RPC clients are linked into this list | 51 | * All RPC clients are linked into this list |
54 | */ | 52 | */ |
53 | static LIST_HEAD(all_clients); | ||
54 | static DEFINE_SPINLOCK(rpc_client_lock); | ||
55 | 55 | ||
56 | static DECLARE_WAIT_QUEUE_HEAD(destroy_wait); | 56 | static DECLARE_WAIT_QUEUE_HEAD(destroy_wait); |
57 | 57 | ||
@@ -81,222 +81,82 @@ static int rpc_ping(struct rpc_clnt *clnt); | |||
81 | 81 | ||
82 | static void rpc_register_client(struct rpc_clnt *clnt) | 82 | static void rpc_register_client(struct rpc_clnt *clnt) |
83 | { | 83 | { |
84 | struct net *net = rpc_net_ns(clnt); | 84 | spin_lock(&rpc_client_lock); |
85 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | 85 | list_add(&clnt->cl_clients, &all_clients); |
86 | 86 | spin_unlock(&rpc_client_lock); | |
87 | spin_lock(&sn->rpc_client_lock); | ||
88 | list_add(&clnt->cl_clients, &sn->all_clients); | ||
89 | spin_unlock(&sn->rpc_client_lock); | ||
90 | } | 87 | } |
91 | 88 | ||
92 | static void rpc_unregister_client(struct rpc_clnt *clnt) | 89 | static void rpc_unregister_client(struct rpc_clnt *clnt) |
93 | { | 90 | { |
94 | struct net *net = rpc_net_ns(clnt); | 91 | spin_lock(&rpc_client_lock); |
95 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
96 | |||
97 | spin_lock(&sn->rpc_client_lock); | ||
98 | list_del(&clnt->cl_clients); | 92 | list_del(&clnt->cl_clients); |
99 | spin_unlock(&sn->rpc_client_lock); | 93 | spin_unlock(&rpc_client_lock); |
100 | } | ||
101 | |||
102 | static void __rpc_clnt_remove_pipedir(struct rpc_clnt *clnt) | ||
103 | { | ||
104 | if (clnt->cl_dentry) { | ||
105 | if (clnt->cl_auth && clnt->cl_auth->au_ops->pipes_destroy) | ||
106 | clnt->cl_auth->au_ops->pipes_destroy(clnt->cl_auth); | ||
107 | rpc_remove_client_dir(clnt->cl_dentry); | ||
108 | } | ||
109 | clnt->cl_dentry = NULL; | ||
110 | } | 94 | } |
111 | 95 | ||
112 | static void rpc_clnt_remove_pipedir(struct rpc_clnt *clnt) | 96 | static int |
113 | { | 97 | rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name) |
114 | struct net *net = rpc_net_ns(clnt); | ||
115 | struct super_block *pipefs_sb; | ||
116 | |||
117 | pipefs_sb = rpc_get_sb_net(net); | ||
118 | if (pipefs_sb) { | ||
119 | __rpc_clnt_remove_pipedir(clnt); | ||
120 | rpc_put_sb_net(net); | ||
121 | } | ||
122 | } | ||
123 | |||
124 | static struct dentry *rpc_setup_pipedir_sb(struct super_block *sb, | ||
125 | struct rpc_clnt *clnt, | ||
126 | const char *dir_name) | ||
127 | { | 98 | { |
128 | static uint32_t clntid; | 99 | static uint32_t clntid; |
100 | struct path path, dir; | ||
129 | char name[15]; | 101 | char name[15]; |
130 | struct qstr q = { .name = name }; | 102 | struct qstr q = { |
131 | struct dentry *dir, *dentry; | 103 | .name = name, |
104 | }; | ||
132 | int error; | 105 | int error; |
133 | 106 | ||
134 | dir = rpc_d_lookup_sb(sb, dir_name); | 107 | clnt->cl_path.mnt = ERR_PTR(-ENOENT); |
135 | if (dir == NULL) { | 108 | clnt->cl_path.dentry = ERR_PTR(-ENOENT); |
136 | pr_info("RPC: pipefs directory doesn't exist: %s\n", dir_name); | 109 | if (dir_name == NULL) |
137 | return dir; | 110 | return 0; |
138 | } | 111 | |
112 | path.mnt = rpc_get_mount(); | ||
113 | if (IS_ERR(path.mnt)) | ||
114 | return PTR_ERR(path.mnt); | ||
115 | error = vfs_path_lookup(path.mnt->mnt_root, path.mnt, dir_name, 0, &dir); | ||
116 | if (error) | ||
117 | goto err; | ||
118 | |||
139 | for (;;) { | 119 | for (;;) { |
140 | q.len = snprintf(name, sizeof(name), "clnt%x", (unsigned int)clntid++); | 120 | q.len = snprintf(name, sizeof(name), "clnt%x", (unsigned int)clntid++); |
141 | name[sizeof(name) - 1] = '\0'; | 121 | name[sizeof(name) - 1] = '\0'; |
142 | q.hash = full_name_hash(q.name, q.len); | 122 | q.hash = full_name_hash(q.name, q.len); |
143 | dentry = rpc_create_client_dir(dir, &q, clnt); | 123 | path.dentry = rpc_create_client_dir(dir.dentry, &q, clnt); |
144 | if (!IS_ERR(dentry)) | 124 | if (!IS_ERR(path.dentry)) |
145 | break; | 125 | break; |
146 | error = PTR_ERR(dentry); | 126 | error = PTR_ERR(path.dentry); |
147 | if (error != -EEXIST) { | 127 | if (error != -EEXIST) { |
148 | printk(KERN_INFO "RPC: Couldn't create pipefs entry" | 128 | printk(KERN_INFO "RPC: Couldn't create pipefs entry" |
149 | " %s/%s, error %d\n", | 129 | " %s/%s, error %d\n", |
150 | dir_name, name, error); | 130 | dir_name, name, error); |
151 | break; | 131 | goto err_path_put; |
152 | } | 132 | } |
153 | } | 133 | } |
154 | dput(dir); | 134 | path_put(&dir); |
155 | return dentry; | 135 | clnt->cl_path = path; |
156 | } | ||
157 | |||
158 | static int | ||
159 | rpc_setup_pipedir(struct rpc_clnt *clnt, const char *dir_name) | ||
160 | { | ||
161 | struct net *net = rpc_net_ns(clnt); | ||
162 | struct super_block *pipefs_sb; | ||
163 | struct dentry *dentry; | ||
164 | |||
165 | clnt->cl_dentry = NULL; | ||
166 | if (dir_name == NULL) | ||
167 | return 0; | ||
168 | pipefs_sb = rpc_get_sb_net(net); | ||
169 | if (!pipefs_sb) | ||
170 | return 0; | ||
171 | dentry = rpc_setup_pipedir_sb(pipefs_sb, clnt, dir_name); | ||
172 | rpc_put_sb_net(net); | ||
173 | if (IS_ERR(dentry)) | ||
174 | return PTR_ERR(dentry); | ||
175 | clnt->cl_dentry = dentry; | ||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | static inline int rpc_clnt_skip_event(struct rpc_clnt *clnt, unsigned long event) | ||
180 | { | ||
181 | if (((event == RPC_PIPEFS_MOUNT) && clnt->cl_dentry) || | ||
182 | ((event == RPC_PIPEFS_UMOUNT) && !clnt->cl_dentry)) | ||
183 | return 1; | ||
184 | return 0; | 136 | return 0; |
185 | } | 137 | err_path_put: |
186 | 138 | path_put(&dir); | |
187 | static int __rpc_clnt_handle_event(struct rpc_clnt *clnt, unsigned long event, | 139 | err: |
188 | struct super_block *sb) | 140 | rpc_put_mount(); |
189 | { | ||
190 | struct dentry *dentry; | ||
191 | int err = 0; | ||
192 | |||
193 | switch (event) { | ||
194 | case RPC_PIPEFS_MOUNT: | ||
195 | dentry = rpc_setup_pipedir_sb(sb, clnt, | ||
196 | clnt->cl_program->pipe_dir_name); | ||
197 | if (!dentry) | ||
198 | return -ENOENT; | ||
199 | if (IS_ERR(dentry)) | ||
200 | return PTR_ERR(dentry); | ||
201 | clnt->cl_dentry = dentry; | ||
202 | if (clnt->cl_auth->au_ops->pipes_create) { | ||
203 | err = clnt->cl_auth->au_ops->pipes_create(clnt->cl_auth); | ||
204 | if (err) | ||
205 | __rpc_clnt_remove_pipedir(clnt); | ||
206 | } | ||
207 | break; | ||
208 | case RPC_PIPEFS_UMOUNT: | ||
209 | __rpc_clnt_remove_pipedir(clnt); | ||
210 | break; | ||
211 | default: | ||
212 | printk(KERN_ERR "%s: unknown event: %ld\n", __func__, event); | ||
213 | return -ENOTSUPP; | ||
214 | } | ||
215 | return err; | ||
216 | } | ||
217 | |||
218 | static int __rpc_pipefs_event(struct rpc_clnt *clnt, unsigned long event, | ||
219 | struct super_block *sb) | ||
220 | { | ||
221 | int error = 0; | ||
222 | |||
223 | for (;; clnt = clnt->cl_parent) { | ||
224 | if (!rpc_clnt_skip_event(clnt, event)) | ||
225 | error = __rpc_clnt_handle_event(clnt, event, sb); | ||
226 | if (error || clnt == clnt->cl_parent) | ||
227 | break; | ||
228 | } | ||
229 | return error; | ||
230 | } | ||
231 | |||
232 | static struct rpc_clnt *rpc_get_client_for_event(struct net *net, int event) | ||
233 | { | ||
234 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
235 | struct rpc_clnt *clnt; | ||
236 | |||
237 | spin_lock(&sn->rpc_client_lock); | ||
238 | list_for_each_entry(clnt, &sn->all_clients, cl_clients) { | ||
239 | if (clnt->cl_program->pipe_dir_name == NULL) | ||
240 | continue; | ||
241 | if (rpc_clnt_skip_event(clnt, event)) | ||
242 | continue; | ||
243 | if (atomic_inc_not_zero(&clnt->cl_count) == 0) | ||
244 | continue; | ||
245 | spin_unlock(&sn->rpc_client_lock); | ||
246 | return clnt; | ||
247 | } | ||
248 | spin_unlock(&sn->rpc_client_lock); | ||
249 | return NULL; | ||
250 | } | ||
251 | |||
252 | static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event, | ||
253 | void *ptr) | ||
254 | { | ||
255 | struct super_block *sb = ptr; | ||
256 | struct rpc_clnt *clnt; | ||
257 | int error = 0; | ||
258 | |||
259 | while ((clnt = rpc_get_client_for_event(sb->s_fs_info, event))) { | ||
260 | error = __rpc_pipefs_event(clnt, event, sb); | ||
261 | rpc_release_client(clnt); | ||
262 | if (error) | ||
263 | break; | ||
264 | } | ||
265 | return error; | 141 | return error; |
266 | } | 142 | } |
267 | 143 | ||
268 | static struct notifier_block rpc_clients_block = { | ||
269 | .notifier_call = rpc_pipefs_event, | ||
270 | .priority = SUNRPC_PIPEFS_RPC_PRIO, | ||
271 | }; | ||
272 | |||
273 | int rpc_clients_notifier_register(void) | ||
274 | { | ||
275 | return rpc_pipefs_notifier_register(&rpc_clients_block); | ||
276 | } | ||
277 | |||
278 | void rpc_clients_notifier_unregister(void) | ||
279 | { | ||
280 | return rpc_pipefs_notifier_unregister(&rpc_clients_block); | ||
281 | } | ||
282 | |||
283 | static void rpc_clnt_set_nodename(struct rpc_clnt *clnt, const char *nodename) | ||
284 | { | ||
285 | clnt->cl_nodelen = strlen(nodename); | ||
286 | if (clnt->cl_nodelen > UNX_MAXNODENAME) | ||
287 | clnt->cl_nodelen = UNX_MAXNODENAME; | ||
288 | memcpy(clnt->cl_nodename, nodename, clnt->cl_nodelen); | ||
289 | } | ||
290 | |||
291 | static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, struct rpc_xprt *xprt) | 144 | static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, struct rpc_xprt *xprt) |
292 | { | 145 | { |
293 | const struct rpc_program *program = args->program; | 146 | struct rpc_program *program = args->program; |
294 | const struct rpc_version *version; | 147 | struct rpc_version *version; |
295 | struct rpc_clnt *clnt = NULL; | 148 | struct rpc_clnt *clnt = NULL; |
296 | struct rpc_auth *auth; | 149 | struct rpc_auth *auth; |
297 | int err; | 150 | int err; |
151 | size_t len; | ||
298 | 152 | ||
299 | /* sanity check the name before trying to print it */ | 153 | /* sanity check the name before trying to print it */ |
154 | err = -EINVAL; | ||
155 | len = strlen(args->servername); | ||
156 | if (len > RPC_MAXNETNAMELEN) | ||
157 | goto out_no_rpciod; | ||
158 | len++; | ||
159 | |||
300 | dprintk("RPC: creating %s client for %s (xprt %p)\n", | 160 | dprintk("RPC: creating %s client for %s (xprt %p)\n", |
301 | program->name, args->servername, xprt); | 161 | program->name, args->servername, xprt); |
302 | 162 | ||
@@ -319,7 +179,17 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru | |||
319 | goto out_err; | 179 | goto out_err; |
320 | clnt->cl_parent = clnt; | 180 | clnt->cl_parent = clnt; |
321 | 181 | ||
322 | rcu_assign_pointer(clnt->cl_xprt, xprt); | 182 | clnt->cl_server = clnt->cl_inline_name; |
183 | if (len > sizeof(clnt->cl_inline_name)) { | ||
184 | char *buf = kmalloc(len, GFP_KERNEL); | ||
185 | if (buf != NULL) | ||
186 | clnt->cl_server = buf; | ||
187 | else | ||
188 | len = sizeof(clnt->cl_inline_name); | ||
189 | } | ||
190 | strlcpy(clnt->cl_server, args->servername, len); | ||
191 | |||
192 | clnt->cl_xprt = xprt; | ||
323 | clnt->cl_procinfo = version->procs; | 193 | clnt->cl_procinfo = version->procs; |
324 | clnt->cl_maxproc = version->nrprocs; | 194 | clnt->cl_maxproc = version->nrprocs; |
325 | clnt->cl_protname = program->name; | 195 | clnt->cl_protname = program->name; |
@@ -334,7 +204,7 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru | |||
334 | INIT_LIST_HEAD(&clnt->cl_tasks); | 204 | INIT_LIST_HEAD(&clnt->cl_tasks); |
335 | spin_lock_init(&clnt->cl_lock); | 205 | spin_lock_init(&clnt->cl_lock); |
336 | 206 | ||
337 | if (!xprt_bound(xprt)) | 207 | if (!xprt_bound(clnt->cl_xprt)) |
338 | clnt->cl_autobind = 1; | 208 | clnt->cl_autobind = 1; |
339 | 209 | ||
340 | clnt->cl_timeout = xprt->timeout; | 210 | clnt->cl_timeout = xprt->timeout; |
@@ -368,17 +238,25 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru | |||
368 | } | 238 | } |
369 | 239 | ||
370 | /* save the nodename */ | 240 | /* save the nodename */ |
371 | rpc_clnt_set_nodename(clnt, utsname()->nodename); | 241 | clnt->cl_nodelen = strlen(init_utsname()->nodename); |
242 | if (clnt->cl_nodelen > UNX_MAXNODENAME) | ||
243 | clnt->cl_nodelen = UNX_MAXNODENAME; | ||
244 | memcpy(clnt->cl_nodename, init_utsname()->nodename, clnt->cl_nodelen); | ||
372 | rpc_register_client(clnt); | 245 | rpc_register_client(clnt); |
373 | return clnt; | 246 | return clnt; |
374 | 247 | ||
375 | out_no_auth: | 248 | out_no_auth: |
376 | rpc_clnt_remove_pipedir(clnt); | 249 | if (!IS_ERR(clnt->cl_path.dentry)) { |
250 | rpc_remove_client_dir(clnt->cl_path.dentry); | ||
251 | rpc_put_mount(); | ||
252 | } | ||
377 | out_no_path: | 253 | out_no_path: |
378 | kfree(clnt->cl_principal); | 254 | kfree(clnt->cl_principal); |
379 | out_no_principal: | 255 | out_no_principal: |
380 | rpc_free_iostats(clnt->cl_metrics); | 256 | rpc_free_iostats(clnt->cl_metrics); |
381 | out_no_stats: | 257 | out_no_stats: |
258 | if (clnt->cl_server != clnt->cl_inline_name) | ||
259 | kfree(clnt->cl_server); | ||
382 | kfree(clnt); | 260 | kfree(clnt); |
383 | out_err: | 261 | out_err: |
384 | xprt_put(xprt); | 262 | xprt_put(xprt); |
@@ -388,7 +266,7 @@ out_no_rpciod: | |||
388 | return ERR_PTR(err); | 266 | return ERR_PTR(err); |
389 | } | 267 | } |
390 | 268 | ||
391 | /** | 269 | /* |
392 | * rpc_create - create an RPC client and transport with one call | 270 | * rpc_create - create an RPC client and transport with one call |
393 | * @args: rpc_clnt create argument structure | 271 | * @args: rpc_clnt create argument structure |
394 | * | 272 | * |
@@ -408,7 +286,6 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args) | |||
408 | .srcaddr = args->saddress, | 286 | .srcaddr = args->saddress, |
409 | .dstaddr = args->address, | 287 | .dstaddr = args->address, |
410 | .addrlen = args->addrsize, | 288 | .addrlen = args->addrsize, |
411 | .servername = args->servername, | ||
412 | .bc_xprt = args->bc_xprt, | 289 | .bc_xprt = args->bc_xprt, |
413 | }; | 290 | }; |
414 | char servername[48]; | 291 | char servername[48]; |
@@ -417,7 +294,7 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args) | |||
417 | * If the caller chooses not to specify a hostname, whip | 294 | * If the caller chooses not to specify a hostname, whip |
418 | * up a string representation of the passed-in address. | 295 | * up a string representation of the passed-in address. |
419 | */ | 296 | */ |
420 | if (xprtargs.servername == NULL) { | 297 | if (args->servername == NULL) { |
421 | struct sockaddr_un *sun = | 298 | struct sockaddr_un *sun = |
422 | (struct sockaddr_un *)args->address; | 299 | (struct sockaddr_un *)args->address; |
423 | struct sockaddr_in *sin = | 300 | struct sockaddr_in *sin = |
@@ -444,7 +321,7 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args) | |||
444 | * address family isn't recognized. */ | 321 | * address family isn't recognized. */ |
445 | return ERR_PTR(-EINVAL); | 322 | return ERR_PTR(-EINVAL); |
446 | } | 323 | } |
447 | xprtargs.servername = servername; | 324 | args->servername = servername; |
448 | } | 325 | } |
449 | 326 | ||
450 | xprt = xprt_create_transport(&xprtargs); | 327 | xprt = xprt_create_transport(&xprtargs); |
@@ -493,86 +370,52 @@ EXPORT_SYMBOL_GPL(rpc_create); | |||
493 | * same transport while varying parameters such as the authentication | 370 | * same transport while varying parameters such as the authentication |
494 | * flavour. | 371 | * flavour. |
495 | */ | 372 | */ |
496 | static struct rpc_clnt *__rpc_clone_client(struct rpc_create_args *args, | 373 | struct rpc_clnt * |
497 | struct rpc_clnt *clnt) | 374 | rpc_clone_client(struct rpc_clnt *clnt) |
498 | { | 375 | { |
499 | struct rpc_xprt *xprt; | ||
500 | struct rpc_clnt *new; | 376 | struct rpc_clnt *new; |
501 | int err; | 377 | int err = -ENOMEM; |
502 | |||
503 | err = -ENOMEM; | ||
504 | rcu_read_lock(); | ||
505 | xprt = xprt_get(rcu_dereference(clnt->cl_xprt)); | ||
506 | rcu_read_unlock(); | ||
507 | if (xprt == NULL) | ||
508 | goto out_err; | ||
509 | args->servername = xprt->servername; | ||
510 | 378 | ||
511 | new = rpc_new_client(args, xprt); | 379 | new = kmemdup(clnt, sizeof(*new), GFP_KERNEL); |
512 | if (IS_ERR(new)) { | 380 | if (!new) |
513 | err = PTR_ERR(new); | 381 | goto out_no_clnt; |
514 | goto out_put; | ||
515 | } | ||
516 | |||
517 | atomic_inc(&clnt->cl_count); | ||
518 | new->cl_parent = clnt; | 382 | new->cl_parent = clnt; |
519 | |||
520 | /* Turn off autobind on clones */ | 383 | /* Turn off autobind on clones */ |
521 | new->cl_autobind = 0; | 384 | new->cl_autobind = 0; |
522 | new->cl_softrtry = clnt->cl_softrtry; | 385 | INIT_LIST_HEAD(&new->cl_tasks); |
523 | new->cl_discrtry = clnt->cl_discrtry; | 386 | spin_lock_init(&new->cl_lock); |
524 | new->cl_chatty = clnt->cl_chatty; | 387 | rpc_init_rtt(&new->cl_rtt_default, clnt->cl_timeout->to_initval); |
388 | new->cl_metrics = rpc_alloc_iostats(clnt); | ||
389 | if (new->cl_metrics == NULL) | ||
390 | goto out_no_stats; | ||
391 | if (clnt->cl_principal) { | ||
392 | new->cl_principal = kstrdup(clnt->cl_principal, GFP_KERNEL); | ||
393 | if (new->cl_principal == NULL) | ||
394 | goto out_no_principal; | ||
395 | } | ||
396 | atomic_set(&new->cl_count, 1); | ||
397 | err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name); | ||
398 | if (err != 0) | ||
399 | goto out_no_path; | ||
400 | if (new->cl_auth) | ||
401 | atomic_inc(&new->cl_auth->au_count); | ||
402 | xprt_get(clnt->cl_xprt); | ||
403 | atomic_inc(&clnt->cl_count); | ||
404 | rpc_register_client(new); | ||
405 | rpciod_up(); | ||
525 | return new; | 406 | return new; |
526 | 407 | out_no_path: | |
527 | out_put: | 408 | kfree(new->cl_principal); |
528 | xprt_put(xprt); | 409 | out_no_principal: |
529 | out_err: | 410 | rpc_free_iostats(new->cl_metrics); |
411 | out_no_stats: | ||
412 | kfree(new); | ||
413 | out_no_clnt: | ||
530 | dprintk("RPC: %s: returned error %d\n", __func__, err); | 414 | dprintk("RPC: %s: returned error %d\n", __func__, err); |
531 | return ERR_PTR(err); | 415 | return ERR_PTR(err); |
532 | } | 416 | } |
533 | |||
534 | /** | ||
535 | * rpc_clone_client - Clone an RPC client structure | ||
536 | * | ||
537 | * @clnt: RPC client whose parameters are copied | ||
538 | * | ||
539 | * Returns a fresh RPC client or an ERR_PTR. | ||
540 | */ | ||
541 | struct rpc_clnt *rpc_clone_client(struct rpc_clnt *clnt) | ||
542 | { | ||
543 | struct rpc_create_args args = { | ||
544 | .program = clnt->cl_program, | ||
545 | .prognumber = clnt->cl_prog, | ||
546 | .version = clnt->cl_vers, | ||
547 | .authflavor = clnt->cl_auth->au_flavor, | ||
548 | .client_name = clnt->cl_principal, | ||
549 | }; | ||
550 | return __rpc_clone_client(&args, clnt); | ||
551 | } | ||
552 | EXPORT_SYMBOL_GPL(rpc_clone_client); | 417 | EXPORT_SYMBOL_GPL(rpc_clone_client); |
553 | 418 | ||
554 | /** | ||
555 | * rpc_clone_client_set_auth - Clone an RPC client structure and set its auth | ||
556 | * | ||
557 | * @clnt: RPC client whose parameters are copied | ||
558 | * @flavor: security flavor for new client | ||
559 | * | ||
560 | * Returns a fresh RPC client or an ERR_PTR. | ||
561 | */ | ||
562 | struct rpc_clnt * | ||
563 | rpc_clone_client_set_auth(struct rpc_clnt *clnt, rpc_authflavor_t flavor) | ||
564 | { | ||
565 | struct rpc_create_args args = { | ||
566 | .program = clnt->cl_program, | ||
567 | .prognumber = clnt->cl_prog, | ||
568 | .version = clnt->cl_vers, | ||
569 | .authflavor = flavor, | ||
570 | .client_name = clnt->cl_principal, | ||
571 | }; | ||
572 | return __rpc_clone_client(&args, clnt); | ||
573 | } | ||
574 | EXPORT_SYMBOL_GPL(rpc_clone_client_set_auth); | ||
575 | |||
576 | /* | 419 | /* |
577 | * Kill all tasks for the given client. | 420 | * Kill all tasks for the given client. |
578 | * XXX: kill their descendants as well? | 421 | * XXX: kill their descendants as well? |
@@ -610,11 +453,8 @@ EXPORT_SYMBOL_GPL(rpc_killall_tasks); | |||
610 | */ | 453 | */ |
611 | void rpc_shutdown_client(struct rpc_clnt *clnt) | 454 | void rpc_shutdown_client(struct rpc_clnt *clnt) |
612 | { | 455 | { |
613 | might_sleep(); | 456 | dprintk("RPC: shutting down %s client for %s\n", |
614 | 457 | clnt->cl_protname, clnt->cl_server); | |
615 | dprintk_rcu("RPC: shutting down %s client for %s\n", | ||
616 | clnt->cl_protname, | ||
617 | rcu_dereference(clnt->cl_xprt)->servername); | ||
618 | 458 | ||
619 | while (!list_empty(&clnt->cl_tasks)) { | 459 | while (!list_empty(&clnt->cl_tasks)) { |
620 | rpc_killall_tasks(clnt); | 460 | rpc_killall_tasks(clnt); |
@@ -632,17 +472,24 @@ EXPORT_SYMBOL_GPL(rpc_shutdown_client); | |||
632 | static void | 472 | static void |
633 | rpc_free_client(struct rpc_clnt *clnt) | 473 | rpc_free_client(struct rpc_clnt *clnt) |
634 | { | 474 | { |
635 | dprintk_rcu("RPC: destroying %s client for %s\n", | 475 | dprintk("RPC: destroying %s client for %s\n", |
636 | clnt->cl_protname, | 476 | clnt->cl_protname, clnt->cl_server); |
637 | rcu_dereference(clnt->cl_xprt)->servername); | 477 | if (!IS_ERR(clnt->cl_path.dentry)) { |
638 | if (clnt->cl_parent != clnt) | 478 | rpc_remove_client_dir(clnt->cl_path.dentry); |
479 | rpc_put_mount(); | ||
480 | } | ||
481 | if (clnt->cl_parent != clnt) { | ||
639 | rpc_release_client(clnt->cl_parent); | 482 | rpc_release_client(clnt->cl_parent); |
483 | goto out_free; | ||
484 | } | ||
485 | if (clnt->cl_server != clnt->cl_inline_name) | ||
486 | kfree(clnt->cl_server); | ||
487 | out_free: | ||
640 | rpc_unregister_client(clnt); | 488 | rpc_unregister_client(clnt); |
641 | rpc_clnt_remove_pipedir(clnt); | ||
642 | rpc_free_iostats(clnt->cl_metrics); | 489 | rpc_free_iostats(clnt->cl_metrics); |
643 | kfree(clnt->cl_principal); | 490 | kfree(clnt->cl_principal); |
644 | clnt->cl_metrics = NULL; | 491 | clnt->cl_metrics = NULL; |
645 | xprt_put(rcu_dereference_raw(clnt->cl_xprt)); | 492 | xprt_put(clnt->cl_xprt); |
646 | rpciod_down(); | 493 | rpciod_down(); |
647 | kfree(clnt); | 494 | kfree(clnt); |
648 | } | 495 | } |
@@ -695,22 +542,24 @@ rpc_release_client(struct rpc_clnt *clnt) | |||
695 | * The Sun NFSv2/v3 ACL protocol can do this. | 542 | * The Sun NFSv2/v3 ACL protocol can do this. |
696 | */ | 543 | */ |
697 | struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old, | 544 | struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old, |
698 | const struct rpc_program *program, | 545 | struct rpc_program *program, |
699 | u32 vers) | 546 | u32 vers) |
700 | { | 547 | { |
701 | struct rpc_create_args args = { | ||
702 | .program = program, | ||
703 | .prognumber = program->number, | ||
704 | .version = vers, | ||
705 | .authflavor = old->cl_auth->au_flavor, | ||
706 | .client_name = old->cl_principal, | ||
707 | }; | ||
708 | struct rpc_clnt *clnt; | 548 | struct rpc_clnt *clnt; |
549 | struct rpc_version *version; | ||
709 | int err; | 550 | int err; |
710 | 551 | ||
711 | clnt = __rpc_clone_client(&args, old); | 552 | BUG_ON(vers >= program->nrvers || !program->version[vers]); |
553 | version = program->version[vers]; | ||
554 | clnt = rpc_clone_client(old); | ||
712 | if (IS_ERR(clnt)) | 555 | if (IS_ERR(clnt)) |
713 | goto out; | 556 | goto out; |
557 | clnt->cl_procinfo = version->procs; | ||
558 | clnt->cl_maxproc = version->nrprocs; | ||
559 | clnt->cl_protname = program->name; | ||
560 | clnt->cl_prog = program->number; | ||
561 | clnt->cl_vers = version->number; | ||
562 | clnt->cl_stats = program->stats; | ||
714 | err = rpc_ping(clnt); | 563 | err = rpc_ping(clnt); |
715 | if (err != 0) { | 564 | if (err != 0) { |
716 | rpc_shutdown_client(clnt); | 565 | rpc_shutdown_client(clnt); |
@@ -745,15 +594,6 @@ void rpc_task_set_client(struct rpc_task *task, struct rpc_clnt *clnt) | |||
745 | atomic_inc(&clnt->cl_count); | 594 | atomic_inc(&clnt->cl_count); |
746 | if (clnt->cl_softrtry) | 595 | if (clnt->cl_softrtry) |
747 | task->tk_flags |= RPC_TASK_SOFT; | 596 | task->tk_flags |= RPC_TASK_SOFT; |
748 | if (sk_memalloc_socks()) { | ||
749 | struct rpc_xprt *xprt; | ||
750 | |||
751 | rcu_read_lock(); | ||
752 | xprt = rcu_dereference(clnt->cl_xprt); | ||
753 | if (xprt->swapper) | ||
754 | task->tk_flags |= RPC_TASK_SWAPPER; | ||
755 | rcu_read_unlock(); | ||
756 | } | ||
757 | /* Add to the client's list of all tasks */ | 597 | /* Add to the client's list of all tasks */ |
758 | spin_lock(&clnt->cl_lock); | 598 | spin_lock(&clnt->cl_lock); |
759 | list_add_tail(&task->tk_task, &clnt->cl_tasks); | 599 | list_add_tail(&task->tk_task, &clnt->cl_tasks); |
@@ -835,12 +675,7 @@ int rpc_call_sync(struct rpc_clnt *clnt, const struct rpc_message *msg, int flag | |||
835 | }; | 675 | }; |
836 | int status; | 676 | int status; |
837 | 677 | ||
838 | WARN_ON_ONCE(flags & RPC_TASK_ASYNC); | 678 | BUG_ON(flags & RPC_TASK_ASYNC); |
839 | if (flags & RPC_TASK_ASYNC) { | ||
840 | rpc_release_calldata(task_setup_data.callback_ops, | ||
841 | task_setup_data.callback_data); | ||
842 | return -EINVAL; | ||
843 | } | ||
844 | 679 | ||
845 | task = rpc_run_task(&task_setup_data); | 680 | task = rpc_run_task(&task_setup_data); |
846 | if (IS_ERR(task)) | 681 | if (IS_ERR(task)) |
@@ -916,7 +751,7 @@ struct rpc_task *rpc_run_bc_task(struct rpc_rqst *req, | |||
916 | 751 | ||
917 | task->tk_action = call_bc_transmit; | 752 | task->tk_action = call_bc_transmit; |
918 | atomic_inc(&task->tk_count); | 753 | atomic_inc(&task->tk_count); |
919 | WARN_ON_ONCE(atomic_read(&task->tk_count) != 2); | 754 | BUG_ON(atomic_read(&task->tk_count) != 2); |
920 | rpc_execute(task); | 755 | rpc_execute(task); |
921 | 756 | ||
922 | out: | 757 | out: |
@@ -943,18 +778,13 @@ EXPORT_SYMBOL_GPL(rpc_call_start); | |||
943 | size_t rpc_peeraddr(struct rpc_clnt *clnt, struct sockaddr *buf, size_t bufsize) | 778 | size_t rpc_peeraddr(struct rpc_clnt *clnt, struct sockaddr *buf, size_t bufsize) |
944 | { | 779 | { |
945 | size_t bytes; | 780 | size_t bytes; |
946 | struct rpc_xprt *xprt; | 781 | struct rpc_xprt *xprt = clnt->cl_xprt; |
947 | 782 | ||
948 | rcu_read_lock(); | 783 | bytes = sizeof(xprt->addr); |
949 | xprt = rcu_dereference(clnt->cl_xprt); | ||
950 | |||
951 | bytes = xprt->addrlen; | ||
952 | if (bytes > bufsize) | 784 | if (bytes > bufsize) |
953 | bytes = bufsize; | 785 | bytes = bufsize; |
954 | memcpy(buf, &xprt->addr, bytes); | 786 | memcpy(buf, &clnt->cl_xprt->addr, bytes); |
955 | rcu_read_unlock(); | 787 | return xprt->addrlen; |
956 | |||
957 | return bytes; | ||
958 | } | 788 | } |
959 | EXPORT_SYMBOL_GPL(rpc_peeraddr); | 789 | EXPORT_SYMBOL_GPL(rpc_peeraddr); |
960 | 790 | ||
@@ -963,16 +793,11 @@ EXPORT_SYMBOL_GPL(rpc_peeraddr); | |||
963 | * @clnt: RPC client structure | 793 | * @clnt: RPC client structure |
964 | * @format: address format | 794 | * @format: address format |
965 | * | 795 | * |
966 | * NB: the lifetime of the memory referenced by the returned pointer is | ||
967 | * the same as the rpc_xprt itself. As long as the caller uses this | ||
968 | * pointer, it must hold the RCU read lock. | ||
969 | */ | 796 | */ |
970 | const char *rpc_peeraddr2str(struct rpc_clnt *clnt, | 797 | const char *rpc_peeraddr2str(struct rpc_clnt *clnt, |
971 | enum rpc_display_format_t format) | 798 | enum rpc_display_format_t format) |
972 | { | 799 | { |
973 | struct rpc_xprt *xprt; | 800 | struct rpc_xprt *xprt = clnt->cl_xprt; |
974 | |||
975 | xprt = rcu_dereference(clnt->cl_xprt); | ||
976 | 801 | ||
977 | if (xprt->address_strings[format] != NULL) | 802 | if (xprt->address_strings[format] != NULL) |
978 | return xprt->address_strings[format]; | 803 | return xprt->address_strings[format]; |
@@ -981,203 +806,17 @@ const char *rpc_peeraddr2str(struct rpc_clnt *clnt, | |||
981 | } | 806 | } |
982 | EXPORT_SYMBOL_GPL(rpc_peeraddr2str); | 807 | EXPORT_SYMBOL_GPL(rpc_peeraddr2str); |
983 | 808 | ||
984 | static const struct sockaddr_in rpc_inaddr_loopback = { | ||
985 | .sin_family = AF_INET, | ||
986 | .sin_addr.s_addr = htonl(INADDR_ANY), | ||
987 | }; | ||
988 | |||
989 | static const struct sockaddr_in6 rpc_in6addr_loopback = { | ||
990 | .sin6_family = AF_INET6, | ||
991 | .sin6_addr = IN6ADDR_ANY_INIT, | ||
992 | }; | ||
993 | |||
994 | /* | ||
995 | * Try a getsockname() on a connected datagram socket. Using a | ||
996 | * connected datagram socket prevents leaving a socket in TIME_WAIT. | ||
997 | * This conserves the ephemeral port number space. | ||
998 | * | ||
999 | * Returns zero and fills in "buf" if successful; otherwise, a | ||
1000 | * negative errno is returned. | ||
1001 | */ | ||
1002 | static int rpc_sockname(struct net *net, struct sockaddr *sap, size_t salen, | ||
1003 | struct sockaddr *buf, int buflen) | ||
1004 | { | ||
1005 | struct socket *sock; | ||
1006 | int err; | ||
1007 | |||
1008 | err = __sock_create(net, sap->sa_family, | ||
1009 | SOCK_DGRAM, IPPROTO_UDP, &sock, 1); | ||
1010 | if (err < 0) { | ||
1011 | dprintk("RPC: can't create UDP socket (%d)\n", err); | ||
1012 | goto out; | ||
1013 | } | ||
1014 | |||
1015 | switch (sap->sa_family) { | ||
1016 | case AF_INET: | ||
1017 | err = kernel_bind(sock, | ||
1018 | (struct sockaddr *)&rpc_inaddr_loopback, | ||
1019 | sizeof(rpc_inaddr_loopback)); | ||
1020 | break; | ||
1021 | case AF_INET6: | ||
1022 | err = kernel_bind(sock, | ||
1023 | (struct sockaddr *)&rpc_in6addr_loopback, | ||
1024 | sizeof(rpc_in6addr_loopback)); | ||
1025 | break; | ||
1026 | default: | ||
1027 | err = -EAFNOSUPPORT; | ||
1028 | goto out; | ||
1029 | } | ||
1030 | if (err < 0) { | ||
1031 | dprintk("RPC: can't bind UDP socket (%d)\n", err); | ||
1032 | goto out_release; | ||
1033 | } | ||
1034 | |||
1035 | err = kernel_connect(sock, sap, salen, 0); | ||
1036 | if (err < 0) { | ||
1037 | dprintk("RPC: can't connect UDP socket (%d)\n", err); | ||
1038 | goto out_release; | ||
1039 | } | ||
1040 | |||
1041 | err = kernel_getsockname(sock, buf, &buflen); | ||
1042 | if (err < 0) { | ||
1043 | dprintk("RPC: getsockname failed (%d)\n", err); | ||
1044 | goto out_release; | ||
1045 | } | ||
1046 | |||
1047 | err = 0; | ||
1048 | if (buf->sa_family == AF_INET6) { | ||
1049 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)buf; | ||
1050 | sin6->sin6_scope_id = 0; | ||
1051 | } | ||
1052 | dprintk("RPC: %s succeeded\n", __func__); | ||
1053 | |||
1054 | out_release: | ||
1055 | sock_release(sock); | ||
1056 | out: | ||
1057 | return err; | ||
1058 | } | ||
1059 | |||
1060 | /* | ||
1061 | * Scraping a connected socket failed, so we don't have a useable | ||
1062 | * local address. Fallback: generate an address that will prevent | ||
1063 | * the server from calling us back. | ||
1064 | * | ||
1065 | * Returns zero and fills in "buf" if successful; otherwise, a | ||
1066 | * negative errno is returned. | ||
1067 | */ | ||
1068 | static int rpc_anyaddr(int family, struct sockaddr *buf, size_t buflen) | ||
1069 | { | ||
1070 | switch (family) { | ||
1071 | case AF_INET: | ||
1072 | if (buflen < sizeof(rpc_inaddr_loopback)) | ||
1073 | return -EINVAL; | ||
1074 | memcpy(buf, &rpc_inaddr_loopback, | ||
1075 | sizeof(rpc_inaddr_loopback)); | ||
1076 | break; | ||
1077 | case AF_INET6: | ||
1078 | if (buflen < sizeof(rpc_in6addr_loopback)) | ||
1079 | return -EINVAL; | ||
1080 | memcpy(buf, &rpc_in6addr_loopback, | ||
1081 | sizeof(rpc_in6addr_loopback)); | ||
1082 | default: | ||
1083 | dprintk("RPC: %s: address family not supported\n", | ||
1084 | __func__); | ||
1085 | return -EAFNOSUPPORT; | ||
1086 | } | ||
1087 | dprintk("RPC: %s: succeeded\n", __func__); | ||
1088 | return 0; | ||
1089 | } | ||
1090 | |||
1091 | /** | ||
1092 | * rpc_localaddr - discover local endpoint address for an RPC client | ||
1093 | * @clnt: RPC client structure | ||
1094 | * @buf: target buffer | ||
1095 | * @buflen: size of target buffer, in bytes | ||
1096 | * | ||
1097 | * Returns zero and fills in "buf" and "buflen" if successful; | ||
1098 | * otherwise, a negative errno is returned. | ||
1099 | * | ||
1100 | * This works even if the underlying transport is not currently connected, | ||
1101 | * or if the upper layer never previously provided a source address. | ||
1102 | * | ||
1103 | * The result of this function call is transient: multiple calls in | ||
1104 | * succession may give different results, depending on how local | ||
1105 | * networking configuration changes over time. | ||
1106 | */ | ||
1107 | int rpc_localaddr(struct rpc_clnt *clnt, struct sockaddr *buf, size_t buflen) | ||
1108 | { | ||
1109 | struct sockaddr_storage address; | ||
1110 | struct sockaddr *sap = (struct sockaddr *)&address; | ||
1111 | struct rpc_xprt *xprt; | ||
1112 | struct net *net; | ||
1113 | size_t salen; | ||
1114 | int err; | ||
1115 | |||
1116 | rcu_read_lock(); | ||
1117 | xprt = rcu_dereference(clnt->cl_xprt); | ||
1118 | salen = xprt->addrlen; | ||
1119 | memcpy(sap, &xprt->addr, salen); | ||
1120 | net = get_net(xprt->xprt_net); | ||
1121 | rcu_read_unlock(); | ||
1122 | |||
1123 | rpc_set_port(sap, 0); | ||
1124 | err = rpc_sockname(net, sap, salen, buf, buflen); | ||
1125 | put_net(net); | ||
1126 | if (err != 0) | ||
1127 | /* Couldn't discover local address, return ANYADDR */ | ||
1128 | return rpc_anyaddr(sap->sa_family, buf, buflen); | ||
1129 | return 0; | ||
1130 | } | ||
1131 | EXPORT_SYMBOL_GPL(rpc_localaddr); | ||
1132 | |||
1133 | void | 809 | void |
1134 | rpc_setbufsize(struct rpc_clnt *clnt, unsigned int sndsize, unsigned int rcvsize) | 810 | rpc_setbufsize(struct rpc_clnt *clnt, unsigned int sndsize, unsigned int rcvsize) |
1135 | { | 811 | { |
1136 | struct rpc_xprt *xprt; | 812 | struct rpc_xprt *xprt = clnt->cl_xprt; |
1137 | |||
1138 | rcu_read_lock(); | ||
1139 | xprt = rcu_dereference(clnt->cl_xprt); | ||
1140 | if (xprt->ops->set_buffer_size) | 813 | if (xprt->ops->set_buffer_size) |
1141 | xprt->ops->set_buffer_size(xprt, sndsize, rcvsize); | 814 | xprt->ops->set_buffer_size(xprt, sndsize, rcvsize); |
1142 | rcu_read_unlock(); | ||
1143 | } | 815 | } |
1144 | EXPORT_SYMBOL_GPL(rpc_setbufsize); | 816 | EXPORT_SYMBOL_GPL(rpc_setbufsize); |
1145 | 817 | ||
1146 | /** | 818 | /* |
1147 | * rpc_protocol - Get transport protocol number for an RPC client | 819 | * Return size of largest payload RPC client can support, in bytes |
1148 | * @clnt: RPC client to query | ||
1149 | * | ||
1150 | */ | ||
1151 | int rpc_protocol(struct rpc_clnt *clnt) | ||
1152 | { | ||
1153 | int protocol; | ||
1154 | |||
1155 | rcu_read_lock(); | ||
1156 | protocol = rcu_dereference(clnt->cl_xprt)->prot; | ||
1157 | rcu_read_unlock(); | ||
1158 | return protocol; | ||
1159 | } | ||
1160 | EXPORT_SYMBOL_GPL(rpc_protocol); | ||
1161 | |||
1162 | /** | ||
1163 | * rpc_net_ns - Get the network namespace for this RPC client | ||
1164 | * @clnt: RPC client to query | ||
1165 | * | ||
1166 | */ | ||
1167 | struct net *rpc_net_ns(struct rpc_clnt *clnt) | ||
1168 | { | ||
1169 | struct net *ret; | ||
1170 | |||
1171 | rcu_read_lock(); | ||
1172 | ret = rcu_dereference(clnt->cl_xprt)->xprt_net; | ||
1173 | rcu_read_unlock(); | ||
1174 | return ret; | ||
1175 | } | ||
1176 | EXPORT_SYMBOL_GPL(rpc_net_ns); | ||
1177 | |||
1178 | /** | ||
1179 | * rpc_max_payload - Get maximum payload size for a transport, in bytes | ||
1180 | * @clnt: RPC client to query | ||
1181 | * | 820 | * |
1182 | * For stream transports, this is one RPC record fragment (see RFC | 821 | * For stream transports, this is one RPC record fragment (see RFC |
1183 | * 1831), as we don't support multi-record requests yet. For datagram | 822 | * 1831), as we don't support multi-record requests yet. For datagram |
@@ -1186,12 +825,7 @@ EXPORT_SYMBOL_GPL(rpc_net_ns); | |||
1186 | */ | 825 | */ |
1187 | size_t rpc_max_payload(struct rpc_clnt *clnt) | 826 | size_t rpc_max_payload(struct rpc_clnt *clnt) |
1188 | { | 827 | { |
1189 | size_t ret; | 828 | return clnt->cl_xprt->max_payload; |
1190 | |||
1191 | rcu_read_lock(); | ||
1192 | ret = rcu_dereference(clnt->cl_xprt)->max_payload; | ||
1193 | rcu_read_unlock(); | ||
1194 | return ret; | ||
1195 | } | 829 | } |
1196 | EXPORT_SYMBOL_GPL(rpc_max_payload); | 830 | EXPORT_SYMBOL_GPL(rpc_max_payload); |
1197 | 831 | ||
@@ -1202,11 +836,8 @@ EXPORT_SYMBOL_GPL(rpc_max_payload); | |||
1202 | */ | 836 | */ |
1203 | void rpc_force_rebind(struct rpc_clnt *clnt) | 837 | void rpc_force_rebind(struct rpc_clnt *clnt) |
1204 | { | 838 | { |
1205 | if (clnt->cl_autobind) { | 839 | if (clnt->cl_autobind) |
1206 | rcu_read_lock(); | 840 | xprt_clear_bound(clnt->cl_xprt); |
1207 | xprt_clear_bound(rcu_dereference(clnt->cl_xprt)); | ||
1208 | rcu_read_unlock(); | ||
1209 | } | ||
1210 | } | 841 | } |
1211 | EXPORT_SYMBOL_GPL(rpc_force_rebind); | 842 | EXPORT_SYMBOL_GPL(rpc_force_rebind); |
1212 | 843 | ||
@@ -1219,9 +850,7 @@ rpc_restart_call_prepare(struct rpc_task *task) | |||
1219 | { | 850 | { |
1220 | if (RPC_ASSASSINATED(task)) | 851 | if (RPC_ASSASSINATED(task)) |
1221 | return 0; | 852 | return 0; |
1222 | task->tk_action = call_start; | 853 | task->tk_action = rpc_prepare_task; |
1223 | if (task->tk_ops->rpc_call_prepare != NULL) | ||
1224 | task->tk_action = rpc_prepare_task; | ||
1225 | return 1; | 854 | return 1; |
1226 | } | 855 | } |
1227 | EXPORT_SYMBOL_GPL(rpc_restart_call_prepare); | 856 | EXPORT_SYMBOL_GPL(rpc_restart_call_prepare); |
@@ -1328,8 +957,6 @@ call_reserveresult(struct rpc_task *task) | |||
1328 | } | 957 | } |
1329 | 958 | ||
1330 | switch (status) { | 959 | switch (status) { |
1331 | case -ENOMEM: | ||
1332 | rpc_delay(task, HZ >> 2); | ||
1333 | case -EAGAIN: /* woken up; retry */ | 960 | case -EAGAIN: /* woken up; retry */ |
1334 | task->tk_action = call_reserve; | 961 | task->tk_action = call_reserve; |
1335 | return; | 962 | return; |
@@ -1376,7 +1003,6 @@ call_refreshresult(struct rpc_task *task) | |||
1376 | return; | 1003 | return; |
1377 | case -ETIMEDOUT: | 1004 | case -ETIMEDOUT: |
1378 | rpc_delay(task, 3*HZ); | 1005 | rpc_delay(task, 3*HZ); |
1379 | case -EKEYEXPIRED: | ||
1380 | case -EAGAIN: | 1006 | case -EAGAIN: |
1381 | status = -EACCES; | 1007 | status = -EACCES; |
1382 | if (!task->tk_cred_retry) | 1008 | if (!task->tk_cred_retry) |
@@ -1535,7 +1161,6 @@ call_bind_status(struct rpc_task *task) | |||
1535 | return; | 1161 | return; |
1536 | } | 1162 | } |
1537 | 1163 | ||
1538 | trace_rpc_bind_status(task); | ||
1539 | switch (task->tk_status) { | 1164 | switch (task->tk_status) { |
1540 | case -ENOMEM: | 1165 | case -ENOMEM: |
1541 | dprintk("RPC: %5u rpcbind out of memory\n", task->tk_pid); | 1166 | dprintk("RPC: %5u rpcbind out of memory\n", task->tk_pid); |
@@ -1635,7 +1260,6 @@ call_connect_status(struct rpc_task *task) | |||
1635 | return; | 1260 | return; |
1636 | } | 1261 | } |
1637 | 1262 | ||
1638 | trace_rpc_connect_status(task, status); | ||
1639 | switch (status) { | 1263 | switch (status) { |
1640 | /* if soft mounted, test if we've timed out */ | 1264 | /* if soft mounted, test if we've timed out */ |
1641 | case -ETIMEDOUT: | 1265 | case -ETIMEDOUT: |
@@ -1663,6 +1287,7 @@ call_transmit(struct rpc_task *task) | |||
1663 | task->tk_action = call_transmit_status; | 1287 | task->tk_action = call_transmit_status; |
1664 | /* Encode here so that rpcsec_gss can use correct sequence number. */ | 1288 | /* Encode here so that rpcsec_gss can use correct sequence number. */ |
1665 | if (rpc_task_need_encode(task)) { | 1289 | if (rpc_task_need_encode(task)) { |
1290 | BUG_ON(task->tk_rqstp->rq_bytes_sent != 0); | ||
1666 | rpc_xdr_encode(task); | 1291 | rpc_xdr_encode(task); |
1667 | /* Did the encode result in an error condition? */ | 1292 | /* Did the encode result in an error condition? */ |
1668 | if (task->tk_status != 0) { | 1293 | if (task->tk_status != 0) { |
@@ -1746,6 +1371,7 @@ call_bc_transmit(struct rpc_task *task) | |||
1746 | { | 1371 | { |
1747 | struct rpc_rqst *req = task->tk_rqstp; | 1372 | struct rpc_rqst *req = task->tk_rqstp; |
1748 | 1373 | ||
1374 | BUG_ON(task->tk_status != 0); | ||
1749 | task->tk_status = xprt_prepare_transmit(task); | 1375 | task->tk_status = xprt_prepare_transmit(task); |
1750 | if (task->tk_status == -EAGAIN) { | 1376 | if (task->tk_status == -EAGAIN) { |
1751 | /* | 1377 | /* |
@@ -1792,7 +1418,7 @@ call_bc_transmit(struct rpc_task *task) | |||
1792 | * We were unable to reply and will have to drop the | 1418 | * We were unable to reply and will have to drop the |
1793 | * request. The server should reconnect and retransmit. | 1419 | * request. The server should reconnect and retransmit. |
1794 | */ | 1420 | */ |
1795 | WARN_ON_ONCE(task->tk_status == -EAGAIN); | 1421 | BUG_ON(task->tk_status == -EAGAIN); |
1796 | printk(KERN_NOTICE "RPC: Could not send backchannel reply " | 1422 | printk(KERN_NOTICE "RPC: Could not send backchannel reply " |
1797 | "error: %d\n", task->tk_status); | 1423 | "error: %d\n", task->tk_status); |
1798 | break; | 1424 | break; |
@@ -1822,7 +1448,6 @@ call_status(struct rpc_task *task) | |||
1822 | return; | 1448 | return; |
1823 | } | 1449 | } |
1824 | 1450 | ||
1825 | trace_rpc_call_status(task); | ||
1826 | task->tk_status = 0; | 1451 | task->tk_status = 0; |
1827 | switch(status) { | 1452 | switch(status) { |
1828 | case -EHOSTDOWN: | 1453 | case -EHOSTDOWN: |
@@ -1885,13 +1510,9 @@ call_timeout(struct rpc_task *task) | |||
1885 | return; | 1510 | return; |
1886 | } | 1511 | } |
1887 | if (RPC_IS_SOFT(task)) { | 1512 | if (RPC_IS_SOFT(task)) { |
1888 | if (clnt->cl_chatty) { | 1513 | if (clnt->cl_chatty) |
1889 | rcu_read_lock(); | ||
1890 | printk(KERN_NOTICE "%s: server %s not responding, timed out\n", | 1514 | printk(KERN_NOTICE "%s: server %s not responding, timed out\n", |
1891 | clnt->cl_protname, | 1515 | clnt->cl_protname, clnt->cl_server); |
1892 | rcu_dereference(clnt->cl_xprt)->servername); | ||
1893 | rcu_read_unlock(); | ||
1894 | } | ||
1895 | if (task->tk_flags & RPC_TASK_TIMEOUT) | 1516 | if (task->tk_flags & RPC_TASK_TIMEOUT) |
1896 | rpc_exit(task, -ETIMEDOUT); | 1517 | rpc_exit(task, -ETIMEDOUT); |
1897 | else | 1518 | else |
@@ -1901,13 +1522,9 @@ call_timeout(struct rpc_task *task) | |||
1901 | 1522 | ||
1902 | if (!(task->tk_flags & RPC_CALL_MAJORSEEN)) { | 1523 | if (!(task->tk_flags & RPC_CALL_MAJORSEEN)) { |
1903 | task->tk_flags |= RPC_CALL_MAJORSEEN; | 1524 | task->tk_flags |= RPC_CALL_MAJORSEEN; |
1904 | if (clnt->cl_chatty) { | 1525 | if (clnt->cl_chatty) |
1905 | rcu_read_lock(); | ||
1906 | printk(KERN_NOTICE "%s: server %s not responding, still trying\n", | 1526 | printk(KERN_NOTICE "%s: server %s not responding, still trying\n", |
1907 | clnt->cl_protname, | 1527 | clnt->cl_protname, clnt->cl_server); |
1908 | rcu_dereference(clnt->cl_xprt)->servername); | ||
1909 | rcu_read_unlock(); | ||
1910 | } | ||
1911 | } | 1528 | } |
1912 | rpc_force_rebind(clnt); | 1529 | rpc_force_rebind(clnt); |
1913 | /* | 1530 | /* |
@@ -1936,13 +1553,9 @@ call_decode(struct rpc_task *task) | |||
1936 | dprint_status(task); | 1553 | dprint_status(task); |
1937 | 1554 | ||
1938 | if (task->tk_flags & RPC_CALL_MAJORSEEN) { | 1555 | if (task->tk_flags & RPC_CALL_MAJORSEEN) { |
1939 | if (clnt->cl_chatty) { | 1556 | if (clnt->cl_chatty) |
1940 | rcu_read_lock(); | ||
1941 | printk(KERN_NOTICE "%s: server %s OK\n", | 1557 | printk(KERN_NOTICE "%s: server %s OK\n", |
1942 | clnt->cl_protname, | 1558 | clnt->cl_protname, clnt->cl_server); |
1943 | rcu_dereference(clnt->cl_xprt)->servername); | ||
1944 | rcu_read_unlock(); | ||
1945 | } | ||
1946 | task->tk_flags &= ~RPC_CALL_MAJORSEEN; | 1559 | task->tk_flags &= ~RPC_CALL_MAJORSEEN; |
1947 | } | 1560 | } |
1948 | 1561 | ||
@@ -2020,7 +1633,6 @@ rpc_encode_header(struct rpc_task *task) | |||
2020 | static __be32 * | 1633 | static __be32 * |
2021 | rpc_verify_header(struct rpc_task *task) | 1634 | rpc_verify_header(struct rpc_task *task) |
2022 | { | 1635 | { |
2023 | struct rpc_clnt *clnt = task->tk_client; | ||
2024 | struct kvec *iov = &task->tk_rqstp->rq_rcv_buf.head[0]; | 1636 | struct kvec *iov = &task->tk_rqstp->rq_rcv_buf.head[0]; |
2025 | int len = task->tk_rqstp->rq_rcv_buf.len >> 2; | 1637 | int len = task->tk_rqstp->rq_rcv_buf.len >> 2; |
2026 | __be32 *p = iov->iov_base; | 1638 | __be32 *p = iov->iov_base; |
@@ -2093,11 +1705,8 @@ rpc_verify_header(struct rpc_task *task) | |||
2093 | task->tk_action = call_bind; | 1705 | task->tk_action = call_bind; |
2094 | goto out_retry; | 1706 | goto out_retry; |
2095 | case RPC_AUTH_TOOWEAK: | 1707 | case RPC_AUTH_TOOWEAK: |
2096 | rcu_read_lock(); | ||
2097 | printk(KERN_NOTICE "RPC: server %s requires stronger " | 1708 | printk(KERN_NOTICE "RPC: server %s requires stronger " |
2098 | "authentication.\n", | 1709 | "authentication.\n", task->tk_client->cl_server); |
2099 | rcu_dereference(clnt->cl_xprt)->servername); | ||
2100 | rcu_read_unlock(); | ||
2101 | break; | 1710 | break; |
2102 | default: | 1711 | default: |
2103 | dprintk("RPC: %5u %s: unknown auth error: %x\n", | 1712 | dprintk("RPC: %5u %s: unknown auth error: %x\n", |
@@ -2120,27 +1729,28 @@ rpc_verify_header(struct rpc_task *task) | |||
2120 | case RPC_SUCCESS: | 1729 | case RPC_SUCCESS: |
2121 | return p; | 1730 | return p; |
2122 | case RPC_PROG_UNAVAIL: | 1731 | case RPC_PROG_UNAVAIL: |
2123 | dprintk_rcu("RPC: %5u %s: program %u is unsupported " | 1732 | dprintk("RPC: %5u %s: program %u is unsupported by server %s\n", |
2124 | "by server %s\n", task->tk_pid, __func__, | 1733 | task->tk_pid, __func__, |
2125 | (unsigned int)clnt->cl_prog, | 1734 | (unsigned int)task->tk_client->cl_prog, |
2126 | rcu_dereference(clnt->cl_xprt)->servername); | 1735 | task->tk_client->cl_server); |
2127 | error = -EPFNOSUPPORT; | 1736 | error = -EPFNOSUPPORT; |
2128 | goto out_err; | 1737 | goto out_err; |
2129 | case RPC_PROG_MISMATCH: | 1738 | case RPC_PROG_MISMATCH: |
2130 | dprintk_rcu("RPC: %5u %s: program %u, version %u unsupported " | 1739 | dprintk("RPC: %5u %s: program %u, version %u unsupported by " |
2131 | "by server %s\n", task->tk_pid, __func__, | 1740 | "server %s\n", task->tk_pid, __func__, |
2132 | (unsigned int)clnt->cl_prog, | 1741 | (unsigned int)task->tk_client->cl_prog, |
2133 | (unsigned int)clnt->cl_vers, | 1742 | (unsigned int)task->tk_client->cl_vers, |
2134 | rcu_dereference(clnt->cl_xprt)->servername); | 1743 | task->tk_client->cl_server); |
2135 | error = -EPROTONOSUPPORT; | 1744 | error = -EPROTONOSUPPORT; |
2136 | goto out_err; | 1745 | goto out_err; |
2137 | case RPC_PROC_UNAVAIL: | 1746 | case RPC_PROC_UNAVAIL: |
2138 | dprintk_rcu("RPC: %5u %s: proc %s unsupported by program %u, " | 1747 | dprintk("RPC: %5u %s: proc %s unsupported by program %u, " |
2139 | "version %u on server %s\n", | 1748 | "version %u on server %s\n", |
2140 | task->tk_pid, __func__, | 1749 | task->tk_pid, __func__, |
2141 | rpc_proc_name(task), | 1750 | rpc_proc_name(task), |
2142 | clnt->cl_prog, clnt->cl_vers, | 1751 | task->tk_client->cl_prog, |
2143 | rcu_dereference(clnt->cl_xprt)->servername); | 1752 | task->tk_client->cl_vers, |
1753 | task->tk_client->cl_server); | ||
2144 | error = -EOPNOTSUPP; | 1754 | error = -EOPNOTSUPP; |
2145 | goto out_err; | 1755 | goto out_err; |
2146 | case RPC_GARBAGE_ARGS: | 1756 | case RPC_GARBAGE_ARGS: |
@@ -2154,7 +1764,7 @@ rpc_verify_header(struct rpc_task *task) | |||
2154 | } | 1764 | } |
2155 | 1765 | ||
2156 | out_garbage: | 1766 | out_garbage: |
2157 | clnt->cl_stats->rpcgarbage++; | 1767 | task->tk_client->cl_stats->rpcgarbage++; |
2158 | if (task->tk_garb_retry) { | 1768 | if (task->tk_garb_retry) { |
2159 | task->tk_garb_retry--; | 1769 | task->tk_garb_retry--; |
2160 | dprintk("RPC: %5u %s: retrying\n", | 1770 | dprintk("RPC: %5u %s: retrying\n", |
@@ -2240,15 +1850,14 @@ static void rpc_show_task(const struct rpc_clnt *clnt, | |||
2240 | task->tk_action, rpc_waitq); | 1850 | task->tk_action, rpc_waitq); |
2241 | } | 1851 | } |
2242 | 1852 | ||
2243 | void rpc_show_tasks(struct net *net) | 1853 | void rpc_show_tasks(void) |
2244 | { | 1854 | { |
2245 | struct rpc_clnt *clnt; | 1855 | struct rpc_clnt *clnt; |
2246 | struct rpc_task *task; | 1856 | struct rpc_task *task; |
2247 | int header = 0; | 1857 | int header = 0; |
2248 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
2249 | 1858 | ||
2250 | spin_lock(&sn->rpc_client_lock); | 1859 | spin_lock(&rpc_client_lock); |
2251 | list_for_each_entry(clnt, &sn->all_clients, cl_clients) { | 1860 | list_for_each_entry(clnt, &all_clients, cl_clients) { |
2252 | spin_lock(&clnt->cl_lock); | 1861 | spin_lock(&clnt->cl_lock); |
2253 | list_for_each_entry(task, &clnt->cl_tasks, tk_task) { | 1862 | list_for_each_entry(task, &clnt->cl_tasks, tk_task) { |
2254 | if (!header) { | 1863 | if (!header) { |
@@ -2259,6 +1868,6 @@ void rpc_show_tasks(struct net *net) | |||
2259 | } | 1868 | } |
2260 | spin_unlock(&clnt->cl_lock); | 1869 | spin_unlock(&clnt->cl_lock); |
2261 | } | 1870 | } |
2262 | spin_unlock(&sn->rpc_client_lock); | 1871 | spin_unlock(&rpc_client_lock); |
2263 | } | 1872 | } |
2264 | #endif | 1873 | #endif |
diff --git a/net/sunrpc/netns.h b/net/sunrpc/netns.h index ce7bd449173..d013bf211ca 100644 --- a/net/sunrpc/netns.h +++ b/net/sunrpc/netns.h | |||
@@ -9,20 +9,6 @@ struct cache_detail; | |||
9 | struct sunrpc_net { | 9 | struct sunrpc_net { |
10 | struct proc_dir_entry *proc_net_rpc; | 10 | struct proc_dir_entry *proc_net_rpc; |
11 | struct cache_detail *ip_map_cache; | 11 | struct cache_detail *ip_map_cache; |
12 | struct cache_detail *unix_gid_cache; | ||
13 | struct cache_detail *rsc_cache; | ||
14 | struct cache_detail *rsi_cache; | ||
15 | |||
16 | struct super_block *pipefs_sb; | ||
17 | struct mutex pipefs_sb_lock; | ||
18 | |||
19 | struct list_head all_clients; | ||
20 | spinlock_t rpc_client_lock; | ||
21 | |||
22 | struct rpc_clnt *rpcb_local_clnt; | ||
23 | struct rpc_clnt *rpcb_local_clnt4; | ||
24 | spinlock_t rpcb_clnt_lock; | ||
25 | unsigned int rpcb_users; | ||
26 | }; | 12 | }; |
27 | 13 | ||
28 | extern int sunrpc_net_id; | 14 | extern int sunrpc_net_id; |
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index fd10981ea79..67dbc188438 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
@@ -16,9 +16,9 @@ | |||
16 | #include <linux/namei.h> | 16 | #include <linux/namei.h> |
17 | #include <linux/fsnotify.h> | 17 | #include <linux/fsnotify.h> |
18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
19 | #include <linux/rcupdate.h> | ||
20 | 19 | ||
21 | #include <asm/ioctls.h> | 20 | #include <asm/ioctls.h> |
21 | #include <linux/fs.h> | ||
22 | #include <linux/poll.h> | 22 | #include <linux/poll.h> |
23 | #include <linux/wait.h> | 23 | #include <linux/wait.h> |
24 | #include <linux/seq_file.h> | 24 | #include <linux/seq_file.h> |
@@ -27,15 +27,9 @@ | |||
27 | #include <linux/workqueue.h> | 27 | #include <linux/workqueue.h> |
28 | #include <linux/sunrpc/rpc_pipe_fs.h> | 28 | #include <linux/sunrpc/rpc_pipe_fs.h> |
29 | #include <linux/sunrpc/cache.h> | 29 | #include <linux/sunrpc/cache.h> |
30 | #include <linux/nsproxy.h> | ||
31 | #include <linux/notifier.h> | ||
32 | 30 | ||
33 | #include "netns.h" | 31 | static struct vfsmount *rpc_mnt __read_mostly; |
34 | #include "sunrpc.h" | 32 | static int rpc_mount_count; |
35 | |||
36 | #define RPCDBG_FACILITY RPCDBG_DEBUG | ||
37 | |||
38 | #define NET_NAME(net) ((net == &init_net) ? " (init_net)" : "") | ||
39 | 33 | ||
40 | static struct file_system_type rpc_pipe_fs_type; | 34 | static struct file_system_type rpc_pipe_fs_type; |
41 | 35 | ||
@@ -44,21 +38,7 @@ static struct kmem_cache *rpc_inode_cachep __read_mostly; | |||
44 | 38 | ||
45 | #define RPC_UPCALL_TIMEOUT (30*HZ) | 39 | #define RPC_UPCALL_TIMEOUT (30*HZ) |
46 | 40 | ||
47 | static BLOCKING_NOTIFIER_HEAD(rpc_pipefs_notifier_list); | 41 | static void rpc_purge_list(struct rpc_inode *rpci, struct list_head *head, |
48 | |||
49 | int rpc_pipefs_notifier_register(struct notifier_block *nb) | ||
50 | { | ||
51 | return blocking_notifier_chain_cond_register(&rpc_pipefs_notifier_list, nb); | ||
52 | } | ||
53 | EXPORT_SYMBOL_GPL(rpc_pipefs_notifier_register); | ||
54 | |||
55 | void rpc_pipefs_notifier_unregister(struct notifier_block *nb) | ||
56 | { | ||
57 | blocking_notifier_chain_unregister(&rpc_pipefs_notifier_list, nb); | ||
58 | } | ||
59 | EXPORT_SYMBOL_GPL(rpc_pipefs_notifier_unregister); | ||
60 | |||
61 | static void rpc_purge_list(wait_queue_head_t *waitq, struct list_head *head, | ||
62 | void (*destroy_msg)(struct rpc_pipe_msg *), int err) | 42 | void (*destroy_msg)(struct rpc_pipe_msg *), int err) |
63 | { | 43 | { |
64 | struct rpc_pipe_msg *msg; | 44 | struct rpc_pipe_msg *msg; |
@@ -71,31 +51,30 @@ static void rpc_purge_list(wait_queue_head_t *waitq, struct list_head *head, | |||
71 | msg->errno = err; | 51 | msg->errno = err; |
72 | destroy_msg(msg); | 52 | destroy_msg(msg); |
73 | } while (!list_empty(head)); | 53 | } while (!list_empty(head)); |
74 | 54 | wake_up(&rpci->waitq); | |
75 | if (waitq) | ||
76 | wake_up(waitq); | ||
77 | } | 55 | } |
78 | 56 | ||
79 | static void | 57 | static void |
80 | rpc_timeout_upcall_queue(struct work_struct *work) | 58 | rpc_timeout_upcall_queue(struct work_struct *work) |
81 | { | 59 | { |
82 | LIST_HEAD(free_list); | 60 | LIST_HEAD(free_list); |
83 | struct rpc_pipe *pipe = | 61 | struct rpc_inode *rpci = |
84 | container_of(work, struct rpc_pipe, queue_timeout.work); | 62 | container_of(work, struct rpc_inode, queue_timeout.work); |
63 | struct inode *inode = &rpci->vfs_inode; | ||
85 | void (*destroy_msg)(struct rpc_pipe_msg *); | 64 | void (*destroy_msg)(struct rpc_pipe_msg *); |
86 | struct dentry *dentry; | ||
87 | 65 | ||
88 | spin_lock(&pipe->lock); | 66 | spin_lock(&inode->i_lock); |
89 | destroy_msg = pipe->ops->destroy_msg; | 67 | if (rpci->ops == NULL) { |
90 | if (pipe->nreaders == 0) { | 68 | spin_unlock(&inode->i_lock); |
91 | list_splice_init(&pipe->pipe, &free_list); | 69 | return; |
92 | pipe->pipelen = 0; | ||
93 | } | 70 | } |
94 | dentry = dget(pipe->dentry); | 71 | destroy_msg = rpci->ops->destroy_msg; |
95 | spin_unlock(&pipe->lock); | 72 | if (rpci->nreaders == 0) { |
96 | rpc_purge_list(dentry ? &RPC_I(dentry->d_inode)->waitq : NULL, | 73 | list_splice_init(&rpci->pipe, &free_list); |
97 | &free_list, destroy_msg, -ETIMEDOUT); | 74 | rpci->pipelen = 0; |
98 | dput(dentry); | 75 | } |
76 | spin_unlock(&inode->i_lock); | ||
77 | rpc_purge_list(rpci, &free_list, destroy_msg, -ETIMEDOUT); | ||
99 | } | 78 | } |
100 | 79 | ||
101 | ssize_t rpc_pipe_generic_upcall(struct file *filp, struct rpc_pipe_msg *msg, | 80 | ssize_t rpc_pipe_generic_upcall(struct file *filp, struct rpc_pipe_msg *msg, |
@@ -120,7 +99,7 @@ EXPORT_SYMBOL_GPL(rpc_pipe_generic_upcall); | |||
120 | 99 | ||
121 | /** | 100 | /** |
122 | * rpc_queue_upcall - queue an upcall message to userspace | 101 | * rpc_queue_upcall - queue an upcall message to userspace |
123 | * @pipe: upcall pipe on which to queue given message | 102 | * @inode: inode of upcall pipe on which to queue given message |
124 | * @msg: message to queue | 103 | * @msg: message to queue |
125 | * | 104 | * |
126 | * Call with an @inode created by rpc_mkpipe() to queue an upcall. | 105 | * Call with an @inode created by rpc_mkpipe() to queue an upcall. |
@@ -129,31 +108,30 @@ EXPORT_SYMBOL_GPL(rpc_pipe_generic_upcall); | |||
129 | * initialize the fields of @msg (other than @msg->list) appropriately. | 108 | * initialize the fields of @msg (other than @msg->list) appropriately. |
130 | */ | 109 | */ |
131 | int | 110 | int |
132 | rpc_queue_upcall(struct rpc_pipe *pipe, struct rpc_pipe_msg *msg) | 111 | rpc_queue_upcall(struct inode *inode, struct rpc_pipe_msg *msg) |
133 | { | 112 | { |
113 | struct rpc_inode *rpci = RPC_I(inode); | ||
134 | int res = -EPIPE; | 114 | int res = -EPIPE; |
135 | struct dentry *dentry; | ||
136 | 115 | ||
137 | spin_lock(&pipe->lock); | 116 | spin_lock(&inode->i_lock); |
138 | if (pipe->nreaders) { | 117 | if (rpci->ops == NULL) |
139 | list_add_tail(&msg->list, &pipe->pipe); | 118 | goto out; |
140 | pipe->pipelen += msg->len; | 119 | if (rpci->nreaders) { |
120 | list_add_tail(&msg->list, &rpci->pipe); | ||
121 | rpci->pipelen += msg->len; | ||
141 | res = 0; | 122 | res = 0; |
142 | } else if (pipe->flags & RPC_PIPE_WAIT_FOR_OPEN) { | 123 | } else if (rpci->flags & RPC_PIPE_WAIT_FOR_OPEN) { |
143 | if (list_empty(&pipe->pipe)) | 124 | if (list_empty(&rpci->pipe)) |
144 | queue_delayed_work(rpciod_workqueue, | 125 | queue_delayed_work(rpciod_workqueue, |
145 | &pipe->queue_timeout, | 126 | &rpci->queue_timeout, |
146 | RPC_UPCALL_TIMEOUT); | 127 | RPC_UPCALL_TIMEOUT); |
147 | list_add_tail(&msg->list, &pipe->pipe); | 128 | list_add_tail(&msg->list, &rpci->pipe); |
148 | pipe->pipelen += msg->len; | 129 | rpci->pipelen += msg->len; |
149 | res = 0; | 130 | res = 0; |
150 | } | 131 | } |
151 | dentry = dget(pipe->dentry); | 132 | out: |
152 | spin_unlock(&pipe->lock); | 133 | spin_unlock(&inode->i_lock); |
153 | if (dentry) { | 134 | wake_up(&rpci->waitq); |
154 | wake_up(&RPC_I(dentry->d_inode)->waitq); | ||
155 | dput(dentry); | ||
156 | } | ||
157 | return res; | 135 | return res; |
158 | } | 136 | } |
159 | EXPORT_SYMBOL_GPL(rpc_queue_upcall); | 137 | EXPORT_SYMBOL_GPL(rpc_queue_upcall); |
@@ -167,26 +145,29 @@ rpc_inode_setowner(struct inode *inode, void *private) | |||
167 | static void | 145 | static void |
168 | rpc_close_pipes(struct inode *inode) | 146 | rpc_close_pipes(struct inode *inode) |
169 | { | 147 | { |
170 | struct rpc_pipe *pipe = RPC_I(inode)->pipe; | 148 | struct rpc_inode *rpci = RPC_I(inode); |
149 | const struct rpc_pipe_ops *ops; | ||
171 | int need_release; | 150 | int need_release; |
172 | LIST_HEAD(free_list); | ||
173 | 151 | ||
174 | mutex_lock(&inode->i_mutex); | 152 | mutex_lock(&inode->i_mutex); |
175 | spin_lock(&pipe->lock); | 153 | ops = rpci->ops; |
176 | need_release = pipe->nreaders != 0 || pipe->nwriters != 0; | 154 | if (ops != NULL) { |
177 | pipe->nreaders = 0; | 155 | LIST_HEAD(free_list); |
178 | list_splice_init(&pipe->in_upcall, &free_list); | 156 | spin_lock(&inode->i_lock); |
179 | list_splice_init(&pipe->pipe, &free_list); | 157 | need_release = rpci->nreaders != 0 || rpci->nwriters != 0; |
180 | pipe->pipelen = 0; | 158 | rpci->nreaders = 0; |
181 | pipe->dentry = NULL; | 159 | list_splice_init(&rpci->in_upcall, &free_list); |
182 | spin_unlock(&pipe->lock); | 160 | list_splice_init(&rpci->pipe, &free_list); |
183 | rpc_purge_list(&RPC_I(inode)->waitq, &free_list, pipe->ops->destroy_msg, -EPIPE); | 161 | rpci->pipelen = 0; |
184 | pipe->nwriters = 0; | 162 | rpci->ops = NULL; |
185 | if (need_release && pipe->ops->release_pipe) | 163 | spin_unlock(&inode->i_lock); |
186 | pipe->ops->release_pipe(inode); | 164 | rpc_purge_list(rpci, &free_list, ops->destroy_msg, -EPIPE); |
187 | cancel_delayed_work_sync(&pipe->queue_timeout); | 165 | rpci->nwriters = 0; |
166 | if (need_release && ops->release_pipe) | ||
167 | ops->release_pipe(inode); | ||
168 | cancel_delayed_work_sync(&rpci->queue_timeout); | ||
169 | } | ||
188 | rpc_inode_setowner(inode, NULL); | 170 | rpc_inode_setowner(inode, NULL); |
189 | RPC_I(inode)->pipe = NULL; | ||
190 | mutex_unlock(&inode->i_mutex); | 171 | mutex_unlock(&inode->i_mutex); |
191 | } | 172 | } |
192 | 173 | ||
@@ -204,6 +185,7 @@ static void | |||
204 | rpc_i_callback(struct rcu_head *head) | 185 | rpc_i_callback(struct rcu_head *head) |
205 | { | 186 | { |
206 | struct inode *inode = container_of(head, struct inode, i_rcu); | 187 | struct inode *inode = container_of(head, struct inode, i_rcu); |
188 | INIT_LIST_HEAD(&inode->i_dentry); | ||
207 | kmem_cache_free(rpc_inode_cachep, RPC_I(inode)); | 189 | kmem_cache_free(rpc_inode_cachep, RPC_I(inode)); |
208 | } | 190 | } |
209 | 191 | ||
@@ -216,24 +198,23 @@ rpc_destroy_inode(struct inode *inode) | |||
216 | static int | 198 | static int |
217 | rpc_pipe_open(struct inode *inode, struct file *filp) | 199 | rpc_pipe_open(struct inode *inode, struct file *filp) |
218 | { | 200 | { |
219 | struct rpc_pipe *pipe; | 201 | struct rpc_inode *rpci = RPC_I(inode); |
220 | int first_open; | 202 | int first_open; |
221 | int res = -ENXIO; | 203 | int res = -ENXIO; |
222 | 204 | ||
223 | mutex_lock(&inode->i_mutex); | 205 | mutex_lock(&inode->i_mutex); |
224 | pipe = RPC_I(inode)->pipe; | 206 | if (rpci->ops == NULL) |
225 | if (pipe == NULL) | ||
226 | goto out; | 207 | goto out; |
227 | first_open = pipe->nreaders == 0 && pipe->nwriters == 0; | 208 | first_open = rpci->nreaders == 0 && rpci->nwriters == 0; |
228 | if (first_open && pipe->ops->open_pipe) { | 209 | if (first_open && rpci->ops->open_pipe) { |
229 | res = pipe->ops->open_pipe(inode); | 210 | res = rpci->ops->open_pipe(inode); |
230 | if (res) | 211 | if (res) |
231 | goto out; | 212 | goto out; |
232 | } | 213 | } |
233 | if (filp->f_mode & FMODE_READ) | 214 | if (filp->f_mode & FMODE_READ) |
234 | pipe->nreaders++; | 215 | rpci->nreaders++; |
235 | if (filp->f_mode & FMODE_WRITE) | 216 | if (filp->f_mode & FMODE_WRITE) |
236 | pipe->nwriters++; | 217 | rpci->nwriters++; |
237 | res = 0; | 218 | res = 0; |
238 | out: | 219 | out: |
239 | mutex_unlock(&inode->i_mutex); | 220 | mutex_unlock(&inode->i_mutex); |
@@ -243,39 +224,38 @@ out: | |||
243 | static int | 224 | static int |
244 | rpc_pipe_release(struct inode *inode, struct file *filp) | 225 | rpc_pipe_release(struct inode *inode, struct file *filp) |
245 | { | 226 | { |
246 | struct rpc_pipe *pipe; | 227 | struct rpc_inode *rpci = RPC_I(inode); |
247 | struct rpc_pipe_msg *msg; | 228 | struct rpc_pipe_msg *msg; |
248 | int last_close; | 229 | int last_close; |
249 | 230 | ||
250 | mutex_lock(&inode->i_mutex); | 231 | mutex_lock(&inode->i_mutex); |
251 | pipe = RPC_I(inode)->pipe; | 232 | if (rpci->ops == NULL) |
252 | if (pipe == NULL) | ||
253 | goto out; | 233 | goto out; |
254 | msg = filp->private_data; | 234 | msg = filp->private_data; |
255 | if (msg != NULL) { | 235 | if (msg != NULL) { |
256 | spin_lock(&pipe->lock); | 236 | spin_lock(&inode->i_lock); |
257 | msg->errno = -EAGAIN; | 237 | msg->errno = -EAGAIN; |
258 | list_del_init(&msg->list); | 238 | list_del_init(&msg->list); |
259 | spin_unlock(&pipe->lock); | 239 | spin_unlock(&inode->i_lock); |
260 | pipe->ops->destroy_msg(msg); | 240 | rpci->ops->destroy_msg(msg); |
261 | } | 241 | } |
262 | if (filp->f_mode & FMODE_WRITE) | 242 | if (filp->f_mode & FMODE_WRITE) |
263 | pipe->nwriters --; | 243 | rpci->nwriters --; |
264 | if (filp->f_mode & FMODE_READ) { | 244 | if (filp->f_mode & FMODE_READ) { |
265 | pipe->nreaders --; | 245 | rpci->nreaders --; |
266 | if (pipe->nreaders == 0) { | 246 | if (rpci->nreaders == 0) { |
267 | LIST_HEAD(free_list); | 247 | LIST_HEAD(free_list); |
268 | spin_lock(&pipe->lock); | 248 | spin_lock(&inode->i_lock); |
269 | list_splice_init(&pipe->pipe, &free_list); | 249 | list_splice_init(&rpci->pipe, &free_list); |
270 | pipe->pipelen = 0; | 250 | rpci->pipelen = 0; |
271 | spin_unlock(&pipe->lock); | 251 | spin_unlock(&inode->i_lock); |
272 | rpc_purge_list(&RPC_I(inode)->waitq, &free_list, | 252 | rpc_purge_list(rpci, &free_list, |
273 | pipe->ops->destroy_msg, -EAGAIN); | 253 | rpci->ops->destroy_msg, -EAGAIN); |
274 | } | 254 | } |
275 | } | 255 | } |
276 | last_close = pipe->nwriters == 0 && pipe->nreaders == 0; | 256 | last_close = rpci->nwriters == 0 && rpci->nreaders == 0; |
277 | if (last_close && pipe->ops->release_pipe) | 257 | if (last_close && rpci->ops->release_pipe) |
278 | pipe->ops->release_pipe(inode); | 258 | rpci->ops->release_pipe(inode); |
279 | out: | 259 | out: |
280 | mutex_unlock(&inode->i_mutex); | 260 | mutex_unlock(&inode->i_mutex); |
281 | return 0; | 261 | return 0; |
@@ -285,40 +265,39 @@ static ssize_t | |||
285 | rpc_pipe_read(struct file *filp, char __user *buf, size_t len, loff_t *offset) | 265 | rpc_pipe_read(struct file *filp, char __user *buf, size_t len, loff_t *offset) |
286 | { | 266 | { |
287 | struct inode *inode = filp->f_path.dentry->d_inode; | 267 | struct inode *inode = filp->f_path.dentry->d_inode; |
288 | struct rpc_pipe *pipe; | 268 | struct rpc_inode *rpci = RPC_I(inode); |
289 | struct rpc_pipe_msg *msg; | 269 | struct rpc_pipe_msg *msg; |
290 | int res = 0; | 270 | int res = 0; |
291 | 271 | ||
292 | mutex_lock(&inode->i_mutex); | 272 | mutex_lock(&inode->i_mutex); |
293 | pipe = RPC_I(inode)->pipe; | 273 | if (rpci->ops == NULL) { |
294 | if (pipe == NULL) { | ||
295 | res = -EPIPE; | 274 | res = -EPIPE; |
296 | goto out_unlock; | 275 | goto out_unlock; |
297 | } | 276 | } |
298 | msg = filp->private_data; | 277 | msg = filp->private_data; |
299 | if (msg == NULL) { | 278 | if (msg == NULL) { |
300 | spin_lock(&pipe->lock); | 279 | spin_lock(&inode->i_lock); |
301 | if (!list_empty(&pipe->pipe)) { | 280 | if (!list_empty(&rpci->pipe)) { |
302 | msg = list_entry(pipe->pipe.next, | 281 | msg = list_entry(rpci->pipe.next, |
303 | struct rpc_pipe_msg, | 282 | struct rpc_pipe_msg, |
304 | list); | 283 | list); |
305 | list_move(&msg->list, &pipe->in_upcall); | 284 | list_move(&msg->list, &rpci->in_upcall); |
306 | pipe->pipelen -= msg->len; | 285 | rpci->pipelen -= msg->len; |
307 | filp->private_data = msg; | 286 | filp->private_data = msg; |
308 | msg->copied = 0; | 287 | msg->copied = 0; |
309 | } | 288 | } |
310 | spin_unlock(&pipe->lock); | 289 | spin_unlock(&inode->i_lock); |
311 | if (msg == NULL) | 290 | if (msg == NULL) |
312 | goto out_unlock; | 291 | goto out_unlock; |
313 | } | 292 | } |
314 | /* NOTE: it is up to the callback to update msg->copied */ | 293 | /* NOTE: it is up to the callback to update msg->copied */ |
315 | res = pipe->ops->upcall(filp, msg, buf, len); | 294 | res = rpci->ops->upcall(filp, msg, buf, len); |
316 | if (res < 0 || msg->len == msg->copied) { | 295 | if (res < 0 || msg->len == msg->copied) { |
317 | filp->private_data = NULL; | 296 | filp->private_data = NULL; |
318 | spin_lock(&pipe->lock); | 297 | spin_lock(&inode->i_lock); |
319 | list_del_init(&msg->list); | 298 | list_del_init(&msg->list); |
320 | spin_unlock(&pipe->lock); | 299 | spin_unlock(&inode->i_lock); |
321 | pipe->ops->destroy_msg(msg); | 300 | rpci->ops->destroy_msg(msg); |
322 | } | 301 | } |
323 | out_unlock: | 302 | out_unlock: |
324 | mutex_unlock(&inode->i_mutex); | 303 | mutex_unlock(&inode->i_mutex); |
@@ -329,12 +308,13 @@ static ssize_t | |||
329 | rpc_pipe_write(struct file *filp, const char __user *buf, size_t len, loff_t *offset) | 308 | rpc_pipe_write(struct file *filp, const char __user *buf, size_t len, loff_t *offset) |
330 | { | 309 | { |
331 | struct inode *inode = filp->f_path.dentry->d_inode; | 310 | struct inode *inode = filp->f_path.dentry->d_inode; |
311 | struct rpc_inode *rpci = RPC_I(inode); | ||
332 | int res; | 312 | int res; |
333 | 313 | ||
334 | mutex_lock(&inode->i_mutex); | 314 | mutex_lock(&inode->i_mutex); |
335 | res = -EPIPE; | 315 | res = -EPIPE; |
336 | if (RPC_I(inode)->pipe != NULL) | 316 | if (rpci->ops != NULL) |
337 | res = RPC_I(inode)->pipe->ops->downcall(filp, buf, len); | 317 | res = rpci->ops->downcall(filp, buf, len); |
338 | mutex_unlock(&inode->i_mutex); | 318 | mutex_unlock(&inode->i_mutex); |
339 | return res; | 319 | return res; |
340 | } | 320 | } |
@@ -342,18 +322,17 @@ rpc_pipe_write(struct file *filp, const char __user *buf, size_t len, loff_t *of | |||
342 | static unsigned int | 322 | static unsigned int |
343 | rpc_pipe_poll(struct file *filp, struct poll_table_struct *wait) | 323 | rpc_pipe_poll(struct file *filp, struct poll_table_struct *wait) |
344 | { | 324 | { |
345 | struct inode *inode = filp->f_path.dentry->d_inode; | 325 | struct rpc_inode *rpci; |
346 | struct rpc_inode *rpci = RPC_I(inode); | 326 | unsigned int mask = 0; |
347 | unsigned int mask = POLLOUT | POLLWRNORM; | ||
348 | 327 | ||
328 | rpci = RPC_I(filp->f_path.dentry->d_inode); | ||
349 | poll_wait(filp, &rpci->waitq, wait); | 329 | poll_wait(filp, &rpci->waitq, wait); |
350 | 330 | ||
351 | mutex_lock(&inode->i_mutex); | 331 | mask = POLLOUT | POLLWRNORM; |
352 | if (rpci->pipe == NULL) | 332 | if (rpci->ops == NULL) |
353 | mask |= POLLERR | POLLHUP; | 333 | mask |= POLLERR | POLLHUP; |
354 | else if (filp->private_data || !list_empty(&rpci->pipe->pipe)) | 334 | if (filp->private_data || !list_empty(&rpci->pipe)) |
355 | mask |= POLLIN | POLLRDNORM; | 335 | mask |= POLLIN | POLLRDNORM; |
356 | mutex_unlock(&inode->i_mutex); | ||
357 | return mask; | 336 | return mask; |
358 | } | 337 | } |
359 | 338 | ||
@@ -361,26 +340,23 @@ static long | |||
361 | rpc_pipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | 340 | rpc_pipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
362 | { | 341 | { |
363 | struct inode *inode = filp->f_path.dentry->d_inode; | 342 | struct inode *inode = filp->f_path.dentry->d_inode; |
364 | struct rpc_pipe *pipe; | 343 | struct rpc_inode *rpci = RPC_I(inode); |
365 | int len; | 344 | int len; |
366 | 345 | ||
367 | switch (cmd) { | 346 | switch (cmd) { |
368 | case FIONREAD: | 347 | case FIONREAD: |
369 | mutex_lock(&inode->i_mutex); | 348 | spin_lock(&inode->i_lock); |
370 | pipe = RPC_I(inode)->pipe; | 349 | if (rpci->ops == NULL) { |
371 | if (pipe == NULL) { | 350 | spin_unlock(&inode->i_lock); |
372 | mutex_unlock(&inode->i_mutex); | ||
373 | return -EPIPE; | 351 | return -EPIPE; |
374 | } | 352 | } |
375 | spin_lock(&pipe->lock); | 353 | len = rpci->pipelen; |
376 | len = pipe->pipelen; | ||
377 | if (filp->private_data) { | 354 | if (filp->private_data) { |
378 | struct rpc_pipe_msg *msg; | 355 | struct rpc_pipe_msg *msg; |
379 | msg = filp->private_data; | 356 | msg = filp->private_data; |
380 | len += msg->len - msg->copied; | 357 | len += msg->len - msg->copied; |
381 | } | 358 | } |
382 | spin_unlock(&pipe->lock); | 359 | spin_unlock(&inode->i_lock); |
383 | mutex_unlock(&inode->i_mutex); | ||
384 | return put_user(len, (int __user *)arg); | 360 | return put_user(len, (int __user *)arg); |
385 | default: | 361 | default: |
386 | return -EINVAL; | 362 | return -EINVAL; |
@@ -403,15 +379,12 @@ rpc_show_info(struct seq_file *m, void *v) | |||
403 | { | 379 | { |
404 | struct rpc_clnt *clnt = m->private; | 380 | struct rpc_clnt *clnt = m->private; |
405 | 381 | ||
406 | rcu_read_lock(); | 382 | seq_printf(m, "RPC server: %s\n", clnt->cl_server); |
407 | seq_printf(m, "RPC server: %s\n", | ||
408 | rcu_dereference(clnt->cl_xprt)->servername); | ||
409 | seq_printf(m, "service: %s (%d) version %d\n", clnt->cl_protname, | 383 | seq_printf(m, "service: %s (%d) version %d\n", clnt->cl_protname, |
410 | clnt->cl_prog, clnt->cl_vers); | 384 | clnt->cl_prog, clnt->cl_vers); |
411 | seq_printf(m, "address: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_ADDR)); | 385 | seq_printf(m, "address: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_ADDR)); |
412 | seq_printf(m, "protocol: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_PROTO)); | 386 | seq_printf(m, "protocol: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_PROTO)); |
413 | seq_printf(m, "port: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_PORT)); | 387 | seq_printf(m, "port: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_PORT)); |
414 | rcu_read_unlock(); | ||
415 | return 0; | 388 | return 0; |
416 | } | 389 | } |
417 | 390 | ||
@@ -468,6 +441,23 @@ struct rpc_filelist { | |||
468 | umode_t mode; | 441 | umode_t mode; |
469 | }; | 442 | }; |
470 | 443 | ||
444 | struct vfsmount *rpc_get_mount(void) | ||
445 | { | ||
446 | int err; | ||
447 | |||
448 | err = simple_pin_fs(&rpc_pipe_fs_type, &rpc_mnt, &rpc_mount_count); | ||
449 | if (err != 0) | ||
450 | return ERR_PTR(err); | ||
451 | return rpc_mnt; | ||
452 | } | ||
453 | EXPORT_SYMBOL_GPL(rpc_get_mount); | ||
454 | |||
455 | void rpc_put_mount(void) | ||
456 | { | ||
457 | simple_release_fs(&rpc_mnt, &rpc_mount_count); | ||
458 | } | ||
459 | EXPORT_SYMBOL_GPL(rpc_put_mount); | ||
460 | |||
471 | static int rpc_delete_dentry(const struct dentry *dentry) | 461 | static int rpc_delete_dentry(const struct dentry *dentry) |
472 | { | 462 | { |
473 | return 1; | 463 | return 1; |
@@ -551,47 +541,12 @@ static int __rpc_mkdir(struct inode *dir, struct dentry *dentry, | |||
551 | return 0; | 541 | return 0; |
552 | } | 542 | } |
553 | 543 | ||
554 | static void | 544 | static int __rpc_mkpipe(struct inode *dir, struct dentry *dentry, |
555 | init_pipe(struct rpc_pipe *pipe) | 545 | umode_t mode, |
556 | { | 546 | const struct file_operations *i_fop, |
557 | pipe->nreaders = 0; | 547 | void *private, |
558 | pipe->nwriters = 0; | 548 | const struct rpc_pipe_ops *ops, |
559 | INIT_LIST_HEAD(&pipe->in_upcall); | 549 | int flags) |
560 | INIT_LIST_HEAD(&pipe->in_downcall); | ||
561 | INIT_LIST_HEAD(&pipe->pipe); | ||
562 | pipe->pipelen = 0; | ||
563 | INIT_DELAYED_WORK(&pipe->queue_timeout, | ||
564 | rpc_timeout_upcall_queue); | ||
565 | pipe->ops = NULL; | ||
566 | spin_lock_init(&pipe->lock); | ||
567 | pipe->dentry = NULL; | ||
568 | } | ||
569 | |||
570 | void rpc_destroy_pipe_data(struct rpc_pipe *pipe) | ||
571 | { | ||
572 | kfree(pipe); | ||
573 | } | ||
574 | EXPORT_SYMBOL_GPL(rpc_destroy_pipe_data); | ||
575 | |||
576 | struct rpc_pipe *rpc_mkpipe_data(const struct rpc_pipe_ops *ops, int flags) | ||
577 | { | ||
578 | struct rpc_pipe *pipe; | ||
579 | |||
580 | pipe = kzalloc(sizeof(struct rpc_pipe), GFP_KERNEL); | ||
581 | if (!pipe) | ||
582 | return ERR_PTR(-ENOMEM); | ||
583 | init_pipe(pipe); | ||
584 | pipe->ops = ops; | ||
585 | pipe->flags = flags; | ||
586 | return pipe; | ||
587 | } | ||
588 | EXPORT_SYMBOL_GPL(rpc_mkpipe_data); | ||
589 | |||
590 | static int __rpc_mkpipe_dentry(struct inode *dir, struct dentry *dentry, | ||
591 | umode_t mode, | ||
592 | const struct file_operations *i_fop, | ||
593 | void *private, | ||
594 | struct rpc_pipe *pipe) | ||
595 | { | 550 | { |
596 | struct rpc_inode *rpci; | 551 | struct rpc_inode *rpci; |
597 | int err; | 552 | int err; |
@@ -600,8 +555,10 @@ static int __rpc_mkpipe_dentry(struct inode *dir, struct dentry *dentry, | |||
600 | if (err) | 555 | if (err) |
601 | return err; | 556 | return err; |
602 | rpci = RPC_I(dentry->d_inode); | 557 | rpci = RPC_I(dentry->d_inode); |
558 | rpci->nkern_readwriters = 1; | ||
603 | rpci->private = private; | 559 | rpci->private = private; |
604 | rpci->pipe = pipe; | 560 | rpci->flags = flags; |
561 | rpci->ops = ops; | ||
605 | fsnotify_create(dir, dentry); | 562 | fsnotify_create(dir, dentry); |
606 | return 0; | 563 | return 0; |
607 | } | 564 | } |
@@ -617,22 +574,6 @@ static int __rpc_rmdir(struct inode *dir, struct dentry *dentry) | |||
617 | return ret; | 574 | return ret; |
618 | } | 575 | } |
619 | 576 | ||
620 | int rpc_rmdir(struct dentry *dentry) | ||
621 | { | ||
622 | struct dentry *parent; | ||
623 | struct inode *dir; | ||
624 | int error; | ||
625 | |||
626 | parent = dget_parent(dentry); | ||
627 | dir = parent->d_inode; | ||
628 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); | ||
629 | error = __rpc_rmdir(dir, dentry); | ||
630 | mutex_unlock(&dir->i_mutex); | ||
631 | dput(parent); | ||
632 | return error; | ||
633 | } | ||
634 | EXPORT_SYMBOL_GPL(rpc_rmdir); | ||
635 | |||
636 | static int __rpc_unlink(struct inode *dir, struct dentry *dentry) | 577 | static int __rpc_unlink(struct inode *dir, struct dentry *dentry) |
637 | { | 578 | { |
638 | int ret; | 579 | int ret; |
@@ -647,12 +588,16 @@ static int __rpc_unlink(struct inode *dir, struct dentry *dentry) | |||
647 | static int __rpc_rmpipe(struct inode *dir, struct dentry *dentry) | 588 | static int __rpc_rmpipe(struct inode *dir, struct dentry *dentry) |
648 | { | 589 | { |
649 | struct inode *inode = dentry->d_inode; | 590 | struct inode *inode = dentry->d_inode; |
591 | struct rpc_inode *rpci = RPC_I(inode); | ||
650 | 592 | ||
593 | rpci->nkern_readwriters--; | ||
594 | if (rpci->nkern_readwriters != 0) | ||
595 | return 0; | ||
651 | rpc_close_pipes(inode); | 596 | rpc_close_pipes(inode); |
652 | return __rpc_unlink(dir, dentry); | 597 | return __rpc_unlink(dir, dentry); |
653 | } | 598 | } |
654 | 599 | ||
655 | static struct dentry *__rpc_lookup_create_exclusive(struct dentry *parent, | 600 | static struct dentry *__rpc_lookup_create(struct dentry *parent, |
656 | struct qstr *name) | 601 | struct qstr *name) |
657 | { | 602 | { |
658 | struct dentry *dentry; | 603 | struct dentry *dentry; |
@@ -660,13 +605,27 @@ static struct dentry *__rpc_lookup_create_exclusive(struct dentry *parent, | |||
660 | dentry = d_lookup(parent, name); | 605 | dentry = d_lookup(parent, name); |
661 | if (!dentry) { | 606 | if (!dentry) { |
662 | dentry = d_alloc(parent, name); | 607 | dentry = d_alloc(parent, name); |
663 | if (!dentry) | 608 | if (!dentry) { |
664 | return ERR_PTR(-ENOMEM); | 609 | dentry = ERR_PTR(-ENOMEM); |
610 | goto out_err; | ||
611 | } | ||
665 | } | 612 | } |
666 | if (dentry->d_inode == NULL) { | 613 | if (!dentry->d_inode) |
667 | d_set_d_op(dentry, &rpc_dentry_operations); | 614 | d_set_d_op(dentry, &rpc_dentry_operations); |
615 | out_err: | ||
616 | return dentry; | ||
617 | } | ||
618 | |||
619 | static struct dentry *__rpc_lookup_create_exclusive(struct dentry *parent, | ||
620 | struct qstr *name) | ||
621 | { | ||
622 | struct dentry *dentry; | ||
623 | |||
624 | dentry = __rpc_lookup_create(parent, name); | ||
625 | if (IS_ERR(dentry)) | ||
626 | return dentry; | ||
627 | if (dentry->d_inode == NULL) | ||
668 | return dentry; | 628 | return dentry; |
669 | } | ||
670 | dput(dentry); | 629 | dput(dentry); |
671 | return ERR_PTR(-EEXIST); | 630 | return ERR_PTR(-EEXIST); |
672 | } | 631 | } |
@@ -819,7 +778,9 @@ static int rpc_rmdir_depopulate(struct dentry *dentry, | |||
819 | * @parent: dentry of directory to create new "pipe" in | 778 | * @parent: dentry of directory to create new "pipe" in |
820 | * @name: name of pipe | 779 | * @name: name of pipe |
821 | * @private: private data to associate with the pipe, for the caller's use | 780 | * @private: private data to associate with the pipe, for the caller's use |
822 | * @pipe: &rpc_pipe containing input parameters | 781 | * @ops: operations defining the behavior of the pipe: upcall, downcall, |
782 | * release_pipe, open_pipe, and destroy_msg. | ||
783 | * @flags: rpc_inode flags | ||
823 | * | 784 | * |
824 | * Data is made available for userspace to read by calls to | 785 | * Data is made available for userspace to read by calls to |
825 | * rpc_queue_upcall(). The actual reads will result in calls to | 786 | * rpc_queue_upcall(). The actual reads will result in calls to |
@@ -832,8 +793,9 @@ static int rpc_rmdir_depopulate(struct dentry *dentry, | |||
832 | * The @private argument passed here will be available to all these methods | 793 | * The @private argument passed here will be available to all these methods |
833 | * from the file pointer, via RPC_I(file->f_dentry->d_inode)->private. | 794 | * from the file pointer, via RPC_I(file->f_dentry->d_inode)->private. |
834 | */ | 795 | */ |
835 | struct dentry *rpc_mkpipe_dentry(struct dentry *parent, const char *name, | 796 | struct dentry *rpc_mkpipe(struct dentry *parent, const char *name, |
836 | void *private, struct rpc_pipe *pipe) | 797 | void *private, const struct rpc_pipe_ops *ops, |
798 | int flags) | ||
837 | { | 799 | { |
838 | struct dentry *dentry; | 800 | struct dentry *dentry; |
839 | struct inode *dir = parent->d_inode; | 801 | struct inode *dir = parent->d_inode; |
@@ -841,9 +803,9 @@ struct dentry *rpc_mkpipe_dentry(struct dentry *parent, const char *name, | |||
841 | struct qstr q; | 803 | struct qstr q; |
842 | int err; | 804 | int err; |
843 | 805 | ||
844 | if (pipe->ops->upcall == NULL) | 806 | if (ops->upcall == NULL) |
845 | umode &= ~S_IRUGO; | 807 | umode &= ~S_IRUGO; |
846 | if (pipe->ops->downcall == NULL) | 808 | if (ops->downcall == NULL) |
847 | umode &= ~S_IWUGO; | 809 | umode &= ~S_IWUGO; |
848 | 810 | ||
849 | q.name = name; | 811 | q.name = name; |
@@ -851,11 +813,24 @@ struct dentry *rpc_mkpipe_dentry(struct dentry *parent, const char *name, | |||
851 | q.hash = full_name_hash(q.name, q.len), | 813 | q.hash = full_name_hash(q.name, q.len), |
852 | 814 | ||
853 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); | 815 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); |
854 | dentry = __rpc_lookup_create_exclusive(parent, &q); | 816 | dentry = __rpc_lookup_create(parent, &q); |
855 | if (IS_ERR(dentry)) | 817 | if (IS_ERR(dentry)) |
856 | goto out; | 818 | goto out; |
857 | err = __rpc_mkpipe_dentry(dir, dentry, umode, &rpc_pipe_fops, | 819 | if (dentry->d_inode) { |
858 | private, pipe); | 820 | struct rpc_inode *rpci = RPC_I(dentry->d_inode); |
821 | if (rpci->private != private || | ||
822 | rpci->ops != ops || | ||
823 | rpci->flags != flags) { | ||
824 | dput (dentry); | ||
825 | err = -EBUSY; | ||
826 | goto out_err; | ||
827 | } | ||
828 | rpci->nkern_readwriters++; | ||
829 | goto out; | ||
830 | } | ||
831 | |||
832 | err = __rpc_mkpipe(dir, dentry, umode, &rpc_pipe_fops, | ||
833 | private, ops, flags); | ||
859 | if (err) | 834 | if (err) |
860 | goto out_err; | 835 | goto out_err; |
861 | out: | 836 | out: |
@@ -868,7 +843,7 @@ out_err: | |||
868 | err); | 843 | err); |
869 | goto out; | 844 | goto out; |
870 | } | 845 | } |
871 | EXPORT_SYMBOL_GPL(rpc_mkpipe_dentry); | 846 | EXPORT_SYMBOL_GPL(rpc_mkpipe); |
872 | 847 | ||
873 | /** | 848 | /** |
874 | * rpc_unlink - remove a pipe | 849 | * rpc_unlink - remove a pipe |
@@ -941,7 +916,7 @@ struct dentry *rpc_create_client_dir(struct dentry *dentry, | |||
941 | 916 | ||
942 | /** | 917 | /** |
943 | * rpc_remove_client_dir - Remove a directory created with rpc_create_client_dir() | 918 | * rpc_remove_client_dir - Remove a directory created with rpc_create_client_dir() |
944 | * @dentry: dentry for the pipe | 919 | * @dentry: directory to remove |
945 | */ | 920 | */ |
946 | int rpc_remove_client_dir(struct dentry *dentry) | 921 | int rpc_remove_client_dir(struct dentry *dentry) |
947 | { | 922 | { |
@@ -979,7 +954,7 @@ static void rpc_cachedir_depopulate(struct dentry *dentry) | |||
979 | } | 954 | } |
980 | 955 | ||
981 | struct dentry *rpc_create_cache_dir(struct dentry *parent, struct qstr *name, | 956 | struct dentry *rpc_create_cache_dir(struct dentry *parent, struct qstr *name, |
982 | umode_t umode, struct cache_detail *cd) | 957 | mode_t umode, struct cache_detail *cd) |
983 | { | 958 | { |
984 | return rpc_mkdir_populate(parent, name, umode, NULL, | 959 | return rpc_mkdir_populate(parent, name, umode, NULL, |
985 | rpc_cachedir_populate, cd); | 960 | rpc_cachedir_populate, cd); |
@@ -1012,7 +987,6 @@ enum { | |||
1012 | RPCAUTH_statd, | 987 | RPCAUTH_statd, |
1013 | RPCAUTH_nfsd4_cb, | 988 | RPCAUTH_nfsd4_cb, |
1014 | RPCAUTH_cache, | 989 | RPCAUTH_cache, |
1015 | RPCAUTH_nfsd, | ||
1016 | RPCAUTH_RootEOF | 990 | RPCAUTH_RootEOF |
1017 | }; | 991 | }; |
1018 | 992 | ||
@@ -1045,67 +1019,13 @@ static const struct rpc_filelist files[] = { | |||
1045 | .name = "cache", | 1019 | .name = "cache", |
1046 | .mode = S_IFDIR | S_IRUGO | S_IXUGO, | 1020 | .mode = S_IFDIR | S_IRUGO | S_IXUGO, |
1047 | }, | 1021 | }, |
1048 | [RPCAUTH_nfsd] = { | ||
1049 | .name = "nfsd", | ||
1050 | .mode = S_IFDIR | S_IRUGO | S_IXUGO, | ||
1051 | }, | ||
1052 | }; | 1022 | }; |
1053 | 1023 | ||
1054 | /* | ||
1055 | * This call can be used only in RPC pipefs mount notification hooks. | ||
1056 | */ | ||
1057 | struct dentry *rpc_d_lookup_sb(const struct super_block *sb, | ||
1058 | const unsigned char *dir_name) | ||
1059 | { | ||
1060 | struct qstr dir = QSTR_INIT(dir_name, strlen(dir_name)); | ||
1061 | |||
1062 | dir.hash = full_name_hash(dir.name, dir.len); | ||
1063 | return d_lookup(sb->s_root, &dir); | ||
1064 | } | ||
1065 | EXPORT_SYMBOL_GPL(rpc_d_lookup_sb); | ||
1066 | |||
1067 | void rpc_pipefs_init_net(struct net *net) | ||
1068 | { | ||
1069 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
1070 | |||
1071 | mutex_init(&sn->pipefs_sb_lock); | ||
1072 | } | ||
1073 | |||
1074 | /* | ||
1075 | * This call will be used for per network namespace operations calls. | ||
1076 | * Note: Function will be returned with pipefs_sb_lock taken if superblock was | ||
1077 | * found. This lock have to be released by rpc_put_sb_net() when all operations | ||
1078 | * will be completed. | ||
1079 | */ | ||
1080 | struct super_block *rpc_get_sb_net(const struct net *net) | ||
1081 | { | ||
1082 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
1083 | |||
1084 | mutex_lock(&sn->pipefs_sb_lock); | ||
1085 | if (sn->pipefs_sb) | ||
1086 | return sn->pipefs_sb; | ||
1087 | mutex_unlock(&sn->pipefs_sb_lock); | ||
1088 | return NULL; | ||
1089 | } | ||
1090 | EXPORT_SYMBOL_GPL(rpc_get_sb_net); | ||
1091 | |||
1092 | void rpc_put_sb_net(const struct net *net) | ||
1093 | { | ||
1094 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
1095 | |||
1096 | WARN_ON(sn->pipefs_sb == NULL); | ||
1097 | mutex_unlock(&sn->pipefs_sb_lock); | ||
1098 | } | ||
1099 | EXPORT_SYMBOL_GPL(rpc_put_sb_net); | ||
1100 | |||
1101 | static int | 1024 | static int |
1102 | rpc_fill_super(struct super_block *sb, void *data, int silent) | 1025 | rpc_fill_super(struct super_block *sb, void *data, int silent) |
1103 | { | 1026 | { |
1104 | struct inode *inode; | 1027 | struct inode *inode; |
1105 | struct dentry *root; | 1028 | struct dentry *root; |
1106 | struct net *net = data; | ||
1107 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
1108 | int err; | ||
1109 | 1029 | ||
1110 | sb->s_blocksize = PAGE_CACHE_SIZE; | 1030 | sb->s_blocksize = PAGE_CACHE_SIZE; |
1111 | sb->s_blocksize_bits = PAGE_CACHE_SHIFT; | 1031 | sb->s_blocksize_bits = PAGE_CACHE_SHIFT; |
@@ -1113,66 +1033,31 @@ rpc_fill_super(struct super_block *sb, void *data, int silent) | |||
1113 | sb->s_op = &s_ops; | 1033 | sb->s_op = &s_ops; |
1114 | sb->s_time_gran = 1; | 1034 | sb->s_time_gran = 1; |
1115 | 1035 | ||
1116 | inode = rpc_get_inode(sb, S_IFDIR | S_IRUGO | S_IXUGO); | 1036 | inode = rpc_get_inode(sb, S_IFDIR | 0755); |
1117 | sb->s_root = root = d_make_root(inode); | 1037 | if (!inode) |
1118 | if (!root) | ||
1119 | return -ENOMEM; | 1038 | return -ENOMEM; |
1039 | sb->s_root = root = d_alloc_root(inode); | ||
1040 | if (!root) { | ||
1041 | iput(inode); | ||
1042 | return -ENOMEM; | ||
1043 | } | ||
1120 | if (rpc_populate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF, NULL)) | 1044 | if (rpc_populate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF, NULL)) |
1121 | return -ENOMEM; | 1045 | return -ENOMEM; |
1122 | dprintk("RPC: sending pipefs MOUNT notification for net %p%s\n", | ||
1123 | net, NET_NAME(net)); | ||
1124 | sn->pipefs_sb = sb; | ||
1125 | err = blocking_notifier_call_chain(&rpc_pipefs_notifier_list, | ||
1126 | RPC_PIPEFS_MOUNT, | ||
1127 | sb); | ||
1128 | if (err) | ||
1129 | goto err_depopulate; | ||
1130 | sb->s_fs_info = get_net(net); | ||
1131 | return 0; | 1046 | return 0; |
1132 | |||
1133 | err_depopulate: | ||
1134 | blocking_notifier_call_chain(&rpc_pipefs_notifier_list, | ||
1135 | RPC_PIPEFS_UMOUNT, | ||
1136 | sb); | ||
1137 | sn->pipefs_sb = NULL; | ||
1138 | __rpc_depopulate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF); | ||
1139 | return err; | ||
1140 | } | 1047 | } |
1141 | 1048 | ||
1142 | static struct dentry * | 1049 | static struct dentry * |
1143 | rpc_mount(struct file_system_type *fs_type, | 1050 | rpc_mount(struct file_system_type *fs_type, |
1144 | int flags, const char *dev_name, void *data) | 1051 | int flags, const char *dev_name, void *data) |
1145 | { | 1052 | { |
1146 | return mount_ns(fs_type, flags, current->nsproxy->net_ns, rpc_fill_super); | 1053 | return mount_single(fs_type, flags, data, rpc_fill_super); |
1147 | } | ||
1148 | |||
1149 | static void rpc_kill_sb(struct super_block *sb) | ||
1150 | { | ||
1151 | struct net *net = sb->s_fs_info; | ||
1152 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
1153 | |||
1154 | mutex_lock(&sn->pipefs_sb_lock); | ||
1155 | if (sn->pipefs_sb != sb) { | ||
1156 | mutex_unlock(&sn->pipefs_sb_lock); | ||
1157 | goto out; | ||
1158 | } | ||
1159 | sn->pipefs_sb = NULL; | ||
1160 | mutex_unlock(&sn->pipefs_sb_lock); | ||
1161 | dprintk("RPC: sending pipefs UMOUNT notification for net %p%s\n", | ||
1162 | net, NET_NAME(net)); | ||
1163 | blocking_notifier_call_chain(&rpc_pipefs_notifier_list, | ||
1164 | RPC_PIPEFS_UMOUNT, | ||
1165 | sb); | ||
1166 | put_net(net); | ||
1167 | out: | ||
1168 | kill_litter_super(sb); | ||
1169 | } | 1054 | } |
1170 | 1055 | ||
1171 | static struct file_system_type rpc_pipe_fs_type = { | 1056 | static struct file_system_type rpc_pipe_fs_type = { |
1172 | .owner = THIS_MODULE, | 1057 | .owner = THIS_MODULE, |
1173 | .name = "rpc_pipefs", | 1058 | .name = "rpc_pipefs", |
1174 | .mount = rpc_mount, | 1059 | .mount = rpc_mount, |
1175 | .kill_sb = rpc_kill_sb, | 1060 | .kill_sb = kill_litter_super, |
1176 | }; | 1061 | }; |
1177 | 1062 | ||
1178 | static void | 1063 | static void |
@@ -1182,8 +1067,16 @@ init_once(void *foo) | |||
1182 | 1067 | ||
1183 | inode_init_once(&rpci->vfs_inode); | 1068 | inode_init_once(&rpci->vfs_inode); |
1184 | rpci->private = NULL; | 1069 | rpci->private = NULL; |
1185 | rpci->pipe = NULL; | 1070 | rpci->nreaders = 0; |
1071 | rpci->nwriters = 0; | ||
1072 | INIT_LIST_HEAD(&rpci->in_upcall); | ||
1073 | INIT_LIST_HEAD(&rpci->in_downcall); | ||
1074 | INIT_LIST_HEAD(&rpci->pipe); | ||
1075 | rpci->pipelen = 0; | ||
1186 | init_waitqueue_head(&rpci->waitq); | 1076 | init_waitqueue_head(&rpci->waitq); |
1077 | INIT_DELAYED_WORK(&rpci->queue_timeout, | ||
1078 | rpc_timeout_upcall_queue); | ||
1079 | rpci->ops = NULL; | ||
1187 | } | 1080 | } |
1188 | 1081 | ||
1189 | int register_rpc_pipefs(void) | 1082 | int register_rpc_pipefs(void) |
@@ -1197,27 +1090,17 @@ int register_rpc_pipefs(void) | |||
1197 | init_once); | 1090 | init_once); |
1198 | if (!rpc_inode_cachep) | 1091 | if (!rpc_inode_cachep) |
1199 | return -ENOMEM; | 1092 | return -ENOMEM; |
1200 | err = rpc_clients_notifier_register(); | ||
1201 | if (err) | ||
1202 | goto err_notifier; | ||
1203 | err = register_filesystem(&rpc_pipe_fs_type); | 1093 | err = register_filesystem(&rpc_pipe_fs_type); |
1204 | if (err) | 1094 | if (err) { |
1205 | goto err_register; | 1095 | kmem_cache_destroy(rpc_inode_cachep); |
1206 | return 0; | 1096 | return err; |
1097 | } | ||
1207 | 1098 | ||
1208 | err_register: | 1099 | return 0; |
1209 | rpc_clients_notifier_unregister(); | ||
1210 | err_notifier: | ||
1211 | kmem_cache_destroy(rpc_inode_cachep); | ||
1212 | return err; | ||
1213 | } | 1100 | } |
1214 | 1101 | ||
1215 | void unregister_rpc_pipefs(void) | 1102 | void unregister_rpc_pipefs(void) |
1216 | { | 1103 | { |
1217 | rpc_clients_notifier_unregister(); | ||
1218 | kmem_cache_destroy(rpc_inode_cachep); | 1104 | kmem_cache_destroy(rpc_inode_cachep); |
1219 | unregister_filesystem(&rpc_pipe_fs_type); | 1105 | unregister_filesystem(&rpc_pipe_fs_type); |
1220 | } | 1106 | } |
1221 | |||
1222 | /* Make 'mount -t rpc_pipefs ...' autoload this module. */ | ||
1223 | MODULE_ALIAS("rpc_pipefs"); | ||
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index 795a0f4e920..e45d2fbbe5a 100644 --- a/net/sunrpc/rpcb_clnt.c +++ b/net/sunrpc/rpcb_clnt.c | |||
@@ -29,8 +29,6 @@ | |||
29 | #include <linux/sunrpc/sched.h> | 29 | #include <linux/sunrpc/sched.h> |
30 | #include <linux/sunrpc/xprtsock.h> | 30 | #include <linux/sunrpc/xprtsock.h> |
31 | 31 | ||
32 | #include "netns.h" | ||
33 | |||
34 | #ifdef RPC_DEBUG | 32 | #ifdef RPC_DEBUG |
35 | # define RPCDBG_FACILITY RPCDBG_BIND | 33 | # define RPCDBG_FACILITY RPCDBG_BIND |
36 | #endif | 34 | #endif |
@@ -111,7 +109,10 @@ enum { | |||
111 | 109 | ||
112 | static void rpcb_getport_done(struct rpc_task *, void *); | 110 | static void rpcb_getport_done(struct rpc_task *, void *); |
113 | static void rpcb_map_release(void *data); | 111 | static void rpcb_map_release(void *data); |
114 | static const struct rpc_program rpcb_program; | 112 | static struct rpc_program rpcb_program; |
113 | |||
114 | static struct rpc_clnt * rpcb_local_clnt; | ||
115 | static struct rpc_clnt * rpcb_local_clnt4; | ||
115 | 116 | ||
116 | struct rpcbind_args { | 117 | struct rpcbind_args { |
117 | struct rpc_xprt * r_xprt; | 118 | struct rpc_xprt * r_xprt; |
@@ -136,8 +137,8 @@ struct rpcb_info { | |||
136 | struct rpc_procinfo * rpc_proc; | 137 | struct rpc_procinfo * rpc_proc; |
137 | }; | 138 | }; |
138 | 139 | ||
139 | static const struct rpcb_info rpcb_next_version[]; | 140 | static struct rpcb_info rpcb_next_version[]; |
140 | static const struct rpcb_info rpcb_next_version6[]; | 141 | static struct rpcb_info rpcb_next_version6[]; |
141 | 142 | ||
142 | static const struct rpc_call_ops rpcb_getport_ops = { | 143 | static const struct rpc_call_ops rpcb_getport_ops = { |
143 | .rpc_call_done = rpcb_getport_done, | 144 | .rpc_call_done = rpcb_getport_done, |
@@ -160,76 +161,18 @@ static void rpcb_map_release(void *data) | |||
160 | kfree(map); | 161 | kfree(map); |
161 | } | 162 | } |
162 | 163 | ||
163 | static int rpcb_get_local(struct net *net) | ||
164 | { | ||
165 | int cnt; | ||
166 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
167 | |||
168 | spin_lock(&sn->rpcb_clnt_lock); | ||
169 | if (sn->rpcb_users) | ||
170 | sn->rpcb_users++; | ||
171 | cnt = sn->rpcb_users; | ||
172 | spin_unlock(&sn->rpcb_clnt_lock); | ||
173 | |||
174 | return cnt; | ||
175 | } | ||
176 | |||
177 | void rpcb_put_local(struct net *net) | ||
178 | { | ||
179 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
180 | struct rpc_clnt *clnt = sn->rpcb_local_clnt; | ||
181 | struct rpc_clnt *clnt4 = sn->rpcb_local_clnt4; | ||
182 | int shutdown = 0; | ||
183 | |||
184 | spin_lock(&sn->rpcb_clnt_lock); | ||
185 | if (sn->rpcb_users) { | ||
186 | if (--sn->rpcb_users == 0) { | ||
187 | sn->rpcb_local_clnt = NULL; | ||
188 | sn->rpcb_local_clnt4 = NULL; | ||
189 | } | ||
190 | shutdown = !sn->rpcb_users; | ||
191 | } | ||
192 | spin_unlock(&sn->rpcb_clnt_lock); | ||
193 | |||
194 | if (shutdown) { | ||
195 | /* | ||
196 | * cleanup_rpcb_clnt - remove xprtsock's sysctls, unregister | ||
197 | */ | ||
198 | if (clnt4) | ||
199 | rpc_shutdown_client(clnt4); | ||
200 | if (clnt) | ||
201 | rpc_shutdown_client(clnt); | ||
202 | } | ||
203 | } | ||
204 | |||
205 | static void rpcb_set_local(struct net *net, struct rpc_clnt *clnt, | ||
206 | struct rpc_clnt *clnt4) | ||
207 | { | ||
208 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
209 | |||
210 | /* Protected by rpcb_create_local_mutex */ | ||
211 | sn->rpcb_local_clnt = clnt; | ||
212 | sn->rpcb_local_clnt4 = clnt4; | ||
213 | smp_wmb(); | ||
214 | sn->rpcb_users = 1; | ||
215 | dprintk("RPC: created new rpcb local clients (rpcb_local_clnt: " | ||
216 | "%p, rpcb_local_clnt4: %p) for net %p%s\n", | ||
217 | sn->rpcb_local_clnt, sn->rpcb_local_clnt4, | ||
218 | net, (net == &init_net) ? " (init_net)" : ""); | ||
219 | } | ||
220 | |||
221 | /* | 164 | /* |
222 | * Returns zero on success, otherwise a negative errno value | 165 | * Returns zero on success, otherwise a negative errno value |
223 | * is returned. | 166 | * is returned. |
224 | */ | 167 | */ |
225 | static int rpcb_create_local_unix(struct net *net) | 168 | static int rpcb_create_local_unix(void) |
226 | { | 169 | { |
227 | static const struct sockaddr_un rpcb_localaddr_rpcbind = { | 170 | static const struct sockaddr_un rpcb_localaddr_rpcbind = { |
228 | .sun_family = AF_LOCAL, | 171 | .sun_family = AF_LOCAL, |
229 | .sun_path = RPCBIND_SOCK_PATHNAME, | 172 | .sun_path = RPCBIND_SOCK_PATHNAME, |
230 | }; | 173 | }; |
231 | struct rpc_create_args args = { | 174 | struct rpc_create_args args = { |
232 | .net = net, | 175 | .net = &init_net, |
233 | .protocol = XPRT_TRANSPORT_LOCAL, | 176 | .protocol = XPRT_TRANSPORT_LOCAL, |
234 | .address = (struct sockaddr *)&rpcb_localaddr_rpcbind, | 177 | .address = (struct sockaddr *)&rpcb_localaddr_rpcbind, |
235 | .addrsize = sizeof(rpcb_localaddr_rpcbind), | 178 | .addrsize = sizeof(rpcb_localaddr_rpcbind), |
@@ -250,7 +193,7 @@ static int rpcb_create_local_unix(struct net *net) | |||
250 | if (IS_ERR(clnt)) { | 193 | if (IS_ERR(clnt)) { |
251 | dprintk("RPC: failed to create AF_LOCAL rpcbind " | 194 | dprintk("RPC: failed to create AF_LOCAL rpcbind " |
252 | "client (errno %ld).\n", PTR_ERR(clnt)); | 195 | "client (errno %ld).\n", PTR_ERR(clnt)); |
253 | result = PTR_ERR(clnt); | 196 | result = -PTR_ERR(clnt); |
254 | goto out; | 197 | goto out; |
255 | } | 198 | } |
256 | 199 | ||
@@ -262,7 +205,9 @@ static int rpcb_create_local_unix(struct net *net) | |||
262 | clnt4 = NULL; | 205 | clnt4 = NULL; |
263 | } | 206 | } |
264 | 207 | ||
265 | rpcb_set_local(net, clnt, clnt4); | 208 | /* Protected by rpcb_create_local_mutex */ |
209 | rpcb_local_clnt = clnt; | ||
210 | rpcb_local_clnt4 = clnt4; | ||
266 | 211 | ||
267 | out: | 212 | out: |
268 | return result; | 213 | return result; |
@@ -272,7 +217,7 @@ out: | |||
272 | * Returns zero on success, otherwise a negative errno value | 217 | * Returns zero on success, otherwise a negative errno value |
273 | * is returned. | 218 | * is returned. |
274 | */ | 219 | */ |
275 | static int rpcb_create_local_net(struct net *net) | 220 | static int rpcb_create_local_net(void) |
276 | { | 221 | { |
277 | static const struct sockaddr_in rpcb_inaddr_loopback = { | 222 | static const struct sockaddr_in rpcb_inaddr_loopback = { |
278 | .sin_family = AF_INET, | 223 | .sin_family = AF_INET, |
@@ -280,7 +225,7 @@ static int rpcb_create_local_net(struct net *net) | |||
280 | .sin_port = htons(RPCBIND_PORT), | 225 | .sin_port = htons(RPCBIND_PORT), |
281 | }; | 226 | }; |
282 | struct rpc_create_args args = { | 227 | struct rpc_create_args args = { |
283 | .net = net, | 228 | .net = &init_net, |
284 | .protocol = XPRT_TRANSPORT_TCP, | 229 | .protocol = XPRT_TRANSPORT_TCP, |
285 | .address = (struct sockaddr *)&rpcb_inaddr_loopback, | 230 | .address = (struct sockaddr *)&rpcb_inaddr_loopback, |
286 | .addrsize = sizeof(rpcb_inaddr_loopback), | 231 | .addrsize = sizeof(rpcb_inaddr_loopback), |
@@ -297,7 +242,7 @@ static int rpcb_create_local_net(struct net *net) | |||
297 | if (IS_ERR(clnt)) { | 242 | if (IS_ERR(clnt)) { |
298 | dprintk("RPC: failed to create local rpcbind " | 243 | dprintk("RPC: failed to create local rpcbind " |
299 | "client (errno %ld).\n", PTR_ERR(clnt)); | 244 | "client (errno %ld).\n", PTR_ERR(clnt)); |
300 | result = PTR_ERR(clnt); | 245 | result = -PTR_ERR(clnt); |
301 | goto out; | 246 | goto out; |
302 | } | 247 | } |
303 | 248 | ||
@@ -314,7 +259,9 @@ static int rpcb_create_local_net(struct net *net) | |||
314 | clnt4 = NULL; | 259 | clnt4 = NULL; |
315 | } | 260 | } |
316 | 261 | ||
317 | rpcb_set_local(net, clnt, clnt4); | 262 | /* Protected by rpcb_create_local_mutex */ |
263 | rpcb_local_clnt = clnt; | ||
264 | rpcb_local_clnt4 = clnt4; | ||
318 | 265 | ||
319 | out: | 266 | out: |
320 | return result; | 267 | return result; |
@@ -324,32 +271,31 @@ out: | |||
324 | * Returns zero on success, otherwise a negative errno value | 271 | * Returns zero on success, otherwise a negative errno value |
325 | * is returned. | 272 | * is returned. |
326 | */ | 273 | */ |
327 | int rpcb_create_local(struct net *net) | 274 | static int rpcb_create_local(void) |
328 | { | 275 | { |
329 | static DEFINE_MUTEX(rpcb_create_local_mutex); | 276 | static DEFINE_MUTEX(rpcb_create_local_mutex); |
330 | int result = 0; | 277 | int result = 0; |
331 | 278 | ||
332 | if (rpcb_get_local(net)) | 279 | if (rpcb_local_clnt) |
333 | return result; | 280 | return result; |
334 | 281 | ||
335 | mutex_lock(&rpcb_create_local_mutex); | 282 | mutex_lock(&rpcb_create_local_mutex); |
336 | if (rpcb_get_local(net)) | 283 | if (rpcb_local_clnt) |
337 | goto out; | 284 | goto out; |
338 | 285 | ||
339 | if (rpcb_create_local_unix(net) != 0) | 286 | if (rpcb_create_local_unix() != 0) |
340 | result = rpcb_create_local_net(net); | 287 | result = rpcb_create_local_net(); |
341 | 288 | ||
342 | out: | 289 | out: |
343 | mutex_unlock(&rpcb_create_local_mutex); | 290 | mutex_unlock(&rpcb_create_local_mutex); |
344 | return result; | 291 | return result; |
345 | } | 292 | } |
346 | 293 | ||
347 | static struct rpc_clnt *rpcb_create(struct net *net, const char *hostname, | 294 | static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr, |
348 | struct sockaddr *srvaddr, size_t salen, | 295 | size_t salen, int proto, u32 version) |
349 | int proto, u32 version) | ||
350 | { | 296 | { |
351 | struct rpc_create_args args = { | 297 | struct rpc_create_args args = { |
352 | .net = net, | 298 | .net = &init_net, |
353 | .protocol = proto, | 299 | .protocol = proto, |
354 | .address = srvaddr, | 300 | .address = srvaddr, |
355 | .addrsize = salen, | 301 | .addrsize = salen, |
@@ -395,7 +341,6 @@ static int rpcb_register_call(struct rpc_clnt *clnt, struct rpc_message *msg) | |||
395 | 341 | ||
396 | /** | 342 | /** |
397 | * rpcb_register - set or unset a port registration with the local rpcbind svc | 343 | * rpcb_register - set or unset a port registration with the local rpcbind svc |
398 | * @net: target network namespace | ||
399 | * @prog: RPC program number to bind | 344 | * @prog: RPC program number to bind |
400 | * @vers: RPC version number to bind | 345 | * @vers: RPC version number to bind |
401 | * @prot: transport protocol to register | 346 | * @prot: transport protocol to register |
@@ -426,7 +371,7 @@ static int rpcb_register_call(struct rpc_clnt *clnt, struct rpc_message *msg) | |||
426 | * IN6ADDR_ANY (ie available for all AF_INET and AF_INET6 | 371 | * IN6ADDR_ANY (ie available for all AF_INET and AF_INET6 |
427 | * addresses). | 372 | * addresses). |
428 | */ | 373 | */ |
429 | int rpcb_register(struct net *net, u32 prog, u32 vers, int prot, unsigned short port) | 374 | int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port) |
430 | { | 375 | { |
431 | struct rpcbind_args map = { | 376 | struct rpcbind_args map = { |
432 | .r_prog = prog, | 377 | .r_prog = prog, |
@@ -437,7 +382,11 @@ int rpcb_register(struct net *net, u32 prog, u32 vers, int prot, unsigned short | |||
437 | struct rpc_message msg = { | 382 | struct rpc_message msg = { |
438 | .rpc_argp = &map, | 383 | .rpc_argp = &map, |
439 | }; | 384 | }; |
440 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | 385 | int error; |
386 | |||
387 | error = rpcb_create_local(); | ||
388 | if (error) | ||
389 | return error; | ||
441 | 390 | ||
442 | dprintk("RPC: %sregistering (%u, %u, %d, %u) with local " | 391 | dprintk("RPC: %sregistering (%u, %u, %d, %u) with local " |
443 | "rpcbind\n", (port ? "" : "un"), | 392 | "rpcbind\n", (port ? "" : "un"), |
@@ -447,14 +396,13 @@ int rpcb_register(struct net *net, u32 prog, u32 vers, int prot, unsigned short | |||
447 | if (port) | 396 | if (port) |
448 | msg.rpc_proc = &rpcb_procedures2[RPCBPROC_SET]; | 397 | msg.rpc_proc = &rpcb_procedures2[RPCBPROC_SET]; |
449 | 398 | ||
450 | return rpcb_register_call(sn->rpcb_local_clnt, &msg); | 399 | return rpcb_register_call(rpcb_local_clnt, &msg); |
451 | } | 400 | } |
452 | 401 | ||
453 | /* | 402 | /* |
454 | * Fill in AF_INET family-specific arguments to register | 403 | * Fill in AF_INET family-specific arguments to register |
455 | */ | 404 | */ |
456 | static int rpcb_register_inet4(struct sunrpc_net *sn, | 405 | static int rpcb_register_inet4(const struct sockaddr *sap, |
457 | const struct sockaddr *sap, | ||
458 | struct rpc_message *msg) | 406 | struct rpc_message *msg) |
459 | { | 407 | { |
460 | const struct sockaddr_in *sin = (const struct sockaddr_in *)sap; | 408 | const struct sockaddr_in *sin = (const struct sockaddr_in *)sap; |
@@ -462,7 +410,7 @@ static int rpcb_register_inet4(struct sunrpc_net *sn, | |||
462 | unsigned short port = ntohs(sin->sin_port); | 410 | unsigned short port = ntohs(sin->sin_port); |
463 | int result; | 411 | int result; |
464 | 412 | ||
465 | map->r_addr = rpc_sockaddr2uaddr(sap, GFP_KERNEL); | 413 | map->r_addr = rpc_sockaddr2uaddr(sap); |
466 | 414 | ||
467 | dprintk("RPC: %sregistering [%u, %u, %s, '%s'] with " | 415 | dprintk("RPC: %sregistering [%u, %u, %s, '%s'] with " |
468 | "local rpcbind\n", (port ? "" : "un"), | 416 | "local rpcbind\n", (port ? "" : "un"), |
@@ -473,7 +421,7 @@ static int rpcb_register_inet4(struct sunrpc_net *sn, | |||
473 | if (port) | 421 | if (port) |
474 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; | 422 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; |
475 | 423 | ||
476 | result = rpcb_register_call(sn->rpcb_local_clnt4, msg); | 424 | result = rpcb_register_call(rpcb_local_clnt4, msg); |
477 | kfree(map->r_addr); | 425 | kfree(map->r_addr); |
478 | return result; | 426 | return result; |
479 | } | 427 | } |
@@ -481,8 +429,7 @@ static int rpcb_register_inet4(struct sunrpc_net *sn, | |||
481 | /* | 429 | /* |
482 | * Fill in AF_INET6 family-specific arguments to register | 430 | * Fill in AF_INET6 family-specific arguments to register |
483 | */ | 431 | */ |
484 | static int rpcb_register_inet6(struct sunrpc_net *sn, | 432 | static int rpcb_register_inet6(const struct sockaddr *sap, |
485 | const struct sockaddr *sap, | ||
486 | struct rpc_message *msg) | 433 | struct rpc_message *msg) |
487 | { | 434 | { |
488 | const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sap; | 435 | const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sap; |
@@ -490,7 +437,7 @@ static int rpcb_register_inet6(struct sunrpc_net *sn, | |||
490 | unsigned short port = ntohs(sin6->sin6_port); | 437 | unsigned short port = ntohs(sin6->sin6_port); |
491 | int result; | 438 | int result; |
492 | 439 | ||
493 | map->r_addr = rpc_sockaddr2uaddr(sap, GFP_KERNEL); | 440 | map->r_addr = rpc_sockaddr2uaddr(sap); |
494 | 441 | ||
495 | dprintk("RPC: %sregistering [%u, %u, %s, '%s'] with " | 442 | dprintk("RPC: %sregistering [%u, %u, %s, '%s'] with " |
496 | "local rpcbind\n", (port ? "" : "un"), | 443 | "local rpcbind\n", (port ? "" : "un"), |
@@ -501,13 +448,12 @@ static int rpcb_register_inet6(struct sunrpc_net *sn, | |||
501 | if (port) | 448 | if (port) |
502 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; | 449 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; |
503 | 450 | ||
504 | result = rpcb_register_call(sn->rpcb_local_clnt4, msg); | 451 | result = rpcb_register_call(rpcb_local_clnt4, msg); |
505 | kfree(map->r_addr); | 452 | kfree(map->r_addr); |
506 | return result; | 453 | return result; |
507 | } | 454 | } |
508 | 455 | ||
509 | static int rpcb_unregister_all_protofamilies(struct sunrpc_net *sn, | 456 | static int rpcb_unregister_all_protofamilies(struct rpc_message *msg) |
510 | struct rpc_message *msg) | ||
511 | { | 457 | { |
512 | struct rpcbind_args *map = msg->rpc_argp; | 458 | struct rpcbind_args *map = msg->rpc_argp; |
513 | 459 | ||
@@ -518,12 +464,11 @@ static int rpcb_unregister_all_protofamilies(struct sunrpc_net *sn, | |||
518 | map->r_addr = ""; | 464 | map->r_addr = ""; |
519 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET]; | 465 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET]; |
520 | 466 | ||
521 | return rpcb_register_call(sn->rpcb_local_clnt4, msg); | 467 | return rpcb_register_call(rpcb_local_clnt4, msg); |
522 | } | 468 | } |
523 | 469 | ||
524 | /** | 470 | /** |
525 | * rpcb_v4_register - set or unset a port registration with the local rpcbind | 471 | * rpcb_v4_register - set or unset a port registration with the local rpcbind |
526 | * @net: target network namespace | ||
527 | * @program: RPC program number of service to (un)register | 472 | * @program: RPC program number of service to (un)register |
528 | * @version: RPC version number of service to (un)register | 473 | * @version: RPC version number of service to (un)register |
529 | * @address: address family, IP address, and port to (un)register | 474 | * @address: address family, IP address, and port to (un)register |
@@ -565,7 +510,7 @@ static int rpcb_unregister_all_protofamilies(struct sunrpc_net *sn, | |||
565 | * service on any IPv4 address, but not on IPv6. The latter | 510 | * service on any IPv4 address, but not on IPv6. The latter |
566 | * advertises the service on all IPv4 and IPv6 addresses. | 511 | * advertises the service on all IPv4 and IPv6 addresses. |
567 | */ | 512 | */ |
568 | int rpcb_v4_register(struct net *net, const u32 program, const u32 version, | 513 | int rpcb_v4_register(const u32 program, const u32 version, |
569 | const struct sockaddr *address, const char *netid) | 514 | const struct sockaddr *address, const char *netid) |
570 | { | 515 | { |
571 | struct rpcbind_args map = { | 516 | struct rpcbind_args map = { |
@@ -577,19 +522,22 @@ int rpcb_v4_register(struct net *net, const u32 program, const u32 version, | |||
577 | struct rpc_message msg = { | 522 | struct rpc_message msg = { |
578 | .rpc_argp = &map, | 523 | .rpc_argp = &map, |
579 | }; | 524 | }; |
580 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | 525 | int error; |
581 | 526 | ||
582 | if (sn->rpcb_local_clnt4 == NULL) | 527 | error = rpcb_create_local(); |
528 | if (error) | ||
529 | return error; | ||
530 | if (rpcb_local_clnt4 == NULL) | ||
583 | return -EPROTONOSUPPORT; | 531 | return -EPROTONOSUPPORT; |
584 | 532 | ||
585 | if (address == NULL) | 533 | if (address == NULL) |
586 | return rpcb_unregister_all_protofamilies(sn, &msg); | 534 | return rpcb_unregister_all_protofamilies(&msg); |
587 | 535 | ||
588 | switch (address->sa_family) { | 536 | switch (address->sa_family) { |
589 | case AF_INET: | 537 | case AF_INET: |
590 | return rpcb_register_inet4(sn, address, &msg); | 538 | return rpcb_register_inet4(address, &msg); |
591 | case AF_INET6: | 539 | case AF_INET6: |
592 | return rpcb_register_inet6(sn, address, &msg); | 540 | return rpcb_register_inet6(address, &msg); |
593 | } | 541 | } |
594 | 542 | ||
595 | return -EAFNOSUPPORT; | 543 | return -EAFNOSUPPORT; |
@@ -623,10 +571,9 @@ static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbi | |||
623 | static struct rpc_clnt *rpcb_find_transport_owner(struct rpc_clnt *clnt) | 571 | static struct rpc_clnt *rpcb_find_transport_owner(struct rpc_clnt *clnt) |
624 | { | 572 | { |
625 | struct rpc_clnt *parent = clnt->cl_parent; | 573 | struct rpc_clnt *parent = clnt->cl_parent; |
626 | struct rpc_xprt *xprt = rcu_dereference(clnt->cl_xprt); | ||
627 | 574 | ||
628 | while (parent != clnt) { | 575 | while (parent != clnt) { |
629 | if (rcu_dereference(parent->cl_xprt) != xprt) | 576 | if (parent->cl_xprt != clnt->cl_xprt) |
630 | break; | 577 | break; |
631 | if (clnt->cl_autobind) | 578 | if (clnt->cl_autobind) |
632 | break; | 579 | break; |
@@ -657,16 +604,12 @@ void rpcb_getport_async(struct rpc_task *task) | |||
657 | size_t salen; | 604 | size_t salen; |
658 | int status; | 605 | int status; |
659 | 606 | ||
660 | rcu_read_lock(); | 607 | clnt = rpcb_find_transport_owner(task->tk_client); |
661 | do { | 608 | xprt = clnt->cl_xprt; |
662 | clnt = rpcb_find_transport_owner(task->tk_client); | ||
663 | xprt = xprt_get(rcu_dereference(clnt->cl_xprt)); | ||
664 | } while (xprt == NULL); | ||
665 | rcu_read_unlock(); | ||
666 | 609 | ||
667 | dprintk("RPC: %5u %s(%s, %u, %u, %d)\n", | 610 | dprintk("RPC: %5u %s(%s, %u, %u, %d)\n", |
668 | task->tk_pid, __func__, | 611 | task->tk_pid, __func__, |
669 | xprt->servername, clnt->cl_prog, clnt->cl_vers, xprt->prot); | 612 | clnt->cl_server, clnt->cl_prog, clnt->cl_vers, xprt->prot); |
670 | 613 | ||
671 | /* Put self on the wait queue to ensure we get notified if | 614 | /* Put self on the wait queue to ensure we get notified if |
672 | * some other task is already attempting to bind the port */ | 615 | * some other task is already attempting to bind the port */ |
@@ -675,7 +618,6 @@ void rpcb_getport_async(struct rpc_task *task) | |||
675 | if (xprt_test_and_set_binding(xprt)) { | 618 | if (xprt_test_and_set_binding(xprt)) { |
676 | dprintk("RPC: %5u %s: waiting for another binder\n", | 619 | dprintk("RPC: %5u %s: waiting for another binder\n", |
677 | task->tk_pid, __func__); | 620 | task->tk_pid, __func__); |
678 | xprt_put(xprt); | ||
679 | return; | 621 | return; |
680 | } | 622 | } |
681 | 623 | ||
@@ -717,8 +659,8 @@ void rpcb_getport_async(struct rpc_task *task) | |||
717 | dprintk("RPC: %5u %s: trying rpcbind version %u\n", | 659 | dprintk("RPC: %5u %s: trying rpcbind version %u\n", |
718 | task->tk_pid, __func__, bind_version); | 660 | task->tk_pid, __func__, bind_version); |
719 | 661 | ||
720 | rpcb_clnt = rpcb_create(xprt->xprt_net, xprt->servername, sap, salen, | 662 | rpcb_clnt = rpcb_create(clnt->cl_server, sap, salen, xprt->prot, |
721 | xprt->prot, bind_version); | 663 | bind_version); |
722 | if (IS_ERR(rpcb_clnt)) { | 664 | if (IS_ERR(rpcb_clnt)) { |
723 | status = PTR_ERR(rpcb_clnt); | 665 | status = PTR_ERR(rpcb_clnt); |
724 | dprintk("RPC: %5u %s: rpcb_create failed, error %ld\n", | 666 | dprintk("RPC: %5u %s: rpcb_create failed, error %ld\n", |
@@ -737,14 +679,14 @@ void rpcb_getport_async(struct rpc_task *task) | |||
737 | map->r_vers = clnt->cl_vers; | 679 | map->r_vers = clnt->cl_vers; |
738 | map->r_prot = xprt->prot; | 680 | map->r_prot = xprt->prot; |
739 | map->r_port = 0; | 681 | map->r_port = 0; |
740 | map->r_xprt = xprt; | 682 | map->r_xprt = xprt_get(xprt); |
741 | map->r_status = -EIO; | 683 | map->r_status = -EIO; |
742 | 684 | ||
743 | switch (bind_version) { | 685 | switch (bind_version) { |
744 | case RPCBVERS_4: | 686 | case RPCBVERS_4: |
745 | case RPCBVERS_3: | 687 | case RPCBVERS_3: |
746 | map->r_netid = xprt->address_strings[RPC_DISPLAY_NETID]; | 688 | map->r_netid = rpc_peeraddr2str(clnt, RPC_DISPLAY_NETID); |
747 | map->r_addr = rpc_sockaddr2uaddr(sap, GFP_ATOMIC); | 689 | map->r_addr = rpc_sockaddr2uaddr(sap); |
748 | map->r_owner = ""; | 690 | map->r_owner = ""; |
749 | break; | 691 | break; |
750 | case RPCBVERS_2: | 692 | case RPCBVERS_2: |
@@ -772,7 +714,6 @@ bailout_release_client: | |||
772 | bailout_nofree: | 714 | bailout_nofree: |
773 | rpcb_wake_rpcbind_waiters(xprt, status); | 715 | rpcb_wake_rpcbind_waiters(xprt, status); |
774 | task->tk_status = status; | 716 | task->tk_status = status; |
775 | xprt_put(xprt); | ||
776 | } | 717 | } |
777 | EXPORT_SYMBOL_GPL(rpcb_getport_async); | 718 | EXPORT_SYMBOL_GPL(rpcb_getport_async); |
778 | 719 | ||
@@ -820,11 +761,11 @@ static void rpcb_getport_done(struct rpc_task *child, void *data) | |||
820 | static void rpcb_enc_mapping(struct rpc_rqst *req, struct xdr_stream *xdr, | 761 | static void rpcb_enc_mapping(struct rpc_rqst *req, struct xdr_stream *xdr, |
821 | const struct rpcbind_args *rpcb) | 762 | const struct rpcbind_args *rpcb) |
822 | { | 763 | { |
764 | struct rpc_task *task = req->rq_task; | ||
823 | __be32 *p; | 765 | __be32 *p; |
824 | 766 | ||
825 | dprintk("RPC: %5u encoding PMAP_%s call (%u, %u, %d, %u)\n", | 767 | dprintk("RPC: %5u encoding PMAP_%s call (%u, %u, %d, %u)\n", |
826 | req->rq_task->tk_pid, | 768 | task->tk_pid, task->tk_msg.rpc_proc->p_name, |
827 | req->rq_task->tk_msg.rpc_proc->p_name, | ||
828 | rpcb->r_prog, rpcb->r_vers, rpcb->r_prot, rpcb->r_port); | 769 | rpcb->r_prog, rpcb->r_vers, rpcb->r_prot, rpcb->r_port); |
829 | 770 | ||
830 | p = xdr_reserve_space(xdr, RPCB_mappingargs_sz << 2); | 771 | p = xdr_reserve_space(xdr, RPCB_mappingargs_sz << 2); |
@@ -837,6 +778,7 @@ static void rpcb_enc_mapping(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
837 | static int rpcb_dec_getport(struct rpc_rqst *req, struct xdr_stream *xdr, | 778 | static int rpcb_dec_getport(struct rpc_rqst *req, struct xdr_stream *xdr, |
838 | struct rpcbind_args *rpcb) | 779 | struct rpcbind_args *rpcb) |
839 | { | 780 | { |
781 | struct rpc_task *task = req->rq_task; | ||
840 | unsigned long port; | 782 | unsigned long port; |
841 | __be32 *p; | 783 | __be32 *p; |
842 | 784 | ||
@@ -847,8 +789,8 @@ static int rpcb_dec_getport(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
847 | return -EIO; | 789 | return -EIO; |
848 | 790 | ||
849 | port = be32_to_cpup(p); | 791 | port = be32_to_cpup(p); |
850 | dprintk("RPC: %5u PMAP_%s result: %lu\n", req->rq_task->tk_pid, | 792 | dprintk("RPC: %5u PMAP_%s result: %lu\n", task->tk_pid, |
851 | req->rq_task->tk_msg.rpc_proc->p_name, port); | 793 | task->tk_msg.rpc_proc->p_name, port); |
852 | if (unlikely(port > USHRT_MAX)) | 794 | if (unlikely(port > USHRT_MAX)) |
853 | return -EIO; | 795 | return -EIO; |
854 | 796 | ||
@@ -859,6 +801,7 @@ static int rpcb_dec_getport(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
859 | static int rpcb_dec_set(struct rpc_rqst *req, struct xdr_stream *xdr, | 801 | static int rpcb_dec_set(struct rpc_rqst *req, struct xdr_stream *xdr, |
860 | unsigned int *boolp) | 802 | unsigned int *boolp) |
861 | { | 803 | { |
804 | struct rpc_task *task = req->rq_task; | ||
862 | __be32 *p; | 805 | __be32 *p; |
863 | 806 | ||
864 | p = xdr_inline_decode(xdr, 4); | 807 | p = xdr_inline_decode(xdr, 4); |
@@ -870,8 +813,7 @@ static int rpcb_dec_set(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
870 | *boolp = 1; | 813 | *boolp = 1; |
871 | 814 | ||
872 | dprintk("RPC: %5u RPCB_%s call %s\n", | 815 | dprintk("RPC: %5u RPCB_%s call %s\n", |
873 | req->rq_task->tk_pid, | 816 | task->tk_pid, task->tk_msg.rpc_proc->p_name, |
874 | req->rq_task->tk_msg.rpc_proc->p_name, | ||
875 | (*boolp ? "succeeded" : "failed")); | 817 | (*boolp ? "succeeded" : "failed")); |
876 | return 0; | 818 | return 0; |
877 | } | 819 | } |
@@ -883,10 +825,7 @@ static void encode_rpcb_string(struct xdr_stream *xdr, const char *string, | |||
883 | u32 len; | 825 | u32 len; |
884 | 826 | ||
885 | len = strlen(string); | 827 | len = strlen(string); |
886 | WARN_ON_ONCE(len > maxstrlen); | 828 | BUG_ON(len > maxstrlen); |
887 | if (len > maxstrlen) | ||
888 | /* truncate and hope for the best */ | ||
889 | len = maxstrlen; | ||
890 | p = xdr_reserve_space(xdr, 4 + len); | 829 | p = xdr_reserve_space(xdr, 4 + len); |
891 | xdr_encode_opaque(p, string, len); | 830 | xdr_encode_opaque(p, string, len); |
892 | } | 831 | } |
@@ -894,11 +833,11 @@ static void encode_rpcb_string(struct xdr_stream *xdr, const char *string, | |||
894 | static void rpcb_enc_getaddr(struct rpc_rqst *req, struct xdr_stream *xdr, | 833 | static void rpcb_enc_getaddr(struct rpc_rqst *req, struct xdr_stream *xdr, |
895 | const struct rpcbind_args *rpcb) | 834 | const struct rpcbind_args *rpcb) |
896 | { | 835 | { |
836 | struct rpc_task *task = req->rq_task; | ||
897 | __be32 *p; | 837 | __be32 *p; |
898 | 838 | ||
899 | dprintk("RPC: %5u encoding RPCB_%s call (%u, %u, '%s', '%s')\n", | 839 | dprintk("RPC: %5u encoding RPCB_%s call (%u, %u, '%s', '%s')\n", |
900 | req->rq_task->tk_pid, | 840 | task->tk_pid, task->tk_msg.rpc_proc->p_name, |
901 | req->rq_task->tk_msg.rpc_proc->p_name, | ||
902 | rpcb->r_prog, rpcb->r_vers, | 841 | rpcb->r_prog, rpcb->r_vers, |
903 | rpcb->r_netid, rpcb->r_addr); | 842 | rpcb->r_netid, rpcb->r_addr); |
904 | 843 | ||
@@ -916,6 +855,7 @@ static int rpcb_dec_getaddr(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
916 | { | 855 | { |
917 | struct sockaddr_storage address; | 856 | struct sockaddr_storage address; |
918 | struct sockaddr *sap = (struct sockaddr *)&address; | 857 | struct sockaddr *sap = (struct sockaddr *)&address; |
858 | struct rpc_task *task = req->rq_task; | ||
919 | __be32 *p; | 859 | __be32 *p; |
920 | u32 len; | 860 | u32 len; |
921 | 861 | ||
@@ -932,7 +872,7 @@ static int rpcb_dec_getaddr(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
932 | */ | 872 | */ |
933 | if (len == 0) { | 873 | if (len == 0) { |
934 | dprintk("RPC: %5u RPCB reply: program not registered\n", | 874 | dprintk("RPC: %5u RPCB reply: program not registered\n", |
935 | req->rq_task->tk_pid); | 875 | task->tk_pid); |
936 | return 0; | 876 | return 0; |
937 | } | 877 | } |
938 | 878 | ||
@@ -942,11 +882,10 @@ static int rpcb_dec_getaddr(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
942 | p = xdr_inline_decode(xdr, len); | 882 | p = xdr_inline_decode(xdr, len); |
943 | if (unlikely(p == NULL)) | 883 | if (unlikely(p == NULL)) |
944 | goto out_fail; | 884 | goto out_fail; |
945 | dprintk("RPC: %5u RPCB_%s reply: %s\n", req->rq_task->tk_pid, | 885 | dprintk("RPC: %5u RPCB_%s reply: %s\n", task->tk_pid, |
946 | req->rq_task->tk_msg.rpc_proc->p_name, (char *)p); | 886 | task->tk_msg.rpc_proc->p_name, (char *)p); |
947 | 887 | ||
948 | if (rpc_uaddr2sockaddr(req->rq_xprt->xprt_net, (char *)p, len, | 888 | if (rpc_uaddr2sockaddr((char *)p, len, sap, sizeof(address)) == 0) |
949 | sap, sizeof(address)) == 0) | ||
950 | goto out_fail; | 889 | goto out_fail; |
951 | rpcb->r_port = rpc_get_port(sap); | 890 | rpcb->r_port = rpc_get_port(sap); |
952 | 891 | ||
@@ -954,8 +893,7 @@ static int rpcb_dec_getaddr(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
954 | 893 | ||
955 | out_fail: | 894 | out_fail: |
956 | dprintk("RPC: %5u malformed RPCB_%s reply\n", | 895 | dprintk("RPC: %5u malformed RPCB_%s reply\n", |
957 | req->rq_task->tk_pid, | 896 | task->tk_pid, task->tk_msg.rpc_proc->p_name); |
958 | req->rq_task->tk_msg.rpc_proc->p_name); | ||
959 | return -EIO; | 897 | return -EIO; |
960 | } | 898 | } |
961 | 899 | ||
@@ -1063,7 +1001,7 @@ static struct rpc_procinfo rpcb_procedures4[] = { | |||
1063 | }, | 1001 | }, |
1064 | }; | 1002 | }; |
1065 | 1003 | ||
1066 | static const struct rpcb_info rpcb_next_version[] = { | 1004 | static struct rpcb_info rpcb_next_version[] = { |
1067 | { | 1005 | { |
1068 | .rpc_vers = RPCBVERS_2, | 1006 | .rpc_vers = RPCBVERS_2, |
1069 | .rpc_proc = &rpcb_procedures2[RPCBPROC_GETPORT], | 1007 | .rpc_proc = &rpcb_procedures2[RPCBPROC_GETPORT], |
@@ -1073,7 +1011,7 @@ static const struct rpcb_info rpcb_next_version[] = { | |||
1073 | }, | 1011 | }, |
1074 | }; | 1012 | }; |
1075 | 1013 | ||
1076 | static const struct rpcb_info rpcb_next_version6[] = { | 1014 | static struct rpcb_info rpcb_next_version6[] = { |
1077 | { | 1015 | { |
1078 | .rpc_vers = RPCBVERS_4, | 1016 | .rpc_vers = RPCBVERS_4, |
1079 | .rpc_proc = &rpcb_procedures4[RPCBPROC_GETADDR], | 1017 | .rpc_proc = &rpcb_procedures4[RPCBPROC_GETADDR], |
@@ -1087,25 +1025,25 @@ static const struct rpcb_info rpcb_next_version6[] = { | |||
1087 | }, | 1025 | }, |
1088 | }; | 1026 | }; |
1089 | 1027 | ||
1090 | static const struct rpc_version rpcb_version2 = { | 1028 | static struct rpc_version rpcb_version2 = { |
1091 | .number = RPCBVERS_2, | 1029 | .number = RPCBVERS_2, |
1092 | .nrprocs = ARRAY_SIZE(rpcb_procedures2), | 1030 | .nrprocs = ARRAY_SIZE(rpcb_procedures2), |
1093 | .procs = rpcb_procedures2 | 1031 | .procs = rpcb_procedures2 |
1094 | }; | 1032 | }; |
1095 | 1033 | ||
1096 | static const struct rpc_version rpcb_version3 = { | 1034 | static struct rpc_version rpcb_version3 = { |
1097 | .number = RPCBVERS_3, | 1035 | .number = RPCBVERS_3, |
1098 | .nrprocs = ARRAY_SIZE(rpcb_procedures3), | 1036 | .nrprocs = ARRAY_SIZE(rpcb_procedures3), |
1099 | .procs = rpcb_procedures3 | 1037 | .procs = rpcb_procedures3 |
1100 | }; | 1038 | }; |
1101 | 1039 | ||
1102 | static const struct rpc_version rpcb_version4 = { | 1040 | static struct rpc_version rpcb_version4 = { |
1103 | .number = RPCBVERS_4, | 1041 | .number = RPCBVERS_4, |
1104 | .nrprocs = ARRAY_SIZE(rpcb_procedures4), | 1042 | .nrprocs = ARRAY_SIZE(rpcb_procedures4), |
1105 | .procs = rpcb_procedures4 | 1043 | .procs = rpcb_procedures4 |
1106 | }; | 1044 | }; |
1107 | 1045 | ||
1108 | static const struct rpc_version *rpcb_version[] = { | 1046 | static struct rpc_version *rpcb_version[] = { |
1109 | NULL, | 1047 | NULL, |
1110 | NULL, | 1048 | NULL, |
1111 | &rpcb_version2, | 1049 | &rpcb_version2, |
@@ -1115,10 +1053,22 @@ static const struct rpc_version *rpcb_version[] = { | |||
1115 | 1053 | ||
1116 | static struct rpc_stat rpcb_stats; | 1054 | static struct rpc_stat rpcb_stats; |
1117 | 1055 | ||
1118 | static const struct rpc_program rpcb_program = { | 1056 | static struct rpc_program rpcb_program = { |
1119 | .name = "rpcbind", | 1057 | .name = "rpcbind", |
1120 | .number = RPCBIND_PROGRAM, | 1058 | .number = RPCBIND_PROGRAM, |
1121 | .nrvers = ARRAY_SIZE(rpcb_version), | 1059 | .nrvers = ARRAY_SIZE(rpcb_version), |
1122 | .version = rpcb_version, | 1060 | .version = rpcb_version, |
1123 | .stats = &rpcb_stats, | 1061 | .stats = &rpcb_stats, |
1124 | }; | 1062 | }; |
1063 | |||
1064 | /** | ||
1065 | * cleanup_rpcb_clnt - remove xprtsock's sysctls, unregister | ||
1066 | * | ||
1067 | */ | ||
1068 | void cleanup_rpcb_clnt(void) | ||
1069 | { | ||
1070 | if (rpcb_local_clnt4) | ||
1071 | rpc_shutdown_client(rpcb_local_clnt4); | ||
1072 | if (rpcb_local_clnt) | ||
1073 | rpc_shutdown_client(rpcb_local_clnt); | ||
1074 | } | ||
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index bfa31714581..d12ffa54581 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c | |||
@@ -18,7 +18,6 @@ | |||
18 | #include <linux/smp.h> | 18 | #include <linux/smp.h> |
19 | #include <linux/spinlock.h> | 19 | #include <linux/spinlock.h> |
20 | #include <linux/mutex.h> | 20 | #include <linux/mutex.h> |
21 | #include <linux/freezer.h> | ||
22 | 21 | ||
23 | #include <linux/sunrpc/clnt.h> | 22 | #include <linux/sunrpc/clnt.h> |
24 | 23 | ||
@@ -28,9 +27,6 @@ | |||
28 | #define RPCDBG_FACILITY RPCDBG_SCHED | 27 | #define RPCDBG_FACILITY RPCDBG_SCHED |
29 | #endif | 28 | #endif |
30 | 29 | ||
31 | #define CREATE_TRACE_POINTS | ||
32 | #include <trace/events/sunrpc.h> | ||
33 | |||
34 | /* | 30 | /* |
35 | * RPC slabs and memory pools | 31 | * RPC slabs and memory pools |
36 | */ | 32 | */ |
@@ -98,23 +94,6 @@ __rpc_add_timer(struct rpc_wait_queue *queue, struct rpc_task *task) | |||
98 | list_add(&task->u.tk_wait.timer_list, &queue->timer_list.list); | 94 | list_add(&task->u.tk_wait.timer_list, &queue->timer_list.list); |
99 | } | 95 | } |
100 | 96 | ||
101 | static void rpc_set_waitqueue_priority(struct rpc_wait_queue *queue, int priority) | ||
102 | { | ||
103 | queue->priority = priority; | ||
104 | } | ||
105 | |||
106 | static void rpc_set_waitqueue_owner(struct rpc_wait_queue *queue, pid_t pid) | ||
107 | { | ||
108 | queue->owner = pid; | ||
109 | queue->nr = RPC_BATCH_COUNT; | ||
110 | } | ||
111 | |||
112 | static void rpc_reset_waitqueue_priority(struct rpc_wait_queue *queue) | ||
113 | { | ||
114 | rpc_set_waitqueue_priority(queue, queue->maxpriority); | ||
115 | rpc_set_waitqueue_owner(queue, 0); | ||
116 | } | ||
117 | |||
118 | /* | 97 | /* |
119 | * Add new request to a priority queue. | 98 | * Add new request to a priority queue. |
120 | */ | 99 | */ |
@@ -126,11 +105,9 @@ static void __rpc_add_wait_queue_priority(struct rpc_wait_queue *queue, | |||
126 | struct rpc_task *t; | 105 | struct rpc_task *t; |
127 | 106 | ||
128 | INIT_LIST_HEAD(&task->u.tk_wait.links); | 107 | INIT_LIST_HEAD(&task->u.tk_wait.links); |
129 | if (unlikely(queue_priority > queue->maxpriority)) | ||
130 | queue_priority = queue->maxpriority; | ||
131 | if (queue_priority > queue->priority) | ||
132 | rpc_set_waitqueue_priority(queue, queue_priority); | ||
133 | q = &queue->tasks[queue_priority]; | 108 | q = &queue->tasks[queue_priority]; |
109 | if (unlikely(queue_priority > queue->maxpriority)) | ||
110 | q = &queue->tasks[queue->maxpriority]; | ||
134 | list_for_each_entry(t, q, u.tk_wait.list) { | 111 | list_for_each_entry(t, q, u.tk_wait.list) { |
135 | if (t->tk_owner == task->tk_owner) { | 112 | if (t->tk_owner == task->tk_owner) { |
136 | list_add_tail(&task->u.tk_wait.list, &t->u.tk_wait.links); | 113 | list_add_tail(&task->u.tk_wait.list, &t->u.tk_wait.links); |
@@ -152,9 +129,7 @@ static void __rpc_add_wait_queue(struct rpc_wait_queue *queue, | |||
152 | struct rpc_task *task, | 129 | struct rpc_task *task, |
153 | unsigned char queue_priority) | 130 | unsigned char queue_priority) |
154 | { | 131 | { |
155 | WARN_ON_ONCE(RPC_IS_QUEUED(task)); | 132 | BUG_ON (RPC_IS_QUEUED(task)); |
156 | if (RPC_IS_QUEUED(task)) | ||
157 | return; | ||
158 | 133 | ||
159 | if (RPC_IS_PRIORITY(queue)) | 134 | if (RPC_IS_PRIORITY(queue)) |
160 | __rpc_add_wait_queue_priority(queue, task, queue_priority); | 135 | __rpc_add_wait_queue_priority(queue, task, queue_priority); |
@@ -199,6 +174,24 @@ static void __rpc_remove_wait_queue(struct rpc_wait_queue *queue, struct rpc_tas | |||
199 | task->tk_pid, queue, rpc_qname(queue)); | 174 | task->tk_pid, queue, rpc_qname(queue)); |
200 | } | 175 | } |
201 | 176 | ||
177 | static inline void rpc_set_waitqueue_priority(struct rpc_wait_queue *queue, int priority) | ||
178 | { | ||
179 | queue->priority = priority; | ||
180 | queue->count = 1 << (priority * 2); | ||
181 | } | ||
182 | |||
183 | static inline void rpc_set_waitqueue_owner(struct rpc_wait_queue *queue, pid_t pid) | ||
184 | { | ||
185 | queue->owner = pid; | ||
186 | queue->nr = RPC_BATCH_COUNT; | ||
187 | } | ||
188 | |||
189 | static inline void rpc_reset_waitqueue_priority(struct rpc_wait_queue *queue) | ||
190 | { | ||
191 | rpc_set_waitqueue_priority(queue, queue->maxpriority); | ||
192 | rpc_set_waitqueue_owner(queue, 0); | ||
193 | } | ||
194 | |||
202 | static void __rpc_init_priority_wait_queue(struct rpc_wait_queue *queue, const char *qname, unsigned char nr_queues) | 195 | static void __rpc_init_priority_wait_queue(struct rpc_wait_queue *queue, const char *qname, unsigned char nr_queues) |
203 | { | 196 | { |
204 | int i; | 197 | int i; |
@@ -211,7 +204,9 @@ static void __rpc_init_priority_wait_queue(struct rpc_wait_queue *queue, const c | |||
211 | queue->qlen = 0; | 204 | queue->qlen = 0; |
212 | setup_timer(&queue->timer_list.timer, __rpc_queue_timer_fn, (unsigned long)queue); | 205 | setup_timer(&queue->timer_list.timer, __rpc_queue_timer_fn, (unsigned long)queue); |
213 | INIT_LIST_HEAD(&queue->timer_list.list); | 206 | INIT_LIST_HEAD(&queue->timer_list.list); |
214 | rpc_assign_waitqueue_name(queue, qname); | 207 | #ifdef RPC_DEBUG |
208 | queue->name = qname; | ||
209 | #endif | ||
215 | } | 210 | } |
216 | 211 | ||
217 | void rpc_init_priority_wait_queue(struct rpc_wait_queue *queue, const char *qname) | 212 | void rpc_init_priority_wait_queue(struct rpc_wait_queue *queue, const char *qname) |
@@ -236,7 +231,7 @@ static int rpc_wait_bit_killable(void *word) | |||
236 | { | 231 | { |
237 | if (fatal_signal_pending(current)) | 232 | if (fatal_signal_pending(current)) |
238 | return -ERESTARTSYS; | 233 | return -ERESTARTSYS; |
239 | freezable_schedule(); | 234 | schedule(); |
240 | return 0; | 235 | return 0; |
241 | } | 236 | } |
242 | 237 | ||
@@ -255,8 +250,6 @@ static inline void rpc_task_set_debuginfo(struct rpc_task *task) | |||
255 | 250 | ||
256 | static void rpc_set_active(struct rpc_task *task) | 251 | static void rpc_set_active(struct rpc_task *task) |
257 | { | 252 | { |
258 | trace_rpc_task_begin(task->tk_client, task, NULL); | ||
259 | |||
260 | rpc_task_set_debuginfo(task); | 253 | rpc_task_set_debuginfo(task); |
261 | set_bit(RPC_TASK_ACTIVE, &task->tk_runstate); | 254 | set_bit(RPC_TASK_ACTIVE, &task->tk_runstate); |
262 | } | 255 | } |
@@ -273,8 +266,6 @@ static int rpc_complete_task(struct rpc_task *task) | |||
273 | unsigned long flags; | 266 | unsigned long flags; |
274 | int ret; | 267 | int ret; |
275 | 268 | ||
276 | trace_rpc_task_complete(task->tk_client, task, NULL); | ||
277 | |||
278 | spin_lock_irqsave(&wq->lock, flags); | 269 | spin_lock_irqsave(&wq->lock, flags); |
279 | clear_bit(RPC_TASK_ACTIVE, &task->tk_runstate); | 270 | clear_bit(RPC_TASK_ACTIVE, &task->tk_runstate); |
280 | ret = atomic_dec_and_test(&task->tk_count); | 271 | ret = atomic_dec_and_test(&task->tk_count); |
@@ -303,9 +294,8 @@ EXPORT_SYMBOL_GPL(__rpc_wait_for_completion_task); | |||
303 | /* | 294 | /* |
304 | * Make an RPC task runnable. | 295 | * Make an RPC task runnable. |
305 | * | 296 | * |
306 | * Note: If the task is ASYNC, and is being made runnable after sitting on an | 297 | * Note: If the task is ASYNC, this must be called with |
307 | * rpc_wait_queue, this must be called with the queue spinlock held to protect | 298 | * the spinlock held to protect the wait queue operation. |
308 | * the wait queue operation. | ||
309 | */ | 299 | */ |
310 | static void rpc_make_runnable(struct rpc_task *task) | 300 | static void rpc_make_runnable(struct rpc_task *task) |
311 | { | 301 | { |
@@ -333,11 +323,9 @@ static void __rpc_sleep_on_priority(struct rpc_wait_queue *q, | |||
333 | dprintk("RPC: %5u sleep_on(queue \"%s\" time %lu)\n", | 323 | dprintk("RPC: %5u sleep_on(queue \"%s\" time %lu)\n", |
334 | task->tk_pid, rpc_qname(q), jiffies); | 324 | task->tk_pid, rpc_qname(q), jiffies); |
335 | 325 | ||
336 | trace_rpc_task_sleep(task->tk_client, task, q); | ||
337 | |||
338 | __rpc_add_wait_queue(q, task, queue_priority); | 326 | __rpc_add_wait_queue(q, task, queue_priority); |
339 | 327 | ||
340 | WARN_ON_ONCE(task->tk_callback != NULL); | 328 | BUG_ON(task->tk_callback != NULL); |
341 | task->tk_callback = action; | 329 | task->tk_callback = action; |
342 | __rpc_add_timer(q, task); | 330 | __rpc_add_timer(q, task); |
343 | } | 331 | } |
@@ -346,12 +334,7 @@ void rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task, | |||
346 | rpc_action action) | 334 | rpc_action action) |
347 | { | 335 | { |
348 | /* We shouldn't ever put an inactive task to sleep */ | 336 | /* We shouldn't ever put an inactive task to sleep */ |
349 | WARN_ON_ONCE(!RPC_IS_ACTIVATED(task)); | 337 | BUG_ON(!RPC_IS_ACTIVATED(task)); |
350 | if (!RPC_IS_ACTIVATED(task)) { | ||
351 | task->tk_status = -EIO; | ||
352 | rpc_put_task_async(task); | ||
353 | return; | ||
354 | } | ||
355 | 338 | ||
356 | /* | 339 | /* |
357 | * Protect the queue operations. | 340 | * Protect the queue operations. |
@@ -366,12 +349,7 @@ void rpc_sleep_on_priority(struct rpc_wait_queue *q, struct rpc_task *task, | |||
366 | rpc_action action, int priority) | 349 | rpc_action action, int priority) |
367 | { | 350 | { |
368 | /* We shouldn't ever put an inactive task to sleep */ | 351 | /* We shouldn't ever put an inactive task to sleep */ |
369 | WARN_ON_ONCE(!RPC_IS_ACTIVATED(task)); | 352 | BUG_ON(!RPC_IS_ACTIVATED(task)); |
370 | if (!RPC_IS_ACTIVATED(task)) { | ||
371 | task->tk_status = -EIO; | ||
372 | rpc_put_task_async(task); | ||
373 | return; | ||
374 | } | ||
375 | 353 | ||
376 | /* | 354 | /* |
377 | * Protect the queue operations. | 355 | * Protect the queue operations. |
@@ -380,7 +358,6 @@ void rpc_sleep_on_priority(struct rpc_wait_queue *q, struct rpc_task *task, | |||
380 | __rpc_sleep_on_priority(q, task, action, priority - RPC_PRIORITY_LOW); | 358 | __rpc_sleep_on_priority(q, task, action, priority - RPC_PRIORITY_LOW); |
381 | spin_unlock_bh(&q->lock); | 359 | spin_unlock_bh(&q->lock); |
382 | } | 360 | } |
383 | EXPORT_SYMBOL_GPL(rpc_sleep_on_priority); | ||
384 | 361 | ||
385 | /** | 362 | /** |
386 | * __rpc_do_wake_up_task - wake up a single rpc_task | 363 | * __rpc_do_wake_up_task - wake up a single rpc_task |
@@ -400,8 +377,6 @@ static void __rpc_do_wake_up_task(struct rpc_wait_queue *queue, struct rpc_task | |||
400 | return; | 377 | return; |
401 | } | 378 | } |
402 | 379 | ||
403 | trace_rpc_task_wakeup(task->tk_client, task, queue); | ||
404 | |||
405 | __rpc_remove_wait_queue(queue, task); | 380 | __rpc_remove_wait_queue(queue, task); |
406 | 381 | ||
407 | rpc_make_runnable(task); | 382 | rpc_make_runnable(task); |
@@ -446,7 +421,7 @@ EXPORT_SYMBOL_GPL(rpc_wake_up_queued_task); | |||
446 | /* | 421 | /* |
447 | * Wake up the next task on a priority queue. | 422 | * Wake up the next task on a priority queue. |
448 | */ | 423 | */ |
449 | static struct rpc_task *__rpc_find_next_queued_priority(struct rpc_wait_queue *queue) | 424 | static struct rpc_task * __rpc_wake_up_next_priority(struct rpc_wait_queue *queue) |
450 | { | 425 | { |
451 | struct list_head *q; | 426 | struct list_head *q; |
452 | struct rpc_task *task; | 427 | struct rpc_task *task; |
@@ -465,7 +440,8 @@ static struct rpc_task *__rpc_find_next_queued_priority(struct rpc_wait_queue *q | |||
465 | /* | 440 | /* |
466 | * Check if we need to switch queues. | 441 | * Check if we need to switch queues. |
467 | */ | 442 | */ |
468 | goto new_owner; | 443 | if (--queue->count) |
444 | goto new_owner; | ||
469 | } | 445 | } |
470 | 446 | ||
471 | /* | 447 | /* |
@@ -490,54 +466,30 @@ new_queue: | |||
490 | new_owner: | 466 | new_owner: |
491 | rpc_set_waitqueue_owner(queue, task->tk_owner); | 467 | rpc_set_waitqueue_owner(queue, task->tk_owner); |
492 | out: | 468 | out: |
469 | rpc_wake_up_task_queue_locked(queue, task); | ||
493 | return task; | 470 | return task; |
494 | } | 471 | } |
495 | 472 | ||
496 | static struct rpc_task *__rpc_find_next_queued(struct rpc_wait_queue *queue) | ||
497 | { | ||
498 | if (RPC_IS_PRIORITY(queue)) | ||
499 | return __rpc_find_next_queued_priority(queue); | ||
500 | if (!list_empty(&queue->tasks[0])) | ||
501 | return list_first_entry(&queue->tasks[0], struct rpc_task, u.tk_wait.list); | ||
502 | return NULL; | ||
503 | } | ||
504 | |||
505 | /* | 473 | /* |
506 | * Wake up the first task on the wait queue. | 474 | * Wake up the next task on the wait queue. |
507 | */ | 475 | */ |
508 | struct rpc_task *rpc_wake_up_first(struct rpc_wait_queue *queue, | 476 | struct rpc_task * rpc_wake_up_next(struct rpc_wait_queue *queue) |
509 | bool (*func)(struct rpc_task *, void *), void *data) | ||
510 | { | 477 | { |
511 | struct rpc_task *task = NULL; | 478 | struct rpc_task *task = NULL; |
512 | 479 | ||
513 | dprintk("RPC: wake_up_first(%p \"%s\")\n", | 480 | dprintk("RPC: wake_up_next(%p \"%s\")\n", |
514 | queue, rpc_qname(queue)); | 481 | queue, rpc_qname(queue)); |
515 | spin_lock_bh(&queue->lock); | 482 | spin_lock_bh(&queue->lock); |
516 | task = __rpc_find_next_queued(queue); | 483 | if (RPC_IS_PRIORITY(queue)) |
517 | if (task != NULL) { | 484 | task = __rpc_wake_up_next_priority(queue); |
518 | if (func(task, data)) | 485 | else { |
486 | task_for_first(task, &queue->tasks[0]) | ||
519 | rpc_wake_up_task_queue_locked(queue, task); | 487 | rpc_wake_up_task_queue_locked(queue, task); |
520 | else | ||
521 | task = NULL; | ||
522 | } | 488 | } |
523 | spin_unlock_bh(&queue->lock); | 489 | spin_unlock_bh(&queue->lock); |
524 | 490 | ||
525 | return task; | 491 | return task; |
526 | } | 492 | } |
527 | EXPORT_SYMBOL_GPL(rpc_wake_up_first); | ||
528 | |||
529 | static bool rpc_wake_up_next_func(struct rpc_task *task, void *data) | ||
530 | { | ||
531 | return true; | ||
532 | } | ||
533 | |||
534 | /* | ||
535 | * Wake up the next task on the wait queue. | ||
536 | */ | ||
537 | struct rpc_task *rpc_wake_up_next(struct rpc_wait_queue *queue) | ||
538 | { | ||
539 | return rpc_wake_up_first(queue, rpc_wake_up_next_func, NULL); | ||
540 | } | ||
541 | EXPORT_SYMBOL_GPL(rpc_wake_up_next); | 493 | EXPORT_SYMBOL_GPL(rpc_wake_up_next); |
542 | 494 | ||
543 | /** | 495 | /** |
@@ -548,18 +500,14 @@ EXPORT_SYMBOL_GPL(rpc_wake_up_next); | |||
548 | */ | 500 | */ |
549 | void rpc_wake_up(struct rpc_wait_queue *queue) | 501 | void rpc_wake_up(struct rpc_wait_queue *queue) |
550 | { | 502 | { |
503 | struct rpc_task *task, *next; | ||
551 | struct list_head *head; | 504 | struct list_head *head; |
552 | 505 | ||
553 | spin_lock_bh(&queue->lock); | 506 | spin_lock_bh(&queue->lock); |
554 | head = &queue->tasks[queue->maxpriority]; | 507 | head = &queue->tasks[queue->maxpriority]; |
555 | for (;;) { | 508 | for (;;) { |
556 | while (!list_empty(head)) { | 509 | list_for_each_entry_safe(task, next, head, u.tk_wait.list) |
557 | struct rpc_task *task; | ||
558 | task = list_first_entry(head, | ||
559 | struct rpc_task, | ||
560 | u.tk_wait.list); | ||
561 | rpc_wake_up_task_queue_locked(queue, task); | 510 | rpc_wake_up_task_queue_locked(queue, task); |
562 | } | ||
563 | if (head == &queue->tasks[0]) | 511 | if (head == &queue->tasks[0]) |
564 | break; | 512 | break; |
565 | head--; | 513 | head--; |
@@ -577,16 +525,13 @@ EXPORT_SYMBOL_GPL(rpc_wake_up); | |||
577 | */ | 525 | */ |
578 | void rpc_wake_up_status(struct rpc_wait_queue *queue, int status) | 526 | void rpc_wake_up_status(struct rpc_wait_queue *queue, int status) |
579 | { | 527 | { |
528 | struct rpc_task *task, *next; | ||
580 | struct list_head *head; | 529 | struct list_head *head; |
581 | 530 | ||
582 | spin_lock_bh(&queue->lock); | 531 | spin_lock_bh(&queue->lock); |
583 | head = &queue->tasks[queue->maxpriority]; | 532 | head = &queue->tasks[queue->maxpriority]; |
584 | for (;;) { | 533 | for (;;) { |
585 | while (!list_empty(head)) { | 534 | list_for_each_entry_safe(task, next, head, u.tk_wait.list) { |
586 | struct rpc_task *task; | ||
587 | task = list_first_entry(head, | ||
588 | struct rpc_task, | ||
589 | u.tk_wait.list); | ||
590 | task->tk_status = status; | 535 | task->tk_status = status; |
591 | rpc_wake_up_task_queue_locked(queue, task); | 536 | rpc_wake_up_task_queue_locked(queue, task); |
592 | } | 537 | } |
@@ -645,27 +590,6 @@ void rpc_prepare_task(struct rpc_task *task) | |||
645 | task->tk_ops->rpc_call_prepare(task, task->tk_calldata); | 590 | task->tk_ops->rpc_call_prepare(task, task->tk_calldata); |
646 | } | 591 | } |
647 | 592 | ||
648 | static void | ||
649 | rpc_init_task_statistics(struct rpc_task *task) | ||
650 | { | ||
651 | /* Initialize retry counters */ | ||
652 | task->tk_garb_retry = 2; | ||
653 | task->tk_cred_retry = 2; | ||
654 | task->tk_rebind_retry = 2; | ||
655 | |||
656 | /* starting timestamp */ | ||
657 | task->tk_start = ktime_get(); | ||
658 | } | ||
659 | |||
660 | static void | ||
661 | rpc_reset_task_statistics(struct rpc_task *task) | ||
662 | { | ||
663 | task->tk_timeouts = 0; | ||
664 | task->tk_flags &= ~(RPC_CALL_MAJORSEEN|RPC_TASK_KILLED|RPC_TASK_SENT); | ||
665 | |||
666 | rpc_init_task_statistics(task); | ||
667 | } | ||
668 | |||
669 | /* | 593 | /* |
670 | * Helper that calls task->tk_ops->rpc_call_done if it exists | 594 | * Helper that calls task->tk_ops->rpc_call_done if it exists |
671 | */ | 595 | */ |
@@ -678,7 +602,6 @@ void rpc_exit_task(struct rpc_task *task) | |||
678 | WARN_ON(RPC_ASSASSINATED(task)); | 602 | WARN_ON(RPC_ASSASSINATED(task)); |
679 | /* Always release the RPC slot and buffer memory */ | 603 | /* Always release the RPC slot and buffer memory */ |
680 | xprt_release(task); | 604 | xprt_release(task); |
681 | rpc_reset_task_statistics(task); | ||
682 | } | 605 | } |
683 | } | 606 | } |
684 | } | 607 | } |
@@ -710,9 +633,7 @@ static void __rpc_execute(struct rpc_task *task) | |||
710 | dprintk("RPC: %5u __rpc_execute flags=0x%x\n", | 633 | dprintk("RPC: %5u __rpc_execute flags=0x%x\n", |
711 | task->tk_pid, task->tk_flags); | 634 | task->tk_pid, task->tk_flags); |
712 | 635 | ||
713 | WARN_ON_ONCE(RPC_IS_QUEUED(task)); | 636 | BUG_ON(RPC_IS_QUEUED(task)); |
714 | if (RPC_IS_QUEUED(task)) | ||
715 | return; | ||
716 | 637 | ||
717 | for (;;) { | 638 | for (;;) { |
718 | void (*do_action)(struct rpc_task *); | 639 | void (*do_action)(struct rpc_task *); |
@@ -733,7 +654,6 @@ static void __rpc_execute(struct rpc_task *task) | |||
733 | if (do_action == NULL) | 654 | if (do_action == NULL) |
734 | break; | 655 | break; |
735 | } | 656 | } |
736 | trace_rpc_task_run_action(task->tk_client, task, task->tk_action); | ||
737 | do_action(task); | 657 | do_action(task); |
738 | 658 | ||
739 | /* | 659 | /* |
@@ -806,9 +726,7 @@ void rpc_execute(struct rpc_task *task) | |||
806 | 726 | ||
807 | static void rpc_async_schedule(struct work_struct *work) | 727 | static void rpc_async_schedule(struct work_struct *work) |
808 | { | 728 | { |
809 | current->flags |= PF_FSTRANS; | ||
810 | __rpc_execute(container_of(work, struct rpc_task, u.tk_work)); | 729 | __rpc_execute(container_of(work, struct rpc_task, u.tk_work)); |
811 | current->flags &= ~PF_FSTRANS; | ||
812 | } | 730 | } |
813 | 731 | ||
814 | /** | 732 | /** |
@@ -830,10 +748,7 @@ static void rpc_async_schedule(struct work_struct *work) | |||
830 | void *rpc_malloc(struct rpc_task *task, size_t size) | 748 | void *rpc_malloc(struct rpc_task *task, size_t size) |
831 | { | 749 | { |
832 | struct rpc_buffer *buf; | 750 | struct rpc_buffer *buf; |
833 | gfp_t gfp = GFP_NOWAIT; | 751 | gfp_t gfp = RPC_IS_SWAPPER(task) ? GFP_ATOMIC : GFP_NOWAIT; |
834 | |||
835 | if (RPC_IS_SWAPPER(task)) | ||
836 | gfp |= __GFP_MEMALLOC; | ||
837 | 752 | ||
838 | size += sizeof(struct rpc_buffer); | 753 | size += sizeof(struct rpc_buffer); |
839 | if (size <= RPC_BUFFER_MAXSIZE) | 754 | if (size <= RPC_BUFFER_MAXSIZE) |
@@ -889,6 +804,11 @@ static void rpc_init_task(struct rpc_task *task, const struct rpc_task_setup *ta | |||
889 | task->tk_calldata = task_setup_data->callback_data; | 804 | task->tk_calldata = task_setup_data->callback_data; |
890 | INIT_LIST_HEAD(&task->tk_task); | 805 | INIT_LIST_HEAD(&task->tk_task); |
891 | 806 | ||
807 | /* Initialize retry counters */ | ||
808 | task->tk_garb_retry = 2; | ||
809 | task->tk_cred_retry = 2; | ||
810 | task->tk_rebind_retry = 2; | ||
811 | |||
892 | task->tk_priority = task_setup_data->priority - RPC_PRIORITY_LOW; | 812 | task->tk_priority = task_setup_data->priority - RPC_PRIORITY_LOW; |
893 | task->tk_owner = current->tgid; | 813 | task->tk_owner = current->tgid; |
894 | 814 | ||
@@ -898,7 +818,8 @@ static void rpc_init_task(struct rpc_task *task, const struct rpc_task_setup *ta | |||
898 | if (task->tk_ops->rpc_call_prepare != NULL) | 818 | if (task->tk_ops->rpc_call_prepare != NULL) |
899 | task->tk_action = rpc_prepare_task; | 819 | task->tk_action = rpc_prepare_task; |
900 | 820 | ||
901 | rpc_init_task_statistics(task); | 821 | /* starting timestamp */ |
822 | task->tk_start = ktime_get(); | ||
902 | 823 | ||
903 | dprintk("RPC: new task initialized, procpid %u\n", | 824 | dprintk("RPC: new task initialized, procpid %u\n", |
904 | task_pid_nr(current)); | 825 | task_pid_nr(current)); |
@@ -907,7 +828,7 @@ static void rpc_init_task(struct rpc_task *task, const struct rpc_task_setup *ta | |||
907 | static struct rpc_task * | 828 | static struct rpc_task * |
908 | rpc_alloc_task(void) | 829 | rpc_alloc_task(void) |
909 | { | 830 | { |
910 | return (struct rpc_task *)mempool_alloc(rpc_task_mempool, GFP_NOIO); | 831 | return (struct rpc_task *)mempool_alloc(rpc_task_mempool, GFP_NOFS); |
911 | } | 832 | } |
912 | 833 | ||
913 | /* | 834 | /* |
@@ -934,35 +855,16 @@ struct rpc_task *rpc_new_task(const struct rpc_task_setup *setup_data) | |||
934 | return task; | 855 | return task; |
935 | } | 856 | } |
936 | 857 | ||
937 | /* | ||
938 | * rpc_free_task - release rpc task and perform cleanups | ||
939 | * | ||
940 | * Note that we free up the rpc_task _after_ rpc_release_calldata() | ||
941 | * in order to work around a workqueue dependency issue. | ||
942 | * | ||
943 | * Tejun Heo states: | ||
944 | * "Workqueue currently considers two work items to be the same if they're | ||
945 | * on the same address and won't execute them concurrently - ie. it | ||
946 | * makes a work item which is queued again while being executed wait | ||
947 | * for the previous execution to complete. | ||
948 | * | ||
949 | * If a work function frees the work item, and then waits for an event | ||
950 | * which should be performed by another work item and *that* work item | ||
951 | * recycles the freed work item, it can create a false dependency loop. | ||
952 | * There really is no reliable way to detect this short of verifying | ||
953 | * every memory free." | ||
954 | * | ||
955 | */ | ||
956 | static void rpc_free_task(struct rpc_task *task) | 858 | static void rpc_free_task(struct rpc_task *task) |
957 | { | 859 | { |
958 | unsigned short tk_flags = task->tk_flags; | 860 | const struct rpc_call_ops *tk_ops = task->tk_ops; |
959 | 861 | void *calldata = task->tk_calldata; | |
960 | rpc_release_calldata(task->tk_ops, task->tk_calldata); | ||
961 | 862 | ||
962 | if (tk_flags & RPC_TASK_DYNAMIC) { | 863 | if (task->tk_flags & RPC_TASK_DYNAMIC) { |
963 | dprintk("RPC: %5u freeing task\n", task->tk_pid); | 864 | dprintk("RPC: %5u freeing task\n", task->tk_pid); |
964 | mempool_free(task, rpc_task_mempool); | 865 | mempool_free(task, rpc_task_mempool); |
965 | } | 866 | } |
867 | rpc_release_calldata(tk_ops, calldata); | ||
966 | } | 868 | } |
967 | 869 | ||
968 | static void rpc_async_release(struct work_struct *work) | 870 | static void rpc_async_release(struct work_struct *work) |
@@ -972,7 +874,8 @@ static void rpc_async_release(struct work_struct *work) | |||
972 | 874 | ||
973 | static void rpc_release_resources_task(struct rpc_task *task) | 875 | static void rpc_release_resources_task(struct rpc_task *task) |
974 | { | 876 | { |
975 | xprt_release(task); | 877 | if (task->tk_rqstp) |
878 | xprt_release(task); | ||
976 | if (task->tk_msg.rpc_cred) { | 879 | if (task->tk_msg.rpc_cred) { |
977 | put_rpccred(task->tk_msg.rpc_cred); | 880 | put_rpccred(task->tk_msg.rpc_cred); |
978 | task->tk_msg.rpc_cred = NULL; | 881 | task->tk_msg.rpc_cred = NULL; |
@@ -1014,7 +917,7 @@ static void rpc_release_task(struct rpc_task *task) | |||
1014 | { | 917 | { |
1015 | dprintk("RPC: %5u release task\n", task->tk_pid); | 918 | dprintk("RPC: %5u release task\n", task->tk_pid); |
1016 | 919 | ||
1017 | WARN_ON_ONCE(RPC_IS_QUEUED(task)); | 920 | BUG_ON (RPC_IS_QUEUED(task)); |
1018 | 921 | ||
1019 | rpc_release_resources_task(task); | 922 | rpc_release_resources_task(task); |
1020 | 923 | ||
@@ -1055,7 +958,7 @@ static int rpciod_start(void) | |||
1055 | * Create the rpciod thread and wait for it to start. | 958 | * Create the rpciod thread and wait for it to start. |
1056 | */ | 959 | */ |
1057 | dprintk("RPC: creating workqueue rpciod\n"); | 960 | dprintk("RPC: creating workqueue rpciod\n"); |
1058 | wq = alloc_workqueue("rpciod", WQ_MEM_RECLAIM, 1); | 961 | wq = alloc_workqueue("rpciod", WQ_MEM_RECLAIM, 0); |
1059 | rpciod_workqueue = wq; | 962 | rpciod_workqueue = wq; |
1060 | return rpciod_workqueue != NULL; | 963 | return rpciod_workqueue != NULL; |
1061 | } | 964 | } |
diff --git a/net/sunrpc/socklib.c b/net/sunrpc/socklib.c index 0a648c502fc..10b4319ebbc 100644 --- a/net/sunrpc/socklib.c +++ b/net/sunrpc/socklib.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <linux/pagemap.h> | 14 | #include <linux/pagemap.h> |
15 | #include <linux/udp.h> | 15 | #include <linux/udp.h> |
16 | #include <linux/sunrpc/xdr.h> | 16 | #include <linux/sunrpc/xdr.h> |
17 | #include <linux/export.h> | ||
18 | 17 | ||
19 | 18 | ||
20 | /** | 19 | /** |
@@ -114,7 +113,7 @@ ssize_t xdr_partial_copy_from_skb(struct xdr_buf *xdr, unsigned int base, struct | |||
114 | } | 113 | } |
115 | 114 | ||
116 | len = PAGE_CACHE_SIZE; | 115 | len = PAGE_CACHE_SIZE; |
117 | kaddr = kmap_atomic(*ppage); | 116 | kaddr = kmap_atomic(*ppage, KM_SKB_SUNRPC_DATA); |
118 | if (base) { | 117 | if (base) { |
119 | len -= base; | 118 | len -= base; |
120 | if (pglen < len) | 119 | if (pglen < len) |
@@ -127,7 +126,7 @@ ssize_t xdr_partial_copy_from_skb(struct xdr_buf *xdr, unsigned int base, struct | |||
127 | ret = copy_actor(desc, kaddr, len); | 126 | ret = copy_actor(desc, kaddr, len); |
128 | } | 127 | } |
129 | flush_dcache_page(*ppage); | 128 | flush_dcache_page(*ppage); |
130 | kunmap_atomic(kaddr); | 129 | kunmap_atomic(kaddr, KM_SKB_SUNRPC_DATA); |
131 | copied += ret; | 130 | copied += ret; |
132 | if (ret != len || !desc->count) | 131 | if (ret != len || !desc->count) |
133 | goto out; | 132 | goto out; |
diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c index bc2068ee795..80df89d957b 100644 --- a/net/sunrpc/stats.c +++ b/net/sunrpc/stats.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include <linux/sunrpc/clnt.h> | 22 | #include <linux/sunrpc/clnt.h> |
23 | #include <linux/sunrpc/svcsock.h> | 23 | #include <linux/sunrpc/svcsock.h> |
24 | #include <linux/sunrpc/metrics.h> | 24 | #include <linux/sunrpc/metrics.h> |
25 | #include <linux/rcupdate.h> | ||
26 | 25 | ||
27 | #include "netns.h" | 26 | #include "netns.h" |
28 | 27 | ||
@@ -134,19 +133,20 @@ EXPORT_SYMBOL_GPL(rpc_free_iostats); | |||
134 | /** | 133 | /** |
135 | * rpc_count_iostats - tally up per-task stats | 134 | * rpc_count_iostats - tally up per-task stats |
136 | * @task: completed rpc_task | 135 | * @task: completed rpc_task |
137 | * @stats: array of stat structures | ||
138 | * | 136 | * |
139 | * Relies on the caller for serialization. | 137 | * Relies on the caller for serialization. |
140 | */ | 138 | */ |
141 | void rpc_count_iostats(const struct rpc_task *task, struct rpc_iostats *stats) | 139 | void rpc_count_iostats(struct rpc_task *task) |
142 | { | 140 | { |
143 | struct rpc_rqst *req = task->tk_rqstp; | 141 | struct rpc_rqst *req = task->tk_rqstp; |
142 | struct rpc_iostats *stats; | ||
144 | struct rpc_iostats *op_metrics; | 143 | struct rpc_iostats *op_metrics; |
145 | ktime_t delta; | 144 | ktime_t delta; |
146 | 145 | ||
147 | if (!stats || !req) | 146 | if (!task->tk_client || !task->tk_client->cl_metrics || !req) |
148 | return; | 147 | return; |
149 | 148 | ||
149 | stats = task->tk_client->cl_metrics; | ||
150 | op_metrics = &stats[task->tk_msg.rpc_proc->p_statidx]; | 150 | op_metrics = &stats[task->tk_msg.rpc_proc->p_statidx]; |
151 | 151 | ||
152 | op_metrics->om_ops++; | 152 | op_metrics->om_ops++; |
@@ -164,7 +164,6 @@ void rpc_count_iostats(const struct rpc_task *task, struct rpc_iostats *stats) | |||
164 | delta = ktime_sub(ktime_get(), task->tk_start); | 164 | delta = ktime_sub(ktime_get(), task->tk_start); |
165 | op_metrics->om_execute = ktime_add(op_metrics->om_execute, delta); | 165 | op_metrics->om_execute = ktime_add(op_metrics->om_execute, delta); |
166 | } | 166 | } |
167 | EXPORT_SYMBOL_GPL(rpc_count_iostats); | ||
168 | 167 | ||
169 | static void _print_name(struct seq_file *seq, unsigned int op, | 168 | static void _print_name(struct seq_file *seq, unsigned int op, |
170 | struct rpc_procinfo *procs) | 169 | struct rpc_procinfo *procs) |
@@ -180,7 +179,7 @@ static void _print_name(struct seq_file *seq, unsigned int op, | |||
180 | void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt) | 179 | void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt) |
181 | { | 180 | { |
182 | struct rpc_iostats *stats = clnt->cl_metrics; | 181 | struct rpc_iostats *stats = clnt->cl_metrics; |
183 | struct rpc_xprt *xprt; | 182 | struct rpc_xprt *xprt = clnt->cl_xprt; |
184 | unsigned int op, maxproc = clnt->cl_maxproc; | 183 | unsigned int op, maxproc = clnt->cl_maxproc; |
185 | 184 | ||
186 | if (!stats) | 185 | if (!stats) |
@@ -190,11 +189,8 @@ void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt) | |||
190 | seq_printf(seq, "p/v: %u/%u (%s)\n", | 189 | seq_printf(seq, "p/v: %u/%u (%s)\n", |
191 | clnt->cl_prog, clnt->cl_vers, clnt->cl_protname); | 190 | clnt->cl_prog, clnt->cl_vers, clnt->cl_protname); |
192 | 191 | ||
193 | rcu_read_lock(); | ||
194 | xprt = rcu_dereference(clnt->cl_xprt); | ||
195 | if (xprt) | 192 | if (xprt) |
196 | xprt->ops->print_stats(xprt, seq); | 193 | xprt->ops->print_stats(xprt, seq); |
197 | rcu_read_unlock(); | ||
198 | 194 | ||
199 | seq_printf(seq, "\tper-op statistics\n"); | 195 | seq_printf(seq, "\tper-op statistics\n"); |
200 | for (op = 0; op < maxproc; op++) { | 196 | for (op = 0; op < maxproc; op++) { |
@@ -217,46 +213,45 @@ EXPORT_SYMBOL_GPL(rpc_print_iostats); | |||
217 | * Register/unregister RPC proc files | 213 | * Register/unregister RPC proc files |
218 | */ | 214 | */ |
219 | static inline struct proc_dir_entry * | 215 | static inline struct proc_dir_entry * |
220 | do_register(struct net *net, const char *name, void *data, | 216 | do_register(const char *name, void *data, const struct file_operations *fops) |
221 | const struct file_operations *fops) | ||
222 | { | 217 | { |
223 | struct sunrpc_net *sn; | 218 | struct sunrpc_net *sn; |
224 | 219 | ||
225 | dprintk("RPC: registering /proc/net/rpc/%s\n", name); | 220 | dprintk("RPC: registering /proc/net/rpc/%s\n", name); |
226 | sn = net_generic(net, sunrpc_net_id); | 221 | sn = net_generic(&init_net, sunrpc_net_id); |
227 | return proc_create_data(name, 0, sn->proc_net_rpc, fops, data); | 222 | return proc_create_data(name, 0, sn->proc_net_rpc, fops, data); |
228 | } | 223 | } |
229 | 224 | ||
230 | struct proc_dir_entry * | 225 | struct proc_dir_entry * |
231 | rpc_proc_register(struct net *net, struct rpc_stat *statp) | 226 | rpc_proc_register(struct rpc_stat *statp) |
232 | { | 227 | { |
233 | return do_register(net, statp->program->name, statp, &rpc_proc_fops); | 228 | return do_register(statp->program->name, statp, &rpc_proc_fops); |
234 | } | 229 | } |
235 | EXPORT_SYMBOL_GPL(rpc_proc_register); | 230 | EXPORT_SYMBOL_GPL(rpc_proc_register); |
236 | 231 | ||
237 | void | 232 | void |
238 | rpc_proc_unregister(struct net *net, const char *name) | 233 | rpc_proc_unregister(const char *name) |
239 | { | 234 | { |
240 | struct sunrpc_net *sn; | 235 | struct sunrpc_net *sn; |
241 | 236 | ||
242 | sn = net_generic(net, sunrpc_net_id); | 237 | sn = net_generic(&init_net, sunrpc_net_id); |
243 | remove_proc_entry(name, sn->proc_net_rpc); | 238 | remove_proc_entry(name, sn->proc_net_rpc); |
244 | } | 239 | } |
245 | EXPORT_SYMBOL_GPL(rpc_proc_unregister); | 240 | EXPORT_SYMBOL_GPL(rpc_proc_unregister); |
246 | 241 | ||
247 | struct proc_dir_entry * | 242 | struct proc_dir_entry * |
248 | svc_proc_register(struct net *net, struct svc_stat *statp, const struct file_operations *fops) | 243 | svc_proc_register(struct svc_stat *statp, const struct file_operations *fops) |
249 | { | 244 | { |
250 | return do_register(net, statp->program->pg_name, statp, fops); | 245 | return do_register(statp->program->pg_name, statp, fops); |
251 | } | 246 | } |
252 | EXPORT_SYMBOL_GPL(svc_proc_register); | 247 | EXPORT_SYMBOL_GPL(svc_proc_register); |
253 | 248 | ||
254 | void | 249 | void |
255 | svc_proc_unregister(struct net *net, const char *name) | 250 | svc_proc_unregister(const char *name) |
256 | { | 251 | { |
257 | struct sunrpc_net *sn; | 252 | struct sunrpc_net *sn; |
258 | 253 | ||
259 | sn = net_generic(net, sunrpc_net_id); | 254 | sn = net_generic(&init_net, sunrpc_net_id); |
260 | remove_proc_entry(name, sn->proc_net_rpc); | 255 | remove_proc_entry(name, sn->proc_net_rpc); |
261 | } | 256 | } |
262 | EXPORT_SYMBOL_GPL(svc_proc_unregister); | 257 | EXPORT_SYMBOL_GPL(svc_proc_unregister); |
diff --git a/net/sunrpc/sunrpc.h b/net/sunrpc/sunrpc.h index 14c9f6d1c5f..90c292e2738 100644 --- a/net/sunrpc/sunrpc.h +++ b/net/sunrpc/sunrpc.h | |||
@@ -47,7 +47,5 @@ int svc_send_common(struct socket *sock, struct xdr_buf *xdr, | |||
47 | struct page *headpage, unsigned long headoffset, | 47 | struct page *headpage, unsigned long headoffset, |
48 | struct page *tailpage, unsigned long tailoffset); | 48 | struct page *tailpage, unsigned long tailoffset); |
49 | 49 | ||
50 | int rpc_clients_notifier_register(void); | ||
51 | void rpc_clients_notifier_unregister(void); | ||
52 | #endif /* _NET_SUNRPC_SUNRPC_H */ | 50 | #endif /* _NET_SUNRPC_SUNRPC_H */ |
53 | 51 | ||
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c index 3d6498af9ad..9d080916099 100644 --- a/net/sunrpc/sunrpc_syms.c +++ b/net/sunrpc/sunrpc_syms.c | |||
@@ -25,12 +25,10 @@ | |||
25 | #include "netns.h" | 25 | #include "netns.h" |
26 | 26 | ||
27 | int sunrpc_net_id; | 27 | int sunrpc_net_id; |
28 | EXPORT_SYMBOL_GPL(sunrpc_net_id); | ||
29 | 28 | ||
30 | static __net_init int sunrpc_init_net(struct net *net) | 29 | static __net_init int sunrpc_init_net(struct net *net) |
31 | { | 30 | { |
32 | int err; | 31 | int err; |
33 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
34 | 32 | ||
35 | err = rpc_proc_init(net); | 33 | err = rpc_proc_init(net); |
36 | if (err) | 34 | if (err) |
@@ -40,18 +38,8 @@ static __net_init int sunrpc_init_net(struct net *net) | |||
40 | if (err) | 38 | if (err) |
41 | goto err_ipmap; | 39 | goto err_ipmap; |
42 | 40 | ||
43 | err = unix_gid_cache_create(net); | ||
44 | if (err) | ||
45 | goto err_unixgid; | ||
46 | |||
47 | rpc_pipefs_init_net(net); | ||
48 | INIT_LIST_HEAD(&sn->all_clients); | ||
49 | spin_lock_init(&sn->rpc_client_lock); | ||
50 | spin_lock_init(&sn->rpcb_clnt_lock); | ||
51 | return 0; | 41 | return 0; |
52 | 42 | ||
53 | err_unixgid: | ||
54 | ip_map_cache_destroy(net); | ||
55 | err_ipmap: | 43 | err_ipmap: |
56 | rpc_proc_exit(net); | 44 | rpc_proc_exit(net); |
57 | err_proc: | 45 | err_proc: |
@@ -60,7 +48,6 @@ err_proc: | |||
60 | 48 | ||
61 | static __net_exit void sunrpc_exit_net(struct net *net) | 49 | static __net_exit void sunrpc_exit_net(struct net *net) |
62 | { | 50 | { |
63 | unix_gid_cache_destroy(net); | ||
64 | ip_map_cache_destroy(net); | 51 | ip_map_cache_destroy(net); |
65 | rpc_proc_exit(net); | 52 | rpc_proc_exit(net); |
66 | } | 53 | } |
@@ -72,38 +59,42 @@ static struct pernet_operations sunrpc_net_ops = { | |||
72 | .size = sizeof(struct sunrpc_net), | 59 | .size = sizeof(struct sunrpc_net), |
73 | }; | 60 | }; |
74 | 61 | ||
62 | extern struct cache_detail unix_gid_cache; | ||
63 | |||
64 | extern void cleanup_rpcb_clnt(void); | ||
65 | |||
75 | static int __init | 66 | static int __init |
76 | init_sunrpc(void) | 67 | init_sunrpc(void) |
77 | { | 68 | { |
78 | int err = rpc_init_mempool(); | 69 | int err = register_rpc_pipefs(); |
79 | if (err) | 70 | if (err) |
80 | goto out; | 71 | goto out; |
81 | err = rpcauth_init_module(); | 72 | err = rpc_init_mempool(); |
82 | if (err) | 73 | if (err) |
83 | goto out2; | 74 | goto out2; |
75 | err = rpcauth_init_module(); | ||
76 | if (err) | ||
77 | goto out3; | ||
84 | 78 | ||
85 | cache_initialize(); | 79 | cache_initialize(); |
86 | 80 | ||
87 | err = register_pernet_subsys(&sunrpc_net_ops); | 81 | err = register_pernet_subsys(&sunrpc_net_ops); |
88 | if (err) | 82 | if (err) |
89 | goto out3; | ||
90 | |||
91 | err = register_rpc_pipefs(); | ||
92 | if (err) | ||
93 | goto out4; | 83 | goto out4; |
94 | #ifdef RPC_DEBUG | 84 | #ifdef RPC_DEBUG |
95 | rpc_register_sysctl(); | 85 | rpc_register_sysctl(); |
96 | #endif | 86 | #endif |
87 | cache_register(&unix_gid_cache); | ||
97 | svc_init_xprt_sock(); /* svc sock transport */ | 88 | svc_init_xprt_sock(); /* svc sock transport */ |
98 | init_socket_xprt(); /* clnt sock transport */ | 89 | init_socket_xprt(); /* clnt sock transport */ |
99 | return 0; | 90 | return 0; |
100 | 91 | ||
101 | out4: | 92 | out4: |
102 | unregister_pernet_subsys(&sunrpc_net_ops); | ||
103 | out3: | ||
104 | rpcauth_remove_module(); | 93 | rpcauth_remove_module(); |
105 | out2: | 94 | out3: |
106 | rpc_destroy_mempool(); | 95 | rpc_destroy_mempool(); |
96 | out2: | ||
97 | unregister_rpc_pipefs(); | ||
107 | out: | 98 | out: |
108 | return err; | 99 | return err; |
109 | } | 100 | } |
@@ -111,11 +102,13 @@ out: | |||
111 | static void __exit | 102 | static void __exit |
112 | cleanup_sunrpc(void) | 103 | cleanup_sunrpc(void) |
113 | { | 104 | { |
105 | cleanup_rpcb_clnt(); | ||
114 | rpcauth_remove_module(); | 106 | rpcauth_remove_module(); |
115 | cleanup_socket_xprt(); | 107 | cleanup_socket_xprt(); |
116 | svc_cleanup_xprt_sock(); | 108 | svc_cleanup_xprt_sock(); |
117 | unregister_rpc_pipefs(); | 109 | unregister_rpc_pipefs(); |
118 | rpc_destroy_mempool(); | 110 | rpc_destroy_mempool(); |
111 | cache_unregister(&unix_gid_cache); | ||
119 | unregister_pernet_subsys(&sunrpc_net_ops); | 112 | unregister_pernet_subsys(&sunrpc_net_ops); |
120 | #ifdef RPC_DEBUG | 113 | #ifdef RPC_DEBUG |
121 | rpc_unregister_sysctl(); | 114 | rpc_unregister_sysctl(); |
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index dbf12ac5ecb..6a69a1131fb 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c | |||
@@ -30,7 +30,7 @@ | |||
30 | 30 | ||
31 | #define RPCDBG_FACILITY RPCDBG_SVCDSP | 31 | #define RPCDBG_FACILITY RPCDBG_SVCDSP |
32 | 32 | ||
33 | static void svc_unregister(const struct svc_serv *serv, struct net *net); | 33 | static void svc_unregister(const struct svc_serv *serv); |
34 | 34 | ||
35 | #define svc_serv_is_pooled(serv) ((serv)->sv_function) | 35 | #define svc_serv_is_pooled(serv) ((serv)->sv_function) |
36 | 36 | ||
@@ -167,7 +167,6 @@ svc_pool_map_alloc_arrays(struct svc_pool_map *m, unsigned int maxpools) | |||
167 | 167 | ||
168 | fail_free: | 168 | fail_free: |
169 | kfree(m->to_pool); | 169 | kfree(m->to_pool); |
170 | m->to_pool = NULL; | ||
171 | fail: | 170 | fail: |
172 | return -ENOMEM; | 171 | return -ENOMEM; |
173 | } | 172 | } |
@@ -286,10 +285,9 @@ svc_pool_map_put(void) | |||
286 | mutex_lock(&svc_pool_map_mutex); | 285 | mutex_lock(&svc_pool_map_mutex); |
287 | 286 | ||
288 | if (!--m->count) { | 287 | if (!--m->count) { |
288 | m->mode = SVC_POOL_DEFAULT; | ||
289 | kfree(m->to_pool); | 289 | kfree(m->to_pool); |
290 | m->to_pool = NULL; | ||
291 | kfree(m->pool_to); | 290 | kfree(m->pool_to); |
292 | m->pool_to = NULL; | ||
293 | m->npools = 0; | 291 | m->npools = 0; |
294 | } | 292 | } |
295 | 293 | ||
@@ -297,18 +295,6 @@ svc_pool_map_put(void) | |||
297 | } | 295 | } |
298 | 296 | ||
299 | 297 | ||
300 | static int svc_pool_map_get_node(unsigned int pidx) | ||
301 | { | ||
302 | const struct svc_pool_map *m = &svc_pool_map; | ||
303 | |||
304 | if (m->count) { | ||
305 | if (m->mode == SVC_POOL_PERCPU) | ||
306 | return cpu_to_node(m->pool_to[pidx]); | ||
307 | if (m->mode == SVC_POOL_PERNODE) | ||
308 | return m->pool_to[pidx]; | ||
309 | } | ||
310 | return NUMA_NO_NODE; | ||
311 | } | ||
312 | /* | 298 | /* |
313 | * Set the given thread's cpus_allowed mask so that it | 299 | * Set the given thread's cpus_allowed mask so that it |
314 | * will only run on cpus in the given pool. | 300 | * will only run on cpus in the given pool. |
@@ -323,9 +309,7 @@ svc_pool_map_set_cpumask(struct task_struct *task, unsigned int pidx) | |||
323 | * The caller checks for sv_nrpools > 1, which | 309 | * The caller checks for sv_nrpools > 1, which |
324 | * implies that we've been initialized. | 310 | * implies that we've been initialized. |
325 | */ | 311 | */ |
326 | WARN_ON_ONCE(m->count == 0); | 312 | BUG_ON(m->count == 0); |
327 | if (m->count == 0) | ||
328 | return; | ||
329 | 313 | ||
330 | switch (m->mode) { | 314 | switch (m->mode) { |
331 | case SVC_POOL_PERCPU: | 315 | case SVC_POOL_PERCPU: |
@@ -370,58 +354,13 @@ svc_pool_for_cpu(struct svc_serv *serv, int cpu) | |||
370 | return &serv->sv_pools[pidx % serv->sv_nrpools]; | 354 | return &serv->sv_pools[pidx % serv->sv_nrpools]; |
371 | } | 355 | } |
372 | 356 | ||
373 | int svc_rpcb_setup(struct svc_serv *serv, struct net *net) | ||
374 | { | ||
375 | int err; | ||
376 | |||
377 | err = rpcb_create_local(net); | ||
378 | if (err) | ||
379 | return err; | ||
380 | |||
381 | /* Remove any stale portmap registrations */ | ||
382 | svc_unregister(serv, net); | ||
383 | return 0; | ||
384 | } | ||
385 | EXPORT_SYMBOL_GPL(svc_rpcb_setup); | ||
386 | |||
387 | void svc_rpcb_cleanup(struct svc_serv *serv, struct net *net) | ||
388 | { | ||
389 | svc_unregister(serv, net); | ||
390 | rpcb_put_local(net); | ||
391 | } | ||
392 | EXPORT_SYMBOL_GPL(svc_rpcb_cleanup); | ||
393 | |||
394 | static int svc_uses_rpcbind(struct svc_serv *serv) | ||
395 | { | ||
396 | struct svc_program *progp; | ||
397 | unsigned int i; | ||
398 | |||
399 | for (progp = serv->sv_program; progp; progp = progp->pg_next) { | ||
400 | for (i = 0; i < progp->pg_nvers; i++) { | ||
401 | if (progp->pg_vers[i] == NULL) | ||
402 | continue; | ||
403 | if (progp->pg_vers[i]->vs_hidden == 0) | ||
404 | return 1; | ||
405 | } | ||
406 | } | ||
407 | |||
408 | return 0; | ||
409 | } | ||
410 | |||
411 | int svc_bind(struct svc_serv *serv, struct net *net) | ||
412 | { | ||
413 | if (!svc_uses_rpcbind(serv)) | ||
414 | return 0; | ||
415 | return svc_rpcb_setup(serv, net); | ||
416 | } | ||
417 | EXPORT_SYMBOL_GPL(svc_bind); | ||
418 | 357 | ||
419 | /* | 358 | /* |
420 | * Create an RPC service | 359 | * Create an RPC service |
421 | */ | 360 | */ |
422 | static struct svc_serv * | 361 | static struct svc_serv * |
423 | __svc_create(struct svc_program *prog, unsigned int bufsize, int npools, | 362 | __svc_create(struct svc_program *prog, unsigned int bufsize, int npools, |
424 | void (*shutdown)(struct svc_serv *serv, struct net *net)) | 363 | void (*shutdown)(struct svc_serv *serv)) |
425 | { | 364 | { |
426 | struct svc_serv *serv; | 365 | struct svc_serv *serv; |
427 | unsigned int vers; | 366 | unsigned int vers; |
@@ -480,15 +419,15 @@ __svc_create(struct svc_program *prog, unsigned int bufsize, int npools, | |||
480 | spin_lock_init(&pool->sp_lock); | 419 | spin_lock_init(&pool->sp_lock); |
481 | } | 420 | } |
482 | 421 | ||
483 | if (svc_uses_rpcbind(serv) && (!serv->sv_shutdown)) | 422 | /* Remove any stale portmap registrations */ |
484 | serv->sv_shutdown = svc_rpcb_cleanup; | 423 | svc_unregister(serv); |
485 | 424 | ||
486 | return serv; | 425 | return serv; |
487 | } | 426 | } |
488 | 427 | ||
489 | struct svc_serv * | 428 | struct svc_serv * |
490 | svc_create(struct svc_program *prog, unsigned int bufsize, | 429 | svc_create(struct svc_program *prog, unsigned int bufsize, |
491 | void (*shutdown)(struct svc_serv *serv, struct net *net)) | 430 | void (*shutdown)(struct svc_serv *serv)) |
492 | { | 431 | { |
493 | return __svc_create(prog, bufsize, /*npools*/1, shutdown); | 432 | return __svc_create(prog, bufsize, /*npools*/1, shutdown); |
494 | } | 433 | } |
@@ -496,7 +435,7 @@ EXPORT_SYMBOL_GPL(svc_create); | |||
496 | 435 | ||
497 | struct svc_serv * | 436 | struct svc_serv * |
498 | svc_create_pooled(struct svc_program *prog, unsigned int bufsize, | 437 | svc_create_pooled(struct svc_program *prog, unsigned int bufsize, |
499 | void (*shutdown)(struct svc_serv *serv, struct net *net), | 438 | void (*shutdown)(struct svc_serv *serv), |
500 | svc_thread_fn func, struct module *mod) | 439 | svc_thread_fn func, struct module *mod) |
501 | { | 440 | { |
502 | struct svc_serv *serv; | 441 | struct svc_serv *serv; |
@@ -513,24 +452,6 @@ svc_create_pooled(struct svc_program *prog, unsigned int bufsize, | |||
513 | } | 452 | } |
514 | EXPORT_SYMBOL_GPL(svc_create_pooled); | 453 | EXPORT_SYMBOL_GPL(svc_create_pooled); |
515 | 454 | ||
516 | void svc_shutdown_net(struct svc_serv *serv, struct net *net) | ||
517 | { | ||
518 | /* | ||
519 | * The set of xprts (contained in the sv_tempsocks and | ||
520 | * sv_permsocks lists) is now constant, since it is modified | ||
521 | * only by accepting new sockets (done by service threads in | ||
522 | * svc_recv) or aging old ones (done by sv_temptimer), or | ||
523 | * configuration changes (excluded by whatever locking the | ||
524 | * caller is using--nfsd_mutex in the case of nfsd). So it's | ||
525 | * safe to traverse those lists and shut everything down: | ||
526 | */ | ||
527 | svc_close_net(serv, net); | ||
528 | |||
529 | if (serv->sv_shutdown) | ||
530 | serv->sv_shutdown(serv, net); | ||
531 | } | ||
532 | EXPORT_SYMBOL_GPL(svc_shutdown_net); | ||
533 | |||
534 | /* | 455 | /* |
535 | * Destroy an RPC service. Should be called with appropriate locking to | 456 | * Destroy an RPC service. Should be called with appropriate locking to |
536 | * protect the sv_nrthreads, sv_permsocks and sv_tempsocks. | 457 | * protect the sv_nrthreads, sv_permsocks and sv_tempsocks. |
@@ -552,10 +473,13 @@ svc_destroy(struct svc_serv *serv) | |||
552 | 473 | ||
553 | del_timer_sync(&serv->sv_temptimer); | 474 | del_timer_sync(&serv->sv_temptimer); |
554 | 475 | ||
555 | /* | 476 | svc_close_all(&serv->sv_tempsocks); |
556 | * The last user is gone and thus all sockets have to be destroyed to | 477 | |
557 | * the point. Check this. | 478 | if (serv->sv_shutdown) |
558 | */ | 479 | serv->sv_shutdown(serv); |
480 | |||
481 | svc_close_all(&serv->sv_permsocks); | ||
482 | |||
559 | BUG_ON(!list_empty(&serv->sv_permsocks)); | 483 | BUG_ON(!list_empty(&serv->sv_permsocks)); |
560 | BUG_ON(!list_empty(&serv->sv_tempsocks)); | 484 | BUG_ON(!list_empty(&serv->sv_tempsocks)); |
561 | 485 | ||
@@ -564,6 +488,7 @@ svc_destroy(struct svc_serv *serv) | |||
564 | if (svc_serv_is_pooled(serv)) | 488 | if (svc_serv_is_pooled(serv)) |
565 | svc_pool_map_put(); | 489 | svc_pool_map_put(); |
566 | 490 | ||
491 | svc_unregister(serv); | ||
567 | kfree(serv->sv_pools); | 492 | kfree(serv->sv_pools); |
568 | kfree(serv); | 493 | kfree(serv); |
569 | } | 494 | } |
@@ -574,7 +499,7 @@ EXPORT_SYMBOL_GPL(svc_destroy); | |||
574 | * We allocate pages and place them in rq_argpages. | 499 | * We allocate pages and place them in rq_argpages. |
575 | */ | 500 | */ |
576 | static int | 501 | static int |
577 | svc_init_buffer(struct svc_rqst *rqstp, unsigned int size, int node) | 502 | svc_init_buffer(struct svc_rqst *rqstp, unsigned int size) |
578 | { | 503 | { |
579 | unsigned int pages, arghi; | 504 | unsigned int pages, arghi; |
580 | 505 | ||
@@ -586,11 +511,9 @@ svc_init_buffer(struct svc_rqst *rqstp, unsigned int size, int node) | |||
586 | * We assume one is at most one page | 511 | * We assume one is at most one page |
587 | */ | 512 | */ |
588 | arghi = 0; | 513 | arghi = 0; |
589 | WARN_ON_ONCE(pages > RPCSVC_MAXPAGES); | 514 | BUG_ON(pages > RPCSVC_MAXPAGES); |
590 | if (pages > RPCSVC_MAXPAGES) | ||
591 | pages = RPCSVC_MAXPAGES; | ||
592 | while (pages) { | 515 | while (pages) { |
593 | struct page *p = alloc_pages_node(node, GFP_KERNEL, 0); | 516 | struct page *p = alloc_page(GFP_KERNEL); |
594 | if (!p) | 517 | if (!p) |
595 | break; | 518 | break; |
596 | rqstp->rq_pages[arghi++] = p; | 519 | rqstp->rq_pages[arghi++] = p; |
@@ -613,11 +536,11 @@ svc_release_buffer(struct svc_rqst *rqstp) | |||
613 | } | 536 | } |
614 | 537 | ||
615 | struct svc_rqst * | 538 | struct svc_rqst * |
616 | svc_prepare_thread(struct svc_serv *serv, struct svc_pool *pool, int node) | 539 | svc_prepare_thread(struct svc_serv *serv, struct svc_pool *pool) |
617 | { | 540 | { |
618 | struct svc_rqst *rqstp; | 541 | struct svc_rqst *rqstp; |
619 | 542 | ||
620 | rqstp = kzalloc_node(sizeof(*rqstp), GFP_KERNEL, node); | 543 | rqstp = kzalloc(sizeof(*rqstp), GFP_KERNEL); |
621 | if (!rqstp) | 544 | if (!rqstp) |
622 | goto out_enomem; | 545 | goto out_enomem; |
623 | 546 | ||
@@ -631,15 +554,15 @@ svc_prepare_thread(struct svc_serv *serv, struct svc_pool *pool, int node) | |||
631 | rqstp->rq_server = serv; | 554 | rqstp->rq_server = serv; |
632 | rqstp->rq_pool = pool; | 555 | rqstp->rq_pool = pool; |
633 | 556 | ||
634 | rqstp->rq_argp = kmalloc_node(serv->sv_xdrsize, GFP_KERNEL, node); | 557 | rqstp->rq_argp = kmalloc(serv->sv_xdrsize, GFP_KERNEL); |
635 | if (!rqstp->rq_argp) | 558 | if (!rqstp->rq_argp) |
636 | goto out_thread; | 559 | goto out_thread; |
637 | 560 | ||
638 | rqstp->rq_resp = kmalloc_node(serv->sv_xdrsize, GFP_KERNEL, node); | 561 | rqstp->rq_resp = kmalloc(serv->sv_xdrsize, GFP_KERNEL); |
639 | if (!rqstp->rq_resp) | 562 | if (!rqstp->rq_resp) |
640 | goto out_thread; | 563 | goto out_thread; |
641 | 564 | ||
642 | if (!svc_init_buffer(rqstp, serv->sv_max_mesg, node)) | 565 | if (!svc_init_buffer(rqstp, serv->sv_max_mesg)) |
643 | goto out_thread; | 566 | goto out_thread; |
644 | 567 | ||
645 | return rqstp; | 568 | return rqstp; |
@@ -706,8 +629,8 @@ found_pool: | |||
706 | * Create or destroy enough new threads to make the number | 629 | * Create or destroy enough new threads to make the number |
707 | * of threads the given number. If `pool' is non-NULL, applies | 630 | * of threads the given number. If `pool' is non-NULL, applies |
708 | * only to threads in that pool, otherwise round-robins between | 631 | * only to threads in that pool, otherwise round-robins between |
709 | * all pools. Caller must ensure that mutual exclusion between this and | 632 | * all pools. Must be called with a svc_get() reference and |
710 | * server startup or shutdown. | 633 | * the BKL or another lock to protect access to svc_serv fields. |
711 | * | 634 | * |
712 | * Destroying threads relies on the service threads filling in | 635 | * Destroying threads relies on the service threads filling in |
713 | * rqstp->rq_task, which only the nfs ones do. Assumes the serv | 636 | * rqstp->rq_task, which only the nfs ones do. Assumes the serv |
@@ -724,7 +647,6 @@ svc_set_num_threads(struct svc_serv *serv, struct svc_pool *pool, int nrservs) | |||
724 | struct svc_pool *chosen_pool; | 647 | struct svc_pool *chosen_pool; |
725 | int error = 0; | 648 | int error = 0; |
726 | unsigned int state = serv->sv_nrthreads-1; | 649 | unsigned int state = serv->sv_nrthreads-1; |
727 | int node; | ||
728 | 650 | ||
729 | if (pool == NULL) { | 651 | if (pool == NULL) { |
730 | /* The -1 assumes caller has done a svc_get() */ | 652 | /* The -1 assumes caller has done a svc_get() */ |
@@ -740,16 +662,14 @@ svc_set_num_threads(struct svc_serv *serv, struct svc_pool *pool, int nrservs) | |||
740 | nrservs--; | 662 | nrservs--; |
741 | chosen_pool = choose_pool(serv, pool, &state); | 663 | chosen_pool = choose_pool(serv, pool, &state); |
742 | 664 | ||
743 | node = svc_pool_map_get_node(chosen_pool->sp_id); | 665 | rqstp = svc_prepare_thread(serv, chosen_pool); |
744 | rqstp = svc_prepare_thread(serv, chosen_pool, node); | ||
745 | if (IS_ERR(rqstp)) { | 666 | if (IS_ERR(rqstp)) { |
746 | error = PTR_ERR(rqstp); | 667 | error = PTR_ERR(rqstp); |
747 | break; | 668 | break; |
748 | } | 669 | } |
749 | 670 | ||
750 | __module_get(serv->sv_module); | 671 | __module_get(serv->sv_module); |
751 | task = kthread_create_on_node(serv->sv_function, rqstp, | 672 | task = kthread_create(serv->sv_function, rqstp, serv->sv_name); |
752 | node, serv->sv_name); | ||
753 | if (IS_ERR(task)) { | 673 | if (IS_ERR(task)) { |
754 | error = PTR_ERR(task); | 674 | error = PTR_ERR(task); |
755 | module_put(serv->sv_module); | 675 | module_put(serv->sv_module); |
@@ -813,8 +733,7 @@ EXPORT_SYMBOL_GPL(svc_exit_thread); | |||
813 | * Returns zero on success; a negative errno value is returned | 733 | * Returns zero on success; a negative errno value is returned |
814 | * if any error occurs. | 734 | * if any error occurs. |
815 | */ | 735 | */ |
816 | static int __svc_rpcb_register4(struct net *net, const u32 program, | 736 | static int __svc_rpcb_register4(const u32 program, const u32 version, |
817 | const u32 version, | ||
818 | const unsigned short protocol, | 737 | const unsigned short protocol, |
819 | const unsigned short port) | 738 | const unsigned short port) |
820 | { | 739 | { |
@@ -837,7 +756,7 @@ static int __svc_rpcb_register4(struct net *net, const u32 program, | |||
837 | return -ENOPROTOOPT; | 756 | return -ENOPROTOOPT; |
838 | } | 757 | } |
839 | 758 | ||
840 | error = rpcb_v4_register(net, program, version, | 759 | error = rpcb_v4_register(program, version, |
841 | (const struct sockaddr *)&sin, netid); | 760 | (const struct sockaddr *)&sin, netid); |
842 | 761 | ||
843 | /* | 762 | /* |
@@ -845,12 +764,12 @@ static int __svc_rpcb_register4(struct net *net, const u32 program, | |||
845 | * registration request with the legacy rpcbind v2 protocol. | 764 | * registration request with the legacy rpcbind v2 protocol. |
846 | */ | 765 | */ |
847 | if (error == -EPROTONOSUPPORT) | 766 | if (error == -EPROTONOSUPPORT) |
848 | error = rpcb_register(net, program, version, protocol, port); | 767 | error = rpcb_register(program, version, protocol, port); |
849 | 768 | ||
850 | return error; | 769 | return error; |
851 | } | 770 | } |
852 | 771 | ||
853 | #if IS_ENABLED(CONFIG_IPV6) | 772 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
854 | /* | 773 | /* |
855 | * Register an "inet6" protocol family netid with the local | 774 | * Register an "inet6" protocol family netid with the local |
856 | * rpcbind daemon via an rpcbind v4 SET request. | 775 | * rpcbind daemon via an rpcbind v4 SET request. |
@@ -861,8 +780,7 @@ static int __svc_rpcb_register4(struct net *net, const u32 program, | |||
861 | * Returns zero on success; a negative errno value is returned | 780 | * Returns zero on success; a negative errno value is returned |
862 | * if any error occurs. | 781 | * if any error occurs. |
863 | */ | 782 | */ |
864 | static int __svc_rpcb_register6(struct net *net, const u32 program, | 783 | static int __svc_rpcb_register6(const u32 program, const u32 version, |
865 | const u32 version, | ||
866 | const unsigned short protocol, | 784 | const unsigned short protocol, |
867 | const unsigned short port) | 785 | const unsigned short port) |
868 | { | 786 | { |
@@ -885,7 +803,7 @@ static int __svc_rpcb_register6(struct net *net, const u32 program, | |||
885 | return -ENOPROTOOPT; | 803 | return -ENOPROTOOPT; |
886 | } | 804 | } |
887 | 805 | ||
888 | error = rpcb_v4_register(net, program, version, | 806 | error = rpcb_v4_register(program, version, |
889 | (const struct sockaddr *)&sin6, netid); | 807 | (const struct sockaddr *)&sin6, netid); |
890 | 808 | ||
891 | /* | 809 | /* |
@@ -897,7 +815,7 @@ static int __svc_rpcb_register6(struct net *net, const u32 program, | |||
897 | 815 | ||
898 | return error; | 816 | return error; |
899 | } | 817 | } |
900 | #endif /* IS_ENABLED(CONFIG_IPV6) */ | 818 | #endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ |
901 | 819 | ||
902 | /* | 820 | /* |
903 | * Register a kernel RPC service via rpcbind version 4. | 821 | * Register a kernel RPC service via rpcbind version 4. |
@@ -905,7 +823,7 @@ static int __svc_rpcb_register6(struct net *net, const u32 program, | |||
905 | * Returns zero on success; a negative errno value is returned | 823 | * Returns zero on success; a negative errno value is returned |
906 | * if any error occurs. | 824 | * if any error occurs. |
907 | */ | 825 | */ |
908 | static int __svc_register(struct net *net, const char *progname, | 826 | static int __svc_register(const char *progname, |
909 | const u32 program, const u32 version, | 827 | const u32 program, const u32 version, |
910 | const int family, | 828 | const int family, |
911 | const unsigned short protocol, | 829 | const unsigned short protocol, |
@@ -915,14 +833,14 @@ static int __svc_register(struct net *net, const char *progname, | |||
915 | 833 | ||
916 | switch (family) { | 834 | switch (family) { |
917 | case PF_INET: | 835 | case PF_INET: |
918 | error = __svc_rpcb_register4(net, program, version, | 836 | error = __svc_rpcb_register4(program, version, |
919 | protocol, port); | 837 | protocol, port); |
920 | break; | 838 | break; |
921 | #if IS_ENABLED(CONFIG_IPV6) | 839 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
922 | case PF_INET6: | 840 | case PF_INET6: |
923 | error = __svc_rpcb_register6(net, program, version, | 841 | error = __svc_rpcb_register6(program, version, |
924 | protocol, port); | 842 | protocol, port); |
925 | #endif | 843 | #endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ |
926 | } | 844 | } |
927 | 845 | ||
928 | if (error < 0) | 846 | if (error < 0) |
@@ -934,24 +852,20 @@ static int __svc_register(struct net *net, const char *progname, | |||
934 | /** | 852 | /** |
935 | * svc_register - register an RPC service with the local portmapper | 853 | * svc_register - register an RPC service with the local portmapper |
936 | * @serv: svc_serv struct for the service to register | 854 | * @serv: svc_serv struct for the service to register |
937 | * @net: net namespace for the service to register | ||
938 | * @family: protocol family of service's listener socket | 855 | * @family: protocol family of service's listener socket |
939 | * @proto: transport protocol number to advertise | 856 | * @proto: transport protocol number to advertise |
940 | * @port: port to advertise | 857 | * @port: port to advertise |
941 | * | 858 | * |
942 | * Service is registered for any address in the passed-in protocol family | 859 | * Service is registered for any address in the passed-in protocol family |
943 | */ | 860 | */ |
944 | int svc_register(const struct svc_serv *serv, struct net *net, | 861 | int svc_register(const struct svc_serv *serv, const int family, |
945 | const int family, const unsigned short proto, | 862 | const unsigned short proto, const unsigned short port) |
946 | const unsigned short port) | ||
947 | { | 863 | { |
948 | struct svc_program *progp; | 864 | struct svc_program *progp; |
949 | unsigned int i; | 865 | unsigned int i; |
950 | int error = 0; | 866 | int error = 0; |
951 | 867 | ||
952 | WARN_ON_ONCE(proto == 0 && port == 0); | 868 | BUG_ON(proto == 0 && port == 0); |
953 | if (proto == 0 && port == 0) | ||
954 | return -EINVAL; | ||
955 | 869 | ||
956 | for (progp = serv->sv_program; progp; progp = progp->pg_next) { | 870 | for (progp = serv->sv_program; progp; progp = progp->pg_next) { |
957 | for (i = 0; i < progp->pg_nvers; i++) { | 871 | for (i = 0; i < progp->pg_nvers; i++) { |
@@ -970,7 +884,7 @@ int svc_register(const struct svc_serv *serv, struct net *net, | |||
970 | if (progp->pg_vers[i]->vs_hidden) | 884 | if (progp->pg_vers[i]->vs_hidden) |
971 | continue; | 885 | continue; |
972 | 886 | ||
973 | error = __svc_register(net, progp->pg_name, progp->pg_prog, | 887 | error = __svc_register(progp->pg_name, progp->pg_prog, |
974 | i, family, proto, port); | 888 | i, family, proto, port); |
975 | if (error < 0) | 889 | if (error < 0) |
976 | break; | 890 | break; |
@@ -987,19 +901,19 @@ int svc_register(const struct svc_serv *serv, struct net *net, | |||
987 | * any "inet6" entries anyway. So a PMAP_UNSET should be sufficient | 901 | * any "inet6" entries anyway. So a PMAP_UNSET should be sufficient |
988 | * in this case to clear all existing entries for [program, version]. | 902 | * in this case to clear all existing entries for [program, version]. |
989 | */ | 903 | */ |
990 | static void __svc_unregister(struct net *net, const u32 program, const u32 version, | 904 | static void __svc_unregister(const u32 program, const u32 version, |
991 | const char *progname) | 905 | const char *progname) |
992 | { | 906 | { |
993 | int error; | 907 | int error; |
994 | 908 | ||
995 | error = rpcb_v4_register(net, program, version, NULL, ""); | 909 | error = rpcb_v4_register(program, version, NULL, ""); |
996 | 910 | ||
997 | /* | 911 | /* |
998 | * User space didn't support rpcbind v4, so retry this | 912 | * User space didn't support rpcbind v4, so retry this |
999 | * request with the legacy rpcbind v2 protocol. | 913 | * request with the legacy rpcbind v2 protocol. |
1000 | */ | 914 | */ |
1001 | if (error == -EPROTONOSUPPORT) | 915 | if (error == -EPROTONOSUPPORT) |
1002 | error = rpcb_register(net, program, version, 0, 0); | 916 | error = rpcb_register(program, version, 0, 0); |
1003 | 917 | ||
1004 | dprintk("svc: %s(%sv%u), error %d\n", | 918 | dprintk("svc: %s(%sv%u), error %d\n", |
1005 | __func__, progname, version, error); | 919 | __func__, progname, version, error); |
@@ -1013,7 +927,7 @@ static void __svc_unregister(struct net *net, const u32 program, const u32 versi | |||
1013 | * The result of unregistration is reported via dprintk for those who want | 927 | * The result of unregistration is reported via dprintk for those who want |
1014 | * verification of the result, but is otherwise not important. | 928 | * verification of the result, but is otherwise not important. |
1015 | */ | 929 | */ |
1016 | static void svc_unregister(const struct svc_serv *serv, struct net *net) | 930 | static void svc_unregister(const struct svc_serv *serv) |
1017 | { | 931 | { |
1018 | struct svc_program *progp; | 932 | struct svc_program *progp; |
1019 | unsigned long flags; | 933 | unsigned long flags; |
@@ -1030,7 +944,7 @@ static void svc_unregister(const struct svc_serv *serv, struct net *net) | |||
1030 | 944 | ||
1031 | dprintk("svc: attempting to unregister %sv%u\n", | 945 | dprintk("svc: attempting to unregister %sv%u\n", |
1032 | progp->pg_name, i); | 946 | progp->pg_name, i); |
1033 | __svc_unregister(net, progp->pg_prog, i, progp->pg_name); | 947 | __svc_unregister(progp->pg_prog, i, progp->pg_name); |
1034 | } | 948 | } |
1035 | } | 949 | } |
1036 | 950 | ||
@@ -1040,23 +954,27 @@ static void svc_unregister(const struct svc_serv *serv, struct net *net) | |||
1040 | } | 954 | } |
1041 | 955 | ||
1042 | /* | 956 | /* |
1043 | * dprintk the given error with the address of the client that caused it. | 957 | * Printk the given error with the address of the client that caused it. |
1044 | */ | 958 | */ |
1045 | static __printf(2, 3) | 959 | static int |
1046 | void svc_printk(struct svc_rqst *rqstp, const char *fmt, ...) | 960 | __attribute__ ((format (printf, 2, 3))) |
961 | svc_printk(struct svc_rqst *rqstp, const char *fmt, ...) | ||
1047 | { | 962 | { |
1048 | struct va_format vaf; | ||
1049 | va_list args; | 963 | va_list args; |
964 | int r; | ||
1050 | char buf[RPC_MAX_ADDRBUFLEN]; | 965 | char buf[RPC_MAX_ADDRBUFLEN]; |
1051 | 966 | ||
1052 | va_start(args, fmt); | 967 | if (!net_ratelimit()) |
1053 | 968 | return 0; | |
1054 | vaf.fmt = fmt; | ||
1055 | vaf.va = &args; | ||
1056 | 969 | ||
1057 | dprintk("svc: %s: %pV", svc_print_addr(rqstp, buf, sizeof(buf)), &vaf); | 970 | printk(KERN_WARNING "svc: %s: ", |
971 | svc_print_addr(rqstp, buf, sizeof(buf))); | ||
1058 | 972 | ||
973 | va_start(args, fmt); | ||
974 | r = vprintk(fmt, args); | ||
1059 | va_end(args); | 975 | va_end(args); |
976 | |||
977 | return r; | ||
1060 | } | 978 | } |
1061 | 979 | ||
1062 | /* | 980 | /* |
@@ -1303,7 +1221,7 @@ svc_process(struct svc_rqst *rqstp) | |||
1303 | * Setup response xdr_buf. | 1221 | * Setup response xdr_buf. |
1304 | * Initially it has just one page | 1222 | * Initially it has just one page |
1305 | */ | 1223 | */ |
1306 | rqstp->rq_next_page = &rqstp->rq_respages[1]; | 1224 | rqstp->rq_resused = 1; |
1307 | resv->iov_base = page_address(rqstp->rq_respages[0]); | 1225 | resv->iov_base = page_address(rqstp->rq_respages[0]); |
1308 | resv->iov_len = 0; | 1226 | resv->iov_len = 0; |
1309 | rqstp->rq_res.pages = rqstp->rq_respages + 1; | 1227 | rqstp->rq_res.pages = rqstp->rq_respages + 1; |
@@ -1378,8 +1296,7 @@ bc_svc_process(struct svc_serv *serv, struct rpc_rqst *req, | |||
1378 | sizeof(req->rq_snd_buf)); | 1296 | sizeof(req->rq_snd_buf)); |
1379 | return bc_send(req); | 1297 | return bc_send(req); |
1380 | } else { | 1298 | } else { |
1381 | /* drop request */ | 1299 | /* Nothing to do to drop request */ |
1382 | xprt_free_bc_request(req); | ||
1383 | return 0; | 1300 | return 0; |
1384 | } | 1301 | } |
1385 | } | 1302 | } |
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index b8e47fac731..bd31208bbb6 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <linux/sunrpc/svc_xprt.h> | 14 | #include <linux/sunrpc/svc_xprt.h> |
15 | #include <linux/sunrpc/svcsock.h> | 15 | #include <linux/sunrpc/svcsock.h> |
16 | #include <linux/sunrpc/xprt.h> | 16 | #include <linux/sunrpc/xprt.h> |
17 | #include <linux/module.h> | ||
18 | 17 | ||
19 | #define RPCDBG_FACILITY RPCDBG_SVCXPRT | 18 | #define RPCDBG_FACILITY RPCDBG_SVCXPRT |
20 | 19 | ||
@@ -22,7 +21,6 @@ static struct svc_deferred_req *svc_deferred_dequeue(struct svc_xprt *xprt); | |||
22 | static int svc_deferred_recv(struct svc_rqst *rqstp); | 21 | static int svc_deferred_recv(struct svc_rqst *rqstp); |
23 | static struct cache_deferred_req *svc_defer(struct cache_req *req); | 22 | static struct cache_deferred_req *svc_defer(struct cache_req *req); |
24 | static void svc_age_temp_xprts(unsigned long closure); | 23 | static void svc_age_temp_xprts(unsigned long closure); |
25 | static void svc_delete_xprt(struct svc_xprt *xprt); | ||
26 | 24 | ||
27 | /* apparently the "standard" is that clients close | 25 | /* apparently the "standard" is that clients close |
28 | * idle connections after 5 minutes, servers after | 26 | * idle connections after 5 minutes, servers after |
@@ -148,8 +146,8 @@ EXPORT_SYMBOL_GPL(svc_xprt_put); | |||
148 | * Called by transport drivers to initialize the transport independent | 146 | * Called by transport drivers to initialize the transport independent |
149 | * portion of the transport instance. | 147 | * portion of the transport instance. |
150 | */ | 148 | */ |
151 | void svc_xprt_init(struct net *net, struct svc_xprt_class *xcl, | 149 | void svc_xprt_init(struct svc_xprt_class *xcl, struct svc_xprt *xprt, |
152 | struct svc_xprt *xprt, struct svc_serv *serv) | 150 | struct svc_serv *serv) |
153 | { | 151 | { |
154 | memset(xprt, 0, sizeof(*xprt)); | 152 | memset(xprt, 0, sizeof(*xprt)); |
155 | xprt->xpt_class = xcl; | 153 | xprt->xpt_class = xcl; |
@@ -164,7 +162,7 @@ void svc_xprt_init(struct net *net, struct svc_xprt_class *xcl, | |||
164 | spin_lock_init(&xprt->xpt_lock); | 162 | spin_lock_init(&xprt->xpt_lock); |
165 | set_bit(XPT_BUSY, &xprt->xpt_flags); | 163 | set_bit(XPT_BUSY, &xprt->xpt_flags); |
166 | rpc_init_wait_queue(&xprt->xpt_bc_pending, "xpt_bc_pending"); | 164 | rpc_init_wait_queue(&xprt->xpt_bc_pending, "xpt_bc_pending"); |
167 | xprt->xpt_net = get_net(net); | 165 | xprt->xpt_net = get_net(&init_net); |
168 | } | 166 | } |
169 | EXPORT_SYMBOL_GPL(svc_xprt_init); | 167 | EXPORT_SYMBOL_GPL(svc_xprt_init); |
170 | 168 | ||
@@ -180,13 +178,13 @@ static struct svc_xprt *__svc_xpo_create(struct svc_xprt_class *xcl, | |||
180 | .sin_addr.s_addr = htonl(INADDR_ANY), | 178 | .sin_addr.s_addr = htonl(INADDR_ANY), |
181 | .sin_port = htons(port), | 179 | .sin_port = htons(port), |
182 | }; | 180 | }; |
183 | #if IS_ENABLED(CONFIG_IPV6) | 181 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
184 | struct sockaddr_in6 sin6 = { | 182 | struct sockaddr_in6 sin6 = { |
185 | .sin6_family = AF_INET6, | 183 | .sin6_family = AF_INET6, |
186 | .sin6_addr = IN6ADDR_ANY_INIT, | 184 | .sin6_addr = IN6ADDR_ANY_INIT, |
187 | .sin6_port = htons(port), | 185 | .sin6_port = htons(port), |
188 | }; | 186 | }; |
189 | #endif | 187 | #endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ |
190 | struct sockaddr *sap; | 188 | struct sockaddr *sap; |
191 | size_t len; | 189 | size_t len; |
192 | 190 | ||
@@ -195,12 +193,12 @@ static struct svc_xprt *__svc_xpo_create(struct svc_xprt_class *xcl, | |||
195 | sap = (struct sockaddr *)&sin; | 193 | sap = (struct sockaddr *)&sin; |
196 | len = sizeof(sin); | 194 | len = sizeof(sin); |
197 | break; | 195 | break; |
198 | #if IS_ENABLED(CONFIG_IPV6) | 196 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
199 | case PF_INET6: | 197 | case PF_INET6: |
200 | sap = (struct sockaddr *)&sin6; | 198 | sap = (struct sockaddr *)&sin6; |
201 | len = sizeof(sin6); | 199 | len = sizeof(sin6); |
202 | break; | 200 | break; |
203 | #endif | 201 | #endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */ |
204 | default: | 202 | default: |
205 | return ERR_PTR(-EAFNOSUPPORT); | 203 | return ERR_PTR(-EAFNOSUPPORT); |
206 | } | 204 | } |
@@ -208,37 +206,6 @@ static struct svc_xprt *__svc_xpo_create(struct svc_xprt_class *xcl, | |||
208 | return xcl->xcl_ops->xpo_create(serv, net, sap, len, flags); | 206 | return xcl->xcl_ops->xpo_create(serv, net, sap, len, flags); |
209 | } | 207 | } |
210 | 208 | ||
211 | /* | ||
212 | * svc_xprt_received conditionally queues the transport for processing | ||
213 | * by another thread. The caller must hold the XPT_BUSY bit and must | ||
214 | * not thereafter touch transport data. | ||
215 | * | ||
216 | * Note: XPT_DATA only gets cleared when a read-attempt finds no (or | ||
217 | * insufficient) data. | ||
218 | */ | ||
219 | static void svc_xprt_received(struct svc_xprt *xprt) | ||
220 | { | ||
221 | WARN_ON_ONCE(!test_bit(XPT_BUSY, &xprt->xpt_flags)); | ||
222 | if (!test_bit(XPT_BUSY, &xprt->xpt_flags)) | ||
223 | return; | ||
224 | /* As soon as we clear busy, the xprt could be closed and | ||
225 | * 'put', so we need a reference to call svc_xprt_enqueue with: | ||
226 | */ | ||
227 | svc_xprt_get(xprt); | ||
228 | clear_bit(XPT_BUSY, &xprt->xpt_flags); | ||
229 | svc_xprt_enqueue(xprt); | ||
230 | svc_xprt_put(xprt); | ||
231 | } | ||
232 | |||
233 | void svc_add_new_perm_xprt(struct svc_serv *serv, struct svc_xprt *new) | ||
234 | { | ||
235 | clear_bit(XPT_TEMP, &new->xpt_flags); | ||
236 | spin_lock_bh(&serv->sv_lock); | ||
237 | list_add(&new->xpt_list, &serv->sv_permsocks); | ||
238 | spin_unlock_bh(&serv->sv_lock); | ||
239 | svc_xprt_received(new); | ||
240 | } | ||
241 | |||
242 | int svc_create_xprt(struct svc_serv *serv, const char *xprt_name, | 209 | int svc_create_xprt(struct svc_serv *serv, const char *xprt_name, |
243 | struct net *net, const int family, | 210 | struct net *net, const int family, |
244 | const unsigned short port, int flags) | 211 | const unsigned short port, int flags) |
@@ -263,8 +230,13 @@ int svc_create_xprt(struct svc_serv *serv, const char *xprt_name, | |||
263 | module_put(xcl->xcl_owner); | 230 | module_put(xcl->xcl_owner); |
264 | return PTR_ERR(newxprt); | 231 | return PTR_ERR(newxprt); |
265 | } | 232 | } |
266 | svc_add_new_perm_xprt(serv, newxprt); | 233 | |
234 | clear_bit(XPT_TEMP, &newxprt->xpt_flags); | ||
235 | spin_lock_bh(&serv->sv_lock); | ||
236 | list_add(&newxprt->xpt_list, &serv->sv_permsocks); | ||
237 | spin_unlock_bh(&serv->sv_lock); | ||
267 | newport = svc_xprt_local_port(newxprt); | 238 | newport = svc_xprt_local_port(newxprt); |
239 | clear_bit(XPT_BUSY, &newxprt->xpt_flags); | ||
268 | return newport; | 240 | return newport; |
269 | } | 241 | } |
270 | err: | 242 | err: |
@@ -282,6 +254,8 @@ EXPORT_SYMBOL_GPL(svc_create_xprt); | |||
282 | */ | 254 | */ |
283 | void svc_xprt_copy_addrs(struct svc_rqst *rqstp, struct svc_xprt *xprt) | 255 | void svc_xprt_copy_addrs(struct svc_rqst *rqstp, struct svc_xprt *xprt) |
284 | { | 256 | { |
257 | struct sockaddr *sin; | ||
258 | |||
285 | memcpy(&rqstp->rq_addr, &xprt->xpt_remote, xprt->xpt_remotelen); | 259 | memcpy(&rqstp->rq_addr, &xprt->xpt_remote, xprt->xpt_remotelen); |
286 | rqstp->rq_addrlen = xprt->xpt_remotelen; | 260 | rqstp->rq_addrlen = xprt->xpt_remotelen; |
287 | 261 | ||
@@ -289,8 +263,15 @@ void svc_xprt_copy_addrs(struct svc_rqst *rqstp, struct svc_xprt *xprt) | |||
289 | * Destination address in request is needed for binding the | 263 | * Destination address in request is needed for binding the |
290 | * source address in RPC replies/callbacks later. | 264 | * source address in RPC replies/callbacks later. |
291 | */ | 265 | */ |
292 | memcpy(&rqstp->rq_daddr, &xprt->xpt_local, xprt->xpt_locallen); | 266 | sin = (struct sockaddr *)&xprt->xpt_local; |
293 | rqstp->rq_daddrlen = xprt->xpt_locallen; | 267 | switch (sin->sa_family) { |
268 | case AF_INET: | ||
269 | rqstp->rq_daddr.addr = ((struct sockaddr_in *)sin)->sin_addr; | ||
270 | break; | ||
271 | case AF_INET6: | ||
272 | rqstp->rq_daddr.addr6 = ((struct sockaddr_in6 *)sin)->sin6_addr; | ||
273 | break; | ||
274 | } | ||
294 | } | 275 | } |
295 | EXPORT_SYMBOL_GPL(svc_xprt_copy_addrs); | 276 | EXPORT_SYMBOL_GPL(svc_xprt_copy_addrs); |
296 | 277 | ||
@@ -342,6 +323,7 @@ static bool svc_xprt_has_something_to_do(struct svc_xprt *xprt) | |||
342 | */ | 323 | */ |
343 | void svc_xprt_enqueue(struct svc_xprt *xprt) | 324 | void svc_xprt_enqueue(struct svc_xprt *xprt) |
344 | { | 325 | { |
326 | struct svc_serv *serv = xprt->xpt_server; | ||
345 | struct svc_pool *pool; | 327 | struct svc_pool *pool; |
346 | struct svc_rqst *rqstp; | 328 | struct svc_rqst *rqstp; |
347 | int cpu; | 329 | int cpu; |
@@ -387,6 +369,8 @@ void svc_xprt_enqueue(struct svc_xprt *xprt) | |||
387 | rqstp, rqstp->rq_xprt); | 369 | rqstp, rqstp->rq_xprt); |
388 | rqstp->rq_xprt = xprt; | 370 | rqstp->rq_xprt = xprt; |
389 | svc_xprt_get(xprt); | 371 | svc_xprt_get(xprt); |
372 | rqstp->rq_reserved = serv->sv_max_mesg; | ||
373 | atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved); | ||
390 | pool->sp_stats.threads_woken++; | 374 | pool->sp_stats.threads_woken++; |
391 | wake_up(&rqstp->rq_wait); | 375 | wake_up(&rqstp->rq_wait); |
392 | } else { | 376 | } else { |
@@ -420,6 +404,27 @@ static struct svc_xprt *svc_xprt_dequeue(struct svc_pool *pool) | |||
420 | return xprt; | 404 | return xprt; |
421 | } | 405 | } |
422 | 406 | ||
407 | /* | ||
408 | * svc_xprt_received conditionally queues the transport for processing | ||
409 | * by another thread. The caller must hold the XPT_BUSY bit and must | ||
410 | * not thereafter touch transport data. | ||
411 | * | ||
412 | * Note: XPT_DATA only gets cleared when a read-attempt finds no (or | ||
413 | * insufficient) data. | ||
414 | */ | ||
415 | void svc_xprt_received(struct svc_xprt *xprt) | ||
416 | { | ||
417 | BUG_ON(!test_bit(XPT_BUSY, &xprt->xpt_flags)); | ||
418 | /* As soon as we clear busy, the xprt could be closed and | ||
419 | * 'put', so we need a reference to call svc_xprt_enqueue with: | ||
420 | */ | ||
421 | svc_xprt_get(xprt); | ||
422 | clear_bit(XPT_BUSY, &xprt->xpt_flags); | ||
423 | svc_xprt_enqueue(xprt); | ||
424 | svc_xprt_put(xprt); | ||
425 | } | ||
426 | EXPORT_SYMBOL_GPL(svc_xprt_received); | ||
427 | |||
423 | /** | 428 | /** |
424 | * svc_reserve - change the space reserved for the reply to a request. | 429 | * svc_reserve - change the space reserved for the reply to a request. |
425 | * @rqstp: The request in question | 430 | * @rqstp: The request in question |
@@ -546,11 +551,14 @@ static void svc_check_conn_limits(struct svc_serv *serv) | |||
546 | struct svc_xprt *xprt = NULL; | 551 | struct svc_xprt *xprt = NULL; |
547 | spin_lock_bh(&serv->sv_lock); | 552 | spin_lock_bh(&serv->sv_lock); |
548 | if (!list_empty(&serv->sv_tempsocks)) { | 553 | if (!list_empty(&serv->sv_tempsocks)) { |
549 | /* Try to help the admin */ | 554 | if (net_ratelimit()) { |
550 | net_notice_ratelimited("%s: too many open connections, consider increasing the %s\n", | 555 | /* Try to help the admin */ |
551 | serv->sv_name, serv->sv_maxconn ? | 556 | printk(KERN_NOTICE "%s: too many open " |
552 | "max number of connections" : | 557 | "connections, consider increasing %s\n", |
553 | "number of threads"); | 558 | serv->sv_name, serv->sv_maxconn ? |
559 | "the max number of connections." : | ||
560 | "the number of threads."); | ||
561 | } | ||
554 | /* | 562 | /* |
555 | * Always select the oldest connection. It's not fair, | 563 | * Always select the oldest connection. It's not fair, |
556 | * but so is life | 564 | * but so is life |
@@ -570,19 +578,36 @@ static void svc_check_conn_limits(struct svc_serv *serv) | |||
570 | } | 578 | } |
571 | } | 579 | } |
572 | 580 | ||
573 | int svc_alloc_arg(struct svc_rqst *rqstp) | 581 | /* |
582 | * Receive the next request on any transport. This code is carefully | ||
583 | * organised not to touch any cachelines in the shared svc_serv | ||
584 | * structure, only cachelines in the local svc_pool. | ||
585 | */ | ||
586 | int svc_recv(struct svc_rqst *rqstp, long timeout) | ||
574 | { | 587 | { |
575 | struct svc_serv *serv = rqstp->rq_server; | 588 | struct svc_xprt *xprt = NULL; |
576 | struct xdr_buf *arg; | 589 | struct svc_serv *serv = rqstp->rq_server; |
577 | int pages; | 590 | struct svc_pool *pool = rqstp->rq_pool; |
578 | int i; | 591 | int len, i; |
592 | int pages; | ||
593 | struct xdr_buf *arg; | ||
594 | DECLARE_WAITQUEUE(wait, current); | ||
595 | long time_left; | ||
596 | |||
597 | dprintk("svc: server %p waiting for data (to = %ld)\n", | ||
598 | rqstp, timeout); | ||
599 | |||
600 | if (rqstp->rq_xprt) | ||
601 | printk(KERN_ERR | ||
602 | "svc_recv: service %p, transport not NULL!\n", | ||
603 | rqstp); | ||
604 | if (waitqueue_active(&rqstp->rq_wait)) | ||
605 | printk(KERN_ERR | ||
606 | "svc_recv: service %p, wait queue active!\n", | ||
607 | rqstp); | ||
579 | 608 | ||
580 | /* now allocate needed pages. If we get a failure, sleep briefly */ | 609 | /* now allocate needed pages. If we get a failure, sleep briefly */ |
581 | pages = (serv->sv_max_mesg + PAGE_SIZE) / PAGE_SIZE; | 610 | pages = (serv->sv_max_mesg + PAGE_SIZE) / PAGE_SIZE; |
582 | WARN_ON_ONCE(pages >= RPCSVC_MAXPAGES); | ||
583 | if (pages >= RPCSVC_MAXPAGES) | ||
584 | /* use as many pages as possible */ | ||
585 | pages = RPCSVC_MAXPAGES - 1; | ||
586 | for (i = 0; i < pages ; i++) | 611 | for (i = 0; i < pages ; i++) |
587 | while (rqstp->rq_pages[i] == NULL) { | 612 | while (rqstp->rq_pages[i] == NULL) { |
588 | struct page *p = alloc_page(GFP_KERNEL); | 613 | struct page *p = alloc_page(GFP_KERNEL); |
@@ -597,6 +622,7 @@ int svc_alloc_arg(struct svc_rqst *rqstp) | |||
597 | rqstp->rq_pages[i] = p; | 622 | rqstp->rq_pages[i] = p; |
598 | } | 623 | } |
599 | rqstp->rq_pages[i++] = NULL; /* this might be seen in nfs_read_actor */ | 624 | rqstp->rq_pages[i++] = NULL; /* this might be seen in nfs_read_actor */ |
625 | BUG_ON(pages >= RPCSVC_MAXPAGES); | ||
600 | 626 | ||
601 | /* Make arg->head point to first page and arg->pages point to rest */ | 627 | /* Make arg->head point to first page and arg->pages point to rest */ |
602 | arg = &rqstp->rq_arg; | 628 | arg = &rqstp->rq_arg; |
@@ -608,15 +634,11 @@ int svc_alloc_arg(struct svc_rqst *rqstp) | |||
608 | arg->page_len = (pages-2)*PAGE_SIZE; | 634 | arg->page_len = (pages-2)*PAGE_SIZE; |
609 | arg->len = (pages-1)*PAGE_SIZE; | 635 | arg->len = (pages-1)*PAGE_SIZE; |
610 | arg->tail[0].iov_len = 0; | 636 | arg->tail[0].iov_len = 0; |
611 | return 0; | ||
612 | } | ||
613 | 637 | ||
614 | struct svc_xprt *svc_get_next_xprt(struct svc_rqst *rqstp, long timeout) | 638 | try_to_freeze(); |
615 | { | 639 | cond_resched(); |
616 | struct svc_xprt *xprt; | 640 | if (signalled() || kthread_should_stop()) |
617 | struct svc_pool *pool = rqstp->rq_pool; | 641 | return -EINTR; |
618 | DECLARE_WAITQUEUE(wait, current); | ||
619 | long time_left; | ||
620 | 642 | ||
621 | /* Normally we will wait up to 5 seconds for any required | 643 | /* Normally we will wait up to 5 seconds for any required |
622 | * cache information to be provided. | 644 | * cache information to be provided. |
@@ -628,6 +650,8 @@ struct svc_xprt *svc_get_next_xprt(struct svc_rqst *rqstp, long timeout) | |||
628 | if (xprt) { | 650 | if (xprt) { |
629 | rqstp->rq_xprt = xprt; | 651 | rqstp->rq_xprt = xprt; |
630 | svc_xprt_get(xprt); | 652 | svc_xprt_get(xprt); |
653 | rqstp->rq_reserved = serv->sv_max_mesg; | ||
654 | atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved); | ||
631 | 655 | ||
632 | /* As there is a shortage of threads and this request | 656 | /* As there is a shortage of threads and this request |
633 | * had to be queued, don't allow the thread to wait so | 657 | * had to be queued, don't allow the thread to wait so |
@@ -654,7 +678,7 @@ struct svc_xprt *svc_get_next_xprt(struct svc_rqst *rqstp, long timeout) | |||
654 | if (kthread_should_stop()) { | 678 | if (kthread_should_stop()) { |
655 | set_current_state(TASK_RUNNING); | 679 | set_current_state(TASK_RUNNING); |
656 | spin_unlock_bh(&pool->sp_lock); | 680 | spin_unlock_bh(&pool->sp_lock); |
657 | return ERR_PTR(-EINTR); | 681 | return -EINTR; |
658 | } | 682 | } |
659 | 683 | ||
660 | add_wait_queue(&rqstp->rq_wait, &wait); | 684 | add_wait_queue(&rqstp->rq_wait, &wait); |
@@ -675,58 +699,48 @@ struct svc_xprt *svc_get_next_xprt(struct svc_rqst *rqstp, long timeout) | |||
675 | spin_unlock_bh(&pool->sp_lock); | 699 | spin_unlock_bh(&pool->sp_lock); |
676 | dprintk("svc: server %p, no data yet\n", rqstp); | 700 | dprintk("svc: server %p, no data yet\n", rqstp); |
677 | if (signalled() || kthread_should_stop()) | 701 | if (signalled() || kthread_should_stop()) |
678 | return ERR_PTR(-EINTR); | 702 | return -EINTR; |
679 | else | 703 | else |
680 | return ERR_PTR(-EAGAIN); | 704 | return -EAGAIN; |
681 | } | 705 | } |
682 | } | 706 | } |
683 | spin_unlock_bh(&pool->sp_lock); | 707 | spin_unlock_bh(&pool->sp_lock); |
684 | return xprt; | ||
685 | } | ||
686 | |||
687 | void svc_add_new_temp_xprt(struct svc_serv *serv, struct svc_xprt *newxpt) | ||
688 | { | ||
689 | spin_lock_bh(&serv->sv_lock); | ||
690 | set_bit(XPT_TEMP, &newxpt->xpt_flags); | ||
691 | list_add(&newxpt->xpt_list, &serv->sv_tempsocks); | ||
692 | serv->sv_tmpcnt++; | ||
693 | if (serv->sv_temptimer.function == NULL) { | ||
694 | /* setup timer to age temp transports */ | ||
695 | setup_timer(&serv->sv_temptimer, svc_age_temp_xprts, | ||
696 | (unsigned long)serv); | ||
697 | mod_timer(&serv->sv_temptimer, | ||
698 | jiffies + svc_conn_age_period * HZ); | ||
699 | } | ||
700 | spin_unlock_bh(&serv->sv_lock); | ||
701 | svc_xprt_received(newxpt); | ||
702 | } | ||
703 | |||
704 | static int svc_handle_xprt(struct svc_rqst *rqstp, struct svc_xprt *xprt) | ||
705 | { | ||
706 | struct svc_serv *serv = rqstp->rq_server; | ||
707 | int len = 0; | ||
708 | 708 | ||
709 | len = 0; | ||
709 | if (test_bit(XPT_CLOSE, &xprt->xpt_flags)) { | 710 | if (test_bit(XPT_CLOSE, &xprt->xpt_flags)) { |
710 | dprintk("svc_recv: found XPT_CLOSE\n"); | 711 | dprintk("svc_recv: found XPT_CLOSE\n"); |
711 | svc_delete_xprt(xprt); | 712 | svc_delete_xprt(xprt); |
712 | /* Leave XPT_BUSY set on the dead xprt: */ | 713 | /* Leave XPT_BUSY set on the dead xprt: */ |
713 | return 0; | 714 | goto out; |
714 | } | 715 | } |
715 | if (test_bit(XPT_LISTENER, &xprt->xpt_flags)) { | 716 | if (test_bit(XPT_LISTENER, &xprt->xpt_flags)) { |
716 | struct svc_xprt *newxpt; | 717 | struct svc_xprt *newxpt; |
717 | /* | ||
718 | * We know this module_get will succeed because the | ||
719 | * listener holds a reference too | ||
720 | */ | ||
721 | __module_get(xprt->xpt_class->xcl_owner); | ||
722 | svc_check_conn_limits(xprt->xpt_server); | ||
723 | newxpt = xprt->xpt_ops->xpo_accept(xprt); | 718 | newxpt = xprt->xpt_ops->xpo_accept(xprt); |
724 | if (newxpt) | 719 | if (newxpt) { |
725 | svc_add_new_temp_xprt(serv, newxpt); | 720 | /* |
721 | * We know this module_get will succeed because the | ||
722 | * listener holds a reference too | ||
723 | */ | ||
724 | __module_get(newxpt->xpt_class->xcl_owner); | ||
725 | svc_check_conn_limits(xprt->xpt_server); | ||
726 | spin_lock_bh(&serv->sv_lock); | ||
727 | set_bit(XPT_TEMP, &newxpt->xpt_flags); | ||
728 | list_add(&newxpt->xpt_list, &serv->sv_tempsocks); | ||
729 | serv->sv_tmpcnt++; | ||
730 | if (serv->sv_temptimer.function == NULL) { | ||
731 | /* setup timer to age temp transports */ | ||
732 | setup_timer(&serv->sv_temptimer, | ||
733 | svc_age_temp_xprts, | ||
734 | (unsigned long)serv); | ||
735 | mod_timer(&serv->sv_temptimer, | ||
736 | jiffies + svc_conn_age_period * HZ); | ||
737 | } | ||
738 | spin_unlock_bh(&serv->sv_lock); | ||
739 | svc_xprt_received(newxpt); | ||
740 | } | ||
726 | } else if (xprt->xpt_ops->xpo_has_wspace(xprt)) { | 741 | } else if (xprt->xpt_ops->xpo_has_wspace(xprt)) { |
727 | /* XPT_DATA|XPT_DEFERRED case: */ | ||
728 | dprintk("svc: server %p, pool %u, transport %p, inuse=%d\n", | 742 | dprintk("svc: server %p, pool %u, transport %p, inuse=%d\n", |
729 | rqstp, rqstp->rq_pool->sp_id, xprt, | 743 | rqstp, pool->sp_id, xprt, |
730 | atomic_read(&xprt->xpt_ref.refcount)); | 744 | atomic_read(&xprt->xpt_ref.refcount)); |
731 | rqstp->rq_deferred = svc_deferred_dequeue(xprt); | 745 | rqstp->rq_deferred = svc_deferred_dequeue(xprt); |
732 | if (rqstp->rq_deferred) | 746 | if (rqstp->rq_deferred) |
@@ -734,54 +748,11 @@ static int svc_handle_xprt(struct svc_rqst *rqstp, struct svc_xprt *xprt) | |||
734 | else | 748 | else |
735 | len = xprt->xpt_ops->xpo_recvfrom(rqstp); | 749 | len = xprt->xpt_ops->xpo_recvfrom(rqstp); |
736 | dprintk("svc: got len=%d\n", len); | 750 | dprintk("svc: got len=%d\n", len); |
737 | rqstp->rq_reserved = serv->sv_max_mesg; | ||
738 | atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved); | ||
739 | } | 751 | } |
740 | /* clear XPT_BUSY: */ | ||
741 | svc_xprt_received(xprt); | 752 | svc_xprt_received(xprt); |
742 | return len; | ||
743 | } | ||
744 | |||
745 | /* | ||
746 | * Receive the next request on any transport. This code is carefully | ||
747 | * organised not to touch any cachelines in the shared svc_serv | ||
748 | * structure, only cachelines in the local svc_pool. | ||
749 | */ | ||
750 | int svc_recv(struct svc_rqst *rqstp, long timeout) | ||
751 | { | ||
752 | struct svc_xprt *xprt = NULL; | ||
753 | struct svc_serv *serv = rqstp->rq_server; | ||
754 | int len, err; | ||
755 | |||
756 | dprintk("svc: server %p waiting for data (to = %ld)\n", | ||
757 | rqstp, timeout); | ||
758 | |||
759 | if (rqstp->rq_xprt) | ||
760 | printk(KERN_ERR | ||
761 | "svc_recv: service %p, transport not NULL!\n", | ||
762 | rqstp); | ||
763 | if (waitqueue_active(&rqstp->rq_wait)) | ||
764 | printk(KERN_ERR | ||
765 | "svc_recv: service %p, wait queue active!\n", | ||
766 | rqstp); | ||
767 | |||
768 | err = svc_alloc_arg(rqstp); | ||
769 | if (err) | ||
770 | return err; | ||
771 | |||
772 | try_to_freeze(); | ||
773 | cond_resched(); | ||
774 | if (signalled() || kthread_should_stop()) | ||
775 | return -EINTR; | ||
776 | |||
777 | xprt = svc_get_next_xprt(rqstp, timeout); | ||
778 | if (IS_ERR(xprt)) | ||
779 | return PTR_ERR(xprt); | ||
780 | |||
781 | len = svc_handle_xprt(rqstp, xprt); | ||
782 | 753 | ||
783 | /* No data, incomplete (TCP) read, or accept() */ | 754 | /* No data, incomplete (TCP) read, or accept() */ |
784 | if (len <= 0) | 755 | if (len == 0 || len == -EAGAIN) |
785 | goto out; | 756 | goto out; |
786 | 757 | ||
787 | clear_bit(XPT_OLD, &xprt->xpt_flags); | 758 | clear_bit(XPT_OLD, &xprt->xpt_flags); |
@@ -833,8 +804,7 @@ int svc_send(struct svc_rqst *rqstp) | |||
833 | 804 | ||
834 | /* Grab mutex to serialize outgoing data. */ | 805 | /* Grab mutex to serialize outgoing data. */ |
835 | mutex_lock(&xprt->xpt_mutex); | 806 | mutex_lock(&xprt->xpt_mutex); |
836 | if (test_bit(XPT_DEAD, &xprt->xpt_flags) | 807 | if (test_bit(XPT_DEAD, &xprt->xpt_flags)) |
837 | || test_bit(XPT_CLOSE, &xprt->xpt_flags)) | ||
838 | len = -ENOTCONN; | 808 | len = -ENOTCONN; |
839 | else | 809 | else |
840 | len = xprt->xpt_ops->xpo_sendto(rqstp); | 810 | len = xprt->xpt_ops->xpo_sendto(rqstp); |
@@ -916,7 +886,7 @@ static void call_xpt_users(struct svc_xprt *xprt) | |||
916 | /* | 886 | /* |
917 | * Remove a dead transport | 887 | * Remove a dead transport |
918 | */ | 888 | */ |
919 | static void svc_delete_xprt(struct svc_xprt *xprt) | 889 | void svc_delete_xprt(struct svc_xprt *xprt) |
920 | { | 890 | { |
921 | struct svc_serv *serv = xprt->xpt_server; | 891 | struct svc_serv *serv = xprt->xpt_server; |
922 | struct svc_deferred_req *dr; | 892 | struct svc_deferred_req *dr; |
@@ -931,7 +901,14 @@ static void svc_delete_xprt(struct svc_xprt *xprt) | |||
931 | spin_lock_bh(&serv->sv_lock); | 901 | spin_lock_bh(&serv->sv_lock); |
932 | if (!test_and_set_bit(XPT_DETACHED, &xprt->xpt_flags)) | 902 | if (!test_and_set_bit(XPT_DETACHED, &xprt->xpt_flags)) |
933 | list_del_init(&xprt->xpt_list); | 903 | list_del_init(&xprt->xpt_list); |
934 | WARN_ON_ONCE(!list_empty(&xprt->xpt_ready)); | 904 | /* |
905 | * The only time we're called while xpt_ready is still on a list | ||
906 | * is while the list itself is about to be destroyed (in | ||
907 | * svc_destroy). BUT svc_xprt_enqueue could still be attempting | ||
908 | * to add new entries to the sp_sockets list, so we can't leave | ||
909 | * a freed xprt on it. | ||
910 | */ | ||
911 | list_del_init(&xprt->xpt_ready); | ||
935 | if (test_bit(XPT_TEMP, &xprt->xpt_flags)) | 912 | if (test_bit(XPT_TEMP, &xprt->xpt_flags)) |
936 | serv->sv_tmpcnt--; | 913 | serv->sv_tmpcnt--; |
937 | spin_unlock_bh(&serv->sv_lock); | 914 | spin_unlock_bh(&serv->sv_lock); |
@@ -959,71 +936,22 @@ void svc_close_xprt(struct svc_xprt *xprt) | |||
959 | } | 936 | } |
960 | EXPORT_SYMBOL_GPL(svc_close_xprt); | 937 | EXPORT_SYMBOL_GPL(svc_close_xprt); |
961 | 938 | ||
962 | static void svc_close_list(struct svc_serv *serv, struct list_head *xprt_list, struct net *net) | 939 | void svc_close_all(struct list_head *xprt_list) |
963 | { | ||
964 | struct svc_xprt *xprt; | ||
965 | |||
966 | spin_lock(&serv->sv_lock); | ||
967 | list_for_each_entry(xprt, xprt_list, xpt_list) { | ||
968 | if (xprt->xpt_net != net) | ||
969 | continue; | ||
970 | set_bit(XPT_CLOSE, &xprt->xpt_flags); | ||
971 | set_bit(XPT_BUSY, &xprt->xpt_flags); | ||
972 | } | ||
973 | spin_unlock(&serv->sv_lock); | ||
974 | } | ||
975 | |||
976 | static void svc_clear_pools(struct svc_serv *serv, struct net *net) | ||
977 | { | ||
978 | struct svc_pool *pool; | ||
979 | struct svc_xprt *xprt; | ||
980 | struct svc_xprt *tmp; | ||
981 | int i; | ||
982 | |||
983 | for (i = 0; i < serv->sv_nrpools; i++) { | ||
984 | pool = &serv->sv_pools[i]; | ||
985 | |||
986 | spin_lock_bh(&pool->sp_lock); | ||
987 | list_for_each_entry_safe(xprt, tmp, &pool->sp_sockets, xpt_ready) { | ||
988 | if (xprt->xpt_net != net) | ||
989 | continue; | ||
990 | list_del_init(&xprt->xpt_ready); | ||
991 | } | ||
992 | spin_unlock_bh(&pool->sp_lock); | ||
993 | } | ||
994 | } | ||
995 | |||
996 | static void svc_clear_list(struct svc_serv *serv, struct list_head *xprt_list, struct net *net) | ||
997 | { | 940 | { |
998 | struct svc_xprt *xprt; | 941 | struct svc_xprt *xprt; |
999 | struct svc_xprt *tmp; | 942 | struct svc_xprt *tmp; |
1000 | LIST_HEAD(victims); | ||
1001 | 943 | ||
1002 | spin_lock(&serv->sv_lock); | ||
1003 | list_for_each_entry_safe(xprt, tmp, xprt_list, xpt_list) { | ||
1004 | if (xprt->xpt_net != net) | ||
1005 | continue; | ||
1006 | list_move(&xprt->xpt_list, &victims); | ||
1007 | } | ||
1008 | spin_unlock(&serv->sv_lock); | ||
1009 | |||
1010 | list_for_each_entry_safe(xprt, tmp, &victims, xpt_list) | ||
1011 | svc_delete_xprt(xprt); | ||
1012 | } | ||
1013 | |||
1014 | void svc_close_net(struct svc_serv *serv, struct net *net) | ||
1015 | { | ||
1016 | svc_close_list(serv, &serv->sv_tempsocks, net); | ||
1017 | svc_close_list(serv, &serv->sv_permsocks, net); | ||
1018 | |||
1019 | svc_clear_pools(serv, net); | ||
1020 | /* | 944 | /* |
1021 | * At this point the sp_sockets lists will stay empty, since | 945 | * The server is shutting down, and no more threads are running. |
1022 | * svc_xprt_enqueue will not add new entries without taking the | 946 | * svc_xprt_enqueue() might still be running, but at worst it |
1023 | * sp_lock and checking XPT_BUSY. | 947 | * will re-add the xprt to sp_sockets, which will soon get |
948 | * freed. So we don't bother with any more locking, and don't | ||
949 | * leave the close to the (nonexistent) server threads: | ||
1024 | */ | 950 | */ |
1025 | svc_clear_list(serv, &serv->sv_tempsocks, net); | 951 | list_for_each_entry_safe(xprt, tmp, xprt_list, xpt_list) { |
1026 | svc_clear_list(serv, &serv->sv_permsocks, net); | 952 | set_bit(XPT_CLOSE, &xprt->xpt_flags); |
953 | svc_delete_xprt(xprt); | ||
954 | } | ||
1027 | } | 955 | } |
1028 | 956 | ||
1029 | /* | 957 | /* |
@@ -1149,7 +1077,6 @@ static struct svc_deferred_req *svc_deferred_dequeue(struct svc_xprt *xprt) | |||
1149 | * svc_find_xprt - find an RPC transport instance | 1077 | * svc_find_xprt - find an RPC transport instance |
1150 | * @serv: pointer to svc_serv to search | 1078 | * @serv: pointer to svc_serv to search |
1151 | * @xcl_name: C string containing transport's class name | 1079 | * @xcl_name: C string containing transport's class name |
1152 | * @net: owner net pointer | ||
1153 | * @af: Address family of transport's local address | 1080 | * @af: Address family of transport's local address |
1154 | * @port: transport's IP port number | 1081 | * @port: transport's IP port number |
1155 | * | 1082 | * |
@@ -1162,8 +1089,7 @@ static struct svc_deferred_req *svc_deferred_dequeue(struct svc_xprt *xprt) | |||
1162 | * service's list that has a matching class name. | 1089 | * service's list that has a matching class name. |
1163 | */ | 1090 | */ |
1164 | struct svc_xprt *svc_find_xprt(struct svc_serv *serv, const char *xcl_name, | 1091 | struct svc_xprt *svc_find_xprt(struct svc_serv *serv, const char *xcl_name, |
1165 | struct net *net, const sa_family_t af, | 1092 | const sa_family_t af, const unsigned short port) |
1166 | const unsigned short port) | ||
1167 | { | 1093 | { |
1168 | struct svc_xprt *xprt; | 1094 | struct svc_xprt *xprt; |
1169 | struct svc_xprt *found = NULL; | 1095 | struct svc_xprt *found = NULL; |
@@ -1174,8 +1100,6 @@ struct svc_xprt *svc_find_xprt(struct svc_serv *serv, const char *xcl_name, | |||
1174 | 1100 | ||
1175 | spin_lock_bh(&serv->sv_lock); | 1101 | spin_lock_bh(&serv->sv_lock); |
1176 | list_for_each_entry(xprt, &serv->sv_permsocks, xpt_list) { | 1102 | list_for_each_entry(xprt, &serv->sv_permsocks, xpt_list) { |
1177 | if (xprt->xpt_net != net) | ||
1178 | continue; | ||
1179 | if (strcmp(xprt->xpt_class->xcl_name, xcl_name)) | 1103 | if (strcmp(xprt->xpt_class->xcl_name, xcl_name)) |
1180 | continue; | 1104 | continue; |
1181 | if (af != AF_UNSPEC && af != xprt->xpt_local.ss_family) | 1105 | if (af != AF_UNSPEC && af != xprt->xpt_local.ss_family) |
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index 4d012920373..ce136323da8 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <net/sock.h> | 14 | #include <net/sock.h> |
15 | #include <net/ipv6.h> | 15 | #include <net/ipv6.h> |
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/user_namespace.h> | ||
18 | #define RPCDBG_FACILITY RPCDBG_AUTH | 17 | #define RPCDBG_FACILITY RPCDBG_AUTH |
19 | 18 | ||
20 | #include <linux/sunrpc/clnt.h> | 19 | #include <linux/sunrpc/clnt.h> |
@@ -104,9 +103,23 @@ static void ip_map_put(struct kref *kref) | |||
104 | kfree(im); | 103 | kfree(im); |
105 | } | 104 | } |
106 | 105 | ||
107 | static inline int hash_ip6(const struct in6_addr *ip) | 106 | #if IP_HASHBITS == 8 |
107 | /* hash_long on a 64 bit machine is currently REALLY BAD for | ||
108 | * IP addresses in reverse-endian (i.e. on a little-endian machine). | ||
109 | * So use a trivial but reliable hash instead | ||
110 | */ | ||
111 | static inline int hash_ip(__be32 ip) | ||
112 | { | ||
113 | int hash = (__force u32)ip ^ ((__force u32)ip>>16); | ||
114 | return (hash ^ (hash>>8)) & 0xff; | ||
115 | } | ||
116 | #endif | ||
117 | static inline int hash_ip6(struct in6_addr ip) | ||
108 | { | 118 | { |
109 | return hash_32(ipv6_addr_hash(ip), IP_HASHBITS); | 119 | return (hash_ip(ip.s6_addr32[0]) ^ |
120 | hash_ip(ip.s6_addr32[1]) ^ | ||
121 | hash_ip(ip.s6_addr32[2]) ^ | ||
122 | hash_ip(ip.s6_addr32[3])); | ||
110 | } | 123 | } |
111 | static int ip_map_match(struct cache_head *corig, struct cache_head *cnew) | 124 | static int ip_map_match(struct cache_head *corig, struct cache_head *cnew) |
112 | { | 125 | { |
@@ -121,7 +134,7 @@ static void ip_map_init(struct cache_head *cnew, struct cache_head *citem) | |||
121 | struct ip_map *item = container_of(citem, struct ip_map, h); | 134 | struct ip_map *item = container_of(citem, struct ip_map, h); |
122 | 135 | ||
123 | strcpy(new->m_class, item->m_class); | 136 | strcpy(new->m_class, item->m_class); |
124 | new->m_addr = item->m_addr; | 137 | ipv6_addr_copy(&new->m_addr, &item->m_addr); |
125 | } | 138 | } |
126 | static void update(struct cache_head *cnew, struct cache_head *citem) | 139 | static void update(struct cache_head *cnew, struct cache_head *citem) |
127 | { | 140 | { |
@@ -198,7 +211,7 @@ static int ip_map_parse(struct cache_detail *cd, | |||
198 | len = qword_get(&mesg, buf, mlen); | 211 | len = qword_get(&mesg, buf, mlen); |
199 | if (len <= 0) return -EINVAL; | 212 | if (len <= 0) return -EINVAL; |
200 | 213 | ||
201 | if (rpc_pton(cd->net, buf, len, &address.sa, sizeof(address)) == 0) | 214 | if (rpc_pton(buf, len, &address.sa, sizeof(address)) == 0) |
202 | return -EINVAL; | 215 | return -EINVAL; |
203 | switch (address.sa.sa_family) { | 216 | switch (address.sa.sa_family) { |
204 | case AF_INET: | 217 | case AF_INET: |
@@ -207,7 +220,7 @@ static int ip_map_parse(struct cache_detail *cd, | |||
207 | ipv6_addr_set_v4mapped(address.s4.sin_addr.s_addr, | 220 | ipv6_addr_set_v4mapped(address.s4.sin_addr.s_addr, |
208 | &sin6.sin6_addr); | 221 | &sin6.sin6_addr); |
209 | break; | 222 | break; |
210 | #if IS_ENABLED(CONFIG_IPV6) | 223 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
211 | case AF_INET6: | 224 | case AF_INET6: |
212 | memcpy(&sin6, &address.s6, sizeof(sin6)); | 225 | memcpy(&sin6, &address.s6, sizeof(sin6)); |
213 | break; | 226 | break; |
@@ -261,7 +274,7 @@ static int ip_map_show(struct seq_file *m, | |||
261 | } | 274 | } |
262 | im = container_of(h, struct ip_map, h); | 275 | im = container_of(h, struct ip_map, h); |
263 | /* class addr domain */ | 276 | /* class addr domain */ |
264 | addr = im->m_addr; | 277 | ipv6_addr_copy(&addr, &im->m_addr); |
265 | 278 | ||
266 | if (test_bit(CACHE_VALID, &h->flags) && | 279 | if (test_bit(CACHE_VALID, &h->flags) && |
267 | !test_bit(CACHE_NEGATIVE, &h->flags)) | 280 | !test_bit(CACHE_NEGATIVE, &h->flags)) |
@@ -284,10 +297,10 @@ static struct ip_map *__ip_map_lookup(struct cache_detail *cd, char *class, | |||
284 | struct cache_head *ch; | 297 | struct cache_head *ch; |
285 | 298 | ||
286 | strcpy(ip.m_class, class); | 299 | strcpy(ip.m_class, class); |
287 | ip.m_addr = *addr; | 300 | ipv6_addr_copy(&ip.m_addr, addr); |
288 | ch = sunrpc_cache_lookup(cd, &ip.h, | 301 | ch = sunrpc_cache_lookup(cd, &ip.h, |
289 | hash_str(class, IP_HASHBITS) ^ | 302 | hash_str(class, IP_HASHBITS) ^ |
290 | hash_ip6(addr)); | 303 | hash_ip6(*addr)); |
291 | 304 | ||
292 | if (ch) | 305 | if (ch) |
293 | return container_of(ch, struct ip_map, h); | 306 | return container_of(ch, struct ip_map, h); |
@@ -317,7 +330,7 @@ static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm, | |||
317 | ip.h.expiry_time = expiry; | 330 | ip.h.expiry_time = expiry; |
318 | ch = sunrpc_cache_update(cd, &ip.h, &ipm->h, | 331 | ch = sunrpc_cache_update(cd, &ip.h, &ipm->h, |
319 | hash_str(ipm->m_class, IP_HASHBITS) ^ | 332 | hash_str(ipm->m_class, IP_HASHBITS) ^ |
320 | hash_ip6(&ipm->m_addr)); | 333 | hash_ip6(ipm->m_addr)); |
321 | if (!ch) | 334 | if (!ch) |
322 | return -ENOMEM; | 335 | return -ENOMEM; |
323 | cache_put(ch, cd); | 336 | cache_put(ch, cd); |
@@ -333,12 +346,17 @@ static inline int ip_map_update(struct net *net, struct ip_map *ipm, | |||
333 | return __ip_map_update(sn->ip_map_cache, ipm, udom, expiry); | 346 | return __ip_map_update(sn->ip_map_cache, ipm, udom, expiry); |
334 | } | 347 | } |
335 | 348 | ||
336 | void svcauth_unix_purge(struct net *net) | 349 | |
350 | void svcauth_unix_purge(void) | ||
337 | { | 351 | { |
338 | struct sunrpc_net *sn; | 352 | struct net *net; |
339 | 353 | ||
340 | sn = net_generic(net, sunrpc_net_id); | 354 | for_each_net(net) { |
341 | cache_purge(sn->ip_map_cache); | 355 | struct sunrpc_net *sn; |
356 | |||
357 | sn = net_generic(net, sunrpc_net_id); | ||
358 | cache_purge(sn->ip_map_cache); | ||
359 | } | ||
342 | } | 360 | } |
343 | EXPORT_SYMBOL_GPL(svcauth_unix_purge); | 361 | EXPORT_SYMBOL_GPL(svcauth_unix_purge); |
344 | 362 | ||
@@ -418,6 +436,7 @@ struct unix_gid { | |||
418 | uid_t uid; | 436 | uid_t uid; |
419 | struct group_info *gi; | 437 | struct group_info *gi; |
420 | }; | 438 | }; |
439 | static struct cache_head *gid_table[GID_HASHMAX]; | ||
421 | 440 | ||
422 | static void unix_gid_put(struct kref *kref) | 441 | static void unix_gid_put(struct kref *kref) |
423 | { | 442 | { |
@@ -475,7 +494,8 @@ static int unix_gid_upcall(struct cache_detail *cd, struct cache_head *h) | |||
475 | return sunrpc_cache_pipe_upcall(cd, h, unix_gid_request); | 494 | return sunrpc_cache_pipe_upcall(cd, h, unix_gid_request); |
476 | } | 495 | } |
477 | 496 | ||
478 | static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, uid_t uid); | 497 | static struct unix_gid *unix_gid_lookup(uid_t uid); |
498 | extern struct cache_detail unix_gid_cache; | ||
479 | 499 | ||
480 | static int unix_gid_parse(struct cache_detail *cd, | 500 | static int unix_gid_parse(struct cache_detail *cd, |
481 | char *mesg, int mlen) | 501 | char *mesg, int mlen) |
@@ -489,7 +509,7 @@ static int unix_gid_parse(struct cache_detail *cd, | |||
489 | time_t expiry; | 509 | time_t expiry; |
490 | struct unix_gid ug, *ugp; | 510 | struct unix_gid ug, *ugp; |
491 | 511 | ||
492 | if (mesg[mlen - 1] != '\n') | 512 | if (mlen <= 0 || mesg[mlen-1] != '\n') |
493 | return -EINVAL; | 513 | return -EINVAL; |
494 | mesg[mlen-1] = 0; | 514 | mesg[mlen-1] = 0; |
495 | 515 | ||
@@ -512,30 +532,26 @@ static int unix_gid_parse(struct cache_detail *cd, | |||
512 | 532 | ||
513 | for (i = 0 ; i < gids ; i++) { | 533 | for (i = 0 ; i < gids ; i++) { |
514 | int gid; | 534 | int gid; |
515 | kgid_t kgid; | ||
516 | rv = get_int(&mesg, &gid); | 535 | rv = get_int(&mesg, &gid); |
517 | err = -EINVAL; | 536 | err = -EINVAL; |
518 | if (rv) | 537 | if (rv) |
519 | goto out; | 538 | goto out; |
520 | kgid = make_kgid(&init_user_ns, gid); | 539 | GROUP_AT(ug.gi, i) = gid; |
521 | if (!gid_valid(kgid)) | ||
522 | goto out; | ||
523 | GROUP_AT(ug.gi, i) = kgid; | ||
524 | } | 540 | } |
525 | 541 | ||
526 | ugp = unix_gid_lookup(cd, uid); | 542 | ugp = unix_gid_lookup(uid); |
527 | if (ugp) { | 543 | if (ugp) { |
528 | struct cache_head *ch; | 544 | struct cache_head *ch; |
529 | ug.h.flags = 0; | 545 | ug.h.flags = 0; |
530 | ug.h.expiry_time = expiry; | 546 | ug.h.expiry_time = expiry; |
531 | ch = sunrpc_cache_update(cd, | 547 | ch = sunrpc_cache_update(&unix_gid_cache, |
532 | &ug.h, &ugp->h, | 548 | &ug.h, &ugp->h, |
533 | hash_long(uid, GID_HASHBITS)); | 549 | hash_long(uid, GID_HASHBITS)); |
534 | if (!ch) | 550 | if (!ch) |
535 | err = -ENOMEM; | 551 | err = -ENOMEM; |
536 | else { | 552 | else { |
537 | err = 0; | 553 | err = 0; |
538 | cache_put(ch, cd); | 554 | cache_put(ch, &unix_gid_cache); |
539 | } | 555 | } |
540 | } else | 556 | } else |
541 | err = -ENOMEM; | 557 | err = -ENOMEM; |
@@ -549,7 +565,6 @@ static int unix_gid_show(struct seq_file *m, | |||
549 | struct cache_detail *cd, | 565 | struct cache_detail *cd, |
550 | struct cache_head *h) | 566 | struct cache_head *h) |
551 | { | 567 | { |
552 | struct user_namespace *user_ns = current_user_ns(); | ||
553 | struct unix_gid *ug; | 568 | struct unix_gid *ug; |
554 | int i; | 569 | int i; |
555 | int glen; | 570 | int glen; |
@@ -567,14 +582,15 @@ static int unix_gid_show(struct seq_file *m, | |||
567 | 582 | ||
568 | seq_printf(m, "%u %d:", ug->uid, glen); | 583 | seq_printf(m, "%u %d:", ug->uid, glen); |
569 | for (i = 0; i < glen; i++) | 584 | for (i = 0; i < glen; i++) |
570 | seq_printf(m, " %d", from_kgid_munged(user_ns, GROUP_AT(ug->gi, i))); | 585 | seq_printf(m, " %d", GROUP_AT(ug->gi, i)); |
571 | seq_printf(m, "\n"); | 586 | seq_printf(m, "\n"); |
572 | return 0; | 587 | return 0; |
573 | } | 588 | } |
574 | 589 | ||
575 | static struct cache_detail unix_gid_cache_template = { | 590 | struct cache_detail unix_gid_cache = { |
576 | .owner = THIS_MODULE, | 591 | .owner = THIS_MODULE, |
577 | .hash_size = GID_HASHMAX, | 592 | .hash_size = GID_HASHMAX, |
593 | .hash_table = gid_table, | ||
578 | .name = "auth.unix.gid", | 594 | .name = "auth.unix.gid", |
579 | .cache_put = unix_gid_put, | 595 | .cache_put = unix_gid_put, |
580 | .cache_upcall = unix_gid_upcall, | 596 | .cache_upcall = unix_gid_upcall, |
@@ -586,42 +602,14 @@ static struct cache_detail unix_gid_cache_template = { | |||
586 | .alloc = unix_gid_alloc, | 602 | .alloc = unix_gid_alloc, |
587 | }; | 603 | }; |
588 | 604 | ||
589 | int unix_gid_cache_create(struct net *net) | 605 | static struct unix_gid *unix_gid_lookup(uid_t uid) |
590 | { | ||
591 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
592 | struct cache_detail *cd; | ||
593 | int err; | ||
594 | |||
595 | cd = cache_create_net(&unix_gid_cache_template, net); | ||
596 | if (IS_ERR(cd)) | ||
597 | return PTR_ERR(cd); | ||
598 | err = cache_register_net(cd, net); | ||
599 | if (err) { | ||
600 | cache_destroy_net(cd, net); | ||
601 | return err; | ||
602 | } | ||
603 | sn->unix_gid_cache = cd; | ||
604 | return 0; | ||
605 | } | ||
606 | |||
607 | void unix_gid_cache_destroy(struct net *net) | ||
608 | { | ||
609 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
610 | struct cache_detail *cd = sn->unix_gid_cache; | ||
611 | |||
612 | sn->unix_gid_cache = NULL; | ||
613 | cache_purge(cd); | ||
614 | cache_unregister_net(cd, net); | ||
615 | cache_destroy_net(cd, net); | ||
616 | } | ||
617 | |||
618 | static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, uid_t uid) | ||
619 | { | 606 | { |
620 | struct unix_gid ug; | 607 | struct unix_gid ug; |
621 | struct cache_head *ch; | 608 | struct cache_head *ch; |
622 | 609 | ||
623 | ug.uid = uid; | 610 | ug.uid = uid; |
624 | ch = sunrpc_cache_lookup(cd, &ug.h, hash_long(uid, GID_HASHBITS)); | 611 | ch = sunrpc_cache_lookup(&unix_gid_cache, &ug.h, |
612 | hash_long(uid, GID_HASHBITS)); | ||
625 | if (ch) | 613 | if (ch) |
626 | return container_of(ch, struct unix_gid, h); | 614 | return container_of(ch, struct unix_gid, h); |
627 | else | 615 | else |
@@ -633,13 +621,11 @@ static struct group_info *unix_gid_find(uid_t uid, struct svc_rqst *rqstp) | |||
633 | struct unix_gid *ug; | 621 | struct unix_gid *ug; |
634 | struct group_info *gi; | 622 | struct group_info *gi; |
635 | int ret; | 623 | int ret; |
636 | struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, | ||
637 | sunrpc_net_id); | ||
638 | 624 | ||
639 | ug = unix_gid_lookup(sn->unix_gid_cache, uid); | 625 | ug = unix_gid_lookup(uid); |
640 | if (!ug) | 626 | if (!ug) |
641 | return ERR_PTR(-EAGAIN); | 627 | return ERR_PTR(-EAGAIN); |
642 | ret = cache_check(sn->unix_gid_cache, &ug->h, &rqstp->rq_chandle); | 628 | ret = cache_check(&unix_gid_cache, &ug->h, &rqstp->rq_chandle); |
643 | switch (ret) { | 629 | switch (ret) { |
644 | case -ENOENT: | 630 | case -ENOENT: |
645 | return ERR_PTR(-ENOENT); | 631 | return ERR_PTR(-ENOENT); |
@@ -647,7 +633,7 @@ static struct group_info *unix_gid_find(uid_t uid, struct svc_rqst *rqstp) | |||
647 | return ERR_PTR(-ESHUTDOWN); | 633 | return ERR_PTR(-ESHUTDOWN); |
648 | case 0: | 634 | case 0: |
649 | gi = get_group_info(ug->gi); | 635 | gi = get_group_info(ug->gi); |
650 | cache_put(&ug->h, sn->unix_gid_cache); | 636 | cache_put(&ug->h, &unix_gid_cache); |
651 | return gi; | 637 | return gi; |
652 | default: | 638 | default: |
653 | return ERR_PTR(-EAGAIN); | 639 | return ERR_PTR(-EAGAIN); |
@@ -732,7 +718,6 @@ svcauth_null_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
732 | struct svc_cred *cred = &rqstp->rq_cred; | 718 | struct svc_cred *cred = &rqstp->rq_cred; |
733 | 719 | ||
734 | cred->cr_group_info = NULL; | 720 | cred->cr_group_info = NULL; |
735 | cred->cr_principal = NULL; | ||
736 | rqstp->rq_client = NULL; | 721 | rqstp->rq_client = NULL; |
737 | 722 | ||
738 | if (argv->iov_len < 3*4) | 723 | if (argv->iov_len < 3*4) |
@@ -760,7 +745,7 @@ svcauth_null_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
760 | svc_putnl(resv, RPC_AUTH_NULL); | 745 | svc_putnl(resv, RPC_AUTH_NULL); |
761 | svc_putnl(resv, 0); | 746 | svc_putnl(resv, 0); |
762 | 747 | ||
763 | rqstp->rq_cred.cr_flavor = RPC_AUTH_NULL; | 748 | rqstp->rq_flavor = RPC_AUTH_NULL; |
764 | return SVC_OK; | 749 | return SVC_OK; |
765 | } | 750 | } |
766 | 751 | ||
@@ -798,7 +783,6 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
798 | int len = argv->iov_len; | 783 | int len = argv->iov_len; |
799 | 784 | ||
800 | cred->cr_group_info = NULL; | 785 | cred->cr_group_info = NULL; |
801 | cred->cr_principal = NULL; | ||
802 | rqstp->rq_client = NULL; | 786 | rqstp->rq_client = NULL; |
803 | 787 | ||
804 | if ((len -= 3*4) < 0) | 788 | if ((len -= 3*4) < 0) |
@@ -820,12 +804,8 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
820 | cred->cr_group_info = groups_alloc(slen); | 804 | cred->cr_group_info = groups_alloc(slen); |
821 | if (cred->cr_group_info == NULL) | 805 | if (cred->cr_group_info == NULL) |
822 | return SVC_CLOSE; | 806 | return SVC_CLOSE; |
823 | for (i = 0; i < slen; i++) { | 807 | for (i = 0; i < slen; i++) |
824 | kgid_t kgid = make_kgid(&init_user_ns, svc_getnl(argv)); | 808 | GROUP_AT(cred->cr_group_info, i) = svc_getnl(argv); |
825 | if (!gid_valid(kgid)) | ||
826 | goto badcred; | ||
827 | GROUP_AT(cred->cr_group_info, i) = kgid; | ||
828 | } | ||
829 | if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) { | 809 | if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) { |
830 | *authp = rpc_autherr_badverf; | 810 | *authp = rpc_autherr_badverf; |
831 | return SVC_DENIED; | 811 | return SVC_DENIED; |
@@ -835,7 +815,7 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
835 | svc_putnl(resv, RPC_AUTH_NULL); | 815 | svc_putnl(resv, RPC_AUTH_NULL); |
836 | svc_putnl(resv, 0); | 816 | svc_putnl(resv, 0); |
837 | 817 | ||
838 | rqstp->rq_cred.cr_flavor = RPC_AUTH_UNIX; | 818 | rqstp->rq_flavor = RPC_AUTH_UNIX; |
839 | return SVC_OK; | 819 | return SVC_OK; |
840 | 820 | ||
841 | badcred: | 821 | badcred: |
@@ -869,45 +849,56 @@ struct auth_ops svcauth_unix = { | |||
869 | .set_client = svcauth_unix_set_client, | 849 | .set_client = svcauth_unix_set_client, |
870 | }; | 850 | }; |
871 | 851 | ||
872 | static struct cache_detail ip_map_cache_template = { | ||
873 | .owner = THIS_MODULE, | ||
874 | .hash_size = IP_HASHMAX, | ||
875 | .name = "auth.unix.ip", | ||
876 | .cache_put = ip_map_put, | ||
877 | .cache_upcall = ip_map_upcall, | ||
878 | .cache_parse = ip_map_parse, | ||
879 | .cache_show = ip_map_show, | ||
880 | .match = ip_map_match, | ||
881 | .init = ip_map_init, | ||
882 | .update = update, | ||
883 | .alloc = ip_map_alloc, | ||
884 | }; | ||
885 | |||
886 | int ip_map_cache_create(struct net *net) | 852 | int ip_map_cache_create(struct net *net) |
887 | { | 853 | { |
888 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | 854 | int err = -ENOMEM; |
889 | struct cache_detail *cd; | 855 | struct cache_detail *cd; |
890 | int err; | 856 | struct cache_head **tbl; |
857 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
858 | |||
859 | cd = kzalloc(sizeof(struct cache_detail), GFP_KERNEL); | ||
860 | if (cd == NULL) | ||
861 | goto err_cd; | ||
862 | |||
863 | tbl = kzalloc(IP_HASHMAX * sizeof(struct cache_head *), GFP_KERNEL); | ||
864 | if (tbl == NULL) | ||
865 | goto err_tbl; | ||
866 | |||
867 | cd->owner = THIS_MODULE, | ||
868 | cd->hash_size = IP_HASHMAX, | ||
869 | cd->hash_table = tbl, | ||
870 | cd->name = "auth.unix.ip", | ||
871 | cd->cache_put = ip_map_put, | ||
872 | cd->cache_upcall = ip_map_upcall, | ||
873 | cd->cache_parse = ip_map_parse, | ||
874 | cd->cache_show = ip_map_show, | ||
875 | cd->match = ip_map_match, | ||
876 | cd->init = ip_map_init, | ||
877 | cd->update = update, | ||
878 | cd->alloc = ip_map_alloc, | ||
891 | 879 | ||
892 | cd = cache_create_net(&ip_map_cache_template, net); | ||
893 | if (IS_ERR(cd)) | ||
894 | return PTR_ERR(cd); | ||
895 | err = cache_register_net(cd, net); | 880 | err = cache_register_net(cd, net); |
896 | if (err) { | 881 | if (err) |
897 | cache_destroy_net(cd, net); | 882 | goto err_reg; |
898 | return err; | 883 | |
899 | } | ||
900 | sn->ip_map_cache = cd; | 884 | sn->ip_map_cache = cd; |
901 | return 0; | 885 | return 0; |
886 | |||
887 | err_reg: | ||
888 | kfree(tbl); | ||
889 | err_tbl: | ||
890 | kfree(cd); | ||
891 | err_cd: | ||
892 | return err; | ||
902 | } | 893 | } |
903 | 894 | ||
904 | void ip_map_cache_destroy(struct net *net) | 895 | void ip_map_cache_destroy(struct net *net) |
905 | { | 896 | { |
906 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | 897 | struct sunrpc_net *sn; |
907 | struct cache_detail *cd = sn->ip_map_cache; | ||
908 | 898 | ||
909 | sn->ip_map_cache = NULL; | 899 | sn = net_generic(net, sunrpc_net_id); |
910 | cache_purge(cd); | 900 | cache_purge(sn->ip_map_cache); |
911 | cache_unregister_net(cd, net); | 901 | cache_unregister_net(sn->ip_map_cache, net); |
912 | cache_destroy_net(cd, net); | 902 | kfree(sn->ip_map_cache->hash_table); |
903 | kfree(sn->ip_map_cache); | ||
913 | } | 904 | } |
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 0a148c9d2a5..767d494de7a 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
@@ -21,7 +21,6 @@ | |||
21 | 21 | ||
22 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
23 | #include <linux/sched.h> | 23 | #include <linux/sched.h> |
24 | #include <linux/module.h> | ||
25 | #include <linux/errno.h> | 24 | #include <linux/errno.h> |
26 | #include <linux/fcntl.h> | 25 | #include <linux/fcntl.h> |
27 | #include <linux/net.h> | 26 | #include <linux/net.h> |
@@ -43,7 +42,6 @@ | |||
43 | #include <net/tcp_states.h> | 42 | #include <net/tcp_states.h> |
44 | #include <asm/uaccess.h> | 43 | #include <asm/uaccess.h> |
45 | #include <asm/ioctls.h> | 44 | #include <asm/ioctls.h> |
46 | #include <trace/events/skb.h> | ||
47 | 45 | ||
48 | #include <linux/sunrpc/types.h> | 46 | #include <linux/sunrpc/types.h> |
49 | #include <linux/sunrpc/clnt.h> | 47 | #include <linux/sunrpc/clnt.h> |
@@ -59,7 +57,7 @@ | |||
59 | 57 | ||
60 | 58 | ||
61 | static struct svc_sock *svc_setup_socket(struct svc_serv *, struct socket *, | 59 | static struct svc_sock *svc_setup_socket(struct svc_serv *, struct socket *, |
62 | int flags); | 60 | int *errp, int flags); |
63 | static void svc_udp_data_ready(struct sock *, int); | 61 | static void svc_udp_data_ready(struct sock *, int); |
64 | static int svc_udp_recvfrom(struct svc_rqst *); | 62 | static int svc_udp_recvfrom(struct svc_rqst *); |
65 | static int svc_udp_sendto(struct svc_rqst *); | 63 | static int svc_udp_sendto(struct svc_rqst *); |
@@ -84,11 +82,7 @@ static struct lock_class_key svc_slock_key[2]; | |||
84 | static void svc_reclassify_socket(struct socket *sock) | 82 | static void svc_reclassify_socket(struct socket *sock) |
85 | { | 83 | { |
86 | struct sock *sk = sock->sk; | 84 | struct sock *sk = sock->sk; |
87 | 85 | BUG_ON(sock_owned_by_user(sk)); | |
88 | WARN_ON_ONCE(sock_owned_by_user(sk)); | ||
89 | if (sock_owned_by_user(sk)) | ||
90 | return; | ||
91 | |||
92 | switch (sk->sk_family) { | 86 | switch (sk->sk_family) { |
93 | case AF_INET: | 87 | case AF_INET: |
94 | sock_lock_init_class_and_name(sk, "slock-AF_INET-NFSD", | 88 | sock_lock_init_class_and_name(sk, "slock-AF_INET-NFSD", |
@@ -149,20 +143,19 @@ static void svc_set_cmsg_data(struct svc_rqst *rqstp, struct cmsghdr *cmh) | |||
149 | cmh->cmsg_level = SOL_IP; | 143 | cmh->cmsg_level = SOL_IP; |
150 | cmh->cmsg_type = IP_PKTINFO; | 144 | cmh->cmsg_type = IP_PKTINFO; |
151 | pki->ipi_ifindex = 0; | 145 | pki->ipi_ifindex = 0; |
152 | pki->ipi_spec_dst.s_addr = | 146 | pki->ipi_spec_dst.s_addr = rqstp->rq_daddr.addr.s_addr; |
153 | svc_daddr_in(rqstp)->sin_addr.s_addr; | ||
154 | cmh->cmsg_len = CMSG_LEN(sizeof(*pki)); | 147 | cmh->cmsg_len = CMSG_LEN(sizeof(*pki)); |
155 | } | 148 | } |
156 | break; | 149 | break; |
157 | 150 | ||
158 | case AF_INET6: { | 151 | case AF_INET6: { |
159 | struct in6_pktinfo *pki = CMSG_DATA(cmh); | 152 | struct in6_pktinfo *pki = CMSG_DATA(cmh); |
160 | struct sockaddr_in6 *daddr = svc_daddr_in6(rqstp); | ||
161 | 153 | ||
162 | cmh->cmsg_level = SOL_IPV6; | 154 | cmh->cmsg_level = SOL_IPV6; |
163 | cmh->cmsg_type = IPV6_PKTINFO; | 155 | cmh->cmsg_type = IPV6_PKTINFO; |
164 | pki->ipi6_ifindex = daddr->sin6_scope_id; | 156 | pki->ipi6_ifindex = 0; |
165 | pki->ipi6_addr = daddr->sin6_addr; | 157 | ipv6_addr_copy(&pki->ipi6_addr, |
158 | &rqstp->rq_daddr.addr6); | ||
166 | cmh->cmsg_len = CMSG_LEN(sizeof(*pki)); | 159 | cmh->cmsg_len = CMSG_LEN(sizeof(*pki)); |
167 | } | 160 | } |
168 | break; | 161 | break; |
@@ -309,6 +302,57 @@ static int svc_one_sock_name(struct svc_sock *svsk, char *buf, int remaining) | |||
309 | return len; | 302 | return len; |
310 | } | 303 | } |
311 | 304 | ||
305 | /** | ||
306 | * svc_sock_names - construct a list of listener names in a string | ||
307 | * @serv: pointer to RPC service | ||
308 | * @buf: pointer to a buffer to fill in with socket names | ||
309 | * @buflen: size of the buffer to be filled | ||
310 | * @toclose: pointer to '\0'-terminated C string containing the name | ||
311 | * of a listener to be closed | ||
312 | * | ||
313 | * Fills in @buf with a '\n'-separated list of names of listener | ||
314 | * sockets. If @toclose is not NULL, the socket named by @toclose | ||
315 | * is closed, and is not included in the output list. | ||
316 | * | ||
317 | * Returns positive length of the socket name string, or a negative | ||
318 | * errno value on error. | ||
319 | */ | ||
320 | int svc_sock_names(struct svc_serv *serv, char *buf, const size_t buflen, | ||
321 | const char *toclose) | ||
322 | { | ||
323 | struct svc_sock *svsk, *closesk = NULL; | ||
324 | int len = 0; | ||
325 | |||
326 | if (!serv) | ||
327 | return 0; | ||
328 | |||
329 | spin_lock_bh(&serv->sv_lock); | ||
330 | list_for_each_entry(svsk, &serv->sv_permsocks, sk_xprt.xpt_list) { | ||
331 | int onelen = svc_one_sock_name(svsk, buf + len, buflen - len); | ||
332 | if (onelen < 0) { | ||
333 | len = onelen; | ||
334 | break; | ||
335 | } | ||
336 | if (toclose && strcmp(toclose, buf + len) == 0) { | ||
337 | closesk = svsk; | ||
338 | svc_xprt_get(&closesk->sk_xprt); | ||
339 | } else | ||
340 | len += onelen; | ||
341 | } | ||
342 | spin_unlock_bh(&serv->sv_lock); | ||
343 | |||
344 | if (closesk) { | ||
345 | /* Should unregister with portmap, but you cannot | ||
346 | * unregister just one protocol... | ||
347 | */ | ||
348 | svc_close_xprt(&closesk->sk_xprt); | ||
349 | svc_xprt_put(&closesk->sk_xprt); | ||
350 | } else if (toclose) | ||
351 | return -ENOENT; | ||
352 | return len; | ||
353 | } | ||
354 | EXPORT_SYMBOL_GPL(svc_sock_names); | ||
355 | |||
312 | /* | 356 | /* |
313 | * Check input queue length | 357 | * Check input queue length |
314 | */ | 358 | */ |
@@ -350,7 +394,7 @@ static int svc_partial_recvfrom(struct svc_rqst *rqstp, | |||
350 | int buflen, unsigned int base) | 394 | int buflen, unsigned int base) |
351 | { | 395 | { |
352 | size_t save_iovlen; | 396 | size_t save_iovlen; |
353 | void *save_iovbase; | 397 | void __user *save_iovbase; |
354 | unsigned int i; | 398 | unsigned int i; |
355 | int ret; | 399 | int ret; |
356 | 400 | ||
@@ -454,13 +498,9 @@ static int svc_udp_get_dest_address4(struct svc_rqst *rqstp, | |||
454 | struct cmsghdr *cmh) | 498 | struct cmsghdr *cmh) |
455 | { | 499 | { |
456 | struct in_pktinfo *pki = CMSG_DATA(cmh); | 500 | struct in_pktinfo *pki = CMSG_DATA(cmh); |
457 | struct sockaddr_in *daddr = svc_daddr_in(rqstp); | ||
458 | |||
459 | if (cmh->cmsg_type != IP_PKTINFO) | 501 | if (cmh->cmsg_type != IP_PKTINFO) |
460 | return 0; | 502 | return 0; |
461 | 503 | rqstp->rq_daddr.addr.s_addr = pki->ipi_spec_dst.s_addr; | |
462 | daddr->sin_family = AF_INET; | ||
463 | daddr->sin_addr.s_addr = pki->ipi_spec_dst.s_addr; | ||
464 | return 1; | 504 | return 1; |
465 | } | 505 | } |
466 | 506 | ||
@@ -471,14 +511,9 @@ static int svc_udp_get_dest_address6(struct svc_rqst *rqstp, | |||
471 | struct cmsghdr *cmh) | 511 | struct cmsghdr *cmh) |
472 | { | 512 | { |
473 | struct in6_pktinfo *pki = CMSG_DATA(cmh); | 513 | struct in6_pktinfo *pki = CMSG_DATA(cmh); |
474 | struct sockaddr_in6 *daddr = svc_daddr_in6(rqstp); | ||
475 | |||
476 | if (cmh->cmsg_type != IPV6_PKTINFO) | 514 | if (cmh->cmsg_type != IPV6_PKTINFO) |
477 | return 0; | 515 | return 0; |
478 | 516 | ipv6_addr_copy(&rqstp->rq_daddr.addr6, &pki->ipi6_addr); | |
479 | daddr->sin6_family = AF_INET6; | ||
480 | daddr->sin6_addr = pki->ipi6_addr; | ||
481 | daddr->sin6_scope_id = pki->ipi6_ifindex; | ||
482 | return 1; | 517 | return 1; |
483 | } | 518 | } |
484 | 519 | ||
@@ -551,9 +586,11 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp) | |||
551 | dprintk("svc: recvfrom returned error %d\n", -err); | 586 | dprintk("svc: recvfrom returned error %d\n", -err); |
552 | set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); | 587 | set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); |
553 | } | 588 | } |
554 | return 0; | 589 | return -EAGAIN; |
555 | } | 590 | } |
556 | len = svc_addr_len(svc_addr(rqstp)); | 591 | len = svc_addr_len(svc_addr(rqstp)); |
592 | if (len == 0) | ||
593 | return -EAFNOSUPPORT; | ||
557 | rqstp->rq_addrlen = len; | 594 | rqstp->rq_addrlen = len; |
558 | if (skb->tstamp.tv64 == 0) { | 595 | if (skb->tstamp.tv64 == 0) { |
559 | skb->tstamp = ktime_get_real(); | 596 | skb->tstamp = ktime_get_real(); |
@@ -569,11 +606,14 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp) | |||
569 | rqstp->rq_prot = IPPROTO_UDP; | 606 | rqstp->rq_prot = IPPROTO_UDP; |
570 | 607 | ||
571 | if (!svc_udp_get_dest_address(rqstp, cmh)) { | 608 | if (!svc_udp_get_dest_address(rqstp, cmh)) { |
572 | net_warn_ratelimited("svc: received unknown control message %d/%d; dropping RPC reply datagram\n", | 609 | if (net_ratelimit()) |
573 | cmh->cmsg_level, cmh->cmsg_type); | 610 | printk(KERN_WARNING |
574 | goto out_free; | 611 | "svc: received unknown control message %d/%d; " |
612 | "dropping RPC reply datagram\n", | ||
613 | cmh->cmsg_level, cmh->cmsg_type); | ||
614 | skb_free_datagram_locked(svsk->sk_sk, skb); | ||
615 | return 0; | ||
575 | } | 616 | } |
576 | rqstp->rq_daddrlen = svc_addr_len(svc_daddr(rqstp)); | ||
577 | 617 | ||
578 | if (skb_is_nonlinear(skb)) { | 618 | if (skb_is_nonlinear(skb)) { |
579 | /* we have to copy */ | 619 | /* we have to copy */ |
@@ -581,7 +621,8 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp) | |||
581 | if (csum_partial_copy_to_xdr(&rqstp->rq_arg, skb)) { | 621 | if (csum_partial_copy_to_xdr(&rqstp->rq_arg, skb)) { |
582 | local_bh_enable(); | 622 | local_bh_enable(); |
583 | /* checksum error */ | 623 | /* checksum error */ |
584 | goto out_free; | 624 | skb_free_datagram_locked(svsk->sk_sk, skb); |
625 | return 0; | ||
585 | } | 626 | } |
586 | local_bh_enable(); | 627 | local_bh_enable(); |
587 | skb_free_datagram_locked(svsk->sk_sk, skb); | 628 | skb_free_datagram_locked(svsk->sk_sk, skb); |
@@ -590,8 +631,10 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp) | |||
590 | rqstp->rq_arg.head[0].iov_base = skb->data + | 631 | rqstp->rq_arg.head[0].iov_base = skb->data + |
591 | sizeof(struct udphdr); | 632 | sizeof(struct udphdr); |
592 | rqstp->rq_arg.head[0].iov_len = len; | 633 | rqstp->rq_arg.head[0].iov_len = len; |
593 | if (skb_checksum_complete(skb)) | 634 | if (skb_checksum_complete(skb)) { |
594 | goto out_free; | 635 | skb_free_datagram_locked(svsk->sk_sk, skb); |
636 | return 0; | ||
637 | } | ||
595 | rqstp->rq_xprt_ctxt = skb; | 638 | rqstp->rq_xprt_ctxt = skb; |
596 | } | 639 | } |
597 | 640 | ||
@@ -605,16 +648,11 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp) | |||
605 | rqstp->rq_respages = rqstp->rq_pages + 1 + | 648 | rqstp->rq_respages = rqstp->rq_pages + 1 + |
606 | DIV_ROUND_UP(rqstp->rq_arg.page_len, PAGE_SIZE); | 649 | DIV_ROUND_UP(rqstp->rq_arg.page_len, PAGE_SIZE); |
607 | } | 650 | } |
608 | rqstp->rq_next_page = rqstp->rq_respages+1; | ||
609 | 651 | ||
610 | if (serv->sv_stats) | 652 | if (serv->sv_stats) |
611 | serv->sv_stats->netudpcnt++; | 653 | serv->sv_stats->netudpcnt++; |
612 | 654 | ||
613 | return len; | 655 | return len; |
614 | out_free: | ||
615 | trace_kfree_skb(skb, svc_udp_recvfrom); | ||
616 | skb_free_datagram_locked(svsk->sk_sk, skb); | ||
617 | return 0; | ||
618 | } | 656 | } |
619 | 657 | ||
620 | static int | 658 | static int |
@@ -689,8 +727,7 @@ static void svc_udp_init(struct svc_sock *svsk, struct svc_serv *serv) | |||
689 | { | 727 | { |
690 | int err, level, optname, one = 1; | 728 | int err, level, optname, one = 1; |
691 | 729 | ||
692 | svc_xprt_init(sock_net(svsk->sk_sock->sk), &svc_udp_class, | 730 | svc_xprt_init(&svc_udp_class, &svsk->sk_xprt, serv); |
693 | &svsk->sk_xprt, serv); | ||
694 | clear_bit(XPT_CACHE_AUTH, &svsk->sk_xprt.xpt_flags); | 731 | clear_bit(XPT_CACHE_AUTH, &svsk->sk_xprt.xpt_flags); |
695 | svsk->sk_sk->sk_data_ready = svc_udp_data_ready; | 732 | svsk->sk_sk->sk_data_ready = svc_udp_data_ready; |
696 | svsk->sk_sk->sk_write_space = svc_write_space; | 733 | svsk->sk_sk->sk_write_space = svc_write_space; |
@@ -821,17 +858,18 @@ static struct svc_xprt *svc_tcp_accept(struct svc_xprt *xprt) | |||
821 | if (err == -ENOMEM) | 858 | if (err == -ENOMEM) |
822 | printk(KERN_WARNING "%s: no more sockets!\n", | 859 | printk(KERN_WARNING "%s: no more sockets!\n", |
823 | serv->sv_name); | 860 | serv->sv_name); |
824 | else if (err != -EAGAIN) | 861 | else if (err != -EAGAIN && net_ratelimit()) |
825 | net_warn_ratelimited("%s: accept failed (err %d)!\n", | 862 | printk(KERN_WARNING "%s: accept failed (err %d)!\n", |
826 | serv->sv_name, -err); | 863 | serv->sv_name, -err); |
827 | return NULL; | 864 | return NULL; |
828 | } | 865 | } |
829 | set_bit(XPT_CONN, &svsk->sk_xprt.xpt_flags); | 866 | set_bit(XPT_CONN, &svsk->sk_xprt.xpt_flags); |
830 | 867 | ||
831 | err = kernel_getpeername(newsock, sin, &slen); | 868 | err = kernel_getpeername(newsock, sin, &slen); |
832 | if (err < 0) { | 869 | if (err < 0) { |
833 | net_warn_ratelimited("%s: peername failed (err %d)!\n", | 870 | if (net_ratelimit()) |
834 | serv->sv_name, -err); | 871 | printk(KERN_WARNING "%s: peername failed (err %d)!\n", |
872 | serv->sv_name, -err); | ||
835 | goto failed; /* aborted connection or whatever */ | 873 | goto failed; /* aborted connection or whatever */ |
836 | } | 874 | } |
837 | 875 | ||
@@ -853,9 +891,8 @@ static struct svc_xprt *svc_tcp_accept(struct svc_xprt *xprt) | |||
853 | */ | 891 | */ |
854 | newsock->sk->sk_sndtimeo = HZ*30; | 892 | newsock->sk->sk_sndtimeo = HZ*30; |
855 | 893 | ||
856 | newsvsk = svc_setup_socket(serv, newsock, | 894 | if (!(newsvsk = svc_setup_socket(serv, newsock, &err, |
857 | (SVC_SOCK_ANONYMOUS | SVC_SOCK_TEMPORARY)); | 895 | (SVC_SOCK_ANONYMOUS | SVC_SOCK_TEMPORARY)))) |
858 | if (IS_ERR(newsvsk)) | ||
859 | goto failed; | 896 | goto failed; |
860 | svc_xprt_set_remote(&newsvsk->sk_xprt, sin, slen); | 897 | svc_xprt_set_remote(&newsvsk->sk_xprt, sin, slen); |
861 | err = kernel_getsockname(newsock, sin, &slen); | 898 | err = kernel_getsockname(newsock, sin, &slen); |
@@ -879,9 +916,9 @@ static unsigned int svc_tcp_restore_pages(struct svc_sock *svsk, struct svc_rqst | |||
879 | { | 916 | { |
880 | unsigned int i, len, npages; | 917 | unsigned int i, len, npages; |
881 | 918 | ||
882 | if (svsk->sk_datalen == 0) | 919 | if (svsk->sk_tcplen <= sizeof(rpc_fraghdr)) |
883 | return 0; | 920 | return 0; |
884 | len = svsk->sk_datalen; | 921 | len = svsk->sk_tcplen - sizeof(rpc_fraghdr); |
885 | npages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT; | 922 | npages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT; |
886 | for (i = 0; i < npages; i++) { | 923 | for (i = 0; i < npages; i++) { |
887 | if (rqstp->rq_pages[i] != NULL) | 924 | if (rqstp->rq_pages[i] != NULL) |
@@ -898,9 +935,9 @@ static void svc_tcp_save_pages(struct svc_sock *svsk, struct svc_rqst *rqstp) | |||
898 | { | 935 | { |
899 | unsigned int i, len, npages; | 936 | unsigned int i, len, npages; |
900 | 937 | ||
901 | if (svsk->sk_datalen == 0) | 938 | if (svsk->sk_tcplen <= sizeof(rpc_fraghdr)) |
902 | return; | 939 | return; |
903 | len = svsk->sk_datalen; | 940 | len = svsk->sk_tcplen - sizeof(rpc_fraghdr); |
904 | npages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT; | 941 | npages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT; |
905 | for (i = 0; i < npages; i++) { | 942 | for (i = 0; i < npages; i++) { |
906 | svsk->sk_pages[i] = rqstp->rq_pages[i]; | 943 | svsk->sk_pages[i] = rqstp->rq_pages[i]; |
@@ -912,9 +949,9 @@ static void svc_tcp_clear_pages(struct svc_sock *svsk) | |||
912 | { | 949 | { |
913 | unsigned int i, len, npages; | 950 | unsigned int i, len, npages; |
914 | 951 | ||
915 | if (svsk->sk_datalen == 0) | 952 | if (svsk->sk_tcplen <= sizeof(rpc_fraghdr)) |
916 | goto out; | 953 | goto out; |
917 | len = svsk->sk_datalen; | 954 | len = svsk->sk_tcplen - sizeof(rpc_fraghdr); |
918 | npages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT; | 955 | npages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT; |
919 | for (i = 0; i < npages; i++) { | 956 | for (i = 0; i < npages; i++) { |
920 | BUG_ON(svsk->sk_pages[i] == NULL); | 957 | BUG_ON(svsk->sk_pages[i] == NULL); |
@@ -923,12 +960,13 @@ static void svc_tcp_clear_pages(struct svc_sock *svsk) | |||
923 | } | 960 | } |
924 | out: | 961 | out: |
925 | svsk->sk_tcplen = 0; | 962 | svsk->sk_tcplen = 0; |
926 | svsk->sk_datalen = 0; | ||
927 | } | 963 | } |
928 | 964 | ||
929 | /* | 965 | /* |
930 | * Receive fragment record header. | 966 | * Receive data. |
931 | * If we haven't gotten the record length yet, get the next four bytes. | 967 | * If we haven't gotten the record length yet, get the next four bytes. |
968 | * Otherwise try to gobble up as much as possible up to the complete | ||
969 | * record length. | ||
932 | */ | 970 | */ |
933 | static int svc_tcp_recv_record(struct svc_sock *svsk, struct svc_rqst *rqstp) | 971 | static int svc_tcp_recv_record(struct svc_sock *svsk, struct svc_rqst *rqstp) |
934 | { | 972 | { |
@@ -954,16 +992,36 @@ static int svc_tcp_recv_record(struct svc_sock *svsk, struct svc_rqst *rqstp) | |||
954 | return -EAGAIN; | 992 | return -EAGAIN; |
955 | } | 993 | } |
956 | 994 | ||
957 | dprintk("svc: TCP record, %d bytes\n", svc_sock_reclen(svsk)); | 995 | svsk->sk_reclen = ntohl(svsk->sk_reclen); |
958 | if (svc_sock_reclen(svsk) + svsk->sk_datalen > | 996 | if (!(svsk->sk_reclen & RPC_LAST_STREAM_FRAGMENT)) { |
959 | serv->sv_max_mesg) { | 997 | /* FIXME: technically, a record can be fragmented, |
960 | net_notice_ratelimited("RPC: fragment too large: %d\n", | 998 | * and non-terminal fragments will not have the top |
961 | svc_sock_reclen(svsk)); | 999 | * bit set in the fragment length header. |
1000 | * But apparently no known nfs clients send fragmented | ||
1001 | * records. */ | ||
1002 | if (net_ratelimit()) | ||
1003 | printk(KERN_NOTICE "RPC: multiple fragments " | ||
1004 | "per record not supported\n"); | ||
1005 | goto err_delete; | ||
1006 | } | ||
1007 | |||
1008 | svsk->sk_reclen &= RPC_FRAGMENT_SIZE_MASK; | ||
1009 | dprintk("svc: TCP record, %d bytes\n", svsk->sk_reclen); | ||
1010 | if (svsk->sk_reclen > serv->sv_max_mesg) { | ||
1011 | if (net_ratelimit()) | ||
1012 | printk(KERN_NOTICE "RPC: " | ||
1013 | "fragment too large: 0x%08lx\n", | ||
1014 | (unsigned long)svsk->sk_reclen); | ||
962 | goto err_delete; | 1015 | goto err_delete; |
963 | } | 1016 | } |
964 | } | 1017 | } |
965 | 1018 | ||
966 | return svc_sock_reclen(svsk); | 1019 | if (svsk->sk_reclen < 8) |
1020 | goto err_delete; /* client is nuts. */ | ||
1021 | |||
1022 | len = svsk->sk_reclen; | ||
1023 | |||
1024 | return len; | ||
967 | error: | 1025 | error: |
968 | dprintk("RPC: TCP recv_record got %d\n", len); | 1026 | dprintk("RPC: TCP recv_record got %d\n", len); |
969 | return len; | 1027 | return len; |
@@ -1007,7 +1065,7 @@ static int receive_cb_reply(struct svc_sock *svsk, struct svc_rqst *rqstp) | |||
1007 | if (dst->iov_len < src->iov_len) | 1065 | if (dst->iov_len < src->iov_len) |
1008 | return -EAGAIN; /* whatever; just giving up. */ | 1066 | return -EAGAIN; /* whatever; just giving up. */ |
1009 | memcpy(dst->iov_base, src->iov_base, src->iov_len); | 1067 | memcpy(dst->iov_base, src->iov_base, src->iov_len); |
1010 | xprt_complete_rqst(req->rq_task, rqstp->rq_arg.len); | 1068 | xprt_complete_rqst(req->rq_task, svsk->sk_reclen); |
1011 | rqstp->rq_arg.len = 0; | 1069 | rqstp->rq_arg.len = 0; |
1012 | return 0; | 1070 | return 0; |
1013 | } | 1071 | } |
@@ -1026,17 +1084,6 @@ static int copy_pages_to_kvecs(struct kvec *vec, struct page **pages, int len) | |||
1026 | return i; | 1084 | return i; |
1027 | } | 1085 | } |
1028 | 1086 | ||
1029 | static void svc_tcp_fragment_received(struct svc_sock *svsk) | ||
1030 | { | ||
1031 | /* If we have more data, signal svc_xprt_enqueue() to try again */ | ||
1032 | if (svc_recv_available(svsk) > sizeof(rpc_fraghdr)) | ||
1033 | set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); | ||
1034 | dprintk("svc: TCP %s record (%d bytes)\n", | ||
1035 | svc_sock_final_rec(svsk) ? "final" : "nonfinal", | ||
1036 | svc_sock_reclen(svsk)); | ||
1037 | svsk->sk_tcplen = 0; | ||
1038 | svsk->sk_reclen = 0; | ||
1039 | } | ||
1040 | 1087 | ||
1041 | /* | 1088 | /* |
1042 | * Receive data from a TCP socket. | 1089 | * Receive data from a TCP socket. |
@@ -1063,39 +1110,29 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp) | |||
1063 | goto error; | 1110 | goto error; |
1064 | 1111 | ||
1065 | base = svc_tcp_restore_pages(svsk, rqstp); | 1112 | base = svc_tcp_restore_pages(svsk, rqstp); |
1066 | want = svc_sock_reclen(svsk) - (svsk->sk_tcplen - sizeof(rpc_fraghdr)); | 1113 | want = svsk->sk_reclen - base; |
1067 | 1114 | ||
1068 | vec = rqstp->rq_vec; | 1115 | vec = rqstp->rq_vec; |
1069 | 1116 | ||
1070 | pnum = copy_pages_to_kvecs(&vec[0], &rqstp->rq_pages[0], | 1117 | pnum = copy_pages_to_kvecs(&vec[0], &rqstp->rq_pages[0], |
1071 | svsk->sk_datalen + want); | 1118 | svsk->sk_reclen); |
1072 | 1119 | ||
1073 | rqstp->rq_respages = &rqstp->rq_pages[pnum]; | 1120 | rqstp->rq_respages = &rqstp->rq_pages[pnum]; |
1074 | rqstp->rq_next_page = rqstp->rq_respages + 1; | ||
1075 | 1121 | ||
1076 | /* Now receive data */ | 1122 | /* Now receive data */ |
1077 | len = svc_partial_recvfrom(rqstp, vec, pnum, want, base); | 1123 | len = svc_partial_recvfrom(rqstp, vec, pnum, want, base); |
1078 | if (len >= 0) { | 1124 | if (len >= 0) |
1079 | svsk->sk_tcplen += len; | 1125 | svsk->sk_tcplen += len; |
1080 | svsk->sk_datalen += len; | 1126 | if (len != want) { |
1081 | } | ||
1082 | if (len != want || !svc_sock_final_rec(svsk)) { | ||
1083 | svc_tcp_save_pages(svsk, rqstp); | ||
1084 | if (len < 0 && len != -EAGAIN) | 1127 | if (len < 0 && len != -EAGAIN) |
1085 | goto err_delete; | 1128 | goto err_other; |
1086 | if (len == want) | 1129 | svc_tcp_save_pages(svsk, rqstp); |
1087 | svc_tcp_fragment_received(svsk); | 1130 | dprintk("svc: incomplete TCP record (%d of %d)\n", |
1088 | else | 1131 | svsk->sk_tcplen, svsk->sk_reclen); |
1089 | dprintk("svc: incomplete TCP record (%d of %d)\n", | ||
1090 | (int)(svsk->sk_tcplen - sizeof(rpc_fraghdr)), | ||
1091 | svc_sock_reclen(svsk)); | ||
1092 | goto err_noclose; | 1132 | goto err_noclose; |
1093 | } | 1133 | } |
1094 | 1134 | ||
1095 | if (svc_sock_reclen(svsk) < 8) | 1135 | rqstp->rq_arg.len = svsk->sk_reclen; |
1096 | goto err_delete; /* client is nuts. */ | ||
1097 | |||
1098 | rqstp->rq_arg.len = svsk->sk_datalen; | ||
1099 | rqstp->rq_arg.page_base = 0; | 1136 | rqstp->rq_arg.page_base = 0; |
1100 | if (rqstp->rq_arg.len <= rqstp->rq_arg.head[0].iov_len) { | 1137 | if (rqstp->rq_arg.len <= rqstp->rq_arg.head[0].iov_len) { |
1101 | rqstp->rq_arg.head[0].iov_len = rqstp->rq_arg.len; | 1138 | rqstp->rq_arg.head[0].iov_len = rqstp->rq_arg.len; |
@@ -1112,8 +1149,11 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp) | |||
1112 | len = receive_cb_reply(svsk, rqstp); | 1149 | len = receive_cb_reply(svsk, rqstp); |
1113 | 1150 | ||
1114 | /* Reset TCP read info */ | 1151 | /* Reset TCP read info */ |
1115 | svsk->sk_datalen = 0; | 1152 | svsk->sk_reclen = 0; |
1116 | svc_tcp_fragment_received(svsk); | 1153 | svsk->sk_tcplen = 0; |
1154 | /* If we have more data, signal svc_xprt_enqueue() to try again */ | ||
1155 | if (svc_recv_available(svsk) > sizeof(rpc_fraghdr)) | ||
1156 | set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); | ||
1117 | 1157 | ||
1118 | if (len < 0) | 1158 | if (len < 0) |
1119 | goto error; | 1159 | goto error; |
@@ -1122,19 +1162,20 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp) | |||
1122 | if (serv->sv_stats) | 1162 | if (serv->sv_stats) |
1123 | serv->sv_stats->nettcpcnt++; | 1163 | serv->sv_stats->nettcpcnt++; |
1124 | 1164 | ||
1165 | dprintk("svc: TCP complete record (%d bytes)\n", rqstp->rq_arg.len); | ||
1125 | return rqstp->rq_arg.len; | 1166 | return rqstp->rq_arg.len; |
1126 | 1167 | ||
1127 | error: | 1168 | error: |
1128 | if (len != -EAGAIN) | 1169 | if (len != -EAGAIN) |
1129 | goto err_delete; | 1170 | goto err_other; |
1130 | dprintk("RPC: TCP recvfrom got EAGAIN\n"); | 1171 | dprintk("RPC: TCP recvfrom got EAGAIN\n"); |
1131 | return 0; | 1172 | return -EAGAIN; |
1132 | err_delete: | 1173 | err_other: |
1133 | printk(KERN_NOTICE "%s: recvfrom returned errno %d\n", | 1174 | printk(KERN_NOTICE "%s: recvfrom returned errno %d\n", |
1134 | svsk->sk_xprt.xpt_server->sv_name, -len); | 1175 | svsk->sk_xprt.xpt_server->sv_name, -len); |
1135 | set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); | 1176 | set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags); |
1136 | err_noclose: | 1177 | err_noclose: |
1137 | return 0; /* record not complete */ | 1178 | return -EAGAIN; /* record not complete */ |
1138 | } | 1179 | } |
1139 | 1180 | ||
1140 | /* | 1181 | /* |
@@ -1290,8 +1331,7 @@ static void svc_tcp_init(struct svc_sock *svsk, struct svc_serv *serv) | |||
1290 | { | 1331 | { |
1291 | struct sock *sk = svsk->sk_sk; | 1332 | struct sock *sk = svsk->sk_sk; |
1292 | 1333 | ||
1293 | svc_xprt_init(sock_net(svsk->sk_sock->sk), &svc_tcp_class, | 1334 | svc_xprt_init(&svc_tcp_class, &svsk->sk_xprt, serv); |
1294 | &svsk->sk_xprt, serv); | ||
1295 | set_bit(XPT_CACHE_AUTH, &svsk->sk_xprt.xpt_flags); | 1335 | set_bit(XPT_CACHE_AUTH, &svsk->sk_xprt.xpt_flags); |
1296 | if (sk->sk_state == TCP_LISTEN) { | 1336 | if (sk->sk_state == TCP_LISTEN) { |
1297 | dprintk("setting up TCP socket for listening\n"); | 1337 | dprintk("setting up TCP socket for listening\n"); |
@@ -1306,7 +1346,6 @@ static void svc_tcp_init(struct svc_sock *svsk, struct svc_serv *serv) | |||
1306 | 1346 | ||
1307 | svsk->sk_reclen = 0; | 1347 | svsk->sk_reclen = 0; |
1308 | svsk->sk_tcplen = 0; | 1348 | svsk->sk_tcplen = 0; |
1309 | svsk->sk_datalen = 0; | ||
1310 | memset(&svsk->sk_pages[0], 0, sizeof(svsk->sk_pages)); | 1349 | memset(&svsk->sk_pages[0], 0, sizeof(svsk->sk_pages)); |
1311 | 1350 | ||
1312 | tcp_sk(sk)->nonagle |= TCP_NAGLE_OFF; | 1351 | tcp_sk(sk)->nonagle |= TCP_NAGLE_OFF; |
@@ -1328,6 +1367,8 @@ void svc_sock_update_bufs(struct svc_serv *serv) | |||
1328 | spin_lock_bh(&serv->sv_lock); | 1367 | spin_lock_bh(&serv->sv_lock); |
1329 | list_for_each_entry(svsk, &serv->sv_permsocks, sk_xprt.xpt_list) | 1368 | list_for_each_entry(svsk, &serv->sv_permsocks, sk_xprt.xpt_list) |
1330 | set_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags); | 1369 | set_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags); |
1370 | list_for_each_entry(svsk, &serv->sv_tempsocks, sk_xprt.xpt_list) | ||
1371 | set_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags); | ||
1331 | spin_unlock_bh(&serv->sv_lock); | 1372 | spin_unlock_bh(&serv->sv_lock); |
1332 | } | 1373 | } |
1333 | EXPORT_SYMBOL_GPL(svc_sock_update_bufs); | 1374 | EXPORT_SYMBOL_GPL(svc_sock_update_bufs); |
@@ -1338,29 +1379,28 @@ EXPORT_SYMBOL_GPL(svc_sock_update_bufs); | |||
1338 | */ | 1379 | */ |
1339 | static struct svc_sock *svc_setup_socket(struct svc_serv *serv, | 1380 | static struct svc_sock *svc_setup_socket(struct svc_serv *serv, |
1340 | struct socket *sock, | 1381 | struct socket *sock, |
1341 | int flags) | 1382 | int *errp, int flags) |
1342 | { | 1383 | { |
1343 | struct svc_sock *svsk; | 1384 | struct svc_sock *svsk; |
1344 | struct sock *inet; | 1385 | struct sock *inet; |
1345 | int pmap_register = !(flags & SVC_SOCK_ANONYMOUS); | 1386 | int pmap_register = !(flags & SVC_SOCK_ANONYMOUS); |
1346 | int err = 0; | ||
1347 | 1387 | ||
1348 | dprintk("svc: svc_setup_socket %p\n", sock); | 1388 | dprintk("svc: svc_setup_socket %p\n", sock); |
1349 | svsk = kzalloc(sizeof(*svsk), GFP_KERNEL); | 1389 | if (!(svsk = kzalloc(sizeof(*svsk), GFP_KERNEL))) { |
1350 | if (!svsk) | 1390 | *errp = -ENOMEM; |
1351 | return ERR_PTR(-ENOMEM); | 1391 | return NULL; |
1392 | } | ||
1352 | 1393 | ||
1353 | inet = sock->sk; | 1394 | inet = sock->sk; |
1354 | 1395 | ||
1355 | /* Register socket with portmapper */ | 1396 | /* Register socket with portmapper */ |
1356 | if (pmap_register) | 1397 | if (*errp >= 0 && pmap_register) |
1357 | err = svc_register(serv, sock_net(sock->sk), inet->sk_family, | 1398 | *errp = svc_register(serv, inet->sk_family, inet->sk_protocol, |
1358 | inet->sk_protocol, | ||
1359 | ntohs(inet_sk(inet)->inet_sport)); | 1399 | ntohs(inet_sk(inet)->inet_sport)); |
1360 | 1400 | ||
1361 | if (err < 0) { | 1401 | if (*errp < 0) { |
1362 | kfree(svsk); | 1402 | kfree(svsk); |
1363 | return ERR_PTR(err); | 1403 | return NULL; |
1364 | } | 1404 | } |
1365 | 1405 | ||
1366 | inet->sk_user_data = svsk; | 1406 | inet->sk_user_data = svsk; |
@@ -1405,38 +1445,42 @@ int svc_addsock(struct svc_serv *serv, const int fd, char *name_return, | |||
1405 | int err = 0; | 1445 | int err = 0; |
1406 | struct socket *so = sockfd_lookup(fd, &err); | 1446 | struct socket *so = sockfd_lookup(fd, &err); |
1407 | struct svc_sock *svsk = NULL; | 1447 | struct svc_sock *svsk = NULL; |
1408 | struct sockaddr_storage addr; | ||
1409 | struct sockaddr *sin = (struct sockaddr *)&addr; | ||
1410 | int salen; | ||
1411 | 1448 | ||
1412 | if (!so) | 1449 | if (!so) |
1413 | return err; | 1450 | return err; |
1414 | err = -EAFNOSUPPORT; | ||
1415 | if ((so->sk->sk_family != PF_INET) && (so->sk->sk_family != PF_INET6)) | 1451 | if ((so->sk->sk_family != PF_INET) && (so->sk->sk_family != PF_INET6)) |
1416 | goto out; | 1452 | err = -EAFNOSUPPORT; |
1417 | err = -EPROTONOSUPPORT; | 1453 | else if (so->sk->sk_protocol != IPPROTO_TCP && |
1418 | if (so->sk->sk_protocol != IPPROTO_TCP && | ||
1419 | so->sk->sk_protocol != IPPROTO_UDP) | 1454 | so->sk->sk_protocol != IPPROTO_UDP) |
1420 | goto out; | 1455 | err = -EPROTONOSUPPORT; |
1421 | err = -EISCONN; | 1456 | else if (so->state > SS_UNCONNECTED) |
1422 | if (so->state > SS_UNCONNECTED) | 1457 | err = -EISCONN; |
1423 | goto out; | 1458 | else { |
1424 | err = -ENOENT; | 1459 | if (!try_module_get(THIS_MODULE)) |
1425 | if (!try_module_get(THIS_MODULE)) | 1460 | err = -ENOENT; |
1426 | goto out; | 1461 | else |
1427 | svsk = svc_setup_socket(serv, so, SVC_SOCK_DEFAULTS); | 1462 | svsk = svc_setup_socket(serv, so, &err, |
1428 | if (IS_ERR(svsk)) { | 1463 | SVC_SOCK_DEFAULTS); |
1429 | module_put(THIS_MODULE); | 1464 | if (svsk) { |
1430 | err = PTR_ERR(svsk); | 1465 | struct sockaddr_storage addr; |
1431 | goto out; | 1466 | struct sockaddr *sin = (struct sockaddr *)&addr; |
1467 | int salen; | ||
1468 | if (kernel_getsockname(svsk->sk_sock, sin, &salen) == 0) | ||
1469 | svc_xprt_set_local(&svsk->sk_xprt, sin, salen); | ||
1470 | clear_bit(XPT_TEMP, &svsk->sk_xprt.xpt_flags); | ||
1471 | spin_lock_bh(&serv->sv_lock); | ||
1472 | list_add(&svsk->sk_xprt.xpt_list, &serv->sv_permsocks); | ||
1473 | spin_unlock_bh(&serv->sv_lock); | ||
1474 | svc_xprt_received(&svsk->sk_xprt); | ||
1475 | err = 0; | ||
1476 | } else | ||
1477 | module_put(THIS_MODULE); | ||
1478 | } | ||
1479 | if (err) { | ||
1480 | sockfd_put(so); | ||
1481 | return err; | ||
1432 | } | 1482 | } |
1433 | if (kernel_getsockname(svsk->sk_sock, sin, &salen) == 0) | ||
1434 | svc_xprt_set_local(&svsk->sk_xprt, sin, salen); | ||
1435 | svc_add_new_perm_xprt(serv, &svsk->sk_xprt); | ||
1436 | return svc_one_sock_name(svsk, name_return, len); | 1483 | return svc_one_sock_name(svsk, name_return, len); |
1437 | out: | ||
1438 | sockfd_put(so); | ||
1439 | return err; | ||
1440 | } | 1484 | } |
1441 | EXPORT_SYMBOL_GPL(svc_addsock); | 1485 | EXPORT_SYMBOL_GPL(svc_addsock); |
1442 | 1486 | ||
@@ -1499,7 +1543,7 @@ static struct svc_xprt *svc_create_socket(struct svc_serv *serv, | |||
1499 | (char *)&val, sizeof(val)); | 1543 | (char *)&val, sizeof(val)); |
1500 | 1544 | ||
1501 | if (type == SOCK_STREAM) | 1545 | if (type == SOCK_STREAM) |
1502 | sock->sk->sk_reuse = SK_CAN_REUSE; /* allow address reuse */ | 1546 | sock->sk->sk_reuse = 1; /* allow address reuse */ |
1503 | error = kernel_bind(sock, sin, len); | 1547 | error = kernel_bind(sock, sin, len); |
1504 | if (error < 0) | 1548 | if (error < 0) |
1505 | goto bummer; | 1549 | goto bummer; |
@@ -1514,13 +1558,11 @@ static struct svc_xprt *svc_create_socket(struct svc_serv *serv, | |||
1514 | goto bummer; | 1558 | goto bummer; |
1515 | } | 1559 | } |
1516 | 1560 | ||
1517 | svsk = svc_setup_socket(serv, sock, flags); | 1561 | if ((svsk = svc_setup_socket(serv, sock, &error, flags)) != NULL) { |
1518 | if (IS_ERR(svsk)) { | 1562 | svc_xprt_set_local(&svsk->sk_xprt, newsin, newlen); |
1519 | error = PTR_ERR(svsk); | 1563 | return (struct svc_xprt *)svsk; |
1520 | goto bummer; | ||
1521 | } | 1564 | } |
1522 | svc_xprt_set_local(&svsk->sk_xprt, newsin, newlen); | 1565 | |
1523 | return (struct svc_xprt *)svsk; | ||
1524 | bummer: | 1566 | bummer: |
1525 | dprintk("svc: svc_create_socket error = %d\n", -error); | 1567 | dprintk("svc: svc_create_socket error = %d\n", -error); |
1526 | sock_release(sock); | 1568 | sock_release(sock); |
@@ -1605,7 +1647,7 @@ static struct svc_xprt *svc_bc_create_socket(struct svc_serv *serv, | |||
1605 | return ERR_PTR(-ENOMEM); | 1647 | return ERR_PTR(-ENOMEM); |
1606 | 1648 | ||
1607 | xprt = &svsk->sk_xprt; | 1649 | xprt = &svsk->sk_xprt; |
1608 | svc_xprt_init(net, &svc_tcp_bc_class, xprt, serv); | 1650 | svc_xprt_init(&svc_tcp_bc_class, xprt, serv); |
1609 | 1651 | ||
1610 | serv->sv_bc_xprt = xprt; | 1652 | serv->sv_bc_xprt = xprt; |
1611 | 1653 | ||
diff --git a/net/sunrpc/sysctl.c b/net/sunrpc/sysctl.c index af7d339add9..e65dcc61333 100644 --- a/net/sunrpc/sysctl.c +++ b/net/sunrpc/sysctl.c | |||
@@ -20,8 +20,6 @@ | |||
20 | #include <linux/sunrpc/stats.h> | 20 | #include <linux/sunrpc/stats.h> |
21 | #include <linux/sunrpc/svc_xprt.h> | 21 | #include <linux/sunrpc/svc_xprt.h> |
22 | 22 | ||
23 | #include "netns.h" | ||
24 | |||
25 | /* | 23 | /* |
26 | * Declare the debug flags here | 24 | * Declare the debug flags here |
27 | */ | 25 | */ |
@@ -112,7 +110,7 @@ proc_dodebug(ctl_table *table, int write, | |||
112 | *(unsigned int *) table->data = value; | 110 | *(unsigned int *) table->data = value; |
113 | /* Display the RPC tasks on writing to rpc_debug */ | 111 | /* Display the RPC tasks on writing to rpc_debug */ |
114 | if (strcmp(table->procname, "rpc_debug") == 0) | 112 | if (strcmp(table->procname, "rpc_debug") == 0) |
115 | rpc_show_tasks(&init_net); | 113 | rpc_show_tasks(); |
116 | } else { | 114 | } else { |
117 | if (!access_ok(VERIFY_WRITE, buffer, left)) | 115 | if (!access_ok(VERIFY_WRITE, buffer, left)) |
118 | return -EFAULT; | 116 | return -EFAULT; |
diff --git a/net/sunrpc/timer.c b/net/sunrpc/timer.c index 08881d0c967..dd824341c34 100644 --- a/net/sunrpc/timer.c +++ b/net/sunrpc/timer.c | |||
@@ -34,7 +34,7 @@ | |||
34 | void rpc_init_rtt(struct rpc_rtt *rt, unsigned long timeo) | 34 | void rpc_init_rtt(struct rpc_rtt *rt, unsigned long timeo) |
35 | { | 35 | { |
36 | unsigned long init = 0; | 36 | unsigned long init = 0; |
37 | unsigned int i; | 37 | unsigned i; |
38 | 38 | ||
39 | rt->timeo = timeo; | 39 | rt->timeo = timeo; |
40 | 40 | ||
@@ -57,7 +57,7 @@ EXPORT_SYMBOL_GPL(rpc_init_rtt); | |||
57 | * NB: When computing the smoothed RTT and standard deviation, | 57 | * NB: When computing the smoothed RTT and standard deviation, |
58 | * be careful not to produce negative intermediate results. | 58 | * be careful not to produce negative intermediate results. |
59 | */ | 59 | */ |
60 | void rpc_update_rtt(struct rpc_rtt *rt, unsigned int timer, long m) | 60 | void rpc_update_rtt(struct rpc_rtt *rt, unsigned timer, long m) |
61 | { | 61 | { |
62 | long *srtt, *sdrtt; | 62 | long *srtt, *sdrtt; |
63 | 63 | ||
@@ -106,7 +106,7 @@ EXPORT_SYMBOL_GPL(rpc_update_rtt); | |||
106 | * read, write, commit - A+4D | 106 | * read, write, commit - A+4D |
107 | * other - timeo | 107 | * other - timeo |
108 | */ | 108 | */ |
109 | unsigned long rpc_calc_rto(struct rpc_rtt *rt, unsigned int timer) | 109 | unsigned long rpc_calc_rto(struct rpc_rtt *rt, unsigned timer) |
110 | { | 110 | { |
111 | unsigned long res; | 111 | unsigned long res; |
112 | 112 | ||
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index 56055632f15..593f4c60530 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c | |||
@@ -122,13 +122,41 @@ xdr_terminate_string(struct xdr_buf *buf, const u32 len) | |||
122 | { | 122 | { |
123 | char *kaddr; | 123 | char *kaddr; |
124 | 124 | ||
125 | kaddr = kmap_atomic(buf->pages[0]); | 125 | kaddr = kmap_atomic(buf->pages[0], KM_USER0); |
126 | kaddr[buf->page_base + len] = '\0'; | 126 | kaddr[buf->page_base + len] = '\0'; |
127 | kunmap_atomic(kaddr); | 127 | kunmap_atomic(kaddr, KM_USER0); |
128 | } | 128 | } |
129 | EXPORT_SYMBOL_GPL(xdr_terminate_string); | 129 | EXPORT_SYMBOL_GPL(xdr_terminate_string); |
130 | 130 | ||
131 | void | 131 | void |
132 | xdr_encode_pages(struct xdr_buf *xdr, struct page **pages, unsigned int base, | ||
133 | unsigned int len) | ||
134 | { | ||
135 | struct kvec *tail = xdr->tail; | ||
136 | u32 *p; | ||
137 | |||
138 | xdr->pages = pages; | ||
139 | xdr->page_base = base; | ||
140 | xdr->page_len = len; | ||
141 | |||
142 | p = (u32 *)xdr->head[0].iov_base + XDR_QUADLEN(xdr->head[0].iov_len); | ||
143 | tail->iov_base = p; | ||
144 | tail->iov_len = 0; | ||
145 | |||
146 | if (len & 3) { | ||
147 | unsigned int pad = 4 - (len & 3); | ||
148 | |||
149 | *p = 0; | ||
150 | tail->iov_base = (char *)p + (len & 3); | ||
151 | tail->iov_len = pad; | ||
152 | len += pad; | ||
153 | } | ||
154 | xdr->buflen += len; | ||
155 | xdr->len += len; | ||
156 | } | ||
157 | EXPORT_SYMBOL_GPL(xdr_encode_pages); | ||
158 | |||
159 | void | ||
132 | xdr_inline_pages(struct xdr_buf *xdr, unsigned int offset, | 160 | xdr_inline_pages(struct xdr_buf *xdr, unsigned int offset, |
133 | struct page **pages, unsigned int base, unsigned int len) | 161 | struct page **pages, unsigned int base, unsigned int len) |
134 | { | 162 | { |
@@ -152,9 +180,7 @@ EXPORT_SYMBOL_GPL(xdr_inline_pages); | |||
152 | 180 | ||
153 | /* | 181 | /* |
154 | * Helper routines for doing 'memmove' like operations on a struct xdr_buf | 182 | * Helper routines for doing 'memmove' like operations on a struct xdr_buf |
155 | */ | 183 | * |
156 | |||
157 | /** | ||
158 | * _shift_data_right_pages | 184 | * _shift_data_right_pages |
159 | * @pages: vector of pages containing both the source and dest memory area. | 185 | * @pages: vector of pages containing both the source and dest memory area. |
160 | * @pgto_base: page vector address of destination | 186 | * @pgto_base: page vector address of destination |
@@ -206,17 +232,17 @@ _shift_data_right_pages(struct page **pages, size_t pgto_base, | |||
206 | pgto_base -= copy; | 232 | pgto_base -= copy; |
207 | pgfrom_base -= copy; | 233 | pgfrom_base -= copy; |
208 | 234 | ||
209 | vto = kmap_atomic(*pgto); | 235 | vto = kmap_atomic(*pgto, KM_USER0); |
210 | vfrom = kmap_atomic(*pgfrom); | 236 | vfrom = kmap_atomic(*pgfrom, KM_USER1); |
211 | memmove(vto + pgto_base, vfrom + pgfrom_base, copy); | 237 | memmove(vto + pgto_base, vfrom + pgfrom_base, copy); |
212 | flush_dcache_page(*pgto); | 238 | flush_dcache_page(*pgto); |
213 | kunmap_atomic(vfrom); | 239 | kunmap_atomic(vfrom, KM_USER1); |
214 | kunmap_atomic(vto); | 240 | kunmap_atomic(vto, KM_USER0); |
215 | 241 | ||
216 | } while ((len -= copy) != 0); | 242 | } while ((len -= copy) != 0); |
217 | } | 243 | } |
218 | 244 | ||
219 | /** | 245 | /* |
220 | * _copy_to_pages | 246 | * _copy_to_pages |
221 | * @pages: array of pages | 247 | * @pages: array of pages |
222 | * @pgbase: page vector address of destination | 248 | * @pgbase: page vector address of destination |
@@ -241,9 +267,9 @@ _copy_to_pages(struct page **pages, size_t pgbase, const char *p, size_t len) | |||
241 | if (copy > len) | 267 | if (copy > len) |
242 | copy = len; | 268 | copy = len; |
243 | 269 | ||
244 | vto = kmap_atomic(*pgto); | 270 | vto = kmap_atomic(*pgto, KM_USER0); |
245 | memcpy(vto + pgbase, p, copy); | 271 | memcpy(vto + pgbase, p, copy); |
246 | kunmap_atomic(vto); | 272 | kunmap_atomic(vto, KM_USER0); |
247 | 273 | ||
248 | len -= copy; | 274 | len -= copy; |
249 | if (len == 0) | 275 | if (len == 0) |
@@ -260,7 +286,7 @@ _copy_to_pages(struct page **pages, size_t pgbase, const char *p, size_t len) | |||
260 | flush_dcache_page(*pgto); | 286 | flush_dcache_page(*pgto); |
261 | } | 287 | } |
262 | 288 | ||
263 | /** | 289 | /* |
264 | * _copy_from_pages | 290 | * _copy_from_pages |
265 | * @p: pointer to destination | 291 | * @p: pointer to destination |
266 | * @pages: array of pages | 292 | * @pages: array of pages |
@@ -285,9 +311,9 @@ _copy_from_pages(char *p, struct page **pages, size_t pgbase, size_t len) | |||
285 | if (copy > len) | 311 | if (copy > len) |
286 | copy = len; | 312 | copy = len; |
287 | 313 | ||
288 | vfrom = kmap_atomic(*pgfrom); | 314 | vfrom = kmap_atomic(*pgfrom, KM_USER0); |
289 | memcpy(p, vfrom + pgbase, copy); | 315 | memcpy(p, vfrom + pgbase, copy); |
290 | kunmap_atomic(vfrom); | 316 | kunmap_atomic(vfrom, KM_USER0); |
291 | 317 | ||
292 | pgbase += copy; | 318 | pgbase += copy; |
293 | if (pgbase == PAGE_CACHE_SIZE) { | 319 | if (pgbase == PAGE_CACHE_SIZE) { |
@@ -300,7 +326,7 @@ _copy_from_pages(char *p, struct page **pages, size_t pgbase, size_t len) | |||
300 | } | 326 | } |
301 | EXPORT_SYMBOL_GPL(_copy_from_pages); | 327 | EXPORT_SYMBOL_GPL(_copy_from_pages); |
302 | 328 | ||
303 | /** | 329 | /* |
304 | * xdr_shrink_bufhead | 330 | * xdr_shrink_bufhead |
305 | * @buf: xdr_buf | 331 | * @buf: xdr_buf |
306 | * @len: bytes to remove from buf->head[0] | 332 | * @len: bytes to remove from buf->head[0] |
@@ -318,10 +344,7 @@ xdr_shrink_bufhead(struct xdr_buf *buf, size_t len) | |||
318 | 344 | ||
319 | tail = buf->tail; | 345 | tail = buf->tail; |
320 | head = buf->head; | 346 | head = buf->head; |
321 | 347 | BUG_ON (len > head->iov_len); | |
322 | WARN_ON_ONCE(len > head->iov_len); | ||
323 | if (len > head->iov_len) | ||
324 | len = head->iov_len; | ||
325 | 348 | ||
326 | /* Shift the tail first */ | 349 | /* Shift the tail first */ |
327 | if (tail->iov_len != 0) { | 350 | if (tail->iov_len != 0) { |
@@ -376,7 +399,7 @@ xdr_shrink_bufhead(struct xdr_buf *buf, size_t len) | |||
376 | buf->len = buf->buflen; | 399 | buf->len = buf->buflen; |
377 | } | 400 | } |
378 | 401 | ||
379 | /** | 402 | /* |
380 | * xdr_shrink_pagelen | 403 | * xdr_shrink_pagelen |
381 | * @buf: xdr_buf | 404 | * @buf: xdr_buf |
382 | * @len: bytes to remove from buf->pages | 405 | * @len: bytes to remove from buf->pages |
@@ -432,16 +455,6 @@ xdr_shift_buf(struct xdr_buf *buf, size_t len) | |||
432 | EXPORT_SYMBOL_GPL(xdr_shift_buf); | 455 | EXPORT_SYMBOL_GPL(xdr_shift_buf); |
433 | 456 | ||
434 | /** | 457 | /** |
435 | * xdr_stream_pos - Return the current offset from the start of the xdr_stream | ||
436 | * @xdr: pointer to struct xdr_stream | ||
437 | */ | ||
438 | unsigned int xdr_stream_pos(const struct xdr_stream *xdr) | ||
439 | { | ||
440 | return (unsigned int)(XDR_QUADLEN(xdr->buf->len) - xdr->nwords) << 2; | ||
441 | } | ||
442 | EXPORT_SYMBOL_GPL(xdr_stream_pos); | ||
443 | |||
444 | /** | ||
445 | * xdr_init_encode - Initialize a struct xdr_stream for sending data. | 458 | * xdr_init_encode - Initialize a struct xdr_stream for sending data. |
446 | * @xdr: pointer to xdr_stream struct | 459 | * @xdr: pointer to xdr_stream struct |
447 | * @buf: pointer to XDR buffer in which to encode data | 460 | * @buf: pointer to XDR buffer in which to encode data |
@@ -541,11 +554,13 @@ void xdr_write_pages(struct xdr_stream *xdr, struct page **pages, unsigned int b | |||
541 | EXPORT_SYMBOL_GPL(xdr_write_pages); | 554 | EXPORT_SYMBOL_GPL(xdr_write_pages); |
542 | 555 | ||
543 | static void xdr_set_iov(struct xdr_stream *xdr, struct kvec *iov, | 556 | static void xdr_set_iov(struct xdr_stream *xdr, struct kvec *iov, |
544 | unsigned int len) | 557 | __be32 *p, unsigned int len) |
545 | { | 558 | { |
546 | if (len > iov->iov_len) | 559 | if (len > iov->iov_len) |
547 | len = iov->iov_len; | 560 | len = iov->iov_len; |
548 | xdr->p = (__be32*)iov->iov_base; | 561 | if (p == NULL) |
562 | p = (__be32*)iov->iov_base; | ||
563 | xdr->p = p; | ||
549 | xdr->end = (__be32*)(iov->iov_base + len); | 564 | xdr->end = (__be32*)(iov->iov_base + len); |
550 | xdr->iov = iov; | 565 | xdr->iov = iov; |
551 | xdr->page_ptr = NULL; | 566 | xdr->page_ptr = NULL; |
@@ -592,7 +607,7 @@ static void xdr_set_next_page(struct xdr_stream *xdr) | |||
592 | newbase -= xdr->buf->page_base; | 607 | newbase -= xdr->buf->page_base; |
593 | 608 | ||
594 | if (xdr_set_page_base(xdr, newbase, PAGE_SIZE) < 0) | 609 | if (xdr_set_page_base(xdr, newbase, PAGE_SIZE) < 0) |
595 | xdr_set_iov(xdr, xdr->buf->tail, xdr->buf->len); | 610 | xdr_set_iov(xdr, xdr->buf->tail, NULL, xdr->buf->len); |
596 | } | 611 | } |
597 | 612 | ||
598 | static bool xdr_set_next_buffer(struct xdr_stream *xdr) | 613 | static bool xdr_set_next_buffer(struct xdr_stream *xdr) |
@@ -601,7 +616,7 @@ static bool xdr_set_next_buffer(struct xdr_stream *xdr) | |||
601 | xdr_set_next_page(xdr); | 616 | xdr_set_next_page(xdr); |
602 | else if (xdr->iov == xdr->buf->head) { | 617 | else if (xdr->iov == xdr->buf->head) { |
603 | if (xdr_set_page_base(xdr, 0, PAGE_SIZE) < 0) | 618 | if (xdr_set_page_base(xdr, 0, PAGE_SIZE) < 0) |
604 | xdr_set_iov(xdr, xdr->buf->tail, xdr->buf->len); | 619 | xdr_set_iov(xdr, xdr->buf->tail, NULL, xdr->buf->len); |
605 | } | 620 | } |
606 | return xdr->p != xdr->end; | 621 | return xdr->p != xdr->end; |
607 | } | 622 | } |
@@ -617,15 +632,10 @@ void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p) | |||
617 | xdr->buf = buf; | 632 | xdr->buf = buf; |
618 | xdr->scratch.iov_base = NULL; | 633 | xdr->scratch.iov_base = NULL; |
619 | xdr->scratch.iov_len = 0; | 634 | xdr->scratch.iov_len = 0; |
620 | xdr->nwords = XDR_QUADLEN(buf->len); | ||
621 | if (buf->head[0].iov_len != 0) | 635 | if (buf->head[0].iov_len != 0) |
622 | xdr_set_iov(xdr, buf->head, buf->len); | 636 | xdr_set_iov(xdr, buf->head, p, buf->len); |
623 | else if (buf->page_len != 0) | 637 | else if (buf->page_len != 0) |
624 | xdr_set_page_base(xdr, 0, buf->len); | 638 | xdr_set_page_base(xdr, 0, buf->len); |
625 | if (p != NULL && p > xdr->p && xdr->end >= p) { | ||
626 | xdr->nwords -= p - xdr->p; | ||
627 | xdr->p = p; | ||
628 | } | ||
629 | } | 639 | } |
630 | EXPORT_SYMBOL_GPL(xdr_init_decode); | 640 | EXPORT_SYMBOL_GPL(xdr_init_decode); |
631 | 641 | ||
@@ -650,14 +660,12 @@ EXPORT_SYMBOL_GPL(xdr_init_decode_pages); | |||
650 | 660 | ||
651 | static __be32 * __xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes) | 661 | static __be32 * __xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes) |
652 | { | 662 | { |
653 | unsigned int nwords = XDR_QUADLEN(nbytes); | ||
654 | __be32 *p = xdr->p; | 663 | __be32 *p = xdr->p; |
655 | __be32 *q = p + nwords; | 664 | __be32 *q = p + XDR_QUADLEN(nbytes); |
656 | 665 | ||
657 | if (unlikely(nwords > xdr->nwords || q > xdr->end || q < p)) | 666 | if (unlikely(q > xdr->end || q < p)) |
658 | return NULL; | 667 | return NULL; |
659 | xdr->p = q; | 668 | xdr->p = q; |
660 | xdr->nwords -= nwords; | ||
661 | return p; | 669 | return p; |
662 | } | 670 | } |
663 | 671 | ||
@@ -724,36 +732,6 @@ __be32 * xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes) | |||
724 | } | 732 | } |
725 | EXPORT_SYMBOL_GPL(xdr_inline_decode); | 733 | EXPORT_SYMBOL_GPL(xdr_inline_decode); |
726 | 734 | ||
727 | static unsigned int xdr_align_pages(struct xdr_stream *xdr, unsigned int len) | ||
728 | { | ||
729 | struct xdr_buf *buf = xdr->buf; | ||
730 | struct kvec *iov; | ||
731 | unsigned int nwords = XDR_QUADLEN(len); | ||
732 | unsigned int cur = xdr_stream_pos(xdr); | ||
733 | |||
734 | if (xdr->nwords == 0) | ||
735 | return 0; | ||
736 | /* Realign pages to current pointer position */ | ||
737 | iov = buf->head; | ||
738 | if (iov->iov_len > cur) { | ||
739 | xdr_shrink_bufhead(buf, iov->iov_len - cur); | ||
740 | xdr->nwords = XDR_QUADLEN(buf->len - cur); | ||
741 | } | ||
742 | |||
743 | if (nwords > xdr->nwords) { | ||
744 | nwords = xdr->nwords; | ||
745 | len = nwords << 2; | ||
746 | } | ||
747 | if (buf->page_len <= len) | ||
748 | len = buf->page_len; | ||
749 | else if (nwords < xdr->nwords) { | ||
750 | /* Truncate page data and move it into the tail */ | ||
751 | xdr_shrink_pagelen(buf, buf->page_len - len); | ||
752 | xdr->nwords = XDR_QUADLEN(buf->len - cur); | ||
753 | } | ||
754 | return len; | ||
755 | } | ||
756 | |||
757 | /** | 735 | /** |
758 | * xdr_read_pages - Ensure page-based XDR data to decode is aligned at current pointer position | 736 | * xdr_read_pages - Ensure page-based XDR data to decode is aligned at current pointer position |
759 | * @xdr: pointer to xdr_stream struct | 737 | * @xdr: pointer to xdr_stream struct |
@@ -762,37 +740,39 @@ static unsigned int xdr_align_pages(struct xdr_stream *xdr, unsigned int len) | |||
762 | * Moves data beyond the current pointer position from the XDR head[] buffer | 740 | * Moves data beyond the current pointer position from the XDR head[] buffer |
763 | * into the page list. Any data that lies beyond current position + "len" | 741 | * into the page list. Any data that lies beyond current position + "len" |
764 | * bytes is moved into the XDR tail[]. | 742 | * bytes is moved into the XDR tail[]. |
765 | * | ||
766 | * Returns the number of XDR encoded bytes now contained in the pages | ||
767 | */ | 743 | */ |
768 | unsigned int xdr_read_pages(struct xdr_stream *xdr, unsigned int len) | 744 | void xdr_read_pages(struct xdr_stream *xdr, unsigned int len) |
769 | { | 745 | { |
770 | struct xdr_buf *buf = xdr->buf; | 746 | struct xdr_buf *buf = xdr->buf; |
771 | struct kvec *iov; | 747 | struct kvec *iov; |
772 | unsigned int nwords; | 748 | ssize_t shift; |
773 | unsigned int end; | 749 | unsigned int end; |
774 | unsigned int padding; | 750 | int padding; |
775 | 751 | ||
776 | len = xdr_align_pages(xdr, len); | 752 | /* Realign pages to current pointer position */ |
777 | if (len == 0) | 753 | iov = buf->head; |
778 | return 0; | 754 | shift = iov->iov_len + (char *)iov->iov_base - (char *)xdr->p; |
779 | nwords = XDR_QUADLEN(len); | 755 | if (shift > 0) |
780 | padding = (nwords << 2) - len; | 756 | xdr_shrink_bufhead(buf, shift); |
757 | |||
758 | /* Truncate page data and move it into the tail */ | ||
759 | if (buf->page_len > len) | ||
760 | xdr_shrink_pagelen(buf, buf->page_len - len); | ||
761 | padding = (XDR_QUADLEN(len) << 2) - len; | ||
781 | xdr->iov = iov = buf->tail; | 762 | xdr->iov = iov = buf->tail; |
782 | /* Compute remaining message length. */ | 763 | /* Compute remaining message length. */ |
783 | end = ((xdr->nwords - nwords) << 2) + padding; | 764 | end = iov->iov_len; |
784 | if (end > iov->iov_len) | 765 | shift = buf->buflen - buf->len; |
785 | end = iov->iov_len; | 766 | if (shift < end) |
786 | 767 | end -= shift; | |
768 | else if (shift > 0) | ||
769 | end = 0; | ||
787 | /* | 770 | /* |
788 | * Position current pointer at beginning of tail, and | 771 | * Position current pointer at beginning of tail, and |
789 | * set remaining message length. | 772 | * set remaining message length. |
790 | */ | 773 | */ |
791 | xdr->p = (__be32 *)((char *)iov->iov_base + padding); | 774 | xdr->p = (__be32 *)((char *)iov->iov_base + padding); |
792 | xdr->end = (__be32 *)((char *)iov->iov_base + end); | 775 | xdr->end = (__be32 *)((char *)iov->iov_base + end); |
793 | xdr->page_ptr = NULL; | ||
794 | xdr->nwords = XDR_QUADLEN(end - padding); | ||
795 | return len; | ||
796 | } | 776 | } |
797 | EXPORT_SYMBOL_GPL(xdr_read_pages); | 777 | EXPORT_SYMBOL_GPL(xdr_read_pages); |
798 | 778 | ||
@@ -808,13 +788,12 @@ EXPORT_SYMBOL_GPL(xdr_read_pages); | |||
808 | */ | 788 | */ |
809 | void xdr_enter_page(struct xdr_stream *xdr, unsigned int len) | 789 | void xdr_enter_page(struct xdr_stream *xdr, unsigned int len) |
810 | { | 790 | { |
811 | len = xdr_align_pages(xdr, len); | 791 | xdr_read_pages(xdr, len); |
812 | /* | 792 | /* |
813 | * Position current pointer at beginning of tail, and | 793 | * Position current pointer at beginning of tail, and |
814 | * set remaining message length. | 794 | * set remaining message length. |
815 | */ | 795 | */ |
816 | if (len != 0) | 796 | xdr_set_page_base(xdr, 0, len); |
817 | xdr_set_page_base(xdr, 0, len); | ||
818 | } | 797 | } |
819 | EXPORT_SYMBOL_GPL(xdr_enter_page); | 798 | EXPORT_SYMBOL_GPL(xdr_enter_page); |
820 | 799 | ||
@@ -1225,7 +1204,7 @@ xdr_process_buf(struct xdr_buf *buf, unsigned int offset, unsigned int len, | |||
1225 | int (*actor)(struct scatterlist *, void *), void *data) | 1204 | int (*actor)(struct scatterlist *, void *), void *data) |
1226 | { | 1205 | { |
1227 | int i, ret = 0; | 1206 | int i, ret = 0; |
1228 | unsigned int page_len, thislen, page_offset; | 1207 | unsigned page_len, thislen, page_offset; |
1229 | struct scatterlist sg[1]; | 1208 | struct scatterlist sg[1]; |
1230 | 1209 | ||
1231 | sg_init_table(sg, 1); | 1210 | sg_init_table(sg, 1); |
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 33811db8788..c64c0ef519b 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
@@ -66,7 +66,6 @@ static void xprt_init(struct rpc_xprt *xprt, struct net *net); | |||
66 | static void xprt_request_init(struct rpc_task *, struct rpc_xprt *); | 66 | static void xprt_request_init(struct rpc_task *, struct rpc_xprt *); |
67 | static void xprt_connect_status(struct rpc_task *task); | 67 | static void xprt_connect_status(struct rpc_task *task); |
68 | static int __xprt_get_cong(struct rpc_xprt *, struct rpc_task *); | 68 | static int __xprt_get_cong(struct rpc_xprt *, struct rpc_task *); |
69 | static void xprt_destroy(struct rpc_xprt *xprt); | ||
70 | 69 | ||
71 | static DEFINE_SPINLOCK(xprt_list_lock); | 70 | static DEFINE_SPINLOCK(xprt_list_lock); |
72 | static LIST_HEAD(xprt_list); | 71 | static LIST_HEAD(xprt_list); |
@@ -231,7 +230,7 @@ EXPORT_SYMBOL_GPL(xprt_reserve_xprt); | |||
231 | static void xprt_clear_locked(struct rpc_xprt *xprt) | 230 | static void xprt_clear_locked(struct rpc_xprt *xprt) |
232 | { | 231 | { |
233 | xprt->snd_task = NULL; | 232 | xprt->snd_task = NULL; |
234 | if (!test_bit(XPRT_CLOSE_WAIT, &xprt->state)) { | 233 | if (!test_bit(XPRT_CLOSE_WAIT, &xprt->state) || xprt->shutdown) { |
235 | smp_mb__before_clear_bit(); | 234 | smp_mb__before_clear_bit(); |
236 | clear_bit(XPRT_LOCKED, &xprt->state); | 235 | clear_bit(XPRT_LOCKED, &xprt->state); |
237 | smp_mb__after_clear_bit(); | 236 | smp_mb__after_clear_bit(); |
@@ -293,57 +292,54 @@ static inline int xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task) | |||
293 | return retval; | 292 | return retval; |
294 | } | 293 | } |
295 | 294 | ||
296 | static bool __xprt_lock_write_func(struct rpc_task *task, void *data) | 295 | static void __xprt_lock_write_next(struct rpc_xprt *xprt) |
297 | { | 296 | { |
298 | struct rpc_xprt *xprt = data; | 297 | struct rpc_task *task; |
299 | struct rpc_rqst *req; | 298 | struct rpc_rqst *req; |
300 | 299 | ||
300 | if (test_and_set_bit(XPRT_LOCKED, &xprt->state)) | ||
301 | return; | ||
302 | |||
303 | task = rpc_wake_up_next(&xprt->sending); | ||
304 | if (task == NULL) | ||
305 | goto out_unlock; | ||
306 | |||
301 | req = task->tk_rqstp; | 307 | req = task->tk_rqstp; |
302 | xprt->snd_task = task; | 308 | xprt->snd_task = task; |
303 | if (req) { | 309 | if (req) { |
304 | req->rq_bytes_sent = 0; | 310 | req->rq_bytes_sent = 0; |
305 | req->rq_ntrans++; | 311 | req->rq_ntrans++; |
306 | } | 312 | } |
307 | return true; | 313 | return; |
308 | } | ||
309 | |||
310 | static void __xprt_lock_write_next(struct rpc_xprt *xprt) | ||
311 | { | ||
312 | if (test_and_set_bit(XPRT_LOCKED, &xprt->state)) | ||
313 | return; | ||
314 | 314 | ||
315 | if (rpc_wake_up_first(&xprt->sending, __xprt_lock_write_func, xprt)) | 315 | out_unlock: |
316 | return; | ||
317 | xprt_clear_locked(xprt); | 316 | xprt_clear_locked(xprt); |
318 | } | 317 | } |
319 | 318 | ||
320 | static bool __xprt_lock_write_cong_func(struct rpc_task *task, void *data) | 319 | static void __xprt_lock_write_next_cong(struct rpc_xprt *xprt) |
321 | { | 320 | { |
322 | struct rpc_xprt *xprt = data; | 321 | struct rpc_task *task; |
323 | struct rpc_rqst *req; | 322 | struct rpc_rqst *req; |
324 | 323 | ||
324 | if (test_and_set_bit(XPRT_LOCKED, &xprt->state)) | ||
325 | return; | ||
326 | if (RPCXPRT_CONGESTED(xprt)) | ||
327 | goto out_unlock; | ||
328 | task = rpc_wake_up_next(&xprt->sending); | ||
329 | if (task == NULL) | ||
330 | goto out_unlock; | ||
331 | |||
325 | req = task->tk_rqstp; | 332 | req = task->tk_rqstp; |
326 | if (req == NULL) { | 333 | if (req == NULL) { |
327 | xprt->snd_task = task; | 334 | xprt->snd_task = task; |
328 | return true; | 335 | return; |
329 | } | 336 | } |
330 | if (__xprt_get_cong(xprt, task)) { | 337 | if (__xprt_get_cong(xprt, task)) { |
331 | xprt->snd_task = task; | 338 | xprt->snd_task = task; |
332 | req->rq_bytes_sent = 0; | 339 | req->rq_bytes_sent = 0; |
333 | req->rq_ntrans++; | 340 | req->rq_ntrans++; |
334 | return true; | ||
335 | } | ||
336 | return false; | ||
337 | } | ||
338 | |||
339 | static void __xprt_lock_write_next_cong(struct rpc_xprt *xprt) | ||
340 | { | ||
341 | if (test_and_set_bit(XPRT_LOCKED, &xprt->state)) | ||
342 | return; | ||
343 | if (RPCXPRT_CONGESTED(xprt)) | ||
344 | goto out_unlock; | ||
345 | if (rpc_wake_up_first(&xprt->sending, __xprt_lock_write_cong_func, xprt)) | ||
346 | return; | 341 | return; |
342 | } | ||
347 | out_unlock: | 343 | out_unlock: |
348 | xprt_clear_locked(xprt); | 344 | xprt_clear_locked(xprt); |
349 | } | 345 | } |
@@ -504,6 +500,9 @@ EXPORT_SYMBOL_GPL(xprt_wait_for_buffer_space); | |||
504 | */ | 500 | */ |
505 | void xprt_write_space(struct rpc_xprt *xprt) | 501 | void xprt_write_space(struct rpc_xprt *xprt) |
506 | { | 502 | { |
503 | if (unlikely(xprt->shutdown)) | ||
504 | return; | ||
505 | |||
507 | spin_lock_bh(&xprt->transport_lock); | 506 | spin_lock_bh(&xprt->transport_lock); |
508 | if (xprt->snd_task) { | 507 | if (xprt->snd_task) { |
509 | dprintk("RPC: write space: waking waiting task on " | 508 | dprintk("RPC: write space: waking waiting task on " |
@@ -528,7 +527,7 @@ void xprt_set_retrans_timeout_def(struct rpc_task *task) | |||
528 | } | 527 | } |
529 | EXPORT_SYMBOL_GPL(xprt_set_retrans_timeout_def); | 528 | EXPORT_SYMBOL_GPL(xprt_set_retrans_timeout_def); |
530 | 529 | ||
531 | /** | 530 | /* |
532 | * xprt_set_retrans_timeout_rtt - set a request's retransmit timeout | 531 | * xprt_set_retrans_timeout_rtt - set a request's retransmit timeout |
533 | * @task: task whose timeout is to be set | 532 | * @task: task whose timeout is to be set |
534 | * | 533 | * |
@@ -676,7 +675,7 @@ xprt_init_autodisconnect(unsigned long data) | |||
676 | struct rpc_xprt *xprt = (struct rpc_xprt *)data; | 675 | struct rpc_xprt *xprt = (struct rpc_xprt *)data; |
677 | 676 | ||
678 | spin_lock(&xprt->transport_lock); | 677 | spin_lock(&xprt->transport_lock); |
679 | if (!list_empty(&xprt->recv)) | 678 | if (!list_empty(&xprt->recv) || xprt->shutdown) |
680 | goto out_abort; | 679 | goto out_abort; |
681 | if (test_and_set_bit(XPRT_LOCKED, &xprt->state)) | 680 | if (test_and_set_bit(XPRT_LOCKED, &xprt->state)) |
682 | goto out_abort; | 681 | goto out_abort; |
@@ -713,7 +712,9 @@ void xprt_connect(struct rpc_task *task) | |||
713 | if (xprt_connected(xprt)) | 712 | if (xprt_connected(xprt)) |
714 | xprt_release_write(xprt, task); | 713 | xprt_release_write(xprt, task); |
715 | else { | 714 | else { |
716 | task->tk_rqstp->rq_bytes_sent = 0; | 715 | if (task->tk_rqstp) |
716 | task->tk_rqstp->rq_bytes_sent = 0; | ||
717 | |||
717 | task->tk_timeout = task->tk_rqstp->rq_timeout; | 718 | task->tk_timeout = task->tk_rqstp->rq_timeout; |
718 | rpc_sleep_on(&xprt->pending, task, xprt_connect_status); | 719 | rpc_sleep_on(&xprt->pending, task, xprt_connect_status); |
719 | 720 | ||
@@ -749,7 +750,7 @@ static void xprt_connect_status(struct rpc_task *task) | |||
749 | default: | 750 | default: |
750 | dprintk("RPC: %5u xprt_connect_status: error %d connecting to " | 751 | dprintk("RPC: %5u xprt_connect_status: error %d connecting to " |
751 | "server %s\n", task->tk_pid, -task->tk_status, | 752 | "server %s\n", task->tk_pid, -task->tk_status, |
752 | xprt->servername); | 753 | task->tk_client->cl_server); |
753 | xprt_release_write(xprt, task); | 754 | xprt_release_write(xprt, task); |
754 | task->tk_status = -EIO; | 755 | task->tk_status = -EIO; |
755 | } | 756 | } |
@@ -780,7 +781,7 @@ static void xprt_update_rtt(struct rpc_task *task) | |||
780 | { | 781 | { |
781 | struct rpc_rqst *req = task->tk_rqstp; | 782 | struct rpc_rqst *req = task->tk_rqstp; |
782 | struct rpc_rtt *rtt = task->tk_client->cl_rtt; | 783 | struct rpc_rtt *rtt = task->tk_client->cl_rtt; |
783 | unsigned int timer = task->tk_msg.rpc_proc->p_timer; | 784 | unsigned timer = task->tk_msg.rpc_proc->p_timer; |
784 | long m = usecs_to_jiffies(ktime_to_us(req->rq_rtt)); | 785 | long m = usecs_to_jiffies(ktime_to_us(req->rq_rtt)); |
785 | 786 | ||
786 | if (timer) { | 787 | if (timer) { |
@@ -883,7 +884,7 @@ void xprt_transmit(struct rpc_task *task) | |||
883 | { | 884 | { |
884 | struct rpc_rqst *req = task->tk_rqstp; | 885 | struct rpc_rqst *req = task->tk_rqstp; |
885 | struct rpc_xprt *xprt = req->rq_xprt; | 886 | struct rpc_xprt *xprt = req->rq_xprt; |
886 | int status, numreqs; | 887 | int status; |
887 | 888 | ||
888 | dprintk("RPC: %5u xprt_transmit(%u)\n", task->tk_pid, req->rq_slen); | 889 | dprintk("RPC: %5u xprt_transmit(%u)\n", task->tk_pid, req->rq_slen); |
889 | 890 | ||
@@ -920,14 +921,9 @@ void xprt_transmit(struct rpc_task *task) | |||
920 | 921 | ||
921 | xprt->ops->set_retrans_timeout(task); | 922 | xprt->ops->set_retrans_timeout(task); |
922 | 923 | ||
923 | numreqs = atomic_read(&xprt->num_reqs); | ||
924 | if (numreqs > xprt->stat.max_slots) | ||
925 | xprt->stat.max_slots = numreqs; | ||
926 | xprt->stat.sends++; | 924 | xprt->stat.sends++; |
927 | xprt->stat.req_u += xprt->stat.sends - xprt->stat.recvs; | 925 | xprt->stat.req_u += xprt->stat.sends - xprt->stat.recvs; |
928 | xprt->stat.bklog_u += xprt->backlog.qlen; | 926 | xprt->stat.bklog_u += xprt->backlog.qlen; |
929 | xprt->stat.sending_u += xprt->sending.qlen; | ||
930 | xprt->stat.pending_u += xprt->pending.qlen; | ||
931 | 927 | ||
932 | /* Don't race with disconnect */ | 928 | /* Don't race with disconnect */ |
933 | if (!xprt_connected(xprt)) | 929 | if (!xprt_connected(xprt)) |
@@ -966,54 +962,36 @@ static bool xprt_dynamic_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *req) | |||
966 | return false; | 962 | return false; |
967 | } | 963 | } |
968 | 964 | ||
969 | void xprt_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task) | 965 | static void xprt_alloc_slot(struct rpc_task *task) |
970 | { | 966 | { |
967 | struct rpc_xprt *xprt = task->tk_xprt; | ||
971 | struct rpc_rqst *req; | 968 | struct rpc_rqst *req; |
972 | 969 | ||
973 | spin_lock(&xprt->reserve_lock); | ||
974 | if (!list_empty(&xprt->free)) { | 970 | if (!list_empty(&xprt->free)) { |
975 | req = list_entry(xprt->free.next, struct rpc_rqst, rq_list); | 971 | req = list_entry(xprt->free.next, struct rpc_rqst, rq_list); |
976 | list_del(&req->rq_list); | 972 | list_del(&req->rq_list); |
977 | goto out_init_req; | 973 | goto out_init_req; |
978 | } | 974 | } |
979 | req = xprt_dynamic_alloc_slot(xprt, GFP_NOWAIT|__GFP_NOWARN); | 975 | req = xprt_dynamic_alloc_slot(xprt, GFP_NOWAIT); |
980 | if (!IS_ERR(req)) | 976 | if (!IS_ERR(req)) |
981 | goto out_init_req; | 977 | goto out_init_req; |
982 | switch (PTR_ERR(req)) { | 978 | switch (PTR_ERR(req)) { |
983 | case -ENOMEM: | 979 | case -ENOMEM: |
980 | rpc_delay(task, HZ >> 2); | ||
984 | dprintk("RPC: dynamic allocation of request slot " | 981 | dprintk("RPC: dynamic allocation of request slot " |
985 | "failed! Retrying\n"); | 982 | "failed! Retrying\n"); |
986 | task->tk_status = -ENOMEM; | ||
987 | break; | 983 | break; |
988 | case -EAGAIN: | 984 | case -EAGAIN: |
989 | rpc_sleep_on(&xprt->backlog, task, NULL); | 985 | rpc_sleep_on(&xprt->backlog, task, NULL); |
990 | dprintk("RPC: waiting for request slot\n"); | 986 | dprintk("RPC: waiting for request slot\n"); |
991 | default: | ||
992 | task->tk_status = -EAGAIN; | ||
993 | } | 987 | } |
994 | spin_unlock(&xprt->reserve_lock); | 988 | task->tk_status = -EAGAIN; |
995 | return; | 989 | return; |
996 | out_init_req: | 990 | out_init_req: |
997 | task->tk_status = 0; | 991 | task->tk_status = 0; |
998 | task->tk_rqstp = req; | 992 | task->tk_rqstp = req; |
999 | xprt_request_init(task, xprt); | 993 | xprt_request_init(task, xprt); |
1000 | spin_unlock(&xprt->reserve_lock); | ||
1001 | } | 994 | } |
1002 | EXPORT_SYMBOL_GPL(xprt_alloc_slot); | ||
1003 | |||
1004 | void xprt_lock_and_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task) | ||
1005 | { | ||
1006 | /* Note: grabbing the xprt_lock_write() ensures that we throttle | ||
1007 | * new slot allocation if the transport is congested (i.e. when | ||
1008 | * reconnecting a stream transport or when out of socket write | ||
1009 | * buffer space). | ||
1010 | */ | ||
1011 | if (xprt_lock_write(xprt, task)) { | ||
1012 | xprt_alloc_slot(xprt, task); | ||
1013 | xprt_release_write(xprt, task); | ||
1014 | } | ||
1015 | } | ||
1016 | EXPORT_SYMBOL_GPL(xprt_lock_and_alloc_slot); | ||
1017 | 995 | ||
1018 | static void xprt_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *req) | 996 | static void xprt_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *req) |
1019 | { | 997 | { |
@@ -1097,9 +1075,20 @@ void xprt_reserve(struct rpc_task *task) | |||
1097 | if (task->tk_rqstp != NULL) | 1075 | if (task->tk_rqstp != NULL) |
1098 | return; | 1076 | return; |
1099 | 1077 | ||
1078 | /* Note: grabbing the xprt_lock_write() here is not strictly needed, | ||
1079 | * but ensures that we throttle new slot allocation if the transport | ||
1080 | * is congested (e.g. if reconnecting or if we're out of socket | ||
1081 | * write buffer space). | ||
1082 | */ | ||
1100 | task->tk_timeout = 0; | 1083 | task->tk_timeout = 0; |
1101 | task->tk_status = -EAGAIN; | 1084 | task->tk_status = -EAGAIN; |
1102 | xprt->ops->alloc_slot(xprt, task); | 1085 | if (!xprt_lock_write(xprt, task)) |
1086 | return; | ||
1087 | |||
1088 | spin_lock(&xprt->reserve_lock); | ||
1089 | xprt_alloc_slot(task); | ||
1090 | spin_unlock(&xprt->reserve_lock); | ||
1091 | xprt_release_write(xprt, task); | ||
1103 | } | 1092 | } |
1104 | 1093 | ||
1105 | static inline __be32 xprt_alloc_xid(struct rpc_xprt *xprt) | 1094 | static inline __be32 xprt_alloc_xid(struct rpc_xprt *xprt) |
@@ -1136,24 +1125,13 @@ static void xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt) | |||
1136 | void xprt_release(struct rpc_task *task) | 1125 | void xprt_release(struct rpc_task *task) |
1137 | { | 1126 | { |
1138 | struct rpc_xprt *xprt; | 1127 | struct rpc_xprt *xprt; |
1139 | struct rpc_rqst *req = task->tk_rqstp; | 1128 | struct rpc_rqst *req; |
1140 | 1129 | ||
1141 | if (req == NULL) { | 1130 | if (!(req = task->tk_rqstp)) |
1142 | if (task->tk_client) { | ||
1143 | rcu_read_lock(); | ||
1144 | xprt = rcu_dereference(task->tk_client->cl_xprt); | ||
1145 | if (xprt->snd_task == task) | ||
1146 | xprt_release_write(xprt, task); | ||
1147 | rcu_read_unlock(); | ||
1148 | } | ||
1149 | return; | 1131 | return; |
1150 | } | ||
1151 | 1132 | ||
1152 | xprt = req->rq_xprt; | 1133 | xprt = req->rq_xprt; |
1153 | if (task->tk_ops->rpc_count_stats != NULL) | 1134 | rpc_count_iostats(task); |
1154 | task->tk_ops->rpc_count_stats(task, task->tk_calldata); | ||
1155 | else if (task->tk_client) | ||
1156 | rpc_count_iostats(task, task->tk_client->cl_metrics); | ||
1157 | spin_lock_bh(&xprt->transport_lock); | 1135 | spin_lock_bh(&xprt->transport_lock); |
1158 | xprt->ops->release_xprt(xprt, task); | 1136 | xprt->ops->release_xprt(xprt, task); |
1159 | if (xprt->ops->release_request) | 1137 | if (xprt->ops->release_request) |
@@ -1242,17 +1220,6 @@ found: | |||
1242 | (unsigned long)xprt); | 1220 | (unsigned long)xprt); |
1243 | else | 1221 | else |
1244 | init_timer(&xprt->timer); | 1222 | init_timer(&xprt->timer); |
1245 | |||
1246 | if (strlen(args->servername) > RPC_MAXNETNAMELEN) { | ||
1247 | xprt_destroy(xprt); | ||
1248 | return ERR_PTR(-EINVAL); | ||
1249 | } | ||
1250 | xprt->servername = kstrdup(args->servername, GFP_KERNEL); | ||
1251 | if (xprt->servername == NULL) { | ||
1252 | xprt_destroy(xprt); | ||
1253 | return ERR_PTR(-ENOMEM); | ||
1254 | } | ||
1255 | |||
1256 | dprintk("RPC: created transport %p with %u slots\n", xprt, | 1223 | dprintk("RPC: created transport %p with %u slots\n", xprt, |
1257 | xprt->max_reqs); | 1224 | xprt->max_reqs); |
1258 | out: | 1225 | out: |
@@ -1267,6 +1234,7 @@ out: | |||
1267 | static void xprt_destroy(struct rpc_xprt *xprt) | 1234 | static void xprt_destroy(struct rpc_xprt *xprt) |
1268 | { | 1235 | { |
1269 | dprintk("RPC: destroying transport %p\n", xprt); | 1236 | dprintk("RPC: destroying transport %p\n", xprt); |
1237 | xprt->shutdown = 1; | ||
1270 | del_timer_sync(&xprt->timer); | 1238 | del_timer_sync(&xprt->timer); |
1271 | 1239 | ||
1272 | rpc_destroy_wait_queue(&xprt->binding); | 1240 | rpc_destroy_wait_queue(&xprt->binding); |
@@ -1274,7 +1242,6 @@ static void xprt_destroy(struct rpc_xprt *xprt) | |||
1274 | rpc_destroy_wait_queue(&xprt->sending); | 1242 | rpc_destroy_wait_queue(&xprt->sending); |
1275 | rpc_destroy_wait_queue(&xprt->backlog); | 1243 | rpc_destroy_wait_queue(&xprt->backlog); |
1276 | cancel_work_sync(&xprt->task_cleanup); | 1244 | cancel_work_sync(&xprt->task_cleanup); |
1277 | kfree(xprt->servername); | ||
1278 | /* | 1245 | /* |
1279 | * Tear down transport state and free the rpc_xprt | 1246 | * Tear down transport state and free the rpc_xprt |
1280 | */ | 1247 | */ |
diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c index 558fbab574f..554d0814c87 100644 --- a/net/sunrpc/xprtrdma/rpc_rdma.c +++ b/net/sunrpc/xprtrdma/rpc_rdma.c | |||
@@ -338,9 +338,9 @@ rpcrdma_inline_pullup(struct rpc_rqst *rqst, int pad) | |||
338 | curlen = copy_len; | 338 | curlen = copy_len; |
339 | dprintk("RPC: %s: page %d destp 0x%p len %d curlen %d\n", | 339 | dprintk("RPC: %s: page %d destp 0x%p len %d curlen %d\n", |
340 | __func__, i, destp, copy_len, curlen); | 340 | __func__, i, destp, copy_len, curlen); |
341 | srcp = kmap_atomic(ppages[i]); | 341 | srcp = kmap_atomic(ppages[i], KM_SKB_SUNRPC_DATA); |
342 | memcpy(destp, srcp+page_base, curlen); | 342 | memcpy(destp, srcp+page_base, curlen); |
343 | kunmap_atomic(srcp); | 343 | kunmap_atomic(srcp, KM_SKB_SUNRPC_DATA); |
344 | rqst->rq_svec[0].iov_len += curlen; | 344 | rqst->rq_svec[0].iov_len += curlen; |
345 | destp += curlen; | 345 | destp += curlen; |
346 | copy_len -= curlen; | 346 | copy_len -= curlen; |
@@ -639,10 +639,10 @@ rpcrdma_inline_fixup(struct rpc_rqst *rqst, char *srcp, int copy_len, int pad) | |||
639 | dprintk("RPC: %s: page %d" | 639 | dprintk("RPC: %s: page %d" |
640 | " srcp 0x%p len %d curlen %d\n", | 640 | " srcp 0x%p len %d curlen %d\n", |
641 | __func__, i, srcp, copy_len, curlen); | 641 | __func__, i, srcp, copy_len, curlen); |
642 | destp = kmap_atomic(ppages[i]); | 642 | destp = kmap_atomic(ppages[i], KM_SKB_SUNRPC_DATA); |
643 | memcpy(destp + page_base, srcp, curlen); | 643 | memcpy(destp + page_base, srcp, curlen); |
644 | flush_dcache_page(ppages[i]); | 644 | flush_dcache_page(ppages[i]); |
645 | kunmap_atomic(destp); | 645 | kunmap_atomic(destp, KM_SKB_SUNRPC_DATA); |
646 | srcp += curlen; | 646 | srcp += curlen; |
647 | copy_len -= curlen; | 647 | copy_len -= curlen; |
648 | if (copy_len == 0) | 648 | if (copy_len == 0) |
@@ -771,18 +771,13 @@ repost: | |||
771 | 771 | ||
772 | /* get request object */ | 772 | /* get request object */ |
773 | req = rpcr_to_rdmar(rqst); | 773 | req = rpcr_to_rdmar(rqst); |
774 | if (req->rl_reply) { | ||
775 | spin_unlock(&xprt->transport_lock); | ||
776 | dprintk("RPC: %s: duplicate reply 0x%p to RPC " | ||
777 | "request 0x%p: xid 0x%08x\n", __func__, rep, req, | ||
778 | headerp->rm_xid); | ||
779 | goto repost; | ||
780 | } | ||
781 | 774 | ||
782 | dprintk("RPC: %s: reply 0x%p completes request 0x%p\n" | 775 | dprintk("RPC: %s: reply 0x%p completes request 0x%p\n" |
783 | " RPC request 0x%p xid 0x%08x\n", | 776 | " RPC request 0x%p xid 0x%08x\n", |
784 | __func__, rep, req, rqst, headerp->rm_xid); | 777 | __func__, rep, req, rqst, headerp->rm_xid); |
785 | 778 | ||
779 | BUG_ON(!req || req->rl_reply); | ||
780 | |||
786 | /* from here on, the reply is no longer an orphan */ | 781 | /* from here on, the reply is no longer an orphan */ |
787 | req->rl_reply = rep; | 782 | req->rl_reply = rep; |
788 | 783 | ||
diff --git a/net/sunrpc/xprtrdma/svc_rdma.c b/net/sunrpc/xprtrdma/svc_rdma.c index 8343737e85f..09af4fab1a4 100644 --- a/net/sunrpc/xprtrdma/svc_rdma.c +++ b/net/sunrpc/xprtrdma/svc_rdma.c | |||
@@ -47,7 +47,6 @@ | |||
47 | #include <linux/sunrpc/clnt.h> | 47 | #include <linux/sunrpc/clnt.h> |
48 | #include <linux/sunrpc/sched.h> | 48 | #include <linux/sunrpc/sched.h> |
49 | #include <linux/sunrpc/svc_rdma.h> | 49 | #include <linux/sunrpc/svc_rdma.h> |
50 | #include "xprt_rdma.h" | ||
51 | 50 | ||
52 | #define RPCDBG_FACILITY RPCDBG_SVCXPRT | 51 | #define RPCDBG_FACILITY RPCDBG_SVCXPRT |
53 | 52 | ||
diff --git a/net/sunrpc/xprtrdma/svc_rdma_marshal.c b/net/sunrpc/xprtrdma/svc_rdma_marshal.c index 8d2edddf48c..9530ef2d40d 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_marshal.c +++ b/net/sunrpc/xprtrdma/svc_rdma_marshal.c | |||
@@ -60,11 +60,21 @@ static u32 *decode_read_list(u32 *va, u32 *vaend) | |||
60 | struct rpcrdma_read_chunk *ch = (struct rpcrdma_read_chunk *)va; | 60 | struct rpcrdma_read_chunk *ch = (struct rpcrdma_read_chunk *)va; |
61 | 61 | ||
62 | while (ch->rc_discrim != xdr_zero) { | 62 | while (ch->rc_discrim != xdr_zero) { |
63 | u64 ch_offset; | ||
64 | |||
63 | if (((unsigned long)ch + sizeof(struct rpcrdma_read_chunk)) > | 65 | if (((unsigned long)ch + sizeof(struct rpcrdma_read_chunk)) > |
64 | (unsigned long)vaend) { | 66 | (unsigned long)vaend) { |
65 | dprintk("svcrdma: vaend=%p, ch=%p\n", vaend, ch); | 67 | dprintk("svcrdma: vaend=%p, ch=%p\n", vaend, ch); |
66 | return NULL; | 68 | return NULL; |
67 | } | 69 | } |
70 | |||
71 | ch->rc_discrim = ntohl(ch->rc_discrim); | ||
72 | ch->rc_position = ntohl(ch->rc_position); | ||
73 | ch->rc_target.rs_handle = ntohl(ch->rc_target.rs_handle); | ||
74 | ch->rc_target.rs_length = ntohl(ch->rc_target.rs_length); | ||
75 | va = (u32 *)&ch->rc_target.rs_offset; | ||
76 | xdr_decode_hyper(va, &ch_offset); | ||
77 | put_unaligned(ch_offset, (u64 *)va); | ||
68 | ch++; | 78 | ch++; |
69 | } | 79 | } |
70 | return (u32 *)&ch->rc_position; | 80 | return (u32 *)&ch->rc_position; |
@@ -81,7 +91,7 @@ void svc_rdma_rcl_chunk_counts(struct rpcrdma_read_chunk *ch, | |||
81 | *byte_count = 0; | 91 | *byte_count = 0; |
82 | *ch_count = 0; | 92 | *ch_count = 0; |
83 | for (; ch->rc_discrim != 0; ch++) { | 93 | for (; ch->rc_discrim != 0; ch++) { |
84 | *byte_count = *byte_count + ntohl(ch->rc_target.rs_length); | 94 | *byte_count = *byte_count + ch->rc_target.rs_length; |
85 | *ch_count = *ch_count + 1; | 95 | *ch_count = *ch_count + 1; |
86 | } | 96 | } |
87 | } | 97 | } |
@@ -98,8 +108,7 @@ void svc_rdma_rcl_chunk_counts(struct rpcrdma_read_chunk *ch, | |||
98 | */ | 108 | */ |
99 | static u32 *decode_write_list(u32 *va, u32 *vaend) | 109 | static u32 *decode_write_list(u32 *va, u32 *vaend) |
100 | { | 110 | { |
101 | int nchunks; | 111 | int ch_no; |
102 | |||
103 | struct rpcrdma_write_array *ary = | 112 | struct rpcrdma_write_array *ary = |
104 | (struct rpcrdma_write_array *)va; | 113 | (struct rpcrdma_write_array *)va; |
105 | 114 | ||
@@ -112,24 +121,37 @@ static u32 *decode_write_list(u32 *va, u32 *vaend) | |||
112 | dprintk("svcrdma: ary=%p, vaend=%p\n", ary, vaend); | 121 | dprintk("svcrdma: ary=%p, vaend=%p\n", ary, vaend); |
113 | return NULL; | 122 | return NULL; |
114 | } | 123 | } |
115 | nchunks = ntohl(ary->wc_nchunks); | 124 | ary->wc_discrim = ntohl(ary->wc_discrim); |
125 | ary->wc_nchunks = ntohl(ary->wc_nchunks); | ||
116 | if (((unsigned long)&ary->wc_array[0] + | 126 | if (((unsigned long)&ary->wc_array[0] + |
117 | (sizeof(struct rpcrdma_write_chunk) * nchunks)) > | 127 | (sizeof(struct rpcrdma_write_chunk) * ary->wc_nchunks)) > |
118 | (unsigned long)vaend) { | 128 | (unsigned long)vaend) { |
119 | dprintk("svcrdma: ary=%p, wc_nchunks=%d, vaend=%p\n", | 129 | dprintk("svcrdma: ary=%p, wc_nchunks=%d, vaend=%p\n", |
120 | ary, nchunks, vaend); | 130 | ary, ary->wc_nchunks, vaend); |
121 | return NULL; | 131 | return NULL; |
122 | } | 132 | } |
133 | for (ch_no = 0; ch_no < ary->wc_nchunks; ch_no++) { | ||
134 | u64 ch_offset; | ||
135 | |||
136 | ary->wc_array[ch_no].wc_target.rs_handle = | ||
137 | ntohl(ary->wc_array[ch_no].wc_target.rs_handle); | ||
138 | ary->wc_array[ch_no].wc_target.rs_length = | ||
139 | ntohl(ary->wc_array[ch_no].wc_target.rs_length); | ||
140 | va = (u32 *)&ary->wc_array[ch_no].wc_target.rs_offset; | ||
141 | xdr_decode_hyper(va, &ch_offset); | ||
142 | put_unaligned(ch_offset, (u64 *)va); | ||
143 | } | ||
144 | |||
123 | /* | 145 | /* |
124 | * rs_length is the 2nd 4B field in wc_target and taking its | 146 | * rs_length is the 2nd 4B field in wc_target and taking its |
125 | * address skips the list terminator | 147 | * address skips the list terminator |
126 | */ | 148 | */ |
127 | return (u32 *)&ary->wc_array[nchunks].wc_target.rs_length; | 149 | return (u32 *)&ary->wc_array[ch_no].wc_target.rs_length; |
128 | } | 150 | } |
129 | 151 | ||
130 | static u32 *decode_reply_array(u32 *va, u32 *vaend) | 152 | static u32 *decode_reply_array(u32 *va, u32 *vaend) |
131 | { | 153 | { |
132 | int nchunks; | 154 | int ch_no; |
133 | struct rpcrdma_write_array *ary = | 155 | struct rpcrdma_write_array *ary = |
134 | (struct rpcrdma_write_array *)va; | 156 | (struct rpcrdma_write_array *)va; |
135 | 157 | ||
@@ -142,15 +164,28 @@ static u32 *decode_reply_array(u32 *va, u32 *vaend) | |||
142 | dprintk("svcrdma: ary=%p, vaend=%p\n", ary, vaend); | 164 | dprintk("svcrdma: ary=%p, vaend=%p\n", ary, vaend); |
143 | return NULL; | 165 | return NULL; |
144 | } | 166 | } |
145 | nchunks = ntohl(ary->wc_nchunks); | 167 | ary->wc_discrim = ntohl(ary->wc_discrim); |
168 | ary->wc_nchunks = ntohl(ary->wc_nchunks); | ||
146 | if (((unsigned long)&ary->wc_array[0] + | 169 | if (((unsigned long)&ary->wc_array[0] + |
147 | (sizeof(struct rpcrdma_write_chunk) * nchunks)) > | 170 | (sizeof(struct rpcrdma_write_chunk) * ary->wc_nchunks)) > |
148 | (unsigned long)vaend) { | 171 | (unsigned long)vaend) { |
149 | dprintk("svcrdma: ary=%p, wc_nchunks=%d, vaend=%p\n", | 172 | dprintk("svcrdma: ary=%p, wc_nchunks=%d, vaend=%p\n", |
150 | ary, nchunks, vaend); | 173 | ary, ary->wc_nchunks, vaend); |
151 | return NULL; | 174 | return NULL; |
152 | } | 175 | } |
153 | return (u32 *)&ary->wc_array[nchunks]; | 176 | for (ch_no = 0; ch_no < ary->wc_nchunks; ch_no++) { |
177 | u64 ch_offset; | ||
178 | |||
179 | ary->wc_array[ch_no].wc_target.rs_handle = | ||
180 | ntohl(ary->wc_array[ch_no].wc_target.rs_handle); | ||
181 | ary->wc_array[ch_no].wc_target.rs_length = | ||
182 | ntohl(ary->wc_array[ch_no].wc_target.rs_length); | ||
183 | va = (u32 *)&ary->wc_array[ch_no].wc_target.rs_offset; | ||
184 | xdr_decode_hyper(va, &ch_offset); | ||
185 | put_unaligned(ch_offset, (u64 *)va); | ||
186 | } | ||
187 | |||
188 | return (u32 *)&ary->wc_array[ch_no]; | ||
154 | } | 189 | } |
155 | 190 | ||
156 | int svc_rdma_xdr_decode_req(struct rpcrdma_msg **rdma_req, | 191 | int svc_rdma_xdr_decode_req(struct rpcrdma_msg **rdma_req, |
@@ -351,14 +386,13 @@ void svc_rdma_xdr_encode_reply_array(struct rpcrdma_write_array *ary, | |||
351 | 386 | ||
352 | void svc_rdma_xdr_encode_array_chunk(struct rpcrdma_write_array *ary, | 387 | void svc_rdma_xdr_encode_array_chunk(struct rpcrdma_write_array *ary, |
353 | int chunk_no, | 388 | int chunk_no, |
354 | __be32 rs_handle, | 389 | u32 rs_handle, u64 rs_offset, |
355 | __be64 rs_offset, | ||
356 | u32 write_len) | 390 | u32 write_len) |
357 | { | 391 | { |
358 | struct rpcrdma_segment *seg = &ary->wc_array[chunk_no].wc_target; | 392 | struct rpcrdma_segment *seg = &ary->wc_array[chunk_no].wc_target; |
359 | seg->rs_handle = rs_handle; | 393 | seg->rs_handle = htonl(rs_handle); |
360 | seg->rs_offset = rs_offset; | ||
361 | seg->rs_length = htonl(write_len); | 394 | seg->rs_length = htonl(write_len); |
395 | xdr_encode_hyper((u32 *) &seg->rs_offset, rs_offset); | ||
362 | } | 396 | } |
363 | 397 | ||
364 | void svc_rdma_xdr_encode_reply_header(struct svcxprt_rdma *xprt, | 398 | void svc_rdma_xdr_encode_reply_header(struct svcxprt_rdma *xprt, |
diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c index 0ce75524ed2..df67211c4ba 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c +++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c | |||
@@ -147,7 +147,7 @@ static int map_read_chunks(struct svcxprt_rdma *xprt, | |||
147 | page_off = 0; | 147 | page_off = 0; |
148 | ch = (struct rpcrdma_read_chunk *)&rmsgp->rm_body.rm_chunks[0]; | 148 | ch = (struct rpcrdma_read_chunk *)&rmsgp->rm_body.rm_chunks[0]; |
149 | ch_no = 0; | 149 | ch_no = 0; |
150 | ch_bytes = ntohl(ch->rc_target.rs_length); | 150 | ch_bytes = ch->rc_target.rs_length; |
151 | head->arg.head[0] = rqstp->rq_arg.head[0]; | 151 | head->arg.head[0] = rqstp->rq_arg.head[0]; |
152 | head->arg.tail[0] = rqstp->rq_arg.tail[0]; | 152 | head->arg.tail[0] = rqstp->rq_arg.tail[0]; |
153 | head->arg.pages = &head->pages[head->count]; | 153 | head->arg.pages = &head->pages[head->count]; |
@@ -183,7 +183,7 @@ static int map_read_chunks(struct svcxprt_rdma *xprt, | |||
183 | ch_no++; | 183 | ch_no++; |
184 | ch++; | 184 | ch++; |
185 | chl_map->ch[ch_no].start = sge_no; | 185 | chl_map->ch[ch_no].start = sge_no; |
186 | ch_bytes = ntohl(ch->rc_target.rs_length); | 186 | ch_bytes = ch->rc_target.rs_length; |
187 | /* If bytes remaining account for next chunk */ | 187 | /* If bytes remaining account for next chunk */ |
188 | if (byte_count) { | 188 | if (byte_count) { |
189 | head->arg.page_len += ch_bytes; | 189 | head->arg.page_len += ch_bytes; |
@@ -281,12 +281,11 @@ static int fast_reg_read_chunks(struct svcxprt_rdma *xprt, | |||
281 | offset = 0; | 281 | offset = 0; |
282 | ch = (struct rpcrdma_read_chunk *)&rmsgp->rm_body.rm_chunks[0]; | 282 | ch = (struct rpcrdma_read_chunk *)&rmsgp->rm_body.rm_chunks[0]; |
283 | for (ch_no = 0; ch_no < ch_count; ch_no++) { | 283 | for (ch_no = 0; ch_no < ch_count; ch_no++) { |
284 | int len = ntohl(ch->rc_target.rs_length); | ||
285 | rpl_map->sge[ch_no].iov_base = frmr->kva + offset; | 284 | rpl_map->sge[ch_no].iov_base = frmr->kva + offset; |
286 | rpl_map->sge[ch_no].iov_len = len; | 285 | rpl_map->sge[ch_no].iov_len = ch->rc_target.rs_length; |
287 | chl_map->ch[ch_no].count = 1; | 286 | chl_map->ch[ch_no].count = 1; |
288 | chl_map->ch[ch_no].start = ch_no; | 287 | chl_map->ch[ch_no].start = ch_no; |
289 | offset += len; | 288 | offset += ch->rc_target.rs_length; |
290 | ch++; | 289 | ch++; |
291 | } | 290 | } |
292 | 291 | ||
@@ -317,7 +316,7 @@ static int rdma_set_ctxt_sge(struct svcxprt_rdma *xprt, | |||
317 | for (i = 0; i < count; i++) { | 316 | for (i = 0; i < count; i++) { |
318 | ctxt->sge[i].length = 0; /* in case map fails */ | 317 | ctxt->sge[i].length = 0; /* in case map fails */ |
319 | if (!frmr) { | 318 | if (!frmr) { |
320 | BUG_ON(!virt_to_page(vec[i].iov_base)); | 319 | BUG_ON(0 == virt_to_page(vec[i].iov_base)); |
321 | off = (unsigned long)vec[i].iov_base & ~PAGE_MASK; | 320 | off = (unsigned long)vec[i].iov_base & ~PAGE_MASK; |
322 | ctxt->sge[i].addr = | 321 | ctxt->sge[i].addr = |
323 | ib_dma_map_page(xprt->sc_cm_id->device, | 322 | ib_dma_map_page(xprt->sc_cm_id->device, |
@@ -427,7 +426,6 @@ static int rdma_read_xdr(struct svcxprt_rdma *xprt, | |||
427 | 426 | ||
428 | for (ch = (struct rpcrdma_read_chunk *)&rmsgp->rm_body.rm_chunks[0]; | 427 | for (ch = (struct rpcrdma_read_chunk *)&rmsgp->rm_body.rm_chunks[0]; |
429 | ch->rc_discrim != 0; ch++, ch_no++) { | 428 | ch->rc_discrim != 0; ch++, ch_no++) { |
430 | u64 rs_offset; | ||
431 | next_sge: | 429 | next_sge: |
432 | ctxt = svc_rdma_get_context(xprt); | 430 | ctxt = svc_rdma_get_context(xprt); |
433 | ctxt->direction = DMA_FROM_DEVICE; | 431 | ctxt->direction = DMA_FROM_DEVICE; |
@@ -442,10 +440,10 @@ next_sge: | |||
442 | read_wr.opcode = IB_WR_RDMA_READ; | 440 | read_wr.opcode = IB_WR_RDMA_READ; |
443 | ctxt->wr_op = read_wr.opcode; | 441 | ctxt->wr_op = read_wr.opcode; |
444 | read_wr.send_flags = IB_SEND_SIGNALED; | 442 | read_wr.send_flags = IB_SEND_SIGNALED; |
445 | read_wr.wr.rdma.rkey = ntohl(ch->rc_target.rs_handle); | 443 | read_wr.wr.rdma.rkey = ch->rc_target.rs_handle; |
446 | xdr_decode_hyper((__be32 *)&ch->rc_target.rs_offset, | 444 | read_wr.wr.rdma.remote_addr = |
447 | &rs_offset); | 445 | get_unaligned(&(ch->rc_target.rs_offset)) + |
448 | read_wr.wr.rdma.remote_addr = rs_offset + sgl_offset; | 446 | sgl_offset; |
449 | read_wr.sg_list = ctxt->sge; | 447 | read_wr.sg_list = ctxt->sge; |
450 | read_wr.num_sge = | 448 | read_wr.num_sge = |
451 | rdma_read_max_sge(xprt, chl_map->ch[ch_no].count); | 449 | rdma_read_max_sge(xprt, chl_map->ch[ch_no].count); |
@@ -521,11 +519,11 @@ next_sge: | |||
521 | rqstp->rq_pages[ch_no] = NULL; | 519 | rqstp->rq_pages[ch_no] = NULL; |
522 | 520 | ||
523 | /* | 521 | /* |
524 | * Detach res pages. If svc_release sees any it will attempt to | 522 | * Detach res pages. svc_release must see a resused count of |
525 | * put them. | 523 | * zero or it will attempt to put them. |
526 | */ | 524 | */ |
527 | while (rqstp->rq_next_page != rqstp->rq_respages) | 525 | while (rqstp->rq_resused) |
528 | *(--rqstp->rq_next_page) = NULL; | 526 | rqstp->rq_respages[--rqstp->rq_resused] = NULL; |
529 | 527 | ||
530 | return err; | 528 | return err; |
531 | } | 529 | } |
@@ -550,7 +548,7 @@ static int rdma_read_complete(struct svc_rqst *rqstp, | |||
550 | 548 | ||
551 | /* rq_respages starts after the last arg page */ | 549 | /* rq_respages starts after the last arg page */ |
552 | rqstp->rq_respages = &rqstp->rq_arg.pages[page_no]; | 550 | rqstp->rq_respages = &rqstp->rq_arg.pages[page_no]; |
553 | rqstp->rq_next_page = &rqstp->rq_arg.pages[page_no]; | 551 | rqstp->rq_resused = 0; |
554 | 552 | ||
555 | /* Rebuild rq_arg head and tail. */ | 553 | /* Rebuild rq_arg head and tail. */ |
556 | rqstp->rq_arg.head[0] = head->arg.head[0]; | 554 | rqstp->rq_arg.head[0] = head->arg.head[0]; |
diff --git a/net/sunrpc/xprtrdma/svc_rdma_sendto.c b/net/sunrpc/xprtrdma/svc_rdma_sendto.c index c1d124dc772..249a835b703 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_sendto.c +++ b/net/sunrpc/xprtrdma/svc_rdma_sendto.c | |||
@@ -409,21 +409,21 @@ static int send_write_chunks(struct svcxprt_rdma *xprt, | |||
409 | u64 rs_offset; | 409 | u64 rs_offset; |
410 | 410 | ||
411 | arg_ch = &arg_ary->wc_array[chunk_no].wc_target; | 411 | arg_ch = &arg_ary->wc_array[chunk_no].wc_target; |
412 | write_len = min(xfer_len, ntohl(arg_ch->rs_length)); | 412 | write_len = min(xfer_len, arg_ch->rs_length); |
413 | 413 | ||
414 | /* Prepare the response chunk given the length actually | 414 | /* Prepare the response chunk given the length actually |
415 | * written */ | 415 | * written */ |
416 | xdr_decode_hyper((__be32 *)&arg_ch->rs_offset, &rs_offset); | 416 | rs_offset = get_unaligned(&(arg_ch->rs_offset)); |
417 | svc_rdma_xdr_encode_array_chunk(res_ary, chunk_no, | 417 | svc_rdma_xdr_encode_array_chunk(res_ary, chunk_no, |
418 | arg_ch->rs_handle, | 418 | arg_ch->rs_handle, |
419 | arg_ch->rs_offset, | 419 | rs_offset, |
420 | write_len); | 420 | write_len); |
421 | chunk_off = 0; | 421 | chunk_off = 0; |
422 | while (write_len) { | 422 | while (write_len) { |
423 | int this_write; | 423 | int this_write; |
424 | this_write = min(write_len, max_write); | 424 | this_write = min(write_len, max_write); |
425 | ret = send_write(xprt, rqstp, | 425 | ret = send_write(xprt, rqstp, |
426 | ntohl(arg_ch->rs_handle), | 426 | arg_ch->rs_handle, |
427 | rs_offset + chunk_off, | 427 | rs_offset + chunk_off, |
428 | xdr_off, | 428 | xdr_off, |
429 | this_write, | 429 | this_write, |
@@ -457,7 +457,6 @@ static int send_reply_chunks(struct svcxprt_rdma *xprt, | |||
457 | u32 xdr_off; | 457 | u32 xdr_off; |
458 | int chunk_no; | 458 | int chunk_no; |
459 | int chunk_off; | 459 | int chunk_off; |
460 | int nchunks; | ||
461 | struct rpcrdma_segment *ch; | 460 | struct rpcrdma_segment *ch; |
462 | struct rpcrdma_write_array *arg_ary; | 461 | struct rpcrdma_write_array *arg_ary; |
463 | struct rpcrdma_write_array *res_ary; | 462 | struct rpcrdma_write_array *res_ary; |
@@ -477,27 +476,26 @@ static int send_reply_chunks(struct svcxprt_rdma *xprt, | |||
477 | max_write = xprt->sc_max_sge * PAGE_SIZE; | 476 | max_write = xprt->sc_max_sge * PAGE_SIZE; |
478 | 477 | ||
479 | /* xdr offset starts at RPC message */ | 478 | /* xdr offset starts at RPC message */ |
480 | nchunks = ntohl(arg_ary->wc_nchunks); | ||
481 | for (xdr_off = 0, chunk_no = 0; | 479 | for (xdr_off = 0, chunk_no = 0; |
482 | xfer_len && chunk_no < nchunks; | 480 | xfer_len && chunk_no < arg_ary->wc_nchunks; |
483 | chunk_no++) { | 481 | chunk_no++) { |
484 | u64 rs_offset; | 482 | u64 rs_offset; |
485 | ch = &arg_ary->wc_array[chunk_no].wc_target; | 483 | ch = &arg_ary->wc_array[chunk_no].wc_target; |
486 | write_len = min(xfer_len, htonl(ch->rs_length)); | 484 | write_len = min(xfer_len, ch->rs_length); |
487 | 485 | ||
488 | /* Prepare the reply chunk given the length actually | 486 | /* Prepare the reply chunk given the length actually |
489 | * written */ | 487 | * written */ |
490 | xdr_decode_hyper((__be32 *)&ch->rs_offset, &rs_offset); | 488 | rs_offset = get_unaligned(&(ch->rs_offset)); |
491 | svc_rdma_xdr_encode_array_chunk(res_ary, chunk_no, | 489 | svc_rdma_xdr_encode_array_chunk(res_ary, chunk_no, |
492 | ch->rs_handle, ch->rs_offset, | 490 | ch->rs_handle, rs_offset, |
493 | write_len); | 491 | write_len); |
494 | chunk_off = 0; | 492 | chunk_off = 0; |
495 | while (write_len) { | 493 | while (write_len) { |
496 | int this_write; | 494 | int this_write; |
497 | 495 | ||
498 | this_write = min(write_len, max_write); | 496 | this_write = min(write_len, max_write); |
499 | ret = send_write(xprt, rqstp, | 497 | ret = send_write(xprt, rqstp, |
500 | ntohl(ch->rs_handle), | 498 | ch->rs_handle, |
501 | rs_offset + chunk_off, | 499 | rs_offset + chunk_off, |
502 | xdr_off, | 500 | xdr_off, |
503 | this_write, | 501 | this_write, |
@@ -548,7 +546,6 @@ static int send_reply(struct svcxprt_rdma *rdma, | |||
548 | int sge_no; | 546 | int sge_no; |
549 | int sge_bytes; | 547 | int sge_bytes; |
550 | int page_no; | 548 | int page_no; |
551 | int pages; | ||
552 | int ret; | 549 | int ret; |
553 | 550 | ||
554 | /* Post a recv buffer to handle another request. */ | 551 | /* Post a recv buffer to handle another request. */ |
@@ -612,8 +609,7 @@ static int send_reply(struct svcxprt_rdma *rdma, | |||
612 | * respages array. They are our pages until the I/O | 609 | * respages array. They are our pages until the I/O |
613 | * completes. | 610 | * completes. |
614 | */ | 611 | */ |
615 | pages = rqstp->rq_next_page - rqstp->rq_respages; | 612 | for (page_no = 0; page_no < rqstp->rq_resused; page_no++) { |
616 | for (page_no = 0; page_no < pages; page_no++) { | ||
617 | ctxt->pages[page_no+1] = rqstp->rq_respages[page_no]; | 613 | ctxt->pages[page_no+1] = rqstp->rq_respages[page_no]; |
618 | ctxt->count++; | 614 | ctxt->count++; |
619 | rqstp->rq_respages[page_no] = NULL; | 615 | rqstp->rq_respages[page_no] = NULL; |
diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c index 62e4f9bcc38..a385430c722 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_transport.c +++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c | |||
@@ -50,8 +50,6 @@ | |||
50 | #include <rdma/ib_verbs.h> | 50 | #include <rdma/ib_verbs.h> |
51 | #include <rdma/rdma_cm.h> | 51 | #include <rdma/rdma_cm.h> |
52 | #include <linux/sunrpc/svc_rdma.h> | 52 | #include <linux/sunrpc/svc_rdma.h> |
53 | #include <linux/export.h> | ||
54 | #include "xprt_rdma.h" | ||
55 | 53 | ||
56 | #define RPCDBG_FACILITY RPCDBG_SVCXPRT | 54 | #define RPCDBG_FACILITY RPCDBG_SVCXPRT |
57 | 55 | ||
@@ -91,6 +89,12 @@ struct svc_xprt_class svc_rdma_class = { | |||
91 | .xcl_max_payload = RPCSVC_MAXPAYLOAD_TCP, | 89 | .xcl_max_payload = RPCSVC_MAXPAYLOAD_TCP, |
92 | }; | 90 | }; |
93 | 91 | ||
92 | /* WR context cache. Created in svc_rdma.c */ | ||
93 | extern struct kmem_cache *svc_rdma_ctxt_cachep; | ||
94 | |||
95 | /* Workqueue created in svc_rdma.c */ | ||
96 | extern struct workqueue_struct *svc_rdma_wq; | ||
97 | |||
94 | struct svc_rdma_op_ctxt *svc_rdma_get_context(struct svcxprt_rdma *xprt) | 98 | struct svc_rdma_op_ctxt *svc_rdma_get_context(struct svcxprt_rdma *xprt) |
95 | { | 99 | { |
96 | struct svc_rdma_op_ctxt *ctxt; | 100 | struct svc_rdma_op_ctxt *ctxt; |
@@ -145,6 +149,9 @@ void svc_rdma_put_context(struct svc_rdma_op_ctxt *ctxt, int free_pages) | |||
145 | atomic_dec(&xprt->sc_ctxt_used); | 149 | atomic_dec(&xprt->sc_ctxt_used); |
146 | } | 150 | } |
147 | 151 | ||
152 | /* Temporary NFS request map cache. Created in svc_rdma.c */ | ||
153 | extern struct kmem_cache *svc_rdma_map_cachep; | ||
154 | |||
148 | /* | 155 | /* |
149 | * Temporary NFS req mappings are shared across all transport | 156 | * Temporary NFS req mappings are shared across all transport |
150 | * instances. These are short lived and should be bounded by the number | 157 | * instances. These are short lived and should be bounded by the number |
@@ -445,7 +452,7 @@ static struct svcxprt_rdma *rdma_create_xprt(struct svc_serv *serv, | |||
445 | 452 | ||
446 | if (!cma_xprt) | 453 | if (!cma_xprt) |
447 | return NULL; | 454 | return NULL; |
448 | svc_xprt_init(&init_net, &svc_rdma_class, &cma_xprt->sc_xprt, serv); | 455 | svc_xprt_init(&svc_rdma_class, &cma_xprt->sc_xprt, serv); |
449 | INIT_LIST_HEAD(&cma_xprt->sc_accept_q); | 456 | INIT_LIST_HEAD(&cma_xprt->sc_accept_q); |
450 | INIT_LIST_HEAD(&cma_xprt->sc_dto_q); | 457 | INIT_LIST_HEAD(&cma_xprt->sc_dto_q); |
451 | INIT_LIST_HEAD(&cma_xprt->sc_rq_dto_q); | 458 | INIT_LIST_HEAD(&cma_xprt->sc_rq_dto_q); |
@@ -578,6 +585,10 @@ static void handle_connect_req(struct rdma_cm_id *new_cma_id, size_t client_ird) | |||
578 | list_add_tail(&newxprt->sc_accept_q, &listen_xprt->sc_accept_q); | 585 | list_add_tail(&newxprt->sc_accept_q, &listen_xprt->sc_accept_q); |
579 | spin_unlock_bh(&listen_xprt->sc_lock); | 586 | spin_unlock_bh(&listen_xprt->sc_lock); |
580 | 587 | ||
588 | /* | ||
589 | * Can't use svc_xprt_received here because we are not on a | ||
590 | * rqstp thread | ||
591 | */ | ||
581 | set_bit(XPT_CONN, &listen_xprt->sc_xprt.xpt_flags); | 592 | set_bit(XPT_CONN, &listen_xprt->sc_xprt.xpt_flags); |
582 | svc_xprt_enqueue(&listen_xprt->sc_xprt); | 593 | svc_xprt_enqueue(&listen_xprt->sc_xprt); |
583 | } | 594 | } |
diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c index c9aa7a35f3b..b446e100286 100644 --- a/net/sunrpc/xprtrdma/transport.c +++ b/net/sunrpc/xprtrdma/transport.c | |||
@@ -199,18 +199,23 @@ xprt_rdma_connect_worker(struct work_struct *work) | |||
199 | struct rpc_xprt *xprt = &r_xprt->xprt; | 199 | struct rpc_xprt *xprt = &r_xprt->xprt; |
200 | int rc = 0; | 200 | int rc = 0; |
201 | 201 | ||
202 | current->flags |= PF_FSTRANS; | 202 | if (!xprt->shutdown) { |
203 | xprt_clear_connected(xprt); | 203 | xprt_clear_connected(xprt); |
204 | 204 | ||
205 | dprintk("RPC: %s: %sconnect\n", __func__, | 205 | dprintk("RPC: %s: %sconnect\n", __func__, |
206 | r_xprt->rx_ep.rep_connected != 0 ? "re" : ""); | 206 | r_xprt->rx_ep.rep_connected != 0 ? "re" : ""); |
207 | rc = rpcrdma_ep_connect(&r_xprt->rx_ep, &r_xprt->rx_ia); | 207 | rc = rpcrdma_ep_connect(&r_xprt->rx_ep, &r_xprt->rx_ia); |
208 | if (rc) | 208 | if (rc) |
209 | xprt_wake_pending_tasks(xprt, rc); | 209 | goto out; |
210 | } | ||
211 | goto out_clear; | ||
212 | |||
213 | out: | ||
214 | xprt_wake_pending_tasks(xprt, rc); | ||
210 | 215 | ||
216 | out_clear: | ||
211 | dprintk("RPC: %s: exit\n", __func__); | 217 | dprintk("RPC: %s: exit\n", __func__); |
212 | xprt_clear_connecting(xprt); | 218 | xprt_clear_connecting(xprt); |
213 | current->flags &= ~PF_FSTRANS; | ||
214 | } | 219 | } |
215 | 220 | ||
216 | /* | 221 | /* |
@@ -707,7 +712,6 @@ static void xprt_rdma_print_stats(struct rpc_xprt *xprt, struct seq_file *seq) | |||
707 | static struct rpc_xprt_ops xprt_rdma_procs = { | 712 | static struct rpc_xprt_ops xprt_rdma_procs = { |
708 | .reserve_xprt = xprt_rdma_reserve_xprt, | 713 | .reserve_xprt = xprt_rdma_reserve_xprt, |
709 | .release_xprt = xprt_release_xprt_cong, /* sunrpc/xprt.c */ | 714 | .release_xprt = xprt_release_xprt_cong, /* sunrpc/xprt.c */ |
710 | .alloc_slot = xprt_alloc_slot, | ||
711 | .release_request = xprt_release_rqst_cong, /* ditto */ | 715 | .release_request = xprt_release_rqst_cong, /* ditto */ |
712 | .set_retrans_timeout = xprt_set_retrans_timeout_def, /* ditto */ | 716 | .set_retrans_timeout = xprt_set_retrans_timeout_def, /* ditto */ |
713 | .rpcbind = rpcb_getport_async, /* sunrpc/rpcb_clnt.c */ | 717 | .rpcbind = rpcb_getport_async, /* sunrpc/rpcb_clnt.c */ |
diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c index 745973b729a..28236bab57f 100644 --- a/net/sunrpc/xprtrdma/verbs.c +++ b/net/sunrpc/xprtrdma/verbs.c | |||
@@ -1490,9 +1490,6 @@ rpcrdma_register_frmr_external(struct rpcrdma_mr_seg *seg, | |||
1490 | u8 key; | 1490 | u8 key; |
1491 | int len, pageoff; | 1491 | int len, pageoff; |
1492 | int i, rc; | 1492 | int i, rc; |
1493 | int seg_len; | ||
1494 | u64 pa; | ||
1495 | int page_no; | ||
1496 | 1493 | ||
1497 | pageoff = offset_in_page(seg1->mr_offset); | 1494 | pageoff = offset_in_page(seg1->mr_offset); |
1498 | seg1->mr_offset -= pageoff; /* start of page */ | 1495 | seg1->mr_offset -= pageoff; /* start of page */ |
@@ -1500,15 +1497,11 @@ rpcrdma_register_frmr_external(struct rpcrdma_mr_seg *seg, | |||
1500 | len = -pageoff; | 1497 | len = -pageoff; |
1501 | if (*nsegs > RPCRDMA_MAX_DATA_SEGS) | 1498 | if (*nsegs > RPCRDMA_MAX_DATA_SEGS) |
1502 | *nsegs = RPCRDMA_MAX_DATA_SEGS; | 1499 | *nsegs = RPCRDMA_MAX_DATA_SEGS; |
1503 | for (page_no = i = 0; i < *nsegs;) { | 1500 | for (i = 0; i < *nsegs;) { |
1504 | rpcrdma_map_one(ia, seg, writing); | 1501 | rpcrdma_map_one(ia, seg, writing); |
1505 | pa = seg->mr_dma; | 1502 | seg1->mr_chunk.rl_mw->r.frmr.fr_pgl->page_list[i] = seg->mr_dma; |
1506 | for (seg_len = seg->mr_len; seg_len > 0; seg_len -= PAGE_SIZE) { | ||
1507 | seg1->mr_chunk.rl_mw->r.frmr.fr_pgl-> | ||
1508 | page_list[page_no++] = pa; | ||
1509 | pa += PAGE_SIZE; | ||
1510 | } | ||
1511 | len += seg->mr_len; | 1503 | len += seg->mr_len; |
1504 | BUG_ON(seg->mr_len > PAGE_SIZE); | ||
1512 | ++seg; | 1505 | ++seg; |
1513 | ++i; | 1506 | ++i; |
1514 | /* Check for holes */ | 1507 | /* Check for holes */ |
@@ -1547,9 +1540,9 @@ rpcrdma_register_frmr_external(struct rpcrdma_mr_seg *seg, | |||
1547 | frmr_wr.send_flags = IB_SEND_SIGNALED; | 1540 | frmr_wr.send_flags = IB_SEND_SIGNALED; |
1548 | frmr_wr.wr.fast_reg.iova_start = seg1->mr_dma; | 1541 | frmr_wr.wr.fast_reg.iova_start = seg1->mr_dma; |
1549 | frmr_wr.wr.fast_reg.page_list = seg1->mr_chunk.rl_mw->r.frmr.fr_pgl; | 1542 | frmr_wr.wr.fast_reg.page_list = seg1->mr_chunk.rl_mw->r.frmr.fr_pgl; |
1550 | frmr_wr.wr.fast_reg.page_list_len = page_no; | 1543 | frmr_wr.wr.fast_reg.page_list_len = i; |
1551 | frmr_wr.wr.fast_reg.page_shift = PAGE_SHIFT; | 1544 | frmr_wr.wr.fast_reg.page_shift = PAGE_SHIFT; |
1552 | frmr_wr.wr.fast_reg.length = page_no << PAGE_SHIFT; | 1545 | frmr_wr.wr.fast_reg.length = i << PAGE_SHIFT; |
1553 | BUG_ON(frmr_wr.wr.fast_reg.length < len); | 1546 | BUG_ON(frmr_wr.wr.fast_reg.length < len); |
1554 | frmr_wr.wr.fast_reg.access_flags = (writing ? | 1547 | frmr_wr.wr.fast_reg.access_flags = (writing ? |
1555 | IB_ACCESS_REMOTE_WRITE | IB_ACCESS_LOCAL_WRITE : | 1548 | IB_ACCESS_REMOTE_WRITE | IB_ACCESS_LOCAL_WRITE : |
diff --git a/net/sunrpc/xprtrdma/xprt_rdma.h b/net/sunrpc/xprtrdma/xprt_rdma.h index 9a66c95b583..08c5d5a128f 100644 --- a/net/sunrpc/xprtrdma/xprt_rdma.h +++ b/net/sunrpc/xprtrdma/xprt_rdma.h | |||
@@ -343,11 +343,4 @@ void rpcrdma_reply_handler(struct rpcrdma_rep *); | |||
343 | */ | 343 | */ |
344 | int rpcrdma_marshal_req(struct rpc_rqst *); | 344 | int rpcrdma_marshal_req(struct rpc_rqst *); |
345 | 345 | ||
346 | /* Temporary NFS request map cache. Created in svc_rdma.c */ | ||
347 | extern struct kmem_cache *svc_rdma_map_cachep; | ||
348 | /* WR context cache. Created in svc_rdma.c */ | ||
349 | extern struct kmem_cache *svc_rdma_ctxt_cachep; | ||
350 | /* Workqueue created in svc_rdma.c */ | ||
351 | extern struct workqueue_struct *svc_rdma_wq; | ||
352 | |||
353 | #endif /* _LINUX_SUNRPC_XPRT_RDMA_H */ | 346 | #endif /* _LINUX_SUNRPC_XPRT_RDMA_H */ |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 68b0a81c31d..b60b75082f3 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -53,12 +53,12 @@ static void xs_close(struct rpc_xprt *xprt); | |||
53 | /* | 53 | /* |
54 | * xprtsock tunables | 54 | * xprtsock tunables |
55 | */ | 55 | */ |
56 | static unsigned int xprt_udp_slot_table_entries = RPC_DEF_SLOT_TABLE; | 56 | unsigned int xprt_udp_slot_table_entries = RPC_DEF_SLOT_TABLE; |
57 | static unsigned int xprt_tcp_slot_table_entries = RPC_MIN_SLOT_TABLE; | 57 | unsigned int xprt_tcp_slot_table_entries = RPC_MIN_SLOT_TABLE; |
58 | static unsigned int xprt_max_tcp_slot_table_entries = RPC_MAX_SLOT_TABLE; | 58 | unsigned int xprt_max_tcp_slot_table_entries = RPC_MAX_SLOT_TABLE; |
59 | 59 | ||
60 | static unsigned int xprt_min_resvport = RPC_DEF_MIN_RESVPORT; | 60 | unsigned int xprt_min_resvport = RPC_DEF_MIN_RESVPORT; |
61 | static unsigned int xprt_max_resvport = RPC_DEF_MAX_RESVPORT; | 61 | unsigned int xprt_max_resvport = RPC_DEF_MAX_RESVPORT; |
62 | 62 | ||
63 | #define XS_TCP_LINGER_TO (15U * HZ) | 63 | #define XS_TCP_LINGER_TO (15U * HZ) |
64 | static unsigned int xs_tcp_fin_timeout __read_mostly = XS_TCP_LINGER_TO; | 64 | static unsigned int xs_tcp_fin_timeout __read_mostly = XS_TCP_LINGER_TO; |
@@ -254,6 +254,7 @@ struct sock_xprt { | |||
254 | void (*old_data_ready)(struct sock *, int); | 254 | void (*old_data_ready)(struct sock *, int); |
255 | void (*old_state_change)(struct sock *); | 255 | void (*old_state_change)(struct sock *); |
256 | void (*old_write_space)(struct sock *); | 256 | void (*old_write_space)(struct sock *); |
257 | void (*old_error_report)(struct sock *); | ||
257 | }; | 258 | }; |
258 | 259 | ||
259 | /* | 260 | /* |
@@ -736,10 +737,10 @@ static int xs_tcp_send_request(struct rpc_task *task) | |||
736 | dprintk("RPC: sendmsg returned unrecognized error %d\n", | 737 | dprintk("RPC: sendmsg returned unrecognized error %d\n", |
737 | -status); | 738 | -status); |
738 | case -ECONNRESET: | 739 | case -ECONNRESET: |
740 | case -EPIPE: | ||
739 | xs_tcp_shutdown(xprt); | 741 | xs_tcp_shutdown(xprt); |
740 | case -ECONNREFUSED: | 742 | case -ECONNREFUSED: |
741 | case -ENOTCONN: | 743 | case -ENOTCONN: |
742 | case -EPIPE: | ||
743 | clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags); | 744 | clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags); |
744 | } | 745 | } |
745 | 746 | ||
@@ -780,6 +781,7 @@ static void xs_save_old_callbacks(struct sock_xprt *transport, struct sock *sk) | |||
780 | transport->old_data_ready = sk->sk_data_ready; | 781 | transport->old_data_ready = sk->sk_data_ready; |
781 | transport->old_state_change = sk->sk_state_change; | 782 | transport->old_state_change = sk->sk_state_change; |
782 | transport->old_write_space = sk->sk_write_space; | 783 | transport->old_write_space = sk->sk_write_space; |
784 | transport->old_error_report = sk->sk_error_report; | ||
783 | } | 785 | } |
784 | 786 | ||
785 | static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *sk) | 787 | static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *sk) |
@@ -787,6 +789,7 @@ static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *s | |||
787 | sk->sk_data_ready = transport->old_data_ready; | 789 | sk->sk_data_ready = transport->old_data_ready; |
788 | sk->sk_state_change = transport->old_state_change; | 790 | sk->sk_state_change = transport->old_state_change; |
789 | sk->sk_write_space = transport->old_write_space; | 791 | sk->sk_write_space = transport->old_write_space; |
792 | sk->sk_error_report = transport->old_error_report; | ||
790 | } | 793 | } |
791 | 794 | ||
792 | static void xs_reset_transport(struct sock_xprt *transport) | 795 | static void xs_reset_transport(struct sock_xprt *transport) |
@@ -914,6 +917,9 @@ static void xs_local_data_ready(struct sock *sk, int len) | |||
914 | if (skb == NULL) | 917 | if (skb == NULL) |
915 | goto out; | 918 | goto out; |
916 | 919 | ||
920 | if (xprt->shutdown) | ||
921 | goto dropit; | ||
922 | |||
917 | repsize = skb->len - sizeof(rpc_fraghdr); | 923 | repsize = skb->len - sizeof(rpc_fraghdr); |
918 | if (repsize < 4) { | 924 | if (repsize < 4) { |
919 | dprintk("RPC: impossible RPC reply size %d\n", repsize); | 925 | dprintk("RPC: impossible RPC reply size %d\n", repsize); |
@@ -975,6 +981,9 @@ static void xs_udp_data_ready(struct sock *sk, int len) | |||
975 | if ((skb = skb_recv_datagram(sk, 0, 1, &err)) == NULL) | 981 | if ((skb = skb_recv_datagram(sk, 0, 1, &err)) == NULL) |
976 | goto out; | 982 | goto out; |
977 | 983 | ||
984 | if (xprt->shutdown) | ||
985 | goto dropit; | ||
986 | |||
978 | repsize = skb->len - sizeof(struct udphdr); | 987 | repsize = skb->len - sizeof(struct udphdr); |
979 | if (repsize < 4) { | 988 | if (repsize < 4) { |
980 | dprintk("RPC: impossible RPC reply size %d!\n", repsize); | 989 | dprintk("RPC: impossible RPC reply size %d!\n", repsize); |
@@ -1005,6 +1014,9 @@ static void xs_udp_data_ready(struct sock *sk, int len) | |||
1005 | 1014 | ||
1006 | UDPX_INC_STATS_BH(sk, UDP_MIB_INDATAGRAMS); | 1015 | UDPX_INC_STATS_BH(sk, UDP_MIB_INDATAGRAMS); |
1007 | 1016 | ||
1017 | /* Something worked... */ | ||
1018 | dst_confirm(skb_dst(skb)); | ||
1019 | |||
1008 | xprt_adjust_cwnd(task, copied); | 1020 | xprt_adjust_cwnd(task, copied); |
1009 | xprt_complete_rqst(task, copied); | 1021 | xprt_complete_rqst(task, copied); |
1010 | 1022 | ||
@@ -1016,16 +1028,6 @@ static void xs_udp_data_ready(struct sock *sk, int len) | |||
1016 | read_unlock_bh(&sk->sk_callback_lock); | 1028 | read_unlock_bh(&sk->sk_callback_lock); |
1017 | } | 1029 | } |
1018 | 1030 | ||
1019 | /* | ||
1020 | * Helper function to force a TCP close if the server is sending | ||
1021 | * junk and/or it has put us in CLOSE_WAIT | ||
1022 | */ | ||
1023 | static void xs_tcp_force_close(struct rpc_xprt *xprt) | ||
1024 | { | ||
1025 | set_bit(XPRT_CONNECTION_CLOSE, &xprt->state); | ||
1026 | xprt_force_disconnect(xprt); | ||
1027 | } | ||
1028 | |||
1029 | static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, struct xdr_skb_reader *desc) | 1031 | static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, struct xdr_skb_reader *desc) |
1030 | { | 1032 | { |
1031 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); | 1033 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); |
@@ -1052,7 +1054,7 @@ static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, struct xdr_skb_rea | |||
1052 | /* Sanity check of the record length */ | 1054 | /* Sanity check of the record length */ |
1053 | if (unlikely(transport->tcp_reclen < 8)) { | 1055 | if (unlikely(transport->tcp_reclen < 8)) { |
1054 | dprintk("RPC: invalid TCP record fragment length\n"); | 1056 | dprintk("RPC: invalid TCP record fragment length\n"); |
1055 | xs_tcp_force_close(xprt); | 1057 | xprt_force_disconnect(xprt); |
1056 | return; | 1058 | return; |
1057 | } | 1059 | } |
1058 | dprintk("RPC: reading TCP record fragment of length %d\n", | 1060 | dprintk("RPC: reading TCP record fragment of length %d\n", |
@@ -1133,7 +1135,7 @@ static inline void xs_tcp_read_calldir(struct sock_xprt *transport, | |||
1133 | break; | 1135 | break; |
1134 | default: | 1136 | default: |
1135 | dprintk("RPC: invalid request message type\n"); | 1137 | dprintk("RPC: invalid request message type\n"); |
1136 | xs_tcp_force_close(&transport->xprt); | 1138 | xprt_force_disconnect(&transport->xprt); |
1137 | } | 1139 | } |
1138 | xs_tcp_check_fraghdr(transport); | 1140 | xs_tcp_check_fraghdr(transport); |
1139 | } | 1141 | } |
@@ -1403,6 +1405,9 @@ static void xs_tcp_data_ready(struct sock *sk, int bytes) | |||
1403 | read_lock_bh(&sk->sk_callback_lock); | 1405 | read_lock_bh(&sk->sk_callback_lock); |
1404 | if (!(xprt = xprt_from_sock(sk))) | 1406 | if (!(xprt = xprt_from_sock(sk))) |
1405 | goto out; | 1407 | goto out; |
1408 | if (xprt->shutdown) | ||
1409 | goto out; | ||
1410 | |||
1406 | /* Any data means we had a useful conversation, so | 1411 | /* Any data means we had a useful conversation, so |
1407 | * the we don't need to delay the next reconnect | 1412 | * the we don't need to delay the next reconnect |
1408 | */ | 1413 | */ |
@@ -1450,19 +1455,12 @@ static void xs_tcp_cancel_linger_timeout(struct rpc_xprt *xprt) | |||
1450 | xprt_clear_connecting(xprt); | 1455 | xprt_clear_connecting(xprt); |
1451 | } | 1456 | } |
1452 | 1457 | ||
1453 | static void xs_sock_reset_connection_flags(struct rpc_xprt *xprt) | 1458 | static void xs_sock_mark_closed(struct rpc_xprt *xprt) |
1454 | { | 1459 | { |
1455 | smp_mb__before_clear_bit(); | 1460 | smp_mb__before_clear_bit(); |
1456 | clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); | ||
1457 | clear_bit(XPRT_CONNECTION_CLOSE, &xprt->state); | ||
1458 | clear_bit(XPRT_CLOSE_WAIT, &xprt->state); | 1461 | clear_bit(XPRT_CLOSE_WAIT, &xprt->state); |
1459 | clear_bit(XPRT_CLOSING, &xprt->state); | 1462 | clear_bit(XPRT_CLOSING, &xprt->state); |
1460 | smp_mb__after_clear_bit(); | 1463 | smp_mb__after_clear_bit(); |
1461 | } | ||
1462 | |||
1463 | static void xs_sock_mark_closed(struct rpc_xprt *xprt) | ||
1464 | { | ||
1465 | xs_sock_reset_connection_flags(xprt); | ||
1466 | /* Mark transport as closed and wake up all pending tasks */ | 1464 | /* Mark transport as closed and wake up all pending tasks */ |
1467 | xprt_disconnect_done(xprt); | 1465 | xprt_disconnect_done(xprt); |
1468 | } | 1466 | } |
@@ -1517,9 +1515,8 @@ static void xs_tcp_state_change(struct sock *sk) | |||
1517 | break; | 1515 | break; |
1518 | case TCP_CLOSE_WAIT: | 1516 | case TCP_CLOSE_WAIT: |
1519 | /* The server initiated a shutdown of the socket */ | 1517 | /* The server initiated a shutdown of the socket */ |
1518 | xprt_force_disconnect(xprt); | ||
1520 | xprt->connect_cookie++; | 1519 | xprt->connect_cookie++; |
1521 | clear_bit(XPRT_CONNECTED, &xprt->state); | ||
1522 | xs_tcp_force_close(xprt); | ||
1523 | case TCP_CLOSING: | 1520 | case TCP_CLOSING: |
1524 | /* | 1521 | /* |
1525 | * If the server closed down the connection, make sure that | 1522 | * If the server closed down the connection, make sure that |
@@ -1543,6 +1540,25 @@ static void xs_tcp_state_change(struct sock *sk) | |||
1543 | read_unlock_bh(&sk->sk_callback_lock); | 1540 | read_unlock_bh(&sk->sk_callback_lock); |
1544 | } | 1541 | } |
1545 | 1542 | ||
1543 | /** | ||
1544 | * xs_error_report - callback mainly for catching socket errors | ||
1545 | * @sk: socket | ||
1546 | */ | ||
1547 | static void xs_error_report(struct sock *sk) | ||
1548 | { | ||
1549 | struct rpc_xprt *xprt; | ||
1550 | |||
1551 | read_lock_bh(&sk->sk_callback_lock); | ||
1552 | if (!(xprt = xprt_from_sock(sk))) | ||
1553 | goto out; | ||
1554 | dprintk("RPC: %s client %p...\n" | ||
1555 | "RPC: error %d\n", | ||
1556 | __func__, xprt, sk->sk_err); | ||
1557 | xprt_wake_pending_tasks(xprt, -EAGAIN); | ||
1558 | out: | ||
1559 | read_unlock_bh(&sk->sk_callback_lock); | ||
1560 | } | ||
1561 | |||
1546 | static void xs_write_space(struct sock *sk) | 1562 | static void xs_write_space(struct sock *sk) |
1547 | { | 1563 | { |
1548 | struct socket *sock; | 1564 | struct socket *sock; |
@@ -1746,6 +1762,7 @@ static inline void xs_reclassify_socketu(struct socket *sock) | |||
1746 | { | 1762 | { |
1747 | struct sock *sk = sock->sk; | 1763 | struct sock *sk = sock->sk; |
1748 | 1764 | ||
1765 | BUG_ON(sock_owned_by_user(sk)); | ||
1749 | sock_lock_init_class_and_name(sk, "slock-AF_LOCAL-RPC", | 1766 | sock_lock_init_class_and_name(sk, "slock-AF_LOCAL-RPC", |
1750 | &xs_slock_key[1], "sk_lock-AF_LOCAL-RPC", &xs_key[1]); | 1767 | &xs_slock_key[1], "sk_lock-AF_LOCAL-RPC", &xs_key[1]); |
1751 | } | 1768 | } |
@@ -1754,6 +1771,7 @@ static inline void xs_reclassify_socket4(struct socket *sock) | |||
1754 | { | 1771 | { |
1755 | struct sock *sk = sock->sk; | 1772 | struct sock *sk = sock->sk; |
1756 | 1773 | ||
1774 | BUG_ON(sock_owned_by_user(sk)); | ||
1757 | sock_lock_init_class_and_name(sk, "slock-AF_INET-RPC", | 1775 | sock_lock_init_class_and_name(sk, "slock-AF_INET-RPC", |
1758 | &xs_slock_key[0], "sk_lock-AF_INET-RPC", &xs_key[0]); | 1776 | &xs_slock_key[0], "sk_lock-AF_INET-RPC", &xs_key[0]); |
1759 | } | 1777 | } |
@@ -1762,16 +1780,13 @@ static inline void xs_reclassify_socket6(struct socket *sock) | |||
1762 | { | 1780 | { |
1763 | struct sock *sk = sock->sk; | 1781 | struct sock *sk = sock->sk; |
1764 | 1782 | ||
1783 | BUG_ON(sock_owned_by_user(sk)); | ||
1765 | sock_lock_init_class_and_name(sk, "slock-AF_INET6-RPC", | 1784 | sock_lock_init_class_and_name(sk, "slock-AF_INET6-RPC", |
1766 | &xs_slock_key[1], "sk_lock-AF_INET6-RPC", &xs_key[1]); | 1785 | &xs_slock_key[1], "sk_lock-AF_INET6-RPC", &xs_key[1]); |
1767 | } | 1786 | } |
1768 | 1787 | ||
1769 | static inline void xs_reclassify_socket(int family, struct socket *sock) | 1788 | static inline void xs_reclassify_socket(int family, struct socket *sock) |
1770 | { | 1789 | { |
1771 | WARN_ON_ONCE(sock_owned_by_user(sock->sk)); | ||
1772 | if (sock_owned_by_user(sock->sk)) | ||
1773 | return; | ||
1774 | |||
1775 | switch (family) { | 1790 | switch (family) { |
1776 | case AF_LOCAL: | 1791 | case AF_LOCAL: |
1777 | xs_reclassify_socketu(sock); | 1792 | xs_reclassify_socketu(sock); |
@@ -1843,6 +1858,7 @@ static int xs_local_finish_connecting(struct rpc_xprt *xprt, | |||
1843 | sk->sk_user_data = xprt; | 1858 | sk->sk_user_data = xprt; |
1844 | sk->sk_data_ready = xs_local_data_ready; | 1859 | sk->sk_data_ready = xs_local_data_ready; |
1845 | sk->sk_write_space = xs_udp_write_space; | 1860 | sk->sk_write_space = xs_udp_write_space; |
1861 | sk->sk_error_report = xs_error_report; | ||
1846 | sk->sk_allocation = GFP_ATOMIC; | 1862 | sk->sk_allocation = GFP_ATOMIC; |
1847 | 1863 | ||
1848 | xprt_clear_connected(xprt); | 1864 | xprt_clear_connected(xprt); |
@@ -1876,7 +1892,8 @@ static void xs_local_setup_socket(struct work_struct *work) | |||
1876 | struct socket *sock; | 1892 | struct socket *sock; |
1877 | int status = -EIO; | 1893 | int status = -EIO; |
1878 | 1894 | ||
1879 | current->flags |= PF_FSTRANS; | 1895 | if (xprt->shutdown) |
1896 | goto out; | ||
1880 | 1897 | ||
1881 | clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); | 1898 | clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); |
1882 | status = __sock_create(xprt->xprt_net, AF_LOCAL, | 1899 | status = __sock_create(xprt->xprt_net, AF_LOCAL, |
@@ -1902,10 +1919,6 @@ static void xs_local_setup_socket(struct work_struct *work) | |||
1902 | dprintk("RPC: xprt %p: socket %s does not exist\n", | 1919 | dprintk("RPC: xprt %p: socket %s does not exist\n", |
1903 | xprt, xprt->address_strings[RPC_DISPLAY_ADDR]); | 1920 | xprt, xprt->address_strings[RPC_DISPLAY_ADDR]); |
1904 | break; | 1921 | break; |
1905 | case -ECONNREFUSED: | ||
1906 | dprintk("RPC: xprt %p: connection refused for %s\n", | ||
1907 | xprt, xprt->address_strings[RPC_DISPLAY_ADDR]); | ||
1908 | break; | ||
1909 | default: | 1922 | default: |
1910 | printk(KERN_ERR "%s: unhandled error (%d) connecting to %s\n", | 1923 | printk(KERN_ERR "%s: unhandled error (%d) connecting to %s\n", |
1911 | __func__, -status, | 1924 | __func__, -status, |
@@ -1915,48 +1928,8 @@ static void xs_local_setup_socket(struct work_struct *work) | |||
1915 | out: | 1928 | out: |
1916 | xprt_clear_connecting(xprt); | 1929 | xprt_clear_connecting(xprt); |
1917 | xprt_wake_pending_tasks(xprt, status); | 1930 | xprt_wake_pending_tasks(xprt, status); |
1918 | current->flags &= ~PF_FSTRANS; | ||
1919 | } | ||
1920 | |||
1921 | #ifdef CONFIG_SUNRPC_SWAP | ||
1922 | static void xs_set_memalloc(struct rpc_xprt *xprt) | ||
1923 | { | ||
1924 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, | ||
1925 | xprt); | ||
1926 | |||
1927 | if (xprt->swapper) | ||
1928 | sk_set_memalloc(transport->inet); | ||
1929 | } | 1931 | } |
1930 | 1932 | ||
1931 | /** | ||
1932 | * xs_swapper - Tag this transport as being used for swap. | ||
1933 | * @xprt: transport to tag | ||
1934 | * @enable: enable/disable | ||
1935 | * | ||
1936 | */ | ||
1937 | int xs_swapper(struct rpc_xprt *xprt, int enable) | ||
1938 | { | ||
1939 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, | ||
1940 | xprt); | ||
1941 | int err = 0; | ||
1942 | |||
1943 | if (enable) { | ||
1944 | xprt->swapper++; | ||
1945 | xs_set_memalloc(xprt); | ||
1946 | } else if (xprt->swapper) { | ||
1947 | xprt->swapper--; | ||
1948 | sk_clear_memalloc(transport->inet); | ||
1949 | } | ||
1950 | |||
1951 | return err; | ||
1952 | } | ||
1953 | EXPORT_SYMBOL_GPL(xs_swapper); | ||
1954 | #else | ||
1955 | static void xs_set_memalloc(struct rpc_xprt *xprt) | ||
1956 | { | ||
1957 | } | ||
1958 | #endif | ||
1959 | |||
1960 | static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) | 1933 | static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) |
1961 | { | 1934 | { |
1962 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); | 1935 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); |
@@ -1971,6 +1944,7 @@ static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) | |||
1971 | sk->sk_user_data = xprt; | 1944 | sk->sk_user_data = xprt; |
1972 | sk->sk_data_ready = xs_udp_data_ready; | 1945 | sk->sk_data_ready = xs_udp_data_ready; |
1973 | sk->sk_write_space = xs_udp_write_space; | 1946 | sk->sk_write_space = xs_udp_write_space; |
1947 | sk->sk_error_report = xs_error_report; | ||
1974 | sk->sk_no_check = UDP_CSUM_NORCV; | 1948 | sk->sk_no_check = UDP_CSUM_NORCV; |
1975 | sk->sk_allocation = GFP_ATOMIC; | 1949 | sk->sk_allocation = GFP_ATOMIC; |
1976 | 1950 | ||
@@ -1980,8 +1954,6 @@ static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) | |||
1980 | transport->sock = sock; | 1954 | transport->sock = sock; |
1981 | transport->inet = sk; | 1955 | transport->inet = sk; |
1982 | 1956 | ||
1983 | xs_set_memalloc(xprt); | ||
1984 | |||
1985 | write_unlock_bh(&sk->sk_callback_lock); | 1957 | write_unlock_bh(&sk->sk_callback_lock); |
1986 | } | 1958 | } |
1987 | xs_udp_do_set_buffer_size(xprt); | 1959 | xs_udp_do_set_buffer_size(xprt); |
@@ -1995,7 +1967,8 @@ static void xs_udp_setup_socket(struct work_struct *work) | |||
1995 | struct socket *sock = transport->sock; | 1967 | struct socket *sock = transport->sock; |
1996 | int status = -EIO; | 1968 | int status = -EIO; |
1997 | 1969 | ||
1998 | current->flags |= PF_FSTRANS; | 1970 | if (xprt->shutdown) |
1971 | goto out; | ||
1999 | 1972 | ||
2000 | /* Start by resetting any existing state */ | 1973 | /* Start by resetting any existing state */ |
2001 | xs_reset_transport(transport); | 1974 | xs_reset_transport(transport); |
@@ -2015,7 +1988,6 @@ static void xs_udp_setup_socket(struct work_struct *work) | |||
2015 | out: | 1988 | out: |
2016 | xprt_clear_connecting(xprt); | 1989 | xprt_clear_connecting(xprt); |
2017 | xprt_wake_pending_tasks(xprt, status); | 1990 | xprt_wake_pending_tasks(xprt, status); |
2018 | current->flags &= ~PF_FSTRANS; | ||
2019 | } | 1991 | } |
2020 | 1992 | ||
2021 | /* | 1993 | /* |
@@ -2037,8 +2009,10 @@ static void xs_abort_connection(struct sock_xprt *transport) | |||
2037 | any.sa_family = AF_UNSPEC; | 2009 | any.sa_family = AF_UNSPEC; |
2038 | result = kernel_connect(transport->sock, &any, sizeof(any), 0); | 2010 | result = kernel_connect(transport->sock, &any, sizeof(any), 0); |
2039 | if (!result) | 2011 | if (!result) |
2040 | xs_sock_reset_connection_flags(&transport->xprt); | 2012 | xs_sock_mark_closed(&transport->xprt); |
2041 | dprintk("RPC: AF_UNSPEC connect return code %d\n", result); | 2013 | else |
2014 | dprintk("RPC: AF_UNSPEC connect return code %d\n", | ||
2015 | result); | ||
2042 | } | 2016 | } |
2043 | 2017 | ||
2044 | static void xs_tcp_reuse_connection(struct sock_xprt *transport) | 2018 | static void xs_tcp_reuse_connection(struct sock_xprt *transport) |
@@ -2083,6 +2057,7 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) | |||
2083 | sk->sk_data_ready = xs_tcp_data_ready; | 2057 | sk->sk_data_ready = xs_tcp_data_ready; |
2084 | sk->sk_state_change = xs_tcp_state_change; | 2058 | sk->sk_state_change = xs_tcp_state_change; |
2085 | sk->sk_write_space = xs_tcp_write_space; | 2059 | sk->sk_write_space = xs_tcp_write_space; |
2060 | sk->sk_error_report = xs_error_report; | ||
2086 | sk->sk_allocation = GFP_ATOMIC; | 2061 | sk->sk_allocation = GFP_ATOMIC; |
2087 | 2062 | ||
2088 | /* socket options */ | 2063 | /* socket options */ |
@@ -2103,8 +2078,6 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) | |||
2103 | if (!xprt_bound(xprt)) | 2078 | if (!xprt_bound(xprt)) |
2104 | goto out; | 2079 | goto out; |
2105 | 2080 | ||
2106 | xs_set_memalloc(xprt); | ||
2107 | |||
2108 | /* Tell the socket layer to start connecting... */ | 2081 | /* Tell the socket layer to start connecting... */ |
2109 | xprt->stat.connect_count++; | 2082 | xprt->stat.connect_count++; |
2110 | xprt->stat.connect_start = jiffies; | 2083 | xprt->stat.connect_start = jiffies; |
@@ -2137,7 +2110,8 @@ static void xs_tcp_setup_socket(struct work_struct *work) | |||
2137 | struct rpc_xprt *xprt = &transport->xprt; | 2110 | struct rpc_xprt *xprt = &transport->xprt; |
2138 | int status = -EIO; | 2111 | int status = -EIO; |
2139 | 2112 | ||
2140 | current->flags |= PF_FSTRANS; | 2113 | if (xprt->shutdown) |
2114 | goto out; | ||
2141 | 2115 | ||
2142 | if (!sock) { | 2116 | if (!sock) { |
2143 | clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); | 2117 | clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); |
@@ -2177,7 +2151,8 @@ static void xs_tcp_setup_socket(struct work_struct *work) | |||
2177 | /* We're probably in TIME_WAIT. Get rid of existing socket, | 2151 | /* We're probably in TIME_WAIT. Get rid of existing socket, |
2178 | * and retry | 2152 | * and retry |
2179 | */ | 2153 | */ |
2180 | xs_tcp_force_close(xprt); | 2154 | set_bit(XPRT_CONNECTION_CLOSE, &xprt->state); |
2155 | xprt_force_disconnect(xprt); | ||
2181 | break; | 2156 | break; |
2182 | case -ECONNREFUSED: | 2157 | case -ECONNREFUSED: |
2183 | case -ECONNRESET: | 2158 | case -ECONNRESET: |
@@ -2187,7 +2162,6 @@ static void xs_tcp_setup_socket(struct work_struct *work) | |||
2187 | case -EINPROGRESS: | 2162 | case -EINPROGRESS: |
2188 | case -EALREADY: | 2163 | case -EALREADY: |
2189 | xprt_clear_connecting(xprt); | 2164 | xprt_clear_connecting(xprt); |
2190 | current->flags &= ~PF_FSTRANS; | ||
2191 | return; | 2165 | return; |
2192 | case -EINVAL: | 2166 | case -EINVAL: |
2193 | /* Happens, for instance, if the user specified a link | 2167 | /* Happens, for instance, if the user specified a link |
@@ -2200,7 +2174,6 @@ out_eagain: | |||
2200 | out: | 2174 | out: |
2201 | xprt_clear_connecting(xprt); | 2175 | xprt_clear_connecting(xprt); |
2202 | xprt_wake_pending_tasks(xprt, status); | 2176 | xprt_wake_pending_tasks(xprt, status); |
2203 | current->flags &= ~PF_FSTRANS; | ||
2204 | } | 2177 | } |
2205 | 2178 | ||
2206 | /** | 2179 | /** |
@@ -2254,7 +2227,7 @@ static void xs_local_print_stats(struct rpc_xprt *xprt, struct seq_file *seq) | |||
2254 | idle_time = (long)(jiffies - xprt->last_used) / HZ; | 2227 | idle_time = (long)(jiffies - xprt->last_used) / HZ; |
2255 | 2228 | ||
2256 | seq_printf(seq, "\txprt:\tlocal %lu %lu %lu %ld %lu %lu %lu " | 2229 | seq_printf(seq, "\txprt:\tlocal %lu %lu %lu %ld %lu %lu %lu " |
2257 | "%llu %llu %lu %llu %llu\n", | 2230 | "%llu %llu\n", |
2258 | xprt->stat.bind_count, | 2231 | xprt->stat.bind_count, |
2259 | xprt->stat.connect_count, | 2232 | xprt->stat.connect_count, |
2260 | xprt->stat.connect_time, | 2233 | xprt->stat.connect_time, |
@@ -2263,10 +2236,7 @@ static void xs_local_print_stats(struct rpc_xprt *xprt, struct seq_file *seq) | |||
2263 | xprt->stat.recvs, | 2236 | xprt->stat.recvs, |
2264 | xprt->stat.bad_xids, | 2237 | xprt->stat.bad_xids, |
2265 | xprt->stat.req_u, | 2238 | xprt->stat.req_u, |
2266 | xprt->stat.bklog_u, | 2239 | xprt->stat.bklog_u); |
2267 | xprt->stat.max_slots, | ||
2268 | xprt->stat.sending_u, | ||
2269 | xprt->stat.pending_u); | ||
2270 | } | 2240 | } |
2271 | 2241 | ||
2272 | /** | 2242 | /** |
@@ -2279,18 +2249,14 @@ static void xs_udp_print_stats(struct rpc_xprt *xprt, struct seq_file *seq) | |||
2279 | { | 2249 | { |
2280 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); | 2250 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); |
2281 | 2251 | ||
2282 | seq_printf(seq, "\txprt:\tudp %u %lu %lu %lu %lu %llu %llu " | 2252 | seq_printf(seq, "\txprt:\tudp %u %lu %lu %lu %lu %Lu %Lu\n", |
2283 | "%lu %llu %llu\n", | ||
2284 | transport->srcport, | 2253 | transport->srcport, |
2285 | xprt->stat.bind_count, | 2254 | xprt->stat.bind_count, |
2286 | xprt->stat.sends, | 2255 | xprt->stat.sends, |
2287 | xprt->stat.recvs, | 2256 | xprt->stat.recvs, |
2288 | xprt->stat.bad_xids, | 2257 | xprt->stat.bad_xids, |
2289 | xprt->stat.req_u, | 2258 | xprt->stat.req_u, |
2290 | xprt->stat.bklog_u, | 2259 | xprt->stat.bklog_u); |
2291 | xprt->stat.max_slots, | ||
2292 | xprt->stat.sending_u, | ||
2293 | xprt->stat.pending_u); | ||
2294 | } | 2260 | } |
2295 | 2261 | ||
2296 | /** | 2262 | /** |
@@ -2307,8 +2273,7 @@ static void xs_tcp_print_stats(struct rpc_xprt *xprt, struct seq_file *seq) | |||
2307 | if (xprt_connected(xprt)) | 2273 | if (xprt_connected(xprt)) |
2308 | idle_time = (long)(jiffies - xprt->last_used) / HZ; | 2274 | idle_time = (long)(jiffies - xprt->last_used) / HZ; |
2309 | 2275 | ||
2310 | seq_printf(seq, "\txprt:\ttcp %u %lu %lu %lu %ld %lu %lu %lu " | 2276 | seq_printf(seq, "\txprt:\ttcp %u %lu %lu %lu %ld %lu %lu %lu %Lu %Lu\n", |
2311 | "%llu %llu %lu %llu %llu\n", | ||
2312 | transport->srcport, | 2277 | transport->srcport, |
2313 | xprt->stat.bind_count, | 2278 | xprt->stat.bind_count, |
2314 | xprt->stat.connect_count, | 2279 | xprt->stat.connect_count, |
@@ -2318,10 +2283,7 @@ static void xs_tcp_print_stats(struct rpc_xprt *xprt, struct seq_file *seq) | |||
2318 | xprt->stat.recvs, | 2283 | xprt->stat.recvs, |
2319 | xprt->stat.bad_xids, | 2284 | xprt->stat.bad_xids, |
2320 | xprt->stat.req_u, | 2285 | xprt->stat.req_u, |
2321 | xprt->stat.bklog_u, | 2286 | xprt->stat.bklog_u); |
2322 | xprt->stat.max_slots, | ||
2323 | xprt->stat.sending_u, | ||
2324 | xprt->stat.pending_u); | ||
2325 | } | 2287 | } |
2326 | 2288 | ||
2327 | /* | 2289 | /* |
@@ -2334,11 +2296,9 @@ static void *bc_malloc(struct rpc_task *task, size_t size) | |||
2334 | struct page *page; | 2296 | struct page *page; |
2335 | struct rpc_buffer *buf; | 2297 | struct rpc_buffer *buf; |
2336 | 2298 | ||
2337 | WARN_ON_ONCE(size > PAGE_SIZE - sizeof(struct rpc_buffer)); | 2299 | BUG_ON(size > PAGE_SIZE - sizeof(struct rpc_buffer)); |
2338 | if (size > PAGE_SIZE - sizeof(struct rpc_buffer)) | ||
2339 | return NULL; | ||
2340 | |||
2341 | page = alloc_page(GFP_KERNEL); | 2300 | page = alloc_page(GFP_KERNEL); |
2301 | |||
2342 | if (!page) | 2302 | if (!page) |
2343 | return NULL; | 2303 | return NULL; |
2344 | 2304 | ||
@@ -2400,6 +2360,7 @@ static int bc_send_request(struct rpc_task *task) | |||
2400 | { | 2360 | { |
2401 | struct rpc_rqst *req = task->tk_rqstp; | 2361 | struct rpc_rqst *req = task->tk_rqstp; |
2402 | struct svc_xprt *xprt; | 2362 | struct svc_xprt *xprt; |
2363 | struct svc_sock *svsk; | ||
2403 | u32 len; | 2364 | u32 len; |
2404 | 2365 | ||
2405 | dprintk("sending request with xid: %08x\n", ntohl(req->rq_xid)); | 2366 | dprintk("sending request with xid: %08x\n", ntohl(req->rq_xid)); |
@@ -2407,6 +2368,7 @@ static int bc_send_request(struct rpc_task *task) | |||
2407 | * Get the server socket associated with this callback xprt | 2368 | * Get the server socket associated with this callback xprt |
2408 | */ | 2369 | */ |
2409 | xprt = req->rq_xprt->bc_xprt; | 2370 | xprt = req->rq_xprt->bc_xprt; |
2371 | svsk = container_of(xprt, struct svc_sock, sk_xprt); | ||
2410 | 2372 | ||
2411 | /* | 2373 | /* |
2412 | * Grab the mutex to serialize data as the connection is shared | 2374 | * Grab the mutex to serialize data as the connection is shared |
@@ -2450,7 +2412,6 @@ static void bc_destroy(struct rpc_xprt *xprt) | |||
2450 | static struct rpc_xprt_ops xs_local_ops = { | 2412 | static struct rpc_xprt_ops xs_local_ops = { |
2451 | .reserve_xprt = xprt_reserve_xprt, | 2413 | .reserve_xprt = xprt_reserve_xprt, |
2452 | .release_xprt = xs_tcp_release_xprt, | 2414 | .release_xprt = xs_tcp_release_xprt, |
2453 | .alloc_slot = xprt_alloc_slot, | ||
2454 | .rpcbind = xs_local_rpcbind, | 2415 | .rpcbind = xs_local_rpcbind, |
2455 | .set_port = xs_local_set_port, | 2416 | .set_port = xs_local_set_port, |
2456 | .connect = xs_connect, | 2417 | .connect = xs_connect, |
@@ -2467,7 +2428,6 @@ static struct rpc_xprt_ops xs_udp_ops = { | |||
2467 | .set_buffer_size = xs_udp_set_buffer_size, | 2428 | .set_buffer_size = xs_udp_set_buffer_size, |
2468 | .reserve_xprt = xprt_reserve_xprt_cong, | 2429 | .reserve_xprt = xprt_reserve_xprt_cong, |
2469 | .release_xprt = xprt_release_xprt_cong, | 2430 | .release_xprt = xprt_release_xprt_cong, |
2470 | .alloc_slot = xprt_alloc_slot, | ||
2471 | .rpcbind = rpcb_getport_async, | 2431 | .rpcbind = rpcb_getport_async, |
2472 | .set_port = xs_set_port, | 2432 | .set_port = xs_set_port, |
2473 | .connect = xs_connect, | 2433 | .connect = xs_connect, |
@@ -2485,7 +2445,6 @@ static struct rpc_xprt_ops xs_udp_ops = { | |||
2485 | static struct rpc_xprt_ops xs_tcp_ops = { | 2445 | static struct rpc_xprt_ops xs_tcp_ops = { |
2486 | .reserve_xprt = xprt_reserve_xprt, | 2446 | .reserve_xprt = xprt_reserve_xprt, |
2487 | .release_xprt = xs_tcp_release_xprt, | 2447 | .release_xprt = xs_tcp_release_xprt, |
2488 | .alloc_slot = xprt_lock_and_alloc_slot, | ||
2489 | .rpcbind = rpcb_getport_async, | 2448 | .rpcbind = rpcb_getport_async, |
2490 | .set_port = xs_set_port, | 2449 | .set_port = xs_set_port, |
2491 | .connect = xs_connect, | 2450 | .connect = xs_connect, |
@@ -2505,8 +2464,6 @@ static struct rpc_xprt_ops xs_tcp_ops = { | |||
2505 | static struct rpc_xprt_ops bc_tcp_ops = { | 2464 | static struct rpc_xprt_ops bc_tcp_ops = { |
2506 | .reserve_xprt = xprt_reserve_xprt, | 2465 | .reserve_xprt = xprt_reserve_xprt, |
2507 | .release_xprt = xprt_release_xprt, | 2466 | .release_xprt = xprt_release_xprt, |
2508 | .alloc_slot = xprt_alloc_slot, | ||
2509 | .rpcbind = xs_local_rpcbind, | ||
2510 | .buf_alloc = bc_malloc, | 2467 | .buf_alloc = bc_malloc, |
2511 | .buf_free = bc_free, | 2468 | .buf_free = bc_free, |
2512 | .send_request = bc_send_request, | 2469 | .send_request = bc_send_request, |
@@ -2572,10 +2529,8 @@ static struct rpc_xprt *xs_setup_xprt(struct xprt_create *args, | |||
2572 | int err; | 2529 | int err; |
2573 | err = xs_init_anyaddr(args->dstaddr->sa_family, | 2530 | err = xs_init_anyaddr(args->dstaddr->sa_family, |
2574 | (struct sockaddr *)&new->srcaddr); | 2531 | (struct sockaddr *)&new->srcaddr); |
2575 | if (err != 0) { | 2532 | if (err != 0) |
2576 | xprt_free(xprt); | ||
2577 | return ERR_PTR(err); | 2533 | return ERR_PTR(err); |
2578 | } | ||
2579 | } | 2534 | } |
2580 | 2535 | ||
2581 | return xprt; | 2536 | return xprt; |