Beispiel #1
0
/* ARGSUSED */
static int
cgd_ioctl_clr(struct cgd_softc *cs, struct lwp *l)
{
	struct	dk_softc *dksc = &cs->sc_dksc;

	if (!DK_ATTACHED(dksc))
		return ENXIO;

	/* Delete all of our wedges. */
	dkwedge_delall(&dksc->sc_dkdev);

	/* Kill off any queued buffers. */
	dk_drain(dksc);
	bufq_free(dksc->sc_bufq);

	(void)vn_close(cs->sc_tvn, FREAD|FWRITE, l->l_cred);
	cs->sc_cfuncs->cf_destroy(cs->sc_cdata.cf_priv);
	free(cs->sc_tpath, M_DEVBUF);
	free(cs->sc_data, M_DEVBUF);
	cs->sc_data_used = 0;
	dk_detach(dksc);
	disk_detach(&dksc->sc_dkdev);

	return 0;
}
Beispiel #2
0
static int
ssdetach(device_t self, int flags)
{
	struct ss_softc *ss = device_private(self);
	int s, cmaj, mn;

	/* locate the major number */
	cmaj = cdevsw_lookup_major(&ss_cdevsw);

	/* kill any pending restart */
	callout_stop(&ss->sc_callout);

	s = splbio();

	/* Kill off any queued buffers. */
	bufq_drain(ss->buf_queue);

	bufq_free(ss->buf_queue);

	/* Kill off any pending commands. */
	scsipi_kill_pending(ss->sc_periph);

	splx(s);

	/* Nuke the vnodes for any open instances */
	mn = SSUNIT(device_unit(self));
	vdevgone(cmaj, mn, mn+SSNMINOR-1, VCHR);

	return 0;
}
Beispiel #3
0
int
mfs_mountroot(void)
{
	struct fs *fs;
	struct mount *mp;
	struct lwp *l = curlwp;		/* XXX */
	struct ufsmount *ump;
	struct mfsnode *mfsp;
	int error = 0;

	if ((error = vfs_rootmountalloc(MOUNT_MFS, "mfs_root", &mp))) {
		vrele(rootvp);
		return (error);
	}

	mfsp = kmem_alloc(sizeof(*mfsp), KM_SLEEP);
	rootvp->v_data = mfsp;
	rootvp->v_op = mfs_vnodeop_p;
	rootvp->v_tag = VT_MFS;
	mfsp->mfs_baseoff = mfs_rootbase;
	mfsp->mfs_size = mfs_rootsize;
	mfsp->mfs_vnode = rootvp;
	mfsp->mfs_proc = NULL;		/* indicate kernel space */
	mfsp->mfs_shutdown = 0;
	cv_init(&mfsp->mfs_cv, "mfs");
	mfsp->mfs_refcnt = 1;
	bufq_alloc(&mfsp->mfs_buflist, "fcfs", 0);
	if ((error = ffs_mountfs(rootvp, mp, l)) != 0) {
		vfs_unbusy(mp, false, NULL);
		bufq_free(mfsp->mfs_buflist);
		vfs_destroy(mp);
		kmem_free(mfsp, sizeof(*mfsp));
		return (error);
	}
	mutex_enter(&mountlist_lock);
	CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
	mutex_exit(&mountlist_lock);
	mp->mnt_vnodecovered = NULLVP;
	ump = VFSTOUFS(mp);
	fs = ump->um_fs;
	(void) copystr(mp->mnt_stat.f_mntonname, fs->fs_fsmnt, MNAMELEN - 1, 0);
	(void)ffs_statvfs(mp, &mp->mnt_stat);
	vfs_unbusy(mp, false, NULL);
	return (0);
}
static int
vnd_detach(device_t self, int flags)
{
	int error;
	struct vnd_softc *sc = device_private(self);

	if (sc->sc_flags & VNF_INITED) {
		error = vnddoclear(sc, 0, -1, (flags & DETACH_FORCE) != 0);
		if (error != 0)
			return error;
	}

	pmf_device_deregister(self);
	bufq_free(sc->sc_tab);
	disk_destroy(&sc->sc_dkdev);

	return 0;
}
Beispiel #5
0
static int
fddetach(device_t self, int flags)
{
	struct fd_softc *fd = device_private(self);
	int bmaj, cmaj, i, mn;

	fd_motor_off(fd);

	/* locate the major number */
	bmaj = bdevsw_lookup_major(&fd_bdevsw);
	cmaj = cdevsw_lookup_major(&fd_cdevsw);

	/* Nuke the vnodes for any open instances. */
	for (i = 0; i < MAXPARTITIONS; i++) {
		mn = DISKMINOR(device_unit(self), i);
		vdevgone(bmaj, mn, mn, VBLK);
		vdevgone(cmaj, mn, mn, VCHR);
	}

	pmf_device_deregister(self);

#if 0 /* XXX need to undo at detach? */
	fd_set_properties(fd);
#endif
#if NRND > 0
	rnd_detach_source(&fd->rnd_source);
#endif

	disk_detach(&fd->sc_dk);
	disk_destroy(&fd->sc_dk);

	/* Kill off any queued buffers. */
	bufq_drain(fd->sc_q);

	bufq_free(fd->sc_q);

	callout_destroy(&fd->sc_motoroff_ch);
	callout_destroy(&fd->sc_motoron_ch);

	return 0;
}
/*
 * Reclaim a memory filesystem devvp so that it can be reused.
 */
int
mfs_reclaim(void *v)
{
	struct vop_reclaim_args /* {
		struct vnode *a_vp;
	} */ *ap = v;
	struct vnode *vp = ap->a_vp;
	struct mfsnode *mfsp = VTOMFS(vp);
	int refcnt;

	mutex_enter(&mfs_lock);
	vp->v_data = NULL;
	refcnt = --mfsp->mfs_refcnt;
	mutex_exit(&mfs_lock);

	if (refcnt == 0) {
		bufq_free(mfsp->mfs_buflist);
		cv_destroy(&mfsp->mfs_cv);
		kmem_free(mfsp, sizeof(*mfsp));
	}

	return VOCALL(spec_vnodeop_p,  VOFFSET(vop_reclaim), ap);
}
Beispiel #7
0
static int
fss_detach(device_t self, int flags)
{
	struct fss_softc *sc = device_private(self);

	if (sc->sc_flags & FSS_ACTIVE)
		return EBUSY;

	if (--fss_num_attached == 0)
		vfs_hooks_detach(&fss_vfs_hooks);

	pmf_device_deregister(self);
	mutex_destroy(&sc->sc_slock);
	mutex_destroy(&sc->sc_lock);
	cv_destroy(&sc->sc_work_cv);
	cv_destroy(&sc->sc_cache_cv);
	bufq_drain(sc->sc_bufq);
	bufq_free(sc->sc_bufq);
	disk_destroy(sc->sc_dkdev);
	free(sc->sc_dkdev, M_DEVBUF);

	return 0;
}
Beispiel #8
0
int
dk_ioctl(struct dk_softc *dksc, dev_t dev,
	    u_long cmd, void *data, int flag, struct lwp *l)
{
	const struct dkdriver *dkd = dksc->sc_dkdev.dk_driver;
	struct	disklabel *lp;
	struct	disk *dk = &dksc->sc_dkdev;
#ifdef __HAVE_OLD_DISKLABEL
	struct	disklabel newlabel;
#endif
	int	error;

	DPRINTF_FOLLOW(("%s(%s, %p, 0x%"PRIx64", 0x%lx)\n", __func__,
	    dksc->sc_xname, dksc, dev, cmd));

	/* ensure that the pseudo disk is open for writes for these commands */
	switch (cmd) {
	case DIOCSDINFO:
	case DIOCWDINFO:
#ifdef __HAVE_OLD_DISKLABEL
	case ODIOCSDINFO:
	case ODIOCWDINFO:
#endif
	case DIOCKLABEL:
	case DIOCWLABEL:
	case DIOCAWEDGE:
	case DIOCDWEDGE:
	case DIOCSSTRATEGY:
		if ((flag & FWRITE) == 0)
			return EBADF;
	}

	/* ensure that the pseudo-disk is initialized for these */
	switch (cmd) {
	case DIOCGDINFO:
	case DIOCSDINFO:
	case DIOCWDINFO:
	case DIOCGPARTINFO:
	case DIOCKLABEL:
	case DIOCWLABEL:
	case DIOCGDEFLABEL:
	case DIOCAWEDGE:
	case DIOCDWEDGE:
	case DIOCLWEDGES:
	case DIOCMWEDGES:
	case DIOCCACHESYNC:
#ifdef __HAVE_OLD_DISKLABEL
	case ODIOCGDINFO:
	case ODIOCSDINFO:
	case ODIOCWDINFO:
	case ODIOCGDEFLABEL:
#endif
		if ((dksc->sc_flags & DKF_INITED) == 0)
			return ENXIO;
	}

	error = disk_ioctl(dk, dev, cmd, data, flag, l);
	if (error != EPASSTHROUGH)
		return error;
	else
		error = 0;

	switch (cmd) {
	case DIOCWDINFO:
	case DIOCSDINFO:
#ifdef __HAVE_OLD_DISKLABEL
	case ODIOCWDINFO:
	case ODIOCSDINFO:
#endif
#ifdef __HAVE_OLD_DISKLABEL
		if (cmd == ODIOCSDINFO || cmd == ODIOCWDINFO) {
			memset(&newlabel, 0, sizeof newlabel);
			memcpy(&newlabel, data, sizeof (struct olddisklabel));
			lp = &newlabel;
		} else
#endif
		lp = (struct disklabel *)data;

		mutex_enter(&dk->dk_openlock);
		dksc->sc_flags |= DKF_LABELLING;

		error = setdisklabel(dksc->sc_dkdev.dk_label,
		    lp, 0, dksc->sc_dkdev.dk_cpulabel);
		if (error == 0) {
			if (cmd == DIOCWDINFO
#ifdef __HAVE_OLD_DISKLABEL
			    || cmd == ODIOCWDINFO
#endif
			   )
				error = writedisklabel(DKLABELDEV(dev),
				    dkd->d_strategy, dksc->sc_dkdev.dk_label,
				    dksc->sc_dkdev.dk_cpulabel);
		}

		dksc->sc_flags &= ~DKF_LABELLING;
		mutex_exit(&dk->dk_openlock);
		break;

	case DIOCKLABEL:
		if (*(int *)data != 0)
			dksc->sc_flags |= DKF_KLABEL;
		else
			dksc->sc_flags &= ~DKF_KLABEL;
		break;

	case DIOCWLABEL:
		if (*(int *)data != 0)
			dksc->sc_flags |= DKF_WLABEL;
		else
			dksc->sc_flags &= ~DKF_WLABEL;
		break;

	case DIOCGDEFLABEL:
		dk_getdefaultlabel(dksc, (struct disklabel *)data);
		break;

#ifdef __HAVE_OLD_DISKLABEL
	case ODIOCGDEFLABEL:
		dk_getdefaultlabel(dksc, &newlabel);
		if (newlabel.d_npartitions > OLDMAXPARTITIONS)
			return ENOTTY;
		memcpy(data, &newlabel, sizeof (struct olddisklabel));
		break;
#endif

	case DIOCGSTRATEGY:
	    {
		struct disk_strategy *dks = (void *)data;

		mutex_enter(&dksc->sc_iolock);
		strlcpy(dks->dks_name, bufq_getstrategyname(dksc->sc_bufq),
		    sizeof(dks->dks_name));
		mutex_exit(&dksc->sc_iolock);
		dks->dks_paramlen = 0;

		return 0;
	    }

	case DIOCSSTRATEGY:
	    {
		struct disk_strategy *dks = (void *)data;
		struct bufq_state *new;
		struct bufq_state *old;

		if (dks->dks_param != NULL) {
			return EINVAL;
		}
		dks->dks_name[sizeof(dks->dks_name) - 1] = 0; /* ensure term */
		error = bufq_alloc(&new, dks->dks_name,
		    BUFQ_EXACT|BUFQ_SORT_RAWBLOCK);
		if (error) {
			return error;
		}
		mutex_enter(&dksc->sc_iolock);
		old = dksc->sc_bufq;
		bufq_move(new, old);
		dksc->sc_bufq = new;
		mutex_exit(&dksc->sc_iolock);
		bufq_free(old);

		return 0;
	    }

	default:
		error = ENOTTY;
	}

	return error;
}
Beispiel #9
0
/* ARGSUSED */
int
mfs_start(struct mount *mp, int flags)
{
	struct vnode *vp;
	struct mfsnode *mfsp;
	struct proc *p;
	struct buf *bp;
	void *base;
	int sleepreturn = 0, refcnt, error;
	ksiginfoq_t kq;

	/*
	 * Ensure that file system is still mounted when getting mfsnode.
	 * Add a reference to the mfsnode to prevent it disappearing in
	 * this routine.
	 */
	if ((error = vfs_busy(mp, NULL)) != 0)
		return error;
	vp = VFSTOUFS(mp)->um_devvp;
	mfsp = VTOMFS(vp);
	mutex_enter(&mfs_lock);
	mfsp->mfs_refcnt++;
	mutex_exit(&mfs_lock);
	vfs_unbusy(mp, false, NULL);

	base = mfsp->mfs_baseoff;
	mutex_enter(&mfs_lock);
	while (mfsp->mfs_shutdown != 1) {
		while ((bp = bufq_get(mfsp->mfs_buflist)) != NULL) {
			mutex_exit(&mfs_lock);
			mfs_doio(bp, base);
			mutex_enter(&mfs_lock);
		}
		/*
		 * If a non-ignored signal is received, try to unmount.
		 * If that fails, or the filesystem is already in the
		 * process of being unmounted, clear the signal (it has been
		 * "processed"), otherwise we will loop here, as tsleep
		 * will always return EINTR/ERESTART.
		 */
		if (sleepreturn != 0) {
			mutex_exit(&mfs_lock);
			if (dounmount(mp, 0, curlwp) != 0) {
				p = curproc;
				ksiginfo_queue_init(&kq);
				mutex_enter(p->p_lock);
				sigclearall(p, NULL, &kq);
				mutex_exit(p->p_lock);
				ksiginfo_queue_drain(&kq);
			}
			sleepreturn = 0;
			mutex_enter(&mfs_lock);
			continue;
		}

		sleepreturn = cv_wait_sig(&mfsp->mfs_cv, &mfs_lock);
	}
	KASSERT(bufq_peek(mfsp->mfs_buflist) == NULL);
	refcnt = --mfsp->mfs_refcnt;
	mutex_exit(&mfs_lock);
	if (refcnt == 0) {
		bufq_free(mfsp->mfs_buflist);
		cv_destroy(&mfsp->mfs_cv);
		kmem_free(mfsp, sizeof(*mfsp));
	}
	return (sleepreturn);
}
int
dk_ioctl(struct dk_intf *di, struct dk_softc *dksc, dev_t dev,
	    u_long cmd, void *data, int flag, struct lwp *l)
{
	struct	disklabel *lp;
	struct	disk *dk;
#ifdef __HAVE_OLD_DISKLABEL
	struct	disklabel newlabel;
#endif
	int	error = 0;

	DPRINTF_FOLLOW(("dk_ioctl(%s, %p, 0x%"PRIx64", 0x%lx)\n",
	    di->di_dkname, dksc, dev, cmd));

	/* ensure that the pseudo disk is open for writes for these commands */
	switch (cmd) {
	case DIOCSDINFO:
	case DIOCWDINFO:
#ifdef __HAVE_OLD_DISKLABEL
	case ODIOCSDINFO:
	case ODIOCWDINFO:
#endif
	case DIOCWLABEL:
	case DIOCAWEDGE:
	case DIOCDWEDGE:
		if ((flag & FWRITE) == 0)
			return EBADF;
	}

	/* ensure that the pseudo-disk is initialized for these */
	switch (cmd) {
#ifdef DIOCGSECTORSIZE
	case DIOCGSECTORSIZE:
	case DIOCGMEDIASIZE:
#endif
	case DIOCGDINFO:
	case DIOCSDINFO:
	case DIOCWDINFO:
	case DIOCGPART:
	case DIOCWLABEL:
	case DIOCGDEFLABEL:
	case DIOCAWEDGE:
	case DIOCDWEDGE:
	case DIOCLWEDGES:
	case DIOCCACHESYNC:
#ifdef __HAVE_OLD_DISKLABEL
	case ODIOCGDINFO:
	case ODIOCSDINFO:
	case ODIOCWDINFO:
	case ODIOCGDEFLABEL:
#endif
		if ((dksc->sc_flags & DKF_INITED) == 0)
			return ENXIO;
	}

	switch (cmd) {
#ifdef DIOCGSECTORSIZE
	case DIOCGSECTORSIZE:
		*(u_int *)data = dksc->sc_dkdev.dk_geom.dg_secsize;
		return 0;
	case DIOCGMEDIASIZE:
		*(off_t *)data =
		    (off_t)dksc->sc_dkdev.dk_geom.dg_secsize *
		    dksc->sc_dkdev.dk_geom.dg_nsectors;
		return 0;
#endif

	case DIOCGDINFO:
		*(struct disklabel *)data = *(dksc->sc_dkdev.dk_label);
		break;

#ifdef __HAVE_OLD_DISKLABEL
	case ODIOCGDINFO:
		newlabel = *(dksc->sc_dkdev.dk_label);
		if (newlabel.d_npartitions > OLDMAXPARTITIONS)
			return ENOTTY;
		memcpy(data, &newlabel, sizeof (struct olddisklabel));
		break;
#endif

	case DIOCGPART:
		((struct partinfo *)data)->disklab = dksc->sc_dkdev.dk_label;
		((struct partinfo *)data)->part =
		    &dksc->sc_dkdev.dk_label->d_partitions[DISKPART(dev)];
		break;

	case DIOCWDINFO:
	case DIOCSDINFO:
#ifdef __HAVE_OLD_DISKLABEL
	case ODIOCWDINFO:
	case ODIOCSDINFO:
#endif
#ifdef __HAVE_OLD_DISKLABEL
		if (cmd == ODIOCSDINFO || cmd == ODIOCWDINFO) {
			memset(&newlabel, 0, sizeof newlabel);
			memcpy(&newlabel, data, sizeof (struct olddisklabel));
			lp = &newlabel;
		} else
#endif
		lp = (struct disklabel *)data;

		dk = &dksc->sc_dkdev;
		mutex_enter(&dk->dk_openlock);
		dksc->sc_flags |= DKF_LABELLING;

		error = setdisklabel(dksc->sc_dkdev.dk_label,
		    lp, 0, dksc->sc_dkdev.dk_cpulabel);
		if (error == 0) {
			if (cmd == DIOCWDINFO
#ifdef __HAVE_OLD_DISKLABEL
			    || cmd == ODIOCWDINFO
#endif
			   )
				error = writedisklabel(DKLABELDEV(dev),
				    di->di_strategy, dksc->sc_dkdev.dk_label,
				    dksc->sc_dkdev.dk_cpulabel);
		}

		dksc->sc_flags &= ~DKF_LABELLING;
		mutex_exit(&dk->dk_openlock);
		break;

	case DIOCWLABEL:
		if (*(int *)data != 0)
			dksc->sc_flags |= DKF_WLABEL;
		else
			dksc->sc_flags &= ~DKF_WLABEL;
		break;

	case DIOCGDEFLABEL:
		dk_getdefaultlabel(di, dksc, (struct disklabel *)data);
		break;

#ifdef __HAVE_OLD_DISKLABEL
	case ODIOCGDEFLABEL:
		dk_getdefaultlabel(di, dksc, &newlabel);
		if (newlabel.d_npartitions > OLDMAXPARTITIONS)
			return ENOTTY;
		memcpy(data, &newlabel, sizeof (struct olddisklabel));
		break;
#endif

	case DIOCAWEDGE:
	    {
	    	struct dkwedge_info *dkw = (void *)data;

		if ((flag & FWRITE) == 0)
			return (EBADF);

		/* If the ioctl happens here, the parent is us. */
		strcpy(dkw->dkw_parent, dksc->sc_dkdev.dk_name);
		return (dkwedge_add(dkw));
	    }

	case DIOCDWEDGE:
	    {
	    	struct dkwedge_info *dkw = (void *)data;

		if ((flag & FWRITE) == 0)
			return (EBADF);

		/* If the ioctl happens here, the parent is us. */
		strcpy(dkw->dkw_parent, dksc->sc_dkdev.dk_name);
		return (dkwedge_del(dkw));
	    }

	case DIOCLWEDGES:
	    {
	    	struct dkwedge_list *dkwl = (void *)data;

		return (dkwedge_list(&dksc->sc_dkdev, dkwl, l));
	    }

	case DIOCGSTRATEGY:
	    {
		struct disk_strategy *dks = (void *)data;
		int s;

		s = splbio();
		strlcpy(dks->dks_name, bufq_getstrategyname(dksc->sc_bufq),
		    sizeof(dks->dks_name));
		splx(s);
		dks->dks_paramlen = 0;

		return 0;
	    }
	
	case DIOCSSTRATEGY:
	    {
		struct disk_strategy *dks = (void *)data;
		struct bufq_state *new;
		struct bufq_state *old;
		int s;

		if ((flag & FWRITE) == 0) {
			return EBADF;
		}
		if (dks->dks_param != NULL) {
			return EINVAL;
		}
		dks->dks_name[sizeof(dks->dks_name) - 1] = 0; /* ensure term */
		error = bufq_alloc(&new, dks->dks_name,
		    BUFQ_EXACT|BUFQ_SORT_RAWBLOCK);
		if (error) {
			return error;
		}
		s = splbio();
		old = dksc->sc_bufq;
		bufq_move(new, old);
		dksc->sc_bufq = new;
		splx(s);
		bufq_free(old);

		return 0;
	    }

	default:
		error = ENOTTY;
	}

	return error;
}