예제 #1
0
/*
 * close the pfsnode (vp) after doing i/o.
 * (vp) is not locked on entry or exit.
 *
 * nothing to do for procfs other than undo
 * any exclusive open flag (see _open above).
 */
static int
linprocfs_close(struct vop_close_args *ap)
{
	struct pfsnode *pfs = VTOPFS(ap->a_vp);
	struct proc *p;

	switch (pfs->pfs_type) {
	case Pmem:
		if ((ap->a_fflag & FWRITE) && (pfs->pfs_flags & O_EXCL))
			pfs->pfs_flags &= ~(FWRITE|O_EXCL);
		/*
		 * If this is the last close, then it checks to see if
		 * the target process has PF_LINGER set in p_pfsflags,
		 * if this is *not* the case, then the process' stop flags
		 * are cleared, and the process is woken up.  This is
		 * to help prevent the case where a process has been
		 * told to stop on an event, but then the requesting process
		 * has gone away or forgotten about it.
		 */
		p = NULL;
		if ((ap->a_vp->v_opencount < 2)
		    && (p = pfind(pfs->pfs_pid))
		    && !(p->p_pfsflags & PF_LINGER)) {
			p->p_stops = 0;
			p->p_step = 0;
			wakeup(&p->p_step);
		}
		if (p)
			PRELE(p);
		break;
	default:
		break;
	}
	return (vop_stdclose(ap));
}
예제 #2
0
/*
 * nwfs_close(struct vnode *a_vp, int a_fflag)
 */
static int
nwfs_close(struct vop_close_args *ap)
{
	thread_t td = curthread; /* XXX */
	struct vnode *vp = ap->a_vp;
	struct nwnode *np = VTONW(vp);
	int error;

	NCPVNDEBUG("name=%s,td=%p,c=%d\n",np->n_name,ap->a_td,np->opened);

	vn_lock(vp, LK_UPGRADE | LK_RETRY);

	error = 0;
	if (vp->v_type == VDIR)
		goto done;
	if (np->opened == 0)
		goto done;
	error = nwfs_vinvalbuf(vp, V_SAVE, 1);
	if (np->opened == 0) {
		error = 0;	/* huh? */
		goto done;
	}
	if (--np->opened == 0) {
		error = ncp_close_file(NWFSTOCONN(VTONWFS(vp)), &np->n_fh, 
		   td, proc0.p_ucred);
	} 
	np->n_atime = 0;
done:
	vop_stdclose(ap);
	return (error);
}
예제 #3
0
static int
puffs_vnop_close(struct vop_close_args *ap)
{
    PUFFS_MSG_VARS(vn, close);
    struct vnode *vp = ap->a_vp;
    struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);

    vn_lock(vp, LK_UPGRADE | LK_RETRY);

    if (!EXISTSOP(pmp, CLOSE))
        return vop_stdclose(ap);

    PUFFS_MSG_ALLOC(vn, close);
    puffs_msg_setfaf(park_close);
    close_msg->pvnr_fflag = ap->a_fflag;
    puffs_msg_setinfo(park_close, PUFFSOP_VN,
                      PUFFS_VN_CLOSE, VPTOPNC(vp));

    puffs_msg_enqueue(pmp, park_close);
    PUFFS_MSG_RELEASE(close);
    return vop_stdclose(ap);
}
예제 #4
0
static int
tmpfs_close(struct vop_close_args *v)
{
	struct vnode *vp = v->a_vp;
	struct tmpfs_node *node;

	node = VP_TO_TMPFS_NODE(vp);

	if (node->tn_links > 0) {
		/* Update node times.  No need to do it if the node has
		 * been deleted, because it will vanish after we return. */
		tmpfs_update(vp);
	}

	return vop_stdclose(v);
}
예제 #5
0
static int
devfs_spec_close(struct vop_close_args *ap)
{
	struct devfs_node *node;
	struct proc *p = curproc;
	struct vnode *vp = ap->a_vp;
	cdev_t dev = vp->v_rdev;
	int error = 0;
	int needrelock;

	/*
	 * We do special tests on the opencount so unfortunately we need
	 * an exclusive lock.
	 */
	vn_lock(vp, LK_UPGRADE | LK_RETRY);

	if (dev)
		devfs_debug(DEVFS_DEBUG_DEBUG,
			    "devfs_spec_close() called on %s! \n",
			    dev->si_name);
	else
		devfs_debug(DEVFS_DEBUG_DEBUG,
			    "devfs_spec_close() called, null vode!\n");

	/*
	 * A couple of hacks for devices and tty devices.  The
	 * vnode ref count cannot be used to figure out the
	 * last close, but we can use v_opencount now that
	 * revoke works properly.
	 *
	 * Detect the last close on a controlling terminal and clear
	 * the session (half-close).
	 */
	if (dev)
		reference_dev(dev);

	if (p && vp->v_opencount <= 1 && vp == p->p_session->s_ttyvp) {
		p->p_session->s_ttyvp = NULL;
		vrele(vp);
	}

	/*
	 * Vnodes can be opened and closed multiple times.  Do not really
	 * close the device unless (1) it is being closed forcibly,
	 * (2) the device wants to track closes, or (3) this is the last
	 * vnode doing its last close on the device.
	 *
	 * XXX the VXLOCK (force close) case can leave vnodes referencing
	 * a closed device.  This might not occur now that our revoke is
	 * fixed.
	 */
	devfs_debug(DEVFS_DEBUG_DEBUG, "devfs_spec_close() -1- \n");
	if (dev && ((vp->v_flag & VRECLAIMED) ||
	    (dev_dflags(dev) & D_TRACKCLOSE) ||
	    (vp->v_opencount == 1))) {
		/*
		 * Ugly pty magic, to make pty devices disappear again once
		 * they are closed.
		 */
		node = DEVFS_NODE(ap->a_vp);
		if (node && (node->flags & DEVFS_PTY))
			node->flags |= DEVFS_INVISIBLE;

		/*
		 * Unlock around dev_dclose(), unless the vnode is
		 * undergoing a vgone/reclaim (during umount).
		 */
		needrelock = 0;
		if ((vp->v_flag & VRECLAIMED) == 0 && vn_islocked(vp)) {
			needrelock = 1;
			vn_unlock(vp);
		}

		/*
		 * WARNING!  If the device destroys itself the devfs node
		 *	     can disappear here.
		 *
		 * WARNING!  vn_lock() will fail if the vp is in a VRECLAIM,
		 *	     which can occur during umount.
		 */
		error = dev_dclose(dev, ap->a_fflag, S_IFCHR, ap->a_fp);
		/* node is now stale */

		if (needrelock) {
			if (vn_lock(vp, LK_EXCLUSIVE |
					LK_RETRY |
					LK_FAILRECLAIM) != 0) {
				panic("devfs_spec_close: vnode %p "
				      "unexpectedly could not be relocked",
				      vp);
			}
		}
	} else {
		error = 0;
	}
	devfs_debug(DEVFS_DEBUG_DEBUG, "devfs_spec_close() -2- \n");

	/*
	 * Track the actual opens and closes on the vnode.  The last close
	 * disassociates the rdev.  If the rdev is already disassociated or
	 * the opencount is already 0, the vnode might have been revoked
	 * and no further opencount tracking occurs.
	 */
	if (dev)
		release_dev(dev);
	if (vp->v_opencount > 0)
		vop_stdclose(ap);
	return(error);

}