libc/libc/rpc: refactor some global variables

* Combine dg_fd_locks and dg_cv into one array.
* Similarly for vc_fd_locks and vc_cv
* Turn some macros into inline functions

This is a mostly cosmetic change to make refactoring these strutures in
a future commit easier.

Sponsored by:	Axcient
Reviewed by:	kib
Differential Revision: https://reviews.freebsd.org/D42597

(cherry picked from commit a5c2f4e939)

lib/libc/rpc: switch the per-fd structs in clnt_{dg,vc}.c to RB Trees

This saves oodles of memory, especially when "ulimit -n" is large.  It
also prevents a buffer overflow if getrlimit should fail.

Also replace per-fd condvars with mutexes to simplify the code.

PR:		274968
Sponsored by:	Axcient
Reviewed by:	kib
Differential Revision: https://reviews.freebsd.org/D42597

(cherry picked from commit 24938f9311)
This commit is contained in:
Alan Somers 2023-11-09 15:58:56 -07:00
parent 8b7963aeb5
commit ad8b59ffe7
6 changed files with 168 additions and 207 deletions

View file

@ -58,7 +58,6 @@
__BEGIN_DECLS
extern u_int __rpc_get_a_size(int);
extern int __rpc_dtbsize(void);
extern int _rpc_dtablesize(void);
extern struct netconfig * __rpcgettp(int);
extern int __rpc_get_default_domain(char **);

View file

@ -49,13 +49,17 @@ static char sccsid[] = "@(#)clnt_dg.c 1.19 89/03/16 Copyr 1988 Sun Micro";
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/tree.h>
#include <arpa/inet.h>
#include <rpc/rpc.h>
#include <rpc/rpcsec_gss.h>
#include <assert.h>
#include <errno.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <stdbool.h>
#include <unistd.h>
#include <err.h>
#include "un-namespace.h"
@ -90,28 +94,65 @@ static void clnt_dg_destroy(CLIENT *);
* This machinery implements per-fd locks for MT-safety. It is not
* sufficient to do per-CLIENT handle locks for MT-safety because a
* user may create more than one CLIENT handle with the same fd behind
* it. Therefore, we allocate an array of flags (dg_fd_locks), protected
* by the clnt_fd_lock mutex, and an array (dg_cv) of condition variables
* similarly protected. Dg_fd_lock[fd] == 1 => a call is active on some
* CLIENT handle created for that fd.
* The current implementation holds locks across the entire RPC and reply,
* including retransmissions. Yes, this is silly, and as soon as this
* code is proven to work, this should be the first thing fixed. One step
* at a time.
* it. Therefore, we allocate an associative array of flags and condition
* variables (dg_fd). The flags and the array are protected by the
* clnt_fd_lock mutex. dg_fd[fd].lock == 1 => a call is active on some
* CLIENT handle created for that fd. The current implementation holds
* locks across the entire RPC and reply, including retransmissions. Yes,
* this is silly, and as soon as this code is proven to work, this should
* be the first thing fixed. One step at a time.
*/
static int *dg_fd_locks;
static cond_t *dg_cv;
#define release_fd_lock(fd, mask) { \
mutex_lock(&clnt_fd_lock); \
dg_fd_locks[fd] = 0; \
mutex_unlock(&clnt_fd_lock); \
thr_sigsetmask(SIG_SETMASK, &(mask), NULL); \
cond_signal(&dg_cv[fd]); \
struct dg_fd {
RB_ENTRY(dg_fd) dg_link;
int fd;
mutex_t mtx;
};
static inline int
cmp_dg_fd(struct dg_fd *a, struct dg_fd *b)
{
if (a->fd > b->fd) {
return (1);
} else if (a->fd < b->fd) {
return (-1);
} else {
return (0);
}
}
RB_HEAD(dg_fd_list, dg_fd);
RB_PROTOTYPE(dg_fd_list, dg_fd, dg_link, cmp_dg_fd);
RB_GENERATE(dg_fd_list, dg_fd, dg_link, cmp_dg_fd);
struct dg_fd_list dg_fd_head = RB_INITIALIZER(&dg_fd_head);
/*
* Find the lock structure for the given file descriptor, or initialize it if
* it does not already exist. The clnt_fd_lock mutex must be held.
*/
static struct dg_fd *
dg_fd_find(int fd)
{
struct dg_fd key, *elem;
key.fd = fd;
elem = RB_FIND(dg_fd_list, &dg_fd_head, &key);
if (elem == NULL) {
elem = calloc(1, sizeof(*elem));
elem->fd = fd;
mutex_init(&elem->mtx, NULL);
RB_INSERT(dg_fd_list, &dg_fd_head, elem);
}
return (elem);
}
static void
release_fd_lock(struct dg_fd *elem, sigset_t mask)
{
mutex_unlock(&elem->mtx);
thr_sigsetmask(SIG_SETMASK, &mask, NULL);
}
static const char mem_err_clnt_dg[] = "clnt_dg_create: out of memory";
/* VARIABLES PROTECTED BY clnt_fd_lock: dg_fd_locks, dg_cv */
/* VARIABLES PROTECTED BY clnt_fd_lock: dg_fd */
#define MCALL_MSG_SIZE 24
@ -169,47 +210,9 @@ clnt_dg_create(int fd, const struct netbuf *svcaddr, rpcprog_t program,
struct cu_data *cu = NULL; /* private data */
struct timeval now;
struct rpc_msg call_msg;
sigset_t mask;
sigset_t newmask;
struct __rpc_sockinfo si;
int one = 1;
sigfillset(&newmask);
thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
mutex_lock(&clnt_fd_lock);
if (dg_fd_locks == (int *) NULL) {
int cv_allocsz;
size_t fd_allocsz;
int dtbsize = __rpc_dtbsize();
fd_allocsz = dtbsize * sizeof (int);
dg_fd_locks = (int *) mem_alloc(fd_allocsz);
if (dg_fd_locks == (int *) NULL) {
mutex_unlock(&clnt_fd_lock);
thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
goto err1;
} else
memset(dg_fd_locks, '\0', fd_allocsz);
cv_allocsz = dtbsize * sizeof (cond_t);
dg_cv = (cond_t *) mem_alloc(cv_allocsz);
if (dg_cv == (cond_t *) NULL) {
mem_free(dg_fd_locks, fd_allocsz);
dg_fd_locks = (int *) NULL;
mutex_unlock(&clnt_fd_lock);
thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
goto err1;
} else {
int i;
for (i = 0; i < dtbsize; i++)
cond_init(&dg_cv[i], 0, (void *) 0);
}
}
mutex_unlock(&clnt_fd_lock);
thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
if (svcaddr == NULL) {
rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
return (NULL);
@ -330,25 +333,21 @@ clnt_dg_call(CLIENT *cl, rpcproc_t proc, xdrproc_t xargs, void *argsp,
struct timespec ts;
struct kevent kv;
struct sockaddr *sa;
struct dg_fd *elem;
sigset_t mask;
sigset_t newmask;
socklen_t salen;
ssize_t recvlen = 0;
int kin_len, n, rpc_lock_value;
int kin_len, n;
u_int32_t xid;
outlen = 0;
sigfillset(&newmask);
thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
mutex_lock(&clnt_fd_lock);
while (dg_fd_locks[cu->cu_fd])
cond_wait(&dg_cv[cu->cu_fd], &clnt_fd_lock);
if (__isthreaded)
rpc_lock_value = 1;
else
rpc_lock_value = 0;
dg_fd_locks[cu->cu_fd] = rpc_lock_value;
elem = dg_fd_find(cu->cu_fd);
mutex_unlock(&clnt_fd_lock);
mutex_lock(&elem->mtx);
if (cu->cu_total.tv_usec == -1) {
timeout = utimeout; /* use supplied timeout */
} else {
@ -602,7 +601,7 @@ clnt_dg_call(CLIENT *cl, rpcproc_t proc, xdrproc_t xargs, void *argsp,
if (cu->cu_kq >= 0)
_close(cu->cu_kq);
cu->cu_kq = -1;
release_fd_lock(cu->cu_fd, mask);
release_fd_lock(elem, mask);
return (cu->cu_error.re_status);
}
@ -618,6 +617,7 @@ static bool_t
clnt_dg_freeres(CLIENT *cl, xdrproc_t xdr_res, void *res_ptr)
{
struct cu_data *cu = (struct cu_data *)cl->cl_private;
struct dg_fd *elem;
XDR *xdrs = &(cu->cu_outxdrs);
bool_t dummy;
sigset_t mask;
@ -626,13 +626,12 @@ clnt_dg_freeres(CLIENT *cl, xdrproc_t xdr_res, void *res_ptr)
sigfillset(&newmask);
thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
mutex_lock(&clnt_fd_lock);
while (dg_fd_locks[cu->cu_fd])
cond_wait(&dg_cv[cu->cu_fd], &clnt_fd_lock);
elem = dg_fd_find(cu->cu_fd);
mutex_lock(&elem->mtx);
xdrs->x_op = XDR_FREE;
dummy = (*xdr_res)(xdrs, res_ptr);
mutex_unlock(&clnt_fd_lock);
thr_sigsetmask(SIG_SETMASK, &mask, NULL);
cond_signal(&dg_cv[cu->cu_fd]);
release_fd_lock(elem, mask);
return (dummy);
}
@ -647,41 +646,36 @@ clnt_dg_control(CLIENT *cl, u_int request, void *info)
{
struct cu_data *cu = (struct cu_data *)cl->cl_private;
struct netbuf *addr;
struct dg_fd *elem;
sigset_t mask;
sigset_t newmask;
int rpc_lock_value;
sigfillset(&newmask);
thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
mutex_lock(&clnt_fd_lock);
while (dg_fd_locks[cu->cu_fd])
cond_wait(&dg_cv[cu->cu_fd], &clnt_fd_lock);
if (__isthreaded)
rpc_lock_value = 1;
else
rpc_lock_value = 0;
dg_fd_locks[cu->cu_fd] = rpc_lock_value;
elem = dg_fd_find(cu->cu_fd);
mutex_unlock(&clnt_fd_lock);
mutex_lock(&elem->mtx);
switch (request) {
case CLSET_FD_CLOSE:
cu->cu_closeit = TRUE;
release_fd_lock(cu->cu_fd, mask);
release_fd_lock(elem, mask);
return (TRUE);
case CLSET_FD_NCLOSE:
cu->cu_closeit = FALSE;
release_fd_lock(cu->cu_fd, mask);
release_fd_lock(elem, mask);
return (TRUE);
}
/* for other requests which use info */
if (info == NULL) {
release_fd_lock(cu->cu_fd, mask);
release_fd_lock(elem, mask);
return (FALSE);
}
switch (request) {
case CLSET_TIMEOUT:
if (time_not_ok((struct timeval *)info)) {
release_fd_lock(cu->cu_fd, mask);
release_fd_lock(elem, mask);
return (FALSE);
}
cu->cu_total = *(struct timeval *)info;
@ -695,7 +689,7 @@ clnt_dg_control(CLIENT *cl, u_int request, void *info)
break;
case CLSET_RETRY_TIMEOUT:
if (time_not_ok((struct timeval *)info)) {
release_fd_lock(cu->cu_fd, mask);
release_fd_lock(elem, mask);
return (FALSE);
}
cu->cu_wait = *(struct timeval *)info;
@ -715,7 +709,7 @@ clnt_dg_control(CLIENT *cl, u_int request, void *info)
case CLSET_SVC_ADDR: /* set to new address */
addr = (struct netbuf *)info;
if (addr->len < sizeof cu->cu_raddr) {
release_fd_lock(cu->cu_fd, mask);
release_fd_lock(elem, mask);
return (FALSE);
}
(void) memcpy(&cu->cu_raddr, addr->buf, addr->len);
@ -778,10 +772,10 @@ clnt_dg_control(CLIENT *cl, u_int request, void *info)
cu->cu_connect = *(int *)info;
break;
default:
release_fd_lock(cu->cu_fd, mask);
release_fd_lock(elem, mask);
return (FALSE);
}
release_fd_lock(cu->cu_fd, mask);
release_fd_lock(elem, mask);
return (TRUE);
}
@ -789,6 +783,7 @@ static void
clnt_dg_destroy(CLIENT *cl)
{
struct cu_data *cu = (struct cu_data *)cl->cl_private;
struct dg_fd *elem;
int cu_fd = cu->cu_fd;
sigset_t mask;
sigset_t newmask;
@ -796,8 +791,8 @@ clnt_dg_destroy(CLIENT *cl)
sigfillset(&newmask);
thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
mutex_lock(&clnt_fd_lock);
while (dg_fd_locks[cu_fd])
cond_wait(&dg_cv[cu_fd], &clnt_fd_lock);
elem = dg_fd_find(cu_fd);
mutex_lock(&elem->mtx);
if (cu->cu_closeit)
(void)_close(cu_fd);
if (cu->cu_kq >= 0)
@ -810,8 +805,7 @@ clnt_dg_destroy(CLIENT *cl)
mem_free(cl->cl_tp, strlen(cl->cl_tp) +1);
mem_free(cl, sizeof (CLIENT));
mutex_unlock(&clnt_fd_lock);
thr_sigsetmask(SIG_SETMASK, &mask, NULL);
cond_signal(&dg_cv[cu_fd]);
release_fd_lock(elem, mask);
}
static struct clnt_ops *

View file

@ -61,6 +61,7 @@ static char sccsid3[] = "@(#)clnt_vc.c 1.19 89/03/16 Copyr 1988 Sun Micro";
#include <sys/poll.h>
#include <sys/syslog.h>
#include <sys/socket.h>
#include <sys/tree.h>
#include <sys/un.h>
#include <sys/uio.h>
@ -69,7 +70,9 @@ static char sccsid3[] = "@(#)clnt_vc.c 1.19 89/03/16 Copyr 1988 Sun Micro";
#include <err.h>
#include <errno.h>
#include <netdb.h>
#include <pthread.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@ -121,22 +124,60 @@ struct ct_data {
* This machinery implements per-fd locks for MT-safety. It is not
* sufficient to do per-CLIENT handle locks for MT-safety because a
* user may create more than one CLIENT handle with the same fd behind
* it. Therefore, we allocate an array of flags (vc_fd_locks), protected
* by the clnt_fd_lock mutex, and an array (vc_cv) of condition variables
* similarly protected. Vc_fd_lock[fd] == 1 => a call is active on some
* CLIENT handle created for that fd.
* The current implementation holds locks across the entire RPC and reply.
* Yes, this is silly, and as soon as this code is proven to work, this
* should be the first thing fixed. One step at a time.
* it. Therefore, we allocate an associative array of flags and condition
* variables (vc_fd). The flags and the array are protected by the
* clnt_fd_lock mutex. vc_fd_lock[fd] == 1 => a call is active on some
* CLIENT handle created for that fd. The current implementation holds
* locks across the entire RPC and reply. Yes, this is silly, and as soon
* as this code is proven to work, this should be the first thing fixed.
* One step at a time.
*/
static int *vc_fd_locks;
static cond_t *vc_cv;
#define release_fd_lock(fd, mask) { \
mutex_lock(&clnt_fd_lock); \
vc_fd_locks[fd] = 0; \
mutex_unlock(&clnt_fd_lock); \
thr_sigsetmask(SIG_SETMASK, &(mask), (sigset_t *) NULL); \
cond_signal(&vc_cv[fd]); \
struct vc_fd {
RB_ENTRY(vc_fd) vc_link;
int fd;
mutex_t mtx;
};
static inline int
cmp_vc_fd(struct vc_fd *a, struct vc_fd *b)
{
if (a->fd > b->fd) {
return (1);
} else if (a->fd < b->fd) {
return (-1);
} else {
return (0);
}
}
RB_HEAD(vc_fd_list, vc_fd);
RB_PROTOTYPE(vc_fd_list, vc_fd, vc_link, cmp_vc_fd);
RB_GENERATE(vc_fd_list, vc_fd, vc_link, cmp_vc_fd);
struct vc_fd_list vc_fd_head = RB_INITIALIZER(&vc_fd_head);
/*
* Find the lock structure for the given file descriptor, or initialize it if
* it does not already exist. The clnt_fd_lock mutex must be held.
*/
static struct vc_fd *
vc_fd_find(int fd)
{
struct vc_fd key, *elem;
key.fd = fd;
elem = RB_FIND(vc_fd_list, &vc_fd_head, &key);
if (elem == NULL) {
elem = calloc(1, sizeof(*elem));
elem->fd = fd;
mutex_init(&elem->mtx, NULL);
RB_INSERT(vc_fd_list, &vc_fd_head, elem);
}
return (elem);
}
static void
release_fd_lock(struct vc_fd *elem, sigset_t mask)
{
mutex_unlock(&elem->mtx);
thr_sigsetmask(SIG_SETMASK, &mask, NULL);
}
static const char clnt_vc_errstr[] = "%s : %s";
@ -170,8 +211,6 @@ clnt_vc_create(int fd, const struct netbuf *raddr, const rpcprog_t prog,
struct timeval now;
struct rpc_msg call_msg;
static u_int32_t disrupt;
sigset_t mask;
sigset_t newmask;
struct sockaddr_storage ss;
socklen_t slen;
struct __rpc_sockinfo si;
@ -189,39 +228,6 @@ clnt_vc_create(int fd, const struct netbuf *raddr, const rpcprog_t prog,
goto err;
}
ct->ct_addr.buf = NULL;
sigfillset(&newmask);
thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
mutex_lock(&clnt_fd_lock);
if (vc_fd_locks == (int *) NULL) {
int cv_allocsz, fd_allocsz;
int dtbsize = __rpc_dtbsize();
fd_allocsz = dtbsize * sizeof (int);
vc_fd_locks = (int *) mem_alloc(fd_allocsz);
if (vc_fd_locks == (int *) NULL) {
mutex_unlock(&clnt_fd_lock);
thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
goto err;
} else
memset(vc_fd_locks, '\0', fd_allocsz);
assert(vc_cv == (cond_t *) NULL);
cv_allocsz = dtbsize * sizeof (cond_t);
vc_cv = (cond_t *) mem_alloc(cv_allocsz);
if (vc_cv == (cond_t *) NULL) {
mem_free(vc_fd_locks, fd_allocsz);
vc_fd_locks = (int *) NULL;
mutex_unlock(&clnt_fd_lock);
thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
goto err;
} else {
int i;
for (i = 0; i < dtbsize; i++)
cond_init(&vc_cv[i], 0, (void *) 0);
}
} else
assert(vc_cv != (cond_t *) NULL);
/*
* XXX - fvdl connecting while holding a mutex?
@ -232,19 +238,16 @@ clnt_vc_create(int fd, const struct netbuf *raddr, const rpcprog_t prog,
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
rpc_createerr.cf_error.re_errno = errno;
mutex_unlock(&clnt_fd_lock);
thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
goto err;
}
if (_connect(fd, (struct sockaddr *)raddr->buf, raddr->len) < 0){
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
rpc_createerr.cf_error.re_errno = errno;
mutex_unlock(&clnt_fd_lock);
thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
goto err;
}
}
mutex_unlock(&clnt_fd_lock);
thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
if (!__rpc_fd2sockinfo(fd, &si))
goto err;
@ -319,12 +322,12 @@ clnt_vc_call(CLIENT *cl, rpcproc_t proc, xdrproc_t xdr_args, void *args_ptr,
struct ct_data *ct = (struct ct_data *) cl->cl_private;
XDR *xdrs = &(ct->ct_xdrs);
struct rpc_msg reply_msg;
struct vc_fd *elem;
u_int32_t x_id;
u_int32_t *msg_x_id = &ct->ct_u.ct_mcalli; /* yuk */
bool_t shipnow;
int refreshes = 2;
sigset_t mask, newmask;
int rpc_lock_value;
bool_t reply_stat;
assert(cl != NULL);
@ -332,14 +335,9 @@ clnt_vc_call(CLIENT *cl, rpcproc_t proc, xdrproc_t xdr_args, void *args_ptr,
sigfillset(&newmask);
thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
mutex_lock(&clnt_fd_lock);
while (vc_fd_locks[ct->ct_fd])
cond_wait(&vc_cv[ct->ct_fd], &clnt_fd_lock);
if (__isthreaded)
rpc_lock_value = 1;
else
rpc_lock_value = 0;
vc_fd_locks[ct->ct_fd] = rpc_lock_value;
elem = vc_fd_find(ct->ct_fd);
mutex_unlock(&clnt_fd_lock);
mutex_lock(&elem->mtx);
if (!ct->ct_waitset) {
/* If time is not within limits, we ignore it. */
if (time_not_ok(&timeout) == FALSE)
@ -363,7 +361,7 @@ clnt_vc_call(CLIENT *cl, rpcproc_t proc, xdrproc_t xdr_args, void *args_ptr,
if (ct->ct_error.re_status == RPC_SUCCESS)
ct->ct_error.re_status = RPC_CANTENCODEARGS;
(void)xdrrec_endofrecord(xdrs, TRUE);
release_fd_lock(ct->ct_fd, mask);
release_fd_lock(elem, mask);
return (ct->ct_error.re_status);
}
} else {
@ -374,23 +372,23 @@ clnt_vc_call(CLIENT *cl, rpcproc_t proc, xdrproc_t xdr_args, void *args_ptr,
if (ct->ct_error.re_status == RPC_SUCCESS)
ct->ct_error.re_status = RPC_CANTENCODEARGS;
(void)xdrrec_endofrecord(xdrs, TRUE);
release_fd_lock(ct->ct_fd, mask);
release_fd_lock(elem, mask);
return (ct->ct_error.re_status);
}
}
if (! xdrrec_endofrecord(xdrs, shipnow)) {
release_fd_lock(ct->ct_fd, mask);
release_fd_lock(elem, mask);
return (ct->ct_error.re_status = RPC_CANTSEND);
}
if (! shipnow) {
release_fd_lock(ct->ct_fd, mask);
release_fd_lock(elem, mask);
return (RPC_SUCCESS);
}
/*
* Hack to provide rpc-based message passing
*/
if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
release_fd_lock(ct->ct_fd, mask);
release_fd_lock(elem, mask);
return(ct->ct_error.re_status = RPC_TIMEDOUT);
}
@ -404,14 +402,14 @@ clnt_vc_call(CLIENT *cl, rpcproc_t proc, xdrproc_t xdr_args, void *args_ptr,
reply_msg.acpted_rply.ar_results.where = NULL;
reply_msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_void;
if (! xdrrec_skiprecord(xdrs)) {
release_fd_lock(ct->ct_fd, mask);
release_fd_lock(elem, mask);
return (ct->ct_error.re_status);
}
/* now decode and validate the response header */
if (! xdr_replymsg(xdrs, &reply_msg)) {
if (ct->ct_error.re_status == RPC_SUCCESS)
continue;
release_fd_lock(ct->ct_fd, mask);
release_fd_lock(elem, mask);
return (ct->ct_error.re_status);
}
if (reply_msg.rm_xid == x_id)
@ -452,7 +450,7 @@ clnt_vc_call(CLIENT *cl, rpcproc_t proc, xdrproc_t xdr_args, void *args_ptr,
if (refreshes-- && AUTH_REFRESH(cl->cl_auth, &reply_msg))
goto call_again;
} /* end of unsuccessful completion */
release_fd_lock(ct->ct_fd, mask);
release_fd_lock(elem, mask);
return (ct->ct_error.re_status);
}
@ -472,6 +470,7 @@ static bool_t
clnt_vc_freeres(CLIENT *cl, xdrproc_t xdr_res, void *res_ptr)
{
struct ct_data *ct;
struct vc_fd *elem;
XDR *xdrs;
bool_t dummy;
sigset_t mask;
@ -485,14 +484,13 @@ clnt_vc_freeres(CLIENT *cl, xdrproc_t xdr_res, void *res_ptr)
sigfillset(&newmask);
thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
mutex_lock(&clnt_fd_lock);
while (vc_fd_locks[ct->ct_fd])
cond_wait(&vc_cv[ct->ct_fd], &clnt_fd_lock);
elem = vc_fd_find(ct->ct_fd);
mutex_lock(&elem->mtx);
xdrs->x_op = XDR_FREE;
dummy = (*xdr_res)(xdrs, res_ptr);
mutex_unlock(&clnt_fd_lock);
thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
cond_signal(&vc_cv[ct->ct_fd]);
mutex_unlock(&clnt_fd_lock);
release_fd_lock(elem, mask);
return dummy;
}
@ -520,10 +518,10 @@ static bool_t
clnt_vc_control(CLIENT *cl, u_int request, void *info)
{
struct ct_data *ct;
struct vc_fd *elem;
void *infop = info;
sigset_t mask;
sigset_t newmask;
int rpc_lock_value;
assert(cl != NULL);
@ -532,23 +530,18 @@ clnt_vc_control(CLIENT *cl, u_int request, void *info)
sigfillset(&newmask);
thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
mutex_lock(&clnt_fd_lock);
while (vc_fd_locks[ct->ct_fd])
cond_wait(&vc_cv[ct->ct_fd], &clnt_fd_lock);
if (__isthreaded)
rpc_lock_value = 1;
else
rpc_lock_value = 0;
vc_fd_locks[ct->ct_fd] = rpc_lock_value;
elem = vc_fd_find(ct->ct_fd);
mutex_unlock(&clnt_fd_lock);
mutex_lock(&elem->mtx);
switch (request) {
case CLSET_FD_CLOSE:
ct->ct_closeit = TRUE;
release_fd_lock(ct->ct_fd, mask);
release_fd_lock(elem, mask);
return (TRUE);
case CLSET_FD_NCLOSE:
ct->ct_closeit = FALSE;
release_fd_lock(ct->ct_fd, mask);
release_fd_lock(elem, mask);
return (TRUE);
default:
break;
@ -556,13 +549,13 @@ clnt_vc_control(CLIENT *cl, u_int request, void *info)
/* for other requests which use info */
if (info == NULL) {
release_fd_lock(ct->ct_fd, mask);
release_fd_lock(elem, mask);
return (FALSE);
}
switch (request) {
case CLSET_TIMEOUT:
if (time_not_ok((struct timeval *)info)) {
release_fd_lock(ct->ct_fd, mask);
release_fd_lock(elem, mask);
return (FALSE);
}
ct->ct_wait = *(struct timeval *)infop;
@ -582,7 +575,7 @@ clnt_vc_control(CLIENT *cl, u_int request, void *info)
*(struct netbuf *)info = ct->ct_addr;
break;
case CLSET_SVC_ADDR: /* set to new address */
release_fd_lock(ct->ct_fd, mask);
release_fd_lock(elem, mask);
return (FALSE);
case CLGET_XID:
/*
@ -626,10 +619,10 @@ clnt_vc_control(CLIENT *cl, u_int request, void *info)
break;
default:
release_fd_lock(ct->ct_fd, mask);
release_fd_lock(elem, mask);
return (FALSE);
}
release_fd_lock(ct->ct_fd, mask);
release_fd_lock(elem, mask);
return (TRUE);
}
@ -638,6 +631,7 @@ static void
clnt_vc_destroy(CLIENT *cl)
{
struct ct_data *ct = (struct ct_data *) cl->cl_private;
struct vc_fd *elem;
int ct_fd = ct->ct_fd;
sigset_t mask;
sigset_t newmask;
@ -649,8 +643,8 @@ clnt_vc_destroy(CLIENT *cl)
sigfillset(&newmask);
thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
mutex_lock(&clnt_fd_lock);
while (vc_fd_locks[ct_fd])
cond_wait(&vc_cv[ct_fd], &clnt_fd_lock);
elem = vc_fd_find(ct_fd);
mutex_lock(&elem->mtx);
if (ct->ct_closeit && ct->ct_fd != -1) {
(void)_close(ct->ct_fd);
}
@ -663,8 +657,7 @@ clnt_vc_destroy(CLIENT *cl)
mem_free(cl->cl_tp, strlen(cl->cl_tp) +1);
mem_free(cl, sizeof(CLIENT));
mutex_unlock(&clnt_fd_lock);
thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
cond_signal(&vc_cv[ct_fd]);
release_fd_lock(elem, mask);
}
/*

View file

@ -60,7 +60,6 @@
__BEGIN_DECLS
extern u_int __rpc_get_a_size(int);
extern int __rpc_dtbsize(void);
extern struct netconfig * __rpcgettp(int);
extern int __rpc_get_default_domain(char **);

View file

@ -105,29 +105,6 @@ static char *strlocase(char *);
#endif
static int getnettype(const char *);
/*
* Cache the result of getrlimit(), so we don't have to do an
* expensive call every time.
*/
int
__rpc_dtbsize(void)
{
static int tbsize;
struct rlimit rl;
if (tbsize) {
return (tbsize);
}
if (getrlimit(RLIMIT_NOFILE, &rl) == 0) {
return (tbsize = (int)rl.rlim_max);
}
/*
* Something wrong. I'll try to save face by returning a
* pessimistic number.
*/
return (32);
}
/*
* Find the appropriate buffer size

View file

@ -70,7 +70,6 @@
__BEGIN_DECLS
#ifndef _KERNEL
extern u_int __rpc_get_a_size(int);
extern int __rpc_dtbsize(void);
extern struct netconfig * __rpcgettp(int);
extern int __rpc_get_default_domain(char **);