Print this page
8634 epoll fails to wake on certain edge-triggered conditions
8635 epoll should not emit POLLNVAL
8636 recursive epoll should emit EPOLLRDNORM
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Toomas Soome <tsoome@me.com>
Reviewed by: Igor Kozhukhov <igor@dilos.org>

*** 19,29 **** * CDDL HEADER END */ /* * Copyright (c) 1984, 2010, Oracle and/or its affiliates. All rights reserved. ! * Copyright 2015, Joyent, Inc. * Copyright (c) 2016 by Delphix. All rights reserved. */ /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ --- 19,29 ---- * CDDL HEADER END */ /* * Copyright (c) 1984, 2010, Oracle and/or its affiliates. All rights reserved. ! * Copyright 2017 Joyent, Inc. * Copyright (c) 2016 by Delphix. All rights reserved. */ /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */
*** 2099,2113 **** return (ufs_iaccess(ip, mode, cr, 0)); } /*ARGSUSED4*/ static int ! ufs_setattr( ! struct vnode *vp, ! struct vattr *vap, ! int flags, ! struct cred *cr, caller_context_t *ct) { struct inode *ip = VTOI(vp); struct ufsvfs *ufsvfsp = ip->i_ufsvfs; struct fs *fs; --- 2099,2109 ---- return (ufs_iaccess(ip, mode, cr, 0)); } /*ARGSUSED4*/ static int ! ufs_setattr(struct vnode *vp, struct vattr *vap, int flags, struct cred *cr, caller_context_t *ct) { struct inode *ip = VTOI(vp); struct ufsvfs *ufsvfsp = ip->i_ufsvfs; struct fs *fs;
*** 2615,2626 **** return (error); } /* ARGSUSED */ static int ! ufs_fsync(struct vnode *vp, int syncflag, struct cred *cr, ! caller_context_t *ct) { struct inode *ip = VTOI(vp); struct ufsvfs *ufsvfsp = ip->i_ufsvfs; struct ulockfs *ulp; int error; --- 2611,2621 ---- return (error); } /* ARGSUSED */ static int ! ufs_fsync(struct vnode *vp, int syncflag, struct cred *cr, caller_context_t *ct) { struct inode *ip = VTOI(vp); struct ufsvfs *ufsvfsp = ip->i_ufsvfs; struct ulockfs *ulp; int error;
*** 3191,3202 **** } extern int ufs_idle_max; /*ARGSUSED*/ static int ! ufs_remove(struct vnode *vp, char *nm, struct cred *cr, ! caller_context_t *ct, int flags) { struct inode *ip = VTOI(vp); struct ufsvfs *ufsvfsp = ip->i_ufsvfs; struct ulockfs *ulp; vnode_t *rmvp = NULL; /* Vnode corresponding to name being removed */ --- 3186,3197 ---- } extern int ufs_idle_max; /*ARGSUSED*/ static int ! ufs_remove(struct vnode *vp, char *nm, struct cred *cr, caller_context_t *ct, ! int flags) { struct inode *ip = VTOI(vp); struct ufsvfs *ufsvfsp = ip->i_ufsvfs; struct ulockfs *ulp; vnode_t *rmvp = NULL; /* Vnode corresponding to name being removed */
*** 3353,3370 **** * can do is always guarantee that the TARGET exists. */ /*ARGSUSED*/ static int ! ufs_rename( ! struct vnode *sdvp, /* old (source) parent vnode */ ! char *snm, /* old (source) entry name */ ! struct vnode *tdvp, /* new (target) parent vnode */ ! char *tnm, /* new (target) entry name */ ! struct cred *cr, ! caller_context_t *ct, ! int flags) { struct inode *sip = NULL; /* source inode */ struct inode *ip = NULL; /* check inode */ struct inode *sdp; /* old (source) parent inode */ struct inode *tdp; /* new (target) parent inode */ --- 3348,3359 ---- * can do is always guarantee that the TARGET exists. */ /*ARGSUSED*/ static int ! ufs_rename(struct vnode *sdvp, char *snm, struct vnode *tdvp, char *tnm, ! struct cred *cr, caller_context_t *ct, int flags) { struct inode *sip = NULL; /* source inode */ struct inode *ip = NULL; /* check inode */ struct inode *sdp; /* old (source) parent inode */ struct inode *tdp; /* new (target) parent inode */
*** 3899,3915 **** return (error); } /* ARGSUSED */ static int ! ufs_readdir( ! struct vnode *vp, ! struct uio *uiop, ! struct cred *cr, ! int *eofp, ! caller_context_t *ct, ! int flags) { struct iovec *iovp; struct inode *ip; struct direct *idp; struct dirent64 *odp; --- 3888,3899 ---- return (error); } /* ARGSUSED */ static int ! ufs_readdir(struct vnode *vp, struct uio *uiop, struct cred *cr, int *eofp, ! caller_context_t *ct, int flags) { struct iovec *iovp; struct inode *ip; struct direct *idp; struct dirent64 *odp;
*** 4108,4125 **** return (error); } /*ARGSUSED*/ static int ! ufs_symlink( ! struct vnode *dvp, /* ptr to parent dir vnode */ ! char *linkname, /* name of symbolic link */ ! struct vattr *vap, /* attributes */ ! char *target, /* target path */ ! struct cred *cr, /* user credentials */ ! caller_context_t *ct, ! int flags) { struct inode *ip, *dip = VTOI(dvp); struct ufsvfs *ufsvfsp = dip->i_ufsvfs; struct ulockfs *ulp; int error; --- 4092,4103 ---- return (error); } /*ARGSUSED*/ static int ! ufs_symlink(struct vnode *dvp, char *linkname, struct vattr *vap, char *target, ! struct cred *cr, caller_context_t *ct, int flags) { struct inode *ip, *dip = VTOI(dvp); struct ufsvfs *ufsvfsp = dip->i_ufsvfs; struct ulockfs *ulp; int error;
*** 4431,4442 **** rw_exit(&ip->i_rwlock); } /* ARGSUSED */ static int ! ufs_seek(struct vnode *vp, offset_t ooff, offset_t *noffp, ! caller_context_t *ct) { return ((*noffp < 0 || *noffp > MAXOFFSET_T) ? EINVAL : 0); } /* ARGSUSED */ --- 4409,4419 ---- rw_exit(&ip->i_rwlock); } /* ARGSUSED */ static int ! ufs_seek(struct vnode *vp, offset_t ooff, offset_t *noffp, caller_context_t *ct) { return ((*noffp < 0 || *noffp > MAXOFFSET_T) ? EINVAL : 0); } /* ARGSUSED */
*** 5189,5203 **** * len == MAXBSIZE (from segmap_release actions), and len == PAGESIZE * (from pageout). */ /*ARGSUSED*/ static int ! ufs_putpages( ! struct vnode *vp, ! offset_t off, ! size_t len, ! int flags, struct cred *cr) { u_offset_t io_off; u_offset_t eoff; struct inode *ip = VTOI(vp); --- 5166,5176 ---- * len == MAXBSIZE (from segmap_release actions), and len == PAGESIZE * (from pageout). */ /*ARGSUSED*/ static int ! ufs_putpages(struct vnode *vp, offset_t off, size_t len, int flags, struct cred *cr) { u_offset_t io_off; u_offset_t eoff; struct inode *ip = VTOI(vp);
*** 5364,5380 **** * * LMXXX - bsize < pagesize not done. */ /*ARGSUSED*/ int ! ufs_putapage( ! struct vnode *vp, ! page_t *pp, ! u_offset_t *offp, ! size_t *lenp, /* return values */ ! int flags, ! struct cred *cr) { u_offset_t io_off; u_offset_t off; struct inode *ip = VTOI(vp); struct ufsvfs *ufsvfsp = ip->i_ufsvfs; --- 5337,5348 ---- * * LMXXX - bsize < pagesize not done. */ /*ARGSUSED*/ int ! ufs_putapage(struct vnode *vp, page_t *pp, u_offset_t *offp, size_t *lenp, ! int flags, struct cred *cr) { u_offset_t io_off; u_offset_t off; struct inode *ip = VTOI(vp); struct ufsvfs *ufsvfsp = ip->i_ufsvfs;
*** 5601,5619 **** uint64_t ufs_map_alock_retry_cnt; uint64_t ufs_map_lockfs_retry_cnt; /* ARGSUSED */ static int ! ufs_map(struct vnode *vp, ! offset_t off, ! struct as *as, ! caddr_t *addrp, ! size_t len, ! uchar_t prot, ! uchar_t maxprot, ! uint_t flags, ! struct cred *cr, caller_context_t *ct) { struct segvn_crargs vn_a; struct ufsvfs *ufsvfsp = VTOI(vp)->i_ufsvfs; struct ulockfs *ulp; --- 5569,5580 ---- uint64_t ufs_map_alock_retry_cnt; uint64_t ufs_map_lockfs_retry_cnt; /* ARGSUSED */ static int ! ufs_map(struct vnode *vp, offset_t off, struct as *as, caddr_t *addrp, ! size_t len, uchar_t prot, uchar_t maxprot, uint_t flags, struct cred *cr, caller_context_t *ct) { struct segvn_crargs vn_a; struct ufsvfs *ufsvfsp = VTOI(vp)->i_ufsvfs; struct ulockfs *ulp;
*** 5726,5745 **** return (error); } /* ARGSUSED */ static int ! ufs_addmap(struct vnode *vp, ! offset_t off, ! struct as *as, ! caddr_t addr, ! size_t len, ! uchar_t prot, ! uchar_t maxprot, ! uint_t flags, ! struct cred *cr, ! caller_context_t *ct) { struct inode *ip = VTOI(vp); if (vp->v_flag & VNOMAP) { return (ENOSYS); --- 5687,5699 ---- return (error); } /* ARGSUSED */ static int ! ufs_addmap(struct vnode *vp, offset_t off, struct as *as, caddr_t addr, ! size_t len, uchar_t prot, uchar_t maxprot, uint_t flags, ! struct cred *cr, caller_context_t *ct) { struct inode *ip = VTOI(vp); if (vp->v_flag & VNOMAP) { return (ENOSYS);
*** 5752,5763 **** } /*ARGSUSED*/ static int ufs_delmap(struct vnode *vp, offset_t off, struct as *as, caddr_t addr, ! size_t len, uint_t prot, uint_t maxprot, uint_t flags, ! struct cred *cr, caller_context_t *ct) { struct inode *ip = VTOI(vp); if (vp->v_flag & VNOMAP) { return (ENOSYS); --- 5706,5717 ---- } /*ARGSUSED*/ static int ufs_delmap(struct vnode *vp, offset_t off, struct as *as, caddr_t addr, ! size_t len, uint_t prot, uint_t maxprot, uint_t flags, struct cred *cr, ! caller_context_t *ct) { struct inode *ip = VTOI(vp); if (vp->v_flag & VNOMAP) { return (ENOSYS);
*** 5779,5788 **** --- 5733,5750 ---- ufs_poll(vnode_t *vp, short ev, int any, short *revp, struct pollhead **phpp, caller_context_t *ct) { struct ufsvfs *ufsvfsp; + /* + * Regular files reject edge-triggered pollers. + * See the comment in fs_poll() for a more detailed explanation. + */ + if (ev & POLLET) { + return (EPERM); + } + *revp = 0; ufsvfsp = VTOI(vp)->i_ufsvfs; if (!ufsvfsp) { *revp = POLLHUP;
*** 5813,5823 **** } if ((ev & POLLPRI) && (*revp & (POLLERR|POLLHUP))) *revp |= POLLPRI; out: ! *phpp = !any && !*revp ? &ufs_pollhd : (struct pollhead *)NULL; return (0); } /* ARGSUSED */ --- 5775,5787 ---- } if ((ev & POLLPRI) && (*revp & (POLLERR|POLLHUP))) *revp |= POLLPRI; out: ! if (*revp == 0 && ! any) { ! *phpp = &ufs_pollhd; ! } return (0); } /* ARGSUSED */