Example #1
0
/*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);
}
Example #2
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);
}
Example #3
0
/*
 * 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);
}
Example #4
0
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;
}