Merged update from upstream sources

This is an automated DistroBaker update from upstream sources.
If you do not know what this is about or would like to opt out,
contact the OSCI team.

Source: https://src.fedoraproject.org/rpms/libtirpc.git#d640290d69629029dca65fea90f451c1f0f90ac2
This commit is contained in:
DistroBaker 2020-12-03 22:48:53 +00:00
parent eb42696d1a
commit ec4c32c97f
4 changed files with 8 additions and 927 deletions

4
.gitignore vendored
View File

@ -1,5 +1,5 @@
Makefile Makefile
cscope* cscope*
x86_64/ x86_64/
libtirpc-1.2.6 /libtirpc-1.3.1.tar.bz2
/libtirpc-1.2.6.tar.bz2 libtirpc-1.3.1

View File

@ -1,920 +0,0 @@
diff --git a/libtirpc.pc.in b/libtirpc.pc.in
index 38034c5..d2c7878 100644
--- a/libtirpc.pc.in
+++ b/libtirpc.pc.in
@@ -7,6 +7,6 @@ Name: libtirpc
Description: Transport Independent RPC Library
Requires:
Version: @PACKAGE_VERSION@
-Libs: -L@libdir@ -ltirpc
+Libs: -L${libdir} -ltirpc
Libs.private: -lpthread
-Cflags: -I@includedir@/tirpc
+Cflags: -I${includedir}/tirpc
diff --git a/src/clnt_dg.c b/src/clnt_dg.c
index eb5467f..abc09f1 100644
--- a/src/clnt_dg.c
+++ b/src/clnt_dg.c
@@ -53,6 +53,7 @@
#include <unistd.h>
#include <err.h>
#include "rpc_com.h"
+#include "clnt_fd_locks.h"
#ifdef IP_RECVERR
#include <asm/types.h>
@@ -78,24 +79,28 @@ 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. Therfore, 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 activte on some
- * CLIENT handle created for that fd.
+ * it.
+ *
+ * We keep track of a list of per-fd locks, protected by the clnt_fd_lock
+ * mutex. Each per-fd lock consists of a predicate indicating whether is
+ * active or not: fd_lock->active == TRUE => a call is active on some
+ * CLIENT handle created for that fd. Each fd predicate is guarded by a
+ * condition variable so that the global mutex can be unlocked while
+ * waiting for the predicate to change.
+ *
* 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 fd_locks_t *dg_fd_locks;
extern mutex_t clnt_fd_lock;
-static cond_t *dg_cv;
-#define release_fd_lock(fd, mask) { \
+#define release_fd_lock(fd_lock, mask) { \
mutex_lock(&clnt_fd_lock); \
- dg_fd_locks[fd] = 0; \
+ fd_lock->active = FALSE; \
mutex_unlock(&clnt_fd_lock); \
thr_sigsetmask(SIG_SETMASK, &(mask), NULL); \
- cond_signal(&dg_cv[fd]); \
+ cond_signal(&fd_lock->cv); \
}
static const char mem_err_clnt_dg[] = "clnt_dg_create: out of memory";
@@ -107,6 +112,7 @@ static const char mem_err_clnt_dg[] = "clnt_dg_create: out of memory";
*/
struct cu_data {
int cu_fd; /* connections fd */
+ fd_lock_t *cu_fd_lock;
bool_t cu_closeit; /* opened by library */
struct sockaddr_storage cu_raddr; /* remote address */
int cu_rlen;
@@ -155,47 +161,20 @@ clnt_dg_create(fd, svcaddr, program, version, sendsz, recvsz)
sigset_t newmask;
struct __rpc_sockinfo si;
int one = 1;
+ fd_lock_t *fd_lock;
sigfillset(&newmask);
thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
mutex_lock(&clnt_fd_lock);
- if (dg_fd_locks == (int *) NULL) {
- size_t cv_allocsz, fd_allocsz;
- unsigned int dtbsize = __rpc_dtbsize();
-
- if ( (size_t) dtbsize > SIZE_MAX/sizeof(cond_t)) {
- mutex_unlock(&clnt_fd_lock);
- thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
- errno = EOVERFLOW;
- goto err1;
- }
-
- 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);
- errno = ENOMEM;
- 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);
- errno = ENOMEM;
+ if (dg_fd_locks == (fd_locks_t *) NULL) {
+ dg_fd_locks = fd_locks_init();
+ if (dg_fd_locks == (fd_locks_t *) NULL) {
goto err1;
- } else {
- int i;
-
- for (i = 0; i < dtbsize; i++)
- cond_init(&dg_cv[i], 0, (void *) 0);
}
}
+ fd_lock = fd_lock_create(fd, dg_fd_locks);
+ if (fd_lock == (fd_lock_t *) NULL)
+ goto err1;
mutex_unlock(&clnt_fd_lock);
thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
@@ -274,6 +253,7 @@ clnt_dg_create(fd, svcaddr, program, version, sendsz, recvsz)
*/
cu->cu_closeit = FALSE;
cu->cu_fd = fd;
+ cu->cu_fd_lock = fd_lock;
cl->cl_ops = clnt_dg_ops();
cl->cl_private = (caddr_t)(void *)cu;
cl->cl_auth = authnone_create();
@@ -319,17 +299,15 @@ clnt_dg_call(cl, proc, xargs, argsp, xresults, resultsp, utimeout)
sigset_t newmask;
socklen_t salen;
ssize_t recvlen = 0;
- int rpc_lock_value;
u_int32_t xid, inval, outval;
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);
- rpc_lock_value = 1;
- dg_fd_locks[cu->cu_fd] = rpc_lock_value;
+ while (cu->cu_fd_lock->active)
+ cond_wait(&cu->cu_fd_lock->cv, &clnt_fd_lock);
+ cu->cu_fd_lock->active = TRUE;
mutex_unlock(&clnt_fd_lock);
if (cu->cu_total.tv_usec == -1) {
timeout = utimeout; /* use supplied timeout */
@@ -473,7 +451,7 @@ get_reply:
mem_free(cbuf, (outlen + 256));
e = (struct sock_extended_err *) CMSG_DATA(cmsg);
cu->cu_error.re_errno = e->ee_errno;
- release_fd_lock(cu->cu_fd, mask);
+ release_fd_lock(cu->cu_fd_lock, mask);
return (cu->cu_error.re_status = RPC_CANTRECV);
}
mem_free(cbuf, (outlen + 256));
@@ -553,7 +531,7 @@ get_reply:
}
out:
- release_fd_lock(cu->cu_fd, mask);
+ release_fd_lock(cu->cu_fd_lock, mask);
return (cu->cu_error.re_status);
}
@@ -582,13 +560,14 @@ clnt_dg_freeres(cl, xdr_res, 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);
+ while (cu->cu_fd_lock->active)
+ cond_wait(&cu->cu_fd_lock->cv, &clnt_fd_lock);
+ cu->cu_fd_lock->active = TRUE;
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(&cu->cu_fd_lock->cv);
return (dummy);
}
@@ -609,36 +588,34 @@ clnt_dg_control(cl, request, info)
struct netbuf *addr;
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);
- rpc_lock_value = 1;
- dg_fd_locks[cu->cu_fd] = rpc_lock_value;
+ while (cu->cu_fd_lock->active)
+ cond_wait(&cu->cu_fd_lock->cv, &clnt_fd_lock);
+ cu->cu_fd_lock->active = TRUE;
mutex_unlock(&clnt_fd_lock);
switch (request) {
case CLSET_FD_CLOSE:
cu->cu_closeit = TRUE;
- release_fd_lock(cu->cu_fd, mask);
+ release_fd_lock(cu->cu_fd_lock, mask);
return (TRUE);
case CLSET_FD_NCLOSE:
cu->cu_closeit = FALSE;
- release_fd_lock(cu->cu_fd, mask);
+ release_fd_lock(cu->cu_fd_lock, mask);
return (TRUE);
}
/* for other requests which use info */
if (info == NULL) {
- release_fd_lock(cu->cu_fd, mask);
+ release_fd_lock(cu->cu_fd_lock, 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(cu->cu_fd_lock, mask);
return (FALSE);
}
cu->cu_total = *(struct timeval *)info;
@@ -652,7 +629,7 @@ clnt_dg_control(cl, request, info)
break;
case CLSET_RETRY_TIMEOUT:
if (time_not_ok((struct timeval *)info)) {
- release_fd_lock(cu->cu_fd, mask);
+ release_fd_lock(cu->cu_fd_lock, mask);
return (FALSE);
}
cu->cu_wait = *(struct timeval *)info;
@@ -672,7 +649,7 @@ clnt_dg_control(cl, request, 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(cu->cu_fd_lock, mask);
return (FALSE);
}
(void) memcpy(&cu->cu_raddr, addr->buf, addr->len);
@@ -735,10 +712,10 @@ clnt_dg_control(cl, request, info)
cu->cu_connect = *(int *)info;
break;
default:
- release_fd_lock(cu->cu_fd, mask);
+ release_fd_lock(cu->cu_fd_lock, mask);
return (FALSE);
}
- release_fd_lock(cu->cu_fd, mask);
+ release_fd_lock(cu->cu_fd_lock, mask);
return (TRUE);
}
@@ -748,14 +725,15 @@ clnt_dg_destroy(cl)
{
struct cu_data *cu = (struct cu_data *)cl->cl_private;
int cu_fd = cu->cu_fd;
+ fd_lock_t *cu_fd_lock = cu->cu_fd_lock;
sigset_t mask;
sigset_t newmask;
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);
+ while (cu_fd_lock->active)
+ cond_wait(&cu_fd_lock->cv, &clnt_fd_lock);
if (cu->cu_closeit)
(void)close(cu_fd);
XDR_DESTROY(&(cu->cu_outxdrs));
@@ -765,9 +743,10 @@ clnt_dg_destroy(cl)
if (cl->cl_tp && cl->cl_tp[0])
mem_free(cl->cl_tp, strlen(cl->cl_tp) +1);
mem_free(cl, sizeof (CLIENT));
+ cond_signal(&cu_fd_lock->cv);
+ fd_lock_destroy(cu_fd, cu_fd_lock, dg_fd_locks);
mutex_unlock(&clnt_fd_lock);
thr_sigsetmask(SIG_SETMASK, &mask, NULL);
- cond_signal(&dg_cv[cu_fd]);
}
static struct clnt_ops *
diff --git a/src/clnt_fd_locks.h b/src/clnt_fd_locks.h
new file mode 100644
index 0000000..359f995
--- /dev/null
+++ b/src/clnt_fd_locks.h
@@ -0,0 +1,207 @@
+/*
+ * debug.h -- debugging routines for libtirpc
+ *
+ * Copyright (c) 2020 SUSE LINUX GmbH, Nuernberg, Germany.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _CLNT_FD_LOCKS_H
+#define _CLNT_FD_LOCKS_H
+
+#include <sys/queue.h>
+#include <errno.h>
+#include <reentrant.h>
+#include <rpc/xdr.h>
+
+
+/*
+ * This utility manages a list of per-fd locks for the clients.
+ *
+ * If MAX_FDLOCKS_PREALLOC is defined, a number of pre-fd locks will be
+ * pre-allocated. This number is the minimum of MAX_FDLOCKS_PREALLOC or
+ * the process soft limit of allowed fds.
+ */
+#ifdef MAX_FDLOCKS_PREALLOC
+static unsigned int fd_locks_prealloc = 0;
+#endif
+
+/* per-fd lock */
+struct fd_lock_t {
+ bool_t active;
+ cond_t cv;
+};
+typedef struct fd_lock_t fd_lock_t;
+
+
+/* internal type to store per-fd locks in a list */
+struct fd_lock_item_t {
+ /* fd_lock_t first so we can cast to fd_lock_item_t */
+ fd_lock_t fd_lock;
+ int fd;
+ unsigned int refs;
+ TAILQ_ENTRY(fd_lock_item_t) link;
+};
+typedef struct fd_lock_item_t fd_lock_item_t;
+#define to_fd_lock_item(fdlock_t_ptr) ((fd_lock_item_t*) fdlock_t_ptr)
+
+
+/* internal list of per-fd locks */
+typedef TAILQ_HEAD(,fd_lock_item_t) fd_lock_list_t;
+
+
+#ifdef MAX_FDLOCKS_PREALLOC
+
+/* With pre-allocation, keep track of both an array and a list */
+struct fd_locks_t {
+ fd_lock_list_t fd_lock_list;
+ fd_lock_t *fd_lock_array;
+};
+typedef struct fd_locks_t fd_locks_t;
+#define to_fd_lock_list(fd_locks_t_ptr) (&fd_locks_t_ptr->fd_lock_list)
+
+#else
+
+/* With no pre-allocation, just keep track of a list */
+typedef fd_lock_list_t fd_locks_t;
+#define to_fd_lock_list(fd_locks_t_ptr) ((fd_lock_list_t *) fd_locks_t_ptr)
+
+#endif
+
+
+/* allocate fd locks */
+static inline
+fd_locks_t* fd_locks_init() {
+ fd_locks_t *fd_locks;
+
+ fd_locks = (fd_locks_t *) mem_alloc(sizeof(fd_locks_t));
+ if (fd_locks == (fd_locks_t *) NULL) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+ TAILQ_INIT(to_fd_lock_list(fd_locks));
+
+#ifdef MAX_FDLOCKS_PREALLOC
+ size_t fd_lock_arraysz;
+
+ if (fd_locks_prealloc == 0) {
+ unsigned int dtbsize = __rpc_dtbsize();
+ if (0 < dtbsize && dtbsize < MAX_FDLOCKS_PREALLOC)
+ fd_locks_prealloc = dtbsize;
+ else
+ fd_locks_prealloc = MAX_FDLOCKS_PREALLOC;
+ }
+
+ if ( (size_t) fd_locks_prealloc > SIZE_MAX/sizeof(fd_lock_t)) {
+ mem_free(fd_locks, sizeof (*fd_locks));
+ errno = EOVERFLOW;
+ return (NULL);
+ }
+
+ fd_lock_arraysz = fd_locks_prealloc * sizeof (fd_lock_t);
+ fd_locks->fd_lock_array = (fd_lock_t *) mem_alloc(fd_lock_arraysz);
+ if (fd_locks->fd_lock_array == (fd_lock_t *) NULL) {
+ mem_free(fd_locks, sizeof (*fd_locks));
+ errno = ENOMEM;
+ return (NULL);
+ }
+ else {
+ int i;
+
+ for (i = 0; i < fd_locks_prealloc; i++) {
+ fd_locks->fd_lock_array[i].active = FALSE;
+ cond_init(&fd_locks->fd_lock_array[i].cv, 0, (void *) 0);
+ }
+ }
+#endif
+
+ return fd_locks;
+}
+
+/* de-allocate fd locks */
+static inline
+void fd_locks_destroy(fd_locks_t *fd_locks) {
+#ifdef MAX_FDLOCKS_PREALLOC
+ fd_lock_t *array = fd_locks->fd_lock_array;
+ mem_free(array, fd_locks_prealloc * sizeof (fd_lock_t));
+#endif
+ fd_lock_item_t *item;
+ fd_lock_list_t *list = to_fd_lock_list(fd_locks);
+
+ TAILQ_FOREACH(item, list, link) {
+ cond_destroy(&item->fd_lock.cv);
+ mem_free(item, sizeof (*item));
+ }
+ mem_free(fd_locks, sizeof (*fd_locks));
+}
+
+/* allocate per-fd lock */
+static inline
+fd_lock_t* fd_lock_create(int fd, fd_locks_t *fd_locks) {
+#ifdef MAX_FDLOCKS_PREALLOC
+ if (fd < fd_locks_prealloc) {
+ return &fd_locks->fd_lock_array[fd];
+ }
+#endif
+ fd_lock_item_t *item;
+ fd_lock_list_t *list = to_fd_lock_list(fd_locks);
+
+ for (item = TAILQ_FIRST(list);
+ item != (fd_lock_item_t *) NULL && item->fd != fd;
+ item = TAILQ_NEXT(item, link));
+
+ if (item == (fd_lock_item_t *) NULL) {
+ item = (fd_lock_item_t *) mem_alloc(sizeof(fd_lock_item_t));
+ if (item == (fd_lock_item_t *) NULL) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+ item->fd = fd;
+ item->refs = 1;
+ item->fd_lock.active = FALSE;
+ cond_init(&item->fd_lock.cv, 0, (void *) 0);
+ TAILQ_INSERT_HEAD(list, item, link);
+ } else {
+ item->refs++;
+ }
+ return &item->fd_lock;
+}
+
+/* de-allocate per-fd lock */
+static inline
+void fd_lock_destroy(int fd, fd_lock_t *fd_lock, fd_locks_t *fd_locks) {
+#ifdef MAX_FDLOCKS_PREALLOC
+ if (fd < fd_locks_prealloc)
+ return;
+#endif
+ fd_lock_item_t* item = to_fd_lock_item(fd_lock);
+ item->refs--;
+ if (item->refs <= 0) {
+ TAILQ_REMOVE(to_fd_lock_list(fd_locks), item, link);
+ cond_destroy(&item->fd_lock.cv);
+ mem_free(item, sizeof (*item));
+ }
+}
+
+#endif /* _CLNT_FD_LOCKS_H */
diff --git a/src/clnt_vc.c b/src/clnt_vc.c
index ec58892..6f7f7da 100644
--- a/src/clnt_vc.c
+++ b/src/clnt_vc.c
@@ -67,6 +67,7 @@
#include <rpc/rpc.h>
#include "rpc_com.h"
+#include "clnt_fd_locks.h"
#define MCALL_MSG_SIZE 24
@@ -110,6 +111,7 @@ static int write_vc(void *, void *, int);
struct ct_data {
int ct_fd; /* connection's fd */
+ fd_lock_t *ct_fd_lock;
bool_t ct_closeit; /* close it on destroy */
struct timeval ct_wait; /* wait interval in milliseconds */
bool_t ct_waitset; /* wait set by clnt_control? */
@@ -124,27 +126,32 @@ 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. Therfore, 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.
+ * 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.
+ *
+ * We keep track of a list of per-fd locks, protected by the clnt_fd_lock
+ * mutex. Each per-fd lock consists of a predicate indicating whether is
+ * active or not: fd_lock->active == TRUE => a call is active on some
+ * CLIENT handle created for that fd. Each fd predicate is guarded by a
+ * condition variable so that the global mutex can be unlocked while
+ * waiting for the predicate to change.
+ *
+ * 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 *vc_fd_locks;
+static fd_locks_t *vc_fd_locks;
extern pthread_mutex_t disrupt_lock;
extern mutex_t clnt_fd_lock;
-static cond_t *vc_cv;
-#define release_fd_lock(fd, mask) { \
+#define release_fd_lock(fd_lock, mask) { \
mutex_lock(&clnt_fd_lock); \
- vc_fd_locks[fd] = 0; \
+ fd_lock->active = FALSE; \
mutex_unlock(&clnt_fd_lock); \
thr_sigsetmask(SIG_SETMASK, &(mask), (sigset_t *) NULL); \
- cond_signal(&vc_cv[fd]); \
+ cond_signal(&fd_lock->cv); \
}
static const char clnt_vc_errstr[] = "%s : %s";
@@ -181,6 +188,7 @@ clnt_vc_create(fd, raddr, prog, vers, sendsz, recvsz)
struct sockaddr_storage ss;
socklen_t slen;
struct __rpc_sockinfo si;
+ fd_lock_t *fd_lock;
mutex_lock(&disrupt_lock);
if (disrupt == 0)
@@ -201,49 +209,22 @@ clnt_vc_create(fd, raddr, prog, vers, sendsz, recvsz)
sigfillset(&newmask);
thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
mutex_lock(&clnt_fd_lock);
- if (vc_fd_locks == (int *) NULL) {
- size_t cv_allocsz, fd_allocsz;
- unsigned int dtbsize = __rpc_dtbsize();
- struct rpc_createerr *ce = &get_rpc_createerr();
-
- if ( (size_t) dtbsize > SIZE_MAX/sizeof(cond_t)) {
- mutex_unlock(&clnt_fd_lock);
- thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
- ce->cf_stat = RPC_SYSTEMERROR;
- ce->cf_error.re_errno = EOVERFLOW;
- goto err;
- }
-
- 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);
- ce->cf_stat = RPC_SYSTEMERROR;
- ce->cf_error.re_errno = ENOMEM;
- 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);
+ if (vc_fd_locks == (fd_locks_t *) NULL) {
+ vc_fd_locks = fd_locks_init();
+ if (vc_fd_locks == (fd_locks_t *) NULL) {
+ struct rpc_createerr *ce = &get_rpc_createerr();
ce->cf_stat = RPC_SYSTEMERROR;
- ce->cf_error.re_errno = ENOMEM;
+ ce->cf_error.re_errno = errno;
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);
+ }
+ fd_lock = fd_lock_create(fd, vc_fd_locks);
+ if (fd_lock == (fd_lock_t *) NULL) {
+ struct rpc_createerr *ce = &get_rpc_createerr();
+ ce->cf_stat = RPC_SYSTEMERROR;
+ ce->cf_error.re_errno = errno;
+ goto err;
+ }
/*
* Do not hold mutex during connect
@@ -279,6 +260,7 @@ clnt_vc_create(fd, raddr, prog, vers, sendsz, recvsz)
* Set up private data struct
*/
ct->ct_fd = fd;
+ ct->ct_fd_lock = fd_lock;
ct->ct_wait.tv_usec = 0;
ct->ct_waitset = FALSE;
ct->ct_addr.buf = malloc(raddr->maxlen);
@@ -361,17 +343,15 @@ clnt_vc_call(cl, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout)
bool_t shipnow;
int refreshes = 2;
sigset_t mask, newmask;
- int rpc_lock_value;
assert(cl != NULL);
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);
- rpc_lock_value = 1;
- vc_fd_locks[ct->ct_fd] = rpc_lock_value;
+ while (ct->ct_fd_lock->active)
+ cond_wait(&ct->ct_fd_lock->cv, &clnt_fd_lock);
+ ct->ct_fd_lock->active = TRUE;
mutex_unlock(&clnt_fd_lock);
if (!ct->ct_waitset) {
/* If time is not within limits, we ignore it. */
@@ -395,22 +375,22 @@ call_again:
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(ct->ct_fd_lock, mask);
return (ct->ct_error.re_status);
}
if (! xdrrec_endofrecord(xdrs, shipnow)) {
- release_fd_lock(ct->ct_fd, mask);
+ release_fd_lock(ct->ct_fd_lock, mask);
return (ct->ct_error.re_status = RPC_CANTSEND);
}
if (! shipnow) {
- release_fd_lock(ct->ct_fd, mask);
+ release_fd_lock(ct->ct_fd_lock, 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(ct->ct_fd_lock, mask);
return(ct->ct_error.re_status = RPC_TIMEDOUT);
}
@@ -424,14 +404,14 @@ call_again:
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(ct->ct_fd_lock, 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(ct->ct_fd_lock, mask);
return (ct->ct_error.re_status);
}
if (reply_msg.rm_xid == x_id)
@@ -464,7 +444,7 @@ call_again:
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(ct->ct_fd_lock, mask);
return (ct->ct_error.re_status);
}
@@ -502,13 +482,13 @@ clnt_vc_freeres(cl, xdr_res, 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);
+ while (ct->ct_fd_lock->active)
+ cond_wait(&ct->ct_fd_lock->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(&ct->ct_fd_lock->cv);
return dummy;
}
@@ -530,7 +510,6 @@ clnt_vc_control(cl, request, info)
void *infop = info;
sigset_t mask;
sigset_t newmask;
- int rpc_lock_value;
u_int32_t tmp;
u_int32_t ltmp;
@@ -541,20 +520,19 @@ clnt_vc_control(cl, request, 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);
- rpc_lock_value = 1;
- vc_fd_locks[ct->ct_fd] = rpc_lock_value;
+ while (ct->ct_fd_lock->active)
+ cond_wait(&ct->ct_fd_lock->cv, &clnt_fd_lock);
+ ct->ct_fd_lock->active = TRUE;
mutex_unlock(&clnt_fd_lock);
switch (request) {
case CLSET_FD_CLOSE:
ct->ct_closeit = TRUE;
- release_fd_lock(ct->ct_fd, mask);
+ release_fd_lock(ct->ct_fd_lock, mask);
return (TRUE);
case CLSET_FD_NCLOSE:
ct->ct_closeit = FALSE;
- release_fd_lock(ct->ct_fd, mask);
+ release_fd_lock(ct->ct_fd_lock, mask);
return (TRUE);
default:
break;
@@ -562,13 +540,13 @@ clnt_vc_control(cl, request, info)
/* for other requests which use info */
if (info == NULL) {
- release_fd_lock(ct->ct_fd, mask);
+ release_fd_lock(ct->ct_fd_lock, 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(ct->ct_fd_lock, mask);
return (FALSE);
}
ct->ct_wait = *(struct timeval *)infop;
@@ -588,7 +566,7 @@ clnt_vc_control(cl, request, 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(ct->ct_fd_lock, mask);
return (FALSE);
case CLGET_XID:
/*
@@ -642,10 +620,10 @@ clnt_vc_control(cl, request, info)
break;
default:
- release_fd_lock(ct->ct_fd, mask);
+ release_fd_lock(ct->ct_fd_lock, mask);
return (FALSE);
}
- release_fd_lock(ct->ct_fd, mask);
+ release_fd_lock(ct->ct_fd_lock, mask);
return (TRUE);
}
@@ -654,20 +632,18 @@ static void
clnt_vc_destroy(cl)
CLIENT *cl;
{
+ assert(cl != NULL);
struct ct_data *ct = (struct ct_data *) cl->cl_private;
int ct_fd = ct->ct_fd;
+ fd_lock_t *ct_fd_lock = ct->ct_fd_lock;
sigset_t mask;
sigset_t newmask;
- assert(cl != NULL);
-
- ct = (struct ct_data *) cl->cl_private;
-
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);
+ while (ct_fd_lock->active)
+ cond_wait(&ct_fd_lock->cv, &clnt_fd_lock);
if (ct->ct_closeit && ct->ct_fd != -1) {
(void)close(ct->ct_fd);
}
@@ -680,9 +656,10 @@ clnt_vc_destroy(cl)
if (cl->cl_tp && cl->cl_tp[0])
mem_free(cl->cl_tp, strlen(cl->cl_tp) +1);
mem_free(cl, sizeof(CLIENT));
+ cond_signal(&ct_fd_lock->cv);
+ fd_lock_destroy(ct_fd, ct_fd_lock, vc_fd_locks);
mutex_unlock(&clnt_fd_lock);
thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
- cond_signal(&vc_cv[ct_fd]);
}
/*
diff --git a/src/rpc_generic.c b/src/rpc_generic.c
index 51f36ac..aabbe4b 100644
--- a/src/rpc_generic.c
+++ b/src/rpc_generic.c
@@ -112,7 +112,7 @@ __rpc_dtbsize()
return (tbsize);
}
if (getrlimit(RLIMIT_NOFILE, &rl) == 0) {
- return (tbsize = (int)rl.rlim_max);
+ return (tbsize = (int)rl.rlim_cur);
}
/*
* Something wrong. I'll try to save face by returning a
diff --git a/src/svc_dg.c b/src/svc_dg.c
index 894ee9b..a9f63ff 100644
--- a/src/svc_dg.c
+++ b/src/svc_dg.c
@@ -328,6 +328,8 @@ svc_dg_destroy(xprt)
(void) mem_free(xprt->xp_ltaddr.buf, xprt->xp_ltaddr.maxlen);
if (xprt->xp_tp)
(void) free(xprt->xp_tp);
+ if (xprt->xp_netid)
+ (void) free(xprt->xp_netid);
(void) mem_free(xprt, sizeof (SVCXPRT));
}
diff --git a/src/svc_vc.c b/src/svc_vc.c
index c23cd36..f1d9f00 100644
--- a/src/svc_vc.c
+++ b/src/svc_vc.c
@@ -243,7 +243,7 @@ svc_fd_create(fd, sendsize, recvsize)
goto freedata;
}
if (!__rpc_set_netbuf(&ret->xp_rtaddr, &ss, sizeof(ss))) {
- warnx("svc_fd_create: no mem for local addr");
+ warnx("svc_fd_create: no mem for remote addr");
goto freedata;
}
@@ -253,9 +253,10 @@ svc_fd_create(fd, sendsize, recvsize)
return ret;
freedata:
- if (ret->xp_ltaddr.buf != NULL)
+ if (ret->xp_ltaddr.buf != NULL) {
mem_free(ret->xp_ltaddr.buf, rep->xp_ltaddr.maxlen);
-
+ ret->xp_ltaddr.buf = NULL;
+ }
return NULL;
}
diff --git a/tirpc/reentrant.h b/tirpc/reentrant.h
index 5f5c96e..5bb581a 100644
--- a/tirpc/reentrant.h
+++ b/tirpc/reentrant.h
@@ -57,6 +57,7 @@
#define mutex_unlock(m) pthread_mutex_unlock(m)
#define cond_init(c, a, p) pthread_cond_init(c, a)
+#define cond_destroy(c) pthread_cond_destroy(c)
#define cond_signal(m) pthread_cond_signal(m)
#define cond_broadcast(m) pthread_cond_broadcast(m)
#define cond_wait(c, m) pthread_cond_wait(c, m)

View File

@ -1,8 +1,8 @@
%define _root_libdir /%{_lib} %define _root_libdir /%{_lib}
Name: libtirpc Name: libtirpc
Version: 1.2.6 Version: 1.3.1
Release: 2.rc4%{?dist} Release: 0%{?dist}
Summary: Transport Independent RPC Library Summary: Transport Independent RPC Library
License: SISSL and BSD License: SISSL and BSD
URL: http://git.linux-nfs.org/?p=steved/libtirpc.git;a=summary URL: http://git.linux-nfs.org/?p=steved/libtirpc.git;a=summary
@ -12,8 +12,6 @@ BuildRequires: automake, autoconf, libtool, pkgconfig
BuildRequires: krb5-devel BuildRequires: krb5-devel
BuildRequires: gcc BuildRequires: gcc
Patch001: libtirpc-1.2.7-rc4.patch
%description %description
This package contains SunLib's implementation of transport-independent This package contains SunLib's implementation of transport-independent
RPC (TI-RPC) documentation. This library forms a piece of the base of RPC (TI-RPC) documentation. This library forms a piece of the base of
@ -113,6 +111,9 @@ mv %{buildroot}%{_mandir}/man3 %{buildroot}%{_mandir}/man3t
%{_mandir}/*/* %{_mandir}/*/*
%changelog %changelog
* Thu Dec 03 2020 Steve Dickson <steved@redhat.com> - 1.3.1
- Updated to latest upstream release: libtirpc-1-3-1 (bz 1903615)
* Tue Aug 04 2020 Steve Dickson <steved@redhat.com> 1.2.6-1.rc4 * Tue Aug 04 2020 Steve Dickson <steved@redhat.com> 1.2.6-1.rc4
- Updated to the latest upstream RC release: libtirpc-1-2-7-rc4 - Updated to the latest upstream RC release: libtirpc-1-2-7-rc4

View File

@ -1 +1 @@
SHA512 (libtirpc-1.2.6.tar.bz2) = bcb6b5c062c1301aa1246ec93ae0a5c1d221b8421126d020863517cb814b43ed038fb6c0c2faf4e68ff133b69abefe4f4d42bfc870671da6c27ca941a30b155a SHA512 (libtirpc-1.3.1.tar.bz2) = 131f746800ac7280cc3900597018fc8dbc8da50c14e29dbaccf36a6d110eded117351108c6b069eaac90d77cfec17014b08e9afddcf153fda2d780ba64260cbc