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);
}