Exemple #1
0
static int
nm_poll(vnode_t *vp, short events, int anyyet, short *reventsp,
	pollhead_t **phpp, caller_context_t *ct)
{
	return (VOP_POLL(VTONM(vp)->nm_filevp, events, anyyet, reventsp,
	    phpp, ct));
}
/*ARGSUSED*/
int
cttypoll(dev_t dev, int events, struct proc *p)
{
    struct vnode *ttyvp = cttyvp(p);

    if (ttyvp == NULL)	/* try operation to get EOF/failure */
        return (seltrue(dev, events, p));
    return (VOP_POLL(ttyvp, events, p));
}
/*ARGSUSED*/
static int
cttypoll(dev_t dev, int events, struct lwp *l)
{
	struct vnode *ttyvp = cttyvp(l->l_proc);

	if (ttyvp == NULL)
		return (seltrue(dev, events, l));
	return (VOP_POLL(ttyvp, events));
}
Exemple #4
0
int
RUMP_VOP_POLL(struct vnode *vp,
    int events)
{
	int error;

	rump_schedule();
	error = VOP_POLL(vp, events);
	rump_unschedule();

	return error;
}
Exemple #5
0
static int
unionfs_poll(void *v)
{
	struct vop_poll_args *ap = v;
	struct unionfs_node *unp;
	struct unionfs_node_status *unsp;
	struct vnode   *ovp;

 	vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY);
	unp = VTOUNIONFS(ap->a_vp);
	unionfs_get_node_status(unp, &unsp);
	ovp = (unsp->uns_upper_opencnt ? unp->un_uppervp : unp->un_lowervp);
	unionfs_tryrem_node_status(unp, unsp);
	VOP_UNLOCK(ap->a_vp);

	if (ovp == NULLVP)
		return (EBADF);

	return (VOP_POLL(ovp, ap->a_events));
}
Exemple #6
0
/*
 * Associate event port polldat_t structure with sub-system pointer to
 * a polhead_t structure.
 */
static int
port_bind_pollhead(pollhead_t **php, polldat_t *pdp, short *revents)
{
	int		error;
	file_t		*fp;

	/*
	 * During re-association of a fd with a port the pd_php pointer
	 * is still the same as at the first association time.
	 */
	if (pdp->pd_php == *php)
		return (0);		/* already associated */

	/* polldat_t associated with another pollhead_t pointer */
	if (pdp->pd_php != NULL)
		pollhead_delete(pdp->pd_php, pdp);

	/*
	 * Before pollhead_insert() pollwakeup() will not detect a polldat
	 * entry in the ph_list and the event notification will disappear.
	 * This happens because polldat_t is still not associated with
	 * the pointer to the pollhead_t structure.
	 */
	pollhead_insert(*php, pdp);

	/*
	 * From now on event notification can be detected in pollwakeup(),
	 * Use VOP_POLL() again to check the current status of the event.
	 */
	pdp->pd_php = *php;
	fp = pdp->pd_fp;
	curthread->t_pollcache = (pollcache_t *)pdp->pd_pcache;
	error = VOP_POLL(fp->f_vnode, pdp->pd_events, 0, revents, php);
	curthread->t_pollcache = NULL;
	return (error);
}
Exemple #7
0
/*
 * File table vnode poll routine.
 */
int
vn_poll(struct file *fp, int events, struct proc *p)
{
	return (VOP_POLL(((struct vnode *)fp->f_data), events, p));
}
Exemple #8
0
/*
 * File table vnode poll routine.
 */
static int
vn_poll(file_t *fp, int events)
{

	return (VOP_POLL(fp->f_data, events));
}
Exemple #9
0
/*
 * port_associate_fd()
 * This function associates new file descriptors with a port or
 * reactivate already associated file descriptors.
 * The reactivation also updates the events types to be checked and the
 * attached user pointer.
 * Per port a cache is used to store associated file descriptors.
 * Internally the VOP_POLL interface is used to poll for existing events.
 * The VOP_POLL interface can also deliver a pointer to a pollhead_t structure
 * which is used to enqueue polldat_t structures with pending events.
 * If VOP_POLL immediately returns valid events (revents) then those events
 * will be submitted to the event port with port_send_event().
 * Otherwise VOP_POLL does not return events but it delivers a pointer to a
 * pollhead_t structure. In such a case the corresponding file system behind
 * VOP_POLL will use the pollwakeup() function to notify about exisiting
 * events.
 */
int
port_associate_fd(port_t *pp, int source, uintptr_t object, int events,
    void *user)
{
	port_fdcache_t	*pcp;
	int		fd;
	struct pollhead	*php = NULL;
	portfd_t	*pfd;
	polldat_t	*pdp;
	file_t		*fp;
	port_kevent_t	*pkevp;
	short		revents;
	int		error = 0;

	pcp = pp->port_queue.portq_pcp;
	if (object > (uintptr_t)INT_MAX)
		return (EBADFD);

	fd = object;

	if ((fp = getf(fd)) == NULL)
		return (EBADFD);

	mutex_enter(&pcp->pc_lock);
	if (pcp->pc_hash == NULL) {
		/*
		 * This is the first time that a fd is being associated with
		 * the current port:
		 * - create PORT_SOURCE_FD cache
		 * - associate PORT_SOURCE_FD source with the port
		 */
		error = port_associate_ksource(pp->port_fd, PORT_SOURCE_FD,
		    NULL, port_close_sourcefd, pp, NULL);
		if (error) {
			mutex_exit(&pcp->pc_lock);
			releasef(fd);
			return (error);
		}

		/* create polldat cache */
		pcp->pc_hashsize = PORTHASH_START;
		pcp->pc_hash = kmem_zalloc(pcp->pc_hashsize *
		    sizeof (portfd_t *), KM_SLEEP);
		pfd = NULL;
	} else {
		/* Check if the fd/fp is already associated with the port */
		pfd = port_cache_lookup_fp(pcp, fd, fp);
	}

	if (pfd == NULL) {
		/*
		 * new entry
		 * Allocate a polldat_t structure per fd
		 * The use of the polldat_t structure to cache file descriptors
		 * is required to be able to share the pollwakeup() function
		 * with poll(2) and devpoll(7d).
		 */
		pfd = kmem_zalloc(sizeof (portfd_t), KM_SLEEP);
		pdp = PFTOD(pfd);
		pdp->pd_fd = fd;
		pdp->pd_fp = fp;
		pdp->pd_pcache = (void *)pcp;

		/* Allocate a port event structure per fd */
		error = port_alloc_event_local(pp, source, PORT_ALLOC_CACHED,
		    &pdp->pd_portev);
		if (error) {
			kmem_free(pfd, sizeof (portfd_t));
			releasef(fd);
			mutex_exit(&pcp->pc_lock);
			return (error);
		}
		pkevp = pdp->pd_portev;
		pkevp->portkev_callback = port_fd_callback;
		pkevp->portkev_arg = pfd;

		/* add portfd_t entry  to the cache */
		port_cache_insert_fd(pcp, pdp);
		pkevp->portkev_object = fd;
		pkevp->portkev_user = user;

		/*
		 * Add current port to the file descriptor interested list
		 * The members of the list are notified when the file descriptor
		 * is closed.
		 */
		addfd_port(fd, pfd);
	} else {
		/*
		 * The file descriptor is already associated with the port
		 */
		pdp = PFTOD(pfd);
		pkevp = pdp->pd_portev;

		/*
		 * Check if the re-association happens before the last
		 * submitted event of the file descriptor was retrieved.
		 * Clear the PORT_KEV_VALID flag if set. No new events
		 * should get submitted after this flag is cleared.
		 */
		mutex_enter(&pkevp->portkev_lock);
		if (pkevp->portkev_flags & PORT_KEV_VALID) {
			pkevp->portkev_flags &= ~PORT_KEV_VALID;
		}
		if (pkevp->portkev_flags & PORT_KEV_DONEQ) {
			mutex_exit(&pkevp->portkev_lock);
			/*
			 * Remove any events that where already fired
			 * for this fd and are still in the port queue.
			 */
			port_remove_done_event(pkevp);
		} else {
			mutex_exit(&pkevp->portkev_lock);
		}
		pkevp->portkev_user = user;
	}

	mutex_enter(&pkevp->portkev_lock);
	pkevp->portkev_events = 0;	/* no fired events */
	pdp->pd_events = events;	/* events associated */
	/*
	 * allow new events.
	 */
	pkevp->portkev_flags |= PORT_KEV_VALID;
	mutex_exit(&pkevp->portkev_lock);

	/*
	 * do VOP_POLL and cache this poll fd.
	 *
	 * XXX - pollrelock() logic needs to know
	 * which pollcache lock to grab. It'd be a
	 * cleaner solution if we could pass pcp as
	 * an arguement in VOP_POLL interface instead
	 * of implicitly passing it using thread_t
	 * struct. On the other hand, changing VOP_POLL
	 * interface will require all driver/file system
	 * poll routine to change.
	 */
	curthread->t_pollcache = (pollcache_t *)pcp;
	error = VOP_POLL(fp->f_vnode, events, 0, &revents, &php);
	curthread->t_pollcache = NULL;

	/*
	 * To keep synchronization between VOP_POLL above and
	 * pollhead_insert below, it is necessary to
	 * call VOP_POLL() again (see port_bind_pollhead()).
	 */
	if (error) {
		/* dissociate the fd from the port */
		delfd_port(fd, pfd);
		port_remove_fd_local(pfd, pcp);
		releasef(fd);
		mutex_exit(&pcp->pc_lock);
		return (error);
	}

	if (php != NULL) {
		/*
		 * No events delivered yet.
		 * Bind pollhead pointer with current polldat_t structure.
		 * Sub-system will call pollwakeup() later with php as
		 * argument.
		 */
		error = port_bind_pollhead(&php, pdp, &revents);
		if (error) {
			delfd_port(fd, pfd);
			port_remove_fd_local(pfd, pcp);
			releasef(fd);
			mutex_exit(&pcp->pc_lock);
			return (error);
		}
	}

	/*
	 * Check if new events where detected and no events have been
	 * delivered. The revents was already set after the VOP_POLL
	 * above or it was updated in port_bind_pollhead().
	 */
	mutex_enter(&pkevp->portkev_lock);
	if (revents && (pkevp->portkev_flags & PORT_KEV_VALID)) {
		ASSERT((pkevp->portkev_flags & PORT_KEV_DONEQ) == 0);
		pkevp->portkev_flags &= ~PORT_KEV_VALID;
		revents = revents & (pdp->pd_events | POLLHUP | POLLERR);
		/* send events to the event port */
		pkevp->portkev_events = revents;
		/*
		 * port_send_event will release the portkev_lock mutex.
		 */
		port_send_event(pkevp);
	} else {
		mutex_exit(&pkevp->portkev_lock);
	}

	releasef(fd);
	mutex_exit(&pcp->pc_lock);
	return (error);
}