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