Annotation of sys/dev/raidframe/rf_openbsdkintf.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: rf_openbsdkintf.c,v 1.42 2007/06/23 03:11:34 krw Exp $ */
! 2: /* $NetBSD: rf_netbsdkintf.c,v 1.109 2001/07/27 03:30:07 oster Exp $ */
! 3:
! 4: /*-
! 5: * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
! 6: * All rights reserved.
! 7: *
! 8: * This code is derived from software contributed to The NetBSD Foundation
! 9: * by Greg Oster; Jason R. Thorpe.
! 10: *
! 11: * Redistribution and use in source and binary forms, with or without
! 12: * modification, are permitted provided that the following conditions
! 13: * are met:
! 14: * 1. Redistributions of source code must retain the above copyright
! 15: * notice, this list of conditions and the following disclaimer.
! 16: * 2. Redistributions in binary form must reproduce the above copyright
! 17: * notice, this list of conditions and the following disclaimer in the
! 18: * documentation and/or other materials provided with the distribution.
! 19: * 3. All advertising materials mentioning features or use of this software
! 20: * must display the following acknowledgement:
! 21: * This product includes software developed by the NetBSD
! 22: * Foundation, Inc. and its contributors.
! 23: * 4. Neither the name of The NetBSD Foundation nor the names of its
! 24: * contributors may be used to endorse or promote products derived
! 25: * from this software without specific prior written permission.
! 26: *
! 27: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
! 28: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
! 29: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
! 30: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
! 31: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
! 32: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
! 33: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
! 34: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
! 35: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
! 36: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 37: * POSSIBILITY OF SUCH DAMAGE.
! 38: */
! 39:
! 40: /*
! 41: * Copyright (c) 1988 University of Utah.
! 42: * Copyright (c) 1990, 1993
! 43: * The Regents of the University of California. All rights reserved.
! 44: *
! 45: * This code is derived from software contributed to Berkeley by
! 46: * the Systems Programming Group of the University of Utah Computer
! 47: * Science Department.
! 48: *
! 49: * Redistribution and use in source and binary forms, with or without
! 50: * modification, are permitted provided that the following conditions
! 51: * are met:
! 52: * 1. Redistributions of source code must retain the above copyright
! 53: * notice, this list of conditions and the following disclaimer.
! 54: * 2. Redistributions in binary form must reproduce the above copyright
! 55: * notice, this list of conditions and the following disclaimer in the
! 56: * documentation and/or other materials provided with the distribution.
! 57: * 3. Neither the name of the University nor the names of its contributors
! 58: * may be used to endorse or promote products derived from this software
! 59: * without specific prior written permission.
! 60: *
! 61: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 62: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 63: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 64: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 65: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 66: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 67: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 68: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 69: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 70: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 71: * SUCH DAMAGE.
! 72: *
! 73: * from: Utah $Hdr: cd.c 1.6 90/11/28$
! 74: *
! 75: * @(#)cd.c 8.2 (Berkeley) 11/16/93
! 76: */
! 77:
! 78: /*
! 79: * Copyright (c) 1995 Carnegie-Mellon University.
! 80: * All rights reserved.
! 81: *
! 82: * Authors: Mark Holland, Jim Zelenka
! 83: *
! 84: * Permission to use, copy, modify and distribute this software and
! 85: * its documentation is hereby granted, provided that both the copyright
! 86: * notice and this permission notice appear in all copies of the
! 87: * software, derivative works or modified versions, and any portions
! 88: * thereof, and that both notices appear in supporting documentation.
! 89: *
! 90: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
! 91: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
! 92: * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
! 93: *
! 94: * Carnegie Mellon requests users of this software to return to
! 95: *
! 96: * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
! 97: * School of Computer Science
! 98: * Carnegie Mellon University
! 99: * Pittsburgh PA 15213-3890
! 100: *
! 101: * any improvements or extensions that they make and grant Carnegie the
! 102: * rights to redistribute these changes.
! 103: */
! 104:
! 105: /*****************************************************************************
! 106: *
! 107: * rf_kintf.c -- The kernel interface routines for RAIDframe.
! 108: *
! 109: *****************************************************************************/
! 110:
! 111: #include <sys/errno.h>
! 112:
! 113: #include <sys/param.h>
! 114: #include <sys/pool.h>
! 115: #include <sys/malloc.h>
! 116: #include <sys/queue.h>
! 117: #include <sys/disk.h>
! 118: #include <sys/device.h>
! 119: #include <sys/stat.h>
! 120: #include <sys/ioctl.h>
! 121: #include <sys/fcntl.h>
! 122: #include <sys/systm.h>
! 123: #include <sys/namei.h>
! 124: #include <sys/conf.h>
! 125: #include <sys/lock.h>
! 126: #include <sys/buf.h>
! 127: #include <sys/user.h>
! 128: #include <sys/reboot.h>
! 129:
! 130: #include "raid.h"
! 131: #include "rf_raid.h"
! 132: #include "rf_raidframe.h"
! 133: #include "rf_copyback.h"
! 134: #include "rf_dag.h"
! 135: #include "rf_dagflags.h"
! 136: #include "rf_desc.h"
! 137: #include "rf_diskqueue.h"
! 138: #include "rf_engine.h"
! 139: #include "rf_acctrace.h"
! 140: #include "rf_etimer.h"
! 141: #include "rf_general.h"
! 142: #include "rf_debugMem.h"
! 143: #include "rf_kintf.h"
! 144: #include "rf_options.h"
! 145: #include "rf_driver.h"
! 146: #include "rf_parityscan.h"
! 147: #include "rf_debugprint.h"
! 148: #include "rf_threadstuff.h"
! 149: #include "rf_configure.h"
! 150:
! 151: int rf_kdebug_level = 0;
! 152:
! 153: #ifdef RAIDDEBUG
! 154: #define db1_printf(a) do { if (rf_kdebug_level > 0) printf a; } while(0)
! 155: #else /* RAIDDEBUG */
! 156: #define db1_printf(a) (void)0
! 157: #endif /* ! RAIDDEBUG */
! 158:
! 159: static RF_Raid_t **raidPtrs; /* Global raid device descriptors. */
! 160:
! 161: RF_DECLARE_STATIC_MUTEX(rf_sparet_wait_mutex);
! 162:
! 163: /* Requests to install a spare table. */
! 164: static RF_SparetWait_t *rf_sparet_wait_queue;
! 165:
! 166: /* Responses from installation process. */
! 167: static RF_SparetWait_t *rf_sparet_resp_queue;
! 168:
! 169: /* Prototypes. */
! 170: void rf_KernelWakeupFunc(struct buf *);
! 171: void rf_InitBP(struct buf *, struct vnode *, unsigned, dev_t, RF_SectorNum_t,
! 172: RF_SectorCount_t, caddr_t, void (*)(struct buf *), void *, int,
! 173: struct proc *);
! 174: void raidinit(RF_Raid_t *);
! 175:
! 176: void raidattach(int);
! 177: daddr64_t raidsize(dev_t);
! 178: int raidopen(dev_t, int, int, struct proc *);
! 179: int raidclose(dev_t, int, int, struct proc *);
! 180: int raidioctl(dev_t, u_long, caddr_t, int, struct proc *);
! 181: int raidwrite(dev_t, struct uio *, int);
! 182: int raidread(dev_t, struct uio *, int);
! 183: void raidstrategy(struct buf *);
! 184: int raiddump(dev_t, daddr64_t, caddr_t, size_t);
! 185:
! 186: /*
! 187: * Pilfered from ccd.c
! 188: */
! 189: struct raidbuf {
! 190: struct buf rf_buf; /* New I/O buf. MUST BE FIRST!!! */
! 191: struct buf *rf_obp; /* Ptr. to original I/O buf. */
! 192: int rf_flags; /* Miscellaneous flags. */
! 193: RF_DiskQueueData_t *req; /* The request that this was part of. */
! 194: };
! 195:
! 196: #define RAIDGETBUF(rs) pool_get(&(rs)->sc_cbufpool, PR_NOWAIT)
! 197: #define RAIDPUTBUF(rs, cbp) pool_put(&(rs)->sc_cbufpool, cbp)
! 198:
! 199: /*
! 200: * Some port (like i386) use a swapgeneric that wants to snoop around
! 201: * in this raid_cd structure. It is preserved (for now) to remain
! 202: * compatible with such practice.
! 203: */
! 204: struct cfdriver raid_cd = {
! 205: NULL, "raid", DV_DISK
! 206: };
! 207:
! 208: /*
! 209: * XXX Not sure if the following should be replacing the raidPtrs above,
! 210: * or if it should be used in conjunction with that...
! 211: */
! 212: struct raid_softc {
! 213: int sc_flags; /* Flags. */
! 214: int sc_cflags; /* Configuration flags. */
! 215: size_t sc_size; /* Size of the raid device. */
! 216: char sc_xname[20]; /* XXX external name. */
! 217: struct disk sc_dkdev; /* Generic disk device info. */
! 218: struct pool sc_cbufpool; /* Component buffer pool. */
! 219: struct buf sc_q; /* Used for the device queue. */
! 220: };
! 221:
! 222: /* sc_flags */
! 223: #define RAIDF_INITED 0x01 /* Unit has been initialized. */
! 224: #define RAIDF_WLABEL 0x02 /* Label area is writable. */
! 225: #define RAIDF_LABELLING 0x04 /* Unit is currently being labelled. */
! 226: #define RAIDF_WANTED 0x40 /* Someone is waiting to obtain a lock. */
! 227: #define RAIDF_LOCKED 0x80 /* Unit is locked. */
! 228:
! 229: int numraid = 0;
! 230:
! 231: /*
! 232: * Here we define a cfattach structure for inserting any new raid device
! 233: * into the device tree. This is needed by some archs that look for
! 234: * bootable devices in there.
! 235: */
! 236: int rf_probe(struct device *, void *, void *);
! 237: void rf_attach(struct device *, struct device *, void *);
! 238: int rf_detach(struct device *, int);
! 239: int rf_activate(struct device *, enum devact);
! 240:
! 241: struct cfattach raid_ca = {
! 242: sizeof(struct raid_softc), rf_probe, rf_attach,
! 243: rf_detach, rf_activate
! 244: };
! 245:
! 246: /*
! 247: * Allow RAIDOUTSTANDING number of simultaneous IO's to this RAID device.
! 248: * Be aware that large numbers can allow the driver to consume a lot of
! 249: * kernel memory, especially on writes, and in degraded mode reads.
! 250: *
! 251: * For example: with a stripe width of 64 blocks (32k) and 5 disks,
! 252: * a single 64K write will typically require 64K for the old data,
! 253: * 64K for the old parity, and 64K for the new parity, for a total
! 254: * of 192K (if the parity buffer is not re-used immediately).
! 255: * Even it if is used immedately, that's still 128K, which when multiplied
! 256: * by say 10 requests, is 1280K, *on top* of the 640K of incoming data.
! 257: *
! 258: * Now in degraded mode, for example, a 64K read on the above setup may
! 259: * require data reconstruction, which will require *all* of the 4 remaining
! 260: * disks to participate -- 4 * 32K/disk == 128K again.
! 261: */
! 262:
! 263: #ifndef RAIDOUTSTANDING
! 264: #define RAIDOUTSTANDING 6
! 265: #endif
! 266:
! 267: /* Declared here, and made public, for the benefit of KVM stuff... */
! 268: struct raid_softc *raid_softc;
! 269: struct raid_softc **raid_scPtrs;
! 270:
! 271: void rf_shutdown_hook(RF_ThreadArg_t);
! 272: void raidgetdefaultlabel(RF_Raid_t *, struct raid_softc *, struct disklabel *);
! 273: void raidgetdisklabel(dev_t, struct disklabel *, int);
! 274:
! 275: int raidlock(struct raid_softc *);
! 276: void raidunlock(struct raid_softc *);
! 277:
! 278: void rf_markalldirty(RF_Raid_t *);
! 279:
! 280: struct device *raidrootdev;
! 281:
! 282: int findblkmajor(struct device *dv);
! 283: char *findblkname(int);
! 284:
! 285: void rf_ReconThread(struct rf_recon_req *);
! 286: /* XXX what I want is: */
! 287: /*void rf_ReconThread(RF_Raid_t *raidPtr);*/
! 288: void rf_RewriteParityThread(RF_Raid_t *raidPtr);
! 289: void rf_CopybackThread(RF_Raid_t *raidPtr);
! 290: void rf_ReconstructInPlaceThread(struct rf_recon_req *);
! 291: #ifdef RAID_AUTOCONFIG
! 292: void rf_buildroothack(void *);
! 293: int rf_reasonable_label(RF_ComponentLabel_t *);
! 294: #endif /* RAID_AUTOCONFIG */
! 295:
! 296: RF_AutoConfig_t *rf_find_raid_components(void);
! 297: RF_ConfigSet_t *rf_create_auto_sets(RF_AutoConfig_t *);
! 298: int rf_does_it_fit(RF_ConfigSet_t *,RF_AutoConfig_t *);
! 299: void rf_create_configuration(RF_AutoConfig_t *,RF_Config_t *,
! 300: RF_Raid_t *);
! 301: int rf_set_autoconfig(RF_Raid_t *, int);
! 302: int rf_set_rootpartition(RF_Raid_t *, int);
! 303: void rf_release_all_vps(RF_ConfigSet_t *);
! 304: void rf_cleanup_config_set(RF_ConfigSet_t *);
! 305: int rf_have_enough_components(RF_ConfigSet_t *);
! 306: int rf_auto_config_set(RF_ConfigSet_t *, int *);
! 307:
! 308: #ifdef RAID_AUTOCONFIG
! 309: static int raidautoconfig = 0; /*
! 310: * Debugging, mostly. Set to 0 to not
! 311: * allow autoconfig to take place.
! 312: * Note that this is overridden by having
! 313: * RAID_AUTOCONFIG as an option in the
! 314: * kernel config file.
! 315: */
! 316: #endif /* RAID_AUTOCONFIG */
! 317:
! 318: int
! 319: rf_probe(struct device *parent, void *match_, void *aux)
! 320: {
! 321: return 0;
! 322: }
! 323:
! 324: void
! 325: rf_attach(struct device *parent, struct device *self, void *aux)
! 326: {
! 327: /*struct raid_softc *raid = (void *)self;*/
! 328: }
! 329:
! 330: int
! 331: rf_detach(struct device *self, int flags)
! 332: {
! 333: return 0;
! 334: }
! 335:
! 336: int
! 337: rf_activate(struct device *self, enum devact act)
! 338: {
! 339: return 0;
! 340: }
! 341:
! 342: void
! 343: raidattach(int num)
! 344: {
! 345: int raidID;
! 346: int i, rc;
! 347: #ifdef RAID_AUTOCONFIG
! 348: RF_AutoConfig_t *ac_list; /* Autoconfig list. */
! 349: RF_ConfigSet_t *config_sets;
! 350: #endif /* RAID_AUTOCONFIG */
! 351:
! 352: db1_printf(("raidattach: Asked for %d units\n", num));
! 353:
! 354: if (num <= 0) {
! 355: #ifdef DIAGNOSTIC
! 356: panic("raidattach: count <= 0");
! 357: #endif /* DIAGNOSTIC */
! 358: return;
! 359: }
! 360:
! 361: /* This is where all the initialization stuff gets done. */
! 362:
! 363: numraid = num;
! 364:
! 365: /* Make some space for requested number of units... */
! 366: RF_Calloc(raidPtrs, num, sizeof(RF_Raid_t *), (RF_Raid_t **));
! 367: if (raidPtrs == NULL) {
! 368: panic("raidPtrs is NULL!!");
! 369: }
! 370:
! 371: rc = rf_mutex_init(&rf_sparet_wait_mutex);
! 372: if (rc) {
! 373: RF_PANIC();
! 374: }
! 375:
! 376: rf_sparet_wait_queue = rf_sparet_resp_queue = NULL;
! 377:
! 378: for (i = 0; i < num; i++)
! 379: raidPtrs[i] = NULL;
! 380: rc = rf_BootRaidframe();
! 381: if (rc == 0)
! 382: printf("Kernelized RAIDframe activated\n");
! 383: else
! 384: panic("Serious error booting RAID !!!");
! 385:
! 386: /*
! 387: * Put together some datastructures like the CCD device does...
! 388: * This lets us lock the device and what-not when it gets opened.
! 389: */
! 390:
! 391: raid_softc = (struct raid_softc *)
! 392: malloc(num * sizeof(struct raid_softc), M_RAIDFRAME, M_NOWAIT);
! 393: if (raid_softc == NULL) {
! 394: printf("WARNING: no memory for RAIDframe driver\n");
! 395: return;
! 396: }
! 397:
! 398: bzero(raid_softc, num * sizeof (struct raid_softc));
! 399:
! 400: raid_scPtrs = (struct raid_softc **)
! 401: malloc(num * sizeof(struct raid_softc *), M_RAIDFRAME,
! 402: M_NOWAIT);
! 403: if (raid_scPtrs == NULL) {
! 404: printf("WARNING: no memory for RAIDframe driver\n");
! 405: return;
! 406: }
! 407:
! 408: bzero(raid_scPtrs, num * sizeof (struct raid_softc *));
! 409:
! 410: raidrootdev = (struct device *)malloc(num * sizeof(struct device),
! 411: M_RAIDFRAME, M_NOWAIT);
! 412: if (raidrootdev == NULL) {
! 413: panic("No memory for RAIDframe driver!!?!?!");
! 414: }
! 415:
! 416: for (raidID = 0; raidID < num; raidID++) {
! 417: #if 0
! 418: SIMPLEQ_INIT(&raid_softc[raidID].sc_q);
! 419: #endif
! 420:
! 421: raidrootdev[raidID].dv_class = DV_DISK;
! 422: raidrootdev[raidID].dv_cfdata = NULL;
! 423: raidrootdev[raidID].dv_unit = raidID;
! 424: raidrootdev[raidID].dv_parent = NULL;
! 425: raidrootdev[raidID].dv_flags = 0;
! 426: snprintf(raidrootdev[raidID].dv_xname,
! 427: sizeof raidrootdev[raidID].dv_xname,"raid%d",raidID);
! 428:
! 429: RF_Calloc(raidPtrs[raidID], 1, sizeof (RF_Raid_t),
! 430: (RF_Raid_t *));
! 431: if (raidPtrs[raidID] == NULL) {
! 432: printf("WARNING: raidPtrs[%d] is NULL\n", raidID);
! 433: numraid = raidID;
! 434: return;
! 435: }
! 436: }
! 437:
! 438: raid_cd.cd_devs = (void **) raid_scPtrs;
! 439: raid_cd.cd_ndevs = num;
! 440:
! 441: #ifdef RAID_AUTOCONFIG
! 442: raidautoconfig = 1;
! 443:
! 444: if (raidautoconfig) {
! 445: /* 1. Locate all RAID components on the system. */
! 446:
! 447: #ifdef RAIDDEBUG
! 448: printf("Searching for raid components...\n");
! 449: #endif /* RAIDDEBUG */
! 450: ac_list = rf_find_raid_components();
! 451:
! 452: /* 2. Sort them into their respective sets. */
! 453:
! 454: config_sets = rf_create_auto_sets(ac_list);
! 455:
! 456: /*
! 457: * 3. Evaluate each set and configure the valid ones
! 458: * This gets done in rf_buildroothack().
! 459: */
! 460:
! 461: /*
! 462: * Schedule the creation of the thread to do the
! 463: * "/ on RAID" stuff.
! 464: */
! 465:
! 466: rf_buildroothack(config_sets);
! 467:
! 468: }
! 469: #endif /* RAID_AUTOCONFIG */
! 470:
! 471: }
! 472:
! 473: #ifdef RAID_AUTOCONFIG
! 474: void
! 475: rf_buildroothack(void *arg)
! 476: {
! 477: RF_ConfigSet_t *config_sets = arg;
! 478: RF_ConfigSet_t *cset;
! 479: RF_ConfigSet_t *next_cset;
! 480: int retcode;
! 481: int raidID;
! 482: int rootID;
! 483: int num_root;
! 484: int majdev;
! 485:
! 486: rootID = 0;
! 487: num_root = 0;
! 488: cset = config_sets;
! 489: while(cset != NULL ) {
! 490: next_cset = cset->next;
! 491: if (rf_have_enough_components(cset) &&
! 492: cset->ac->clabel->autoconfigure==1) {
! 493: retcode = rf_auto_config_set(cset,&raidID);
! 494: if (!retcode) {
! 495: if (cset->rootable) {
! 496: rootID = raidID;
! 497: #ifdef RAIDDEBUG
! 498: printf("eligible root device %d:"
! 499: " raid%d\n", num_root, rootID);
! 500: #endif /* RAIDDEBUG */
! 501: num_root++;
! 502: }
! 503: } else {
! 504: /* The autoconfig didn't work :( */
! 505: #ifdef RAIDDEBUG
! 506: printf("Autoconfig failed with code %d for"
! 507: " raid%d\n", retcode, raidID);
! 508: #endif /* RAIDDEBUG */
! 509: rf_release_all_vps(cset);
! 510: }
! 511: } else {
! 512: /*
! 513: * We're not autoconfiguring this set...
! 514: * Release the associated resources.
! 515: */
! 516: rf_release_all_vps(cset);
! 517: }
! 518: /* Cleanup. */
! 519: rf_cleanup_config_set(cset);
! 520: cset = next_cset;
! 521: }
! 522: if (boothowto & RB_ASKNAME) {
! 523: /* We don't auto-config... */
! 524: } else {
! 525: /* They didn't ask, and we found something bootable... */
! 526:
! 527: if (num_root == 1) {
! 528: majdev = findblkmajor(&raidrootdev[rootID]);
! 529: if (majdev < 0)
! 530: boothowto |= RB_ASKNAME;
! 531: else {
! 532: rootdev = MAKEDISKDEV(majdev,rootID,0);
! 533: boothowto |= RB_DFLTROOT;
! 534: }
! 535: } else if (num_root > 1) {
! 536: /* We can't guess... Require the user to answer... */
! 537: boothowto |= RB_ASKNAME;
! 538: }
! 539: }
! 540: }
! 541: #endif /* RAID_AUTOCONFIG */
! 542:
! 543: void
! 544: rf_shutdown_hook(RF_ThreadArg_t arg)
! 545: {
! 546: int unit;
! 547: struct raid_softc *rs;
! 548: RF_Raid_t *raidPtr;
! 549:
! 550: /* Don't do it if we are not "safe". */
! 551: if (boothowto & RB_NOSYNC)
! 552: return;
! 553:
! 554: raidPtr = (RF_Raid_t *) arg;
! 555: unit = raidPtr->raidid;
! 556: rs = &raid_softc[unit];
! 557:
! 558: /* Shutdown the system. */
! 559:
! 560: if (rf_hook_cookies != NULL && rf_hook_cookies[unit] != NULL)
! 561: rf_hook_cookies[unit] = NULL;
! 562:
! 563: rf_Shutdown(raidPtr);
! 564:
! 565: pool_destroy(&rs->sc_cbufpool);
! 566:
! 567: /* It's no longer initialized... */
! 568: rs->sc_flags &= ~RAIDF_INITED;
! 569:
! 570: /* config_detach the device. */
! 571: config_detach(device_lookup(&raid_cd, unit), 0);
! 572:
! 573: /* Detach the disk. */
! 574: disk_detach(&rs->sc_dkdev);
! 575: }
! 576:
! 577: daddr64_t
! 578: raidsize(dev_t dev)
! 579: {
! 580: struct raid_softc *rs;
! 581: struct disklabel *lp;
! 582: int part, unit, omask, size;
! 583:
! 584: unit = DISKUNIT(dev);
! 585: if (unit >= numraid)
! 586: return (-1);
! 587: rs = &raid_softc[unit];
! 588:
! 589: if ((rs->sc_flags & RAIDF_INITED) == 0)
! 590: return (-1);
! 591:
! 592: part = DISKPART(dev);
! 593: omask = rs->sc_dkdev.dk_openmask & (1 << part);
! 594: lp = rs->sc_dkdev.dk_label;
! 595:
! 596: if (omask == 0 && raidopen(dev, 0, S_IFBLK, curproc))
! 597: return (-1);
! 598:
! 599: if (lp->d_partitions[part].p_fstype != FS_SWAP)
! 600: size = -1;
! 601: else
! 602: size = DL_GETPSIZE(&lp->d_partitions[part]) *
! 603: (lp->d_secsize / DEV_BSIZE);
! 604:
! 605: if (omask == 0 && raidclose(dev, 0, S_IFBLK, curproc))
! 606: return (-1);
! 607:
! 608: return (size);
! 609:
! 610: }
! 611:
! 612: int
! 613: raiddump(dev_t dev, daddr64_t blkno, caddr_t va, size_t size)
! 614: {
! 615: /* Not implemented. */
! 616: return (ENXIO);
! 617: }
! 618:
! 619: /* ARGSUSED */
! 620: int
! 621: raidopen(dev_t dev, int flags, int fmt, struct proc *p)
! 622: {
! 623: int unit = DISKUNIT(dev);
! 624: struct raid_softc *rs;
! 625: int part,pmask;
! 626: int error = 0;
! 627:
! 628: if (unit >= numraid)
! 629: return (ENXIO);
! 630: rs = &raid_softc[unit];
! 631:
! 632: if ((error = raidlock(rs)) != 0)
! 633: return (error);
! 634:
! 635: part = DISKPART(dev);
! 636: pmask = (1 << part);
! 637:
! 638: db1_printf(
! 639: ("Opening raid device number: %d partition: %d\n", unit, part));
! 640:
! 641:
! 642: if ((rs->sc_flags & RAIDF_INITED) && (rs->sc_dkdev.dk_openmask == 0))
! 643: raidgetdisklabel(dev, rs->sc_dkdev.dk_label, 0);
! 644:
! 645: /* Make sure that this partition exists. */
! 646:
! 647: if (part != RAW_PART) {
! 648: db1_printf(("Not a raw partition..\n"));
! 649: if (((rs->sc_flags & RAIDF_INITED) == 0) ||
! 650: ((part >= rs->sc_dkdev.dk_label->d_npartitions) ||
! 651: (rs->sc_dkdev.dk_label->d_partitions[part].p_fstype ==
! 652: FS_UNUSED))) {
! 653: error = ENXIO;
! 654: raidunlock(rs);
! 655: db1_printf(("Bailing out...\n"));
! 656: return (error);
! 657: }
! 658: }
! 659:
! 660: /* Prevent this unit from being unconfigured while opened. */
! 661: switch (fmt) {
! 662: case S_IFCHR:
! 663: rs->sc_dkdev.dk_copenmask |= pmask;
! 664: break;
! 665:
! 666: case S_IFBLK:
! 667: rs->sc_dkdev.dk_bopenmask |= pmask;
! 668: break;
! 669: }
! 670:
! 671: if ((rs->sc_dkdev.dk_openmask == 0) &&
! 672: ((rs->sc_flags & RAIDF_INITED) != 0)) {
! 673: /*
! 674: * First one... Mark things as dirty... Note that we *MUST*
! 675: * have done a configure before this. I DO NOT WANT TO BE
! 676: * SCRIBBLING TO RANDOM COMPONENTS UNTIL IT'S BEEN DETERMINED
! 677: * THAT THEY BELONG TOGETHER!!!!!
! 678: */
! 679: /*
! 680: * XXX should check to see if we're only open for reading
! 681: * here... If so, we needn't do this, but then need some
! 682: * other way of keeping track of what's happened...
! 683: */
! 684:
! 685: rf_markalldirty( raidPtrs[unit] );
! 686: }
! 687:
! 688: rs->sc_dkdev.dk_openmask =
! 689: rs->sc_dkdev.dk_copenmask | rs->sc_dkdev.dk_bopenmask;
! 690:
! 691: raidunlock(rs);
! 692:
! 693: return (error);
! 694: }
! 695:
! 696: /* ARGSUSED */
! 697: int
! 698: raidclose(dev_t dev, int flags, int fmt, struct proc *p)
! 699: {
! 700: int unit = DISKUNIT(dev);
! 701: struct raid_softc *rs;
! 702: int error = 0;
! 703: int part;
! 704:
! 705: if (unit >= numraid)
! 706: return (ENXIO);
! 707: rs = &raid_softc[unit];
! 708:
! 709: if ((error = raidlock(rs)) != 0)
! 710: return (error);
! 711:
! 712: part = DISKPART(dev);
! 713:
! 714: /* ...that much closer to allowing unconfiguration... */
! 715: switch (fmt) {
! 716: case S_IFCHR:
! 717: rs->sc_dkdev.dk_copenmask &= ~(1 << part);
! 718: break;
! 719:
! 720: case S_IFBLK:
! 721: rs->sc_dkdev.dk_bopenmask &= ~(1 << part);
! 722: break;
! 723: }
! 724: rs->sc_dkdev.dk_openmask =
! 725: rs->sc_dkdev.dk_copenmask | rs->sc_dkdev.dk_bopenmask;
! 726:
! 727: if ((rs->sc_dkdev.dk_openmask == 0) &&
! 728: ((rs->sc_flags & RAIDF_INITED) != 0)) {
! 729: /*
! 730: * Last one... Device is not unconfigured yet.
! 731: * Device shutdown has taken care of setting the
! 732: * clean bits if RAIDF_INITED is not set.
! 733: * Mark things as clean...
! 734: */
! 735: db1_printf(("Last one on raid%d. Updating status.\n",unit));
! 736: rf_update_component_labels(raidPtrs[unit],
! 737: RF_FINAL_COMPONENT_UPDATE);
! 738: }
! 739:
! 740: raidunlock(rs);
! 741: return (0);
! 742: }
! 743:
! 744: void
! 745: raidstrategy(struct buf *bp)
! 746: {
! 747: int s;
! 748:
! 749: unsigned int raidID = DISKUNIT(bp->b_dev);
! 750: RF_Raid_t *raidPtr;
! 751: struct raid_softc *rs = &raid_softc[raidID];
! 752: struct disklabel *lp;
! 753: int wlabel;
! 754:
! 755: s = splbio();
! 756:
! 757: if ((rs->sc_flags & RAIDF_INITED) ==0) {
! 758: bp->b_error = ENXIO;
! 759: bp->b_flags |= B_ERROR;
! 760: bp->b_resid = bp->b_bcount;
! 761: biodone(bp);
! 762: goto raidstrategy_end;
! 763: }
! 764: if (raidID >= numraid || !raidPtrs[raidID]) {
! 765: bp->b_error = ENODEV;
! 766: bp->b_flags |= B_ERROR;
! 767: bp->b_resid = bp->b_bcount;
! 768: biodone(bp);
! 769: goto raidstrategy_end;
! 770: }
! 771: raidPtr = raidPtrs[raidID];
! 772: if (!raidPtr->valid) {
! 773: bp->b_error = ENODEV;
! 774: bp->b_flags |= B_ERROR;
! 775: bp->b_resid = bp->b_bcount;
! 776: biodone(bp);
! 777: goto raidstrategy_end;
! 778: }
! 779: if (bp->b_bcount == 0) {
! 780: db1_printf(("b_bcount is zero..\n"));
! 781: biodone(bp);
! 782: goto raidstrategy_end;
! 783: }
! 784: lp = rs->sc_dkdev.dk_label;
! 785:
! 786: /*
! 787: * Do bounds checking and adjust transfer. If there's an
! 788: * error, the bounds check will flag that for us.
! 789: */
! 790: wlabel = rs->sc_flags & (RAIDF_WLABEL | RAIDF_LABELLING);
! 791: if (DISKPART(bp->b_dev) != RAW_PART)
! 792: if (bounds_check_with_label(bp, lp, wlabel) <= 0) {
! 793: db1_printf(("Bounds check failed!!:%d %d\n",
! 794: (int)bp->b_blkno, (int)wlabel));
! 795: biodone(bp);
! 796: goto raidstrategy_end;
! 797: }
! 798:
! 799: bp->b_resid = 0;
! 800:
! 801: bp->b_actf = rs->sc_q.b_actf;
! 802: rs->sc_q.b_actf = bp;
! 803: rs->sc_q.b_active++;
! 804:
! 805: raidstart(raidPtrs[raidID]);
! 806:
! 807: raidstrategy_end:
! 808: splx(s);
! 809: }
! 810:
! 811: /* ARGSUSED */
! 812: int
! 813: raidread(dev_t dev, struct uio *uio, int flags)
! 814: {
! 815: int unit = DISKUNIT(dev);
! 816: struct raid_softc *rs;
! 817: int part;
! 818:
! 819: if (unit >= numraid)
! 820: return (ENXIO);
! 821: rs = &raid_softc[unit];
! 822:
! 823: if ((rs->sc_flags & RAIDF_INITED) == 0)
! 824: return (ENXIO);
! 825: part = DISKPART(dev);
! 826:
! 827: db1_printf(("raidread: unit: %d partition: %d\n", unit, part));
! 828:
! 829: return (physio(raidstrategy, NULL, dev, B_READ, minphys, uio));
! 830: }
! 831:
! 832: /* ARGSUSED */
! 833: int
! 834: raidwrite(dev_t dev, struct uio *uio, int flags)
! 835: {
! 836: int unit = DISKUNIT(dev);
! 837: struct raid_softc *rs;
! 838:
! 839: if (unit >= numraid)
! 840: return (ENXIO);
! 841: rs = &raid_softc[unit];
! 842:
! 843: if ((rs->sc_flags & RAIDF_INITED) == 0)
! 844: return (ENXIO);
! 845: db1_printf(("raidwrite\n"));
! 846: return (physio(raidstrategy, NULL, dev, B_WRITE, minphys, uio));
! 847: }
! 848:
! 849: int
! 850: raidioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
! 851: {
! 852: int unit = DISKUNIT(dev);
! 853: int error = 0;
! 854: int part, pmask;
! 855: struct raid_softc *rs;
! 856: RF_Config_t *k_cfg, *u_cfg;
! 857: RF_Raid_t *raidPtr;
! 858: RF_RaidDisk_t *diskPtr;
! 859: RF_AccTotals_t *totals;
! 860: RF_DeviceConfig_t *d_cfg, **ucfgp;
! 861: u_char *specific_buf;
! 862: int retcode = 0;
! 863: int row;
! 864: int column;
! 865: struct rf_recon_req *rrcopy, *rr;
! 866: RF_ComponentLabel_t *clabel;
! 867: RF_ComponentLabel_t ci_label;
! 868: RF_ComponentLabel_t **clabel_ptr;
! 869: RF_SingleComponent_t *sparePtr,*componentPtr;
! 870: RF_SingleComponent_t hot_spare;
! 871: RF_SingleComponent_t component;
! 872: RF_ProgressInfo_t progressInfo, **progressInfoPtr;
! 873: int i, j, d;
! 874:
! 875: if (unit >= numraid)
! 876: return (ENXIO);
! 877: rs = &raid_softc[unit];
! 878: raidPtr = raidPtrs[unit];
! 879:
! 880: db1_printf(("raidioctl: %d %d %d %d\n", (int)dev, (int)DISKPART(dev),
! 881: (int)unit, (int)cmd));
! 882:
! 883: /* Must be open for writes for these commands... */
! 884: switch (cmd) {
! 885: case DIOCSDINFO:
! 886: case DIOCWDINFO:
! 887: case DIOCWLABEL:
! 888: if ((flag & FWRITE) == 0)
! 889: return (EBADF);
! 890: }
! 891:
! 892: /* Must be initialized for these... */
! 893: switch (cmd) {
! 894: case DIOCGDINFO:
! 895: case DIOCSDINFO:
! 896: case DIOCWDINFO:
! 897: case DIOCGPART:
! 898: case DIOCWLABEL:
! 899: case DIOCGPDINFO:
! 900: case RAIDFRAME_SHUTDOWN:
! 901: case RAIDFRAME_REWRITEPARITY:
! 902: case RAIDFRAME_GET_INFO:
! 903: case RAIDFRAME_RESET_ACCTOTALS:
! 904: case RAIDFRAME_GET_ACCTOTALS:
! 905: case RAIDFRAME_KEEP_ACCTOTALS:
! 906: case RAIDFRAME_GET_SIZE:
! 907: case RAIDFRAME_FAIL_DISK:
! 908: case RAIDFRAME_COPYBACK:
! 909: case RAIDFRAME_CHECK_RECON_STATUS:
! 910: case RAIDFRAME_CHECK_RECON_STATUS_EXT:
! 911: case RAIDFRAME_GET_COMPONENT_LABEL:
! 912: case RAIDFRAME_SET_COMPONENT_LABEL:
! 913: case RAIDFRAME_ADD_HOT_SPARE:
! 914: case RAIDFRAME_REMOVE_HOT_SPARE:
! 915: case RAIDFRAME_INIT_LABELS:
! 916: case RAIDFRAME_REBUILD_IN_PLACE:
! 917: case RAIDFRAME_CHECK_PARITY:
! 918: case RAIDFRAME_CHECK_PARITYREWRITE_STATUS:
! 919: case RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT:
! 920: case RAIDFRAME_CHECK_COPYBACK_STATUS:
! 921: case RAIDFRAME_CHECK_COPYBACK_STATUS_EXT:
! 922: case RAIDFRAME_SET_AUTOCONFIG:
! 923: case RAIDFRAME_SET_ROOT:
! 924: case RAIDFRAME_DELETE_COMPONENT:
! 925: case RAIDFRAME_INCORPORATE_HOT_SPARE:
! 926: if ((rs->sc_flags & RAIDF_INITED) == 0)
! 927: return (ENXIO);
! 928: }
! 929:
! 930: switch (cmd) {
! 931: /* Configure the system. */
! 932: case RAIDFRAME_CONFIGURE:
! 933:
! 934: if (raidPtr->valid) {
! 935: /* There is a valid RAID set running on this unit ! */
! 936: printf("raid%d: Device already configured!\n",unit);
! 937: return(EINVAL);
! 938: }
! 939:
! 940: /*
! 941: * Copy-in the configuration information.
! 942: * data points to a pointer to the configuration structure.
! 943: */
! 944: u_cfg = *((RF_Config_t **)data);
! 945: RF_Malloc(k_cfg, sizeof (RF_Config_t), (RF_Config_t *));
! 946: if (k_cfg == NULL) {
! 947: return (ENOMEM);
! 948: }
! 949: retcode = copyin((caddr_t)u_cfg, (caddr_t)k_cfg,
! 950: sizeof (RF_Config_t));
! 951: if (retcode) {
! 952: RF_Free(k_cfg, sizeof(RF_Config_t));
! 953: return (retcode);
! 954: }
! 955:
! 956: /*
! 957: * Allocate a buffer for the layout-specific data,
! 958: * and copy it in.
! 959: */
! 960: if (k_cfg->layoutSpecificSize) {
! 961: if (k_cfg->layoutSpecificSize > 10000) {
! 962: /* Sanity check. */
! 963: RF_Free(k_cfg, sizeof(RF_Config_t));
! 964: return (EINVAL);
! 965: }
! 966: RF_Malloc(specific_buf, k_cfg->layoutSpecificSize,
! 967: (u_char *));
! 968: if (specific_buf == NULL) {
! 969: RF_Free(k_cfg, sizeof (RF_Config_t));
! 970: return (ENOMEM);
! 971: }
! 972: retcode = copyin(k_cfg->layoutSpecific,
! 973: (caddr_t)specific_buf, k_cfg->layoutSpecificSize);
! 974: if (retcode) {
! 975: RF_Free(k_cfg, sizeof(RF_Config_t));
! 976: RF_Free(specific_buf,
! 977: k_cfg->layoutSpecificSize);
! 978: return (retcode);
! 979: }
! 980: } else
! 981: specific_buf = NULL;
! 982: k_cfg->layoutSpecific = specific_buf;
! 983:
! 984: /*
! 985: * We should do some kind of sanity check on the
! 986: * configuration.
! 987: * Store the sum of all the bytes in the last byte ?
! 988: */
! 989:
! 990: /*
! 991: * Clear the entire RAID descriptor, just to make sure
! 992: * there is no stale data left in the case of a
! 993: * reconfiguration.
! 994: */
! 995: bzero((char *) raidPtr, sizeof(RF_Raid_t));
! 996:
! 997: /* Configure the system. */
! 998: raidPtr->raidid = unit;
! 999:
! 1000: retcode = rf_Configure(raidPtr, k_cfg, NULL);
! 1001:
! 1002: if (retcode == 0) {
! 1003:
! 1004: /*
! 1005: * Allow this many simultaneous IO's to
! 1006: * this RAID device.
! 1007: */
! 1008: raidPtr->openings = RAIDOUTSTANDING;
! 1009:
! 1010: raidinit(raidPtr);
! 1011: rf_markalldirty(raidPtr);
! 1012: }
! 1013:
! 1014: /* Free the buffers. No return code here. */
! 1015: if (k_cfg->layoutSpecificSize) {
! 1016: RF_Free(specific_buf, k_cfg->layoutSpecificSize);
! 1017: }
! 1018: RF_Free(k_cfg, sizeof (RF_Config_t));
! 1019:
! 1020: return (retcode);
! 1021:
! 1022: case RAIDFRAME_SHUTDOWN:
! 1023: /* Shutdown the system. */
! 1024:
! 1025: if ((error = raidlock(rs)) != 0)
! 1026: return (error);
! 1027:
! 1028: /*
! 1029: * If somebody has a partition mounted, we shouldn't
! 1030: * shutdown.
! 1031: */
! 1032:
! 1033: part = DISKPART(dev);
! 1034: pmask = (1 << part);
! 1035: if ((rs->sc_dkdev.dk_openmask & ~pmask) ||
! 1036: ((rs->sc_dkdev.dk_bopenmask & pmask) &&
! 1037: (rs->sc_dkdev.dk_copenmask & pmask))) {
! 1038: raidunlock(rs);
! 1039: return (EBUSY);
! 1040: }
! 1041:
! 1042: if ((retcode = rf_Shutdown(raidPtr)) == 0) {
! 1043:
! 1044: pool_destroy(&rs->sc_cbufpool);
! 1045:
! 1046: /* It's no longer initialized... */
! 1047: rs->sc_flags &= ~RAIDF_INITED;
! 1048:
! 1049: /* config_detach the device. */
! 1050: config_detach(device_lookup(&raid_cd, unit), 0);
! 1051:
! 1052: /* Detach the disk. */
! 1053: disk_detach(&rs->sc_dkdev);
! 1054: }
! 1055:
! 1056: raidunlock(rs);
! 1057:
! 1058: return (retcode);
! 1059:
! 1060: case RAIDFRAME_GET_COMPONENT_LABEL:
! 1061: clabel_ptr = (RF_ComponentLabel_t **) data;
! 1062: /*
! 1063: * We need to read the component label for the disk indicated
! 1064: * by row,column in clabel.
! 1065: */
! 1066:
! 1067: /*
! 1068: * For practice, let's get it directly from disk, rather
! 1069: * than from the in-core copy.
! 1070: */
! 1071: RF_Malloc( clabel, sizeof( RF_ComponentLabel_t ),
! 1072: (RF_ComponentLabel_t *));
! 1073: if (clabel == NULL)
! 1074: return (ENOMEM);
! 1075:
! 1076: bzero((char *) clabel, sizeof(RF_ComponentLabel_t));
! 1077:
! 1078: retcode = copyin( *clabel_ptr, clabel,
! 1079: sizeof(RF_ComponentLabel_t));
! 1080:
! 1081: if (retcode) {
! 1082: RF_Free( clabel, sizeof(RF_ComponentLabel_t));
! 1083: return(retcode);
! 1084: }
! 1085:
! 1086: row = clabel->row;
! 1087: column = clabel->column;
! 1088:
! 1089: if ((row < 0) || (row >= raidPtr->numRow) ||
! 1090: (column < 0) || (column >= raidPtr->numCol)) {
! 1091: RF_Free( clabel, sizeof(RF_ComponentLabel_t));
! 1092: return(EINVAL);
! 1093: }
! 1094:
! 1095: raidread_component_label(raidPtr->Disks[row][column].dev,
! 1096: raidPtr->raid_cinfo[row][column].ci_vp, clabel );
! 1097:
! 1098: retcode = copyout((caddr_t) clabel,
! 1099: (caddr_t) *clabel_ptr,
! 1100: sizeof(RF_ComponentLabel_t));
! 1101: RF_Free( clabel, sizeof(RF_ComponentLabel_t));
! 1102: return (retcode);
! 1103:
! 1104: case RAIDFRAME_SET_COMPONENT_LABEL:
! 1105: clabel = (RF_ComponentLabel_t *) data;
! 1106:
! 1107: /* XXX check the label for valid stuff... */
! 1108: /*
! 1109: * Note that some things *should not* get modified --
! 1110: * the user should be re-initing the labels instead of
! 1111: * trying to patch things.
! 1112: */
! 1113:
! 1114: #ifdef RAIDDEBUG
! 1115: printf("Got component label:\n");
! 1116: printf("Version: %d\n",clabel->version);
! 1117: printf("Serial Number: %d\n",clabel->serial_number);
! 1118: printf("Mod counter: %d\n",clabel->mod_counter);
! 1119: printf("Row: %d\n", clabel->row);
! 1120: printf("Column: %d\n", clabel->column);
! 1121: printf("Num Rows: %d\n", clabel->num_rows);
! 1122: printf("Num Columns: %d\n", clabel->num_columns);
! 1123: printf("Clean: %d\n", clabel->clean);
! 1124: printf("Status: %d\n", clabel->status);
! 1125: #endif /* RAIDDEBUG */
! 1126:
! 1127: row = clabel->row;
! 1128: column = clabel->column;
! 1129:
! 1130: if ((row < 0) || (row >= raidPtr->numRow) ||
! 1131: (column < 0) || (column >= raidPtr->numCol)) {
! 1132: return(EINVAL);
! 1133: }
! 1134:
! 1135: /* XXX this isn't allowed to do anything for now :-) */
! 1136: #if 0
! 1137: raidwrite_component_label(raidPtr->Disks[row][column].dev,
! 1138: raidPtr->raid_cinfo[row][column].ci_vp, clabel );
! 1139: #endif
! 1140: return (0);
! 1141:
! 1142: case RAIDFRAME_INIT_LABELS:
! 1143: clabel = (RF_ComponentLabel_t *) data;
! 1144: /*
! 1145: * We only want the serial number from the above.
! 1146: * We get all the rest of the information from
! 1147: * the config that was used to create this RAID
! 1148: * set.
! 1149: */
! 1150:
! 1151: raidPtr->serial_number = clabel->serial_number;
! 1152:
! 1153: raid_init_component_label(raidPtr, &ci_label);
! 1154: ci_label.serial_number = clabel->serial_number;
! 1155:
! 1156: for(row=0;row<raidPtr->numRow;row++) {
! 1157: ci_label.row = row;
! 1158: for(column=0;column<raidPtr->numCol;column++) {
! 1159: diskPtr = &raidPtr->Disks[row][column];
! 1160: if (!RF_DEAD_DISK(diskPtr->status)) {
! 1161: ci_label.partitionSize =
! 1162: diskPtr->partitionSize;
! 1163: ci_label.column = column;
! 1164: raidwrite_component_label(
! 1165: raidPtr->Disks[row][column].dev,
! 1166: raidPtr->raid_cinfo[row][column].ci_vp,
! 1167: &ci_label );
! 1168: }
! 1169: }
! 1170: }
! 1171:
! 1172: return (retcode);
! 1173:
! 1174: case RAIDFRAME_REWRITEPARITY:
! 1175:
! 1176: if (raidPtr->Layout.map->faultsTolerated == 0) {
! 1177: /* Parity for RAID 0 is trivially correct. */
! 1178: raidPtr->parity_good = RF_RAID_CLEAN;
! 1179: return(0);
! 1180: }
! 1181:
! 1182:
! 1183: if (raidPtr->parity_rewrite_in_progress == 1) {
! 1184: /* Re-write is already in progress ! */
! 1185: return(EINVAL);
! 1186: }
! 1187:
! 1188: retcode = RF_CREATE_THREAD(raidPtr->parity_rewrite_thread,
! 1189: rf_RewriteParityThread,
! 1190: raidPtr,"raid_parity");
! 1191:
! 1192: return (retcode);
! 1193:
! 1194: case RAIDFRAME_SET_AUTOCONFIG:
! 1195: d = rf_set_autoconfig(raidPtr, *(int *) data);
! 1196: db1_printf(("New autoconfig value is: %d\n", d));
! 1197: *(int *) data = d;
! 1198: return (retcode);
! 1199:
! 1200: case RAIDFRAME_SET_ROOT:
! 1201: d = rf_set_rootpartition(raidPtr, *(int *) data);
! 1202: db1_printf(("New rootpartition value is: %d\n", d));
! 1203: *(int *) data = d;
! 1204: return (retcode);
! 1205:
! 1206:
! 1207: case RAIDFRAME_ADD_HOT_SPARE:
! 1208: sparePtr = (RF_SingleComponent_t *) data;
! 1209: memcpy( &hot_spare, sparePtr, sizeof(RF_SingleComponent_t));
! 1210: retcode = rf_add_hot_spare(raidPtr, &hot_spare);
! 1211: return(retcode);
! 1212:
! 1213: case RAIDFRAME_REMOVE_HOT_SPARE:
! 1214: return(retcode);
! 1215:
! 1216: case RAIDFRAME_DELETE_COMPONENT:
! 1217: componentPtr = (RF_SingleComponent_t *)data;
! 1218: memcpy( &component, componentPtr,
! 1219: sizeof(RF_SingleComponent_t));
! 1220: retcode = rf_delete_component(raidPtr, &component);
! 1221: return(retcode);
! 1222:
! 1223: case RAIDFRAME_INCORPORATE_HOT_SPARE:
! 1224: componentPtr = (RF_SingleComponent_t *)data;
! 1225: memcpy( &component, componentPtr,
! 1226: sizeof(RF_SingleComponent_t));
! 1227: retcode = rf_incorporate_hot_spare(raidPtr, &component);
! 1228: return(retcode);
! 1229:
! 1230: case RAIDFRAME_REBUILD_IN_PLACE:
! 1231:
! 1232: if (raidPtr->Layout.map->faultsTolerated == 0) {
! 1233: /* Can't do this on a RAID 0 !! */
! 1234: return(EINVAL);
! 1235: }
! 1236:
! 1237: if (raidPtr->recon_in_progress == 1) {
! 1238: /* A reconstruct is already in progress ! */
! 1239: return(EINVAL);
! 1240: }
! 1241:
! 1242: componentPtr = (RF_SingleComponent_t *) data;
! 1243: memcpy( &component, componentPtr,
! 1244: sizeof(RF_SingleComponent_t));
! 1245: row = component.row;
! 1246: column = component.column;
! 1247: db1_printf(("Rebuild: %d %d\n",row, column));
! 1248: if ((row < 0) || (row >= raidPtr->numRow) ||
! 1249: (column < 0) || (column >= raidPtr->numCol)) {
! 1250: return(EINVAL);
! 1251: }
! 1252:
! 1253: RF_Malloc(rrcopy, sizeof(*rrcopy), (struct rf_recon_req *));
! 1254: if (rrcopy == NULL)
! 1255: return(ENOMEM);
! 1256:
! 1257: rrcopy->raidPtr = (void *) raidPtr;
! 1258: rrcopy->row = row;
! 1259: rrcopy->col = column;
! 1260:
! 1261: retcode = RF_CREATE_THREAD(raidPtr->recon_thread,
! 1262: rf_ReconstructInPlaceThread,
! 1263: rrcopy,"raid_reconip");
! 1264:
! 1265: return (retcode);
! 1266:
! 1267: case RAIDFRAME_GET_INFO:
! 1268: if (!raidPtr->valid)
! 1269: return (ENODEV);
! 1270: ucfgp = (RF_DeviceConfig_t **) data;
! 1271: RF_Malloc(d_cfg, sizeof(RF_DeviceConfig_t),
! 1272: (RF_DeviceConfig_t *));
! 1273: if (d_cfg == NULL)
! 1274: return (ENOMEM);
! 1275: bzero((char *) d_cfg, sizeof(RF_DeviceConfig_t));
! 1276: d_cfg->rows = raidPtr->numRow;
! 1277: d_cfg->cols = raidPtr->numCol;
! 1278: d_cfg->ndevs = raidPtr->numRow * raidPtr->numCol;
! 1279: if (d_cfg->ndevs >= RF_MAX_DISKS) {
! 1280: RF_Free(d_cfg, sizeof(RF_DeviceConfig_t));
! 1281: return (ENOMEM);
! 1282: }
! 1283: d_cfg->nspares = raidPtr->numSpare;
! 1284: if (d_cfg->nspares >= RF_MAX_DISKS) {
! 1285: RF_Free(d_cfg, sizeof(RF_DeviceConfig_t));
! 1286: return (ENOMEM);
! 1287: }
! 1288: d_cfg->maxqdepth = raidPtr->maxQueueDepth;
! 1289: d = 0;
! 1290: for (i = 0; i < d_cfg->rows; i++) {
! 1291: for (j = 0; j < d_cfg->cols; j++) {
! 1292: d_cfg->devs[d] = raidPtr->Disks[i][j];
! 1293: d++;
! 1294: }
! 1295: }
! 1296: for (j = d_cfg->cols, i = 0; i < d_cfg->nspares; i++, j++) {
! 1297: d_cfg->spares[i] = raidPtr->Disks[0][j];
! 1298: }
! 1299: retcode = copyout((caddr_t) d_cfg, (caddr_t) * ucfgp,
! 1300: sizeof(RF_DeviceConfig_t));
! 1301: RF_Free(d_cfg, sizeof(RF_DeviceConfig_t));
! 1302:
! 1303: return (retcode);
! 1304:
! 1305: case RAIDFRAME_CHECK_PARITY:
! 1306: *(int *) data = raidPtr->parity_good;
! 1307: return (0);
! 1308:
! 1309: case RAIDFRAME_RESET_ACCTOTALS:
! 1310: bzero(&raidPtr->acc_totals, sizeof(raidPtr->acc_totals));
! 1311: return (0);
! 1312:
! 1313: case RAIDFRAME_GET_ACCTOTALS:
! 1314: totals = (RF_AccTotals_t *) data;
! 1315: *totals = raidPtr->acc_totals;
! 1316: return (0);
! 1317:
! 1318: case RAIDFRAME_KEEP_ACCTOTALS:
! 1319: raidPtr->keep_acc_totals = *(int *)data;
! 1320: return (0);
! 1321:
! 1322: case RAIDFRAME_GET_SIZE:
! 1323: *(int *) data = raidPtr->totalSectors;
! 1324: return (0);
! 1325:
! 1326: /* Fail a disk & optionally start reconstruction. */
! 1327: case RAIDFRAME_FAIL_DISK:
! 1328: rr = (struct rf_recon_req *)data;
! 1329:
! 1330: if (rr->row < 0 || rr->row >= raidPtr->numRow ||
! 1331: rr->col < 0 || rr->col >= raidPtr->numCol)
! 1332: return (EINVAL);
! 1333:
! 1334: db1_printf(("raid%d: Failing the disk: row: %d col: %d\n",
! 1335: unit, rr->row, rr->col));
! 1336:
! 1337: /*
! 1338: * Make a copy of the recon request so that we don't
! 1339: * rely on the user's buffer.
! 1340: */
! 1341: RF_Malloc(rrcopy, sizeof(*rrcopy), (struct rf_recon_req *));
! 1342: if (rrcopy == NULL)
! 1343: return(ENOMEM);
! 1344: bcopy(rr, rrcopy, sizeof(*rr));
! 1345: rrcopy->raidPtr = (void *)raidPtr;
! 1346:
! 1347: retcode = RF_CREATE_THREAD(raidPtr->recon_thread,
! 1348: rf_ReconThread,
! 1349: rrcopy,"raid_recon");
! 1350: return (0);
! 1351:
! 1352: /*
! 1353: * Invoke a copyback operation after recon on whatever
! 1354: * disk needs it, if any.
! 1355: */
! 1356: case RAIDFRAME_COPYBACK:
! 1357: if (raidPtr->Layout.map->faultsTolerated == 0) {
! 1358: /* This makes no sense on a RAID 0 !! */
! 1359: return(EINVAL);
! 1360: }
! 1361:
! 1362: if (raidPtr->copyback_in_progress == 1) {
! 1363: /* Copyback is already in progress ! */
! 1364: return(EINVAL);
! 1365: }
! 1366:
! 1367: retcode = RF_CREATE_THREAD(raidPtr->copyback_thread,
! 1368: rf_CopybackThread,
! 1369: raidPtr,"raid_copyback");
! 1370: return (retcode);
! 1371:
! 1372: /* Return the percentage completion of reconstruction. */
! 1373: case RAIDFRAME_CHECK_RECON_STATUS:
! 1374: if (raidPtr->Layout.map->faultsTolerated == 0) {
! 1375: /*
! 1376: * This makes no sense on a RAID 0, so tell the
! 1377: * user it's done.
! 1378: */
! 1379: *(int *) data = 100;
! 1380: return(0);
! 1381: }
! 1382: row = 0; /* XXX we only consider a single row... */
! 1383: if (raidPtr->status[row] != rf_rs_reconstructing)
! 1384: *(int *)data = 100;
! 1385: else
! 1386: *(int *)data =
! 1387: raidPtr->reconControl[row]->percentComplete;
! 1388: return (0);
! 1389:
! 1390: case RAIDFRAME_CHECK_RECON_STATUS_EXT:
! 1391: progressInfoPtr = (RF_ProgressInfo_t **) data;
! 1392: row = 0; /* XXX we only consider a single row... */
! 1393: if (raidPtr->status[row] != rf_rs_reconstructing) {
! 1394: progressInfo.remaining = 0;
! 1395: progressInfo.completed = 100;
! 1396: progressInfo.total = 100;
! 1397: } else {
! 1398: progressInfo.total =
! 1399: raidPtr->reconControl[row]->numRUsTotal;
! 1400: progressInfo.completed =
! 1401: raidPtr->reconControl[row]->numRUsComplete;
! 1402: progressInfo.remaining = progressInfo.total -
! 1403: progressInfo.completed;
! 1404: }
! 1405: retcode = copyout((caddr_t) &progressInfo,
! 1406: (caddr_t) *progressInfoPtr,
! 1407: sizeof(RF_ProgressInfo_t));
! 1408: return (retcode);
! 1409:
! 1410: case RAIDFRAME_CHECK_PARITYREWRITE_STATUS:
! 1411: if (raidPtr->Layout.map->faultsTolerated == 0) {
! 1412: /*
! 1413: * This makes no sense on a RAID 0, so tell the
! 1414: * user it's done.
! 1415: */
! 1416: *(int *) data = 100;
! 1417: return(0);
! 1418: }
! 1419: if (raidPtr->parity_rewrite_in_progress == 1) {
! 1420: *(int *) data = 100 *
! 1421: raidPtr->parity_rewrite_stripes_done /
! 1422: raidPtr->Layout.numStripe;
! 1423: } else {
! 1424: *(int *) data = 100;
! 1425: }
! 1426: return (0);
! 1427:
! 1428: case RAIDFRAME_CHECK_PARITYREWRITE_STATUS_EXT:
! 1429: progressInfoPtr = (RF_ProgressInfo_t **) data;
! 1430: if (raidPtr->parity_rewrite_in_progress == 1) {
! 1431: progressInfo.total = raidPtr->Layout.numStripe;
! 1432: progressInfo.completed =
! 1433: raidPtr->parity_rewrite_stripes_done;
! 1434: progressInfo.remaining = progressInfo.total -
! 1435: progressInfo.completed;
! 1436: } else {
! 1437: progressInfo.remaining = 0;
! 1438: progressInfo.completed = 100;
! 1439: progressInfo.total = 100;
! 1440: }
! 1441: retcode = copyout((caddr_t) &progressInfo,
! 1442: (caddr_t) *progressInfoPtr,
! 1443: sizeof(RF_ProgressInfo_t));
! 1444: return (retcode);
! 1445:
! 1446: case RAIDFRAME_CHECK_COPYBACK_STATUS:
! 1447: if (raidPtr->Layout.map->faultsTolerated == 0) {
! 1448: /* This makes no sense on a RAID 0 !! */
! 1449: *(int *) data = 100;
! 1450: return(0);
! 1451: }
! 1452: if (raidPtr->copyback_in_progress == 1) {
! 1453: *(int *) data = 100 * raidPtr->copyback_stripes_done /
! 1454: raidPtr->Layout.numStripe;
! 1455: } else {
! 1456: *(int *) data = 100;
! 1457: }
! 1458: return (0);
! 1459:
! 1460: case RAIDFRAME_CHECK_COPYBACK_STATUS_EXT:
! 1461: progressInfoPtr = (RF_ProgressInfo_t **) data;
! 1462: if (raidPtr->copyback_in_progress == 1) {
! 1463: progressInfo.total = raidPtr->Layout.numStripe;
! 1464: progressInfo.completed =
! 1465: raidPtr->copyback_stripes_done;
! 1466: progressInfo.remaining = progressInfo.total -
! 1467: progressInfo.completed;
! 1468: } else {
! 1469: progressInfo.remaining = 0;
! 1470: progressInfo.completed = 100;
! 1471: progressInfo.total = 100;
! 1472: }
! 1473: retcode = copyout((caddr_t) &progressInfo,
! 1474: (caddr_t) *progressInfoPtr,
! 1475: sizeof(RF_ProgressInfo_t));
! 1476: return (retcode);
! 1477:
! 1478: #if 0
! 1479: case RAIDFRAME_SPARET_WAIT:
! 1480: /*
! 1481: * The sparetable daemon calls this to wait for the
! 1482: * kernel to need a spare table.
! 1483: * This ioctl does not return until a spare table is needed.
! 1484: * XXX -- Calling mpsleep here in the ioctl code is almost
! 1485: * certainly wrong and evil. -- XXX
! 1486: * XXX -- I should either compute the spare table in the
! 1487: * kernel, or have a different. -- XXX
! 1488: * XXX -- Interface (a different character device) for
! 1489: * delivering the table. -- XXX
! 1490: */
! 1491: RF_LOCK_MUTEX(rf_sparet_wait_mutex);
! 1492: while (!rf_sparet_wait_queue)
! 1493: mpsleep(&rf_sparet_wait_queue, (PZERO + 1) | PCATCH,
! 1494: "sparet wait", 0,
! 1495: (void *)simple_lock_addr(rf_sparet_wait_mutex),
! 1496: MS_LOCK_SIMPLE);
! 1497: waitreq = rf_sparet_wait_queue;
! 1498: rf_sparet_wait_queue = rf_sparet_wait_queue->next;
! 1499: RF_UNLOCK_MUTEX(rf_sparet_wait_mutex);
! 1500:
! 1501: *((RF_SparetWait_t *)data) = *waitreq;
! 1502:
! 1503: RF_Free(waitreq, sizeof *waitreq);
! 1504: return (0);
! 1505:
! 1506: case RAIDFRAME_ABORT_SPARET_WAIT:
! 1507: /*
! 1508: * Wakes up a process waiting on SPARET_WAIT and puts an
! 1509: * error code in it that will cause the dameon to exit.
! 1510: */
! 1511: RF_Malloc(waitreq, sizeof (*waitreq), (RF_SparetWait_t *));
! 1512: waitreq->fcol = -1;
! 1513: RF_LOCK_MUTEX(rf_sparet_wait_mutex);
! 1514: waitreq->next = rf_sparet_wait_queue;
! 1515: rf_sparet_wait_queue = waitreq;
! 1516: RF_UNLOCK_MUTEX(rf_sparet_wait_mutex);
! 1517: wakeup(&rf_sparet_wait_queue);
! 1518: return (0);
! 1519:
! 1520: case RAIDFRAME_SEND_SPARET:
! 1521: /*
! 1522: * Used by the spare table daemon to deliver a spare table
! 1523: * into the kernel.
! 1524: */
! 1525:
! 1526: /* Install the spare table. */
! 1527: retcode = rf_SetSpareTable(raidPtr,*(void **)data);
! 1528:
! 1529: /*
! 1530: * Respond to the requestor. The return status of the
! 1531: * spare table installation is passed in the "fcol" field.
! 1532: */
! 1533: RF_Malloc(waitreq, sizeof *waitreq, (RF_SparetWait_t *));
! 1534: waitreq->fcol = retcode;
! 1535: RF_LOCK_MUTEX(rf_sparet_wait_mutex);
! 1536: waitreq->next = rf_sparet_resp_queue;
! 1537: rf_sparet_resp_queue = waitreq;
! 1538: wakeup(&rf_sparet_resp_queue);
! 1539: RF_UNLOCK_MUTEX(rf_sparet_wait_mutex);
! 1540:
! 1541: return (retcode);
! 1542: #endif
! 1543: /* Fall through to the os-specific code below. */
! 1544: default:
! 1545: break;
! 1546: }
! 1547:
! 1548: if (!raidPtr->valid)
! 1549: return (EINVAL);
! 1550:
! 1551: /*
! 1552: * Add support for "regular" device ioctls here.
! 1553: */
! 1554: switch (cmd) {
! 1555: case DIOCGDINFO:
! 1556: *(struct disklabel *)data = *(rs->sc_dkdev.dk_label);
! 1557: break;
! 1558:
! 1559: case DIOCGPART:
! 1560: ((struct partinfo *)data)->disklab = rs->sc_dkdev.dk_label;
! 1561: ((struct partinfo *)data)->part =
! 1562: &rs->sc_dkdev.dk_label->d_partitions[DISKPART(dev)];
! 1563: break;
! 1564:
! 1565: case DIOCWDINFO:
! 1566: case DIOCSDINFO:
! 1567: {
! 1568: struct disklabel *lp;
! 1569: lp = (struct disklabel *)data;
! 1570:
! 1571: if ((error = raidlock(rs)) != 0)
! 1572: return (error);
! 1573:
! 1574: rs->sc_flags |= RAIDF_LABELLING;
! 1575:
! 1576: error = setdisklabel(rs->sc_dkdev.dk_label, lp, 0);
! 1577: if (error == 0) {
! 1578: if (cmd == DIOCWDINFO)
! 1579: error = writedisklabel(DISKLABELDEV(dev),
! 1580: raidstrategy, rs->sc_dkdev.dk_label);
! 1581: }
! 1582:
! 1583: rs->sc_flags &= ~RAIDF_LABELLING;
! 1584:
! 1585: raidunlock(rs);
! 1586:
! 1587: if (error)
! 1588: return (error);
! 1589: break;
! 1590: }
! 1591:
! 1592: case DIOCWLABEL:
! 1593: if (*(int *)data != 0)
! 1594: rs->sc_flags |= RAIDF_WLABEL;
! 1595: else
! 1596: rs->sc_flags &= ~RAIDF_WLABEL;
! 1597: break;
! 1598:
! 1599: case DIOCGPDINFO:
! 1600: raidgetdisklabel(dev, (struct disklabel *)data, 1);
! 1601: break;
! 1602:
! 1603: default:
! 1604: retcode = ENOTTY;
! 1605: }
! 1606:
! 1607: return (retcode);
! 1608: }
! 1609:
! 1610: /*
! 1611: * raidinit -- Complete the rest of the initialization for the
! 1612: * RAIDframe device.
! 1613: */
! 1614: void
! 1615: raidinit(RF_Raid_t *raidPtr)
! 1616: {
! 1617: struct raid_softc *rs;
! 1618: struct cfdata *cf;
! 1619: int unit;
! 1620:
! 1621: unit = raidPtr->raidid;
! 1622:
! 1623: rs = &raid_softc[unit];
! 1624: pool_init(&rs->sc_cbufpool, sizeof(struct raidbuf), 0,
! 1625: 0, 0, "raidpl", NULL);
! 1626:
! 1627: /* XXX should check return code first... */
! 1628: rs->sc_flags |= RAIDF_INITED;
! 1629:
! 1630: /* XXX doesn't check bounds. */
! 1631: snprintf(rs->sc_xname, sizeof rs->sc_xname, "raid%d", unit);
! 1632:
! 1633: rs->sc_dkdev.dk_name = rs->sc_xname;
! 1634:
! 1635: /*
! 1636: * disk_attach actually creates space for the CPU disklabel, among
! 1637: * other things, so it's critical to call this *BEFORE* we try
! 1638: * putzing with disklabels.
! 1639: */
! 1640: disk_attach(&rs->sc_dkdev);
! 1641:
! 1642: /*
! 1643: * XXX There may be a weird interaction here between this, and
! 1644: * protectedSectors, as used in RAIDframe.
! 1645: */
! 1646: rs->sc_size = raidPtr->totalSectors;
! 1647:
! 1648: /*
! 1649: * config_attach the raid device into the device tree.
! 1650: * For autoconf rootdev selection...
! 1651: */
! 1652: cf = malloc(sizeof(struct cfdata), M_RAIDFRAME, M_NOWAIT);
! 1653: if (cf == NULL) {
! 1654: printf("WARNING: no memory for cfdata struct\n");
! 1655: return;
! 1656: }
! 1657: bzero(cf, sizeof(struct cfdata));
! 1658:
! 1659: cf->cf_attach = &raid_ca;
! 1660: cf->cf_driver = &raid_cd;
! 1661: cf->cf_unit = unit;
! 1662:
! 1663: config_attach(NULL, cf, NULL, NULL);
! 1664: }
! 1665:
! 1666: /*
! 1667: * Wake up the daemon & tell it to get us a spare table.
! 1668: * XXX
! 1669: * The entries in the queues should be tagged with the raidPtr so that
! 1670: * in the extremely rare case that two recons happen at once, we know
! 1671: * which devices were requesting a spare table.
! 1672: * XXX
! 1673: *
! 1674: * XXX This code is not currently used. GO
! 1675: */
! 1676: int
! 1677: rf_GetSpareTableFromDaemon(RF_SparetWait_t *req)
! 1678: {
! 1679: int retcode;
! 1680:
! 1681: RF_LOCK_MUTEX(rf_sparet_wait_mutex);
! 1682: req->next = rf_sparet_wait_queue;
! 1683: rf_sparet_wait_queue = req;
! 1684: wakeup(&rf_sparet_wait_queue);
! 1685:
! 1686: /* mpsleep unlocks the mutex. */
! 1687: while (!rf_sparet_resp_queue) {
! 1688: tsleep(&rf_sparet_resp_queue, PRIBIO,
! 1689: "RAIDframe getsparetable", 0);
! 1690: }
! 1691: req = rf_sparet_resp_queue;
! 1692: rf_sparet_resp_queue = req->next;
! 1693: RF_UNLOCK_MUTEX(rf_sparet_wait_mutex);
! 1694:
! 1695: retcode = req->fcol;
! 1696: /* This is not the same req as we alloc'd. */
! 1697: RF_Free(req, sizeof *req);
! 1698: return (retcode);
! 1699: }
! 1700:
! 1701: /*
! 1702: * A wrapper around rf_DoAccess that extracts appropriate info from the
! 1703: * bp and passes it down.
! 1704: * Any calls originating in the kernel must use non-blocking I/O.
! 1705: * Do some extra sanity checking to return "appropriate" error values for
! 1706: * certain conditions (to make some standard utilities work).
! 1707: *
! 1708: * Formerly known as: rf_DoAccessKernel
! 1709: */
! 1710: void
! 1711: raidstart(RF_Raid_t *raidPtr)
! 1712: {
! 1713: RF_SectorCount_t num_blocks, pb, sum;
! 1714: RF_RaidAddr_t raid_addr;
! 1715: int retcode;
! 1716: struct partition *pp;
! 1717: daddr64_t blocknum;
! 1718: int unit;
! 1719: struct raid_softc *rs;
! 1720: int do_async;
! 1721: struct buf *bp;
! 1722:
! 1723: unit = raidPtr->raidid;
! 1724: rs = &raid_softc[unit];
! 1725:
! 1726: /* Quick check to see if anything has died recently. */
! 1727: RF_LOCK_MUTEX(raidPtr->mutex);
! 1728: if (raidPtr->numNewFailures > 0) {
! 1729: rf_update_component_labels(raidPtr,
! 1730: RF_NORMAL_COMPONENT_UPDATE);
! 1731: raidPtr->numNewFailures--;
! 1732: }
! 1733: RF_UNLOCK_MUTEX(raidPtr->mutex);
! 1734:
! 1735: /* Check to see if we're at the limit... */
! 1736: RF_LOCK_MUTEX(raidPtr->mutex);
! 1737: while (raidPtr->openings > 0) {
! 1738: RF_UNLOCK_MUTEX(raidPtr->mutex);
! 1739:
! 1740: bp = rs->sc_q.b_actf;
! 1741: if (bp == NULL) {
! 1742: /* Nothing more to do. */
! 1743: return;
! 1744: }
! 1745: rs->sc_q.b_actf = bp->b_actf;
! 1746:
! 1747: /*
! 1748: * Ok, for the bp we have here, bp->b_blkno is relative to the
! 1749: * partition... We need to make it absolute to the underlying
! 1750: * device...
! 1751: */
! 1752:
! 1753: blocknum = bp->b_blkno;
! 1754: if (DISKPART(bp->b_dev) != RAW_PART) {
! 1755: pp = &rs->sc_dkdev.dk_label->d_partitions[DISKPART(bp->b_dev)];
! 1756: blocknum += DL_GETPOFFSET(pp);
! 1757: }
! 1758:
! 1759: db1_printf(("Blocks: %d, %lld\n", (int) bp->b_blkno,
! 1760: blocknum));
! 1761:
! 1762: db1_printf(("bp->b_bcount = %d\n", (int) bp->b_bcount));
! 1763: db1_printf(("bp->b_resid = %d\n", (int) bp->b_resid));
! 1764:
! 1765: /*
! 1766: * *THIS* is where we adjust what block we're going to...
! 1767: * But DO NOT TOUCH bp->b_blkno !!!
! 1768: */
! 1769: raid_addr = blocknum;
! 1770:
! 1771: num_blocks = bp->b_bcount >> raidPtr->logBytesPerSector;
! 1772: pb = (bp->b_bcount & raidPtr->sectorMask) ? 1 : 0;
! 1773: sum = raid_addr + num_blocks + pb;
! 1774: if (1 || rf_debugKernelAccess) {
! 1775: db1_printf(("raid_addr=%d sum=%d num_blocks=%d(+%d)"
! 1776: " (%d)\n", (int)raid_addr, (int)sum,
! 1777: (int)num_blocks, (int)pb, (int)bp->b_resid));
! 1778: }
! 1779: if ((sum > raidPtr->totalSectors) || (sum < raid_addr)
! 1780: || (sum < num_blocks) || (sum < pb)) {
! 1781: bp->b_error = ENOSPC;
! 1782: bp->b_flags |= B_ERROR;
! 1783: bp->b_resid = bp->b_bcount;
! 1784: /* db1_printf(("%s: Calling biodone on 0x%x\n",
! 1785: __func__, bp)); */
! 1786: splassert(IPL_BIO);
! 1787: biodone(bp);
! 1788: RF_LOCK_MUTEX(raidPtr->mutex);
! 1789: continue;
! 1790: }
! 1791: /*
! 1792: * XXX rf_DoAccess() should do this, not just DoAccessKernel().
! 1793: */
! 1794:
! 1795: if (bp->b_bcount & raidPtr->sectorMask) {
! 1796: bp->b_error = EINVAL;
! 1797: bp->b_flags |= B_ERROR;
! 1798: bp->b_resid = bp->b_bcount;
! 1799: /* db1_printf(("%s: Calling biodone on 0x%x\n",
! 1800: __func__, bp)); */
! 1801: splassert(IPL_BIO);
! 1802: biodone(bp);
! 1803: RF_LOCK_MUTEX(raidPtr->mutex);
! 1804: continue;
! 1805:
! 1806: }
! 1807: db1_printf(("Calling DoAccess..\n"));
! 1808:
! 1809:
! 1810: RF_LOCK_MUTEX(raidPtr->mutex);
! 1811: raidPtr->openings--;
! 1812: RF_UNLOCK_MUTEX(raidPtr->mutex);
! 1813:
! 1814: /*
! 1815: * Everything is async.
! 1816: */
! 1817: do_async = 1;
! 1818:
! 1819: disk_busy(&rs->sc_dkdev);
! 1820:
! 1821: /*
! 1822: * XXX we're still at splbio() here... Do we *really*
! 1823: * need to be ?
! 1824: */
! 1825:
! 1826: /*
! 1827: * Don't ever condition on bp->b_flags & B_WRITE.
! 1828: * Always condition on B_READ instead.
! 1829: */
! 1830:
! 1831: retcode = rf_DoAccess(raidPtr, (bp->b_flags & B_READ) ?
! 1832: RF_IO_TYPE_READ : RF_IO_TYPE_WRITE,
! 1833: do_async, raid_addr, num_blocks,
! 1834: bp->b_data, bp, NULL, NULL,
! 1835: RF_DAG_NONBLOCKING_IO, NULL, NULL, NULL);
! 1836:
! 1837: RF_LOCK_MUTEX(raidPtr->mutex);
! 1838: }
! 1839: RF_UNLOCK_MUTEX(raidPtr->mutex);
! 1840: }
! 1841:
! 1842: /* Invoke an I/O from kernel mode. Disk queue should be locked upon entry. */
! 1843:
! 1844: int
! 1845: rf_DispatchKernelIO(RF_DiskQueue_t *queue, RF_DiskQueueData_t *req)
! 1846: {
! 1847: int op = (req->type == RF_IO_TYPE_READ) ? B_READ : B_WRITE;
! 1848: struct buf *bp;
! 1849: struct raidbuf *raidbp = NULL;
! 1850: struct raid_softc *rs;
! 1851: int unit;
! 1852: /*int s = splbio();*/ /* Want to test this. */
! 1853:
! 1854: /*
! 1855: * XXX along with the vnode, we also need the softc associated with
! 1856: * this device...
! 1857: */
! 1858: req->queue = queue;
! 1859:
! 1860: unit = queue->raidPtr->raidid;
! 1861:
! 1862: db1_printf(("DispatchKernelIO unit: %d\n", unit));
! 1863:
! 1864: if (unit >= numraid) {
! 1865: printf("Invalid unit number: %d %d\n", unit, numraid);
! 1866: panic("Invalid Unit number in rf_DispatchKernelIO");
! 1867: }
! 1868:
! 1869: rs = &raid_softc[unit];
! 1870:
! 1871: bp = req->bp;
! 1872:
! 1873: #if 1
! 1874: /*
! 1875: * XXX When there is a physical disk failure, someone is passing
! 1876: * us a buffer that contains old stuff !! Attempt to deal with
! 1877: * this problem without taking a performance hit...
! 1878: * (not sure where the real bug is; it's buried in RAIDframe
! 1879: * somewhere) :-( GO )
! 1880: */
! 1881: if (bp->b_flags & B_ERROR) {
! 1882: bp->b_flags &= ~B_ERROR;
! 1883: }
! 1884: if (bp->b_error!=0) {
! 1885: bp->b_error = 0;
! 1886: }
! 1887: #endif
! 1888:
! 1889: raidbp = RAIDGETBUF(rs);
! 1890:
! 1891: raidbp->rf_flags = 0; /* XXX not really used anywhere... */
! 1892:
! 1893: /*
! 1894: * Context for raidiodone.
! 1895: */
! 1896: raidbp->rf_obp = bp;
! 1897: raidbp->req = req;
! 1898:
! 1899: LIST_INIT(&raidbp->rf_buf.b_dep);
! 1900:
! 1901: switch (req->type) {
! 1902: case RF_IO_TYPE_NOP:
! 1903: /* Used primarily to unlock a locked queue. */
! 1904:
! 1905: db1_printf(("rf_DispatchKernelIO: NOP to r %d c %d\n",
! 1906: queue->row, queue->col));
! 1907:
! 1908: /* XXX need to do something extra here... */
! 1909:
! 1910: /*
! 1911: * I'm leaving this in, as I've never actually seen it
! 1912: * used, and I'd like folks to report it... GO
! 1913: */
! 1914: db1_printf(("WAKEUP CALLED\n"));
! 1915: queue->numOutstanding++;
! 1916:
! 1917: /* XXX need to glue the original buffer into this ?? */
! 1918:
! 1919: rf_KernelWakeupFunc(&raidbp->rf_buf);
! 1920: break;
! 1921:
! 1922: case RF_IO_TYPE_READ:
! 1923: case RF_IO_TYPE_WRITE:
! 1924: if (req->tracerec) {
! 1925: RF_ETIMER_START(req->tracerec->timer);
! 1926: }
! 1927:
! 1928: rf_InitBP(&raidbp->rf_buf, queue->rf_cinfo->ci_vp,
! 1929: op | bp->b_flags, queue->rf_cinfo->ci_dev,
! 1930: req->sectorOffset, req->numSector,
! 1931: req->buf, rf_KernelWakeupFunc, (void *)req,
! 1932: queue->raidPtr->logBytesPerSector, req->b_proc);
! 1933:
! 1934: if (rf_debugKernelAccess) {
! 1935: db1_printf(("dispatch: bp->b_blkno = %ld\n",
! 1936: (long)bp->b_blkno));
! 1937: }
! 1938: queue->numOutstanding++;
! 1939: queue->last_deq_sector = req->sectorOffset;
! 1940:
! 1941: /*
! 1942: * Acc wouldn't have been let in if there were any
! 1943: * pending reqs at any other priority.
! 1944: */
! 1945: queue->curPriority = req->priority;
! 1946:
! 1947: db1_printf(("Going for %c to unit %d row %d col %d\n",
! 1948: req->type, unit, queue->row, queue->col));
! 1949: db1_printf(("sector %d count %d (%d bytes) %d\n",
! 1950: (int)req->sectorOffset, (int)req->numSector,
! 1951: (int)(req->numSector << queue->raidPtr->logBytesPerSector),
! 1952: (int)queue->raidPtr->logBytesPerSector));
! 1953: if ((raidbp->rf_buf.b_flags & B_READ) == 0) {
! 1954: raidbp->rf_buf.b_vp->v_numoutput++;
! 1955: }
! 1956:
! 1957: VOP_STRATEGY(&raidbp->rf_buf);
! 1958: break;
! 1959:
! 1960: default:
! 1961: panic("bad req->type in rf_DispatchKernelIO");
! 1962: }
! 1963: db1_printf(("Exiting from DispatchKernelIO\n"));
! 1964: /*splx(s);*/ /* want to test this */
! 1965: return (0);
! 1966: }
! 1967:
! 1968: /*
! 1969: * This is the callback function associated with a I/O invoked from
! 1970: * kernel code.
! 1971: */
! 1972: void
! 1973: rf_KernelWakeupFunc(struct buf *vbp)
! 1974: {
! 1975: RF_DiskQueueData_t *req = NULL;
! 1976: RF_DiskQueue_t *queue;
! 1977: struct raidbuf *raidbp = (struct raidbuf *)vbp;
! 1978: struct buf *bp;
! 1979: struct raid_softc *rs;
! 1980: int unit;
! 1981: int s;
! 1982:
! 1983: s = splbio();
! 1984: db1_printf(("recovering the request queue:\n"));
! 1985: req = raidbp->req;
! 1986:
! 1987: bp = raidbp->rf_obp;
! 1988:
! 1989: queue = (RF_DiskQueue_t *)req->queue;
! 1990:
! 1991: if (raidbp->rf_buf.b_flags & B_ERROR) {
! 1992: bp->b_flags |= B_ERROR;
! 1993: bp->b_error =
! 1994: raidbp->rf_buf.b_error ? raidbp->rf_buf.b_error : EIO;
! 1995: }
! 1996:
! 1997: #if 1
! 1998: /* XXX Methinks this could be wrong... */
! 1999: bp->b_resid = raidbp->rf_buf.b_resid;
! 2000: #endif
! 2001:
! 2002: if (req->tracerec) {
! 2003: RF_ETIMER_STOP(req->tracerec->timer);
! 2004: RF_ETIMER_EVAL(req->tracerec->timer);
! 2005: RF_LOCK_MUTEX(rf_tracing_mutex);
! 2006: req->tracerec->diskwait_us +=
! 2007: RF_ETIMER_VAL_US(req->tracerec->timer);
! 2008: req->tracerec->phys_io_us +=
! 2009: RF_ETIMER_VAL_US(req->tracerec->timer);
! 2010: req->tracerec->num_phys_ios++;
! 2011: RF_UNLOCK_MUTEX(rf_tracing_mutex);
! 2012: }
! 2013:
! 2014: bp->b_bcount = raidbp->rf_buf.b_bcount; /* XXXX ?? */
! 2015:
! 2016: unit = queue->raidPtr->raidid; /* *Much* simpler :-> */
! 2017:
! 2018: /*
! 2019: * XXX Ok, let's get aggressive... If B_ERROR is set, let's go
! 2020: * ballistic, and mark the component as hosed...
! 2021: */
! 2022: if (bp->b_flags & B_ERROR) {
! 2023: /* Mark the disk as dead but only mark it once... */
! 2024: if (queue->raidPtr->Disks[queue->row][queue->col].status ==
! 2025: rf_ds_optimal) {
! 2026: printf("raid%d: IO Error. Marking %s as failed.\n",
! 2027: unit,
! 2028: queue->raidPtr->
! 2029: Disks[queue->row][queue->col].devname);
! 2030: queue->raidPtr->Disks[queue->row][queue->col].status =
! 2031: rf_ds_failed;
! 2032: queue->raidPtr->status[queue->row] = rf_rs_degraded;
! 2033: queue->raidPtr->numFailures++;
! 2034: queue->raidPtr->numNewFailures++;
! 2035: } else {
! 2036: /* Disk is already dead... */
! 2037: /* printf("Disk already marked as dead!\n"); */
! 2038: }
! 2039: }
! 2040:
! 2041: rs = &raid_softc[unit];
! 2042: RAIDPUTBUF(rs, raidbp);
! 2043:
! 2044: rf_DiskIOComplete(queue, req, (bp->b_flags & B_ERROR) ? 1 : 0);
! 2045: (req->CompleteFunc)(req->argument, (bp->b_flags & B_ERROR) ? 1 : 0);
! 2046:
! 2047: splx(s);
! 2048: }
! 2049:
! 2050: /*
! 2051: * Initialize a buf structure for doing an I/O in the kernel.
! 2052: */
! 2053: void
! 2054: rf_InitBP(
! 2055: struct buf *bp,
! 2056: struct vnode *b_vp,
! 2057: unsigned rw_flag,
! 2058: dev_t dev,
! 2059: RF_SectorNum_t startSect,
! 2060: RF_SectorCount_t numSect,
! 2061: caddr_t buf,
! 2062: void (*cbFunc)(struct buf *),
! 2063: void *cbArg,
! 2064: int logBytesPerSector,
! 2065: struct proc *b_proc
! 2066: )
! 2067: {
! 2068: /*bp->b_flags = B_PHYS | rw_flag;*/
! 2069: bp->b_flags = B_CALL | rw_flag; /* XXX need B_PHYS here too ??? */
! 2070: bp->b_bcount = numSect << logBytesPerSector;
! 2071: bp->b_bufsize = bp->b_bcount;
! 2072: bp->b_error = 0;
! 2073: bp->b_dev = dev;
! 2074: bp->b_data = buf;
! 2075: bp->b_blkno = startSect;
! 2076: bp->b_resid = bp->b_bcount; /* XXX is this right !??!?!! */
! 2077: if (bp->b_bcount == 0) {
! 2078: panic("bp->b_bcount is zero in rf_InitBP!!");
! 2079: }
! 2080: bp->b_proc = b_proc;
! 2081: bp->b_iodone = cbFunc;
! 2082: bp->b_vp = b_vp;
! 2083: LIST_INIT(&bp->b_dep);
! 2084: }
! 2085:
! 2086: void
! 2087: raidgetdefaultlabel(RF_Raid_t *raidPtr, struct raid_softc *rs,
! 2088: struct disklabel *lp)
! 2089: {
! 2090: db1_printf(("Building a default label...\n"));
! 2091: bzero(lp, sizeof(*lp));
! 2092:
! 2093: /* Fabricate a label... */
! 2094: DL_SETDSIZE(lp, raidPtr->totalSectors);
! 2095: lp->d_secsize = raidPtr->bytesPerSector;
! 2096: lp->d_nsectors = raidPtr->Layout.dataSectorsPerStripe;
! 2097: lp->d_ntracks = 4 * raidPtr->numCol;
! 2098: lp->d_ncylinders = raidPtr->totalSectors /
! 2099: (lp->d_nsectors * lp->d_ntracks);
! 2100: lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
! 2101:
! 2102: strncpy(lp->d_typename, "raid", sizeof(lp->d_typename));
! 2103: lp->d_type = DTYPE_RAID;
! 2104: strncpy(lp->d_packname, "fictitious", sizeof(lp->d_packname));
! 2105: lp->d_rpm = 3600;
! 2106: lp->d_flags = 0;
! 2107: lp->d_interleave = 1;
! 2108: lp->d_version = 1;
! 2109:
! 2110: DL_SETPOFFSET(&lp->d_partitions[RAW_PART], 0);
! 2111: DL_SETPSIZE(&lp->d_partitions[RAW_PART], raidPtr->totalSectors);
! 2112: lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED;
! 2113: lp->d_npartitions = RAW_PART + 1;
! 2114:
! 2115: lp->d_magic = DISKMAGIC;
! 2116: lp->d_magic2 = DISKMAGIC;
! 2117: lp->d_checksum = dkcksum(rs->sc_dkdev.dk_label);
! 2118: }
! 2119:
! 2120: /*
! 2121: * Read the disklabel from the raid device.
! 2122: * If one is not present, fake one up.
! 2123: */
! 2124: void
! 2125: raidgetdisklabel(dev_t dev, struct disklabel *lp, int spoofonly)
! 2126: {
! 2127: int unit = DISKUNIT(dev);
! 2128: struct raid_softc *rs = &raid_softc[unit];
! 2129: char *errstring;
! 2130: RF_Raid_t *raidPtr;
! 2131: int i;
! 2132: struct partition *pp;
! 2133:
! 2134: db1_printf(("Getting the disklabel...\n"));
! 2135:
! 2136: bzero(lp, sizeof(*lp));
! 2137:
! 2138: raidPtr = raidPtrs[unit];
! 2139:
! 2140: raidgetdefaultlabel(raidPtr, rs, lp);
! 2141:
! 2142: /*
! 2143: * Call the generic disklabel extraction routine.
! 2144: */
! 2145: errstring = readdisklabel(DISKLABELDEV(dev), raidstrategy, lp,
! 2146: spoofonly);
! 2147: if (errstring) {
! 2148: /*printf("%s: %s\n", rs->sc_xname, errstring);*/
! 2149: return;
! 2150: }
! 2151:
! 2152: /*
! 2153: * Sanity check whether the found disklabel is valid.
! 2154: *
! 2155: * This is necessary since total size of the raid device
! 2156: * may vary when an interleave is changed even though exactly
! 2157: * same componets are used, and old disklabel may used
! 2158: * if that is found.
! 2159: */
! 2160: #ifdef RAIDDEBUG
! 2161: if (DL_GETDSIZE(lp) != rs->sc_size)
! 2162: printf("WARNING: %s: "
! 2163: "total sector size in disklabel (%d) != "
! 2164: "the size of raid (%ld)\n", rs->sc_xname,
! 2165: DL_GETDSIZE(lp), (long) rs->sc_size);
! 2166: #endif /* RAIDDEBUG */
! 2167: for (i = 0; i < lp->d_npartitions; i++) {
! 2168: pp = &lp->d_partitions[i];
! 2169: if (DL_GETPOFFSET(pp) + DL_GETPSIZE(pp) > rs->sc_size)
! 2170: printf("WARNING: %s: end of partition `%c' "
! 2171: "exceeds the size of raid (%ld)\n",
! 2172: rs->sc_xname, 'a' + i, (long) rs->sc_size);
! 2173: }
! 2174: }
! 2175:
! 2176: /*
! 2177: * Lookup the provided name in the filesystem. If the file exists,
! 2178: * is a valid block device, and isn't being used by anyone else,
! 2179: * set *vpp to the file's vnode.
! 2180: * You'll find the original of this in ccd.c
! 2181: */
! 2182: int
! 2183: raidlookup(char *path, struct proc *p, struct vnode **vpp /* result */)
! 2184: {
! 2185: struct nameidata nd;
! 2186: struct vnode *vp;
! 2187: struct vattr va;
! 2188: int error;
! 2189:
! 2190: NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, path, p);
! 2191: if ((error = vn_open(&nd, FREAD|FWRITE, 0)) != 0) {
! 2192: #ifdef RAIDDEBUG
! 2193: printf("RAIDframe: vn_open returned %d\n", error);
! 2194: #endif /* RAIDDEBUG */
! 2195: return (error);
! 2196: }
! 2197: vp = nd.ni_vp;
! 2198: if (vp->v_usecount > 1) {
! 2199: VOP_UNLOCK(vp, 0, p);
! 2200: (void)vn_close(vp, FREAD|FWRITE, p->p_ucred, p);
! 2201: return (EBUSY);
! 2202: }
! 2203: if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) != 0) {
! 2204: VOP_UNLOCK(vp, 0, p);
! 2205: (void)vn_close(vp, FREAD|FWRITE, p->p_ucred, p);
! 2206: return (error);
! 2207: }
! 2208: /* XXX: eventually we should handle VREG, too. */
! 2209: if (va.va_type != VBLK) {
! 2210: VOP_UNLOCK(vp, 0, p);
! 2211: (void)vn_close(vp, FREAD|FWRITE, p->p_ucred, p);
! 2212: return (ENOTBLK);
! 2213: }
! 2214: VOP_UNLOCK(vp, 0, p);
! 2215: *vpp = vp;
! 2216: return (0);
! 2217: }
! 2218:
! 2219: /*
! 2220: * Wait interruptibly for an exclusive lock.
! 2221: *
! 2222: * XXX
! 2223: * Several drivers do this; it should be abstracted and made MP-safe.
! 2224: * (Hmm... where have we seen this warning before :-> GO )
! 2225: */
! 2226: int
! 2227: raidlock(struct raid_softc *rs)
! 2228: {
! 2229: int error;
! 2230:
! 2231: while ((rs->sc_flags & RAIDF_LOCKED) != 0) {
! 2232: rs->sc_flags |= RAIDF_WANTED;
! 2233: if ((error = tsleep(rs, PRIBIO | PCATCH, "raidlck", 0)) != 0)
! 2234: return (error);
! 2235: }
! 2236: rs->sc_flags |= RAIDF_LOCKED;
! 2237: return (0);
! 2238: }
! 2239:
! 2240: /*
! 2241: * Unlock and wake up any waiters.
! 2242: */
! 2243: void
! 2244: raidunlock(struct raid_softc *rs)
! 2245: {
! 2246: rs->sc_flags &= ~RAIDF_LOCKED;
! 2247: if ((rs->sc_flags & RAIDF_WANTED) != 0) {
! 2248: rs->sc_flags &= ~RAIDF_WANTED;
! 2249: wakeup(rs);
! 2250: }
! 2251: }
! 2252:
! 2253:
! 2254: #define RF_COMPONENT_INFO_OFFSET 16384 /* bytes */
! 2255: #define RF_COMPONENT_INFO_SIZE 1024 /* bytes */
! 2256:
! 2257: int
! 2258: raidmarkclean(dev_t dev, struct vnode *b_vp, int mod_counter)
! 2259: {
! 2260: RF_ComponentLabel_t clabel;
! 2261: raidread_component_label(dev, b_vp, &clabel);
! 2262: clabel.mod_counter = mod_counter;
! 2263: clabel.clean = RF_RAID_CLEAN;
! 2264: raidwrite_component_label(dev, b_vp, &clabel);
! 2265: return(0);
! 2266: }
! 2267:
! 2268:
! 2269: int
! 2270: raidmarkdirty(dev_t dev, struct vnode *b_vp, int mod_counter)
! 2271: {
! 2272: RF_ComponentLabel_t clabel;
! 2273: raidread_component_label(dev, b_vp, &clabel);
! 2274: clabel.mod_counter = mod_counter;
! 2275: clabel.clean = RF_RAID_DIRTY;
! 2276: raidwrite_component_label(dev, b_vp, &clabel);
! 2277: return(0);
! 2278: }
! 2279:
! 2280: /* ARGSUSED */
! 2281: int
! 2282: raidread_component_label(dev_t dev, struct vnode *b_vp,
! 2283: RF_ComponentLabel_t *clabel)
! 2284: {
! 2285: struct buf *bp;
! 2286: int error;
! 2287:
! 2288: /*
! 2289: * XXX should probably ensure that we don't try to do this if
! 2290: * someone has changed rf_protected_sectors.
! 2291: */
! 2292:
! 2293: if (b_vp == NULL) {
! 2294: /*
! 2295: * For whatever reason, this component is not valid.
! 2296: * Don't try to read a component label from it.
! 2297: */
! 2298: return(EINVAL);
! 2299: }
! 2300:
! 2301: /* Get a block of the appropriate size... */
! 2302: bp = geteblk((int)RF_COMPONENT_INFO_SIZE);
! 2303: bp->b_dev = dev;
! 2304:
! 2305: /* Get our ducks in a row for the read. */
! 2306: bp->b_blkno = RF_COMPONENT_INFO_OFFSET / DEV_BSIZE;
! 2307: bp->b_bcount = RF_COMPONENT_INFO_SIZE;
! 2308: bp->b_flags |= B_READ;
! 2309: bp->b_resid = RF_COMPONENT_INFO_SIZE / DEV_BSIZE;
! 2310:
! 2311: (*bdevsw[major(bp->b_dev)].d_strategy)(bp);
! 2312:
! 2313: error = biowait(bp);
! 2314:
! 2315: if (!error) {
! 2316: memcpy(clabel, bp->b_data, sizeof(RF_ComponentLabel_t));
! 2317: #if 0
! 2318: rf_print_component_label( clabel );
! 2319: #endif
! 2320: } else {
! 2321: db1_printf(("Failed to read RAID component label!\n"));
! 2322: }
! 2323:
! 2324: brelse(bp);
! 2325: return(error);
! 2326: }
! 2327:
! 2328: /* ARGSUSED */
! 2329: int
! 2330: raidwrite_component_label(dev_t dev, struct vnode *b_vp,
! 2331: RF_ComponentLabel_t *clabel)
! 2332: {
! 2333: struct buf *bp;
! 2334: int error;
! 2335:
! 2336: /* Get a block of the appropriate size... */
! 2337: bp = geteblk((int)RF_COMPONENT_INFO_SIZE);
! 2338: bp->b_dev = dev;
! 2339:
! 2340: /* Get our ducks in a row for the write. */
! 2341: bp->b_blkno = RF_COMPONENT_INFO_OFFSET / DEV_BSIZE;
! 2342: bp->b_bcount = RF_COMPONENT_INFO_SIZE;
! 2343: bp->b_flags |= B_WRITE;
! 2344: bp->b_resid = RF_COMPONENT_INFO_SIZE / DEV_BSIZE;
! 2345:
! 2346: memset(bp->b_data, 0, RF_COMPONENT_INFO_SIZE );
! 2347:
! 2348: memcpy(bp->b_data, clabel, sizeof(RF_ComponentLabel_t));
! 2349:
! 2350: (*bdevsw[major(bp->b_dev)].d_strategy)(bp);
! 2351: error = biowait(bp);
! 2352: brelse(bp);
! 2353: if (error) {
! 2354: printf("Failed to write RAID component info!\n");
! 2355: }
! 2356:
! 2357: return(error);
! 2358: }
! 2359:
! 2360: void
! 2361: rf_markalldirty(RF_Raid_t *raidPtr)
! 2362: {
! 2363: RF_ComponentLabel_t clabel;
! 2364: int r,c;
! 2365:
! 2366: raidPtr->mod_counter++;
! 2367: for (r = 0; r < raidPtr->numRow; r++) {
! 2368: for (c = 0; c < raidPtr->numCol; c++) {
! 2369: /*
! 2370: * We don't want to touch (at all) a disk that has
! 2371: * failed.
! 2372: */
! 2373: if (!RF_DEAD_DISK(raidPtr->Disks[r][c].status)) {
! 2374: raidread_component_label(
! 2375: raidPtr->Disks[r][c].dev,
! 2376: raidPtr->raid_cinfo[r][c].ci_vp, &clabel);
! 2377: if (clabel.status == rf_ds_spared) {
! 2378: /*
! 2379: * XXX do something special...
! 2380: * But whatever you do, don't
! 2381: * try to access it !!!
! 2382: */
! 2383: } else {
! 2384: #if 0
! 2385: clabel.status =
! 2386: raidPtr->Disks[r][c].status;
! 2387: raidwrite_component_label(
! 2388: raidPtr->Disks[r][c].dev,
! 2389: raidPtr->raid_cinfo[r][c].ci_vp,
! 2390: &clabel);
! 2391: #endif
! 2392: raidmarkdirty(
! 2393: raidPtr->Disks[r][c].dev,
! 2394: raidPtr->raid_cinfo[r][c].ci_vp,
! 2395: raidPtr->mod_counter);
! 2396: }
! 2397: }
! 2398: }
! 2399: }
! 2400: /*printf("Component labels marked dirty.\n");*/
! 2401: #if 0
! 2402: for( c = 0; c < raidPtr->numSpare ; c++) {
! 2403: sparecol = raidPtr->numCol + c;
! 2404: if (raidPtr->Disks[r][sparecol].status == rf_ds_used_spare) {
! 2405: /*
! 2406: * XXX This is where we get fancy and map this spare
! 2407: * into it's correct spot in the array.
! 2408: */
! 2409: /*
! 2410: * We claim this disk is "optimal" if it's
! 2411: * rf_ds_used_spare, as that means it should be
! 2412: * directly substitutable for the disk it replaced.
! 2413: * We note that too...
! 2414: */
! 2415:
! 2416: for(i=0;i<raidPtr->numRow;i++) {
! 2417: for(j=0;j<raidPtr->numCol;j++) {
! 2418: if ((raidPtr->Disks[i][j].spareRow ==
! 2419: r) &&
! 2420: (raidPtr->Disks[i][j].spareCol ==
! 2421: sparecol)) {
! 2422: srow = r;
! 2423: scol = sparecol;
! 2424: break;
! 2425: }
! 2426: }
! 2427: }
! 2428:
! 2429: raidread_component_label(
! 2430: raidPtr->Disks[r][sparecol].dev,
! 2431: raidPtr->raid_cinfo[r][sparecol].ci_vp, &clabel);
! 2432: /* Make sure status is noted. */
! 2433: clabel.version = RF_COMPONENT_LABEL_VERSION;
! 2434: clabel.mod_counter = raidPtr->mod_counter;
! 2435: clabel.serial_number = raidPtr->serial_number;
! 2436: clabel.row = srow;
! 2437: clabel.column = scol;
! 2438: clabel.num_rows = raidPtr->numRow;
! 2439: clabel.num_columns = raidPtr->numCol;
! 2440: clabel.clean = RF_RAID_DIRTY; /* Changed in a bit. */
! 2441: clabel.status = rf_ds_optimal;
! 2442: raidwrite_component_label(
! 2443: raidPtr->Disks[r][sparecol].dev,
! 2444: raidPtr->raid_cinfo[r][sparecol].ci_vp, &clabel);
! 2445: raidmarkclean( raidPtr->Disks[r][sparecol].dev,
! 2446: raidPtr->raid_cinfo[r][sparecol].ci_vp);
! 2447: }
! 2448: }
! 2449:
! 2450: #endif
! 2451: }
! 2452:
! 2453:
! 2454: void
! 2455: rf_update_component_labels(RF_Raid_t *raidPtr, int final)
! 2456: {
! 2457: RF_ComponentLabel_t clabel;
! 2458: int sparecol;
! 2459: int r,c;
! 2460: int i,j;
! 2461: int srow, scol;
! 2462:
! 2463: srow = -1;
! 2464: scol = -1;
! 2465:
! 2466: /*
! 2467: * XXX should do extra checks to make sure things really are clean,
! 2468: * rather than blindly setting the clean bit...
! 2469: */
! 2470:
! 2471: raidPtr->mod_counter++;
! 2472:
! 2473: for (r = 0; r < raidPtr->numRow; r++) {
! 2474: for (c = 0; c < raidPtr->numCol; c++) {
! 2475: if (raidPtr->Disks[r][c].status == rf_ds_optimal) {
! 2476: raidread_component_label(
! 2477: raidPtr->Disks[r][c].dev,
! 2478: raidPtr->raid_cinfo[r][c].ci_vp,
! 2479: &clabel);
! 2480: /* Make sure status is noted. */
! 2481: clabel.status = rf_ds_optimal;
! 2482: /* Bump the counter. */
! 2483: clabel.mod_counter = raidPtr->mod_counter;
! 2484:
! 2485: raidwrite_component_label(
! 2486: raidPtr->Disks[r][c].dev,
! 2487: raidPtr->raid_cinfo[r][c].ci_vp,
! 2488: &clabel);
! 2489: if (final == RF_FINAL_COMPONENT_UPDATE) {
! 2490: if (raidPtr->parity_good ==
! 2491: RF_RAID_CLEAN) {
! 2492: raidmarkclean(
! 2493: raidPtr->Disks[r][c].dev,
! 2494: raidPtr->
! 2495: raid_cinfo[r][c].ci_vp,
! 2496: raidPtr->mod_counter);
! 2497: }
! 2498: }
! 2499: }
! 2500: /* Else we don't touch it... */
! 2501: }
! 2502: }
! 2503:
! 2504: for( c = 0; c < raidPtr->numSpare ; c++) {
! 2505: sparecol = raidPtr->numCol + c;
! 2506: if (raidPtr->Disks[0][sparecol].status == rf_ds_used_spare) {
! 2507: /*
! 2508: * We claim this disk is "optimal" if it's
! 2509: * rf_ds_used_spare, as that means it should be
! 2510: * directly substitutable for the disk it replaced.
! 2511: * We note that too...
! 2512: */
! 2513:
! 2514: for(i=0;i<raidPtr->numRow;i++) {
! 2515: for(j=0;j<raidPtr->numCol;j++) {
! 2516: if ((raidPtr->Disks[i][j].spareRow ==
! 2517: 0) &&
! 2518: (raidPtr->Disks[i][j].spareCol ==
! 2519: sparecol)) {
! 2520: srow = i;
! 2521: scol = j;
! 2522: break;
! 2523: }
! 2524: }
! 2525: }
! 2526:
! 2527: /* XXX Shouldn't *really* need this... */
! 2528: raidread_component_label(
! 2529: raidPtr->Disks[0][sparecol].dev,
! 2530: raidPtr->raid_cinfo[0][sparecol].ci_vp, &clabel);
! 2531: /* Make sure status is noted. */
! 2532:
! 2533: raid_init_component_label(raidPtr, &clabel);
! 2534:
! 2535: clabel.mod_counter = raidPtr->mod_counter;
! 2536: clabel.row = srow;
! 2537: clabel.column = scol;
! 2538: clabel.status = rf_ds_optimal;
! 2539:
! 2540: raidwrite_component_label(
! 2541: raidPtr->Disks[0][sparecol].dev,
! 2542: raidPtr->raid_cinfo[0][sparecol].ci_vp, &clabel);
! 2543: if (final == RF_FINAL_COMPONENT_UPDATE) {
! 2544: if (raidPtr->parity_good == RF_RAID_CLEAN) {
! 2545: raidmarkclean(raidPtr->
! 2546: Disks[0][sparecol].dev,
! 2547: raidPtr->
! 2548: raid_cinfo[0][sparecol].ci_vp,
! 2549: raidPtr->mod_counter);
! 2550: }
! 2551: }
! 2552: }
! 2553: }
! 2554: /*printf("Component labels updated\n");*/
! 2555: }
! 2556:
! 2557: void
! 2558: rf_close_component(RF_Raid_t *raidPtr, struct vnode *vp, int auto_configured)
! 2559: {
! 2560: struct proc *p = curproc;
! 2561:
! 2562: if (vp != NULL) {
! 2563: if (auto_configured == 1) {
! 2564: /* component was opened by rf_find_raid_components() */
! 2565: VOP_CLOSE(vp, FREAD | FWRITE, NOCRED, p);
! 2566: vrele(vp);
! 2567: } else {
! 2568: /* component was opened by raidlookup() */
! 2569: (void) vn_close(vp, FREAD | FWRITE, p->p_ucred, p);
! 2570: }
! 2571: } else {
! 2572: printf("vnode was NULL\n");
! 2573: }
! 2574: }
! 2575:
! 2576: void
! 2577: rf_UnconfigureVnodes(RF_Raid_t *raidPtr)
! 2578: {
! 2579: int r,c;
! 2580: struct vnode *vp;
! 2581: int acd;
! 2582:
! 2583:
! 2584: /* We take this opportunity to close the vnodes like we should... */
! 2585:
! 2586: for (r = 0; r < raidPtr->numRow; r++) {
! 2587: for (c = 0; c < raidPtr->numCol; c++) {
! 2588: db1_printf(("Closing vnode for row: %d col: %d\n",
! 2589: r, c));
! 2590: vp = raidPtr->raid_cinfo[r][c].ci_vp;
! 2591: acd = raidPtr->Disks[r][c].auto_configured;
! 2592: rf_close_component(raidPtr, vp, acd);
! 2593: raidPtr->raid_cinfo[r][c].ci_vp = NULL;
! 2594: raidPtr->Disks[r][c].auto_configured = 0;
! 2595: }
! 2596: }
! 2597: for (r = 0; r < raidPtr->numSpare; r++) {
! 2598: db1_printf(("Closing vnode for spare: %d\n", r));
! 2599: vp = raidPtr->raid_cinfo[0][raidPtr->numCol + r].ci_vp;
! 2600: acd = raidPtr->Disks[0][raidPtr->numCol + r].auto_configured;
! 2601: rf_close_component(raidPtr, vp, acd);
! 2602: raidPtr->raid_cinfo[0][raidPtr->numCol + r].ci_vp = NULL;
! 2603: raidPtr->Disks[0][raidPtr->numCol + r].auto_configured = 0;
! 2604: }
! 2605: }
! 2606:
! 2607:
! 2608: void
! 2609: rf_ReconThread(struct rf_recon_req *req)
! 2610: {
! 2611: int s;
! 2612: RF_Raid_t *raidPtr;
! 2613:
! 2614: s = splbio();
! 2615: raidPtr = (RF_Raid_t *) req->raidPtr;
! 2616: raidPtr->recon_in_progress = 1;
! 2617:
! 2618: rf_FailDisk((RF_Raid_t *) req->raidPtr, req->row, req->col,
! 2619: ((req->flags & RF_FDFLAGS_RECON) ? 1 : 0));
! 2620:
! 2621: /* XXX Get rid of this! we don't need it at all... */
! 2622: RF_Free(req, sizeof(*req));
! 2623:
! 2624: raidPtr->recon_in_progress = 0;
! 2625: splx(s);
! 2626:
! 2627: /* That's all... */
! 2628: kthread_exit(0); /* Does not return. */
! 2629: }
! 2630:
! 2631: void
! 2632: rf_RewriteParityThread(RF_Raid_t *raidPtr)
! 2633: {
! 2634: int retcode;
! 2635: int s;
! 2636:
! 2637: s = splbio();
! 2638: raidPtr->parity_rewrite_in_progress = 1;
! 2639: retcode = rf_RewriteParity(raidPtr);
! 2640: if (retcode) {
! 2641: printf("raid%d: Error re-writing parity!\n",raidPtr->raidid);
! 2642: } else {
! 2643: /*
! 2644: * Set the clean bit ! If we shutdown correctly,
! 2645: * the clean bit on each component label will get
! 2646: * set.
! 2647: */
! 2648: raidPtr->parity_good = RF_RAID_CLEAN;
! 2649: }
! 2650: raidPtr->parity_rewrite_in_progress = 0;
! 2651: splx(s);
! 2652:
! 2653: /* Anyone waiting for us to stop ? If so, inform them... */
! 2654: if (raidPtr->waitShutdown) {
! 2655: wakeup(&raidPtr->parity_rewrite_in_progress);
! 2656: }
! 2657:
! 2658: /* That's all... */
! 2659: kthread_exit(0); /* Does not return. */
! 2660: }
! 2661:
! 2662:
! 2663: void
! 2664: rf_CopybackThread(RF_Raid_t *raidPtr)
! 2665: {
! 2666: int s;
! 2667:
! 2668: s = splbio();
! 2669: raidPtr->copyback_in_progress = 1;
! 2670: rf_CopybackReconstructedData(raidPtr);
! 2671: raidPtr->copyback_in_progress = 0;
! 2672: splx(s);
! 2673:
! 2674: /* That's all... */
! 2675: kthread_exit(0); /* Does not return. */
! 2676: }
! 2677:
! 2678:
! 2679: void
! 2680: rf_ReconstructInPlaceThread(struct rf_recon_req *req)
! 2681: {
! 2682: int retcode;
! 2683: int s;
! 2684: RF_Raid_t *raidPtr;
! 2685:
! 2686: s = splbio();
! 2687: raidPtr = req->raidPtr;
! 2688: raidPtr->recon_in_progress = 1;
! 2689: retcode = rf_ReconstructInPlace(raidPtr, req->row, req->col);
! 2690: RF_Free(req, sizeof(*req));
! 2691: raidPtr->recon_in_progress = 0;
! 2692: splx(s);
! 2693:
! 2694: /* That's all... */
! 2695: kthread_exit(0); /* Does not return. */
! 2696: }
! 2697:
! 2698:
! 2699: RF_AutoConfig_t *
! 2700: rf_find_raid_components(void)
! 2701: {
! 2702: #ifdef RAID_AUTOCONFIG
! 2703: int major;
! 2704: struct vnode *vp;
! 2705: struct disklabel label;
! 2706: struct device *dv;
! 2707: dev_t dev;
! 2708: int error;
! 2709: int i;
! 2710: int good_one;
! 2711: RF_ComponentLabel_t *clabel;
! 2712: RF_AutoConfig_t *ac;
! 2713: #endif /* RAID_AUTOCONFIG */
! 2714: RF_AutoConfig_t *ac_list;
! 2715:
! 2716:
! 2717: /* Initialize the AutoConfig list. */
! 2718: ac_list = NULL;
! 2719:
! 2720: #ifdef RAID_AUTOCONFIG
! 2721: /* We begin by trolling through *all* the devices on the system. */
! 2722:
! 2723: TAILQ_FOREACH(dv, &alldevs, dv_list) {
! 2724:
! 2725: /* We are only interested in disks... */
! 2726: if (dv->dv_class != DV_DISK)
! 2727: continue;
! 2728:
! 2729: /* We don't care about floppies... */
! 2730: if (!strcmp(dv->dv_cfdata->cf_driver->cd_name,"fd")) {
! 2731: continue;
! 2732: }
! 2733:
! 2734: /*
! 2735: * We need to find the device_name_to_block_device_major
! 2736: * stuff.
! 2737: */
! 2738: major = findblkmajor(dv);
! 2739:
! 2740: /* Get a vnode for the raw partition of this disk. */
! 2741:
! 2742: dev = MAKEDISKDEV(major, dv->dv_unit, RAW_PART);
! 2743: if (bdevvp(dev, &vp))
! 2744: panic("RAID can't alloc vnode");
! 2745:
! 2746: error = VOP_OPEN(vp, FREAD, NOCRED, 0);
! 2747:
! 2748: if (error) {
! 2749: /*
! 2750: * "Who cares." Continue looking
! 2751: * for something that exists.
! 2752: */
! 2753: vput(vp);
! 2754: continue;
! 2755: }
! 2756:
! 2757: /* Ok, the disk exists. Go get the disklabel. */
! 2758: error = VOP_IOCTL(vp, DIOCGDINFO, (caddr_t)&label,
! 2759: FREAD, NOCRED, 0);
! 2760: if (error) {
! 2761: /*
! 2762: * XXX can't happen - open() would
! 2763: * have errored out (or faked up one).
! 2764: */
! 2765: printf("can't get label for dev %s%c (%d)!?!?\n",
! 2766: dv->dv_xname, 'a' + RAW_PART, error);
! 2767: }
! 2768:
! 2769: /*
! 2770: * We don't need this any more. We'll allocate it again
! 2771: * a little later if we really do...
! 2772: */
! 2773: VOP_CLOSE(vp, FREAD | FWRITE, NOCRED, 0);
! 2774: vrele(vp);
! 2775:
! 2776: for (i=0; i < label.d_npartitions; i++) {
! 2777: /*
! 2778: * We only support partitions marked as RAID.
! 2779: * Except on sparc/sparc64 where FS_RAID doesn't
! 2780: * fit in the SUN disklabel and we need to look
! 2781: * into each and every partition !!!
! 2782: */
! 2783: #if !defined(__sparc__) && !defined(__sparc64__) && !defined(__sun3__)
! 2784: if (label.d_partitions[i].p_fstype != FS_RAID)
! 2785: continue;
! 2786: #else /* !__sparc__ && !__sparc64__ && !__sun3__ */
! 2787: if (label.d_partitions[i].p_fstype == FS_SWAP ||
! 2788: label.d_partitions[i].p_fstype == FS_UNUSED)
! 2789: continue;
! 2790: #endif /* __sparc__ || __sparc64__ || __sun3__ */
! 2791:
! 2792: dev = MAKEDISKDEV(major, dv->dv_unit, i);
! 2793: if (bdevvp(dev, &vp))
! 2794: panic("RAID can't alloc vnode");
! 2795:
! 2796: error = VOP_OPEN(vp, FREAD, NOCRED, 0);
! 2797: if (error) {
! 2798: /* Whatever... */
! 2799: vput(vp);
! 2800: continue;
! 2801: }
! 2802:
! 2803: good_one = 0;
! 2804:
! 2805: clabel = (RF_ComponentLabel_t *)
! 2806: malloc(sizeof(RF_ComponentLabel_t), M_RAIDFRAME,
! 2807: M_NOWAIT);
! 2808: if (clabel == NULL) {
! 2809: /* XXX CLEANUP HERE. */
! 2810: printf("RAID auto config: out of memory!\n");
! 2811: return(NULL); /* XXX probably should panic ? */
! 2812: }
! 2813:
! 2814: if (!raidread_component_label(dev, vp, clabel)) {
! 2815: /* Got the label. Does it look reasonable ? */
! 2816: if (rf_reasonable_label(clabel) &&
! 2817: (clabel->partitionSize <=
! 2818: DL_GETPSIZE(&label.d_partitions[i]))) {
! 2819: #ifdef RAIDDEBUG
! 2820: printf("Component on: %s%c: %d\n",
! 2821: dv->dv_xname, 'a'+i,
! 2822: DL_GETPSIZE(&label.d_partitions[i]));
! 2823: rf_print_component_label(clabel);
! 2824: #endif /* RAIDDEBUG */
! 2825: /*
! 2826: * If it's reasonable, add it,
! 2827: * else ignore it.
! 2828: */
! 2829: ac = (RF_AutoConfig_t *)
! 2830: malloc(sizeof(RF_AutoConfig_t),
! 2831: M_RAIDFRAME, M_NOWAIT);
! 2832: if (ac == NULL) {
! 2833: /* XXX should panic ??? */
! 2834: return(NULL);
! 2835: }
! 2836:
! 2837: snprintf(ac->devname,
! 2838: sizeof ac->devname, "%s%c",
! 2839: dv->dv_xname, 'a'+i);
! 2840: ac->dev = dev;
! 2841: ac->vp = vp;
! 2842: ac->clabel = clabel;
! 2843: ac->next = ac_list;
! 2844: ac_list = ac;
! 2845: good_one = 1;
! 2846: }
! 2847: }
! 2848: if (!good_one) {
! 2849: /* Cleanup. */
! 2850: free(clabel, M_RAIDFRAME);
! 2851: VOP_CLOSE(vp, FREAD | FWRITE, NOCRED, 0);
! 2852: vrele(vp);
! 2853: }
! 2854: }
! 2855: }
! 2856: #endif /* RAID_AUTOCONFIG */
! 2857: return(ac_list);
! 2858: }
! 2859:
! 2860: #ifdef RAID_AUTOCONFIG
! 2861: int
! 2862: rf_reasonable_label(RF_ComponentLabel_t *clabel)
! 2863: {
! 2864:
! 2865: if (((clabel->version==RF_COMPONENT_LABEL_VERSION_1) ||
! 2866: (clabel->version==RF_COMPONENT_LABEL_VERSION)) &&
! 2867: ((clabel->clean == RF_RAID_CLEAN) ||
! 2868: (clabel->clean == RF_RAID_DIRTY)) &&
! 2869: clabel->row >=0 &&
! 2870: clabel->column >= 0 &&
! 2871: clabel->num_rows > 0 &&
! 2872: clabel->num_columns > 0 &&
! 2873: clabel->row < clabel->num_rows &&
! 2874: clabel->column < clabel->num_columns &&
! 2875: clabel->blockSize > 0 &&
! 2876: clabel->numBlocks > 0) {
! 2877: /* Label looks reasonable enough... */
! 2878: return(1);
! 2879: }
! 2880: return(0);
! 2881: }
! 2882: #endif /* RAID_AUTOCONFIG */
! 2883:
! 2884: void
! 2885: rf_print_component_label(RF_ComponentLabel_t *clabel)
! 2886: {
! 2887: printf(" Row: %d Column: %d Num Rows: %d Num Columns: %d\n",
! 2888: clabel->row, clabel->column, clabel->num_rows, clabel->num_columns);
! 2889: printf(" Version: %d Serial Number: %d Mod Counter: %d\n",
! 2890: clabel->version, clabel->serial_number, clabel->mod_counter);
! 2891: printf(" Clean: %s Status: %d\n", clabel->clean ? "Yes" : "No",
! 2892: clabel->status );
! 2893: printf(" sectPerSU: %d SUsPerPU: %d SUsPerRU: %d\n",
! 2894: clabel->sectPerSU, clabel->SUsPerPU, clabel->SUsPerRU);
! 2895: printf(" RAID Level: %c blocksize: %d numBlocks: %d\n",
! 2896: (char) clabel->parityConfig, clabel->blockSize, clabel->numBlocks);
! 2897: printf(" Autoconfig: %s\n", clabel->autoconfigure ? "Yes" : "No" );
! 2898: printf(" Contains root partition: %s\n", clabel->root_partition ?
! 2899: "Yes" : "No" );
! 2900: printf(" Last configured as: raid%d\n", clabel->last_unit );
! 2901: #if 0
! 2902: printf(" Config order: %d\n", clabel->config_order);
! 2903: #endif
! 2904: }
! 2905:
! 2906: RF_ConfigSet_t *
! 2907: rf_create_auto_sets(RF_AutoConfig_t *ac_list)
! 2908: {
! 2909: RF_AutoConfig_t *ac;
! 2910: RF_ConfigSet_t *config_sets;
! 2911: RF_ConfigSet_t *cset;
! 2912: RF_AutoConfig_t *ac_next;
! 2913:
! 2914:
! 2915: config_sets = NULL;
! 2916:
! 2917: /*
! 2918: * Go through the AutoConfig list, and figure out which components
! 2919: * belong to what sets.
! 2920: */
! 2921: ac = ac_list;
! 2922: while(ac!=NULL) {
! 2923: /*
! 2924: * We're going to putz with ac->next, so save it here
! 2925: * for use at the end of the loop.
! 2926: */
! 2927: ac_next = ac->next;
! 2928:
! 2929: if (config_sets == NULL) {
! 2930: /* We will need at least this one... */
! 2931: config_sets = (RF_ConfigSet_t *)
! 2932: malloc(sizeof(RF_ConfigSet_t), M_RAIDFRAME,
! 2933: M_NOWAIT);
! 2934: if (config_sets == NULL) {
! 2935: panic("rf_create_auto_sets: No memory!");
! 2936: }
! 2937: /* This one is easy :) */
! 2938: config_sets->ac = ac;
! 2939: config_sets->next = NULL;
! 2940: config_sets->rootable = 0;
! 2941: ac->next = NULL;
! 2942: } else {
! 2943: /* Which set does this component fit into ? */
! 2944: cset = config_sets;
! 2945: while(cset!=NULL) {
! 2946: if (rf_does_it_fit(cset, ac)) {
! 2947: /* Looks like it matches... */
! 2948: ac->next = cset->ac;
! 2949: cset->ac = ac;
! 2950: break;
! 2951: }
! 2952: cset = cset->next;
! 2953: }
! 2954: if (cset==NULL) {
! 2955: /* Didn't find a match above... new set... */
! 2956: cset = (RF_ConfigSet_t *)
! 2957: malloc(sizeof(RF_ConfigSet_t),
! 2958: M_RAIDFRAME, M_NOWAIT);
! 2959: if (cset == NULL) {
! 2960: panic("rf_create_auto_sets: No memory!");
! 2961: }
! 2962: cset->ac = ac;
! 2963: ac->next = NULL;
! 2964: cset->next = config_sets;
! 2965: cset->rootable = 0;
! 2966: config_sets = cset;
! 2967: }
! 2968: }
! 2969: ac = ac_next;
! 2970: }
! 2971:
! 2972:
! 2973: return(config_sets);
! 2974: }
! 2975:
! 2976: int
! 2977: rf_does_it_fit(RF_ConfigSet_t *cset, RF_AutoConfig_t *ac)
! 2978: {
! 2979: RF_ComponentLabel_t *clabel1, *clabel2;
! 2980:
! 2981: /*
! 2982: * If this one matches the *first* one in the set, that's good
! 2983: * enough, since the other members of the set would have been
! 2984: * through here too...
! 2985: */
! 2986: /*
! 2987: * Note that we are not checking partitionSize here...
! 2988: *
! 2989: * Note that we are also not checking the mod_counters here.
! 2990: * If everything else matches except the mod_counter, that's
! 2991: * good enough for this test. We will deal with the mod_counters
! 2992: * a little later in the autoconfiguration process.
! 2993: *
! 2994: * (clabel1->mod_counter == clabel2->mod_counter) &&
! 2995: *
! 2996: * The reason we don't check for this is that failed disks
! 2997: * will have lower modification counts. If those disks are
! 2998: * not added to the set they used to belong to, then they will
! 2999: * form their own set, which may result in 2 different sets,
! 3000: * for example, competing to be configured at raid0, and
! 3001: * perhaps competing to be the root filesystem set. If the
! 3002: * wrong ones get configured, or both attempt to become /,
! 3003: * weird behaviour and or serious lossage will occur. Thus we
! 3004: * need to bring them into the fold here, and kick them out at
! 3005: * a later point.
! 3006: */
! 3007:
! 3008: clabel1 = cset->ac->clabel;
! 3009: clabel2 = ac->clabel;
! 3010: if ((clabel1->version == clabel2->version) &&
! 3011: (clabel1->serial_number == clabel2->serial_number) &&
! 3012: (clabel1->num_rows == clabel2->num_rows) &&
! 3013: (clabel1->num_columns == clabel2->num_columns) &&
! 3014: (clabel1->sectPerSU == clabel2->sectPerSU) &&
! 3015: (clabel1->SUsPerPU == clabel2->SUsPerPU) &&
! 3016: (clabel1->SUsPerRU == clabel2->SUsPerRU) &&
! 3017: (clabel1->parityConfig == clabel2->parityConfig) &&
! 3018: (clabel1->maxOutstanding == clabel2->maxOutstanding) &&
! 3019: (clabel1->blockSize == clabel2->blockSize) &&
! 3020: (clabel1->numBlocks == clabel2->numBlocks) &&
! 3021: (clabel1->autoconfigure == clabel2->autoconfigure) &&
! 3022: (clabel1->root_partition == clabel2->root_partition) &&
! 3023: (clabel1->last_unit == clabel2->last_unit) &&
! 3024: (clabel1->config_order == clabel2->config_order)) {
! 3025: /* If it get's here, it almost *has* to be a match. */
! 3026: } else {
! 3027: /* It's not consistent with somebody in the set... Punt. */
! 3028: return(0);
! 3029: }
! 3030: /* All was fine.. It must fit... */
! 3031: return(1);
! 3032: }
! 3033:
! 3034: int
! 3035: rf_have_enough_components(RF_ConfigSet_t *cset)
! 3036: {
! 3037: RF_AutoConfig_t *ac;
! 3038: RF_AutoConfig_t *auto_config;
! 3039: RF_ComponentLabel_t *clabel;
! 3040: int r,c;
! 3041: int num_rows;
! 3042: int num_cols;
! 3043: int num_missing;
! 3044: int mod_counter;
! 3045: int mod_counter_found;
! 3046: int even_pair_failed;
! 3047: char parity_type;
! 3048:
! 3049:
! 3050: /*
! 3051: * Check to see that we have enough 'live' components
! 3052: * of this set. If so, we can configure it if necessary.
! 3053: */
! 3054:
! 3055: num_rows = cset->ac->clabel->num_rows;
! 3056: num_cols = cset->ac->clabel->num_columns;
! 3057: parity_type = cset->ac->clabel->parityConfig;
! 3058:
! 3059: /* XXX Check for duplicate components !?!?!? */
! 3060:
! 3061: /* Determine what the mod_counter is supposed to be for this set. */
! 3062:
! 3063: mod_counter_found = 0;
! 3064: mod_counter = 0;
! 3065: ac = cset->ac;
! 3066: while(ac!=NULL) {
! 3067: if (mod_counter_found==0) {
! 3068: mod_counter = ac->clabel->mod_counter;
! 3069: mod_counter_found = 1;
! 3070: } else {
! 3071: if (ac->clabel->mod_counter > mod_counter) {
! 3072: mod_counter = ac->clabel->mod_counter;
! 3073: }
! 3074: }
! 3075: ac = ac->next;
! 3076: }
! 3077:
! 3078: num_missing = 0;
! 3079: auto_config = cset->ac;
! 3080:
! 3081: for(r=0; r<num_rows; r++) {
! 3082: even_pair_failed = 0;
! 3083: for(c=0; c<num_cols; c++) {
! 3084: ac = auto_config;
! 3085: while(ac!=NULL) {
! 3086: if ((ac->clabel->row == r) &&
! 3087: (ac->clabel->column == c) &&
! 3088: (ac->clabel->mod_counter == mod_counter)) {
! 3089: /* It's this one... */
! 3090: #ifdef RAIDDEBUG
! 3091: printf("Found: %s at %d,%d\n",
! 3092: ac->devname,r,c);
! 3093: #endif /* RAIDDEBUG */
! 3094: break;
! 3095: }
! 3096: ac=ac->next;
! 3097: }
! 3098: if (ac==NULL) {
! 3099: /* Didn't find one here! */
! 3100: /*
! 3101: * Special case for RAID 1, especially
! 3102: * where there are more than 2
! 3103: * components (where RAIDframe treats
! 3104: * things a little differently :( )
! 3105: */
! 3106: if (parity_type == '1') {
! 3107: if (c%2 == 0) { /* Even component. */
! 3108: even_pair_failed = 1;
! 3109: } else { /*
! 3110: * Odd component.
! 3111: * If we're failed,
! 3112: * and so is the even
! 3113: * component, it's
! 3114: * "Good Night, Charlie"
! 3115: */
! 3116: if (even_pair_failed == 1) {
! 3117: return(0);
! 3118: }
! 3119: }
! 3120: } else {
! 3121: /* Normal accounting. */
! 3122: num_missing++;
! 3123: }
! 3124: }
! 3125: if ((parity_type == '1') && (c%2 == 1)) {
! 3126: /*
! 3127: * Just did an even component, and we didn't
! 3128: * bail... Reset the even_pair_failed flag,
! 3129: * and go on to the next component...
! 3130: */
! 3131: even_pair_failed = 0;
! 3132: }
! 3133: }
! 3134: }
! 3135:
! 3136: clabel = cset->ac->clabel;
! 3137:
! 3138: if (((clabel->parityConfig == '0') && (num_missing > 0)) ||
! 3139: ((clabel->parityConfig == '4') && (num_missing > 1)) ||
! 3140: ((clabel->parityConfig == '5') && (num_missing > 1))) {
! 3141: /* XXX This needs to be made *much* more general. */
! 3142: /* Too many failures. */
! 3143: return(0);
! 3144: }
! 3145: /*
! 3146: * Otherwise, all is well, and we've got enough to take a kick
! 3147: * at autoconfiguring this set.
! 3148: */
! 3149: return(1);
! 3150: }
! 3151:
! 3152: void
! 3153: rf_create_configuration(RF_AutoConfig_t *ac, RF_Config_t *config,
! 3154: RF_Raid_t *raidPtr)
! 3155: {
! 3156: RF_ComponentLabel_t *clabel;
! 3157: int i;
! 3158:
! 3159: clabel = ac->clabel;
! 3160:
! 3161: /* 1. Fill in the common stuff. */
! 3162: config->numRow = clabel->num_rows;
! 3163: config->numCol = clabel->num_columns;
! 3164: config->numSpare = 0; /* XXX Should this be set here ? */
! 3165: config->sectPerSU = clabel->sectPerSU;
! 3166: config->SUsPerPU = clabel->SUsPerPU;
! 3167: config->SUsPerRU = clabel->SUsPerRU;
! 3168: config->parityConfig = clabel->parityConfig;
! 3169: /* XXX... */
! 3170: strlcpy(config->diskQueueType,"fifo", sizeof config->diskQueueType);
! 3171: config->maxOutstandingDiskReqs = clabel->maxOutstanding;
! 3172: config->layoutSpecificSize = 0; /* XXX ?? */
! 3173:
! 3174: while(ac!=NULL) {
! 3175: /*
! 3176: * row/col values will be in range due to the checks
! 3177: * in reasonable_label().
! 3178: */
! 3179: strlcpy(config->devnames[ac->clabel->row][ac->clabel->column],
! 3180: ac->devname,
! 3181: sizeof config->devnames[ac->clabel->row][ac->clabel->column]);
! 3182: ac = ac->next;
! 3183: }
! 3184:
! 3185: for(i=0;i<RF_MAXDBGV;i++) {
! 3186: config->debugVars[i][0] = NULL;
! 3187: }
! 3188:
! 3189: #ifdef RAID_DEBUG_ALL
! 3190:
! 3191: #ifdef RF_DBG_OPTION
! 3192: #undef RF_DBG_OPTION
! 3193: #endif /* RF_DBG_OPTION */
! 3194:
! 3195: #ifdef __STDC__
! 3196: #define RF_DBG_OPTION(_option_,_val_) do { \
! 3197: snprintf(&(config->debugVars[i++][0]), 50, "%s %ld", \
! 3198: #_option_, _val_); \
! 3199: } while (0)
! 3200: #else /* __STDC__ */
! 3201: #define RF_DBG_OPTION(_option_,_val_) do { \
! 3202: snprintf(&(config->debugVars[i++][0]), 50, "%s %ld", \
! 3203: "/**/_option_/**/", _val_); \
! 3204: } while (0)
! 3205: #endif /* __STDC__ */
! 3206:
! 3207: i = 0;
! 3208:
! 3209: /* RF_DBG_OPTION(accessDebug, 0); */
! 3210: /* RF_DBG_OPTION(accessTraceBufSize, 0); */
! 3211: RF_DBG_OPTION(cscanDebug, 1); /* Debug CSCAN sorting. */
! 3212: RF_DBG_OPTION(dagDebug, 1);
! 3213: /* RF_DBG_OPTION(debugPrintUseBuffer, 0); */
! 3214: RF_DBG_OPTION(degDagDebug, 1);
! 3215: RF_DBG_OPTION(disableAsyncAccs, 1);
! 3216: RF_DBG_OPTION(diskDebug, 1);
! 3217: RF_DBG_OPTION(enableAtomicRMW, 0);
! 3218: /*
! 3219: * This debug variable enables locking of the
! 3220: * disk arm during small-write operations.
! 3221: * Setting this variable to anything other than
! 3222: * 0 will result in deadlock. (wvcii)
! 3223: */
! 3224: RF_DBG_OPTION(engineDebug, 1);
! 3225: RF_DBG_OPTION(fifoDebug, 1); /* Debug fifo queueing. */
! 3226: /* RF_DBG_OPTION(floatingRbufDebug, 1); */
! 3227: /* RF_DBG_OPTION(forceHeadSepLimit, -1); */
! 3228: /* RF_DBG_OPTION(forceNumFloatingReconBufs, -1); */
! 3229: /*
! 3230: * Wire down the number of extra recon buffers
! 3231: * to use.
! 3232: */
! 3233: /* RF_DBG_OPTION(keepAccTotals, 1); */
! 3234: /* Turn on keep_acc_totals. */
! 3235: RF_DBG_OPTION(lockTableSize, RF_DEFAULT_LOCK_TABLE_SIZE);
! 3236: RF_DBG_OPTION(mapDebug, 1);
! 3237: RF_DBG_OPTION(maxNumTraces, -1);
! 3238:
! 3239: /* RF_DBG_OPTION(memChunkDebug, 1); */
! 3240: /* RF_DBG_OPTION(memDebug, 1); */
! 3241: /* RF_DBG_OPTION(memDebugAddress, 1); */
! 3242: /* RF_DBG_OPTION(numBufsToAccumulate, 1); */
! 3243: /*
! 3244: * Number of buffers to accumulate before
! 3245: * doing XOR.
! 3246: */
! 3247: RF_DBG_OPTION(prReconSched, 0);
! 3248: RF_DBG_OPTION(printDAGsDebug, 1);
! 3249: RF_DBG_OPTION(printStatesDebug, 1);
! 3250: RF_DBG_OPTION(protectedSectors, 64L);
! 3251: /*
! 3252: * Number of sectors at start of disk to exclude
! 3253: * from RAID address space.
! 3254: */
! 3255: RF_DBG_OPTION(pssDebug, 1);
! 3256: RF_DBG_OPTION(queueDebug, 1);
! 3257: RF_DBG_OPTION(quiesceDebug, 1);
! 3258: RF_DBG_OPTION(raidSectorOffset, 0);
! 3259: /*
! 3260: * Value added to all incoming sectors to debug
! 3261: * alignment problems.
! 3262: */
! 3263: RF_DBG_OPTION(reconDebug, 1);
! 3264: RF_DBG_OPTION(reconbufferDebug, 1);
! 3265: RF_DBG_OPTION(scanDebug, 1); /* Debug SCAN sorting. */
! 3266: RF_DBG_OPTION(showXorCallCounts, 0);
! 3267: /* Show n-way Xor call counts. */
! 3268: RF_DBG_OPTION(shutdownDebug, 1); /* Show shutdown calls. */
! 3269: RF_DBG_OPTION(sizePercentage, 100);
! 3270: RF_DBG_OPTION(sstfDebug, 1);
! 3271: /* Turn on debugging info for sstf queueing. */
! 3272: RF_DBG_OPTION(stripeLockDebug, 1);
! 3273: RF_DBG_OPTION(suppressLocksAndLargeWrites, 0);
! 3274: RF_DBG_OPTION(suppressTraceDelays, 0);
! 3275: RF_DBG_OPTION(useMemChunks, 1);
! 3276: RF_DBG_OPTION(validateDAGDebug, 1);
! 3277: RF_DBG_OPTION(validateVisitedDebug, 1);
! 3278: /* XXX turn to zero by default ? */
! 3279: RF_DBG_OPTION(verifyParityDebug, 1);
! 3280: RF_DBG_OPTION(debugKernelAccess, 1);
! 3281: /* DoAccessKernel debugging. */
! 3282:
! 3283: #if RF_INCLUDE_PARITYLOGGING > 0
! 3284: RF_DBG_OPTION(forceParityLogReint, 0);
! 3285: RF_DBG_OPTION(numParityRegions, 0);
! 3286: /* Number of regions in the array. */
! 3287: RF_DBG_OPTION(numReintegrationThreads, 1);
! 3288: RF_DBG_OPTION(parityLogDebug, 1);
! 3289: /* If nonzero, enables debugging of parity logging. */
! 3290: RF_DBG_OPTION(totalInCoreLogCapacity, 1024 * 1024);
! 3291: /* Target bytes available for in-core logs. */
! 3292: #endif /* RF_INCLUDE_PARITYLOGGING > 0 */
! 3293:
! 3294: #endif /* RAID_DEBUG_ALL */
! 3295: }
! 3296:
! 3297: int
! 3298: rf_set_autoconfig(RF_Raid_t *raidPtr, int new_value)
! 3299: {
! 3300: RF_ComponentLabel_t clabel;
! 3301: struct vnode *vp;
! 3302: dev_t dev;
! 3303: int row, column;
! 3304:
! 3305: raidPtr->autoconfigure = new_value;
! 3306: for(row=0; row<raidPtr->numRow; row++) {
! 3307: for(column=0; column<raidPtr->numCol; column++) {
! 3308: if (raidPtr->Disks[row][column].status ==
! 3309: rf_ds_optimal) {
! 3310: dev = raidPtr->Disks[row][column].dev;
! 3311: vp = raidPtr->raid_cinfo[row][column].ci_vp;
! 3312: raidread_component_label(dev, vp, &clabel);
! 3313: clabel.autoconfigure = new_value;
! 3314: raidwrite_component_label(dev, vp, &clabel);
! 3315: }
! 3316: }
! 3317: }
! 3318: return(new_value);
! 3319: }
! 3320:
! 3321: int
! 3322: rf_set_rootpartition(RF_Raid_t *raidPtr, int new_value)
! 3323: {
! 3324: RF_ComponentLabel_t clabel;
! 3325: struct vnode *vp;
! 3326: dev_t dev;
! 3327: int row, column;
! 3328:
! 3329: raidPtr->root_partition = new_value;
! 3330: for(row=0; row<raidPtr->numRow; row++) {
! 3331: for(column=0; column<raidPtr->numCol; column++) {
! 3332: if (raidPtr->Disks[row][column].status ==
! 3333: rf_ds_optimal) {
! 3334: dev = raidPtr->Disks[row][column].dev;
! 3335: vp = raidPtr->raid_cinfo[row][column].ci_vp;
! 3336: raidread_component_label(dev, vp, &clabel);
! 3337: clabel.root_partition = new_value;
! 3338: raidwrite_component_label(dev, vp, &clabel);
! 3339: }
! 3340: }
! 3341: }
! 3342: return(new_value);
! 3343: }
! 3344:
! 3345: void
! 3346: rf_release_all_vps(RF_ConfigSet_t *cset)
! 3347: {
! 3348: RF_AutoConfig_t *ac;
! 3349:
! 3350: ac = cset->ac;
! 3351: while(ac!=NULL) {
! 3352: /* Close the vp, and give it back. */
! 3353: if (ac->vp) {
! 3354: VOP_CLOSE(ac->vp, FREAD, NOCRED, 0);
! 3355: vrele(ac->vp);
! 3356: ac->vp = NULL;
! 3357: }
! 3358: ac = ac->next;
! 3359: }
! 3360: }
! 3361:
! 3362:
! 3363: void
! 3364: rf_cleanup_config_set(RF_ConfigSet_t *cset)
! 3365: {
! 3366: RF_AutoConfig_t *ac;
! 3367: RF_AutoConfig_t *next_ac;
! 3368:
! 3369: ac = cset->ac;
! 3370: while(ac!=NULL) {
! 3371: next_ac = ac->next;
! 3372: /* Nuke the label. */
! 3373: free(ac->clabel, M_RAIDFRAME);
! 3374: /* Cleanup the config structure. */
! 3375: free(ac, M_RAIDFRAME);
! 3376: /* "next..." */
! 3377: ac = next_ac;
! 3378: }
! 3379: /* And, finally, nuke the config set. */
! 3380: free(cset, M_RAIDFRAME);
! 3381: }
! 3382:
! 3383:
! 3384: void
! 3385: raid_init_component_label(RF_Raid_t *raidPtr, RF_ComponentLabel_t *clabel)
! 3386: {
! 3387: /* Current version number. */
! 3388: clabel->version = RF_COMPONENT_LABEL_VERSION;
! 3389: clabel->serial_number = raidPtr->serial_number;
! 3390: clabel->mod_counter = raidPtr->mod_counter;
! 3391: clabel->num_rows = raidPtr->numRow;
! 3392: clabel->num_columns = raidPtr->numCol;
! 3393: clabel->clean = RF_RAID_DIRTY; /* Not clean. */
! 3394: clabel->status = rf_ds_optimal; /* "It's good !" */
! 3395:
! 3396: clabel->sectPerSU = raidPtr->Layout.sectorsPerStripeUnit;
! 3397: clabel->SUsPerPU = raidPtr->Layout.SUsPerPU;
! 3398: clabel->SUsPerRU = raidPtr->Layout.SUsPerRU;
! 3399:
! 3400: clabel->blockSize = raidPtr->bytesPerSector;
! 3401: clabel->numBlocks = raidPtr->sectorsPerDisk;
! 3402:
! 3403: /* XXX Not portable. */
! 3404: clabel->parityConfig = raidPtr->Layout.map->parityConfig;
! 3405: clabel->maxOutstanding = raidPtr->maxOutstanding;
! 3406: clabel->autoconfigure = raidPtr->autoconfigure;
! 3407: clabel->root_partition = raidPtr->root_partition;
! 3408: clabel->last_unit = raidPtr->raidid;
! 3409: clabel->config_order = raidPtr->config_order;
! 3410: }
! 3411:
! 3412: int
! 3413: rf_auto_config_set(RF_ConfigSet_t *cset, int *unit)
! 3414: {
! 3415: RF_Raid_t *raidPtr;
! 3416: RF_Config_t *config;
! 3417: int raidID;
! 3418: int retcode;
! 3419:
! 3420: db1_printf(("RAID autoconfigure\n"));
! 3421:
! 3422: retcode = 0;
! 3423: *unit = -1;
! 3424:
! 3425: /* 1. Create a config structure. */
! 3426:
! 3427: config = (RF_Config_t *)malloc(sizeof(RF_Config_t), M_RAIDFRAME,
! 3428: M_NOWAIT);
! 3429: if (config==NULL) {
! 3430: printf("Out of mem!?!?\n");
! 3431: /* XXX Do something more intelligent here. */
! 3432: return(1);
! 3433: }
! 3434:
! 3435: memset(config, 0, sizeof(RF_Config_t));
! 3436:
! 3437: /* XXX raidID needs to be set correctly... */
! 3438:
! 3439: /*
! 3440: * 2. Figure out what RAID ID this one is supposed to live at.
! 3441: * See if we can get the same RAID dev that it was configured
! 3442: * on last time...
! 3443: */
! 3444:
! 3445: raidID = cset->ac->clabel->last_unit;
! 3446: if ((raidID < 0) || (raidID >= numraid)) {
! 3447: /* Let's not wander off into lala land. */
! 3448: raidID = numraid - 1;
! 3449: }
! 3450: if (raidPtrs[raidID]->valid != 0) {
! 3451:
! 3452: /*
! 3453: * Nope... Go looking for an alternative...
! 3454: * Start high so we don't immediately use raid0 if that's
! 3455: * not taken.
! 3456: */
! 3457:
! 3458: for(raidID = numraid - 1; raidID >= 0; raidID--) {
! 3459: if (raidPtrs[raidID]->valid == 0) {
! 3460: /* We can use this one ! */
! 3461: break;
! 3462: }
! 3463: }
! 3464: }
! 3465:
! 3466: if (raidID < 0) {
! 3467: /* Punt... */
! 3468: printf("Unable to auto configure this set!\n");
! 3469: printf("(Out of RAID devs!)\n");
! 3470: return(1);
! 3471: }
! 3472: raidPtr = raidPtrs[raidID];
! 3473:
! 3474: /* XXX All this stuff should be done SOMEWHERE ELSE ! */
! 3475: raidPtr->raidid = raidID;
! 3476: raidPtr->openings = RAIDOUTSTANDING;
! 3477:
! 3478: /* 3. Build the configuration structure. */
! 3479: rf_create_configuration(cset->ac, config, raidPtr);
! 3480:
! 3481: /* 4. Do the configuration. */
! 3482: retcode = rf_Configure(raidPtr, config, cset->ac);
! 3483:
! 3484: if (retcode == 0) {
! 3485:
! 3486: raidinit(raidPtrs[raidID]);
! 3487:
! 3488: rf_markalldirty(raidPtrs[raidID]);
! 3489: raidPtrs[raidID]->autoconfigure = 1; /* XXX Do this here ? */
! 3490: if (cset->ac->clabel->root_partition==1) {
! 3491: /*
! 3492: * Everything configured just fine. Make a note
! 3493: * that this set is eligible to be root.
! 3494: */
! 3495: cset->rootable = 1;
! 3496: /* XXX Do this here ? */
! 3497: raidPtrs[raidID]->root_partition = 1;
! 3498: }
! 3499: }
! 3500:
! 3501: printf(": (%s) total number of sectors is %lu (%lu MB)%s\n",
! 3502: (raidPtrs[raidID]->Layout).map->configName,
! 3503: (unsigned long) raidPtrs[raidID]->totalSectors,
! 3504: (unsigned long) (raidPtrs[raidID]->totalSectors / 1024 *
! 3505: (1 << raidPtrs[raidID]->logBytesPerSector) / 1024),
! 3506: raidPtrs[raidID]->root_partition ? " as root" : "");
! 3507:
! 3508: /* 5. Cleanup. */
! 3509: free(config, M_RAIDFRAME);
! 3510:
! 3511: *unit = raidID;
! 3512: return(retcode);
! 3513: }
! 3514:
! 3515: void
! 3516: rf_disk_unbusy(RF_RaidAccessDesc_t *desc)
! 3517: {
! 3518: struct buf *bp;
! 3519:
! 3520: bp = (struct buf *)desc->bp;
! 3521: disk_unbusy(&raid_softc[desc->raidPtr->raidid].sc_dkdev,
! 3522: (bp->b_bcount - bp->b_resid),
! 3523: (bp->b_flags & B_READ));
! 3524: }
CVSweb