summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpjd <pjd@FreeBSD.org>2014-09-14 09:27:12 +0000
committerpjd <pjd@FreeBSD.org>2014-09-14 09:27:12 +0000
commitac34a053f072f1933dbc1c773218e096fa8e04cf (patch)
treece0fb0b471e79cf7f785cb685ba52b88fd99ca47
parent4a0b0e233c26fc824e0e91281e54b1772f518204 (diff)
downloadFreeBSD-src-ac34a053f072f1933dbc1c773218e096fa8e04cf.zip
FreeBSD-src-ac34a053f072f1933dbc1c773218e096fa8e04cf.tar.gz
Remove the limit on descriptors that can be send in one nvlist.
Submitted by: Mariusz Zaborski
-rw-r--r--lib/libnv/msgio.c113
1 files changed, 96 insertions, 17 deletions
diff --git a/lib/libnv/msgio.c b/lib/libnv/msgio.c
index 41292aa..27620a1 100644
--- a/lib/libnv/msgio.c
+++ b/lib/libnv/msgio.c
@@ -31,7 +31,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include <sys/types.h>
+#include <sys/param.h>
#include <sys/socket.h>
#include <errno.h>
@@ -56,6 +56,8 @@ __FBSDID("$FreeBSD$");
#define PJDLOG_ABORT(...) abort()
#endif
+#define PKG_MAX_SIZE (MCLBYTES / CMSG_SPACE(sizeof(int)) - 1)
+
static int
msghdr_add_fd(struct cmsghdr *cmsg, int fd)
{
@@ -234,22 +236,31 @@ cred_recv(int sock, struct cmsgcred *cred)
return (0);
}
-int
-fd_send(int sock, const int *fds, size_t nfds)
+static int
+fd_package_send(int sock, const int *fds, size_t nfds)
{
struct msghdr msg;
struct cmsghdr *cmsg;
+ struct iovec iov;
unsigned int i;
int serrno, ret;
+ uint8_t dummy;
- if (nfds == 0 || fds == NULL) {
- errno = EINVAL;
- return (-1);
- }
+ PJDLOG_ASSERT(sock >= 0);
+ PJDLOG_ASSERT(fds != NULL);
+ PJDLOG_ASSERT(nfds > 0);
bzero(&msg, sizeof(msg));
- msg.msg_iov = NULL;
- msg.msg_iovlen = 0;
+
+ /*
+ * XXX: Look into cred_send function for more details.
+ */
+ dummy = 0;
+ iov.iov_base = &dummy;
+ iov.iov_len = sizeof(dummy);
+
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
msg.msg_controllen = nfds * CMSG_SPACE(sizeof(int));
msg.msg_control = calloc(1, msg.msg_controllen);
if (msg.msg_control == NULL)
@@ -274,22 +285,32 @@ end:
return (ret);
}
-int
-fd_recv(int sock, int *fds, size_t nfds)
+static int
+fd_package_recv(int sock, int *fds, size_t nfds)
{
struct msghdr msg;
struct cmsghdr *cmsg;
unsigned int i;
int serrno, ret;
+ struct iovec iov;
+ uint8_t dummy;
- if (nfds == 0 || fds == NULL) {
- errno = EINVAL;
- return (-1);
- }
+ PJDLOG_ASSERT(sock >= 0);
+ PJDLOG_ASSERT(nfds > 0);
+ PJDLOG_ASSERT(fds != NULL);
+ i = 0;
bzero(&msg, sizeof(msg));
- msg.msg_iov = NULL;
- msg.msg_iovlen = 0;
+ bzero(&iov, sizeof(iov));
+
+ /*
+ * XXX: Look into cred_send function for more details.
+ */
+ iov.iov_base = &dummy;
+ iov.iov_len = sizeof(dummy);
+
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
msg.msg_controllen = nfds * CMSG_SPACE(sizeof(int));
msg.msg_control = calloc(1, msg.msg_controllen);
if (msg.msg_control == NULL)
@@ -333,6 +354,64 @@ end:
}
int
+fd_recv(int sock, int *fds, size_t nfds)
+{
+ unsigned int i, step, j;
+ int ret, serrno;
+
+ if (nfds == 0 || fds == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ ret = i = step = 0;
+ while (i < nfds) {
+ if (PKG_MAX_SIZE < nfds - i)
+ step = PKG_MAX_SIZE;
+ else
+ step = nfds - i;
+ ret = fd_package_recv(sock, fds + i, step);
+ if (ret != 0) {
+ /* Close all received descriptors. */
+ serrno = errno;
+ for (j = 0; j < i; j++)
+ close(fds[j]);
+ errno = serrno;
+ break;
+ }
+ i += step;
+ }
+
+ return (ret);
+}
+
+int
+fd_send(int sock, const int *fds, size_t nfds)
+{
+ unsigned int i, step;
+ int ret;
+
+ if (nfds == 0 || fds == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ ret = i = step = 0;
+ while (i < nfds) {
+ if (PKG_MAX_SIZE < nfds - i)
+ step = PKG_MAX_SIZE;
+ else
+ step = nfds - i;
+ ret = fd_package_send(sock, fds + i, step);
+ if (ret != 0)
+ break;
+ i += step;
+ }
+
+ return (ret);
+}
+
+int
buf_send(int sock, void *buf, size_t size)
{
ssize_t done;
OpenPOWER on IntegriCloud