Print this page
OS-5518 devpoll write feigns success in the face of EINTR
OS-5520 epoll_ctl not allowed to emit EINTR
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Bryan Cantrill <bryan@joyent.com>
OS-5516 vmxnet3s declares wrong sdu
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
Approved by: Bryan Cantrill <bryan@joyent.com>
OS-5511 epoll should not leave dangling polldat_t entries
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Bryan Cantrill <bryan@joyent.com>
OS-5260 lxbrand epoll_pwait needs sigset translation
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
        
*** 351,362 ****
                                   */
                                  if (is_epoll) {
                                          pdp->pd_fp = NULL;
                                          pdp->pd_events = 0;
  
!                                         if (php != NULL) {
!                                                 pollhead_delete(php, pdp);
                                                  pdp->pd_php = NULL;
                                          }
  
                                          BT_CLEAR(pcp->pc_bitmap, fd);
                                          continue;
--- 351,363 ----
                                   */
                                  if (is_epoll) {
                                          pdp->pd_fp = NULL;
                                          pdp->pd_events = 0;
  
!                                         if (pdp->pd_php != NULL) {
!                                                 pollhead_delete(pdp->pd_php,
!                                                     pdp);
                                                  pdp->pd_php = NULL;
                                          }
  
                                          BT_CLEAR(pcp->pc_bitmap, fd);
                                          continue;
*** 501,512 ****
                                   */
                                  if (pdp->pd_events & POLLONESHOT) {
                                          pdp->pd_fp = NULL;
                                          pdp->pd_events = 0;
  
!                                         if (php != NULL) {
!                                                 pollhead_delete(php, pdp);
                                                  pdp->pd_php = NULL;
                                          }
  
                                          BT_CLEAR(pcp->pc_bitmap, fd);
                                  }
--- 502,514 ----
                                   */
                                  if (pdp->pd_events & POLLONESHOT) {
                                          pdp->pd_fp = NULL;
                                          pdp->pd_events = 0;
  
!                                         if (pdp->pd_php != NULL) {
!                                                 pollhead_delete(pdp->pd_php,
!                                                     pdp);
                                                  pdp->pd_php = NULL;
                                          }
  
                                          BT_CLEAR(pcp->pc_bitmap, fd);
                                  }
*** 637,646 ****
--- 639,649 ----
          pollfd_t        *pollfdp, *pfdp;
          dvpoll_epollfd_t *epfdp;
          uintptr_t       limit;
          int             error, size;
          ssize_t         uiosize;
+         size_t          copysize;
          nfds_t          pollfdnum;
          struct pollhead *php = NULL;
          polldat_t       *pdp;
          int             fd;
          file_t          *fp;
*** 702,716 ****
           * not supposed to function as a seekable device. To prevent offset
           * from growing and eventually exceed the maximum, reset the offset
           * here for every call.
           */
          uiop->uio_loffset = 0;
!         if ((error = uiomove((caddr_t)pollfdp, uiosize, UIO_WRITE, uiop))
!             != 0) {
                  kmem_free(pollfdp, uiosize);
                  return (error);
          }
          /*
           * We are about to enter the core portion of dpwrite(). Make sure this
           * write has exclusive access in this portion of the code, i.e., no
           * other writers in this code.
           *
--- 705,727 ----
           * not supposed to function as a seekable device. To prevent offset
           * from growing and eventually exceed the maximum, reset the offset
           * here for every call.
           */
          uiop->uio_loffset = 0;
! 
!         /*
!          * Use uiocopy instead of uiomove when populating pollfdp, keeping
!          * uio_resid untouched for now.  Write syscalls will translate EINTR
!          * into a success if they detect "successfully transfered" data via an
!          * updated uio_resid.  Falsely suppressing such errors is disastrous.
!          */
!         if ((error = uiocopy((caddr_t)pollfdp, uiosize, UIO_WRITE, uiop,
!             ©size)) != 0) {
                  kmem_free(pollfdp, uiosize);
                  return (error);
          }
+ 
          /*
           * We are about to enter the core portion of dpwrite(). Make sure this
           * write has exclusive access in this portion of the code, i.e., no
           * other writers in this code.
           *
*** 979,988 ****
--- 990,1006 ----
          dpep->dpe_flag &= ~DP_WRITER_PRESENT;
          dpep->dpe_refcnt--;
          cv_broadcast(&dpep->dpe_cv);
          mutex_exit(&dpep->dpe_lock);
          kmem_free(pollfdp, uiosize);
+         if (error == 0) {
+                 /*
+                  * The state of uio_resid is updated only after the pollcache
+                  * is successfully modified.
+                  */
+                 uioskip(uiop, copysize);
+         }
          return (error);
  }
  
  #define DP_SIGMASK_RESTORE(ksetp) {                                     \
          if (ksetp != NULL) {                                            \
*** 1121,1137 ****
  
                  if (cmd == DP_PPOLL) {
                          void *setp = STRUCT_FGETP(dvpoll, dp_setp);
  
                          if (setp != NULL) {
                                  if (copyin(setp, &set, sizeof (set))) {
                                          DP_REFRELE(dpep);
                                          return (EFAULT);
                                  }
- 
                                  sigutok(&set, &kset);
                                  ksetp = &kset;
  
                                  mutex_enter(&p->p_lock);
                                  schedctl_finish_sigblock(t);
                                  lwp->lwp_sigoldmask = t->t_hold;
                                  t->t_hold = *ksetp;
--- 1139,1159 ----
  
                  if (cmd == DP_PPOLL) {
                          void *setp = STRUCT_FGETP(dvpoll, dp_setp);
  
                          if (setp != NULL) {
+                                 if ((mode & FKIOCTL) != 0) {
+                                         /* Use the signal set directly */
+                                         ksetp = (k_sigset_t *)setp;
+                                 } else {
                                          if (copyin(setp, &set, sizeof (set))) {
                                                  DP_REFRELE(dpep);
                                                  return (EFAULT);
                                          }
                                          sigutok(&set, &kset);
                                          ksetp = &kset;
+                                 }
  
                                  mutex_enter(&p->p_lock);
                                  schedctl_finish_sigblock(t);
                                  lwp->lwp_sigoldmask = t->t_hold;
                                  t->t_hold = *ksetp;
*** 1277,1286 ****
--- 1299,1312 ----
                  pollstate_exit(pcp);
  
                  DP_SIGMASK_RESTORE(ksetp);
  
                  if (error == 0 && fdcnt > 0) {
+                         /*
+                          * It should be noted that FKIOCTL does not influence
+                          * the copyout (vs bcopy) of dp_fds at this time.
+                          */
                          if (copyout(ps->ps_dpbuf,
                              STRUCT_FGETP(dvpoll, dp_fds), fdcnt * fdsize)) {
                                  DP_REFRELE(dpep);
                                  return (EFAULT);
                          }