1e2738b4fSPoul-Henning Kamp /* $Id: ccd.c,v 1.25 1997/10/11 07:35:25 phk Exp $ */ 2aa8bdaecSSatoshi Asami 3a56bb8a5SSatoshi Asami /* $NetBSD: ccd.c,v 1.22 1995/12/08 19:13:26 thorpej Exp $ */ 4a56bb8a5SSatoshi Asami 5a56bb8a5SSatoshi Asami /* 6a56bb8a5SSatoshi Asami * Copyright (c) 1995 Jason R. Thorpe. 7a56bb8a5SSatoshi Asami * All rights reserved. 8a56bb8a5SSatoshi Asami * 9a56bb8a5SSatoshi Asami * Redistribution and use in source and binary forms, with or without 10a56bb8a5SSatoshi Asami * modification, are permitted provided that the following conditions 11a56bb8a5SSatoshi Asami * are met: 12a56bb8a5SSatoshi Asami * 1. Redistributions of source code must retain the above copyright 13a56bb8a5SSatoshi Asami * notice, this list of conditions and the following disclaimer. 14a56bb8a5SSatoshi Asami * 2. Redistributions in binary form must reproduce the above copyright 15a56bb8a5SSatoshi Asami * notice, this list of conditions and the following disclaimer in the 16a56bb8a5SSatoshi Asami * documentation and/or other materials provided with the distribution. 17a56bb8a5SSatoshi Asami * 3. All advertising materials mentioning features or use of this software 18a56bb8a5SSatoshi Asami * must display the following acknowledgement: 19a56bb8a5SSatoshi Asami * This product includes software developed for the NetBSD Project 20a56bb8a5SSatoshi Asami * by Jason R. Thorpe. 21a56bb8a5SSatoshi Asami * 4. The name of the author may not be used to endorse or promote products 22a56bb8a5SSatoshi Asami * derived from this software without specific prior written permission. 23a56bb8a5SSatoshi Asami * 24a56bb8a5SSatoshi Asami * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 25a56bb8a5SSatoshi Asami * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 26a56bb8a5SSatoshi Asami * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 27a56bb8a5SSatoshi Asami * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 28a56bb8a5SSatoshi Asami * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 29a56bb8a5SSatoshi Asami * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 30a56bb8a5SSatoshi Asami * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 31a56bb8a5SSatoshi Asami * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 32a56bb8a5SSatoshi Asami * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33a56bb8a5SSatoshi Asami * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34a56bb8a5SSatoshi Asami * SUCH DAMAGE. 35a56bb8a5SSatoshi Asami */ 36a56bb8a5SSatoshi Asami 37a56bb8a5SSatoshi Asami /* 38a56bb8a5SSatoshi Asami * Copyright (c) 1988 University of Utah. 39a56bb8a5SSatoshi Asami * Copyright (c) 1990, 1993 40a56bb8a5SSatoshi Asami * The Regents of the University of California. All rights reserved. 41a56bb8a5SSatoshi Asami * 42a56bb8a5SSatoshi Asami * This code is derived from software contributed to Berkeley by 43a56bb8a5SSatoshi Asami * the Systems Programming Group of the University of Utah Computer 44a56bb8a5SSatoshi Asami * Science Department. 45a56bb8a5SSatoshi Asami * 46a56bb8a5SSatoshi Asami * Redistribution and use in source and binary forms, with or without 47a56bb8a5SSatoshi Asami * modification, are permitted provided that the following conditions 48a56bb8a5SSatoshi Asami * are met: 49a56bb8a5SSatoshi Asami * 1. Redistributions of source code must retain the above copyright 50a56bb8a5SSatoshi Asami * notice, this list of conditions and the following disclaimer. 51a56bb8a5SSatoshi Asami * 2. Redistributions in binary form must reproduce the above copyright 52a56bb8a5SSatoshi Asami * notice, this list of conditions and the following disclaimer in the 53a56bb8a5SSatoshi Asami * documentation and/or other materials provided with the distribution. 54a56bb8a5SSatoshi Asami * 3. All advertising materials mentioning features or use of this software 55a56bb8a5SSatoshi Asami * must display the following acknowledgement: 56a56bb8a5SSatoshi Asami * This product includes software developed by the University of 57a56bb8a5SSatoshi Asami * California, Berkeley and its contributors. 58a56bb8a5SSatoshi Asami * 4. Neither the name of the University nor the names of its contributors 59a56bb8a5SSatoshi Asami * may be used to endorse or promote products derived from this software 60a56bb8a5SSatoshi Asami * without specific prior written permission. 61a56bb8a5SSatoshi Asami * 62a56bb8a5SSatoshi Asami * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 63a56bb8a5SSatoshi Asami * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 64a56bb8a5SSatoshi Asami * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 65a56bb8a5SSatoshi Asami * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 66a56bb8a5SSatoshi Asami * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 67a56bb8a5SSatoshi Asami * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 68a56bb8a5SSatoshi Asami * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 69a56bb8a5SSatoshi Asami * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 70a56bb8a5SSatoshi Asami * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 71a56bb8a5SSatoshi Asami * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 72a56bb8a5SSatoshi Asami * SUCH DAMAGE. 73a56bb8a5SSatoshi Asami * 74a56bb8a5SSatoshi Asami * from: Utah $Hdr: cd.c 1.6 90/11/28$ 75a56bb8a5SSatoshi Asami * 76a56bb8a5SSatoshi Asami * @(#)cd.c 8.2 (Berkeley) 11/16/93 77a56bb8a5SSatoshi Asami */ 78a56bb8a5SSatoshi Asami 79a56bb8a5SSatoshi Asami /* 80a56bb8a5SSatoshi Asami * "Concatenated" disk driver. 81a56bb8a5SSatoshi Asami * 82a56bb8a5SSatoshi Asami * Dynamic configuration and disklabel support by: 83a56bb8a5SSatoshi Asami * Jason R. Thorpe <thorpej@nas.nasa.gov> 84a56bb8a5SSatoshi Asami * Numerical Aerodynamic Simulation Facility 85a56bb8a5SSatoshi Asami * Mail Stop 258-6 86a56bb8a5SSatoshi Asami * NASA Ames Research Center 87a56bb8a5SSatoshi Asami * Moffett Field, CA 94035 88a56bb8a5SSatoshi Asami */ 89a56bb8a5SSatoshi Asami 90d8594dfbSSatoshi Asami #include "ccd.h" 91d8594dfbSSatoshi Asami #if NCCD > 0 92d8594dfbSSatoshi Asami 93a56bb8a5SSatoshi Asami #include <sys/param.h> 94a56bb8a5SSatoshi Asami #include <sys/systm.h> 95e2a13e8cSSatoshi Asami #include <sys/kernel.h> 96e2a13e8cSSatoshi Asami #ifdef DEVFS 97e2a13e8cSSatoshi Asami #include <sys/devfsext.h> 98e2a13e8cSSatoshi Asami #endif /*DEVFS*/ 99a56bb8a5SSatoshi Asami #include <sys/proc.h> 100a56bb8a5SSatoshi Asami #include <sys/buf.h> 101a56bb8a5SSatoshi Asami #include <sys/malloc.h> 102a56bb8a5SSatoshi Asami #include <sys/namei.h> 103a56bb8a5SSatoshi Asami #include <sys/conf.h> 104a56bb8a5SSatoshi Asami #include <sys/stat.h> 105e2738b4fSPoul-Henning Kamp #include <sys/sysctl.h> 106a56bb8a5SSatoshi Asami #include <sys/disklabel.h> 107d8594dfbSSatoshi Asami #include <ufs/ffs/fs.h> 108a56bb8a5SSatoshi Asami #include <sys/device.h> 109e2a13e8cSSatoshi Asami #undef KERNEL /* XXX */ 110a56bb8a5SSatoshi Asami #include <sys/disk.h> 111e2a13e8cSSatoshi Asami #define KERNEL 112a56bb8a5SSatoshi Asami #include <sys/fcntl.h> 113a56bb8a5SSatoshi Asami #include <sys/vnode.h> 114a56bb8a5SSatoshi Asami 115d8594dfbSSatoshi Asami #include <sys/ccdvar.h> 116a56bb8a5SSatoshi Asami 117a56bb8a5SSatoshi Asami #if defined(CCDDEBUG) && !defined(DEBUG) 118a56bb8a5SSatoshi Asami #define DEBUG 119a56bb8a5SSatoshi Asami #endif 120a56bb8a5SSatoshi Asami 121a56bb8a5SSatoshi Asami #ifdef DEBUG 122a56bb8a5SSatoshi Asami #define CCDB_FOLLOW 0x01 123a56bb8a5SSatoshi Asami #define CCDB_INIT 0x02 124a56bb8a5SSatoshi Asami #define CCDB_IO 0x04 125a56bb8a5SSatoshi Asami #define CCDB_LABEL 0x08 126a56bb8a5SSatoshi Asami #define CCDB_VNODE 0x10 127e2738b4fSPoul-Henning Kamp static int ccddebug = CCDB_FOLLOW | CCDB_INIT | CCDB_IO | CCDB_LABEL | 128e2738b4fSPoul-Henning Kamp CCDB_VNODE; 129e2738b4fSPoul-Henning Kamp SYSCTL_INT(_debug, OID_AUTO, ccddebug, CTLFLAG_RW, &ccddebug, 0, ""); 130d8594dfbSSatoshi Asami #undef DEBUG 131a56bb8a5SSatoshi Asami #endif 132a56bb8a5SSatoshi Asami 133d8594dfbSSatoshi Asami #define ccdunit(x) dkunit(x) 134d8594dfbSSatoshi Asami #define ccdpart(x) dkpart(x) 135a56bb8a5SSatoshi Asami 136e7322872SSatoshi Asami /* 137e7322872SSatoshi Asami This is how mirroring works (only writes are special): 138e7322872SSatoshi Asami 139e7322872SSatoshi Asami When initiating a write, ccdbuffer() returns two "struct ccdbuf *"s 140e7322872SSatoshi Asami linked together by the cb_mirror field. "cb_pflags & 141e7322872SSatoshi Asami CCDPF_MIRROR_DONE" is set to 0 on both of them. 142e7322872SSatoshi Asami 143e7322872SSatoshi Asami When a component returns to ccdiodone(), it checks if "cb_pflags & 144e7322872SSatoshi Asami CCDPF_MIRROR_DONE" is set or not. If not, it sets the partner's 145e7322872SSatoshi Asami flag and returns. If it is, it means its partner has already 146e7322872SSatoshi Asami returned, so it will go to the regular cleanup. 147e7322872SSatoshi Asami 148e7322872SSatoshi Asami */ 149e7322872SSatoshi Asami 150a56bb8a5SSatoshi Asami struct ccdbuf { 151a56bb8a5SSatoshi Asami struct buf cb_buf; /* new I/O buf */ 152a56bb8a5SSatoshi Asami struct buf *cb_obp; /* ptr. to original I/O buf */ 153a56bb8a5SSatoshi Asami int cb_unit; /* target unit */ 154a56bb8a5SSatoshi Asami int cb_comp; /* target component */ 155e7322872SSatoshi Asami int cb_pflags; /* mirror/parity status flag */ 156e7322872SSatoshi Asami struct ccdbuf *cb_mirror; /* mirror counterpart */ 157a56bb8a5SSatoshi Asami }; 158a56bb8a5SSatoshi Asami 159e7322872SSatoshi Asami /* bits in cb_pflags */ 160e7322872SSatoshi Asami #define CCDPF_MIRROR_DONE 1 /* if set, mirror counterpart is done */ 161e7322872SSatoshi Asami 162a56bb8a5SSatoshi Asami #define getccdbuf() \ 163a56bb8a5SSatoshi Asami ((struct ccdbuf *)malloc(sizeof(struct ccdbuf), M_DEVBUF, M_WAITOK)) 164a56bb8a5SSatoshi Asami #define putccdbuf(cbp) \ 165a56bb8a5SSatoshi Asami free((caddr_t)(cbp), M_DEVBUF) 166a56bb8a5SSatoshi Asami 167a56bb8a5SSatoshi Asami #define CCDLABELDEV(dev) \ 168d8594dfbSSatoshi Asami (makedev(major((dev)), dkmakeminor(ccdunit((dev)), 0, RAW_PART))) 169a56bb8a5SSatoshi Asami 170e2738b4fSPoul-Henning Kamp static d_open_t ccdopen; 171e2738b4fSPoul-Henning Kamp static d_close_t ccdclose; 172e2738b4fSPoul-Henning Kamp static d_strategy_t ccdstrategy; 173e2738b4fSPoul-Henning Kamp static d_ioctl_t ccdioctl; 174e2738b4fSPoul-Henning Kamp static d_dump_t ccddump; 175e2738b4fSPoul-Henning Kamp static d_psize_t ccdsize; 176e2738b4fSPoul-Henning Kamp static d_read_t ccdread; 177e2738b4fSPoul-Henning Kamp static d_write_t ccdwrite; 178d8594dfbSSatoshi Asami 179e2a13e8cSSatoshi Asami #define CDEV_MAJOR 74 180e2a13e8cSSatoshi Asami #define BDEV_MAJOR 21 181a56bb8a5SSatoshi Asami 182cba8a5ddSPoul-Henning Kamp static struct cdevsw ccd_cdevsw; 183e2a13e8cSSatoshi Asami static struct bdevsw ccd_bdevsw = { 184e2a13e8cSSatoshi Asami ccdopen, ccdclose, ccdstrategy, ccdioctl, 185e2a13e8cSSatoshi Asami ccddump, ccdsize, 0, 186e2a13e8cSSatoshi Asami "ccd", &ccd_cdevsw, -1 187e2a13e8cSSatoshi Asami }; 188e2a13e8cSSatoshi Asami 189e2a13e8cSSatoshi Asami /* Called by main() during pseudo-device attachment */ 190e2a13e8cSSatoshi Asami static void ccdattach __P((void *)); 191e2a13e8cSSatoshi Asami PSEUDO_SET(ccdattach, ccd); 192a56bb8a5SSatoshi Asami 193a56bb8a5SSatoshi Asami /* called by biodone() at interrupt time */ 194e2738b4fSPoul-Henning Kamp static void ccdiodone __P((struct ccdbuf *cbp)); 195a56bb8a5SSatoshi Asami 196a56bb8a5SSatoshi Asami static void ccdstart __P((struct ccd_softc *, struct buf *)); 197a56bb8a5SSatoshi Asami static void ccdinterleave __P((struct ccd_softc *, int)); 198a56bb8a5SSatoshi Asami static void ccdintr __P((struct ccd_softc *, struct buf *)); 199a56bb8a5SSatoshi Asami static int ccdinit __P((struct ccddevice *, char **, struct proc *)); 200a56bb8a5SSatoshi Asami static int ccdlookup __P((char *, struct proc *p, struct vnode **)); 2013bc746beSSatoshi Asami static void ccdbuffer __P((struct ccdbuf **ret, struct ccd_softc *, 2023bc746beSSatoshi Asami struct buf *, daddr_t, caddr_t, long)); 203a56bb8a5SSatoshi Asami static void ccdgetdisklabel __P((dev_t)); 204a56bb8a5SSatoshi Asami static void ccdmakedisklabel __P((struct ccd_softc *)); 205a56bb8a5SSatoshi Asami static int ccdlock __P((struct ccd_softc *)); 206a56bb8a5SSatoshi Asami static void ccdunlock __P((struct ccd_softc *)); 207a56bb8a5SSatoshi Asami 208a56bb8a5SSatoshi Asami #ifdef DEBUG 209a56bb8a5SSatoshi Asami static void printiinfo __P((struct ccdiinfo *)); 210a56bb8a5SSatoshi Asami #endif 211a56bb8a5SSatoshi Asami 212a56bb8a5SSatoshi Asami /* Non-private for the benefit of libkvm. */ 213a56bb8a5SSatoshi Asami struct ccd_softc *ccd_softc; 214a56bb8a5SSatoshi Asami struct ccddevice *ccddevs; 215e2738b4fSPoul-Henning Kamp static int numccd = 0; 216a56bb8a5SSatoshi Asami 21752faebb2SSatoshi Asami static int ccd_devsw_installed = 0; 218d8594dfbSSatoshi Asami 219a56bb8a5SSatoshi Asami /* 2200d88ef07SSatoshi Asami * Number of blocks to untouched in front of a component partition. 2210d88ef07SSatoshi Asami * This is to avoid violating its disklabel area when it starts at the 2220d88ef07SSatoshi Asami * beginning of the slice. 2230d88ef07SSatoshi Asami */ 2241af0e025SSatoshi Asami #if !defined(CCD_OFFSET) 2250d88ef07SSatoshi Asami #define CCD_OFFSET 16 2261af0e025SSatoshi Asami #endif 2270d88ef07SSatoshi Asami 2280d88ef07SSatoshi Asami /* 229a56bb8a5SSatoshi Asami * Called by main() during pseudo-device attachment. All we need 230e2a13e8cSSatoshi Asami * to do is allocate enough space for devices to be configured later, and 231e2a13e8cSSatoshi Asami * add devsw entries. 232a56bb8a5SSatoshi Asami */ 233e2738b4fSPoul-Henning Kamp static void 234e2a13e8cSSatoshi Asami ccdattach(dummy) 235e2a13e8cSSatoshi Asami void *dummy; 236a56bb8a5SSatoshi Asami { 237a56bb8a5SSatoshi Asami int i; 238e2a13e8cSSatoshi Asami int num = NCCD; 239a56bb8a5SSatoshi Asami 240e2a13e8cSSatoshi Asami if (num > 1) 241e2a13e8cSSatoshi Asami printf("ccd0-%d: Concatenated disk drivers\n", num-1); 242d8594dfbSSatoshi Asami else 243e2a13e8cSSatoshi Asami printf("ccd0: Concatenated disk driver\n"); 244d8594dfbSSatoshi Asami 245a56bb8a5SSatoshi Asami ccd_softc = (struct ccd_softc *)malloc(num * sizeof(struct ccd_softc), 246a56bb8a5SSatoshi Asami M_DEVBUF, M_NOWAIT); 247a56bb8a5SSatoshi Asami ccddevs = (struct ccddevice *)malloc(num * sizeof(struct ccddevice), 248a56bb8a5SSatoshi Asami M_DEVBUF, M_NOWAIT); 249a56bb8a5SSatoshi Asami if ((ccd_softc == NULL) || (ccddevs == NULL)) { 250a56bb8a5SSatoshi Asami printf("WARNING: no memory for concatenated disks\n"); 251a56bb8a5SSatoshi Asami if (ccd_softc != NULL) 252a56bb8a5SSatoshi Asami free(ccd_softc, M_DEVBUF); 253a56bb8a5SSatoshi Asami if (ccddevs != NULL) 254a56bb8a5SSatoshi Asami free(ccddevs, M_DEVBUF); 255e2a13e8cSSatoshi Asami return; 256a56bb8a5SSatoshi Asami } 257a56bb8a5SSatoshi Asami numccd = num; 258a56bb8a5SSatoshi Asami bzero(ccd_softc, num * sizeof(struct ccd_softc)); 259a56bb8a5SSatoshi Asami bzero(ccddevs, num * sizeof(struct ccddevice)); 260a56bb8a5SSatoshi Asami 261a56bb8a5SSatoshi Asami /* XXX: is this necessary? */ 262a56bb8a5SSatoshi Asami for (i = 0; i < numccd; ++i) 263a56bb8a5SSatoshi Asami ccddevs[i].ccd_dk = -1; 264d8594dfbSSatoshi Asami 265e2a13e8cSSatoshi Asami if( ! ccd_devsw_installed ) { 266cba8a5ddSPoul-Henning Kamp bdevsw_add_generic(BDEV_MAJOR,CDEV_MAJOR, &ccd_bdevsw); 267e2a13e8cSSatoshi Asami ccd_devsw_installed = 1; 268e2a13e8cSSatoshi Asami } 269e2a13e8cSSatoshi Asami else { 270e2a13e8cSSatoshi Asami printf("huh?\n"); 271e2a13e8cSSatoshi Asami } 272a56bb8a5SSatoshi Asami } 273a56bb8a5SSatoshi Asami 274a56bb8a5SSatoshi Asami static int 275a56bb8a5SSatoshi Asami ccdinit(ccd, cpaths, p) 276a56bb8a5SSatoshi Asami struct ccddevice *ccd; 277a56bb8a5SSatoshi Asami char **cpaths; 278a56bb8a5SSatoshi Asami struct proc *p; 279a56bb8a5SSatoshi Asami { 280a56bb8a5SSatoshi Asami register struct ccd_softc *cs = &ccd_softc[ccd->ccd_unit]; 281e2a13e8cSSatoshi Asami register struct ccdcinfo *ci = NULL; /* XXX */ 282a56bb8a5SSatoshi Asami register size_t size; 283a56bb8a5SSatoshi Asami register int ix; 284a56bb8a5SSatoshi Asami struct vnode *vp; 285a56bb8a5SSatoshi Asami struct vattr va; 286a56bb8a5SSatoshi Asami size_t minsize; 287a56bb8a5SSatoshi Asami int maxsecsize; 288a56bb8a5SSatoshi Asami struct partinfo dpart; 289a56bb8a5SSatoshi Asami struct ccdgeom *ccg = &cs->sc_geom; 290a56bb8a5SSatoshi Asami char tmppath[MAXPATHLEN]; 291a56bb8a5SSatoshi Asami int error; 292a56bb8a5SSatoshi Asami 293a56bb8a5SSatoshi Asami #ifdef DEBUG 294a56bb8a5SSatoshi Asami if (ccddebug & (CCDB_FOLLOW|CCDB_INIT)) 295a56bb8a5SSatoshi Asami printf("ccdinit: unit %d\n", ccd->ccd_unit); 296a56bb8a5SSatoshi Asami #endif 297a56bb8a5SSatoshi Asami 298a56bb8a5SSatoshi Asami #ifdef WORKING_DISK_STATISTICS /* XXX !! */ 299a56bb8a5SSatoshi Asami cs->sc_dk = ccd->ccd_dk; 300a56bb8a5SSatoshi Asami #endif 301a56bb8a5SSatoshi Asami cs->sc_size = 0; 302a56bb8a5SSatoshi Asami cs->sc_ileave = ccd->ccd_interleave; 303a56bb8a5SSatoshi Asami cs->sc_nccdisks = ccd->ccd_ndev; 304a56bb8a5SSatoshi Asami 305a56bb8a5SSatoshi Asami /* Allocate space for the component info. */ 306a56bb8a5SSatoshi Asami cs->sc_cinfo = malloc(cs->sc_nccdisks * sizeof(struct ccdcinfo), 307a56bb8a5SSatoshi Asami M_DEVBUF, M_WAITOK); 308a56bb8a5SSatoshi Asami 309a56bb8a5SSatoshi Asami /* 310a56bb8a5SSatoshi Asami * Verify that each component piece exists and record 311a56bb8a5SSatoshi Asami * relevant information about it. 312a56bb8a5SSatoshi Asami */ 313a56bb8a5SSatoshi Asami maxsecsize = 0; 314a56bb8a5SSatoshi Asami minsize = 0; 315a56bb8a5SSatoshi Asami for (ix = 0; ix < cs->sc_nccdisks; ix++) { 316a56bb8a5SSatoshi Asami vp = ccd->ccd_vpp[ix]; 317a56bb8a5SSatoshi Asami ci = &cs->sc_cinfo[ix]; 318a56bb8a5SSatoshi Asami ci->ci_vp = vp; 319a56bb8a5SSatoshi Asami 320a56bb8a5SSatoshi Asami /* 321a56bb8a5SSatoshi Asami * Copy in the pathname of the component. 322a56bb8a5SSatoshi Asami */ 323a56bb8a5SSatoshi Asami bzero(tmppath, sizeof(tmppath)); /* sanity */ 324a56bb8a5SSatoshi Asami if (error = copyinstr(cpaths[ix], tmppath, 325a56bb8a5SSatoshi Asami MAXPATHLEN, &ci->ci_pathlen)) { 326a56bb8a5SSatoshi Asami #ifdef DEBUG 327a56bb8a5SSatoshi Asami if (ccddebug & (CCDB_FOLLOW|CCDB_INIT)) 328a56bb8a5SSatoshi Asami printf("ccd%d: can't copy path, error = %d\n", 329a56bb8a5SSatoshi Asami ccd->ccd_unit, error); 330a56bb8a5SSatoshi Asami #endif 33134f35216SSatoshi Asami while (ci > cs->sc_cinfo) { 33234f35216SSatoshi Asami ci--; 33334f35216SSatoshi Asami free(ci->ci_path, M_DEVBUF); 33434f35216SSatoshi Asami } 335a56bb8a5SSatoshi Asami free(cs->sc_cinfo, M_DEVBUF); 336a56bb8a5SSatoshi Asami return (error); 337a56bb8a5SSatoshi Asami } 338a56bb8a5SSatoshi Asami ci->ci_path = malloc(ci->ci_pathlen, M_DEVBUF, M_WAITOK); 339a56bb8a5SSatoshi Asami bcopy(tmppath, ci->ci_path, ci->ci_pathlen); 340a56bb8a5SSatoshi Asami 341a56bb8a5SSatoshi Asami /* 342a56bb8a5SSatoshi Asami * XXX: Cache the component's dev_t. 343a56bb8a5SSatoshi Asami */ 344a56bb8a5SSatoshi Asami if (error = VOP_GETATTR(vp, &va, p->p_ucred, p)) { 345a56bb8a5SSatoshi Asami #ifdef DEBUG 346a56bb8a5SSatoshi Asami if (ccddebug & (CCDB_FOLLOW|CCDB_INIT)) 347a56bb8a5SSatoshi Asami printf("ccd%d: %s: getattr failed %s = %d\n", 348a56bb8a5SSatoshi Asami ccd->ccd_unit, ci->ci_path, 349a56bb8a5SSatoshi Asami "error", error); 350a56bb8a5SSatoshi Asami #endif 35134f35216SSatoshi Asami while (ci >= cs->sc_cinfo) { 352a56bb8a5SSatoshi Asami free(ci->ci_path, M_DEVBUF); 35334f35216SSatoshi Asami ci--; 35434f35216SSatoshi Asami } 355a56bb8a5SSatoshi Asami free(cs->sc_cinfo, M_DEVBUF); 356a56bb8a5SSatoshi Asami return (error); 357a56bb8a5SSatoshi Asami } 358a56bb8a5SSatoshi Asami ci->ci_dev = va.va_rdev; 359a56bb8a5SSatoshi Asami 360a56bb8a5SSatoshi Asami /* 361a56bb8a5SSatoshi Asami * Get partition information for the component. 362a56bb8a5SSatoshi Asami */ 363a56bb8a5SSatoshi Asami if (error = VOP_IOCTL(vp, DIOCGPART, (caddr_t)&dpart, 364a56bb8a5SSatoshi Asami FREAD, p->p_ucred, p)) { 365a56bb8a5SSatoshi Asami #ifdef DEBUG 366a56bb8a5SSatoshi Asami if (ccddebug & (CCDB_FOLLOW|CCDB_INIT)) 367a56bb8a5SSatoshi Asami printf("ccd%d: %s: ioctl failed, error = %d\n", 368a56bb8a5SSatoshi Asami ccd->ccd_unit, ci->ci_path, error); 369a56bb8a5SSatoshi Asami #endif 37034f35216SSatoshi Asami while (ci >= cs->sc_cinfo) { 371a56bb8a5SSatoshi Asami free(ci->ci_path, M_DEVBUF); 37234f35216SSatoshi Asami ci--; 37334f35216SSatoshi Asami } 374a56bb8a5SSatoshi Asami free(cs->sc_cinfo, M_DEVBUF); 375a56bb8a5SSatoshi Asami return (error); 376a56bb8a5SSatoshi Asami } 377a56bb8a5SSatoshi Asami if (dpart.part->p_fstype == FS_BSDFFS) { 378a56bb8a5SSatoshi Asami maxsecsize = 379a56bb8a5SSatoshi Asami ((dpart.disklab->d_secsize > maxsecsize) ? 380a56bb8a5SSatoshi Asami dpart.disklab->d_secsize : maxsecsize); 3810d88ef07SSatoshi Asami size = dpart.part->p_size - CCD_OFFSET; 382a56bb8a5SSatoshi Asami } else { 383a56bb8a5SSatoshi Asami #ifdef DEBUG 384a56bb8a5SSatoshi Asami if (ccddebug & (CCDB_FOLLOW|CCDB_INIT)) 385a56bb8a5SSatoshi Asami printf("ccd%d: %s: incorrect partition type\n", 386a56bb8a5SSatoshi Asami ccd->ccd_unit, ci->ci_path); 387a56bb8a5SSatoshi Asami #endif 38834f35216SSatoshi Asami while (ci >= cs->sc_cinfo) { 389a56bb8a5SSatoshi Asami free(ci->ci_path, M_DEVBUF); 39034f35216SSatoshi Asami ci--; 39134f35216SSatoshi Asami } 392a56bb8a5SSatoshi Asami free(cs->sc_cinfo, M_DEVBUF); 393a56bb8a5SSatoshi Asami return (EFTYPE); 394a56bb8a5SSatoshi Asami } 395a56bb8a5SSatoshi Asami 396a56bb8a5SSatoshi Asami /* 397a56bb8a5SSatoshi Asami * Calculate the size, truncating to an interleave 398a56bb8a5SSatoshi Asami * boundary if necessary. 399a56bb8a5SSatoshi Asami */ 400a56bb8a5SSatoshi Asami 401a56bb8a5SSatoshi Asami if (cs->sc_ileave > 1) 402a56bb8a5SSatoshi Asami size -= size % cs->sc_ileave; 403a56bb8a5SSatoshi Asami 404a56bb8a5SSatoshi Asami if (size == 0) { 405a56bb8a5SSatoshi Asami #ifdef DEBUG 406a56bb8a5SSatoshi Asami if (ccddebug & (CCDB_FOLLOW|CCDB_INIT)) 407a56bb8a5SSatoshi Asami printf("ccd%d: %s: size == 0\n", 408a56bb8a5SSatoshi Asami ccd->ccd_unit, ci->ci_path); 409a56bb8a5SSatoshi Asami #endif 41034f35216SSatoshi Asami while (ci >= cs->sc_cinfo) { 411a56bb8a5SSatoshi Asami free(ci->ci_path, M_DEVBUF); 41234f35216SSatoshi Asami ci--; 41334f35216SSatoshi Asami } 414a56bb8a5SSatoshi Asami free(cs->sc_cinfo, M_DEVBUF); 415a56bb8a5SSatoshi Asami return (ENODEV); 416a56bb8a5SSatoshi Asami } 417a56bb8a5SSatoshi Asami 418a56bb8a5SSatoshi Asami if (minsize == 0 || size < minsize) 419a56bb8a5SSatoshi Asami minsize = size; 420a56bb8a5SSatoshi Asami ci->ci_size = size; 421a56bb8a5SSatoshi Asami cs->sc_size += size; 422a56bb8a5SSatoshi Asami } 423a56bb8a5SSatoshi Asami 424a56bb8a5SSatoshi Asami /* 425a56bb8a5SSatoshi Asami * Don't allow the interleave to be smaller than 426a56bb8a5SSatoshi Asami * the biggest component sector. 427a56bb8a5SSatoshi Asami */ 428a56bb8a5SSatoshi Asami if ((cs->sc_ileave > 0) && 429a56bb8a5SSatoshi Asami (cs->sc_ileave < (maxsecsize / DEV_BSIZE))) { 430a56bb8a5SSatoshi Asami #ifdef DEBUG 431a56bb8a5SSatoshi Asami if (ccddebug & (CCDB_FOLLOW|CCDB_INIT)) 432a56bb8a5SSatoshi Asami printf("ccd%d: interleave must be at least %d\n", 433a56bb8a5SSatoshi Asami ccd->ccd_unit, (maxsecsize / DEV_BSIZE)); 434a56bb8a5SSatoshi Asami #endif 43534f35216SSatoshi Asami while (ci >= cs->sc_cinfo) { 436a56bb8a5SSatoshi Asami free(ci->ci_path, M_DEVBUF); 43734f35216SSatoshi Asami ci--; 43834f35216SSatoshi Asami } 439a56bb8a5SSatoshi Asami free(cs->sc_cinfo, M_DEVBUF); 440a56bb8a5SSatoshi Asami return (EINVAL); 441a56bb8a5SSatoshi Asami } 442a56bb8a5SSatoshi Asami 443a56bb8a5SSatoshi Asami /* 444a56bb8a5SSatoshi Asami * If uniform interleave is desired set all sizes to that of 445a56bb8a5SSatoshi Asami * the smallest component. 446a56bb8a5SSatoshi Asami */ 447a56bb8a5SSatoshi Asami if (ccd->ccd_flags & CCDF_UNIFORM) { 448a56bb8a5SSatoshi Asami for (ci = cs->sc_cinfo; 449a56bb8a5SSatoshi Asami ci < &cs->sc_cinfo[cs->sc_nccdisks]; ci++) 450a56bb8a5SSatoshi Asami ci->ci_size = minsize; 45109b59204SSatoshi Asami if (ccd->ccd_flags & CCDF_MIRROR) { 45234f35216SSatoshi Asami /* 45334f35216SSatoshi Asami * Check to see if an even number of components 45434f35216SSatoshi Asami * have been specified. 45534f35216SSatoshi Asami */ 45609b59204SSatoshi Asami if (cs->sc_nccdisks % 2) { 45734f35216SSatoshi Asami printf("ccd%d: mirroring requires an even number of disks\n", ccd->ccd_unit ); 45834f35216SSatoshi Asami while (ci > cs->sc_cinfo) { 45934f35216SSatoshi Asami ci--; 46034f35216SSatoshi Asami free(ci->ci_path, M_DEVBUF); 46134f35216SSatoshi Asami } 46234f35216SSatoshi Asami free(cs->sc_cinfo, M_DEVBUF); 46334f35216SSatoshi Asami return (EINVAL); 46409b59204SSatoshi Asami } 46509b59204SSatoshi Asami cs->sc_size = (cs->sc_nccdisks/2) * minsize; 46609b59204SSatoshi Asami } 46709b59204SSatoshi Asami else if (ccd->ccd_flags & CCDF_PARITY) 4687ecb65faSSatoshi Asami cs->sc_size = (cs->sc_nccdisks-1) * minsize; 4697ecb65faSSatoshi Asami else 470a56bb8a5SSatoshi Asami cs->sc_size = cs->sc_nccdisks * minsize; 471a56bb8a5SSatoshi Asami } 472a56bb8a5SSatoshi Asami 473a56bb8a5SSatoshi Asami /* 474a56bb8a5SSatoshi Asami * Construct the interleave table. 475a56bb8a5SSatoshi Asami */ 476a56bb8a5SSatoshi Asami ccdinterleave(cs, ccd->ccd_unit); 477a56bb8a5SSatoshi Asami 478a56bb8a5SSatoshi Asami /* 479a56bb8a5SSatoshi Asami * Create pseudo-geometry based on 1MB cylinders. It's 480a56bb8a5SSatoshi Asami * pretty close. 481a56bb8a5SSatoshi Asami */ 482e59f3105SSøren Schmidt ccg->ccg_secsize = maxsecsize; 483a56bb8a5SSatoshi Asami ccg->ccg_ntracks = 1; 484a56bb8a5SSatoshi Asami ccg->ccg_nsectors = 1024 * (1024 / ccg->ccg_secsize); 485a56bb8a5SSatoshi Asami ccg->ccg_ncylinders = cs->sc_size / ccg->ccg_nsectors; 486a56bb8a5SSatoshi Asami 487a56bb8a5SSatoshi Asami #ifdef WORKING_DISK_STATISTICS /* XXX !! */ 488a56bb8a5SSatoshi Asami if (ccd->ccd_dk >= 0) 489a56bb8a5SSatoshi Asami dk_wpms[ccd->ccd_dk] = 32 * (60 * DEV_BSIZE / 2); /* XXX */ 490a56bb8a5SSatoshi Asami #endif 491a56bb8a5SSatoshi Asami 492a56bb8a5SSatoshi Asami cs->sc_flags |= CCDF_INITED; 493a56bb8a5SSatoshi Asami cs->sc_cflags = ccd->ccd_flags; /* So we can find out later... */ 494a56bb8a5SSatoshi Asami cs->sc_unit = ccd->ccd_unit; 495a56bb8a5SSatoshi Asami return (0); 496a56bb8a5SSatoshi Asami } 497a56bb8a5SSatoshi Asami 498a56bb8a5SSatoshi Asami static void 499a56bb8a5SSatoshi Asami ccdinterleave(cs, unit) 500a56bb8a5SSatoshi Asami register struct ccd_softc *cs; 501a56bb8a5SSatoshi Asami int unit; 502a56bb8a5SSatoshi Asami { 503a56bb8a5SSatoshi Asami register struct ccdcinfo *ci, *smallci; 504a56bb8a5SSatoshi Asami register struct ccdiinfo *ii; 505a56bb8a5SSatoshi Asami register daddr_t bn, lbn; 506a56bb8a5SSatoshi Asami register int ix; 507a56bb8a5SSatoshi Asami u_long size; 508a56bb8a5SSatoshi Asami 509a56bb8a5SSatoshi Asami #ifdef DEBUG 510a56bb8a5SSatoshi Asami if (ccddebug & CCDB_INIT) 511a56bb8a5SSatoshi Asami printf("ccdinterleave(%x): ileave %d\n", cs, cs->sc_ileave); 512a56bb8a5SSatoshi Asami #endif 513a56bb8a5SSatoshi Asami /* 514a56bb8a5SSatoshi Asami * Allocate an interleave table. 515a56bb8a5SSatoshi Asami * Chances are this is too big, but we don't care. 516a56bb8a5SSatoshi Asami */ 517a56bb8a5SSatoshi Asami size = (cs->sc_nccdisks + 1) * sizeof(struct ccdiinfo); 518a56bb8a5SSatoshi Asami cs->sc_itable = (struct ccdiinfo *)malloc(size, M_DEVBUF, M_WAITOK); 519a56bb8a5SSatoshi Asami bzero((caddr_t)cs->sc_itable, size); 520a56bb8a5SSatoshi Asami 521a56bb8a5SSatoshi Asami /* 522a56bb8a5SSatoshi Asami * Trivial case: no interleave (actually interleave of disk size). 523a56bb8a5SSatoshi Asami * Each table entry represents a single component in its entirety. 524a56bb8a5SSatoshi Asami */ 525a56bb8a5SSatoshi Asami if (cs->sc_ileave == 0) { 526a56bb8a5SSatoshi Asami bn = 0; 527a56bb8a5SSatoshi Asami ii = cs->sc_itable; 528a56bb8a5SSatoshi Asami 529a56bb8a5SSatoshi Asami for (ix = 0; ix < cs->sc_nccdisks; ix++) { 530a56bb8a5SSatoshi Asami /* Allocate space for ii_index. */ 531a56bb8a5SSatoshi Asami ii->ii_index = malloc(sizeof(int), M_DEVBUF, M_WAITOK); 532a56bb8a5SSatoshi Asami ii->ii_ndisk = 1; 533a56bb8a5SSatoshi Asami ii->ii_startblk = bn; 534a56bb8a5SSatoshi Asami ii->ii_startoff = 0; 535a56bb8a5SSatoshi Asami ii->ii_index[0] = ix; 536a56bb8a5SSatoshi Asami bn += cs->sc_cinfo[ix].ci_size; 537a56bb8a5SSatoshi Asami ii++; 538a56bb8a5SSatoshi Asami } 539a56bb8a5SSatoshi Asami ii->ii_ndisk = 0; 540a56bb8a5SSatoshi Asami #ifdef DEBUG 541a56bb8a5SSatoshi Asami if (ccddebug & CCDB_INIT) 542a56bb8a5SSatoshi Asami printiinfo(cs->sc_itable); 543a56bb8a5SSatoshi Asami #endif 544a56bb8a5SSatoshi Asami return; 545a56bb8a5SSatoshi Asami } 546a56bb8a5SSatoshi Asami 547a56bb8a5SSatoshi Asami /* 548a56bb8a5SSatoshi Asami * The following isn't fast or pretty; it doesn't have to be. 549a56bb8a5SSatoshi Asami */ 550a56bb8a5SSatoshi Asami size = 0; 551a56bb8a5SSatoshi Asami bn = lbn = 0; 552a56bb8a5SSatoshi Asami for (ii = cs->sc_itable; ; ii++) { 553a56bb8a5SSatoshi Asami /* Allocate space for ii_index. */ 554a56bb8a5SSatoshi Asami ii->ii_index = malloc((sizeof(int) * cs->sc_nccdisks), 555a56bb8a5SSatoshi Asami M_DEVBUF, M_WAITOK); 556a56bb8a5SSatoshi Asami 557a56bb8a5SSatoshi Asami /* 558a56bb8a5SSatoshi Asami * Locate the smallest of the remaining components 559a56bb8a5SSatoshi Asami */ 560a56bb8a5SSatoshi Asami smallci = NULL; 561a56bb8a5SSatoshi Asami for (ci = cs->sc_cinfo; 562a56bb8a5SSatoshi Asami ci < &cs->sc_cinfo[cs->sc_nccdisks]; ci++) 563a56bb8a5SSatoshi Asami if (ci->ci_size > size && 564a56bb8a5SSatoshi Asami (smallci == NULL || 565a56bb8a5SSatoshi Asami ci->ci_size < smallci->ci_size)) 566a56bb8a5SSatoshi Asami smallci = ci; 567a56bb8a5SSatoshi Asami 568a56bb8a5SSatoshi Asami /* 569a56bb8a5SSatoshi Asami * Nobody left, all done 570a56bb8a5SSatoshi Asami */ 571a56bb8a5SSatoshi Asami if (smallci == NULL) { 572a56bb8a5SSatoshi Asami ii->ii_ndisk = 0; 573a56bb8a5SSatoshi Asami break; 574a56bb8a5SSatoshi Asami } 575a56bb8a5SSatoshi Asami 576a56bb8a5SSatoshi Asami /* 577a56bb8a5SSatoshi Asami * Record starting logical block and component offset 578a56bb8a5SSatoshi Asami */ 579a56bb8a5SSatoshi Asami ii->ii_startblk = bn / cs->sc_ileave; 580a56bb8a5SSatoshi Asami ii->ii_startoff = lbn; 581a56bb8a5SSatoshi Asami 582a56bb8a5SSatoshi Asami /* 583a56bb8a5SSatoshi Asami * Determine how many disks take part in this interleave 584a56bb8a5SSatoshi Asami * and record their indices. 585a56bb8a5SSatoshi Asami */ 586a56bb8a5SSatoshi Asami ix = 0; 587a56bb8a5SSatoshi Asami for (ci = cs->sc_cinfo; 588a56bb8a5SSatoshi Asami ci < &cs->sc_cinfo[cs->sc_nccdisks]; ci++) 589a56bb8a5SSatoshi Asami if (ci->ci_size >= smallci->ci_size) 590a56bb8a5SSatoshi Asami ii->ii_index[ix++] = ci - cs->sc_cinfo; 591a56bb8a5SSatoshi Asami ii->ii_ndisk = ix; 592a56bb8a5SSatoshi Asami bn += ix * (smallci->ci_size - size); 593a56bb8a5SSatoshi Asami lbn = smallci->ci_size / cs->sc_ileave; 594a56bb8a5SSatoshi Asami size = smallci->ci_size; 595a56bb8a5SSatoshi Asami } 596a56bb8a5SSatoshi Asami #ifdef DEBUG 597a56bb8a5SSatoshi Asami if (ccddebug & CCDB_INIT) 598a56bb8a5SSatoshi Asami printiinfo(cs->sc_itable); 599a56bb8a5SSatoshi Asami #endif 600a56bb8a5SSatoshi Asami } 601a56bb8a5SSatoshi Asami 602a56bb8a5SSatoshi Asami /* ARGSUSED */ 603e2738b4fSPoul-Henning Kamp static int 604a56bb8a5SSatoshi Asami ccdopen(dev, flags, fmt, p) 605a56bb8a5SSatoshi Asami dev_t dev; 606a56bb8a5SSatoshi Asami int flags, fmt; 607a56bb8a5SSatoshi Asami struct proc *p; 608a56bb8a5SSatoshi Asami { 609a56bb8a5SSatoshi Asami int unit = ccdunit(dev); 610a56bb8a5SSatoshi Asami struct ccd_softc *cs; 611a56bb8a5SSatoshi Asami struct disklabel *lp; 612a56bb8a5SSatoshi Asami int error = 0, part, pmask; 613a56bb8a5SSatoshi Asami 614a56bb8a5SSatoshi Asami #ifdef DEBUG 615a56bb8a5SSatoshi Asami if (ccddebug & CCDB_FOLLOW) 616a56bb8a5SSatoshi Asami printf("ccdopen(%x, %x)\n", dev, flags); 617a56bb8a5SSatoshi Asami #endif 618a56bb8a5SSatoshi Asami if (unit >= numccd) 619a56bb8a5SSatoshi Asami return (ENXIO); 620a56bb8a5SSatoshi Asami cs = &ccd_softc[unit]; 621a56bb8a5SSatoshi Asami 622a56bb8a5SSatoshi Asami if (error = ccdlock(cs)) 623a56bb8a5SSatoshi Asami return (error); 624a56bb8a5SSatoshi Asami 625a56bb8a5SSatoshi Asami lp = &cs->sc_dkdev.dk_label; 626a56bb8a5SSatoshi Asami 627d8594dfbSSatoshi Asami part = ccdpart(dev); 628a56bb8a5SSatoshi Asami pmask = (1 << part); 629a56bb8a5SSatoshi Asami 630a56bb8a5SSatoshi Asami /* 631a56bb8a5SSatoshi Asami * If we're initialized, check to see if there are any other 632a56bb8a5SSatoshi Asami * open partitions. If not, then it's safe to update 633a56bb8a5SSatoshi Asami * the in-core disklabel. 634a56bb8a5SSatoshi Asami */ 635a56bb8a5SSatoshi Asami if ((cs->sc_flags & CCDF_INITED) && (cs->sc_dkdev.dk_openmask == 0)) 636a56bb8a5SSatoshi Asami ccdgetdisklabel(dev); 637a56bb8a5SSatoshi Asami 638a56bb8a5SSatoshi Asami /* Check that the partition exists. */ 639a56bb8a5SSatoshi Asami if (part != RAW_PART && ((part > lp->d_npartitions) || 640a56bb8a5SSatoshi Asami (lp->d_partitions[part].p_fstype == FS_UNUSED))) { 641a56bb8a5SSatoshi Asami error = ENXIO; 642a56bb8a5SSatoshi Asami goto done; 643a56bb8a5SSatoshi Asami } 644a56bb8a5SSatoshi Asami 645a56bb8a5SSatoshi Asami /* Prevent our unit from being unconfigured while open. */ 646a56bb8a5SSatoshi Asami switch (fmt) { 647a56bb8a5SSatoshi Asami case S_IFCHR: 648a56bb8a5SSatoshi Asami cs->sc_dkdev.dk_copenmask |= pmask; 649a56bb8a5SSatoshi Asami break; 650a56bb8a5SSatoshi Asami 651a56bb8a5SSatoshi Asami case S_IFBLK: 652a56bb8a5SSatoshi Asami cs->sc_dkdev.dk_bopenmask |= pmask; 653a56bb8a5SSatoshi Asami break; 654a56bb8a5SSatoshi Asami } 655a56bb8a5SSatoshi Asami cs->sc_dkdev.dk_openmask = 656a56bb8a5SSatoshi Asami cs->sc_dkdev.dk_copenmask | cs->sc_dkdev.dk_bopenmask; 657a56bb8a5SSatoshi Asami 658a56bb8a5SSatoshi Asami done: 659a56bb8a5SSatoshi Asami ccdunlock(cs); 660a56bb8a5SSatoshi Asami return (0); 661a56bb8a5SSatoshi Asami } 662a56bb8a5SSatoshi Asami 663a56bb8a5SSatoshi Asami /* ARGSUSED */ 664e2738b4fSPoul-Henning Kamp static int 665a56bb8a5SSatoshi Asami ccdclose(dev, flags, fmt, p) 666a56bb8a5SSatoshi Asami dev_t dev; 667a56bb8a5SSatoshi Asami int flags, fmt; 668a56bb8a5SSatoshi Asami struct proc *p; 669a56bb8a5SSatoshi Asami { 670a56bb8a5SSatoshi Asami int unit = ccdunit(dev); 671a56bb8a5SSatoshi Asami struct ccd_softc *cs; 672a56bb8a5SSatoshi Asami int error = 0, part; 673a56bb8a5SSatoshi Asami 674a56bb8a5SSatoshi Asami #ifdef DEBUG 675a56bb8a5SSatoshi Asami if (ccddebug & CCDB_FOLLOW) 676a56bb8a5SSatoshi Asami printf("ccdclose(%x, %x)\n", dev, flags); 677a56bb8a5SSatoshi Asami #endif 678a56bb8a5SSatoshi Asami 679a56bb8a5SSatoshi Asami if (unit >= numccd) 680a56bb8a5SSatoshi Asami return (ENXIO); 681a56bb8a5SSatoshi Asami cs = &ccd_softc[unit]; 682a56bb8a5SSatoshi Asami 683a56bb8a5SSatoshi Asami if (error = ccdlock(cs)) 684a56bb8a5SSatoshi Asami return (error); 685a56bb8a5SSatoshi Asami 686d8594dfbSSatoshi Asami part = ccdpart(dev); 687a56bb8a5SSatoshi Asami 688a56bb8a5SSatoshi Asami /* ...that much closer to allowing unconfiguration... */ 689a56bb8a5SSatoshi Asami switch (fmt) { 690a56bb8a5SSatoshi Asami case S_IFCHR: 691a56bb8a5SSatoshi Asami cs->sc_dkdev.dk_copenmask &= ~(1 << part); 692a56bb8a5SSatoshi Asami break; 693a56bb8a5SSatoshi Asami 694a56bb8a5SSatoshi Asami case S_IFBLK: 695a56bb8a5SSatoshi Asami cs->sc_dkdev.dk_bopenmask &= ~(1 << part); 696a56bb8a5SSatoshi Asami break; 697a56bb8a5SSatoshi Asami } 698a56bb8a5SSatoshi Asami cs->sc_dkdev.dk_openmask = 699a56bb8a5SSatoshi Asami cs->sc_dkdev.dk_copenmask | cs->sc_dkdev.dk_bopenmask; 700a56bb8a5SSatoshi Asami 701a56bb8a5SSatoshi Asami ccdunlock(cs); 702a56bb8a5SSatoshi Asami return (0); 703a56bb8a5SSatoshi Asami } 704a56bb8a5SSatoshi Asami 705e2738b4fSPoul-Henning Kamp static void 706a56bb8a5SSatoshi Asami ccdstrategy(bp) 707a56bb8a5SSatoshi Asami register struct buf *bp; 708a56bb8a5SSatoshi Asami { 709a56bb8a5SSatoshi Asami register int unit = ccdunit(bp->b_dev); 710a56bb8a5SSatoshi Asami register struct ccd_softc *cs = &ccd_softc[unit]; 711c23670e2SGary Palmer register int s; 712a56bb8a5SSatoshi Asami int wlabel; 713a56bb8a5SSatoshi Asami struct disklabel *lp; 714a56bb8a5SSatoshi Asami 715a56bb8a5SSatoshi Asami #ifdef DEBUG 716a56bb8a5SSatoshi Asami if (ccddebug & CCDB_FOLLOW) 717a56bb8a5SSatoshi Asami printf("ccdstrategy(%x): unit %d\n", bp, unit); 718a56bb8a5SSatoshi Asami #endif 719a56bb8a5SSatoshi Asami if ((cs->sc_flags & CCDF_INITED) == 0) { 720a56bb8a5SSatoshi Asami bp->b_error = ENXIO; 721a56bb8a5SSatoshi Asami bp->b_flags |= B_ERROR; 722a56bb8a5SSatoshi Asami goto done; 723a56bb8a5SSatoshi Asami } 724a56bb8a5SSatoshi Asami 725a56bb8a5SSatoshi Asami /* If it's a nil transfer, wake up the top half now. */ 726a56bb8a5SSatoshi Asami if (bp->b_bcount == 0) 727a56bb8a5SSatoshi Asami goto done; 728a56bb8a5SSatoshi Asami 729a56bb8a5SSatoshi Asami lp = &cs->sc_dkdev.dk_label; 730a56bb8a5SSatoshi Asami 731a56bb8a5SSatoshi Asami /* 732a56bb8a5SSatoshi Asami * Do bounds checking and adjust transfer. If there's an 733a56bb8a5SSatoshi Asami * error, the bounds check will flag that for us. 734a56bb8a5SSatoshi Asami */ 735a56bb8a5SSatoshi Asami wlabel = cs->sc_flags & (CCDF_WLABEL|CCDF_LABELLING); 736d8594dfbSSatoshi Asami if (ccdpart(bp->b_dev) != RAW_PART) 737a56bb8a5SSatoshi Asami if (bounds_check_with_label(bp, lp, wlabel) <= 0) 738a56bb8a5SSatoshi Asami goto done; 739a56bb8a5SSatoshi Asami 740a56bb8a5SSatoshi Asami bp->b_resid = bp->b_bcount; 741a56bb8a5SSatoshi Asami 742a56bb8a5SSatoshi Asami /* 743a56bb8a5SSatoshi Asami * "Start" the unit. 744a56bb8a5SSatoshi Asami */ 745a56bb8a5SSatoshi Asami s = splbio(); 746a56bb8a5SSatoshi Asami ccdstart(cs, bp); 747a56bb8a5SSatoshi Asami splx(s); 748a56bb8a5SSatoshi Asami return; 749a56bb8a5SSatoshi Asami done: 750a56bb8a5SSatoshi Asami biodone(bp); 751a56bb8a5SSatoshi Asami } 752a56bb8a5SSatoshi Asami 753a56bb8a5SSatoshi Asami static void 754a56bb8a5SSatoshi Asami ccdstart(cs, bp) 755a56bb8a5SSatoshi Asami register struct ccd_softc *cs; 756a56bb8a5SSatoshi Asami register struct buf *bp; 757a56bb8a5SSatoshi Asami { 758a56bb8a5SSatoshi Asami register long bcount, rcount; 7593bc746beSSatoshi Asami struct ccdbuf *cbp[4]; 7603bc746beSSatoshi Asami /* XXX! : 2 reads and 2 writes for RAID 4/5 */ 761a56bb8a5SSatoshi Asami caddr_t addr; 762a56bb8a5SSatoshi Asami daddr_t bn; 763a56bb8a5SSatoshi Asami struct partition *pp; 764a56bb8a5SSatoshi Asami 765a56bb8a5SSatoshi Asami #ifdef DEBUG 766a56bb8a5SSatoshi Asami if (ccddebug & CCDB_FOLLOW) 767a56bb8a5SSatoshi Asami printf("ccdstart(%x, %x)\n", cs, bp); 768a56bb8a5SSatoshi Asami #endif 769a56bb8a5SSatoshi Asami 770a56bb8a5SSatoshi Asami #ifdef WORKING_DISK_STATISTICS /* XXX !! */ 771a56bb8a5SSatoshi Asami /* 772a56bb8a5SSatoshi Asami * Instrumentation (not very meaningful) 773a56bb8a5SSatoshi Asami */ 774a56bb8a5SSatoshi Asami cs->sc_nactive++; 775a56bb8a5SSatoshi Asami if (cs->sc_dk >= 0) { 776a56bb8a5SSatoshi Asami dk_busy |= 1 << cs->sc_dk; 777a56bb8a5SSatoshi Asami dk_xfer[cs->sc_dk]++; 778a56bb8a5SSatoshi Asami dk_wds[cs->sc_dk] += bp->b_bcount >> 6; 779a56bb8a5SSatoshi Asami } 780a56bb8a5SSatoshi Asami #endif 781a56bb8a5SSatoshi Asami 782a56bb8a5SSatoshi Asami /* 783a56bb8a5SSatoshi Asami * Translate the partition-relative block number to an absolute. 784a56bb8a5SSatoshi Asami */ 785a56bb8a5SSatoshi Asami bn = bp->b_blkno; 786d8594dfbSSatoshi Asami if (ccdpart(bp->b_dev) != RAW_PART) { 787d8594dfbSSatoshi Asami pp = &cs->sc_dkdev.dk_label.d_partitions[ccdpart(bp->b_dev)]; 788a56bb8a5SSatoshi Asami bn += pp->p_offset; 789a56bb8a5SSatoshi Asami } 790a56bb8a5SSatoshi Asami 791a56bb8a5SSatoshi Asami /* 792a56bb8a5SSatoshi Asami * Allocate component buffers and fire off the requests 793a56bb8a5SSatoshi Asami */ 794a56bb8a5SSatoshi Asami addr = bp->b_data; 795a56bb8a5SSatoshi Asami for (bcount = bp->b_bcount; bcount > 0; bcount -= rcount) { 7963bc746beSSatoshi Asami ccdbuffer(cbp, cs, bp, bn, addr, bcount); 7973bc746beSSatoshi Asami rcount = cbp[0]->cb_buf.b_bcount; 7983bc746beSSatoshi Asami if ((cbp[0]->cb_buf.b_flags & B_READ) == 0) 7993bc746beSSatoshi Asami cbp[0]->cb_buf.b_vp->v_numoutput++; 8003bc746beSSatoshi Asami VOP_STRATEGY(&cbp[0]->cb_buf); 8013bc746beSSatoshi Asami if (cs->sc_cflags & CCDF_MIRROR && 8023bc746beSSatoshi Asami (cbp[0]->cb_buf.b_flags & B_READ) == 0) { 8033bc746beSSatoshi Asami /* mirror, start another write */ 8043bc746beSSatoshi Asami cbp[1]->cb_buf.b_vp->v_numoutput++; 8053bc746beSSatoshi Asami VOP_STRATEGY(&cbp[1]->cb_buf); 8063bc746beSSatoshi Asami } 807a56bb8a5SSatoshi Asami bn += btodb(rcount); 808a56bb8a5SSatoshi Asami addr += rcount; 809a56bb8a5SSatoshi Asami } 810a56bb8a5SSatoshi Asami } 811a56bb8a5SSatoshi Asami 812a56bb8a5SSatoshi Asami /* 813a56bb8a5SSatoshi Asami * Build a component buffer header. 814a56bb8a5SSatoshi Asami */ 815e2738b4fSPoul-Henning Kamp static void 8163bc746beSSatoshi Asami ccdbuffer(cb, cs, bp, bn, addr, bcount) 8173bc746beSSatoshi Asami register struct ccdbuf **cb; 818a56bb8a5SSatoshi Asami register struct ccd_softc *cs; 819a56bb8a5SSatoshi Asami struct buf *bp; 820a56bb8a5SSatoshi Asami daddr_t bn; 821a56bb8a5SSatoshi Asami caddr_t addr; 822a56bb8a5SSatoshi Asami long bcount; 823a56bb8a5SSatoshi Asami { 824e2a13e8cSSatoshi Asami register struct ccdcinfo *ci, *ci2 = NULL; /* XXX */ 825a56bb8a5SSatoshi Asami register struct ccdbuf *cbp; 826a56bb8a5SSatoshi Asami register daddr_t cbn, cboff; 827a56bb8a5SSatoshi Asami 828a56bb8a5SSatoshi Asami #ifdef DEBUG 829a56bb8a5SSatoshi Asami if (ccddebug & CCDB_IO) 830a56bb8a5SSatoshi Asami printf("ccdbuffer(%x, %x, %d, %x, %d)\n", 831a56bb8a5SSatoshi Asami cs, bp, bn, addr, bcount); 832a56bb8a5SSatoshi Asami #endif 833a56bb8a5SSatoshi Asami /* 834a56bb8a5SSatoshi Asami * Determine which component bn falls in. 835a56bb8a5SSatoshi Asami */ 836a56bb8a5SSatoshi Asami cbn = bn; 837a56bb8a5SSatoshi Asami cboff = 0; 838a56bb8a5SSatoshi Asami 839a56bb8a5SSatoshi Asami /* 840a56bb8a5SSatoshi Asami * Serially concatenated 841a56bb8a5SSatoshi Asami */ 842a56bb8a5SSatoshi Asami if (cs->sc_ileave == 0) { 843a56bb8a5SSatoshi Asami register daddr_t sblk; 844a56bb8a5SSatoshi Asami 845a56bb8a5SSatoshi Asami sblk = 0; 846a56bb8a5SSatoshi Asami for (ci = cs->sc_cinfo; cbn >= sblk + ci->ci_size; ci++) 847a56bb8a5SSatoshi Asami sblk += ci->ci_size; 848a56bb8a5SSatoshi Asami cbn -= sblk; 849a56bb8a5SSatoshi Asami } 850a56bb8a5SSatoshi Asami /* 851a56bb8a5SSatoshi Asami * Interleaved 852a56bb8a5SSatoshi Asami */ 853a56bb8a5SSatoshi Asami else { 854a56bb8a5SSatoshi Asami register struct ccdiinfo *ii; 855a56bb8a5SSatoshi Asami int ccdisk, off; 856a56bb8a5SSatoshi Asami 857a56bb8a5SSatoshi Asami cboff = cbn % cs->sc_ileave; 858a56bb8a5SSatoshi Asami cbn /= cs->sc_ileave; 859a56bb8a5SSatoshi Asami for (ii = cs->sc_itable; ii->ii_ndisk; ii++) 860a56bb8a5SSatoshi Asami if (ii->ii_startblk > cbn) 861a56bb8a5SSatoshi Asami break; 862a56bb8a5SSatoshi Asami ii--; 863a56bb8a5SSatoshi Asami off = cbn - ii->ii_startblk; 864a56bb8a5SSatoshi Asami if (ii->ii_ndisk == 1) { 865a56bb8a5SSatoshi Asami ccdisk = ii->ii_index[0]; 866a56bb8a5SSatoshi Asami cbn = ii->ii_startoff + off; 867a56bb8a5SSatoshi Asami } else { 86809b59204SSatoshi Asami if (cs->sc_cflags & CCDF_MIRROR) { 86909b59204SSatoshi Asami ccdisk = ii->ii_index[off % (ii->ii_ndisk/2)]; 87009b59204SSatoshi Asami cbn = ii->ii_startoff + off / (ii->ii_ndisk/2); 8713bc746beSSatoshi Asami /* mirrored data */ 8723bc746beSSatoshi Asami ci2 = &cs->sc_cinfo[ccdisk + ii->ii_ndisk/2]; 87309b59204SSatoshi Asami } 87409b59204SSatoshi Asami else if (cs->sc_cflags & CCDF_PARITY) { 8757ecb65faSSatoshi Asami ccdisk = ii->ii_index[off % (ii->ii_ndisk-1)]; 8767ecb65faSSatoshi Asami cbn = ii->ii_startoff + off / (ii->ii_ndisk-1); 8777ecb65faSSatoshi Asami if (cbn % ii->ii_ndisk <= ccdisk) 8787ecb65faSSatoshi Asami ccdisk++; 8797ecb65faSSatoshi Asami } 8807ecb65faSSatoshi Asami else { 881a56bb8a5SSatoshi Asami ccdisk = ii->ii_index[off % ii->ii_ndisk]; 882a56bb8a5SSatoshi Asami cbn = ii->ii_startoff + off / ii->ii_ndisk; 883a56bb8a5SSatoshi Asami } 8847ecb65faSSatoshi Asami } 885a56bb8a5SSatoshi Asami cbn *= cs->sc_ileave; 886a56bb8a5SSatoshi Asami ci = &cs->sc_cinfo[ccdisk]; 887a56bb8a5SSatoshi Asami } 888a56bb8a5SSatoshi Asami 889a56bb8a5SSatoshi Asami /* 890a56bb8a5SSatoshi Asami * Fill in the component buf structure. 891a56bb8a5SSatoshi Asami */ 892a56bb8a5SSatoshi Asami cbp = getccdbuf(); 893a56bb8a5SSatoshi Asami cbp->cb_buf.b_flags = bp->b_flags | B_CALL; 894e2a13e8cSSatoshi Asami cbp->cb_buf.b_iodone = (void (*)(struct buf *))ccdiodone; 895a56bb8a5SSatoshi Asami cbp->cb_buf.b_proc = bp->b_proc; 896a56bb8a5SSatoshi Asami cbp->cb_buf.b_dev = ci->ci_dev; /* XXX */ 8970d88ef07SSatoshi Asami cbp->cb_buf.b_blkno = cbn + cboff + CCD_OFFSET; 898a56bb8a5SSatoshi Asami cbp->cb_buf.b_data = addr; 899a56bb8a5SSatoshi Asami cbp->cb_buf.b_vp = ci->ci_vp; 900a56bb8a5SSatoshi Asami if (cs->sc_ileave == 0) 901a56bb8a5SSatoshi Asami cbp->cb_buf.b_bcount = dbtob(ci->ci_size - cbn); 902a56bb8a5SSatoshi Asami else 903a56bb8a5SSatoshi Asami cbp->cb_buf.b_bcount = dbtob(cs->sc_ileave - cboff); 904a56bb8a5SSatoshi Asami if (cbp->cb_buf.b_bcount > bcount) 905a56bb8a5SSatoshi Asami cbp->cb_buf.b_bcount = bcount; 906a56bb8a5SSatoshi Asami 907c0b89506SJohn Dyson cbp->cb_buf.b_bufsize = cbp->cb_buf.b_bcount; 908c0b89506SJohn Dyson 909a56bb8a5SSatoshi Asami /* 910a56bb8a5SSatoshi Asami * context for ccdiodone 911a56bb8a5SSatoshi Asami */ 912a56bb8a5SSatoshi Asami cbp->cb_obp = bp; 913a56bb8a5SSatoshi Asami cbp->cb_unit = cs - ccd_softc; 914a56bb8a5SSatoshi Asami cbp->cb_comp = ci - cs->sc_cinfo; 915a56bb8a5SSatoshi Asami 916a56bb8a5SSatoshi Asami #ifdef DEBUG 917a56bb8a5SSatoshi Asami if (ccddebug & CCDB_IO) 918a56bb8a5SSatoshi Asami printf(" dev %x(u%d): cbp %x bn %d addr %x bcnt %d\n", 919a56bb8a5SSatoshi Asami ci->ci_dev, ci-cs->sc_cinfo, cbp, cbp->cb_buf.b_blkno, 920a56bb8a5SSatoshi Asami cbp->cb_buf.b_data, cbp->cb_buf.b_bcount); 921a56bb8a5SSatoshi Asami #endif 9223bc746beSSatoshi Asami cb[0] = cbp; 9233bc746beSSatoshi Asami if (cs->sc_cflags & CCDF_MIRROR && 9243bc746beSSatoshi Asami (cbp->cb_buf.b_flags & B_READ) == 0) { 9253bc746beSSatoshi Asami /* mirror, start one more write */ 9263bc746beSSatoshi Asami cbp = getccdbuf(); 9273bc746beSSatoshi Asami *cbp = *cb[0]; 9283bc746beSSatoshi Asami cbp->cb_buf.b_dev = ci2->ci_dev; 9293bc746beSSatoshi Asami cbp->cb_buf.b_vp = ci2->ci_vp; 9303bc746beSSatoshi Asami cbp->cb_comp = ci2 - cs->sc_cinfo; 9313bc746beSSatoshi Asami cb[1] = cbp; 932e7322872SSatoshi Asami /* link together the ccdbuf's and clear "mirror done" flag */ 933e7322872SSatoshi Asami cb[0]->cb_mirror = cb[1]; 934e7322872SSatoshi Asami cb[1]->cb_mirror = cb[0]; 935e7322872SSatoshi Asami cb[0]->cb_pflags &= ~CCDPF_MIRROR_DONE; 936e7322872SSatoshi Asami cb[1]->cb_pflags &= ~CCDPF_MIRROR_DONE; 9373bc746beSSatoshi Asami } 938a56bb8a5SSatoshi Asami } 939a56bb8a5SSatoshi Asami 940a56bb8a5SSatoshi Asami static void 941a56bb8a5SSatoshi Asami ccdintr(cs, bp) 942a56bb8a5SSatoshi Asami register struct ccd_softc *cs; 943a56bb8a5SSatoshi Asami register struct buf *bp; 944a56bb8a5SSatoshi Asami { 945a56bb8a5SSatoshi Asami 946a56bb8a5SSatoshi Asami #ifdef DEBUG 947a56bb8a5SSatoshi Asami if (ccddebug & CCDB_FOLLOW) 948a56bb8a5SSatoshi Asami printf("ccdintr(%x, %x)\n", cs, bp); 949a56bb8a5SSatoshi Asami #endif 950a56bb8a5SSatoshi Asami /* 951a56bb8a5SSatoshi Asami * Request is done for better or worse, wakeup the top half. 952a56bb8a5SSatoshi Asami */ 953a56bb8a5SSatoshi Asami #ifdef WORKING_DISK_STATISTICS /* XXX !! */ 954a56bb8a5SSatoshi Asami --cs->sc_nactive; 955a56bb8a5SSatoshi Asami #ifdef DIAGNOSTIC 956a56bb8a5SSatoshi Asami if (cs->sc_nactive < 0) 957a56bb8a5SSatoshi Asami panic("ccdintr: ccd%d: sc_nactive < 0", cs->sc_unit); 958a56bb8a5SSatoshi Asami #endif 959a56bb8a5SSatoshi Asami 960a56bb8a5SSatoshi Asami if (cs->sc_nactive == 0 && cs->sc_dk >= 0) 961a56bb8a5SSatoshi Asami dk_busy &= ~(1 << cs->sc_dk); 962a56bb8a5SSatoshi Asami #endif 963a56bb8a5SSatoshi Asami if (bp->b_flags & B_ERROR) 964a56bb8a5SSatoshi Asami bp->b_resid = bp->b_bcount; 965a56bb8a5SSatoshi Asami biodone(bp); 966a56bb8a5SSatoshi Asami } 967a56bb8a5SSatoshi Asami 968a56bb8a5SSatoshi Asami /* 969a56bb8a5SSatoshi Asami * Called at interrupt time. 970a56bb8a5SSatoshi Asami * Mark the component as done and if all components are done, 971a56bb8a5SSatoshi Asami * take a ccd interrupt. 972a56bb8a5SSatoshi Asami */ 973e2738b4fSPoul-Henning Kamp static void 974a56bb8a5SSatoshi Asami ccdiodone(cbp) 975a56bb8a5SSatoshi Asami struct ccdbuf *cbp; 976a56bb8a5SSatoshi Asami { 977a56bb8a5SSatoshi Asami register struct buf *bp = cbp->cb_obp; 978a56bb8a5SSatoshi Asami register int unit = cbp->cb_unit; 979a56bb8a5SSatoshi Asami int count, s; 980a56bb8a5SSatoshi Asami 981a56bb8a5SSatoshi Asami s = splbio(); 982a56bb8a5SSatoshi Asami #ifdef DEBUG 983a56bb8a5SSatoshi Asami if (ccddebug & CCDB_FOLLOW) 984a56bb8a5SSatoshi Asami printf("ccdiodone(%x)\n", cbp); 985a56bb8a5SSatoshi Asami if (ccddebug & CCDB_IO) { 986a56bb8a5SSatoshi Asami printf("ccdiodone: bp %x bcount %d resid %d\n", 987a56bb8a5SSatoshi Asami bp, bp->b_bcount, bp->b_resid); 988a56bb8a5SSatoshi Asami printf(" dev %x(u%d), cbp %x bn %d addr %x bcnt %d\n", 989a56bb8a5SSatoshi Asami cbp->cb_buf.b_dev, cbp->cb_comp, cbp, 990a56bb8a5SSatoshi Asami cbp->cb_buf.b_blkno, cbp->cb_buf.b_data, 991a56bb8a5SSatoshi Asami cbp->cb_buf.b_bcount); 992a56bb8a5SSatoshi Asami } 993a56bb8a5SSatoshi Asami #endif 994a56bb8a5SSatoshi Asami 995a56bb8a5SSatoshi Asami if (cbp->cb_buf.b_flags & B_ERROR) { 996a56bb8a5SSatoshi Asami bp->b_flags |= B_ERROR; 997a56bb8a5SSatoshi Asami bp->b_error = cbp->cb_buf.b_error ? cbp->cb_buf.b_error : EIO; 998a56bb8a5SSatoshi Asami #ifdef DEBUG 999a56bb8a5SSatoshi Asami printf("ccd%d: error %d on component %d\n", 1000a56bb8a5SSatoshi Asami unit, bp->b_error, cbp->cb_comp); 1001a56bb8a5SSatoshi Asami #endif 1002a56bb8a5SSatoshi Asami } 1003e7322872SSatoshi Asami 1004e7322872SSatoshi Asami if (ccd_softc[unit].sc_cflags & CCDF_MIRROR && 1005e7322872SSatoshi Asami (cbp->cb_buf.b_flags & B_READ) == 0) 1006e7322872SSatoshi Asami if ((cbp->cb_pflags & CCDPF_MIRROR_DONE) == 0) { 1007e7322872SSatoshi Asami /* I'm done before my counterpart, so just set 1008e7322872SSatoshi Asami partner's flag and return */ 1009e7322872SSatoshi Asami cbp->cb_mirror->cb_pflags |= CCDPF_MIRROR_DONE; 1010e7322872SSatoshi Asami putccdbuf(cbp); 1011e7322872SSatoshi Asami splx(s); 1012e7322872SSatoshi Asami return; 1013e7322872SSatoshi Asami } 1014e7322872SSatoshi Asami 1015a56bb8a5SSatoshi Asami count = cbp->cb_buf.b_bcount; 1016a56bb8a5SSatoshi Asami putccdbuf(cbp); 1017a56bb8a5SSatoshi Asami 1018a56bb8a5SSatoshi Asami /* 1019a56bb8a5SSatoshi Asami * If all done, "interrupt". 1020a56bb8a5SSatoshi Asami */ 1021a56bb8a5SSatoshi Asami bp->b_resid -= count; 1022a56bb8a5SSatoshi Asami if (bp->b_resid < 0) 1023a56bb8a5SSatoshi Asami panic("ccdiodone: count"); 1024a56bb8a5SSatoshi Asami if (bp->b_resid == 0) 1025a56bb8a5SSatoshi Asami ccdintr(&ccd_softc[unit], bp); 1026a56bb8a5SSatoshi Asami splx(s); 1027a56bb8a5SSatoshi Asami } 1028a56bb8a5SSatoshi Asami 1029e2738b4fSPoul-Henning Kamp static int 1030a56bb8a5SSatoshi Asami ccdioctl(dev, cmd, data, flag, p) 1031a56bb8a5SSatoshi Asami dev_t dev; 1032d8594dfbSSatoshi Asami int cmd; 1033a56bb8a5SSatoshi Asami caddr_t data; 1034a56bb8a5SSatoshi Asami int flag; 1035a56bb8a5SSatoshi Asami struct proc *p; 1036a56bb8a5SSatoshi Asami { 1037a56bb8a5SSatoshi Asami int unit = ccdunit(dev); 1038a56bb8a5SSatoshi Asami int i, j, lookedup = 0, error = 0; 1039a56bb8a5SSatoshi Asami int part, pmask, s; 1040a56bb8a5SSatoshi Asami struct ccd_softc *cs; 1041a56bb8a5SSatoshi Asami struct ccd_ioctl *ccio = (struct ccd_ioctl *)data; 1042a56bb8a5SSatoshi Asami struct ccddevice ccd; 1043a56bb8a5SSatoshi Asami char **cpp; 1044a56bb8a5SSatoshi Asami struct vnode **vpp; 1045a56bb8a5SSatoshi Asami #ifdef WORKING_DISK_STATISTICS /* XXX !! */ 1046a56bb8a5SSatoshi Asami extern int dkn; 1047a56bb8a5SSatoshi Asami #endif 1048a56bb8a5SSatoshi Asami 1049a56bb8a5SSatoshi Asami if (unit >= numccd) 1050a56bb8a5SSatoshi Asami return (ENXIO); 1051a56bb8a5SSatoshi Asami cs = &ccd_softc[unit]; 1052a56bb8a5SSatoshi Asami 1053a56bb8a5SSatoshi Asami bzero(&ccd, sizeof(ccd)); 1054a56bb8a5SSatoshi Asami 1055a56bb8a5SSatoshi Asami switch (cmd) { 1056a56bb8a5SSatoshi Asami case CCDIOCSET: 1057a56bb8a5SSatoshi Asami if (cs->sc_flags & CCDF_INITED) 1058a56bb8a5SSatoshi Asami return (EBUSY); 1059a56bb8a5SSatoshi Asami 1060a56bb8a5SSatoshi Asami if ((flag & FWRITE) == 0) 1061a56bb8a5SSatoshi Asami return (EBADF); 1062a56bb8a5SSatoshi Asami 1063a56bb8a5SSatoshi Asami if (error = ccdlock(cs)) 1064a56bb8a5SSatoshi Asami return (error); 1065a56bb8a5SSatoshi Asami 1066a56bb8a5SSatoshi Asami /* Fill in some important bits. */ 1067a56bb8a5SSatoshi Asami ccd.ccd_unit = unit; 1068a56bb8a5SSatoshi Asami ccd.ccd_interleave = ccio->ccio_ileave; 1069b8e29b55SSatoshi Asami if (ccd.ccd_interleave == 0 && 1070b8e29b55SSatoshi Asami ((ccio->ccio_flags & CCDF_MIRROR) || 1071b8e29b55SSatoshi Asami (ccio->ccio_flags & CCDF_PARITY))) { 1072b8e29b55SSatoshi Asami printf("ccd%d: disabling mirror/parity, interleave is 0\n", unit); 1073b8e29b55SSatoshi Asami ccio->ccio_flags &= ~(CCDF_MIRROR | CCDF_PARITY); 1074b8e29b55SSatoshi Asami } 107509b59204SSatoshi Asami if ((ccio->ccio_flags & CCDF_MIRROR) && 107609b59204SSatoshi Asami (ccio->ccio_flags & CCDF_PARITY)) { 107709b59204SSatoshi Asami printf("ccd%d: can't specify both mirror and parity, using mirror\n", unit); 107809b59204SSatoshi Asami ccio->ccio_flags &= ~CCDF_PARITY; 107909b59204SSatoshi Asami } 108009b59204SSatoshi Asami if ((ccio->ccio_flags & (CCDF_MIRROR | CCDF_PARITY)) && 10817ecb65faSSatoshi Asami !(ccio->ccio_flags & CCDF_UNIFORM)) { 108209b59204SSatoshi Asami printf("ccd%d: mirror/parity forces uniform flag\n", 108309b59204SSatoshi Asami unit); 10847ecb65faSSatoshi Asami ccio->ccio_flags |= CCDF_UNIFORM; 10857ecb65faSSatoshi Asami } 1086a56bb8a5SSatoshi Asami ccd.ccd_flags = ccio->ccio_flags & CCDF_USERMASK; 1087a56bb8a5SSatoshi Asami 1088a56bb8a5SSatoshi Asami /* 1089a56bb8a5SSatoshi Asami * Allocate space for and copy in the array of 1090a56bb8a5SSatoshi Asami * componet pathnames and device numbers. 1091a56bb8a5SSatoshi Asami */ 1092a56bb8a5SSatoshi Asami cpp = malloc(ccio->ccio_ndisks * sizeof(char *), 1093a56bb8a5SSatoshi Asami M_DEVBUF, M_WAITOK); 1094a56bb8a5SSatoshi Asami vpp = malloc(ccio->ccio_ndisks * sizeof(struct vnode *), 1095a56bb8a5SSatoshi Asami M_DEVBUF, M_WAITOK); 1096a56bb8a5SSatoshi Asami 1097a56bb8a5SSatoshi Asami error = copyin((caddr_t)ccio->ccio_disks, (caddr_t)cpp, 1098a56bb8a5SSatoshi Asami ccio->ccio_ndisks * sizeof(char **)); 1099a56bb8a5SSatoshi Asami if (error) { 1100a56bb8a5SSatoshi Asami free(vpp, M_DEVBUF); 1101a56bb8a5SSatoshi Asami free(cpp, M_DEVBUF); 1102a56bb8a5SSatoshi Asami ccdunlock(cs); 1103a56bb8a5SSatoshi Asami return (error); 1104a56bb8a5SSatoshi Asami } 1105a56bb8a5SSatoshi Asami 1106a56bb8a5SSatoshi Asami #ifdef DEBUG 1107a56bb8a5SSatoshi Asami if (ccddebug & CCDB_INIT) 1108a56bb8a5SSatoshi Asami for (i = 0; i < ccio->ccio_ndisks; ++i) 1109a56bb8a5SSatoshi Asami printf("ccdioctl: component %d: 0x%x\n", 1110a56bb8a5SSatoshi Asami i, cpp[i]); 1111a56bb8a5SSatoshi Asami #endif 1112a56bb8a5SSatoshi Asami 1113a56bb8a5SSatoshi Asami for (i = 0; i < ccio->ccio_ndisks; ++i) { 1114a56bb8a5SSatoshi Asami #ifdef DEBUG 1115a56bb8a5SSatoshi Asami if (ccddebug & CCDB_INIT) 1116a56bb8a5SSatoshi Asami printf("ccdioctl: lookedup = %d\n", lookedup); 1117a56bb8a5SSatoshi Asami #endif 1118a56bb8a5SSatoshi Asami if (error = ccdlookup(cpp[i], p, &vpp[i])) { 1119a56bb8a5SSatoshi Asami for (j = 0; j < lookedup; ++j) 1120a56bb8a5SSatoshi Asami (void)vn_close(vpp[j], FREAD|FWRITE, 1121a56bb8a5SSatoshi Asami p->p_ucred, p); 1122a56bb8a5SSatoshi Asami free(vpp, M_DEVBUF); 1123a56bb8a5SSatoshi Asami free(cpp, M_DEVBUF); 1124a56bb8a5SSatoshi Asami ccdunlock(cs); 1125a56bb8a5SSatoshi Asami return (error); 1126a56bb8a5SSatoshi Asami } 1127a56bb8a5SSatoshi Asami ++lookedup; 1128a56bb8a5SSatoshi Asami } 1129a56bb8a5SSatoshi Asami ccd.ccd_cpp = cpp; 1130a56bb8a5SSatoshi Asami ccd.ccd_vpp = vpp; 1131a56bb8a5SSatoshi Asami ccd.ccd_ndev = ccio->ccio_ndisks; 1132a56bb8a5SSatoshi Asami 1133a56bb8a5SSatoshi Asami #ifdef WORKING_DISK_STATISTICS /* XXX !! */ 1134a56bb8a5SSatoshi Asami /* 1135a56bb8a5SSatoshi Asami * Assign disk index first so that init routine 1136a56bb8a5SSatoshi Asami * can use it (saves having the driver drag around 1137a56bb8a5SSatoshi Asami * the ccddevice pointer just to set up the dk_* 1138a56bb8a5SSatoshi Asami * info in the open routine). 1139a56bb8a5SSatoshi Asami */ 1140a56bb8a5SSatoshi Asami if (dkn < DK_NDRIVE) 1141a56bb8a5SSatoshi Asami ccd.ccd_dk = dkn++; 1142a56bb8a5SSatoshi Asami else 1143a56bb8a5SSatoshi Asami ccd.ccd_dk = -1; 1144a56bb8a5SSatoshi Asami #endif 1145a56bb8a5SSatoshi Asami 1146a56bb8a5SSatoshi Asami /* 1147a56bb8a5SSatoshi Asami * Initialize the ccd. Fills in the softc for us. 1148a56bb8a5SSatoshi Asami */ 1149a56bb8a5SSatoshi Asami if (error = ccdinit(&ccd, cpp, p)) { 1150a56bb8a5SSatoshi Asami #ifdef WORKING_DISK_STATISTICS /* XXX !! */ 1151a56bb8a5SSatoshi Asami if (ccd.ccd_dk >= 0) 1152a56bb8a5SSatoshi Asami --dkn; 1153a56bb8a5SSatoshi Asami #endif 1154a56bb8a5SSatoshi Asami for (j = 0; j < lookedup; ++j) 1155a56bb8a5SSatoshi Asami (void)vn_close(vpp[j], FREAD|FWRITE, 1156a56bb8a5SSatoshi Asami p->p_ucred, p); 1157a56bb8a5SSatoshi Asami bzero(&ccd_softc[unit], sizeof(struct ccd_softc)); 1158a56bb8a5SSatoshi Asami free(vpp, M_DEVBUF); 1159a56bb8a5SSatoshi Asami free(cpp, M_DEVBUF); 1160a56bb8a5SSatoshi Asami ccdunlock(cs); 1161a56bb8a5SSatoshi Asami return (error); 1162a56bb8a5SSatoshi Asami } 1163a56bb8a5SSatoshi Asami 1164a56bb8a5SSatoshi Asami /* 1165a56bb8a5SSatoshi Asami * The ccd has been successfully initialized, so 1166a56bb8a5SSatoshi Asami * we can place it into the array and read the disklabel. 1167a56bb8a5SSatoshi Asami */ 1168a56bb8a5SSatoshi Asami bcopy(&ccd, &ccddevs[unit], sizeof(ccd)); 1169a56bb8a5SSatoshi Asami ccio->ccio_unit = unit; 1170a56bb8a5SSatoshi Asami ccio->ccio_size = cs->sc_size; 1171a56bb8a5SSatoshi Asami ccdgetdisklabel(dev); 1172a56bb8a5SSatoshi Asami 1173a56bb8a5SSatoshi Asami ccdunlock(cs); 1174a56bb8a5SSatoshi Asami 1175a56bb8a5SSatoshi Asami break; 1176a56bb8a5SSatoshi Asami 1177a56bb8a5SSatoshi Asami case CCDIOCCLR: 1178a56bb8a5SSatoshi Asami if ((cs->sc_flags & CCDF_INITED) == 0) 1179a56bb8a5SSatoshi Asami return (ENXIO); 1180a56bb8a5SSatoshi Asami 1181a56bb8a5SSatoshi Asami if ((flag & FWRITE) == 0) 1182a56bb8a5SSatoshi Asami return (EBADF); 1183a56bb8a5SSatoshi Asami 1184a56bb8a5SSatoshi Asami if (error = ccdlock(cs)) 1185a56bb8a5SSatoshi Asami return (error); 1186a56bb8a5SSatoshi Asami 1187a56bb8a5SSatoshi Asami /* 1188a56bb8a5SSatoshi Asami * Don't unconfigure if any other partitions are open 1189a56bb8a5SSatoshi Asami * or if both the character and block flavors of this 1190a56bb8a5SSatoshi Asami * partition are open. 1191a56bb8a5SSatoshi Asami */ 1192d8594dfbSSatoshi Asami part = ccdpart(dev); 1193a56bb8a5SSatoshi Asami pmask = (1 << part); 1194a56bb8a5SSatoshi Asami if ((cs->sc_dkdev.dk_openmask & ~pmask) || 1195a56bb8a5SSatoshi Asami ((cs->sc_dkdev.dk_bopenmask & pmask) && 1196a56bb8a5SSatoshi Asami (cs->sc_dkdev.dk_copenmask & pmask))) { 1197a56bb8a5SSatoshi Asami ccdunlock(cs); 1198a56bb8a5SSatoshi Asami return (EBUSY); 1199a56bb8a5SSatoshi Asami } 1200a56bb8a5SSatoshi Asami 1201a56bb8a5SSatoshi Asami /* 1202a56bb8a5SSatoshi Asami * Free ccd_softc information and clear entry. 1203a56bb8a5SSatoshi Asami */ 1204a56bb8a5SSatoshi Asami 1205a56bb8a5SSatoshi Asami /* Close the components and free their pathnames. */ 1206a56bb8a5SSatoshi Asami for (i = 0; i < cs->sc_nccdisks; ++i) { 1207a56bb8a5SSatoshi Asami /* 1208a56bb8a5SSatoshi Asami * XXX: this close could potentially fail and 1209a56bb8a5SSatoshi Asami * cause Bad Things. Maybe we need to force 1210a56bb8a5SSatoshi Asami * the close to happen? 1211a56bb8a5SSatoshi Asami */ 1212a56bb8a5SSatoshi Asami #ifdef DEBUG 1213a56bb8a5SSatoshi Asami if (ccddebug & CCDB_VNODE) 1214a56bb8a5SSatoshi Asami vprint("CCDIOCCLR: vnode info", 1215a56bb8a5SSatoshi Asami cs->sc_cinfo[i].ci_vp); 1216a56bb8a5SSatoshi Asami #endif 1217a56bb8a5SSatoshi Asami (void)vn_close(cs->sc_cinfo[i].ci_vp, FREAD|FWRITE, 1218a56bb8a5SSatoshi Asami p->p_ucred, p); 1219a56bb8a5SSatoshi Asami free(cs->sc_cinfo[i].ci_path, M_DEVBUF); 1220a56bb8a5SSatoshi Asami } 1221a56bb8a5SSatoshi Asami 1222a56bb8a5SSatoshi Asami /* Free interleave index. */ 1223a56bb8a5SSatoshi Asami for (i = 0; cs->sc_itable[i].ii_ndisk; ++i) 1224a56bb8a5SSatoshi Asami free(cs->sc_itable[i].ii_index, M_DEVBUF); 1225a56bb8a5SSatoshi Asami 1226a56bb8a5SSatoshi Asami /* Free component info and interleave table. */ 1227a56bb8a5SSatoshi Asami free(cs->sc_cinfo, M_DEVBUF); 1228a56bb8a5SSatoshi Asami free(cs->sc_itable, M_DEVBUF); 1229a56bb8a5SSatoshi Asami cs->sc_flags &= ~CCDF_INITED; 1230a56bb8a5SSatoshi Asami 1231a56bb8a5SSatoshi Asami /* 1232a56bb8a5SSatoshi Asami * Free ccddevice information and clear entry. 1233a56bb8a5SSatoshi Asami */ 1234a56bb8a5SSatoshi Asami free(ccddevs[unit].ccd_cpp, M_DEVBUF); 1235a56bb8a5SSatoshi Asami free(ccddevs[unit].ccd_vpp, M_DEVBUF); 1236a56bb8a5SSatoshi Asami ccd.ccd_dk = -1; 1237a56bb8a5SSatoshi Asami bcopy(&ccd, &ccddevs[unit], sizeof(ccd)); 1238a56bb8a5SSatoshi Asami 1239a56bb8a5SSatoshi Asami /* This must be atomic. */ 1240a56bb8a5SSatoshi Asami s = splhigh(); 1241a56bb8a5SSatoshi Asami ccdunlock(cs); 1242a56bb8a5SSatoshi Asami bzero(cs, sizeof(struct ccd_softc)); 1243a56bb8a5SSatoshi Asami splx(s); 1244a56bb8a5SSatoshi Asami 1245a56bb8a5SSatoshi Asami break; 1246a56bb8a5SSatoshi Asami 1247a56bb8a5SSatoshi Asami case DIOCGDINFO: 1248a56bb8a5SSatoshi Asami if ((cs->sc_flags & CCDF_INITED) == 0) 1249a56bb8a5SSatoshi Asami return (ENXIO); 1250a56bb8a5SSatoshi Asami 1251a56bb8a5SSatoshi Asami *(struct disklabel *)data = cs->sc_dkdev.dk_label; 1252a56bb8a5SSatoshi Asami break; 1253a56bb8a5SSatoshi Asami 1254a56bb8a5SSatoshi Asami case DIOCGPART: 1255a56bb8a5SSatoshi Asami if ((cs->sc_flags & CCDF_INITED) == 0) 1256a56bb8a5SSatoshi Asami return (ENXIO); 1257a56bb8a5SSatoshi Asami 1258a56bb8a5SSatoshi Asami ((struct partinfo *)data)->disklab = &cs->sc_dkdev.dk_label; 1259a56bb8a5SSatoshi Asami ((struct partinfo *)data)->part = 1260d8594dfbSSatoshi Asami &cs->sc_dkdev.dk_label.d_partitions[ccdpart(dev)]; 1261a56bb8a5SSatoshi Asami break; 1262a56bb8a5SSatoshi Asami 1263a56bb8a5SSatoshi Asami case DIOCWDINFO: 1264a56bb8a5SSatoshi Asami case DIOCSDINFO: 1265a56bb8a5SSatoshi Asami if ((cs->sc_flags & CCDF_INITED) == 0) 1266a56bb8a5SSatoshi Asami return (ENXIO); 1267a56bb8a5SSatoshi Asami 1268a56bb8a5SSatoshi Asami if ((flag & FWRITE) == 0) 1269a56bb8a5SSatoshi Asami return (EBADF); 1270a56bb8a5SSatoshi Asami 1271a56bb8a5SSatoshi Asami if (error = ccdlock(cs)) 1272a56bb8a5SSatoshi Asami return (error); 1273a56bb8a5SSatoshi Asami 1274a56bb8a5SSatoshi Asami cs->sc_flags |= CCDF_LABELLING; 1275a56bb8a5SSatoshi Asami 1276a56bb8a5SSatoshi Asami error = setdisklabel(&cs->sc_dkdev.dk_label, 1277d8594dfbSSatoshi Asami (struct disklabel *)data, 0); 1278d8594dfbSSatoshi Asami /*, &cs->sc_dkdev.dk_cpulabel); */ 1279a56bb8a5SSatoshi Asami if (error == 0) { 1280a56bb8a5SSatoshi Asami if (cmd == DIOCWDINFO) 1281e2a13e8cSSatoshi Asami error = writedisklabel(CCDLABELDEV(dev), 1282d8594dfbSSatoshi Asami ccdstrategy, &cs->sc_dkdev.dk_label); 1283d8594dfbSSatoshi Asami /* 1284d8594dfbSSatoshi Asami &cs->sc_dkdev.dk_cpulabel); */ 1285a56bb8a5SSatoshi Asami } 1286a56bb8a5SSatoshi Asami 1287a56bb8a5SSatoshi Asami cs->sc_flags &= ~CCDF_LABELLING; 1288a56bb8a5SSatoshi Asami 1289a56bb8a5SSatoshi Asami ccdunlock(cs); 1290a56bb8a5SSatoshi Asami 1291a56bb8a5SSatoshi Asami if (error) 1292a56bb8a5SSatoshi Asami return (error); 1293a56bb8a5SSatoshi Asami break; 1294a56bb8a5SSatoshi Asami 1295a56bb8a5SSatoshi Asami case DIOCWLABEL: 1296a56bb8a5SSatoshi Asami if ((cs->sc_flags & CCDF_INITED) == 0) 1297a56bb8a5SSatoshi Asami return (ENXIO); 1298a56bb8a5SSatoshi Asami 1299a56bb8a5SSatoshi Asami if ((flag & FWRITE) == 0) 1300a56bb8a5SSatoshi Asami return (EBADF); 1301a56bb8a5SSatoshi Asami if (*(int *)data != 0) 1302a56bb8a5SSatoshi Asami cs->sc_flags |= CCDF_WLABEL; 1303a56bb8a5SSatoshi Asami else 1304a56bb8a5SSatoshi Asami cs->sc_flags &= ~CCDF_WLABEL; 1305a56bb8a5SSatoshi Asami break; 1306a56bb8a5SSatoshi Asami 1307a56bb8a5SSatoshi Asami default: 1308a56bb8a5SSatoshi Asami return (ENOTTY); 1309a56bb8a5SSatoshi Asami } 1310a56bb8a5SSatoshi Asami 1311a56bb8a5SSatoshi Asami return (0); 1312a56bb8a5SSatoshi Asami } 1313a56bb8a5SSatoshi Asami 1314e2738b4fSPoul-Henning Kamp static int 1315a56bb8a5SSatoshi Asami ccdsize(dev) 1316a56bb8a5SSatoshi Asami dev_t dev; 1317a56bb8a5SSatoshi Asami { 1318a56bb8a5SSatoshi Asami struct ccd_softc *cs; 1319a56bb8a5SSatoshi Asami int part, size; 1320a56bb8a5SSatoshi Asami 1321a56bb8a5SSatoshi Asami if (ccdopen(dev, 0, S_IFBLK, curproc)) 1322a56bb8a5SSatoshi Asami return (-1); 1323a56bb8a5SSatoshi Asami 1324a56bb8a5SSatoshi Asami cs = &ccd_softc[ccdunit(dev)]; 1325d8594dfbSSatoshi Asami part = ccdpart(dev); 1326a56bb8a5SSatoshi Asami 1327a56bb8a5SSatoshi Asami if ((cs->sc_flags & CCDF_INITED) == 0) 1328a56bb8a5SSatoshi Asami return (-1); 1329a56bb8a5SSatoshi Asami 1330a56bb8a5SSatoshi Asami if (cs->sc_dkdev.dk_label.d_partitions[part].p_fstype != FS_SWAP) 1331a56bb8a5SSatoshi Asami size = -1; 1332a56bb8a5SSatoshi Asami else 1333a56bb8a5SSatoshi Asami size = cs->sc_dkdev.dk_label.d_partitions[part].p_size; 1334a56bb8a5SSatoshi Asami 1335a56bb8a5SSatoshi Asami if (ccdclose(dev, 0, S_IFBLK, curproc)) 1336a56bb8a5SSatoshi Asami return (-1); 1337a56bb8a5SSatoshi Asami 1338a56bb8a5SSatoshi Asami return (size); 1339a56bb8a5SSatoshi Asami } 1340a56bb8a5SSatoshi Asami 1341e2738b4fSPoul-Henning Kamp static int 1342e2a13e8cSSatoshi Asami ccddump(dev) 1343a56bb8a5SSatoshi Asami dev_t dev; 1344a56bb8a5SSatoshi Asami { 1345a56bb8a5SSatoshi Asami 1346a56bb8a5SSatoshi Asami /* Not implemented. */ 1347a56bb8a5SSatoshi Asami return ENXIO; 1348a56bb8a5SSatoshi Asami } 1349a56bb8a5SSatoshi Asami 1350a56bb8a5SSatoshi Asami /* 1351a56bb8a5SSatoshi Asami * Lookup the provided name in the filesystem. If the file exists, 1352a56bb8a5SSatoshi Asami * is a valid block device, and isn't being used by anyone else, 1353a56bb8a5SSatoshi Asami * set *vpp to the file's vnode. 1354a56bb8a5SSatoshi Asami */ 1355a56bb8a5SSatoshi Asami static int 1356a56bb8a5SSatoshi Asami ccdlookup(path, p, vpp) 1357a56bb8a5SSatoshi Asami char *path; 1358a56bb8a5SSatoshi Asami struct proc *p; 1359a56bb8a5SSatoshi Asami struct vnode **vpp; /* result */ 1360a56bb8a5SSatoshi Asami { 1361a56bb8a5SSatoshi Asami struct nameidata nd; 1362a56bb8a5SSatoshi Asami struct vnode *vp; 1363a56bb8a5SSatoshi Asami struct vattr va; 1364a56bb8a5SSatoshi Asami int error; 1365a56bb8a5SSatoshi Asami 1366a56bb8a5SSatoshi Asami NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, path, p); 1367a56bb8a5SSatoshi Asami if (error = vn_open(&nd, FREAD|FWRITE, 0)) { 1368a56bb8a5SSatoshi Asami #ifdef DEBUG 1369a56bb8a5SSatoshi Asami if (ccddebug & CCDB_FOLLOW|CCDB_INIT) 1370a56bb8a5SSatoshi Asami printf("ccdlookup: vn_open error = %d\n", error); 1371a56bb8a5SSatoshi Asami #endif 1372a56bb8a5SSatoshi Asami return (error); 1373a56bb8a5SSatoshi Asami } 1374a56bb8a5SSatoshi Asami vp = nd.ni_vp; 1375a56bb8a5SSatoshi Asami 1376a56bb8a5SSatoshi Asami if (vp->v_usecount > 1) { 137706bcc9e5SMike Pritchard VOP_UNLOCK(vp, 0, p); 1378a56bb8a5SSatoshi Asami (void)vn_close(vp, FREAD|FWRITE, p->p_ucred, p); 1379a56bb8a5SSatoshi Asami return (EBUSY); 1380a56bb8a5SSatoshi Asami } 1381a56bb8a5SSatoshi Asami 1382a56bb8a5SSatoshi Asami if (error = VOP_GETATTR(vp, &va, p->p_ucred, p)) { 1383a56bb8a5SSatoshi Asami #ifdef DEBUG 1384a56bb8a5SSatoshi Asami if (ccddebug & CCDB_FOLLOW|CCDB_INIT) 1385a56bb8a5SSatoshi Asami printf("ccdlookup: getattr error = %d\n", error); 1386a56bb8a5SSatoshi Asami #endif 138706bcc9e5SMike Pritchard VOP_UNLOCK(vp, 0, p); 1388a56bb8a5SSatoshi Asami (void)vn_close(vp, FREAD|FWRITE, p->p_ucred, p); 1389a56bb8a5SSatoshi Asami return (error); 1390a56bb8a5SSatoshi Asami } 1391a56bb8a5SSatoshi Asami 1392a56bb8a5SSatoshi Asami /* XXX: eventually we should handle VREG, too. */ 1393a56bb8a5SSatoshi Asami if (va.va_type != VBLK) { 139406bcc9e5SMike Pritchard VOP_UNLOCK(vp, 0, p); 1395a56bb8a5SSatoshi Asami (void)vn_close(vp, FREAD|FWRITE, p->p_ucred, p); 1396a56bb8a5SSatoshi Asami return (ENOTBLK); 1397a56bb8a5SSatoshi Asami } 1398a56bb8a5SSatoshi Asami 1399a56bb8a5SSatoshi Asami #ifdef DEBUG 1400a56bb8a5SSatoshi Asami if (ccddebug & CCDB_VNODE) 1401a56bb8a5SSatoshi Asami vprint("ccdlookup: vnode info", vp); 1402a56bb8a5SSatoshi Asami #endif 1403a56bb8a5SSatoshi Asami 140406bcc9e5SMike Pritchard VOP_UNLOCK(vp, 0, p); 1405a56bb8a5SSatoshi Asami *vpp = vp; 1406a56bb8a5SSatoshi Asami return (0); 1407a56bb8a5SSatoshi Asami } 1408a56bb8a5SSatoshi Asami 1409a56bb8a5SSatoshi Asami /* 1410a56bb8a5SSatoshi Asami * Read the disklabel from the ccd. If one is not present, fake one 1411a56bb8a5SSatoshi Asami * up. 1412a56bb8a5SSatoshi Asami */ 1413a56bb8a5SSatoshi Asami static void 1414a56bb8a5SSatoshi Asami ccdgetdisklabel(dev) 1415a56bb8a5SSatoshi Asami dev_t dev; 1416a56bb8a5SSatoshi Asami { 1417a56bb8a5SSatoshi Asami int unit = ccdunit(dev); 1418a56bb8a5SSatoshi Asami struct ccd_softc *cs = &ccd_softc[unit]; 1419a56bb8a5SSatoshi Asami char *errstring; 1420a56bb8a5SSatoshi Asami struct disklabel *lp = &cs->sc_dkdev.dk_label; 1421a56bb8a5SSatoshi Asami struct ccdgeom *ccg = &cs->sc_geom; 1422a56bb8a5SSatoshi Asami 1423a56bb8a5SSatoshi Asami bzero(lp, sizeof(*lp)); 1424a56bb8a5SSatoshi Asami 1425a56bb8a5SSatoshi Asami lp->d_secperunit = cs->sc_size; 1426a56bb8a5SSatoshi Asami lp->d_secsize = ccg->ccg_secsize; 1427a56bb8a5SSatoshi Asami lp->d_nsectors = ccg->ccg_nsectors; 1428a56bb8a5SSatoshi Asami lp->d_ntracks = ccg->ccg_ntracks; 1429a56bb8a5SSatoshi Asami lp->d_ncylinders = ccg->ccg_ncylinders; 1430a56bb8a5SSatoshi Asami lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors; 1431a56bb8a5SSatoshi Asami 1432a56bb8a5SSatoshi Asami strncpy(lp->d_typename, "ccd", sizeof(lp->d_typename)); 1433a56bb8a5SSatoshi Asami lp->d_type = DTYPE_CCD; 1434a56bb8a5SSatoshi Asami strncpy(lp->d_packname, "fictitious", sizeof(lp->d_packname)); 1435a56bb8a5SSatoshi Asami lp->d_rpm = 3600; 1436a56bb8a5SSatoshi Asami lp->d_interleave = 1; 1437a56bb8a5SSatoshi Asami lp->d_flags = 0; 1438a56bb8a5SSatoshi Asami 1439a56bb8a5SSatoshi Asami lp->d_partitions[RAW_PART].p_offset = 0; 1440a56bb8a5SSatoshi Asami lp->d_partitions[RAW_PART].p_size = cs->sc_size; 1441a56bb8a5SSatoshi Asami lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED; 1442a56bb8a5SSatoshi Asami lp->d_npartitions = RAW_PART + 1; 1443a56bb8a5SSatoshi Asami 1444d8594dfbSSatoshi Asami lp->d_bbsize = BBSIZE; /* XXX */ 1445d8594dfbSSatoshi Asami lp->d_sbsize = SBSIZE; /* XXX */ 1446d8594dfbSSatoshi Asami 1447a56bb8a5SSatoshi Asami lp->d_magic = DISKMAGIC; 1448a56bb8a5SSatoshi Asami lp->d_magic2 = DISKMAGIC; 1449a56bb8a5SSatoshi Asami lp->d_checksum = dkcksum(&cs->sc_dkdev.dk_label); 1450a56bb8a5SSatoshi Asami 1451a56bb8a5SSatoshi Asami /* 1452a56bb8a5SSatoshi Asami * Call the generic disklabel extraction routine. 1453a56bb8a5SSatoshi Asami */ 1454e2a13e8cSSatoshi Asami if (errstring = readdisklabel(CCDLABELDEV(dev), ccdstrategy, 1455c23670e2SGary Palmer &cs->sc_dkdev.dk_label)) 1456a56bb8a5SSatoshi Asami ccdmakedisklabel(cs); 1457a56bb8a5SSatoshi Asami 1458a56bb8a5SSatoshi Asami #ifdef DEBUG 1459a56bb8a5SSatoshi Asami /* It's actually extremely common to have unlabeled ccds. */ 1460a56bb8a5SSatoshi Asami if (ccddebug & CCDB_LABEL) 1461a56bb8a5SSatoshi Asami if (errstring != NULL) 1462a56bb8a5SSatoshi Asami printf("ccd%d: %s\n", unit, errstring); 1463a56bb8a5SSatoshi Asami #endif 1464a56bb8a5SSatoshi Asami } 1465a56bb8a5SSatoshi Asami 1466a56bb8a5SSatoshi Asami /* 1467a56bb8a5SSatoshi Asami * Take care of things one might want to take care of in the event 1468a56bb8a5SSatoshi Asami * that a disklabel isn't present. 1469a56bb8a5SSatoshi Asami */ 1470a56bb8a5SSatoshi Asami static void 1471a56bb8a5SSatoshi Asami ccdmakedisklabel(cs) 1472a56bb8a5SSatoshi Asami struct ccd_softc *cs; 1473a56bb8a5SSatoshi Asami { 1474a56bb8a5SSatoshi Asami struct disklabel *lp = &cs->sc_dkdev.dk_label; 1475a56bb8a5SSatoshi Asami 1476a56bb8a5SSatoshi Asami /* 1477a56bb8a5SSatoshi Asami * For historical reasons, if there's no disklabel present 1478a56bb8a5SSatoshi Asami * the raw partition must be marked FS_BSDFFS. 1479a56bb8a5SSatoshi Asami */ 1480a56bb8a5SSatoshi Asami lp->d_partitions[RAW_PART].p_fstype = FS_BSDFFS; 1481a56bb8a5SSatoshi Asami 1482a56bb8a5SSatoshi Asami strncpy(lp->d_packname, "default label", sizeof(lp->d_packname)); 1483a56bb8a5SSatoshi Asami } 1484a56bb8a5SSatoshi Asami 1485a56bb8a5SSatoshi Asami /* 1486a56bb8a5SSatoshi Asami * Wait interruptibly for an exclusive lock. 1487a56bb8a5SSatoshi Asami * 1488a56bb8a5SSatoshi Asami * XXX 1489a56bb8a5SSatoshi Asami * Several drivers do this; it should be abstracted and made MP-safe. 1490a56bb8a5SSatoshi Asami */ 1491a56bb8a5SSatoshi Asami static int 1492a56bb8a5SSatoshi Asami ccdlock(cs) 1493a56bb8a5SSatoshi Asami struct ccd_softc *cs; 1494a56bb8a5SSatoshi Asami { 1495a56bb8a5SSatoshi Asami int error; 1496a56bb8a5SSatoshi Asami 1497a56bb8a5SSatoshi Asami while ((cs->sc_flags & CCDF_LOCKED) != 0) { 1498a56bb8a5SSatoshi Asami cs->sc_flags |= CCDF_WANTED; 1499a56bb8a5SSatoshi Asami if ((error = tsleep(cs, PRIBIO | PCATCH, "ccdlck", 0)) != 0) 1500a56bb8a5SSatoshi Asami return (error); 1501a56bb8a5SSatoshi Asami } 1502a56bb8a5SSatoshi Asami cs->sc_flags |= CCDF_LOCKED; 1503a56bb8a5SSatoshi Asami return (0); 1504a56bb8a5SSatoshi Asami } 1505a56bb8a5SSatoshi Asami 1506a56bb8a5SSatoshi Asami /* 1507a56bb8a5SSatoshi Asami * Unlock and wake up any waiters. 1508a56bb8a5SSatoshi Asami */ 1509a56bb8a5SSatoshi Asami static void 1510a56bb8a5SSatoshi Asami ccdunlock(cs) 1511a56bb8a5SSatoshi Asami struct ccd_softc *cs; 1512a56bb8a5SSatoshi Asami { 1513a56bb8a5SSatoshi Asami 1514a56bb8a5SSatoshi Asami cs->sc_flags &= ~CCDF_LOCKED; 1515a56bb8a5SSatoshi Asami if ((cs->sc_flags & CCDF_WANTED) != 0) { 1516a56bb8a5SSatoshi Asami cs->sc_flags &= ~CCDF_WANTED; 1517a56bb8a5SSatoshi Asami wakeup(cs); 1518a56bb8a5SSatoshi Asami } 1519a56bb8a5SSatoshi Asami } 1520a56bb8a5SSatoshi Asami 1521a56bb8a5SSatoshi Asami #ifdef DEBUG 1522a56bb8a5SSatoshi Asami static void 1523a56bb8a5SSatoshi Asami printiinfo(ii) 1524a56bb8a5SSatoshi Asami struct ccdiinfo *ii; 1525a56bb8a5SSatoshi Asami { 1526a56bb8a5SSatoshi Asami register int ix, i; 1527a56bb8a5SSatoshi Asami 1528a56bb8a5SSatoshi Asami for (ix = 0; ii->ii_ndisk; ix++, ii++) { 1529a56bb8a5SSatoshi Asami printf(" itab[%d]: #dk %d sblk %d soff %d", 1530a56bb8a5SSatoshi Asami ix, ii->ii_ndisk, ii->ii_startblk, ii->ii_startoff); 1531a56bb8a5SSatoshi Asami for (i = 0; i < ii->ii_ndisk; i++) 1532a56bb8a5SSatoshi Asami printf(" %d", ii->ii_index[i]); 1533a56bb8a5SSatoshi Asami printf("\n"); 1534a56bb8a5SSatoshi Asami } 1535a56bb8a5SSatoshi Asami } 1536a56bb8a5SSatoshi Asami #endif 1537d8594dfbSSatoshi Asami 1538d8594dfbSSatoshi Asami #endif /* NCCD > 0 */ 1539d8594dfbSSatoshi Asami 1540d8594dfbSSatoshi Asami /* Local Variables: */ 1541d8594dfbSSatoshi Asami /* c-argdecl-indent: 8 */ 154209b59204SSatoshi Asami /* c-continued-statement-offset: 8 */ 1543d8594dfbSSatoshi Asami /* c-indent-level: 8 */ 1544d8594dfbSSatoshi Asami /* End: */ 1545