Annotation of sys/dev/raidframe/rf_reconutil.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: rf_reconutil.c,v 1.3 2002/12/16 07:01:05 tdeval Exp $ */
2: /* $NetBSD: rf_reconutil.c,v 1.3 1999/02/05 00:06:17 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: * rf_reconutil.c -- Reconstruction utilities.
33: **********************************************/
34:
35: #include "rf_types.h"
36: #include "rf_raid.h"
37: #include "rf_desc.h"
38: #include "rf_reconutil.h"
39: #include "rf_reconbuffer.h"
40: #include "rf_general.h"
41: #include "rf_decluster.h"
42: #include "rf_raid5_rotatedspare.h"
43: #include "rf_interdecluster.h"
44: #include "rf_chaindecluster.h"
45:
46:
47: /*********************************************************************
48: * Allocates/frees the reconstruction control information structures.
49: *********************************************************************/
50: RF_ReconCtrl_t *
51: rf_MakeReconControl(
52: RF_RaidReconDesc_t *reconDesc,
53: RF_RowCol_t frow, /* Failed row and column. */
54: RF_RowCol_t fcol,
55: RF_RowCol_t srow, /* Identifies which spare we're using. */
56: RF_RowCol_t scol
57: )
58: {
59: RF_Raid_t *raidPtr = reconDesc->raidPtr;
60: RF_RaidLayout_t *layoutPtr = &raidPtr->Layout;
61: RF_ReconUnitCount_t RUsPerPU = layoutPtr->SUsPerPU /
62: layoutPtr->SUsPerRU;
63: RF_ReconUnitCount_t numSpareRUs;
64: RF_ReconCtrl_t *reconCtrlPtr;
65: RF_ReconBuffer_t *rbuf;
66: RF_LayoutSW_t *lp;
67: int retcode, rc;
68: RF_RowCol_t i;
69:
70: lp = raidPtr->Layout.map;
71:
72: /*
73: * Make and zero the global reconstruction structure and the per-disk
74: * structure.
75: */
76: RF_Calloc(reconCtrlPtr, 1, sizeof(RF_ReconCtrl_t), (RF_ReconCtrl_t *));
77: /* This zeros it. */
78: RF_Calloc(reconCtrlPtr->perDiskInfo, raidPtr->numCol,
79: sizeof(RF_PerDiskReconCtrl_t), (RF_PerDiskReconCtrl_t *));
80: reconCtrlPtr->reconDesc = reconDesc;
81: reconCtrlPtr->fcol = fcol;
82: reconCtrlPtr->spareRow = srow;
83: reconCtrlPtr->spareCol = scol;
84: reconCtrlPtr->lastPSID = layoutPtr->numStripe / layoutPtr->SUsPerPU;
85: reconCtrlPtr->percentComplete = 0;
86:
87: /* Initialize each per-disk recon information structure. */
88: for (i = 0; i < raidPtr->numCol; i++) {
89: reconCtrlPtr->perDiskInfo[i].reconCtrl = reconCtrlPtr;
90: reconCtrlPtr->perDiskInfo[i].row = frow;
91: reconCtrlPtr->perDiskInfo[i].col = i;
92: /* Make it appear as if we just finished an RU. */
93: reconCtrlPtr->perDiskInfo[i].curPSID = -1;
94: reconCtrlPtr->perDiskInfo[i].ru_count = RUsPerPU - 1;
95: }
96:
97: /*
98: * Get the number of spare units per disk and the sparemap in case
99: * spare is distributed.
100: */
101:
102: if (lp->GetNumSpareRUs) {
103: numSpareRUs = lp->GetNumSpareRUs(raidPtr);
104: } else {
105: numSpareRUs = 0;
106: }
107:
108: /*
109: * Not all distributed sparing archs need dynamic mappings.
110: */
111: if (lp->InstallSpareTable) {
112: retcode = rf_InstallSpareTable(raidPtr, frow, fcol);
113: if (retcode) {
114: RF_PANIC(); /* XXX Fix this. */
115: }
116: }
117: /* Make the reconstruction map. */
118: reconCtrlPtr->reconMap = rf_MakeReconMap(raidPtr,
119: (int) (layoutPtr->SUsPerRU * layoutPtr->sectorsPerStripeUnit),
120: raidPtr->sectorsPerDisk, numSpareRUs);
121:
122: /* Make the per-disk reconstruction buffers. */
123: for (i = 0; i < raidPtr->numCol; i++) {
124: reconCtrlPtr->perDiskInfo[i].rbuf = (i == fcol) ? NULL :
125: rf_MakeReconBuffer(raidPtr, frow, i,
126: RF_RBUF_TYPE_EXCLUSIVE);
127: }
128:
129: /* Initialize the event queue. */
130: rc = rf_mutex_init(&reconCtrlPtr->eq_mutex);
131: if (rc) {
132: /* XXX Deallocate, cleanup. */
133: RF_ERRORMSG3("Unable to init mutex file %s line %d rc=%d.\n",
134: __FILE__, __LINE__, rc);
135: return (NULL);
136: }
137: rc = rf_cond_init(&reconCtrlPtr->eq_cond);
138: if (rc) {
139: /* XXX Deallocate, cleanup. */
140: RF_ERRORMSG3("Unable to init cond file %s line %d rc=%d.\n",
141: __FILE__, __LINE__, rc);
142: return (NULL);
143: }
144: reconCtrlPtr->eventQueue = NULL;
145: reconCtrlPtr->eq_count = 0;
146:
147: /* Make the floating recon buffers and append them to the free list. */
148: rc = rf_mutex_init(&reconCtrlPtr->rb_mutex);
149: if (rc) {
150: /* XXX Deallocate, cleanup. */
151: RF_ERRORMSG3("Unable to init mutex file %s line %d rc=%d.\n",
152: __FILE__, __LINE__, rc);
153: return (NULL);
154: }
155: reconCtrlPtr->fullBufferList = NULL;
156: reconCtrlPtr->priorityList = NULL;
157: reconCtrlPtr->floatingRbufs = NULL;
158: reconCtrlPtr->committedRbufs = NULL;
159: for (i = 0; i < raidPtr->numFloatingReconBufs; i++) {
160: rbuf = rf_MakeReconBuffer(raidPtr, frow, fcol,
161: RF_RBUF_TYPE_FLOATING);
162: rbuf->next = reconCtrlPtr->floatingRbufs;
163: reconCtrlPtr->floatingRbufs = rbuf;
164: }
165:
166: /* Create the parity stripe status table. */
167: reconCtrlPtr->pssTable = rf_MakeParityStripeStatusTable(raidPtr);
168:
169: /* Set the initial min head sep counter val. */
170: reconCtrlPtr->minHeadSepCounter = 0;
171:
172: return (reconCtrlPtr);
173: }
174:
175: void
176: rf_FreeReconControl(RF_Raid_t *raidPtr, RF_RowCol_t row)
177: {
178: RF_ReconCtrl_t *reconCtrlPtr = raidPtr->reconControl[row];
179: RF_ReconBuffer_t *t;
180: RF_ReconUnitNum_t i;
181:
182: RF_ASSERT(reconCtrlPtr);
183: for (i = 0; i < raidPtr->numCol; i++)
184: if (reconCtrlPtr->perDiskInfo[i].rbuf)
185: rf_FreeReconBuffer(reconCtrlPtr->perDiskInfo[i].rbuf);
186: for (i = 0; i < raidPtr->numFloatingReconBufs; i++) {
187: t = reconCtrlPtr->floatingRbufs;
188: RF_ASSERT(t);
189: reconCtrlPtr->floatingRbufs = t->next;
190: rf_FreeReconBuffer(t);
191: }
192: rf_mutex_destroy(&reconCtrlPtr->rb_mutex);
193: rf_mutex_destroy(&reconCtrlPtr->eq_mutex);
194: rf_cond_destroy(&reconCtrlPtr->eq_cond);
195: rf_FreeReconMap(reconCtrlPtr->reconMap);
196: rf_FreeParityStripeStatusTable(raidPtr, reconCtrlPtr->pssTable);
197: RF_Free(reconCtrlPtr->perDiskInfo, raidPtr->numCol *
198: sizeof(RF_PerDiskReconCtrl_t));
199: RF_Free(reconCtrlPtr, sizeof(*reconCtrlPtr));
200: }
201:
202:
203: /*****************************************************************************
204: * Computes the default head separation limit.
205: *****************************************************************************/
206: RF_HeadSepLimit_t
207: rf_GetDefaultHeadSepLimit(RF_Raid_t *raidPtr)
208: {
209: RF_HeadSepLimit_t hsl;
210: RF_LayoutSW_t *lp;
211:
212: lp = raidPtr->Layout.map;
213: if (lp->GetDefaultHeadSepLimit == NULL)
214: return (-1);
215: hsl = lp->GetDefaultHeadSepLimit(raidPtr);
216: return (hsl);
217: }
218:
219:
220: /*****************************************************************************
221: * Computes the default number of floating recon buffers.
222: *****************************************************************************/
223: int
224: rf_GetDefaultNumFloatingReconBuffers(RF_Raid_t *raidPtr)
225: {
226: RF_LayoutSW_t *lp;
227: int nrb;
228:
229: lp = raidPtr->Layout.map;
230: if (lp->GetDefaultNumFloatingReconBuffers == NULL)
231: return (3 * raidPtr->numCol);
232: nrb = lp->GetDefaultNumFloatingReconBuffers(raidPtr);
233: return (nrb);
234: }
235:
236:
237: /*****************************************************************************
238: * Creates and initializes a reconstruction buffer.
239: *****************************************************************************/
240: RF_ReconBuffer_t *
241: rf_MakeReconBuffer(RF_Raid_t *raidPtr, RF_RowCol_t row, RF_RowCol_t col,
242: RF_RbufType_t type)
243: {
244: RF_RaidLayout_t *layoutPtr = &raidPtr->Layout;
245: RF_ReconBuffer_t *t;
246: u_int recon_buffer_size = rf_RaidAddressToByte(raidPtr,
247: layoutPtr->SUsPerRU * layoutPtr->sectorsPerStripeUnit);
248:
249: RF_Malloc(t, sizeof(RF_ReconBuffer_t), (RF_ReconBuffer_t *));
250: RF_Malloc(t->buffer, recon_buffer_size, (caddr_t));
251: RF_Malloc(t->arrived, raidPtr->numCol * sizeof(char), (char *));
252: t->raidPtr = raidPtr;
253: t->row = row;
254: t->col = col;
255: t->priority = RF_IO_RECON_PRIORITY;
256: t->type = type;
257: t->pssPtr = NULL;
258: t->next = NULL;
259: return (t);
260: }
261:
262:
263: /*****************************************************************************
264: * Frees a reconstruction buffer.
265: *****************************************************************************/
266: void
267: rf_FreeReconBuffer(RF_ReconBuffer_t *rbuf)
268: {
269: RF_Raid_t *raidPtr = rbuf->raidPtr;
270: u_int recon_buffer_size = rf_RaidAddressToByte(raidPtr,
271: raidPtr->Layout.SUsPerRU * raidPtr->Layout.sectorsPerStripeUnit);
272:
273: RF_Free(rbuf->arrived, raidPtr->numCol * sizeof(char));
274: RF_Free(rbuf->buffer, recon_buffer_size);
275: RF_Free(rbuf, sizeof(*rbuf));
276: }
277:
278:
279: /*****************************************************************************
280: * Debug only: Sanity check the number of floating recon bufs in use.
281: *****************************************************************************/
282: void
283: rf_CheckFloatingRbufCount(RF_Raid_t *raidPtr, int dolock)
284: {
285: RF_ReconParityStripeStatus_t *p;
286: RF_PSStatusHeader_t *pssTable;
287: RF_ReconBuffer_t *rbuf;
288: int i, j, sum = 0;
289: RF_RowCol_t frow = 0;
290:
291: for (i = 0; i < raidPtr->numRow; i++)
292: if (raidPtr->reconControl[i]) {
293: frow = i;
294: break;
295: }
296: RF_ASSERT(frow >= 0);
297:
298: if (dolock)
299: RF_LOCK_MUTEX(raidPtr->reconControl[frow]->rb_mutex);
300: pssTable = raidPtr->reconControl[frow]->pssTable;
301:
302: for (i = 0; i < raidPtr->pssTableSize; i++) {
303: RF_LOCK_MUTEX(pssTable[i].mutex);
304: for (p = pssTable[i].chain; p; p = p->next) {
305: rbuf = (RF_ReconBuffer_t *) p->rbuf;
306: if (rbuf && rbuf->type == RF_RBUF_TYPE_FLOATING)
307: sum++;
308:
309: rbuf = (RF_ReconBuffer_t *) p->writeRbuf;
310: if (rbuf && rbuf->type == RF_RBUF_TYPE_FLOATING)
311: sum++;
312:
313: for (j = 0; j < p->xorBufCount; j++) {
314: rbuf = (RF_ReconBuffer_t *) p->rbufsForXor[j];
315: RF_ASSERT(rbuf);
316: if (rbuf->type == RF_RBUF_TYPE_FLOATING)
317: sum++;
318: }
319: }
320: RF_UNLOCK_MUTEX(pssTable[i].mutex);
321: }
322:
323: for (rbuf = raidPtr->reconControl[frow]->floatingRbufs; rbuf;
324: rbuf = rbuf->next) {
325: if (rbuf->type == RF_RBUF_TYPE_FLOATING)
326: sum++;
327: }
328: for (rbuf = raidPtr->reconControl[frow]->committedRbufs; rbuf;
329: rbuf = rbuf->next) {
330: if (rbuf->type == RF_RBUF_TYPE_FLOATING)
331: sum++;
332: }
333: for (rbuf = raidPtr->reconControl[frow]->fullBufferList; rbuf;
334: rbuf = rbuf->next) {
335: if (rbuf->type == RF_RBUF_TYPE_FLOATING)
336: sum++;
337: }
338: for (rbuf = raidPtr->reconControl[frow]->priorityList; rbuf;
339: rbuf = rbuf->next) {
340: if (rbuf->type == RF_RBUF_TYPE_FLOATING)
341: sum++;
342: }
343:
344: RF_ASSERT(sum == raidPtr->numFloatingReconBufs);
345:
346: if (dolock)
347: RF_UNLOCK_MUTEX(raidPtr->reconControl[frow]->rb_mutex);
348: }
CVSweb