Deleted Added
full compact
clnt_vc.c (177685) clnt_vc.c (180025)
1/* $NetBSD: clnt_vc.c,v 1.4 2000/07/14 08:40:42 fvdl Exp $ */
2
3/*
4 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
5 * unrestricted use provided that this legend is included on all tape
6 * media and as a part of the software program in whole or part. Users
7 * may copy or modify Sun RPC without charge, but are not authorized
8 * to license or distribute it to anyone else except as part of a product or

--- 21 unchanged lines hidden (view full) ---

30 */
31
32#if defined(LIBC_SCCS) && !defined(lint)
33static char *sccsid2 = "@(#)clnt_tcp.c 1.37 87/10/05 Copyr 1984 Sun Micro";
34static char *sccsid = "@(#)clnt_tcp.c 2.2 88/08/01 4.0 RPCSRC";
35static char sccsid3[] = "@(#)clnt_vc.c 1.19 89/03/16 Copyr 1988 Sun Micro";
36#endif
37#include <sys/cdefs.h>
1/* $NetBSD: clnt_vc.c,v 1.4 2000/07/14 08:40:42 fvdl Exp $ */
2
3/*
4 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
5 * unrestricted use provided that this legend is included on all tape
6 * media and as a part of the software program in whole or part. Users
7 * may copy or modify Sun RPC without charge, but are not authorized
8 * to license or distribute it to anyone else except as part of a product or

--- 21 unchanged lines hidden (view full) ---

30 */
31
32#if defined(LIBC_SCCS) && !defined(lint)
33static char *sccsid2 = "@(#)clnt_tcp.c 1.37 87/10/05 Copyr 1984 Sun Micro";
34static char *sccsid = "@(#)clnt_tcp.c 2.2 88/08/01 4.0 RPCSRC";
35static char sccsid3[] = "@(#)clnt_vc.c 1.19 89/03/16 Copyr 1988 Sun Micro";
36#endif
37#include <sys/cdefs.h>
38__FBSDID("$FreeBSD: head/sys/rpc/clnt_vc.c 177685 2008-03-28 09:50:32Z dfr $");
38__FBSDID("$FreeBSD: head/sys/rpc/clnt_vc.c 180025 2008-06-26 10:21:54Z dfr $");
39
40/*
41 * clnt_tcp.c, Implements a TCP/IP based, client side RPC.
42 *
43 * Copyright (C) 1984, Sun Microsystems, Inc.
44 *
45 * TCP based RPC supports 'batched calls'.
46 * A sequence of calls may be batched-up in a send buffer. The rpc call

--- 28 unchanged lines hidden (view full) ---

75
76#define MCALL_MSG_SIZE 24
77
78struct cmessage {
79 struct cmsghdr cmsg;
80 struct cmsgcred cmcred;
81};
82
39
40/*
41 * clnt_tcp.c, Implements a TCP/IP based, client side RPC.
42 *
43 * Copyright (C) 1984, Sun Microsystems, Inc.
44 *
45 * TCP based RPC supports 'batched calls'.
46 * A sequence of calls may be batched-up in a send buffer. The rpc call

--- 28 unchanged lines hidden (view full) ---

75
76#define MCALL_MSG_SIZE 24
77
78struct cmessage {
79 struct cmsghdr cmsg;
80 struct cmsgcred cmcred;
81};
82
83static enum clnt_stat clnt_vc_call(CLIENT *, rpcproc_t, xdrproc_t, void *,
84 xdrproc_t, void *, struct timeval);
83static enum clnt_stat clnt_vc_call(CLIENT *, struct rpc_callextra *,
84 rpcproc_t, xdrproc_t, void *, xdrproc_t, void *, struct timeval);
85static void clnt_vc_geterr(CLIENT *, struct rpc_err *);
86static bool_t clnt_vc_freeres(CLIENT *, xdrproc_t, void *);
87static void clnt_vc_abort(CLIENT *);
88static bool_t clnt_vc_control(CLIENT *, u_int, void *);
89static void clnt_vc_destroy(CLIENT *);
90static bool_t time_not_ok(struct timeval *);
91static void clnt_vc_soupcall(struct socket *so, void *arg, int waitflag);
92
93static struct clnt_ops clnt_vc_ops = {
94 .cl_call = clnt_vc_call,
95 .cl_abort = clnt_vc_abort,
96 .cl_geterr = clnt_vc_geterr,
97 .cl_freeres = clnt_vc_freeres,
98 .cl_destroy = clnt_vc_destroy,
99 .cl_control = clnt_vc_control
100};
101
102/*
85static void clnt_vc_geterr(CLIENT *, struct rpc_err *);
86static bool_t clnt_vc_freeres(CLIENT *, xdrproc_t, void *);
87static void clnt_vc_abort(CLIENT *);
88static bool_t clnt_vc_control(CLIENT *, u_int, void *);
89static void clnt_vc_destroy(CLIENT *);
90static bool_t time_not_ok(struct timeval *);
91static void clnt_vc_soupcall(struct socket *so, void *arg, int waitflag);
92
93static struct clnt_ops clnt_vc_ops = {
94 .cl_call = clnt_vc_call,
95 .cl_abort = clnt_vc_abort,
96 .cl_geterr = clnt_vc_geterr,
97 .cl_freeres = clnt_vc_freeres,
98 .cl_destroy = clnt_vc_destroy,
99 .cl_control = clnt_vc_control
100};
101
102/*
103 * A pending RPC request which awaits a reply.
103 * A pending RPC request which awaits a reply. Requests which have
104 * received their reply will have cr_xid set to zero and cr_mrep to
105 * the mbuf chain of the reply.
104 */
105struct ct_request {
106 TAILQ_ENTRY(ct_request) cr_link;
107 uint32_t cr_xid; /* XID of request */
108 struct mbuf *cr_mrep; /* reply received by upcall */
109 int cr_error; /* any error from upcall */
110};
111
112TAILQ_HEAD(ct_request_list, ct_request);
113
114struct ct_data {
115 struct mtx ct_lock;
106 */
107struct ct_request {
108 TAILQ_ENTRY(ct_request) cr_link;
109 uint32_t cr_xid; /* XID of request */
110 struct mbuf *cr_mrep; /* reply received by upcall */
111 int cr_error; /* any error from upcall */
112};
113
114TAILQ_HEAD(ct_request_list, ct_request);
115
116struct ct_data {
117 struct mtx ct_lock;
118 int ct_threads; /* number of threads in clnt_vc_call */
119 bool_t ct_closing; /* TRUE if we are destroying client */
116 struct socket *ct_socket; /* connection socket */
117 bool_t ct_closeit; /* close it on destroy */
118 struct timeval ct_wait; /* wait interval in milliseconds */
119 struct sockaddr_storage ct_addr; /* remote addr */
120 struct rpc_err ct_error;
121 uint32_t ct_xid;
122 char ct_mcallc[MCALL_MSG_SIZE]; /* marshalled callmsg */
123 size_t ct_mpos; /* pos after marshal */

--- 32 unchanged lines hidden (view full) ---

156{
157 CLIENT *cl; /* client handle */
158 struct ct_data *ct = NULL; /* client handle */
159 struct timeval now;
160 struct rpc_msg call_msg;
161 static uint32_t disrupt;
162 struct __rpc_sockinfo si;
163 XDR xdrs;
120 struct socket *ct_socket; /* connection socket */
121 bool_t ct_closeit; /* close it on destroy */
122 struct timeval ct_wait; /* wait interval in milliseconds */
123 struct sockaddr_storage ct_addr; /* remote addr */
124 struct rpc_err ct_error;
125 uint32_t ct_xid;
126 char ct_mcallc[MCALL_MSG_SIZE]; /* marshalled callmsg */
127 size_t ct_mpos; /* pos after marshal */

--- 32 unchanged lines hidden (view full) ---

160{
161 CLIENT *cl; /* client handle */
162 struct ct_data *ct = NULL; /* client handle */
163 struct timeval now;
164 struct rpc_msg call_msg;
165 static uint32_t disrupt;
166 struct __rpc_sockinfo si;
167 XDR xdrs;
164 int error;
168 int error, interrupted;
165
166 if (disrupt == 0)
167 disrupt = (uint32_t)(long)raddr;
168
169 cl = (CLIENT *)mem_alloc(sizeof (*cl));
170 ct = (struct ct_data *)mem_alloc(sizeof (*ct));
171
172 mtx_init(&ct->ct_lock, "ct->ct_lock", NULL, MTX_DEF);
169
170 if (disrupt == 0)
171 disrupt = (uint32_t)(long)raddr;
172
173 cl = (CLIENT *)mem_alloc(sizeof (*cl));
174 ct = (struct ct_data *)mem_alloc(sizeof (*ct));
175
176 mtx_init(&ct->ct_lock, "ct->ct_lock", NULL, MTX_DEF);
177 ct->ct_threads = 0;
178 ct->ct_closing = FALSE;
173
174 if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) {
175 error = soconnect(so, raddr, curthread);
179
180 if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) {
181 error = soconnect(so, raddr, curthread);
182 SOCK_LOCK(so);
183 interrupted = 0;
184 while ((so->so_state & SS_ISCONNECTING)
185 && so->so_error == 0) {
186 error = msleep(&so->so_timeo, SOCK_MTX(so),
187 PSOCK | PCATCH, "connec", 0);
188 if (error) {
189 if (error == EINTR || error == ERESTART)
190 interrupted = 1;
191 break;
192 }
193 }
194 if (error == 0) {
195 error = so->so_error;
196 so->so_error = 0;
197 }
198 SOCK_UNLOCK(so);
176 if (error) {
199 if (error) {
200 if (!interrupted)
201 so->so_state &= ~SS_ISCONNECTING;
177 rpc_createerr.cf_stat = RPC_SYSTEMERROR;
178 rpc_createerr.cf_error.re_errno = error;
179 goto err;
180 }
181 }
182
183 if (!__rpc_socket2sockinfo(so, &si))
184 goto err;

--- 34 unchanged lines hidden (view full) ---

219 XDR_DESTROY(&xdrs);
220 ct->ct_waitchan = "rpcrecv";
221 ct->ct_waitflag = 0;
222
223 /*
224 * Create a client handle which uses xdrrec for serialization
225 * and authnone for authentication.
226 */
202 rpc_createerr.cf_stat = RPC_SYSTEMERROR;
203 rpc_createerr.cf_error.re_errno = error;
204 goto err;
205 }
206 }
207
208 if (!__rpc_socket2sockinfo(so, &si))
209 goto err;

--- 34 unchanged lines hidden (view full) ---

244 XDR_DESTROY(&xdrs);
245 ct->ct_waitchan = "rpcrecv";
246 ct->ct_waitflag = 0;
247
248 /*
249 * Create a client handle which uses xdrrec for serialization
250 * and authnone for authentication.
251 */
252 cl->cl_refs = 1;
227 cl->cl_ops = &clnt_vc_ops;
228 cl->cl_private = ct;
229 cl->cl_auth = authnone_create();
230 sendsz = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsz);
231 recvsz = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsz);
232
233 SOCKBUF_LOCK(&ct->ct_socket->so_rcv);
234 ct->ct_socket->so_upcallarg = ct;

--- 15 unchanged lines hidden (view full) ---

250 mem_free(cl, sizeof (CLIENT));
251 }
252 return ((CLIENT *)NULL);
253}
254
255static enum clnt_stat
256clnt_vc_call(
257 CLIENT *cl,
253 cl->cl_ops = &clnt_vc_ops;
254 cl->cl_private = ct;
255 cl->cl_auth = authnone_create();
256 sendsz = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsz);
257 recvsz = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsz);
258
259 SOCKBUF_LOCK(&ct->ct_socket->so_rcv);
260 ct->ct_socket->so_upcallarg = ct;

--- 15 unchanged lines hidden (view full) ---

276 mem_free(cl, sizeof (CLIENT));
277 }
278 return ((CLIENT *)NULL);
279}
280
281static enum clnt_stat
282clnt_vc_call(
283 CLIENT *cl,
284 struct rpc_callextra *ext,
258 rpcproc_t proc,
259 xdrproc_t xdr_args,
260 void *args_ptr,
261 xdrproc_t xdr_results,
262 void *results_ptr,
263 struct timeval utimeout)
264{
265 struct ct_data *ct = (struct ct_data *) cl->cl_private;
285 rpcproc_t proc,
286 xdrproc_t xdr_args,
287 void *args_ptr,
288 xdrproc_t xdr_results,
289 void *results_ptr,
290 struct timeval utimeout)
291{
292 struct ct_data *ct = (struct ct_data *) cl->cl_private;
293 AUTH *auth;
266 XDR xdrs;
267 struct rpc_msg reply_msg;
268 bool_t ok;
269 int nrefreshes = 2; /* number of times to refresh cred */
270 struct timeval timeout;
271 uint32_t xid;
272 struct mbuf *mreq = NULL;
294 XDR xdrs;
295 struct rpc_msg reply_msg;
296 bool_t ok;
297 int nrefreshes = 2; /* number of times to refresh cred */
298 struct timeval timeout;
299 uint32_t xid;
300 struct mbuf *mreq = NULL;
273 struct ct_request cr;
301 struct ct_request *cr;
274 int error;
275
302 int error;
303
304 cr = malloc(sizeof(struct ct_request), M_RPC, M_WAITOK);
305
276 mtx_lock(&ct->ct_lock);
277
306 mtx_lock(&ct->ct_lock);
307
278 cr.cr_mrep = NULL;
279 cr.cr_error = 0;
308 if (ct->ct_closing) {
309 mtx_unlock(&ct->ct_lock);
310 free(cr, M_RPC);
311 return (RPC_CANTSEND);
312 }
313 ct->ct_threads++;
280
314
315 if (ext)
316 auth = ext->rc_auth;
317 else
318 auth = cl->cl_auth;
319
320 cr->cr_mrep = NULL;
321 cr->cr_error = 0;
322
281 if (ct->ct_wait.tv_usec == -1) {
282 timeout = utimeout; /* use supplied timeout */
283 } else {
284 timeout = ct->ct_wait; /* use default timeout */
285 }
286
287call_again:
288 mtx_assert(&ct->ct_lock, MA_OWNED);

--- 17 unchanged lines hidden (view full) ---

306 */
307 *mtod(mreq, uint32_t *) = htonl(xid);
308
309 xdrmbuf_create(&xdrs, mreq, XDR_ENCODE);
310
311 ct->ct_error.re_status = RPC_SUCCESS;
312
313 if ((! XDR_PUTINT32(&xdrs, &proc)) ||
323 if (ct->ct_wait.tv_usec == -1) {
324 timeout = utimeout; /* use supplied timeout */
325 } else {
326 timeout = ct->ct_wait; /* use default timeout */
327 }
328
329call_again:
330 mtx_assert(&ct->ct_lock, MA_OWNED);

--- 17 unchanged lines hidden (view full) ---

348 */
349 *mtod(mreq, uint32_t *) = htonl(xid);
350
351 xdrmbuf_create(&xdrs, mreq, XDR_ENCODE);
352
353 ct->ct_error.re_status = RPC_SUCCESS;
354
355 if ((! XDR_PUTINT32(&xdrs, &proc)) ||
314 (! AUTH_MARSHALL(cl->cl_auth, &xdrs)) ||
356 (! AUTH_MARSHALL(auth, &xdrs)) ||
315 (! (*xdr_args)(&xdrs, args_ptr))) {
316 if (ct->ct_error.re_status == RPC_SUCCESS)
317 ct->ct_error.re_status = RPC_CANTENCODEARGS;
357 (! (*xdr_args)(&xdrs, args_ptr))) {
358 if (ct->ct_error.re_status == RPC_SUCCESS)
359 ct->ct_error.re_status = RPC_CANTENCODEARGS;
318 m_freem(mreq);
319 return (ct->ct_error.re_status);
360 mtx_lock(&ct->ct_lock);
361 goto out;
320 }
321 m_fixhdr(mreq);
322
323 /*
324 * Prepend a record marker containing the packet length.
325 */
326 M_PREPEND(mreq, sizeof(uint32_t), M_WAIT);
327 *mtod(mreq, uint32_t *) =
328 htonl(0x80000000 | (mreq->m_pkthdr.len - sizeof(uint32_t)));
329
362 }
363 m_fixhdr(mreq);
364
365 /*
366 * Prepend a record marker containing the packet length.
367 */
368 M_PREPEND(mreq, sizeof(uint32_t), M_WAIT);
369 *mtod(mreq, uint32_t *) =
370 htonl(0x80000000 | (mreq->m_pkthdr.len - sizeof(uint32_t)));
371
330 cr.cr_xid = xid;
372 cr->cr_xid = xid;
331 mtx_lock(&ct->ct_lock);
373 mtx_lock(&ct->ct_lock);
332 TAILQ_INSERT_TAIL(&ct->ct_pending, &cr, cr_link);
374 TAILQ_INSERT_TAIL(&ct->ct_pending, cr, cr_link);
333 mtx_unlock(&ct->ct_lock);
334
335 /*
336 * sosend consumes mreq.
337 */
338 error = sosend(ct->ct_socket, NULL, NULL, mreq, NULL, 0, curthread);
339 mreq = NULL;
340
341 reply_msg.acpted_rply.ar_verf = _null_auth;
342 reply_msg.acpted_rply.ar_results.where = results_ptr;
343 reply_msg.acpted_rply.ar_results.proc = xdr_results;
344
345 mtx_lock(&ct->ct_lock);
375 mtx_unlock(&ct->ct_lock);
376
377 /*
378 * sosend consumes mreq.
379 */
380 error = sosend(ct->ct_socket, NULL, NULL, mreq, NULL, 0, curthread);
381 mreq = NULL;
382
383 reply_msg.acpted_rply.ar_verf = _null_auth;
384 reply_msg.acpted_rply.ar_results.where = results_ptr;
385 reply_msg.acpted_rply.ar_results.proc = xdr_results;
386
387 mtx_lock(&ct->ct_lock);
346
347 if (error) {
388 if (error) {
348 TAILQ_REMOVE(&ct->ct_pending, &cr, cr_link);
349
389 TAILQ_REMOVE(&ct->ct_pending, cr, cr_link);
350 ct->ct_error.re_errno = error;
351 ct->ct_error.re_status = RPC_CANTSEND;
352 goto out;
353 }
354
355 /*
356 * Check to see if we got an upcall while waiting for the
357 * lock. In both these cases, the request has been removed
358 * from ct->ct_pending.
359 */
390 ct->ct_error.re_errno = error;
391 ct->ct_error.re_status = RPC_CANTSEND;
392 goto out;
393 }
394
395 /*
396 * Check to see if we got an upcall while waiting for the
397 * lock. In both these cases, the request has been removed
398 * from ct->ct_pending.
399 */
360 if (cr.cr_error) {
361 ct->ct_error.re_errno = cr.cr_error;
400 if (cr->cr_error) {
401 TAILQ_REMOVE(&ct->ct_pending, cr, cr_link);
402 ct->ct_error.re_errno = cr->cr_error;
362 ct->ct_error.re_status = RPC_CANTRECV;
363 goto out;
364 }
403 ct->ct_error.re_status = RPC_CANTRECV;
404 goto out;
405 }
365 if (cr.cr_mrep) {
406 if (cr->cr_mrep) {
407 TAILQ_REMOVE(&ct->ct_pending, cr, cr_link);
366 goto got_reply;
367 }
368
369 /*
370 * Hack to provide rpc-based message passing
371 */
372 if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
408 goto got_reply;
409 }
410
411 /*
412 * Hack to provide rpc-based message passing
413 */
414 if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
373 if (cr.cr_xid)
374 TAILQ_REMOVE(&ct->ct_pending, &cr, cr_link);
415 TAILQ_REMOVE(&ct->ct_pending, cr, cr_link);
375 ct->ct_error.re_status = RPC_TIMEDOUT;
376 goto out;
377 }
378
416 ct->ct_error.re_status = RPC_TIMEDOUT;
417 goto out;
418 }
419
379 error = msleep(&cr, &ct->ct_lock, ct->ct_waitflag, ct->ct_waitchan,
420 error = msleep(cr, &ct->ct_lock, ct->ct_waitflag, ct->ct_waitchan,
380 tvtohz(&timeout));
381
421 tvtohz(&timeout));
422
423 TAILQ_REMOVE(&ct->ct_pending, cr, cr_link);
424
382 if (error) {
383 /*
384 * The sleep returned an error so our request is still
385 * on the list. Turn the error code into an
386 * appropriate client status.
387 */
425 if (error) {
426 /*
427 * The sleep returned an error so our request is still
428 * on the list. Turn the error code into an
429 * appropriate client status.
430 */
388 if (cr.cr_xid)
389 TAILQ_REMOVE(&ct->ct_pending, &cr, cr_link);
390 ct->ct_error.re_errno = error;
391 switch (error) {
392 case EINTR:
393 ct->ct_error.re_status = RPC_INTR;
394 break;
395 case EWOULDBLOCK:
396 ct->ct_error.re_status = RPC_TIMEDOUT;
397 break;
398 default:
399 ct->ct_error.re_status = RPC_CANTRECV;
400 }
401 goto out;
402 } else {
403 /*
404 * We were woken up by the upcall. If the
405 * upcall had a receive error, report that,
406 * otherwise we have a reply.
407 */
431 ct->ct_error.re_errno = error;
432 switch (error) {
433 case EINTR:
434 ct->ct_error.re_status = RPC_INTR;
435 break;
436 case EWOULDBLOCK:
437 ct->ct_error.re_status = RPC_TIMEDOUT;
438 break;
439 default:
440 ct->ct_error.re_status = RPC_CANTRECV;
441 }
442 goto out;
443 } else {
444 /*
445 * We were woken up by the upcall. If the
446 * upcall had a receive error, report that,
447 * otherwise we have a reply.
448 */
408 if (cr.cr_error) {
409 ct->ct_error.re_errno = cr.cr_error;
449 if (cr->cr_error) {
450 ct->ct_error.re_errno = cr->cr_error;
410 ct->ct_error.re_status = RPC_CANTRECV;
411 goto out;
412 }
413 }
414
415got_reply:
416 /*
417 * Now decode and validate the response. We need to drop the
418 * lock since xdr_replymsg may end up sleeping in malloc.
419 */
420 mtx_unlock(&ct->ct_lock);
421
451 ct->ct_error.re_status = RPC_CANTRECV;
452 goto out;
453 }
454 }
455
456got_reply:
457 /*
458 * Now decode and validate the response. We need to drop the
459 * lock since xdr_replymsg may end up sleeping in malloc.
460 */
461 mtx_unlock(&ct->ct_lock);
462
422 xdrmbuf_create(&xdrs, cr.cr_mrep, XDR_DECODE);
463 xdrmbuf_create(&xdrs, cr->cr_mrep, XDR_DECODE);
423 ok = xdr_replymsg(&xdrs, &reply_msg);
424 XDR_DESTROY(&xdrs);
464 ok = xdr_replymsg(&xdrs, &reply_msg);
465 XDR_DESTROY(&xdrs);
425 cr.cr_mrep = NULL;
466 cr->cr_mrep = NULL;
426
427 mtx_lock(&ct->ct_lock);
428
429 if (ok) {
430 if ((reply_msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
431 (reply_msg.acpted_rply.ar_stat == SUCCESS))
432 ct->ct_error.re_status = RPC_SUCCESS;
433 else

--- 27 unchanged lines hidden (view full) ---

461 else {
462 ct->ct_error.re_status = RPC_CANTDECODERES;
463 }
464out:
465 mtx_assert(&ct->ct_lock, MA_OWNED);
466
467 if (mreq)
468 m_freem(mreq);
467
468 mtx_lock(&ct->ct_lock);
469
470 if (ok) {
471 if ((reply_msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
472 (reply_msg.acpted_rply.ar_stat == SUCCESS))
473 ct->ct_error.re_status = RPC_SUCCESS;
474 else

--- 27 unchanged lines hidden (view full) ---

502 else {
503 ct->ct_error.re_status = RPC_CANTDECODERES;
504 }
505out:
506 mtx_assert(&ct->ct_lock, MA_OWNED);
507
508 if (mreq)
509 m_freem(mreq);
469 if (cr.cr_mrep)
470 m_freem(cr.cr_mrep);
510 if (cr->cr_mrep)
511 m_freem(cr->cr_mrep);
471
512
513 ct->ct_threads--;
514 if (ct->ct_closing)
515 wakeup(ct);
516
472 mtx_unlock(&ct->ct_lock);
517 mtx_unlock(&ct->ct_lock);
518
519 free(cr, M_RPC);
520
473 return (ct->ct_error.re_status);
474}
475
476static void
477clnt_vc_geterr(CLIENT *cl, struct rpc_err *errp)
478{
479 struct ct_data *ct = (struct ct_data *) cl->cl_private;
480

--- 142 unchanged lines hidden (view full) ---

623 mtx_unlock(&ct->ct_lock);
624 return (TRUE);
625}
626
627static void
628clnt_vc_destroy(CLIENT *cl)
629{
630 struct ct_data *ct = (struct ct_data *) cl->cl_private;
521 return (ct->ct_error.re_status);
522}
523
524static void
525clnt_vc_geterr(CLIENT *cl, struct rpc_err *errp)
526{
527 struct ct_data *ct = (struct ct_data *) cl->cl_private;
528

--- 142 unchanged lines hidden (view full) ---

671 mtx_unlock(&ct->ct_lock);
672 return (TRUE);
673}
674
675static void
676clnt_vc_destroy(CLIENT *cl)
677{
678 struct ct_data *ct = (struct ct_data *) cl->cl_private;
679 struct ct_request *cr;
631 struct socket *so = NULL;
632
633 mtx_lock(&ct->ct_lock);
634
635 if (ct->ct_socket) {
636 SOCKBUF_LOCK(&ct->ct_socket->so_rcv);
637 ct->ct_socket->so_upcallarg = NULL;
638 ct->ct_socket->so_upcall = NULL;
639 ct->ct_socket->so_rcv.sb_flags &= ~SB_UPCALL;
640 SOCKBUF_UNLOCK(&ct->ct_socket->so_rcv);
641
680 struct socket *so = NULL;
681
682 mtx_lock(&ct->ct_lock);
683
684 if (ct->ct_socket) {
685 SOCKBUF_LOCK(&ct->ct_socket->so_rcv);
686 ct->ct_socket->so_upcallarg = NULL;
687 ct->ct_socket->so_upcall = NULL;
688 ct->ct_socket->so_rcv.sb_flags &= ~SB_UPCALL;
689 SOCKBUF_UNLOCK(&ct->ct_socket->so_rcv);
690
642 KASSERT(!TAILQ_FIRST(&ct->ct_pending),
643 ("Destroying RPC client with pending RPC requests"));
691 /*
692 * Abort any pending requests and wait until everyone
693 * has finished with clnt_vc_call.
694 */
695 ct->ct_closing = TRUE;
696 TAILQ_FOREACH(cr, &ct->ct_pending, cr_link) {
697 cr->cr_xid = 0;
698 cr->cr_error = ESHUTDOWN;
699 wakeup(cr);
700 }
644
701
702 while (ct->ct_threads)
703 msleep(ct, &ct->ct_lock, 0, "rpcclose", 0);
704
645 if (ct->ct_closeit) {
646 so = ct->ct_socket;
647 }
648 }
649
650 mtx_unlock(&ct->ct_lock);
651
652 mtx_destroy(&ct->ct_lock);

--- 74 unchanged lines hidden (view full) ---

727 error = ECONNRESET;
728 }
729 ct->ct_error.re_status = RPC_CANTRECV;
730 ct->ct_error.re_errno = error;
731 TAILQ_FOREACH(cr, &ct->ct_pending, cr_link) {
732 cr->cr_error = error;
733 wakeup(cr);
734 }
705 if (ct->ct_closeit) {
706 so = ct->ct_socket;
707 }
708 }
709
710 mtx_unlock(&ct->ct_lock);
711
712 mtx_destroy(&ct->ct_lock);

--- 74 unchanged lines hidden (view full) ---

787 error = ECONNRESET;
788 }
789 ct->ct_error.re_status = RPC_CANTRECV;
790 ct->ct_error.re_errno = error;
791 TAILQ_FOREACH(cr, &ct->ct_pending, cr_link) {
792 cr->cr_error = error;
793 wakeup(cr);
794 }
735 TAILQ_INIT(&ct->ct_pending);
736 mtx_unlock(&ct->ct_lock);
737 break;
738 }
739 memcpy(&header, mtod(m, uint32_t *), sizeof(uint32_t));
740 header = ntohl(header);
741 ct->ct_record = NULL;
742 ct->ct_record_resid = header & 0x7fffffff;
743 ct->ct_record_eor = ((header & 0x80000000) != 0);

--- 46 unchanged lines hidden (view full) ---

790 xid = ntohl(xid);
791
792 mtx_lock(&ct->ct_lock);
793 foundreq = 0;
794 TAILQ_FOREACH(cr, &ct->ct_pending, cr_link) {
795 if (cr->cr_xid == xid) {
796 /*
797 * This one
795 mtx_unlock(&ct->ct_lock);
796 break;
797 }
798 memcpy(&header, mtod(m, uint32_t *), sizeof(uint32_t));
799 header = ntohl(header);
800 ct->ct_record = NULL;
801 ct->ct_record_resid = header & 0x7fffffff;
802 ct->ct_record_eor = ((header & 0x80000000) != 0);

--- 46 unchanged lines hidden (view full) ---

849 xid = ntohl(xid);
850
851 mtx_lock(&ct->ct_lock);
852 foundreq = 0;
853 TAILQ_FOREACH(cr, &ct->ct_pending, cr_link) {
854 if (cr->cr_xid == xid) {
855 /*
856 * This one
798 * matches. We snip it
799 * out of the pending
800 * list and leave the
801 * reply mbuf in
857 * matches. We leave
858 * the reply mbuf in
802 * cr->cr_mrep. Set
803 * the XID to zero so
859 * cr->cr_mrep. Set
860 * the XID to zero so
804 * that clnt_vc_call
805 * can know not to
806 * repeat the
807 * TAILQ_REMOVE.
861 * that we will ignore
862 * any duplicaed
863 * replies.
808 */
864 */
809 TAILQ_REMOVE(&ct->ct_pending,
810 cr, cr_link);
811 cr->cr_xid = 0;
812 cr->cr_mrep = ct->ct_record;
813 cr->cr_error = 0;
814 foundreq = 1;
815 wakeup(cr);
816 break;
817 }
818 }
819 mtx_unlock(&ct->ct_lock);
820
821 if (!foundreq)
822 m_freem(ct->ct_record);
823 ct->ct_record = NULL;
824 }
825 }
826 } while (m);
827}
865 cr->cr_xid = 0;
866 cr->cr_mrep = ct->ct_record;
867 cr->cr_error = 0;
868 foundreq = 1;
869 wakeup(cr);
870 break;
871 }
872 }
873 mtx_unlock(&ct->ct_lock);
874
875 if (!foundreq)
876 m_freem(ct->ct_record);
877 ct->ct_record = NULL;
878 }
879 }
880 } while (m);
881}