Home | History | Annotate | Line # | Download | only in raidframe
rf_driver.c revision 1.71
      1  1.71    martin /*	$NetBSD: rf_driver.c,v 1.71 2003/06/23 11:02:00 martin Exp $	*/
      2   1.9     oster /*-
      3   1.9     oster  * Copyright (c) 1999 The NetBSD Foundation, Inc.
      4   1.9     oster  * All rights reserved.
      5   1.9     oster  *
      6   1.9     oster  * This code is derived from software contributed to The NetBSD Foundation
      7   1.9     oster  * by Greg Oster
      8   1.9     oster  *
      9   1.9     oster  * Redistribution and use in source and binary forms, with or without
     10   1.9     oster  * modification, are permitted provided that the following conditions
     11   1.9     oster  * are met:
     12   1.9     oster  * 1. Redistributions of source code must retain the above copyright
     13   1.9     oster  *    notice, this list of conditions and the following disclaimer.
     14   1.9     oster  * 2. Redistributions in binary form must reproduce the above copyright
     15   1.9     oster  *    notice, this list of conditions and the following disclaimer in the
     16   1.9     oster  *    documentation and/or other materials provided with the distribution.
     17   1.9     oster  * 3. All advertising materials mentioning features or use of this software
     18   1.9     oster  *    must display the following acknowledgement:
     19   1.9     oster  *        This product includes software developed by the NetBSD
     20   1.9     oster  *        Foundation, Inc. and its contributors.
     21   1.9     oster  * 4. Neither the name of The NetBSD Foundation nor the names of its
     22   1.9     oster  *    contributors may be used to endorse or promote products derived
     23   1.9     oster  *    from this software without specific prior written permission.
     24   1.9     oster  *
     25   1.9     oster  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     26   1.9     oster  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     27   1.9     oster  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     28   1.9     oster  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     29   1.9     oster  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     30   1.9     oster  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     31   1.9     oster  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     32   1.9     oster  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     33   1.9     oster  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     34   1.9     oster  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     35   1.9     oster  * POSSIBILITY OF SUCH DAMAGE.
     36   1.9     oster  */
     37   1.9     oster 
     38   1.1     oster /*
     39   1.1     oster  * Copyright (c) 1995 Carnegie-Mellon University.
     40   1.1     oster  * All rights reserved.
     41   1.1     oster  *
     42   1.1     oster  * Author: Mark Holland, Khalil Amiri, Claudson Bornstein, William V. Courtright II,
     43   1.1     oster  *         Robby Findler, Daniel Stodolsky, Rachad Youssef, Jim Zelenka
     44   1.1     oster  *
     45   1.1     oster  * Permission to use, copy, modify and distribute this software and
     46   1.1     oster  * its documentation is hereby granted, provided that both the copyright
     47   1.1     oster  * notice and this permission notice appear in all copies of the
     48   1.1     oster  * software, derivative works or modified versions, and any portions
     49   1.1     oster  * thereof, and that both notices appear in supporting documentation.
     50   1.1     oster  *
     51   1.1     oster  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
     52   1.1     oster  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
     53   1.1     oster  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
     54   1.1     oster  *
     55   1.1     oster  * Carnegie Mellon requests users of this software to return to
     56   1.1     oster  *
     57   1.1     oster  *  Software Distribution Coordinator  or  Software.Distribution (at) CS.CMU.EDU
     58   1.1     oster  *  School of Computer Science
     59   1.1     oster  *  Carnegie Mellon University
     60   1.1     oster  *  Pittsburgh PA 15213-3890
     61   1.1     oster  *
     62   1.1     oster  * any improvements or extensions that they make and grant Carnegie the
     63   1.1     oster  * rights to redistribute these changes.
     64   1.1     oster  */
     65   1.1     oster 
     66   1.1     oster /******************************************************************************
     67   1.1     oster  *
     68   1.1     oster  * rf_driver.c -- main setup, teardown, and access routines for the RAID driver
     69   1.1     oster  *
     70   1.1     oster  * all routines are prefixed with rf_ (raidframe), to avoid conficts.
     71   1.1     oster  *
     72   1.1     oster  ******************************************************************************/
     73   1.1     oster 
     74  1.44     lukem 
     75  1.44     lukem #include <sys/cdefs.h>
     76  1.71    martin __KERNEL_RCSID(0, "$NetBSD: rf_driver.c,v 1.71 2003/06/23 11:02:00 martin Exp $");
     77  1.71    martin 
     78  1.71    martin #include "opt_raid_diagnostic.h"
     79   1.1     oster 
     80   1.1     oster #include <sys/param.h>
     81   1.1     oster #include <sys/systm.h>
     82   1.1     oster #include <sys/ioctl.h>
     83   1.1     oster #include <sys/fcntl.h>
     84   1.1     oster #include <sys/vnode.h>
     85   1.1     oster 
     86   1.1     oster 
     87   1.1     oster #include "rf_archs.h"
     88   1.1     oster #include "rf_threadstuff.h"
     89   1.1     oster 
     90   1.1     oster #include <sys/errno.h>
     91   1.1     oster 
     92   1.1     oster #include "rf_raid.h"
     93   1.1     oster #include "rf_dag.h"
     94   1.1     oster #include "rf_aselect.h"
     95   1.1     oster #include "rf_diskqueue.h"
     96   1.1     oster #include "rf_parityscan.h"
     97   1.1     oster #include "rf_alloclist.h"
     98   1.1     oster #include "rf_dagutils.h"
     99   1.1     oster #include "rf_utils.h"
    100   1.1     oster #include "rf_etimer.h"
    101   1.1     oster #include "rf_acctrace.h"
    102   1.1     oster #include "rf_general.h"
    103   1.1     oster #include "rf_desc.h"
    104   1.1     oster #include "rf_states.h"
    105   1.1     oster #include "rf_freelist.h"
    106   1.1     oster #include "rf_decluster.h"
    107   1.1     oster #include "rf_map.h"
    108   1.1     oster #include "rf_revent.h"
    109   1.1     oster #include "rf_callback.h"
    110   1.1     oster #include "rf_engine.h"
    111   1.1     oster #include "rf_mcpair.h"
    112   1.1     oster #include "rf_nwayxor.h"
    113   1.1     oster #include "rf_copyback.h"
    114   1.1     oster #include "rf_driver.h"
    115   1.1     oster #include "rf_options.h"
    116   1.1     oster #include "rf_shutdown.h"
    117  1.24     oster #include "rf_kintf.h"
    118   1.1     oster 
    119   1.1     oster #include <sys/buf.h>
    120   1.1     oster 
    121  1.61     oster #ifndef RF_ACCESS_DEBUG
    122  1.61     oster #define RF_ACCESS_DEBUG 0
    123  1.61     oster #endif
    124  1.61     oster 
    125   1.1     oster /* rad == RF_RaidAccessDesc_t */
    126   1.1     oster static RF_FreeList_t *rf_rad_freelist;
    127   1.1     oster #define RF_MAX_FREE_RAD 128
    128   1.1     oster #define RF_RAD_INC       16
    129   1.1     oster #define RF_RAD_INITIAL   32
    130   1.1     oster 
    131   1.1     oster /* debug variables */
    132   1.6     oster char    rf_panicbuf[2048];	/* a buffer to hold an error msg when we panic */
    133   1.1     oster 
    134   1.1     oster /* main configuration routines */
    135   1.1     oster static int raidframe_booted = 0;
    136   1.1     oster 
    137   1.6     oster static void rf_ConfigureDebug(RF_Config_t * cfgPtr);
    138   1.1     oster static void set_debug_option(char *name, long val);
    139   1.1     oster static void rf_UnconfigureArray(void);
    140   1.1     oster static int init_rad(RF_RaidAccessDesc_t *);
    141   1.1     oster static void clean_rad(RF_RaidAccessDesc_t *);
    142   1.1     oster static void rf_ShutdownRDFreeList(void *);
    143   1.1     oster static int rf_ConfigureRDFreeList(RF_ShutdownList_t **);
    144   1.1     oster 
    145   1.6     oster RF_DECLARE_MUTEX(rf_printf_mutex)	/* debug only:  avoids interleaved
    146   1.6     oster 					 * printfs by different stripes */
    147   1.1     oster 
    148   1.1     oster #define SIGNAL_QUIESCENT_COND(_raid_)  wakeup(&((_raid_)->accesses_suspended))
    149   1.1     oster #define WAIT_FOR_QUIESCENCE(_raid_) \
    150  1.38     oster 	ltsleep(&((_raid_)->accesses_suspended), PRIBIO, \
    151  1.38     oster 		"raidframe quiesce", 0, &((_raid_)->access_suspend_mutex))
    152   1.1     oster 
    153  1.20     oster #define IO_BUF_ERR(bp, err) { \
    154   1.1     oster 	bp->b_flags |= B_ERROR; \
    155   1.1     oster 	bp->b_resid = bp->b_bcount; \
    156   1.1     oster 	bp->b_error = err; \
    157   1.1     oster 	biodone(bp); \
    158   1.1     oster }
    159   1.1     oster 
    160   1.9     oster static int configureCount = 0;	/* number of active configurations */
    161   1.9     oster static int isconfigged = 0;	/* is basic raidframe (non per-array)
    162   1.9     oster 				 * stuff configged */
    163  1.55     oster RF_DECLARE_LKMGR_STATIC_MUTEX(configureMutex)	/* used to lock the configuration
    164   1.6     oster 					 * stuff */
    165   1.9     oster static RF_ShutdownList_t *globalShutdown;	/* non array-specific
    166   1.9     oster 						 * stuff */
    167   1.1     oster 
    168   1.9     oster static int rf_ConfigureRDFreeList(RF_ShutdownList_t ** listp);
    169   1.1     oster 
    170   1.1     oster /* called at system boot time */
    171   1.7     oster int
    172   1.7     oster rf_BootRaidframe()
    173   1.1     oster {
    174   1.6     oster 	int     rc;
    175   1.1     oster 
    176   1.6     oster 	if (raidframe_booted)
    177   1.6     oster 		return (EBUSY);
    178   1.6     oster 	raidframe_booted = 1;
    179   1.1     oster 
    180  1.55     oster 	rc = rf_lkmgr_mutex_init(&configureMutex);
    181   1.6     oster 	if (rc) {
    182  1.58     oster 		rf_print_unable_to_init_mutex( __FILE__, __LINE__, rc);
    183   1.6     oster 		RF_PANIC();
    184   1.6     oster 	}
    185   1.6     oster 	configureCount = 0;
    186   1.6     oster 	isconfigged = 0;
    187   1.6     oster 	globalShutdown = NULL;
    188   1.6     oster 	return (0);
    189   1.1     oster }
    190   1.1     oster 
    191   1.1     oster /*
    192   1.1     oster  * Called whenever an array is shutdown
    193   1.1     oster  */
    194   1.6     oster static void
    195   1.6     oster rf_UnconfigureArray()
    196   1.1     oster {
    197   1.6     oster 	int     rc;
    198   1.1     oster 
    199  1.55     oster 	RF_LOCK_LKMGR_MUTEX(configureMutex);
    200   1.6     oster 	if (--configureCount == 0) {	/* if no active configurations, shut
    201   1.6     oster 					 * everything down */
    202   1.6     oster 		isconfigged = 0;
    203   1.6     oster 
    204   1.6     oster 		rc = rf_ShutdownList(&globalShutdown);
    205   1.6     oster 		if (rc) {
    206   1.6     oster 			RF_ERRORMSG1("RAIDFRAME: unable to do global shutdown, rc=%d\n", rc);
    207   1.6     oster 		}
    208   1.6     oster 
    209   1.6     oster 		/*
    210   1.6     oster 	         * We must wait until now, because the AllocList module
    211   1.6     oster 	         * uses the DebugMem module.
    212   1.6     oster 	         */
    213  1.60     oster #if RF_DEBUG_MEM
    214   1.6     oster 		if (rf_memDebug)
    215   1.6     oster 			rf_print_unfreed();
    216  1.60     oster #endif
    217   1.6     oster 	}
    218  1.55     oster 	RF_UNLOCK_LKMGR_MUTEX(configureMutex);
    219   1.9     oster }
    220   1.9     oster 
    221   1.1     oster /*
    222   1.1     oster  * Called to shut down an array.
    223   1.1     oster  */
    224   1.6     oster int
    225   1.6     oster rf_Shutdown(raidPtr)
    226   1.6     oster 	RF_Raid_t *raidPtr;
    227   1.1     oster {
    228   1.1     oster 
    229   1.6     oster 	if (!raidPtr->valid) {
    230   1.6     oster 		RF_ERRORMSG("Attempt to shut down unconfigured RAIDframe driver.  Aborting shutdown\n");
    231   1.6     oster 		return (EINVAL);
    232   1.6     oster 	}
    233   1.6     oster 	/*
    234   1.6     oster          * wait for outstanding IOs to land
    235   1.6     oster          * As described in rf_raid.h, we use the rad_freelist lock
    236   1.6     oster          * to protect the per-array info about outstanding descs
    237   1.6     oster          * since we need to do freelist locking anyway, and this
    238   1.6     oster          * cuts down on the amount of serialization we've got going
    239   1.6     oster          * on.
    240   1.6     oster          */
    241   1.6     oster 	RF_FREELIST_DO_LOCK(rf_rad_freelist);
    242   1.6     oster 	if (raidPtr->waitShutdown) {
    243   1.6     oster 		RF_FREELIST_DO_UNLOCK(rf_rad_freelist);
    244   1.6     oster 		return (EBUSY);
    245   1.6     oster 	}
    246   1.6     oster 	raidPtr->waitShutdown = 1;
    247   1.6     oster 	while (raidPtr->nAccOutstanding) {
    248   1.6     oster 		RF_WAIT_COND(raidPtr->outstandingCond, RF_FREELIST_MUTEX_OF(rf_rad_freelist));
    249   1.6     oster 	}
    250   1.6     oster 	RF_FREELIST_DO_UNLOCK(rf_rad_freelist);
    251  1.35     oster 
    252  1.35     oster 	/* Wait for any parity re-writes to stop... */
    253  1.35     oster 	while (raidPtr->parity_rewrite_in_progress) {
    254  1.35     oster 		printf("Waiting for parity re-write to exit...\n");
    255  1.35     oster 		tsleep(&raidPtr->parity_rewrite_in_progress, PRIBIO,
    256  1.35     oster 		       "rfprwshutdown", 0);
    257  1.35     oster 	}
    258   1.6     oster 
    259   1.6     oster 	raidPtr->valid = 0;
    260   1.6     oster 
    261  1.37     oster 	rf_update_component_labels(raidPtr, RF_FINAL_COMPONENT_UPDATE);
    262   1.6     oster 
    263   1.7     oster 	rf_UnconfigureVnodes(raidPtr);
    264   1.7     oster 
    265   1.7     oster 	rf_ShutdownList(&raidPtr->shutdownList);
    266   1.7     oster 
    267   1.7     oster 	rf_UnconfigureArray();
    268   1.7     oster 
    269   1.7     oster 	return (0);
    270   1.7     oster }
    271   1.1     oster 
    272   1.6     oster 
    273   1.1     oster #define DO_INIT_CONFIGURE(f) { \
    274   1.1     oster 	rc = f (&globalShutdown); \
    275   1.1     oster 	if (rc) { \
    276   1.1     oster 		RF_ERRORMSG2("RAIDFRAME: failed %s with %d\n", RF_STRING(f), rc); \
    277   1.1     oster 		rf_ShutdownList(&globalShutdown); \
    278   1.1     oster 		configureCount--; \
    279  1.55     oster 		RF_UNLOCK_LKMGR_MUTEX(configureMutex); \
    280   1.1     oster 		return(rc); \
    281   1.1     oster 	} \
    282   1.1     oster }
    283   1.1     oster 
    284   1.1     oster #define DO_RAID_FAIL() { \
    285  1.12     oster 	rf_UnconfigureVnodes(raidPtr); \
    286   1.1     oster 	rf_ShutdownList(&raidPtr->shutdownList); \
    287   1.1     oster 	rf_UnconfigureArray(); \
    288   1.1     oster }
    289   1.1     oster 
    290   1.1     oster #define DO_RAID_INIT_CONFIGURE(f) { \
    291   1.1     oster 	rc = f (&raidPtr->shutdownList, raidPtr, cfgPtr); \
    292   1.1     oster 	if (rc) { \
    293   1.1     oster 		RF_ERRORMSG2("RAIDFRAME: failed %s with %d\n", RF_STRING(f), rc); \
    294   1.1     oster 		DO_RAID_FAIL(); \
    295   1.1     oster 		return(rc); \
    296   1.1     oster 	} \
    297   1.1     oster }
    298   1.1     oster 
    299   1.1     oster #define DO_RAID_MUTEX(_m_) { \
    300   1.1     oster 	rc = rf_create_managed_mutex(&raidPtr->shutdownList, (_m_)); \
    301   1.1     oster 	if (rc) { \
    302  1.58     oster 		rf_print_unable_to_init_mutex(__FILE__, __LINE__, rc); \
    303   1.1     oster 		DO_RAID_FAIL(); \
    304   1.1     oster 		return(rc); \
    305   1.1     oster 	} \
    306   1.1     oster }
    307   1.1     oster 
    308   1.1     oster #define DO_RAID_COND(_c_) { \
    309   1.1     oster 	rc = rf_create_managed_cond(&raidPtr->shutdownList, (_c_)); \
    310   1.1     oster 	if (rc) { \
    311  1.58     oster 		rf_print_unable_to_init_cond(__FILE__, __LINE__, rc); \
    312   1.1     oster 		DO_RAID_FAIL(); \
    313   1.1     oster 		return(rc); \
    314   1.1     oster 	} \
    315   1.1     oster }
    316   1.1     oster 
    317   1.6     oster int
    318  1.28     oster rf_Configure(raidPtr, cfgPtr, ac)
    319   1.6     oster 	RF_Raid_t *raidPtr;
    320   1.6     oster 	RF_Config_t *cfgPtr;
    321  1.28     oster 	RF_AutoConfig_t *ac;
    322   1.6     oster {
    323   1.6     oster 	RF_RowCol_t row, col;
    324   1.6     oster 	int     i, rc;
    325   1.6     oster 
    326  1.55     oster 	RF_LOCK_LKMGR_MUTEX(configureMutex);
    327   1.6     oster 	configureCount++;
    328   1.6     oster 	if (isconfigged == 0) {
    329   1.6     oster 		rc = rf_create_managed_mutex(&globalShutdown, &rf_printf_mutex);
    330   1.6     oster 		if (rc) {
    331  1.58     oster 			rf_print_unable_to_init_mutex(__FILE__, __LINE__, rc);
    332   1.6     oster 			rf_ShutdownList(&globalShutdown);
    333   1.6     oster 			return (rc);
    334   1.6     oster 		}
    335   1.6     oster 		/* initialize globals */
    336   1.6     oster 
    337   1.6     oster 		DO_INIT_CONFIGURE(rf_ConfigureAllocList);
    338  1.28     oster 
    339   1.6     oster 		/*
    340  1.28     oster 	         * Yes, this does make debugging general to the whole
    341  1.28     oster 	         * system instead of being array specific. Bummer, drag.
    342  1.28     oster 		 */
    343   1.6     oster 		rf_ConfigureDebug(cfgPtr);
    344   1.6     oster 		DO_INIT_CONFIGURE(rf_ConfigureDebugMem);
    345   1.6     oster 		DO_INIT_CONFIGURE(rf_ConfigureAccessTrace);
    346   1.6     oster 		DO_INIT_CONFIGURE(rf_ConfigureMapModule);
    347   1.6     oster 		DO_INIT_CONFIGURE(rf_ConfigureReconEvent);
    348   1.6     oster 		DO_INIT_CONFIGURE(rf_ConfigureCallback);
    349   1.6     oster 		DO_INIT_CONFIGURE(rf_ConfigureRDFreeList);
    350   1.6     oster 		DO_INIT_CONFIGURE(rf_ConfigureNWayXor);
    351   1.6     oster 		DO_INIT_CONFIGURE(rf_ConfigureStripeLockFreeList);
    352   1.6     oster 		DO_INIT_CONFIGURE(rf_ConfigureMCPair);
    353   1.6     oster 		DO_INIT_CONFIGURE(rf_ConfigureDAGs);
    354   1.6     oster 		DO_INIT_CONFIGURE(rf_ConfigureDAGFuncs);
    355   1.6     oster 		DO_INIT_CONFIGURE(rf_ConfigureReconstruction);
    356   1.6     oster 		DO_INIT_CONFIGURE(rf_ConfigureCopyback);
    357   1.6     oster 		DO_INIT_CONFIGURE(rf_ConfigureDiskQueueSystem);
    358   1.6     oster 		isconfigged = 1;
    359   1.6     oster 	}
    360  1.55     oster 	RF_UNLOCK_LKMGR_MUTEX(configureMutex);
    361   1.6     oster 
    362   1.6     oster 	DO_RAID_MUTEX(&raidPtr->mutex);
    363   1.6     oster 	/* set up the cleanup list.  Do this after ConfigureDebug so that
    364   1.6     oster 	 * value of memDebug will be set */
    365   1.6     oster 
    366   1.6     oster 	rf_MakeAllocList(raidPtr->cleanupList);
    367   1.6     oster 	if (raidPtr->cleanupList == NULL) {
    368   1.6     oster 		DO_RAID_FAIL();
    369   1.6     oster 		return (ENOMEM);
    370   1.6     oster 	}
    371   1.6     oster 	rc = rf_ShutdownCreate(&raidPtr->shutdownList,
    372   1.6     oster 	    (void (*) (void *)) rf_FreeAllocList,
    373   1.6     oster 	    raidPtr->cleanupList);
    374   1.6     oster 	if (rc) {
    375  1.58     oster 		rf_print_unable_to_add_shutdown(__FILE__, __LINE__, rc);
    376   1.6     oster 		DO_RAID_FAIL();
    377   1.6     oster 		return (rc);
    378   1.6     oster 	}
    379   1.6     oster 	raidPtr->numRow = cfgPtr->numRow;
    380   1.6     oster 	raidPtr->numCol = cfgPtr->numCol;
    381   1.6     oster 	raidPtr->numSpare = cfgPtr->numSpare;
    382   1.6     oster 
    383   1.6     oster 	/* XXX we don't even pretend to support more than one row in the
    384   1.6     oster 	 * kernel... */
    385   1.6     oster 	if (raidPtr->numRow != 1) {
    386   1.6     oster 		RF_ERRORMSG("Only one row supported in kernel.\n");
    387   1.6     oster 		DO_RAID_FAIL();
    388   1.6     oster 		return (EINVAL);
    389   1.6     oster 	}
    390   1.6     oster 	RF_CallocAndAdd(raidPtr->status, raidPtr->numRow, sizeof(RF_RowStatus_t),
    391   1.6     oster 	    (RF_RowStatus_t *), raidPtr->cleanupList);
    392   1.6     oster 	if (raidPtr->status == NULL) {
    393   1.6     oster 		DO_RAID_FAIL();
    394   1.6     oster 		return (ENOMEM);
    395   1.6     oster 	}
    396   1.6     oster 	RF_CallocAndAdd(raidPtr->reconControl, raidPtr->numRow,
    397   1.6     oster 	    sizeof(RF_ReconCtrl_t *), (RF_ReconCtrl_t **), raidPtr->cleanupList);
    398   1.6     oster 	if (raidPtr->reconControl == NULL) {
    399   1.6     oster 		DO_RAID_FAIL();
    400   1.6     oster 		return (ENOMEM);
    401   1.6     oster 	}
    402   1.6     oster 	for (i = 0; i < raidPtr->numRow; i++) {
    403   1.6     oster 		raidPtr->status[i] = rf_rs_optimal;
    404   1.6     oster 		raidPtr->reconControl[i] = NULL;
    405   1.6     oster 	}
    406  1.64     oster 
    407  1.64     oster 	TAILQ_INIT(&(raidPtr->iodone));
    408  1.64     oster 	simple_lock_init(&(raidPtr->iodone_lock));
    409   1.6     oster 
    410   1.6     oster 	DO_RAID_INIT_CONFIGURE(rf_ConfigureEngine);
    411   1.6     oster 	DO_RAID_INIT_CONFIGURE(rf_ConfigureStripeLocks);
    412   1.6     oster 
    413   1.6     oster 	DO_RAID_COND(&raidPtr->outstandingCond);
    414   1.6     oster 
    415   1.6     oster 	raidPtr->nAccOutstanding = 0;
    416   1.6     oster 	raidPtr->waitShutdown = 0;
    417   1.6     oster 
    418   1.6     oster 	DO_RAID_MUTEX(&raidPtr->access_suspend_mutex);
    419   1.6     oster 	DO_RAID_COND(&raidPtr->quiescent_cond);
    420   1.6     oster 
    421   1.6     oster 	DO_RAID_COND(&raidPtr->waitForReconCond);
    422   1.6     oster 
    423   1.6     oster 	DO_RAID_MUTEX(&raidPtr->recon_done_proc_mutex);
    424  1.28     oster 
    425  1.28     oster 	if (ac!=NULL) {
    426  1.28     oster 		/* We have an AutoConfig structure..  Don't do the
    427  1.28     oster 		   normal disk configuration... call the auto config
    428  1.28     oster 		   stuff */
    429  1.28     oster 		rf_AutoConfigureDisks(raidPtr, cfgPtr, ac);
    430  1.28     oster 	} else {
    431  1.28     oster 		DO_RAID_INIT_CONFIGURE(rf_ConfigureDisks);
    432  1.28     oster 		DO_RAID_INIT_CONFIGURE(rf_ConfigureSpareDisks);
    433  1.28     oster 	}
    434   1.6     oster 	/* do this after ConfigureDisks & ConfigureSpareDisks to be sure dev
    435   1.6     oster 	 * no. is set */
    436   1.6     oster 	DO_RAID_INIT_CONFIGURE(rf_ConfigureDiskQueues);
    437   1.6     oster 
    438   1.6     oster 	DO_RAID_INIT_CONFIGURE(rf_ConfigureLayout);
    439   1.6     oster 
    440   1.6     oster 	DO_RAID_INIT_CONFIGURE(rf_ConfigurePSStatus);
    441   1.6     oster 
    442   1.6     oster 	for (row = 0; row < raidPtr->numRow; row++) {
    443   1.6     oster 		for (col = 0; col < raidPtr->numCol; col++) {
    444   1.6     oster 			/*
    445   1.6     oster 		         * XXX better distribution
    446   1.6     oster 		         */
    447   1.6     oster 			raidPtr->hist_diskreq[row][col] = 0;
    448   1.6     oster 		}
    449   1.6     oster 	}
    450  1.28     oster 
    451  1.30     oster 	raidPtr->numNewFailures = 0;
    452  1.28     oster 	raidPtr->copyback_in_progress = 0;
    453  1.28     oster 	raidPtr->parity_rewrite_in_progress = 0;
    454  1.66     oster 	raidPtr->adding_hot_spare = 0;
    455  1.28     oster 	raidPtr->recon_in_progress = 0;
    456  1.29     oster 	raidPtr->maxOutstanding = cfgPtr->maxOutstandingDiskReqs;
    457  1.29     oster 
    458  1.29     oster 	/* autoconfigure and root_partition will actually get filled in
    459  1.29     oster 	   after the config is done */
    460  1.29     oster 	raidPtr->autoconfigure = 0;
    461  1.29     oster 	raidPtr->root_partition = 0;
    462  1.29     oster 	raidPtr->last_unit = raidPtr->raidid;
    463  1.29     oster 	raidPtr->config_order = 0;
    464   1.6     oster 
    465   1.6     oster 	if (rf_keepAccTotals) {
    466   1.6     oster 		raidPtr->keep_acc_totals = 1;
    467   1.6     oster 	}
    468   1.6     oster 	rf_StartUserStats(raidPtr);
    469   1.1     oster 
    470   1.6     oster 	raidPtr->valid = 1;
    471  1.52     oster 
    472  1.52     oster 	printf("raid%d: %s\n", raidPtr->raidid,
    473  1.52     oster 	       raidPtr->Layout.map->configName);
    474  1.52     oster 	printf("raid%d: Components:", raidPtr->raidid);
    475  1.52     oster 	for (row = 0; row < raidPtr->numRow; row++) {
    476  1.52     oster 		for (col = 0; col < raidPtr->numCol; col++) {
    477  1.52     oster 			printf(" %s", raidPtr->Disks[row][col].devname);
    478  1.52     oster 			if (RF_DEAD_DISK(raidPtr->Disks[row][col].status)) {
    479  1.52     oster 				printf("[**FAILED**]");
    480  1.52     oster 			}
    481  1.52     oster 		}
    482  1.52     oster 	}
    483  1.52     oster 	printf("\n");
    484  1.52     oster 	printf("raid%d: Total Sectors: %lu (%lu MB)\n",
    485  1.52     oster 	       raidPtr->raidid,
    486  1.52     oster 	       (unsigned long) raidPtr->totalSectors,
    487  1.52     oster 	       (unsigned long) (raidPtr->totalSectors / 1024 *
    488  1.52     oster 				(1 << raidPtr->logBytesPerSector) / 1024));
    489  1.50     oster 
    490   1.6     oster 	return (0);
    491   1.1     oster }
    492   1.1     oster 
    493   1.6     oster static int
    494   1.6     oster init_rad(desc)
    495   1.6     oster 	RF_RaidAccessDesc_t *desc;
    496   1.1     oster {
    497   1.6     oster 	int     rc;
    498   1.1     oster 
    499   1.1     oster 	rc = rf_mutex_init(&desc->mutex);
    500   1.1     oster 	if (rc) {
    501  1.58     oster 		rf_print_unable_to_init_mutex(__FILE__, __LINE__, rc);
    502   1.6     oster 		return (rc);
    503   1.1     oster 	}
    504   1.1     oster 	rc = rf_cond_init(&desc->cond);
    505   1.1     oster 	if (rc) {
    506  1.58     oster 		rf_print_unable_to_init_cond(__FILE__, __LINE__, rc);
    507   1.1     oster 		rf_mutex_destroy(&desc->mutex);
    508   1.6     oster 		return (rc);
    509   1.1     oster 	}
    510   1.6     oster 	return (0);
    511   1.1     oster }
    512   1.1     oster 
    513   1.6     oster static void
    514   1.6     oster clean_rad(desc)
    515   1.6     oster 	RF_RaidAccessDesc_t *desc;
    516   1.1     oster {
    517   1.1     oster 	rf_mutex_destroy(&desc->mutex);
    518   1.1     oster 	rf_cond_destroy(&desc->cond);
    519   1.1     oster }
    520   1.1     oster 
    521   1.6     oster static void
    522   1.6     oster rf_ShutdownRDFreeList(ignored)
    523   1.6     oster 	void   *ignored;
    524   1.1     oster {
    525   1.6     oster 	RF_FREELIST_DESTROY_CLEAN(rf_rad_freelist, next, (RF_RaidAccessDesc_t *), clean_rad);
    526   1.1     oster }
    527   1.1     oster 
    528   1.6     oster static int
    529   1.6     oster rf_ConfigureRDFreeList(listp)
    530   1.6     oster 	RF_ShutdownList_t **listp;
    531   1.1     oster {
    532   1.6     oster 	int     rc;
    533   1.1     oster 
    534   1.1     oster 	RF_FREELIST_CREATE(rf_rad_freelist, RF_MAX_FREE_RAD,
    535   1.6     oster 	    RF_RAD_INC, sizeof(RF_RaidAccessDesc_t));
    536   1.1     oster 	if (rf_rad_freelist == NULL) {
    537   1.6     oster 		return (ENOMEM);
    538   1.1     oster 	}
    539   1.1     oster 	rc = rf_ShutdownCreate(listp, rf_ShutdownRDFreeList, NULL);
    540   1.1     oster 	if (rc) {
    541  1.58     oster 		rf_print_unable_to_add_shutdown(__FILE__, __LINE__, rc);
    542   1.1     oster 		rf_ShutdownRDFreeList(NULL);
    543   1.6     oster 		return (rc);
    544   1.1     oster 	}
    545   1.6     oster 	RF_FREELIST_PRIME_INIT(rf_rad_freelist, RF_RAD_INITIAL, next,
    546   1.6     oster 	    (RF_RaidAccessDesc_t *), init_rad);
    547   1.6     oster 	return (0);
    548   1.6     oster }
    549   1.6     oster 
    550   1.6     oster RF_RaidAccessDesc_t *
    551   1.6     oster rf_AllocRaidAccDesc(
    552   1.6     oster     RF_Raid_t * raidPtr,
    553   1.6     oster     RF_IoType_t type,
    554   1.6     oster     RF_RaidAddr_t raidAddress,
    555   1.6     oster     RF_SectorCount_t numBlocks,
    556   1.6     oster     caddr_t bufPtr,
    557   1.6     oster     void *bp,
    558   1.6     oster     RF_RaidAccessFlags_t flags,
    559   1.6     oster     RF_AccessState_t * states)
    560   1.6     oster {
    561   1.6     oster 	RF_RaidAccessDesc_t *desc;
    562   1.6     oster 
    563   1.6     oster 	RF_FREELIST_GET_INIT_NOUNLOCK(rf_rad_freelist, desc, next, (RF_RaidAccessDesc_t *), init_rad);
    564   1.6     oster 	if (raidPtr->waitShutdown) {
    565   1.6     oster 		/*
    566   1.6     oster 	         * Actually, we're shutting the array down. Free the desc
    567   1.6     oster 	         * and return NULL.
    568   1.6     oster 	         */
    569   1.6     oster 		RF_FREELIST_DO_UNLOCK(rf_rad_freelist);
    570   1.6     oster 		RF_FREELIST_FREE_CLEAN(rf_rad_freelist, desc, next, clean_rad);
    571   1.6     oster 		return (NULL);
    572   1.6     oster 	}
    573   1.6     oster 	raidPtr->nAccOutstanding++;
    574   1.6     oster 	RF_FREELIST_DO_UNLOCK(rf_rad_freelist);
    575   1.6     oster 
    576   1.6     oster 	desc->raidPtr = (void *) raidPtr;
    577   1.6     oster 	desc->type = type;
    578   1.6     oster 	desc->raidAddress = raidAddress;
    579   1.6     oster 	desc->numBlocks = numBlocks;
    580   1.6     oster 	desc->bufPtr = bufPtr;
    581   1.6     oster 	desc->bp = bp;
    582  1.41     oster 	desc->paramDAG = NULL;
    583  1.41     oster 	desc->paramASM = NULL;
    584   1.6     oster 	desc->flags = flags;
    585   1.6     oster 	desc->states = states;
    586   1.6     oster 	desc->state = 0;
    587   1.6     oster 
    588   1.6     oster 	desc->status = 0;
    589  1.40   thorpej 	memset((char *) &desc->tracerec, 0, sizeof(RF_AccTraceEntry_t));
    590  1.41     oster 	desc->callbackFunc = NULL;
    591  1.41     oster 	desc->callbackArg = NULL;
    592   1.6     oster 	desc->next = NULL;
    593   1.6     oster 	desc->head = desc;
    594   1.6     oster 	desc->cleanupList = NULL;
    595   1.6     oster 	rf_MakeAllocList(desc->cleanupList);
    596   1.6     oster 	return (desc);
    597   1.6     oster }
    598   1.6     oster 
    599   1.6     oster void
    600   1.6     oster rf_FreeRaidAccDesc(RF_RaidAccessDesc_t * desc)
    601   1.6     oster {
    602   1.6     oster 	RF_Raid_t *raidPtr = desc->raidPtr;
    603   1.6     oster 
    604   1.6     oster 	RF_ASSERT(desc);
    605   1.6     oster 
    606   1.6     oster 	rf_FreeAllocList(desc->cleanupList);
    607   1.6     oster 	RF_FREELIST_FREE_CLEAN_NOUNLOCK(rf_rad_freelist, desc, next, clean_rad);
    608   1.6     oster 	raidPtr->nAccOutstanding--;
    609   1.6     oster 	if (raidPtr->waitShutdown) {
    610   1.6     oster 		RF_SIGNAL_COND(raidPtr->outstandingCond);
    611   1.6     oster 	}
    612   1.6     oster 	RF_FREELIST_DO_UNLOCK(rf_rad_freelist);
    613   1.1     oster }
    614   1.1     oster /*********************************************************************
    615   1.1     oster  * Main routine for performing an access.
    616   1.1     oster  * Accesses are retried until a DAG can not be selected.  This occurs
    617   1.1     oster  * when either the DAG library is incomplete or there are too many
    618   1.1     oster  * failures in a parity group.
    619   1.1     oster  ********************************************************************/
    620   1.6     oster int
    621   1.6     oster rf_DoAccess(
    622   1.6     oster     RF_Raid_t * raidPtr,
    623   1.6     oster     RF_IoType_t type,
    624   1.6     oster     int async_flag,
    625   1.6     oster     RF_RaidAddr_t raidAddress,
    626   1.6     oster     RF_SectorCount_t numBlocks,
    627   1.6     oster     caddr_t bufPtr,
    628   1.6     oster     void *bp_in,
    629  1.41     oster     RF_RaidAccessFlags_t flags)
    630   1.1     oster /*
    631   1.1     oster type should be read or write
    632   1.1     oster async_flag should be RF_TRUE or RF_FALSE
    633   1.1     oster bp_in is a buf pointer.  void * to facilitate ignoring it outside the kernel
    634   1.1     oster */
    635   1.1     oster {
    636   1.6     oster 	RF_RaidAccessDesc_t *desc;
    637   1.6     oster 	caddr_t lbufPtr = bufPtr;
    638   1.6     oster 	struct buf *bp = (struct buf *) bp_in;
    639   1.6     oster 
    640   1.6     oster 	raidAddress += rf_raidSectorOffset;
    641   1.6     oster 
    642  1.61     oster #if RF_ACCESS_DEBUG
    643   1.6     oster 	if (rf_accessDebug) {
    644   1.1     oster 
    645   1.6     oster 		printf("logBytes is: %d %d %d\n", raidPtr->raidid,
    646   1.6     oster 		    raidPtr->logBytesPerSector,
    647   1.6     oster 		    (int) rf_RaidAddressToByte(raidPtr, numBlocks));
    648  1.22     oster 		printf("raid%d: %s raidAddr %d (stripeid %d-%d) numBlocks %d (%d bytes) buf 0x%lx\n", raidPtr->raidid,
    649   1.6     oster 		    (type == RF_IO_TYPE_READ) ? "READ" : "WRITE", (int) raidAddress,
    650   1.6     oster 		    (int) rf_RaidAddressToStripeID(&raidPtr->Layout, raidAddress),
    651   1.6     oster 		    (int) rf_RaidAddressToStripeID(&raidPtr->Layout, raidAddress + numBlocks - 1),
    652   1.6     oster 		    (int) numBlocks,
    653   1.6     oster 		    (int) rf_RaidAddressToByte(raidPtr, numBlocks),
    654   1.6     oster 		    (long) bufPtr);
    655   1.6     oster 	}
    656  1.61     oster #endif
    657   1.6     oster 	if (raidAddress + numBlocks > raidPtr->totalSectors) {
    658   1.1     oster 
    659   1.6     oster 		printf("DoAccess: raid addr %lu too large to access %lu sectors.  Max legal addr is %lu\n",
    660   1.6     oster 		    (u_long) raidAddress, (u_long) numBlocks, (u_long) raidPtr->totalSectors);
    661   1.1     oster 
    662  1.20     oster 		IO_BUF_ERR(bp, ENOSPC);
    663  1.16     oster 		return (ENOSPC);
    664   1.6     oster 	}
    665   1.6     oster 	desc = rf_AllocRaidAccDesc(raidPtr, type, raidAddress,
    666  1.41     oster 	    numBlocks, lbufPtr, bp, flags, raidPtr->Layout.map->states);
    667   1.1     oster 
    668   1.6     oster 	if (desc == NULL) {
    669   1.6     oster 		return (ENOMEM);
    670   1.6     oster 	}
    671   1.6     oster 	RF_ETIMER_START(desc->tracerec.tot_timer);
    672   1.1     oster 
    673   1.6     oster 	desc->async_flag = async_flag;
    674   1.3  explorer 
    675   1.6     oster 	rf_ContinueRaidAccess(desc);
    676   1.1     oster 
    677   1.6     oster 	return (0);
    678   1.1     oster }
    679  1.46     oster #if 0
    680   1.1     oster /* force the array into reconfigured mode without doing reconstruction */
    681   1.6     oster int
    682   1.6     oster rf_SetReconfiguredMode(raidPtr, row, col)
    683   1.6     oster 	RF_Raid_t *raidPtr;
    684   1.6     oster 	int     row;
    685   1.6     oster 	int     col;
    686   1.6     oster {
    687   1.6     oster 	if (!(raidPtr->Layout.map->flags & RF_DISTRIBUTE_SPARE)) {
    688   1.6     oster 		printf("Can't set reconfigured mode in dedicated-spare array\n");
    689   1.6     oster 		RF_PANIC();
    690   1.6     oster 	}
    691   1.6     oster 	RF_LOCK_MUTEX(raidPtr->mutex);
    692   1.6     oster 	raidPtr->numFailures++;
    693   1.6     oster 	raidPtr->Disks[row][col].status = rf_ds_dist_spared;
    694   1.6     oster 	raidPtr->status[row] = rf_rs_reconfigured;
    695  1.37     oster 	rf_update_component_labels(raidPtr, RF_NORMAL_COMPONENT_UPDATE);
    696   1.6     oster 	/* install spare table only if declustering + distributed sparing
    697   1.6     oster 	 * architecture. */
    698   1.6     oster 	if (raidPtr->Layout.map->flags & RF_BD_DECLUSTERED)
    699   1.6     oster 		rf_InstallSpareTable(raidPtr, row, col);
    700   1.6     oster 	RF_UNLOCK_MUTEX(raidPtr->mutex);
    701   1.6     oster 	return (0);
    702   1.1     oster }
    703  1.46     oster #endif
    704   1.1     oster 
    705   1.6     oster int
    706   1.6     oster rf_FailDisk(
    707   1.6     oster     RF_Raid_t * raidPtr,
    708   1.6     oster     int frow,
    709   1.6     oster     int fcol,
    710   1.6     oster     int initRecon)
    711   1.6     oster {
    712   1.6     oster 	RF_LOCK_MUTEX(raidPtr->mutex);
    713  1.68     oster 	if (raidPtr->Disks[frow][fcol].status != rf_ds_failed) {
    714  1.68     oster 		/* must be failing something that is valid, or else it's
    715  1.68     oster 		   already marked as failed (in which case we don't
    716  1.68     oster 		   want to mark it failed again!) */
    717  1.68     oster 		raidPtr->numFailures++;
    718  1.68     oster 		raidPtr->Disks[frow][fcol].status = rf_ds_failed;
    719  1.68     oster 		raidPtr->status[frow] = rf_rs_degraded;
    720  1.68     oster 	}
    721  1.65     oster 	RF_UNLOCK_MUTEX(raidPtr->mutex);
    722  1.68     oster 
    723  1.37     oster 	rf_update_component_labels(raidPtr, RF_NORMAL_COMPONENT_UPDATE);
    724  1.68     oster 
    725  1.56     oster 	/* Close the component, so that it's not "locked" if someone
    726  1.56     oster 	   else want's to use it! */
    727  1.56     oster 
    728  1.56     oster 	rf_close_component(raidPtr, raidPtr->raid_cinfo[frow][fcol].ci_vp,
    729  1.56     oster 			   raidPtr->Disks[frow][fcol].auto_configured);
    730  1.65     oster 
    731  1.65     oster 	RF_LOCK_MUTEX(raidPtr->mutex);
    732  1.56     oster 	raidPtr->raid_cinfo[frow][fcol].ci_vp = NULL;
    733  1.56     oster 
    734  1.56     oster 	/* Need to mark the component as not being auto_configured
    735  1.56     oster 	   (in case it was previously). */
    736  1.56     oster 
    737  1.56     oster 	raidPtr->Disks[frow][fcol].auto_configured = 0;
    738  1.65     oster 	RF_UNLOCK_MUTEX(raidPtr->mutex);
    739  1.56     oster 
    740   1.6     oster 	if (initRecon)
    741   1.6     oster 		rf_ReconstructFailedDisk(raidPtr, frow, fcol);
    742   1.6     oster 	return (0);
    743   1.1     oster }
    744   1.1     oster /* releases a thread that is waiting for the array to become quiesced.
    745   1.1     oster  * access_suspend_mutex should be locked upon calling this
    746   1.1     oster  */
    747   1.6     oster void
    748  1.63     oster rf_SignalQuiescenceLock(raidPtr)
    749   1.6     oster 	RF_Raid_t *raidPtr;
    750   1.6     oster {
    751  1.61     oster #if RF_DEBUG_QUIESCE
    752   1.6     oster 	if (rf_quiesceDebug) {
    753  1.22     oster 		printf("raid%d: Signalling quiescence lock\n",
    754  1.22     oster 		       raidPtr->raidid);
    755   1.6     oster 	}
    756  1.61     oster #endif
    757   1.6     oster 	raidPtr->access_suspend_release = 1;
    758   1.6     oster 
    759   1.6     oster 	if (raidPtr->waiting_for_quiescence) {
    760   1.6     oster 		SIGNAL_QUIESCENT_COND(raidPtr);
    761   1.6     oster 	}
    762   1.1     oster }
    763   1.1     oster /* suspends all new requests to the array.  No effect on accesses that are in flight.  */
    764   1.6     oster int
    765   1.6     oster rf_SuspendNewRequestsAndWait(raidPtr)
    766   1.6     oster 	RF_Raid_t *raidPtr;
    767   1.6     oster {
    768  1.61     oster #if RF_DEBUG_QUIESCE
    769   1.6     oster 	if (rf_quiesceDebug)
    770  1.53     oster 		printf("raid%d: Suspending new reqs\n", raidPtr->raidid);
    771  1.61     oster #endif
    772   1.6     oster 	RF_LOCK_MUTEX(raidPtr->access_suspend_mutex);
    773   1.6     oster 	raidPtr->accesses_suspended++;
    774   1.6     oster 	raidPtr->waiting_for_quiescence = (raidPtr->accs_in_flight == 0) ? 0 : 1;
    775   1.6     oster 
    776   1.6     oster 	if (raidPtr->waiting_for_quiescence) {
    777   1.6     oster 		raidPtr->access_suspend_release = 0;
    778   1.6     oster 		while (!raidPtr->access_suspend_release) {
    779  1.53     oster 			printf("raid%d: Suspending: Waiting for Quiescence\n",
    780  1.53     oster 			       raidPtr->raidid);
    781   1.6     oster 			WAIT_FOR_QUIESCENCE(raidPtr);
    782   1.6     oster 			raidPtr->waiting_for_quiescence = 0;
    783   1.6     oster 		}
    784   1.6     oster 	}
    785  1.53     oster 	printf("raid%d: Quiescence reached..\n", raidPtr->raidid);
    786   1.1     oster 
    787   1.6     oster 	RF_UNLOCK_MUTEX(raidPtr->access_suspend_mutex);
    788   1.6     oster 	return (raidPtr->waiting_for_quiescence);
    789   1.1     oster }
    790   1.1     oster /* wake up everyone waiting for quiescence to be released */
    791   1.6     oster void
    792   1.6     oster rf_ResumeNewRequests(raidPtr)
    793   1.6     oster 	RF_Raid_t *raidPtr;
    794   1.6     oster {
    795   1.6     oster 	RF_CallbackDesc_t *t, *cb;
    796   1.6     oster 
    797  1.61     oster #if RF_DEBUG_QUIESCE
    798   1.6     oster 	if (rf_quiesceDebug)
    799   1.6     oster 		printf("Resuming new reqs\n");
    800  1.61     oster #endif
    801   1.6     oster 
    802   1.6     oster 	RF_LOCK_MUTEX(raidPtr->access_suspend_mutex);
    803   1.6     oster 	raidPtr->accesses_suspended--;
    804   1.6     oster 	if (raidPtr->accesses_suspended == 0)
    805   1.6     oster 		cb = raidPtr->quiesce_wait_list;
    806   1.6     oster 	else
    807   1.6     oster 		cb = NULL;
    808   1.6     oster 	raidPtr->quiesce_wait_list = NULL;
    809   1.6     oster 	RF_UNLOCK_MUTEX(raidPtr->access_suspend_mutex);
    810   1.6     oster 
    811   1.6     oster 	while (cb) {
    812   1.6     oster 		t = cb;
    813   1.6     oster 		cb = cb->next;
    814   1.6     oster 		(t->callbackFunc) (t->callbackArg);
    815   1.6     oster 		rf_FreeCallbackDesc(t);
    816   1.6     oster 	}
    817   1.1     oster }
    818   1.1     oster /*****************************************************************************************
    819   1.1     oster  *
    820   1.1     oster  * debug routines
    821   1.1     oster  *
    822   1.1     oster  ****************************************************************************************/
    823   1.1     oster 
    824   1.6     oster static void
    825   1.6     oster set_debug_option(name, val)
    826   1.6     oster 	char   *name;
    827   1.6     oster 	long    val;
    828   1.6     oster {
    829   1.6     oster 	RF_DebugName_t *p;
    830   1.6     oster 
    831   1.6     oster 	for (p = rf_debugNames; p->name; p++) {
    832   1.6     oster 		if (!strcmp(p->name, name)) {
    833   1.6     oster 			*(p->ptr) = val;
    834   1.6     oster 			printf("[Set debug variable %s to %ld]\n", name, val);
    835   1.6     oster 			return;
    836   1.6     oster 		}
    837   1.6     oster 	}
    838   1.6     oster 	RF_ERRORMSG1("Unknown debug string \"%s\"\n", name);
    839   1.1     oster }
    840   1.1     oster 
    841   1.1     oster 
    842   1.1     oster /* would like to use sscanf here, but apparently not available in kernel */
    843   1.1     oster /*ARGSUSED*/
    844   1.6     oster static void
    845   1.6     oster rf_ConfigureDebug(cfgPtr)
    846   1.6     oster 	RF_Config_t *cfgPtr;
    847   1.6     oster {
    848   1.6     oster 	char   *val_p, *name_p, *white_p;
    849   1.6     oster 	long    val;
    850   1.6     oster 	int     i;
    851   1.6     oster 
    852   1.6     oster 	rf_ResetDebugOptions();
    853   1.6     oster 	for (i = 0; cfgPtr->debugVars[i][0] && i < RF_MAXDBGV; i++) {
    854   1.6     oster 		name_p = rf_find_non_white(&cfgPtr->debugVars[i][0]);
    855   1.6     oster 		white_p = rf_find_white(name_p);	/* skip to start of 2nd
    856   1.6     oster 							 * word */
    857   1.6     oster 		val_p = rf_find_non_white(white_p);
    858   1.6     oster 		if (*val_p == '0' && *(val_p + 1) == 'x')
    859   1.6     oster 			val = rf_htoi(val_p + 2);
    860   1.6     oster 		else
    861   1.6     oster 			val = rf_atoi(val_p);
    862   1.6     oster 		*white_p = '\0';
    863   1.6     oster 		set_debug_option(name_p, val);
    864   1.6     oster 	}
    865   1.1     oster }
    866   1.1     oster /* performance monitoring stuff */
    867   1.1     oster 
    868   1.1     oster #define TIMEVAL_TO_US(t) (((long) t.tv_sec) * 1000000L + (long) t.tv_usec)
    869   1.1     oster 
    870   1.4     oster #if !defined(_KERNEL) && !defined(SIMULATE)
    871   1.1     oster 
    872   1.1     oster /*
    873   1.1     oster  * Throughput stats currently only used in user-level RAIDframe
    874   1.1     oster  */
    875   1.1     oster 
    876   1.6     oster static int
    877   1.6     oster rf_InitThroughputStats(
    878   1.6     oster     RF_ShutdownList_t ** listp,
    879   1.6     oster     RF_Raid_t * raidPtr,
    880   1.6     oster     RF_Config_t * cfgPtr)
    881   1.1     oster {
    882   1.6     oster 	int     rc;
    883   1.1     oster 
    884   1.6     oster 	/* these used by user-level raidframe only */
    885   1.6     oster 	rc = rf_create_managed_mutex(listp, &raidPtr->throughputstats.mutex);
    886   1.6     oster 	if (rc) {
    887  1.58     oster 		rf_print_unable_to_init_mutex(__FILE__, __LINE__, rc);
    888   1.6     oster 		return (rc);
    889   1.6     oster 	}
    890   1.6     oster 	raidPtr->throughputstats.sum_io_us = 0;
    891   1.6     oster 	raidPtr->throughputstats.num_ios = 0;
    892   1.6     oster 	raidPtr->throughputstats.num_out_ios = 0;
    893   1.6     oster 	return (0);
    894   1.6     oster }
    895   1.6     oster 
    896   1.6     oster void
    897   1.6     oster rf_StartThroughputStats(RF_Raid_t * raidPtr)
    898   1.6     oster {
    899   1.6     oster 	RF_LOCK_MUTEX(raidPtr->throughputstats.mutex);
    900   1.6     oster 	raidPtr->throughputstats.num_ios++;
    901   1.6     oster 	raidPtr->throughputstats.num_out_ios++;
    902   1.6     oster 	if (raidPtr->throughputstats.num_out_ios == 1)
    903   1.6     oster 		RF_GETTIME(raidPtr->throughputstats.start);
    904   1.6     oster 	RF_UNLOCK_MUTEX(raidPtr->throughputstats.mutex);
    905   1.6     oster }
    906   1.6     oster 
    907   1.6     oster static void
    908   1.6     oster rf_StopThroughputStats(RF_Raid_t * raidPtr)
    909   1.6     oster {
    910   1.6     oster 	struct timeval diff;
    911   1.6     oster 
    912   1.6     oster 	RF_LOCK_MUTEX(raidPtr->throughputstats.mutex);
    913   1.6     oster 	raidPtr->throughputstats.num_out_ios--;
    914   1.6     oster 	if (raidPtr->throughputstats.num_out_ios == 0) {
    915   1.6     oster 		RF_GETTIME(raidPtr->throughputstats.stop);
    916   1.6     oster 		RF_TIMEVAL_DIFF(&raidPtr->throughputstats.start, &raidPtr->throughputstats.stop, &diff);
    917   1.6     oster 		raidPtr->throughputstats.sum_io_us += TIMEVAL_TO_US(diff);
    918   1.6     oster 	}
    919   1.6     oster 	RF_UNLOCK_MUTEX(raidPtr->throughputstats.mutex);
    920   1.1     oster }
    921   1.1     oster 
    922   1.6     oster static void
    923   1.6     oster rf_PrintThroughputStats(RF_Raid_t * raidPtr)
    924   1.1     oster {
    925   1.6     oster 	RF_ASSERT(raidPtr->throughputstats.num_out_ios == 0);
    926   1.6     oster 	if (raidPtr->throughputstats.sum_io_us != 0) {
    927   1.6     oster 		printf("[Througphut: %8.2f IOs/second]\n", raidPtr->throughputstats.num_ios
    928   1.6     oster 		    / (raidPtr->throughputstats.sum_io_us / 1000000.0));
    929   1.6     oster 	}
    930   1.1     oster }
    931   1.6     oster #endif				/* !KERNEL && !SIMULATE */
    932   1.1     oster 
    933   1.6     oster void
    934   1.6     oster rf_StartUserStats(RF_Raid_t * raidPtr)
    935   1.1     oster {
    936   1.6     oster 	RF_GETTIME(raidPtr->userstats.start);
    937   1.6     oster 	raidPtr->userstats.sum_io_us = 0;
    938   1.6     oster 	raidPtr->userstats.num_ios = 0;
    939   1.6     oster 	raidPtr->userstats.num_sect_moved = 0;
    940   1.1     oster }
    941   1.1     oster 
    942   1.6     oster void
    943   1.6     oster rf_StopUserStats(RF_Raid_t * raidPtr)
    944   1.1     oster {
    945   1.6     oster 	RF_GETTIME(raidPtr->userstats.stop);
    946   1.1     oster }
    947   1.1     oster 
    948   1.6     oster void
    949   1.6     oster rf_UpdateUserStats(raidPtr, rt, numsect)
    950   1.6     oster 	RF_Raid_t *raidPtr;
    951   1.6     oster 	int     rt;		/* resp time in us */
    952   1.6     oster 	int     numsect;	/* number of sectors for this access */
    953   1.1     oster {
    954   1.6     oster 	raidPtr->userstats.sum_io_us += rt;
    955   1.6     oster 	raidPtr->userstats.num_ios++;
    956   1.6     oster 	raidPtr->userstats.num_sect_moved += numsect;
    957   1.1     oster }
    958   1.1     oster 
    959   1.6     oster void
    960   1.6     oster rf_PrintUserStats(RF_Raid_t * raidPtr)
    961   1.1     oster {
    962   1.6     oster 	long    elapsed_us, mbs, mbs_frac;
    963   1.6     oster 	struct timeval diff;
    964   1.1     oster 
    965  1.69     oster 	RF_TIMEVAL_DIFF(&raidPtr->userstats.start,
    966  1.69     oster 			&raidPtr->userstats.stop, &diff);
    967   1.6     oster 	elapsed_us = TIMEVAL_TO_US(diff);
    968   1.1     oster 
    969   1.6     oster 	/* 2000 sectors per megabyte, 10000000 microseconds per second */
    970   1.6     oster 	if (elapsed_us)
    971  1.69     oster 		mbs = (raidPtr->userstats.num_sect_moved / 2000) /
    972  1.69     oster 			(elapsed_us / 1000000);
    973   1.6     oster 	else
    974   1.6     oster 		mbs = 0;
    975   1.1     oster 
    976   1.6     oster 	/* this computes only the first digit of the fractional mb/s moved */
    977   1.6     oster 	if (elapsed_us) {
    978  1.69     oster 		mbs_frac = ((raidPtr->userstats.num_sect_moved / 200) /
    979  1.69     oster 			    (elapsed_us / 1000000)) - (mbs * 10);
    980   1.6     oster 	} else {
    981   1.6     oster 		mbs_frac = 0;
    982   1.6     oster 	}
    983   1.1     oster 
    984  1.69     oster 	printf("raid%d: Number of I/Os:             %ld\n",
    985  1.69     oster 	       raidPtr->raidid, raidPtr->userstats.num_ios);
    986  1.69     oster 	printf("raid%d: Elapsed time (us):          %ld\n",
    987  1.69     oster 	       raidPtr->raidid, elapsed_us);
    988  1.69     oster 	printf("raid%d: User I/Os per second:       %ld\n",
    989  1.69     oster 	       raidPtr->raidid, RF_DB0_CHECK(raidPtr->userstats.num_ios,
    990  1.69     oster 					     (elapsed_us / 1000000)));
    991  1.69     oster 	printf("raid%d: Average user response time: %ld us\n",
    992  1.69     oster 	       raidPtr->raidid, RF_DB0_CHECK(raidPtr->userstats.sum_io_us,
    993  1.69     oster 					     raidPtr->userstats.num_ios));
    994  1.69     oster 	printf("raid%d: Total sectors moved:        %ld\n",
    995  1.69     oster 	       raidPtr->raidid, raidPtr->userstats.num_sect_moved);
    996  1.69     oster 	printf("raid%d: Average access size (sect): %ld\n",
    997  1.69     oster 	       raidPtr->raidid, RF_DB0_CHECK(raidPtr->userstats.num_sect_moved,
    998  1.69     oster 					     raidPtr->userstats.num_ios));
    999  1.69     oster 	printf("raid%d: Achieved data rate:         %ld.%ld MB/sec\n",
   1000  1.69     oster 	       raidPtr->raidid, mbs, mbs_frac);
   1001  1.39     oster }
   1002  1.39     oster 
   1003  1.39     oster 
   1004  1.39     oster void
   1005  1.39     oster rf_print_panic_message(line,file)
   1006  1.39     oster 	int line;
   1007  1.39     oster 	char *file;
   1008  1.39     oster {
   1009  1.39     oster 	sprintf(rf_panicbuf,"raidframe error at line %d file %s",
   1010  1.39     oster 		line, file);
   1011  1.39     oster }
   1012  1.39     oster 
   1013  1.62     oster #ifdef RAID_DIAGNOSTIC
   1014  1.39     oster void
   1015  1.39     oster rf_print_assert_panic_message(line,file,condition)
   1016  1.39     oster 	int line;
   1017  1.39     oster 	char *file;
   1018  1.39     oster 	char *condition;
   1019  1.39     oster {
   1020  1.39     oster 	sprintf(rf_panicbuf,
   1021  1.39     oster 		"raidframe error at line %d file %s (failed asserting %s)\n",
   1022  1.39     oster 		line, file, condition);
   1023  1.58     oster }
   1024  1.62     oster #endif
   1025  1.58     oster 
   1026  1.58     oster void
   1027  1.58     oster rf_print_unable_to_init_mutex(file,line,rc)
   1028  1.58     oster 	char *file;
   1029  1.58     oster 	int line;
   1030  1.58     oster 	int rc;
   1031  1.58     oster {
   1032  1.58     oster 	RF_ERRORMSG3("Unable to init mutex file %s line %d rc=%d\n",
   1033  1.58     oster 		     file, line, rc);
   1034  1.58     oster }
   1035  1.58     oster 
   1036  1.58     oster void
   1037  1.58     oster rf_print_unable_to_init_cond(file,line,rc)
   1038  1.58     oster 	char *file;
   1039  1.58     oster 	int line;
   1040  1.58     oster 	int rc;
   1041  1.58     oster {
   1042  1.58     oster 	RF_ERRORMSG3("Unable to init cond file %s line %d rc=%d\n",
   1043  1.58     oster 		     file, line, rc);
   1044  1.58     oster }
   1045  1.58     oster 
   1046  1.58     oster void
   1047  1.58     oster rf_print_unable_to_add_shutdown(file,line,rc)
   1048  1.58     oster 	char *file;
   1049  1.58     oster 	int line;
   1050  1.58     oster 	int rc;
   1051  1.58     oster {
   1052  1.58     oster 	RF_ERRORMSG3("Unable to add to shutdown list file %s line %d rc=%d\n",
   1053  1.58     oster 		     file, line, rc);
   1054   1.1     oster }
   1055