diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 2011-10-06 20:49:30 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 2011-10-06 20:49:30 +0000 |
commit | 0647d56dd089f299d35587686681e19ad074627d (patch) | |
tree | 0bd77a196ba8c5bf639b51b50f88745e18caeec0 /sys/dev | |
parent | a4b88cea1f45014461763fd53d46221663687d94 (diff) |
ccd goes to the attic
discussed with jsing and millert
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/ccd.c | 1345 | ||||
-rw-r--r-- | sys/dev/ccdvar.h | 184 |
2 files changed, 0 insertions, 1529 deletions
diff --git a/sys/dev/ccd.c b/sys/dev/ccd.c deleted file mode 100644 index 9f6a0bb04a7..00000000000 --- a/sys/dev/ccd.c +++ /dev/null @@ -1,1345 +0,0 @@ -/* $OpenBSD: ccd.c,v 1.97 2011/07/06 04:49:36 matthew Exp $ */ -/* $NetBSD: ccd.c,v 1.33 1996/05/05 04:21:14 thorpej Exp $ */ - -/*- - * Copyright (c) 1996 The NetBSD Foundation, Inc. - * Copyright (c) 1997 Niklas Hallqvist. - * Copyright (c) 2005 Michael Shalayeff. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Jason R. Thorpe. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Copyright (c) 1988 University of Utah. - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * the Systems Programming Group of the University of Utah Computer - * Science Department. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: Utah $Hdr: cd.c 1.6 90/11/28$ - * - * @(#)cd.c 8.2 (Berkeley) 11/16/93 - */ - -/* - * "Concatenated" disk driver. - * - * Dynamic configuration and disklabel support by: - * Jason R. Thorpe <thorpej@nas.nasa.gov> - * Numerical Aerodynamic Simulation Facility - * Mail Stop 258-6 - * NASA Ames Research Center - * Moffett Field, CA 94035 - * - * Mirroring support based on code written by Satoshi Asami - * and Nisha Talagala. - */ -/* #define CCDDEBUG */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/proc.h> -#include <sys/errno.h> -#include <sys/buf.h> -#include <sys/malloc.h> -#include <sys/pool.h> -#include <sys/namei.h> -#include <sys/stat.h> -#include <sys/ioctl.h> -#include <sys/disklabel.h> -#include <sys/device.h> -#include <sys/disk.h> -#include <sys/syslog.h> -#include <sys/fcntl.h> -#include <sys/vnode.h> -#include <sys/conf.h> -#include <sys/rwlock.h> -#include <sys/dkio.h> - -#include <dev/ccdvar.h> - -#ifdef __GNUC__ -#define INLINE static __inline -#else -#define INLINE -#endif - -/* - * A concatenated disk is described after initialization by this structure. - */ -struct ccd_softc { - struct disk sc_dkdev; /* generic disk device info */ - struct ccdgeom sc_geom; /* pseudo geometry info */ - struct ccdcinfo *sc_cinfo; /* component info */ - struct ccdiinfo *sc_itable; /* interleave table */ - char sc_xname[8]; /* XXX external name */ - size_t sc_size; /* size of ccd */ - int sc_flags; /* flags */ - int sc_cflags; /* copy of ccd_flags */ - int sc_ileave; /* interleave */ - u_int sc_nccdisks; /* # of components */ - u_int sc_nccunits; /* # of components for data */ - struct rwlock sc_rwlock; /* lock */ - -}; - -/* sc_flags */ -#define CCDF_INITED 0x01 /* unit has been initialized */ - -#ifdef CCDDEBUG -#define CCD_DCALL(m,c) if (ccddebug & (m)) c -#define CCD_DPRINTF(m,a) CCD_DCALL(m, printf a) -#define CCDB_FOLLOW 0x01 -#define CCDB_INIT 0x02 -#define CCDB_IO 0x04 -#define CCDB_LABEL 0x08 -#define CCDB_VNODE 0x10 -int ccddebug = 0x00; -#else -#define CCD_DCALL(m,c) /* m, c */ -#define CCD_DPRINTF(m,a) /* m, a */ -#endif - -struct ccdbuf { - struct buf cb_buf; /* new I/O buf */ - struct buf *cb_obp; /* ptr. to original I/O buf */ - struct ccd_softc*cb_sc; /* point back to the device */ - struct ccdbuf *cb_dep; /* mutual ptrs for mirror part */ - int cb_comp; /* target component */ - int cb_flags; /* misc. flags */ -#define CBF_MIRROR 0x01 /* we're for a mirror component */ -#define CBF_DONE 0x02 /* this buffer is done */ -}; - -/* called by main() at boot time */ -void ccdattach(int); - -/* called by biodone() at interrupt time */ -void ccdiodone(struct buf *); -daddr64_t ccdsize(dev_t); - -void ccdstart(struct ccd_softc *, struct buf *); -void ccdinterleave(struct ccd_softc *); -void ccdintr(struct ccd_softc *, struct buf *); -int ccdinit(struct ccddevice *, char **, struct proc *); -int ccdlookup(char *, struct proc *p, struct vnode **); -long ccdbuffer(struct ccd_softc *, struct buf *, daddr64_t, caddr_t, - long, struct ccdbuf **); -int ccdgetdisklabel(dev_t, struct ccd_softc *, struct disklabel *, int); -INLINE struct ccdbuf *getccdbuf(void); -INLINE void putccdbuf(struct ccdbuf *); - -#define ccdlock(sc) rw_enter(&sc->sc_rwlock, RW_WRITE|RW_INTR) -#define ccdunlock(sc) rw_exit_write(&sc->sc_rwlock) - -#ifdef CCDDEBUG -void printiinfo(struct ccdiinfo *); -#endif - -/* Non-private for the benefit of libkvm. */ -struct ccd_softc *ccd_softc; -struct ccddevice *ccddevs; -int numccd = 0; - -/* - * struct ccdbuf allocator - */ -struct pool ccdbufpl; - -/* - * Manage the ccd buffer structures. - */ -INLINE struct ccdbuf * -getccdbuf(void) -{ - struct ccdbuf *cbp; - - cbp = pool_get(&ccdbufpl, PR_WAITOK | PR_ZERO); - - return (cbp); -} - -INLINE void -putccdbuf(struct ccdbuf *cbp) -{ - pool_put(&ccdbufpl, cbp); -} - -/* - * Called by main() during pseudo-device attachment. All we need - * to do is allocate enough space for devices to be configured later. - */ -void -ccdattach(int num) -{ - int i; - - if (num <= 0) { -#ifdef DIAGNOSTIC - panic("ccdattach: count <= 0"); -#endif - return; - } - - ccd_softc = (struct ccd_softc *)malloc(num * sizeof(struct ccd_softc), - M_DEVBUF, M_NOWAIT | M_ZERO); - ccddevs = (struct ccddevice *)malloc(num * sizeof(struct ccddevice), - M_DEVBUF, M_NOWAIT | M_ZERO); - if ((ccd_softc == NULL) || (ccddevs == NULL)) { - printf("WARNING: no memory for concatenated disks\n"); - if (ccd_softc != NULL) - free(ccd_softc, M_DEVBUF); - if (ccddevs != NULL) - free(ccddevs, M_DEVBUF); - return; - } - for (i = 0; i < num; i++) { - rw_init(&ccd_softc[i].sc_rwlock, "ccdlock"); - } - numccd = num; - - pool_init(&ccdbufpl, sizeof(struct ccdbuf), 0, 0, 0, "ccdbufpl", NULL); - pool_setlowat(&ccdbufpl, 16); - pool_sethiwat(&ccdbufpl, 1024); -} - -int -ccdinit(struct ccddevice *ccd, char **cpaths, struct proc *p) -{ - struct ccd_softc *cs = &ccd_softc[ccd->ccd_unit]; - struct ccdcinfo *ci = NULL; - daddr64_t size; - int ix; - struct vnode *vp; - struct vattr va; - size_t minsize; - int maxsecsize; - struct partinfo dpart; - struct ccdgeom *ccg = &cs->sc_geom; - char tmppath[MAXPATHLEN]; - int error; - - CCD_DPRINTF(CCDB_FOLLOW | CCDB_INIT, ("ccdinit: unit %d cflags %b\n", - ccd->ccd_unit, ccd->ccd_flags, CCDF_BITS)); - - cs->sc_size = 0; - cs->sc_ileave = ccd->ccd_interleave; - cs->sc_nccdisks = ccd->ccd_ndev; - if (snprintf(cs->sc_xname, sizeof(cs->sc_xname), "ccd%d", - ccd->ccd_unit) >= sizeof(cs->sc_xname)) { - printf("ccdinit: device name too long.\n"); - return(ENXIO); - } - - /* Allocate space for the component info. */ - cs->sc_cinfo = malloc(cs->sc_nccdisks * sizeof(struct ccdcinfo), - M_DEVBUF, M_WAITOK | M_ZERO); - - /* - * Verify that each component piece exists and record - * relevant information about it. - */ - maxsecsize = 0; - minsize = 0; - for (ix = 0; ix < cs->sc_nccdisks; ix++) { - vp = ccd->ccd_vpp[ix]; - ci = &cs->sc_cinfo[ix]; - ci->ci_vp = vp; - - /* - * Copy in the pathname of the component. - */ - bzero(tmppath, sizeof(tmppath)); /* sanity */ - error = copyinstr(cpaths[ix], tmppath, - MAXPATHLEN, &ci->ci_pathlen); - if (error) { - CCD_DPRINTF(CCDB_FOLLOW | CCDB_INIT, - ("%s: can't copy path, error = %d\n", - cs->sc_xname, error)); - free(cs->sc_cinfo, M_DEVBUF); - return (error); - } - ci->ci_path = malloc(ci->ci_pathlen, M_DEVBUF, M_WAITOK); - bcopy(tmppath, ci->ci_path, ci->ci_pathlen); - - /* - * XXX: Cache the component's dev_t. - */ - if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) != 0) { - CCD_DPRINTF(CCDB_FOLLOW | CCDB_INIT, - ("%s: %s: getattr failed error = %d\n", - cs->sc_xname, ci->ci_path, error)); - free(ci->ci_path, M_DEVBUF); - free(cs->sc_cinfo, M_DEVBUF); - return (error); - } - ci->ci_dev = va.va_rdev; - - /* - * Get partition information for the component. - */ - error = VOP_IOCTL(vp, DIOCGPART, (caddr_t)&dpart, - FREAD, p->p_ucred, p); - if (error) { - CCD_DPRINTF(CCDB_FOLLOW | CCDB_INIT, - ("%s: %s: ioctl failed, error = %d\n", - cs->sc_xname, ci->ci_path, error)); - free(ci->ci_path, M_DEVBUF); - free(cs->sc_cinfo, M_DEVBUF); - return (error); - } - if (dpart.part->p_fstype == FS_CCD || - dpart.part->p_fstype == FS_BSDFFS) { - maxsecsize = - ((dpart.disklab->d_secsize > maxsecsize) ? - dpart.disklab->d_secsize : maxsecsize); - size = DL_GETPSIZE(dpart.part); - } else { - CCD_DPRINTF(CCDB_FOLLOW | CCDB_INIT, - ("%s: %s: incorrect partition type\n", - cs->sc_xname, ci->ci_path)); - free(ci->ci_path, M_DEVBUF); - free(cs->sc_cinfo, M_DEVBUF); - return (EFTYPE); - } - - /* - * Calculate the size, truncating to an interleave - * boundary if necessary. - */ - if (cs->sc_ileave > 1) - size -= size % cs->sc_ileave; - - if (size == 0) { - CCD_DPRINTF(CCDB_FOLLOW | CCDB_INIT, - ("%s: %s: size == 0\n", cs->sc_xname, ci->ci_path)); - free(ci->ci_path, M_DEVBUF); - free(cs->sc_cinfo, M_DEVBUF); - return (ENODEV); - } - - if (minsize == 0 || size < minsize) - minsize = size; - ci->ci_size = size; - cs->sc_size += size; - } - ccg->ccg_rpm = 0; - - /* - * Don't allow the interleave to be smaller than - * the biggest component sector. - */ - if ((cs->sc_ileave > 0) && - (cs->sc_ileave < (maxsecsize / DEV_BSIZE))) { - CCD_DPRINTF(CCDB_FOLLOW | CCDB_INIT, - ("%s: interleave must be at least %d\n", - cs->sc_xname, (maxsecsize / DEV_BSIZE))); - free(ci->ci_path, M_DEVBUF); - free(cs->sc_cinfo, M_DEVBUF); - return (EINVAL); - } - - /* - * Mirroring support requires uniform interleave and - * and even number of components. - */ - if (ccd->ccd_flags & CCDF_MIRROR) { - ccd->ccd_flags |= CCDF_UNIFORM; - if (cs->sc_ileave == 0) { - CCD_DPRINTF(CCDB_FOLLOW | CCDB_INIT, - ("%s: mirroring requires interleave\n", - cs->sc_xname)); - free(ci->ci_path, M_DEVBUF); - free(cs->sc_cinfo, M_DEVBUF); - return (EINVAL); - } - if (cs->sc_nccdisks % 2) { - CCD_DPRINTF(CCDB_FOLLOW | CCDB_INIT, - ("%s: mirroring requires even # of components\n", - cs->sc_xname)); - free(ci->ci_path, M_DEVBUF); - free(cs->sc_cinfo, M_DEVBUF); - return (EINVAL); - } - } - - /* - * If uniform interleave is desired set all sizes to that of - * the smallest component. - */ - ccg->ccg_ntracks = cs->sc_nccunits = cs->sc_nccdisks; - if (ccd->ccd_flags & CCDF_UNIFORM) { - for (ci = cs->sc_cinfo; - ci < &cs->sc_cinfo[cs->sc_nccdisks]; ci++) - ci->ci_size = minsize; - - if (ccd->ccd_flags & CCDF_MIRROR) - cs->sc_nccunits = ccg->ccg_ntracks /= 2; - cs->sc_size = ccg->ccg_ntracks * minsize; - } - - cs->sc_cflags = ccd->ccd_flags; /* So we can find out later... */ - - /* - * Construct the interleave table. - */ - ccdinterleave(cs); - - /* - * Create pseudo-geometry based on 1MB cylinders. It's - * pretty close. - */ - ccg->ccg_secsize = DEV_BSIZE; - ccg->ccg_nsectors = cs->sc_ileave? cs->sc_ileave : - 1024 * (1024 / ccg->ccg_secsize); - ccg->ccg_ncylinders = cs->sc_size / ccg->ccg_ntracks / - ccg->ccg_nsectors; - - cs->sc_flags |= CCDF_INITED; - - return (0); -} - -void -ccdinterleave(struct ccd_softc *cs) -{ - struct ccdcinfo *ci, *smallci; - struct ccdiinfo *ii; - daddr64_t bn, lbn; - int ix; - u_long size; - - CCD_DPRINTF(CCDB_INIT, - ("ccdinterleave(%p): ileave %d\n", cs, cs->sc_ileave)); - - /* - * Allocate an interleave table. - * Chances are this is too big, but we don't care. - */ - size = (cs->sc_nccdisks + 1) * sizeof(struct ccdiinfo); - cs->sc_itable = (struct ccdiinfo *)malloc(size, M_DEVBUF, - M_WAITOK | M_ZERO); - - /* - * Trivial case: no interleave (actually interleave of disk size). - * Each table entry represents a single component in its entirety. - */ - if (cs->sc_ileave == 0) { - bn = 0; - ii = cs->sc_itable; - - for (ix = 0; ix < cs->sc_nccdisks; ix++) { - /* Allocate space for ii_index. */ - ii->ii_index = malloc(sizeof(int), M_DEVBUF, M_WAITOK); - ii->ii_ndisk = 1; - ii->ii_startblk = bn; - ii->ii_startoff = 0; - ii->ii_index[0] = ix; - bn += cs->sc_cinfo[ix].ci_size; - ii++; - } - ii->ii_ndisk = 0; - - CCD_DCALL(CCDB_INIT, printiinfo(cs->sc_itable)); - return; - } - - /* - * The following isn't fast or pretty; it doesn't have to be. - */ - size = 0; - bn = lbn = 0; - for (ii = cs->sc_itable; ; ii++) { - /* Allocate space for ii_index. */ - ii->ii_index = malloc((sizeof(int) * cs->sc_nccdisks), - M_DEVBUF, M_WAITOK); - - /* - * Locate the smallest of the remaining components - */ - smallci = NULL; - for (ci = cs->sc_cinfo; - ci < &cs->sc_cinfo[cs->sc_nccdisks]; ci++) - if (ci->ci_size > size && - (smallci == NULL || - ci->ci_size < smallci->ci_size)) - smallci = ci; - - /* - * Nobody left, all done - */ - if (smallci == NULL) { - ii->ii_ndisk = 0; - break; - } - - /* - * Record starting logical block and component offset - */ - ii->ii_startblk = bn / cs->sc_ileave; - ii->ii_startoff = lbn; - - /* - * Determine how many disks take part in this interleave - * and record their indices. - */ - ix = 0; - for (ci = cs->sc_cinfo; - ci < &cs->sc_cinfo[cs->sc_nccunits]; ci++) - if (ci->ci_size >= smallci->ci_size) - ii->ii_index[ix++] = ci - cs->sc_cinfo; - ii->ii_ndisk = ix; - bn += ix * (smallci->ci_size - size); - lbn = smallci->ci_size / cs->sc_ileave; - size = smallci->ci_size; - } - - CCD_DCALL(CCDB_INIT, printiinfo(cs->sc_itable)); -} - -/* ARGSUSED */ -int -ccdopen(dev_t dev, int flags, int fmt, struct proc *p) -{ - int unit = DISKUNIT(dev); - struct ccd_softc *cs; - struct disklabel *lp; - int error = 0, part; - - CCD_DPRINTF(CCDB_FOLLOW, ("ccdopen(%x, %x)\n", dev, flags)); - - if (unit >= numccd) - return (ENXIO); - cs = &ccd_softc[unit]; - - if ((error = ccdlock(cs)) != 0) - return (error); - - lp = cs->sc_dkdev.dk_label; - - part = DISKPART(dev); - - /* - * If we're initialized, check to see if there are any other - * open partitions. If not, then it's safe to update - * the in-core disklabel. - */ - if ((cs->sc_flags & CCDF_INITED) && (cs->sc_dkdev.dk_openmask == 0)) - ccdgetdisklabel(dev, cs, lp, 0); - - error = disk_openpart(&cs->sc_dkdev, part, fmt, - (cs->sc_flags & CCDF_INITED) != 0); - - ccdunlock(cs); - return (error); -} - -/* ARGSUSED */ -int -ccdclose(dev_t dev, int flags, int fmt, struct proc *p) -{ - int unit = DISKUNIT(dev); - struct ccd_softc *cs; - int error = 0, part; - - CCD_DPRINTF(CCDB_FOLLOW, ("ccdclose(%x, %x)\n", dev, flags)); - - if (unit >= numccd) - return (ENXIO); - cs = &ccd_softc[unit]; - - if ((error = ccdlock(cs)) != 0) - return (error); - - part = DISKPART(dev); - - disk_closepart(&cs->sc_dkdev, part, fmt); - - ccdunlock(cs); - return (0); -} - -void -ccdstrategy(struct buf *bp) -{ - int unit = DISKUNIT(bp->b_dev); - struct ccd_softc *cs = &ccd_softc[unit]; - int s; - - CCD_DPRINTF(CCDB_FOLLOW, ("ccdstrategy(%p): unit %d\n", bp, unit)); - - if ((cs->sc_flags & CCDF_INITED) == 0) { - bp->b_error = ENXIO; - bp->b_flags |= B_ERROR; - bp->b_resid = bp->b_bcount; - goto done; - } - - /* Validate the request. */ - if (bounds_check_with_label(bp, cs->sc_dkdev.dk_label) == -1) - goto done; - - bp->b_resid = bp->b_bcount; - - /* - * "Start" the unit. - */ - s = splbio(); - ccdstart(cs, bp); - splx(s); - return; - - done: - s = splbio(); - biodone(bp); - splx(s); -} - -void -ccdstart(struct ccd_softc *cs, struct buf *bp) -{ - long bcount, rcount; - struct ccdbuf **cbpp; - caddr_t addr; - daddr64_t bn; - struct partition *pp; - - CCD_DPRINTF(CCDB_FOLLOW, ("ccdstart(%p, %p, %s)\n", cs, bp, - bp->b_flags & B_READ? "read" : "write")); - - /* Instrumentation. */ - disk_busy(&cs->sc_dkdev); - - /* - * Translate the partition-relative block number to an absolute. - */ - bn = bp->b_blkno; - pp = &cs->sc_dkdev.dk_label->d_partitions[DISKPART(bp->b_dev)]; - bn += DL_GETPOFFSET(pp); - - /* - * Allocate component buffers - */ - cbpp = malloc(2 * cs->sc_nccdisks * sizeof(struct ccdbuf *), M_DEVBUF, - M_WAITOK | M_ZERO); - addr = bp->b_data; - for (bcount = bp->b_bcount; bcount > 0; bcount -= rcount) { - rcount = ccdbuffer(cs, bp, bn, addr, bcount, cbpp); - - /* - * This is the old, slower, but less restrictive, mode of - * operation. It allows interleaves which are not multiples - * of PAGE_SIZE and mirroring. - */ - if ((cbpp[0]->cb_buf.b_flags & B_READ) == 0) - cbpp[0]->cb_buf.b_vp->v_numoutput++; - VOP_STRATEGY(&cbpp[0]->cb_buf); - - if ((cs->sc_cflags & CCDF_MIRROR) && - ((cbpp[0]->cb_buf.b_flags & B_READ) == 0)) { - cbpp[1]->cb_buf.b_vp->v_numoutput++; - VOP_STRATEGY(&cbpp[1]->cb_buf); - } - - bn += btodb(rcount); - addr += rcount; - } - - free(cbpp, M_DEVBUF); -} - -/* - * Build a component buffer header. - */ -long -ccdbuffer(struct ccd_softc *cs, struct buf *bp, daddr64_t bn, caddr_t addr, - long bcount, struct ccdbuf **cbpp) -{ - struct ccdcinfo *ci, *ci2 = NULL; - struct ccdbuf *cbp; - daddr64_t cbn, cboff, sblk; - int ccdisk, ccdisk2, off; - long cnt; - struct ccdiinfo *ii; - struct buf *nbp; - - CCD_DPRINTF(CCDB_IO, ("ccdbuffer(%p, %p, %d, %p, %ld, %p)\n", - cs, bp, bn, addr, bcount, cbpp)); - - /* - * Determine which component bn falls in. - */ - cbn = bn; - cboff = 0; - - if (cs->sc_ileave == 0) { - /* - * Serially concatenated - */ - sblk = 0; - for (ccdisk = 0, ci = &cs->sc_cinfo[ccdisk]; - cbn >= sblk + ci->ci_size; - ccdisk++, ci = &cs->sc_cinfo[ccdisk]) - sblk += ci->ci_size; - cbn -= sblk; - } else { - /* - * Interleaved - */ - cboff = cbn % cs->sc_ileave; - cbn /= cs->sc_ileave; - for (ii = cs->sc_itable; ii->ii_ndisk; ii++) - if (ii->ii_startblk > cbn) - break; - ii--; - off = cbn - ii->ii_startblk; - if (ii->ii_ndisk == 1) { - ccdisk = ii->ii_index[0]; - cbn = ii->ii_startoff + off; - } else { - ccdisk = ii->ii_index[off % ii->ii_ndisk]; - cbn = ii->ii_startoff + off / ii->ii_ndisk; - } - ci = &cs->sc_cinfo[ccdisk]; - if (cs->sc_cflags & CCDF_MIRROR) { - /* Mirrored data */ - ccdisk2 = ccdisk + ii->ii_ndisk; - ci2 = &cs->sc_cinfo[ccdisk2]; - /* spread the read over both parts */ - if (bp->b_flags & B_READ && - bcount > bp->b_bcount / 2 && - (!(ci2->ci_flags & CCIF_FAILED) || - ci->ci_flags & CCIF_FAILED)) { - ccdisk = ccdisk2; - ci = ci2; - } - } - cbn *= cs->sc_ileave; - CCD_DPRINTF(CCDB_IO, ("ccdisk %d cbn %lld ci %p ci2 %p\n", - ccdisk, cbn, ci, ci2)); - } - - /* Limit the operation at next component border */ - if (cs->sc_ileave == 0) - cnt = dbtob(ci->ci_size - cbn); - else - cnt = dbtob(cs->sc_ileave - cboff); - if (cnt < bcount) - bcount = cnt; - - /* - * Setup new component buffer. - */ - cbp = cbpp[0] = getccdbuf(); - cbp->cb_flags = 0; - nbp = &cbp->cb_buf; - nbp->b_flags = bp->b_flags | B_CALL; - nbp->b_iodone = ccdiodone; - nbp->b_proc = bp->b_proc; - nbp->b_dev = ci->ci_dev; /* XXX */ - nbp->b_blkno = cbn + cboff; - nbp->b_vp = ci->ci_vp; - nbp->b_bcount = bcount; - LIST_INIT(&nbp->b_dep); - nbp->b_data = addr; - - /* - * context for ccdiodone - */ - cbp->cb_obp = bp; - cbp->cb_sc = cs; - cbp->cb_comp = ccdisk; - - /* - * Mirrors have an additional write operation that is nearly - * identical to the first. - */ - if ((cs->sc_cflags & CCDF_MIRROR) && - !(ci2->ci_flags & CCIF_FAILED) && - ((cbp->cb_buf.b_flags & B_READ) == 0)) { - struct ccdbuf *cbp2; - cbpp[1] = cbp2 = getccdbuf(); - *cbp2 = *cbp; - cbp2->cb_flags = CBF_MIRROR; - cbp2->cb_buf.b_dev = ci2->ci_dev; /* XXX */ - cbp2->cb_buf.b_vp = ci2->ci_vp; - LIST_INIT(&cbp2->cb_buf.b_dep); - cbp2->cb_comp = ccdisk2; - cbp2->cb_dep = cbp; - cbp->cb_dep = cbp2; - } - - CCD_DPRINTF(CCDB_IO, (" dev %x(u%d): cbp %p bn %lld addr %p bcnt %ld\n", - ci->ci_dev, ci-cs->sc_cinfo, cbp, bp->b_blkno, - bp->b_data, bp->b_bcount)); - - return (bcount); -} - -void -ccdintr(struct ccd_softc *cs, struct buf *bp) -{ - - splassert(IPL_BIO); - - CCD_DPRINTF(CCDB_FOLLOW, ("ccdintr(%p, %p)\n", cs, bp)); - - /* - * Request is done for better or worse, wakeup the top half. - */ - if (bp->b_flags & B_ERROR) - bp->b_resid = bp->b_bcount; - disk_unbusy(&cs->sc_dkdev, (bp->b_bcount - bp->b_resid), - (bp->b_flags & B_READ)); - biodone(bp); -} - -/* - * Called at interrupt time. - * Mark the component as done and if all components are done, - * take a ccd interrupt. - */ -void -ccdiodone(struct buf *vbp) -{ - struct ccdbuf *cbp = (struct ccdbuf *)vbp; - struct buf *bp = cbp->cb_obp; - struct ccd_softc *cs = cbp->cb_sc; - long count = bp->b_bcount; - char *comptype; - - splassert(IPL_BIO); - - CCD_DPRINTF(CCDB_FOLLOW, ("ccdiodone(%p)\n", cbp)); - CCD_DPRINTF(CCDB_IO, (cbp->cb_flags & CBF_MIRROR? - "ccdiodone: mirror component\n" : - "ccdiodone: bp %p bcount %ld resid %ld\n", - bp, bp->b_bcount, bp->b_resid)); - CCD_DPRINTF(CCDB_IO, (" dev %x(u%d), cbp %p bn %lld addr %p bcnt %ld\n", - vbp->b_dev, cbp->cb_comp, cbp, vbp->b_blkno, - vbp->b_data, vbp->b_bcount)); - - if (vbp->b_flags & B_ERROR) { - cs->sc_cinfo[cbp->cb_comp].ci_flags |= CCIF_FAILED; - if (cbp->cb_flags & CBF_MIRROR) - comptype = " (mirror)"; - else { - bp->b_flags |= B_ERROR; - bp->b_error = vbp->b_error ? - vbp->b_error : EIO; - comptype = ""; - } - - printf("%s: error %d on component %d%s\n", - cs->sc_xname, bp->b_error, cbp->cb_comp, comptype); - } - cbp->cb_flags |= CBF_DONE; - - if (cbp->cb_dep && - (cbp->cb_dep->cb_flags & CBF_DONE) != (cbp->cb_flags & CBF_DONE)) - return; - - if (cbp->cb_flags & CBF_MIRROR && - !(cbp->cb_dep->cb_flags & CBF_MIRROR)) { - cbp = cbp->cb_dep; - vbp = (struct buf *)cbp; - } - - count = vbp->b_bcount; - - if (cbp->cb_dep) - putccdbuf(cbp->cb_dep); - putccdbuf(cbp); - - /* - * If all done, "interrupt". - * - * Note that mirror component buffers aren't counted against - * the original I/O buffer. - */ - if (count > bp->b_resid) - panic("ccdiodone: count"); - bp->b_resid -= count; - if (bp->b_resid == 0) - ccdintr(cs, bp); -} - -/* ARGSUSED */ -int -ccdread(dev_t dev, struct uio *uio, int flags) -{ - int unit = DISKUNIT(dev); - struct ccd_softc *cs; - - CCD_DPRINTF(CCDB_FOLLOW, ("ccdread(%x, %p)\n", dev, uio)); - - if (unit >= numccd) - return (ENXIO); - cs = &ccd_softc[unit]; - - if ((cs->sc_flags & CCDF_INITED) == 0) - return (ENXIO); - - /* - * XXX: It's not clear that using minphys() is completely safe, - * in particular, for raw I/O. Underlying devices might have some - * non-obvious limits, because of the copy to user-space. - */ - return (physio(ccdstrategy, dev, B_READ, minphys, uio)); -} - -/* ARGSUSED */ -int -ccdwrite(dev_t dev, struct uio *uio, int flags) -{ - int unit = DISKUNIT(dev); - struct ccd_softc *cs; - - CCD_DPRINTF(CCDB_FOLLOW, ("ccdwrite(%x, %p)\n", dev, uio)); - - if (unit >= numccd) - return (ENXIO); - cs = &ccd_softc[unit]; - - if ((cs->sc_flags & CCDF_INITED) == 0) - return (ENXIO); - - /* - * XXX: It's not clear that using minphys() is completely safe, - * in particular, for raw I/O. Underlying devices might have some - * non-obvious limits, because of the copy to user-space. - */ - return (physio(ccdstrategy, dev, B_WRITE, minphys, uio)); -} - -int -ccdioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) -{ - int unit = DISKUNIT(dev); - int i, j, lookedup = 0, error = 0; - int part, pmask, s; - struct disklabel *lp; - struct ccd_softc *cs; - struct ccd_ioctl *ccio = (struct ccd_ioctl *)data; - struct ccddevice ccd; - char **cpp; - struct vnode **vpp; - - 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: - 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; - - /* - * 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; - - /* Attach the disk. */ - cs->sc_dkdev.dk_name = cs->sc_xname; - disk_attach(NULL, &cs->sc_dkdev); - - /* Try and read the disklabel. */ - ccdgetdisklabel(dev, cs, cs->sc_dkdev.dk_label, 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)); - - /* Detach 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 DIOCRLDINFO: - if ((error = ccdlock(cs)) != 0) - return (error); - - lp = malloc(sizeof(*lp), M_TEMP, M_WAITOK); - ccdgetdisklabel(dev, cs, lp, 0); - *(cs->sc_dkdev.dk_label) = *lp; - free(lp, M_TEMP); - - ccdunlock(cs); - break; - - case DIOCGPDINFO: - if ((error = ccdlock(cs)) != 0) - return (error); - - ccdgetdisklabel(dev, cs, (struct disklabel *)data, 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); - - error = setdisklabel(cs->sc_dkdev.dk_label, - (struct disklabel *)data, 0); - if (error == 0) { - if (cmd == DIOCWDINFO) - error = writedisklabel(DISKLABELDEV(dev), - ccdstrategy, cs->sc_dkdev.dk_label); - } - - ccdunlock(cs); - - if (error) - return (error); - break; - - default: - return (ENOTTY); - } - - return (0); -} - -daddr64_t -ccdsize(dev_t dev) -{ - struct ccd_softc *cs; - int part, unit; - daddr64_t size; - - unit = DISKUNIT(dev); - if (unit >= numccd) - return (-1); - - cs = &ccd_softc[unit]; - if ((cs->sc_flags & CCDF_INITED) == 0) - return (-1); - - if (ccdopen(dev, 0, S_IFBLK, curproc)) - return (-1); - - part = DISKPART(dev); - if (cs->sc_dkdev.dk_label->d_partitions[part].p_fstype != FS_SWAP) - size = -1; - else - size = DL_GETPSIZE(&cs->sc_dkdev.dk_label->d_partitions[part]); - - if (ccdclose(dev, 0, S_IFBLK, curproc)) - return (-1); - - return (size); -} - -int -ccddump(dev_t dev, daddr64_t blkno, caddr_t va, size_t size) -{ - - /* Not implemented. */ - return ENXIO; -} - -/* - * Lookup the provided name in the filesystem. If the file exists, - * is a valid block device, and isn't being used by anyone else, - * set *vpp to the file's vnode. - */ -int -ccdlookup(char *path, struct proc *p, struct vnode **vpp) -{ - struct nameidata nd; - struct vnode *vp; - struct vattr va; - int error; - - NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, path, p); - if ((error = vn_open(&nd, FREAD|FWRITE, 0)) != 0) { - CCD_DPRINTF(CCDB_FOLLOW | CCDB_INIT, - ("ccdlookup: vn_open error = %d\n", error)); - return (error); - } - vp = nd.ni_vp; - - if (vp->v_usecount > 1) { - VOP_UNLOCK(vp, 0, p); - (void)vn_close(vp, FREAD|FWRITE, p->p_ucred, p); - return (EBUSY); - } - - if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) != 0) { - CCD_DPRINTF(CCDB_FOLLOW | CCDB_INIT, - ("ccdlookup: getattr error = %d\n", error)); - VOP_UNLOCK(vp, 0, p); - (void)vn_close(vp, FREAD|FWRITE, p->p_ucred, p); - return (error); - } - - /* XXX: eventually we should handle VREG, too. */ - if (va.va_type != VBLK) { - VOP_UNLOCK(vp, 0, p); - (void)vn_close(vp, FREAD|FWRITE, p->p_ucred, p); - return (ENOTBLK); - } - -#ifdef DIAGNOSTIC - CCD_DCALL(CCDB_VNODE, vprint("ccdlookup: vnode info", vp)); -#endif - - VOP_UNLOCK(vp, 0, p); - *vpp = vp; - return (0); -} - -/* - * Read the disklabel from the ccd. If one is not present, fake one - * up. - */ -int -ccdgetdisklabel(dev_t dev, struct ccd_softc *cs, struct disklabel *lp, - int spoofonly) -{ - struct ccdgeom *ccg = &cs->sc_geom; - - bzero(lp, sizeof(*lp)); - - DL_SETDSIZE(lp, cs->sc_size); - lp->d_secsize = ccg->ccg_secsize; - lp->d_nsectors = ccg->ccg_nsectors; - lp->d_ntracks = ccg->ccg_ntracks; - lp->d_ncylinders = ccg->ccg_ncylinders; - lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors; - - strncpy(lp->d_typename, "ccd", sizeof(lp->d_typename)); - lp->d_type = DTYPE_CCD; - strncpy(lp->d_packname, "fictitious", sizeof(lp->d_packname)); - lp->d_flags = 0; - lp->d_version = 1; - - lp->d_magic = DISKMAGIC; - lp->d_magic2 = DISKMAGIC; - lp->d_checksum = dkcksum(cs->sc_dkdev.dk_label); - - /* - * Call the generic disklabel extraction routine. - */ - return readdisklabel(DISKLABELDEV(dev), ccdstrategy, - cs->sc_dkdev.dk_label, spoofonly); -} - -#ifdef CCDDEBUG -void -printiinfo(struct ccdiinfo *ii) -{ - int ix, i; - - for (ix = 0; ii->ii_ndisk; ix++, ii++) { - printf(" itab[%d]: #dk %d sblk %d soff %d", - ix, ii->ii_ndisk, ii->ii_startblk, ii->ii_startoff); - for (i = 0; i < ii->ii_ndisk; i++) - printf(" %d", ii->ii_index[i]); - printf("\n"); - } -} -#endif diff --git a/sys/dev/ccdvar.h b/sys/dev/ccdvar.h deleted file mode 100644 index 998413dc918..00000000000 --- a/sys/dev/ccdvar.h +++ /dev/null @@ -1,184 +0,0 @@ -/* $OpenBSD: ccdvar.h,v 1.12 2008/06/26 05:42:14 ray Exp $ */ -/* $NetBSD: ccdvar.h,v 1.11 1996/02/28 01:08:32 thorpej Exp $ */ - -/*- - * Copyright (c) 1996 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Jason R. Thorpe. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Copyright (c) 1988 University of Utah. - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * the Systems Programming Group of the University of Utah Computer - * Science Department. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: Utah $Hdr: cdvar.h 1.1 90/07/09$ - * - * @(#)cdvar.h 8.1 (Berkeley) 6/10/93 - */ - -/* - * Dynamic configuration and disklabel support by: - * Jason R. Thorpe <thorpej@nas.nasa.gov> - * Numerical Aerodynamic Simulation Facility - * Mail Stop 258-6 - * NASA Ames Research Center - * Moffett Field, CA 94035 - */ - -/* - * A concatenated disk is described at initialization time by this structure. - */ -struct ccddevice { - struct vnode **ccd_vpp; /* array of component vnodes */ - char **ccd_cpp; /* array of component pathnames */ - int ccd_unit; /* logical unit of this ccd */ - int ccd_interleave; /* interleave (DEV_BSIZE blocks) */ - int ccd_flags; /* misc. information */ - int ccd_ndev; /* number of component devices */ -}; - -/* - * This structure is used to configure a ccd via ioctl(2). - */ -struct ccd_ioctl { - char **ccio_disks; /* pointer to component paths */ - u_int ccio_ndisks; /* number of disks to concatenate */ - int ccio_ileave; /* interleave (DEV_BSIZE blocks) */ - int ccio_flags; /* misc. information */ - int ccio_unit; /* unit number: use varies */ - size_t ccio_size; /* (returned) size of ccd */ -}; - -/* ccd_flags */ -#define CCDF_SWAP 0x01 /* interleave should be dmmax */ -#define CCDF_UNIFORM 0x02 /* use LCCD of sizes for uniform interleave */ -#define CCDF_MIRROR 0x04 /* enable data mirroring */ -#define CCDF_OLD 0x08 /* legacy */ -#define CCDF_BITS \ - "\020\01swap\02uniform\03mirror\04old" - -/* Mask of user-settable ccd flags. */ -#define CCDF_USERMASK \ - (CCDF_SWAP|CCDF_UNIFORM|CCDF_MIRROR|CCDF_OLD) - -/* - * Component info table. - * Describes a single component of a concatenated disk. - */ -struct ccdcinfo { - struct vnode *ci_vp; /* device's vnode */ - char *ci_path; /* path to component */ - size_t ci_size; /* size */ - size_t ci_pathlen; /* length of component path */ - dev_t ci_dev; /* XXX: device's dev_t */ - int ci_flags; /* see below */ -}; - -#define CCIF_FAILED 0x01 /* had a B_ERROR on this one */ - -/* - * Interleave description table. - * Computed at boot time to speed irregular-interleave lookups. - * The idea is that we interleave in "groups". First we interleave - * evenly over all component disks up to the size of the smallest - * component (the first group), then we interleave evenly over all - * remaining disks up to the size of the next-smallest (second group), - * and so on. - * - * Each table entry describes the interleave characteristics of one - * of these groups. For example if a concatenated disk consisted of - * three components of 5, 3, and 7 DEV_BSIZE blocks interleaved at - * DEV_BSIZE (1), the table would have three entries: - * - * ndisk startblk startoff dev - * 3 0 0 0, 1, 2 - * 2 9 3 0, 2 - * 1 13 5 2 - * 0 - - - - * - * which says that the first nine blocks (0-8) are interleaved over - * 3 disks (0, 1, 2) starting at block offset 0 on any component disk, - * the next 4 blocks (9-12) are interleaved over 2 disks (0, 2) starting - * at component block 3, and the remaining blocks (13-14) are on disk - * 2 starting at offset 5. - */ -struct ccdiinfo { - daddr64_t ii_startblk; /* starting scaled block # for range */ - daddr64_t ii_startoff; /* starting component offset (block #) */ - int *ii_index; /* ordered list of components in range */ - int *ii_parity; /* list of parity shifts */ - int ii_ndisk; /* # of disks range is interleaved over */ -}; - -/* - * Concatenated disk pseudo-geometry information. - */ -struct ccdgeom { - u_int32_t ccg_secsize; /* # bytes per sector */ - u_int32_t ccg_nsectors; /* # data sectors per track */ - u_int32_t ccg_ntracks; /* # tracks per cylinder */ - u_int32_t ccg_ncylinders; /* # cylinders per unit */ - u_int16_t ccg_rpm; -}; - -/* - * Before you can use a unit, it must be configured with CCDIOCSET. - * The configuration persists across opens and closes of the device; - * a CCDIOCCLR must be used to reset a configuration. An attempt to - * CCDIOCSET an already active unit will return EBUSY. Attempts to - * CCDIOCCLR an inactive unit will return ENXIO. - */ -#define CCDIOCSET _IOWR('F', 16, struct ccd_ioctl) /* enable ccd */ -#define CCDIOCCLR _IOW('F', 17, struct ccd_ioctl) /* disable ccd */ |