diff options
Diffstat (limited to 'net/sunrpc')
-rw-r--r-- | net/sunrpc/addr.c | 6 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/auth_gss.c | 28 | ||||
-rw-r--r-- | net/sunrpc/auth_unix.c | 3 | ||||
-rw-r--r-- | net/sunrpc/clnt.c | 4 | ||||
-rw-r--r-- | net/sunrpc/rpc_pipe.c | 23 | ||||
-rw-r--r-- | net/sunrpc/rpcb_clnt.c | 94 | ||||
-rw-r--r-- | net/sunrpc/sunrpc_syms.c | 3 | ||||
-rw-r--r-- | net/sunrpc/svc.c | 86 | ||||
-rw-r--r-- | net/sunrpc/svc_xprt.c | 13 | ||||
-rw-r--r-- | net/sunrpc/svcsock.c | 23 |
10 files changed, 187 insertions, 96 deletions
diff --git a/net/sunrpc/addr.c b/net/sunrpc/addr.c index 4195233c4914..4548757c9871 100644 --- a/net/sunrpc/addr.c +++ b/net/sunrpc/addr.c | |||
@@ -255,12 +255,13 @@ EXPORT_SYMBOL_GPL(rpc_pton); | |||
255 | /** | 255 | /** |
256 | * rpc_sockaddr2uaddr - Construct a universal address string from @sap. | 256 | * rpc_sockaddr2uaddr - Construct a universal address string from @sap. |
257 | * @sap: socket address | 257 | * @sap: socket address |
258 | * @gfp_flags: allocation mode | ||
258 | * | 259 | * |
259 | * Returns a %NUL-terminated string in dynamically allocated memory; | 260 | * Returns a %NUL-terminated string in dynamically allocated memory; |
260 | * otherwise NULL is returned if an error occurred. Caller must | 261 | * otherwise NULL is returned if an error occurred. Caller must |
261 | * free the returned string. | 262 | * free the returned string. |
262 | */ | 263 | */ |
263 | char *rpc_sockaddr2uaddr(const struct sockaddr *sap) | 264 | char *rpc_sockaddr2uaddr(const struct sockaddr *sap, gfp_t gfp_flags) |
264 | { | 265 | { |
265 | char portbuf[RPCBIND_MAXUADDRPLEN]; | 266 | char portbuf[RPCBIND_MAXUADDRPLEN]; |
266 | char addrbuf[RPCBIND_MAXUADDRLEN]; | 267 | char addrbuf[RPCBIND_MAXUADDRLEN]; |
@@ -288,9 +289,8 @@ char *rpc_sockaddr2uaddr(const struct sockaddr *sap) | |||
288 | if (strlcat(addrbuf, portbuf, sizeof(addrbuf)) > sizeof(addrbuf)) | 289 | if (strlcat(addrbuf, portbuf, sizeof(addrbuf)) > sizeof(addrbuf)) |
289 | return NULL; | 290 | return NULL; |
290 | 291 | ||
291 | return kstrdup(addrbuf, GFP_KERNEL); | 292 | return kstrdup(addrbuf, gfp_flags); |
292 | } | 293 | } |
293 | EXPORT_SYMBOL_GPL(rpc_sockaddr2uaddr); | ||
294 | 294 | ||
295 | /** | 295 | /** |
296 | * rpc_uaddr2sockaddr - convert a universal address to a socket address. | 296 | * rpc_uaddr2sockaddr - convert a universal address to a socket address. |
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 364eb45e989d..afb56553dfe7 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -122,7 +122,7 @@ gss_cred_set_ctx(struct rpc_cred *cred, struct gss_cl_ctx *ctx) | |||
122 | if (!test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags)) | 122 | if (!test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags)) |
123 | return; | 123 | return; |
124 | gss_get_ctx(ctx); | 124 | gss_get_ctx(ctx); |
125 | rcu_assign_pointer(gss_cred->gc_ctx, ctx); | 125 | RCU_INIT_POINTER(gss_cred->gc_ctx, ctx); |
126 | set_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); | 126 | set_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); |
127 | smp_mb__before_clear_bit(); | 127 | smp_mb__before_clear_bit(); |
128 | clear_bit(RPCAUTH_CRED_NEW, &cred->cr_flags); | 128 | clear_bit(RPCAUTH_CRED_NEW, &cred->cr_flags); |
@@ -603,26 +603,6 @@ out: | |||
603 | return err; | 603 | return err; |
604 | } | 604 | } |
605 | 605 | ||
606 | static ssize_t | ||
607 | gss_pipe_upcall(struct file *filp, struct rpc_pipe_msg *msg, | ||
608 | char __user *dst, size_t buflen) | ||
609 | { | ||
610 | char *data = (char *)msg->data + msg->copied; | ||
611 | size_t mlen = min(msg->len, buflen); | ||
612 | unsigned long left; | ||
613 | |||
614 | left = copy_to_user(dst, data, mlen); | ||
615 | if (left == mlen) { | ||
616 | msg->errno = -EFAULT; | ||
617 | return -EFAULT; | ||
618 | } | ||
619 | |||
620 | mlen -= left; | ||
621 | msg->copied += mlen; | ||
622 | msg->errno = 0; | ||
623 | return mlen; | ||
624 | } | ||
625 | |||
626 | #define MSG_BUF_MAXSIZE 1024 | 606 | #define MSG_BUF_MAXSIZE 1024 |
627 | 607 | ||
628 | static ssize_t | 608 | static ssize_t |
@@ -970,7 +950,7 @@ gss_destroy_nullcred(struct rpc_cred *cred) | |||
970 | struct gss_auth *gss_auth = container_of(cred->cr_auth, struct gss_auth, rpc_auth); | 950 | struct gss_auth *gss_auth = container_of(cred->cr_auth, struct gss_auth, rpc_auth); |
971 | struct gss_cl_ctx *ctx = gss_cred->gc_ctx; | 951 | struct gss_cl_ctx *ctx = gss_cred->gc_ctx; |
972 | 952 | ||
973 | rcu_assign_pointer(gss_cred->gc_ctx, NULL); | 953 | RCU_INIT_POINTER(gss_cred->gc_ctx, NULL); |
974 | call_rcu(&cred->cr_rcu, gss_free_cred_callback); | 954 | call_rcu(&cred->cr_rcu, gss_free_cred_callback); |
975 | if (ctx) | 955 | if (ctx) |
976 | gss_put_ctx(ctx); | 956 | gss_put_ctx(ctx); |
@@ -1590,7 +1570,7 @@ static const struct rpc_credops gss_nullops = { | |||
1590 | }; | 1570 | }; |
1591 | 1571 | ||
1592 | static const struct rpc_pipe_ops gss_upcall_ops_v0 = { | 1572 | static const struct rpc_pipe_ops gss_upcall_ops_v0 = { |
1593 | .upcall = gss_pipe_upcall, | 1573 | .upcall = rpc_pipe_generic_upcall, |
1594 | .downcall = gss_pipe_downcall, | 1574 | .downcall = gss_pipe_downcall, |
1595 | .destroy_msg = gss_pipe_destroy_msg, | 1575 | .destroy_msg = gss_pipe_destroy_msg, |
1596 | .open_pipe = gss_pipe_open_v0, | 1576 | .open_pipe = gss_pipe_open_v0, |
@@ -1598,7 +1578,7 @@ static const struct rpc_pipe_ops gss_upcall_ops_v0 = { | |||
1598 | }; | 1578 | }; |
1599 | 1579 | ||
1600 | static const struct rpc_pipe_ops gss_upcall_ops_v1 = { | 1580 | static const struct rpc_pipe_ops gss_upcall_ops_v1 = { |
1601 | .upcall = gss_pipe_upcall, | 1581 | .upcall = rpc_pipe_generic_upcall, |
1602 | .downcall = gss_pipe_downcall, | 1582 | .downcall = gss_pipe_downcall, |
1603 | .destroy_msg = gss_pipe_destroy_msg, | 1583 | .destroy_msg = gss_pipe_destroy_msg, |
1604 | .open_pipe = gss_pipe_open_v1, | 1584 | .open_pipe = gss_pipe_open_v1, |
diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c index 4cb70dc6e7ad..e50502d8ceb7 100644 --- a/net/sunrpc/auth_unix.c +++ b/net/sunrpc/auth_unix.c | |||
@@ -129,6 +129,9 @@ unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int flags) | |||
129 | for (i = 0; i < groups ; i++) | 129 | for (i = 0; i < groups ; i++) |
130 | if (cred->uc_gids[i] != GROUP_AT(acred->group_info, i)) | 130 | if (cred->uc_gids[i] != GROUP_AT(acred->group_info, i)) |
131 | return 0; | 131 | return 0; |
132 | if (groups < NFS_NGROUPS && | ||
133 | cred->uc_gids[groups] != NOGROUP) | ||
134 | return 0; | ||
132 | return 1; | 135 | return 1; |
133 | } | 136 | } |
134 | 137 | ||
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index c5347d29cfb7..f0268ea7e711 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -850,7 +850,9 @@ rpc_restart_call_prepare(struct rpc_task *task) | |||
850 | { | 850 | { |
851 | if (RPC_ASSASSINATED(task)) | 851 | if (RPC_ASSASSINATED(task)) |
852 | return 0; | 852 | return 0; |
853 | task->tk_action = rpc_prepare_task; | 853 | task->tk_action = call_start; |
854 | if (task->tk_ops->rpc_call_prepare != NULL) | ||
855 | task->tk_action = rpc_prepare_task; | ||
854 | return 1; | 856 | return 1; |
855 | } | 857 | } |
856 | EXPORT_SYMBOL_GPL(rpc_restart_call_prepare); | 858 | EXPORT_SYMBOL_GPL(rpc_restart_call_prepare); |
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index b181e3441323..bfddd68b31d3 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
@@ -77,6 +77,26 @@ rpc_timeout_upcall_queue(struct work_struct *work) | |||
77 | rpc_purge_list(rpci, &free_list, destroy_msg, -ETIMEDOUT); | 77 | rpc_purge_list(rpci, &free_list, destroy_msg, -ETIMEDOUT); |
78 | } | 78 | } |
79 | 79 | ||
80 | ssize_t rpc_pipe_generic_upcall(struct file *filp, struct rpc_pipe_msg *msg, | ||
81 | char __user *dst, size_t buflen) | ||
82 | { | ||
83 | char *data = (char *)msg->data + msg->copied; | ||
84 | size_t mlen = min(msg->len - msg->copied, buflen); | ||
85 | unsigned long left; | ||
86 | |||
87 | left = copy_to_user(dst, data, mlen); | ||
88 | if (left == mlen) { | ||
89 | msg->errno = -EFAULT; | ||
90 | return -EFAULT; | ||
91 | } | ||
92 | |||
93 | mlen -= left; | ||
94 | msg->copied += mlen; | ||
95 | msg->errno = 0; | ||
96 | return mlen; | ||
97 | } | ||
98 | EXPORT_SYMBOL_GPL(rpc_pipe_generic_upcall); | ||
99 | |||
80 | /** | 100 | /** |
81 | * rpc_queue_upcall - queue an upcall message to userspace | 101 | * rpc_queue_upcall - queue an upcall message to userspace |
82 | * @inode: inode of upcall pipe on which to queue given message | 102 | * @inode: inode of upcall pipe on which to queue given message |
@@ -1084,3 +1104,6 @@ void unregister_rpc_pipefs(void) | |||
1084 | kmem_cache_destroy(rpc_inode_cachep); | 1104 | kmem_cache_destroy(rpc_inode_cachep); |
1085 | unregister_filesystem(&rpc_pipe_fs_type); | 1105 | unregister_filesystem(&rpc_pipe_fs_type); |
1086 | } | 1106 | } |
1107 | |||
1108 | /* Make 'mount -t rpc_pipefs ...' autoload this module. */ | ||
1109 | MODULE_ALIAS("rpc_pipefs"); | ||
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index e45d2fbbe5a8..8761bf8e36fc 100644 --- a/net/sunrpc/rpcb_clnt.c +++ b/net/sunrpc/rpcb_clnt.c | |||
@@ -114,6 +114,9 @@ static struct rpc_program rpcb_program; | |||
114 | static struct rpc_clnt * rpcb_local_clnt; | 114 | static struct rpc_clnt * rpcb_local_clnt; |
115 | static struct rpc_clnt * rpcb_local_clnt4; | 115 | static struct rpc_clnt * rpcb_local_clnt4; |
116 | 116 | ||
117 | DEFINE_SPINLOCK(rpcb_clnt_lock); | ||
118 | unsigned int rpcb_users; | ||
119 | |||
117 | struct rpcbind_args { | 120 | struct rpcbind_args { |
118 | struct rpc_xprt * r_xprt; | 121 | struct rpc_xprt * r_xprt; |
119 | 122 | ||
@@ -161,6 +164,56 @@ static void rpcb_map_release(void *data) | |||
161 | kfree(map); | 164 | kfree(map); |
162 | } | 165 | } |
163 | 166 | ||
167 | static int rpcb_get_local(void) | ||
168 | { | ||
169 | int cnt; | ||
170 | |||
171 | spin_lock(&rpcb_clnt_lock); | ||
172 | if (rpcb_users) | ||
173 | rpcb_users++; | ||
174 | cnt = rpcb_users; | ||
175 | spin_unlock(&rpcb_clnt_lock); | ||
176 | |||
177 | return cnt; | ||
178 | } | ||
179 | |||
180 | void rpcb_put_local(void) | ||
181 | { | ||
182 | struct rpc_clnt *clnt = rpcb_local_clnt; | ||
183 | struct rpc_clnt *clnt4 = rpcb_local_clnt4; | ||
184 | int shutdown; | ||
185 | |||
186 | spin_lock(&rpcb_clnt_lock); | ||
187 | if (--rpcb_users == 0) { | ||
188 | rpcb_local_clnt = NULL; | ||
189 | rpcb_local_clnt4 = NULL; | ||
190 | } | ||
191 | shutdown = !rpcb_users; | ||
192 | spin_unlock(&rpcb_clnt_lock); | ||
193 | |||
194 | if (shutdown) { | ||
195 | /* | ||
196 | * cleanup_rpcb_clnt - remove xprtsock's sysctls, unregister | ||
197 | */ | ||
198 | if (clnt4) | ||
199 | rpc_shutdown_client(clnt4); | ||
200 | if (clnt) | ||
201 | rpc_shutdown_client(clnt); | ||
202 | } | ||
203 | } | ||
204 | |||
205 | static void rpcb_set_local(struct rpc_clnt *clnt, struct rpc_clnt *clnt4) | ||
206 | { | ||
207 | /* Protected by rpcb_create_local_mutex */ | ||
208 | rpcb_local_clnt = clnt; | ||
209 | rpcb_local_clnt4 = clnt4; | ||
210 | smp_wmb(); | ||
211 | rpcb_users = 1; | ||
212 | dprintk("RPC: created new rpcb local clients (rpcb_local_clnt: " | ||
213 | "%p, rpcb_local_clnt4: %p)\n", rpcb_local_clnt, | ||
214 | rpcb_local_clnt4); | ||
215 | } | ||
216 | |||
164 | /* | 217 | /* |
165 | * Returns zero on success, otherwise a negative errno value | 218 | * Returns zero on success, otherwise a negative errno value |
166 | * is returned. | 219 | * is returned. |
@@ -205,9 +258,7 @@ static int rpcb_create_local_unix(void) | |||
205 | clnt4 = NULL; | 258 | clnt4 = NULL; |
206 | } | 259 | } |
207 | 260 | ||
208 | /* Protected by rpcb_create_local_mutex */ | 261 | rpcb_set_local(clnt, clnt4); |
209 | rpcb_local_clnt = clnt; | ||
210 | rpcb_local_clnt4 = clnt4; | ||
211 | 262 | ||
212 | out: | 263 | out: |
213 | return result; | 264 | return result; |
@@ -259,9 +310,7 @@ static int rpcb_create_local_net(void) | |||
259 | clnt4 = NULL; | 310 | clnt4 = NULL; |
260 | } | 311 | } |
261 | 312 | ||
262 | /* Protected by rpcb_create_local_mutex */ | 313 | rpcb_set_local(clnt, clnt4); |
263 | rpcb_local_clnt = clnt; | ||
264 | rpcb_local_clnt4 = clnt4; | ||
265 | 314 | ||
266 | out: | 315 | out: |
267 | return result; | 316 | return result; |
@@ -271,16 +320,16 @@ out: | |||
271 | * Returns zero on success, otherwise a negative errno value | 320 | * Returns zero on success, otherwise a negative errno value |
272 | * is returned. | 321 | * is returned. |
273 | */ | 322 | */ |
274 | static int rpcb_create_local(void) | 323 | int rpcb_create_local(void) |
275 | { | 324 | { |
276 | static DEFINE_MUTEX(rpcb_create_local_mutex); | 325 | static DEFINE_MUTEX(rpcb_create_local_mutex); |
277 | int result = 0; | 326 | int result = 0; |
278 | 327 | ||
279 | if (rpcb_local_clnt) | 328 | if (rpcb_get_local()) |
280 | return result; | 329 | return result; |
281 | 330 | ||
282 | mutex_lock(&rpcb_create_local_mutex); | 331 | mutex_lock(&rpcb_create_local_mutex); |
283 | if (rpcb_local_clnt) | 332 | if (rpcb_get_local()) |
284 | goto out; | 333 | goto out; |
285 | 334 | ||
286 | if (rpcb_create_local_unix() != 0) | 335 | if (rpcb_create_local_unix() != 0) |
@@ -382,11 +431,6 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port) | |||
382 | struct rpc_message msg = { | 431 | struct rpc_message msg = { |
383 | .rpc_argp = &map, | 432 | .rpc_argp = &map, |
384 | }; | 433 | }; |
385 | int error; | ||
386 | |||
387 | error = rpcb_create_local(); | ||
388 | if (error) | ||
389 | return error; | ||
390 | 434 | ||
391 | dprintk("RPC: %sregistering (%u, %u, %d, %u) with local " | 435 | dprintk("RPC: %sregistering (%u, %u, %d, %u) with local " |
392 | "rpcbind\n", (port ? "" : "un"), | 436 | "rpcbind\n", (port ? "" : "un"), |
@@ -410,7 +454,7 @@ static int rpcb_register_inet4(const struct sockaddr *sap, | |||
410 | unsigned short port = ntohs(sin->sin_port); | 454 | unsigned short port = ntohs(sin->sin_port); |
411 | int result; | 455 | int result; |
412 | 456 | ||
413 | map->r_addr = rpc_sockaddr2uaddr(sap); | 457 | map->r_addr = rpc_sockaddr2uaddr(sap, GFP_KERNEL); |
414 | 458 | ||
415 | dprintk("RPC: %sregistering [%u, %u, %s, '%s'] with " | 459 | dprintk("RPC: %sregistering [%u, %u, %s, '%s'] with " |
416 | "local rpcbind\n", (port ? "" : "un"), | 460 | "local rpcbind\n", (port ? "" : "un"), |
@@ -437,7 +481,7 @@ static int rpcb_register_inet6(const struct sockaddr *sap, | |||
437 | unsigned short port = ntohs(sin6->sin6_port); | 481 | unsigned short port = ntohs(sin6->sin6_port); |
438 | int result; | 482 | int result; |
439 | 483 | ||
440 | map->r_addr = rpc_sockaddr2uaddr(sap); | 484 | map->r_addr = rpc_sockaddr2uaddr(sap, GFP_KERNEL); |
441 | 485 | ||
442 | dprintk("RPC: %sregistering [%u, %u, %s, '%s'] with " | 486 | dprintk("RPC: %sregistering [%u, %u, %s, '%s'] with " |
443 | "local rpcbind\n", (port ? "" : "un"), | 487 | "local rpcbind\n", (port ? "" : "un"), |
@@ -522,11 +566,7 @@ int rpcb_v4_register(const u32 program, const u32 version, | |||
522 | struct rpc_message msg = { | 566 | struct rpc_message msg = { |
523 | .rpc_argp = &map, | 567 | .rpc_argp = &map, |
524 | }; | 568 | }; |
525 | int error; | ||
526 | 569 | ||
527 | error = rpcb_create_local(); | ||
528 | if (error) | ||
529 | return error; | ||
530 | if (rpcb_local_clnt4 == NULL) | 570 | if (rpcb_local_clnt4 == NULL) |
531 | return -EPROTONOSUPPORT; | 571 | return -EPROTONOSUPPORT; |
532 | 572 | ||
@@ -686,7 +726,7 @@ void rpcb_getport_async(struct rpc_task *task) | |||
686 | case RPCBVERS_4: | 726 | case RPCBVERS_4: |
687 | case RPCBVERS_3: | 727 | case RPCBVERS_3: |
688 | map->r_netid = rpc_peeraddr2str(clnt, RPC_DISPLAY_NETID); | 728 | map->r_netid = rpc_peeraddr2str(clnt, RPC_DISPLAY_NETID); |
689 | map->r_addr = rpc_sockaddr2uaddr(sap); | 729 | map->r_addr = rpc_sockaddr2uaddr(sap, GFP_ATOMIC); |
690 | map->r_owner = ""; | 730 | map->r_owner = ""; |
691 | break; | 731 | break; |
692 | case RPCBVERS_2: | 732 | case RPCBVERS_2: |
@@ -1060,15 +1100,3 @@ static struct rpc_program rpcb_program = { | |||
1060 | .version = rpcb_version, | 1100 | .version = rpcb_version, |
1061 | .stats = &rpcb_stats, | 1101 | .stats = &rpcb_stats, |
1062 | }; | 1102 | }; |
1063 | |||
1064 | /** | ||
1065 | * cleanup_rpcb_clnt - remove xprtsock's sysctls, unregister | ||
1066 | * | ||
1067 | */ | ||
1068 | void cleanup_rpcb_clnt(void) | ||
1069 | { | ||
1070 | if (rpcb_local_clnt4) | ||
1071 | rpc_shutdown_client(rpcb_local_clnt4); | ||
1072 | if (rpcb_local_clnt) | ||
1073 | rpc_shutdown_client(rpcb_local_clnt); | ||
1074 | } | ||
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c index 9d0809160994..8ec9778c3f4a 100644 --- a/net/sunrpc/sunrpc_syms.c +++ b/net/sunrpc/sunrpc_syms.c | |||
@@ -61,8 +61,6 @@ static struct pernet_operations sunrpc_net_ops = { | |||
61 | 61 | ||
62 | extern struct cache_detail unix_gid_cache; | 62 | extern struct cache_detail unix_gid_cache; |
63 | 63 | ||
64 | extern void cleanup_rpcb_clnt(void); | ||
65 | |||
66 | static int __init | 64 | static int __init |
67 | init_sunrpc(void) | 65 | init_sunrpc(void) |
68 | { | 66 | { |
@@ -102,7 +100,6 @@ out: | |||
102 | static void __exit | 100 | static void __exit |
103 | cleanup_sunrpc(void) | 101 | cleanup_sunrpc(void) |
104 | { | 102 | { |
105 | cleanup_rpcb_clnt(); | ||
106 | rpcauth_remove_module(); | 103 | rpcauth_remove_module(); |
107 | cleanup_socket_xprt(); | 104 | cleanup_socket_xprt(); |
108 | svc_cleanup_xprt_sock(); | 105 | svc_cleanup_xprt_sock(); |
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index 6a69a1131fb7..6e038884ae0c 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c | |||
@@ -295,6 +295,18 @@ svc_pool_map_put(void) | |||
295 | } | 295 | } |
296 | 296 | ||
297 | 297 | ||
298 | static int svc_pool_map_get_node(unsigned int pidx) | ||
299 | { | ||
300 | const struct svc_pool_map *m = &svc_pool_map; | ||
301 | |||
302 | if (m->count) { | ||
303 | if (m->mode == SVC_POOL_PERCPU) | ||
304 | return cpu_to_node(m->pool_to[pidx]); | ||
305 | if (m->mode == SVC_POOL_PERNODE) | ||
306 | return m->pool_to[pidx]; | ||
307 | } | ||
308 | return NUMA_NO_NODE; | ||
309 | } | ||
298 | /* | 310 | /* |
299 | * Set the given thread's cpus_allowed mask so that it | 311 | * Set the given thread's cpus_allowed mask so that it |
300 | * will only run on cpus in the given pool. | 312 | * will only run on cpus in the given pool. |
@@ -354,6 +366,42 @@ svc_pool_for_cpu(struct svc_serv *serv, int cpu) | |||
354 | return &serv->sv_pools[pidx % serv->sv_nrpools]; | 366 | return &serv->sv_pools[pidx % serv->sv_nrpools]; |
355 | } | 367 | } |
356 | 368 | ||
369 | static int svc_rpcb_setup(struct svc_serv *serv) | ||
370 | { | ||
371 | int err; | ||
372 | |||
373 | err = rpcb_create_local(); | ||
374 | if (err) | ||
375 | return err; | ||
376 | |||
377 | /* Remove any stale portmap registrations */ | ||
378 | svc_unregister(serv); | ||
379 | return 0; | ||
380 | } | ||
381 | |||
382 | void svc_rpcb_cleanup(struct svc_serv *serv) | ||
383 | { | ||
384 | svc_unregister(serv); | ||
385 | rpcb_put_local(); | ||
386 | } | ||
387 | EXPORT_SYMBOL_GPL(svc_rpcb_cleanup); | ||
388 | |||
389 | static int svc_uses_rpcbind(struct svc_serv *serv) | ||
390 | { | ||
391 | struct svc_program *progp; | ||
392 | unsigned int i; | ||
393 | |||
394 | for (progp = serv->sv_program; progp; progp = progp->pg_next) { | ||
395 | for (i = 0; i < progp->pg_nvers; i++) { | ||
396 | if (progp->pg_vers[i] == NULL) | ||
397 | continue; | ||
398 | if (progp->pg_vers[i]->vs_hidden == 0) | ||
399 | return 1; | ||
400 | } | ||
401 | } | ||
402 | |||
403 | return 0; | ||
404 | } | ||
357 | 405 | ||
358 | /* | 406 | /* |
359 | * Create an RPC service | 407 | * Create an RPC service |
@@ -419,8 +467,15 @@ __svc_create(struct svc_program *prog, unsigned int bufsize, int npools, | |||
419 | spin_lock_init(&pool->sp_lock); | 467 | spin_lock_init(&pool->sp_lock); |
420 | } | 468 | } |
421 | 469 | ||
422 | /* Remove any stale portmap registrations */ | 470 | if (svc_uses_rpcbind(serv)) { |
423 | svc_unregister(serv); | 471 | if (svc_rpcb_setup(serv) < 0) { |
472 | kfree(serv->sv_pools); | ||
473 | kfree(serv); | ||
474 | return NULL; | ||
475 | } | ||
476 | if (!serv->sv_shutdown) | ||
477 | serv->sv_shutdown = svc_rpcb_cleanup; | ||
478 | } | ||
424 | 479 | ||
425 | return serv; | 480 | return serv; |
426 | } | 481 | } |
@@ -488,7 +543,6 @@ svc_destroy(struct svc_serv *serv) | |||
488 | if (svc_serv_is_pooled(serv)) | 543 | if (svc_serv_is_pooled(serv)) |
489 | svc_pool_map_put(); | 544 | svc_pool_map_put(); |
490 | 545 | ||
491 | svc_unregister(serv); | ||
492 | kfree(serv->sv_pools); | 546 | kfree(serv->sv_pools); |
493 | kfree(serv); | 547 | kfree(serv); |
494 | } | 548 | } |
@@ -499,7 +553,7 @@ EXPORT_SYMBOL_GPL(svc_destroy); | |||
499 | * We allocate pages and place them in rq_argpages. | 553 | * We allocate pages and place them in rq_argpages. |
500 | */ | 554 | */ |
501 | static int | 555 | static int |
502 | svc_init_buffer(struct svc_rqst *rqstp, unsigned int size) | 556 | svc_init_buffer(struct svc_rqst *rqstp, unsigned int size, int node) |
503 | { | 557 | { |
504 | unsigned int pages, arghi; | 558 | unsigned int pages, arghi; |
505 | 559 | ||
@@ -513,7 +567,7 @@ svc_init_buffer(struct svc_rqst *rqstp, unsigned int size) | |||
513 | arghi = 0; | 567 | arghi = 0; |
514 | BUG_ON(pages > RPCSVC_MAXPAGES); | 568 | BUG_ON(pages > RPCSVC_MAXPAGES); |
515 | while (pages) { | 569 | while (pages) { |
516 | struct page *p = alloc_page(GFP_KERNEL); | 570 | struct page *p = alloc_pages_node(node, GFP_KERNEL, 0); |
517 | if (!p) | 571 | if (!p) |
518 | break; | 572 | break; |
519 | rqstp->rq_pages[arghi++] = p; | 573 | rqstp->rq_pages[arghi++] = p; |
@@ -536,11 +590,11 @@ svc_release_buffer(struct svc_rqst *rqstp) | |||
536 | } | 590 | } |
537 | 591 | ||
538 | struct svc_rqst * | 592 | struct svc_rqst * |
539 | svc_prepare_thread(struct svc_serv *serv, struct svc_pool *pool) | 593 | svc_prepare_thread(struct svc_serv *serv, struct svc_pool *pool, int node) |
540 | { | 594 | { |
541 | struct svc_rqst *rqstp; | 595 | struct svc_rqst *rqstp; |
542 | 596 | ||
543 | rqstp = kzalloc(sizeof(*rqstp), GFP_KERNEL); | 597 | rqstp = kzalloc_node(sizeof(*rqstp), GFP_KERNEL, node); |
544 | if (!rqstp) | 598 | if (!rqstp) |
545 | goto out_enomem; | 599 | goto out_enomem; |
546 | 600 | ||
@@ -554,15 +608,15 @@ svc_prepare_thread(struct svc_serv *serv, struct svc_pool *pool) | |||
554 | rqstp->rq_server = serv; | 608 | rqstp->rq_server = serv; |
555 | rqstp->rq_pool = pool; | 609 | rqstp->rq_pool = pool; |
556 | 610 | ||
557 | rqstp->rq_argp = kmalloc(serv->sv_xdrsize, GFP_KERNEL); | 611 | rqstp->rq_argp = kmalloc_node(serv->sv_xdrsize, GFP_KERNEL, node); |
558 | if (!rqstp->rq_argp) | 612 | if (!rqstp->rq_argp) |
559 | goto out_thread; | 613 | goto out_thread; |
560 | 614 | ||
561 | rqstp->rq_resp = kmalloc(serv->sv_xdrsize, GFP_KERNEL); | 615 | rqstp->rq_resp = kmalloc_node(serv->sv_xdrsize, GFP_KERNEL, node); |
562 | if (!rqstp->rq_resp) | 616 | if (!rqstp->rq_resp) |
563 | goto out_thread; | 617 | goto out_thread; |
564 | 618 | ||
565 | if (!svc_init_buffer(rqstp, serv->sv_max_mesg)) | 619 | if (!svc_init_buffer(rqstp, serv->sv_max_mesg, node)) |
566 | goto out_thread; | 620 | goto out_thread; |
567 | 621 | ||
568 | return rqstp; | 622 | return rqstp; |
@@ -647,6 +701,7 @@ svc_set_num_threads(struct svc_serv *serv, struct svc_pool *pool, int nrservs) | |||
647 | struct svc_pool *chosen_pool; | 701 | struct svc_pool *chosen_pool; |
648 | int error = 0; | 702 | int error = 0; |
649 | unsigned int state = serv->sv_nrthreads-1; | 703 | unsigned int state = serv->sv_nrthreads-1; |
704 | int node; | ||
650 | 705 | ||
651 | if (pool == NULL) { | 706 | if (pool == NULL) { |
652 | /* The -1 assumes caller has done a svc_get() */ | 707 | /* The -1 assumes caller has done a svc_get() */ |
@@ -662,14 +717,16 @@ svc_set_num_threads(struct svc_serv *serv, struct svc_pool *pool, int nrservs) | |||
662 | nrservs--; | 717 | nrservs--; |
663 | chosen_pool = choose_pool(serv, pool, &state); | 718 | chosen_pool = choose_pool(serv, pool, &state); |
664 | 719 | ||
665 | rqstp = svc_prepare_thread(serv, chosen_pool); | 720 | node = svc_pool_map_get_node(chosen_pool->sp_id); |
721 | rqstp = svc_prepare_thread(serv, chosen_pool, node); | ||
666 | if (IS_ERR(rqstp)) { | 722 | if (IS_ERR(rqstp)) { |
667 | error = PTR_ERR(rqstp); | 723 | error = PTR_ERR(rqstp); |
668 | break; | 724 | break; |
669 | } | 725 | } |
670 | 726 | ||
671 | __module_get(serv->sv_module); | 727 | __module_get(serv->sv_module); |
672 | task = kthread_create(serv->sv_function, rqstp, serv->sv_name); | 728 | task = kthread_create_on_node(serv->sv_function, rqstp, |
729 | node, serv->sv_name); | ||
673 | if (IS_ERR(task)) { | 730 | if (IS_ERR(task)) { |
674 | error = PTR_ERR(task); | 731 | error = PTR_ERR(task); |
675 | module_put(serv->sv_module); | 732 | module_put(serv->sv_module); |
@@ -956,9 +1013,8 @@ static void svc_unregister(const struct svc_serv *serv) | |||
956 | /* | 1013 | /* |
957 | * Printk the given error with the address of the client that caused it. | 1014 | * Printk the given error with the address of the client that caused it. |
958 | */ | 1015 | */ |
959 | static int | 1016 | static __printf(2, 3) |
960 | __attribute__ ((format (printf, 2, 3))) | 1017 | int svc_printk(struct svc_rqst *rqstp, const char *fmt, ...) |
961 | svc_printk(struct svc_rqst *rqstp, const char *fmt, ...) | ||
962 | { | 1018 | { |
963 | va_list args; | 1019 | va_list args; |
964 | int r; | 1020 | int r; |
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index bd31208bbb61..d86bb673e1f6 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c | |||
@@ -254,8 +254,6 @@ EXPORT_SYMBOL_GPL(svc_create_xprt); | |||
254 | */ | 254 | */ |
255 | void svc_xprt_copy_addrs(struct svc_rqst *rqstp, struct svc_xprt *xprt) | 255 | void svc_xprt_copy_addrs(struct svc_rqst *rqstp, struct svc_xprt *xprt) |
256 | { | 256 | { |
257 | struct sockaddr *sin; | ||
258 | |||
259 | memcpy(&rqstp->rq_addr, &xprt->xpt_remote, xprt->xpt_remotelen); | 257 | memcpy(&rqstp->rq_addr, &xprt->xpt_remote, xprt->xpt_remotelen); |
260 | rqstp->rq_addrlen = xprt->xpt_remotelen; | 258 | rqstp->rq_addrlen = xprt->xpt_remotelen; |
261 | 259 | ||
@@ -263,15 +261,8 @@ void svc_xprt_copy_addrs(struct svc_rqst *rqstp, struct svc_xprt *xprt) | |||
263 | * Destination address in request is needed for binding the | 261 | * Destination address in request is needed for binding the |
264 | * source address in RPC replies/callbacks later. | 262 | * source address in RPC replies/callbacks later. |
265 | */ | 263 | */ |
266 | sin = (struct sockaddr *)&xprt->xpt_local; | 264 | memcpy(&rqstp->rq_daddr, &xprt->xpt_local, xprt->xpt_locallen); |
267 | switch (sin->sa_family) { | 265 | rqstp->rq_daddrlen = xprt->xpt_locallen; |
268 | case AF_INET: | ||
269 | rqstp->rq_daddr.addr = ((struct sockaddr_in *)sin)->sin_addr; | ||
270 | break; | ||
271 | case AF_INET6: | ||
272 | rqstp->rq_daddr.addr6 = ((struct sockaddr_in6 *)sin)->sin6_addr; | ||
273 | break; | ||
274 | } | ||
275 | } | 266 | } |
276 | EXPORT_SYMBOL_GPL(svc_xprt_copy_addrs); | 267 | EXPORT_SYMBOL_GPL(svc_xprt_copy_addrs); |
277 | 268 | ||
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 767d494de7a2..dfd686eb0b7f 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
@@ -143,19 +143,20 @@ static void svc_set_cmsg_data(struct svc_rqst *rqstp, struct cmsghdr *cmh) | |||
143 | cmh->cmsg_level = SOL_IP; | 143 | cmh->cmsg_level = SOL_IP; |
144 | cmh->cmsg_type = IP_PKTINFO; | 144 | cmh->cmsg_type = IP_PKTINFO; |
145 | pki->ipi_ifindex = 0; | 145 | pki->ipi_ifindex = 0; |
146 | pki->ipi_spec_dst.s_addr = rqstp->rq_daddr.addr.s_addr; | 146 | pki->ipi_spec_dst.s_addr = |
147 | svc_daddr_in(rqstp)->sin_addr.s_addr; | ||
147 | cmh->cmsg_len = CMSG_LEN(sizeof(*pki)); | 148 | cmh->cmsg_len = CMSG_LEN(sizeof(*pki)); |
148 | } | 149 | } |
149 | break; | 150 | break; |
150 | 151 | ||
151 | case AF_INET6: { | 152 | case AF_INET6: { |
152 | struct in6_pktinfo *pki = CMSG_DATA(cmh); | 153 | struct in6_pktinfo *pki = CMSG_DATA(cmh); |
154 | struct sockaddr_in6 *daddr = svc_daddr_in6(rqstp); | ||
153 | 155 | ||
154 | cmh->cmsg_level = SOL_IPV6; | 156 | cmh->cmsg_level = SOL_IPV6; |
155 | cmh->cmsg_type = IPV6_PKTINFO; | 157 | cmh->cmsg_type = IPV6_PKTINFO; |
156 | pki->ipi6_ifindex = 0; | 158 | pki->ipi6_ifindex = daddr->sin6_scope_id; |
157 | ipv6_addr_copy(&pki->ipi6_addr, | 159 | ipv6_addr_copy(&pki->ipi6_addr, &daddr->sin6_addr); |
158 | &rqstp->rq_daddr.addr6); | ||
159 | cmh->cmsg_len = CMSG_LEN(sizeof(*pki)); | 160 | cmh->cmsg_len = CMSG_LEN(sizeof(*pki)); |
160 | } | 161 | } |
161 | break; | 162 | break; |
@@ -498,9 +499,13 @@ static int svc_udp_get_dest_address4(struct svc_rqst *rqstp, | |||
498 | struct cmsghdr *cmh) | 499 | struct cmsghdr *cmh) |
499 | { | 500 | { |
500 | struct in_pktinfo *pki = CMSG_DATA(cmh); | 501 | struct in_pktinfo *pki = CMSG_DATA(cmh); |
502 | struct sockaddr_in *daddr = svc_daddr_in(rqstp); | ||
503 | |||
501 | if (cmh->cmsg_type != IP_PKTINFO) | 504 | if (cmh->cmsg_type != IP_PKTINFO) |
502 | return 0; | 505 | return 0; |
503 | rqstp->rq_daddr.addr.s_addr = pki->ipi_spec_dst.s_addr; | 506 | |
507 | daddr->sin_family = AF_INET; | ||
508 | daddr->sin_addr.s_addr = pki->ipi_spec_dst.s_addr; | ||
504 | return 1; | 509 | return 1; |
505 | } | 510 | } |
506 | 511 | ||
@@ -511,9 +516,14 @@ static int svc_udp_get_dest_address6(struct svc_rqst *rqstp, | |||
511 | struct cmsghdr *cmh) | 516 | struct cmsghdr *cmh) |
512 | { | 517 | { |
513 | struct in6_pktinfo *pki = CMSG_DATA(cmh); | 518 | struct in6_pktinfo *pki = CMSG_DATA(cmh); |
519 | struct sockaddr_in6 *daddr = svc_daddr_in6(rqstp); | ||
520 | |||
514 | if (cmh->cmsg_type != IPV6_PKTINFO) | 521 | if (cmh->cmsg_type != IPV6_PKTINFO) |
515 | return 0; | 522 | return 0; |
516 | ipv6_addr_copy(&rqstp->rq_daddr.addr6, &pki->ipi6_addr); | 523 | |
524 | daddr->sin6_family = AF_INET6; | ||
525 | ipv6_addr_copy(&daddr->sin6_addr, &pki->ipi6_addr); | ||
526 | daddr->sin6_scope_id = pki->ipi6_ifindex; | ||
517 | return 1; | 527 | return 1; |
518 | } | 528 | } |
519 | 529 | ||
@@ -614,6 +624,7 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp) | |||
614 | skb_free_datagram_locked(svsk->sk_sk, skb); | 624 | skb_free_datagram_locked(svsk->sk_sk, skb); |
615 | return 0; | 625 | return 0; |
616 | } | 626 | } |
627 | rqstp->rq_daddrlen = svc_addr_len(svc_daddr(rqstp)); | ||
617 | 628 | ||
618 | if (skb_is_nonlinear(skb)) { | 629 | if (skb_is_nonlinear(skb)) { |
619 | /* we have to copy */ | 630 | /* we have to copy */ |