Fri Nov 6 19:34:14 2015 UTC ()
- Provide multi-threaded fdset's for everyone not just rump if requested.
- Abstract fd_set access, and don't limit the fd_set size.
- Maintain binary compatibility by keeping the old global variables around.


(christos)
diff -r1.22 -r1.23 src/lib/libc/rpc/Makefile.inc
diff -r1.22 -r1.23 src/lib/libc/rpc/svc_run.c
diff -r1.34 -r1.35 src/lib/libc/rpc/svc.c
diff -r1.1 -r1.2 src/lib/libc/rpc/svc_fdset.c
diff -r1.1 -r1.2 src/lib/libc/rpc/svc_fdset.h
diff -r1.30 -r1.31 src/lib/libc/rpc/svc_vc.c

cvs diff -r1.22 -r1.23 src/lib/libc/rpc/Makefile.inc (expand / switch to unified diff)

--- src/lib/libc/rpc/Makefile.inc 2015/04/15 19:13:47 1.22
+++ src/lib/libc/rpc/Makefile.inc 2015/11/06 19:34:13 1.23
@@ -1,28 +1,28 @@ @@ -1,28 +1,28 @@
1# $NetBSD: Makefile.inc,v 1.22 2015/04/15 19:13:47 mrg Exp $ 1# $NetBSD: Makefile.inc,v 1.23 2015/11/06 19:34:13 christos Exp $
2 2
3# librpc sources 3# librpc sources
4.PATH: ${.CURDIR}/rpc 4.PATH: ${.CURDIR}/rpc
5 5
6SRCS+= auth_none.c auth_unix.c authunix_prot.c bindresvport.c \ 6SRCS+= auth_none.c auth_unix.c authunix_prot.c bindresvport.c \
7 clnt_bcast.c clnt_dg.c clnt_generic.c clnt_perror.c \ 7 clnt_bcast.c clnt_dg.c clnt_generic.c clnt_perror.c \
8 clnt_raw.c clnt_simple.c \ 8 clnt_raw.c clnt_simple.c \
9 clnt_vc.c rpc_dtablesize.c \ 9 clnt_vc.c rpc_dtablesize.c \
10 getnetconfig.c getnetpath.c getrpcent.c getrpcport.c \ 10 getnetconfig.c getnetpath.c getrpcent.c getrpcport.c \
11 mt_misc.c pmap_clnt.c pmap_getmaps.c pmap_getport.c pmap_prot.c \ 11 mt_misc.c pmap_clnt.c pmap_getmaps.c pmap_getport.c pmap_prot.c \
12 pmap_prot2.c pmap_rmt.c rpc_prot.c rpc_commondata.c rpc_callmsg.c \ 12 pmap_prot2.c pmap_rmt.c rpc_prot.c rpc_commondata.c rpc_callmsg.c \
13 rpc_generic.c rpc_soc.c rpcb_clnt.c rpcb_prot.c rpcb_st_xdr.c \ 13 rpc_generic.c rpc_soc.c rpcb_clnt.c rpcb_prot.c rpcb_st_xdr.c \
14 svc.c svc_auth.c svc_dg.c svc_auth_unix.c svc_generic.c svc_raw.c \ 14 svc.c svc_auth.c svc_dg.c svc_auth_unix.c svc_generic.c svc_raw.c \
15 svc_run.c svc_simple.c svc_vc.c \ 15 svc_run.c svc_simple.c svc_vc.c svc_fdset.c \
16 xdr.c xdr_array.c xdr_float.c xdr_mem.c xdr_rec.c xdr_reference.c \ 16 xdr.c xdr_array.c xdr_float.c xdr_mem.c xdr_rec.c xdr_reference.c \
17 xdr_stdio.c xdr_sizeof.c __rpc_getxid.c 17 xdr_stdio.c xdr_sizeof.c __rpc_getxid.c
18 18
19CPPFLAGS+= -DPORTMAP 19CPPFLAGS+= -DPORTMAP
20 20
21MAN+= bindresvport.3 getnetconfig.3 getnetpath.3 getrpcent.3 getrpcport.3 \ 21MAN+= bindresvport.3 getnetconfig.3 getnetpath.3 getrpcent.3 getrpcport.3 \
22 rpc.3 rpc_soc.3 rpc_clnt_auth.3 rpc_clnt_calls.3 rpc_clnt_create.3 \ 22 rpc.3 rpc_soc.3 rpc_clnt_auth.3 rpc_clnt_calls.3 rpc_clnt_create.3 \
23 rpc_svc_calls.3 rpc_svc_create.3 rpc_svc_err.3 rpc_svc_reg.3 \ 23 rpc_svc_calls.3 rpc_svc_create.3 rpc_svc_err.3 rpc_svc_reg.3 \
24 rpc_xdr.3 rpcbind.3 xdr.3 24 rpc_xdr.3 rpcbind.3 xdr.3
25MLINKS+= bindresvport.3 bindresvport_sa.3 \ 25MLINKS+= bindresvport.3 bindresvport_sa.3 \
26 getnetconfig.3 setnetconfig.3 \ 26 getnetconfig.3 setnetconfig.3 \
27 getnetconfig.3 getnetconfigent.3 \ 27 getnetconfig.3 getnetconfigent.3 \
28 getnetconfig.3 endnetconfig.3 \ 28 getnetconfig.3 endnetconfig.3 \

cvs diff -r1.22 -r1.23 src/lib/libc/rpc/svc_run.c (expand / switch to unified diff)

--- src/lib/libc/rpc/svc_run.c 2013/03/11 20:19:29 1.22
+++ src/lib/libc/rpc/svc_run.c 2015/11/06 19:34:13 1.23
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: svc_run.c,v 1.22 2013/03/11 20:19:29 tron Exp $ */ 1/* $NetBSD: svc_run.c,v 1.23 2015/11/06 19:34:13 christos Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2010, Oracle America, Inc. 4 * Copyright (c) 2010, Oracle America, Inc.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are 7 * modification, are permitted provided that the following conditions are
8 * met: 8 * met:
9 * 9 *
10 * * Redistributions of source code must retain the above copyright 10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above 12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following 13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials 14 * disclaimer in the documentation and/or other materials
@@ -27,101 +27,113 @@ @@ -27,101 +27,113 @@
27 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */ 32 */
33 33
34#include <sys/cdefs.h> 34#include <sys/cdefs.h>
35#if defined(LIBC_SCCS) && !defined(lint) 35#if defined(LIBC_SCCS) && !defined(lint)
36#if 0 36#if 0
37static char *sccsid = "@(#)svc_run.c 1.1 87/10/13 Copyr 1984 Sun Micro"; 37static char *sccsid = "@(#)svc_run.c 1.1 87/10/13 Copyr 1984 Sun Micro";
38static char *sccsid = "@(#)svc_run.c 2.1 88/07/29 4.0 RPCSRC"; 38static char *sccsid = "@(#)svc_run.c 2.1 88/07/29 4.0 RPCSRC";
39#else 39#else
40__RCSID("$NetBSD: svc_run.c,v 1.22 2013/03/11 20:19:29 tron Exp $"); 40__RCSID("$NetBSD: svc_run.c,v 1.23 2015/11/06 19:34:13 christos Exp $");
41#endif 41#endif
42#endif 42#endif
43 43
44/* 44/*
45 * This is the rpc server side idle loop 45 * This is the rpc server side idle loop
46 * Wait for input, call server program. 46 * Wait for input, call server program.
47 */ 47 */
48#include "namespace.h" 48#include "namespace.h"
49#include "reentrant.h" 49#include "reentrant.h"
50#include <err.h> 50#include <err.h>
51#include <errno.h> 51#include <errno.h>
52#include <stdio.h> 52#include <stdio.h>
 53#include <stdlib.h>
53#include <string.h> 54#include <string.h>
54#include <unistd.h> 55#include <unistd.h>
55 56
56#include <rpc/rpc.h> 57#include <rpc/rpc.h>
57 58
58#include "svc_fdset.h" 59#include "svc_fdset.h"
59#include "rpc_internal.h" 60#include "rpc_internal.h"
60 61
61#ifdef __weak_alias 62#ifdef __weak_alias
62__weak_alias(svc_run,_svc_run) 63__weak_alias(svc_run,_svc_run)
63__weak_alias(svc_exit,_svc_exit) 64__weak_alias(svc_exit,_svc_exit)
64#endif 65#endif
65 66
66void 67void
67svc_run(void) 68svc_run(void)
68{ 69{
69 fd_set readfds, cleanfds; 70 fd_set *readfds, *cleanfds;
70 struct timeval timeout; 71 struct timeval timeout;
71 int maxfd; 72 int maxfd, fdsize;
72#ifndef RUMP_RPC  73#ifndef RUMP_RPC
73 int probs = 0; 74 int probs = 0;
74#endif 75#endif
75#ifdef _REENTRANT 76#ifdef _REENTRANT
76 extern rwlock_t svc_fd_lock; 77 extern rwlock_t svc_fd_lock;
77#endif 78#endif
78 79
 80 readfds = NULL;
 81 cleanfds = NULL;
 82 fdsize = 0;
79 timeout.tv_sec = 30; 83 timeout.tv_sec = 30;
80 timeout.tv_usec = 0; 84 timeout.tv_usec = 0;
81 85
82 for (;;) { 86 for (;;) {
83 rwlock_rdlock(&svc_fd_lock); 87 rwlock_rdlock(&svc_fd_lock);
84 readfds = *get_fdset(); 88 if (fdsize != svc_fdset_getsize(0)) {
85 cleanfds = *get_fdset(); 89 fdsize = svc_fdset_getsize(0);
86 maxfd = *get_fdsetmax(); 90 free(readfds);
 91 readfds = svc_fdset_copy(svc_fdset_get());
 92 free(cleanfds);
 93 cleanfds = svc_fdset_copy(svc_fdset_get());
 94 }
 95 maxfd = *svc_fdset_getmax();
87 rwlock_unlock(&svc_fd_lock); 96 rwlock_unlock(&svc_fd_lock);
88 switch (select(maxfd + 1, &readfds, NULL, NULL, &timeout)) { 97 switch (select(maxfd + 1, readfds, NULL, NULL, &timeout)) {
89 case -1: 98 case -1:
90#ifndef RUMP_RPC  99#ifndef RUMP_RPC
91 if ((errno == EINTR || errno == EBADF) && probs < 100) { 100 if ((errno == EINTR || errno == EBADF) && probs < 100) {
92 probs++; 101 probs++;
93 continue; 102 continue;
94 } 103 }
95#endif 104#endif
96 if (errno == EINTR) { 105 if (errno == EINTR) {
97 continue; 106 continue;
98 } 107 }
99 warn("%s: select failed", __func__); 108 warn("%s: select failed", __func__);
100 return; 109 goto out;
101 case 0: 110 case 0:
102 __svc_clean_idle(&cleanfds, 30, FALSE); 111 __svc_clean_idle(cleanfds, 30, FALSE);
103 continue; 112 continue;
104 default: 113 default:
105 svc_getreqset(&readfds); 114 svc_getreqset2(readfds, fdsize);
106#ifndef RUMP_RPC 115#ifndef RUMP_RPC
107 probs = 0; 116 probs = 0;
108#endif 117#endif
109 } 118 }
110 } 119 }
 120out:
 121 free(readfds);
 122 free(cleanfds);
111} 123}
112 124
113/* 125/*
114 * This function causes svc_run() to exit by telling it that it has no 126 * This function causes svc_run() to exit by telling it that it has no
115 * more work to do. 127 * more work to do.
116 */ 128 */
117void 129void
118svc_exit(void) 130svc_exit(void)
119{ 131{
120#ifdef _REENTRANT 132#ifdef _REENTRANT
121 extern rwlock_t svc_fd_lock; 133 extern rwlock_t svc_fd_lock;
122#endif 134#endif
123 135
124 rwlock_wrlock(&svc_fd_lock); 136 rwlock_wrlock(&svc_fd_lock);
125 FD_ZERO(get_fdset()); 137 svc_fdset_zero();
126 rwlock_unlock(&svc_fd_lock); 138 rwlock_unlock(&svc_fd_lock);
127} 139}

cvs diff -r1.34 -r1.35 src/lib/libc/rpc/svc.c (expand / switch to unified diff)

--- src/lib/libc/rpc/svc.c 2013/03/11 20:19:29 1.34
+++ src/lib/libc/rpc/svc.c 2015/11/06 19:34:13 1.35
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: svc.c,v 1.34 2013/03/11 20:19:29 tron Exp $ */ 1/* $NetBSD: svc.c,v 1.35 2015/11/06 19:34:13 christos Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2010, Oracle America, Inc. 4 * Copyright (c) 2010, Oracle America, Inc.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are 7 * modification, are permitted provided that the following conditions are
8 * met: 8 * met:
9 * 9 *
10 * * Redistributions of source code must retain the above copyright 10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above 12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following 13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials 14 * disclaimer in the documentation and/or other materials
@@ -27,27 +27,27 @@ @@ -27,27 +27,27 @@
27 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */ 32 */
33 33
34#include <sys/cdefs.h> 34#include <sys/cdefs.h>
35#if defined(LIBC_SCCS) && !defined(lint)  35#if defined(LIBC_SCCS) && !defined(lint)
36#if 0 36#if 0
37static char *sccsid = "@(#)svc.c 1.44 88/02/08 Copyr 1984 Sun Micro"; 37static char *sccsid = "@(#)svc.c 1.44 88/02/08 Copyr 1984 Sun Micro";
38static char *sccsid = "@(#)svc.c 2.4 88/08/11 4.0 RPCSRC"; 38static char *sccsid = "@(#)svc.c 2.4 88/08/11 4.0 RPCSRC";
39#else 39#else
40__RCSID("$NetBSD: svc.c,v 1.34 2013/03/11 20:19:29 tron Exp $"); 40__RCSID("$NetBSD: svc.c,v 1.35 2015/11/06 19:34:13 christos Exp $");
41#endif 41#endif
42#endif 42#endif
43 43
44/* 44/*
45 * svc.c, Server-side remote procedure call interface. 45 * svc.c, Server-side remote procedure call interface.
46 * 46 *
47 * There are two sets of procedures here. The xprt routines are 47 * There are two sets of procedures here. The xprt routines are
48 * for handling transport handles. The svc routines handle the 48 * for handling transport handles. The svc routines handle the
49 * list of service routines. 49 * list of service routines.
50 * 50 *
51 * Copyright (C) 1984, Sun Microsystems, Inc. 51 * Copyright (C) 1984, Sun Microsystems, Inc.
52 */ 52 */
53 53
@@ -80,27 +80,29 @@ __weak_alias(svc_sendreply,_svc_sendrepl @@ -80,27 +80,29 @@ __weak_alias(svc_sendreply,_svc_sendrepl
80__weak_alias(svc_unregister,_svc_unregister) 80__weak_alias(svc_unregister,_svc_unregister)
81__weak_alias(svcerr_auth,_svcerr_auth) 81__weak_alias(svcerr_auth,_svcerr_auth)
82__weak_alias(svcerr_decode,_svcerr_decode) 82__weak_alias(svcerr_decode,_svcerr_decode)
83__weak_alias(svcerr_noproc,_svcerr_noproc) 83__weak_alias(svcerr_noproc,_svcerr_noproc)
84__weak_alias(svcerr_noprog,_svcerr_noprog) 84__weak_alias(svcerr_noprog,_svcerr_noprog)
85__weak_alias(svcerr_progvers,_svcerr_progvers) 85__weak_alias(svcerr_progvers,_svcerr_progvers)
86__weak_alias(svcerr_systemerr,_svcerr_systemerr) 86__weak_alias(svcerr_systemerr,_svcerr_systemerr)
87__weak_alias(svcerr_weakauth,_svcerr_weakauth) 87__weak_alias(svcerr_weakauth,_svcerr_weakauth)
88__weak_alias(xprt_register,_xprt_register) 88__weak_alias(xprt_register,_xprt_register)
89__weak_alias(xprt_unregister,_xprt_unregister) 89__weak_alias(xprt_unregister,_xprt_unregister)
90__weak_alias(rpc_control,_rpc_control) 90__weak_alias(rpc_control,_rpc_control)
91#endif 91#endif
92 92
 93/* __svc_xports[-1] is reserved for raw */
93SVCXPRT **__svc_xports; 94SVCXPRT **__svc_xports;
 95int __svc_maxxports;
94int __svc_maxrec; 96int __svc_maxrec;
95 97
96#define RQCRED_SIZE 400 /* this size is excessive */ 98#define RQCRED_SIZE 400 /* this size is excessive */
97 99
98#define SVC_VERSQUIET 0x0001 /* keep quiet about vers mismatch */ 100#define SVC_VERSQUIET 0x0001 /* keep quiet about vers mismatch */
99#define version_keepquiet(xp) ((u_long)(xp)->xp_p3 & SVC_VERSQUIET) 101#define version_keepquiet(xp) ((u_long)(xp)->xp_p3 & SVC_VERSQUIET)
100 102
101#define max(a, b) (a > b ? a : b) 103#define max(a, b) (a > b ? a : b)
102 104
103/* 105/*
104 * The services list 106 * The services list
105 * Each entry represents a set of procedures (an rpc program). 107 * Each entry represents a set of procedures (an rpc program).
106 * The dispatch routine takes request structs and runs the 108 * The dispatch routine takes request structs and runs the
@@ -115,99 +117,130 @@ static struct svc_callout { @@ -115,99 +117,130 @@ static struct svc_callout {
115} *svc_head; 117} *svc_head;
116 118
117#ifdef _REENTRANT 119#ifdef _REENTRANT
118extern rwlock_t svc_lock; 120extern rwlock_t svc_lock;
119extern rwlock_t svc_fd_lock; 121extern rwlock_t svc_fd_lock;
120#endif 122#endif
121 123
122static struct svc_callout *svc_find(rpcprog_t, rpcvers_t, 124static struct svc_callout *svc_find(rpcprog_t, rpcvers_t,
123 struct svc_callout **, char *); 125 struct svc_callout **, char *);
124static void __xprt_do_unregister(SVCXPRT *xprt, bool_t dolock); 126static void __xprt_do_unregister(SVCXPRT *xprt, bool_t dolock);
125 127
126/* *************** SVCXPRT related stuff **************** */ 128/* *************** SVCXPRT related stuff **************** */
127 129
 130static bool_t
 131xprt_alloc(int sock)
 132{
 133 int maxset;
 134 char *newxports;
 135
 136 if (++sock < 0)
 137 return FALSE;
 138
 139 maxset = svc_fdset_getsize(sock);
 140 if (maxset == -1)
 141 return FALSE;
 142
 143 if (__svc_xports != NULL && maxset <= __svc_maxxports)
 144 return TRUE;
 145
 146 if (__svc_xports != NULL)
 147 --__svc_xports;
 148 newxports = realloc(__svc_xports, maxset * sizeof(SVCXPRT *));
 149 if (newxports == NULL) {
 150 warn("%s: out of memory", __func__);
 151 return FALSE;
 152 }
 153
 154 memset(newxports + __svc_maxxports * sizeof(SVCXPRT *), 0,
 155 (maxset - __svc_maxxports) * sizeof(SVCXPRT *));
 156
 157 __svc_xports = (void *)newxports;
 158 __svc_xports++;
 159 __svc_maxxports = maxset;
 160
 161 return TRUE;
 162}
 163
128/* 164/*
129 * Activate a transport handle. 165 * Activate a transport handle.
130 */ 166 */
131bool_t 167bool_t
132xprt_register(SVCXPRT *xprt) 168xprt_register(SVCXPRT *xprt)
133{ 169{
134 int sock; 170 int sock;
135 171
136 _DIAGASSERT(xprt != NULL); 172 _DIAGASSERT(xprt != NULL);
137 173
 174 rwlock_wrlock(&svc_fd_lock);
138 sock = xprt->xp_fd; 175 sock = xprt->xp_fd;
139 176
140 rwlock_wrlock(&svc_fd_lock); 177 if (!xprt_alloc(sock))
141 if (__svc_xports == NULL) { 
142 __svc_xports = mem_alloc(FD_SETSIZE * sizeof(SVCXPRT *)); 
143 if (__svc_xports == NULL) { 
144 warn("%s: out of memory", __func__); 
145 goto out; 
146 } 
147 memset(__svc_xports, '\0', FD_SETSIZE * sizeof(SVCXPRT *)); 
148 } 
149 if (sock >= FD_SETSIZE) { 
150 warnx("%s: socket descriptor %d too large for setsize %u", 
151 __func__, sock, (unsigned)FD_SETSIZE); 
152 goto out; 178 goto out;
153 } 179
154 __svc_xports[sock] = xprt; 180 __svc_xports[sock] = xprt;
155 FD_SET(sock, get_fdset()); 181 if (sock != -1) {
156 *get_fdsetmax() = max(*get_fdsetmax(), sock); 182 svc_fdset_set(sock);
 183 }
157 rwlock_unlock(&svc_fd_lock); 184 rwlock_unlock(&svc_fd_lock);
158 return (TRUE); 185 return (TRUE);
159 186
160out: 187out:
161 rwlock_unlock(&svc_fd_lock); 188 rwlock_unlock(&svc_fd_lock);
162 return (FALSE); 189 return (FALSE);
163} 190}
164 191
165void 192void
166xprt_unregister(SVCXPRT *xprt) 193xprt_unregister(SVCXPRT *xprt)
167{ 194{
168 __xprt_do_unregister(xprt, TRUE); 195 __xprt_do_unregister(xprt, TRUE);
169} 196}
170 197
171void 198void
172__xprt_unregister_unlocked(SVCXPRT *xprt) 199__xprt_unregister_unlocked(SVCXPRT *xprt)
173{ 200{
174 __xprt_do_unregister(xprt, FALSE); 201 __xprt_do_unregister(xprt, FALSE);
175} 202}
176 203
177/* 204/*
178 * De-activate a transport handle.  205 * De-activate a transport handle.
179 */ 206 */
180static void 207static void
181__xprt_do_unregister(SVCXPRT *xprt, bool_t dolock) 208__xprt_do_unregister(SVCXPRT *xprt, bool_t dolock)
182{  209{
183 int sock; 210 int sock, *fdmax;
184 211
185 _DIAGASSERT(xprt != NULL); 212 _DIAGASSERT(xprt != NULL);
186 213
187 sock = xprt->xp_fd; 
188 
189 if (dolock) 214 if (dolock)
190 rwlock_wrlock(&svc_fd_lock); 215 rwlock_wrlock(&svc_fd_lock);
191 if ((sock < FD_SETSIZE) && (__svc_xports[sock] == xprt)) { 216
192 __svc_xports[sock] = NULL; 217 sock = xprt->xp_fd;
193 FD_CLR(sock, get_fdset()); 218 if (sock >= __svc_maxxports || __svc_xports[sock] != xprt)
194 if (sock >= *get_fdsetmax()) { 219 goto out;
195 for ((*get_fdsetmax())--; *get_fdsetmax() >= 0; 220
196 (*get_fdsetmax())--) 221 __svc_xports[sock] = NULL;
197 if (__svc_xports[*get_fdsetmax()]) 222 if (sock == -1)
198 break; 223 goto out;
199 } 224 fdmax = svc_fdset_getmax();
200 } 225 if (sock < *fdmax)
 226 goto clr;
 227
 228 for ((*fdmax)--; *fdmax >= 0; (*fdmax)--)
 229 if (__svc_xports[*fdmax])
 230 break;
 231clr:
 232 svc_fdset_clr(sock);
 233out:
201 if (dolock) 234 if (dolock)
202 rwlock_unlock(&svc_fd_lock); 235 rwlock_unlock(&svc_fd_lock);
203} 236}
204 237
205/* 238/*
206 * Add a service program to the callout list. 239 * Add a service program to the callout list.
207 * The dispatch routine will be called when a rpc request for this 240 * The dispatch routine will be called when a rpc request for this
208 * program number comes in. 241 * program number comes in.
209 */ 242 */
210bool_t 243bool_t
211svc_reg(SVCXPRT *xprt, const rpcprog_t prog, const rpcvers_t vers, 244svc_reg(SVCXPRT *xprt, const rpcprog_t prog, const rpcvers_t vers,
212 void (*dispatch)(struct svc_req *, SVCXPRT *), 245 void (*dispatch)(struct svc_req *, SVCXPRT *),
213 const struct netconfig *nconf) 246 const struct netconfig *nconf)
@@ -590,53 +623,59 @@ svcerr_progvers(SVCXPRT *xprt, rpcvers_t @@ -590,53 +623,59 @@ svcerr_progvers(SVCXPRT *xprt, rpcvers_t
590 * the "cooked" credentials (rqst->rq_clntcred). 623 * the "cooked" credentials (rqst->rq_clntcred).
591 * However, this function does not know the structure of the cooked 624 * However, this function does not know the structure of the cooked
592 * credentials, so it make the following assumptions:  625 * credentials, so it make the following assumptions:
593 * a) the structure is contiguous (no pointers), and 626 * a) the structure is contiguous (no pointers), and
594 * b) the cred structure size does not exceed RQCRED_SIZE bytes.  627 * b) the cred structure size does not exceed RQCRED_SIZE bytes.
595 * In all events, all three parameters are freed upon exit from this routine. 628 * In all events, all three parameters are freed upon exit from this routine.
596 * The storage is trivially management on the call stack in user land, but 629 * The storage is trivially management on the call stack in user land, but
597 * is mallocated in kernel land. 630 * is mallocated in kernel land.
598 */ 631 */
599 632
600void 633void
601svc_getreq(int rdfds) 634svc_getreq(int rdfds)
602{ 635{
603 fd_set readfds; 636 fd_set *readfds = svc_fdset_copy(NULL);
604 637
605 FD_ZERO(&readfds); 638 readfds->fds_bits[0] = (unsigned int)rdfds;
606 readfds.fds_bits[0] = (unsigned int)rdfds; 639 svc_getreqset(readfds);
607 svc_getreqset(&readfds); 640 free(readfds);
608} 641}
609 642
610void 643void
611svc_getreqset(fd_set *readfds) 644svc_getreqset2(fd_set *readfds, int maxsize)
612{ 645{
613 uint32_t mask, *maskp; 646 uint32_t mask, *maskp;
614 int sock, bit, fd; 647 int sock, bit, fd;
615 648
616 _DIAGASSERT(readfds != NULL); 649 _DIAGASSERT(readfds != NULL);
617 650
618 maskp = readfds->fds_bits; 651 maskp = readfds->fds_bits;
619 for (sock = 0; sock < FD_SETSIZE; sock += NFDBITS) { 652 for (sock = 0; sock < maxsize; sock += NFDBITS) {
620 for (mask = *maskp++; (bit = ffs((int)mask)) != 0; 653 for (mask = *maskp++; (bit = ffs((int)mask)) != 0;
621 mask ^= (1 << (bit - 1))) { 654 mask ^= (1 << (bit - 1))) {
622 /* sock has input waiting */ 655 /* sock has input waiting */
623 fd = sock + bit - 1; 656 fd = sock + bit - 1;
624 svc_getreq_common(fd); 657 svc_getreq_common(fd);
625 } 658 }
626 } 659 }
627} 660}
628 661
629void 662void
 663svc_getreqset(fd_set *readfds)
 664{
 665 svc_getreqset2(readfds, FD_SETSIZE);
 666}
 667
 668void
630svc_getreq_common(int fd) 669svc_getreq_common(int fd)
631{ 670{
632 SVCXPRT *xprt; 671 SVCXPRT *xprt;
633 struct svc_req r; 672 struct svc_req r;
634 struct rpc_msg msg; 673 struct rpc_msg msg;
635 int prog_found; 674 int prog_found;
636 rpcvers_t low_vers; 675 rpcvers_t low_vers;
637 rpcvers_t high_vers; 676 rpcvers_t high_vers;
638 enum xprt_stat stat; 677 enum xprt_stat stat;
639 char cred_area[2*MAX_AUTH_BYTES + RQCRED_SIZE]; 678 char cred_area[2*MAX_AUTH_BYTES + RQCRED_SIZE];
640 679
641 msg.rm_call.cb_cred.oa_base = cred_area; 680 msg.rm_call.cb_cred.oa_base = cred_area;
642 msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]); 681 msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]);
@@ -730,27 +769,27 @@ svc_getreq_poll(struct pollfd *pfdp, int @@ -730,27 +769,27 @@ svc_getreq_poll(struct pollfd *pfdp, int
730 /* 769 /*
731 * We assume that this function is only called 770 * We assume that this function is only called
732 * via someone select()ing from svc_fdset or 771 * via someone select()ing from svc_fdset or
733 * pollts()ing from svc_pollset[]. Thus it's safe 772 * pollts()ing from svc_pollset[]. Thus it's safe
734 * to handle the POLLNVAL event by simply turning 773 * to handle the POLLNVAL event by simply turning
735 * the corresponding bit off in svc_fdset. The 774 * the corresponding bit off in svc_fdset. The
736 * svc_pollset[] array is derived from svc_fdset 775 * svc_pollset[] array is derived from svc_fdset
737 * and so will also be updated eventually. 776 * and so will also be updated eventually.
738 * 777 *
739 * XXX Should we do an xprt_unregister() instead? 778 * XXX Should we do an xprt_unregister() instead?
740 */ 779 */
741 if (p->revents & POLLNVAL) { 780 if (p->revents & POLLNVAL) {
742 rwlock_wrlock(&svc_fd_lock); 781 rwlock_wrlock(&svc_fd_lock);
743 FD_CLR(p->fd, get_fdset()); 782 svc_fdset_clr(p->fd);
744 rwlock_unlock(&svc_fd_lock); 783 rwlock_unlock(&svc_fd_lock);
745 } else 784 } else
746 svc_getreq_common(p->fd); 785 svc_getreq_common(p->fd);
747 } 786 }
748 } 787 }
749} 788}
750 789
751bool_t 790bool_t
752rpc_control(int what, void *arg) 791rpc_control(int what, void *arg)
753{ 792{
754 int val; 793 int val;
755 794
756 switch (what) { 795 switch (what) {

cvs diff -r1.1 -r1.2 src/lib/libc/rpc/svc_fdset.c (expand / switch to unified diff)

--- src/lib/libc/rpc/svc_fdset.c 2013/03/05 19:55:23 1.1
+++ src/lib/libc/rpc/svc_fdset.c 2015/11/06 19:34:13 1.2
@@ -1,63 +1,300 @@ @@ -1,63 +1,300 @@
1/* $NetBSD: svc_fdset.c,v 1.1 2013/03/05 19:55:23 christos Exp $ */ 1/* $NetBSD: svc_fdset.c,v 1.2 2015/11/06 19:34:13 christos Exp $ */
2 2
3#include <sys/cdefs.h> 3#include <sys/cdefs.h>
4__RCSID("$NetBSD: svc_fdset.c,v 1.1 2013/03/05 19:55:23 christos Exp $"); 4__RCSID("$NetBSD: svc_fdset.c,v 1.2 2015/11/06 19:34:13 christos Exp $");
 5
 6
 7#include "reentrant.h"
 8
 9#include <sys/fd_set.h>
 10
 11#include <rpc/rpc.h>
5 12
6#include <pthread.h> 
7#include <stdlib.h> 13#include <stdlib.h>
8#include <string.h> 14#include <string.h>
9#include <sys/select.h> 
10 15
11#include "svc_fdset.h" 16struct svc_fdset {
 17 fd_set *fdset;
 18 int fdmax;
 19 int fdsize;
 20};
 21
 22
 23/* The single threaded, one global fd_set version */
 24static fd_set *__svc_fdset;
 25static int svc_fdsize = 0;
 26
 27/*
 28 * Update the old global svc_fdset if needed for binary compatibility
 29 */
 30#define COMPAT_UPDATE(a) \
 31 do \
 32 if ((a) == __svc_fdset) \
 33 svc_fdset = *__svc_fdset; \
 34 while (/*CONSTCOND*/0)
 35
 36static thread_key_t fdsetkey = -2;
 37
 38#ifdef FDSET_DEBUG
 39#include <stdio.h>
 40#include <stdarg.h>
 41#include <unistd.h>
 42#include <lwp.h>
 43
 44static void __printflike(3, 0)
 45svc_header(const char *func, size_t line, const char *fmt, va_list ap)
 46{
 47 fprintf(stderr, "%s[%d.%d]: %s, %zu: ", getprogname(), (int)getpid(),
 48 (int)_lwp_self(), func, line);
 49 vfprintf(stderr, fmt, ap);
 50 va_end(ap);
 51}
 52
 53static void __printflike(5, 6)
 54svc_fdset_print(const char *func, size_t line, const fd_set *fds, int fdmax,
 55 const char *fmt, ...)
 56{
 57 va_list ap;
 58 const char *did = "";
 59
 60 va_start(ap, fmt);
 61 svc_header(func, line, fmt, ap);
 62 va_end(ap);
 63
 64 if (fdmax == 0)
 65 fdmax = FD_SETSIZE;
 66
 67 fprintf(stderr, "%p[%d] <", fds, fdmax);
 68 for (int i = 0; i <= fdmax; i++) {
 69 if (!FD_ISSET(i, fds))
 70 continue;
 71 fprintf(stderr, "%s%d", did, i);
 72 did = ", ";
 73 }
 74 fprintf(stderr, ">\n");
 75}
 76
 77static void __printflike(3, 4)
 78svc_print(const char *func, size_t line, const char *fmt, ...)
 79{
 80 va_list ap;
 81
 82 va_start(ap, fmt);
 83 svc_header(func, line, fmt, ap);
 84 va_end(ap);
 85 fprintf(stderr, "\n");
 86}
 87
 88#define DPRINTF_FDSET(...) svc_fdset_print(__func__, __LINE__, __VA_ARGS__)
 89#define DPRINTF(...) svc_print(__func__, __LINE__, __VA_ARGS__)
 90#else
 91#define DPRINTF_FDSET(...)
 92#define DPRINTF(...)
 93#endif
 94
 95
 96static void
 97svc_fdset_free(void *v)
 98{
 99 struct svc_fdset *rv = v;
 100 DPRINTF_FDSET(rv->fdset, 0, "free");
 101
 102 free(rv->fdset);
 103 free(rv);
 104}
 105
 106static fd_set *
 107svc_fdset_resize(int fd, fd_set **fdset, int *fdsize)
 108{
 109 if (*fdset && fd < *fdsize) {
 110 DPRINTF_FDSET(*fdset, 0, "keeping %d < %d",
 111 fd, *fdsize);
 112 return *fdset;
 113 }
 114
 115 fd += FD_SETSIZE;
 116 if (fd == 517)
 117 abort();
 118
 119 char *newfdset = realloc(*fdset, __NFD_BYTES(fd));
 120 if (newfdset == NULL)
 121 return NULL;
 122
 123 memset(newfdset + __NFD_BYTES(*fdsize), 0,
 124 __NFD_BYTES(fd) - __NFD_BYTES(*fdsize));
 125
 126
 127 *fdset = (void *)newfdset;
 128 DPRINTF_FDSET(*fdset, 0, "resize %d > %d", fd, *fdsize);
 129 *fdsize = fd;
 130
 131 COMPAT_UPDATE(*fdset);
 132
 133 return *fdset;
 134}
 135
 136static struct svc_fdset *
 137svc_fdset_alloc(int fd)
 138{
 139 struct svc_fdset *rv;
 140
 141 if (fdsetkey == -1)
 142 thr_keycreate(&fdsetkey, svc_fdset_free);
 143
 144 if ((rv = thr_getspecific(fdsetkey)) == NULL) {
 145
 146 rv = calloc(1, sizeof(*rv));
 147 if (rv == NULL)
 148 return NULL;
 149
 150 (void)thr_setspecific(fdsetkey, rv);
 151
 152 if (svc_fdsize != 0) {
 153 rv->fdset = __svc_fdset;
 154 DPRINTF("switching to %p", rv->fdset);
 155 rv->fdmax = svc_maxfd;
 156 rv->fdsize = svc_fdsize;
 157
 158 svc_fdsize = 0;
 159 } else {
 160 DPRINTF("first thread time %p", rv->fdset);
 161 }
 162 } else {
 163 DPRINTF("again for %p", rv->fdset);
 164 if (fd < rv->fdsize)
 165 return rv;
 166 }
 167 if (svc_fdset_resize(fd, &rv->fdset, &rv->fdsize) == NULL)
 168 return NULL;
 169 return rv;
 170}
 171
 172static fd_set *
 173svc_fdset_get_internal(int fd)
 174{
 175 struct svc_fdset *rv;
 176
 177 if (!__isthreaded || fdsetkey == -2)
 178 return svc_fdset_resize(fd, &__svc_fdset, &svc_fdsize);
 179
 180 rv = svc_fdset_alloc(fd);
 181 if (rv == NULL)
 182 return NULL;
 183 return rv->fdset;
 184}
 185
12 186
13static pthread_key_t fdsetkey; 187/* allow each thread to have their own copy */
14static pthread_key_t fdmaxkey; 188void
15static fd_set thefdset; 189svc_fdset_init(int flags)
16static int thefdmax; 190{
 191 DPRINTF("%x", flags);
 192 if ((flags & SVC_FDSET_MT) && fdsetkey == -2)
 193 fdsetkey = -1;
 194}
17 195
18void 196void
19init_fdsets(void) 197svc_fdset_zero(void)
20{ 198{
 199 DPRINTF("zero");
 200 fd_set *fds = svc_fdset_get_internal(0);
 201 int size = svc_fdset_getsize(0);
 202 memset(fds, 0, __NFD_BYTES(size));
 203 *svc_fdset_getmax() = 0;
 204
 205 COMPAT_UPDATE(fds);
21 206
22 pthread_key_create(&fdsetkey, NULL); 
23 pthread_key_create(&fdmaxkey, NULL); 
24} 207}
25 208
26void 209void
27alloc_fdset(void) 210svc_fdset_set(int fd)
28{ 211{
29 fd_set *fdsetti; 212 fd_set *fds = svc_fdset_get_internal(fd);
30 int *fdmax; 213 int *fdmax = svc_fdset_getmax();
 214 FD_SET(fd, fds);
 215 if (fd > *fdmax)
 216 *fdmax = fd;
 217 DPRINTF_FDSET(fds, *fdmax, "%d", fd);
31 218
32 fdsetti = malloc(sizeof(*fdsetti)); 219 COMPAT_UPDATE(fds);
33 memset(fdsetti, 0, sizeof(*fdsetti)); 220}
34 pthread_setspecific(fdsetkey, fdsetti); 221
35 222int
36 fdmax = malloc(sizeof(*fdmax)); 223svc_fdset_isset(int fd)
37 memset(fdmax, 0, sizeof(*fdmax)); 224{
38 pthread_setspecific(fdmaxkey, fdmax); 225 fd_set *fds = svc_fdset_get_internal(fd);
 226 DPRINTF_FDSET(fds, 0, "%d", fd);
 227 return FD_ISSET(fd, fds);
 228}
 229
 230void
 231svc_fdset_clr(int fd)
 232{
 233 fd_set *fds = svc_fdset_get_internal(fd);
 234 FD_CLR(fd, fds);
 235 /* XXX: update fdmax? */
 236 DPRINTF_FDSET(fds, 0, "%d", fd);
 237
 238 COMPAT_UPDATE(fds);
39} 239}
40 240
41fd_set * 241fd_set *
42get_fdset(void) 242svc_fdset_copy(const fd_set *orig)
43{ 243{
44 fd_set *rv; 244 int len, fdmax;
 245 fd_set *fds;
 246
 247 len = 0;
 248 fds = 0;
 249 fdmax = *svc_fdset_getmax();
 250
 251 DPRINTF_FDSET(orig, 0, "[orig]");
 252 fds = svc_fdset_resize(fdmax, &fds, &len);
 253 if (fds == NULL)
 254 return NULL;
 255
 256 if (orig)
 257 memcpy(fds, orig, __NFD_BYTES(fdmax));
 258 DPRINTF_FDSET(fds, 0, "[copy]");
 259 return fds;
 260}
45 261
46 rv = pthread_getspecific(fdsetkey); 262fd_set *
47 if (rv) 263svc_fdset_get(void)
48 return rv; 264{
49 else 265 fd_set *fds = svc_fdset_get_internal(0);
50 return &thefdset; 266 DPRINTF_FDSET(fds, 0, "get");
 267 return fds;
51} 268}
52 269
53int * 270int *
54get_fdsetmax(void) 271svc_fdset_getmax(void)
 272{
 273 struct svc_fdset *rv;
 274
 275 if (!__isthreaded || fdsetkey == -2)
 276 return &svc_maxfd;
 277
 278 rv = svc_fdset_alloc(0);
 279 if (rv == NULL)
 280 return NULL;
 281 return &rv->fdmax;
 282}
 283
 284int
 285svc_fdset_getsize(int fd)
55{ 286{
56 int *rv; 287 struct svc_fdset *rv;
57 288
58 rv = pthread_getspecific(fdmaxkey); 289 if (!__isthreaded || fdsetkey == -2) {
59 if (rv) 290 if (svc_fdset_resize(fd, &__svc_fdset, &svc_fdsize) == NULL)
60 return rv; 291 return -1;
61 else 292 else
62 return &thefdmax; 293 return svc_fdsize;
 294 }
 295
 296 rv = svc_fdset_alloc(fd);
 297 if (rv == NULL)
 298 return -1;
 299 return rv->fdsize;
63} 300}

cvs diff -r1.1 -r1.2 src/lib/libc/rpc/svc_fdset.h (expand / switch to unified diff)

--- src/lib/libc/rpc/svc_fdset.h 2013/03/05 19:55:23 1.1
+++ src/lib/libc/rpc/svc_fdset.h 2015/11/06 19:34:13 1.2
@@ -1,30 +1,18 @@ @@ -1,30 +1,18 @@
1/* $NetBSD: svc_fdset.h,v 1.1 2013/03/05 19:55:23 christos Exp $ */ 1/* $NetBSD: svc_fdset.h,v 1.2 2015/11/06 19:34:13 christos Exp $ */
2 
3#ifndef _LIBC 
4 
5void init_fdsets(void); 
6void alloc_fdset(void); 
7fd_set *get_fdset(void); 
8int *get_fdsetmax(void); 
9 2
10# ifdef RUMP_RPC 3# ifdef RUMP_RPC
11# include <rump/rump.h> 4# include <rump/rump.h>
12# include <rump/rump_syscalls.h> 5# include <rump/rump_syscalls.h>
13# undef close 6# undef close
14# define close(a) rump_sys_close(a) 7# define close(a) rump_sys_close(a)
15# undef fcntl 8# undef fcntl
16# define fcntl(a, b, c) rump_sys_fcntl(a, b, c) 9# define fcntl(a, b, c) rump_sys_fcntl(a, b, c)
17# undef read 10# undef read
18# define read(a, b, c) rump_sys_read(a, b, c) 11# define read(a, b, c) rump_sys_read(a, b, c)
19# undef write 12# undef write
20# define write(a, b, c) rump_sys_write(a, b, c) 13# define write(a, b, c) rump_sys_write(a, b, c)
21# undef pollts 14# undef pollts
22# define pollts(a, b, c, d) rump_sys_pollts(a, b, c, d) 15# define pollts(a, b, c, d) rump_sys_pollts(a, b, c, d)
23# undef select 16# undef select
24# define select(a, b, c, d, e) rump_sys_select(a, b, c, d, e) 17# define select(a, b, c, d, e) rump_sys_select(a, b, c, d, e)
25# endif 18# endif
26 
27#else 
28# define get_fdset() (&svc_fdset) 
29# define get_fdsetmax() (&svc_maxfd) 
30#endif 

cvs diff -r1.30 -r1.31 src/lib/libc/rpc/svc_vc.c (expand / switch to unified diff)

--- src/lib/libc/rpc/svc_vc.c 2013/03/11 20:19:29 1.30
+++ src/lib/libc/rpc/svc_vc.c 2015/11/06 19:34:13 1.31
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: svc_vc.c,v 1.30 2013/03/11 20:19:29 tron Exp $ */ 1/* $NetBSD: svc_vc.c,v 1.31 2015/11/06 19:34:13 christos Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2010, Oracle America, Inc. 4 * Copyright (c) 2010, Oracle America, Inc.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are 7 * modification, are permitted provided that the following conditions are
8 * met: 8 * met:
9 * 9 *
10 * * Redistributions of source code must retain the above copyright 10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above 12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following 13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials 14 * disclaimer in the documentation and/or other materials
@@ -27,27 +27,27 @@ @@ -27,27 +27,27 @@
27 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */ 32 */
33 33
34#include <sys/cdefs.h> 34#include <sys/cdefs.h>
35#if defined(LIBC_SCCS) && !defined(lint) 35#if defined(LIBC_SCCS) && !defined(lint)
36#if 0 36#if 0
37static char *sccsid = "@(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro"; 37static char *sccsid = "@(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro";
38static char *sccsid = "@(#)svc_tcp.c 2.2 88/08/01 4.0 RPCSRC"; 38static char *sccsid = "@(#)svc_tcp.c 2.2 88/08/01 4.0 RPCSRC";
39#else 39#else
40__RCSID("$NetBSD: svc_vc.c,v 1.30 2013/03/11 20:19:29 tron Exp $"); 40__RCSID("$NetBSD: svc_vc.c,v 1.31 2015/11/06 19:34:13 christos Exp $");
41#endif 41#endif
42#endif 42#endif
43 43
44/* 44/*
45 * svc_vc.c, Server side for Connection Oriented based RPC.  45 * svc_vc.c, Server side for Connection Oriented based RPC.
46 * 46 *
47 * Actually implements two flavors of transporter - 47 * Actually implements two flavors of transporter -
48 * a tcp rendezvouser (a listner and connection establisher) 48 * a tcp rendezvouser (a listner and connection establisher)
49 * and a record/tcp stream. 49 * and a record/tcp stream.
50 */ 50 */
51 51
52#include "namespace.h" 52#include "namespace.h"
53#include "reentrant.h" 53#include "reentrant.h"
@@ -302,45 +302,46 @@ out: @@ -302,45 +302,46 @@ out:
302} 302}
303 303
304/*ARGSUSED*/ 304/*ARGSUSED*/
305static bool_t 305static bool_t
306rendezvous_request(SVCXPRT *xprt, struct rpc_msg *msg) 306rendezvous_request(SVCXPRT *xprt, struct rpc_msg *msg)
307{ 307{
308 int sock, flags; 308 int sock, flags;
309 struct cf_rendezvous *r; 309 struct cf_rendezvous *r;
310 struct cf_conn *cd; 310 struct cf_conn *cd;
311 struct sockaddr_storage addr; 311 struct sockaddr_storage addr;
312 socklen_t len; 312 socklen_t len;
313 struct __rpc_sockinfo si; 313 struct __rpc_sockinfo si;
314 SVCXPRT *newxprt; 314 SVCXPRT *newxprt;
315 fd_set cleanfds; 
316 315
317 _DIAGASSERT(xprt != NULL); 316 _DIAGASSERT(xprt != NULL);
318 _DIAGASSERT(msg != NULL); 317 _DIAGASSERT(msg != NULL);
319 318
320 r = (struct cf_rendezvous *)xprt->xp_p1; 319 r = (struct cf_rendezvous *)xprt->xp_p1;
321again: 320again:
322 len = sizeof addr; 321 len = sizeof addr;
323 if ((sock = accept(xprt->xp_fd, (struct sockaddr *)(void *)&addr, 322 if ((sock = accept(xprt->xp_fd, (struct sockaddr *)(void *)&addr,
324 &len)) < 0) { 323 &len)) < 0) {
325 if (errno == EINTR) 324 if (errno == EINTR)
326 goto again; 325 goto again;
327 /* 326 /*
328 * Clean out the most idle file descriptor when we're 327 * Clean out the most idle file descriptor when we're
329 * running out. 328 * running out.
330 */ 329 */
331 if (errno == EMFILE || errno == ENFILE) { 330 if (errno == EMFILE || errno == ENFILE) {
332 cleanfds = *get_fdset(); 331 fd_set *cleanfds = svc_fdset_copy(svc_fdset_get());
333 if (__svc_clean_idle(&cleanfds, 0, FALSE)) 332 int rv = __svc_clean_idle(cleanfds, 0, FALSE);
 333 free(cleanfds);
 334 if (rv)
334 goto again; 335 goto again;
335 } 336 }
336 return FALSE; 337 return FALSE;
337 } 338 }
338 /* 339 /*
339 * make a new transporter (re-uses xprt) 340 * make a new transporter (re-uses xprt)
340 */ 341 */
341 newxprt = makefd_xprt(sock, r->sendsize, r->recvsize); 342 newxprt = makefd_xprt(sock, r->sendsize, r->recvsize);
342 if (newxprt == NULL) 343 if (newxprt == NULL)
343 goto out; 344 goto out;
344 newxprt->xp_rtaddr.buf = mem_alloc(len); 345 newxprt->xp_rtaddr.buf = mem_alloc(len);
345 if (newxprt->xp_rtaddr.buf == NULL) 346 if (newxprt->xp_rtaddr.buf == NULL)
346 goto out; 347 goto out;
@@ -750,54 +751,59 @@ svc_vc_rendezvous_ops(SVCXPRT *xprt) @@ -750,54 +751,59 @@ svc_vc_rendezvous_ops(SVCXPRT *xprt)
750 xprt->xp_ops = &ops; 751 xprt->xp_ops = &ops;
751 xprt->xp_ops2 = &ops2; 752 xprt->xp_ops2 = &ops2;
752 mutex_unlock(&ops_lock); 753 mutex_unlock(&ops_lock);
753} 754}
754 755
755/* 756/*
756 * Destroy xprts that have not have had any activity in 'timeout' seconds. 757 * Destroy xprts that have not have had any activity in 'timeout' seconds.
757 * If 'cleanblock' is true, blocking connections (the default) are also 758 * If 'cleanblock' is true, blocking connections (the default) are also
758 * cleaned. If timeout is 0, the least active connection is picked. 759 * cleaned. If timeout is 0, the least active connection is picked.
759 */ 760 */
760bool_t 761bool_t
761__svc_clean_idle(fd_set *fds, int timeout, bool_t cleanblock) 762__svc_clean_idle(fd_set *fds, int timeout, bool_t cleanblock)
762{ 763{
763 int i, ncleaned; 764 int i, ncleaned, fdmax;
764 SVCXPRT *xprt, *least_active; 765 SVCXPRT *xprt, *least_active;
765 struct timeval tv, tdiff, tmax; 766 struct timeval tv, tdiff, tmax;
766 struct cf_conn *cd; 767 struct cf_conn *cd;
767 768
768 gettimeofday(&tv, NULL); 769 gettimeofday(&tv, NULL);
769 tmax.tv_sec = tmax.tv_usec = 0; 770 tmax.tv_sec = tmax.tv_usec = 0;
770 least_active = NULL; 771 least_active = NULL;
771 rwlock_wrlock(&svc_fd_lock); 772 rwlock_wrlock(&svc_fd_lock);
772 for (i = ncleaned = 0; i <= svc_maxfd; i++) { 773 fdmax = *svc_fdset_getmax();
773 if (FD_ISSET(i, fds)) { 774 for (i = ncleaned = 0; i <= fdmax; i++) {
774 xprt = __svc_xports[i]; 775 if (!svc_fdset_isset(i))
775 if (xprt == NULL || xprt->xp_ops == NULL || 776 continue;
776 xprt->xp_ops->xp_recv != svc_vc_recv) 777
777 continue; 778 xprt = __svc_xports[i];
778 cd = (struct cf_conn *)xprt->xp_p1; 779 if (xprt == NULL || xprt->xp_ops == NULL ||
779 if (!cleanblock && !cd->nonblock) 780 xprt->xp_ops->xp_recv != svc_vc_recv)
780 continue; 781 continue;
781 if (timeout == 0) { 782
782 timersub(&tv, &cd->last_recv_time, &tdiff); 783 cd = (struct cf_conn *)xprt->xp_p1;
783 if (timercmp(&tdiff, &tmax, >)) { 784 if (!cleanblock && !cd->nonblock)
784 tmax = tdiff; 785 continue;
785 least_active = xprt; 786
786 } 787 if (timeout == 0) {
787 continue; 788 timersub(&tv, &cd->last_recv_time, &tdiff);
788 } 789 if (timercmp(&tdiff, &tmax, >)) {
789 if (tv.tv_sec - cd->last_recv_time.tv_sec > timeout) { 790 tmax = tdiff;
790 __xprt_unregister_unlocked(xprt); 791 least_active = xprt;
791 __svc_vc_dodestroy(xprt); 
792 ncleaned++; 
793 } 792 }
 793 continue;
 794 }
 795
 796 if (tv.tv_sec - cd->last_recv_time.tv_sec > timeout) {
 797 __xprt_unregister_unlocked(xprt);
 798 __svc_vc_dodestroy(xprt);
 799 ncleaned++;
794 } 800 }
795 } 801 }
796 if (timeout == 0 && least_active != NULL) { 802 if (timeout == 0 && least_active != NULL) {
797 __xprt_unregister_unlocked(least_active); 803 __xprt_unregister_unlocked(least_active);
798 __svc_vc_dodestroy(least_active); 804 __svc_vc_dodestroy(least_active);
799 ncleaned++; 805 ncleaned++;
800 } 806 }
801 rwlock_unlock(&svc_fd_lock); 807 rwlock_unlock(&svc_fd_lock);
802 return ncleaned > 0 ? TRUE : FALSE; 808 return ncleaned > 0 ? TRUE : FALSE;
803} 809}