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 */