rf_psstatus.c revision 1.2 1 /* $NetBSD: rf_psstatus.c,v 1.2 1999/01/26 02:34:00 oster 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 (at) 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 "rf_types.h"
40 #include "rf_raid.h"
41 #include "rf_threadid.h"
42 #include "rf_general.h"
43 #include "rf_debugprint.h"
44 #include "rf_freelist.h"
45 #include "rf_psstatus.h"
46 #include "rf_shutdown.h"
47 #include "rf_sys.h"
48
49 #define Dprintf1(s,a) if (rf_pssDebug) rf_debug_printf(s,(void *)((unsigned long)a),NULL,NULL,NULL,NULL,NULL,NULL,NULL)
50 #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)
51 #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)
52
53 static void RealPrintPSStatusTable(RF_Raid_t *raidPtr,
54 RF_PSStatusHeader_t *pssTable);
55
56 #define RF_MAX_FREE_PSS 32
57 #define RF_PSS_INC 8
58 #define RF_PSS_INITIAL 4
59
60 static int init_pss( RF_ReconParityStripeStatus_t *, RF_Raid_t *);
61 static void clean_pss(RF_ReconParityStripeStatus_t *, RF_Raid_t *);
62 static void rf_ShutdownPSStatus(void *);
63
64 static int init_pss(p, raidPtr)
65 RF_ReconParityStripeStatus_t *p;
66 RF_Raid_t *raidPtr;
67 {
68 RF_Calloc(p->issued, raidPtr->numCol, sizeof(char), (char *));
69 if (p->issued == NULL)
70 return(ENOMEM);
71 return(0);
72 }
73
74 static void clean_pss(p, raidPtr)
75 RF_ReconParityStripeStatus_t *p;
76 RF_Raid_t *raidPtr;
77 {
78 RF_Free(p->issued, raidPtr->numCol*sizeof(char));
79 }
80
81 static void rf_ShutdownPSStatus(arg)
82 void *arg;
83 {
84 RF_Raid_t *raidPtr = (RF_Raid_t *)arg;
85
86 RF_FREELIST_DESTROY_CLEAN_ARG(raidPtr->pss_freelist,next,(RF_ReconParityStripeStatus_t *),clean_pss,raidPtr);
87 }
88
89 int rf_ConfigurePSStatus(
90 RF_ShutdownList_t **listp,
91 RF_Raid_t *raidPtr,
92 RF_Config_t *cfgPtr)
93 {
94 int rc;
95
96 raidPtr->pssTableSize = RF_PSS_DEFAULT_TABLESIZE;
97 RF_FREELIST_CREATE(raidPtr->pss_freelist, RF_MAX_FREE_PSS,
98 RF_PSS_INC, sizeof(RF_ReconParityStripeStatus_t));
99 if (raidPtr->pss_freelist == NULL)
100 return(ENOMEM);
101 rc = rf_ShutdownCreate(listp, rf_ShutdownPSStatus, raidPtr);
102 if (rc) {
103 RF_ERRORMSG3("Unable to add to shutdown list file %s line %d rc=%d\n",
104 __FILE__, __LINE__, rc);
105 rf_ShutdownPSStatus(raidPtr);
106 return(rc);
107 }
108 RF_FREELIST_PRIME_INIT_ARG(raidPtr->pss_freelist, RF_PSS_INITIAL,next,
109 (RF_ReconParityStripeStatus_t *),init_pss,raidPtr);
110 return(0);
111 }
112
113 /*****************************************************************************************
114 * sets up the pss table
115 * We pre-allocate a bunch of entries to avoid as much as possible having to
116 * malloc up hash chain entries.
117 ****************************************************************************************/
118 RF_PSStatusHeader_t *rf_MakeParityStripeStatusTable(raidPtr)
119 RF_Raid_t *raidPtr;
120 {
121 RF_PSStatusHeader_t *pssTable;
122 int i, j, rc;
123
124 RF_Calloc(pssTable, raidPtr->pssTableSize, sizeof(RF_PSStatusHeader_t), (RF_PSStatusHeader_t *));
125 for (i=0; i<raidPtr->pssTableSize; i++) {
126 rc = rf_mutex_init(&pssTable[i].mutex);
127 if (rc) {
128 RF_ERRORMSG3("Unable to init mutex file %s line %d rc=%d\n", __FILE__,
129 __LINE__, rc);
130 /* fail and deallocate */
131 for(j=0;j<i;j++) {
132 rf_mutex_destroy(&pssTable[i].mutex);
133 }
134 RF_Free(pssTable, raidPtr->pssTableSize*sizeof(RF_PSStatusHeader_t));
135 return(NULL);
136 }
137 }
138 return(pssTable);
139 }
140
141 void rf_FreeParityStripeStatusTable(raidPtr, pssTable)
142 RF_Raid_t *raidPtr;
143 RF_PSStatusHeader_t *pssTable;
144 {
145 int i;
146
147 if (rf_pssDebug)
148 RealPrintPSStatusTable(raidPtr, pssTable);
149 for (i=0; i<raidPtr->pssTableSize; i++) {
150 if (pssTable[i].chain) {
151 printf("ERROR: pss hash chain not null at recon shutdown\n");
152 }
153 rf_mutex_destroy(&pssTable[i].mutex);
154 }
155 RF_Free(pssTable, raidPtr->pssTableSize * sizeof(RF_PSStatusHeader_t));
156 }
157
158
159 /* looks up the status structure for a parity stripe.
160 * if the create_flag is on, creates and returns the status structure it it doesn't exist
161 * otherwise returns NULL if the status structure does not exist
162 *
163 * ASSUMES THE PSS DESCRIPTOR IS LOCKED UPON ENTRY
164 */
165 RF_ReconParityStripeStatus_t *rf_LookupRUStatus(
166 RF_Raid_t *raidPtr,
167 RF_PSStatusHeader_t *pssTable,
168 RF_StripeNum_t psID,
169 RF_ReconUnitNum_t which_ru,
170 RF_PSSFlags_t flags, /* whether or not to create it if it doesn't exist + what flags to set initially */
171 int *created)
172 {
173 RF_PSStatusHeader_t *hdr = &pssTable[ RF_HASH_PSID(raidPtr,psID) ];
174 RF_ReconParityStripeStatus_t *p, *pssPtr = hdr->chain;
175
176 *created = 0;
177 for (p = pssPtr; p; p=p->next) {
178 if (p->parityStripeID == psID && p->which_ru == which_ru)
179 break;
180 }
181
182 if (!p && (flags&RF_PSS_CREATE)) {
183 Dprintf2("PSS: creating pss for psid %ld ru %d\n",psID,which_ru);
184 p = rf_AllocPSStatus(raidPtr);
185 p->next = hdr->chain; hdr->chain = p;
186
187 p->parityStripeID = psID;
188 p->which_ru = which_ru;
189 p->flags = flags;
190 p->rbuf = NULL;
191 p->writeRbuf = NULL;
192 p->blockCount = 0;
193 p->procWaitList = NULL;
194 p->blockWaitList = NULL;
195 p->bufWaitList = NULL;
196 *created = 1;
197 } else if (p) { /* we didn't create, but we want to specify some new status */
198 p->flags |= flags; /* add in whatever flags we're specifying */
199 }
200 if (p && (flags & RF_PSS_RECON_BLOCKED)) {
201 int tid;
202 rf_get_threadid(tid);
203 p->blockCount++; /* if we're asking to block recon, bump the count */
204 Dprintf3("[%d] Blocked recon on psid %ld. count now %d\n",tid,psID,p->blockCount);
205 }
206 return(p);
207 }
208
209 /* deletes an entry from the parity stripe status table. typically used
210 * when an entry has been allocated solely to block reconstruction, and
211 * no recon was requested while recon was blocked. Assumes the hash
212 * chain is ALREADY LOCKED.
213 */
214 void rf_PSStatusDelete(raidPtr, pssTable, pssPtr)
215 RF_Raid_t *raidPtr;
216 RF_PSStatusHeader_t *pssTable;
217 RF_ReconParityStripeStatus_t *pssPtr;
218 {
219 RF_PSStatusHeader_t *hdr = &(pssTable[ RF_HASH_PSID(raidPtr,pssPtr->parityStripeID) ] );
220 RF_ReconParityStripeStatus_t *p = hdr->chain, *pt = NULL;
221
222 while (p) {
223 if (p == pssPtr) {
224 if (pt) pt->next = p->next; else hdr->chain = p->next;
225 p->next = NULL;
226 rf_FreePSStatus(raidPtr, p);
227 return;
228 }
229 pt = p; p=p->next;
230 }
231 RF_ASSERT(0); /* we must find it here */
232 }
233
234 /* deletes an entry from the ps status table after reconstruction has completed */
235 void rf_RemoveFromActiveReconTable(raidPtr, row, psid, which_ru)
236 RF_Raid_t *raidPtr;
237 RF_RowCol_t row;
238 RF_ReconUnitNum_t which_ru;
239 RF_StripeNum_t psid;
240 {
241 RF_PSStatusHeader_t *hdr = &(raidPtr->reconControl[row]->pssTable[ RF_HASH_PSID(raidPtr,psid) ]);
242 RF_ReconParityStripeStatus_t *p, *pt;
243 RF_CallbackDesc_t *cb, *cb1;
244
245 RF_LOCK_MUTEX( hdr->mutex );
246 for (pt=NULL, p = hdr->chain; p; pt=p,p=p->next) {
247 if ((p->parityStripeID == psid) && (p->which_ru == which_ru))
248 break;
249 }
250 if (p == NULL) {
251 rf_PrintPSStatusTable(raidPtr, row);
252 }
253 RF_ASSERT(p); /* it must be there */
254
255 Dprintf2("PSS: deleting pss for psid %ld ru %d\n",psid,which_ru);
256
257 /* delete this entry from the hash chain */
258 if (pt) pt->next = p->next;
259 else hdr->chain = p->next;
260 p->next = NULL;
261
262 RF_UNLOCK_MUTEX( hdr->mutex );
263
264 /* wakup anyone waiting on the parity stripe ID */
265 cb = p->procWaitList;
266 p->procWaitList = NULL;
267 while (cb) {
268 Dprintf1("Waking up access waiting on parity stripe ID %ld\n",p->parityStripeID);
269 cb1 = cb->next;
270 (cb->callbackFunc)(cb->callbackArg);
271
272 /* THIS IS WHAT THE ORIGINAL CODE HAD... the extra 0 is bogus, IMHO */
273 /* (cb->callbackFunc)(cb->callbackArg, 0); */
274 rf_FreeCallbackDesc(cb);
275 cb = cb1;
276 }
277
278 rf_FreePSStatus(raidPtr, p);
279 }
280
281 RF_ReconParityStripeStatus_t *rf_AllocPSStatus(raidPtr)
282 RF_Raid_t *raidPtr;
283 {
284 RF_ReconParityStripeStatus_t *p;
285
286 RF_FREELIST_GET_INIT_ARG(raidPtr->pss_freelist,p,next,(RF_ReconParityStripeStatus_t *),init_pss,raidPtr);
287 if (p) {
288 bzero(p->issued, raidPtr->numCol);
289 }
290 p->next = NULL;
291 /* no need to initialize here b/c the only place we're called from is the above Lookup */
292 return(p);
293 }
294
295 void rf_FreePSStatus(raidPtr, p)
296 RF_Raid_t *raidPtr;
297 RF_ReconParityStripeStatus_t *p;
298 {
299 RF_ASSERT(p->procWaitList == NULL);
300 RF_ASSERT(p->blockWaitList == NULL);
301 RF_ASSERT(p->bufWaitList == NULL);
302
303 RF_FREELIST_FREE_CLEAN_ARG(raidPtr->pss_freelist,p,next,clean_pss,raidPtr);
304 }
305
306 static void RealPrintPSStatusTable(raidPtr, pssTable)
307 RF_Raid_t *raidPtr;
308 RF_PSStatusHeader_t *pssTable;
309 {
310 int i, j, procsWaiting, blocksWaiting, bufsWaiting;
311 RF_ReconParityStripeStatus_t *p;
312 RF_CallbackDesc_t *cb;
313
314 printf("\nParity Stripe Status Table\n");
315 for (i=0; i< raidPtr->pssTableSize; i++) {
316 for (p = pssTable[i].chain; p; p=p->next) {
317 procsWaiting = blocksWaiting = bufsWaiting = 0;
318 for (cb = p->procWaitList; cb; cb=cb->next) procsWaiting++;
319 for (cb = p->blockWaitList; cb; cb=cb->next) blocksWaiting++;
320 for (cb = p->bufWaitList; cb; cb=cb->next) bufsWaiting++;
321 printf("PSID %ld RU %d : blockCount %d %d/%d/%d proc/block/buf waiting, issued ",
322 (long)p->parityStripeID, p->which_ru, p->blockCount, procsWaiting, blocksWaiting, bufsWaiting);
323 for (j=0;j<raidPtr->numCol; j++) printf("%c", (p->issued[j]) ? '1' : '0');
324 if (!p->flags) printf(" flags: (none)");
325 else {
326 if (p->flags & RF_PSS_UNDER_RECON) printf(" under-recon");
327 if (p->flags & RF_PSS_FORCED_ON_WRITE) printf(" forced-w");
328 if (p->flags & RF_PSS_FORCED_ON_READ) printf(" forced-r");
329 if (p->flags & RF_PSS_RECON_BLOCKED) printf(" blocked");
330 if (p->flags & RF_PSS_BUFFERWAIT) printf(" bufwait");
331 }
332 printf("\n");
333 }
334 }
335 }
336
337 void rf_PrintPSStatusTable(raidPtr, row)
338 RF_Raid_t *raidPtr;
339 RF_RowCol_t row;
340 {
341 RF_PSStatusHeader_t *pssTable = raidPtr->reconControl[row]->pssTable;
342 RealPrintPSStatusTable(raidPtr, pssTable);
343 }
344