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_states.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_states.c,v 1.35 2004/03/23 13:09:18 oster Exp $     */
    2 /*
    3  * Copyright (c) 1995 Carnegie-Mellon University.
    4  * All rights reserved.
    5  *
    6  * Author: Mark Holland, William V. Courtright II, Robby Findler
    7  *
    8  * Permission to use, copy, modify and distribute this software and
    9  * its documentation is hereby granted, provided that both the copyright
   10  * notice and this permission notice appear in all copies of the
   11  * software, derivative works or modified versions, and any portions
   12  * thereof, and that both notices appear in supporting documentation.
   13  *
   14  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   15  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
   16  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   17  *
   18  * Carnegie Mellon requests users of this software to return to
   19  *
   20  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   21  *  School of Computer Science
   22  *  Carnegie Mellon University
   23  *  Pittsburgh PA 15213-3890
   24  *
   25  * any improvements or extensions that they make and grant Carnegie the
   26  * rights to redistribute these changes.
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __KERNEL_RCSID(0, "$NetBSD: rf_states.c,v 1.35 2004/03/23 13:09:18 oster Exp $");
   31 
   32 #include <sys/errno.h>
   33 
   34 #include "rf_archs.h"
   35 #include "rf_threadstuff.h"
   36 #include "rf_raid.h"
   37 #include "rf_dag.h"
   38 #include "rf_desc.h"
   39 #include "rf_aselect.h"
   40 #include "rf_general.h"
   41 #include "rf_states.h"
   42 #include "rf_dagutils.h"
   43 #include "rf_driver.h"
   44 #include "rf_engine.h"
   45 #include "rf_map.h"
   46 #include "rf_etimer.h"
   47 #include "rf_kintf.h"
   48 
   49 #ifndef RF_DEBUG_STATES
   50 #define RF_DEBUG_STATES 0
   51 #endif
   52 
   53 /* prototypes for some of the available states.
   54 
   55    States must:
   56 
   57      - not block.
   58 
   59      - either schedule rf_ContinueRaidAccess as a callback and return
   60        RF_TRUE, or complete all of their work and return RF_FALSE.
   61 
   62      - increment desc->state when they have finished their work.
   63 */
   64 
   65 #if RF_DEBUG_STATES
   66 static char *
   67 StateName(RF_AccessState_t state)
   68 {
   69         switch (state) {
   70                 case rf_QuiesceState:return "QuiesceState";
   71         case rf_MapState:
   72                 return "MapState";
   73         case rf_LockState:
   74                 return "LockState";
   75         case rf_CreateDAGState:
   76                 return "CreateDAGState";
   77         case rf_ExecuteDAGState:
   78                 return "ExecuteDAGState";
   79         case rf_ProcessDAGState:
   80                 return "ProcessDAGState";
   81         case rf_CleanupState:
   82                 return "CleanupState";
   83         case rf_LastState:
   84                 return "LastState";
   85         case rf_IncrAccessesCountState:
   86                 return "IncrAccessesCountState";
   87         case rf_DecrAccessesCountState:
   88                 return "DecrAccessesCountState";
   89         default:
   90                 return "!!! UnnamedState !!!";
   91         }
   92 }
   93 #endif
   94 
   95 void 
   96 rf_ContinueRaidAccess(RF_RaidAccessDesc_t *desc)
   97 {
   98         int     suspended = RF_FALSE;
   99         int     current_state_index = desc->state;
  100         RF_AccessState_t current_state = desc->states[current_state_index];
  101 #if RF_DEBUG_STATES
  102         int     unit = desc->raidPtr->raidid;
  103 #endif
  104 
  105         do {
  106 
  107                 current_state_index = desc->state;
  108                 current_state = desc->states[current_state_index];
  109 
  110                 switch (current_state) {
  111 
  112                 case rf_QuiesceState:
  113                         suspended = rf_State_Quiesce(desc);
  114                         break;
  115                 case rf_IncrAccessesCountState:
  116                         suspended = rf_State_IncrAccessCount(desc);
  117                         break;
  118                 case rf_MapState:
  119                         suspended = rf_State_Map(desc);
  120                         break;
  121                 case rf_LockState:
  122                         suspended = rf_State_Lock(desc);
  123                         break;
  124                 case rf_CreateDAGState:
  125                         suspended = rf_State_CreateDAG(desc);
  126                         break;
  127                 case rf_ExecuteDAGState:
  128                         suspended = rf_State_ExecuteDAG(desc);
  129                         break;
  130                 case rf_ProcessDAGState:
  131                         suspended = rf_State_ProcessDAG(desc);
  132                         break;
  133                 case rf_CleanupState:
  134                         suspended = rf_State_Cleanup(desc);
  135                         break;
  136                 case rf_DecrAccessesCountState:
  137                         suspended = rf_State_DecrAccessCount(desc);
  138                         break;
  139                 case rf_LastState:
  140                         suspended = rf_State_LastState(desc);
  141                         break;
  142                 }
  143 
  144                 /* after this point, we cannot dereference desc since
  145                  * desc may have been freed. desc is only freed in
  146                  * LastState, so if we renter this function or loop
  147                  * back up, desc should be valid. */
  148 
  149 #if RF_DEBUG_STATES
  150                 if (rf_printStatesDebug) {
  151                         printf("raid%d: State: %-24s StateIndex: %3i desc: 0x%ld %s\n",
  152                                unit, StateName(current_state), 
  153                                current_state_index, (long) desc,
  154                                suspended ? "callback scheduled" : "looping");
  155                 }
  156 #endif
  157         } while (!suspended && current_state != rf_LastState);
  158 
  159         return;
  160 }
  161 
  162 
  163 void 
  164 rf_ContinueDagAccess(RF_DagList_t *dagList)
  165 {
  166 #if RF_ACC_TRACE > 0
  167         RF_AccTraceEntry_t *tracerec = &(dagList->desc->tracerec);
  168         RF_Etimer_t timer;
  169 #endif
  170         RF_RaidAccessDesc_t *desc;
  171         RF_DagHeader_t *dag_h;
  172         int     i;
  173 
  174         desc = dagList->desc;
  175 
  176 #if RF_ACC_TRACE > 0
  177         timer = tracerec->timer;
  178         RF_ETIMER_STOP(timer);
  179         RF_ETIMER_EVAL(timer);
  180         tracerec->specific.user.exec_us = RF_ETIMER_VAL_US(timer);
  181         RF_ETIMER_START(tracerec->timer);
  182 #endif
  183 
  184         /* skip to dag which just finished */
  185         dag_h = dagList->dags;
  186         for (i = 0; i < dagList->numDagsDone; i++) {
  187                 dag_h = dag_h->next;
  188         }
  189 
  190         /* check to see if retry is required */
  191         if (dag_h->status == rf_rollBackward) {
  192                 /* when a dag fails, mark desc status as bad and allow
  193                  * all other dags in the desc to execute to
  194                  * completion.  then, free all dags and start over */
  195                 desc->status = 1;       /* bad status */
  196 #if 0
  197                 printf("raid%d: DAG failure: %c addr 0x%lx "
  198                        "(%ld) nblk 0x%x (%d) buf 0x%lx state %d\n",
  199                        desc->raidPtr->raidid, desc->type, 
  200                        (long) desc->raidAddress,
  201                        (long) desc->raidAddress, (int) desc->numBlocks,
  202                        (int) desc->numBlocks, 
  203                        (unsigned long) (desc->bufPtr), desc->state);
  204 #endif
  205         }
  206         dagList->numDagsDone++;
  207         rf_ContinueRaidAccess(desc);
  208 }
  209 
  210 int 
  211 rf_State_LastState(RF_RaidAccessDesc_t *desc)
  212 {
  213         void    (*callbackFunc) (RF_CBParam_t) = desc->callbackFunc;
  214         RF_CBParam_t callbackArg;
  215 
  216         callbackArg.p = desc->callbackArg;
  217         
  218         /*
  219          * If this is not an async request, wake up the caller
  220          */
  221         if (desc->async_flag == 0)
  222                 wakeup(desc->bp);
  223 
  224         /*
  225          * That's all the IO for this one... unbusy the 'disk'.
  226          */
  227 
  228         rf_disk_unbusy(desc);
  229 
  230         /* 
  231          * Wakeup any requests waiting to go.
  232          */
  233         
  234         RF_LOCK_MUTEX(((RF_Raid_t *) desc->raidPtr)->mutex);
  235         ((RF_Raid_t *) desc->raidPtr)->openings++;
  236         RF_UNLOCK_MUTEX(((RF_Raid_t *) desc->raidPtr)->mutex);
  237 
  238         /* wake up any pending IO */
  239         raidstart(((RF_Raid_t *) desc->raidPtr));
  240                 
  241         /* printf("Calling biodone on 0x%x\n",desc->bp); */
  242         biodone(desc->bp);      /* access came through ioctl */
  243 
  244         if (callbackFunc)
  245                 callbackFunc(callbackArg);
  246         rf_FreeRaidAccDesc(desc);
  247 
  248         return RF_FALSE;
  249 }
  250 
  251 int 
  252 rf_State_IncrAccessCount(RF_RaidAccessDesc_t *desc)
  253 {
  254         RF_Raid_t *raidPtr;
  255 
  256         raidPtr = desc->raidPtr;
  257         /* Bummer. We have to do this to be 100% safe w.r.t. the increment
  258          * below */
  259         RF_LOCK_MUTEX(raidPtr->access_suspend_mutex);
  260         raidPtr->accs_in_flight++;      /* used to detect quiescence */
  261         RF_UNLOCK_MUTEX(raidPtr->access_suspend_mutex);
  262 
  263         desc->state++;
  264         return RF_FALSE;
  265 }
  266 
  267 int 
  268 rf_State_DecrAccessCount(RF_RaidAccessDesc_t *desc)
  269 {
  270         RF_Raid_t *raidPtr;
  271 
  272         raidPtr = desc->raidPtr;
  273 
  274         RF_LOCK_MUTEX(raidPtr->access_suspend_mutex);
  275         raidPtr->accs_in_flight--;
  276         if (raidPtr->accesses_suspended && raidPtr->accs_in_flight == 0) {
  277                 rf_SignalQuiescenceLock(raidPtr);
  278         }
  279         RF_UNLOCK_MUTEX(raidPtr->access_suspend_mutex);
  280 
  281         desc->state++;
  282         return RF_FALSE;
  283 }
  284 
  285 int 
  286 rf_State_Quiesce(RF_RaidAccessDesc_t *desc)
  287 {
  288 #if RF_ACC_TRACE > 0
  289         RF_AccTraceEntry_t *tracerec = &desc->tracerec;
  290         RF_Etimer_t timer;
  291 #endif
  292         RF_CallbackDesc_t *cb;
  293         RF_Raid_t *raidPtr;
  294         int     suspended = RF_FALSE;
  295         int need_cb, used_cb;
  296 
  297         raidPtr = desc->raidPtr;
  298 
  299 #if RF_ACC_TRACE > 0
  300         RF_ETIMER_START(timer);
  301         RF_ETIMER_START(desc->timer);
  302 #endif
  303 
  304         need_cb = 0;
  305         used_cb = 0;
  306         cb = NULL;
  307 
  308         RF_LOCK_MUTEX(raidPtr->access_suspend_mutex);
  309         /* Do an initial check to see if we might need a callback structure */
  310         if (raidPtr->accesses_suspended) {
  311                 need_cb = 1;
  312         }
  313         RF_UNLOCK_MUTEX(raidPtr->access_suspend_mutex);
  314 
  315         if (need_cb) {
  316                 /* create a callback if we might need it...
  317                    and we likely do. */
  318                 cb = rf_AllocCallbackDesc();
  319         }
  320 
  321         RF_LOCK_MUTEX(raidPtr->access_suspend_mutex);
  322         if (raidPtr->accesses_suspended) {
  323                 cb->callbackFunc = (void (*) (RF_CBParam_t)) rf_ContinueRaidAccess;
  324                 cb->callbackArg.p = (void *) desc;
  325                 cb->next = raidPtr->quiesce_wait_list;
  326                 raidPtr->quiesce_wait_list = cb;
  327                 suspended = RF_TRUE;
  328                 used_cb = 1;
  329         }
  330         RF_UNLOCK_MUTEX(raidPtr->access_suspend_mutex);
  331 
  332         if ((need_cb == 1) && (used_cb == 0)) {
  333                 rf_FreeCallbackDesc(cb);
  334         }
  335 
  336 #if RF_ACC_TRACE > 0
  337         RF_ETIMER_STOP(timer);
  338         RF_ETIMER_EVAL(timer);
  339         tracerec->specific.user.suspend_ovhd_us += RF_ETIMER_VAL_US(timer);
  340 #endif
  341 
  342 #if RF_DEBUG_QUIESCE
  343         if (suspended && rf_quiesceDebug)
  344                 printf("Stalling access due to quiescence lock\n");
  345 #endif
  346         desc->state++;
  347         return suspended;
  348 }
  349 
  350 int 
  351 rf_State_Map(RF_RaidAccessDesc_t *desc)
  352 {
  353         RF_Raid_t *raidPtr = desc->raidPtr;
  354 #if RF_ACC_TRACE > 0
  355         RF_AccTraceEntry_t *tracerec = &desc->tracerec;
  356         RF_Etimer_t timer;
  357 
  358         RF_ETIMER_START(timer);
  359 #endif
  360 
  361         if (!(desc->asmap = rf_MapAccess(raidPtr, desc->raidAddress, desc->numBlocks,
  362                     desc->bufPtr, RF_DONT_REMAP)))
  363                 RF_PANIC();
  364 
  365 #if RF_ACC_TRACE > 0
  366         RF_ETIMER_STOP(timer);
  367         RF_ETIMER_EVAL(timer);
  368         tracerec->specific.user.map_us = RF_ETIMER_VAL_US(timer);
  369 #endif
  370 
  371         desc->state++;
  372         return RF_FALSE;
  373 }
  374 
  375 int 
  376 rf_State_Lock(RF_RaidAccessDesc_t *desc)
  377 {
  378 #if RF_ACC_TRACE > 0
  379         RF_AccTraceEntry_t *tracerec = &desc->tracerec;
  380         RF_Etimer_t timer;
  381 #endif
  382         RF_Raid_t *raidPtr = desc->raidPtr;
  383         RF_AccessStripeMapHeader_t *asmh = desc->asmap;
  384         RF_AccessStripeMap_t *asm_p;
  385         RF_StripeNum_t lastStripeID = -1;
  386         int     suspended = RF_FALSE;
  387 
  388 #if RF_ACC_TRACE > 0
  389         RF_ETIMER_START(timer);
  390 #endif
  391         
  392         /* acquire each lock that we don't already hold */
  393         for (asm_p = asmh->stripeMap; asm_p; asm_p = asm_p->next) {
  394                 RF_ASSERT(RF_IO_IS_R_OR_W(desc->type));
  395                 if (!rf_suppressLocksAndLargeWrites &&
  396                     asm_p->parityInfo &&
  397                     !(desc->flags & RF_DAG_SUPPRESS_LOCKS) &&
  398                     !(asm_p->flags & RF_ASM_FLAGS_LOCK_TRIED)) {
  399                         asm_p->flags |= RF_ASM_FLAGS_LOCK_TRIED;
  400                                 /* locks must be acquired hierarchically */
  401                         RF_ASSERT(asm_p->stripeID > lastStripeID);
  402                         lastStripeID = asm_p->stripeID;
  403                         
  404                         RF_INIT_LOCK_REQ_DESC(asm_p->lockReqDesc, desc->type,
  405                                               (void (*) (struct buf *)) rf_ContinueRaidAccess, desc, asm_p,
  406                                               raidPtr->Layout.dataSectorsPerStripe);
  407                         if (rf_AcquireStripeLock(raidPtr->lockTable, asm_p->stripeID,
  408                                                  &asm_p->lockReqDesc)) {
  409                                 suspended = RF_TRUE;
  410                                 break;
  411                         }
  412                 }
  413                 if (desc->type == RF_IO_TYPE_WRITE &&
  414                     raidPtr->status == rf_rs_reconstructing) {
  415                         if (!(asm_p->flags & RF_ASM_FLAGS_FORCE_TRIED)) {
  416                                 int     val;
  417                                 
  418                                 asm_p->flags |= RF_ASM_FLAGS_FORCE_TRIED;
  419                                 val = rf_ForceOrBlockRecon(raidPtr, asm_p,
  420                                                            (void (*) (RF_Raid_t *, void *)) rf_ContinueRaidAccess, desc);
  421                                 if (val == 0) {
  422                                         asm_p->flags |= RF_ASM_FLAGS_RECON_BLOCKED;
  423                                 } else {
  424                                         suspended = RF_TRUE;
  425                                         break;
  426                                 }
  427                         } else {
  428 #if RF_DEBUG_PSS > 0
  429                                 if (rf_pssDebug) {
  430                                         printf("raid%d: skipping force/block because already done, psid %ld\n",
  431                                                desc->raidPtr->raidid, 
  432                                                (long) asm_p->stripeID);
  433                                 }
  434 #endif
  435                         }
  436                 } else {
  437 #if RF_DEBUG_PSS > 0
  438                         if (rf_pssDebug) {
  439                                 printf("raid%d: skipping force/block because not write or not under recon, psid %ld\n",
  440                                        desc->raidPtr->raidid, 
  441                                        (long) asm_p->stripeID);
  442                         }
  443 #endif
  444                 }
  445         }
  446 #if RF_ACC_TRACE > 0
  447         RF_ETIMER_STOP(timer);
  448         RF_ETIMER_EVAL(timer);
  449         tracerec->specific.user.lock_us += RF_ETIMER_VAL_US(timer);
  450 #endif
  451         if (suspended)
  452                 return (RF_TRUE);
  453 
  454         desc->state++;
  455         return (RF_FALSE);
  456 }
  457 /*
  458  * the following three states create, execute, and post-process dags
  459  * the error recovery unit is a single dag.
  460  * by default, SelectAlgorithm creates an array of dags, one per parity stripe
  461  * in some tricky cases, multiple dags per stripe are created
  462  *   - dags within a parity stripe are executed sequentially (arbitrary order)
  463  *   - dags for distinct parity stripes are executed concurrently
  464  *
  465  * repeat until all dags complete successfully -or- dag selection fails
  466  *
  467  * while !done
  468  *   create dag(s) (SelectAlgorithm)
  469  *   if dag
  470  *     execute dag (DispatchDAG)
  471  *     if dag successful
  472  *       done (SUCCESS)
  473  *     else
  474  *       !done (RETRY - start over with new dags)
  475  *   else
  476  *     done (FAIL)
  477  */
  478 int 
  479 rf_State_CreateDAG(RF_RaidAccessDesc_t *desc)
  480 {
  481 #if RF_ACC_TRACE > 0
  482         RF_AccTraceEntry_t *tracerec = &desc->tracerec;
  483         RF_Etimer_t timer;
  484 #endif
  485         RF_DagHeader_t *dag_h;
  486         RF_DagList_t *dagList;
  487         struct buf *bp;
  488         int     i, selectStatus;
  489 
  490         /* generate a dag for the access, and fire it off.  When the dag
  491          * completes, we'll get re-invoked in the next state. */
  492 #if RF_ACC_TRACE > 0
  493         RF_ETIMER_START(timer);
  494 #endif
  495         /* SelectAlgorithm returns one or more dags */
  496         selectStatus = rf_SelectAlgorithm(desc, desc->flags | RF_DAG_SUPPRESS_LOCKS);
  497 #if RF_DEBUG_VALIDATE_DAG
  498         if (rf_printDAGsDebug) {
  499                 dagList = desc->dagList;
  500                 for (i = 0; i < desc->numStripes; i++) {
  501                         rf_PrintDAGList(dagList.dags);
  502                         dagList = dagList->next;
  503                 }
  504         }
  505 #endif /* RF_DEBUG_VALIDATE_DAG */
  506 #if RF_ACC_TRACE > 0
  507         RF_ETIMER_STOP(timer);
  508         RF_ETIMER_EVAL(timer);
  509         /* update time to create all dags */
  510         tracerec->specific.user.dag_create_us = RF_ETIMER_VAL_US(timer);
  511 #endif
  512 
  513         desc->status = 0;       /* good status */
  514 
  515         if (selectStatus) {
  516                 /* failed to create a dag */
  517                 /* this happens when there are too many faults or incomplete
  518                  * dag libraries */
  519                 printf("raid%d: failed to create a dag. "
  520                        "Too many component failures.\n", 
  521                        desc->raidPtr->raidid);
  522 
  523                 desc->status = 1; /* bad status */ 
  524                 /* skip straight to rf_State_Cleanup() */
  525                 desc->state = rf_CleanupState;
  526                 bp = (struct buf *)desc->bp;
  527                 bp->b_flags |= B_ERROR;
  528                 bp->b_error = EIO;
  529         } else {
  530                 /* bind dags to desc */
  531                 dagList = desc->dagList;
  532                 for (i = 0; i < desc->numStripes; i++) {
  533                         dag_h = dagList->dags;
  534                         while (dag_h) {
  535                                 dag_h->bp = (struct buf *) desc->bp;
  536 #if RF_ACC_TRACE > 0
  537                                 dag_h->tracerec = tracerec;
  538 #endif
  539                                 dag_h = dag_h->next;
  540                         }
  541                         dagList = dagList->next;
  542                 }
  543                 desc->flags |= RF_DAG_DISPATCH_RETURNED;
  544                 desc->state++;  /* next state should be rf_State_ExecuteDAG */
  545         }
  546         return RF_FALSE;
  547 }
  548 
  549 
  550 
  551 /* the access has an list of dagLists, one dagList per parity stripe.
  552  * fire the first dag in each parity stripe (dagList).
  553  * dags within a stripe (dagList) must be executed sequentially
  554  *  - this preserves atomic parity update
  555  * dags for independents parity groups (stripes) are fired concurrently */
  556 
  557 int 
  558 rf_State_ExecuteDAG(RF_RaidAccessDesc_t *desc)
  559 {
  560         int     i;
  561         RF_DagHeader_t *dag_h;
  562         RF_DagList_t *dagList;
  563 
  564         /* next state is always rf_State_ProcessDAG important to do
  565          * this before firing the first dag (it may finish before we
  566          * leave this routine) */
  567         desc->state++;
  568 
  569         /* sweep dag array, a stripe at a time, firing the first dag
  570          * in each stripe */
  571         dagList = desc->dagList;
  572         for (i = 0; i < desc->numStripes; i++) {
  573                 RF_ASSERT(dagList->numDags > 0);
  574                 RF_ASSERT(dagList->numDagsDone == 0);
  575                 RF_ASSERT(dagList->numDagsFired == 0);
  576 #if RF_ACC_TRACE > 0
  577                 RF_ETIMER_START(dagList->tracerec.timer);
  578 #endif
  579                 /* fire first dag in this stripe */
  580                 dag_h = dagList->dags;
  581                 RF_ASSERT(dag_h);
  582                 dagList->numDagsFired++;
  583                 rf_DispatchDAG(dag_h, (void (*) (void *)) rf_ContinueDagAccess, dagList);
  584                 dagList = dagList->next;
  585         }
  586 
  587         /* the DAG will always call the callback, even if there was no
  588          * blocking, so we are always suspended in this state */
  589         return RF_TRUE;
  590 }
  591 
  592 
  593 
  594 /* rf_State_ProcessDAG is entered when a dag completes.
  595  * first, check to all dags in the access have completed
  596  * if not, fire as many dags as possible */
  597 
  598 int 
  599 rf_State_ProcessDAG(RF_RaidAccessDesc_t *desc)
  600 {
  601         RF_AccessStripeMapHeader_t *asmh = desc->asmap;
  602         RF_Raid_t *raidPtr = desc->raidPtr;
  603         RF_DagHeader_t *dag_h;
  604         int     i, j, done = RF_TRUE;
  605         RF_DagList_t *dagList, *temp;
  606 
  607         /* check to see if this is the last dag */
  608         dagList = desc->dagList;
  609         for (i = 0; i < desc->numStripes; i++) {
  610                 if (dagList->numDags != dagList->numDagsDone)
  611                         done = RF_FALSE;
  612                 dagList = dagList->next;
  613         }
  614 
  615         if (done) {
  616                 if (desc->status) {
  617                         /* a dag failed, retry */
  618                         /* free all dags */
  619                         dagList = desc->dagList;
  620                         for (i = 0; i < desc->numStripes; i++) {
  621                                 rf_FreeDAG(dagList->dags);
  622                                 temp = dagList;
  623                                 dagList = dagList->next;
  624                                 rf_FreeDAGList(temp);
  625                         }
  626                         rf_MarkFailuresInASMList(raidPtr, asmh);
  627                         /* back up to rf_State_CreateDAG */
  628                         desc->state = desc->state - 2;
  629                         return RF_FALSE;
  630                 } else {
  631                         /* move on to rf_State_Cleanup */
  632                         desc->state++;
  633                 }
  634                 return RF_FALSE;
  635         } else {
  636                 /* more dags to execute */
  637                 /* see if any are ready to be fired.  if so, fire them */
  638                 /* don't fire the initial dag in a list, it's fired in
  639                  * rf_State_ExecuteDAG */
  640                 dagList = desc->dagList;
  641                 for (i = 0; i < desc->numStripes; i++) {
  642                         if ((dagList->numDagsDone < dagList->numDags)
  643                             && (dagList->numDagsDone == dagList->numDagsFired)
  644                             && (dagList->numDagsFired > 0)) {
  645 #if RF_ACC_TRACE > 0
  646                                 RF_ETIMER_START(dagList->tracerec.timer);
  647 #endif
  648                                 /* fire next dag in this stripe */
  649                                 /* first, skip to next dag awaiting execution */
  650                                 dag_h = dagList->dags;
  651                                 for (j = 0; j < dagList->numDagsDone; j++)
  652                                         dag_h = dag_h->next;
  653                                 dagList->numDagsFired++;
  654                                 rf_DispatchDAG(dag_h, (void (*) (void *)) rf_ContinueDagAccess,
  655                                     dagList);
  656                         }
  657                         dagList = dagList->next;
  658                 }
  659                 return RF_TRUE;
  660         }
  661 }
  662 /* only make it this far if all dags complete successfully */
  663 int 
  664 rf_State_Cleanup(RF_RaidAccessDesc_t *desc)
  665 {
  666 #if RF_ACC_TRACE > 0
  667         RF_AccTraceEntry_t *tracerec = &desc->tracerec;
  668         RF_Etimer_t timer;
  669 #endif
  670         RF_AccessStripeMapHeader_t *asmh = desc->asmap;
  671         RF_Raid_t *raidPtr = desc->raidPtr;
  672         RF_AccessStripeMap_t *asm_p;
  673         RF_DagList_t *dagList;
  674         int i;
  675 
  676         desc->state++;
  677 
  678 #if RF_ACC_TRACE > 0
  679         timer = tracerec->timer;
  680         RF_ETIMER_STOP(timer);
  681         RF_ETIMER_EVAL(timer);
  682         tracerec->specific.user.dag_retry_us = RF_ETIMER_VAL_US(timer);
  683 
  684         /* the RAID I/O is complete.  Clean up. */
  685         tracerec->specific.user.dag_retry_us = 0;
  686 
  687         RF_ETIMER_START(timer);
  688 #endif
  689         /* free all dags */
  690         dagList = desc->dagList;
  691         for (i = 0; i < desc->numStripes; i++) {
  692                 rf_FreeDAG(dagList->dags);
  693                 dagList = dagList->next;
  694         }
  695 #if RF_ACC_TRACE > 0
  696         RF_ETIMER_STOP(timer);
  697         RF_ETIMER_EVAL(timer);
  698         tracerec->specific.user.cleanup_us = RF_ETIMER_VAL_US(timer);
  699 
  700         RF_ETIMER_START(timer);
  701 #endif
  702         for (asm_p = asmh->stripeMap; asm_p; asm_p = asm_p->next) {
  703                 if (!rf_suppressLocksAndLargeWrites &&
  704                     asm_p->parityInfo &&
  705                     !(desc->flags & RF_DAG_SUPPRESS_LOCKS)) {
  706                         RF_ASSERT_VALID_LOCKREQ(&asm_p->lockReqDesc);
  707                         rf_ReleaseStripeLock(raidPtr->lockTable, 
  708                                              asm_p->stripeID,
  709                                              &asm_p->lockReqDesc);
  710                 }
  711                 if (asm_p->flags & RF_ASM_FLAGS_RECON_BLOCKED) {
  712                         rf_UnblockRecon(raidPtr, asm_p);
  713                 }
  714         }
  715 #if RF_ACC_TRACE > 0
  716         RF_ETIMER_STOP(timer);
  717         RF_ETIMER_EVAL(timer);
  718         tracerec->specific.user.lock_us += RF_ETIMER_VAL_US(timer);
  719 
  720         RF_ETIMER_START(timer);
  721 #endif
  722         rf_FreeAccessStripeMap(asmh);
  723 #if RF_ACC_TRACE > 0
  724         RF_ETIMER_STOP(timer);
  725         RF_ETIMER_EVAL(timer);
  726         tracerec->specific.user.cleanup_us += RF_ETIMER_VAL_US(timer);
  727 
  728         RF_ETIMER_STOP(desc->timer);
  729         RF_ETIMER_EVAL(desc->timer);
  730 
  731         timer = desc->tracerec.tot_timer;
  732         RF_ETIMER_STOP(timer);
  733         RF_ETIMER_EVAL(timer);
  734         desc->tracerec.total_us = RF_ETIMER_VAL_US(timer);
  735 
  736         rf_LogTraceRec(raidPtr, tracerec);
  737 #endif
  738         desc->flags |= RF_DAG_ACCESS_COMPLETE;
  739 
  740         return RF_FALSE;
  741 }

Cache object: fc04c4072ca756b8a18286f9beb7acad


[ 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.