diff options
author | J. Bruce Fields <bfields@redhat.com> | 2012-03-21 16:42:14 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2012-03-26 11:48:54 -0400 |
commit | 1df00640c9111c881633d9b219f18e66c52599ec (patch) | |
tree | e36d3924d84f47ec93f6650ff1fd5b8ea7d10d24 /net | |
parent | ab4684d1560f8d77f6ce82bd3f1f82937070d397 (diff) | |
parent | 5a7c9eec9fde1da0e3adf0a4ddb64ff2a324a492 (diff) |
Merge nfs containerization work from Trond's tree
The nfs containerization work is a prerequisite for Jeff Layton's reboot
recovery rework.
Diffstat (limited to 'net')
28 files changed, 1559 insertions, 733 deletions
diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c index 97f70e50ad3b..761ad9d6cc3b 100644 --- a/net/ceph/ceph_common.c +++ b/net/ceph/ceph_common.c | |||
@@ -85,8 +85,6 @@ int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid) | |||
85 | } else { | 85 | } else { |
86 | pr_info("client%lld fsid %pU\n", ceph_client_id(client), fsid); | 86 | pr_info("client%lld fsid %pU\n", ceph_client_id(client), fsid); |
87 | memcpy(&client->fsid, fsid, sizeof(*fsid)); | 87 | memcpy(&client->fsid, fsid, sizeof(*fsid)); |
88 | ceph_debugfs_client_init(client); | ||
89 | client->have_fsid = true; | ||
90 | } | 88 | } |
91 | return 0; | 89 | return 0; |
92 | } | 90 | } |
diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index 0b62deae42bd..1845cde26227 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c | |||
@@ -8,8 +8,8 @@ | |||
8 | 8 | ||
9 | #include <linux/ceph/mon_client.h> | 9 | #include <linux/ceph/mon_client.h> |
10 | #include <linux/ceph/libceph.h> | 10 | #include <linux/ceph/libceph.h> |
11 | #include <linux/ceph/debugfs.h> | ||
11 | #include <linux/ceph/decode.h> | 12 | #include <linux/ceph/decode.h> |
12 | |||
13 | #include <linux/ceph/auth.h> | 13 | #include <linux/ceph/auth.h> |
14 | 14 | ||
15 | /* | 15 | /* |
@@ -340,8 +340,19 @@ static void ceph_monc_handle_map(struct ceph_mon_client *monc, | |||
340 | client->monc.monmap = monmap; | 340 | client->monc.monmap = monmap; |
341 | kfree(old); | 341 | kfree(old); |
342 | 342 | ||
343 | if (!client->have_fsid) { | ||
344 | client->have_fsid = true; | ||
345 | mutex_unlock(&monc->mutex); | ||
346 | /* | ||
347 | * do debugfs initialization without mutex to avoid | ||
348 | * creating a locking dependency | ||
349 | */ | ||
350 | ceph_debugfs_client_init(client); | ||
351 | goto out_unlocked; | ||
352 | } | ||
343 | out: | 353 | out: |
344 | mutex_unlock(&monc->mutex); | 354 | mutex_unlock(&monc->mutex); |
355 | out_unlocked: | ||
345 | wake_up_all(&client->auth_wq); | 356 | wake_up_all(&client->auth_wq); |
346 | } | 357 | } |
347 | 358 | ||
diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig index ffd243d09188..9fe8857d8d59 100644 --- a/net/sunrpc/Kconfig +++ b/net/sunrpc/Kconfig | |||
@@ -39,3 +39,16 @@ config RPCSEC_GSS_KRB5 | |||
39 | Kerberos support should be installed. | 39 | Kerberos support should be installed. |
40 | 40 | ||
41 | If unsure, say Y. | 41 | If unsure, say Y. |
42 | |||
43 | config SUNRPC_DEBUG | ||
44 | bool "RPC: Enable dprintk debugging" | ||
45 | depends on SUNRPC && SYSCTL | ||
46 | help | ||
47 | This option enables a sysctl-based debugging interface | ||
48 | that is be used by the 'rpcdebug' utility to turn on or off | ||
49 | logging of different aspects of the kernel RPC activity. | ||
50 | |||
51 | Disabling this option will make your kernel slightly smaller, | ||
52 | but makes troubleshooting NFS issues significantly harder. | ||
53 | |||
54 | If unsure, say Y. | ||
diff --git a/net/sunrpc/addr.c b/net/sunrpc/addr.c index ee77742e0ed6..d11418f97f1f 100644 --- a/net/sunrpc/addr.c +++ b/net/sunrpc/addr.c | |||
@@ -156,8 +156,9 @@ static size_t rpc_pton4(const char *buf, const size_t buflen, | |||
156 | } | 156 | } |
157 | 157 | ||
158 | #if IS_ENABLED(CONFIG_IPV6) | 158 | #if IS_ENABLED(CONFIG_IPV6) |
159 | static int rpc_parse_scope_id(const char *buf, const size_t buflen, | 159 | static int rpc_parse_scope_id(struct net *net, const char *buf, |
160 | const char *delim, struct sockaddr_in6 *sin6) | 160 | const size_t buflen, const char *delim, |
161 | struct sockaddr_in6 *sin6) | ||
161 | { | 162 | { |
162 | char *p; | 163 | char *p; |
163 | size_t len; | 164 | size_t len; |
@@ -177,7 +178,7 @@ static int rpc_parse_scope_id(const char *buf, const size_t buflen, | |||
177 | unsigned long scope_id = 0; | 178 | unsigned long scope_id = 0; |
178 | struct net_device *dev; | 179 | struct net_device *dev; |
179 | 180 | ||
180 | dev = dev_get_by_name(&init_net, p); | 181 | dev = dev_get_by_name(net, p); |
181 | if (dev != NULL) { | 182 | if (dev != NULL) { |
182 | scope_id = dev->ifindex; | 183 | scope_id = dev->ifindex; |
183 | dev_put(dev); | 184 | dev_put(dev); |
@@ -197,7 +198,7 @@ static int rpc_parse_scope_id(const char *buf, const size_t buflen, | |||
197 | return 0; | 198 | return 0; |
198 | } | 199 | } |
199 | 200 | ||
200 | static size_t rpc_pton6(const char *buf, const size_t buflen, | 201 | static size_t rpc_pton6(struct net *net, const char *buf, const size_t buflen, |
201 | struct sockaddr *sap, const size_t salen) | 202 | struct sockaddr *sap, const size_t salen) |
202 | { | 203 | { |
203 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap; | 204 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap; |
@@ -213,14 +214,14 @@ static size_t rpc_pton6(const char *buf, const size_t buflen, | |||
213 | if (in6_pton(buf, buflen, addr, IPV6_SCOPE_DELIMITER, &delim) == 0) | 214 | if (in6_pton(buf, buflen, addr, IPV6_SCOPE_DELIMITER, &delim) == 0) |
214 | return 0; | 215 | return 0; |
215 | 216 | ||
216 | if (!rpc_parse_scope_id(buf, buflen, delim, sin6)) | 217 | if (!rpc_parse_scope_id(net, buf, buflen, delim, sin6)) |
217 | return 0; | 218 | return 0; |
218 | 219 | ||
219 | sin6->sin6_family = AF_INET6; | 220 | sin6->sin6_family = AF_INET6; |
220 | return sizeof(struct sockaddr_in6); | 221 | return sizeof(struct sockaddr_in6); |
221 | } | 222 | } |
222 | #else | 223 | #else |
223 | static size_t rpc_pton6(const char *buf, const size_t buflen, | 224 | static size_t rpc_pton6(struct net *net, const char *buf, const size_t buflen, |
224 | struct sockaddr *sap, const size_t salen) | 225 | struct sockaddr *sap, const size_t salen) |
225 | { | 226 | { |
226 | return 0; | 227 | return 0; |
@@ -229,6 +230,7 @@ static size_t rpc_pton6(const char *buf, const size_t buflen, | |||
229 | 230 | ||
230 | /** | 231 | /** |
231 | * rpc_pton - Construct a sockaddr in @sap | 232 | * rpc_pton - Construct a sockaddr in @sap |
233 | * @net: applicable network namespace | ||
232 | * @buf: C string containing presentation format IP address | 234 | * @buf: C string containing presentation format IP address |
233 | * @buflen: length of presentation address in bytes | 235 | * @buflen: length of presentation address in bytes |
234 | * @sap: buffer into which to plant socket address | 236 | * @sap: buffer into which to plant socket address |
@@ -241,14 +243,14 @@ static size_t rpc_pton6(const char *buf, const size_t buflen, | |||
241 | * socket address, if successful. Returns zero if an error | 243 | * socket address, if successful. Returns zero if an error |
242 | * occurred. | 244 | * occurred. |
243 | */ | 245 | */ |
244 | size_t rpc_pton(const char *buf, const size_t buflen, | 246 | size_t rpc_pton(struct net *net, const char *buf, const size_t buflen, |
245 | struct sockaddr *sap, const size_t salen) | 247 | struct sockaddr *sap, const size_t salen) |
246 | { | 248 | { |
247 | unsigned int i; | 249 | unsigned int i; |
248 | 250 | ||
249 | for (i = 0; i < buflen; i++) | 251 | for (i = 0; i < buflen; i++) |
250 | if (buf[i] == ':') | 252 | if (buf[i] == ':') |
251 | return rpc_pton6(buf, buflen, sap, salen); | 253 | return rpc_pton6(net, buf, buflen, sap, salen); |
252 | return rpc_pton4(buf, buflen, sap, salen); | 254 | return rpc_pton4(buf, buflen, sap, salen); |
253 | } | 255 | } |
254 | EXPORT_SYMBOL_GPL(rpc_pton); | 256 | EXPORT_SYMBOL_GPL(rpc_pton); |
@@ -295,6 +297,7 @@ char *rpc_sockaddr2uaddr(const struct sockaddr *sap, gfp_t gfp_flags) | |||
295 | 297 | ||
296 | /** | 298 | /** |
297 | * rpc_uaddr2sockaddr - convert a universal address to a socket address. | 299 | * rpc_uaddr2sockaddr - convert a universal address to a socket address. |
300 | * @net: applicable network namespace | ||
298 | * @uaddr: C string containing universal address to convert | 301 | * @uaddr: C string containing universal address to convert |
299 | * @uaddr_len: length of universal address string | 302 | * @uaddr_len: length of universal address string |
300 | * @sap: buffer into which to plant socket address | 303 | * @sap: buffer into which to plant socket address |
@@ -306,8 +309,9 @@ char *rpc_sockaddr2uaddr(const struct sockaddr *sap, gfp_t gfp_flags) | |||
306 | * Returns the size of the socket address if successful; otherwise | 309 | * Returns the size of the socket address if successful; otherwise |
307 | * zero is returned. | 310 | * zero is returned. |
308 | */ | 311 | */ |
309 | size_t rpc_uaddr2sockaddr(const char *uaddr, const size_t uaddr_len, | 312 | size_t rpc_uaddr2sockaddr(struct net *net, const char *uaddr, |
310 | struct sockaddr *sap, const size_t salen) | 313 | const size_t uaddr_len, struct sockaddr *sap, |
314 | const size_t salen) | ||
311 | { | 315 | { |
312 | char *c, buf[RPCBIND_MAXUADDRLEN + sizeof('\0')]; | 316 | char *c, buf[RPCBIND_MAXUADDRLEN + sizeof('\0')]; |
313 | unsigned long portlo, porthi; | 317 | unsigned long portlo, porthi; |
@@ -339,7 +343,7 @@ size_t rpc_uaddr2sockaddr(const char *uaddr, const size_t uaddr_len, | |||
339 | port = (unsigned short)((porthi << 8) | portlo); | 343 | port = (unsigned short)((porthi << 8) | portlo); |
340 | 344 | ||
341 | *c = '\0'; | 345 | *c = '\0'; |
342 | if (rpc_pton(buf, strlen(buf), sap, salen) == 0) | 346 | if (rpc_pton(net, buf, strlen(buf), sap, salen) == 0) |
343 | return 0; | 347 | return 0; |
344 | 348 | ||
345 | switch (sap->sa_family) { | 349 | switch (sap->sa_family) { |
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index affa631ac1ab..d3ad81f8da5b 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 dentry *dentry[2]; | 84 | struct rpc_pipe *pipe[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 inode->i_lock. | 115 | * and a new one is protected by the pipe->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) |
@@ -251,7 +251,7 @@ struct gss_upcall_msg { | |||
251 | struct rpc_pipe_msg msg; | 251 | struct rpc_pipe_msg msg; |
252 | struct list_head list; | 252 | struct list_head list; |
253 | struct gss_auth *auth; | 253 | struct gss_auth *auth; |
254 | struct rpc_inode *inode; | 254 | struct rpc_pipe *pipe; |
255 | struct rpc_wait_queue rpc_waitqueue; | 255 | struct rpc_wait_queue rpc_waitqueue; |
256 | wait_queue_head_t waitqueue; | 256 | wait_queue_head_t waitqueue; |
257 | struct gss_cl_ctx *ctx; | 257 | struct gss_cl_ctx *ctx; |
@@ -294,10 +294,10 @@ gss_release_msg(struct gss_upcall_msg *gss_msg) | |||
294 | } | 294 | } |
295 | 295 | ||
296 | static struct gss_upcall_msg * | 296 | static struct gss_upcall_msg * |
297 | __gss_find_upcall(struct rpc_inode *rpci, uid_t uid) | 297 | __gss_find_upcall(struct rpc_pipe *pipe, uid_t uid) |
298 | { | 298 | { |
299 | struct gss_upcall_msg *pos; | 299 | struct gss_upcall_msg *pos; |
300 | list_for_each_entry(pos, &rpci->in_downcall, list) { | 300 | list_for_each_entry(pos, &pipe->in_downcall, list) { |
301 | if (pos->uid != uid) | 301 | if (pos->uid != uid) |
302 | continue; | 302 | continue; |
303 | atomic_inc(&pos->count); | 303 | atomic_inc(&pos->count); |
@@ -315,18 +315,17 @@ __gss_find_upcall(struct rpc_inode *rpci, uid_t uid) | |||
315 | static inline struct gss_upcall_msg * | 315 | static inline struct gss_upcall_msg * |
316 | gss_add_msg(struct gss_upcall_msg *gss_msg) | 316 | gss_add_msg(struct gss_upcall_msg *gss_msg) |
317 | { | 317 | { |
318 | struct rpc_inode *rpci = gss_msg->inode; | 318 | struct rpc_pipe *pipe = gss_msg->pipe; |
319 | struct inode *inode = &rpci->vfs_inode; | ||
320 | struct gss_upcall_msg *old; | 319 | struct gss_upcall_msg *old; |
321 | 320 | ||
322 | spin_lock(&inode->i_lock); | 321 | spin_lock(&pipe->lock); |
323 | old = __gss_find_upcall(rpci, gss_msg->uid); | 322 | old = __gss_find_upcall(pipe, gss_msg->uid); |
324 | if (old == NULL) { | 323 | if (old == NULL) { |
325 | atomic_inc(&gss_msg->count); | 324 | atomic_inc(&gss_msg->count); |
326 | list_add(&gss_msg->list, &rpci->in_downcall); | 325 | list_add(&gss_msg->list, &pipe->in_downcall); |
327 | } else | 326 | } else |
328 | gss_msg = old; | 327 | gss_msg = old; |
329 | spin_unlock(&inode->i_lock); | 328 | spin_unlock(&pipe->lock); |
330 | return gss_msg; | 329 | return gss_msg; |
331 | } | 330 | } |
332 | 331 | ||
@@ -342,14 +341,14 @@ __gss_unhash_msg(struct gss_upcall_msg *gss_msg) | |||
342 | static void | 341 | static void |
343 | gss_unhash_msg(struct gss_upcall_msg *gss_msg) | 342 | gss_unhash_msg(struct gss_upcall_msg *gss_msg) |
344 | { | 343 | { |
345 | struct inode *inode = &gss_msg->inode->vfs_inode; | 344 | struct rpc_pipe *pipe = gss_msg->pipe; |
346 | 345 | ||
347 | if (list_empty(&gss_msg->list)) | 346 | if (list_empty(&gss_msg->list)) |
348 | return; | 347 | return; |
349 | spin_lock(&inode->i_lock); | 348 | spin_lock(&pipe->lock); |
350 | if (!list_empty(&gss_msg->list)) | 349 | if (!list_empty(&gss_msg->list)) |
351 | __gss_unhash_msg(gss_msg); | 350 | __gss_unhash_msg(gss_msg); |
352 | spin_unlock(&inode->i_lock); | 351 | spin_unlock(&pipe->lock); |
353 | } | 352 | } |
354 | 353 | ||
355 | static void | 354 | static void |
@@ -376,11 +375,11 @@ gss_upcall_callback(struct rpc_task *task) | |||
376 | struct gss_cred *gss_cred = container_of(task->tk_rqstp->rq_cred, | 375 | struct gss_cred *gss_cred = container_of(task->tk_rqstp->rq_cred, |
377 | struct gss_cred, gc_base); | 376 | struct gss_cred, gc_base); |
378 | struct gss_upcall_msg *gss_msg = gss_cred->gc_upcall; | 377 | struct gss_upcall_msg *gss_msg = gss_cred->gc_upcall; |
379 | struct inode *inode = &gss_msg->inode->vfs_inode; | 378 | struct rpc_pipe *pipe = gss_msg->pipe; |
380 | 379 | ||
381 | spin_lock(&inode->i_lock); | 380 | spin_lock(&pipe->lock); |
382 | gss_handle_downcall_result(gss_cred, gss_msg); | 381 | gss_handle_downcall_result(gss_cred, gss_msg); |
383 | spin_unlock(&inode->i_lock); | 382 | spin_unlock(&pipe->lock); |
384 | task->tk_status = gss_msg->msg.errno; | 383 | task->tk_status = gss_msg->msg.errno; |
385 | gss_release_msg(gss_msg); | 384 | gss_release_msg(gss_msg); |
386 | } | 385 | } |
@@ -450,7 +449,7 @@ gss_alloc_msg(struct gss_auth *gss_auth, struct rpc_clnt *clnt, | |||
450 | kfree(gss_msg); | 449 | kfree(gss_msg); |
451 | return ERR_PTR(vers); | 450 | return ERR_PTR(vers); |
452 | } | 451 | } |
453 | gss_msg->inode = RPC_I(gss_auth->dentry[vers]->d_inode); | 452 | gss_msg->pipe = gss_auth->pipe[vers]; |
454 | INIT_LIST_HEAD(&gss_msg->list); | 453 | INIT_LIST_HEAD(&gss_msg->list); |
455 | rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq"); | 454 | rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq"); |
456 | init_waitqueue_head(&gss_msg->waitqueue); | 455 | init_waitqueue_head(&gss_msg->waitqueue); |
@@ -474,8 +473,7 @@ gss_setup_upcall(struct rpc_clnt *clnt, struct gss_auth *gss_auth, struct rpc_cr | |||
474 | return gss_new; | 473 | return gss_new; |
475 | gss_msg = gss_add_msg(gss_new); | 474 | gss_msg = gss_add_msg(gss_new); |
476 | if (gss_msg == gss_new) { | 475 | if (gss_msg == gss_new) { |
477 | struct inode *inode = &gss_new->inode->vfs_inode; | 476 | int res = rpc_queue_upcall(gss_new->pipe, &gss_new->msg); |
478 | int res = rpc_queue_upcall(inode, &gss_new->msg); | ||
479 | if (res) { | 477 | if (res) { |
480 | gss_unhash_msg(gss_new); | 478 | gss_unhash_msg(gss_new); |
481 | gss_msg = ERR_PTR(res); | 479 | gss_msg = ERR_PTR(res); |
@@ -506,7 +504,7 @@ gss_refresh_upcall(struct rpc_task *task) | |||
506 | struct gss_cred *gss_cred = container_of(cred, | 504 | struct gss_cred *gss_cred = container_of(cred, |
507 | struct gss_cred, gc_base); | 505 | struct gss_cred, gc_base); |
508 | struct gss_upcall_msg *gss_msg; | 506 | struct gss_upcall_msg *gss_msg; |
509 | struct inode *inode; | 507 | struct rpc_pipe *pipe; |
510 | int err = 0; | 508 | int err = 0; |
511 | 509 | ||
512 | dprintk("RPC: %5u gss_refresh_upcall for uid %u\n", task->tk_pid, | 510 | dprintk("RPC: %5u gss_refresh_upcall for uid %u\n", task->tk_pid, |
@@ -524,8 +522,8 @@ gss_refresh_upcall(struct rpc_task *task) | |||
524 | err = PTR_ERR(gss_msg); | 522 | err = PTR_ERR(gss_msg); |
525 | goto out; | 523 | goto out; |
526 | } | 524 | } |
527 | inode = &gss_msg->inode->vfs_inode; | 525 | pipe = gss_msg->pipe; |
528 | spin_lock(&inode->i_lock); | 526 | spin_lock(&pipe->lock); |
529 | if (gss_cred->gc_upcall != NULL) | 527 | if (gss_cred->gc_upcall != NULL) |
530 | rpc_sleep_on(&gss_cred->gc_upcall->rpc_waitqueue, task, NULL); | 528 | rpc_sleep_on(&gss_cred->gc_upcall->rpc_waitqueue, task, NULL); |
531 | else if (gss_msg->ctx == NULL && gss_msg->msg.errno >= 0) { | 529 | else if (gss_msg->ctx == NULL && gss_msg->msg.errno >= 0) { |
@@ -538,7 +536,7 @@ gss_refresh_upcall(struct rpc_task *task) | |||
538 | gss_handle_downcall_result(gss_cred, gss_msg); | 536 | gss_handle_downcall_result(gss_cred, gss_msg); |
539 | err = gss_msg->msg.errno; | 537 | err = gss_msg->msg.errno; |
540 | } | 538 | } |
541 | spin_unlock(&inode->i_lock); | 539 | spin_unlock(&pipe->lock); |
542 | gss_release_msg(gss_msg); | 540 | gss_release_msg(gss_msg); |
543 | out: | 541 | out: |
544 | dprintk("RPC: %5u gss_refresh_upcall for uid %u result %d\n", | 542 | dprintk("RPC: %5u gss_refresh_upcall for uid %u result %d\n", |
@@ -549,7 +547,7 @@ out: | |||
549 | static inline int | 547 | static inline int |
550 | gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred) | 548 | gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred) |
551 | { | 549 | { |
552 | struct inode *inode; | 550 | struct rpc_pipe *pipe; |
553 | struct rpc_cred *cred = &gss_cred->gc_base; | 551 | struct rpc_cred *cred = &gss_cred->gc_base; |
554 | struct gss_upcall_msg *gss_msg; | 552 | struct gss_upcall_msg *gss_msg; |
555 | DEFINE_WAIT(wait); | 553 | DEFINE_WAIT(wait); |
@@ -573,14 +571,14 @@ retry: | |||
573 | err = PTR_ERR(gss_msg); | 571 | err = PTR_ERR(gss_msg); |
574 | goto out; | 572 | goto out; |
575 | } | 573 | } |
576 | inode = &gss_msg->inode->vfs_inode; | 574 | pipe = gss_msg->pipe; |
577 | for (;;) { | 575 | for (;;) { |
578 | prepare_to_wait(&gss_msg->waitqueue, &wait, TASK_KILLABLE); | 576 | prepare_to_wait(&gss_msg->waitqueue, &wait, TASK_KILLABLE); |
579 | spin_lock(&inode->i_lock); | 577 | spin_lock(&pipe->lock); |
580 | if (gss_msg->ctx != NULL || gss_msg->msg.errno < 0) { | 578 | if (gss_msg->ctx != NULL || gss_msg->msg.errno < 0) { |
581 | break; | 579 | break; |
582 | } | 580 | } |
583 | spin_unlock(&inode->i_lock); | 581 | spin_unlock(&pipe->lock); |
584 | if (fatal_signal_pending(current)) { | 582 | if (fatal_signal_pending(current)) { |
585 | err = -ERESTARTSYS; | 583 | err = -ERESTARTSYS; |
586 | goto out_intr; | 584 | goto out_intr; |
@@ -591,7 +589,7 @@ retry: | |||
591 | gss_cred_set_ctx(cred, gss_msg->ctx); | 589 | gss_cred_set_ctx(cred, gss_msg->ctx); |
592 | else | 590 | else |
593 | err = gss_msg->msg.errno; | 591 | err = gss_msg->msg.errno; |
594 | spin_unlock(&inode->i_lock); | 592 | spin_unlock(&pipe->lock); |
595 | out_intr: | 593 | out_intr: |
596 | finish_wait(&gss_msg->waitqueue, &wait); | 594 | finish_wait(&gss_msg->waitqueue, &wait); |
597 | gss_release_msg(gss_msg); | 595 | gss_release_msg(gss_msg); |
@@ -609,7 +607,7 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) | |||
609 | const void *p, *end; | 607 | const void *p, *end; |
610 | void *buf; | 608 | void *buf; |
611 | struct gss_upcall_msg *gss_msg; | 609 | struct gss_upcall_msg *gss_msg; |
612 | struct inode *inode = filp->f_path.dentry->d_inode; | 610 | struct rpc_pipe *pipe = RPC_I(filp->f_dentry->d_inode)->pipe; |
613 | struct gss_cl_ctx *ctx; | 611 | struct gss_cl_ctx *ctx; |
614 | uid_t uid; | 612 | uid_t uid; |
615 | ssize_t err = -EFBIG; | 613 | ssize_t err = -EFBIG; |
@@ -639,14 +637,14 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) | |||
639 | 637 | ||
640 | err = -ENOENT; | 638 | err = -ENOENT; |
641 | /* Find a matching upcall */ | 639 | /* Find a matching upcall */ |
642 | spin_lock(&inode->i_lock); | 640 | spin_lock(&pipe->lock); |
643 | gss_msg = __gss_find_upcall(RPC_I(inode), uid); | 641 | gss_msg = __gss_find_upcall(pipe, uid); |
644 | if (gss_msg == NULL) { | 642 | if (gss_msg == NULL) { |
645 | spin_unlock(&inode->i_lock); | 643 | spin_unlock(&pipe->lock); |
646 | goto err_put_ctx; | 644 | goto err_put_ctx; |
647 | } | 645 | } |
648 | list_del_init(&gss_msg->list); | 646 | list_del_init(&gss_msg->list); |
649 | spin_unlock(&inode->i_lock); | 647 | spin_unlock(&pipe->lock); |
650 | 648 | ||
651 | p = gss_fill_context(p, end, ctx, gss_msg->auth->mech); | 649 | p = gss_fill_context(p, end, ctx, gss_msg->auth->mech); |
652 | if (IS_ERR(p)) { | 650 | if (IS_ERR(p)) { |
@@ -674,9 +672,9 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) | |||
674 | err = mlen; | 672 | err = mlen; |
675 | 673 | ||
676 | err_release_msg: | 674 | err_release_msg: |
677 | spin_lock(&inode->i_lock); | 675 | spin_lock(&pipe->lock); |
678 | __gss_unhash_msg(gss_msg); | 676 | __gss_unhash_msg(gss_msg); |
679 | spin_unlock(&inode->i_lock); | 677 | spin_unlock(&pipe->lock); |
680 | gss_release_msg(gss_msg); | 678 | gss_release_msg(gss_msg); |
681 | err_put_ctx: | 679 | err_put_ctx: |
682 | gss_put_ctx(ctx); | 680 | gss_put_ctx(ctx); |
@@ -722,23 +720,23 @@ static int gss_pipe_open_v1(struct inode *inode) | |||
722 | static void | 720 | static void |
723 | gss_pipe_release(struct inode *inode) | 721 | gss_pipe_release(struct inode *inode) |
724 | { | 722 | { |
725 | struct rpc_inode *rpci = RPC_I(inode); | 723 | struct rpc_pipe *pipe = RPC_I(inode)->pipe; |
726 | struct gss_upcall_msg *gss_msg; | 724 | struct gss_upcall_msg *gss_msg; |
727 | 725 | ||
728 | restart: | 726 | restart: |
729 | spin_lock(&inode->i_lock); | 727 | spin_lock(&pipe->lock); |
730 | list_for_each_entry(gss_msg, &rpci->in_downcall, list) { | 728 | list_for_each_entry(gss_msg, &pipe->in_downcall, list) { |
731 | 729 | ||
732 | if (!list_empty(&gss_msg->msg.list)) | 730 | if (!list_empty(&gss_msg->msg.list)) |
733 | continue; | 731 | continue; |
734 | gss_msg->msg.errno = -EPIPE; | 732 | gss_msg->msg.errno = -EPIPE; |
735 | atomic_inc(&gss_msg->count); | 733 | atomic_inc(&gss_msg->count); |
736 | __gss_unhash_msg(gss_msg); | 734 | __gss_unhash_msg(gss_msg); |
737 | spin_unlock(&inode->i_lock); | 735 | spin_unlock(&pipe->lock); |
738 | gss_release_msg(gss_msg); | 736 | gss_release_msg(gss_msg); |
739 | goto restart; | 737 | goto restart; |
740 | } | 738 | } |
741 | spin_unlock(&inode->i_lock); | 739 | spin_unlock(&pipe->lock); |
742 | 740 | ||
743 | put_pipe_version(); | 741 | put_pipe_version(); |
744 | } | 742 | } |
@@ -759,6 +757,75 @@ gss_pipe_destroy_msg(struct rpc_pipe_msg *msg) | |||
759 | } | 757 | } |
760 | } | 758 | } |
761 | 759 | ||
760 | static void gss_pipes_dentries_destroy(struct rpc_auth *auth) | ||
761 | { | ||
762 | struct gss_auth *gss_auth; | ||
763 | |||
764 | gss_auth = container_of(auth, struct gss_auth, rpc_auth); | ||
765 | if (gss_auth->pipe[0]->dentry) | ||
766 | rpc_unlink(gss_auth->pipe[0]->dentry); | ||
767 | if (gss_auth->pipe[1]->dentry) | ||
768 | rpc_unlink(gss_auth->pipe[1]->dentry); | ||
769 | } | ||
770 | |||
771 | static int gss_pipes_dentries_create(struct rpc_auth *auth) | ||
772 | { | ||
773 | int err; | ||
774 | struct gss_auth *gss_auth; | ||
775 | struct rpc_clnt *clnt; | ||
776 | |||
777 | gss_auth = container_of(auth, struct gss_auth, rpc_auth); | ||
778 | clnt = gss_auth->client; | ||
779 | |||
780 | gss_auth->pipe[1]->dentry = rpc_mkpipe_dentry(clnt->cl_dentry, | ||
781 | "gssd", | ||
782 | clnt, gss_auth->pipe[1]); | ||
783 | if (IS_ERR(gss_auth->pipe[1]->dentry)) | ||
784 | return PTR_ERR(gss_auth->pipe[1]->dentry); | ||
785 | gss_auth->pipe[0]->dentry = rpc_mkpipe_dentry(clnt->cl_dentry, | ||
786 | gss_auth->mech->gm_name, | ||
787 | clnt, gss_auth->pipe[0]); | ||
788 | if (IS_ERR(gss_auth->pipe[0]->dentry)) { | ||
789 | err = PTR_ERR(gss_auth->pipe[0]->dentry); | ||
790 | goto err_unlink_pipe_1; | ||
791 | } | ||
792 | return 0; | ||
793 | |||
794 | err_unlink_pipe_1: | ||
795 | rpc_unlink(gss_auth->pipe[1]->dentry); | ||
796 | return err; | ||
797 | } | ||
798 | |||
799 | static void gss_pipes_dentries_destroy_net(struct rpc_clnt *clnt, | ||
800 | struct rpc_auth *auth) | ||
801 | { | ||
802 | struct net *net = rpc_net_ns(clnt); | ||
803 | struct super_block *sb; | ||
804 | |||
805 | sb = rpc_get_sb_net(net); | ||
806 | if (sb) { | ||
807 | if (clnt->cl_dentry) | ||
808 | gss_pipes_dentries_destroy(auth); | ||
809 | rpc_put_sb_net(net); | ||
810 | } | ||
811 | } | ||
812 | |||
813 | static int gss_pipes_dentries_create_net(struct rpc_clnt *clnt, | ||
814 | struct rpc_auth *auth) | ||
815 | { | ||
816 | struct net *net = rpc_net_ns(clnt); | ||
817 | struct super_block *sb; | ||
818 | int err = 0; | ||
819 | |||
820 | sb = rpc_get_sb_net(net); | ||
821 | if (sb) { | ||
822 | if (clnt->cl_dentry) | ||
823 | err = gss_pipes_dentries_create(auth); | ||
824 | rpc_put_sb_net(net); | ||
825 | } | ||
826 | return err; | ||
827 | } | ||
828 | |||
762 | /* | 829 | /* |
763 | * NOTE: we have the opportunity to use different | 830 | * NOTE: we have the opportunity to use different |
764 | * parameters based on the input flavor (which must be a pseudoflavor) | 831 | * parameters based on the input flavor (which must be a pseudoflavor) |
@@ -801,32 +868,33 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor) | |||
801 | * that we supported only the old pipe. So we instead create | 868 | * that we supported only the old pipe. So we instead create |
802 | * the new pipe first. | 869 | * the new pipe first. |
803 | */ | 870 | */ |
804 | gss_auth->dentry[1] = rpc_mkpipe(clnt->cl_path.dentry, | 871 | gss_auth->pipe[1] = rpc_mkpipe_data(&gss_upcall_ops_v1, |
805 | "gssd", | 872 | RPC_PIPE_WAIT_FOR_OPEN); |
806 | clnt, &gss_upcall_ops_v1, | 873 | if (IS_ERR(gss_auth->pipe[1])) { |
807 | RPC_PIPE_WAIT_FOR_OPEN); | 874 | err = PTR_ERR(gss_auth->pipe[1]); |
808 | if (IS_ERR(gss_auth->dentry[1])) { | ||
809 | err = PTR_ERR(gss_auth->dentry[1]); | ||
810 | goto err_put_mech; | 875 | goto err_put_mech; |
811 | } | 876 | } |
812 | 877 | ||
813 | gss_auth->dentry[0] = rpc_mkpipe(clnt->cl_path.dentry, | 878 | gss_auth->pipe[0] = rpc_mkpipe_data(&gss_upcall_ops_v0, |
814 | gss_auth->mech->gm_name, | 879 | RPC_PIPE_WAIT_FOR_OPEN); |
815 | clnt, &gss_upcall_ops_v0, | 880 | if (IS_ERR(gss_auth->pipe[0])) { |
816 | RPC_PIPE_WAIT_FOR_OPEN); | 881 | err = PTR_ERR(gss_auth->pipe[0]); |
817 | if (IS_ERR(gss_auth->dentry[0])) { | 882 | goto err_destroy_pipe_1; |
818 | err = PTR_ERR(gss_auth->dentry[0]); | ||
819 | goto err_unlink_pipe_1; | ||
820 | } | 883 | } |
884 | err = gss_pipes_dentries_create_net(clnt, auth); | ||
885 | if (err) | ||
886 | goto err_destroy_pipe_0; | ||
821 | err = rpcauth_init_credcache(auth); | 887 | err = rpcauth_init_credcache(auth); |
822 | if (err) | 888 | if (err) |
823 | goto err_unlink_pipe_0; | 889 | goto err_unlink_pipes; |
824 | 890 | ||
825 | return auth; | 891 | return auth; |
826 | err_unlink_pipe_0: | 892 | err_unlink_pipes: |
827 | rpc_unlink(gss_auth->dentry[0]); | 893 | gss_pipes_dentries_destroy_net(clnt, auth); |
828 | err_unlink_pipe_1: | 894 | err_destroy_pipe_0: |
829 | rpc_unlink(gss_auth->dentry[1]); | 895 | rpc_destroy_pipe_data(gss_auth->pipe[0]); |
896 | err_destroy_pipe_1: | ||
897 | rpc_destroy_pipe_data(gss_auth->pipe[1]); | ||
830 | err_put_mech: | 898 | err_put_mech: |
831 | gss_mech_put(gss_auth->mech); | 899 | gss_mech_put(gss_auth->mech); |
832 | err_free: | 900 | err_free: |
@@ -839,8 +907,9 @@ out_dec: | |||
839 | static void | 907 | static void |
840 | gss_free(struct gss_auth *gss_auth) | 908 | gss_free(struct gss_auth *gss_auth) |
841 | { | 909 | { |
842 | rpc_unlink(gss_auth->dentry[1]); | 910 | gss_pipes_dentries_destroy_net(gss_auth->client, &gss_auth->rpc_auth); |
843 | rpc_unlink(gss_auth->dentry[0]); | 911 | rpc_destroy_pipe_data(gss_auth->pipe[0]); |
912 | rpc_destroy_pipe_data(gss_auth->pipe[1]); | ||
844 | gss_mech_put(gss_auth->mech); | 913 | gss_mech_put(gss_auth->mech); |
845 | 914 | ||
846 | kfree(gss_auth); | 915 | kfree(gss_auth); |
@@ -1547,7 +1616,9 @@ static const struct rpc_authops authgss_ops = { | |||
1547 | .create = gss_create, | 1616 | .create = gss_create, |
1548 | .destroy = gss_destroy, | 1617 | .destroy = gss_destroy, |
1549 | .lookup_cred = gss_lookup_cred, | 1618 | .lookup_cred = gss_lookup_cred, |
1550 | .crcreate = gss_create_cred | 1619 | .crcreate = gss_create_cred, |
1620 | .pipes_create = gss_pipes_dentries_create, | ||
1621 | .pipes_destroy = gss_pipes_dentries_destroy, | ||
1551 | }; | 1622 | }; |
1552 | 1623 | ||
1553 | static const struct rpc_credops gss_credops = { | 1624 | static const struct rpc_credops gss_credops = { |
@@ -1591,6 +1662,21 @@ static const struct rpc_pipe_ops gss_upcall_ops_v1 = { | |||
1591 | .release_pipe = gss_pipe_release, | 1662 | .release_pipe = gss_pipe_release, |
1592 | }; | 1663 | }; |
1593 | 1664 | ||
1665 | static __net_init int rpcsec_gss_init_net(struct net *net) | ||
1666 | { | ||
1667 | return gss_svc_init_net(net); | ||
1668 | } | ||
1669 | |||
1670 | static __net_exit void rpcsec_gss_exit_net(struct net *net) | ||
1671 | { | ||
1672 | gss_svc_shutdown_net(net); | ||
1673 | } | ||
1674 | |||
1675 | static struct pernet_operations rpcsec_gss_net_ops = { | ||
1676 | .init = rpcsec_gss_init_net, | ||
1677 | .exit = rpcsec_gss_exit_net, | ||
1678 | }; | ||
1679 | |||
1594 | /* | 1680 | /* |
1595 | * Initialize RPCSEC_GSS module | 1681 | * Initialize RPCSEC_GSS module |
1596 | */ | 1682 | */ |
@@ -1604,8 +1690,13 @@ static int __init init_rpcsec_gss(void) | |||
1604 | err = gss_svc_init(); | 1690 | err = gss_svc_init(); |
1605 | if (err) | 1691 | if (err) |
1606 | goto out_unregister; | 1692 | goto out_unregister; |
1693 | err = register_pernet_subsys(&rpcsec_gss_net_ops); | ||
1694 | if (err) | ||
1695 | goto out_svc_exit; | ||
1607 | rpc_init_wait_queue(&pipe_version_rpc_waitqueue, "gss pipe version"); | 1696 | rpc_init_wait_queue(&pipe_version_rpc_waitqueue, "gss pipe version"); |
1608 | return 0; | 1697 | return 0; |
1698 | out_svc_exit: | ||
1699 | gss_svc_shutdown(); | ||
1609 | out_unregister: | 1700 | out_unregister: |
1610 | rpcauth_unregister(&authgss_ops); | 1701 | rpcauth_unregister(&authgss_ops); |
1611 | out: | 1702 | out: |
@@ -1614,6 +1705,7 @@ out: | |||
1614 | 1705 | ||
1615 | static void __exit exit_rpcsec_gss(void) | 1706 | static void __exit exit_rpcsec_gss(void) |
1616 | { | 1707 | { |
1708 | unregister_pernet_subsys(&rpcsec_gss_net_ops); | ||
1617 | gss_svc_shutdown(); | 1709 | gss_svc_shutdown(); |
1618 | rpcauth_unregister(&authgss_ops); | 1710 | rpcauth_unregister(&authgss_ops); |
1619 | rcu_barrier(); /* Wait for completion of call_rcu()'s */ | 1711 | 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 9576f35ab701..0f43e894bc0a 100644 --- a/net/sunrpc/auth_gss/gss_krb5_crypto.c +++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c | |||
@@ -600,11 +600,14 @@ 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[crypto_blkcipher_blocksize(cipher) * 2]; | 603 | u8 data[GSS_KRB5_MAX_BLOCKSIZE * 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 | BUG_ON(len > crypto_blkcipher_blocksize(cipher) * 2); | 607 | if (len > ARRAY_SIZE(data)) { |
608 | WARN_ON(0); | ||
609 | return -ENOMEM; | ||
610 | } | ||
608 | 611 | ||
609 | /* | 612 | /* |
610 | * For encryption, we want to read from the cleartext | 613 | * 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 8c67890de427..8eff8c32d1b9 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 | struct crypto_blkcipher * | 347 | static 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; |
diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c index d7941eab7796..62ae3273186c 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 | u32 | 162 | static 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/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 8d0f7d3c71c8..1600cfb1618c 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c | |||
@@ -48,6 +48,8 @@ | |||
48 | #include <linux/sunrpc/svcauth_gss.h> | 48 | #include <linux/sunrpc/svcauth_gss.h> |
49 | #include <linux/sunrpc/cache.h> | 49 | #include <linux/sunrpc/cache.h> |
50 | 50 | ||
51 | #include "../netns.h" | ||
52 | |||
51 | #ifdef RPC_DEBUG | 53 | #ifdef RPC_DEBUG |
52 | # define RPCDBG_FACILITY RPCDBG_AUTH | 54 | # define RPCDBG_FACILITY RPCDBG_AUTH |
53 | #endif | 55 | #endif |
@@ -75,10 +77,8 @@ struct rsi { | |||
75 | int major_status, minor_status; | 77 | int major_status, minor_status; |
76 | }; | 78 | }; |
77 | 79 | ||
78 | static struct cache_head *rsi_table[RSI_HASHMAX]; | 80 | static struct rsi *rsi_update(struct cache_detail *cd, struct rsi *new, struct rsi *old); |
79 | static struct cache_detail rsi_cache; | 81 | static struct rsi *rsi_lookup(struct cache_detail *cd, struct rsi *item); |
80 | static struct rsi *rsi_update(struct rsi *new, struct rsi *old); | ||
81 | static struct rsi *rsi_lookup(struct rsi *item); | ||
82 | 82 | ||
83 | static void rsi_free(struct rsi *rsii) | 83 | static void rsi_free(struct rsi *rsii) |
84 | { | 84 | { |
@@ -216,7 +216,7 @@ static int rsi_parse(struct cache_detail *cd, | |||
216 | if (dup_to_netobj(&rsii.in_token, buf, len)) | 216 | if (dup_to_netobj(&rsii.in_token, buf, len)) |
217 | goto out; | 217 | goto out; |
218 | 218 | ||
219 | rsip = rsi_lookup(&rsii); | 219 | rsip = rsi_lookup(cd, &rsii); |
220 | if (!rsip) | 220 | if (!rsip) |
221 | goto out; | 221 | goto out; |
222 | 222 | ||
@@ -258,21 +258,20 @@ static int rsi_parse(struct cache_detail *cd, | |||
258 | if (dup_to_netobj(&rsii.out_token, buf, len)) | 258 | if (dup_to_netobj(&rsii.out_token, buf, len)) |
259 | goto out; | 259 | goto out; |
260 | rsii.h.expiry_time = expiry; | 260 | rsii.h.expiry_time = expiry; |
261 | rsip = rsi_update(&rsii, rsip); | 261 | rsip = rsi_update(cd, &rsii, rsip); |
262 | status = 0; | 262 | status = 0; |
263 | out: | 263 | out: |
264 | rsi_free(&rsii); | 264 | rsi_free(&rsii); |
265 | if (rsip) | 265 | if (rsip) |
266 | cache_put(&rsip->h, &rsi_cache); | 266 | cache_put(&rsip->h, cd); |
267 | else | 267 | else |
268 | status = -ENOMEM; | 268 | status = -ENOMEM; |
269 | return status; | 269 | return status; |
270 | } | 270 | } |
271 | 271 | ||
272 | static struct cache_detail rsi_cache = { | 272 | static struct cache_detail rsi_cache_template = { |
273 | .owner = THIS_MODULE, | 273 | .owner = THIS_MODULE, |
274 | .hash_size = RSI_HASHMAX, | 274 | .hash_size = RSI_HASHMAX, |
275 | .hash_table = rsi_table, | ||
276 | .name = "auth.rpcsec.init", | 275 | .name = "auth.rpcsec.init", |
277 | .cache_put = rsi_put, | 276 | .cache_put = rsi_put, |
278 | .cache_upcall = rsi_upcall, | 277 | .cache_upcall = rsi_upcall, |
@@ -283,24 +282,24 @@ static struct cache_detail rsi_cache = { | |||
283 | .alloc = rsi_alloc, | 282 | .alloc = rsi_alloc, |
284 | }; | 283 | }; |
285 | 284 | ||
286 | static struct rsi *rsi_lookup(struct rsi *item) | 285 | static struct rsi *rsi_lookup(struct cache_detail *cd, struct rsi *item) |
287 | { | 286 | { |
288 | struct cache_head *ch; | 287 | struct cache_head *ch; |
289 | int hash = rsi_hash(item); | 288 | int hash = rsi_hash(item); |
290 | 289 | ||
291 | ch = sunrpc_cache_lookup(&rsi_cache, &item->h, hash); | 290 | ch = sunrpc_cache_lookup(cd, &item->h, hash); |
292 | if (ch) | 291 | if (ch) |
293 | return container_of(ch, struct rsi, h); | 292 | return container_of(ch, struct rsi, h); |
294 | else | 293 | else |
295 | return NULL; | 294 | return NULL; |
296 | } | 295 | } |
297 | 296 | ||
298 | static struct rsi *rsi_update(struct rsi *new, struct rsi *old) | 297 | static struct rsi *rsi_update(struct cache_detail *cd, struct rsi *new, struct rsi *old) |
299 | { | 298 | { |
300 | struct cache_head *ch; | 299 | struct cache_head *ch; |
301 | int hash = rsi_hash(new); | 300 | int hash = rsi_hash(new); |
302 | 301 | ||
303 | ch = sunrpc_cache_update(&rsi_cache, &new->h, | 302 | ch = sunrpc_cache_update(cd, &new->h, |
304 | &old->h, hash); | 303 | &old->h, hash); |
305 | if (ch) | 304 | if (ch) |
306 | return container_of(ch, struct rsi, h); | 305 | return container_of(ch, struct rsi, h); |
@@ -339,10 +338,8 @@ struct rsc { | |||
339 | char *client_name; | 338 | char *client_name; |
340 | }; | 339 | }; |
341 | 340 | ||
342 | static struct cache_head *rsc_table[RSC_HASHMAX]; | 341 | static struct rsc *rsc_update(struct cache_detail *cd, struct rsc *new, struct rsc *old); |
343 | static struct cache_detail rsc_cache; | 342 | static struct rsc *rsc_lookup(struct cache_detail *cd, struct rsc *item); |
344 | static struct rsc *rsc_update(struct rsc *new, struct rsc *old); | ||
345 | static struct rsc *rsc_lookup(struct rsc *item); | ||
346 | 343 | ||
347 | static void rsc_free(struct rsc *rsci) | 344 | static void rsc_free(struct rsc *rsci) |
348 | { | 345 | { |
@@ -444,7 +441,7 @@ static int rsc_parse(struct cache_detail *cd, | |||
444 | if (expiry == 0) | 441 | if (expiry == 0) |
445 | goto out; | 442 | goto out; |
446 | 443 | ||
447 | rscp = rsc_lookup(&rsci); | 444 | rscp = rsc_lookup(cd, &rsci); |
448 | if (!rscp) | 445 | if (!rscp) |
449 | goto out; | 446 | goto out; |
450 | 447 | ||
@@ -506,22 +503,21 @@ static int rsc_parse(struct cache_detail *cd, | |||
506 | 503 | ||
507 | } | 504 | } |
508 | rsci.h.expiry_time = expiry; | 505 | rsci.h.expiry_time = expiry; |
509 | rscp = rsc_update(&rsci, rscp); | 506 | rscp = rsc_update(cd, &rsci, rscp); |
510 | status = 0; | 507 | status = 0; |
511 | out: | 508 | out: |
512 | gss_mech_put(gm); | 509 | gss_mech_put(gm); |
513 | rsc_free(&rsci); | 510 | rsc_free(&rsci); |
514 | if (rscp) | 511 | if (rscp) |
515 | cache_put(&rscp->h, &rsc_cache); | 512 | cache_put(&rscp->h, cd); |
516 | else | 513 | else |
517 | status = -ENOMEM; | 514 | status = -ENOMEM; |
518 | return status; | 515 | return status; |
519 | } | 516 | } |
520 | 517 | ||
521 | static struct cache_detail rsc_cache = { | 518 | static struct cache_detail rsc_cache_template = { |
522 | .owner = THIS_MODULE, | 519 | .owner = THIS_MODULE, |
523 | .hash_size = RSC_HASHMAX, | 520 | .hash_size = RSC_HASHMAX, |
524 | .hash_table = rsc_table, | ||
525 | .name = "auth.rpcsec.context", | 521 | .name = "auth.rpcsec.context", |
526 | .cache_put = rsc_put, | 522 | .cache_put = rsc_put, |
527 | .cache_parse = rsc_parse, | 523 | .cache_parse = rsc_parse, |
@@ -531,24 +527,24 @@ static struct cache_detail rsc_cache = { | |||
531 | .alloc = rsc_alloc, | 527 | .alloc = rsc_alloc, |
532 | }; | 528 | }; |
533 | 529 | ||
534 | static struct rsc *rsc_lookup(struct rsc *item) | 530 | static struct rsc *rsc_lookup(struct cache_detail *cd, struct rsc *item) |
535 | { | 531 | { |
536 | struct cache_head *ch; | 532 | struct cache_head *ch; |
537 | int hash = rsc_hash(item); | 533 | int hash = rsc_hash(item); |
538 | 534 | ||
539 | ch = sunrpc_cache_lookup(&rsc_cache, &item->h, hash); | 535 | ch = sunrpc_cache_lookup(cd, &item->h, hash); |
540 | if (ch) | 536 | if (ch) |
541 | return container_of(ch, struct rsc, h); | 537 | return container_of(ch, struct rsc, h); |
542 | else | 538 | else |
543 | return NULL; | 539 | return NULL; |
544 | } | 540 | } |
545 | 541 | ||
546 | static struct rsc *rsc_update(struct rsc *new, struct rsc *old) | 542 | static struct rsc *rsc_update(struct cache_detail *cd, struct rsc *new, struct rsc *old) |
547 | { | 543 | { |
548 | struct cache_head *ch; | 544 | struct cache_head *ch; |
549 | int hash = rsc_hash(new); | 545 | int hash = rsc_hash(new); |
550 | 546 | ||
551 | ch = sunrpc_cache_update(&rsc_cache, &new->h, | 547 | ch = sunrpc_cache_update(cd, &new->h, |
552 | &old->h, hash); | 548 | &old->h, hash); |
553 | if (ch) | 549 | if (ch) |
554 | return container_of(ch, struct rsc, h); | 550 | return container_of(ch, struct rsc, h); |
@@ -558,7 +554,7 @@ static struct rsc *rsc_update(struct rsc *new, struct rsc *old) | |||
558 | 554 | ||
559 | 555 | ||
560 | static struct rsc * | 556 | static struct rsc * |
561 | gss_svc_searchbyctx(struct xdr_netobj *handle) | 557 | gss_svc_searchbyctx(struct cache_detail *cd, struct xdr_netobj *handle) |
562 | { | 558 | { |
563 | struct rsc rsci; | 559 | struct rsc rsci; |
564 | struct rsc *found; | 560 | struct rsc *found; |
@@ -566,11 +562,11 @@ gss_svc_searchbyctx(struct xdr_netobj *handle) | |||
566 | memset(&rsci, 0, sizeof(rsci)); | 562 | memset(&rsci, 0, sizeof(rsci)); |
567 | if (dup_to_netobj(&rsci.handle, handle->data, handle->len)) | 563 | if (dup_to_netobj(&rsci.handle, handle->data, handle->len)) |
568 | return NULL; | 564 | return NULL; |
569 | found = rsc_lookup(&rsci); | 565 | found = rsc_lookup(cd, &rsci); |
570 | rsc_free(&rsci); | 566 | rsc_free(&rsci); |
571 | if (!found) | 567 | if (!found) |
572 | return NULL; | 568 | return NULL; |
573 | if (cache_check(&rsc_cache, &found->h, NULL)) | 569 | if (cache_check(cd, &found->h, NULL)) |
574 | return NULL; | 570 | return NULL; |
575 | return found; | 571 | return found; |
576 | } | 572 | } |
@@ -968,20 +964,20 @@ svcauth_gss_set_client(struct svc_rqst *rqstp) | |||
968 | } | 964 | } |
969 | 965 | ||
970 | static inline int | 966 | static inline int |
971 | gss_write_init_verf(struct svc_rqst *rqstp, struct rsi *rsip) | 967 | gss_write_init_verf(struct cache_detail *cd, struct svc_rqst *rqstp, struct rsi *rsip) |
972 | { | 968 | { |
973 | struct rsc *rsci; | 969 | struct rsc *rsci; |
974 | int rc; | 970 | int rc; |
975 | 971 | ||
976 | if (rsip->major_status != GSS_S_COMPLETE) | 972 | if (rsip->major_status != GSS_S_COMPLETE) |
977 | return gss_write_null_verf(rqstp); | 973 | return gss_write_null_verf(rqstp); |
978 | rsci = gss_svc_searchbyctx(&rsip->out_handle); | 974 | rsci = gss_svc_searchbyctx(cd, &rsip->out_handle); |
979 | if (rsci == NULL) { | 975 | if (rsci == NULL) { |
980 | rsip->major_status = GSS_S_NO_CONTEXT; | 976 | rsip->major_status = GSS_S_NO_CONTEXT; |
981 | return gss_write_null_verf(rqstp); | 977 | return gss_write_null_verf(rqstp); |
982 | } | 978 | } |
983 | rc = gss_write_verf(rqstp, rsci->mechctx, GSS_SEQ_WIN); | 979 | rc = gss_write_verf(rqstp, rsci->mechctx, GSS_SEQ_WIN); |
984 | cache_put(&rsci->h, &rsc_cache); | 980 | cache_put(&rsci->h, cd); |
985 | return rc; | 981 | return rc; |
986 | } | 982 | } |
987 | 983 | ||
@@ -1000,6 +996,7 @@ static int svcauth_gss_handle_init(struct svc_rqst *rqstp, | |||
1000 | struct xdr_netobj tmpobj; | 996 | struct xdr_netobj tmpobj; |
1001 | struct rsi *rsip, rsikey; | 997 | struct rsi *rsip, rsikey; |
1002 | int ret; | 998 | int ret; |
999 | struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, sunrpc_net_id); | ||
1003 | 1000 | ||
1004 | /* Read the verifier; should be NULL: */ | 1001 | /* Read the verifier; should be NULL: */ |
1005 | *authp = rpc_autherr_badverf; | 1002 | *authp = rpc_autherr_badverf; |
@@ -1028,17 +1025,17 @@ static int svcauth_gss_handle_init(struct svc_rqst *rqstp, | |||
1028 | } | 1025 | } |
1029 | 1026 | ||
1030 | /* Perform upcall, or find upcall result: */ | 1027 | /* Perform upcall, or find upcall result: */ |
1031 | rsip = rsi_lookup(&rsikey); | 1028 | rsip = rsi_lookup(sn->rsi_cache, &rsikey); |
1032 | rsi_free(&rsikey); | 1029 | rsi_free(&rsikey); |
1033 | if (!rsip) | 1030 | if (!rsip) |
1034 | return SVC_CLOSE; | 1031 | return SVC_CLOSE; |
1035 | if (cache_check(&rsi_cache, &rsip->h, &rqstp->rq_chandle) < 0) | 1032 | if (cache_check(sn->rsi_cache, &rsip->h, &rqstp->rq_chandle) < 0) |
1036 | /* No upcall result: */ | 1033 | /* No upcall result: */ |
1037 | return SVC_CLOSE; | 1034 | return SVC_CLOSE; |
1038 | 1035 | ||
1039 | ret = SVC_CLOSE; | 1036 | ret = SVC_CLOSE; |
1040 | /* Got an answer to the upcall; use it: */ | 1037 | /* Got an answer to the upcall; use it: */ |
1041 | if (gss_write_init_verf(rqstp, rsip)) | 1038 | if (gss_write_init_verf(sn->rsc_cache, rqstp, rsip)) |
1042 | goto out; | 1039 | goto out; |
1043 | if (resv->iov_len + 4 > PAGE_SIZE) | 1040 | if (resv->iov_len + 4 > PAGE_SIZE) |
1044 | goto out; | 1041 | goto out; |
@@ -1055,7 +1052,7 @@ static int svcauth_gss_handle_init(struct svc_rqst *rqstp, | |||
1055 | 1052 | ||
1056 | ret = SVC_COMPLETE; | 1053 | ret = SVC_COMPLETE; |
1057 | out: | 1054 | out: |
1058 | cache_put(&rsip->h, &rsi_cache); | 1055 | cache_put(&rsip->h, sn->rsi_cache); |
1059 | return ret; | 1056 | return ret; |
1060 | } | 1057 | } |
1061 | 1058 | ||
@@ -1079,6 +1076,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
1079 | __be32 *rpcstart; | 1076 | __be32 *rpcstart; |
1080 | __be32 *reject_stat = resv->iov_base + resv->iov_len; | 1077 | __be32 *reject_stat = resv->iov_base + resv->iov_len; |
1081 | int ret; | 1078 | int ret; |
1079 | struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, sunrpc_net_id); | ||
1082 | 1080 | ||
1083 | dprintk("RPC: svcauth_gss: argv->iov_len = %zd\n", | 1081 | dprintk("RPC: svcauth_gss: argv->iov_len = %zd\n", |
1084 | argv->iov_len); | 1082 | argv->iov_len); |
@@ -1129,7 +1127,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
1129 | case RPC_GSS_PROC_DESTROY: | 1127 | case RPC_GSS_PROC_DESTROY: |
1130 | /* Look up the context, and check the verifier: */ | 1128 | /* Look up the context, and check the verifier: */ |
1131 | *authp = rpcsec_gsserr_credproblem; | 1129 | *authp = rpcsec_gsserr_credproblem; |
1132 | rsci = gss_svc_searchbyctx(&gc->gc_ctx); | 1130 | rsci = gss_svc_searchbyctx(sn->rsc_cache, &gc->gc_ctx); |
1133 | if (!rsci) | 1131 | if (!rsci) |
1134 | goto auth_err; | 1132 | goto auth_err; |
1135 | switch (gss_verify_header(rqstp, rsci, rpcstart, gc, authp)) { | 1133 | switch (gss_verify_header(rqstp, rsci, rpcstart, gc, authp)) { |
@@ -1209,7 +1207,7 @@ drop: | |||
1209 | ret = SVC_DROP; | 1207 | ret = SVC_DROP; |
1210 | out: | 1208 | out: |
1211 | if (rsci) | 1209 | if (rsci) |
1212 | cache_put(&rsci->h, &rsc_cache); | 1210 | cache_put(&rsci->h, sn->rsc_cache); |
1213 | return ret; | 1211 | return ret; |
1214 | } | 1212 | } |
1215 | 1213 | ||
@@ -1362,6 +1360,7 @@ svcauth_gss_release(struct svc_rqst *rqstp) | |||
1362 | struct rpc_gss_wire_cred *gc = &gsd->clcred; | 1360 | struct rpc_gss_wire_cred *gc = &gsd->clcred; |
1363 | struct xdr_buf *resbuf = &rqstp->rq_res; | 1361 | struct xdr_buf *resbuf = &rqstp->rq_res; |
1364 | int stat = -EINVAL; | 1362 | int stat = -EINVAL; |
1363 | struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, sunrpc_net_id); | ||
1365 | 1364 | ||
1366 | if (gc->gc_proc != RPC_GSS_PROC_DATA) | 1365 | if (gc->gc_proc != RPC_GSS_PROC_DATA) |
1367 | goto out; | 1366 | goto out; |
@@ -1404,7 +1403,7 @@ out_err: | |||
1404 | put_group_info(rqstp->rq_cred.cr_group_info); | 1403 | put_group_info(rqstp->rq_cred.cr_group_info); |
1405 | rqstp->rq_cred.cr_group_info = NULL; | 1404 | rqstp->rq_cred.cr_group_info = NULL; |
1406 | if (gsd->rsci) | 1405 | if (gsd->rsci) |
1407 | cache_put(&gsd->rsci->h, &rsc_cache); | 1406 | cache_put(&gsd->rsci->h, sn->rsc_cache); |
1408 | gsd->rsci = NULL; | 1407 | gsd->rsci = NULL; |
1409 | 1408 | ||
1410 | return stat; | 1409 | return stat; |
@@ -1429,30 +1428,96 @@ static struct auth_ops svcauthops_gss = { | |||
1429 | .set_client = svcauth_gss_set_client, | 1428 | .set_client = svcauth_gss_set_client, |
1430 | }; | 1429 | }; |
1431 | 1430 | ||
1431 | static int rsi_cache_create_net(struct net *net) | ||
1432 | { | ||
1433 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
1434 | struct cache_detail *cd; | ||
1435 | int err; | ||
1436 | |||
1437 | cd = cache_create_net(&rsi_cache_template, net); | ||
1438 | if (IS_ERR(cd)) | ||
1439 | return PTR_ERR(cd); | ||
1440 | err = cache_register_net(cd, net); | ||
1441 | if (err) { | ||
1442 | cache_destroy_net(cd, net); | ||
1443 | return err; | ||
1444 | } | ||
1445 | sn->rsi_cache = cd; | ||
1446 | return 0; | ||
1447 | } | ||
1448 | |||
1449 | static void rsi_cache_destroy_net(struct net *net) | ||
1450 | { | ||
1451 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
1452 | struct cache_detail *cd = sn->rsi_cache; | ||
1453 | |||
1454 | sn->rsi_cache = NULL; | ||
1455 | cache_purge(cd); | ||
1456 | cache_unregister_net(cd, net); | ||
1457 | cache_destroy_net(cd, net); | ||
1458 | } | ||
1459 | |||
1460 | static int rsc_cache_create_net(struct net *net) | ||
1461 | { | ||
1462 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
1463 | struct cache_detail *cd; | ||
1464 | int err; | ||
1465 | |||
1466 | cd = cache_create_net(&rsc_cache_template, net); | ||
1467 | if (IS_ERR(cd)) | ||
1468 | return PTR_ERR(cd); | ||
1469 | err = cache_register_net(cd, net); | ||
1470 | if (err) { | ||
1471 | cache_destroy_net(cd, net); | ||
1472 | return err; | ||
1473 | } | ||
1474 | sn->rsc_cache = cd; | ||
1475 | return 0; | ||
1476 | } | ||
1477 | |||
1478 | static void rsc_cache_destroy_net(struct net *net) | ||
1479 | { | ||
1480 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
1481 | struct cache_detail *cd = sn->rsc_cache; | ||
1482 | |||
1483 | sn->rsc_cache = NULL; | ||
1484 | cache_purge(cd); | ||
1485 | cache_unregister_net(cd, net); | ||
1486 | cache_destroy_net(cd, net); | ||
1487 | } | ||
1488 | |||
1432 | int | 1489 | int |
1433 | gss_svc_init(void) | 1490 | gss_svc_init_net(struct net *net) |
1434 | { | 1491 | { |
1435 | int rv = svc_auth_register(RPC_AUTH_GSS, &svcauthops_gss); | 1492 | int rv; |
1493 | |||
1494 | rv = rsc_cache_create_net(net); | ||
1436 | if (rv) | 1495 | if (rv) |
1437 | return rv; | 1496 | return rv; |
1438 | rv = cache_register(&rsc_cache); | 1497 | rv = rsi_cache_create_net(net); |
1439 | if (rv) | 1498 | if (rv) |
1440 | goto out1; | 1499 | goto out1; |
1441 | rv = cache_register(&rsi_cache); | ||
1442 | if (rv) | ||
1443 | goto out2; | ||
1444 | return 0; | 1500 | return 0; |
1445 | out2: | ||
1446 | cache_unregister(&rsc_cache); | ||
1447 | out1: | 1501 | out1: |
1448 | svc_auth_unregister(RPC_AUTH_GSS); | 1502 | rsc_cache_destroy_net(net); |
1449 | return rv; | 1503 | return rv; |
1450 | } | 1504 | } |
1451 | 1505 | ||
1452 | void | 1506 | void |
1507 | gss_svc_shutdown_net(struct net *net) | ||
1508 | { | ||
1509 | rsi_cache_destroy_net(net); | ||
1510 | rsc_cache_destroy_net(net); | ||
1511 | } | ||
1512 | |||
1513 | int | ||
1514 | gss_svc_init(void) | ||
1515 | { | ||
1516 | return svc_auth_register(RPC_AUTH_GSS, &svcauthops_gss); | ||
1517 | } | ||
1518 | |||
1519 | void | ||
1453 | gss_svc_shutdown(void) | 1520 | gss_svc_shutdown(void) |
1454 | { | 1521 | { |
1455 | cache_unregister(&rsc_cache); | ||
1456 | cache_unregister(&rsi_cache); | ||
1457 | svc_auth_unregister(RPC_AUTH_GSS); | 1522 | svc_auth_unregister(RPC_AUTH_GSS); |
1458 | } | 1523 | } |
diff --git a/net/sunrpc/backchannel_rqst.c b/net/sunrpc/backchannel_rqst.c index 3ad435a14ada..31def68a0f6e 100644 --- a/net/sunrpc/backchannel_rqst.c +++ b/net/sunrpc/backchannel_rqst.c | |||
@@ -25,6 +25,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
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> | 27 | #include <linux/export.h> |
28 | #include <linux/sunrpc/bc_xprt.h> | ||
28 | 29 | ||
29 | #ifdef RPC_DEBUG | 30 | #ifdef RPC_DEBUG |
30 | #define RPCDBG_FACILITY RPCDBG_TRANS | 31 | #define RPCDBG_FACILITY RPCDBG_TRANS |
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 8c6598e0334a..de0b0f39d9d8 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 | static void sunrpc_init_cache_detail(struct cache_detail *cd) | 347 | 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,8 +360,9 @@ static 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); | ||
363 | 364 | ||
364 | static void sunrpc_destroy_cache_detail(struct cache_detail *cd) | 365 | void sunrpc_destroy_cache_detail(struct cache_detail *cd) |
365 | { | 366 | { |
366 | cache_purge(cd); | 367 | cache_purge(cd); |
367 | spin_lock(&cache_list_lock); | 368 | spin_lock(&cache_list_lock); |
@@ -384,6 +385,7 @@ static void sunrpc_destroy_cache_detail(struct cache_detail *cd) | |||
384 | out: | 385 | out: |
385 | printk(KERN_ERR "nfsd: failed to unregister %s cache\n", cd->name); | 386 | printk(KERN_ERR "nfsd: failed to unregister %s cache\n", cd->name); |
386 | } | 387 | } |
388 | EXPORT_SYMBOL_GPL(sunrpc_destroy_cache_detail); | ||
387 | 389 | ||
388 | /* clean cache tries to find something to clean | 390 | /* clean cache tries to find something to clean |
389 | * and cleans it. | 391 | * and cleans it. |
@@ -1645,12 +1647,6 @@ int cache_register_net(struct cache_detail *cd, struct net *net) | |||
1645 | } | 1647 | } |
1646 | EXPORT_SYMBOL_GPL(cache_register_net); | 1648 | EXPORT_SYMBOL_GPL(cache_register_net); |
1647 | 1649 | ||
1648 | int cache_register(struct cache_detail *cd) | ||
1649 | { | ||
1650 | return cache_register_net(cd, &init_net); | ||
1651 | } | ||
1652 | EXPORT_SYMBOL_GPL(cache_register); | ||
1653 | |||
1654 | void cache_unregister_net(struct cache_detail *cd, struct net *net) | 1650 | void cache_unregister_net(struct cache_detail *cd, struct net *net) |
1655 | { | 1651 | { |
1656 | remove_cache_proc_entries(cd, net); | 1652 | remove_cache_proc_entries(cd, net); |
@@ -1658,11 +1654,31 @@ void cache_unregister_net(struct cache_detail *cd, struct net *net) | |||
1658 | } | 1654 | } |
1659 | EXPORT_SYMBOL_GPL(cache_unregister_net); | 1655 | EXPORT_SYMBOL_GPL(cache_unregister_net); |
1660 | 1656 | ||
1661 | void cache_unregister(struct cache_detail *cd) | 1657 | struct cache_detail *cache_create_net(struct cache_detail *tmpl, struct net *net) |
1658 | { | ||
1659 | struct cache_detail *cd; | ||
1660 | |||
1661 | cd = kmemdup(tmpl, sizeof(struct cache_detail), GFP_KERNEL); | ||
1662 | if (cd == NULL) | ||
1663 | return ERR_PTR(-ENOMEM); | ||
1664 | |||
1665 | cd->hash_table = kzalloc(cd->hash_size * sizeof(struct cache_head *), | ||
1666 | GFP_KERNEL); | ||
1667 | if (cd->hash_table == NULL) { | ||
1668 | kfree(cd); | ||
1669 | return ERR_PTR(-ENOMEM); | ||
1670 | } | ||
1671 | cd->net = net; | ||
1672 | return cd; | ||
1673 | } | ||
1674 | EXPORT_SYMBOL_GPL(cache_create_net); | ||
1675 | |||
1676 | void cache_destroy_net(struct cache_detail *cd, struct net *net) | ||
1662 | { | 1677 | { |
1663 | cache_unregister_net(cd, &init_net); | 1678 | kfree(cd->hash_table); |
1679 | kfree(cd); | ||
1664 | } | 1680 | } |
1665 | EXPORT_SYMBOL_GPL(cache_unregister); | 1681 | EXPORT_SYMBOL_GPL(cache_destroy_net); |
1666 | 1682 | ||
1667 | static ssize_t cache_read_pipefs(struct file *filp, char __user *buf, | 1683 | static ssize_t cache_read_pipefs(struct file *filp, char __user *buf, |
1668 | size_t count, loff_t *ppos) | 1684 | size_t count, loff_t *ppos) |
@@ -1789,17 +1805,14 @@ int sunrpc_cache_register_pipefs(struct dentry *parent, | |||
1789 | struct dentry *dir; | 1805 | struct dentry *dir; |
1790 | int ret = 0; | 1806 | int ret = 0; |
1791 | 1807 | ||
1792 | sunrpc_init_cache_detail(cd); | ||
1793 | q.name = name; | 1808 | q.name = name; |
1794 | q.len = strlen(name); | 1809 | q.len = strlen(name); |
1795 | q.hash = full_name_hash(q.name, q.len); | 1810 | q.hash = full_name_hash(q.name, q.len); |
1796 | dir = rpc_create_cache_dir(parent, &q, umode, cd); | 1811 | dir = rpc_create_cache_dir(parent, &q, umode, cd); |
1797 | if (!IS_ERR(dir)) | 1812 | if (!IS_ERR(dir)) |
1798 | cd->u.pipefs.dir = dir; | 1813 | cd->u.pipefs.dir = dir; |
1799 | else { | 1814 | else |
1800 | sunrpc_destroy_cache_detail(cd); | ||
1801 | ret = PTR_ERR(dir); | 1815 | ret = PTR_ERR(dir); |
1802 | } | ||
1803 | return ret; | 1816 | return ret; |
1804 | } | 1817 | } |
1805 | EXPORT_SYMBOL_GPL(sunrpc_cache_register_pipefs); | 1818 | EXPORT_SYMBOL_GPL(sunrpc_cache_register_pipefs); |
@@ -1808,7 +1821,6 @@ void sunrpc_cache_unregister_pipefs(struct cache_detail *cd) | |||
1808 | { | 1821 | { |
1809 | rpc_remove_cache_dir(cd->u.pipefs.dir); | 1822 | rpc_remove_cache_dir(cd->u.pipefs.dir); |
1810 | cd->u.pipefs.dir = NULL; | 1823 | cd->u.pipefs.dir = NULL; |
1811 | sunrpc_destroy_cache_detail(cd); | ||
1812 | } | 1824 | } |
1813 | EXPORT_SYMBOL_GPL(sunrpc_cache_unregister_pipefs); | 1825 | EXPORT_SYMBOL_GPL(sunrpc_cache_unregister_pipefs); |
1814 | 1826 | ||
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index f0268ea7e711..7a4cb5fdc212 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -31,13 +31,16 @@ | |||
31 | #include <linux/in.h> | 31 | #include <linux/in.h> |
32 | #include <linux/in6.h> | 32 | #include <linux/in6.h> |
33 | #include <linux/un.h> | 33 | #include <linux/un.h> |
34 | #include <linux/rcupdate.h> | ||
34 | 35 | ||
35 | #include <linux/sunrpc/clnt.h> | 36 | #include <linux/sunrpc/clnt.h> |
36 | #include <linux/sunrpc/rpc_pipe_fs.h> | 37 | #include <linux/sunrpc/rpc_pipe_fs.h> |
37 | #include <linux/sunrpc/metrics.h> | 38 | #include <linux/sunrpc/metrics.h> |
38 | #include <linux/sunrpc/bc_xprt.h> | 39 | #include <linux/sunrpc/bc_xprt.h> |
40 | #include <trace/events/sunrpc.h> | ||
39 | 41 | ||
40 | #include "sunrpc.h" | 42 | #include "sunrpc.h" |
43 | #include "netns.h" | ||
41 | 44 | ||
42 | #ifdef RPC_DEBUG | 45 | #ifdef RPC_DEBUG |
43 | # define RPCDBG_FACILITY RPCDBG_CALL | 46 | # define RPCDBG_FACILITY RPCDBG_CALL |
@@ -50,8 +53,6 @@ | |||
50 | /* | 53 | /* |
51 | * All RPC clients are linked into this list | 54 | * All RPC clients are linked into this list |
52 | */ | 55 | */ |
53 | static LIST_HEAD(all_clients); | ||
54 | static DEFINE_SPINLOCK(rpc_client_lock); | ||
55 | 56 | ||
56 | static DECLARE_WAIT_QUEUE_HEAD(destroy_wait); | 57 | static DECLARE_WAIT_QUEUE_HEAD(destroy_wait); |
57 | 58 | ||
@@ -81,82 +82,191 @@ static int rpc_ping(struct rpc_clnt *clnt); | |||
81 | 82 | ||
82 | static void rpc_register_client(struct rpc_clnt *clnt) | 83 | static void rpc_register_client(struct rpc_clnt *clnt) |
83 | { | 84 | { |
84 | spin_lock(&rpc_client_lock); | 85 | struct net *net = rpc_net_ns(clnt); |
85 | list_add(&clnt->cl_clients, &all_clients); | 86 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
86 | spin_unlock(&rpc_client_lock); | 87 | |
88 | spin_lock(&sn->rpc_client_lock); | ||
89 | list_add(&clnt->cl_clients, &sn->all_clients); | ||
90 | spin_unlock(&sn->rpc_client_lock); | ||
87 | } | 91 | } |
88 | 92 | ||
89 | static void rpc_unregister_client(struct rpc_clnt *clnt) | 93 | static void rpc_unregister_client(struct rpc_clnt *clnt) |
90 | { | 94 | { |
91 | spin_lock(&rpc_client_lock); | 95 | struct net *net = rpc_net_ns(clnt); |
96 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
97 | |||
98 | spin_lock(&sn->rpc_client_lock); | ||
92 | list_del(&clnt->cl_clients); | 99 | list_del(&clnt->cl_clients); |
93 | spin_unlock(&rpc_client_lock); | 100 | spin_unlock(&sn->rpc_client_lock); |
94 | } | 101 | } |
95 | 102 | ||
96 | static int | 103 | static void __rpc_clnt_remove_pipedir(struct rpc_clnt *clnt) |
97 | rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name) | 104 | { |
105 | if (clnt->cl_dentry) { | ||
106 | if (clnt->cl_auth && clnt->cl_auth->au_ops->pipes_destroy) | ||
107 | clnt->cl_auth->au_ops->pipes_destroy(clnt->cl_auth); | ||
108 | rpc_remove_client_dir(clnt->cl_dentry); | ||
109 | } | ||
110 | clnt->cl_dentry = NULL; | ||
111 | } | ||
112 | |||
113 | static void rpc_clnt_remove_pipedir(struct rpc_clnt *clnt) | ||
114 | { | ||
115 | struct net *net = rpc_net_ns(clnt); | ||
116 | struct super_block *pipefs_sb; | ||
117 | |||
118 | pipefs_sb = rpc_get_sb_net(net); | ||
119 | if (pipefs_sb) { | ||
120 | __rpc_clnt_remove_pipedir(clnt); | ||
121 | rpc_put_sb_net(net); | ||
122 | } | ||
123 | } | ||
124 | |||
125 | static struct dentry *rpc_setup_pipedir_sb(struct super_block *sb, | ||
126 | struct rpc_clnt *clnt, | ||
127 | const char *dir_name) | ||
98 | { | 128 | { |
99 | static uint32_t clntid; | 129 | static uint32_t clntid; |
100 | struct path path, dir; | ||
101 | char name[15]; | 130 | char name[15]; |
102 | struct qstr q = { | 131 | struct qstr q = { |
103 | .name = name, | 132 | .name = name, |
104 | }; | 133 | }; |
134 | struct dentry *dir, *dentry; | ||
105 | int error; | 135 | int error; |
106 | 136 | ||
107 | clnt->cl_path.mnt = ERR_PTR(-ENOENT); | 137 | dir = rpc_d_lookup_sb(sb, dir_name); |
108 | clnt->cl_path.dentry = ERR_PTR(-ENOENT); | 138 | if (dir == NULL) |
109 | if (dir_name == NULL) | 139 | return dir; |
110 | return 0; | ||
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 | |||
119 | for (;;) { | 140 | for (;;) { |
120 | q.len = snprintf(name, sizeof(name), "clnt%x", (unsigned int)clntid++); | 141 | q.len = snprintf(name, sizeof(name), "clnt%x", (unsigned int)clntid++); |
121 | name[sizeof(name) - 1] = '\0'; | 142 | name[sizeof(name) - 1] = '\0'; |
122 | q.hash = full_name_hash(q.name, q.len); | 143 | q.hash = full_name_hash(q.name, q.len); |
123 | path.dentry = rpc_create_client_dir(dir.dentry, &q, clnt); | 144 | dentry = rpc_create_client_dir(dir, &q, clnt); |
124 | if (!IS_ERR(path.dentry)) | 145 | if (!IS_ERR(dentry)) |
125 | break; | 146 | break; |
126 | error = PTR_ERR(path.dentry); | 147 | error = PTR_ERR(dentry); |
127 | if (error != -EEXIST) { | 148 | if (error != -EEXIST) { |
128 | printk(KERN_INFO "RPC: Couldn't create pipefs entry" | 149 | printk(KERN_INFO "RPC: Couldn't create pipefs entry" |
129 | " %s/%s, error %d\n", | 150 | " %s/%s, error %d\n", |
130 | dir_name, name, error); | 151 | dir_name, name, error); |
131 | goto err_path_put; | 152 | break; |
132 | } | 153 | } |
133 | } | 154 | } |
134 | path_put(&dir); | 155 | dput(dir); |
135 | clnt->cl_path = path; | 156 | return dentry; |
157 | } | ||
158 | |||
159 | static int | ||
160 | rpc_setup_pipedir(struct rpc_clnt *clnt, const char *dir_name) | ||
161 | { | ||
162 | struct net *net = rpc_net_ns(clnt); | ||
163 | struct super_block *pipefs_sb; | ||
164 | struct dentry *dentry; | ||
165 | |||
166 | clnt->cl_dentry = NULL; | ||
167 | if (dir_name == NULL) | ||
168 | return 0; | ||
169 | pipefs_sb = rpc_get_sb_net(net); | ||
170 | if (!pipefs_sb) | ||
171 | return 0; | ||
172 | dentry = rpc_setup_pipedir_sb(pipefs_sb, clnt, dir_name); | ||
173 | rpc_put_sb_net(net); | ||
174 | if (IS_ERR(dentry)) | ||
175 | return PTR_ERR(dentry); | ||
176 | clnt->cl_dentry = dentry; | ||
136 | return 0; | 177 | return 0; |
137 | err_path_put: | 178 | } |
138 | path_put(&dir); | 179 | |
139 | err: | 180 | static int __rpc_pipefs_event(struct rpc_clnt *clnt, unsigned long event, |
140 | rpc_put_mount(); | 181 | struct super_block *sb) |
182 | { | ||
183 | struct dentry *dentry; | ||
184 | int err = 0; | ||
185 | |||
186 | switch (event) { | ||
187 | case RPC_PIPEFS_MOUNT: | ||
188 | if (clnt->cl_program->pipe_dir_name == NULL) | ||
189 | break; | ||
190 | dentry = rpc_setup_pipedir_sb(sb, clnt, | ||
191 | clnt->cl_program->pipe_dir_name); | ||
192 | BUG_ON(dentry == NULL); | ||
193 | if (IS_ERR(dentry)) | ||
194 | return PTR_ERR(dentry); | ||
195 | clnt->cl_dentry = dentry; | ||
196 | if (clnt->cl_auth->au_ops->pipes_create) { | ||
197 | err = clnt->cl_auth->au_ops->pipes_create(clnt->cl_auth); | ||
198 | if (err) | ||
199 | __rpc_clnt_remove_pipedir(clnt); | ||
200 | } | ||
201 | break; | ||
202 | case RPC_PIPEFS_UMOUNT: | ||
203 | __rpc_clnt_remove_pipedir(clnt); | ||
204 | break; | ||
205 | default: | ||
206 | printk(KERN_ERR "%s: unknown event: %ld\n", __func__, event); | ||
207 | return -ENOTSUPP; | ||
208 | } | ||
209 | return err; | ||
210 | } | ||
211 | |||
212 | static struct rpc_clnt *rpc_get_client_for_event(struct net *net, int event) | ||
213 | { | ||
214 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
215 | struct rpc_clnt *clnt; | ||
216 | |||
217 | spin_lock(&sn->rpc_client_lock); | ||
218 | list_for_each_entry(clnt, &sn->all_clients, cl_clients) { | ||
219 | if (((event == RPC_PIPEFS_MOUNT) && clnt->cl_dentry) || | ||
220 | ((event == RPC_PIPEFS_UMOUNT) && !clnt->cl_dentry)) | ||
221 | continue; | ||
222 | atomic_inc(&clnt->cl_count); | ||
223 | spin_unlock(&sn->rpc_client_lock); | ||
224 | return clnt; | ||
225 | } | ||
226 | spin_unlock(&sn->rpc_client_lock); | ||
227 | return NULL; | ||
228 | } | ||
229 | |||
230 | static int rpc_pipefs_event(struct notifier_block *nb, unsigned long event, | ||
231 | void *ptr) | ||
232 | { | ||
233 | struct super_block *sb = ptr; | ||
234 | struct rpc_clnt *clnt; | ||
235 | int error = 0; | ||
236 | |||
237 | while ((clnt = rpc_get_client_for_event(sb->s_fs_info, event))) { | ||
238 | error = __rpc_pipefs_event(clnt, event, sb); | ||
239 | rpc_release_client(clnt); | ||
240 | if (error) | ||
241 | break; | ||
242 | } | ||
141 | return error; | 243 | return error; |
142 | } | 244 | } |
143 | 245 | ||
246 | static struct notifier_block rpc_clients_block = { | ||
247 | .notifier_call = rpc_pipefs_event, | ||
248 | .priority = SUNRPC_PIPEFS_RPC_PRIO, | ||
249 | }; | ||
250 | |||
251 | int rpc_clients_notifier_register(void) | ||
252 | { | ||
253 | return rpc_pipefs_notifier_register(&rpc_clients_block); | ||
254 | } | ||
255 | |||
256 | void rpc_clients_notifier_unregister(void) | ||
257 | { | ||
258 | return rpc_pipefs_notifier_unregister(&rpc_clients_block); | ||
259 | } | ||
260 | |||
144 | static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, struct rpc_xprt *xprt) | 261 | static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, struct rpc_xprt *xprt) |
145 | { | 262 | { |
146 | struct rpc_program *program = args->program; | 263 | const struct rpc_program *program = args->program; |
147 | struct rpc_version *version; | 264 | const struct rpc_version *version; |
148 | struct rpc_clnt *clnt = NULL; | 265 | struct rpc_clnt *clnt = NULL; |
149 | struct rpc_auth *auth; | 266 | struct rpc_auth *auth; |
150 | int err; | 267 | int err; |
151 | size_t len; | ||
152 | 268 | ||
153 | /* sanity check the name before trying to print it */ | 269 | /* 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 | |||
160 | dprintk("RPC: creating %s client for %s (xprt %p)\n", | 270 | dprintk("RPC: creating %s client for %s (xprt %p)\n", |
161 | program->name, args->servername, xprt); | 271 | program->name, args->servername, xprt); |
162 | 272 | ||
@@ -179,17 +289,7 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru | |||
179 | goto out_err; | 289 | goto out_err; |
180 | clnt->cl_parent = clnt; | 290 | clnt->cl_parent = clnt; |
181 | 291 | ||
182 | clnt->cl_server = clnt->cl_inline_name; | 292 | rcu_assign_pointer(clnt->cl_xprt, xprt); |
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; | ||
193 | clnt->cl_procinfo = version->procs; | 293 | clnt->cl_procinfo = version->procs; |
194 | clnt->cl_maxproc = version->nrprocs; | 294 | clnt->cl_maxproc = version->nrprocs; |
195 | clnt->cl_protname = program->name; | 295 | clnt->cl_protname = program->name; |
@@ -204,7 +304,7 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru | |||
204 | INIT_LIST_HEAD(&clnt->cl_tasks); | 304 | INIT_LIST_HEAD(&clnt->cl_tasks); |
205 | spin_lock_init(&clnt->cl_lock); | 305 | spin_lock_init(&clnt->cl_lock); |
206 | 306 | ||
207 | if (!xprt_bound(clnt->cl_xprt)) | 307 | if (!xprt_bound(xprt)) |
208 | clnt->cl_autobind = 1; | 308 | clnt->cl_autobind = 1; |
209 | 309 | ||
210 | clnt->cl_timeout = xprt->timeout; | 310 | clnt->cl_timeout = xprt->timeout; |
@@ -246,17 +346,12 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru | |||
246 | return clnt; | 346 | return clnt; |
247 | 347 | ||
248 | out_no_auth: | 348 | out_no_auth: |
249 | if (!IS_ERR(clnt->cl_path.dentry)) { | 349 | rpc_clnt_remove_pipedir(clnt); |
250 | rpc_remove_client_dir(clnt->cl_path.dentry); | ||
251 | rpc_put_mount(); | ||
252 | } | ||
253 | out_no_path: | 350 | out_no_path: |
254 | kfree(clnt->cl_principal); | 351 | kfree(clnt->cl_principal); |
255 | out_no_principal: | 352 | out_no_principal: |
256 | rpc_free_iostats(clnt->cl_metrics); | 353 | rpc_free_iostats(clnt->cl_metrics); |
257 | out_no_stats: | 354 | out_no_stats: |
258 | if (clnt->cl_server != clnt->cl_inline_name) | ||
259 | kfree(clnt->cl_server); | ||
260 | kfree(clnt); | 355 | kfree(clnt); |
261 | out_err: | 356 | out_err: |
262 | xprt_put(xprt); | 357 | xprt_put(xprt); |
@@ -286,6 +381,7 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args) | |||
286 | .srcaddr = args->saddress, | 381 | .srcaddr = args->saddress, |
287 | .dstaddr = args->address, | 382 | .dstaddr = args->address, |
288 | .addrlen = args->addrsize, | 383 | .addrlen = args->addrsize, |
384 | .servername = args->servername, | ||
289 | .bc_xprt = args->bc_xprt, | 385 | .bc_xprt = args->bc_xprt, |
290 | }; | 386 | }; |
291 | char servername[48]; | 387 | char servername[48]; |
@@ -294,7 +390,7 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args) | |||
294 | * If the caller chooses not to specify a hostname, whip | 390 | * If the caller chooses not to specify a hostname, whip |
295 | * up a string representation of the passed-in address. | 391 | * up a string representation of the passed-in address. |
296 | */ | 392 | */ |
297 | if (args->servername == NULL) { | 393 | if (xprtargs.servername == NULL) { |
298 | struct sockaddr_un *sun = | 394 | struct sockaddr_un *sun = |
299 | (struct sockaddr_un *)args->address; | 395 | (struct sockaddr_un *)args->address; |
300 | struct sockaddr_in *sin = | 396 | struct sockaddr_in *sin = |
@@ -321,7 +417,7 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args) | |||
321 | * address family isn't recognized. */ | 417 | * address family isn't recognized. */ |
322 | return ERR_PTR(-EINVAL); | 418 | return ERR_PTR(-EINVAL); |
323 | } | 419 | } |
324 | args->servername = servername; | 420 | xprtargs.servername = servername; |
325 | } | 421 | } |
326 | 422 | ||
327 | xprt = xprt_create_transport(&xprtargs); | 423 | xprt = xprt_create_transport(&xprtargs); |
@@ -374,6 +470,7 @@ struct rpc_clnt * | |||
374 | rpc_clone_client(struct rpc_clnt *clnt) | 470 | rpc_clone_client(struct rpc_clnt *clnt) |
375 | { | 471 | { |
376 | struct rpc_clnt *new; | 472 | struct rpc_clnt *new; |
473 | struct rpc_xprt *xprt; | ||
377 | int err = -ENOMEM; | 474 | int err = -ENOMEM; |
378 | 475 | ||
379 | new = kmemdup(clnt, sizeof(*new), GFP_KERNEL); | 476 | new = kmemdup(clnt, sizeof(*new), GFP_KERNEL); |
@@ -393,18 +490,25 @@ rpc_clone_client(struct rpc_clnt *clnt) | |||
393 | if (new->cl_principal == NULL) | 490 | if (new->cl_principal == NULL) |
394 | goto out_no_principal; | 491 | goto out_no_principal; |
395 | } | 492 | } |
493 | rcu_read_lock(); | ||
494 | xprt = xprt_get(rcu_dereference(clnt->cl_xprt)); | ||
495 | rcu_read_unlock(); | ||
496 | if (xprt == NULL) | ||
497 | goto out_no_transport; | ||
498 | rcu_assign_pointer(new->cl_xprt, xprt); | ||
396 | atomic_set(&new->cl_count, 1); | 499 | atomic_set(&new->cl_count, 1); |
397 | err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name); | 500 | err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name); |
398 | if (err != 0) | 501 | if (err != 0) |
399 | goto out_no_path; | 502 | goto out_no_path; |
400 | if (new->cl_auth) | 503 | if (new->cl_auth) |
401 | atomic_inc(&new->cl_auth->au_count); | 504 | atomic_inc(&new->cl_auth->au_count); |
402 | xprt_get(clnt->cl_xprt); | ||
403 | atomic_inc(&clnt->cl_count); | 505 | atomic_inc(&clnt->cl_count); |
404 | rpc_register_client(new); | 506 | rpc_register_client(new); |
405 | rpciod_up(); | 507 | rpciod_up(); |
406 | return new; | 508 | return new; |
407 | out_no_path: | 509 | out_no_path: |
510 | xprt_put(xprt); | ||
511 | out_no_transport: | ||
408 | kfree(new->cl_principal); | 512 | kfree(new->cl_principal); |
409 | out_no_principal: | 513 | out_no_principal: |
410 | rpc_free_iostats(new->cl_metrics); | 514 | rpc_free_iostats(new->cl_metrics); |
@@ -453,8 +557,9 @@ EXPORT_SYMBOL_GPL(rpc_killall_tasks); | |||
453 | */ | 557 | */ |
454 | void rpc_shutdown_client(struct rpc_clnt *clnt) | 558 | void rpc_shutdown_client(struct rpc_clnt *clnt) |
455 | { | 559 | { |
456 | dprintk("RPC: shutting down %s client for %s\n", | 560 | dprintk_rcu("RPC: shutting down %s client for %s\n", |
457 | clnt->cl_protname, clnt->cl_server); | 561 | clnt->cl_protname, |
562 | rcu_dereference(clnt->cl_xprt)->servername); | ||
458 | 563 | ||
459 | while (!list_empty(&clnt->cl_tasks)) { | 564 | while (!list_empty(&clnt->cl_tasks)) { |
460 | rpc_killall_tasks(clnt); | 565 | rpc_killall_tasks(clnt); |
@@ -472,24 +577,17 @@ EXPORT_SYMBOL_GPL(rpc_shutdown_client); | |||
472 | static void | 577 | static void |
473 | rpc_free_client(struct rpc_clnt *clnt) | 578 | rpc_free_client(struct rpc_clnt *clnt) |
474 | { | 579 | { |
475 | dprintk("RPC: destroying %s client for %s\n", | 580 | dprintk_rcu("RPC: destroying %s client for %s\n", |
476 | clnt->cl_protname, clnt->cl_server); | 581 | clnt->cl_protname, |
477 | if (!IS_ERR(clnt->cl_path.dentry)) { | 582 | rcu_dereference(clnt->cl_xprt)->servername); |
478 | rpc_remove_client_dir(clnt->cl_path.dentry); | 583 | if (clnt->cl_parent != clnt) |
479 | rpc_put_mount(); | ||
480 | } | ||
481 | if (clnt->cl_parent != clnt) { | ||
482 | rpc_release_client(clnt->cl_parent); | 584 | 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: | ||
488 | rpc_unregister_client(clnt); | 585 | rpc_unregister_client(clnt); |
586 | rpc_clnt_remove_pipedir(clnt); | ||
489 | rpc_free_iostats(clnt->cl_metrics); | 587 | rpc_free_iostats(clnt->cl_metrics); |
490 | kfree(clnt->cl_principal); | 588 | kfree(clnt->cl_principal); |
491 | clnt->cl_metrics = NULL; | 589 | clnt->cl_metrics = NULL; |
492 | xprt_put(clnt->cl_xprt); | 590 | xprt_put(rcu_dereference_raw(clnt->cl_xprt)); |
493 | rpciod_down(); | 591 | rpciod_down(); |
494 | kfree(clnt); | 592 | kfree(clnt); |
495 | } | 593 | } |
@@ -542,11 +640,11 @@ rpc_release_client(struct rpc_clnt *clnt) | |||
542 | * The Sun NFSv2/v3 ACL protocol can do this. | 640 | * The Sun NFSv2/v3 ACL protocol can do this. |
543 | */ | 641 | */ |
544 | struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old, | 642 | struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old, |
545 | struct rpc_program *program, | 643 | const struct rpc_program *program, |
546 | u32 vers) | 644 | u32 vers) |
547 | { | 645 | { |
548 | struct rpc_clnt *clnt; | 646 | struct rpc_clnt *clnt; |
549 | struct rpc_version *version; | 647 | const struct rpc_version *version; |
550 | int err; | 648 | int err; |
551 | 649 | ||
552 | BUG_ON(vers >= program->nrvers || !program->version[vers]); | 650 | BUG_ON(vers >= program->nrvers || !program->version[vers]); |
@@ -778,13 +876,18 @@ EXPORT_SYMBOL_GPL(rpc_call_start); | |||
778 | size_t rpc_peeraddr(struct rpc_clnt *clnt, struct sockaddr *buf, size_t bufsize) | 876 | size_t rpc_peeraddr(struct rpc_clnt *clnt, struct sockaddr *buf, size_t bufsize) |
779 | { | 877 | { |
780 | size_t bytes; | 878 | size_t bytes; |
781 | struct rpc_xprt *xprt = clnt->cl_xprt; | 879 | struct rpc_xprt *xprt; |
782 | 880 | ||
783 | bytes = sizeof(xprt->addr); | 881 | rcu_read_lock(); |
882 | xprt = rcu_dereference(clnt->cl_xprt); | ||
883 | |||
884 | bytes = xprt->addrlen; | ||
784 | if (bytes > bufsize) | 885 | if (bytes > bufsize) |
785 | bytes = bufsize; | 886 | bytes = bufsize; |
786 | memcpy(buf, &clnt->cl_xprt->addr, bytes); | 887 | memcpy(buf, &xprt->addr, bytes); |
787 | return xprt->addrlen; | 888 | rcu_read_unlock(); |
889 | |||
890 | return bytes; | ||
788 | } | 891 | } |
789 | EXPORT_SYMBOL_GPL(rpc_peeraddr); | 892 | EXPORT_SYMBOL_GPL(rpc_peeraddr); |
790 | 893 | ||
@@ -793,11 +896,16 @@ EXPORT_SYMBOL_GPL(rpc_peeraddr); | |||
793 | * @clnt: RPC client structure | 896 | * @clnt: RPC client structure |
794 | * @format: address format | 897 | * @format: address format |
795 | * | 898 | * |
899 | * NB: the lifetime of the memory referenced by the returned pointer is | ||
900 | * the same as the rpc_xprt itself. As long as the caller uses this | ||
901 | * pointer, it must hold the RCU read lock. | ||
796 | */ | 902 | */ |
797 | const char *rpc_peeraddr2str(struct rpc_clnt *clnt, | 903 | const char *rpc_peeraddr2str(struct rpc_clnt *clnt, |
798 | enum rpc_display_format_t format) | 904 | enum rpc_display_format_t format) |
799 | { | 905 | { |
800 | struct rpc_xprt *xprt = clnt->cl_xprt; | 906 | struct rpc_xprt *xprt; |
907 | |||
908 | xprt = rcu_dereference(clnt->cl_xprt); | ||
801 | 909 | ||
802 | if (xprt->address_strings[format] != NULL) | 910 | if (xprt->address_strings[format] != NULL) |
803 | return xprt->address_strings[format]; | 911 | return xprt->address_strings[format]; |
@@ -806,17 +914,203 @@ const char *rpc_peeraddr2str(struct rpc_clnt *clnt, | |||
806 | } | 914 | } |
807 | EXPORT_SYMBOL_GPL(rpc_peeraddr2str); | 915 | EXPORT_SYMBOL_GPL(rpc_peeraddr2str); |
808 | 916 | ||
917 | static const struct sockaddr_in rpc_inaddr_loopback = { | ||
918 | .sin_family = AF_INET, | ||
919 | .sin_addr.s_addr = htonl(INADDR_ANY), | ||
920 | }; | ||
921 | |||
922 | static const struct sockaddr_in6 rpc_in6addr_loopback = { | ||
923 | .sin6_family = AF_INET6, | ||
924 | .sin6_addr = IN6ADDR_ANY_INIT, | ||
925 | }; | ||
926 | |||
927 | /* | ||
928 | * Try a getsockname() on a connected datagram socket. Using a | ||
929 | * connected datagram socket prevents leaving a socket in TIME_WAIT. | ||
930 | * This conserves the ephemeral port number space. | ||
931 | * | ||
932 | * Returns zero and fills in "buf" if successful; otherwise, a | ||
933 | * negative errno is returned. | ||
934 | */ | ||
935 | static int rpc_sockname(struct net *net, struct sockaddr *sap, size_t salen, | ||
936 | struct sockaddr *buf, int buflen) | ||
937 | { | ||
938 | struct socket *sock; | ||
939 | int err; | ||
940 | |||
941 | err = __sock_create(net, sap->sa_family, | ||
942 | SOCK_DGRAM, IPPROTO_UDP, &sock, 1); | ||
943 | if (err < 0) { | ||
944 | dprintk("RPC: can't create UDP socket (%d)\n", err); | ||
945 | goto out; | ||
946 | } | ||
947 | |||
948 | switch (sap->sa_family) { | ||
949 | case AF_INET: | ||
950 | err = kernel_bind(sock, | ||
951 | (struct sockaddr *)&rpc_inaddr_loopback, | ||
952 | sizeof(rpc_inaddr_loopback)); | ||
953 | break; | ||
954 | case AF_INET6: | ||
955 | err = kernel_bind(sock, | ||
956 | (struct sockaddr *)&rpc_in6addr_loopback, | ||
957 | sizeof(rpc_in6addr_loopback)); | ||
958 | break; | ||
959 | default: | ||
960 | err = -EAFNOSUPPORT; | ||
961 | goto out; | ||
962 | } | ||
963 | if (err < 0) { | ||
964 | dprintk("RPC: can't bind UDP socket (%d)\n", err); | ||
965 | goto out_release; | ||
966 | } | ||
967 | |||
968 | err = kernel_connect(sock, sap, salen, 0); | ||
969 | if (err < 0) { | ||
970 | dprintk("RPC: can't connect UDP socket (%d)\n", err); | ||
971 | goto out_release; | ||
972 | } | ||
973 | |||
974 | err = kernel_getsockname(sock, buf, &buflen); | ||
975 | if (err < 0) { | ||
976 | dprintk("RPC: getsockname failed (%d)\n", err); | ||
977 | goto out_release; | ||
978 | } | ||
979 | |||
980 | err = 0; | ||
981 | if (buf->sa_family == AF_INET6) { | ||
982 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)buf; | ||
983 | sin6->sin6_scope_id = 0; | ||
984 | } | ||
985 | dprintk("RPC: %s succeeded\n", __func__); | ||
986 | |||
987 | out_release: | ||
988 | sock_release(sock); | ||
989 | out: | ||
990 | return err; | ||
991 | } | ||
992 | |||
993 | /* | ||
994 | * Scraping a connected socket failed, so we don't have a useable | ||
995 | * local address. Fallback: generate an address that will prevent | ||
996 | * the server from calling us back. | ||
997 | * | ||
998 | * Returns zero and fills in "buf" if successful; otherwise, a | ||
999 | * negative errno is returned. | ||
1000 | */ | ||
1001 | static int rpc_anyaddr(int family, struct sockaddr *buf, size_t buflen) | ||
1002 | { | ||
1003 | switch (family) { | ||
1004 | case AF_INET: | ||
1005 | if (buflen < sizeof(rpc_inaddr_loopback)) | ||
1006 | return -EINVAL; | ||
1007 | memcpy(buf, &rpc_inaddr_loopback, | ||
1008 | sizeof(rpc_inaddr_loopback)); | ||
1009 | break; | ||
1010 | case AF_INET6: | ||
1011 | if (buflen < sizeof(rpc_in6addr_loopback)) | ||
1012 | return -EINVAL; | ||
1013 | memcpy(buf, &rpc_in6addr_loopback, | ||
1014 | sizeof(rpc_in6addr_loopback)); | ||
1015 | default: | ||
1016 | dprintk("RPC: %s: address family not supported\n", | ||
1017 | __func__); | ||
1018 | return -EAFNOSUPPORT; | ||
1019 | } | ||
1020 | dprintk("RPC: %s: succeeded\n", __func__); | ||
1021 | return 0; | ||
1022 | } | ||
1023 | |||
1024 | /** | ||
1025 | * rpc_localaddr - discover local endpoint address for an RPC client | ||
1026 | * @clnt: RPC client structure | ||
1027 | * @buf: target buffer | ||
1028 | * @buflen: size of target buffer, in bytes | ||
1029 | * | ||
1030 | * Returns zero and fills in "buf" and "buflen" if successful; | ||
1031 | * otherwise, a negative errno is returned. | ||
1032 | * | ||
1033 | * This works even if the underlying transport is not currently connected, | ||
1034 | * or if the upper layer never previously provided a source address. | ||
1035 | * | ||
1036 | * The result of this function call is transient: multiple calls in | ||
1037 | * succession may give different results, depending on how local | ||
1038 | * networking configuration changes over time. | ||
1039 | */ | ||
1040 | int rpc_localaddr(struct rpc_clnt *clnt, struct sockaddr *buf, size_t buflen) | ||
1041 | { | ||
1042 | struct sockaddr_storage address; | ||
1043 | struct sockaddr *sap = (struct sockaddr *)&address; | ||
1044 | struct rpc_xprt *xprt; | ||
1045 | struct net *net; | ||
1046 | size_t salen; | ||
1047 | int err; | ||
1048 | |||
1049 | rcu_read_lock(); | ||
1050 | xprt = rcu_dereference(clnt->cl_xprt); | ||
1051 | salen = xprt->addrlen; | ||
1052 | memcpy(sap, &xprt->addr, salen); | ||
1053 | net = get_net(xprt->xprt_net); | ||
1054 | rcu_read_unlock(); | ||
1055 | |||
1056 | rpc_set_port(sap, 0); | ||
1057 | err = rpc_sockname(net, sap, salen, buf, buflen); | ||
1058 | put_net(net); | ||
1059 | if (err != 0) | ||
1060 | /* Couldn't discover local address, return ANYADDR */ | ||
1061 | return rpc_anyaddr(sap->sa_family, buf, buflen); | ||
1062 | return 0; | ||
1063 | } | ||
1064 | EXPORT_SYMBOL_GPL(rpc_localaddr); | ||
1065 | |||
809 | void | 1066 | void |
810 | rpc_setbufsize(struct rpc_clnt *clnt, unsigned int sndsize, unsigned int rcvsize) | 1067 | rpc_setbufsize(struct rpc_clnt *clnt, unsigned int sndsize, unsigned int rcvsize) |
811 | { | 1068 | { |
812 | struct rpc_xprt *xprt = clnt->cl_xprt; | 1069 | struct rpc_xprt *xprt; |
1070 | |||
1071 | rcu_read_lock(); | ||
1072 | xprt = rcu_dereference(clnt->cl_xprt); | ||
813 | if (xprt->ops->set_buffer_size) | 1073 | if (xprt->ops->set_buffer_size) |
814 | xprt->ops->set_buffer_size(xprt, sndsize, rcvsize); | 1074 | xprt->ops->set_buffer_size(xprt, sndsize, rcvsize); |
1075 | rcu_read_unlock(); | ||
815 | } | 1076 | } |
816 | EXPORT_SYMBOL_GPL(rpc_setbufsize); | 1077 | EXPORT_SYMBOL_GPL(rpc_setbufsize); |
817 | 1078 | ||
818 | /* | 1079 | /** |
819 | * Return size of largest payload RPC client can support, in bytes | 1080 | * rpc_protocol - Get transport protocol number for an RPC client |
1081 | * @clnt: RPC client to query | ||
1082 | * | ||
1083 | */ | ||
1084 | int rpc_protocol(struct rpc_clnt *clnt) | ||
1085 | { | ||
1086 | int protocol; | ||
1087 | |||
1088 | rcu_read_lock(); | ||
1089 | protocol = rcu_dereference(clnt->cl_xprt)->prot; | ||
1090 | rcu_read_unlock(); | ||
1091 | return protocol; | ||
1092 | } | ||
1093 | EXPORT_SYMBOL_GPL(rpc_protocol); | ||
1094 | |||
1095 | /** | ||
1096 | * rpc_net_ns - Get the network namespace for this RPC client | ||
1097 | * @clnt: RPC client to query | ||
1098 | * | ||
1099 | */ | ||
1100 | struct net *rpc_net_ns(struct rpc_clnt *clnt) | ||
1101 | { | ||
1102 | struct net *ret; | ||
1103 | |||
1104 | rcu_read_lock(); | ||
1105 | ret = rcu_dereference(clnt->cl_xprt)->xprt_net; | ||
1106 | rcu_read_unlock(); | ||
1107 | return ret; | ||
1108 | } | ||
1109 | EXPORT_SYMBOL_GPL(rpc_net_ns); | ||
1110 | |||
1111 | /** | ||
1112 | * rpc_max_payload - Get maximum payload size for a transport, in bytes | ||
1113 | * @clnt: RPC client to query | ||
820 | * | 1114 | * |
821 | * For stream transports, this is one RPC record fragment (see RFC | 1115 | * For stream transports, this is one RPC record fragment (see RFC |
822 | * 1831), as we don't support multi-record requests yet. For datagram | 1116 | * 1831), as we don't support multi-record requests yet. For datagram |
@@ -825,7 +1119,12 @@ EXPORT_SYMBOL_GPL(rpc_setbufsize); | |||
825 | */ | 1119 | */ |
826 | size_t rpc_max_payload(struct rpc_clnt *clnt) | 1120 | size_t rpc_max_payload(struct rpc_clnt *clnt) |
827 | { | 1121 | { |
828 | return clnt->cl_xprt->max_payload; | 1122 | size_t ret; |
1123 | |||
1124 | rcu_read_lock(); | ||
1125 | ret = rcu_dereference(clnt->cl_xprt)->max_payload; | ||
1126 | rcu_read_unlock(); | ||
1127 | return ret; | ||
829 | } | 1128 | } |
830 | EXPORT_SYMBOL_GPL(rpc_max_payload); | 1129 | EXPORT_SYMBOL_GPL(rpc_max_payload); |
831 | 1130 | ||
@@ -836,8 +1135,11 @@ EXPORT_SYMBOL_GPL(rpc_max_payload); | |||
836 | */ | 1135 | */ |
837 | void rpc_force_rebind(struct rpc_clnt *clnt) | 1136 | void rpc_force_rebind(struct rpc_clnt *clnt) |
838 | { | 1137 | { |
839 | if (clnt->cl_autobind) | 1138 | if (clnt->cl_autobind) { |
840 | xprt_clear_bound(clnt->cl_xprt); | 1139 | rcu_read_lock(); |
1140 | xprt_clear_bound(rcu_dereference(clnt->cl_xprt)); | ||
1141 | rcu_read_unlock(); | ||
1142 | } | ||
841 | } | 1143 | } |
842 | EXPORT_SYMBOL_GPL(rpc_force_rebind); | 1144 | EXPORT_SYMBOL_GPL(rpc_force_rebind); |
843 | 1145 | ||
@@ -1163,6 +1465,7 @@ call_bind_status(struct rpc_task *task) | |||
1163 | return; | 1465 | return; |
1164 | } | 1466 | } |
1165 | 1467 | ||
1468 | trace_rpc_bind_status(task); | ||
1166 | switch (task->tk_status) { | 1469 | switch (task->tk_status) { |
1167 | case -ENOMEM: | 1470 | case -ENOMEM: |
1168 | dprintk("RPC: %5u rpcbind out of memory\n", task->tk_pid); | 1471 | dprintk("RPC: %5u rpcbind out of memory\n", task->tk_pid); |
@@ -1262,6 +1565,7 @@ call_connect_status(struct rpc_task *task) | |||
1262 | return; | 1565 | return; |
1263 | } | 1566 | } |
1264 | 1567 | ||
1568 | trace_rpc_connect_status(task, status); | ||
1265 | switch (status) { | 1569 | switch (status) { |
1266 | /* if soft mounted, test if we've timed out */ | 1570 | /* if soft mounted, test if we've timed out */ |
1267 | case -ETIMEDOUT: | 1571 | case -ETIMEDOUT: |
@@ -1450,6 +1754,7 @@ call_status(struct rpc_task *task) | |||
1450 | return; | 1754 | return; |
1451 | } | 1755 | } |
1452 | 1756 | ||
1757 | trace_rpc_call_status(task); | ||
1453 | task->tk_status = 0; | 1758 | task->tk_status = 0; |
1454 | switch(status) { | 1759 | switch(status) { |
1455 | case -EHOSTDOWN: | 1760 | case -EHOSTDOWN: |
@@ -1513,8 +1818,11 @@ call_timeout(struct rpc_task *task) | |||
1513 | } | 1818 | } |
1514 | if (RPC_IS_SOFT(task)) { | 1819 | if (RPC_IS_SOFT(task)) { |
1515 | if (clnt->cl_chatty) | 1820 | if (clnt->cl_chatty) |
1821 | rcu_read_lock(); | ||
1516 | printk(KERN_NOTICE "%s: server %s not responding, timed out\n", | 1822 | printk(KERN_NOTICE "%s: server %s not responding, timed out\n", |
1517 | clnt->cl_protname, clnt->cl_server); | 1823 | clnt->cl_protname, |
1824 | rcu_dereference(clnt->cl_xprt)->servername); | ||
1825 | rcu_read_unlock(); | ||
1518 | if (task->tk_flags & RPC_TASK_TIMEOUT) | 1826 | if (task->tk_flags & RPC_TASK_TIMEOUT) |
1519 | rpc_exit(task, -ETIMEDOUT); | 1827 | rpc_exit(task, -ETIMEDOUT); |
1520 | else | 1828 | else |
@@ -1524,9 +1832,13 @@ call_timeout(struct rpc_task *task) | |||
1524 | 1832 | ||
1525 | if (!(task->tk_flags & RPC_CALL_MAJORSEEN)) { | 1833 | if (!(task->tk_flags & RPC_CALL_MAJORSEEN)) { |
1526 | task->tk_flags |= RPC_CALL_MAJORSEEN; | 1834 | task->tk_flags |= RPC_CALL_MAJORSEEN; |
1527 | if (clnt->cl_chatty) | 1835 | if (clnt->cl_chatty) { |
1836 | rcu_read_lock(); | ||
1528 | printk(KERN_NOTICE "%s: server %s not responding, still trying\n", | 1837 | printk(KERN_NOTICE "%s: server %s not responding, still trying\n", |
1529 | clnt->cl_protname, clnt->cl_server); | 1838 | clnt->cl_protname, |
1839 | rcu_dereference(clnt->cl_xprt)->servername); | ||
1840 | rcu_read_unlock(); | ||
1841 | } | ||
1530 | } | 1842 | } |
1531 | rpc_force_rebind(clnt); | 1843 | rpc_force_rebind(clnt); |
1532 | /* | 1844 | /* |
@@ -1555,9 +1867,13 @@ call_decode(struct rpc_task *task) | |||
1555 | dprint_status(task); | 1867 | dprint_status(task); |
1556 | 1868 | ||
1557 | if (task->tk_flags & RPC_CALL_MAJORSEEN) { | 1869 | if (task->tk_flags & RPC_CALL_MAJORSEEN) { |
1558 | if (clnt->cl_chatty) | 1870 | if (clnt->cl_chatty) { |
1871 | rcu_read_lock(); | ||
1559 | printk(KERN_NOTICE "%s: server %s OK\n", | 1872 | printk(KERN_NOTICE "%s: server %s OK\n", |
1560 | clnt->cl_protname, clnt->cl_server); | 1873 | clnt->cl_protname, |
1874 | rcu_dereference(clnt->cl_xprt)->servername); | ||
1875 | rcu_read_unlock(); | ||
1876 | } | ||
1561 | task->tk_flags &= ~RPC_CALL_MAJORSEEN; | 1877 | task->tk_flags &= ~RPC_CALL_MAJORSEEN; |
1562 | } | 1878 | } |
1563 | 1879 | ||
@@ -1635,6 +1951,7 @@ rpc_encode_header(struct rpc_task *task) | |||
1635 | static __be32 * | 1951 | static __be32 * |
1636 | rpc_verify_header(struct rpc_task *task) | 1952 | rpc_verify_header(struct rpc_task *task) |
1637 | { | 1953 | { |
1954 | struct rpc_clnt *clnt = task->tk_client; | ||
1638 | struct kvec *iov = &task->tk_rqstp->rq_rcv_buf.head[0]; | 1955 | struct kvec *iov = &task->tk_rqstp->rq_rcv_buf.head[0]; |
1639 | int len = task->tk_rqstp->rq_rcv_buf.len >> 2; | 1956 | int len = task->tk_rqstp->rq_rcv_buf.len >> 2; |
1640 | __be32 *p = iov->iov_base; | 1957 | __be32 *p = iov->iov_base; |
@@ -1707,8 +2024,11 @@ rpc_verify_header(struct rpc_task *task) | |||
1707 | task->tk_action = call_bind; | 2024 | task->tk_action = call_bind; |
1708 | goto out_retry; | 2025 | goto out_retry; |
1709 | case RPC_AUTH_TOOWEAK: | 2026 | case RPC_AUTH_TOOWEAK: |
2027 | rcu_read_lock(); | ||
1710 | printk(KERN_NOTICE "RPC: server %s requires stronger " | 2028 | printk(KERN_NOTICE "RPC: server %s requires stronger " |
1711 | "authentication.\n", task->tk_client->cl_server); | 2029 | "authentication.\n", |
2030 | rcu_dereference(clnt->cl_xprt)->servername); | ||
2031 | rcu_read_unlock(); | ||
1712 | break; | 2032 | break; |
1713 | default: | 2033 | default: |
1714 | dprintk("RPC: %5u %s: unknown auth error: %x\n", | 2034 | dprintk("RPC: %5u %s: unknown auth error: %x\n", |
@@ -1731,28 +2051,27 @@ rpc_verify_header(struct rpc_task *task) | |||
1731 | case RPC_SUCCESS: | 2051 | case RPC_SUCCESS: |
1732 | return p; | 2052 | return p; |
1733 | case RPC_PROG_UNAVAIL: | 2053 | case RPC_PROG_UNAVAIL: |
1734 | dprintk("RPC: %5u %s: program %u is unsupported by server %s\n", | 2054 | dprintk_rcu("RPC: %5u %s: program %u is unsupported " |
1735 | task->tk_pid, __func__, | 2055 | "by server %s\n", task->tk_pid, __func__, |
1736 | (unsigned int)task->tk_client->cl_prog, | 2056 | (unsigned int)clnt->cl_prog, |
1737 | task->tk_client->cl_server); | 2057 | rcu_dereference(clnt->cl_xprt)->servername); |
1738 | error = -EPFNOSUPPORT; | 2058 | error = -EPFNOSUPPORT; |
1739 | goto out_err; | 2059 | goto out_err; |
1740 | case RPC_PROG_MISMATCH: | 2060 | case RPC_PROG_MISMATCH: |
1741 | dprintk("RPC: %5u %s: program %u, version %u unsupported by " | 2061 | dprintk_rcu("RPC: %5u %s: program %u, version %u unsupported " |
1742 | "server %s\n", task->tk_pid, __func__, | 2062 | "by server %s\n", task->tk_pid, __func__, |
1743 | (unsigned int)task->tk_client->cl_prog, | 2063 | (unsigned int)clnt->cl_prog, |
1744 | (unsigned int)task->tk_client->cl_vers, | 2064 | (unsigned int)clnt->cl_vers, |
1745 | task->tk_client->cl_server); | 2065 | rcu_dereference(clnt->cl_xprt)->servername); |
1746 | error = -EPROTONOSUPPORT; | 2066 | error = -EPROTONOSUPPORT; |
1747 | goto out_err; | 2067 | goto out_err; |
1748 | case RPC_PROC_UNAVAIL: | 2068 | case RPC_PROC_UNAVAIL: |
1749 | dprintk("RPC: %5u %s: proc %s unsupported by program %u, " | 2069 | dprintk_rcu("RPC: %5u %s: proc %s unsupported by program %u, " |
1750 | "version %u on server %s\n", | 2070 | "version %u on server %s\n", |
1751 | task->tk_pid, __func__, | 2071 | task->tk_pid, __func__, |
1752 | rpc_proc_name(task), | 2072 | rpc_proc_name(task), |
1753 | task->tk_client->cl_prog, | 2073 | clnt->cl_prog, clnt->cl_vers, |
1754 | task->tk_client->cl_vers, | 2074 | rcu_dereference(clnt->cl_xprt)->servername); |
1755 | task->tk_client->cl_server); | ||
1756 | error = -EOPNOTSUPP; | 2075 | error = -EOPNOTSUPP; |
1757 | goto out_err; | 2076 | goto out_err; |
1758 | case RPC_GARBAGE_ARGS: | 2077 | case RPC_GARBAGE_ARGS: |
@@ -1766,7 +2085,7 @@ rpc_verify_header(struct rpc_task *task) | |||
1766 | } | 2085 | } |
1767 | 2086 | ||
1768 | out_garbage: | 2087 | out_garbage: |
1769 | task->tk_client->cl_stats->rpcgarbage++; | 2088 | clnt->cl_stats->rpcgarbage++; |
1770 | if (task->tk_garb_retry) { | 2089 | if (task->tk_garb_retry) { |
1771 | task->tk_garb_retry--; | 2090 | task->tk_garb_retry--; |
1772 | dprintk("RPC: %5u %s: retrying\n", | 2091 | dprintk("RPC: %5u %s: retrying\n", |
@@ -1852,14 +2171,15 @@ static void rpc_show_task(const struct rpc_clnt *clnt, | |||
1852 | task->tk_action, rpc_waitq); | 2171 | task->tk_action, rpc_waitq); |
1853 | } | 2172 | } |
1854 | 2173 | ||
1855 | void rpc_show_tasks(void) | 2174 | void rpc_show_tasks(struct net *net) |
1856 | { | 2175 | { |
1857 | struct rpc_clnt *clnt; | 2176 | struct rpc_clnt *clnt; |
1858 | struct rpc_task *task; | 2177 | struct rpc_task *task; |
1859 | int header = 0; | 2178 | int header = 0; |
2179 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
1860 | 2180 | ||
1861 | spin_lock(&rpc_client_lock); | 2181 | spin_lock(&sn->rpc_client_lock); |
1862 | list_for_each_entry(clnt, &all_clients, cl_clients) { | 2182 | list_for_each_entry(clnt, &sn->all_clients, cl_clients) { |
1863 | spin_lock(&clnt->cl_lock); | 2183 | spin_lock(&clnt->cl_lock); |
1864 | list_for_each_entry(task, &clnt->cl_tasks, tk_task) { | 2184 | list_for_each_entry(task, &clnt->cl_tasks, tk_task) { |
1865 | if (!header) { | 2185 | if (!header) { |
@@ -1870,6 +2190,6 @@ void rpc_show_tasks(void) | |||
1870 | } | 2190 | } |
1871 | spin_unlock(&clnt->cl_lock); | 2191 | spin_unlock(&clnt->cl_lock); |
1872 | } | 2192 | } |
1873 | spin_unlock(&rpc_client_lock); | 2193 | spin_unlock(&sn->rpc_client_lock); |
1874 | } | 2194 | } |
1875 | #endif | 2195 | #endif |
diff --git a/net/sunrpc/netns.h b/net/sunrpc/netns.h index d013bf211cae..ce7bd449173d 100644 --- a/net/sunrpc/netns.h +++ b/net/sunrpc/netns.h | |||
@@ -9,6 +9,20 @@ 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; | ||
12 | }; | 26 | }; |
13 | 27 | ||
14 | extern int sunrpc_net_id; | 28 | extern int sunrpc_net_id; |
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 63a7a7add21e..8584ec068e97 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> | ||
19 | 20 | ||
20 | #include <asm/ioctls.h> | 21 | #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,9 +27,15 @@ | |||
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> | ||
30 | 32 | ||
31 | static struct vfsmount *rpc_mnt __read_mostly; | 33 | #include "netns.h" |
32 | static int rpc_mount_count; | 34 | #include "sunrpc.h" |
35 | |||
36 | #define RPCDBG_FACILITY RPCDBG_DEBUG | ||
37 | |||
38 | #define NET_NAME(net) ((net == &init_net) ? " (init_net)" : "") | ||
33 | 39 | ||
34 | static struct file_system_type rpc_pipe_fs_type; | 40 | static struct file_system_type rpc_pipe_fs_type; |
35 | 41 | ||
@@ -38,7 +44,21 @@ static struct kmem_cache *rpc_inode_cachep __read_mostly; | |||
38 | 44 | ||
39 | #define RPC_UPCALL_TIMEOUT (30*HZ) | 45 | #define RPC_UPCALL_TIMEOUT (30*HZ) |
40 | 46 | ||
41 | static void rpc_purge_list(struct rpc_inode *rpci, struct list_head *head, | 47 | static BLOCKING_NOTIFIER_HEAD(rpc_pipefs_notifier_list); |
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, | ||
42 | void (*destroy_msg)(struct rpc_pipe_msg *), int err) | 62 | void (*destroy_msg)(struct rpc_pipe_msg *), int err) |
43 | { | 63 | { |
44 | struct rpc_pipe_msg *msg; | 64 | struct rpc_pipe_msg *msg; |
@@ -51,30 +71,31 @@ static void rpc_purge_list(struct rpc_inode *rpci, struct list_head *head, | |||
51 | msg->errno = err; | 71 | msg->errno = err; |
52 | destroy_msg(msg); | 72 | destroy_msg(msg); |
53 | } while (!list_empty(head)); | 73 | } while (!list_empty(head)); |
54 | wake_up(&rpci->waitq); | 74 | wake_up(waitq); |
55 | } | 75 | } |
56 | 76 | ||
57 | static void | 77 | static void |
58 | rpc_timeout_upcall_queue(struct work_struct *work) | 78 | rpc_timeout_upcall_queue(struct work_struct *work) |
59 | { | 79 | { |
60 | LIST_HEAD(free_list); | 80 | LIST_HEAD(free_list); |
61 | struct rpc_inode *rpci = | 81 | struct rpc_pipe *pipe = |
62 | container_of(work, struct rpc_inode, queue_timeout.work); | 82 | container_of(work, struct rpc_pipe, queue_timeout.work); |
63 | struct inode *inode = &rpci->vfs_inode; | ||
64 | void (*destroy_msg)(struct rpc_pipe_msg *); | 83 | void (*destroy_msg)(struct rpc_pipe_msg *); |
84 | struct dentry *dentry; | ||
65 | 85 | ||
66 | spin_lock(&inode->i_lock); | 86 | spin_lock(&pipe->lock); |
67 | if (rpci->ops == NULL) { | 87 | destroy_msg = pipe->ops->destroy_msg; |
68 | spin_unlock(&inode->i_lock); | 88 | if (pipe->nreaders == 0) { |
69 | return; | 89 | list_splice_init(&pipe->pipe, &free_list); |
90 | pipe->pipelen = 0; | ||
70 | } | 91 | } |
71 | destroy_msg = rpci->ops->destroy_msg; | 92 | dentry = dget(pipe->dentry); |
72 | if (rpci->nreaders == 0) { | 93 | spin_unlock(&pipe->lock); |
73 | list_splice_init(&rpci->pipe, &free_list); | 94 | if (dentry) { |
74 | rpci->pipelen = 0; | 95 | rpc_purge_list(&RPC_I(dentry->d_inode)->waitq, |
96 | &free_list, destroy_msg, -ETIMEDOUT); | ||
97 | dput(dentry); | ||
75 | } | 98 | } |
76 | spin_unlock(&inode->i_lock); | ||
77 | rpc_purge_list(rpci, &free_list, destroy_msg, -ETIMEDOUT); | ||
78 | } | 99 | } |
79 | 100 | ||
80 | ssize_t rpc_pipe_generic_upcall(struct file *filp, struct rpc_pipe_msg *msg, | 101 | ssize_t rpc_pipe_generic_upcall(struct file *filp, struct rpc_pipe_msg *msg, |
@@ -108,30 +129,31 @@ EXPORT_SYMBOL_GPL(rpc_pipe_generic_upcall); | |||
108 | * initialize the fields of @msg (other than @msg->list) appropriately. | 129 | * initialize the fields of @msg (other than @msg->list) appropriately. |
109 | */ | 130 | */ |
110 | int | 131 | int |
111 | rpc_queue_upcall(struct inode *inode, struct rpc_pipe_msg *msg) | 132 | rpc_queue_upcall(struct rpc_pipe *pipe, struct rpc_pipe_msg *msg) |
112 | { | 133 | { |
113 | struct rpc_inode *rpci = RPC_I(inode); | ||
114 | int res = -EPIPE; | 134 | int res = -EPIPE; |
135 | struct dentry *dentry; | ||
115 | 136 | ||
116 | spin_lock(&inode->i_lock); | 137 | spin_lock(&pipe->lock); |
117 | if (rpci->ops == NULL) | 138 | if (pipe->nreaders) { |
118 | goto out; | 139 | list_add_tail(&msg->list, &pipe->pipe); |
119 | if (rpci->nreaders) { | 140 | pipe->pipelen += msg->len; |
120 | list_add_tail(&msg->list, &rpci->pipe); | ||
121 | rpci->pipelen += msg->len; | ||
122 | res = 0; | 141 | res = 0; |
123 | } else if (rpci->flags & RPC_PIPE_WAIT_FOR_OPEN) { | 142 | } else if (pipe->flags & RPC_PIPE_WAIT_FOR_OPEN) { |
124 | if (list_empty(&rpci->pipe)) | 143 | if (list_empty(&pipe->pipe)) |
125 | queue_delayed_work(rpciod_workqueue, | 144 | queue_delayed_work(rpciod_workqueue, |
126 | &rpci->queue_timeout, | 145 | &pipe->queue_timeout, |
127 | RPC_UPCALL_TIMEOUT); | 146 | RPC_UPCALL_TIMEOUT); |
128 | list_add_tail(&msg->list, &rpci->pipe); | 147 | list_add_tail(&msg->list, &pipe->pipe); |
129 | rpci->pipelen += msg->len; | 148 | pipe->pipelen += msg->len; |
130 | res = 0; | 149 | res = 0; |
131 | } | 150 | } |
132 | out: | 151 | dentry = dget(pipe->dentry); |
133 | spin_unlock(&inode->i_lock); | 152 | spin_unlock(&pipe->lock); |
134 | wake_up(&rpci->waitq); | 153 | if (dentry) { |
154 | wake_up(&RPC_I(dentry->d_inode)->waitq); | ||
155 | dput(dentry); | ||
156 | } | ||
135 | return res; | 157 | return res; |
136 | } | 158 | } |
137 | EXPORT_SYMBOL_GPL(rpc_queue_upcall); | 159 | EXPORT_SYMBOL_GPL(rpc_queue_upcall); |
@@ -145,29 +167,26 @@ rpc_inode_setowner(struct inode *inode, void *private) | |||
145 | static void | 167 | static void |
146 | rpc_close_pipes(struct inode *inode) | 168 | rpc_close_pipes(struct inode *inode) |
147 | { | 169 | { |
148 | struct rpc_inode *rpci = RPC_I(inode); | 170 | struct rpc_pipe *pipe = RPC_I(inode)->pipe; |
149 | const struct rpc_pipe_ops *ops; | ||
150 | int need_release; | 171 | int need_release; |
172 | LIST_HEAD(free_list); | ||
151 | 173 | ||
152 | mutex_lock(&inode->i_mutex); | 174 | mutex_lock(&inode->i_mutex); |
153 | ops = rpci->ops; | 175 | spin_lock(&pipe->lock); |
154 | if (ops != NULL) { | 176 | need_release = pipe->nreaders != 0 || pipe->nwriters != 0; |
155 | LIST_HEAD(free_list); | 177 | pipe->nreaders = 0; |
156 | spin_lock(&inode->i_lock); | 178 | list_splice_init(&pipe->in_upcall, &free_list); |
157 | need_release = rpci->nreaders != 0 || rpci->nwriters != 0; | 179 | list_splice_init(&pipe->pipe, &free_list); |
158 | rpci->nreaders = 0; | 180 | pipe->pipelen = 0; |
159 | list_splice_init(&rpci->in_upcall, &free_list); | 181 | pipe->dentry = NULL; |
160 | list_splice_init(&rpci->pipe, &free_list); | 182 | spin_unlock(&pipe->lock); |
161 | rpci->pipelen = 0; | 183 | rpc_purge_list(&RPC_I(inode)->waitq, &free_list, pipe->ops->destroy_msg, -EPIPE); |
162 | rpci->ops = NULL; | 184 | pipe->nwriters = 0; |
163 | spin_unlock(&inode->i_lock); | 185 | if (need_release && pipe->ops->release_pipe) |
164 | rpc_purge_list(rpci, &free_list, ops->destroy_msg, -EPIPE); | 186 | pipe->ops->release_pipe(inode); |
165 | rpci->nwriters = 0; | 187 | cancel_delayed_work_sync(&pipe->queue_timeout); |
166 | if (need_release && ops->release_pipe) | ||
167 | ops->release_pipe(inode); | ||
168 | cancel_delayed_work_sync(&rpci->queue_timeout); | ||
169 | } | ||
170 | rpc_inode_setowner(inode, NULL); | 188 | rpc_inode_setowner(inode, NULL); |
189 | RPC_I(inode)->pipe = NULL; | ||
171 | mutex_unlock(&inode->i_mutex); | 190 | mutex_unlock(&inode->i_mutex); |
172 | } | 191 | } |
173 | 192 | ||
@@ -197,23 +216,24 @@ rpc_destroy_inode(struct inode *inode) | |||
197 | static int | 216 | static int |
198 | rpc_pipe_open(struct inode *inode, struct file *filp) | 217 | rpc_pipe_open(struct inode *inode, struct file *filp) |
199 | { | 218 | { |
200 | struct rpc_inode *rpci = RPC_I(inode); | 219 | struct rpc_pipe *pipe; |
201 | int first_open; | 220 | int first_open; |
202 | int res = -ENXIO; | 221 | int res = -ENXIO; |
203 | 222 | ||
204 | mutex_lock(&inode->i_mutex); | 223 | mutex_lock(&inode->i_mutex); |
205 | if (rpci->ops == NULL) | 224 | pipe = RPC_I(inode)->pipe; |
225 | if (pipe == NULL) | ||
206 | goto out; | 226 | goto out; |
207 | first_open = rpci->nreaders == 0 && rpci->nwriters == 0; | 227 | first_open = pipe->nreaders == 0 && pipe->nwriters == 0; |
208 | if (first_open && rpci->ops->open_pipe) { | 228 | if (first_open && pipe->ops->open_pipe) { |
209 | res = rpci->ops->open_pipe(inode); | 229 | res = pipe->ops->open_pipe(inode); |
210 | if (res) | 230 | if (res) |
211 | goto out; | 231 | goto out; |
212 | } | 232 | } |
213 | if (filp->f_mode & FMODE_READ) | 233 | if (filp->f_mode & FMODE_READ) |
214 | rpci->nreaders++; | 234 | pipe->nreaders++; |
215 | if (filp->f_mode & FMODE_WRITE) | 235 | if (filp->f_mode & FMODE_WRITE) |
216 | rpci->nwriters++; | 236 | pipe->nwriters++; |
217 | res = 0; | 237 | res = 0; |
218 | out: | 238 | out: |
219 | mutex_unlock(&inode->i_mutex); | 239 | mutex_unlock(&inode->i_mutex); |
@@ -223,38 +243,39 @@ out: | |||
223 | static int | 243 | static int |
224 | rpc_pipe_release(struct inode *inode, struct file *filp) | 244 | rpc_pipe_release(struct inode *inode, struct file *filp) |
225 | { | 245 | { |
226 | struct rpc_inode *rpci = RPC_I(inode); | 246 | struct rpc_pipe *pipe; |
227 | struct rpc_pipe_msg *msg; | 247 | struct rpc_pipe_msg *msg; |
228 | int last_close; | 248 | int last_close; |
229 | 249 | ||
230 | mutex_lock(&inode->i_mutex); | 250 | mutex_lock(&inode->i_mutex); |
231 | if (rpci->ops == NULL) | 251 | pipe = RPC_I(inode)->pipe; |
252 | if (pipe == NULL) | ||
232 | goto out; | 253 | goto out; |
233 | msg = filp->private_data; | 254 | msg = filp->private_data; |
234 | if (msg != NULL) { | 255 | if (msg != NULL) { |
235 | spin_lock(&inode->i_lock); | 256 | spin_lock(&pipe->lock); |
236 | msg->errno = -EAGAIN; | 257 | msg->errno = -EAGAIN; |
237 | list_del_init(&msg->list); | 258 | list_del_init(&msg->list); |
238 | spin_unlock(&inode->i_lock); | 259 | spin_unlock(&pipe->lock); |
239 | rpci->ops->destroy_msg(msg); | 260 | pipe->ops->destroy_msg(msg); |
240 | } | 261 | } |
241 | if (filp->f_mode & FMODE_WRITE) | 262 | if (filp->f_mode & FMODE_WRITE) |
242 | rpci->nwriters --; | 263 | pipe->nwriters --; |
243 | if (filp->f_mode & FMODE_READ) { | 264 | if (filp->f_mode & FMODE_READ) { |
244 | rpci->nreaders --; | 265 | pipe->nreaders --; |
245 | if (rpci->nreaders == 0) { | 266 | if (pipe->nreaders == 0) { |
246 | LIST_HEAD(free_list); | 267 | LIST_HEAD(free_list); |
247 | spin_lock(&inode->i_lock); | 268 | spin_lock(&pipe->lock); |
248 | list_splice_init(&rpci->pipe, &free_list); | 269 | list_splice_init(&pipe->pipe, &free_list); |
249 | rpci->pipelen = 0; | 270 | pipe->pipelen = 0; |
250 | spin_unlock(&inode->i_lock); | 271 | spin_unlock(&pipe->lock); |
251 | rpc_purge_list(rpci, &free_list, | 272 | rpc_purge_list(&RPC_I(inode)->waitq, &free_list, |
252 | rpci->ops->destroy_msg, -EAGAIN); | 273 | pipe->ops->destroy_msg, -EAGAIN); |
253 | } | 274 | } |
254 | } | 275 | } |
255 | last_close = rpci->nwriters == 0 && rpci->nreaders == 0; | 276 | last_close = pipe->nwriters == 0 && pipe->nreaders == 0; |
256 | if (last_close && rpci->ops->release_pipe) | 277 | if (last_close && pipe->ops->release_pipe) |
257 | rpci->ops->release_pipe(inode); | 278 | pipe->ops->release_pipe(inode); |
258 | out: | 279 | out: |
259 | mutex_unlock(&inode->i_mutex); | 280 | mutex_unlock(&inode->i_mutex); |
260 | return 0; | 281 | return 0; |
@@ -264,39 +285,40 @@ static ssize_t | |||
264 | rpc_pipe_read(struct file *filp, char __user *buf, size_t len, loff_t *offset) | 285 | rpc_pipe_read(struct file *filp, char __user *buf, size_t len, loff_t *offset) |
265 | { | 286 | { |
266 | struct inode *inode = filp->f_path.dentry->d_inode; | 287 | struct inode *inode = filp->f_path.dentry->d_inode; |
267 | struct rpc_inode *rpci = RPC_I(inode); | 288 | struct rpc_pipe *pipe; |
268 | struct rpc_pipe_msg *msg; | 289 | struct rpc_pipe_msg *msg; |
269 | int res = 0; | 290 | int res = 0; |
270 | 291 | ||
271 | mutex_lock(&inode->i_mutex); | 292 | mutex_lock(&inode->i_mutex); |
272 | if (rpci->ops == NULL) { | 293 | pipe = RPC_I(inode)->pipe; |
294 | if (pipe == NULL) { | ||
273 | res = -EPIPE; | 295 | res = -EPIPE; |
274 | goto out_unlock; | 296 | goto out_unlock; |
275 | } | 297 | } |
276 | msg = filp->private_data; | 298 | msg = filp->private_data; |
277 | if (msg == NULL) { | 299 | if (msg == NULL) { |
278 | spin_lock(&inode->i_lock); | 300 | spin_lock(&pipe->lock); |
279 | if (!list_empty(&rpci->pipe)) { | 301 | if (!list_empty(&pipe->pipe)) { |
280 | msg = list_entry(rpci->pipe.next, | 302 | msg = list_entry(pipe->pipe.next, |
281 | struct rpc_pipe_msg, | 303 | struct rpc_pipe_msg, |
282 | list); | 304 | list); |
283 | list_move(&msg->list, &rpci->in_upcall); | 305 | list_move(&msg->list, &pipe->in_upcall); |
284 | rpci->pipelen -= msg->len; | 306 | pipe->pipelen -= msg->len; |
285 | filp->private_data = msg; | 307 | filp->private_data = msg; |
286 | msg->copied = 0; | 308 | msg->copied = 0; |
287 | } | 309 | } |
288 | spin_unlock(&inode->i_lock); | 310 | spin_unlock(&pipe->lock); |
289 | if (msg == NULL) | 311 | if (msg == NULL) |
290 | goto out_unlock; | 312 | goto out_unlock; |
291 | } | 313 | } |
292 | /* NOTE: it is up to the callback to update msg->copied */ | 314 | /* NOTE: it is up to the callback to update msg->copied */ |
293 | res = rpci->ops->upcall(filp, msg, buf, len); | 315 | res = pipe->ops->upcall(filp, msg, buf, len); |
294 | if (res < 0 || msg->len == msg->copied) { | 316 | if (res < 0 || msg->len == msg->copied) { |
295 | filp->private_data = NULL; | 317 | filp->private_data = NULL; |
296 | spin_lock(&inode->i_lock); | 318 | spin_lock(&pipe->lock); |
297 | list_del_init(&msg->list); | 319 | list_del_init(&msg->list); |
298 | spin_unlock(&inode->i_lock); | 320 | spin_unlock(&pipe->lock); |
299 | rpci->ops->destroy_msg(msg); | 321 | pipe->ops->destroy_msg(msg); |
300 | } | 322 | } |
301 | out_unlock: | 323 | out_unlock: |
302 | mutex_unlock(&inode->i_mutex); | 324 | mutex_unlock(&inode->i_mutex); |
@@ -307,13 +329,12 @@ static ssize_t | |||
307 | rpc_pipe_write(struct file *filp, const char __user *buf, size_t len, loff_t *offset) | 329 | rpc_pipe_write(struct file *filp, const char __user *buf, size_t len, loff_t *offset) |
308 | { | 330 | { |
309 | struct inode *inode = filp->f_path.dentry->d_inode; | 331 | struct inode *inode = filp->f_path.dentry->d_inode; |
310 | struct rpc_inode *rpci = RPC_I(inode); | ||
311 | int res; | 332 | int res; |
312 | 333 | ||
313 | mutex_lock(&inode->i_mutex); | 334 | mutex_lock(&inode->i_mutex); |
314 | res = -EPIPE; | 335 | res = -EPIPE; |
315 | if (rpci->ops != NULL) | 336 | if (RPC_I(inode)->pipe != NULL) |
316 | res = rpci->ops->downcall(filp, buf, len); | 337 | res = RPC_I(inode)->pipe->ops->downcall(filp, buf, len); |
317 | mutex_unlock(&inode->i_mutex); | 338 | mutex_unlock(&inode->i_mutex); |
318 | return res; | 339 | return res; |
319 | } | 340 | } |
@@ -321,17 +342,18 @@ rpc_pipe_write(struct file *filp, const char __user *buf, size_t len, loff_t *of | |||
321 | static unsigned int | 342 | static unsigned int |
322 | rpc_pipe_poll(struct file *filp, struct poll_table_struct *wait) | 343 | rpc_pipe_poll(struct file *filp, struct poll_table_struct *wait) |
323 | { | 344 | { |
324 | struct rpc_inode *rpci; | 345 | struct inode *inode = filp->f_path.dentry->d_inode; |
325 | unsigned int mask = 0; | 346 | struct rpc_inode *rpci = RPC_I(inode); |
347 | unsigned int mask = POLLOUT | POLLWRNORM; | ||
326 | 348 | ||
327 | rpci = RPC_I(filp->f_path.dentry->d_inode); | ||
328 | poll_wait(filp, &rpci->waitq, wait); | 349 | poll_wait(filp, &rpci->waitq, wait); |
329 | 350 | ||
330 | mask = POLLOUT | POLLWRNORM; | 351 | mutex_lock(&inode->i_mutex); |
331 | if (rpci->ops == NULL) | 352 | if (rpci->pipe == NULL) |
332 | mask |= POLLERR | POLLHUP; | 353 | mask |= POLLERR | POLLHUP; |
333 | if (filp->private_data || !list_empty(&rpci->pipe)) | 354 | else if (filp->private_data || !list_empty(&rpci->pipe->pipe)) |
334 | mask |= POLLIN | POLLRDNORM; | 355 | mask |= POLLIN | POLLRDNORM; |
356 | mutex_unlock(&inode->i_mutex); | ||
335 | return mask; | 357 | return mask; |
336 | } | 358 | } |
337 | 359 | ||
@@ -339,23 +361,26 @@ static long | |||
339 | rpc_pipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | 361 | rpc_pipe_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
340 | { | 362 | { |
341 | struct inode *inode = filp->f_path.dentry->d_inode; | 363 | struct inode *inode = filp->f_path.dentry->d_inode; |
342 | struct rpc_inode *rpci = RPC_I(inode); | 364 | struct rpc_pipe *pipe; |
343 | int len; | 365 | int len; |
344 | 366 | ||
345 | switch (cmd) { | 367 | switch (cmd) { |
346 | case FIONREAD: | 368 | case FIONREAD: |
347 | spin_lock(&inode->i_lock); | 369 | mutex_lock(&inode->i_mutex); |
348 | if (rpci->ops == NULL) { | 370 | pipe = RPC_I(inode)->pipe; |
349 | spin_unlock(&inode->i_lock); | 371 | if (pipe == NULL) { |
372 | mutex_unlock(&inode->i_mutex); | ||
350 | return -EPIPE; | 373 | return -EPIPE; |
351 | } | 374 | } |
352 | len = rpci->pipelen; | 375 | spin_lock(&pipe->lock); |
376 | len = pipe->pipelen; | ||
353 | if (filp->private_data) { | 377 | if (filp->private_data) { |
354 | struct rpc_pipe_msg *msg; | 378 | struct rpc_pipe_msg *msg; |
355 | msg = filp->private_data; | 379 | msg = filp->private_data; |
356 | len += msg->len - msg->copied; | 380 | len += msg->len - msg->copied; |
357 | } | 381 | } |
358 | spin_unlock(&inode->i_lock); | 382 | spin_unlock(&pipe->lock); |
383 | mutex_unlock(&inode->i_mutex); | ||
359 | return put_user(len, (int __user *)arg); | 384 | return put_user(len, (int __user *)arg); |
360 | default: | 385 | default: |
361 | return -EINVAL; | 386 | return -EINVAL; |
@@ -378,12 +403,15 @@ rpc_show_info(struct seq_file *m, void *v) | |||
378 | { | 403 | { |
379 | struct rpc_clnt *clnt = m->private; | 404 | struct rpc_clnt *clnt = m->private; |
380 | 405 | ||
381 | seq_printf(m, "RPC server: %s\n", clnt->cl_server); | 406 | rcu_read_lock(); |
407 | seq_printf(m, "RPC server: %s\n", | ||
408 | rcu_dereference(clnt->cl_xprt)->servername); | ||
382 | seq_printf(m, "service: %s (%d) version %d\n", clnt->cl_protname, | 409 | seq_printf(m, "service: %s (%d) version %d\n", clnt->cl_protname, |
383 | clnt->cl_prog, clnt->cl_vers); | 410 | clnt->cl_prog, clnt->cl_vers); |
384 | seq_printf(m, "address: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_ADDR)); | 411 | seq_printf(m, "address: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_ADDR)); |
385 | seq_printf(m, "protocol: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_PROTO)); | 412 | seq_printf(m, "protocol: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_PROTO)); |
386 | seq_printf(m, "port: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_PORT)); | 413 | seq_printf(m, "port: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_PORT)); |
414 | rcu_read_unlock(); | ||
387 | return 0; | 415 | return 0; |
388 | } | 416 | } |
389 | 417 | ||
@@ -440,23 +468,6 @@ struct rpc_filelist { | |||
440 | umode_t mode; | 468 | umode_t mode; |
441 | }; | 469 | }; |
442 | 470 | ||
443 | struct vfsmount *rpc_get_mount(void) | ||
444 | { | ||
445 | int err; | ||
446 | |||
447 | err = simple_pin_fs(&rpc_pipe_fs_type, &rpc_mnt, &rpc_mount_count); | ||
448 | if (err != 0) | ||
449 | return ERR_PTR(err); | ||
450 | return rpc_mnt; | ||
451 | } | ||
452 | EXPORT_SYMBOL_GPL(rpc_get_mount); | ||
453 | |||
454 | void rpc_put_mount(void) | ||
455 | { | ||
456 | simple_release_fs(&rpc_mnt, &rpc_mount_count); | ||
457 | } | ||
458 | EXPORT_SYMBOL_GPL(rpc_put_mount); | ||
459 | |||
460 | static int rpc_delete_dentry(const struct dentry *dentry) | 471 | static int rpc_delete_dentry(const struct dentry *dentry) |
461 | { | 472 | { |
462 | return 1; | 473 | return 1; |
@@ -540,12 +551,47 @@ static int __rpc_mkdir(struct inode *dir, struct dentry *dentry, | |||
540 | return 0; | 551 | return 0; |
541 | } | 552 | } |
542 | 553 | ||
543 | static int __rpc_mkpipe(struct inode *dir, struct dentry *dentry, | 554 | static void |
544 | umode_t mode, | 555 | init_pipe(struct rpc_pipe *pipe) |
545 | const struct file_operations *i_fop, | 556 | { |
546 | void *private, | 557 | pipe->nreaders = 0; |
547 | const struct rpc_pipe_ops *ops, | 558 | pipe->nwriters = 0; |
548 | int flags) | 559 | INIT_LIST_HEAD(&pipe->in_upcall); |
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) | ||
549 | { | 595 | { |
550 | struct rpc_inode *rpci; | 596 | struct rpc_inode *rpci; |
551 | int err; | 597 | int err; |
@@ -554,10 +600,8 @@ static int __rpc_mkpipe(struct inode *dir, struct dentry *dentry, | |||
554 | if (err) | 600 | if (err) |
555 | return err; | 601 | return err; |
556 | rpci = RPC_I(dentry->d_inode); | 602 | rpci = RPC_I(dentry->d_inode); |
557 | rpci->nkern_readwriters = 1; | ||
558 | rpci->private = private; | 603 | rpci->private = private; |
559 | rpci->flags = flags; | 604 | rpci->pipe = pipe; |
560 | rpci->ops = ops; | ||
561 | fsnotify_create(dir, dentry); | 605 | fsnotify_create(dir, dentry); |
562 | return 0; | 606 | return 0; |
563 | } | 607 | } |
@@ -573,6 +617,22 @@ static int __rpc_rmdir(struct inode *dir, struct dentry *dentry) | |||
573 | return ret; | 617 | return ret; |
574 | } | 618 | } |
575 | 619 | ||
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 | |||
576 | static int __rpc_unlink(struct inode *dir, struct dentry *dentry) | 636 | static int __rpc_unlink(struct inode *dir, struct dentry *dentry) |
577 | { | 637 | { |
578 | int ret; | 638 | int ret; |
@@ -587,16 +647,12 @@ static int __rpc_unlink(struct inode *dir, struct dentry *dentry) | |||
587 | static int __rpc_rmpipe(struct inode *dir, struct dentry *dentry) | 647 | static int __rpc_rmpipe(struct inode *dir, struct dentry *dentry) |
588 | { | 648 | { |
589 | struct inode *inode = dentry->d_inode; | 649 | struct inode *inode = dentry->d_inode; |
590 | struct rpc_inode *rpci = RPC_I(inode); | ||
591 | 650 | ||
592 | rpci->nkern_readwriters--; | ||
593 | if (rpci->nkern_readwriters != 0) | ||
594 | return 0; | ||
595 | rpc_close_pipes(inode); | 651 | rpc_close_pipes(inode); |
596 | return __rpc_unlink(dir, dentry); | 652 | return __rpc_unlink(dir, dentry); |
597 | } | 653 | } |
598 | 654 | ||
599 | static struct dentry *__rpc_lookup_create(struct dentry *parent, | 655 | static struct dentry *__rpc_lookup_create_exclusive(struct dentry *parent, |
600 | struct qstr *name) | 656 | struct qstr *name) |
601 | { | 657 | { |
602 | struct dentry *dentry; | 658 | struct dentry *dentry; |
@@ -604,27 +660,13 @@ static struct dentry *__rpc_lookup_create(struct dentry *parent, | |||
604 | dentry = d_lookup(parent, name); | 660 | dentry = d_lookup(parent, name); |
605 | if (!dentry) { | 661 | if (!dentry) { |
606 | dentry = d_alloc(parent, name); | 662 | dentry = d_alloc(parent, name); |
607 | if (!dentry) { | 663 | if (!dentry) |
608 | dentry = ERR_PTR(-ENOMEM); | 664 | return ERR_PTR(-ENOMEM); |
609 | goto out_err; | ||
610 | } | ||
611 | } | 665 | } |
612 | if (!dentry->d_inode) | 666 | if (dentry->d_inode == NULL) { |
613 | d_set_d_op(dentry, &rpc_dentry_operations); | 667 | d_set_d_op(dentry, &rpc_dentry_operations); |
614 | out_err: | ||
615 | return dentry; | ||
616 | } | ||
617 | |||
618 | static struct dentry *__rpc_lookup_create_exclusive(struct dentry *parent, | ||
619 | struct qstr *name) | ||
620 | { | ||
621 | struct dentry *dentry; | ||
622 | |||
623 | dentry = __rpc_lookup_create(parent, name); | ||
624 | if (IS_ERR(dentry)) | ||
625 | return dentry; | ||
626 | if (dentry->d_inode == NULL) | ||
627 | return dentry; | 668 | return dentry; |
669 | } | ||
628 | dput(dentry); | 670 | dput(dentry); |
629 | return ERR_PTR(-EEXIST); | 671 | return ERR_PTR(-EEXIST); |
630 | } | 672 | } |
@@ -779,7 +821,7 @@ static int rpc_rmdir_depopulate(struct dentry *dentry, | |||
779 | * @private: private data to associate with the pipe, for the caller's use | 821 | * @private: private data to associate with the pipe, for the caller's use |
780 | * @ops: operations defining the behavior of the pipe: upcall, downcall, | 822 | * @ops: operations defining the behavior of the pipe: upcall, downcall, |
781 | * release_pipe, open_pipe, and destroy_msg. | 823 | * release_pipe, open_pipe, and destroy_msg. |
782 | * @flags: rpc_inode flags | 824 | * @flags: rpc_pipe flags |
783 | * | 825 | * |
784 | * Data is made available for userspace to read by calls to | 826 | * Data is made available for userspace to read by calls to |
785 | * rpc_queue_upcall(). The actual reads will result in calls to | 827 | * rpc_queue_upcall(). The actual reads will result in calls to |
@@ -792,9 +834,8 @@ static int rpc_rmdir_depopulate(struct dentry *dentry, | |||
792 | * The @private argument passed here will be available to all these methods | 834 | * The @private argument passed here will be available to all these methods |
793 | * from the file pointer, via RPC_I(file->f_dentry->d_inode)->private. | 835 | * from the file pointer, via RPC_I(file->f_dentry->d_inode)->private. |
794 | */ | 836 | */ |
795 | struct dentry *rpc_mkpipe(struct dentry *parent, const char *name, | 837 | struct dentry *rpc_mkpipe_dentry(struct dentry *parent, const char *name, |
796 | void *private, const struct rpc_pipe_ops *ops, | 838 | void *private, struct rpc_pipe *pipe) |
797 | int flags) | ||
798 | { | 839 | { |
799 | struct dentry *dentry; | 840 | struct dentry *dentry; |
800 | struct inode *dir = parent->d_inode; | 841 | struct inode *dir = parent->d_inode; |
@@ -802,9 +843,9 @@ struct dentry *rpc_mkpipe(struct dentry *parent, const char *name, | |||
802 | struct qstr q; | 843 | struct qstr q; |
803 | int err; | 844 | int err; |
804 | 845 | ||
805 | if (ops->upcall == NULL) | 846 | if (pipe->ops->upcall == NULL) |
806 | umode &= ~S_IRUGO; | 847 | umode &= ~S_IRUGO; |
807 | if (ops->downcall == NULL) | 848 | if (pipe->ops->downcall == NULL) |
808 | umode &= ~S_IWUGO; | 849 | umode &= ~S_IWUGO; |
809 | 850 | ||
810 | q.name = name; | 851 | q.name = name; |
@@ -812,24 +853,11 @@ struct dentry *rpc_mkpipe(struct dentry *parent, const char *name, | |||
812 | q.hash = full_name_hash(q.name, q.len), | 853 | q.hash = full_name_hash(q.name, q.len), |
813 | 854 | ||
814 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); | 855 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); |
815 | dentry = __rpc_lookup_create(parent, &q); | 856 | dentry = __rpc_lookup_create_exclusive(parent, &q); |
816 | if (IS_ERR(dentry)) | 857 | if (IS_ERR(dentry)) |
817 | goto out; | 858 | goto out; |
818 | if (dentry->d_inode) { | 859 | err = __rpc_mkpipe_dentry(dir, dentry, umode, &rpc_pipe_fops, |
819 | struct rpc_inode *rpci = RPC_I(dentry->d_inode); | 860 | private, pipe); |
820 | if (rpci->private != private || | ||
821 | rpci->ops != ops || | ||
822 | rpci->flags != flags) { | ||
823 | dput (dentry); | ||
824 | err = -EBUSY; | ||
825 | goto out_err; | ||
826 | } | ||
827 | rpci->nkern_readwriters++; | ||
828 | goto out; | ||
829 | } | ||
830 | |||
831 | err = __rpc_mkpipe(dir, dentry, umode, &rpc_pipe_fops, | ||
832 | private, ops, flags); | ||
833 | if (err) | 861 | if (err) |
834 | goto out_err; | 862 | goto out_err; |
835 | out: | 863 | out: |
@@ -842,7 +870,7 @@ out_err: | |||
842 | err); | 870 | err); |
843 | goto out; | 871 | goto out; |
844 | } | 872 | } |
845 | EXPORT_SYMBOL_GPL(rpc_mkpipe); | 873 | EXPORT_SYMBOL_GPL(rpc_mkpipe_dentry); |
846 | 874 | ||
847 | /** | 875 | /** |
848 | * rpc_unlink - remove a pipe | 876 | * rpc_unlink - remove a pipe |
@@ -915,7 +943,7 @@ struct dentry *rpc_create_client_dir(struct dentry *dentry, | |||
915 | 943 | ||
916 | /** | 944 | /** |
917 | * rpc_remove_client_dir - Remove a directory created with rpc_create_client_dir() | 945 | * rpc_remove_client_dir - Remove a directory created with rpc_create_client_dir() |
918 | * @dentry: directory to remove | 946 | * @clnt: rpc client |
919 | */ | 947 | */ |
920 | int rpc_remove_client_dir(struct dentry *dentry) | 948 | int rpc_remove_client_dir(struct dentry *dentry) |
921 | { | 949 | { |
@@ -1020,11 +1048,64 @@ static const struct rpc_filelist files[] = { | |||
1020 | }, | 1048 | }, |
1021 | }; | 1049 | }; |
1022 | 1050 | ||
1051 | /* | ||
1052 | * This call can be used only in RPC pipefs mount notification hooks. | ||
1053 | */ | ||
1054 | struct dentry *rpc_d_lookup_sb(const struct super_block *sb, | ||
1055 | const unsigned char *dir_name) | ||
1056 | { | ||
1057 | struct qstr dir = { | ||
1058 | .name = dir_name, | ||
1059 | .len = strlen(dir_name), | ||
1060 | .hash = full_name_hash(dir_name, strlen(dir_name)), | ||
1061 | }; | ||
1062 | |||
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 | BUG_ON(sn->pipefs_sb == NULL); | ||
1097 | mutex_unlock(&sn->pipefs_sb_lock); | ||
1098 | } | ||
1099 | EXPORT_SYMBOL_GPL(rpc_put_sb_net); | ||
1100 | |||
1023 | static int | 1101 | static int |
1024 | rpc_fill_super(struct super_block *sb, void *data, int silent) | 1102 | rpc_fill_super(struct super_block *sb, void *data, int silent) |
1025 | { | 1103 | { |
1026 | struct inode *inode; | 1104 | struct inode *inode; |
1027 | struct dentry *root; | 1105 | struct dentry *root; |
1106 | struct net *net = data; | ||
1107 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
1108 | int err; | ||
1028 | 1109 | ||
1029 | sb->s_blocksize = PAGE_CACHE_SIZE; | 1110 | sb->s_blocksize = PAGE_CACHE_SIZE; |
1030 | sb->s_blocksize_bits = PAGE_CACHE_SHIFT; | 1111 | sb->s_blocksize_bits = PAGE_CACHE_SHIFT; |
@@ -1042,21 +1123,54 @@ rpc_fill_super(struct super_block *sb, void *data, int silent) | |||
1042 | } | 1123 | } |
1043 | if (rpc_populate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF, NULL)) | 1124 | if (rpc_populate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF, NULL)) |
1044 | return -ENOMEM; | 1125 | return -ENOMEM; |
1126 | dprintk("RPC: sending pipefs MOUNT notification for net %p%s\n", net, | ||
1127 | NET_NAME(net)); | ||
1128 | err = blocking_notifier_call_chain(&rpc_pipefs_notifier_list, | ||
1129 | RPC_PIPEFS_MOUNT, | ||
1130 | sb); | ||
1131 | if (err) | ||
1132 | goto err_depopulate; | ||
1133 | sb->s_fs_info = get_net(net); | ||
1134 | sn->pipefs_sb = sb; | ||
1045 | return 0; | 1135 | return 0; |
1136 | |||
1137 | err_depopulate: | ||
1138 | blocking_notifier_call_chain(&rpc_pipefs_notifier_list, | ||
1139 | RPC_PIPEFS_UMOUNT, | ||
1140 | sb); | ||
1141 | __rpc_depopulate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF); | ||
1142 | return err; | ||
1046 | } | 1143 | } |
1047 | 1144 | ||
1048 | static struct dentry * | 1145 | static struct dentry * |
1049 | rpc_mount(struct file_system_type *fs_type, | 1146 | rpc_mount(struct file_system_type *fs_type, |
1050 | int flags, const char *dev_name, void *data) | 1147 | int flags, const char *dev_name, void *data) |
1051 | { | 1148 | { |
1052 | return mount_single(fs_type, flags, data, rpc_fill_super); | 1149 | return mount_ns(fs_type, flags, current->nsproxy->net_ns, rpc_fill_super); |
1150 | } | ||
1151 | |||
1152 | static void rpc_kill_sb(struct super_block *sb) | ||
1153 | { | ||
1154 | struct net *net = sb->s_fs_info; | ||
1155 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
1156 | |||
1157 | mutex_lock(&sn->pipefs_sb_lock); | ||
1158 | sn->pipefs_sb = NULL; | ||
1159 | mutex_unlock(&sn->pipefs_sb_lock); | ||
1160 | put_net(net); | ||
1161 | dprintk("RPC: sending pipefs UMOUNT notification for net %p%s\n", net, | ||
1162 | NET_NAME(net)); | ||
1163 | blocking_notifier_call_chain(&rpc_pipefs_notifier_list, | ||
1164 | RPC_PIPEFS_UMOUNT, | ||
1165 | sb); | ||
1166 | kill_litter_super(sb); | ||
1053 | } | 1167 | } |
1054 | 1168 | ||
1055 | static struct file_system_type rpc_pipe_fs_type = { | 1169 | static struct file_system_type rpc_pipe_fs_type = { |
1056 | .owner = THIS_MODULE, | 1170 | .owner = THIS_MODULE, |
1057 | .name = "rpc_pipefs", | 1171 | .name = "rpc_pipefs", |
1058 | .mount = rpc_mount, | 1172 | .mount = rpc_mount, |
1059 | .kill_sb = kill_litter_super, | 1173 | .kill_sb = rpc_kill_sb, |
1060 | }; | 1174 | }; |
1061 | 1175 | ||
1062 | static void | 1176 | static void |
@@ -1066,16 +1180,8 @@ init_once(void *foo) | |||
1066 | 1180 | ||
1067 | inode_init_once(&rpci->vfs_inode); | 1181 | inode_init_once(&rpci->vfs_inode); |
1068 | rpci->private = NULL; | 1182 | rpci->private = NULL; |
1069 | rpci->nreaders = 0; | 1183 | rpci->pipe = NULL; |
1070 | rpci->nwriters = 0; | ||
1071 | INIT_LIST_HEAD(&rpci->in_upcall); | ||
1072 | INIT_LIST_HEAD(&rpci->in_downcall); | ||
1073 | INIT_LIST_HEAD(&rpci->pipe); | ||
1074 | rpci->pipelen = 0; | ||
1075 | init_waitqueue_head(&rpci->waitq); | 1184 | init_waitqueue_head(&rpci->waitq); |
1076 | INIT_DELAYED_WORK(&rpci->queue_timeout, | ||
1077 | rpc_timeout_upcall_queue); | ||
1078 | rpci->ops = NULL; | ||
1079 | } | 1185 | } |
1080 | 1186 | ||
1081 | int register_rpc_pipefs(void) | 1187 | int register_rpc_pipefs(void) |
@@ -1089,17 +1195,24 @@ int register_rpc_pipefs(void) | |||
1089 | init_once); | 1195 | init_once); |
1090 | if (!rpc_inode_cachep) | 1196 | if (!rpc_inode_cachep) |
1091 | return -ENOMEM; | 1197 | return -ENOMEM; |
1198 | err = rpc_clients_notifier_register(); | ||
1199 | if (err) | ||
1200 | goto err_notifier; | ||
1092 | err = register_filesystem(&rpc_pipe_fs_type); | 1201 | err = register_filesystem(&rpc_pipe_fs_type); |
1093 | if (err) { | 1202 | if (err) |
1094 | kmem_cache_destroy(rpc_inode_cachep); | 1203 | goto err_register; |
1095 | return err; | ||
1096 | } | ||
1097 | |||
1098 | return 0; | 1204 | return 0; |
1205 | |||
1206 | err_register: | ||
1207 | rpc_clients_notifier_unregister(); | ||
1208 | err_notifier: | ||
1209 | kmem_cache_destroy(rpc_inode_cachep); | ||
1210 | return err; | ||
1099 | } | 1211 | } |
1100 | 1212 | ||
1101 | void unregister_rpc_pipefs(void) | 1213 | void unregister_rpc_pipefs(void) |
1102 | { | 1214 | { |
1215 | rpc_clients_notifier_unregister(); | ||
1103 | kmem_cache_destroy(rpc_inode_cachep); | 1216 | kmem_cache_destroy(rpc_inode_cachep); |
1104 | unregister_filesystem(&rpc_pipe_fs_type); | 1217 | unregister_filesystem(&rpc_pipe_fs_type); |
1105 | } | 1218 | } |
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index 8761bf8e36fc..207a74696c9f 100644 --- a/net/sunrpc/rpcb_clnt.c +++ b/net/sunrpc/rpcb_clnt.c | |||
@@ -23,12 +23,15 @@ | |||
23 | #include <linux/errno.h> | 23 | #include <linux/errno.h> |
24 | #include <linux/mutex.h> | 24 | #include <linux/mutex.h> |
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/nsproxy.h> | ||
26 | #include <net/ipv6.h> | 27 | #include <net/ipv6.h> |
27 | 28 | ||
28 | #include <linux/sunrpc/clnt.h> | 29 | #include <linux/sunrpc/clnt.h> |
29 | #include <linux/sunrpc/sched.h> | 30 | #include <linux/sunrpc/sched.h> |
30 | #include <linux/sunrpc/xprtsock.h> | 31 | #include <linux/sunrpc/xprtsock.h> |
31 | 32 | ||
33 | #include "netns.h" | ||
34 | |||
32 | #ifdef RPC_DEBUG | 35 | #ifdef RPC_DEBUG |
33 | # define RPCDBG_FACILITY RPCDBG_BIND | 36 | # define RPCDBG_FACILITY RPCDBG_BIND |
34 | #endif | 37 | #endif |
@@ -109,13 +112,7 @@ enum { | |||
109 | 112 | ||
110 | static void rpcb_getport_done(struct rpc_task *, void *); | 113 | static void rpcb_getport_done(struct rpc_task *, void *); |
111 | static void rpcb_map_release(void *data); | 114 | static void rpcb_map_release(void *data); |
112 | static struct rpc_program rpcb_program; | 115 | static const struct rpc_program rpcb_program; |
113 | |||
114 | static struct rpc_clnt * rpcb_local_clnt; | ||
115 | static struct rpc_clnt * rpcb_local_clnt4; | ||
116 | |||
117 | DEFINE_SPINLOCK(rpcb_clnt_lock); | ||
118 | unsigned int rpcb_users; | ||
119 | 116 | ||
120 | struct rpcbind_args { | 117 | struct rpcbind_args { |
121 | struct rpc_xprt * r_xprt; | 118 | struct rpc_xprt * r_xprt; |
@@ -140,8 +137,8 @@ struct rpcb_info { | |||
140 | struct rpc_procinfo * rpc_proc; | 137 | struct rpc_procinfo * rpc_proc; |
141 | }; | 138 | }; |
142 | 139 | ||
143 | static struct rpcb_info rpcb_next_version[]; | 140 | static const struct rpcb_info rpcb_next_version[]; |
144 | static struct rpcb_info rpcb_next_version6[]; | 141 | static const struct rpcb_info rpcb_next_version6[]; |
145 | 142 | ||
146 | static const struct rpc_call_ops rpcb_getport_ops = { | 143 | static const struct rpc_call_ops rpcb_getport_ops = { |
147 | .rpc_call_done = rpcb_getport_done, | 144 | .rpc_call_done = rpcb_getport_done, |
@@ -164,32 +161,34 @@ static void rpcb_map_release(void *data) | |||
164 | kfree(map); | 161 | kfree(map); |
165 | } | 162 | } |
166 | 163 | ||
167 | static int rpcb_get_local(void) | 164 | static int rpcb_get_local(struct net *net) |
168 | { | 165 | { |
169 | int cnt; | 166 | int cnt; |
167 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
170 | 168 | ||
171 | spin_lock(&rpcb_clnt_lock); | 169 | spin_lock(&sn->rpcb_clnt_lock); |
172 | if (rpcb_users) | 170 | if (sn->rpcb_users) |
173 | rpcb_users++; | 171 | sn->rpcb_users++; |
174 | cnt = rpcb_users; | 172 | cnt = sn->rpcb_users; |
175 | spin_unlock(&rpcb_clnt_lock); | 173 | spin_unlock(&sn->rpcb_clnt_lock); |
176 | 174 | ||
177 | return cnt; | 175 | return cnt; |
178 | } | 176 | } |
179 | 177 | ||
180 | void rpcb_put_local(void) | 178 | void rpcb_put_local(struct net *net) |
181 | { | 179 | { |
182 | struct rpc_clnt *clnt = rpcb_local_clnt; | 180 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
183 | struct rpc_clnt *clnt4 = rpcb_local_clnt4; | 181 | struct rpc_clnt *clnt = sn->rpcb_local_clnt; |
182 | struct rpc_clnt *clnt4 = sn->rpcb_local_clnt4; | ||
184 | int shutdown; | 183 | int shutdown; |
185 | 184 | ||
186 | spin_lock(&rpcb_clnt_lock); | 185 | spin_lock(&sn->rpcb_clnt_lock); |
187 | if (--rpcb_users == 0) { | 186 | if (--sn->rpcb_users == 0) { |
188 | rpcb_local_clnt = NULL; | 187 | sn->rpcb_local_clnt = NULL; |
189 | rpcb_local_clnt4 = NULL; | 188 | sn->rpcb_local_clnt4 = NULL; |
190 | } | 189 | } |
191 | shutdown = !rpcb_users; | 190 | shutdown = !sn->rpcb_users; |
192 | spin_unlock(&rpcb_clnt_lock); | 191 | spin_unlock(&sn->rpcb_clnt_lock); |
193 | 192 | ||
194 | if (shutdown) { | 193 | if (shutdown) { |
195 | /* | 194 | /* |
@@ -202,30 +201,34 @@ void rpcb_put_local(void) | |||
202 | } | 201 | } |
203 | } | 202 | } |
204 | 203 | ||
205 | static void rpcb_set_local(struct rpc_clnt *clnt, struct rpc_clnt *clnt4) | 204 | static void rpcb_set_local(struct net *net, struct rpc_clnt *clnt, |
205 | struct rpc_clnt *clnt4) | ||
206 | { | 206 | { |
207 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
208 | |||
207 | /* Protected by rpcb_create_local_mutex */ | 209 | /* Protected by rpcb_create_local_mutex */ |
208 | rpcb_local_clnt = clnt; | 210 | sn->rpcb_local_clnt = clnt; |
209 | rpcb_local_clnt4 = clnt4; | 211 | sn->rpcb_local_clnt4 = clnt4; |
210 | smp_wmb(); | 212 | smp_wmb(); |
211 | rpcb_users = 1; | 213 | sn->rpcb_users = 1; |
212 | dprintk("RPC: created new rpcb local clients (rpcb_local_clnt: " | 214 | dprintk("RPC: created new rpcb local clients (rpcb_local_clnt: " |
213 | "%p, rpcb_local_clnt4: %p)\n", rpcb_local_clnt, | 215 | "%p, rpcb_local_clnt4: %p) for net %p%s\n", |
214 | rpcb_local_clnt4); | 216 | sn->rpcb_local_clnt, sn->rpcb_local_clnt4, |
217 | net, (net == &init_net) ? " (init_net)" : ""); | ||
215 | } | 218 | } |
216 | 219 | ||
217 | /* | 220 | /* |
218 | * Returns zero on success, otherwise a negative errno value | 221 | * Returns zero on success, otherwise a negative errno value |
219 | * is returned. | 222 | * is returned. |
220 | */ | 223 | */ |
221 | static int rpcb_create_local_unix(void) | 224 | static int rpcb_create_local_unix(struct net *net) |
222 | { | 225 | { |
223 | static const struct sockaddr_un rpcb_localaddr_rpcbind = { | 226 | static const struct sockaddr_un rpcb_localaddr_rpcbind = { |
224 | .sun_family = AF_LOCAL, | 227 | .sun_family = AF_LOCAL, |
225 | .sun_path = RPCBIND_SOCK_PATHNAME, | 228 | .sun_path = RPCBIND_SOCK_PATHNAME, |
226 | }; | 229 | }; |
227 | struct rpc_create_args args = { | 230 | struct rpc_create_args args = { |
228 | .net = &init_net, | 231 | .net = net, |
229 | .protocol = XPRT_TRANSPORT_LOCAL, | 232 | .protocol = XPRT_TRANSPORT_LOCAL, |
230 | .address = (struct sockaddr *)&rpcb_localaddr_rpcbind, | 233 | .address = (struct sockaddr *)&rpcb_localaddr_rpcbind, |
231 | .addrsize = sizeof(rpcb_localaddr_rpcbind), | 234 | .addrsize = sizeof(rpcb_localaddr_rpcbind), |
@@ -258,7 +261,7 @@ static int rpcb_create_local_unix(void) | |||
258 | clnt4 = NULL; | 261 | clnt4 = NULL; |
259 | } | 262 | } |
260 | 263 | ||
261 | rpcb_set_local(clnt, clnt4); | 264 | rpcb_set_local(net, clnt, clnt4); |
262 | 265 | ||
263 | out: | 266 | out: |
264 | return result; | 267 | return result; |
@@ -268,7 +271,7 @@ out: | |||
268 | * Returns zero on success, otherwise a negative errno value | 271 | * Returns zero on success, otherwise a negative errno value |
269 | * is returned. | 272 | * is returned. |
270 | */ | 273 | */ |
271 | static int rpcb_create_local_net(void) | 274 | static int rpcb_create_local_net(struct net *net) |
272 | { | 275 | { |
273 | static const struct sockaddr_in rpcb_inaddr_loopback = { | 276 | static const struct sockaddr_in rpcb_inaddr_loopback = { |
274 | .sin_family = AF_INET, | 277 | .sin_family = AF_INET, |
@@ -276,7 +279,7 @@ static int rpcb_create_local_net(void) | |||
276 | .sin_port = htons(RPCBIND_PORT), | 279 | .sin_port = htons(RPCBIND_PORT), |
277 | }; | 280 | }; |
278 | struct rpc_create_args args = { | 281 | struct rpc_create_args args = { |
279 | .net = &init_net, | 282 | .net = net, |
280 | .protocol = XPRT_TRANSPORT_TCP, | 283 | .protocol = XPRT_TRANSPORT_TCP, |
281 | .address = (struct sockaddr *)&rpcb_inaddr_loopback, | 284 | .address = (struct sockaddr *)&rpcb_inaddr_loopback, |
282 | .addrsize = sizeof(rpcb_inaddr_loopback), | 285 | .addrsize = sizeof(rpcb_inaddr_loopback), |
@@ -310,7 +313,7 @@ static int rpcb_create_local_net(void) | |||
310 | clnt4 = NULL; | 313 | clnt4 = NULL; |
311 | } | 314 | } |
312 | 315 | ||
313 | rpcb_set_local(clnt, clnt4); | 316 | rpcb_set_local(net, clnt, clnt4); |
314 | 317 | ||
315 | out: | 318 | out: |
316 | return result; | 319 | return result; |
@@ -320,31 +323,32 @@ out: | |||
320 | * Returns zero on success, otherwise a negative errno value | 323 | * Returns zero on success, otherwise a negative errno value |
321 | * is returned. | 324 | * is returned. |
322 | */ | 325 | */ |
323 | int rpcb_create_local(void) | 326 | int rpcb_create_local(struct net *net) |
324 | { | 327 | { |
325 | static DEFINE_MUTEX(rpcb_create_local_mutex); | 328 | static DEFINE_MUTEX(rpcb_create_local_mutex); |
326 | int result = 0; | 329 | int result = 0; |
327 | 330 | ||
328 | if (rpcb_get_local()) | 331 | if (rpcb_get_local(net)) |
329 | return result; | 332 | return result; |
330 | 333 | ||
331 | mutex_lock(&rpcb_create_local_mutex); | 334 | mutex_lock(&rpcb_create_local_mutex); |
332 | if (rpcb_get_local()) | 335 | if (rpcb_get_local(net)) |
333 | goto out; | 336 | goto out; |
334 | 337 | ||
335 | if (rpcb_create_local_unix() != 0) | 338 | if (rpcb_create_local_unix(net) != 0) |
336 | result = rpcb_create_local_net(); | 339 | result = rpcb_create_local_net(net); |
337 | 340 | ||
338 | out: | 341 | out: |
339 | mutex_unlock(&rpcb_create_local_mutex); | 342 | mutex_unlock(&rpcb_create_local_mutex); |
340 | return result; | 343 | return result; |
341 | } | 344 | } |
342 | 345 | ||
343 | static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr, | 346 | static struct rpc_clnt *rpcb_create(struct net *net, const char *hostname, |
344 | size_t salen, int proto, u32 version) | 347 | struct sockaddr *srvaddr, size_t salen, |
348 | int proto, u32 version) | ||
345 | { | 349 | { |
346 | struct rpc_create_args args = { | 350 | struct rpc_create_args args = { |
347 | .net = &init_net, | 351 | .net = net, |
348 | .protocol = proto, | 352 | .protocol = proto, |
349 | .address = srvaddr, | 353 | .address = srvaddr, |
350 | .addrsize = salen, | 354 | .addrsize = salen, |
@@ -420,7 +424,7 @@ static int rpcb_register_call(struct rpc_clnt *clnt, struct rpc_message *msg) | |||
420 | * IN6ADDR_ANY (ie available for all AF_INET and AF_INET6 | 424 | * IN6ADDR_ANY (ie available for all AF_INET and AF_INET6 |
421 | * addresses). | 425 | * addresses). |
422 | */ | 426 | */ |
423 | int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port) | 427 | int rpcb_register(struct net *net, u32 prog, u32 vers, int prot, unsigned short port) |
424 | { | 428 | { |
425 | struct rpcbind_args map = { | 429 | struct rpcbind_args map = { |
426 | .r_prog = prog, | 430 | .r_prog = prog, |
@@ -431,6 +435,7 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port) | |||
431 | struct rpc_message msg = { | 435 | struct rpc_message msg = { |
432 | .rpc_argp = &map, | 436 | .rpc_argp = &map, |
433 | }; | 437 | }; |
438 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
434 | 439 | ||
435 | dprintk("RPC: %sregistering (%u, %u, %d, %u) with local " | 440 | dprintk("RPC: %sregistering (%u, %u, %d, %u) with local " |
436 | "rpcbind\n", (port ? "" : "un"), | 441 | "rpcbind\n", (port ? "" : "un"), |
@@ -440,13 +445,14 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port) | |||
440 | if (port) | 445 | if (port) |
441 | msg.rpc_proc = &rpcb_procedures2[RPCBPROC_SET]; | 446 | msg.rpc_proc = &rpcb_procedures2[RPCBPROC_SET]; |
442 | 447 | ||
443 | return rpcb_register_call(rpcb_local_clnt, &msg); | 448 | return rpcb_register_call(sn->rpcb_local_clnt, &msg); |
444 | } | 449 | } |
445 | 450 | ||
446 | /* | 451 | /* |
447 | * Fill in AF_INET family-specific arguments to register | 452 | * Fill in AF_INET family-specific arguments to register |
448 | */ | 453 | */ |
449 | static int rpcb_register_inet4(const struct sockaddr *sap, | 454 | static int rpcb_register_inet4(struct sunrpc_net *sn, |
455 | const struct sockaddr *sap, | ||
450 | struct rpc_message *msg) | 456 | struct rpc_message *msg) |
451 | { | 457 | { |
452 | const struct sockaddr_in *sin = (const struct sockaddr_in *)sap; | 458 | const struct sockaddr_in *sin = (const struct sockaddr_in *)sap; |
@@ -465,7 +471,7 @@ static int rpcb_register_inet4(const struct sockaddr *sap, | |||
465 | if (port) | 471 | if (port) |
466 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; | 472 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; |
467 | 473 | ||
468 | result = rpcb_register_call(rpcb_local_clnt4, msg); | 474 | result = rpcb_register_call(sn->rpcb_local_clnt4, msg); |
469 | kfree(map->r_addr); | 475 | kfree(map->r_addr); |
470 | return result; | 476 | return result; |
471 | } | 477 | } |
@@ -473,7 +479,8 @@ static int rpcb_register_inet4(const struct sockaddr *sap, | |||
473 | /* | 479 | /* |
474 | * Fill in AF_INET6 family-specific arguments to register | 480 | * Fill in AF_INET6 family-specific arguments to register |
475 | */ | 481 | */ |
476 | static int rpcb_register_inet6(const struct sockaddr *sap, | 482 | static int rpcb_register_inet6(struct sunrpc_net *sn, |
483 | const struct sockaddr *sap, | ||
477 | struct rpc_message *msg) | 484 | struct rpc_message *msg) |
478 | { | 485 | { |
479 | const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sap; | 486 | const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sap; |
@@ -492,12 +499,13 @@ static int rpcb_register_inet6(const struct sockaddr *sap, | |||
492 | if (port) | 499 | if (port) |
493 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; | 500 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; |
494 | 501 | ||
495 | result = rpcb_register_call(rpcb_local_clnt4, msg); | 502 | result = rpcb_register_call(sn->rpcb_local_clnt4, msg); |
496 | kfree(map->r_addr); | 503 | kfree(map->r_addr); |
497 | return result; | 504 | return result; |
498 | } | 505 | } |
499 | 506 | ||
500 | static int rpcb_unregister_all_protofamilies(struct rpc_message *msg) | 507 | static int rpcb_unregister_all_protofamilies(struct sunrpc_net *sn, |
508 | struct rpc_message *msg) | ||
501 | { | 509 | { |
502 | struct rpcbind_args *map = msg->rpc_argp; | 510 | struct rpcbind_args *map = msg->rpc_argp; |
503 | 511 | ||
@@ -508,7 +516,7 @@ static int rpcb_unregister_all_protofamilies(struct rpc_message *msg) | |||
508 | map->r_addr = ""; | 516 | map->r_addr = ""; |
509 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET]; | 517 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET]; |
510 | 518 | ||
511 | return rpcb_register_call(rpcb_local_clnt4, msg); | 519 | return rpcb_register_call(sn->rpcb_local_clnt4, msg); |
512 | } | 520 | } |
513 | 521 | ||
514 | /** | 522 | /** |
@@ -554,7 +562,7 @@ static int rpcb_unregister_all_protofamilies(struct rpc_message *msg) | |||
554 | * service on any IPv4 address, but not on IPv6. The latter | 562 | * service on any IPv4 address, but not on IPv6. The latter |
555 | * advertises the service on all IPv4 and IPv6 addresses. | 563 | * advertises the service on all IPv4 and IPv6 addresses. |
556 | */ | 564 | */ |
557 | int rpcb_v4_register(const u32 program, const u32 version, | 565 | int rpcb_v4_register(struct net *net, const u32 program, const u32 version, |
558 | const struct sockaddr *address, const char *netid) | 566 | const struct sockaddr *address, const char *netid) |
559 | { | 567 | { |
560 | struct rpcbind_args map = { | 568 | struct rpcbind_args map = { |
@@ -566,18 +574,19 @@ int rpcb_v4_register(const u32 program, const u32 version, | |||
566 | struct rpc_message msg = { | 574 | struct rpc_message msg = { |
567 | .rpc_argp = &map, | 575 | .rpc_argp = &map, |
568 | }; | 576 | }; |
577 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
569 | 578 | ||
570 | if (rpcb_local_clnt4 == NULL) | 579 | if (sn->rpcb_local_clnt4 == NULL) |
571 | return -EPROTONOSUPPORT; | 580 | return -EPROTONOSUPPORT; |
572 | 581 | ||
573 | if (address == NULL) | 582 | if (address == NULL) |
574 | return rpcb_unregister_all_protofamilies(&msg); | 583 | return rpcb_unregister_all_protofamilies(sn, &msg); |
575 | 584 | ||
576 | switch (address->sa_family) { | 585 | switch (address->sa_family) { |
577 | case AF_INET: | 586 | case AF_INET: |
578 | return rpcb_register_inet4(address, &msg); | 587 | return rpcb_register_inet4(sn, address, &msg); |
579 | case AF_INET6: | 588 | case AF_INET6: |
580 | return rpcb_register_inet6(address, &msg); | 589 | return rpcb_register_inet6(sn, address, &msg); |
581 | } | 590 | } |
582 | 591 | ||
583 | return -EAFNOSUPPORT; | 592 | return -EAFNOSUPPORT; |
@@ -611,9 +620,10 @@ static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbi | |||
611 | static struct rpc_clnt *rpcb_find_transport_owner(struct rpc_clnt *clnt) | 620 | static struct rpc_clnt *rpcb_find_transport_owner(struct rpc_clnt *clnt) |
612 | { | 621 | { |
613 | struct rpc_clnt *parent = clnt->cl_parent; | 622 | struct rpc_clnt *parent = clnt->cl_parent; |
623 | struct rpc_xprt *xprt = rcu_dereference(clnt->cl_xprt); | ||
614 | 624 | ||
615 | while (parent != clnt) { | 625 | while (parent != clnt) { |
616 | if (parent->cl_xprt != clnt->cl_xprt) | 626 | if (rcu_dereference(parent->cl_xprt) != xprt) |
617 | break; | 627 | break; |
618 | if (clnt->cl_autobind) | 628 | if (clnt->cl_autobind) |
619 | break; | 629 | break; |
@@ -644,12 +654,16 @@ void rpcb_getport_async(struct rpc_task *task) | |||
644 | size_t salen; | 654 | size_t salen; |
645 | int status; | 655 | int status; |
646 | 656 | ||
647 | clnt = rpcb_find_transport_owner(task->tk_client); | 657 | rcu_read_lock(); |
648 | xprt = clnt->cl_xprt; | 658 | do { |
659 | clnt = rpcb_find_transport_owner(task->tk_client); | ||
660 | xprt = xprt_get(rcu_dereference(clnt->cl_xprt)); | ||
661 | } while (xprt == NULL); | ||
662 | rcu_read_unlock(); | ||
649 | 663 | ||
650 | dprintk("RPC: %5u %s(%s, %u, %u, %d)\n", | 664 | dprintk("RPC: %5u %s(%s, %u, %u, %d)\n", |
651 | task->tk_pid, __func__, | 665 | task->tk_pid, __func__, |
652 | clnt->cl_server, clnt->cl_prog, clnt->cl_vers, xprt->prot); | 666 | xprt->servername, clnt->cl_prog, clnt->cl_vers, xprt->prot); |
653 | 667 | ||
654 | /* Put self on the wait queue to ensure we get notified if | 668 | /* Put self on the wait queue to ensure we get notified if |
655 | * some other task is already attempting to bind the port */ | 669 | * some other task is already attempting to bind the port */ |
@@ -658,6 +672,7 @@ void rpcb_getport_async(struct rpc_task *task) | |||
658 | if (xprt_test_and_set_binding(xprt)) { | 672 | if (xprt_test_and_set_binding(xprt)) { |
659 | dprintk("RPC: %5u %s: waiting for another binder\n", | 673 | dprintk("RPC: %5u %s: waiting for another binder\n", |
660 | task->tk_pid, __func__); | 674 | task->tk_pid, __func__); |
675 | xprt_put(xprt); | ||
661 | return; | 676 | return; |
662 | } | 677 | } |
663 | 678 | ||
@@ -699,8 +714,8 @@ void rpcb_getport_async(struct rpc_task *task) | |||
699 | dprintk("RPC: %5u %s: trying rpcbind version %u\n", | 714 | dprintk("RPC: %5u %s: trying rpcbind version %u\n", |
700 | task->tk_pid, __func__, bind_version); | 715 | task->tk_pid, __func__, bind_version); |
701 | 716 | ||
702 | rpcb_clnt = rpcb_create(clnt->cl_server, sap, salen, xprt->prot, | 717 | rpcb_clnt = rpcb_create(xprt->xprt_net, xprt->servername, sap, salen, |
703 | bind_version); | 718 | xprt->prot, bind_version); |
704 | if (IS_ERR(rpcb_clnt)) { | 719 | if (IS_ERR(rpcb_clnt)) { |
705 | status = PTR_ERR(rpcb_clnt); | 720 | status = PTR_ERR(rpcb_clnt); |
706 | dprintk("RPC: %5u %s: rpcb_create failed, error %ld\n", | 721 | dprintk("RPC: %5u %s: rpcb_create failed, error %ld\n", |
@@ -725,7 +740,7 @@ void rpcb_getport_async(struct rpc_task *task) | |||
725 | switch (bind_version) { | 740 | switch (bind_version) { |
726 | case RPCBVERS_4: | 741 | case RPCBVERS_4: |
727 | case RPCBVERS_3: | 742 | case RPCBVERS_3: |
728 | map->r_netid = rpc_peeraddr2str(clnt, RPC_DISPLAY_NETID); | 743 | map->r_netid = xprt->address_strings[RPC_DISPLAY_NETID]; |
729 | map->r_addr = rpc_sockaddr2uaddr(sap, GFP_ATOMIC); | 744 | map->r_addr = rpc_sockaddr2uaddr(sap, GFP_ATOMIC); |
730 | map->r_owner = ""; | 745 | map->r_owner = ""; |
731 | break; | 746 | break; |
@@ -754,6 +769,7 @@ bailout_release_client: | |||
754 | bailout_nofree: | 769 | bailout_nofree: |
755 | rpcb_wake_rpcbind_waiters(xprt, status); | 770 | rpcb_wake_rpcbind_waiters(xprt, status); |
756 | task->tk_status = status; | 771 | task->tk_status = status; |
772 | xprt_put(xprt); | ||
757 | } | 773 | } |
758 | EXPORT_SYMBOL_GPL(rpcb_getport_async); | 774 | EXPORT_SYMBOL_GPL(rpcb_getport_async); |
759 | 775 | ||
@@ -801,11 +817,11 @@ static void rpcb_getport_done(struct rpc_task *child, void *data) | |||
801 | static void rpcb_enc_mapping(struct rpc_rqst *req, struct xdr_stream *xdr, | 817 | static void rpcb_enc_mapping(struct rpc_rqst *req, struct xdr_stream *xdr, |
802 | const struct rpcbind_args *rpcb) | 818 | const struct rpcbind_args *rpcb) |
803 | { | 819 | { |
804 | struct rpc_task *task = req->rq_task; | ||
805 | __be32 *p; | 820 | __be32 *p; |
806 | 821 | ||
807 | dprintk("RPC: %5u encoding PMAP_%s call (%u, %u, %d, %u)\n", | 822 | dprintk("RPC: %5u encoding PMAP_%s call (%u, %u, %d, %u)\n", |
808 | task->tk_pid, task->tk_msg.rpc_proc->p_name, | 823 | req->rq_task->tk_pid, |
824 | req->rq_task->tk_msg.rpc_proc->p_name, | ||
809 | rpcb->r_prog, rpcb->r_vers, rpcb->r_prot, rpcb->r_port); | 825 | rpcb->r_prog, rpcb->r_vers, rpcb->r_prot, rpcb->r_port); |
810 | 826 | ||
811 | p = xdr_reserve_space(xdr, RPCB_mappingargs_sz << 2); | 827 | p = xdr_reserve_space(xdr, RPCB_mappingargs_sz << 2); |
@@ -818,7 +834,6 @@ static void rpcb_enc_mapping(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
818 | static int rpcb_dec_getport(struct rpc_rqst *req, struct xdr_stream *xdr, | 834 | static int rpcb_dec_getport(struct rpc_rqst *req, struct xdr_stream *xdr, |
819 | struct rpcbind_args *rpcb) | 835 | struct rpcbind_args *rpcb) |
820 | { | 836 | { |
821 | struct rpc_task *task = req->rq_task; | ||
822 | unsigned long port; | 837 | unsigned long port; |
823 | __be32 *p; | 838 | __be32 *p; |
824 | 839 | ||
@@ -829,8 +844,8 @@ static int rpcb_dec_getport(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
829 | return -EIO; | 844 | return -EIO; |
830 | 845 | ||
831 | port = be32_to_cpup(p); | 846 | port = be32_to_cpup(p); |
832 | dprintk("RPC: %5u PMAP_%s result: %lu\n", task->tk_pid, | 847 | dprintk("RPC: %5u PMAP_%s result: %lu\n", req->rq_task->tk_pid, |
833 | task->tk_msg.rpc_proc->p_name, port); | 848 | req->rq_task->tk_msg.rpc_proc->p_name, port); |
834 | if (unlikely(port > USHRT_MAX)) | 849 | if (unlikely(port > USHRT_MAX)) |
835 | return -EIO; | 850 | return -EIO; |
836 | 851 | ||
@@ -841,7 +856,6 @@ static int rpcb_dec_getport(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
841 | static int rpcb_dec_set(struct rpc_rqst *req, struct xdr_stream *xdr, | 856 | static int rpcb_dec_set(struct rpc_rqst *req, struct xdr_stream *xdr, |
842 | unsigned int *boolp) | 857 | unsigned int *boolp) |
843 | { | 858 | { |
844 | struct rpc_task *task = req->rq_task; | ||
845 | __be32 *p; | 859 | __be32 *p; |
846 | 860 | ||
847 | p = xdr_inline_decode(xdr, 4); | 861 | p = xdr_inline_decode(xdr, 4); |
@@ -853,7 +867,8 @@ static int rpcb_dec_set(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
853 | *boolp = 1; | 867 | *boolp = 1; |
854 | 868 | ||
855 | dprintk("RPC: %5u RPCB_%s call %s\n", | 869 | dprintk("RPC: %5u RPCB_%s call %s\n", |
856 | task->tk_pid, task->tk_msg.rpc_proc->p_name, | 870 | req->rq_task->tk_pid, |
871 | req->rq_task->tk_msg.rpc_proc->p_name, | ||
857 | (*boolp ? "succeeded" : "failed")); | 872 | (*boolp ? "succeeded" : "failed")); |
858 | return 0; | 873 | return 0; |
859 | } | 874 | } |
@@ -873,11 +888,11 @@ static void encode_rpcb_string(struct xdr_stream *xdr, const char *string, | |||
873 | static void rpcb_enc_getaddr(struct rpc_rqst *req, struct xdr_stream *xdr, | 888 | static void rpcb_enc_getaddr(struct rpc_rqst *req, struct xdr_stream *xdr, |
874 | const struct rpcbind_args *rpcb) | 889 | const struct rpcbind_args *rpcb) |
875 | { | 890 | { |
876 | struct rpc_task *task = req->rq_task; | ||
877 | __be32 *p; | 891 | __be32 *p; |
878 | 892 | ||
879 | dprintk("RPC: %5u encoding RPCB_%s call (%u, %u, '%s', '%s')\n", | 893 | dprintk("RPC: %5u encoding RPCB_%s call (%u, %u, '%s', '%s')\n", |
880 | task->tk_pid, task->tk_msg.rpc_proc->p_name, | 894 | req->rq_task->tk_pid, |
895 | req->rq_task->tk_msg.rpc_proc->p_name, | ||
881 | rpcb->r_prog, rpcb->r_vers, | 896 | rpcb->r_prog, rpcb->r_vers, |
882 | rpcb->r_netid, rpcb->r_addr); | 897 | rpcb->r_netid, rpcb->r_addr); |
883 | 898 | ||
@@ -895,7 +910,6 @@ static int rpcb_dec_getaddr(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
895 | { | 910 | { |
896 | struct sockaddr_storage address; | 911 | struct sockaddr_storage address; |
897 | struct sockaddr *sap = (struct sockaddr *)&address; | 912 | struct sockaddr *sap = (struct sockaddr *)&address; |
898 | struct rpc_task *task = req->rq_task; | ||
899 | __be32 *p; | 913 | __be32 *p; |
900 | u32 len; | 914 | u32 len; |
901 | 915 | ||
@@ -912,7 +926,7 @@ static int rpcb_dec_getaddr(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
912 | */ | 926 | */ |
913 | if (len == 0) { | 927 | if (len == 0) { |
914 | dprintk("RPC: %5u RPCB reply: program not registered\n", | 928 | dprintk("RPC: %5u RPCB reply: program not registered\n", |
915 | task->tk_pid); | 929 | req->rq_task->tk_pid); |
916 | return 0; | 930 | return 0; |
917 | } | 931 | } |
918 | 932 | ||
@@ -922,10 +936,11 @@ static int rpcb_dec_getaddr(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
922 | p = xdr_inline_decode(xdr, len); | 936 | p = xdr_inline_decode(xdr, len); |
923 | if (unlikely(p == NULL)) | 937 | if (unlikely(p == NULL)) |
924 | goto out_fail; | 938 | goto out_fail; |
925 | dprintk("RPC: %5u RPCB_%s reply: %s\n", task->tk_pid, | 939 | dprintk("RPC: %5u RPCB_%s reply: %s\n", req->rq_task->tk_pid, |
926 | task->tk_msg.rpc_proc->p_name, (char *)p); | 940 | req->rq_task->tk_msg.rpc_proc->p_name, (char *)p); |
927 | 941 | ||
928 | if (rpc_uaddr2sockaddr((char *)p, len, sap, sizeof(address)) == 0) | 942 | if (rpc_uaddr2sockaddr(req->rq_xprt->xprt_net, (char *)p, len, |
943 | sap, sizeof(address)) == 0) | ||
929 | goto out_fail; | 944 | goto out_fail; |
930 | rpcb->r_port = rpc_get_port(sap); | 945 | rpcb->r_port = rpc_get_port(sap); |
931 | 946 | ||
@@ -933,7 +948,8 @@ static int rpcb_dec_getaddr(struct rpc_rqst *req, struct xdr_stream *xdr, | |||
933 | 948 | ||
934 | out_fail: | 949 | out_fail: |
935 | dprintk("RPC: %5u malformed RPCB_%s reply\n", | 950 | dprintk("RPC: %5u malformed RPCB_%s reply\n", |
936 | task->tk_pid, task->tk_msg.rpc_proc->p_name); | 951 | req->rq_task->tk_pid, |
952 | req->rq_task->tk_msg.rpc_proc->p_name); | ||
937 | return -EIO; | 953 | return -EIO; |
938 | } | 954 | } |
939 | 955 | ||
@@ -1041,7 +1057,7 @@ static struct rpc_procinfo rpcb_procedures4[] = { | |||
1041 | }, | 1057 | }, |
1042 | }; | 1058 | }; |
1043 | 1059 | ||
1044 | static struct rpcb_info rpcb_next_version[] = { | 1060 | static const struct rpcb_info rpcb_next_version[] = { |
1045 | { | 1061 | { |
1046 | .rpc_vers = RPCBVERS_2, | 1062 | .rpc_vers = RPCBVERS_2, |
1047 | .rpc_proc = &rpcb_procedures2[RPCBPROC_GETPORT], | 1063 | .rpc_proc = &rpcb_procedures2[RPCBPROC_GETPORT], |
@@ -1051,7 +1067,7 @@ static struct rpcb_info rpcb_next_version[] = { | |||
1051 | }, | 1067 | }, |
1052 | }; | 1068 | }; |
1053 | 1069 | ||
1054 | static struct rpcb_info rpcb_next_version6[] = { | 1070 | static const struct rpcb_info rpcb_next_version6[] = { |
1055 | { | 1071 | { |
1056 | .rpc_vers = RPCBVERS_4, | 1072 | .rpc_vers = RPCBVERS_4, |
1057 | .rpc_proc = &rpcb_procedures4[RPCBPROC_GETADDR], | 1073 | .rpc_proc = &rpcb_procedures4[RPCBPROC_GETADDR], |
@@ -1065,25 +1081,25 @@ static struct rpcb_info rpcb_next_version6[] = { | |||
1065 | }, | 1081 | }, |
1066 | }; | 1082 | }; |
1067 | 1083 | ||
1068 | static struct rpc_version rpcb_version2 = { | 1084 | static const struct rpc_version rpcb_version2 = { |
1069 | .number = RPCBVERS_2, | 1085 | .number = RPCBVERS_2, |
1070 | .nrprocs = ARRAY_SIZE(rpcb_procedures2), | 1086 | .nrprocs = ARRAY_SIZE(rpcb_procedures2), |
1071 | .procs = rpcb_procedures2 | 1087 | .procs = rpcb_procedures2 |
1072 | }; | 1088 | }; |
1073 | 1089 | ||
1074 | static struct rpc_version rpcb_version3 = { | 1090 | static const struct rpc_version rpcb_version3 = { |
1075 | .number = RPCBVERS_3, | 1091 | .number = RPCBVERS_3, |
1076 | .nrprocs = ARRAY_SIZE(rpcb_procedures3), | 1092 | .nrprocs = ARRAY_SIZE(rpcb_procedures3), |
1077 | .procs = rpcb_procedures3 | 1093 | .procs = rpcb_procedures3 |
1078 | }; | 1094 | }; |
1079 | 1095 | ||
1080 | static struct rpc_version rpcb_version4 = { | 1096 | static const struct rpc_version rpcb_version4 = { |
1081 | .number = RPCBVERS_4, | 1097 | .number = RPCBVERS_4, |
1082 | .nrprocs = ARRAY_SIZE(rpcb_procedures4), | 1098 | .nrprocs = ARRAY_SIZE(rpcb_procedures4), |
1083 | .procs = rpcb_procedures4 | 1099 | .procs = rpcb_procedures4 |
1084 | }; | 1100 | }; |
1085 | 1101 | ||
1086 | static struct rpc_version *rpcb_version[] = { | 1102 | static const struct rpc_version *rpcb_version[] = { |
1087 | NULL, | 1103 | NULL, |
1088 | NULL, | 1104 | NULL, |
1089 | &rpcb_version2, | 1105 | &rpcb_version2, |
@@ -1093,7 +1109,7 @@ static struct rpc_version *rpcb_version[] = { | |||
1093 | 1109 | ||
1094 | static struct rpc_stat rpcb_stats; | 1110 | static struct rpc_stat rpcb_stats; |
1095 | 1111 | ||
1096 | static struct rpc_program rpcb_program = { | 1112 | static const struct rpc_program rpcb_program = { |
1097 | .name = "rpcbind", | 1113 | .name = "rpcbind", |
1098 | .number = RPCBIND_PROGRAM, | 1114 | .number = RPCBIND_PROGRAM, |
1099 | .nrvers = ARRAY_SIZE(rpcb_version), | 1115 | .nrvers = ARRAY_SIZE(rpcb_version), |
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 3341d8962786..994cfea2bad6 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c | |||
@@ -28,6 +28,9 @@ | |||
28 | #define RPCDBG_FACILITY RPCDBG_SCHED | 28 | #define RPCDBG_FACILITY RPCDBG_SCHED |
29 | #endif | 29 | #endif |
30 | 30 | ||
31 | #define CREATE_TRACE_POINTS | ||
32 | #include <trace/events/sunrpc.h> | ||
33 | |||
31 | /* | 34 | /* |
32 | * RPC slabs and memory pools | 35 | * RPC slabs and memory pools |
33 | */ | 36 | */ |
@@ -205,9 +208,7 @@ static void __rpc_init_priority_wait_queue(struct rpc_wait_queue *queue, const c | |||
205 | queue->qlen = 0; | 208 | queue->qlen = 0; |
206 | setup_timer(&queue->timer_list.timer, __rpc_queue_timer_fn, (unsigned long)queue); | 209 | setup_timer(&queue->timer_list.timer, __rpc_queue_timer_fn, (unsigned long)queue); |
207 | INIT_LIST_HEAD(&queue->timer_list.list); | 210 | INIT_LIST_HEAD(&queue->timer_list.list); |
208 | #ifdef RPC_DEBUG | 211 | rpc_assign_waitqueue_name(queue, qname); |
209 | queue->name = qname; | ||
210 | #endif | ||
211 | } | 212 | } |
212 | 213 | ||
213 | void rpc_init_priority_wait_queue(struct rpc_wait_queue *queue, const char *qname) | 214 | void rpc_init_priority_wait_queue(struct rpc_wait_queue *queue, const char *qname) |
@@ -251,6 +252,8 @@ static inline void rpc_task_set_debuginfo(struct rpc_task *task) | |||
251 | 252 | ||
252 | static void rpc_set_active(struct rpc_task *task) | 253 | static void rpc_set_active(struct rpc_task *task) |
253 | { | 254 | { |
255 | trace_rpc_task_begin(task->tk_client, task, NULL); | ||
256 | |||
254 | rpc_task_set_debuginfo(task); | 257 | rpc_task_set_debuginfo(task); |
255 | set_bit(RPC_TASK_ACTIVE, &task->tk_runstate); | 258 | set_bit(RPC_TASK_ACTIVE, &task->tk_runstate); |
256 | } | 259 | } |
@@ -267,6 +270,8 @@ static int rpc_complete_task(struct rpc_task *task) | |||
267 | unsigned long flags; | 270 | unsigned long flags; |
268 | int ret; | 271 | int ret; |
269 | 272 | ||
273 | trace_rpc_task_complete(task->tk_client, task, NULL); | ||
274 | |||
270 | spin_lock_irqsave(&wq->lock, flags); | 275 | spin_lock_irqsave(&wq->lock, flags); |
271 | clear_bit(RPC_TASK_ACTIVE, &task->tk_runstate); | 276 | clear_bit(RPC_TASK_ACTIVE, &task->tk_runstate); |
272 | ret = atomic_dec_and_test(&task->tk_count); | 277 | ret = atomic_dec_and_test(&task->tk_count); |
@@ -324,6 +329,8 @@ static void __rpc_sleep_on_priority(struct rpc_wait_queue *q, | |||
324 | dprintk("RPC: %5u sleep_on(queue \"%s\" time %lu)\n", | 329 | dprintk("RPC: %5u sleep_on(queue \"%s\" time %lu)\n", |
325 | task->tk_pid, rpc_qname(q), jiffies); | 330 | task->tk_pid, rpc_qname(q), jiffies); |
326 | 331 | ||
332 | trace_rpc_task_sleep(task->tk_client, task, q); | ||
333 | |||
327 | __rpc_add_wait_queue(q, task, queue_priority); | 334 | __rpc_add_wait_queue(q, task, queue_priority); |
328 | 335 | ||
329 | BUG_ON(task->tk_callback != NULL); | 336 | BUG_ON(task->tk_callback != NULL); |
@@ -378,6 +385,8 @@ static void __rpc_do_wake_up_task(struct rpc_wait_queue *queue, struct rpc_task | |||
378 | return; | 385 | return; |
379 | } | 386 | } |
380 | 387 | ||
388 | trace_rpc_task_wakeup(task->tk_client, task, queue); | ||
389 | |||
381 | __rpc_remove_wait_queue(queue, task); | 390 | __rpc_remove_wait_queue(queue, task); |
382 | 391 | ||
383 | rpc_make_runnable(task); | 392 | rpc_make_runnable(task); |
@@ -422,7 +431,7 @@ EXPORT_SYMBOL_GPL(rpc_wake_up_queued_task); | |||
422 | /* | 431 | /* |
423 | * Wake up the next task on a priority queue. | 432 | * Wake up the next task on a priority queue. |
424 | */ | 433 | */ |
425 | static struct rpc_task * __rpc_wake_up_next_priority(struct rpc_wait_queue *queue) | 434 | static struct rpc_task *__rpc_find_next_queued_priority(struct rpc_wait_queue *queue) |
426 | { | 435 | { |
427 | struct list_head *q; | 436 | struct list_head *q; |
428 | struct rpc_task *task; | 437 | struct rpc_task *task; |
@@ -467,30 +476,54 @@ new_queue: | |||
467 | new_owner: | 476 | new_owner: |
468 | rpc_set_waitqueue_owner(queue, task->tk_owner); | 477 | rpc_set_waitqueue_owner(queue, task->tk_owner); |
469 | out: | 478 | out: |
470 | rpc_wake_up_task_queue_locked(queue, task); | ||
471 | return task; | 479 | return task; |
472 | } | 480 | } |
473 | 481 | ||
482 | static struct rpc_task *__rpc_find_next_queued(struct rpc_wait_queue *queue) | ||
483 | { | ||
484 | if (RPC_IS_PRIORITY(queue)) | ||
485 | return __rpc_find_next_queued_priority(queue); | ||
486 | if (!list_empty(&queue->tasks[0])) | ||
487 | return list_first_entry(&queue->tasks[0], struct rpc_task, u.tk_wait.list); | ||
488 | return NULL; | ||
489 | } | ||
490 | |||
474 | /* | 491 | /* |
475 | * Wake up the next task on the wait queue. | 492 | * Wake up the first task on the wait queue. |
476 | */ | 493 | */ |
477 | struct rpc_task * rpc_wake_up_next(struct rpc_wait_queue *queue) | 494 | struct rpc_task *rpc_wake_up_first(struct rpc_wait_queue *queue, |
495 | bool (*func)(struct rpc_task *, void *), void *data) | ||
478 | { | 496 | { |
479 | struct rpc_task *task = NULL; | 497 | struct rpc_task *task = NULL; |
480 | 498 | ||
481 | dprintk("RPC: wake_up_next(%p \"%s\")\n", | 499 | dprintk("RPC: wake_up_first(%p \"%s\")\n", |
482 | queue, rpc_qname(queue)); | 500 | queue, rpc_qname(queue)); |
483 | spin_lock_bh(&queue->lock); | 501 | spin_lock_bh(&queue->lock); |
484 | if (RPC_IS_PRIORITY(queue)) | 502 | task = __rpc_find_next_queued(queue); |
485 | task = __rpc_wake_up_next_priority(queue); | 503 | if (task != NULL) { |
486 | else { | 504 | if (func(task, data)) |
487 | task_for_first(task, &queue->tasks[0]) | ||
488 | rpc_wake_up_task_queue_locked(queue, task); | 505 | rpc_wake_up_task_queue_locked(queue, task); |
506 | else | ||
507 | task = NULL; | ||
489 | } | 508 | } |
490 | spin_unlock_bh(&queue->lock); | 509 | spin_unlock_bh(&queue->lock); |
491 | 510 | ||
492 | return task; | 511 | return task; |
493 | } | 512 | } |
513 | EXPORT_SYMBOL_GPL(rpc_wake_up_first); | ||
514 | |||
515 | static bool rpc_wake_up_next_func(struct rpc_task *task, void *data) | ||
516 | { | ||
517 | return true; | ||
518 | } | ||
519 | |||
520 | /* | ||
521 | * Wake up the next task on the wait queue. | ||
522 | */ | ||
523 | struct rpc_task *rpc_wake_up_next(struct rpc_wait_queue *queue) | ||
524 | { | ||
525 | return rpc_wake_up_first(queue, rpc_wake_up_next_func, NULL); | ||
526 | } | ||
494 | EXPORT_SYMBOL_GPL(rpc_wake_up_next); | 527 | EXPORT_SYMBOL_GPL(rpc_wake_up_next); |
495 | 528 | ||
496 | /** | 529 | /** |
@@ -501,14 +534,18 @@ EXPORT_SYMBOL_GPL(rpc_wake_up_next); | |||
501 | */ | 534 | */ |
502 | void rpc_wake_up(struct rpc_wait_queue *queue) | 535 | void rpc_wake_up(struct rpc_wait_queue *queue) |
503 | { | 536 | { |
504 | struct rpc_task *task, *next; | ||
505 | struct list_head *head; | 537 | struct list_head *head; |
506 | 538 | ||
507 | spin_lock_bh(&queue->lock); | 539 | spin_lock_bh(&queue->lock); |
508 | head = &queue->tasks[queue->maxpriority]; | 540 | head = &queue->tasks[queue->maxpriority]; |
509 | for (;;) { | 541 | for (;;) { |
510 | list_for_each_entry_safe(task, next, head, u.tk_wait.list) | 542 | while (!list_empty(head)) { |
543 | struct rpc_task *task; | ||
544 | task = list_first_entry(head, | ||
545 | struct rpc_task, | ||
546 | u.tk_wait.list); | ||
511 | rpc_wake_up_task_queue_locked(queue, task); | 547 | rpc_wake_up_task_queue_locked(queue, task); |
548 | } | ||
512 | if (head == &queue->tasks[0]) | 549 | if (head == &queue->tasks[0]) |
513 | break; | 550 | break; |
514 | head--; | 551 | head--; |
@@ -526,13 +563,16 @@ EXPORT_SYMBOL_GPL(rpc_wake_up); | |||
526 | */ | 563 | */ |
527 | void rpc_wake_up_status(struct rpc_wait_queue *queue, int status) | 564 | void rpc_wake_up_status(struct rpc_wait_queue *queue, int status) |
528 | { | 565 | { |
529 | struct rpc_task *task, *next; | ||
530 | struct list_head *head; | 566 | struct list_head *head; |
531 | 567 | ||
532 | spin_lock_bh(&queue->lock); | 568 | spin_lock_bh(&queue->lock); |
533 | head = &queue->tasks[queue->maxpriority]; | 569 | head = &queue->tasks[queue->maxpriority]; |
534 | for (;;) { | 570 | for (;;) { |
535 | list_for_each_entry_safe(task, next, head, u.tk_wait.list) { | 571 | while (!list_empty(head)) { |
572 | struct rpc_task *task; | ||
573 | task = list_first_entry(head, | ||
574 | struct rpc_task, | ||
575 | u.tk_wait.list); | ||
536 | task->tk_status = status; | 576 | task->tk_status = status; |
537 | rpc_wake_up_task_queue_locked(queue, task); | 577 | rpc_wake_up_task_queue_locked(queue, task); |
538 | } | 578 | } |
@@ -677,6 +717,7 @@ static void __rpc_execute(struct rpc_task *task) | |||
677 | if (do_action == NULL) | 717 | if (do_action == NULL) |
678 | break; | 718 | break; |
679 | } | 719 | } |
720 | trace_rpc_task_run_action(task->tk_client, task, task->tk_action); | ||
680 | do_action(task); | 721 | do_action(task); |
681 | 722 | ||
682 | /* | 723 | /* |
diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c index 80df89d957ba..bc2068ee795b 100644 --- a/net/sunrpc/stats.c +++ b/net/sunrpc/stats.c | |||
@@ -22,6 +22,7 @@ | |||
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> | ||
25 | 26 | ||
26 | #include "netns.h" | 27 | #include "netns.h" |
27 | 28 | ||
@@ -133,20 +134,19 @@ EXPORT_SYMBOL_GPL(rpc_free_iostats); | |||
133 | /** | 134 | /** |
134 | * rpc_count_iostats - tally up per-task stats | 135 | * rpc_count_iostats - tally up per-task stats |
135 | * @task: completed rpc_task | 136 | * @task: completed rpc_task |
137 | * @stats: array of stat structures | ||
136 | * | 138 | * |
137 | * Relies on the caller for serialization. | 139 | * Relies on the caller for serialization. |
138 | */ | 140 | */ |
139 | void rpc_count_iostats(struct rpc_task *task) | 141 | void rpc_count_iostats(const struct rpc_task *task, struct rpc_iostats *stats) |
140 | { | 142 | { |
141 | struct rpc_rqst *req = task->tk_rqstp; | 143 | struct rpc_rqst *req = task->tk_rqstp; |
142 | struct rpc_iostats *stats; | ||
143 | struct rpc_iostats *op_metrics; | 144 | struct rpc_iostats *op_metrics; |
144 | ktime_t delta; | 145 | ktime_t delta; |
145 | 146 | ||
146 | if (!task->tk_client || !task->tk_client->cl_metrics || !req) | 147 | if (!stats || !req) |
147 | return; | 148 | return; |
148 | 149 | ||
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,6 +164,7 @@ void rpc_count_iostats(struct rpc_task *task) | |||
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); | ||
167 | 168 | ||
168 | static void _print_name(struct seq_file *seq, unsigned int op, | 169 | static void _print_name(struct seq_file *seq, unsigned int op, |
169 | struct rpc_procinfo *procs) | 170 | struct rpc_procinfo *procs) |
@@ -179,7 +180,7 @@ static void _print_name(struct seq_file *seq, unsigned int op, | |||
179 | void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt) | 180 | void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt) |
180 | { | 181 | { |
181 | struct rpc_iostats *stats = clnt->cl_metrics; | 182 | struct rpc_iostats *stats = clnt->cl_metrics; |
182 | struct rpc_xprt *xprt = clnt->cl_xprt; | 183 | struct rpc_xprt *xprt; |
183 | unsigned int op, maxproc = clnt->cl_maxproc; | 184 | unsigned int op, maxproc = clnt->cl_maxproc; |
184 | 185 | ||
185 | if (!stats) | 186 | if (!stats) |
@@ -189,8 +190,11 @@ void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt) | |||
189 | seq_printf(seq, "p/v: %u/%u (%s)\n", | 190 | seq_printf(seq, "p/v: %u/%u (%s)\n", |
190 | clnt->cl_prog, clnt->cl_vers, clnt->cl_protname); | 191 | clnt->cl_prog, clnt->cl_vers, clnt->cl_protname); |
191 | 192 | ||
193 | rcu_read_lock(); | ||
194 | xprt = rcu_dereference(clnt->cl_xprt); | ||
192 | if (xprt) | 195 | if (xprt) |
193 | xprt->ops->print_stats(xprt, seq); | 196 | xprt->ops->print_stats(xprt, seq); |
197 | rcu_read_unlock(); | ||
194 | 198 | ||
195 | seq_printf(seq, "\tper-op statistics\n"); | 199 | seq_printf(seq, "\tper-op statistics\n"); |
196 | for (op = 0; op < maxproc; op++) { | 200 | for (op = 0; op < maxproc; op++) { |
@@ -213,45 +217,46 @@ EXPORT_SYMBOL_GPL(rpc_print_iostats); | |||
213 | * Register/unregister RPC proc files | 217 | * Register/unregister RPC proc files |
214 | */ | 218 | */ |
215 | static inline struct proc_dir_entry * | 219 | static inline struct proc_dir_entry * |
216 | do_register(const char *name, void *data, const struct file_operations *fops) | 220 | do_register(struct net *net, const char *name, void *data, |
221 | const struct file_operations *fops) | ||
217 | { | 222 | { |
218 | struct sunrpc_net *sn; | 223 | struct sunrpc_net *sn; |
219 | 224 | ||
220 | dprintk("RPC: registering /proc/net/rpc/%s\n", name); | 225 | dprintk("RPC: registering /proc/net/rpc/%s\n", name); |
221 | sn = net_generic(&init_net, sunrpc_net_id); | 226 | sn = net_generic(net, sunrpc_net_id); |
222 | return proc_create_data(name, 0, sn->proc_net_rpc, fops, data); | 227 | return proc_create_data(name, 0, sn->proc_net_rpc, fops, data); |
223 | } | 228 | } |
224 | 229 | ||
225 | struct proc_dir_entry * | 230 | struct proc_dir_entry * |
226 | rpc_proc_register(struct rpc_stat *statp) | 231 | rpc_proc_register(struct net *net, struct rpc_stat *statp) |
227 | { | 232 | { |
228 | return do_register(statp->program->name, statp, &rpc_proc_fops); | 233 | return do_register(net, statp->program->name, statp, &rpc_proc_fops); |
229 | } | 234 | } |
230 | EXPORT_SYMBOL_GPL(rpc_proc_register); | 235 | EXPORT_SYMBOL_GPL(rpc_proc_register); |
231 | 236 | ||
232 | void | 237 | void |
233 | rpc_proc_unregister(const char *name) | 238 | rpc_proc_unregister(struct net *net, const char *name) |
234 | { | 239 | { |
235 | struct sunrpc_net *sn; | 240 | struct sunrpc_net *sn; |
236 | 241 | ||
237 | sn = net_generic(&init_net, sunrpc_net_id); | 242 | sn = net_generic(net, sunrpc_net_id); |
238 | remove_proc_entry(name, sn->proc_net_rpc); | 243 | remove_proc_entry(name, sn->proc_net_rpc); |
239 | } | 244 | } |
240 | EXPORT_SYMBOL_GPL(rpc_proc_unregister); | 245 | EXPORT_SYMBOL_GPL(rpc_proc_unregister); |
241 | 246 | ||
242 | struct proc_dir_entry * | 247 | struct proc_dir_entry * |
243 | svc_proc_register(struct svc_stat *statp, const struct file_operations *fops) | 248 | svc_proc_register(struct net *net, struct svc_stat *statp, const struct file_operations *fops) |
244 | { | 249 | { |
245 | return do_register(statp->program->pg_name, statp, fops); | 250 | return do_register(net, statp->program->pg_name, statp, fops); |
246 | } | 251 | } |
247 | EXPORT_SYMBOL_GPL(svc_proc_register); | 252 | EXPORT_SYMBOL_GPL(svc_proc_register); |
248 | 253 | ||
249 | void | 254 | void |
250 | svc_proc_unregister(const char *name) | 255 | svc_proc_unregister(struct net *net, const char *name) |
251 | { | 256 | { |
252 | struct sunrpc_net *sn; | 257 | struct sunrpc_net *sn; |
253 | 258 | ||
254 | sn = net_generic(&init_net, sunrpc_net_id); | 259 | sn = net_generic(net, sunrpc_net_id); |
255 | remove_proc_entry(name, sn->proc_net_rpc); | 260 | remove_proc_entry(name, sn->proc_net_rpc); |
256 | } | 261 | } |
257 | EXPORT_SYMBOL_GPL(svc_proc_unregister); | 262 | EXPORT_SYMBOL_GPL(svc_proc_unregister); |
diff --git a/net/sunrpc/sunrpc.h b/net/sunrpc/sunrpc.h index 90c292e2738b..14c9f6d1c5ff 100644 --- a/net/sunrpc/sunrpc.h +++ b/net/sunrpc/sunrpc.h | |||
@@ -47,5 +47,7 @@ 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); | ||
50 | #endif /* _NET_SUNRPC_SUNRPC_H */ | 52 | #endif /* _NET_SUNRPC_SUNRPC_H */ |
51 | 53 | ||
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c index 8ec9778c3f4a..8adfc88e793a 100644 --- a/net/sunrpc/sunrpc_syms.c +++ b/net/sunrpc/sunrpc_syms.c | |||
@@ -25,10 +25,12 @@ | |||
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); | ||
28 | 29 | ||
29 | static __net_init int sunrpc_init_net(struct net *net) | 30 | static __net_init int sunrpc_init_net(struct net *net) |
30 | { | 31 | { |
31 | int err; | 32 | int err; |
33 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
32 | 34 | ||
33 | err = rpc_proc_init(net); | 35 | err = rpc_proc_init(net); |
34 | if (err) | 36 | if (err) |
@@ -38,8 +40,18 @@ static __net_init int sunrpc_init_net(struct net *net) | |||
38 | if (err) | 40 | if (err) |
39 | goto err_ipmap; | 41 | goto err_ipmap; |
40 | 42 | ||
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); | ||
41 | return 0; | 51 | return 0; |
42 | 52 | ||
53 | err_unixgid: | ||
54 | ip_map_cache_destroy(net); | ||
43 | err_ipmap: | 55 | err_ipmap: |
44 | rpc_proc_exit(net); | 56 | rpc_proc_exit(net); |
45 | err_proc: | 57 | err_proc: |
@@ -48,6 +60,7 @@ err_proc: | |||
48 | 60 | ||
49 | static __net_exit void sunrpc_exit_net(struct net *net) | 61 | static __net_exit void sunrpc_exit_net(struct net *net) |
50 | { | 62 | { |
63 | unix_gid_cache_destroy(net); | ||
51 | ip_map_cache_destroy(net); | 64 | ip_map_cache_destroy(net); |
52 | rpc_proc_exit(net); | 65 | rpc_proc_exit(net); |
53 | } | 66 | } |
@@ -59,8 +72,6 @@ static struct pernet_operations sunrpc_net_ops = { | |||
59 | .size = sizeof(struct sunrpc_net), | 72 | .size = sizeof(struct sunrpc_net), |
60 | }; | 73 | }; |
61 | 74 | ||
62 | extern struct cache_detail unix_gid_cache; | ||
63 | |||
64 | static int __init | 75 | static int __init |
65 | init_sunrpc(void) | 76 | init_sunrpc(void) |
66 | { | 77 | { |
@@ -82,7 +93,6 @@ init_sunrpc(void) | |||
82 | #ifdef RPC_DEBUG | 93 | #ifdef RPC_DEBUG |
83 | rpc_register_sysctl(); | 94 | rpc_register_sysctl(); |
84 | #endif | 95 | #endif |
85 | cache_register(&unix_gid_cache); | ||
86 | svc_init_xprt_sock(); /* svc sock transport */ | 96 | svc_init_xprt_sock(); /* svc sock transport */ |
87 | init_socket_xprt(); /* clnt sock transport */ | 97 | init_socket_xprt(); /* clnt sock transport */ |
88 | return 0; | 98 | return 0; |
@@ -105,7 +115,6 @@ cleanup_sunrpc(void) | |||
105 | svc_cleanup_xprt_sock(); | 115 | svc_cleanup_xprt_sock(); |
106 | unregister_rpc_pipefs(); | 116 | unregister_rpc_pipefs(); |
107 | rpc_destroy_mempool(); | 117 | rpc_destroy_mempool(); |
108 | cache_unregister(&unix_gid_cache); | ||
109 | unregister_pernet_subsys(&sunrpc_net_ops); | 118 | unregister_pernet_subsys(&sunrpc_net_ops); |
110 | #ifdef RPC_DEBUG | 119 | #ifdef RPC_DEBUG |
111 | rpc_unregister_sysctl(); | 120 | rpc_unregister_sysctl(); |
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index e4aabc02368b..4153846984ac 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/kthread.h> | 21 | #include <linux/kthread.h> |
22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | #include <linux/nsproxy.h> | ||
23 | 24 | ||
24 | #include <linux/sunrpc/types.h> | 25 | #include <linux/sunrpc/types.h> |
25 | #include <linux/sunrpc/xdr.h> | 26 | #include <linux/sunrpc/xdr.h> |
@@ -30,7 +31,7 @@ | |||
30 | 31 | ||
31 | #define RPCDBG_FACILITY RPCDBG_SVCDSP | 32 | #define RPCDBG_FACILITY RPCDBG_SVCDSP |
32 | 33 | ||
33 | static void svc_unregister(const struct svc_serv *serv); | 34 | static void svc_unregister(const struct svc_serv *serv, struct net *net); |
34 | 35 | ||
35 | #define svc_serv_is_pooled(serv) ((serv)->sv_function) | 36 | #define svc_serv_is_pooled(serv) ((serv)->sv_function) |
36 | 37 | ||
@@ -368,23 +369,24 @@ svc_pool_for_cpu(struct svc_serv *serv, int cpu) | |||
368 | return &serv->sv_pools[pidx % serv->sv_nrpools]; | 369 | return &serv->sv_pools[pidx % serv->sv_nrpools]; |
369 | } | 370 | } |
370 | 371 | ||
371 | static int svc_rpcb_setup(struct svc_serv *serv) | 372 | int svc_rpcb_setup(struct svc_serv *serv, struct net *net) |
372 | { | 373 | { |
373 | int err; | 374 | int err; |
374 | 375 | ||
375 | err = rpcb_create_local(); | 376 | err = rpcb_create_local(net); |
376 | if (err) | 377 | if (err) |
377 | return err; | 378 | return err; |
378 | 379 | ||
379 | /* Remove any stale portmap registrations */ | 380 | /* Remove any stale portmap registrations */ |
380 | svc_unregister(serv); | 381 | svc_unregister(serv, net); |
381 | return 0; | 382 | return 0; |
382 | } | 383 | } |
384 | EXPORT_SYMBOL_GPL(svc_rpcb_setup); | ||
383 | 385 | ||
384 | void svc_rpcb_cleanup(struct svc_serv *serv) | 386 | void svc_rpcb_cleanup(struct svc_serv *serv, struct net *net) |
385 | { | 387 | { |
386 | svc_unregister(serv); | 388 | svc_unregister(serv, net); |
387 | rpcb_put_local(); | 389 | rpcb_put_local(net); |
388 | } | 390 | } |
389 | EXPORT_SYMBOL_GPL(svc_rpcb_cleanup); | 391 | EXPORT_SYMBOL_GPL(svc_rpcb_cleanup); |
390 | 392 | ||
@@ -410,7 +412,7 @@ static int svc_uses_rpcbind(struct svc_serv *serv) | |||
410 | */ | 412 | */ |
411 | static struct svc_serv * | 413 | static struct svc_serv * |
412 | __svc_create(struct svc_program *prog, unsigned int bufsize, int npools, | 414 | __svc_create(struct svc_program *prog, unsigned int bufsize, int npools, |
413 | void (*shutdown)(struct svc_serv *serv)) | 415 | void (*shutdown)(struct svc_serv *serv, struct net *net)) |
414 | { | 416 | { |
415 | struct svc_serv *serv; | 417 | struct svc_serv *serv; |
416 | unsigned int vers; | 418 | unsigned int vers; |
@@ -470,7 +472,7 @@ __svc_create(struct svc_program *prog, unsigned int bufsize, int npools, | |||
470 | } | 472 | } |
471 | 473 | ||
472 | if (svc_uses_rpcbind(serv)) { | 474 | if (svc_uses_rpcbind(serv)) { |
473 | if (svc_rpcb_setup(serv) < 0) { | 475 | if (svc_rpcb_setup(serv, current->nsproxy->net_ns) < 0) { |
474 | kfree(serv->sv_pools); | 476 | kfree(serv->sv_pools); |
475 | kfree(serv); | 477 | kfree(serv); |
476 | return NULL; | 478 | return NULL; |
@@ -484,7 +486,7 @@ __svc_create(struct svc_program *prog, unsigned int bufsize, int npools, | |||
484 | 486 | ||
485 | struct svc_serv * | 487 | struct svc_serv * |
486 | svc_create(struct svc_program *prog, unsigned int bufsize, | 488 | svc_create(struct svc_program *prog, unsigned int bufsize, |
487 | void (*shutdown)(struct svc_serv *serv)) | 489 | void (*shutdown)(struct svc_serv *serv, struct net *net)) |
488 | { | 490 | { |
489 | return __svc_create(prog, bufsize, /*npools*/1, shutdown); | 491 | return __svc_create(prog, bufsize, /*npools*/1, shutdown); |
490 | } | 492 | } |
@@ -492,7 +494,7 @@ EXPORT_SYMBOL_GPL(svc_create); | |||
492 | 494 | ||
493 | struct svc_serv * | 495 | struct svc_serv * |
494 | svc_create_pooled(struct svc_program *prog, unsigned int bufsize, | 496 | svc_create_pooled(struct svc_program *prog, unsigned int bufsize, |
495 | void (*shutdown)(struct svc_serv *serv), | 497 | void (*shutdown)(struct svc_serv *serv, struct net *net), |
496 | svc_thread_fn func, struct module *mod) | 498 | svc_thread_fn func, struct module *mod) |
497 | { | 499 | { |
498 | struct svc_serv *serv; | 500 | struct svc_serv *serv; |
@@ -509,6 +511,24 @@ svc_create_pooled(struct svc_program *prog, unsigned int bufsize, | |||
509 | } | 511 | } |
510 | EXPORT_SYMBOL_GPL(svc_create_pooled); | 512 | EXPORT_SYMBOL_GPL(svc_create_pooled); |
511 | 513 | ||
514 | void svc_shutdown_net(struct svc_serv *serv, struct net *net) | ||
515 | { | ||
516 | /* | ||
517 | * The set of xprts (contained in the sv_tempsocks and | ||
518 | * sv_permsocks lists) is now constant, since it is modified | ||
519 | * only by accepting new sockets (done by service threads in | ||
520 | * svc_recv) or aging old ones (done by sv_temptimer), or | ||
521 | * configuration changes (excluded by whatever locking the | ||
522 | * caller is using--nfsd_mutex in the case of nfsd). So it's | ||
523 | * safe to traverse those lists and shut everything down: | ||
524 | */ | ||
525 | svc_close_net(serv, net); | ||
526 | |||
527 | if (serv->sv_shutdown) | ||
528 | serv->sv_shutdown(serv, net); | ||
529 | } | ||
530 | EXPORT_SYMBOL_GPL(svc_shutdown_net); | ||
531 | |||
512 | /* | 532 | /* |
513 | * Destroy an RPC service. Should be called with appropriate locking to | 533 | * Destroy an RPC service. Should be called with appropriate locking to |
514 | * protect the sv_nrthreads, sv_permsocks and sv_tempsocks. | 534 | * protect the sv_nrthreads, sv_permsocks and sv_tempsocks. |
@@ -516,6 +536,8 @@ EXPORT_SYMBOL_GPL(svc_create_pooled); | |||
516 | void | 536 | void |
517 | svc_destroy(struct svc_serv *serv) | 537 | svc_destroy(struct svc_serv *serv) |
518 | { | 538 | { |
539 | struct net *net = current->nsproxy->net_ns; | ||
540 | |||
519 | dprintk("svc: svc_destroy(%s, %d)\n", | 541 | dprintk("svc: svc_destroy(%s, %d)\n", |
520 | serv->sv_program->pg_name, | 542 | serv->sv_program->pg_name, |
521 | serv->sv_nrthreads); | 543 | serv->sv_nrthreads); |
@@ -529,19 +551,15 @@ svc_destroy(struct svc_serv *serv) | |||
529 | printk("svc_destroy: no threads for serv=%p!\n", serv); | 551 | printk("svc_destroy: no threads for serv=%p!\n", serv); |
530 | 552 | ||
531 | del_timer_sync(&serv->sv_temptimer); | 553 | del_timer_sync(&serv->sv_temptimer); |
554 | |||
555 | svc_shutdown_net(serv, net); | ||
556 | |||
532 | /* | 557 | /* |
533 | * The set of xprts (contained in the sv_tempsocks and | 558 | * The last user is gone and thus all sockets have to be destroyed to |
534 | * sv_permsocks lists) is now constant, since it is modified | 559 | * the point. Check this. |
535 | * only by accepting new sockets (done by service threads in | ||
536 | * svc_recv) or aging old ones (done by sv_temptimer), or | ||
537 | * configuration changes (excluded by whatever locking the | ||
538 | * caller is using--nfsd_mutex in the case of nfsd). So it's | ||
539 | * safe to traverse those lists and shut everything down: | ||
540 | */ | 560 | */ |
541 | svc_close_all(serv); | 561 | BUG_ON(!list_empty(&serv->sv_permsocks)); |
542 | 562 | BUG_ON(!list_empty(&serv->sv_tempsocks)); | |
543 | if (serv->sv_shutdown) | ||
544 | serv->sv_shutdown(serv); | ||
545 | 563 | ||
546 | cache_clean_deferred(serv); | 564 | cache_clean_deferred(serv); |
547 | 565 | ||
@@ -795,7 +813,8 @@ EXPORT_SYMBOL_GPL(svc_exit_thread); | |||
795 | * Returns zero on success; a negative errno value is returned | 813 | * Returns zero on success; a negative errno value is returned |
796 | * if any error occurs. | 814 | * if any error occurs. |
797 | */ | 815 | */ |
798 | static int __svc_rpcb_register4(const u32 program, const u32 version, | 816 | static int __svc_rpcb_register4(struct net *net, const u32 program, |
817 | const u32 version, | ||
799 | const unsigned short protocol, | 818 | const unsigned short protocol, |
800 | const unsigned short port) | 819 | const unsigned short port) |
801 | { | 820 | { |
@@ -818,7 +837,7 @@ static int __svc_rpcb_register4(const u32 program, const u32 version, | |||
818 | return -ENOPROTOOPT; | 837 | return -ENOPROTOOPT; |
819 | } | 838 | } |
820 | 839 | ||
821 | error = rpcb_v4_register(program, version, | 840 | error = rpcb_v4_register(net, program, version, |
822 | (const struct sockaddr *)&sin, netid); | 841 | (const struct sockaddr *)&sin, netid); |
823 | 842 | ||
824 | /* | 843 | /* |
@@ -826,7 +845,7 @@ static int __svc_rpcb_register4(const u32 program, const u32 version, | |||
826 | * registration request with the legacy rpcbind v2 protocol. | 845 | * registration request with the legacy rpcbind v2 protocol. |
827 | */ | 846 | */ |
828 | if (error == -EPROTONOSUPPORT) | 847 | if (error == -EPROTONOSUPPORT) |
829 | error = rpcb_register(program, version, protocol, port); | 848 | error = rpcb_register(net, program, version, protocol, port); |
830 | 849 | ||
831 | return error; | 850 | return error; |
832 | } | 851 | } |
@@ -842,7 +861,8 @@ static int __svc_rpcb_register4(const u32 program, const u32 version, | |||
842 | * Returns zero on success; a negative errno value is returned | 861 | * Returns zero on success; a negative errno value is returned |
843 | * if any error occurs. | 862 | * if any error occurs. |
844 | */ | 863 | */ |
845 | static int __svc_rpcb_register6(const u32 program, const u32 version, | 864 | static int __svc_rpcb_register6(struct net *net, const u32 program, |
865 | const u32 version, | ||
846 | const unsigned short protocol, | 866 | const unsigned short protocol, |
847 | const unsigned short port) | 867 | const unsigned short port) |
848 | { | 868 | { |
@@ -865,7 +885,7 @@ static int __svc_rpcb_register6(const u32 program, const u32 version, | |||
865 | return -ENOPROTOOPT; | 885 | return -ENOPROTOOPT; |
866 | } | 886 | } |
867 | 887 | ||
868 | error = rpcb_v4_register(program, version, | 888 | error = rpcb_v4_register(net, program, version, |
869 | (const struct sockaddr *)&sin6, netid); | 889 | (const struct sockaddr *)&sin6, netid); |
870 | 890 | ||
871 | /* | 891 | /* |
@@ -885,7 +905,7 @@ static int __svc_rpcb_register6(const u32 program, const u32 version, | |||
885 | * Returns zero on success; a negative errno value is returned | 905 | * Returns zero on success; a negative errno value is returned |
886 | * if any error occurs. | 906 | * if any error occurs. |
887 | */ | 907 | */ |
888 | static int __svc_register(const char *progname, | 908 | static int __svc_register(struct net *net, const char *progname, |
889 | const u32 program, const u32 version, | 909 | const u32 program, const u32 version, |
890 | const int family, | 910 | const int family, |
891 | const unsigned short protocol, | 911 | const unsigned short protocol, |
@@ -895,12 +915,12 @@ static int __svc_register(const char *progname, | |||
895 | 915 | ||
896 | switch (family) { | 916 | switch (family) { |
897 | case PF_INET: | 917 | case PF_INET: |
898 | error = __svc_rpcb_register4(program, version, | 918 | error = __svc_rpcb_register4(net, program, version, |
899 | protocol, port); | 919 | protocol, port); |
900 | break; | 920 | break; |
901 | #if IS_ENABLED(CONFIG_IPV6) | 921 | #if IS_ENABLED(CONFIG_IPV6) |
902 | case PF_INET6: | 922 | case PF_INET6: |
903 | error = __svc_rpcb_register6(program, version, | 923 | error = __svc_rpcb_register6(net, program, version, |
904 | protocol, port); | 924 | protocol, port); |
905 | #endif | 925 | #endif |
906 | } | 926 | } |
@@ -914,14 +934,16 @@ static int __svc_register(const char *progname, | |||
914 | /** | 934 | /** |
915 | * svc_register - register an RPC service with the local portmapper | 935 | * svc_register - register an RPC service with the local portmapper |
916 | * @serv: svc_serv struct for the service to register | 936 | * @serv: svc_serv struct for the service to register |
937 | * @net: net namespace for the service to register | ||
917 | * @family: protocol family of service's listener socket | 938 | * @family: protocol family of service's listener socket |
918 | * @proto: transport protocol number to advertise | 939 | * @proto: transport protocol number to advertise |
919 | * @port: port to advertise | 940 | * @port: port to advertise |
920 | * | 941 | * |
921 | * Service is registered for any address in the passed-in protocol family | 942 | * Service is registered for any address in the passed-in protocol family |
922 | */ | 943 | */ |
923 | int svc_register(const struct svc_serv *serv, const int family, | 944 | int svc_register(const struct svc_serv *serv, struct net *net, |
924 | const unsigned short proto, const unsigned short port) | 945 | const int family, const unsigned short proto, |
946 | const unsigned short port) | ||
925 | { | 947 | { |
926 | struct svc_program *progp; | 948 | struct svc_program *progp; |
927 | unsigned int i; | 949 | unsigned int i; |
@@ -946,7 +968,7 @@ int svc_register(const struct svc_serv *serv, const int family, | |||
946 | if (progp->pg_vers[i]->vs_hidden) | 968 | if (progp->pg_vers[i]->vs_hidden) |
947 | continue; | 969 | continue; |
948 | 970 | ||
949 | error = __svc_register(progp->pg_name, progp->pg_prog, | 971 | error = __svc_register(net, progp->pg_name, progp->pg_prog, |
950 | i, family, proto, port); | 972 | i, family, proto, port); |
951 | if (error < 0) | 973 | if (error < 0) |
952 | break; | 974 | break; |
@@ -963,19 +985,19 @@ int svc_register(const struct svc_serv *serv, const int family, | |||
963 | * any "inet6" entries anyway. So a PMAP_UNSET should be sufficient | 985 | * any "inet6" entries anyway. So a PMAP_UNSET should be sufficient |
964 | * in this case to clear all existing entries for [program, version]. | 986 | * in this case to clear all existing entries for [program, version]. |
965 | */ | 987 | */ |
966 | static void __svc_unregister(const u32 program, const u32 version, | 988 | static void __svc_unregister(struct net *net, const u32 program, const u32 version, |
967 | const char *progname) | 989 | const char *progname) |
968 | { | 990 | { |
969 | int error; | 991 | int error; |
970 | 992 | ||
971 | error = rpcb_v4_register(program, version, NULL, ""); | 993 | error = rpcb_v4_register(net, program, version, NULL, ""); |
972 | 994 | ||
973 | /* | 995 | /* |
974 | * User space didn't support rpcbind v4, so retry this | 996 | * User space didn't support rpcbind v4, so retry this |
975 | * request with the legacy rpcbind v2 protocol. | 997 | * request with the legacy rpcbind v2 protocol. |
976 | */ | 998 | */ |
977 | if (error == -EPROTONOSUPPORT) | 999 | if (error == -EPROTONOSUPPORT) |
978 | error = rpcb_register(program, version, 0, 0); | 1000 | error = rpcb_register(net, program, version, 0, 0); |
979 | 1001 | ||
980 | dprintk("svc: %s(%sv%u), error %d\n", | 1002 | dprintk("svc: %s(%sv%u), error %d\n", |
981 | __func__, progname, version, error); | 1003 | __func__, progname, version, error); |
@@ -989,7 +1011,7 @@ static void __svc_unregister(const u32 program, const u32 version, | |||
989 | * The result of unregistration is reported via dprintk for those who want | 1011 | * The result of unregistration is reported via dprintk for those who want |
990 | * verification of the result, but is otherwise not important. | 1012 | * verification of the result, but is otherwise not important. |
991 | */ | 1013 | */ |
992 | static void svc_unregister(const struct svc_serv *serv) | 1014 | static void svc_unregister(const struct svc_serv *serv, struct net *net) |
993 | { | 1015 | { |
994 | struct svc_program *progp; | 1016 | struct svc_program *progp; |
995 | unsigned long flags; | 1017 | unsigned long flags; |
@@ -1006,7 +1028,7 @@ static void svc_unregister(const struct svc_serv *serv) | |||
1006 | 1028 | ||
1007 | dprintk("svc: attempting to unregister %sv%u\n", | 1029 | dprintk("svc: attempting to unregister %sv%u\n", |
1008 | progp->pg_name, i); | 1030 | progp->pg_name, i); |
1009 | __svc_unregister(progp->pg_prog, i, progp->pg_name); | 1031 | __svc_unregister(net, progp->pg_prog, i, progp->pg_name); |
1010 | } | 1032 | } |
1011 | } | 1033 | } |
1012 | 1034 | ||
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index 74cb0d8e9ca1..4bda09d7e1a4 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c | |||
@@ -922,48 +922,65 @@ void svc_close_xprt(struct svc_xprt *xprt) | |||
922 | } | 922 | } |
923 | EXPORT_SYMBOL_GPL(svc_close_xprt); | 923 | EXPORT_SYMBOL_GPL(svc_close_xprt); |
924 | 924 | ||
925 | static void svc_close_list(struct list_head *xprt_list) | 925 | static void svc_close_list(struct list_head *xprt_list, struct net *net) |
926 | { | 926 | { |
927 | struct svc_xprt *xprt; | 927 | struct svc_xprt *xprt; |
928 | 928 | ||
929 | list_for_each_entry(xprt, xprt_list, xpt_list) { | 929 | list_for_each_entry(xprt, xprt_list, xpt_list) { |
930 | if (xprt->xpt_net != net) | ||
931 | continue; | ||
930 | set_bit(XPT_CLOSE, &xprt->xpt_flags); | 932 | set_bit(XPT_CLOSE, &xprt->xpt_flags); |
931 | set_bit(XPT_BUSY, &xprt->xpt_flags); | 933 | set_bit(XPT_BUSY, &xprt->xpt_flags); |
932 | } | 934 | } |
933 | } | 935 | } |
934 | 936 | ||
935 | void svc_close_all(struct svc_serv *serv) | 937 | static void svc_clear_pools(struct svc_serv *serv, struct net *net) |
936 | { | 938 | { |
937 | struct svc_pool *pool; | 939 | struct svc_pool *pool; |
938 | struct svc_xprt *xprt; | 940 | struct svc_xprt *xprt; |
939 | struct svc_xprt *tmp; | 941 | struct svc_xprt *tmp; |
940 | int i; | 942 | int i; |
941 | 943 | ||
942 | svc_close_list(&serv->sv_tempsocks); | ||
943 | svc_close_list(&serv->sv_permsocks); | ||
944 | |||
945 | for (i = 0; i < serv->sv_nrpools; i++) { | 944 | for (i = 0; i < serv->sv_nrpools; i++) { |
946 | pool = &serv->sv_pools[i]; | 945 | pool = &serv->sv_pools[i]; |
947 | 946 | ||
948 | spin_lock_bh(&pool->sp_lock); | 947 | spin_lock_bh(&pool->sp_lock); |
949 | while (!list_empty(&pool->sp_sockets)) { | 948 | list_for_each_entry_safe(xprt, tmp, &pool->sp_sockets, xpt_ready) { |
950 | xprt = list_first_entry(&pool->sp_sockets, struct svc_xprt, xpt_ready); | 949 | if (xprt->xpt_net != net) |
950 | continue; | ||
951 | list_del_init(&xprt->xpt_ready); | 951 | list_del_init(&xprt->xpt_ready); |
952 | } | 952 | } |
953 | spin_unlock_bh(&pool->sp_lock); | 953 | spin_unlock_bh(&pool->sp_lock); |
954 | } | 954 | } |
955 | } | ||
956 | |||
957 | static void svc_clear_list(struct list_head *xprt_list, struct net *net) | ||
958 | { | ||
959 | struct svc_xprt *xprt; | ||
960 | struct svc_xprt *tmp; | ||
961 | |||
962 | list_for_each_entry_safe(xprt, tmp, xprt_list, xpt_list) { | ||
963 | if (xprt->xpt_net != net) | ||
964 | continue; | ||
965 | svc_delete_xprt(xprt); | ||
966 | } | ||
967 | list_for_each_entry(xprt, xprt_list, xpt_list) | ||
968 | BUG_ON(xprt->xpt_net == net); | ||
969 | } | ||
970 | |||
971 | void svc_close_net(struct svc_serv *serv, struct net *net) | ||
972 | { | ||
973 | svc_close_list(&serv->sv_tempsocks, net); | ||
974 | svc_close_list(&serv->sv_permsocks, net); | ||
975 | |||
976 | svc_clear_pools(serv, net); | ||
955 | /* | 977 | /* |
956 | * At this point the sp_sockets lists will stay empty, since | 978 | * At this point the sp_sockets lists will stay empty, since |
957 | * svc_enqueue will not add new entries without taking the | 979 | * svc_enqueue will not add new entries without taking the |
958 | * sp_lock and checking XPT_BUSY. | 980 | * sp_lock and checking XPT_BUSY. |
959 | */ | 981 | */ |
960 | list_for_each_entry_safe(xprt, tmp, &serv->sv_tempsocks, xpt_list) | 982 | svc_clear_list(&serv->sv_tempsocks, net); |
961 | svc_delete_xprt(xprt); | 983 | svc_clear_list(&serv->sv_permsocks, net); |
962 | list_for_each_entry_safe(xprt, tmp, &serv->sv_permsocks, xpt_list) | ||
963 | svc_delete_xprt(xprt); | ||
964 | |||
965 | BUG_ON(!list_empty(&serv->sv_permsocks)); | ||
966 | BUG_ON(!list_empty(&serv->sv_tempsocks)); | ||
967 | } | 984 | } |
968 | 985 | ||
969 | /* | 986 | /* |
@@ -1089,6 +1106,7 @@ static struct svc_deferred_req *svc_deferred_dequeue(struct svc_xprt *xprt) | |||
1089 | * svc_find_xprt - find an RPC transport instance | 1106 | * svc_find_xprt - find an RPC transport instance |
1090 | * @serv: pointer to svc_serv to search | 1107 | * @serv: pointer to svc_serv to search |
1091 | * @xcl_name: C string containing transport's class name | 1108 | * @xcl_name: C string containing transport's class name |
1109 | * @net: owner net pointer | ||
1092 | * @af: Address family of transport's local address | 1110 | * @af: Address family of transport's local address |
1093 | * @port: transport's IP port number | 1111 | * @port: transport's IP port number |
1094 | * | 1112 | * |
@@ -1101,7 +1119,8 @@ static struct svc_deferred_req *svc_deferred_dequeue(struct svc_xprt *xprt) | |||
1101 | * service's list that has a matching class name. | 1119 | * service's list that has a matching class name. |
1102 | */ | 1120 | */ |
1103 | struct svc_xprt *svc_find_xprt(struct svc_serv *serv, const char *xcl_name, | 1121 | struct svc_xprt *svc_find_xprt(struct svc_serv *serv, const char *xcl_name, |
1104 | const sa_family_t af, const unsigned short port) | 1122 | struct net *net, const sa_family_t af, |
1123 | const unsigned short port) | ||
1105 | { | 1124 | { |
1106 | struct svc_xprt *xprt; | 1125 | struct svc_xprt *xprt; |
1107 | struct svc_xprt *found = NULL; | 1126 | struct svc_xprt *found = NULL; |
@@ -1112,6 +1131,8 @@ struct svc_xprt *svc_find_xprt(struct svc_serv *serv, const char *xcl_name, | |||
1112 | 1131 | ||
1113 | spin_lock_bh(&serv->sv_lock); | 1132 | spin_lock_bh(&serv->sv_lock); |
1114 | list_for_each_entry(xprt, &serv->sv_permsocks, xpt_list) { | 1133 | list_for_each_entry(xprt, &serv->sv_permsocks, xpt_list) { |
1134 | if (xprt->xpt_net != net) | ||
1135 | continue; | ||
1115 | if (strcmp(xprt->xpt_class->xcl_name, xcl_name)) | 1136 | if (strcmp(xprt->xpt_class->xcl_name, xcl_name)) |
1116 | continue; | 1137 | continue; |
1117 | if (af != AF_UNSPEC && af != xprt->xpt_local.ss_family) | 1138 | 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 6ab35736d88f..521d8f7dc833 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c | |||
@@ -211,7 +211,7 @@ static int ip_map_parse(struct cache_detail *cd, | |||
211 | len = qword_get(&mesg, buf, mlen); | 211 | len = qword_get(&mesg, buf, mlen); |
212 | if (len <= 0) return -EINVAL; | 212 | if (len <= 0) return -EINVAL; |
213 | 213 | ||
214 | if (rpc_pton(buf, len, &address.sa, sizeof(address)) == 0) | 214 | if (rpc_pton(cd->net, buf, len, &address.sa, sizeof(address)) == 0) |
215 | return -EINVAL; | 215 | return -EINVAL; |
216 | switch (address.sa.sa_family) { | 216 | switch (address.sa.sa_family) { |
217 | case AF_INET: | 217 | case AF_INET: |
@@ -436,7 +436,6 @@ struct unix_gid { | |||
436 | uid_t uid; | 436 | uid_t uid; |
437 | struct group_info *gi; | 437 | struct group_info *gi; |
438 | }; | 438 | }; |
439 | static struct cache_head *gid_table[GID_HASHMAX]; | ||
440 | 439 | ||
441 | static void unix_gid_put(struct kref *kref) | 440 | static void unix_gid_put(struct kref *kref) |
442 | { | 441 | { |
@@ -494,8 +493,7 @@ static int unix_gid_upcall(struct cache_detail *cd, struct cache_head *h) | |||
494 | return sunrpc_cache_pipe_upcall(cd, h, unix_gid_request); | 493 | return sunrpc_cache_pipe_upcall(cd, h, unix_gid_request); |
495 | } | 494 | } |
496 | 495 | ||
497 | static struct unix_gid *unix_gid_lookup(uid_t uid); | 496 | static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, uid_t uid); |
498 | extern struct cache_detail unix_gid_cache; | ||
499 | 497 | ||
500 | static int unix_gid_parse(struct cache_detail *cd, | 498 | static int unix_gid_parse(struct cache_detail *cd, |
501 | char *mesg, int mlen) | 499 | char *mesg, int mlen) |
@@ -539,19 +537,19 @@ static int unix_gid_parse(struct cache_detail *cd, | |||
539 | GROUP_AT(ug.gi, i) = gid; | 537 | GROUP_AT(ug.gi, i) = gid; |
540 | } | 538 | } |
541 | 539 | ||
542 | ugp = unix_gid_lookup(uid); | 540 | ugp = unix_gid_lookup(cd, uid); |
543 | if (ugp) { | 541 | if (ugp) { |
544 | struct cache_head *ch; | 542 | struct cache_head *ch; |
545 | ug.h.flags = 0; | 543 | ug.h.flags = 0; |
546 | ug.h.expiry_time = expiry; | 544 | ug.h.expiry_time = expiry; |
547 | ch = sunrpc_cache_update(&unix_gid_cache, | 545 | ch = sunrpc_cache_update(cd, |
548 | &ug.h, &ugp->h, | 546 | &ug.h, &ugp->h, |
549 | hash_long(uid, GID_HASHBITS)); | 547 | hash_long(uid, GID_HASHBITS)); |
550 | if (!ch) | 548 | if (!ch) |
551 | err = -ENOMEM; | 549 | err = -ENOMEM; |
552 | else { | 550 | else { |
553 | err = 0; | 551 | err = 0; |
554 | cache_put(ch, &unix_gid_cache); | 552 | cache_put(ch, cd); |
555 | } | 553 | } |
556 | } else | 554 | } else |
557 | err = -ENOMEM; | 555 | err = -ENOMEM; |
@@ -587,10 +585,9 @@ static int unix_gid_show(struct seq_file *m, | |||
587 | return 0; | 585 | return 0; |
588 | } | 586 | } |
589 | 587 | ||
590 | struct cache_detail unix_gid_cache = { | 588 | static struct cache_detail unix_gid_cache_template = { |
591 | .owner = THIS_MODULE, | 589 | .owner = THIS_MODULE, |
592 | .hash_size = GID_HASHMAX, | 590 | .hash_size = GID_HASHMAX, |
593 | .hash_table = gid_table, | ||
594 | .name = "auth.unix.gid", | 591 | .name = "auth.unix.gid", |
595 | .cache_put = unix_gid_put, | 592 | .cache_put = unix_gid_put, |
596 | .cache_upcall = unix_gid_upcall, | 593 | .cache_upcall = unix_gid_upcall, |
@@ -602,14 +599,42 @@ struct cache_detail unix_gid_cache = { | |||
602 | .alloc = unix_gid_alloc, | 599 | .alloc = unix_gid_alloc, |
603 | }; | 600 | }; |
604 | 601 | ||
605 | static struct unix_gid *unix_gid_lookup(uid_t uid) | 602 | int unix_gid_cache_create(struct net *net) |
603 | { | ||
604 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
605 | struct cache_detail *cd; | ||
606 | int err; | ||
607 | |||
608 | cd = cache_create_net(&unix_gid_cache_template, net); | ||
609 | if (IS_ERR(cd)) | ||
610 | return PTR_ERR(cd); | ||
611 | err = cache_register_net(cd, net); | ||
612 | if (err) { | ||
613 | cache_destroy_net(cd, net); | ||
614 | return err; | ||
615 | } | ||
616 | sn->unix_gid_cache = cd; | ||
617 | return 0; | ||
618 | } | ||
619 | |||
620 | void unix_gid_cache_destroy(struct net *net) | ||
621 | { | ||
622 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | ||
623 | struct cache_detail *cd = sn->unix_gid_cache; | ||
624 | |||
625 | sn->unix_gid_cache = NULL; | ||
626 | cache_purge(cd); | ||
627 | cache_unregister_net(cd, net); | ||
628 | cache_destroy_net(cd, net); | ||
629 | } | ||
630 | |||
631 | static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, uid_t uid) | ||
606 | { | 632 | { |
607 | struct unix_gid ug; | 633 | struct unix_gid ug; |
608 | struct cache_head *ch; | 634 | struct cache_head *ch; |
609 | 635 | ||
610 | ug.uid = uid; | 636 | ug.uid = uid; |
611 | ch = sunrpc_cache_lookup(&unix_gid_cache, &ug.h, | 637 | ch = sunrpc_cache_lookup(cd, &ug.h, hash_long(uid, GID_HASHBITS)); |
612 | hash_long(uid, GID_HASHBITS)); | ||
613 | if (ch) | 638 | if (ch) |
614 | return container_of(ch, struct unix_gid, h); | 639 | return container_of(ch, struct unix_gid, h); |
615 | else | 640 | else |
@@ -621,11 +646,13 @@ static struct group_info *unix_gid_find(uid_t uid, struct svc_rqst *rqstp) | |||
621 | struct unix_gid *ug; | 646 | struct unix_gid *ug; |
622 | struct group_info *gi; | 647 | struct group_info *gi; |
623 | int ret; | 648 | int ret; |
649 | struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, | ||
650 | sunrpc_net_id); | ||
624 | 651 | ||
625 | ug = unix_gid_lookup(uid); | 652 | ug = unix_gid_lookup(sn->unix_gid_cache, uid); |
626 | if (!ug) | 653 | if (!ug) |
627 | return ERR_PTR(-EAGAIN); | 654 | return ERR_PTR(-EAGAIN); |
628 | ret = cache_check(&unix_gid_cache, &ug->h, &rqstp->rq_chandle); | 655 | ret = cache_check(sn->unix_gid_cache, &ug->h, &rqstp->rq_chandle); |
629 | switch (ret) { | 656 | switch (ret) { |
630 | case -ENOENT: | 657 | case -ENOENT: |
631 | return ERR_PTR(-ENOENT); | 658 | return ERR_PTR(-ENOENT); |
@@ -633,7 +660,7 @@ static struct group_info *unix_gid_find(uid_t uid, struct svc_rqst *rqstp) | |||
633 | return ERR_PTR(-ESHUTDOWN); | 660 | return ERR_PTR(-ESHUTDOWN); |
634 | case 0: | 661 | case 0: |
635 | gi = get_group_info(ug->gi); | 662 | gi = get_group_info(ug->gi); |
636 | cache_put(&ug->h, &unix_gid_cache); | 663 | cache_put(&ug->h, sn->unix_gid_cache); |
637 | return gi; | 664 | return gi; |
638 | default: | 665 | default: |
639 | return ERR_PTR(-EAGAIN); | 666 | return ERR_PTR(-EAGAIN); |
@@ -849,56 +876,45 @@ struct auth_ops svcauth_unix = { | |||
849 | .set_client = svcauth_unix_set_client, | 876 | .set_client = svcauth_unix_set_client, |
850 | }; | 877 | }; |
851 | 878 | ||
879 | static struct cache_detail ip_map_cache_template = { | ||
880 | .owner = THIS_MODULE, | ||
881 | .hash_size = IP_HASHMAX, | ||
882 | .name = "auth.unix.ip", | ||
883 | .cache_put = ip_map_put, | ||
884 | .cache_upcall = ip_map_upcall, | ||
885 | .cache_parse = ip_map_parse, | ||
886 | .cache_show = ip_map_show, | ||
887 | .match = ip_map_match, | ||
888 | .init = ip_map_init, | ||
889 | .update = update, | ||
890 | .alloc = ip_map_alloc, | ||
891 | }; | ||
892 | |||
852 | int ip_map_cache_create(struct net *net) | 893 | int ip_map_cache_create(struct net *net) |
853 | { | 894 | { |
854 | int err = -ENOMEM; | ||
855 | struct cache_detail *cd; | ||
856 | struct cache_head **tbl; | ||
857 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); | 895 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
896 | struct cache_detail *cd; | ||
897 | int err; | ||
858 | 898 | ||
859 | cd = kzalloc(sizeof(struct cache_detail), GFP_KERNEL); | 899 | cd = cache_create_net(&ip_map_cache_template, net); |
860 | if (cd == NULL) | 900 | if (IS_ERR(cd)) |
861 | goto err_cd; | 901 | return PTR_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, | ||
879 | |||
880 | err = cache_register_net(cd, net); | 902 | err = cache_register_net(cd, net); |
881 | if (err) | 903 | if (err) { |
882 | goto err_reg; | 904 | cache_destroy_net(cd, net); |
883 | 905 | return err; | |
906 | } | ||
884 | sn->ip_map_cache = cd; | 907 | sn->ip_map_cache = cd; |
885 | return 0; | 908 | return 0; |
886 | |||
887 | err_reg: | ||
888 | kfree(tbl); | ||
889 | err_tbl: | ||
890 | kfree(cd); | ||
891 | err_cd: | ||
892 | return err; | ||
893 | } | 909 | } |
894 | 910 | ||
895 | void ip_map_cache_destroy(struct net *net) | 911 | void ip_map_cache_destroy(struct net *net) |
896 | { | 912 | { |
897 | struct sunrpc_net *sn; | 913 | struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); |
914 | struct cache_detail *cd = sn->ip_map_cache; | ||
898 | 915 | ||
899 | sn = net_generic(net, sunrpc_net_id); | 916 | sn->ip_map_cache = NULL; |
900 | cache_purge(sn->ip_map_cache); | 917 | cache_purge(cd); |
901 | cache_unregister_net(sn->ip_map_cache, net); | 918 | cache_unregister_net(cd, net); |
902 | kfree(sn->ip_map_cache->hash_table); | 919 | cache_destroy_net(cd, net); |
903 | kfree(sn->ip_map_cache); | ||
904 | } | 920 | } |
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index b3bb18ba350a..824d32fb3121 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
@@ -396,7 +396,7 @@ static int svc_partial_recvfrom(struct svc_rqst *rqstp, | |||
396 | int buflen, unsigned int base) | 396 | int buflen, unsigned int base) |
397 | { | 397 | { |
398 | size_t save_iovlen; | 398 | size_t save_iovlen; |
399 | void __user *save_iovbase; | 399 | void *save_iovbase; |
400 | unsigned int i; | 400 | unsigned int i; |
401 | int ret; | 401 | int ret; |
402 | 402 | ||
@@ -1407,7 +1407,8 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv, | |||
1407 | 1407 | ||
1408 | /* Register socket with portmapper */ | 1408 | /* Register socket with portmapper */ |
1409 | if (*errp >= 0 && pmap_register) | 1409 | if (*errp >= 0 && pmap_register) |
1410 | *errp = svc_register(serv, inet->sk_family, inet->sk_protocol, | 1410 | *errp = svc_register(serv, sock_net(sock->sk), inet->sk_family, |
1411 | inet->sk_protocol, | ||
1411 | ntohs(inet_sk(inet)->inet_sport)); | 1412 | ntohs(inet_sk(inet)->inet_sport)); |
1412 | 1413 | ||
1413 | if (*errp < 0) { | 1414 | if (*errp < 0) { |
diff --git a/net/sunrpc/sysctl.c b/net/sunrpc/sysctl.c index e65dcc613339..af7d339add9d 100644 --- a/net/sunrpc/sysctl.c +++ b/net/sunrpc/sysctl.c | |||
@@ -20,6 +20,8 @@ | |||
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 | |||
23 | /* | 25 | /* |
24 | * Declare the debug flags here | 26 | * Declare the debug flags here |
25 | */ | 27 | */ |
@@ -110,7 +112,7 @@ proc_dodebug(ctl_table *table, int write, | |||
110 | *(unsigned int *) table->data = value; | 112 | *(unsigned int *) table->data = value; |
111 | /* Display the RPC tasks on writing to rpc_debug */ | 113 | /* Display the RPC tasks on writing to rpc_debug */ |
112 | if (strcmp(table->procname, "rpc_debug") == 0) | 114 | if (strcmp(table->procname, "rpc_debug") == 0) |
113 | rpc_show_tasks(); | 115 | rpc_show_tasks(&init_net); |
114 | } else { | 116 | } else { |
115 | if (!access_ok(VERIFY_WRITE, buffer, left)) | 117 | if (!access_ok(VERIFY_WRITE, buffer, left)) |
116 | return -EFAULT; | 118 | return -EFAULT; |
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index c64c0ef519b5..0cbcd1ab49ab 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
@@ -66,6 +66,7 @@ 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); | ||
69 | 70 | ||
70 | static DEFINE_SPINLOCK(xprt_list_lock); | 71 | static DEFINE_SPINLOCK(xprt_list_lock); |
71 | static LIST_HEAD(xprt_list); | 72 | static LIST_HEAD(xprt_list); |
@@ -292,54 +293,57 @@ static inline int xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task) | |||
292 | return retval; | 293 | return retval; |
293 | } | 294 | } |
294 | 295 | ||
295 | static void __xprt_lock_write_next(struct rpc_xprt *xprt) | 296 | static bool __xprt_lock_write_func(struct rpc_task *task, void *data) |
296 | { | 297 | { |
297 | struct rpc_task *task; | 298 | struct rpc_xprt *xprt = data; |
298 | struct rpc_rqst *req; | 299 | struct rpc_rqst *req; |
299 | 300 | ||
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 | |||
307 | req = task->tk_rqstp; | 301 | req = task->tk_rqstp; |
308 | xprt->snd_task = task; | 302 | xprt->snd_task = task; |
309 | if (req) { | 303 | if (req) { |
310 | req->rq_bytes_sent = 0; | 304 | req->rq_bytes_sent = 0; |
311 | req->rq_ntrans++; | 305 | req->rq_ntrans++; |
312 | } | 306 | } |
313 | return; | 307 | return true; |
308 | } | ||
314 | 309 | ||
315 | out_unlock: | 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 | |||
315 | if (rpc_wake_up_first(&xprt->sending, __xprt_lock_write_func, xprt)) | ||
316 | return; | ||
316 | xprt_clear_locked(xprt); | 317 | xprt_clear_locked(xprt); |
317 | } | 318 | } |
318 | 319 | ||
319 | static void __xprt_lock_write_next_cong(struct rpc_xprt *xprt) | 320 | static bool __xprt_lock_write_cong_func(struct rpc_task *task, void *data) |
320 | { | 321 | { |
321 | struct rpc_task *task; | 322 | struct rpc_xprt *xprt = data; |
322 | struct rpc_rqst *req; | 323 | struct rpc_rqst *req; |
323 | 324 | ||
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 | |||
332 | req = task->tk_rqstp; | 325 | req = task->tk_rqstp; |
333 | if (req == NULL) { | 326 | if (req == NULL) { |
334 | xprt->snd_task = task; | 327 | xprt->snd_task = task; |
335 | return; | 328 | return true; |
336 | } | 329 | } |
337 | if (__xprt_get_cong(xprt, task)) { | 330 | if (__xprt_get_cong(xprt, task)) { |
338 | xprt->snd_task = task; | 331 | xprt->snd_task = task; |
339 | req->rq_bytes_sent = 0; | 332 | req->rq_bytes_sent = 0; |
340 | req->rq_ntrans++; | 333 | req->rq_ntrans++; |
341 | return; | 334 | return true; |
342 | } | 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; | ||
343 | out_unlock: | 347 | out_unlock: |
344 | xprt_clear_locked(xprt); | 348 | xprt_clear_locked(xprt); |
345 | } | 349 | } |
@@ -712,9 +716,7 @@ void xprt_connect(struct rpc_task *task) | |||
712 | if (xprt_connected(xprt)) | 716 | if (xprt_connected(xprt)) |
713 | xprt_release_write(xprt, task); | 717 | xprt_release_write(xprt, task); |
714 | else { | 718 | else { |
715 | if (task->tk_rqstp) | 719 | task->tk_rqstp->rq_bytes_sent = 0; |
716 | task->tk_rqstp->rq_bytes_sent = 0; | ||
717 | |||
718 | task->tk_timeout = task->tk_rqstp->rq_timeout; | 720 | task->tk_timeout = task->tk_rqstp->rq_timeout; |
719 | rpc_sleep_on(&xprt->pending, task, xprt_connect_status); | 721 | rpc_sleep_on(&xprt->pending, task, xprt_connect_status); |
720 | 722 | ||
@@ -750,7 +752,7 @@ static void xprt_connect_status(struct rpc_task *task) | |||
750 | default: | 752 | default: |
751 | dprintk("RPC: %5u xprt_connect_status: error %d connecting to " | 753 | dprintk("RPC: %5u xprt_connect_status: error %d connecting to " |
752 | "server %s\n", task->tk_pid, -task->tk_status, | 754 | "server %s\n", task->tk_pid, -task->tk_status, |
753 | task->tk_client->cl_server); | 755 | xprt->servername); |
754 | xprt_release_write(xprt, task); | 756 | xprt_release_write(xprt, task); |
755 | task->tk_status = -EIO; | 757 | task->tk_status = -EIO; |
756 | } | 758 | } |
@@ -884,7 +886,7 @@ void xprt_transmit(struct rpc_task *task) | |||
884 | { | 886 | { |
885 | struct rpc_rqst *req = task->tk_rqstp; | 887 | struct rpc_rqst *req = task->tk_rqstp; |
886 | struct rpc_xprt *xprt = req->rq_xprt; | 888 | struct rpc_xprt *xprt = req->rq_xprt; |
887 | int status; | 889 | int status, numreqs; |
888 | 890 | ||
889 | dprintk("RPC: %5u xprt_transmit(%u)\n", task->tk_pid, req->rq_slen); | 891 | dprintk("RPC: %5u xprt_transmit(%u)\n", task->tk_pid, req->rq_slen); |
890 | 892 | ||
@@ -921,9 +923,14 @@ void xprt_transmit(struct rpc_task *task) | |||
921 | 923 | ||
922 | xprt->ops->set_retrans_timeout(task); | 924 | xprt->ops->set_retrans_timeout(task); |
923 | 925 | ||
926 | numreqs = atomic_read(&xprt->num_reqs); | ||
927 | if (numreqs > xprt->stat.max_slots) | ||
928 | xprt->stat.max_slots = numreqs; | ||
924 | xprt->stat.sends++; | 929 | xprt->stat.sends++; |
925 | xprt->stat.req_u += xprt->stat.sends - xprt->stat.recvs; | 930 | xprt->stat.req_u += xprt->stat.sends - xprt->stat.recvs; |
926 | xprt->stat.bklog_u += xprt->backlog.qlen; | 931 | xprt->stat.bklog_u += xprt->backlog.qlen; |
932 | xprt->stat.sending_u += xprt->sending.qlen; | ||
933 | xprt->stat.pending_u += xprt->pending.qlen; | ||
927 | 934 | ||
928 | /* Don't race with disconnect */ | 935 | /* Don't race with disconnect */ |
929 | if (!xprt_connected(xprt)) | 936 | if (!xprt_connected(xprt)) |
@@ -1131,7 +1138,10 @@ void xprt_release(struct rpc_task *task) | |||
1131 | return; | 1138 | return; |
1132 | 1139 | ||
1133 | xprt = req->rq_xprt; | 1140 | xprt = req->rq_xprt; |
1134 | rpc_count_iostats(task); | 1141 | if (task->tk_ops->rpc_count_stats != NULL) |
1142 | task->tk_ops->rpc_count_stats(task, task->tk_calldata); | ||
1143 | else if (task->tk_client) | ||
1144 | rpc_count_iostats(task, task->tk_client->cl_metrics); | ||
1135 | spin_lock_bh(&xprt->transport_lock); | 1145 | spin_lock_bh(&xprt->transport_lock); |
1136 | xprt->ops->release_xprt(xprt, task); | 1146 | xprt->ops->release_xprt(xprt, task); |
1137 | if (xprt->ops->release_request) | 1147 | if (xprt->ops->release_request) |
@@ -1220,6 +1230,17 @@ found: | |||
1220 | (unsigned long)xprt); | 1230 | (unsigned long)xprt); |
1221 | else | 1231 | else |
1222 | init_timer(&xprt->timer); | 1232 | init_timer(&xprt->timer); |
1233 | |||
1234 | if (strlen(args->servername) > RPC_MAXNETNAMELEN) { | ||
1235 | xprt_destroy(xprt); | ||
1236 | return ERR_PTR(-EINVAL); | ||
1237 | } | ||
1238 | xprt->servername = kstrdup(args->servername, GFP_KERNEL); | ||
1239 | if (xprt->servername == NULL) { | ||
1240 | xprt_destroy(xprt); | ||
1241 | return ERR_PTR(-ENOMEM); | ||
1242 | } | ||
1243 | |||
1223 | dprintk("RPC: created transport %p with %u slots\n", xprt, | 1244 | dprintk("RPC: created transport %p with %u slots\n", xprt, |
1224 | xprt->max_reqs); | 1245 | xprt->max_reqs); |
1225 | out: | 1246 | out: |
@@ -1242,6 +1263,7 @@ static void xprt_destroy(struct rpc_xprt *xprt) | |||
1242 | rpc_destroy_wait_queue(&xprt->sending); | 1263 | rpc_destroy_wait_queue(&xprt->sending); |
1243 | rpc_destroy_wait_queue(&xprt->backlog); | 1264 | rpc_destroy_wait_queue(&xprt->backlog); |
1244 | cancel_work_sync(&xprt->task_cleanup); | 1265 | cancel_work_sync(&xprt->task_cleanup); |
1266 | kfree(xprt->servername); | ||
1245 | /* | 1267 | /* |
1246 | * Tear down transport state and free the rpc_xprt | 1268 | * Tear down transport state and free the rpc_xprt |
1247 | */ | 1269 | */ |
diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c index 554d0814c875..12de982b7a50 100644 --- a/net/sunrpc/xprtrdma/rpc_rdma.c +++ b/net/sunrpc/xprtrdma/rpc_rdma.c | |||
@@ -771,13 +771,18 @@ 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 | } | ||
774 | 781 | ||
775 | dprintk("RPC: %s: reply 0x%p completes request 0x%p\n" | 782 | dprintk("RPC: %s: reply 0x%p completes request 0x%p\n" |
776 | " RPC request 0x%p xid 0x%08x\n", | 783 | " RPC request 0x%p xid 0x%08x\n", |
777 | __func__, rep, req, rqst, headerp->rm_xid); | 784 | __func__, rep, req, rqst, headerp->rm_xid); |
778 | 785 | ||
779 | BUG_ON(!req || req->rl_reply); | ||
780 | |||
781 | /* from here on, the reply is no longer an orphan */ | 786 | /* from here on, the reply is no longer an orphan */ |
782 | req->rl_reply = rep; | 787 | req->rl_reply = rep; |
783 | 788 | ||
diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c index 28236bab57f9..745973b729af 100644 --- a/net/sunrpc/xprtrdma/verbs.c +++ b/net/sunrpc/xprtrdma/verbs.c | |||
@@ -1490,6 +1490,9 @@ 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; | ||
1493 | 1496 | ||
1494 | pageoff = offset_in_page(seg1->mr_offset); | 1497 | pageoff = offset_in_page(seg1->mr_offset); |
1495 | seg1->mr_offset -= pageoff; /* start of page */ | 1498 | seg1->mr_offset -= pageoff; /* start of page */ |
@@ -1497,11 +1500,15 @@ rpcrdma_register_frmr_external(struct rpcrdma_mr_seg *seg, | |||
1497 | len = -pageoff; | 1500 | len = -pageoff; |
1498 | if (*nsegs > RPCRDMA_MAX_DATA_SEGS) | 1501 | if (*nsegs > RPCRDMA_MAX_DATA_SEGS) |
1499 | *nsegs = RPCRDMA_MAX_DATA_SEGS; | 1502 | *nsegs = RPCRDMA_MAX_DATA_SEGS; |
1500 | for (i = 0; i < *nsegs;) { | 1503 | for (page_no = i = 0; i < *nsegs;) { |
1501 | rpcrdma_map_one(ia, seg, writing); | 1504 | rpcrdma_map_one(ia, seg, writing); |
1502 | seg1->mr_chunk.rl_mw->r.frmr.fr_pgl->page_list[i] = seg->mr_dma; | 1505 | pa = 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 | } | ||
1503 | len += seg->mr_len; | 1511 | len += seg->mr_len; |
1504 | BUG_ON(seg->mr_len > PAGE_SIZE); | ||
1505 | ++seg; | 1512 | ++seg; |
1506 | ++i; | 1513 | ++i; |
1507 | /* Check for holes */ | 1514 | /* Check for holes */ |
@@ -1540,9 +1547,9 @@ rpcrdma_register_frmr_external(struct rpcrdma_mr_seg *seg, | |||
1540 | frmr_wr.send_flags = IB_SEND_SIGNALED; | 1547 | frmr_wr.send_flags = IB_SEND_SIGNALED; |
1541 | frmr_wr.wr.fast_reg.iova_start = seg1->mr_dma; | 1548 | frmr_wr.wr.fast_reg.iova_start = seg1->mr_dma; |
1542 | frmr_wr.wr.fast_reg.page_list = seg1->mr_chunk.rl_mw->r.frmr.fr_pgl; | 1549 | frmr_wr.wr.fast_reg.page_list = seg1->mr_chunk.rl_mw->r.frmr.fr_pgl; |
1543 | frmr_wr.wr.fast_reg.page_list_len = i; | 1550 | frmr_wr.wr.fast_reg.page_list_len = page_no; |
1544 | frmr_wr.wr.fast_reg.page_shift = PAGE_SHIFT; | 1551 | frmr_wr.wr.fast_reg.page_shift = PAGE_SHIFT; |
1545 | frmr_wr.wr.fast_reg.length = i << PAGE_SHIFT; | 1552 | frmr_wr.wr.fast_reg.length = page_no << PAGE_SHIFT; |
1546 | BUG_ON(frmr_wr.wr.fast_reg.length < len); | 1553 | BUG_ON(frmr_wr.wr.fast_reg.length < len); |
1547 | frmr_wr.wr.fast_reg.access_flags = (writing ? | 1554 | frmr_wr.wr.fast_reg.access_flags = (writing ? |
1548 | IB_ACCESS_REMOTE_WRITE | IB_ACCESS_LOCAL_WRITE : | 1555 | IB_ACCESS_REMOTE_WRITE | IB_ACCESS_LOCAL_WRITE : |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 55472c48825e..92bc5181dbeb 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 | unsigned int xprt_udp_slot_table_entries = RPC_DEF_SLOT_TABLE; | 56 | static unsigned int xprt_udp_slot_table_entries = RPC_DEF_SLOT_TABLE; |
57 | unsigned int xprt_tcp_slot_table_entries = RPC_MIN_SLOT_TABLE; | 57 | static unsigned int xprt_tcp_slot_table_entries = RPC_MIN_SLOT_TABLE; |
58 | unsigned int xprt_max_tcp_slot_table_entries = RPC_MAX_SLOT_TABLE; | 58 | static unsigned int xprt_max_tcp_slot_table_entries = RPC_MAX_SLOT_TABLE; |
59 | 59 | ||
60 | unsigned int xprt_min_resvport = RPC_DEF_MIN_RESVPORT; | 60 | static unsigned int xprt_min_resvport = RPC_DEF_MIN_RESVPORT; |
61 | unsigned int xprt_max_resvport = RPC_DEF_MAX_RESVPORT; | 61 | static 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; |
@@ -2227,7 +2227,7 @@ static void xs_local_print_stats(struct rpc_xprt *xprt, struct seq_file *seq) | |||
2227 | idle_time = (long)(jiffies - xprt->last_used) / HZ; | 2227 | idle_time = (long)(jiffies - xprt->last_used) / HZ; |
2228 | 2228 | ||
2229 | 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 " |
2230 | "%llu %llu\n", | 2230 | "%llu %llu %lu %llu %llu\n", |
2231 | xprt->stat.bind_count, | 2231 | xprt->stat.bind_count, |
2232 | xprt->stat.connect_count, | 2232 | xprt->stat.connect_count, |
2233 | xprt->stat.connect_time, | 2233 | xprt->stat.connect_time, |
@@ -2236,7 +2236,10 @@ static void xs_local_print_stats(struct rpc_xprt *xprt, struct seq_file *seq) | |||
2236 | xprt->stat.recvs, | 2236 | xprt->stat.recvs, |
2237 | xprt->stat.bad_xids, | 2237 | xprt->stat.bad_xids, |
2238 | xprt->stat.req_u, | 2238 | xprt->stat.req_u, |
2239 | xprt->stat.bklog_u); | 2239 | xprt->stat.bklog_u, |
2240 | xprt->stat.max_slots, | ||
2241 | xprt->stat.sending_u, | ||
2242 | xprt->stat.pending_u); | ||
2240 | } | 2243 | } |
2241 | 2244 | ||
2242 | /** | 2245 | /** |
@@ -2249,14 +2252,18 @@ static void xs_udp_print_stats(struct rpc_xprt *xprt, struct seq_file *seq) | |||
2249 | { | 2252 | { |
2250 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); | 2253 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); |
2251 | 2254 | ||
2252 | seq_printf(seq, "\txprt:\tudp %u %lu %lu %lu %lu %Lu %Lu\n", | 2255 | seq_printf(seq, "\txprt:\tudp %u %lu %lu %lu %lu %llu %llu " |
2256 | "%lu %llu %llu\n", | ||
2253 | transport->srcport, | 2257 | transport->srcport, |
2254 | xprt->stat.bind_count, | 2258 | xprt->stat.bind_count, |
2255 | xprt->stat.sends, | 2259 | xprt->stat.sends, |
2256 | xprt->stat.recvs, | 2260 | xprt->stat.recvs, |
2257 | xprt->stat.bad_xids, | 2261 | xprt->stat.bad_xids, |
2258 | xprt->stat.req_u, | 2262 | xprt->stat.req_u, |
2259 | xprt->stat.bklog_u); | 2263 | xprt->stat.bklog_u, |
2264 | xprt->stat.max_slots, | ||
2265 | xprt->stat.sending_u, | ||
2266 | xprt->stat.pending_u); | ||
2260 | } | 2267 | } |
2261 | 2268 | ||
2262 | /** | 2269 | /** |
@@ -2273,7 +2280,8 @@ static void xs_tcp_print_stats(struct rpc_xprt *xprt, struct seq_file *seq) | |||
2273 | if (xprt_connected(xprt)) | 2280 | if (xprt_connected(xprt)) |
2274 | idle_time = (long)(jiffies - xprt->last_used) / HZ; | 2281 | idle_time = (long)(jiffies - xprt->last_used) / HZ; |
2275 | 2282 | ||
2276 | seq_printf(seq, "\txprt:\ttcp %u %lu %lu %lu %ld %lu %lu %lu %Lu %Lu\n", | 2283 | seq_printf(seq, "\txprt:\ttcp %u %lu %lu %lu %ld %lu %lu %lu " |
2284 | "%llu %llu %lu %llu %llu\n", | ||
2277 | transport->srcport, | 2285 | transport->srcport, |
2278 | xprt->stat.bind_count, | 2286 | xprt->stat.bind_count, |
2279 | xprt->stat.connect_count, | 2287 | xprt->stat.connect_count, |
@@ -2283,7 +2291,10 @@ static void xs_tcp_print_stats(struct rpc_xprt *xprt, struct seq_file *seq) | |||
2283 | xprt->stat.recvs, | 2291 | xprt->stat.recvs, |
2284 | xprt->stat.bad_xids, | 2292 | xprt->stat.bad_xids, |
2285 | xprt->stat.req_u, | 2293 | xprt->stat.req_u, |
2286 | xprt->stat.bklog_u); | 2294 | xprt->stat.bklog_u, |
2295 | xprt->stat.max_slots, | ||
2296 | xprt->stat.sending_u, | ||
2297 | xprt->stat.pending_u); | ||
2287 | } | 2298 | } |
2288 | 2299 | ||
2289 | /* | 2300 | /* |