/* * 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)); }
/* * 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); }
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); }
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); }
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); }