diff options
Diffstat (limited to 'net/sunrpc/clnt.c')
| -rw-r--r-- | net/sunrpc/clnt.c | 300 |
1 files changed, 181 insertions, 119 deletions
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index aa8965e9d307..124ff0ceb55b 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
| @@ -60,8 +60,8 @@ static void call_refreshresult(struct rpc_task *task); | |||
| 60 | static void call_timeout(struct rpc_task *task); | 60 | static void call_timeout(struct rpc_task *task); |
| 61 | static void call_connect(struct rpc_task *task); | 61 | static void call_connect(struct rpc_task *task); |
| 62 | static void call_connect_status(struct rpc_task *task); | 62 | static void call_connect_status(struct rpc_task *task); |
| 63 | static u32 * call_header(struct rpc_task *task); | 63 | static __be32 * call_header(struct rpc_task *task); |
| 64 | static u32 * call_verify(struct rpc_task *task); | 64 | static __be32 * call_verify(struct rpc_task *task); |
| 65 | 65 | ||
| 66 | 66 | ||
| 67 | static int | 67 | static int |
| @@ -97,17 +97,7 @@ rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name) | |||
| 97 | } | 97 | } |
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | /* | 100 | static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, struct rpc_program *program, u32 vers, rpc_authflavor_t flavor) |
| 101 | * Create an RPC client | ||
| 102 | * FIXME: This should also take a flags argument (as in task->tk_flags). | ||
| 103 | * It's called (among others) from pmap_create_client, which may in | ||
| 104 | * turn be called by an async task. In this case, rpciod should not be | ||
| 105 | * made to sleep too long. | ||
| 106 | */ | ||
| 107 | struct rpc_clnt * | ||
| 108 | rpc_new_client(struct rpc_xprt *xprt, char *servname, | ||
| 109 | struct rpc_program *program, u32 vers, | ||
| 110 | rpc_authflavor_t flavor) | ||
| 111 | { | 101 | { |
| 112 | struct rpc_version *version; | 102 | struct rpc_version *version; |
| 113 | struct rpc_clnt *clnt = NULL; | 103 | struct rpc_clnt *clnt = NULL; |
| @@ -125,10 +115,9 @@ rpc_new_client(struct rpc_xprt *xprt, char *servname, | |||
| 125 | goto out_err; | 115 | goto out_err; |
| 126 | 116 | ||
| 127 | err = -ENOMEM; | 117 | err = -ENOMEM; |
| 128 | clnt = kmalloc(sizeof(*clnt), GFP_KERNEL); | 118 | clnt = kzalloc(sizeof(*clnt), GFP_KERNEL); |
| 129 | if (!clnt) | 119 | if (!clnt) |
| 130 | goto out_err; | 120 | goto out_err; |
| 131 | memset(clnt, 0, sizeof(*clnt)); | ||
| 132 | atomic_set(&clnt->cl_users, 0); | 121 | atomic_set(&clnt->cl_users, 0); |
| 133 | atomic_set(&clnt->cl_count, 1); | 122 | atomic_set(&clnt->cl_count, 1); |
| 134 | clnt->cl_parent = clnt; | 123 | clnt->cl_parent = clnt; |
| @@ -148,16 +137,12 @@ rpc_new_client(struct rpc_xprt *xprt, char *servname, | |||
| 148 | clnt->cl_procinfo = version->procs; | 137 | clnt->cl_procinfo = version->procs; |
| 149 | clnt->cl_maxproc = version->nrprocs; | 138 | clnt->cl_maxproc = version->nrprocs; |
| 150 | clnt->cl_protname = program->name; | 139 | clnt->cl_protname = program->name; |
| 151 | clnt->cl_pmap = &clnt->cl_pmap_default; | ||
| 152 | clnt->cl_port = xprt->addr.sin_port; | ||
| 153 | clnt->cl_prog = program->number; | 140 | clnt->cl_prog = program->number; |
| 154 | clnt->cl_vers = version->number; | 141 | clnt->cl_vers = version->number; |
| 155 | clnt->cl_prot = xprt->prot; | ||
| 156 | clnt->cl_stats = program->stats; | 142 | clnt->cl_stats = program->stats; |
| 157 | clnt->cl_metrics = rpc_alloc_iostats(clnt); | 143 | clnt->cl_metrics = rpc_alloc_iostats(clnt); |
| 158 | rpc_init_wait_queue(&clnt->cl_pmap_default.pm_bindwait, "bindwait"); | ||
| 159 | 144 | ||
| 160 | if (!clnt->cl_port) | 145 | if (!xprt_bound(clnt->cl_xprt)) |
| 161 | clnt->cl_autobind = 1; | 146 | clnt->cl_autobind = 1; |
| 162 | 147 | ||
| 163 | clnt->cl_rtt = &clnt->cl_rtt_default; | 148 | clnt->cl_rtt = &clnt->cl_rtt_default; |
| @@ -184,8 +169,7 @@ rpc_new_client(struct rpc_xprt *xprt, char *servname, | |||
| 184 | 169 | ||
| 185 | out_no_auth: | 170 | out_no_auth: |
| 186 | if (!IS_ERR(clnt->cl_dentry)) { | 171 | if (!IS_ERR(clnt->cl_dentry)) { |
| 187 | rpc_rmdir(clnt->cl_pathname); | 172 | rpc_rmdir(clnt->cl_dentry); |
| 188 | dput(clnt->cl_dentry); | ||
| 189 | rpc_put_mount(); | 173 | rpc_put_mount(); |
| 190 | } | 174 | } |
| 191 | out_no_path: | 175 | out_no_path: |
| @@ -193,40 +177,71 @@ out_no_path: | |||
| 193 | kfree(clnt->cl_server); | 177 | kfree(clnt->cl_server); |
| 194 | kfree(clnt); | 178 | kfree(clnt); |
| 195 | out_err: | 179 | out_err: |
| 196 | xprt_destroy(xprt); | 180 | xprt_put(xprt); |
| 197 | out_no_xprt: | 181 | out_no_xprt: |
| 198 | return ERR_PTR(err); | 182 | return ERR_PTR(err); |
| 199 | } | 183 | } |
| 200 | 184 | ||
| 201 | /** | 185 | /* |
| 202 | * Create an RPC client | 186 | * rpc_create - create an RPC client and transport with one call |
| 203 | * @xprt - pointer to xprt struct | 187 | * @args: rpc_clnt create argument structure |
| 204 | * @servname - name of server | ||
| 205 | * @info - rpc_program | ||
| 206 | * @version - rpc_program version | ||
| 207 | * @authflavor - rpc_auth flavour to use | ||
| 208 | * | 188 | * |
| 209 | * Creates an RPC client structure, then pings the server in order to | 189 | * Creates and initializes an RPC transport and an RPC client. |
| 210 | * determine if it is up, and if it supports this program and version. | ||
| 211 | * | 190 | * |
| 212 | * This function should never be called by asynchronous tasks such as | 191 | * It can ping the server in order to determine if it is up, and to see if |
| 213 | * the portmapper. | 192 | * it supports this program and version. RPC_CLNT_CREATE_NOPING disables |
| 193 | * this behavior so asynchronous tasks can also use rpc_create. | ||
| 214 | */ | 194 | */ |
| 215 | struct rpc_clnt *rpc_create_client(struct rpc_xprt *xprt, char *servname, | 195 | struct rpc_clnt *rpc_create(struct rpc_create_args *args) |
| 216 | struct rpc_program *info, u32 version, rpc_authflavor_t authflavor) | ||
| 217 | { | 196 | { |
| 197 | struct rpc_xprt *xprt; | ||
| 218 | struct rpc_clnt *clnt; | 198 | struct rpc_clnt *clnt; |
| 219 | int err; | 199 | |
| 220 | 200 | xprt = xprt_create_transport(args->protocol, args->address, | |
| 221 | clnt = rpc_new_client(xprt, servname, info, version, authflavor); | 201 | args->addrsize, args->timeout); |
| 202 | if (IS_ERR(xprt)) | ||
| 203 | return (struct rpc_clnt *)xprt; | ||
| 204 | |||
| 205 | /* | ||
| 206 | * By default, kernel RPC client connects from a reserved port. | ||
| 207 | * CAP_NET_BIND_SERVICE will not be set for unprivileged requesters, | ||
| 208 | * but it is always enabled for rpciod, which handles the connect | ||
| 209 | * operation. | ||
| 210 | */ | ||
| 211 | xprt->resvport = 1; | ||
| 212 | if (args->flags & RPC_CLNT_CREATE_NONPRIVPORT) | ||
| 213 | xprt->resvport = 0; | ||
| 214 | |||
| 215 | dprintk("RPC: creating %s client for %s (xprt %p)\n", | ||
| 216 | args->program->name, args->servername, xprt); | ||
| 217 | |||
| 218 | clnt = rpc_new_client(xprt, args->servername, args->program, | ||
| 219 | args->version, args->authflavor); | ||
| 222 | if (IS_ERR(clnt)) | 220 | if (IS_ERR(clnt)) |
| 223 | return clnt; | 221 | return clnt; |
| 224 | err = rpc_ping(clnt, RPC_TASK_SOFT|RPC_TASK_NOINTR); | 222 | |
| 225 | if (err == 0) | 223 | if (!(args->flags & RPC_CLNT_CREATE_NOPING)) { |
| 226 | return clnt; | 224 | int err = rpc_ping(clnt, RPC_TASK_SOFT|RPC_TASK_NOINTR); |
| 227 | rpc_shutdown_client(clnt); | 225 | if (err != 0) { |
| 228 | return ERR_PTR(err); | 226 | rpc_shutdown_client(clnt); |
| 227 | return ERR_PTR(err); | ||
| 228 | } | ||
| 229 | } | ||
| 230 | |||
| 231 | clnt->cl_softrtry = 1; | ||
| 232 | if (args->flags & RPC_CLNT_CREATE_HARDRTRY) | ||
| 233 | clnt->cl_softrtry = 0; | ||
| 234 | |||
| 235 | if (args->flags & RPC_CLNT_CREATE_INTR) | ||
| 236 | clnt->cl_intr = 1; | ||
| 237 | if (args->flags & RPC_CLNT_CREATE_AUTOBIND) | ||
| 238 | clnt->cl_autobind = 1; | ||
| 239 | if (args->flags & RPC_CLNT_CREATE_ONESHOT) | ||
| 240 | clnt->cl_oneshot = 1; | ||
| 241 | |||
| 242 | return clnt; | ||
| 229 | } | 243 | } |
| 244 | EXPORT_SYMBOL_GPL(rpc_create); | ||
| 230 | 245 | ||
| 231 | /* | 246 | /* |
| 232 | * This function clones the RPC client structure. It allows us to share the | 247 | * This function clones the RPC client structure. It allows us to share the |
| @@ -246,21 +261,17 @@ rpc_clone_client(struct rpc_clnt *clnt) | |||
| 246 | atomic_set(&new->cl_users, 0); | 261 | atomic_set(&new->cl_users, 0); |
| 247 | new->cl_parent = clnt; | 262 | new->cl_parent = clnt; |
| 248 | atomic_inc(&clnt->cl_count); | 263 | atomic_inc(&clnt->cl_count); |
| 249 | /* Duplicate portmapper */ | 264 | new->cl_xprt = xprt_get(clnt->cl_xprt); |
| 250 | rpc_init_wait_queue(&new->cl_pmap_default.pm_bindwait, "bindwait"); | ||
| 251 | /* Turn off autobind on clones */ | 265 | /* Turn off autobind on clones */ |
| 252 | new->cl_autobind = 0; | 266 | new->cl_autobind = 0; |
| 253 | new->cl_oneshot = 0; | 267 | new->cl_oneshot = 0; |
| 254 | new->cl_dead = 0; | 268 | new->cl_dead = 0; |
| 255 | if (!IS_ERR(new->cl_dentry)) { | 269 | if (!IS_ERR(new->cl_dentry)) |
| 256 | dget(new->cl_dentry); | 270 | dget(new->cl_dentry); |
| 257 | rpc_get_mount(); | ||
| 258 | } | ||
| 259 | rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval); | 271 | rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval); |
| 260 | if (new->cl_auth) | 272 | if (new->cl_auth) |
| 261 | atomic_inc(&new->cl_auth->au_count); | 273 | atomic_inc(&new->cl_auth->au_count); |
| 262 | new->cl_pmap = &new->cl_pmap_default; | 274 | new->cl_metrics = rpc_alloc_iostats(clnt); |
| 263 | new->cl_metrics = rpc_alloc_iostats(clnt); | ||
| 264 | return new; | 275 | return new; |
| 265 | out_no_clnt: | 276 | out_no_clnt: |
| 266 | printk(KERN_INFO "RPC: out of memory in %s\n", __FUNCTION__); | 277 | printk(KERN_INFO "RPC: out of memory in %s\n", __FUNCTION__); |
| @@ -318,24 +329,21 @@ rpc_destroy_client(struct rpc_clnt *clnt) | |||
| 318 | clnt->cl_auth = NULL; | 329 | clnt->cl_auth = NULL; |
| 319 | } | 330 | } |
| 320 | if (clnt->cl_parent != clnt) { | 331 | if (clnt->cl_parent != clnt) { |
| 332 | if (!IS_ERR(clnt->cl_dentry)) | ||
| 333 | dput(clnt->cl_dentry); | ||
| 321 | rpc_destroy_client(clnt->cl_parent); | 334 | rpc_destroy_client(clnt->cl_parent); |
| 322 | goto out_free; | 335 | goto out_free; |
| 323 | } | 336 | } |
| 324 | if (clnt->cl_pathname[0]) | 337 | if (!IS_ERR(clnt->cl_dentry)) { |
| 325 | rpc_rmdir(clnt->cl_pathname); | 338 | rpc_rmdir(clnt->cl_dentry); |
| 326 | if (clnt->cl_xprt) { | 339 | rpc_put_mount(); |
| 327 | xprt_destroy(clnt->cl_xprt); | ||
| 328 | clnt->cl_xprt = NULL; | ||
| 329 | } | 340 | } |
| 330 | if (clnt->cl_server != clnt->cl_inline_name) | 341 | if (clnt->cl_server != clnt->cl_inline_name) |
| 331 | kfree(clnt->cl_server); | 342 | kfree(clnt->cl_server); |
| 332 | out_free: | 343 | out_free: |
| 333 | rpc_free_iostats(clnt->cl_metrics); | 344 | rpc_free_iostats(clnt->cl_metrics); |
| 334 | clnt->cl_metrics = NULL; | 345 | clnt->cl_metrics = NULL; |
| 335 | if (!IS_ERR(clnt->cl_dentry)) { | 346 | xprt_put(clnt->cl_xprt); |
| 336 | dput(clnt->cl_dentry); | ||
| 337 | rpc_put_mount(); | ||
| 338 | } | ||
| 339 | kfree(clnt); | 347 | kfree(clnt); |
| 340 | return 0; | 348 | return 0; |
| 341 | } | 349 | } |
| @@ -544,6 +552,40 @@ rpc_call_setup(struct rpc_task *task, struct rpc_message *msg, int flags) | |||
| 544 | task->tk_action = rpc_exit_task; | 552 | task->tk_action = rpc_exit_task; |
| 545 | } | 553 | } |
| 546 | 554 | ||
| 555 | /** | ||
| 556 | * rpc_peeraddr - extract remote peer address from clnt's xprt | ||
| 557 | * @clnt: RPC client structure | ||
| 558 | * @buf: target buffer | ||
| 559 | * @size: length of target buffer | ||
| 560 | * | ||
| 561 | * Returns the number of bytes that are actually in the stored address. | ||
| 562 | */ | ||
| 563 | size_t rpc_peeraddr(struct rpc_clnt *clnt, struct sockaddr *buf, size_t bufsize) | ||
| 564 | { | ||
| 565 | size_t bytes; | ||
| 566 | struct rpc_xprt *xprt = clnt->cl_xprt; | ||
| 567 | |||
| 568 | bytes = sizeof(xprt->addr); | ||
| 569 | if (bytes > bufsize) | ||
| 570 | bytes = bufsize; | ||
| 571 | memcpy(buf, &clnt->cl_xprt->addr, bytes); | ||
| 572 | return xprt->addrlen; | ||
| 573 | } | ||
| 574 | EXPORT_SYMBOL_GPL(rpc_peeraddr); | ||
| 575 | |||
| 576 | /** | ||
| 577 | * rpc_peeraddr2str - return remote peer address in printable format | ||
| 578 | * @clnt: RPC client structure | ||
| 579 | * @format: address format | ||
| 580 | * | ||
| 581 | */ | ||
| 582 | char *rpc_peeraddr2str(struct rpc_clnt *clnt, enum rpc_display_format_t format) | ||
| 583 | { | ||
| 584 | struct rpc_xprt *xprt = clnt->cl_xprt; | ||
| 585 | return xprt->ops->print_addr(xprt, format); | ||
| 586 | } | ||
| 587 | EXPORT_SYMBOL_GPL(rpc_peeraddr2str); | ||
| 588 | |||
| 547 | void | 589 | void |
| 548 | rpc_setbufsize(struct rpc_clnt *clnt, unsigned int sndsize, unsigned int rcvsize) | 590 | rpc_setbufsize(struct rpc_clnt *clnt, unsigned int sndsize, unsigned int rcvsize) |
| 549 | { | 591 | { |
| @@ -564,7 +606,7 @@ size_t rpc_max_payload(struct rpc_clnt *clnt) | |||
| 564 | { | 606 | { |
| 565 | return clnt->cl_xprt->max_payload; | 607 | return clnt->cl_xprt->max_payload; |
| 566 | } | 608 | } |
| 567 | EXPORT_SYMBOL(rpc_max_payload); | 609 | EXPORT_SYMBOL_GPL(rpc_max_payload); |
| 568 | 610 | ||
| 569 | /** | 611 | /** |
| 570 | * rpc_force_rebind - force transport to check that remote port is unchanged | 612 | * rpc_force_rebind - force transport to check that remote port is unchanged |
| @@ -574,9 +616,9 @@ EXPORT_SYMBOL(rpc_max_payload); | |||
| 574 | void rpc_force_rebind(struct rpc_clnt *clnt) | 616 | void rpc_force_rebind(struct rpc_clnt *clnt) |
| 575 | { | 617 | { |
| 576 | if (clnt->cl_autobind) | 618 | if (clnt->cl_autobind) |
| 577 | clnt->cl_port = 0; | 619 | xprt_clear_bound(clnt->cl_xprt); |
| 578 | } | 620 | } |
| 579 | EXPORT_SYMBOL(rpc_force_rebind); | 621 | EXPORT_SYMBOL_GPL(rpc_force_rebind); |
| 580 | 622 | ||
| 581 | /* | 623 | /* |
| 582 | * Restart an (async) RPC call. Usually called from within the | 624 | * Restart an (async) RPC call. Usually called from within the |
| @@ -740,7 +782,7 @@ call_encode(struct rpc_task *task) | |||
| 740 | struct xdr_buf *rcvbuf = &req->rq_rcv_buf; | 782 | struct xdr_buf *rcvbuf = &req->rq_rcv_buf; |
| 741 | unsigned int bufsiz; | 783 | unsigned int bufsiz; |
| 742 | kxdrproc_t encode; | 784 | kxdrproc_t encode; |
| 743 | u32 *p; | 785 | __be32 *p; |
| 744 | 786 | ||
| 745 | dprintk("RPC: %4d call_encode (status %d)\n", | 787 | dprintk("RPC: %4d call_encode (status %d)\n", |
| 746 | task->tk_pid, task->tk_status); | 788 | task->tk_pid, task->tk_status); |
| @@ -785,16 +827,16 @@ call_encode(struct rpc_task *task) | |||
| 785 | static void | 827 | static void |
| 786 | call_bind(struct rpc_task *task) | 828 | call_bind(struct rpc_task *task) |
| 787 | { | 829 | { |
| 788 | struct rpc_clnt *clnt = task->tk_client; | 830 | struct rpc_xprt *xprt = task->tk_xprt; |
| 789 | 831 | ||
| 790 | dprintk("RPC: %4d call_bind (status %d)\n", | 832 | dprintk("RPC: %4d call_bind (status %d)\n", |
| 791 | task->tk_pid, task->tk_status); | 833 | task->tk_pid, task->tk_status); |
| 792 | 834 | ||
| 793 | task->tk_action = call_connect; | 835 | task->tk_action = call_connect; |
| 794 | if (!clnt->cl_port) { | 836 | if (!xprt_bound(xprt)) { |
| 795 | task->tk_action = call_bind_status; | 837 | task->tk_action = call_bind_status; |
| 796 | task->tk_timeout = task->tk_xprt->bind_timeout; | 838 | task->tk_timeout = xprt->bind_timeout; |
| 797 | rpc_getport(task, clnt); | 839 | xprt->ops->rpcbind(task); |
| 798 | } | 840 | } |
| 799 | } | 841 | } |
| 800 | 842 | ||
| @@ -819,15 +861,11 @@ call_bind_status(struct rpc_task *task) | |||
| 819 | dprintk("RPC: %4d remote rpcbind: RPC program/version unavailable\n", | 861 | dprintk("RPC: %4d remote rpcbind: RPC program/version unavailable\n", |
| 820 | task->tk_pid); | 862 | task->tk_pid); |
| 821 | rpc_delay(task, 3*HZ); | 863 | rpc_delay(task, 3*HZ); |
| 822 | goto retry_bind; | 864 | goto retry_timeout; |
| 823 | case -ETIMEDOUT: | 865 | case -ETIMEDOUT: |
| 824 | dprintk("RPC: %4d rpcbind request timed out\n", | 866 | dprintk("RPC: %4d rpcbind request timed out\n", |
| 825 | task->tk_pid); | 867 | task->tk_pid); |
| 826 | if (RPC_IS_SOFT(task)) { | 868 | goto retry_timeout; |
| 827 | status = -EIO; | ||
| 828 | break; | ||
| 829 | } | ||
| 830 | goto retry_bind; | ||
| 831 | case -EPFNOSUPPORT: | 869 | case -EPFNOSUPPORT: |
| 832 | dprintk("RPC: %4d remote rpcbind service unavailable\n", | 870 | dprintk("RPC: %4d remote rpcbind service unavailable\n", |
| 833 | task->tk_pid); | 871 | task->tk_pid); |
| @@ -840,16 +878,13 @@ call_bind_status(struct rpc_task *task) | |||
| 840 | dprintk("RPC: %4d unrecognized rpcbind error (%d)\n", | 878 | dprintk("RPC: %4d unrecognized rpcbind error (%d)\n", |
| 841 | task->tk_pid, -task->tk_status); | 879 | task->tk_pid, -task->tk_status); |
| 842 | status = -EIO; | 880 | status = -EIO; |
| 843 | break; | ||
| 844 | } | 881 | } |
| 845 | 882 | ||
| 846 | rpc_exit(task, status); | 883 | rpc_exit(task, status); |
| 847 | return; | 884 | return; |
| 848 | 885 | ||
| 849 | retry_bind: | 886 | retry_timeout: |
| 850 | task->tk_status = 0; | 887 | task->tk_action = call_timeout; |
| 851 | task->tk_action = call_bind; | ||
| 852 | return; | ||
| 853 | } | 888 | } |
| 854 | 889 | ||
| 855 | /* | 890 | /* |
| @@ -897,14 +932,16 @@ call_connect_status(struct rpc_task *task) | |||
| 897 | 932 | ||
| 898 | switch (status) { | 933 | switch (status) { |
| 899 | case -ENOTCONN: | 934 | case -ENOTCONN: |
| 900 | case -ETIMEDOUT: | ||
| 901 | case -EAGAIN: | 935 | case -EAGAIN: |
| 902 | task->tk_action = call_bind; | 936 | task->tk_action = call_bind; |
| 903 | break; | 937 | if (!RPC_IS_SOFT(task)) |
| 904 | default: | 938 | return; |
| 905 | rpc_exit(task, -EIO); | 939 | /* if soft mounted, test if we've timed out */ |
| 906 | break; | 940 | case -ETIMEDOUT: |
| 941 | task->tk_action = call_timeout; | ||
| 942 | return; | ||
| 907 | } | 943 | } |
| 944 | rpc_exit(task, -EIO); | ||
| 908 | } | 945 | } |
| 909 | 946 | ||
| 910 | /* | 947 | /* |
| @@ -922,26 +959,43 @@ call_transmit(struct rpc_task *task) | |||
| 922 | task->tk_status = xprt_prepare_transmit(task); | 959 | task->tk_status = xprt_prepare_transmit(task); |
| 923 | if (task->tk_status != 0) | 960 | if (task->tk_status != 0) |
| 924 | return; | 961 | return; |
| 962 | task->tk_action = call_transmit_status; | ||
| 925 | /* Encode here so that rpcsec_gss can use correct sequence number. */ | 963 | /* Encode here so that rpcsec_gss can use correct sequence number. */ |
| 926 | if (rpc_task_need_encode(task)) { | 964 | if (rpc_task_need_encode(task)) { |
| 927 | task->tk_rqstp->rq_bytes_sent = 0; | 965 | BUG_ON(task->tk_rqstp->rq_bytes_sent != 0); |
| 928 | call_encode(task); | 966 | call_encode(task); |
| 929 | /* Did the encode result in an error condition? */ | 967 | /* Did the encode result in an error condition? */ |
| 930 | if (task->tk_status != 0) | 968 | if (task->tk_status != 0) |
| 931 | goto out_nosend; | 969 | return; |
| 932 | } | 970 | } |
| 933 | task->tk_action = call_transmit_status; | ||
| 934 | xprt_transmit(task); | 971 | xprt_transmit(task); |
| 935 | if (task->tk_status < 0) | 972 | if (task->tk_status < 0) |
| 936 | return; | 973 | return; |
| 937 | if (!task->tk_msg.rpc_proc->p_decode) { | 974 | /* |
| 938 | task->tk_action = rpc_exit_task; | 975 | * On success, ensure that we call xprt_end_transmit() before sleeping |
| 939 | rpc_wake_up_task(task); | 976 | * in order to allow access to the socket to other RPC requests. |
| 940 | } | 977 | */ |
| 941 | return; | 978 | call_transmit_status(task); |
| 942 | out_nosend: | 979 | if (task->tk_msg.rpc_proc->p_decode != NULL) |
| 943 | /* release socket write lock before attempting to handle error */ | 980 | return; |
| 944 | xprt_abort_transmit(task); | 981 | task->tk_action = rpc_exit_task; |
| 982 | rpc_wake_up_task(task); | ||
| 983 | } | ||
| 984 | |||
| 985 | /* | ||
| 986 | * 5a. Handle cleanup after a transmission | ||
| 987 | */ | ||
| 988 | static void | ||
| 989 | call_transmit_status(struct rpc_task *task) | ||
| 990 | { | ||
| 991 | task->tk_action = call_status; | ||
| 992 | /* | ||
| 993 | * Special case: if we've been waiting on the socket's write_space() | ||
| 994 | * callback, then don't call xprt_end_transmit(). | ||
| 995 | */ | ||
| 996 | if (task->tk_status == -EAGAIN) | ||
| 997 | return; | ||
| 998 | xprt_end_transmit(task); | ||
| 945 | rpc_task_force_reencode(task); | 999 | rpc_task_force_reencode(task); |
| 946 | } | 1000 | } |
| 947 | 1001 | ||
| @@ -969,6 +1023,14 @@ call_status(struct rpc_task *task) | |||
| 969 | 1023 | ||
| 970 | task->tk_status = 0; | 1024 | task->tk_status = 0; |
| 971 | switch(status) { | 1025 | switch(status) { |
| 1026 | case -EHOSTDOWN: | ||
| 1027 | case -EHOSTUNREACH: | ||
| 1028 | case -ENETUNREACH: | ||
| 1029 | /* | ||
| 1030 | * Delay any retries for 3 seconds, then handle as if it | ||
| 1031 | * were a timeout. | ||
| 1032 | */ | ||
| 1033 | rpc_delay(task, 3*HZ); | ||
| 972 | case -ETIMEDOUT: | 1034 | case -ETIMEDOUT: |
| 973 | task->tk_action = call_timeout; | 1035 | task->tk_action = call_timeout; |
| 974 | break; | 1036 | break; |
| @@ -988,23 +1050,11 @@ call_status(struct rpc_task *task) | |||
| 988 | printk("%s: RPC call returned error %d\n", | 1050 | printk("%s: RPC call returned error %d\n", |
| 989 | clnt->cl_protname, -status); | 1051 | clnt->cl_protname, -status); |
| 990 | rpc_exit(task, status); | 1052 | rpc_exit(task, status); |
| 991 | break; | ||
| 992 | } | 1053 | } |
| 993 | } | 1054 | } |
| 994 | 1055 | ||
| 995 | /* | 1056 | /* |
| 996 | * 6a. Handle transmission errors. | 1057 | * 6a. Handle RPC timeout |
| 997 | */ | ||
| 998 | static void | ||
| 999 | call_transmit_status(struct rpc_task *task) | ||
| 1000 | { | ||
| 1001 | if (task->tk_status != -EAGAIN) | ||
| 1002 | rpc_task_force_reencode(task); | ||
| 1003 | call_status(task); | ||
| 1004 | } | ||
| 1005 | |||
| 1006 | /* | ||
| 1007 | * 6b. Handle RPC timeout | ||
| 1008 | * We do not release the request slot, so we keep using the | 1058 | * We do not release the request slot, so we keep using the |
| 1009 | * same XID for all retransmits. | 1059 | * same XID for all retransmits. |
| 1010 | */ | 1060 | */ |
| @@ -1050,7 +1100,7 @@ call_decode(struct rpc_task *task) | |||
| 1050 | struct rpc_clnt *clnt = task->tk_client; | 1100 | struct rpc_clnt *clnt = task->tk_client; |
| 1051 | struct rpc_rqst *req = task->tk_rqstp; | 1101 | struct rpc_rqst *req = task->tk_rqstp; |
| 1052 | kxdrproc_t decode = task->tk_msg.rpc_proc->p_decode; | 1102 | kxdrproc_t decode = task->tk_msg.rpc_proc->p_decode; |
| 1053 | u32 *p; | 1103 | __be32 *p; |
| 1054 | 1104 | ||
| 1055 | dprintk("RPC: %4d call_decode (status %d)\n", | 1105 | dprintk("RPC: %4d call_decode (status %d)\n", |
| 1056 | task->tk_pid, task->tk_status); | 1106 | task->tk_pid, task->tk_status); |
| @@ -1067,10 +1117,10 @@ call_decode(struct rpc_task *task) | |||
| 1067 | clnt->cl_stats->rpcretrans++; | 1117 | clnt->cl_stats->rpcretrans++; |
| 1068 | goto out_retry; | 1118 | goto out_retry; |
| 1069 | } | 1119 | } |
| 1070 | printk(KERN_WARNING "%s: too small RPC reply size (%d bytes)\n", | 1120 | dprintk("%s: too small RPC reply size (%d bytes)\n", |
| 1071 | clnt->cl_protname, task->tk_status); | 1121 | clnt->cl_protname, task->tk_status); |
| 1072 | rpc_exit(task, -EIO); | 1122 | task->tk_action = call_timeout; |
| 1073 | return; | 1123 | goto out_retry; |
| 1074 | } | 1124 | } |
| 1075 | 1125 | ||
| 1076 | /* | 1126 | /* |
| @@ -1147,12 +1197,12 @@ call_refreshresult(struct rpc_task *task) | |||
| 1147 | /* | 1197 | /* |
| 1148 | * Call header serialization | 1198 | * Call header serialization |
| 1149 | */ | 1199 | */ |
| 1150 | static u32 * | 1200 | static __be32 * |
| 1151 | call_header(struct rpc_task *task) | 1201 | call_header(struct rpc_task *task) |
| 1152 | { | 1202 | { |
| 1153 | struct rpc_clnt *clnt = task->tk_client; | 1203 | struct rpc_clnt *clnt = task->tk_client; |
| 1154 | struct rpc_rqst *req = task->tk_rqstp; | 1204 | struct rpc_rqst *req = task->tk_rqstp; |
| 1155 | u32 *p = req->rq_svec[0].iov_base; | 1205 | __be32 *p = req->rq_svec[0].iov_base; |
| 1156 | 1206 | ||
| 1157 | /* FIXME: check buffer size? */ | 1207 | /* FIXME: check buffer size? */ |
| 1158 | 1208 | ||
| @@ -1171,14 +1221,26 @@ call_header(struct rpc_task *task) | |||
| 1171 | /* | 1221 | /* |
| 1172 | * Reply header verification | 1222 | * Reply header verification |
| 1173 | */ | 1223 | */ |
| 1174 | static u32 * | 1224 | static __be32 * |
| 1175 | call_verify(struct rpc_task *task) | 1225 | call_verify(struct rpc_task *task) |
| 1176 | { | 1226 | { |
| 1177 | struct kvec *iov = &task->tk_rqstp->rq_rcv_buf.head[0]; | 1227 | struct kvec *iov = &task->tk_rqstp->rq_rcv_buf.head[0]; |
| 1178 | int len = task->tk_rqstp->rq_rcv_buf.len >> 2; | 1228 | int len = task->tk_rqstp->rq_rcv_buf.len >> 2; |
| 1179 | u32 *p = iov->iov_base, n; | 1229 | __be32 *p = iov->iov_base; |
| 1230 | u32 n; | ||
| 1180 | int error = -EACCES; | 1231 | int error = -EACCES; |
| 1181 | 1232 | ||
| 1233 | if ((task->tk_rqstp->rq_rcv_buf.len & 3) != 0) { | ||
| 1234 | /* RFC-1014 says that the representation of XDR data must be a | ||
| 1235 | * multiple of four bytes | ||
| 1236 | * - if it isn't pointer subtraction in the NFS client may give | ||
| 1237 | * undefined results | ||
| 1238 | */ | ||
| 1239 | printk(KERN_WARNING | ||
| 1240 | "call_verify: XDR representation not a multiple of" | ||
| 1241 | " 4 bytes: 0x%x\n", task->tk_rqstp->rq_rcv_buf.len); | ||
| 1242 | goto out_eio; | ||
| 1243 | } | ||
| 1182 | if ((len -= 3) < 0) | 1244 | if ((len -= 3) < 0) |
| 1183 | goto out_overflow; | 1245 | goto out_overflow; |
| 1184 | p += 1; /* skip XID */ | 1246 | p += 1; /* skip XID */ |
| @@ -1242,7 +1304,7 @@ call_verify(struct rpc_task *task) | |||
| 1242 | printk(KERN_WARNING "call_verify: auth check failed\n"); | 1304 | printk(KERN_WARNING "call_verify: auth check failed\n"); |
| 1243 | goto out_garbage; /* bad verifier, retry */ | 1305 | goto out_garbage; /* bad verifier, retry */ |
| 1244 | } | 1306 | } |
| 1245 | len = p - (u32 *)iov->iov_base - 1; | 1307 | len = p - (__be32 *)iov->iov_base - 1; |
| 1246 | if (len < 0) | 1308 | if (len < 0) |
| 1247 | goto out_overflow; | 1309 | goto out_overflow; |
| 1248 | switch ((n = ntohl(*p++))) { | 1310 | switch ((n = ntohl(*p++))) { |
| @@ -1297,12 +1359,12 @@ out_overflow: | |||
| 1297 | goto out_garbage; | 1359 | goto out_garbage; |
| 1298 | } | 1360 | } |
| 1299 | 1361 | ||
| 1300 | static int rpcproc_encode_null(void *rqstp, u32 *data, void *obj) | 1362 | static int rpcproc_encode_null(void *rqstp, __be32 *data, void *obj) |
| 1301 | { | 1363 | { |
| 1302 | return 0; | 1364 | return 0; |
| 1303 | } | 1365 | } |
| 1304 | 1366 | ||
| 1305 | static int rpcproc_decode_null(void *rqstp, u32 *data, void *obj) | 1367 | static int rpcproc_decode_null(void *rqstp, __be32 *data, void *obj) |
| 1306 | { | 1368 | { |
| 1307 | return 0; | 1369 | return 0; |
| 1308 | } | 1370 | } |
