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,11 +19,11 @@
  * CDDL HEADER END
  */
 
 /*
  * Copyright (c) 1984, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2015, Joyent, Inc.
+ * 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,15 +2099,11 @@
         return (ufs_iaccess(ip, mode, cr, 0));
 }
 
 /*ARGSUSED4*/
 static int
-ufs_setattr(
-        struct vnode *vp,
-        struct vattr *vap,
-        int flags,
-        struct cred *cr,
+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,12 +2611,11 @@
         return (error);
 }
 
 /* ARGSUSED */
 static int
-ufs_fsync(struct vnode *vp, int syncflag, struct cred *cr,
-        caller_context_t *ct)
+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,12 +3186,12 @@
 }
 
 extern int ufs_idle_max;
 /*ARGSUSED*/
 static int
-ufs_remove(struct vnode *vp, char *nm, struct cred *cr,
-        caller_context_t *ct, int flags)
+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,18 +3348,12 @@
  * 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)
+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,17 +3888,12 @@
         return (error);
 }
 
 /* ARGSUSED */
 static int
-ufs_readdir(
-        struct vnode *vp,
-        struct uio *uiop,
-        struct cred *cr,
-        int *eofp,
-        caller_context_t *ct,
-        int flags)
+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,18 +4092,12 @@
         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)
+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,12 +4409,11 @@
         rw_exit(&ip->i_rwlock);
 }
 
 /* ARGSUSED */
 static int
-ufs_seek(struct vnode *vp, offset_t ooff, offset_t *noffp,
-        caller_context_t *ct)
+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,15 +5166,11 @@
  * 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,
+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,17 +5337,12 @@
  *
  * 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)
+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,19 +5569,12 @@
 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,
+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,20 +5687,13 @@
         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)
+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,12 +5706,12 @@
 }
 
 /*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)
+    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,10 +5733,18 @@
 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,11 +5775,13 @@
         }
 
         if ((ev & POLLPRI) && (*revp & (POLLERR|POLLHUP)))
                 *revp |= POLLPRI;
 out:
-        *phpp = !any && !*revp ? &ufs_pollhd : (struct pollhead *)NULL;
+        if (*revp == 0 && ! any) {
+                *phpp = &ufs_pollhd;
+        }
 
         return (0);
 }
 
 /* ARGSUSED */