int cddetach(struct device *self, int flags) { struct cd_softc *cd = (struct cd_softc *)self; int bmaj, cmaj, mn; cd_kill_buffers(cd); /* Locate the lowest minor number to be detached. */ mn = DISKMINOR(self->dv_unit, 0); for (bmaj = 0; bmaj < nblkdev; bmaj++) if (bdevsw[bmaj].d_open == cdopen) vdevgone(bmaj, mn, mn + MAXPARTITIONS - 1, VBLK); for (cmaj = 0; cmaj < nchrdev; cmaj++) if (cdevsw[cmaj].d_open == cdopen) vdevgone(cmaj, mn, mn + MAXPARTITIONS - 1, VCHR); /* Get rid of the power hook. */ if (cd->sc_cdpwrhook != NULL) powerhook_disestablish(cd->sc_cdpwrhook); /* Detach disk. */ disk_detach(&cd->sc_dk); return (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; }
static void maru_shutdown_sc(struct maru_softc *sc) { int n; int s; DB("maru_shutdown_sc(%p)\n", sc); s = splbio(); if (sc->sc_flags&MUF_INITED) { disk_detach(&sc->sc_dkdev); sc->sc_flags &= ~MUF_INITED; if (sc->sc_kapi) sc->sc_kapi->ka_shutdown(sc->sc_kapi); if (maru_tokens) { for (n=0; n<NUM_TOKENS; n++) { struct maru_token *tok = &maru_tokens[n]; if (tok->qt_sc == sc) { if (tok->qt_bp) maru_berror(tok->qt_bp, ENXIO); maru_release_token(tok); } } if (maru_tokens_active == 0) { free(maru_tokens, M_DEVBUF); maru_tokens = NULL; } } } splx(s); }
static int xbd_detach(struct device *dv, int flags) { struct xbd_softc *xs = (struct xbd_softc *)dv; /* * Mark disk about to be removed (between now and when the xs * will be freed). */ xs->sc_shutdown = 1; /* And give it some time to settle if it's busy. */ if (xs->sc_dksc.sc_dkdev.dk_busy > 0) tsleep(&xs, PWAIT, "xbdetach", hz); /* Detach the disk. */ disk_detach(&xs->sc_dksc.sc_dkdev); /* XXX decrement bufq_users and free? */ /* XXX no need to remove sysctl nodes since they only exist * in domain0 and domain0's devices are never removed. */ return 0; }
/* * dm_detach: * * Autoconfiguration detach function for pseudo-device glue. * This routine is called by dm_ioctl::dm_dev_remove_ioctl and by autoconf to * remove devices created in device-mapper. */ static int dm_detach(device_t self, int flags) { dm_dev_t *dmv; /* Detach device from global device list */ if ((dmv = dm_dev_detach(self)) == NULL) return ENOENT; /* Destroy active table first. */ dm_table_destroy(&dmv->table_head, DM_TABLE_ACTIVE); /* Destroy inactive table if exits, too. */ dm_table_destroy(&dmv->table_head, DM_TABLE_INACTIVE); dm_table_head_destroy(&dmv->table_head); /* Destroy disk device structure */ disk_detach(dmv->diskp); disk_destroy(dmv->diskp); /* Destroy device */ (void)dm_dev_free(dmv); /* Decrement device counter After removing device */ atomic_dec_32(&dm_dev_counter); return 0; }
int rd_detach(struct device *self, int flags) { struct rd_softc *sc = (struct rd_softc *)self; disk_gone(rdopen, self->dv_unit); /* Detach disk. */ disk_detach(&sc->sc_dk); return (0); }
void ldenddetach(struct ld_softc *sc) { struct buf *bp; int s, bmaj, cmaj, mn; if ((sc->sc_flags & LDF_ENABLED) == 0) return; /* Wait for commands queued with the hardware to complete. */ if (sc->sc_queuecnt != 0) if (tsleep(&sc->sc_queuecnt, PRIBIO, "lddtch", 30 * hz)) printf("%s: not drained\n", sc->sc_dv.dv_xname); /* Locate the major numbers. */ for (bmaj = 0; bmaj <= nblkdev; bmaj++) if (bdevsw[bmaj].d_open == ldopen) break; for (cmaj = 0; cmaj <= nchrdev; cmaj++) if (cdevsw[cmaj].d_open == ldopen) break; /* Kill off any queued buffers. */ s = splbio(); while ((bp = BUFQ_FIRST(&sc->sc_bufq)) != NULL) { BUFQ_REMOVE(&sc->sc_bufq, bp); bp->b_error = EIO; bp->b_flags |= B_ERROR; bp->b_resid = bp->b_bcount; biodone(bp); } splx(s); /* Nuke the vnodes for any open instances. */ mn = DISKUNIT(sc->sc_dv.dv_unit); vdevgone(bmaj, mn, mn + (MAXPARTITIONS - 1), VBLK); vdevgone(cmaj, mn, mn + (MAXPARTITIONS - 1), VCHR); /* Detach from the disk list. */ disk_detach(&sc->sc_dk); #if NRND > 0 /* Unhook the entropy source. */ rnd_detach_source(&sc->sc_rnd_source); #endif /* Flush the device's cache. */ if (sc->sc_flush != NULL) if ((*sc->sc_flush)(sc) != 0) printf("%s: unable to flush cache\n", sc->sc_dv.dv_xname); }
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); }
static int vnddoclear(struct vnd_softc *vnd, int pmask, int minor, bool force) { int error; if ((error = vndlock(vnd)) != 0) return error; /* * Don't unconfigure if any other partitions are open * or if both the character and block flavors of this * partition are open. */ if (DK_BUSY(vnd, pmask) && !force) { vndunlock(vnd); return EBUSY; } /* Delete all of our wedges */ dkwedge_delall(&vnd->sc_dkdev); /* * XXX vndclear() might call vndclose() implicitly; * release lock to avoid recursion * * Set VNF_CLEARING to prevent vndopen() from * sneaking in after we vndunlock(). */ vnd->sc_flags |= VNF_CLEARING; vndunlock(vnd); vndclear(vnd, minor); #ifdef DEBUG if (vnddebug & VDB_INIT) printf("vndioctl: CLRed\n"); #endif /* Destroy the xfer and buffer pools. */ pool_destroy(&vnd->sc_vxpool); /* Detach the disk. */ disk_detach(&vnd->sc_dkdev); 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; }
/* * Free the variable sized parts of the softc. */ static void fss_softc_free(struct fss_softc *sc) { int i; if ((sc->sc_flags & FSS_BS_THREAD) != 0) { mutex_enter(&sc->sc_slock); sc->sc_flags &= ~FSS_BS_THREAD; cv_signal(&sc->sc_work_cv); mutex_exit(&sc->sc_slock); kthread_join(sc->sc_bs_lwp); disk_detach(sc->sc_dkdev); } if (sc->sc_copied != NULL) kmem_free(sc->sc_copied, howmany(sc->sc_clcount, NBBY)); sc->sc_copied = NULL; if (sc->sc_cache != NULL) { for (i = 0; i < sc->sc_cache_size; i++) if (sc->sc_cache[i].fc_data != NULL) { cv_destroy(&sc->sc_cache[i].fc_state_cv); kmem_free(sc->sc_cache[i].fc_data, FSS_CLSIZE(sc)); } kmem_free(sc->sc_cache, sc->sc_cache_size*sizeof(struct fss_cache)); } sc->sc_cache = NULL; if (sc->sc_indir_valid != NULL) kmem_free(sc->sc_indir_valid, howmany(sc->sc_indir_size, NBBY)); sc->sc_indir_valid = NULL; if (sc->sc_indir_data != NULL) kmem_free(sc->sc_indir_data, FSS_CLSIZE(sc)); sc->sc_indir_data = NULL; }
int ccdioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { int unit = ccdunit(dev); int i, j, lookedup = 0, error = 0; int part, pmask, s; struct ccd_softc *cs; struct ccd_ioctl *ccio = (struct ccd_ioctl *)data; struct ccddevice ccd; char **cpp; struct vnode **vpp; vaddr_t min, max; if (unit >= numccd) return (ENXIO); cs = &ccd_softc[unit]; if (cmd != CCDIOCSET && !(cs->sc_flags & CCDF_INITED)) return (ENXIO); /* access control */ switch (cmd) { case CCDIOCSET: case CCDIOCCLR: case DIOCWDINFO: case DIOCSDINFO: case DIOCWLABEL: if ((flag & FWRITE) == 0) return (EBADF); } bzero(&ccd, sizeof(ccd)); switch (cmd) { case CCDIOCSET: if (cs->sc_flags & CCDF_INITED) return (EBUSY); if (ccio->ccio_ndisks == 0 || ccio->ccio_ndisks > INT_MAX || ccio->ccio_ileave < 0) return (EINVAL); if ((error = ccdlock(cs)) != 0) return (error); /* Fill in some important bits. */ ccd.ccd_unit = unit; ccd.ccd_interleave = ccio->ccio_ileave; ccd.ccd_flags = ccio->ccio_flags & CCDF_USERMASK; /* XXX the new code is unstable still */ ccd.ccd_flags |= CCDF_OLD; /* * Interleaving which is not a multiple of the click size * must use the old I/O code (by design) */ if (ccio->ccio_ileave % (PAGE_SIZE / DEV_BSIZE) != 0) ccd.ccd_flags |= CCDF_OLD; /* * Allocate space for and copy in the array of * componet pathnames and device numbers. */ cpp = malloc(ccio->ccio_ndisks * sizeof(char *), M_DEVBUF, M_WAITOK); vpp = malloc(ccio->ccio_ndisks * sizeof(struct vnode *), M_DEVBUF, M_WAITOK); error = copyin((caddr_t)ccio->ccio_disks, (caddr_t)cpp, ccio->ccio_ndisks * sizeof(char **)); if (error) { free(vpp, M_DEVBUF); free(cpp, M_DEVBUF); ccdunlock(cs); return (error); } for (i = 0; i < ccio->ccio_ndisks; ++i) { CCD_DPRINTF(CCDB_INIT, ("ccdioctl: component %d: %p, lookedup = %d\n", i, cpp[i], lookedup)); if ((error = ccdlookup(cpp[i], p, &vpp[i])) != 0) { for (j = 0; j < lookedup; ++j) (void)vn_close(vpp[j], FREAD|FWRITE, p->p_ucred, p); free(vpp, M_DEVBUF); free(cpp, M_DEVBUF); ccdunlock(cs); return (error); } ++lookedup; } ccd.ccd_cpp = cpp; ccd.ccd_vpp = vpp; ccd.ccd_ndev = ccio->ccio_ndisks; /* * Initialize the ccd. Fills in the softc for us. */ if ((error = ccdinit(&ccd, cpp, p)) != 0) { for (j = 0; j < lookedup; ++j) (void)vn_close(vpp[j], FREAD|FWRITE, p->p_ucred, p); bzero(&ccd_softc[unit], sizeof(struct ccd_softc)); free(vpp, M_DEVBUF); free(cpp, M_DEVBUF); ccdunlock(cs); return (error); } /* * The ccd has been successfully initialized, so * we can place it into the array. Don't try to * read the disklabel until the disk has been attached, * because space for the disklabel is allocated * in disk_attach(); */ bcopy(&ccd, &ccddevs[unit], sizeof(ccd)); ccio->ccio_unit = unit; ccio->ccio_size = cs->sc_size; /* * If we use the optimized protocol we need some kvm space * for the component buffers. Allocate it here. * * XXX I'd like to have a more dynamic way of acquiring kvm * XXX space, but that is problematic as we are not allowed * XXX to lock the kernel_map in interrupt context. It is * XXX doable via a freelist implementation though. */ if (!ccdmap && !(ccd.ccd_flags & CCDF_OLD)) { min = vm_map_min(kernel_map); ccdmap = uvm_km_suballoc(kernel_map, &min, &max, CCD_CLUSTERS * MAXBSIZE, VM_MAP_INTRSAFE, FALSE, NULL); } /* Attach the disk. */ cs->sc_dkdev.dk_name = cs->sc_xname; disk_attach(&cs->sc_dkdev); /* Try and read the disklabel. */ ccdgetdisklabel(dev, cs, cs->sc_dkdev.dk_label, cs->sc_dkdev.dk_cpulabel, 0); ccdunlock(cs); break; case CCDIOCCLR: if ((error = ccdlock(cs)) != 0) return (error); /* * Don't unconfigure if any other partitions are open * or if both the character and block flavors of this * partition are open. */ part = DISKPART(dev); pmask = (1 << part); if ((cs->sc_dkdev.dk_openmask & ~pmask) || ((cs->sc_dkdev.dk_bopenmask & pmask) && (cs->sc_dkdev.dk_copenmask & pmask))) { ccdunlock(cs); return (EBUSY); } /* * Free ccd_softc information and clear entry. */ /* Close the components and free their pathnames. */ for (i = 0; i < cs->sc_nccdisks; ++i) { /* * XXX: this close could potentially fail and * cause Bad Things. Maybe we need to force * the close to happen? */ #ifdef DIAGNOSTIC CCD_DCALL(CCDB_VNODE, vprint("CCDIOCCLR: vnode info", cs->sc_cinfo[i].ci_vp)); #endif (void)vn_close(cs->sc_cinfo[i].ci_vp, FREAD|FWRITE, p->p_ucred, p); free(cs->sc_cinfo[i].ci_path, M_DEVBUF); } /* Free interleave index. */ for (i = 0; cs->sc_itable[i].ii_ndisk; ++i) free(cs->sc_itable[i].ii_index, M_DEVBUF); /* Free component info and interleave table. */ free(cs->sc_cinfo, M_DEVBUF); free(cs->sc_itable, M_DEVBUF); cs->sc_flags &= ~CCDF_INITED; /* * Free ccddevice information and clear entry. */ free(ccddevs[unit].ccd_cpp, M_DEVBUF); free(ccddevs[unit].ccd_vpp, M_DEVBUF); bcopy(&ccd, &ccddevs[unit], sizeof(ccd)); /* Detatch the disk. */ disk_detach(&cs->sc_dkdev); /* This must be atomic. */ s = splhigh(); ccdunlock(cs); bzero(cs, sizeof(struct ccd_softc)); splx(s); break; case DIOCGPDINFO: { struct cpu_disklabel osdep; if ((error = ccdlock(cs)) != 0) return (error); ccdgetdisklabel(dev, cs, (struct disklabel *)data, &osdep, 1); ccdunlock(cs); break; } case DIOCGDINFO: *(struct disklabel *)data = *(cs->sc_dkdev.dk_label); break; case DIOCGPART: ((struct partinfo *)data)->disklab = cs->sc_dkdev.dk_label; ((struct partinfo *)data)->part = &cs->sc_dkdev.dk_label->d_partitions[DISKPART(dev)]; break; case DIOCWDINFO: case DIOCSDINFO: if ((error = ccdlock(cs)) != 0) return (error); cs->sc_flags |= CCDF_LABELLING; error = setdisklabel(cs->sc_dkdev.dk_label, (struct disklabel *)data, 0, cs->sc_dkdev.dk_cpulabel); if (error == 0) { if (cmd == DIOCWDINFO) error = writedisklabel(CCDLABELDEV(dev), ccdstrategy, cs->sc_dkdev.dk_label, cs->sc_dkdev.dk_cpulabel); } cs->sc_flags &= ~CCDF_LABELLING; ccdunlock(cs); if (error) return (error); break; case DIOCWLABEL: if (*(int *)data != 0) cs->sc_flags |= CCDF_WLABEL; else cs->sc_flags &= ~CCDF_WLABEL; break; default: return (ENOTTY); } return (0); }
/* ARGSUSED */ int vndioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) { int unit = DISKUNIT(dev); struct disklabel *lp; struct vnd_softc *sc; struct vnd_ioctl *vio; struct vnd_user *vnu; struct vattr vattr; struct nameidata nd; int error, part, pmask; DNPRINTF(VDB_FOLLOW, "vndioctl(%x, %lx, %p, %x, %p): unit %d\n", dev, cmd, addr, flag, p, unit); error = suser(p, 0); if (error) return (error); if (unit >= numvnd) return (ENXIO); sc = &vnd_softc[unit]; vio = (struct vnd_ioctl *)addr; switch (cmd) { case VNDIOCSET: if (sc->sc_flags & VNF_INITED) return (EBUSY); /* Geometry eventually has to fit into label fields */ if (vio->vnd_secsize > UINT_MAX || vio->vnd_ntracks > UINT_MAX || vio->vnd_nsectors > UINT_MAX) return (EINVAL); if ((error = disk_lock(&sc->sc_dk)) != 0) return (error); if ((error = copyinstr(vio->vnd_file, sc->sc_file, sizeof(sc->sc_file), NULL))) { disk_unlock(&sc->sc_dk); return (error); } /* Set geometry for device. */ sc->sc_secsize = vio->vnd_secsize; sc->sc_ntracks = vio->vnd_ntracks; sc->sc_nsectors = vio->vnd_nsectors; /* * Open for read and write first. This lets vn_open() weed out * directories, sockets, etc. so we don't have to worry about * them. */ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, vio->vnd_file, p); sc->sc_flags &= ~VNF_READONLY; error = vn_open(&nd, FREAD|FWRITE, 0); if (error == EROFS) { sc->sc_flags |= VNF_READONLY; error = vn_open(&nd, FREAD, 0); } if (error) { disk_unlock(&sc->sc_dk); return (error); } if (nd.ni_vp->v_type == VBLK) sc->sc_size = vndbdevsize(nd.ni_vp, p); else { error = VOP_GETATTR(nd.ni_vp, &vattr, p->p_ucred, p); if (error) { VOP_UNLOCK(nd.ni_vp, 0, p); vn_close(nd.ni_vp, VNDRW(sc), p->p_ucred, p); disk_unlock(&sc->sc_dk); return (error); } sc->sc_size = vattr.va_size / sc->sc_secsize; } VOP_UNLOCK(nd.ni_vp, 0, p); sc->sc_vp = nd.ni_vp; if ((error = vndsetcred(sc, p->p_ucred)) != 0) { (void) vn_close(nd.ni_vp, VNDRW(sc), p->p_ucred, p); disk_unlock(&sc->sc_dk); return (error); } if (vio->vnd_keylen > 0) { char key[BLF_MAXUTILIZED]; if (vio->vnd_keylen > sizeof(key)) vio->vnd_keylen = sizeof(key); if ((error = copyin(vio->vnd_key, key, vio->vnd_keylen)) != 0) { (void) vn_close(nd.ni_vp, VNDRW(sc), p->p_ucred, p); disk_unlock(&sc->sc_dk); return (error); } sc->sc_keyctx = malloc(sizeof(*sc->sc_keyctx), M_DEVBUF, M_WAITOK); blf_key(sc->sc_keyctx, key, vio->vnd_keylen); explicit_bzero(key, vio->vnd_keylen); } else sc->sc_keyctx = NULL; vio->vnd_size = sc->sc_size * sc->sc_secsize; sc->sc_flags |= VNF_INITED; DNPRINTF(VDB_INIT, "vndioctl: SET vp %p size %llx\n", sc->sc_vp, (unsigned long long)sc->sc_size); /* Attach the disk. */ sc->sc_dk.dk_name = sc->sc_dev.dv_xname; disk_attach(&sc->sc_dev, &sc->sc_dk); disk_unlock(&sc->sc_dk); break; case VNDIOCCLR: if ((sc->sc_flags & VNF_INITED) == 0) return (ENXIO); if ((error = disk_lock(&sc->sc_dk)) != 0) return (error); /* * Don't unconfigure if any other partitions are open * or if both the character and block flavors of this * partition are open. */ part = DISKPART(dev); pmask = (1 << part); if ((sc->sc_dk.dk_openmask & ~pmask) || ((sc->sc_dk.dk_bopenmask & pmask) && (sc->sc_dk.dk_copenmask & pmask))) { disk_unlock(&sc->sc_dk); return (EBUSY); } vndclear(sc); DNPRINTF(VDB_INIT, "vndioctl: CLRed\n"); /* Free crypto key */ if (sc->sc_keyctx) { explicit_bzero(sc->sc_keyctx, sizeof(*sc->sc_keyctx)); free(sc->sc_keyctx, M_DEVBUF, sizeof(*sc->sc_keyctx)); } /* Detach the disk. */ disk_detach(&sc->sc_dk); disk_unlock(&sc->sc_dk); break; case VNDIOCGET: vnu = (struct vnd_user *)addr; if (vnu->vnu_unit == -1) vnu->vnu_unit = unit; if (vnu->vnu_unit >= numvnd) return (ENXIO); if (vnu->vnu_unit < 0) return (EINVAL); sc = &vnd_softc[vnu->vnu_unit]; if (sc->sc_flags & VNF_INITED) { error = VOP_GETATTR(sc->sc_vp, &vattr, p->p_ucred, p); if (error) return (error); strlcpy(vnu->vnu_file, sc->sc_file, sizeof(vnu->vnu_file)); vnu->vnu_dev = vattr.va_fsid; vnu->vnu_ino = vattr.va_fileid; } else { vnu->vnu_dev = 0; vnu->vnu_ino = 0; } break; case DIOCRLDINFO: if ((sc->sc_flags & VNF_HAVELABEL) == 0) return (ENOTTY); lp = malloc(sizeof(*lp), M_TEMP, M_WAITOK); vndgetdisklabel(dev, sc, lp, 0); *(sc->sc_dk.dk_label) = *lp; free(lp, M_TEMP, sizeof(*lp)); return (0); case DIOCGPDINFO: if ((sc->sc_flags & VNF_HAVELABEL) == 0) return (ENOTTY); vndgetdisklabel(dev, sc, (struct disklabel *)addr, 1); return (0); case DIOCGDINFO: if ((sc->sc_flags & VNF_HAVELABEL) == 0) return (ENOTTY); *(struct disklabel *)addr = *(sc->sc_dk.dk_label); return (0); case DIOCGPART: if ((sc->sc_flags & VNF_HAVELABEL) == 0) return (ENOTTY); ((struct partinfo *)addr)->disklab = sc->sc_dk.dk_label; ((struct partinfo *)addr)->part = &sc->sc_dk.dk_label->d_partitions[DISKPART(dev)]; return (0); case DIOCWDINFO: case DIOCSDINFO: if ((sc->sc_flags & VNF_HAVELABEL) == 0) return (ENOTTY); if ((flag & FWRITE) == 0) return (EBADF); if ((error = disk_lock(&sc->sc_dk)) != 0) return (error); error = setdisklabel(sc->sc_dk.dk_label, (struct disklabel *)addr, /* sc->sc_dk.dk_openmask */ 0); if (error == 0) { if (cmd == DIOCWDINFO) error = writedisklabel(DISKLABELDEV(dev), vndstrategy, sc->sc_dk.dk_label); } disk_unlock(&sc->sc_dk); return (error); default: return (ENOTTY); } return (0); }