Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F152436379
D42597.id130081.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
16 KB
Referenced Files
None
Subscribers
None
D42597.id130081.diff
View Options
diff --git a/include/rpc/rpc_com.h b/include/rpc/rpc_com.h
--- a/include/rpc/rpc_com.h
+++ b/include/rpc/rpc_com.h
@@ -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 **);
diff --git a/lib/libc/rpc/clnt_dg.c b/lib/libc/rpc/clnt_dg.c
--- a/lib/libc/rpc/clnt_dg.c
+++ b/lib/libc/rpc/clnt_dg.c
@@ -48,9 +48,11 @@
#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 <stdlib.h>
#include <string.h>
@@ -89,28 +91,75 @@
* 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) 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;
+ int lock;
+ cond_t cv;
+};
+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;
+ cond_init(&elem->cv, 0, 0);
+ RB_INSERT(dg_fd_list, &dg_fd_head, elem);
+ }
+ return (elem);
+}
+
+static void
+release_fd_lock(int fd, sigset_t mask)
+{
+ struct dg_fd *elem;
+ struct dg_fd key;
+
+ key.fd = fd;
+ mutex_lock(&clnt_fd_lock);
+ elem = RB_FIND(dg_fd_list, &dg_fd_head, &key);
+ assert(elem != NULL);
+ elem->lock = 0;
+ mutex_unlock(&clnt_fd_lock);
+ thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
+ cond_signal(&elem->cv);
}
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
@@ -168,47 +217,9 @@
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);
@@ -329,6 +340,7 @@
struct timespec ts;
struct kevent kv;
struct sockaddr *sa;
+ struct dg_fd *elem;
sigset_t mask;
sigset_t newmask;
socklen_t salen;
@@ -340,13 +352,14 @@
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);
+ while (elem->lock)
+ cond_wait(&elem->cv, &clnt_fd_lock);
if (__isthreaded)
rpc_lock_value = 1;
else
rpc_lock_value = 0;
- dg_fd_locks[cu->cu_fd] = rpc_lock_value;
+ elem->lock = rpc_lock_value;
mutex_unlock(&clnt_fd_lock);
if (cu->cu_total.tv_usec == -1) {
timeout = utimeout; /* use supplied timeout */
@@ -617,6 +630,7 @@
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;
@@ -625,13 +639,14 @@
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);
+ while (elem->lock)
+ cond_wait(&elem->cv, &clnt_fd_lock);
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]);
+ cond_signal(&elem->cv);
return (dummy);
}
@@ -646,6 +661,7 @@
{
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;
@@ -653,13 +669,14 @@
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);
+ while (elem->lock)
+ cond_wait(&elem->cv, &clnt_fd_lock);
if (__isthreaded)
rpc_lock_value = 1;
else
rpc_lock_value = 0;
- dg_fd_locks[cu->cu_fd] = rpc_lock_value;
+ elem->lock = rpc_lock_value;
mutex_unlock(&clnt_fd_lock);
switch (request) {
case CLSET_FD_CLOSE:
@@ -788,6 +805,7 @@
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;
@@ -795,8 +813,9 @@
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);
+ while (elem->lock)
+ cond_wait(&elem->cv, &clnt_fd_lock);
if (cu->cu_closeit)
(void)_close(cu_fd);
if (cu->cu_kq >= 0)
@@ -810,7 +829,7 @@
mem_free(cl, sizeof (CLIENT));
mutex_unlock(&clnt_fd_lock);
thr_sigsetmask(SIG_SETMASK, &mask, NULL);
- cond_signal(&dg_cv[cu_fd]);
+ cond_signal(&elem->cv);
}
static struct clnt_ops *
diff --git a/lib/libc/rpc/clnt_vc.c b/lib/libc/rpc/clnt_vc.c
--- a/lib/libc/rpc/clnt_vc.c
+++ b/lib/libc/rpc/clnt_vc.c
@@ -60,6 +60,7 @@
#include <sys/poll.h>
#include <sys/syslog.h>
#include <sys/socket.h>
+#include <sys/tree.h>
#include <sys/un.h>
#include <sys/uio.h>
@@ -120,22 +121,69 @@
* 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) 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;
+ int lock;
+ cond_t cv;
+};
+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;
+ cond_init(&elem->cv, 0, 0);
+ RB_INSERT(vc_fd_list, &vc_fd_head, elem);
+ }
+ return (elem);
+}
+
+static void
+release_fd_lock(int fd, sigset_t mask)
+{
+ struct vc_fd *elem;
+ struct vc_fd key;
+
+ key.fd = fd;
+ mutex_lock(&clnt_fd_lock);
+ elem = RB_FIND(vc_fd_list, &vc_fd_head, &key);
+ assert(elem != NULL);
+ elem->lock = 0;
+ mutex_unlock(&clnt_fd_lock);
+ thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
+ cond_signal(&elem->cv);
}
static const char clnt_vc_errstr[] = "%s : %s";
@@ -169,8 +217,6 @@
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;
@@ -188,39 +234,6 @@
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?
@@ -231,19 +244,16 @@
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;
@@ -318,6 +328,7 @@
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;
@@ -331,13 +342,14 @@
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);
+ while (elem->lock)
+ cond_wait(&elem->cv, &clnt_fd_lock);
if (__isthreaded)
rpc_lock_value = 1;
else
rpc_lock_value = 0;
- vc_fd_locks[ct->ct_fd] = rpc_lock_value;
+ elem->lock = rpc_lock_value;
mutex_unlock(&clnt_fd_lock);
if (!ct->ct_waitset) {
/* If time is not within limits, we ignore it. */
@@ -471,6 +483,7 @@
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;
@@ -484,13 +497,14 @@
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);
+ while (elem->lock)
+ cond_wait(&elem->cv, &clnt_fd_lock);
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]);
+ cond_signal(&elem->cv);
return dummy;
}
@@ -519,6 +533,7 @@
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;
@@ -531,13 +546,14 @@
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);
+ while (elem->lock)
+ cond_wait(&elem->cv, &clnt_fd_lock);
if (__isthreaded)
rpc_lock_value = 1;
else
rpc_lock_value = 0;
- vc_fd_locks[ct->ct_fd] = rpc_lock_value;
+ elem->lock = rpc_lock_value;
mutex_unlock(&clnt_fd_lock);
switch (request) {
@@ -637,6 +653,7 @@
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;
@@ -648,8 +665,9 @@
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);
+ while (elem->lock)
+ cond_wait(&elem->cv, &clnt_fd_lock);
if (ct->ct_closeit && ct->ct_fd != -1) {
(void)_close(ct->ct_fd);
}
@@ -663,7 +681,7 @@
mem_free(cl, sizeof(CLIENT));
mutex_unlock(&clnt_fd_lock);
thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
- cond_signal(&vc_cv[ct_fd]);
+ cond_signal(&elem->cv);
}
/*
diff --git a/lib/libc/rpc/rpc_com.h b/lib/libc/rpc/rpc_com.h
--- a/lib/libc/rpc/rpc_com.h
+++ b/lib/libc/rpc/rpc_com.h
@@ -59,7 +59,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 **);
diff --git a/lib/libc/rpc/rpc_generic.c b/lib/libc/rpc/rpc_generic.c
--- a/lib/libc/rpc/rpc_generic.c
+++ b/lib/libc/rpc/rpc_generic.c
@@ -104,29 +104,6 @@
#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
diff --git a/sys/rpc/rpc_com.h b/sys/rpc/rpc_com.h
--- a/sys/rpc/rpc_com.h
+++ b/sys/rpc/rpc_com.h
@@ -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 **);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Apr 15, 11:12 PM (55 m, 20 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31542565
Default Alt Text
D42597.id130081.diff (16 KB)
Attached To
Mode
D42597: libc/libc/rpc: refactor some global variables
Attached
Detach File
Event Timeline
Log In to Comment