/*ARGSUSED*/ int spec_sync(struct vfs *vfsp, short flag, struct cred *cr) { struct snode *sync_list; register struct snode **spp, *sp, *spnext; register struct vnode *vp; if (mutex_tryenter(&spec_syncbusy) == 0) return (0); if (flag & SYNC_ATTR) { mutex_exit(&spec_syncbusy); return (0); } mutex_enter(&stable_lock); sync_list = NULL; /* * Find all the snodes that are dirty and add them to the sync_list */ for (spp = stable; spp < &stable[STABLESIZE]; spp++) { for (sp = *spp; sp != NULL; sp = sp->s_next) { vp = STOV(sp); /* * Don't bother sync'ing a vp if it's * part of a virtual swap device. */ if (IS_SWAPVP(vp)) continue; if (vp->v_type == VBLK && vn_has_cached_data(vp)) { /* * Prevent vp from going away before we * we get a chance to do a VOP_PUTPAGE * via sync_list processing */ VN_HOLD(vp); sp->s_list = sync_list; sync_list = sp; } } } mutex_exit(&stable_lock); /* * Now write out all the snodes we marked asynchronously. */ for (sp = sync_list; sp != NULL; sp = spnext) { spnext = sp->s_list; vp = STOV(sp); (void) VOP_PUTPAGE(vp, (offset_t)0, (uint_t)0, B_ASYNC, cr); VN_RELE(vp); /* Release our hold on vnode */ } mutex_exit(&spec_syncbusy); return (0); }
/* * New Leaf driver open entry point. We make a vnode and go through specfs * in order to obtain open close exclusions guarantees. Note that we drop * OTYP_LYR if it was specified - we are going through specfs and it provides * last close semantics (FKLYR is provided to open(9E)). Also, since * spec_open will drive attach via e_ddi_hold_devi_by_dev for a makespecvp * vnode with no SDIP_SET on the common snode, the dev_lopen caller no longer * needs to call ddi_hold_installed_driver. */ int dev_lopen(dev_t *devp, int flag, int otype, struct cred *cred) { struct vnode *vp; int error; struct vnode *cvp; vp = makespecvp(*devp, (otype == OTYP_BLK) ? VBLK : VCHR); error = VOP_OPEN(&vp, flag | FKLYR, cred, NULL); if (error == 0) { /* Pick up the (possibly) new dev_t value. */ *devp = vp->v_rdev; /* * Place extra hold on the common vnode, which contains the * open count, so that it is not destroyed by the VN_RELE of * the shadow makespecvp vnode below. */ cvp = STOV(VTOCS(vp)); VN_HOLD(cvp); } /* release the shadow makespecvp vnode. */ VN_RELE(vp); return (error); }
/* * Leaf driver close entry point. We make a vnode and go through specfs in * order to obtain open close exclusions guarantees. Note that we drop * OTYP_LYR if it was specified - we are going through specfs and it provides * last close semantics (FLKYR is provided to close(9E)). */ int dev_lclose(dev_t dev, int flag, int otype, struct cred *cred) { struct vnode *vp; int error; struct vnode *cvp; char *funcname; ulong_t offset; vp = makespecvp(dev, (otype == OTYP_BLK) ? VBLK : VCHR); error = VOP_CLOSE(vp, flag | FKLYR, 1, (offset_t)0, cred, NULL); /* * Release the extra dev_lopen hold on the common vnode. We inline a * VN_RELE(cvp) call so that we can detect more dev_lclose calls than * dev_lopen calls without panic. See vn_rele. If our inline of * vn_rele called VOP_INACTIVE(cvp, CRED(), ...) we would panic on the * "release the makespecvp vnode" VN_RELE(vp) that follows - so * instead we diagnose this situation. Note that the driver has * still seen a double close(9E), but that would have occurred with * the old dev_close implementation too. */ cvp = STOV(VTOCS(vp)); mutex_enter(&cvp->v_lock); switch (cvp->v_count) { default: cvp->v_count--; break; case 0: VTOS(vp)->s_commonvp = NULL; /* avoid panic */ /*FALLTHROUGH*/ case 1: /* * The following message indicates a serious problem in the * identified driver, the driver should be fixed. If obtaining * a panic dump is needed to diagnose the driver problem then * adding "set dev_lclose_ce=3" to /etc/system will cause a * panic when this occurs. */ funcname = modgetsymname((uintptr_t)caller(), &offset); cmn_err(dev_lclose_ce, "dev_lclose: extra close of dev_t 0x%lx " "from %s`%s()", dev, mod_containing_pc(caller()), funcname ? funcname : "unknown..."); break; } mutex_exit(&cvp->v_lock); /* release the makespecvp vnode. */ VN_RELE(vp); return (error); }
static int synthfs_insertnode(struct synthfsnode *newnode_sp, struct synthfsnode *parent_sp) { struct timeval now; DBG_ASSERT(parent_sp->s_type == SYNTHFS_DIRECTORY); TAILQ_INSERT_TAIL(&parent_sp->s_u.d.d_subnodes, newnode_sp, s_sibling); ++parent_sp->s_u.d.d_entrycount; newnode_sp->s_parent = parent_sp; parent_sp->s_nodeflags |= IN_CHANGE | IN_MODIFIED; now = time; VOP_UPDATE(STOV(parent_sp), &now, &now, 0); return 0; }