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; }
void dk_drain(struct dk_softc *dksc) { struct buf *bp; mutex_enter(&dksc->sc_iolock); bp = dksc->sc_deferred; dksc->sc_deferred = NULL; if (bp != NULL) { bp->b_error = EIO; bp->b_resid = bp->b_bcount; biodone(bp); } bufq_drain(dksc->sc_bufq); mutex_exit(&dksc->sc_iolock); }
int wddetach(struct device *self, int flags) { struct wd_softc *sc = (struct wd_softc *)self; timeout_del(&sc->sc_restart_timeout); bufq_drain(&sc->sc_bufq); disk_gone(wdopen, self->dv_unit); /* Detach disk. */ bufq_destroy(&sc->sc_bufq); disk_detach(&sc->sc_dk); return (0); }
int sddetach(struct device *self, int flags) { struct sd_softc *sc = (struct sd_softc *)self; bufq_drain(&sc->sc_bufq); disk_gone(sdopen, self->dv_unit); /* Get rid of the shutdown hook. */ if (sc->sc_sdhook != NULL) shutdownhook_disestablish(sc->sc_sdhook); /* Detach disk. */ bufq_destroy(&sc->sc_bufq); disk_detach(&sc->sc_dk); 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; }
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; }
/* * sdstart looks to see if there is a buf waiting for the device * and that the device is not already busy. If both are true, * It dequeues the buf and creates a scsi command to perform the * transfer in the buf. The transfer request will call scsi_done * on completion, which will in turn call this routine again * so that the next queued transfer is performed. * The bufs are queued by the strategy routine (sdstrategy) * * This routine is also called after other non-queued requests * have been made of the scsi driver, to ensure that the queue * continues to be drained. */ void sdstart(struct scsi_xfer *xs) { struct scsi_link *link = xs->sc_link; struct sd_softc *sc = link->device_softc; struct buf *bp; u_int64_t secno; int nsecs; int read; struct partition *p; if (sc->flags & SDF_DYING) { scsi_xs_put(xs); return; } if ((link->flags & SDEV_MEDIA_LOADED) == 0) { bufq_drain(&sc->sc_bufq); scsi_xs_put(xs); return; } bp = bufq_dequeue(&sc->sc_bufq); if (bp == NULL) { scsi_xs_put(xs); return; } secno = DL_BLKTOSEC(sc->sc_dk.dk_label, bp->b_blkno); p = &sc->sc_dk.dk_label->d_partitions[DISKPART(bp->b_dev)]; secno += DL_GETPOFFSET(p); nsecs = howmany(bp->b_bcount, sc->sc_dk.dk_label->d_secsize); read = bp->b_flags & B_READ; /* * Fill out the scsi command. If the transfer will * fit in a "small" cdb, use it. */ if (!(link->flags & SDEV_ATAPI) && !(link->quirks & SDEV_ONLYBIG) && ((secno & 0x1fffff) == secno) && ((nsecs & 0xff) == nsecs)) sd_cmd_rw6(xs, read, secno, nsecs); else if (((secno & 0xffffffff) == secno) && ((nsecs & 0xffff) == nsecs)) sd_cmd_rw10(xs, read, secno, nsecs); else if (((secno & 0xffffffff) == secno) && ((nsecs & 0xffffffff) == nsecs)) sd_cmd_rw12(xs, read, secno, nsecs); else sd_cmd_rw16(xs, read, secno, nsecs); xs->flags |= (read ? SCSI_DATA_IN : SCSI_DATA_OUT); xs->timeout = 60000; xs->data = bp->b_data; xs->datalen = bp->b_bcount; xs->done = sd_buf_done; xs->cookie = bp; xs->bp = bp; /* Instrumentation. */ disk_busy(&sc->sc_dk); /* Mark disk as dirty. */ if (!read) sc->flags |= SDF_DIRTY; scsi_xs_exec(xs); /* move onto the next io */ if (ISSET(sc->flags, SDF_WAITING)) CLR(sc->flags, SDF_WAITING); else if (bufq_peek(&sc->sc_bufq)) scsi_xsh_add(&sc->sc_xsh); }
static void vndclear(struct vnd_softc *vnd, int myminor) { struct vnode *vp = vnd->sc_vp; int fflags = FREAD; int bmaj, cmaj, i, mn; int s; #ifdef DEBUG if (vnddebug & VDB_FOLLOW) printf("vndclear(%p): vp %p\n", vnd, vp); #endif /* locate the major number */ bmaj = bdevsw_lookup_major(&vnd_bdevsw); cmaj = cdevsw_lookup_major(&vnd_cdevsw); /* Nuke the vnodes for any open instances */ for (i = 0; i < MAXPARTITIONS; i++) { mn = DISKMINOR(device_unit(vnd->sc_dev), i); vdevgone(bmaj, mn, mn, VBLK); if (mn != myminor) /* XXX avoid to kill own vnode */ vdevgone(cmaj, mn, mn, VCHR); } if ((vnd->sc_flags & VNF_READONLY) == 0) fflags |= FWRITE; s = splbio(); bufq_drain(vnd->sc_tab); splx(s); vnd->sc_flags |= VNF_VUNCONF; wakeup(&vnd->sc_tab); while (vnd->sc_flags & VNF_KTHREAD) tsleep(&vnd->sc_kthread, PRIBIO, "vnthr", 0); #ifdef VND_COMPRESSION /* free the compressed file buffers */ if (vnd->sc_flags & VNF_COMP) { if (vnd->sc_comp_offsets) { free(vnd->sc_comp_offsets, M_DEVBUF); vnd->sc_comp_offsets = NULL; } if (vnd->sc_comp_buff) { free(vnd->sc_comp_buff, M_DEVBUF); vnd->sc_comp_buff = NULL; } if (vnd->sc_comp_decombuf) { free(vnd->sc_comp_decombuf, M_DEVBUF); vnd->sc_comp_decombuf = NULL; } } #endif /* VND_COMPRESSION */ vnd->sc_flags &= ~(VNF_INITED | VNF_READONLY | VNF_VLABEL | VNF_VUNCONF | VNF_COMP | VNF_CLEARING); if (vp == NULL) panic("vndclear: null vp"); (void) vn_close(vp, fflags, vnd->sc_cred); kauth_cred_free(vnd->sc_cred); vnd->sc_vp = NULL; vnd->sc_cred = NULL; vnd->sc_size = 0; }