The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/raidframe/rf_driver.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 01b6caf2f70e066895d49f7ac6ed05fc


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.