Annotation of sys/dev/raidframe/rf_psstatus.c, Revision 1.1
1.1 ! nbrk 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: }
CVSweb