root/dev/raidframe/rf_psstatus.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rf_init_pss
  2. rf_clean_pss
  3. rf_ShutdownPSStatus
  4. rf_ConfigurePSStatus
  5. rf_MakeParityStripeStatusTable
  6. rf_FreeParityStripeStatusTable
  7. rf_LookupRUStatus
  8. rf_PSStatusDelete
  9. rf_RemoveFromActiveReconTable
  10. rf_AllocPSStatus
  11. rf_FreePSStatus
  12. rf_RealPrintPSStatusTable
  13. rf_PrintPSStatusTable

    1 /*      $OpenBSD: rf_psstatus.c,v 1.6 2002/12/16 07:01:04 tdeval Exp $  */
    2 /*      $NetBSD: rf_psstatus.c,v 1.5 2000/01/08 22:57:31 oster Exp $    */
    3 
    4 /*
    5  * Copyright (c) 1995 Carnegie-Mellon University.
    6  * All rights reserved.
    7  *
    8  * Author: Mark Holland
    9  *
   10  * Permission to use, copy, modify and distribute this software and
   11  * its documentation is hereby granted, provided that both the copyright
   12  * notice and this permission notice appear in all copies of the
   13  * software, derivative works or modified versions, and any portions
   14  * thereof, and that both notices appear in supporting documentation.
   15  *
   16  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   17  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
   18  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   19  *
   20  * Carnegie Mellon requests users of this software to return to
   21  *
   22  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   23  *  School of Computer Science
   24  *  Carnegie Mellon University
   25  *  Pittsburgh PA 15213-3890
   26  *
   27  * any improvements or extensions that they make and grant Carnegie the
   28  * rights to redistribute these changes.
   29  */
   30 
   31 /*****************************************************************************
   32  *
   33  * psstatus.c
   34  *
   35  * The reconstruction code maintains a bunch of status related to the parity
   36  * stripes that are currently under reconstruction. This header file defines
   37  * the status structures.
   38  *
   39  *****************************************************************************/
   40 
   41 #include "rf_types.h"
   42 #include "rf_raid.h"
   43 #include "rf_general.h"
   44 #include "rf_debugprint.h"
   45 #include "rf_freelist.h"
   46 #include "rf_psstatus.h"
   47 #include "rf_shutdown.h"
   48 
   49 #define Dprintf1(s,a)                                                   \
   50 do {                                                                    \
   51         if (rf_pssDebug)                                                \
   52                 rf_debug_printf(s,                                      \
   53                     (void *)((unsigned long)a),                         \
   54                     NULL, NULL, NULL, NULL, NULL, NULL, NULL);          \
   55 } while(0)
   56 #define Dprintf2(s,a,b)                                                 \
   57 do {                                                                    \
   58         if (rf_pssDebug)                                                \
   59                 rf_debug_printf(s,                                      \
   60                     (void *)((unsigned long)a),                         \
   61                     (void *)((unsigned long)b),                         \
   62                     NULL, NULL, NULL, NULL, NULL, NULL);                \
   63 } while(0)
   64 #define Dprintf3(s,a,b,c)                                               \
   65 do {                                                                    \
   66         if (rf_pssDebug)                                                \
   67                 rf_debug_printf(s,                                      \
   68                     (void *)((unsigned long)a),                         \
   69                     (void *)((unsigned long)b),                         \
   70                     (void *)((unsigned long)c),                         \
   71                     NULL, NULL, NULL, NULL, NULL);                      \
   72 } while(0)
   73 
   74 void rf_RealPrintPSStatusTable(RF_Raid_t *, RF_PSStatusHeader_t *);
   75 
   76 #define RF_MAX_FREE_PSS         32
   77 #define RF_PSS_INC               8
   78 #define RF_PSS_INITIAL           4
   79 
   80 int  rf_init_pss(RF_ReconParityStripeStatus_t *, RF_Raid_t *);
   81 void rf_clean_pss(RF_ReconParityStripeStatus_t *, RF_Raid_t *);
   82 void rf_ShutdownPSStatus(void *);
   83 
   84 int
   85 rf_init_pss(RF_ReconParityStripeStatus_t *p, RF_Raid_t *raidPtr)
   86 {
   87         RF_Calloc(p->issued, raidPtr->numCol, sizeof(char), (char *));
   88         if (p->issued == NULL)
   89                 return (ENOMEM);
   90         return (0);
   91 }
   92 
   93 void
   94 rf_clean_pss(RF_ReconParityStripeStatus_t *p, RF_Raid_t *raidPtr)
   95 {
   96         RF_Free(p->issued, raidPtr->numCol * sizeof(char));
   97 }
   98 
   99 void
  100 rf_ShutdownPSStatus(void *arg)
  101 {
  102         RF_Raid_t *raidPtr = (RF_Raid_t *) arg;
  103 
  104         RF_FREELIST_DESTROY_CLEAN_ARG(raidPtr->pss_freelist, next,
  105             (RF_ReconParityStripeStatus_t *), rf_clean_pss, raidPtr);
  106 }
  107 
  108 int
  109 rf_ConfigurePSStatus(RF_ShutdownList_t **listp, RF_Raid_t *raidPtr,
  110     RF_Config_t *cfgPtr)
  111 {
  112         int rc;
  113 
  114         raidPtr->pssTableSize = RF_PSS_DEFAULT_TABLESIZE;
  115         RF_FREELIST_CREATE(raidPtr->pss_freelist, RF_MAX_FREE_PSS, RF_PSS_INC,
  116             sizeof(RF_ReconParityStripeStatus_t));
  117         if (raidPtr->pss_freelist == NULL)
  118                 return (ENOMEM);
  119         rc = rf_ShutdownCreate(listp, rf_ShutdownPSStatus, raidPtr);
  120         if (rc) {
  121                 RF_ERRORMSG3("Unable to add to shutdown list file %s line %d"
  122                              " rc=%d.\n", __FILE__, __LINE__, rc);
  123                 rf_ShutdownPSStatus(raidPtr);
  124                 return (rc);
  125         }
  126         RF_FREELIST_PRIME_INIT_ARG(raidPtr->pss_freelist, RF_PSS_INITIAL, next,
  127             (RF_ReconParityStripeStatus_t *), rf_init_pss, raidPtr);
  128         return (0);
  129 }
  130 
  131 
  132 /*****************************************************************************
  133  * Sets up the pss table.
  134  * We pre-allocate a bunch of entries to avoid as much as possible having to
  135  * malloc up hash chain entries.
  136  *****************************************************************************/
  137 RF_PSStatusHeader_t *
  138 rf_MakeParityStripeStatusTable(RF_Raid_t *raidPtr)
  139 {
  140         RF_PSStatusHeader_t *pssTable;
  141         int i, j, rc;
  142 
  143         RF_Calloc(pssTable, raidPtr->pssTableSize, sizeof(RF_PSStatusHeader_t),
  144             (RF_PSStatusHeader_t *));
  145         for (i = 0; i < raidPtr->pssTableSize; i++) {
  146                 rc = rf_mutex_init(&pssTable[i].mutex);
  147                 if (rc) {
  148                         RF_ERRORMSG3("Unable to init mutex file %s line %d"
  149                                      " rc=%d.\n", __FILE__, __LINE__, rc);
  150                         /* Fail and deallocate. */
  151                         for (j = 0; j < i; j++) {
  152                                 rf_mutex_destroy(&pssTable[i].mutex);
  153                         }
  154                         RF_Free(pssTable, raidPtr->pssTableSize *
  155                             sizeof(RF_PSStatusHeader_t));
  156                         return (NULL);
  157                 }
  158         }
  159         return (pssTable);
  160 }
  161 
  162 void
  163 rf_FreeParityStripeStatusTable(RF_Raid_t *raidPtr,
  164     RF_PSStatusHeader_t *pssTable)
  165 {
  166         int i;
  167 
  168         if (rf_pssDebug)
  169                 rf_RealPrintPSStatusTable(raidPtr, pssTable);
  170         for (i = 0; i < raidPtr->pssTableSize; i++) {
  171                 if (pssTable[i].chain) {
  172                         printf("ERROR: pss hash chain not null at recon"
  173                                " shutdown.\n");
  174                 }
  175                 rf_mutex_destroy(&pssTable[i].mutex);
  176         }
  177         RF_Free(pssTable, raidPtr->pssTableSize * sizeof(RF_PSStatusHeader_t));
  178 }
  179 
  180 
  181 /*
  182  * Looks up the status structure for a parity stripe.
  183  * If the create_flag is on, returns the status structure, creating it if
  184  * it doesn't exist. Otherwise returns NULL if the status structure does
  185  * not exist already.
  186  *
  187  * The flags tell whether or not to create it if it doesn't exist + what
  188  * flags to set initially.
  189  *
  190  * ASSUMES THE PSS DESCRIPTOR IS LOCKED UPON ENTRY.
  191  */
  192 RF_ReconParityStripeStatus_t *
  193 rf_LookupRUStatus(RF_Raid_t *raidPtr, RF_PSStatusHeader_t *pssTable,
  194     RF_StripeNum_t psID, RF_ReconUnitNum_t which_ru, RF_PSSFlags_t flags,
  195     int *created)
  196 {
  197         RF_PSStatusHeader_t *hdr = &pssTable[RF_HASH_PSID(raidPtr, psID)];
  198         RF_ReconParityStripeStatus_t *p, *pssPtr = hdr->chain;
  199 
  200         *created = 0;
  201         for (p = pssPtr; p; p = p->next) {
  202                 if (p->parityStripeID == psID && p->which_ru == which_ru)
  203                         break;
  204         }
  205 
  206         if (!p && (flags & RF_PSS_CREATE)) {
  207                 Dprintf2("PSS: creating pss for psid %ld ru %d.\n",
  208                     psID, which_ru);
  209                 p = rf_AllocPSStatus(raidPtr);
  210                 p->next = hdr->chain;
  211                 hdr->chain = p;
  212 
  213                 p->parityStripeID = psID;
  214                 p->which_ru = which_ru;
  215                 p->flags = flags;
  216                 p->rbuf = NULL;
  217                 p->writeRbuf = NULL;
  218                 p->xorBufCount = 0;
  219                 p->blockCount = 0;
  220                 p->procWaitList = NULL;
  221                 p->blockWaitList = NULL;
  222                 p->bufWaitList = NULL;
  223                 *created = 1;
  224         } else
  225                 if (p) {
  226                         /*
  227                          * We didn't create, but we want to specify
  228                          * some new status.
  229                          */
  230                         p->flags |= flags;      /*
  231                                                  * Add in whatever flags we're
  232                                                  * specifying.
  233                                                  */
  234                 }
  235         if (p && (flags & RF_PSS_RECON_BLOCKED)) {
  236                 /* If we're asking to block recon, bump the count. */
  237                 p->blockCount++;
  238                 Dprintf3("raid%d: Blocked recon on psid %ld. count now %d.\n",
  239                          raidPtr->raidid, psID, p->blockCount);
  240         }
  241         return (p);
  242 }
  243 
  244 
  245 /*
  246  * Deletes an entry from the parity stripe status table. Typically used
  247  * when an entry has been allocated solely to block reconstruction, and
  248  * no recon was requested while recon was blocked. Assumes the hash
  249  * chain is ALREADY LOCKED.
  250  */
  251 void
  252 rf_PSStatusDelete(RF_Raid_t *raidPtr, RF_PSStatusHeader_t *pssTable,
  253     RF_ReconParityStripeStatus_t *pssPtr)
  254 {
  255         RF_PSStatusHeader_t *hdr =
  256             &(pssTable[RF_HASH_PSID(raidPtr, pssPtr->parityStripeID)]);
  257         RF_ReconParityStripeStatus_t *p = hdr->chain, *pt = NULL;
  258 
  259         while (p) {
  260                 if (p == pssPtr) {
  261                         if (pt)
  262                                 pt->next = p->next;
  263                         else
  264                                 hdr->chain = p->next;
  265                         p->next = NULL;
  266                         rf_FreePSStatus(raidPtr, p);
  267                         return;
  268                 }
  269                 pt = p;
  270                 p = p->next;
  271         }
  272         RF_ASSERT(0);           /* We must find it here. */
  273 }
  274 
  275 
  276 /*
  277  * Deletes an entry from the ps status table after reconstruction has
  278  * completed.
  279  */
  280 void
  281 rf_RemoveFromActiveReconTable(RF_Raid_t *raidPtr, RF_RowCol_t row,
  282     RF_StripeNum_t psid, RF_ReconUnitNum_t which_ru)
  283 {
  284         RF_PSStatusHeader_t *hdr =
  285             &(raidPtr->reconControl[row]
  286              ->pssTable[RF_HASH_PSID(raidPtr, psid)]);
  287         RF_ReconParityStripeStatus_t *p, *pt;
  288         RF_CallbackDesc_t *cb, *cb1;
  289 
  290         RF_LOCK_MUTEX(hdr->mutex);
  291         for (pt = NULL, p = hdr->chain; p; pt = p, p = p->next) {
  292                 if ((p->parityStripeID == psid) && (p->which_ru == which_ru))
  293                         break;
  294         }
  295         if (p == NULL) {
  296                 rf_PrintPSStatusTable(raidPtr, row);
  297         }
  298         RF_ASSERT(p);           /* It must be there. */
  299 
  300         Dprintf2("PSS: deleting pss for psid %ld ru %d.\n", psid, which_ru);
  301 
  302         /* Delete this entry from the hash chain. */
  303         if (pt)
  304                 pt->next = p->next;
  305         else
  306                 hdr->chain = p->next;
  307         p->next = NULL;
  308 
  309         RF_UNLOCK_MUTEX(hdr->mutex);
  310 
  311         /* Wake-up anyone waiting on the parity stripe ID. */
  312         cb = p->procWaitList;
  313         p->procWaitList = NULL;
  314         while (cb) {
  315                 Dprintf1("Waking up access waiting on parity stripe ID %ld.\n",
  316                     p->parityStripeID);
  317                 cb1 = cb->next;
  318                 (cb->callbackFunc) (cb->callbackArg);
  319 
  320                 /*
  321                  * THIS IS WHAT THE ORIGINAL CODE HAD... the extra 0 is bogus,
  322                  * IMHO.
  323                  */
  324                 /* (cb->callbackFunc)(cb->callbackArg, 0); */
  325                 rf_FreeCallbackDesc(cb);
  326                 cb = cb1;
  327         }
  328 
  329         rf_FreePSStatus(raidPtr, p);
  330 }
  331 
  332 RF_ReconParityStripeStatus_t *
  333 rf_AllocPSStatus(RF_Raid_t *raidPtr)
  334 {
  335         RF_ReconParityStripeStatus_t *p;
  336 
  337         RF_FREELIST_GET_INIT_ARG(raidPtr->pss_freelist, p, next,
  338             (RF_ReconParityStripeStatus_t *), rf_init_pss, raidPtr);
  339         if (p) {
  340                 bzero(p->issued, raidPtr->numCol);
  341         }
  342         p->next = NULL;
  343         /*
  344          * No need to initialize here b/c the only place we're called from is
  345          * the above Lookup.
  346          */
  347         return (p);
  348 }
  349 
  350 void
  351 rf_FreePSStatus(RF_Raid_t *raidPtr, RF_ReconParityStripeStatus_t *p)
  352 {
  353         RF_ASSERT(p->procWaitList == NULL);
  354         RF_ASSERT(p->blockWaitList == NULL);
  355         RF_ASSERT(p->bufWaitList == NULL);
  356 
  357         RF_FREELIST_FREE_CLEAN_ARG(raidPtr->pss_freelist, p, next,
  358             rf_clean_pss, raidPtr);
  359 }
  360 
  361 void
  362 rf_RealPrintPSStatusTable(RF_Raid_t *raidPtr, RF_PSStatusHeader_t *pssTable)
  363 {
  364         int i, j, procsWaiting, blocksWaiting, bufsWaiting;
  365         RF_ReconParityStripeStatus_t *p;
  366         RF_CallbackDesc_t *cb;
  367 
  368         printf("\nParity Stripe Status Table\n");
  369         for (i = 0; i < raidPtr->pssTableSize; i++) {
  370                 for (p = pssTable[i].chain; p; p = p->next) {
  371                         procsWaiting = blocksWaiting = bufsWaiting = 0;
  372                         for (cb = p->procWaitList; cb; cb = cb->next)
  373                                 procsWaiting++;
  374                         for (cb = p->blockWaitList; cb; cb = cb->next)
  375                                 blocksWaiting++;
  376                         for (cb = p->bufWaitList; cb; cb = cb->next)
  377                                 bufsWaiting++;
  378                         printf("PSID %ld RU %d : blockCount %d %d/%d/%d"
  379                             " proc/block/buf waiting, issued ",
  380                             (long) p->parityStripeID, p->which_ru,
  381                             p->blockCount, procsWaiting, blocksWaiting,
  382                             bufsWaiting);
  383                         for (j = 0; j < raidPtr->numCol; j++)
  384                                 printf("%c", (p->issued[j]) ? '1' : '0');
  385                         if (!p->flags)
  386                                 printf(" flags: (none)");
  387                         else {
  388                                 if (p->flags & RF_PSS_UNDER_RECON)
  389                                         printf(" under-recon");
  390                                 if (p->flags & RF_PSS_FORCED_ON_WRITE)
  391                                         printf(" forced-w");
  392                                 if (p->flags & RF_PSS_FORCED_ON_READ)
  393                                         printf(" forced-r");
  394                                 if (p->flags & RF_PSS_RECON_BLOCKED)
  395                                         printf(" blocked");
  396                                 if (p->flags & RF_PSS_BUFFERWAIT)
  397                                         printf(" bufwait");
  398                         }
  399                         printf("\n");
  400                 }
  401         }
  402 }
  403 
  404 void
  405 rf_PrintPSStatusTable(RF_Raid_t *raidPtr, RF_RowCol_t row)
  406 {
  407         RF_PSStatusHeader_t *pssTable = raidPtr->reconControl[row]->pssTable;
  408         rf_RealPrintPSStatusTable(raidPtr, pssTable);
  409 }

/* [<][>][^][v][top][bottom][index][help] */