1c0b89506SJohn Dyson /* $Id: ccd.c,v 1.17 1996/09/06 23:06:40 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/errno.h> 101a56bb8a5SSatoshi Asami #include <sys/dkstat.h> 102a56bb8a5SSatoshi Asami #include <sys/buf.h> 103a56bb8a5SSatoshi Asami #include <sys/malloc.h> 104a56bb8a5SSatoshi Asami #include <sys/namei.h> 105a56bb8a5SSatoshi Asami #include <sys/conf.h> 106a56bb8a5SSatoshi Asami #include <sys/stat.h> 107a56bb8a5SSatoshi Asami #include <sys/ioctl.h> 108a56bb8a5SSatoshi Asami #include <sys/disklabel.h> 109d8594dfbSSatoshi Asami #include <ufs/ffs/fs.h> 110a56bb8a5SSatoshi Asami #include <sys/device.h> 111e2a13e8cSSatoshi Asami #undef KERNEL /* XXX */ 112a56bb8a5SSatoshi Asami #include <sys/disk.h> 113e2a13e8cSSatoshi Asami #define KERNEL 114a56bb8a5SSatoshi Asami #include <sys/syslog.h> 115a56bb8a5SSatoshi Asami #include <sys/fcntl.h> 116a56bb8a5SSatoshi Asami #include <sys/vnode.h> 117d8594dfbSSatoshi Asami #include <sys/dkbad.h> 118a56bb8a5SSatoshi Asami 119d8594dfbSSatoshi Asami #include <sys/ccdvar.h> 120a56bb8a5SSatoshi Asami 121a56bb8a5SSatoshi Asami #if defined(CCDDEBUG) && !defined(DEBUG) 122a56bb8a5SSatoshi Asami #define DEBUG 123a56bb8a5SSatoshi Asami #endif 124a56bb8a5SSatoshi Asami 125a56bb8a5SSatoshi Asami #ifdef DEBUG 126a56bb8a5SSatoshi Asami #define CCDB_FOLLOW 0x01 127a56bb8a5SSatoshi Asami #define CCDB_INIT 0x02 128a56bb8a5SSatoshi Asami #define CCDB_IO 0x04 129a56bb8a5SSatoshi Asami #define CCDB_LABEL 0x08 130a56bb8a5SSatoshi Asami #define CCDB_VNODE 0x10 131d8594dfbSSatoshi Asami int ccddebug = CCDB_FOLLOW | CCDB_INIT | CCDB_IO | CCDB_LABEL | CCDB_VNODE; 132d8594dfbSSatoshi Asami #undef DEBUG 133a56bb8a5SSatoshi Asami #endif 134a56bb8a5SSatoshi Asami 135d8594dfbSSatoshi Asami #define ccdunit(x) dkunit(x) 136d8594dfbSSatoshi Asami #define ccdpart(x) dkpart(x) 137a56bb8a5SSatoshi Asami 138e7322872SSatoshi Asami /* 139e7322872SSatoshi Asami This is how mirroring works (only writes are special): 140e7322872SSatoshi Asami 141e7322872SSatoshi Asami When initiating a write, ccdbuffer() returns two "struct ccdbuf *"s 142e7322872SSatoshi Asami linked together by the cb_mirror field. "cb_pflags & 143e7322872SSatoshi Asami CCDPF_MIRROR_DONE" is set to 0 on both of them. 144e7322872SSatoshi Asami 145e7322872SSatoshi Asami When a component returns to ccdiodone(), it checks if "cb_pflags & 146e7322872SSatoshi Asami CCDPF_MIRROR_DONE" is set or not. If not, it sets the partner's 147e7322872SSatoshi Asami flag and returns. If it is, it means its partner has already 148e7322872SSatoshi Asami returned, so it will go to the regular cleanup. 149e7322872SSatoshi Asami 150e7322872SSatoshi Asami */ 151e7322872SSatoshi Asami 152a56bb8a5SSatoshi Asami struct ccdbuf { 153a56bb8a5SSatoshi Asami struct buf cb_buf; /* new I/O buf */ 154a56bb8a5SSatoshi Asami struct buf *cb_obp; /* ptr. to original I/O buf */ 155a56bb8a5SSatoshi Asami int cb_unit; /* target unit */ 156a56bb8a5SSatoshi Asami int cb_comp; /* target component */ 157e7322872SSatoshi Asami int cb_pflags; /* mirror/parity status flag */ 158e7322872SSatoshi Asami struct ccdbuf *cb_mirror; /* mirror counterpart */ 159a56bb8a5SSatoshi Asami }; 160a56bb8a5SSatoshi Asami 161e7322872SSatoshi Asami /* bits in cb_pflags */ 162e7322872SSatoshi Asami #define CCDPF_MIRROR_DONE 1 /* if set, mirror counterpart is done */ 163e7322872SSatoshi Asami 164a56bb8a5SSatoshi Asami #define getccdbuf() \ 165a56bb8a5SSatoshi Asami ((struct ccdbuf *)malloc(sizeof(struct ccdbuf), M_DEVBUF, M_WAITOK)) 166a56bb8a5SSatoshi Asami #define putccdbuf(cbp) \ 167a56bb8a5SSatoshi Asami free((caddr_t)(cbp), M_DEVBUF) 168a56bb8a5SSatoshi Asami 169a56bb8a5SSatoshi Asami #define CCDLABELDEV(dev) \ 170d8594dfbSSatoshi Asami (makedev(major((dev)), dkmakeminor(ccdunit((dev)), 0, RAW_PART))) 171a56bb8a5SSatoshi Asami 172d8594dfbSSatoshi Asami d_open_t ccdopen; 173d8594dfbSSatoshi Asami d_close_t ccdclose; 174d8594dfbSSatoshi Asami d_strategy_t ccdstrategy; 175d8594dfbSSatoshi Asami d_ioctl_t ccdioctl; 176e2a13e8cSSatoshi Asami d_dump_t ccddump; 177e2a13e8cSSatoshi Asami d_psize_t ccdsize; 178d8594dfbSSatoshi Asami d_read_t ccdread; 179d8594dfbSSatoshi Asami d_write_t ccdwrite; 180d8594dfbSSatoshi Asami 181e2a13e8cSSatoshi Asami #define CDEV_MAJOR 74 182e2a13e8cSSatoshi Asami #define BDEV_MAJOR 21 183a56bb8a5SSatoshi Asami 184cba8a5ddSPoul-Henning Kamp static struct cdevsw ccd_cdevsw; 185e2a13e8cSSatoshi Asami static struct bdevsw ccd_bdevsw = { 186e2a13e8cSSatoshi Asami ccdopen, ccdclose, ccdstrategy, ccdioctl, 187e2a13e8cSSatoshi Asami ccddump, ccdsize, 0, 188e2a13e8cSSatoshi Asami "ccd", &ccd_cdevsw, -1 189e2a13e8cSSatoshi Asami }; 190e2a13e8cSSatoshi Asami 191e2a13e8cSSatoshi Asami /* Called by main() during pseudo-device attachment */ 192e2a13e8cSSatoshi Asami static void ccdattach __P((void *)); 193e2a13e8cSSatoshi Asami PSEUDO_SET(ccdattach, ccd); 194a56bb8a5SSatoshi Asami 195a56bb8a5SSatoshi Asami /* called by biodone() at interrupt time */ 196a56bb8a5SSatoshi Asami void ccdiodone __P((struct ccdbuf *cbp)); 197a56bb8a5SSatoshi Asami 198a56bb8a5SSatoshi Asami static void ccdstart __P((struct ccd_softc *, struct buf *)); 199a56bb8a5SSatoshi Asami static void ccdinterleave __P((struct ccd_softc *, int)); 200a56bb8a5SSatoshi Asami static void ccdintr __P((struct ccd_softc *, struct buf *)); 201a56bb8a5SSatoshi Asami static int ccdinit __P((struct ccddevice *, char **, struct proc *)); 202a56bb8a5SSatoshi Asami static int ccdlookup __P((char *, struct proc *p, struct vnode **)); 2033bc746beSSatoshi Asami static void ccdbuffer __P((struct ccdbuf **ret, struct ccd_softc *, 2043bc746beSSatoshi Asami struct buf *, daddr_t, caddr_t, long)); 205a56bb8a5SSatoshi Asami static void ccdgetdisklabel __P((dev_t)); 206a56bb8a5SSatoshi Asami static void ccdmakedisklabel __P((struct ccd_softc *)); 207a56bb8a5SSatoshi Asami static int ccdlock __P((struct ccd_softc *)); 208a56bb8a5SSatoshi Asami static void ccdunlock __P((struct ccd_softc *)); 209a56bb8a5SSatoshi Asami 210a56bb8a5SSatoshi Asami #ifdef DEBUG 211a56bb8a5SSatoshi Asami static void printiinfo __P((struct ccdiinfo *)); 212a56bb8a5SSatoshi Asami #endif 213a56bb8a5SSatoshi Asami 214a56bb8a5SSatoshi Asami /* Non-private for the benefit of libkvm. */ 215a56bb8a5SSatoshi Asami struct ccd_softc *ccd_softc; 216a56bb8a5SSatoshi Asami struct ccddevice *ccddevs; 217a56bb8a5SSatoshi Asami int numccd = 0; 218a56bb8a5SSatoshi Asami 21952faebb2SSatoshi Asami static int ccd_devsw_installed = 0; 220d8594dfbSSatoshi Asami 221a56bb8a5SSatoshi Asami /* 2220d88ef07SSatoshi Asami * Number of blocks to untouched in front of a component partition. 2230d88ef07SSatoshi Asami * This is to avoid violating its disklabel area when it starts at the 2240d88ef07SSatoshi Asami * beginning of the slice. 2250d88ef07SSatoshi Asami */ 2261af0e025SSatoshi Asami #if !defined(CCD_OFFSET) 2270d88ef07SSatoshi Asami #define CCD_OFFSET 16 2281af0e025SSatoshi Asami #endif 2290d88ef07SSatoshi Asami 2300d88ef07SSatoshi Asami /* 231a56bb8a5SSatoshi Asami * Called by main() during pseudo-device attachment. All we need 232e2a13e8cSSatoshi Asami * to do is allocate enough space for devices to be configured later, and 233e2a13e8cSSatoshi Asami * add devsw entries. 234a56bb8a5SSatoshi Asami */ 235e2a13e8cSSatoshi Asami void 236e2a13e8cSSatoshi Asami ccdattach(dummy) 237e2a13e8cSSatoshi Asami void *dummy; 238a56bb8a5SSatoshi Asami { 239a56bb8a5SSatoshi Asami int i; 240e2a13e8cSSatoshi Asami int num = NCCD; 241a56bb8a5SSatoshi Asami 242e2a13e8cSSatoshi Asami if (num > 1) 243e2a13e8cSSatoshi Asami printf("ccd0-%d: Concatenated disk drivers\n", num-1); 244d8594dfbSSatoshi Asami else 245e2a13e8cSSatoshi Asami printf("ccd0: Concatenated disk driver\n"); 246d8594dfbSSatoshi Asami 247a56bb8a5SSatoshi Asami ccd_softc = (struct ccd_softc *)malloc(num * sizeof(struct ccd_softc), 248a56bb8a5SSatoshi Asami M_DEVBUF, M_NOWAIT); 249a56bb8a5SSatoshi Asami ccddevs = (struct ccddevice *)malloc(num * sizeof(struct ccddevice), 250a56bb8a5SSatoshi Asami M_DEVBUF, M_NOWAIT); 251a56bb8a5SSatoshi Asami if ((ccd_softc == NULL) || (ccddevs == NULL)) { 252a56bb8a5SSatoshi Asami printf("WARNING: no memory for concatenated disks\n"); 253a56bb8a5SSatoshi Asami if (ccd_softc != NULL) 254a56bb8a5SSatoshi Asami free(ccd_softc, M_DEVBUF); 255a56bb8a5SSatoshi Asami if (ccddevs != NULL) 256a56bb8a5SSatoshi Asami free(ccddevs, M_DEVBUF); 257e2a13e8cSSatoshi Asami return; 258a56bb8a5SSatoshi Asami } 259a56bb8a5SSatoshi Asami numccd = num; 260a56bb8a5SSatoshi Asami bzero(ccd_softc, num * sizeof(struct ccd_softc)); 261a56bb8a5SSatoshi Asami bzero(ccddevs, num * sizeof(struct ccddevice)); 262a56bb8a5SSatoshi Asami 263a56bb8a5SSatoshi Asami /* XXX: is this necessary? */ 264a56bb8a5SSatoshi Asami for (i = 0; i < numccd; ++i) 265a56bb8a5SSatoshi Asami ccddevs[i].ccd_dk = -1; 266d8594dfbSSatoshi Asami 267e2a13e8cSSatoshi Asami if( ! ccd_devsw_installed ) { 268cba8a5ddSPoul-Henning Kamp bdevsw_add_generic(BDEV_MAJOR,CDEV_MAJOR, &ccd_bdevsw); 269e2a13e8cSSatoshi Asami ccd_devsw_installed = 1; 270e2a13e8cSSatoshi Asami } 271e2a13e8cSSatoshi Asami else { 272e2a13e8cSSatoshi Asami printf("huh?\n"); 273e2a13e8cSSatoshi Asami } 274a56bb8a5SSatoshi Asami } 275a56bb8a5SSatoshi Asami 276a56bb8a5SSatoshi Asami static int 277a56bb8a5SSatoshi Asami ccdinit(ccd, cpaths, p) 278a56bb8a5SSatoshi Asami struct ccddevice *ccd; 279a56bb8a5SSatoshi Asami char **cpaths; 280a56bb8a5SSatoshi Asami struct proc *p; 281a56bb8a5SSatoshi Asami { 282a56bb8a5SSatoshi Asami register struct ccd_softc *cs = &ccd_softc[ccd->ccd_unit]; 283e2a13e8cSSatoshi Asami register struct ccdcinfo *ci = NULL; /* XXX */ 284a56bb8a5SSatoshi Asami register size_t size; 285a56bb8a5SSatoshi Asami register int ix; 286a56bb8a5SSatoshi Asami struct vnode *vp; 287a56bb8a5SSatoshi Asami struct vattr va; 288a56bb8a5SSatoshi Asami size_t minsize; 289a56bb8a5SSatoshi Asami int maxsecsize; 290a56bb8a5SSatoshi Asami struct partinfo dpart; 291a56bb8a5SSatoshi Asami struct ccdgeom *ccg = &cs->sc_geom; 292a56bb8a5SSatoshi Asami char tmppath[MAXPATHLEN]; 293a56bb8a5SSatoshi Asami int error; 294a56bb8a5SSatoshi Asami 295a56bb8a5SSatoshi Asami #ifdef DEBUG 296a56bb8a5SSatoshi Asami if (ccddebug & (CCDB_FOLLOW|CCDB_INIT)) 297a56bb8a5SSatoshi Asami printf("ccdinit: unit %d\n", ccd->ccd_unit); 298a56bb8a5SSatoshi Asami #endif 299a56bb8a5SSatoshi Asami 300a56bb8a5SSatoshi Asami #ifdef WORKING_DISK_STATISTICS /* XXX !! */ 301a56bb8a5SSatoshi Asami cs->sc_dk = ccd->ccd_dk; 302a56bb8a5SSatoshi Asami #endif 303a56bb8a5SSatoshi Asami cs->sc_size = 0; 304a56bb8a5SSatoshi Asami cs->sc_ileave = ccd->ccd_interleave; 305a56bb8a5SSatoshi Asami cs->sc_nccdisks = ccd->ccd_ndev; 306a56bb8a5SSatoshi Asami 307a56bb8a5SSatoshi Asami /* Allocate space for the component info. */ 308a56bb8a5SSatoshi Asami cs->sc_cinfo = malloc(cs->sc_nccdisks * sizeof(struct ccdcinfo), 309a56bb8a5SSatoshi Asami M_DEVBUF, M_WAITOK); 310a56bb8a5SSatoshi Asami 311a56bb8a5SSatoshi Asami /* 312a56bb8a5SSatoshi Asami * Verify that each component piece exists and record 313a56bb8a5SSatoshi Asami * relevant information about it. 314a56bb8a5SSatoshi Asami */ 315a56bb8a5SSatoshi Asami maxsecsize = 0; 316a56bb8a5SSatoshi Asami minsize = 0; 317a56bb8a5SSatoshi Asami for (ix = 0; ix < cs->sc_nccdisks; ix++) { 318a56bb8a5SSatoshi Asami vp = ccd->ccd_vpp[ix]; 319a56bb8a5SSatoshi Asami ci = &cs->sc_cinfo[ix]; 320a56bb8a5SSatoshi Asami ci->ci_vp = vp; 321a56bb8a5SSatoshi Asami 322a56bb8a5SSatoshi Asami /* 323a56bb8a5SSatoshi Asami * Copy in the pathname of the component. 324a56bb8a5SSatoshi Asami */ 325a56bb8a5SSatoshi Asami bzero(tmppath, sizeof(tmppath)); /* sanity */ 326a56bb8a5SSatoshi Asami if (error = copyinstr(cpaths[ix], tmppath, 327a56bb8a5SSatoshi Asami MAXPATHLEN, &ci->ci_pathlen)) { 328a56bb8a5SSatoshi Asami #ifdef DEBUG 329a56bb8a5SSatoshi Asami if (ccddebug & (CCDB_FOLLOW|CCDB_INIT)) 330a56bb8a5SSatoshi Asami printf("ccd%d: can't copy path, error = %d\n", 331a56bb8a5SSatoshi Asami ccd->ccd_unit, error); 332a56bb8a5SSatoshi Asami #endif 33334f35216SSatoshi Asami while (ci > cs->sc_cinfo) { 33434f35216SSatoshi Asami ci--; 33534f35216SSatoshi Asami free(ci->ci_path, M_DEVBUF); 33634f35216SSatoshi Asami } 337a56bb8a5SSatoshi Asami free(cs->sc_cinfo, M_DEVBUF); 338a56bb8a5SSatoshi Asami return (error); 339a56bb8a5SSatoshi Asami } 340a56bb8a5SSatoshi Asami ci->ci_path = malloc(ci->ci_pathlen, M_DEVBUF, M_WAITOK); 341a56bb8a5SSatoshi Asami bcopy(tmppath, ci->ci_path, ci->ci_pathlen); 342a56bb8a5SSatoshi Asami 343a56bb8a5SSatoshi Asami /* 344a56bb8a5SSatoshi Asami * XXX: Cache the component's dev_t. 345a56bb8a5SSatoshi Asami */ 346a56bb8a5SSatoshi Asami if (error = VOP_GETATTR(vp, &va, p->p_ucred, p)) { 347a56bb8a5SSatoshi Asami #ifdef DEBUG 348a56bb8a5SSatoshi Asami if (ccddebug & (CCDB_FOLLOW|CCDB_INIT)) 349a56bb8a5SSatoshi Asami printf("ccd%d: %s: getattr failed %s = %d\n", 350a56bb8a5SSatoshi Asami ccd->ccd_unit, ci->ci_path, 351a56bb8a5SSatoshi Asami "error", error); 352a56bb8a5SSatoshi Asami #endif 35334f35216SSatoshi Asami while (ci >= cs->sc_cinfo) { 354a56bb8a5SSatoshi Asami free(ci->ci_path, M_DEVBUF); 35534f35216SSatoshi Asami ci--; 35634f35216SSatoshi Asami } 357a56bb8a5SSatoshi Asami free(cs->sc_cinfo, M_DEVBUF); 358a56bb8a5SSatoshi Asami return (error); 359a56bb8a5SSatoshi Asami } 360a56bb8a5SSatoshi Asami ci->ci_dev = va.va_rdev; 361a56bb8a5SSatoshi Asami 362a56bb8a5SSatoshi Asami /* 363a56bb8a5SSatoshi Asami * Get partition information for the component. 364a56bb8a5SSatoshi Asami */ 365a56bb8a5SSatoshi Asami if (error = VOP_IOCTL(vp, DIOCGPART, (caddr_t)&dpart, 366a56bb8a5SSatoshi Asami FREAD, p->p_ucred, p)) { 367a56bb8a5SSatoshi Asami #ifdef DEBUG 368a56bb8a5SSatoshi Asami if (ccddebug & (CCDB_FOLLOW|CCDB_INIT)) 369a56bb8a5SSatoshi Asami printf("ccd%d: %s: ioctl failed, error = %d\n", 370a56bb8a5SSatoshi Asami ccd->ccd_unit, ci->ci_path, error); 371a56bb8a5SSatoshi Asami #endif 37234f35216SSatoshi Asami while (ci >= cs->sc_cinfo) { 373a56bb8a5SSatoshi Asami free(ci->ci_path, M_DEVBUF); 37434f35216SSatoshi Asami ci--; 37534f35216SSatoshi Asami } 376a56bb8a5SSatoshi Asami free(cs->sc_cinfo, M_DEVBUF); 377a56bb8a5SSatoshi Asami return (error); 378a56bb8a5SSatoshi Asami } 379a56bb8a5SSatoshi Asami if (dpart.part->p_fstype == FS_BSDFFS) { 380a56bb8a5SSatoshi Asami maxsecsize = 381a56bb8a5SSatoshi Asami ((dpart.disklab->d_secsize > maxsecsize) ? 382a56bb8a5SSatoshi Asami dpart.disklab->d_secsize : maxsecsize); 3830d88ef07SSatoshi Asami size = dpart.part->p_size - CCD_OFFSET; 384a56bb8a5SSatoshi Asami } else { 385a56bb8a5SSatoshi Asami #ifdef DEBUG 386a56bb8a5SSatoshi Asami if (ccddebug & (CCDB_FOLLOW|CCDB_INIT)) 387a56bb8a5SSatoshi Asami printf("ccd%d: %s: incorrect partition type\n", 388a56bb8a5SSatoshi Asami ccd->ccd_unit, ci->ci_path); 389a56bb8a5SSatoshi Asami #endif 39034f35216SSatoshi Asami while (ci >= cs->sc_cinfo) { 391a56bb8a5SSatoshi Asami free(ci->ci_path, M_DEVBUF); 39234f35216SSatoshi Asami ci--; 39334f35216SSatoshi Asami } 394a56bb8a5SSatoshi Asami free(cs->sc_cinfo, M_DEVBUF); 395a56bb8a5SSatoshi Asami return (EFTYPE); 396a56bb8a5SSatoshi Asami } 397a56bb8a5SSatoshi Asami 398a56bb8a5SSatoshi Asami /* 399a56bb8a5SSatoshi Asami * Calculate the size, truncating to an interleave 400a56bb8a5SSatoshi Asami * boundary if necessary. 401a56bb8a5SSatoshi Asami */ 402b8e29b55SSatoshi Asami #ifndef __FreeBSD__ 403a56bb8a5SSatoshi Asami if (size < 0) 404a56bb8a5SSatoshi Asami size = 0; 405b8e29b55SSatoshi Asami #endif 406a56bb8a5SSatoshi Asami 407a56bb8a5SSatoshi Asami if (cs->sc_ileave > 1) 408a56bb8a5SSatoshi Asami size -= size % cs->sc_ileave; 409a56bb8a5SSatoshi Asami 410a56bb8a5SSatoshi Asami if (size == 0) { 411a56bb8a5SSatoshi Asami #ifdef DEBUG 412a56bb8a5SSatoshi Asami if (ccddebug & (CCDB_FOLLOW|CCDB_INIT)) 413a56bb8a5SSatoshi Asami printf("ccd%d: %s: size == 0\n", 414a56bb8a5SSatoshi Asami ccd->ccd_unit, ci->ci_path); 415a56bb8a5SSatoshi Asami #endif 41634f35216SSatoshi Asami while (ci >= cs->sc_cinfo) { 417a56bb8a5SSatoshi Asami free(ci->ci_path, M_DEVBUF); 41834f35216SSatoshi Asami ci--; 41934f35216SSatoshi Asami } 420a56bb8a5SSatoshi Asami free(cs->sc_cinfo, M_DEVBUF); 421a56bb8a5SSatoshi Asami return (ENODEV); 422a56bb8a5SSatoshi Asami } 423a56bb8a5SSatoshi Asami 424a56bb8a5SSatoshi Asami if (minsize == 0 || size < minsize) 425a56bb8a5SSatoshi Asami minsize = size; 426a56bb8a5SSatoshi Asami ci->ci_size = size; 427a56bb8a5SSatoshi Asami cs->sc_size += size; 428a56bb8a5SSatoshi Asami } 429a56bb8a5SSatoshi Asami 430a56bb8a5SSatoshi Asami /* 431a56bb8a5SSatoshi Asami * Don't allow the interleave to be smaller than 432a56bb8a5SSatoshi Asami * the biggest component sector. 433a56bb8a5SSatoshi Asami */ 434a56bb8a5SSatoshi Asami if ((cs->sc_ileave > 0) && 435a56bb8a5SSatoshi Asami (cs->sc_ileave < (maxsecsize / DEV_BSIZE))) { 436a56bb8a5SSatoshi Asami #ifdef DEBUG 437a56bb8a5SSatoshi Asami if (ccddebug & (CCDB_FOLLOW|CCDB_INIT)) 438a56bb8a5SSatoshi Asami printf("ccd%d: interleave must be at least %d\n", 439a56bb8a5SSatoshi Asami ccd->ccd_unit, (maxsecsize / DEV_BSIZE)); 440a56bb8a5SSatoshi Asami #endif 44134f35216SSatoshi Asami while (ci >= cs->sc_cinfo) { 442a56bb8a5SSatoshi Asami free(ci->ci_path, M_DEVBUF); 44334f35216SSatoshi Asami ci--; 44434f35216SSatoshi Asami } 445a56bb8a5SSatoshi Asami free(cs->sc_cinfo, M_DEVBUF); 446a56bb8a5SSatoshi Asami return (EINVAL); 447a56bb8a5SSatoshi Asami } 448a56bb8a5SSatoshi Asami 449a56bb8a5SSatoshi Asami /* 450a56bb8a5SSatoshi Asami * If uniform interleave is desired set all sizes to that of 451a56bb8a5SSatoshi Asami * the smallest component. 452a56bb8a5SSatoshi Asami */ 453a56bb8a5SSatoshi Asami if (ccd->ccd_flags & CCDF_UNIFORM) { 454a56bb8a5SSatoshi Asami for (ci = cs->sc_cinfo; 455a56bb8a5SSatoshi Asami ci < &cs->sc_cinfo[cs->sc_nccdisks]; ci++) 456a56bb8a5SSatoshi Asami ci->ci_size = minsize; 45709b59204SSatoshi Asami if (ccd->ccd_flags & CCDF_MIRROR) { 45834f35216SSatoshi Asami /* 45934f35216SSatoshi Asami * Check to see if an even number of components 46034f35216SSatoshi Asami * have been specified. 46134f35216SSatoshi Asami */ 46209b59204SSatoshi Asami if (cs->sc_nccdisks % 2) { 46334f35216SSatoshi Asami printf("ccd%d: mirroring requires an even number of disks\n", ccd->ccd_unit ); 46434f35216SSatoshi Asami while (ci > cs->sc_cinfo) { 46534f35216SSatoshi Asami ci--; 46634f35216SSatoshi Asami free(ci->ci_path, M_DEVBUF); 46734f35216SSatoshi Asami } 46834f35216SSatoshi Asami free(cs->sc_cinfo, M_DEVBUF); 46934f35216SSatoshi Asami return (EINVAL); 47009b59204SSatoshi Asami } 47109b59204SSatoshi Asami cs->sc_size = (cs->sc_nccdisks/2) * minsize; 47209b59204SSatoshi Asami } 47309b59204SSatoshi Asami else if (ccd->ccd_flags & CCDF_PARITY) 4747ecb65faSSatoshi Asami cs->sc_size = (cs->sc_nccdisks-1) * minsize; 4757ecb65faSSatoshi Asami else 476a56bb8a5SSatoshi Asami cs->sc_size = cs->sc_nccdisks * minsize; 477a56bb8a5SSatoshi Asami } 478a56bb8a5SSatoshi Asami 479a56bb8a5SSatoshi Asami /* 480a56bb8a5SSatoshi Asami * Construct the interleave table. 481a56bb8a5SSatoshi Asami */ 482a56bb8a5SSatoshi Asami ccdinterleave(cs, ccd->ccd_unit); 483a56bb8a5SSatoshi Asami 484a56bb8a5SSatoshi Asami /* 485a56bb8a5SSatoshi Asami * Create pseudo-geometry based on 1MB cylinders. It's 486a56bb8a5SSatoshi Asami * pretty close. 487a56bb8a5SSatoshi Asami */ 488a56bb8a5SSatoshi Asami ccg->ccg_secsize = DEV_BSIZE; 489a56bb8a5SSatoshi Asami ccg->ccg_ntracks = 1; 490a56bb8a5SSatoshi Asami ccg->ccg_nsectors = 1024 * (1024 / ccg->ccg_secsize); 491a56bb8a5SSatoshi Asami ccg->ccg_ncylinders = cs->sc_size / ccg->ccg_nsectors; 492a56bb8a5SSatoshi Asami 493a56bb8a5SSatoshi Asami #ifdef WORKING_DISK_STATISTICS /* XXX !! */ 494a56bb8a5SSatoshi Asami if (ccd->ccd_dk >= 0) 495a56bb8a5SSatoshi Asami dk_wpms[ccd->ccd_dk] = 32 * (60 * DEV_BSIZE / 2); /* XXX */ 496a56bb8a5SSatoshi Asami #endif 497a56bb8a5SSatoshi Asami 498a56bb8a5SSatoshi Asami cs->sc_flags |= CCDF_INITED; 499a56bb8a5SSatoshi Asami cs->sc_cflags = ccd->ccd_flags; /* So we can find out later... */ 500a56bb8a5SSatoshi Asami cs->sc_unit = ccd->ccd_unit; 501a56bb8a5SSatoshi Asami return (0); 502a56bb8a5SSatoshi Asami } 503a56bb8a5SSatoshi Asami 504a56bb8a5SSatoshi Asami static void 505a56bb8a5SSatoshi Asami ccdinterleave(cs, unit) 506a56bb8a5SSatoshi Asami register struct ccd_softc *cs; 507a56bb8a5SSatoshi Asami int unit; 508a56bb8a5SSatoshi Asami { 509a56bb8a5SSatoshi Asami register struct ccdcinfo *ci, *smallci; 510a56bb8a5SSatoshi Asami register struct ccdiinfo *ii; 511a56bb8a5SSatoshi Asami register daddr_t bn, lbn; 512a56bb8a5SSatoshi Asami register int ix; 513a56bb8a5SSatoshi Asami u_long size; 514a56bb8a5SSatoshi Asami 515a56bb8a5SSatoshi Asami #ifdef DEBUG 516a56bb8a5SSatoshi Asami if (ccddebug & CCDB_INIT) 517a56bb8a5SSatoshi Asami printf("ccdinterleave(%x): ileave %d\n", cs, cs->sc_ileave); 518a56bb8a5SSatoshi Asami #endif 519a56bb8a5SSatoshi Asami /* 520a56bb8a5SSatoshi Asami * Allocate an interleave table. 521a56bb8a5SSatoshi Asami * Chances are this is too big, but we don't care. 522a56bb8a5SSatoshi Asami */ 523a56bb8a5SSatoshi Asami size = (cs->sc_nccdisks + 1) * sizeof(struct ccdiinfo); 524a56bb8a5SSatoshi Asami cs->sc_itable = (struct ccdiinfo *)malloc(size, M_DEVBUF, M_WAITOK); 525a56bb8a5SSatoshi Asami bzero((caddr_t)cs->sc_itable, size); 526a56bb8a5SSatoshi Asami 527a56bb8a5SSatoshi Asami /* 528a56bb8a5SSatoshi Asami * Trivial case: no interleave (actually interleave of disk size). 529a56bb8a5SSatoshi Asami * Each table entry represents a single component in its entirety. 530a56bb8a5SSatoshi Asami */ 531a56bb8a5SSatoshi Asami if (cs->sc_ileave == 0) { 532a56bb8a5SSatoshi Asami bn = 0; 533a56bb8a5SSatoshi Asami ii = cs->sc_itable; 534a56bb8a5SSatoshi Asami 535a56bb8a5SSatoshi Asami for (ix = 0; ix < cs->sc_nccdisks; ix++) { 536a56bb8a5SSatoshi Asami /* Allocate space for ii_index. */ 537a56bb8a5SSatoshi Asami ii->ii_index = malloc(sizeof(int), M_DEVBUF, M_WAITOK); 538a56bb8a5SSatoshi Asami ii->ii_ndisk = 1; 539a56bb8a5SSatoshi Asami ii->ii_startblk = bn; 540a56bb8a5SSatoshi Asami ii->ii_startoff = 0; 541a56bb8a5SSatoshi Asami ii->ii_index[0] = ix; 542a56bb8a5SSatoshi Asami bn += cs->sc_cinfo[ix].ci_size; 543a56bb8a5SSatoshi Asami ii++; 544a56bb8a5SSatoshi Asami } 545a56bb8a5SSatoshi Asami ii->ii_ndisk = 0; 546a56bb8a5SSatoshi Asami #ifdef DEBUG 547a56bb8a5SSatoshi Asami if (ccddebug & CCDB_INIT) 548a56bb8a5SSatoshi Asami printiinfo(cs->sc_itable); 549a56bb8a5SSatoshi Asami #endif 550a56bb8a5SSatoshi Asami return; 551a56bb8a5SSatoshi Asami } 552a56bb8a5SSatoshi Asami 553a56bb8a5SSatoshi Asami /* 554a56bb8a5SSatoshi Asami * The following isn't fast or pretty; it doesn't have to be. 555a56bb8a5SSatoshi Asami */ 556a56bb8a5SSatoshi Asami size = 0; 557a56bb8a5SSatoshi Asami bn = lbn = 0; 558a56bb8a5SSatoshi Asami for (ii = cs->sc_itable; ; ii++) { 559a56bb8a5SSatoshi Asami /* Allocate space for ii_index. */ 560a56bb8a5SSatoshi Asami ii->ii_index = malloc((sizeof(int) * cs->sc_nccdisks), 561a56bb8a5SSatoshi Asami M_DEVBUF, M_WAITOK); 562a56bb8a5SSatoshi Asami 563a56bb8a5SSatoshi Asami /* 564a56bb8a5SSatoshi Asami * Locate the smallest of the remaining components 565a56bb8a5SSatoshi Asami */ 566a56bb8a5SSatoshi Asami smallci = NULL; 567a56bb8a5SSatoshi Asami for (ci = cs->sc_cinfo; 568a56bb8a5SSatoshi Asami ci < &cs->sc_cinfo[cs->sc_nccdisks]; ci++) 569a56bb8a5SSatoshi Asami if (ci->ci_size > size && 570a56bb8a5SSatoshi Asami (smallci == NULL || 571a56bb8a5SSatoshi Asami ci->ci_size < smallci->ci_size)) 572a56bb8a5SSatoshi Asami smallci = ci; 573a56bb8a5SSatoshi Asami 574a56bb8a5SSatoshi Asami /* 575a56bb8a5SSatoshi Asami * Nobody left, all done 576a56bb8a5SSatoshi Asami */ 577a56bb8a5SSatoshi Asami if (smallci == NULL) { 578a56bb8a5SSatoshi Asami ii->ii_ndisk = 0; 579a56bb8a5SSatoshi Asami break; 580a56bb8a5SSatoshi Asami } 581a56bb8a5SSatoshi Asami 582a56bb8a5SSatoshi Asami /* 583a56bb8a5SSatoshi Asami * Record starting logical block and component offset 584a56bb8a5SSatoshi Asami */ 585a56bb8a5SSatoshi Asami ii->ii_startblk = bn / cs->sc_ileave; 586a56bb8a5SSatoshi Asami ii->ii_startoff = lbn; 587a56bb8a5SSatoshi Asami 588a56bb8a5SSatoshi Asami /* 589a56bb8a5SSatoshi Asami * Determine how many disks take part in this interleave 590a56bb8a5SSatoshi Asami * and record their indices. 591a56bb8a5SSatoshi Asami */ 592a56bb8a5SSatoshi Asami ix = 0; 593a56bb8a5SSatoshi Asami for (ci = cs->sc_cinfo; 594a56bb8a5SSatoshi Asami ci < &cs->sc_cinfo[cs->sc_nccdisks]; ci++) 595a56bb8a5SSatoshi Asami if (ci->ci_size >= smallci->ci_size) 596a56bb8a5SSatoshi Asami ii->ii_index[ix++] = ci - cs->sc_cinfo; 597a56bb8a5SSatoshi Asami ii->ii_ndisk = ix; 598a56bb8a5SSatoshi Asami bn += ix * (smallci->ci_size - size); 599a56bb8a5SSatoshi Asami lbn = smallci->ci_size / cs->sc_ileave; 600a56bb8a5SSatoshi Asami size = smallci->ci_size; 601a56bb8a5SSatoshi Asami } 602a56bb8a5SSatoshi Asami #ifdef DEBUG 603a56bb8a5SSatoshi Asami if (ccddebug & CCDB_INIT) 604a56bb8a5SSatoshi Asami printiinfo(cs->sc_itable); 605a56bb8a5SSatoshi Asami #endif 606a56bb8a5SSatoshi Asami } 607a56bb8a5SSatoshi Asami 608a56bb8a5SSatoshi Asami /* ARGSUSED */ 609a56bb8a5SSatoshi Asami int 610a56bb8a5SSatoshi Asami ccdopen(dev, flags, fmt, p) 611a56bb8a5SSatoshi Asami dev_t dev; 612a56bb8a5SSatoshi Asami int flags, fmt; 613a56bb8a5SSatoshi Asami struct proc *p; 614a56bb8a5SSatoshi Asami { 615a56bb8a5SSatoshi Asami int unit = ccdunit(dev); 616a56bb8a5SSatoshi Asami struct ccd_softc *cs; 617a56bb8a5SSatoshi Asami struct disklabel *lp; 618a56bb8a5SSatoshi Asami int error = 0, part, pmask; 619a56bb8a5SSatoshi Asami 620a56bb8a5SSatoshi Asami #ifdef DEBUG 621a56bb8a5SSatoshi Asami if (ccddebug & CCDB_FOLLOW) 622a56bb8a5SSatoshi Asami printf("ccdopen(%x, %x)\n", dev, flags); 623a56bb8a5SSatoshi Asami #endif 624a56bb8a5SSatoshi Asami if (unit >= numccd) 625a56bb8a5SSatoshi Asami return (ENXIO); 626a56bb8a5SSatoshi Asami cs = &ccd_softc[unit]; 627a56bb8a5SSatoshi Asami 628a56bb8a5SSatoshi Asami if (error = ccdlock(cs)) 629a56bb8a5SSatoshi Asami return (error); 630a56bb8a5SSatoshi Asami 631a56bb8a5SSatoshi Asami lp = &cs->sc_dkdev.dk_label; 632a56bb8a5SSatoshi Asami 633d8594dfbSSatoshi Asami part = ccdpart(dev); 634a56bb8a5SSatoshi Asami pmask = (1 << part); 635a56bb8a5SSatoshi Asami 636a56bb8a5SSatoshi Asami /* 637a56bb8a5SSatoshi Asami * If we're initialized, check to see if there are any other 638a56bb8a5SSatoshi Asami * open partitions. If not, then it's safe to update 639a56bb8a5SSatoshi Asami * the in-core disklabel. 640a56bb8a5SSatoshi Asami */ 641a56bb8a5SSatoshi Asami if ((cs->sc_flags & CCDF_INITED) && (cs->sc_dkdev.dk_openmask == 0)) 642a56bb8a5SSatoshi Asami ccdgetdisklabel(dev); 643a56bb8a5SSatoshi Asami 644a56bb8a5SSatoshi Asami /* Check that the partition exists. */ 645a56bb8a5SSatoshi Asami if (part != RAW_PART && ((part > lp->d_npartitions) || 646a56bb8a5SSatoshi Asami (lp->d_partitions[part].p_fstype == FS_UNUSED))) { 647a56bb8a5SSatoshi Asami error = ENXIO; 648a56bb8a5SSatoshi Asami goto done; 649a56bb8a5SSatoshi Asami } 650a56bb8a5SSatoshi Asami 651a56bb8a5SSatoshi Asami /* Prevent our unit from being unconfigured while open. */ 652a56bb8a5SSatoshi Asami switch (fmt) { 653a56bb8a5SSatoshi Asami case S_IFCHR: 654a56bb8a5SSatoshi Asami cs->sc_dkdev.dk_copenmask |= pmask; 655a56bb8a5SSatoshi Asami break; 656a56bb8a5SSatoshi Asami 657a56bb8a5SSatoshi Asami case S_IFBLK: 658a56bb8a5SSatoshi Asami cs->sc_dkdev.dk_bopenmask |= pmask; 659a56bb8a5SSatoshi Asami break; 660a56bb8a5SSatoshi Asami } 661a56bb8a5SSatoshi Asami cs->sc_dkdev.dk_openmask = 662a56bb8a5SSatoshi Asami cs->sc_dkdev.dk_copenmask | cs->sc_dkdev.dk_bopenmask; 663a56bb8a5SSatoshi Asami 664a56bb8a5SSatoshi Asami done: 665a56bb8a5SSatoshi Asami ccdunlock(cs); 666a56bb8a5SSatoshi Asami return (0); 667a56bb8a5SSatoshi Asami } 668a56bb8a5SSatoshi Asami 669a56bb8a5SSatoshi Asami /* ARGSUSED */ 670a56bb8a5SSatoshi Asami int 671a56bb8a5SSatoshi Asami ccdclose(dev, flags, fmt, p) 672a56bb8a5SSatoshi Asami dev_t dev; 673a56bb8a5SSatoshi Asami int flags, fmt; 674a56bb8a5SSatoshi Asami struct proc *p; 675a56bb8a5SSatoshi Asami { 676a56bb8a5SSatoshi Asami int unit = ccdunit(dev); 677a56bb8a5SSatoshi Asami struct ccd_softc *cs; 678a56bb8a5SSatoshi Asami int error = 0, part; 679a56bb8a5SSatoshi Asami 680a56bb8a5SSatoshi Asami #ifdef DEBUG 681a56bb8a5SSatoshi Asami if (ccddebug & CCDB_FOLLOW) 682a56bb8a5SSatoshi Asami printf("ccdclose(%x, %x)\n", dev, flags); 683a56bb8a5SSatoshi Asami #endif 684a56bb8a5SSatoshi Asami 685a56bb8a5SSatoshi Asami if (unit >= numccd) 686a56bb8a5SSatoshi Asami return (ENXIO); 687a56bb8a5SSatoshi Asami cs = &ccd_softc[unit]; 688a56bb8a5SSatoshi Asami 689a56bb8a5SSatoshi Asami if (error = ccdlock(cs)) 690a56bb8a5SSatoshi Asami return (error); 691a56bb8a5SSatoshi Asami 692d8594dfbSSatoshi Asami part = ccdpart(dev); 693a56bb8a5SSatoshi Asami 694a56bb8a5SSatoshi Asami /* ...that much closer to allowing unconfiguration... */ 695a56bb8a5SSatoshi Asami switch (fmt) { 696a56bb8a5SSatoshi Asami case S_IFCHR: 697a56bb8a5SSatoshi Asami cs->sc_dkdev.dk_copenmask &= ~(1 << part); 698a56bb8a5SSatoshi Asami break; 699a56bb8a5SSatoshi Asami 700a56bb8a5SSatoshi Asami case S_IFBLK: 701a56bb8a5SSatoshi Asami cs->sc_dkdev.dk_bopenmask &= ~(1 << part); 702a56bb8a5SSatoshi Asami break; 703a56bb8a5SSatoshi Asami } 704a56bb8a5SSatoshi Asami cs->sc_dkdev.dk_openmask = 705a56bb8a5SSatoshi Asami cs->sc_dkdev.dk_copenmask | cs->sc_dkdev.dk_bopenmask; 706a56bb8a5SSatoshi Asami 707a56bb8a5SSatoshi Asami ccdunlock(cs); 708a56bb8a5SSatoshi Asami return (0); 709a56bb8a5SSatoshi Asami } 710a56bb8a5SSatoshi Asami 711a56bb8a5SSatoshi Asami void 712a56bb8a5SSatoshi Asami ccdstrategy(bp) 713a56bb8a5SSatoshi Asami register struct buf *bp; 714a56bb8a5SSatoshi Asami { 715a56bb8a5SSatoshi Asami register int unit = ccdunit(bp->b_dev); 716a56bb8a5SSatoshi Asami register struct ccd_softc *cs = &ccd_softc[unit]; 717c23670e2SGary Palmer register int s; 718a56bb8a5SSatoshi Asami int wlabel; 719a56bb8a5SSatoshi Asami struct disklabel *lp; 720a56bb8a5SSatoshi Asami 721a56bb8a5SSatoshi Asami #ifdef DEBUG 722a56bb8a5SSatoshi Asami if (ccddebug & CCDB_FOLLOW) 723a56bb8a5SSatoshi Asami printf("ccdstrategy(%x): unit %d\n", bp, unit); 724a56bb8a5SSatoshi Asami #endif 725a56bb8a5SSatoshi Asami if ((cs->sc_flags & CCDF_INITED) == 0) { 726a56bb8a5SSatoshi Asami bp->b_error = ENXIO; 727a56bb8a5SSatoshi Asami bp->b_flags |= B_ERROR; 728a56bb8a5SSatoshi Asami goto done; 729a56bb8a5SSatoshi Asami } 730a56bb8a5SSatoshi Asami 731a56bb8a5SSatoshi Asami /* If it's a nil transfer, wake up the top half now. */ 732a56bb8a5SSatoshi Asami if (bp->b_bcount == 0) 733a56bb8a5SSatoshi Asami goto done; 734a56bb8a5SSatoshi Asami 735a56bb8a5SSatoshi Asami lp = &cs->sc_dkdev.dk_label; 736a56bb8a5SSatoshi Asami 737a56bb8a5SSatoshi Asami /* 738a56bb8a5SSatoshi Asami * Do bounds checking and adjust transfer. If there's an 739a56bb8a5SSatoshi Asami * error, the bounds check will flag that for us. 740a56bb8a5SSatoshi Asami */ 741a56bb8a5SSatoshi Asami wlabel = cs->sc_flags & (CCDF_WLABEL|CCDF_LABELLING); 742d8594dfbSSatoshi Asami if (ccdpart(bp->b_dev) != RAW_PART) 743a56bb8a5SSatoshi Asami if (bounds_check_with_label(bp, lp, wlabel) <= 0) 744a56bb8a5SSatoshi Asami goto done; 745a56bb8a5SSatoshi Asami 746a56bb8a5SSatoshi Asami bp->b_resid = bp->b_bcount; 747a56bb8a5SSatoshi Asami 748a56bb8a5SSatoshi Asami /* 749a56bb8a5SSatoshi Asami * "Start" the unit. 750a56bb8a5SSatoshi Asami */ 751a56bb8a5SSatoshi Asami s = splbio(); 752a56bb8a5SSatoshi Asami ccdstart(cs, bp); 753a56bb8a5SSatoshi Asami splx(s); 754a56bb8a5SSatoshi Asami return; 755a56bb8a5SSatoshi Asami done: 756a56bb8a5SSatoshi Asami biodone(bp); 757a56bb8a5SSatoshi Asami } 758a56bb8a5SSatoshi Asami 759a56bb8a5SSatoshi Asami static void 760a56bb8a5SSatoshi Asami ccdstart(cs, bp) 761a56bb8a5SSatoshi Asami register struct ccd_softc *cs; 762a56bb8a5SSatoshi Asami register struct buf *bp; 763a56bb8a5SSatoshi Asami { 764a56bb8a5SSatoshi Asami register long bcount, rcount; 7653bc746beSSatoshi Asami struct ccdbuf *cbp[4]; 7663bc746beSSatoshi Asami /* XXX! : 2 reads and 2 writes for RAID 4/5 */ 767a56bb8a5SSatoshi Asami caddr_t addr; 768a56bb8a5SSatoshi Asami daddr_t bn; 769a56bb8a5SSatoshi Asami struct partition *pp; 770a56bb8a5SSatoshi Asami 771a56bb8a5SSatoshi Asami #ifdef DEBUG 772a56bb8a5SSatoshi Asami if (ccddebug & CCDB_FOLLOW) 773a56bb8a5SSatoshi Asami printf("ccdstart(%x, %x)\n", cs, bp); 774a56bb8a5SSatoshi Asami #endif 775a56bb8a5SSatoshi Asami 776a56bb8a5SSatoshi Asami #ifdef WORKING_DISK_STATISTICS /* XXX !! */ 777a56bb8a5SSatoshi Asami /* 778a56bb8a5SSatoshi Asami * Instrumentation (not very meaningful) 779a56bb8a5SSatoshi Asami */ 780a56bb8a5SSatoshi Asami cs->sc_nactive++; 781a56bb8a5SSatoshi Asami if (cs->sc_dk >= 0) { 782a56bb8a5SSatoshi Asami dk_busy |= 1 << cs->sc_dk; 783a56bb8a5SSatoshi Asami dk_xfer[cs->sc_dk]++; 784a56bb8a5SSatoshi Asami dk_wds[cs->sc_dk] += bp->b_bcount >> 6; 785a56bb8a5SSatoshi Asami } 786a56bb8a5SSatoshi Asami #endif 787a56bb8a5SSatoshi Asami 788a56bb8a5SSatoshi Asami /* 789a56bb8a5SSatoshi Asami * Translate the partition-relative block number to an absolute. 790a56bb8a5SSatoshi Asami */ 791a56bb8a5SSatoshi Asami bn = bp->b_blkno; 792d8594dfbSSatoshi Asami if (ccdpart(bp->b_dev) != RAW_PART) { 793d8594dfbSSatoshi Asami pp = &cs->sc_dkdev.dk_label.d_partitions[ccdpart(bp->b_dev)]; 794a56bb8a5SSatoshi Asami bn += pp->p_offset; 795a56bb8a5SSatoshi Asami } 796a56bb8a5SSatoshi Asami 797a56bb8a5SSatoshi Asami /* 798a56bb8a5SSatoshi Asami * Allocate component buffers and fire off the requests 799a56bb8a5SSatoshi Asami */ 800a56bb8a5SSatoshi Asami addr = bp->b_data; 801a56bb8a5SSatoshi Asami for (bcount = bp->b_bcount; bcount > 0; bcount -= rcount) { 8023bc746beSSatoshi Asami ccdbuffer(cbp, cs, bp, bn, addr, bcount); 8033bc746beSSatoshi Asami rcount = cbp[0]->cb_buf.b_bcount; 8043bc746beSSatoshi Asami if ((cbp[0]->cb_buf.b_flags & B_READ) == 0) 8053bc746beSSatoshi Asami cbp[0]->cb_buf.b_vp->v_numoutput++; 8063bc746beSSatoshi Asami VOP_STRATEGY(&cbp[0]->cb_buf); 8073bc746beSSatoshi Asami if (cs->sc_cflags & CCDF_MIRROR && 8083bc746beSSatoshi Asami (cbp[0]->cb_buf.b_flags & B_READ) == 0) { 8093bc746beSSatoshi Asami /* mirror, start another write */ 8103bc746beSSatoshi Asami cbp[1]->cb_buf.b_vp->v_numoutput++; 8113bc746beSSatoshi Asami VOP_STRATEGY(&cbp[1]->cb_buf); 8123bc746beSSatoshi Asami } 813a56bb8a5SSatoshi Asami bn += btodb(rcount); 814a56bb8a5SSatoshi Asami addr += rcount; 815a56bb8a5SSatoshi Asami } 816a56bb8a5SSatoshi Asami } 817a56bb8a5SSatoshi Asami 818a56bb8a5SSatoshi Asami /* 819a56bb8a5SSatoshi Asami * Build a component buffer header. 820a56bb8a5SSatoshi Asami */ 8213bc746beSSatoshi Asami void 8223bc746beSSatoshi Asami ccdbuffer(cb, cs, bp, bn, addr, bcount) 8233bc746beSSatoshi Asami register struct ccdbuf **cb; 824a56bb8a5SSatoshi Asami register struct ccd_softc *cs; 825a56bb8a5SSatoshi Asami struct buf *bp; 826a56bb8a5SSatoshi Asami daddr_t bn; 827a56bb8a5SSatoshi Asami caddr_t addr; 828a56bb8a5SSatoshi Asami long bcount; 829a56bb8a5SSatoshi Asami { 830e2a13e8cSSatoshi Asami register struct ccdcinfo *ci, *ci2 = NULL; /* XXX */ 831a56bb8a5SSatoshi Asami register struct ccdbuf *cbp; 832a56bb8a5SSatoshi Asami register daddr_t cbn, cboff; 833a56bb8a5SSatoshi Asami 834a56bb8a5SSatoshi Asami #ifdef DEBUG 835a56bb8a5SSatoshi Asami if (ccddebug & CCDB_IO) 836a56bb8a5SSatoshi Asami printf("ccdbuffer(%x, %x, %d, %x, %d)\n", 837a56bb8a5SSatoshi Asami cs, bp, bn, addr, bcount); 838a56bb8a5SSatoshi Asami #endif 839a56bb8a5SSatoshi Asami /* 840a56bb8a5SSatoshi Asami * Determine which component bn falls in. 841a56bb8a5SSatoshi Asami */ 842a56bb8a5SSatoshi Asami cbn = bn; 843a56bb8a5SSatoshi Asami cboff = 0; 844a56bb8a5SSatoshi Asami 845a56bb8a5SSatoshi Asami /* 846a56bb8a5SSatoshi Asami * Serially concatenated 847a56bb8a5SSatoshi Asami */ 848a56bb8a5SSatoshi Asami if (cs->sc_ileave == 0) { 849a56bb8a5SSatoshi Asami register daddr_t sblk; 850a56bb8a5SSatoshi Asami 851a56bb8a5SSatoshi Asami sblk = 0; 852a56bb8a5SSatoshi Asami for (ci = cs->sc_cinfo; cbn >= sblk + ci->ci_size; ci++) 853a56bb8a5SSatoshi Asami sblk += ci->ci_size; 854a56bb8a5SSatoshi Asami cbn -= sblk; 855a56bb8a5SSatoshi Asami } 856a56bb8a5SSatoshi Asami /* 857a56bb8a5SSatoshi Asami * Interleaved 858a56bb8a5SSatoshi Asami */ 859a56bb8a5SSatoshi Asami else { 860a56bb8a5SSatoshi Asami register struct ccdiinfo *ii; 861a56bb8a5SSatoshi Asami int ccdisk, off; 862a56bb8a5SSatoshi Asami 863a56bb8a5SSatoshi Asami cboff = cbn % cs->sc_ileave; 864a56bb8a5SSatoshi Asami cbn /= cs->sc_ileave; 865a56bb8a5SSatoshi Asami for (ii = cs->sc_itable; ii->ii_ndisk; ii++) 866a56bb8a5SSatoshi Asami if (ii->ii_startblk > cbn) 867a56bb8a5SSatoshi Asami break; 868a56bb8a5SSatoshi Asami ii--; 869a56bb8a5SSatoshi Asami off = cbn - ii->ii_startblk; 870a56bb8a5SSatoshi Asami if (ii->ii_ndisk == 1) { 871a56bb8a5SSatoshi Asami ccdisk = ii->ii_index[0]; 872a56bb8a5SSatoshi Asami cbn = ii->ii_startoff + off; 873a56bb8a5SSatoshi Asami } else { 87409b59204SSatoshi Asami if (cs->sc_cflags & CCDF_MIRROR) { 87509b59204SSatoshi Asami ccdisk = ii->ii_index[off % (ii->ii_ndisk/2)]; 87609b59204SSatoshi Asami cbn = ii->ii_startoff + off / (ii->ii_ndisk/2); 8773bc746beSSatoshi Asami /* mirrored data */ 8783bc746beSSatoshi Asami ci2 = &cs->sc_cinfo[ccdisk + ii->ii_ndisk/2]; 87909b59204SSatoshi Asami } 88009b59204SSatoshi Asami else if (cs->sc_cflags & CCDF_PARITY) { 8817ecb65faSSatoshi Asami ccdisk = ii->ii_index[off % (ii->ii_ndisk-1)]; 8827ecb65faSSatoshi Asami cbn = ii->ii_startoff + off / (ii->ii_ndisk-1); 8837ecb65faSSatoshi Asami if (cbn % ii->ii_ndisk <= ccdisk) 8847ecb65faSSatoshi Asami ccdisk++; 8857ecb65faSSatoshi Asami } 8867ecb65faSSatoshi Asami else { 887a56bb8a5SSatoshi Asami ccdisk = ii->ii_index[off % ii->ii_ndisk]; 888a56bb8a5SSatoshi Asami cbn = ii->ii_startoff + off / ii->ii_ndisk; 889a56bb8a5SSatoshi Asami } 8907ecb65faSSatoshi Asami } 891a56bb8a5SSatoshi Asami cbn *= cs->sc_ileave; 892a56bb8a5SSatoshi Asami ci = &cs->sc_cinfo[ccdisk]; 893a56bb8a5SSatoshi Asami } 894a56bb8a5SSatoshi Asami 895a56bb8a5SSatoshi Asami /* 896a56bb8a5SSatoshi Asami * Fill in the component buf structure. 897a56bb8a5SSatoshi Asami */ 898a56bb8a5SSatoshi Asami cbp = getccdbuf(); 899a56bb8a5SSatoshi Asami cbp->cb_buf.b_flags = bp->b_flags | B_CALL; 900e2a13e8cSSatoshi Asami cbp->cb_buf.b_iodone = (void (*)(struct buf *))ccdiodone; 901a56bb8a5SSatoshi Asami cbp->cb_buf.b_proc = bp->b_proc; 902a56bb8a5SSatoshi Asami cbp->cb_buf.b_dev = ci->ci_dev; /* XXX */ 9030d88ef07SSatoshi Asami cbp->cb_buf.b_blkno = cbn + cboff + CCD_OFFSET; 904a56bb8a5SSatoshi Asami cbp->cb_buf.b_data = addr; 905a56bb8a5SSatoshi Asami cbp->cb_buf.b_vp = ci->ci_vp; 906a56bb8a5SSatoshi Asami if (cs->sc_ileave == 0) 907a56bb8a5SSatoshi Asami cbp->cb_buf.b_bcount = dbtob(ci->ci_size - cbn); 908a56bb8a5SSatoshi Asami else 909a56bb8a5SSatoshi Asami cbp->cb_buf.b_bcount = dbtob(cs->sc_ileave - cboff); 910a56bb8a5SSatoshi Asami if (cbp->cb_buf.b_bcount > bcount) 911a56bb8a5SSatoshi Asami cbp->cb_buf.b_bcount = bcount; 912a56bb8a5SSatoshi Asami 913c0b89506SJohn Dyson cbp->cb_buf.b_bufsize = cbp->cb_buf.b_bcount; 914c0b89506SJohn Dyson 915a56bb8a5SSatoshi Asami /* 916a56bb8a5SSatoshi Asami * context for ccdiodone 917a56bb8a5SSatoshi Asami */ 918a56bb8a5SSatoshi Asami cbp->cb_obp = bp; 919a56bb8a5SSatoshi Asami cbp->cb_unit = cs - ccd_softc; 920a56bb8a5SSatoshi Asami cbp->cb_comp = ci - cs->sc_cinfo; 921a56bb8a5SSatoshi Asami 922a56bb8a5SSatoshi Asami #ifdef DEBUG 923a56bb8a5SSatoshi Asami if (ccddebug & CCDB_IO) 924a56bb8a5SSatoshi Asami printf(" dev %x(u%d): cbp %x bn %d addr %x bcnt %d\n", 925a56bb8a5SSatoshi Asami ci->ci_dev, ci-cs->sc_cinfo, cbp, cbp->cb_buf.b_blkno, 926a56bb8a5SSatoshi Asami cbp->cb_buf.b_data, cbp->cb_buf.b_bcount); 927a56bb8a5SSatoshi Asami #endif 9283bc746beSSatoshi Asami cb[0] = cbp; 9293bc746beSSatoshi Asami if (cs->sc_cflags & CCDF_MIRROR && 9303bc746beSSatoshi Asami (cbp->cb_buf.b_flags & B_READ) == 0) { 9313bc746beSSatoshi Asami /* mirror, start one more write */ 9323bc746beSSatoshi Asami cbp = getccdbuf(); 9333bc746beSSatoshi Asami *cbp = *cb[0]; 9343bc746beSSatoshi Asami cbp->cb_buf.b_dev = ci2->ci_dev; 9353bc746beSSatoshi Asami cbp->cb_buf.b_vp = ci2->ci_vp; 9363bc746beSSatoshi Asami cbp->cb_comp = ci2 - cs->sc_cinfo; 9373bc746beSSatoshi Asami cb[1] = cbp; 938e7322872SSatoshi Asami /* link together the ccdbuf's and clear "mirror done" flag */ 939e7322872SSatoshi Asami cb[0]->cb_mirror = cb[1]; 940e7322872SSatoshi Asami cb[1]->cb_mirror = cb[0]; 941e7322872SSatoshi Asami cb[0]->cb_pflags &= ~CCDPF_MIRROR_DONE; 942e7322872SSatoshi Asami cb[1]->cb_pflags &= ~CCDPF_MIRROR_DONE; 9433bc746beSSatoshi Asami } 944a56bb8a5SSatoshi Asami } 945a56bb8a5SSatoshi Asami 946a56bb8a5SSatoshi Asami static void 947a56bb8a5SSatoshi Asami ccdintr(cs, bp) 948a56bb8a5SSatoshi Asami register struct ccd_softc *cs; 949a56bb8a5SSatoshi Asami register struct buf *bp; 950a56bb8a5SSatoshi Asami { 951a56bb8a5SSatoshi Asami 952a56bb8a5SSatoshi Asami #ifdef DEBUG 953a56bb8a5SSatoshi Asami if (ccddebug & CCDB_FOLLOW) 954a56bb8a5SSatoshi Asami printf("ccdintr(%x, %x)\n", cs, bp); 955a56bb8a5SSatoshi Asami #endif 956a56bb8a5SSatoshi Asami /* 957a56bb8a5SSatoshi Asami * Request is done for better or worse, wakeup the top half. 958a56bb8a5SSatoshi Asami */ 959a56bb8a5SSatoshi Asami #ifdef WORKING_DISK_STATISTICS /* XXX !! */ 960a56bb8a5SSatoshi Asami --cs->sc_nactive; 961a56bb8a5SSatoshi Asami #ifdef DIAGNOSTIC 962a56bb8a5SSatoshi Asami if (cs->sc_nactive < 0) 963a56bb8a5SSatoshi Asami panic("ccdintr: ccd%d: sc_nactive < 0", cs->sc_unit); 964a56bb8a5SSatoshi Asami #endif 965a56bb8a5SSatoshi Asami 966a56bb8a5SSatoshi Asami if (cs->sc_nactive == 0 && cs->sc_dk >= 0) 967a56bb8a5SSatoshi Asami dk_busy &= ~(1 << cs->sc_dk); 968a56bb8a5SSatoshi Asami #endif 969a56bb8a5SSatoshi Asami if (bp->b_flags & B_ERROR) 970a56bb8a5SSatoshi Asami bp->b_resid = bp->b_bcount; 971a56bb8a5SSatoshi Asami biodone(bp); 972a56bb8a5SSatoshi Asami } 973a56bb8a5SSatoshi Asami 974a56bb8a5SSatoshi Asami /* 975a56bb8a5SSatoshi Asami * Called at interrupt time. 976a56bb8a5SSatoshi Asami * Mark the component as done and if all components are done, 977a56bb8a5SSatoshi Asami * take a ccd interrupt. 978a56bb8a5SSatoshi Asami */ 979a56bb8a5SSatoshi Asami void 980a56bb8a5SSatoshi Asami ccdiodone(cbp) 981a56bb8a5SSatoshi Asami struct ccdbuf *cbp; 982a56bb8a5SSatoshi Asami { 983a56bb8a5SSatoshi Asami register struct buf *bp = cbp->cb_obp; 984a56bb8a5SSatoshi Asami register int unit = cbp->cb_unit; 985a56bb8a5SSatoshi Asami int count, s; 986a56bb8a5SSatoshi Asami 987a56bb8a5SSatoshi Asami s = splbio(); 988a56bb8a5SSatoshi Asami #ifdef DEBUG 989a56bb8a5SSatoshi Asami if (ccddebug & CCDB_FOLLOW) 990a56bb8a5SSatoshi Asami printf("ccdiodone(%x)\n", cbp); 991a56bb8a5SSatoshi Asami if (ccddebug & CCDB_IO) { 992a56bb8a5SSatoshi Asami printf("ccdiodone: bp %x bcount %d resid %d\n", 993a56bb8a5SSatoshi Asami bp, bp->b_bcount, bp->b_resid); 994a56bb8a5SSatoshi Asami printf(" dev %x(u%d), cbp %x bn %d addr %x bcnt %d\n", 995a56bb8a5SSatoshi Asami cbp->cb_buf.b_dev, cbp->cb_comp, cbp, 996a56bb8a5SSatoshi Asami cbp->cb_buf.b_blkno, cbp->cb_buf.b_data, 997a56bb8a5SSatoshi Asami cbp->cb_buf.b_bcount); 998a56bb8a5SSatoshi Asami } 999a56bb8a5SSatoshi Asami #endif 1000a56bb8a5SSatoshi Asami 1001a56bb8a5SSatoshi Asami if (cbp->cb_buf.b_flags & B_ERROR) { 1002a56bb8a5SSatoshi Asami bp->b_flags |= B_ERROR; 1003a56bb8a5SSatoshi Asami bp->b_error = cbp->cb_buf.b_error ? cbp->cb_buf.b_error : EIO; 1004a56bb8a5SSatoshi Asami #ifdef DEBUG 1005a56bb8a5SSatoshi Asami printf("ccd%d: error %d on component %d\n", 1006a56bb8a5SSatoshi Asami unit, bp->b_error, cbp->cb_comp); 1007a56bb8a5SSatoshi Asami #endif 1008a56bb8a5SSatoshi Asami } 1009e7322872SSatoshi Asami 1010e7322872SSatoshi Asami if (ccd_softc[unit].sc_cflags & CCDF_MIRROR && 1011e7322872SSatoshi Asami (cbp->cb_buf.b_flags & B_READ) == 0) 1012e7322872SSatoshi Asami if ((cbp->cb_pflags & CCDPF_MIRROR_DONE) == 0) { 1013e7322872SSatoshi Asami /* I'm done before my counterpart, so just set 1014e7322872SSatoshi Asami partner's flag and return */ 1015e7322872SSatoshi Asami cbp->cb_mirror->cb_pflags |= CCDPF_MIRROR_DONE; 1016e7322872SSatoshi Asami putccdbuf(cbp); 1017e7322872SSatoshi Asami splx(s); 1018e7322872SSatoshi Asami return; 1019e7322872SSatoshi Asami } 1020e7322872SSatoshi Asami 1021a56bb8a5SSatoshi Asami count = cbp->cb_buf.b_bcount; 1022a56bb8a5SSatoshi Asami putccdbuf(cbp); 1023a56bb8a5SSatoshi Asami 1024a56bb8a5SSatoshi Asami /* 1025a56bb8a5SSatoshi Asami * If all done, "interrupt". 1026a56bb8a5SSatoshi Asami */ 1027a56bb8a5SSatoshi Asami bp->b_resid -= count; 1028a56bb8a5SSatoshi Asami if (bp->b_resid < 0) 1029a56bb8a5SSatoshi Asami panic("ccdiodone: count"); 1030a56bb8a5SSatoshi Asami if (bp->b_resid == 0) 1031a56bb8a5SSatoshi Asami ccdintr(&ccd_softc[unit], bp); 1032a56bb8a5SSatoshi Asami splx(s); 1033a56bb8a5SSatoshi Asami } 1034a56bb8a5SSatoshi Asami 1035a56bb8a5SSatoshi Asami int 1036a56bb8a5SSatoshi Asami ccdioctl(dev, cmd, data, flag, p) 1037a56bb8a5SSatoshi Asami dev_t dev; 1038d8594dfbSSatoshi Asami int cmd; 1039a56bb8a5SSatoshi Asami caddr_t data; 1040a56bb8a5SSatoshi Asami int flag; 1041a56bb8a5SSatoshi Asami struct proc *p; 1042a56bb8a5SSatoshi Asami { 1043a56bb8a5SSatoshi Asami int unit = ccdunit(dev); 1044a56bb8a5SSatoshi Asami int i, j, lookedup = 0, error = 0; 1045a56bb8a5SSatoshi Asami int part, pmask, s; 1046a56bb8a5SSatoshi Asami struct ccd_softc *cs; 1047a56bb8a5SSatoshi Asami struct ccd_ioctl *ccio = (struct ccd_ioctl *)data; 1048a56bb8a5SSatoshi Asami struct ccddevice ccd; 1049a56bb8a5SSatoshi Asami char **cpp; 1050a56bb8a5SSatoshi Asami struct vnode **vpp; 1051a56bb8a5SSatoshi Asami #ifdef WORKING_DISK_STATISTICS /* XXX !! */ 1052a56bb8a5SSatoshi Asami extern int dkn; 1053a56bb8a5SSatoshi Asami #endif 1054a56bb8a5SSatoshi Asami 1055a56bb8a5SSatoshi Asami if (unit >= numccd) 1056a56bb8a5SSatoshi Asami return (ENXIO); 1057a56bb8a5SSatoshi Asami cs = &ccd_softc[unit]; 1058a56bb8a5SSatoshi Asami 1059a56bb8a5SSatoshi Asami bzero(&ccd, sizeof(ccd)); 1060a56bb8a5SSatoshi Asami 1061a56bb8a5SSatoshi Asami switch (cmd) { 1062a56bb8a5SSatoshi Asami case CCDIOCSET: 1063a56bb8a5SSatoshi Asami if (cs->sc_flags & CCDF_INITED) 1064a56bb8a5SSatoshi Asami return (EBUSY); 1065a56bb8a5SSatoshi Asami 1066a56bb8a5SSatoshi Asami if ((flag & FWRITE) == 0) 1067a56bb8a5SSatoshi Asami return (EBADF); 1068a56bb8a5SSatoshi Asami 1069a56bb8a5SSatoshi Asami if (error = ccdlock(cs)) 1070a56bb8a5SSatoshi Asami return (error); 1071a56bb8a5SSatoshi Asami 1072a56bb8a5SSatoshi Asami /* Fill in some important bits. */ 1073a56bb8a5SSatoshi Asami ccd.ccd_unit = unit; 1074a56bb8a5SSatoshi Asami ccd.ccd_interleave = ccio->ccio_ileave; 1075b8e29b55SSatoshi Asami if (ccd.ccd_interleave == 0 && 1076b8e29b55SSatoshi Asami ((ccio->ccio_flags & CCDF_MIRROR) || 1077b8e29b55SSatoshi Asami (ccio->ccio_flags & CCDF_PARITY))) { 1078b8e29b55SSatoshi Asami printf("ccd%d: disabling mirror/parity, interleave is 0\n", unit); 1079b8e29b55SSatoshi Asami ccio->ccio_flags &= ~(CCDF_MIRROR | CCDF_PARITY); 1080b8e29b55SSatoshi Asami } 108109b59204SSatoshi Asami if ((ccio->ccio_flags & CCDF_MIRROR) && 108209b59204SSatoshi Asami (ccio->ccio_flags & CCDF_PARITY)) { 108309b59204SSatoshi Asami printf("ccd%d: can't specify both mirror and parity, using mirror\n", unit); 108409b59204SSatoshi Asami ccio->ccio_flags &= ~CCDF_PARITY; 108509b59204SSatoshi Asami } 108609b59204SSatoshi Asami if ((ccio->ccio_flags & (CCDF_MIRROR | CCDF_PARITY)) && 10877ecb65faSSatoshi Asami !(ccio->ccio_flags & CCDF_UNIFORM)) { 108809b59204SSatoshi Asami printf("ccd%d: mirror/parity forces uniform flag\n", 108909b59204SSatoshi Asami unit); 10907ecb65faSSatoshi Asami ccio->ccio_flags |= CCDF_UNIFORM; 10917ecb65faSSatoshi Asami } 1092a56bb8a5SSatoshi Asami ccd.ccd_flags = ccio->ccio_flags & CCDF_USERMASK; 1093a56bb8a5SSatoshi Asami 1094a56bb8a5SSatoshi Asami /* 1095a56bb8a5SSatoshi Asami * Allocate space for and copy in the array of 1096a56bb8a5SSatoshi Asami * componet pathnames and device numbers. 1097a56bb8a5SSatoshi Asami */ 1098a56bb8a5SSatoshi Asami cpp = malloc(ccio->ccio_ndisks * sizeof(char *), 1099a56bb8a5SSatoshi Asami M_DEVBUF, M_WAITOK); 1100a56bb8a5SSatoshi Asami vpp = malloc(ccio->ccio_ndisks * sizeof(struct vnode *), 1101a56bb8a5SSatoshi Asami M_DEVBUF, M_WAITOK); 1102a56bb8a5SSatoshi Asami 1103a56bb8a5SSatoshi Asami error = copyin((caddr_t)ccio->ccio_disks, (caddr_t)cpp, 1104a56bb8a5SSatoshi Asami ccio->ccio_ndisks * sizeof(char **)); 1105a56bb8a5SSatoshi Asami if (error) { 1106a56bb8a5SSatoshi Asami free(vpp, M_DEVBUF); 1107a56bb8a5SSatoshi Asami free(cpp, M_DEVBUF); 1108a56bb8a5SSatoshi Asami ccdunlock(cs); 1109a56bb8a5SSatoshi Asami return (error); 1110a56bb8a5SSatoshi Asami } 1111a56bb8a5SSatoshi Asami 1112a56bb8a5SSatoshi Asami #ifdef DEBUG 1113a56bb8a5SSatoshi Asami if (ccddebug & CCDB_INIT) 1114a56bb8a5SSatoshi Asami for (i = 0; i < ccio->ccio_ndisks; ++i) 1115a56bb8a5SSatoshi Asami printf("ccdioctl: component %d: 0x%x\n", 1116a56bb8a5SSatoshi Asami i, cpp[i]); 1117a56bb8a5SSatoshi Asami #endif 1118a56bb8a5SSatoshi Asami 1119a56bb8a5SSatoshi Asami for (i = 0; i < ccio->ccio_ndisks; ++i) { 1120a56bb8a5SSatoshi Asami #ifdef DEBUG 1121a56bb8a5SSatoshi Asami if (ccddebug & CCDB_INIT) 1122a56bb8a5SSatoshi Asami printf("ccdioctl: lookedup = %d\n", lookedup); 1123a56bb8a5SSatoshi Asami #endif 1124a56bb8a5SSatoshi Asami if (error = ccdlookup(cpp[i], p, &vpp[i])) { 1125a56bb8a5SSatoshi Asami for (j = 0; j < lookedup; ++j) 1126a56bb8a5SSatoshi Asami (void)vn_close(vpp[j], FREAD|FWRITE, 1127a56bb8a5SSatoshi Asami p->p_ucred, p); 1128a56bb8a5SSatoshi Asami free(vpp, M_DEVBUF); 1129a56bb8a5SSatoshi Asami free(cpp, M_DEVBUF); 1130a56bb8a5SSatoshi Asami ccdunlock(cs); 1131a56bb8a5SSatoshi Asami return (error); 1132a56bb8a5SSatoshi Asami } 1133a56bb8a5SSatoshi Asami ++lookedup; 1134a56bb8a5SSatoshi Asami } 1135a56bb8a5SSatoshi Asami ccd.ccd_cpp = cpp; 1136a56bb8a5SSatoshi Asami ccd.ccd_vpp = vpp; 1137a56bb8a5SSatoshi Asami ccd.ccd_ndev = ccio->ccio_ndisks; 1138a56bb8a5SSatoshi Asami 1139a56bb8a5SSatoshi Asami #ifdef WORKING_DISK_STATISTICS /* XXX !! */ 1140a56bb8a5SSatoshi Asami /* 1141a56bb8a5SSatoshi Asami * Assign disk index first so that init routine 1142a56bb8a5SSatoshi Asami * can use it (saves having the driver drag around 1143a56bb8a5SSatoshi Asami * the ccddevice pointer just to set up the dk_* 1144a56bb8a5SSatoshi Asami * info in the open routine). 1145a56bb8a5SSatoshi Asami */ 1146a56bb8a5SSatoshi Asami if (dkn < DK_NDRIVE) 1147a56bb8a5SSatoshi Asami ccd.ccd_dk = dkn++; 1148a56bb8a5SSatoshi Asami else 1149a56bb8a5SSatoshi Asami ccd.ccd_dk = -1; 1150a56bb8a5SSatoshi Asami #endif 1151a56bb8a5SSatoshi Asami 1152a56bb8a5SSatoshi Asami /* 1153a56bb8a5SSatoshi Asami * Initialize the ccd. Fills in the softc for us. 1154a56bb8a5SSatoshi Asami */ 1155a56bb8a5SSatoshi Asami if (error = ccdinit(&ccd, cpp, p)) { 1156a56bb8a5SSatoshi Asami #ifdef WORKING_DISK_STATISTICS /* XXX !! */ 1157a56bb8a5SSatoshi Asami if (ccd.ccd_dk >= 0) 1158a56bb8a5SSatoshi Asami --dkn; 1159a56bb8a5SSatoshi Asami #endif 1160a56bb8a5SSatoshi Asami for (j = 0; j < lookedup; ++j) 1161a56bb8a5SSatoshi Asami (void)vn_close(vpp[j], FREAD|FWRITE, 1162a56bb8a5SSatoshi Asami p->p_ucred, p); 1163a56bb8a5SSatoshi Asami bzero(&ccd_softc[unit], sizeof(struct ccd_softc)); 1164a56bb8a5SSatoshi Asami free(vpp, M_DEVBUF); 1165a56bb8a5SSatoshi Asami free(cpp, M_DEVBUF); 1166a56bb8a5SSatoshi Asami ccdunlock(cs); 1167a56bb8a5SSatoshi Asami return (error); 1168a56bb8a5SSatoshi Asami } 1169a56bb8a5SSatoshi Asami 1170a56bb8a5SSatoshi Asami /* 1171a56bb8a5SSatoshi Asami * The ccd has been successfully initialized, so 1172a56bb8a5SSatoshi Asami * we can place it into the array and read the disklabel. 1173a56bb8a5SSatoshi Asami */ 1174a56bb8a5SSatoshi Asami bcopy(&ccd, &ccddevs[unit], sizeof(ccd)); 1175a56bb8a5SSatoshi Asami ccio->ccio_unit = unit; 1176a56bb8a5SSatoshi Asami ccio->ccio_size = cs->sc_size; 1177a56bb8a5SSatoshi Asami ccdgetdisklabel(dev); 1178a56bb8a5SSatoshi Asami 1179a56bb8a5SSatoshi Asami ccdunlock(cs); 1180a56bb8a5SSatoshi Asami 1181a56bb8a5SSatoshi Asami break; 1182a56bb8a5SSatoshi Asami 1183a56bb8a5SSatoshi Asami case CCDIOCCLR: 1184a56bb8a5SSatoshi Asami if ((cs->sc_flags & CCDF_INITED) == 0) 1185a56bb8a5SSatoshi Asami return (ENXIO); 1186a56bb8a5SSatoshi Asami 1187a56bb8a5SSatoshi Asami if ((flag & FWRITE) == 0) 1188a56bb8a5SSatoshi Asami return (EBADF); 1189a56bb8a5SSatoshi Asami 1190a56bb8a5SSatoshi Asami if (error = ccdlock(cs)) 1191a56bb8a5SSatoshi Asami return (error); 1192a56bb8a5SSatoshi Asami 1193a56bb8a5SSatoshi Asami /* 1194a56bb8a5SSatoshi Asami * Don't unconfigure if any other partitions are open 1195a56bb8a5SSatoshi Asami * or if both the character and block flavors of this 1196a56bb8a5SSatoshi Asami * partition are open. 1197a56bb8a5SSatoshi Asami */ 1198d8594dfbSSatoshi Asami part = ccdpart(dev); 1199a56bb8a5SSatoshi Asami pmask = (1 << part); 1200a56bb8a5SSatoshi Asami if ((cs->sc_dkdev.dk_openmask & ~pmask) || 1201a56bb8a5SSatoshi Asami ((cs->sc_dkdev.dk_bopenmask & pmask) && 1202a56bb8a5SSatoshi Asami (cs->sc_dkdev.dk_copenmask & pmask))) { 1203a56bb8a5SSatoshi Asami ccdunlock(cs); 1204a56bb8a5SSatoshi Asami return (EBUSY); 1205a56bb8a5SSatoshi Asami } 1206a56bb8a5SSatoshi Asami 1207a56bb8a5SSatoshi Asami /* 1208a56bb8a5SSatoshi Asami * Free ccd_softc information and clear entry. 1209a56bb8a5SSatoshi Asami */ 1210a56bb8a5SSatoshi Asami 1211a56bb8a5SSatoshi Asami /* Close the components and free their pathnames. */ 1212a56bb8a5SSatoshi Asami for (i = 0; i < cs->sc_nccdisks; ++i) { 1213a56bb8a5SSatoshi Asami /* 1214a56bb8a5SSatoshi Asami * XXX: this close could potentially fail and 1215a56bb8a5SSatoshi Asami * cause Bad Things. Maybe we need to force 1216a56bb8a5SSatoshi Asami * the close to happen? 1217a56bb8a5SSatoshi Asami */ 1218a56bb8a5SSatoshi Asami #ifdef DEBUG 1219a56bb8a5SSatoshi Asami if (ccddebug & CCDB_VNODE) 1220a56bb8a5SSatoshi Asami vprint("CCDIOCCLR: vnode info", 1221a56bb8a5SSatoshi Asami cs->sc_cinfo[i].ci_vp); 1222a56bb8a5SSatoshi Asami #endif 1223a56bb8a5SSatoshi Asami (void)vn_close(cs->sc_cinfo[i].ci_vp, FREAD|FWRITE, 1224a56bb8a5SSatoshi Asami p->p_ucred, p); 1225a56bb8a5SSatoshi Asami free(cs->sc_cinfo[i].ci_path, M_DEVBUF); 1226a56bb8a5SSatoshi Asami } 1227a56bb8a5SSatoshi Asami 1228a56bb8a5SSatoshi Asami /* Free interleave index. */ 1229a56bb8a5SSatoshi Asami for (i = 0; cs->sc_itable[i].ii_ndisk; ++i) 1230a56bb8a5SSatoshi Asami free(cs->sc_itable[i].ii_index, M_DEVBUF); 1231a56bb8a5SSatoshi Asami 1232a56bb8a5SSatoshi Asami /* Free component info and interleave table. */ 1233a56bb8a5SSatoshi Asami free(cs->sc_cinfo, M_DEVBUF); 1234a56bb8a5SSatoshi Asami free(cs->sc_itable, M_DEVBUF); 1235a56bb8a5SSatoshi Asami cs->sc_flags &= ~CCDF_INITED; 1236a56bb8a5SSatoshi Asami 1237a56bb8a5SSatoshi Asami /* 1238a56bb8a5SSatoshi Asami * Free ccddevice information and clear entry. 1239a56bb8a5SSatoshi Asami */ 1240a56bb8a5SSatoshi Asami free(ccddevs[unit].ccd_cpp, M_DEVBUF); 1241a56bb8a5SSatoshi Asami free(ccddevs[unit].ccd_vpp, M_DEVBUF); 1242a56bb8a5SSatoshi Asami ccd.ccd_dk = -1; 1243a56bb8a5SSatoshi Asami bcopy(&ccd, &ccddevs[unit], sizeof(ccd)); 1244a56bb8a5SSatoshi Asami 1245a56bb8a5SSatoshi Asami /* This must be atomic. */ 1246a56bb8a5SSatoshi Asami s = splhigh(); 1247a56bb8a5SSatoshi Asami ccdunlock(cs); 1248a56bb8a5SSatoshi Asami bzero(cs, sizeof(struct ccd_softc)); 1249a56bb8a5SSatoshi Asami splx(s); 1250a56bb8a5SSatoshi Asami 1251a56bb8a5SSatoshi Asami break; 1252a56bb8a5SSatoshi Asami 1253a56bb8a5SSatoshi Asami case DIOCGDINFO: 1254a56bb8a5SSatoshi Asami if ((cs->sc_flags & CCDF_INITED) == 0) 1255a56bb8a5SSatoshi Asami return (ENXIO); 1256a56bb8a5SSatoshi Asami 1257a56bb8a5SSatoshi Asami *(struct disklabel *)data = cs->sc_dkdev.dk_label; 1258a56bb8a5SSatoshi Asami break; 1259a56bb8a5SSatoshi Asami 1260a56bb8a5SSatoshi Asami case DIOCGPART: 1261a56bb8a5SSatoshi Asami if ((cs->sc_flags & CCDF_INITED) == 0) 1262a56bb8a5SSatoshi Asami return (ENXIO); 1263a56bb8a5SSatoshi Asami 1264a56bb8a5SSatoshi Asami ((struct partinfo *)data)->disklab = &cs->sc_dkdev.dk_label; 1265a56bb8a5SSatoshi Asami ((struct partinfo *)data)->part = 1266d8594dfbSSatoshi Asami &cs->sc_dkdev.dk_label.d_partitions[ccdpart(dev)]; 1267a56bb8a5SSatoshi Asami break; 1268a56bb8a5SSatoshi Asami 1269a56bb8a5SSatoshi Asami case DIOCWDINFO: 1270a56bb8a5SSatoshi Asami case DIOCSDINFO: 1271a56bb8a5SSatoshi Asami if ((cs->sc_flags & CCDF_INITED) == 0) 1272a56bb8a5SSatoshi Asami return (ENXIO); 1273a56bb8a5SSatoshi Asami 1274a56bb8a5SSatoshi Asami if ((flag & FWRITE) == 0) 1275a56bb8a5SSatoshi Asami return (EBADF); 1276a56bb8a5SSatoshi Asami 1277a56bb8a5SSatoshi Asami if (error = ccdlock(cs)) 1278a56bb8a5SSatoshi Asami return (error); 1279a56bb8a5SSatoshi Asami 1280a56bb8a5SSatoshi Asami cs->sc_flags |= CCDF_LABELLING; 1281a56bb8a5SSatoshi Asami 1282a56bb8a5SSatoshi Asami error = setdisklabel(&cs->sc_dkdev.dk_label, 1283d8594dfbSSatoshi Asami (struct disklabel *)data, 0); 1284d8594dfbSSatoshi Asami /*, &cs->sc_dkdev.dk_cpulabel); */ 1285a56bb8a5SSatoshi Asami if (error == 0) { 1286a56bb8a5SSatoshi Asami if (cmd == DIOCWDINFO) 1287e2a13e8cSSatoshi Asami error = writedisklabel(CCDLABELDEV(dev), 1288d8594dfbSSatoshi Asami ccdstrategy, &cs->sc_dkdev.dk_label); 1289d8594dfbSSatoshi Asami /* 1290d8594dfbSSatoshi Asami &cs->sc_dkdev.dk_cpulabel); */ 1291a56bb8a5SSatoshi Asami } 1292a56bb8a5SSatoshi Asami 1293a56bb8a5SSatoshi Asami cs->sc_flags &= ~CCDF_LABELLING; 1294a56bb8a5SSatoshi Asami 1295a56bb8a5SSatoshi Asami ccdunlock(cs); 1296a56bb8a5SSatoshi Asami 1297a56bb8a5SSatoshi Asami if (error) 1298a56bb8a5SSatoshi Asami return (error); 1299a56bb8a5SSatoshi Asami break; 1300a56bb8a5SSatoshi Asami 1301a56bb8a5SSatoshi Asami case DIOCWLABEL: 1302a56bb8a5SSatoshi Asami if ((cs->sc_flags & CCDF_INITED) == 0) 1303a56bb8a5SSatoshi Asami return (ENXIO); 1304a56bb8a5SSatoshi Asami 1305a56bb8a5SSatoshi Asami if ((flag & FWRITE) == 0) 1306a56bb8a5SSatoshi Asami return (EBADF); 1307a56bb8a5SSatoshi Asami if (*(int *)data != 0) 1308a56bb8a5SSatoshi Asami cs->sc_flags |= CCDF_WLABEL; 1309a56bb8a5SSatoshi Asami else 1310a56bb8a5SSatoshi Asami cs->sc_flags &= ~CCDF_WLABEL; 1311a56bb8a5SSatoshi Asami break; 1312a56bb8a5SSatoshi Asami 1313a56bb8a5SSatoshi Asami default: 1314a56bb8a5SSatoshi Asami return (ENOTTY); 1315a56bb8a5SSatoshi Asami } 1316a56bb8a5SSatoshi Asami 1317a56bb8a5SSatoshi Asami return (0); 1318a56bb8a5SSatoshi Asami } 1319a56bb8a5SSatoshi Asami 1320a56bb8a5SSatoshi Asami int 1321a56bb8a5SSatoshi Asami ccdsize(dev) 1322a56bb8a5SSatoshi Asami dev_t dev; 1323a56bb8a5SSatoshi Asami { 1324a56bb8a5SSatoshi Asami struct ccd_softc *cs; 1325a56bb8a5SSatoshi Asami int part, size; 1326a56bb8a5SSatoshi Asami 1327a56bb8a5SSatoshi Asami if (ccdopen(dev, 0, S_IFBLK, curproc)) 1328a56bb8a5SSatoshi Asami return (-1); 1329a56bb8a5SSatoshi Asami 1330a56bb8a5SSatoshi Asami cs = &ccd_softc[ccdunit(dev)]; 1331d8594dfbSSatoshi Asami part = ccdpart(dev); 1332a56bb8a5SSatoshi Asami 1333a56bb8a5SSatoshi Asami if ((cs->sc_flags & CCDF_INITED) == 0) 1334a56bb8a5SSatoshi Asami return (-1); 1335a56bb8a5SSatoshi Asami 1336a56bb8a5SSatoshi Asami if (cs->sc_dkdev.dk_label.d_partitions[part].p_fstype != FS_SWAP) 1337a56bb8a5SSatoshi Asami size = -1; 1338a56bb8a5SSatoshi Asami else 1339a56bb8a5SSatoshi Asami size = cs->sc_dkdev.dk_label.d_partitions[part].p_size; 1340a56bb8a5SSatoshi Asami 1341a56bb8a5SSatoshi Asami if (ccdclose(dev, 0, S_IFBLK, curproc)) 1342a56bb8a5SSatoshi Asami return (-1); 1343a56bb8a5SSatoshi Asami 1344a56bb8a5SSatoshi Asami return (size); 1345a56bb8a5SSatoshi Asami } 1346a56bb8a5SSatoshi Asami 1347a56bb8a5SSatoshi Asami int 1348e2a13e8cSSatoshi Asami ccddump(dev) 1349a56bb8a5SSatoshi Asami dev_t dev; 1350a56bb8a5SSatoshi Asami { 1351a56bb8a5SSatoshi Asami 1352a56bb8a5SSatoshi Asami /* Not implemented. */ 1353a56bb8a5SSatoshi Asami return ENXIO; 1354a56bb8a5SSatoshi Asami } 1355a56bb8a5SSatoshi Asami 1356a56bb8a5SSatoshi Asami /* 1357a56bb8a5SSatoshi Asami * Lookup the provided name in the filesystem. If the file exists, 1358a56bb8a5SSatoshi Asami * is a valid block device, and isn't being used by anyone else, 1359a56bb8a5SSatoshi Asami * set *vpp to the file's vnode. 1360a56bb8a5SSatoshi Asami */ 1361a56bb8a5SSatoshi Asami static int 1362a56bb8a5SSatoshi Asami ccdlookup(path, p, vpp) 1363a56bb8a5SSatoshi Asami char *path; 1364a56bb8a5SSatoshi Asami struct proc *p; 1365a56bb8a5SSatoshi Asami struct vnode **vpp; /* result */ 1366a56bb8a5SSatoshi Asami { 1367a56bb8a5SSatoshi Asami struct nameidata nd; 1368a56bb8a5SSatoshi Asami struct vnode *vp; 1369a56bb8a5SSatoshi Asami struct vattr va; 1370a56bb8a5SSatoshi Asami int error; 1371a56bb8a5SSatoshi Asami 1372a56bb8a5SSatoshi Asami NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, path, p); 1373a56bb8a5SSatoshi Asami if (error = vn_open(&nd, FREAD|FWRITE, 0)) { 1374a56bb8a5SSatoshi Asami #ifdef DEBUG 1375a56bb8a5SSatoshi Asami if (ccddebug & CCDB_FOLLOW|CCDB_INIT) 1376a56bb8a5SSatoshi Asami printf("ccdlookup: vn_open error = %d\n", error); 1377a56bb8a5SSatoshi Asami #endif 1378a56bb8a5SSatoshi Asami return (error); 1379a56bb8a5SSatoshi Asami } 1380a56bb8a5SSatoshi Asami vp = nd.ni_vp; 1381a56bb8a5SSatoshi Asami 1382a56bb8a5SSatoshi Asami if (vp->v_usecount > 1) { 1383a56bb8a5SSatoshi Asami VOP_UNLOCK(vp); 1384a56bb8a5SSatoshi Asami (void)vn_close(vp, FREAD|FWRITE, p->p_ucred, p); 1385a56bb8a5SSatoshi Asami return (EBUSY); 1386a56bb8a5SSatoshi Asami } 1387a56bb8a5SSatoshi Asami 1388a56bb8a5SSatoshi Asami if (error = VOP_GETATTR(vp, &va, p->p_ucred, p)) { 1389a56bb8a5SSatoshi Asami #ifdef DEBUG 1390a56bb8a5SSatoshi Asami if (ccddebug & CCDB_FOLLOW|CCDB_INIT) 1391a56bb8a5SSatoshi Asami printf("ccdlookup: getattr error = %d\n", error); 1392a56bb8a5SSatoshi Asami #endif 1393a56bb8a5SSatoshi Asami VOP_UNLOCK(vp); 1394a56bb8a5SSatoshi Asami (void)vn_close(vp, FREAD|FWRITE, p->p_ucred, p); 1395a56bb8a5SSatoshi Asami return (error); 1396a56bb8a5SSatoshi Asami } 1397a56bb8a5SSatoshi Asami 1398a56bb8a5SSatoshi Asami /* XXX: eventually we should handle VREG, too. */ 1399a56bb8a5SSatoshi Asami if (va.va_type != VBLK) { 1400a56bb8a5SSatoshi Asami VOP_UNLOCK(vp); 1401a56bb8a5SSatoshi Asami (void)vn_close(vp, FREAD|FWRITE, p->p_ucred, p); 1402a56bb8a5SSatoshi Asami return (ENOTBLK); 1403a56bb8a5SSatoshi Asami } 1404a56bb8a5SSatoshi Asami 1405a56bb8a5SSatoshi Asami #ifdef DEBUG 1406a56bb8a5SSatoshi Asami if (ccddebug & CCDB_VNODE) 1407a56bb8a5SSatoshi Asami vprint("ccdlookup: vnode info", vp); 1408a56bb8a5SSatoshi Asami #endif 1409a56bb8a5SSatoshi Asami 1410a56bb8a5SSatoshi Asami VOP_UNLOCK(vp); 1411a56bb8a5SSatoshi Asami *vpp = vp; 1412a56bb8a5SSatoshi Asami return (0); 1413a56bb8a5SSatoshi Asami } 1414a56bb8a5SSatoshi Asami 1415a56bb8a5SSatoshi Asami /* 1416a56bb8a5SSatoshi Asami * Read the disklabel from the ccd. If one is not present, fake one 1417a56bb8a5SSatoshi Asami * up. 1418a56bb8a5SSatoshi Asami */ 1419a56bb8a5SSatoshi Asami static void 1420a56bb8a5SSatoshi Asami ccdgetdisklabel(dev) 1421a56bb8a5SSatoshi Asami dev_t dev; 1422a56bb8a5SSatoshi Asami { 1423a56bb8a5SSatoshi Asami int unit = ccdunit(dev); 1424a56bb8a5SSatoshi Asami struct ccd_softc *cs = &ccd_softc[unit]; 1425a56bb8a5SSatoshi Asami char *errstring; 1426a56bb8a5SSatoshi Asami struct disklabel *lp = &cs->sc_dkdev.dk_label; 1427a56bb8a5SSatoshi Asami struct ccdgeom *ccg = &cs->sc_geom; 1428a56bb8a5SSatoshi Asami 1429a56bb8a5SSatoshi Asami bzero(lp, sizeof(*lp)); 1430a56bb8a5SSatoshi Asami 1431a56bb8a5SSatoshi Asami lp->d_secperunit = cs->sc_size; 1432a56bb8a5SSatoshi Asami lp->d_secsize = ccg->ccg_secsize; 1433a56bb8a5SSatoshi Asami lp->d_nsectors = ccg->ccg_nsectors; 1434a56bb8a5SSatoshi Asami lp->d_ntracks = ccg->ccg_ntracks; 1435a56bb8a5SSatoshi Asami lp->d_ncylinders = ccg->ccg_ncylinders; 1436a56bb8a5SSatoshi Asami lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors; 1437a56bb8a5SSatoshi Asami 1438a56bb8a5SSatoshi Asami strncpy(lp->d_typename, "ccd", sizeof(lp->d_typename)); 1439a56bb8a5SSatoshi Asami lp->d_type = DTYPE_CCD; 1440a56bb8a5SSatoshi Asami strncpy(lp->d_packname, "fictitious", sizeof(lp->d_packname)); 1441a56bb8a5SSatoshi Asami lp->d_rpm = 3600; 1442a56bb8a5SSatoshi Asami lp->d_interleave = 1; 1443a56bb8a5SSatoshi Asami lp->d_flags = 0; 1444a56bb8a5SSatoshi Asami 1445a56bb8a5SSatoshi Asami lp->d_partitions[RAW_PART].p_offset = 0; 1446a56bb8a5SSatoshi Asami lp->d_partitions[RAW_PART].p_size = cs->sc_size; 1447a56bb8a5SSatoshi Asami lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED; 1448a56bb8a5SSatoshi Asami lp->d_npartitions = RAW_PART + 1; 1449a56bb8a5SSatoshi Asami 1450d8594dfbSSatoshi Asami lp->d_bbsize = BBSIZE; /* XXX */ 1451d8594dfbSSatoshi Asami lp->d_sbsize = SBSIZE; /* XXX */ 1452d8594dfbSSatoshi Asami 1453a56bb8a5SSatoshi Asami lp->d_magic = DISKMAGIC; 1454a56bb8a5SSatoshi Asami lp->d_magic2 = DISKMAGIC; 1455a56bb8a5SSatoshi Asami lp->d_checksum = dkcksum(&cs->sc_dkdev.dk_label); 1456a56bb8a5SSatoshi Asami 1457a56bb8a5SSatoshi Asami /* 1458a56bb8a5SSatoshi Asami * Call the generic disklabel extraction routine. 1459a56bb8a5SSatoshi Asami */ 1460e2a13e8cSSatoshi Asami if (errstring = readdisklabel(CCDLABELDEV(dev), ccdstrategy, 1461c23670e2SGary Palmer &cs->sc_dkdev.dk_label)) 1462a56bb8a5SSatoshi Asami ccdmakedisklabel(cs); 1463a56bb8a5SSatoshi Asami 1464a56bb8a5SSatoshi Asami #ifdef DEBUG 1465a56bb8a5SSatoshi Asami /* It's actually extremely common to have unlabeled ccds. */ 1466a56bb8a5SSatoshi Asami if (ccddebug & CCDB_LABEL) 1467a56bb8a5SSatoshi Asami if (errstring != NULL) 1468a56bb8a5SSatoshi Asami printf("ccd%d: %s\n", unit, errstring); 1469a56bb8a5SSatoshi Asami #endif 1470a56bb8a5SSatoshi Asami } 1471a56bb8a5SSatoshi Asami 1472a56bb8a5SSatoshi Asami /* 1473a56bb8a5SSatoshi Asami * Take care of things one might want to take care of in the event 1474a56bb8a5SSatoshi Asami * that a disklabel isn't present. 1475a56bb8a5SSatoshi Asami */ 1476a56bb8a5SSatoshi Asami static void 1477a56bb8a5SSatoshi Asami ccdmakedisklabel(cs) 1478a56bb8a5SSatoshi Asami struct ccd_softc *cs; 1479a56bb8a5SSatoshi Asami { 1480a56bb8a5SSatoshi Asami struct disklabel *lp = &cs->sc_dkdev.dk_label; 1481a56bb8a5SSatoshi Asami 1482a56bb8a5SSatoshi Asami /* 1483a56bb8a5SSatoshi Asami * For historical reasons, if there's no disklabel present 1484a56bb8a5SSatoshi Asami * the raw partition must be marked FS_BSDFFS. 1485a56bb8a5SSatoshi Asami */ 1486a56bb8a5SSatoshi Asami lp->d_partitions[RAW_PART].p_fstype = FS_BSDFFS; 1487a56bb8a5SSatoshi Asami 1488a56bb8a5SSatoshi Asami strncpy(lp->d_packname, "default label", sizeof(lp->d_packname)); 1489a56bb8a5SSatoshi Asami } 1490a56bb8a5SSatoshi Asami 1491a56bb8a5SSatoshi Asami /* 1492a56bb8a5SSatoshi Asami * Wait interruptibly for an exclusive lock. 1493a56bb8a5SSatoshi Asami * 1494a56bb8a5SSatoshi Asami * XXX 1495a56bb8a5SSatoshi Asami * Several drivers do this; it should be abstracted and made MP-safe. 1496a56bb8a5SSatoshi Asami */ 1497a56bb8a5SSatoshi Asami static int 1498a56bb8a5SSatoshi Asami ccdlock(cs) 1499a56bb8a5SSatoshi Asami struct ccd_softc *cs; 1500a56bb8a5SSatoshi Asami { 1501a56bb8a5SSatoshi Asami int error; 1502a56bb8a5SSatoshi Asami 1503a56bb8a5SSatoshi Asami while ((cs->sc_flags & CCDF_LOCKED) != 0) { 1504a56bb8a5SSatoshi Asami cs->sc_flags |= CCDF_WANTED; 1505a56bb8a5SSatoshi Asami if ((error = tsleep(cs, PRIBIO | PCATCH, "ccdlck", 0)) != 0) 1506a56bb8a5SSatoshi Asami return (error); 1507a56bb8a5SSatoshi Asami } 1508a56bb8a5SSatoshi Asami cs->sc_flags |= CCDF_LOCKED; 1509a56bb8a5SSatoshi Asami return (0); 1510a56bb8a5SSatoshi Asami } 1511a56bb8a5SSatoshi Asami 1512a56bb8a5SSatoshi Asami /* 1513a56bb8a5SSatoshi Asami * Unlock and wake up any waiters. 1514a56bb8a5SSatoshi Asami */ 1515a56bb8a5SSatoshi Asami static void 1516a56bb8a5SSatoshi Asami ccdunlock(cs) 1517a56bb8a5SSatoshi Asami struct ccd_softc *cs; 1518a56bb8a5SSatoshi Asami { 1519a56bb8a5SSatoshi Asami 1520a56bb8a5SSatoshi Asami cs->sc_flags &= ~CCDF_LOCKED; 1521a56bb8a5SSatoshi Asami if ((cs->sc_flags & CCDF_WANTED) != 0) { 1522a56bb8a5SSatoshi Asami cs->sc_flags &= ~CCDF_WANTED; 1523a56bb8a5SSatoshi Asami wakeup(cs); 1524a56bb8a5SSatoshi Asami } 1525a56bb8a5SSatoshi Asami } 1526a56bb8a5SSatoshi Asami 1527a56bb8a5SSatoshi Asami #ifdef DEBUG 1528a56bb8a5SSatoshi Asami static void 1529a56bb8a5SSatoshi Asami printiinfo(ii) 1530a56bb8a5SSatoshi Asami struct ccdiinfo *ii; 1531a56bb8a5SSatoshi Asami { 1532a56bb8a5SSatoshi Asami register int ix, i; 1533a56bb8a5SSatoshi Asami 1534a56bb8a5SSatoshi Asami for (ix = 0; ii->ii_ndisk; ix++, ii++) { 1535a56bb8a5SSatoshi Asami printf(" itab[%d]: #dk %d sblk %d soff %d", 1536a56bb8a5SSatoshi Asami ix, ii->ii_ndisk, ii->ii_startblk, ii->ii_startoff); 1537a56bb8a5SSatoshi Asami for (i = 0; i < ii->ii_ndisk; i++) 1538a56bb8a5SSatoshi Asami printf(" %d", ii->ii_index[i]); 1539a56bb8a5SSatoshi Asami printf("\n"); 1540a56bb8a5SSatoshi Asami } 1541a56bb8a5SSatoshi Asami } 1542a56bb8a5SSatoshi Asami #endif 1543d8594dfbSSatoshi Asami 1544d8594dfbSSatoshi Asami #endif /* NCCD > 0 */ 1545d8594dfbSSatoshi Asami 1546d8594dfbSSatoshi Asami /* Local Variables: */ 1547d8594dfbSSatoshi Asami /* c-argdecl-indent: 8 */ 154809b59204SSatoshi Asami /* c-continued-statement-offset: 8 */ 1549d8594dfbSSatoshi Asami /* c-indent-level: 8 */ 1550d8594dfbSSatoshi Asami /* End: */ 1551