diff options
Diffstat (limited to 'net/sunrpc/clnt.c')
-rw-r--r-- | net/sunrpc/clnt.c | 194 |
1 files changed, 121 insertions, 73 deletions
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 3e19d321067a..084a0ad5c64e 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -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; |
@@ -147,16 +137,12 @@ rpc_new_client(struct rpc_xprt *xprt, char *servname, | |||
147 | clnt->cl_procinfo = version->procs; | 137 | clnt->cl_procinfo = version->procs; |
148 | clnt->cl_maxproc = version->nrprocs; | 138 | clnt->cl_maxproc = version->nrprocs; |
149 | clnt->cl_protname = program->name; | 139 | clnt->cl_protname = program->name; |
150 | clnt->cl_pmap = &clnt->cl_pmap_default; | ||
151 | clnt->cl_port = xprt->addr.sin_port; | ||
152 | clnt->cl_prog = program->number; | 140 | clnt->cl_prog = program->number; |
153 | clnt->cl_vers = version->number; | 141 | clnt->cl_vers = version->number; |
154 | clnt->cl_prot = xprt->prot; | ||
155 | clnt->cl_stats = program->stats; | 142 | clnt->cl_stats = program->stats; |
156 | clnt->cl_metrics = rpc_alloc_iostats(clnt); | 143 | clnt->cl_metrics = rpc_alloc_iostats(clnt); |
157 | rpc_init_wait_queue(&clnt->cl_pmap_default.pm_bindwait, "bindwait"); | ||
158 | 144 | ||
159 | if (!clnt->cl_port) | 145 | if (!xprt_bound(clnt->cl_xprt)) |
160 | clnt->cl_autobind = 1; | 146 | clnt->cl_autobind = 1; |
161 | 147 | ||
162 | clnt->cl_rtt = &clnt->cl_rtt_default; | 148 | clnt->cl_rtt = &clnt->cl_rtt_default; |
@@ -191,40 +177,71 @@ out_no_path: | |||
191 | kfree(clnt->cl_server); | 177 | kfree(clnt->cl_server); |
192 | kfree(clnt); | 178 | kfree(clnt); |
193 | out_err: | 179 | out_err: |
194 | xprt_destroy(xprt); | 180 | xprt_put(xprt); |
195 | out_no_xprt: | 181 | out_no_xprt: |
196 | return ERR_PTR(err); | 182 | return ERR_PTR(err); |
197 | } | 183 | } |
198 | 184 | ||
199 | /** | 185 | /* |
200 | * Create an RPC client | 186 | * rpc_create - create an RPC client and transport with one call |
201 | * @xprt - pointer to xprt struct | 187 | * @args: rpc_clnt create argument structure |
202 | * @servname - name of server | ||
203 | * @info - rpc_program | ||
204 | * @version - rpc_program version | ||
205 | * @authflavor - rpc_auth flavour to use | ||
206 | * | 188 | * |
207 | * Creates an RPC client structure, then pings the server in order to | 189 | * Creates and initializes an RPC transport and an RPC client. |
208 | * determine if it is up, and if it supports this program and version. | ||
209 | * | 190 | * |
210 | * 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 |
211 | * 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. | ||
212 | */ | 194 | */ |
213 | struct rpc_clnt *rpc_create_client(struct rpc_xprt *xprt, char *servname, | 195 | struct rpc_clnt *rpc_create(struct rpc_create_args *args) |
214 | struct rpc_program *info, u32 version, rpc_authflavor_t authflavor) | ||
215 | { | 196 | { |
197 | struct rpc_xprt *xprt; | ||
216 | struct rpc_clnt *clnt; | 198 | struct rpc_clnt *clnt; |
217 | int err; | 199 | |
218 | 200 | xprt = xprt_create_transport(args->protocol, args->address, | |
219 | 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); | ||
220 | if (IS_ERR(clnt)) | 220 | if (IS_ERR(clnt)) |
221 | return clnt; | 221 | return clnt; |
222 | err = rpc_ping(clnt, RPC_TASK_SOFT|RPC_TASK_NOINTR); | 222 | |
223 | if (err == 0) | 223 | if (!(args->flags & RPC_CLNT_CREATE_NOPING)) { |
224 | return clnt; | 224 | int err = rpc_ping(clnt, RPC_TASK_SOFT|RPC_TASK_NOINTR); |
225 | rpc_shutdown_client(clnt); | 225 | if (err != 0) { |
226 | 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; | ||
227 | } | 243 | } |
244 | EXPORT_SYMBOL_GPL(rpc_create); | ||
228 | 245 | ||
229 | /* | 246 | /* |
230 | * 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 |
@@ -244,8 +261,7 @@ rpc_clone_client(struct rpc_clnt *clnt) | |||
244 | atomic_set(&new->cl_users, 0); | 261 | atomic_set(&new->cl_users, 0); |
245 | new->cl_parent = clnt; | 262 | new->cl_parent = clnt; |
246 | atomic_inc(&clnt->cl_count); | 263 | atomic_inc(&clnt->cl_count); |
247 | /* Duplicate portmapper */ | 264 | new->cl_xprt = xprt_get(clnt->cl_xprt); |
248 | rpc_init_wait_queue(&new->cl_pmap_default.pm_bindwait, "bindwait"); | ||
249 | /* Turn off autobind on clones */ | 265 | /* Turn off autobind on clones */ |
250 | new->cl_autobind = 0; | 266 | new->cl_autobind = 0; |
251 | new->cl_oneshot = 0; | 267 | new->cl_oneshot = 0; |
@@ -255,8 +271,7 @@ rpc_clone_client(struct rpc_clnt *clnt) | |||
255 | 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); |
256 | if (new->cl_auth) | 272 | if (new->cl_auth) |
257 | atomic_inc(&new->cl_auth->au_count); | 273 | atomic_inc(&new->cl_auth->au_count); |
258 | new->cl_pmap = &new->cl_pmap_default; | 274 | new->cl_metrics = rpc_alloc_iostats(clnt); |
259 | new->cl_metrics = rpc_alloc_iostats(clnt); | ||
260 | return new; | 275 | return new; |
261 | out_no_clnt: | 276 | out_no_clnt: |
262 | printk(KERN_INFO "RPC: out of memory in %s\n", __FUNCTION__); | 277 | printk(KERN_INFO "RPC: out of memory in %s\n", __FUNCTION__); |
@@ -323,15 +338,12 @@ rpc_destroy_client(struct rpc_clnt *clnt) | |||
323 | rpc_rmdir(clnt->cl_dentry); | 338 | rpc_rmdir(clnt->cl_dentry); |
324 | rpc_put_mount(); | 339 | rpc_put_mount(); |
325 | } | 340 | } |
326 | if (clnt->cl_xprt) { | ||
327 | xprt_destroy(clnt->cl_xprt); | ||
328 | clnt->cl_xprt = NULL; | ||
329 | } | ||
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; |
346 | xprt_put(clnt->cl_xprt); | ||
335 | kfree(clnt); | 347 | kfree(clnt); |
336 | return 0; | 348 | return 0; |
337 | } | 349 | } |
@@ -540,6 +552,40 @@ rpc_call_setup(struct rpc_task *task, struct rpc_message *msg, int flags) | |||
540 | task->tk_action = rpc_exit_task; | 552 | task->tk_action = rpc_exit_task; |
541 | } | 553 | } |
542 | 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 | |||
543 | void | 589 | void |
544 | 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) |
545 | { | 591 | { |
@@ -560,7 +606,7 @@ size_t rpc_max_payload(struct rpc_clnt *clnt) | |||
560 | { | 606 | { |
561 | return clnt->cl_xprt->max_payload; | 607 | return clnt->cl_xprt->max_payload; |
562 | } | 608 | } |
563 | EXPORT_SYMBOL(rpc_max_payload); | 609 | EXPORT_SYMBOL_GPL(rpc_max_payload); |
564 | 610 | ||
565 | /** | 611 | /** |
566 | * 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 |
@@ -570,9 +616,9 @@ EXPORT_SYMBOL(rpc_max_payload); | |||
570 | void rpc_force_rebind(struct rpc_clnt *clnt) | 616 | void rpc_force_rebind(struct rpc_clnt *clnt) |
571 | { | 617 | { |
572 | if (clnt->cl_autobind) | 618 | if (clnt->cl_autobind) |
573 | clnt->cl_port = 0; | 619 | xprt_clear_bound(clnt->cl_xprt); |
574 | } | 620 | } |
575 | EXPORT_SYMBOL(rpc_force_rebind); | 621 | EXPORT_SYMBOL_GPL(rpc_force_rebind); |
576 | 622 | ||
577 | /* | 623 | /* |
578 | * Restart an (async) RPC call. Usually called from within the | 624 | * Restart an (async) RPC call. Usually called from within the |
@@ -781,16 +827,16 @@ call_encode(struct rpc_task *task) | |||
781 | static void | 827 | static void |
782 | call_bind(struct rpc_task *task) | 828 | call_bind(struct rpc_task *task) |
783 | { | 829 | { |
784 | struct rpc_clnt *clnt = task->tk_client; | 830 | struct rpc_xprt *xprt = task->tk_xprt; |
785 | 831 | ||
786 | dprintk("RPC: %4d call_bind (status %d)\n", | 832 | dprintk("RPC: %4d call_bind (status %d)\n", |
787 | task->tk_pid, task->tk_status); | 833 | task->tk_pid, task->tk_status); |
788 | 834 | ||
789 | task->tk_action = call_connect; | 835 | task->tk_action = call_connect; |
790 | if (!clnt->cl_port) { | 836 | if (!xprt_bound(xprt)) { |
791 | task->tk_action = call_bind_status; | 837 | task->tk_action = call_bind_status; |
792 | task->tk_timeout = task->tk_xprt->bind_timeout; | 838 | task->tk_timeout = xprt->bind_timeout; |
793 | rpc_getport(task, clnt); | 839 | xprt->ops->rpcbind(task); |
794 | } | 840 | } |
795 | } | 841 | } |
796 | 842 | ||
@@ -815,15 +861,11 @@ call_bind_status(struct rpc_task *task) | |||
815 | dprintk("RPC: %4d remote rpcbind: RPC program/version unavailable\n", | 861 | dprintk("RPC: %4d remote rpcbind: RPC program/version unavailable\n", |
816 | task->tk_pid); | 862 | task->tk_pid); |
817 | rpc_delay(task, 3*HZ); | 863 | rpc_delay(task, 3*HZ); |
818 | goto retry_bind; | 864 | goto retry_timeout; |
819 | case -ETIMEDOUT: | 865 | case -ETIMEDOUT: |
820 | dprintk("RPC: %4d rpcbind request timed out\n", | 866 | dprintk("RPC: %4d rpcbind request timed out\n", |
821 | task->tk_pid); | 867 | task->tk_pid); |
822 | if (RPC_IS_SOFT(task)) { | 868 | goto retry_timeout; |
823 | status = -EIO; | ||
824 | break; | ||
825 | } | ||
826 | goto retry_bind; | ||
827 | case -EPFNOSUPPORT: | 869 | case -EPFNOSUPPORT: |
828 | dprintk("RPC: %4d remote rpcbind service unavailable\n", | 870 | dprintk("RPC: %4d remote rpcbind service unavailable\n", |
829 | task->tk_pid); | 871 | task->tk_pid); |
@@ -836,16 +878,13 @@ call_bind_status(struct rpc_task *task) | |||
836 | dprintk("RPC: %4d unrecognized rpcbind error (%d)\n", | 878 | dprintk("RPC: %4d unrecognized rpcbind error (%d)\n", |
837 | task->tk_pid, -task->tk_status); | 879 | task->tk_pid, -task->tk_status); |
838 | status = -EIO; | 880 | status = -EIO; |
839 | break; | ||
840 | } | 881 | } |
841 | 882 | ||
842 | rpc_exit(task, status); | 883 | rpc_exit(task, status); |
843 | return; | 884 | return; |
844 | 885 | ||
845 | retry_bind: | 886 | retry_timeout: |
846 | task->tk_status = 0; | 887 | task->tk_action = call_timeout; |
847 | task->tk_action = call_bind; | ||
848 | return; | ||
849 | } | 888 | } |
850 | 889 | ||
851 | /* | 890 | /* |
@@ -893,14 +932,16 @@ call_connect_status(struct rpc_task *task) | |||
893 | 932 | ||
894 | switch (status) { | 933 | switch (status) { |
895 | case -ENOTCONN: | 934 | case -ENOTCONN: |
896 | case -ETIMEDOUT: | ||
897 | case -EAGAIN: | 935 | case -EAGAIN: |
898 | task->tk_action = call_bind; | 936 | task->tk_action = call_bind; |
899 | break; | 937 | if (!RPC_IS_SOFT(task)) |
900 | default: | 938 | return; |
901 | rpc_exit(task, -EIO); | 939 | /* if soft mounted, test if we've timed out */ |
902 | break; | 940 | case -ETIMEDOUT: |
941 | task->tk_action = call_timeout; | ||
942 | return; | ||
903 | } | 943 | } |
944 | rpc_exit(task, -EIO); | ||
904 | } | 945 | } |
905 | 946 | ||
906 | /* | 947 | /* |
@@ -982,6 +1023,14 @@ call_status(struct rpc_task *task) | |||
982 | 1023 | ||
983 | task->tk_status = 0; | 1024 | task->tk_status = 0; |
984 | 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); | ||
985 | case -ETIMEDOUT: | 1034 | case -ETIMEDOUT: |
986 | task->tk_action = call_timeout; | 1035 | task->tk_action = call_timeout; |
987 | break; | 1036 | break; |
@@ -1001,7 +1050,6 @@ call_status(struct rpc_task *task) | |||
1001 | printk("%s: RPC call returned error %d\n", | 1050 | printk("%s: RPC call returned error %d\n", |
1002 | clnt->cl_protname, -status); | 1051 | clnt->cl_protname, -status); |
1003 | rpc_exit(task, status); | 1052 | rpc_exit(task, status); |
1004 | break; | ||
1005 | } | 1053 | } |
1006 | } | 1054 | } |
1007 | 1055 | ||
@@ -1069,10 +1117,10 @@ call_decode(struct rpc_task *task) | |||
1069 | clnt->cl_stats->rpcretrans++; | 1117 | clnt->cl_stats->rpcretrans++; |
1070 | goto out_retry; | 1118 | goto out_retry; |
1071 | } | 1119 | } |
1072 | printk(KERN_WARNING "%s: too small RPC reply size (%d bytes)\n", | 1120 | dprintk("%s: too small RPC reply size (%d bytes)\n", |
1073 | clnt->cl_protname, task->tk_status); | 1121 | clnt->cl_protname, task->tk_status); |
1074 | rpc_exit(task, -EIO); | 1122 | task->tk_action = call_timeout; |
1075 | return; | 1123 | goto out_retry; |
1076 | } | 1124 | } |
1077 | 1125 | ||
1078 | /* | 1126 | /* |