Author: pjd
Date: Sun Sep 14 09:27:12 2014
New Revision: 271578
URL: http://svnweb.freebsd.org/changeset/base/271578

Log:
  Remove the limit on descriptors that can be send in one nvlist.
  
  Submitted by: Mariusz Zaborski

Modified:
  head/lib/libnv/msgio.c

Modified: head/lib/libnv/msgio.c
==============================================================================
--- head/lib/libnv/msgio.c      Sun Sep 14 09:26:33 2014        (r271577)
+++ head/lib/libnv/msgio.c      Sun Sep 14 09:27:12 2014        (r271578)
@@ -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 *cre
        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;
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to