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