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