1/* $NetBSD: rf_psstatus.c,v 1.33 2006/11/16 01:33:23 christos Exp $ */ 2/* 3 * Copyright (c) 1995 Carnegie-Mellon University. 4 * All rights reserved. 5 * 6 * Author: Mark Holland 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/***************************************************************************** 30 * 31 * psstatus.c 32 * 33 * The reconstruction code maintains a bunch of status related to the parity 34 * stripes that are currently under reconstruction. This header file defines 35 * the status structures. 36 * 37 *****************************************************************************/ 38 39#include <sys/cdefs.h> 40__KERNEL_RCSID(0, "$NetBSD: rf_psstatus.c,v 1.33 2006/11/16 01:33:23 christos Exp $"); 41 42#include <dev/raidframe/raidframevar.h> 43 44#include "rf_raid.h" 45#include "rf_general.h" 46#include "rf_debugprint.h" 47#include "rf_psstatus.h" 48#include "rf_shutdown.h" 49 50#if RF_DEBUG_PSS 51#define Dprintf1(s,a) if (rf_pssDebug) rf_debug_printf(s,(void *)((unsigned long)a),NULL,NULL,NULL,NULL,NULL,NULL,NULL) 52#define Dprintf2(s,a,b) if (rf_pssDebug) rf_debug_printf(s,(void *)((unsigned long)a),(void *)((unsigned long)b),NULL,NULL,NULL,NULL,NULL,NULL) 53#define Dprintf3(s,a,b,c) if (rf_pssDebug) rf_debug_printf(s,(void *)((unsigned long)a),(void *)((unsigned long)b),(void *)((unsigned long)c),NULL,NULL,NULL,NULL,NULL) 54#else 55#define Dprintf1(s,a) 56#define Dprintf2(s,a,b) 57#define Dprintf3(s,a,b,c) 58#endif 59 60static void 61RealPrintPSStatusTable(RF_Raid_t * raidPtr, 62 RF_PSStatusHeader_t * pssTable); 63 64#define RF_MAX_FREE_PSS 32 65#define RF_MIN_FREE_PSS 8 66 67static void rf_ShutdownPSStatus(void *); 68 69static void 70rf_ShutdownPSStatus(void *arg) 71{ 72 73 pool_destroy(&rf_pools.pss); 74} 75 76int 77rf_ConfigurePSStatus(RF_ShutdownList_t **listp) 78{ 79 80 rf_pool_init(&rf_pools.pss, sizeof(RF_ReconParityStripeStatus_t), 81 "raidpsspl", RF_MIN_FREE_PSS, RF_MAX_FREE_PSS); 82 rf_ShutdownCreate(listp, rf_ShutdownPSStatus, NULL); 83 84 return (0); 85} 86 87void 88rf_InitPSStatus(RF_Raid_t *raidPtr) 89{ 90 raidPtr->pssTableSize = RF_PSS_DEFAULT_TABLESIZE; 91} 92 93 94/***************************************************************************************** 95 * sets up the pss table 96 * We pre-allocate a bunch of entries to avoid as much as possible having to 97 * malloc up hash chain entries. 98 ****************************************************************************************/ 99RF_PSStatusHeader_t * 100rf_MakeParityStripeStatusTable(RF_Raid_t *raidPtr) 101{ 102 RF_PSStatusHeader_t *pssTable; 103 int i; 104 105 RF_Malloc(pssTable, 106 raidPtr->pssTableSize * sizeof(RF_PSStatusHeader_t), 107 (RF_PSStatusHeader_t *)); 108 for (i = 0; i < raidPtr->pssTableSize; i++) { 109 rf_init_mutex2(pssTable[i].mutex, IPL_VM); 110 rf_init_cond2(pssTable[i].cond, "rfpsslk"); 111 } 112 return (pssTable); 113} 114 115void 116rf_FreeParityStripeStatusTable(RF_Raid_t *raidPtr, 117 RF_PSStatusHeader_t *pssTable) 118{ 119 int i; 120 121#if RF_DEBUG_PSS 122 if (rf_pssDebug) 123 RealPrintPSStatusTable(raidPtr, pssTable); 124 125 for (i = 0; i < raidPtr->pssTableSize; i++) { 126 if (pssTable[i].chain) { 127 printf("ERROR: pss hash chain not null at recon shutdown\n"); 128 } 129 } 130#endif 131 for (i = 0; i < raidPtr->pssTableSize; i++) { 132 rf_destroy_mutex2(pssTable[i].mutex); 133 rf_destroy_cond2(pssTable[i].cond); 134 } 135 RF_Free(pssTable, raidPtr->pssTableSize * sizeof(RF_PSStatusHeader_t)); 136} 137 138 139/* looks up the status structure for a parity stripe. 140 * if the create_flag is on, uses (and returns) newpssPtr if 141 * a parity status structure doesn't exist 142 * otherwise returns NULL if the status structure does not exist 143 * 144 * ASSUMES THE PSS DESCRIPTOR IS LOCKED UPON ENTRY 145 * 146 * flags - whether or not to use newpssPtr if the needed PSS 147 * doesn't exist and what flags to set it to initially 148 */ 149RF_ReconParityStripeStatus_t * 150rf_LookupRUStatus(RF_Raid_t *raidPtr, RF_PSStatusHeader_t *pssTable, 151 RF_StripeNum_t psID, RF_ReconUnitNum_t which_ru, 152 RF_PSSFlags_t flags, RF_ReconParityStripeStatus_t *newpssPtr) 153{ 154 RF_PSStatusHeader_t *hdr = &pssTable[RF_HASH_PSID(raidPtr, psID)]; 155 RF_ReconParityStripeStatus_t *p, *pssPtr = hdr->chain; 156 157 for (p = pssPtr; p; p = p->next) { 158 if (p->parityStripeID == psID && p->which_ru == which_ru) 159 break; 160 } 161 162 if (!p && (flags & RF_PSS_CREATE)) { 163 p = newpssPtr; 164 p->next = hdr->chain; 165 hdr->chain = p; 166 167 p->parityStripeID = psID; 168 p->which_ru = which_ru; 169 p->flags = flags; 170 p->rbuf = NULL; 171 p->writeRbuf = NULL; 172 p->xorBufCount = 0; 173 p->blockCount = 0; 174 p->procWaitList = NULL; 175 p->blockWaitList = NULL; 176 p->bufWaitList = NULL; 177 } else 178 if (p) { /* we didn't create, but we want to specify 179 * some new status */ 180 p->flags |= flags; /* add in whatever flags we're 181 * specifying */ 182 } 183 if (p && (flags & RF_PSS_RECON_BLOCKED)) { 184 p->blockCount++;/* if we're asking to block recon, bump the 185 * count */ 186 Dprintf3("raid%d: Blocked recon on psid %ld. count now %d\n", 187 raidPtr->raidid, psID, p->blockCount); 188 } 189 return (p); 190} 191/* deletes an entry from the parity stripe status table. typically used 192 * when an entry has been allocated solely to block reconstruction, and 193 * no recon was requested while recon was blocked. Assumes the hash 194 * chain is ALREADY LOCKED. 195 */ 196void 197rf_PSStatusDelete(RF_Raid_t *raidPtr, RF_PSStatusHeader_t *pssTable, 198 RF_ReconParityStripeStatus_t *pssPtr) 199{ 200 RF_PSStatusHeader_t *hdr = &(pssTable[RF_HASH_PSID(raidPtr, pssPtr->parityStripeID)]); 201 RF_ReconParityStripeStatus_t *p = hdr->chain, *pt = NULL; 202 203 while (p) { 204 if (p == pssPtr) { 205 if (pt) 206 pt->next = p->next; 207 else 208 hdr->chain = p->next; 209 p->next = NULL; 210 rf_FreePSStatus(raidPtr, p); 211 return; 212 } 213 pt = p; 214 p = p->next; 215 } 216 RF_ASSERT(0); /* we must find it here */ 217} 218/* deletes an entry from the ps status table after reconstruction has completed */ 219void 220rf_RemoveFromActiveReconTable(RF_Raid_t *raidPtr, RF_StripeNum_t psid, 221 RF_ReconUnitNum_t which_ru) 222{ 223 RF_PSStatusHeader_t *hdr = &(raidPtr->reconControl->pssTable[RF_HASH_PSID(raidPtr, psid)]); 224 RF_ReconParityStripeStatus_t *p, *pt; 225 RF_CallbackDesc_t *cb, *cb1; 226 227 rf_lock_mutex2(hdr->mutex); 228 while(hdr->lock) { 229 rf_wait_cond2(hdr->cond, hdr->mutex); 230 } 231 hdr->lock = 1; 232 rf_unlock_mutex2(hdr->mutex); 233 for (pt = NULL, p = hdr->chain; p; pt = p, p = p->next) { 234 if ((p->parityStripeID == psid) && (p->which_ru == which_ru)) 235 break; 236 } 237 if (p == NULL) { 238 rf_PrintPSStatusTable(raidPtr); 239 } 240 RF_ASSERT(p); /* it must be there */ 241 242 Dprintf2("PSS: deleting pss for psid %ld ru %d\n", psid, which_ru); 243 244 /* delete this entry from the hash chain */ 245 if (pt) 246 pt->next = p->next; 247 else 248 hdr->chain = p->next; 249 p->next = NULL; 250 251 rf_lock_mutex2(hdr->mutex); 252 hdr->lock = 0; 253 rf_unlock_mutex2(hdr->mutex); 254 255 /* wakup anyone waiting on the parity stripe ID */ 256 cb = p->procWaitList; 257 p->procWaitList = NULL; 258 while (cb) { 259 Dprintf1("Waking up access waiting on parity stripe ID %ld\n", p->parityStripeID); 260 cb1 = cb->next; 261 (cb->callbackFunc) (cb->callbackArg); 262 rf_FreeCallbackDesc(cb); 263 cb = cb1; 264 } 265 266 rf_FreePSStatus(raidPtr, p); 267} 268 269RF_ReconParityStripeStatus_t * 270rf_AllocPSStatus(RF_Raid_t *raidPtr) 271{ 272 RF_ReconParityStripeStatus_t *p; 273 274 p = pool_get(&rf_pools.pss, PR_WAITOK); 275 memset(p, 0, sizeof(RF_ReconParityStripeStatus_t)); 276 return (p); 277} 278 279void 280rf_FreePSStatus(RF_Raid_t *raidPtr, RF_ReconParityStripeStatus_t *p) 281{ 282 RF_ASSERT(p->procWaitList == NULL); 283 RF_ASSERT(p->blockWaitList == NULL); 284 RF_ASSERT(p->bufWaitList == NULL); 285 286 pool_put(&rf_pools.pss, p); 287} 288 289static void 290RealPrintPSStatusTable(RF_Raid_t *raidPtr, RF_PSStatusHeader_t *pssTable) 291{ 292 int i, j, procsWaiting, blocksWaiting, bufsWaiting; 293 RF_ReconParityStripeStatus_t *p; 294 RF_CallbackDesc_t *cb; 295 296 printf("\nParity Stripe Status Table\n"); 297 for (i = 0; i < raidPtr->pssTableSize; i++) { 298 for (p = pssTable[i].chain; p; p = p->next) { 299 procsWaiting = blocksWaiting = bufsWaiting = 0; 300 for (cb = p->procWaitList; cb; cb = cb->next) 301 procsWaiting++; 302 for (cb = p->blockWaitList; cb; cb = cb->next) 303 blocksWaiting++; 304 for (cb = p->bufWaitList; cb; cb = cb->next) 305 bufsWaiting++; 306 printf("PSID %ld RU %d : blockCount %d %d/%d/%d proc/block/buf waiting, issued ", 307 (long) p->parityStripeID, p->which_ru, p->blockCount, procsWaiting, blocksWaiting, bufsWaiting); 308 for (j = 0; j < raidPtr->numCol; j++) 309 printf("%c", (p->issued[j]) ? '1' : '0'); 310 if (!p->flags) 311 printf(" flags: (none)"); 312 else { 313 if (p->flags & RF_PSS_UNDER_RECON) 314 printf(" under-recon"); 315 if (p->flags & RF_PSS_FORCED_ON_WRITE) 316 printf(" forced-w"); 317 if (p->flags & RF_PSS_FORCED_ON_READ) 318 printf(" forced-r"); 319 if (p->flags & RF_PSS_RECON_BLOCKED) 320 printf(" blocked"); 321 if (p->flags & RF_PSS_BUFFERWAIT) 322 printf(" bufwait"); 323 } 324 printf("\n"); 325 } 326 } 327} 328 329void 330rf_PrintPSStatusTable(RF_Raid_t *raidPtr) 331{ 332 RF_PSStatusHeader_t *pssTable = raidPtr->reconControl->pssTable; 333 RealPrintPSStatusTable(raidPtr, pssTable); 334} 335