Author: mjg
Date: Sun Apr 14 17:08:34 2013
New Revision: 249480
URL: http://svnweb.freebsd.org/changeset/base/249480

Log:
  Add fdallocn function and use it when passing fds over unix socket.
  
  This gets rid of "unp_externalize fdalloc failed" panic.
  
  Reviewed by:  pjd
  MFC after:    1 week

Modified:
  head/sys/kern/kern_descrip.c
  head/sys/kern/uipc_usrreq.c
  head/sys/sys/filedesc.h

Modified: head/sys/kern/kern_descrip.c
==============================================================================
--- head/sys/kern/kern_descrip.c        Sun Apr 14 16:49:27 2013        
(r249479)
+++ head/sys/kern/kern_descrip.c        Sun Apr 14 17:08:34 2013        
(r249480)
@@ -1582,6 +1582,34 @@ fdalloc(struct thread *td, int minfd, in
 }
 
 /*
+ * Allocate n file descriptors for the process.
+ */
+int
+fdallocn(struct thread *td, int minfd, int *fds, int n)
+{
+       struct proc *p = td->td_proc;
+       struct filedesc *fdp = p->p_fd;
+       int i;
+
+       FILEDESC_XLOCK_ASSERT(fdp);
+
+       if (!fdavail(td, n))
+               return (EMFILE);
+
+       for (i = 0; i < n; i++)
+               if (fdalloc(td, 0, &fds[i]) != 0)
+                       break;
+
+       if (i < n) {
+               for (i--; i >= 0; i--)
+                       fdunused(fdp, fds[i]);
+               return (EMFILE);
+       }
+
+       return (0);
+}
+
+/*
  * Check to see whether n user file descriptors are available to the process
  * p.
  */

Modified: head/sys/kern/uipc_usrreq.c
==============================================================================
--- head/sys/kern/uipc_usrreq.c Sun Apr 14 16:49:27 2013        (r249479)
+++ head/sys/kern/uipc_usrreq.c Sun Apr 14 17:08:34 2013        (r249480)
@@ -1706,7 +1706,6 @@ unp_externalize(struct mbuf *control, st
        void *data;
        socklen_t clen = control->m_len, datalen;
        int error, newfds;
-       int f;
        u_int newlen;
 
        UNP_LINK_UNLOCK_ASSERT();
@@ -1732,13 +1731,6 @@ unp_externalize(struct mbuf *control, st
                                goto next;
                        }
                        FILEDESC_XLOCK(fdesc);
-                       /* if the new FD's will not fit free them.  */
-                       if (!fdavail(td, newfds)) {
-                               FILEDESC_XUNLOCK(fdesc);
-                               error = EMSGSIZE;
-                               unp_freerights(fdep, newfds);
-                               goto next;
-                       }
 
                        /*
                         * Now change each pointer to an fd in the global
@@ -1758,17 +1750,22 @@ unp_externalize(struct mbuf *control, st
 
                        fdp = (int *)
                            CMSG_DATA(mtod(*controlp, struct cmsghdr *));
+                       if (fdallocn(td, 0, fdp, newfds) != 0) {
+                               FILEDESC_XUNLOCK(td->td_proc->p_fd);
+                               error = EMSGSIZE;
+                               unp_freerights(fdep, newfds);
+                               m_freem(*controlp);
+                               *controlp = NULL;
+                               goto next;
+                       }
                        for (i = 0; i < newfds; i++, fdp++) {
-                               if (fdalloc(td, 0, &f))
-                                       panic("unp_externalize fdalloc failed");
-                               fde = &fdesc->fd_ofiles[f];
+                               fde = &fdesc->fd_ofiles[*fdp];
                                fde->fde_file = fdep[0]->fde_file;
                                filecaps_move(&fdep[0]->fde_caps,
                                    &fde->fde_caps);
                                if ((flags & MSG_CMSG_CLOEXEC) != 0)
                                        fde->fde_flags |= UF_EXCLOSE;
                                unp_externalize_fp(fde->fde_file);
-                               *fdp = f;
                        }
                        FILEDESC_XUNLOCK(fdesc);
                        free(fdep[0], M_FILECAPS);

Modified: head/sys/sys/filedesc.h
==============================================================================
--- head/sys/sys/filedesc.h     Sun Apr 14 16:49:27 2013        (r249479)
+++ head/sys/sys/filedesc.h     Sun Apr 14 17:08:34 2013        (r249480)
@@ -150,6 +150,7 @@ int falloc_noinstall(struct thread *td, 
 int    finstall(struct thread *td, struct file *fp, int *resultfp, int flags,
            struct filecaps *fcaps);
 int    fdalloc(struct thread *td, int minfd, int *result);
+int    fdallocn(struct thread *td, int minfd, int *fds, int n);
 int    fdavail(struct thread *td, int n);
 int    fdcheckstd(struct thread *td);
 void   fdclose(struct filedesc *fdp, struct file *fp, int idx, struct thread 
*td);
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to