1 /* $NetBSD: rf_psstatus.c,v 1.32 2006/10/12 01:31:52 christos Exp $ */
3 * Copyright (c) 1995 Carnegie-Mellon University.
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.
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.
18 * Carnegie Mellon requests users of this software to return to
20 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
21 * School of Computer Science
22 * Carnegie Mellon University
23 * Pittsburgh PA 15213-3890
25 * any improvements or extensions that they make and grant Carnegie the
26 * rights to redistribute these changes.
29 /*****************************************************************************
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.
37 *****************************************************************************/
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: rf_psstatus.c,v 1.32 2006/10/12 01:31:52 christos Exp $");
42 #include <dev/raidframe/raidframevar.h>
45 #include "rf_general.h"
46 #include "rf_debugprint.h"
47 #include "rf_psstatus.h"
48 #include "rf_shutdown.h"
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)
56 #define Dprintf2(s,a,b)
57 #define Dprintf3(s,a,b,c)
61 RealPrintPSStatusTable(RF_Raid_t
* raidPtr
,
62 RF_PSStatusHeader_t
* pssTable
);
64 #define RF_MAX_FREE_PSS 32
65 #define RF_MIN_FREE_PSS 8
67 static void rf_ShutdownPSStatus(void *);
70 rf_ShutdownPSStatus(void *arg
)
73 pool_destroy(&rf_pools
.pss
);
77 rf_ConfigurePSStatus(RF_ShutdownList_t
**listp
)
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
);
88 rf_InitPSStatus(RF_Raid_t
*raidPtr
)
90 raidPtr
->pssTableSize
= RF_PSS_DEFAULT_TABLESIZE
;
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 ****************************************************************************************/
100 rf_MakeParityStripeStatusTable(RF_Raid_t
*raidPtr
)
102 RF_PSStatusHeader_t
*pssTable
;
106 raidPtr
->pssTableSize
* sizeof(RF_PSStatusHeader_t
),
107 (RF_PSStatusHeader_t
*));
108 for (i
= 0; i
< raidPtr
->pssTableSize
; i
++) {
109 rf_mutex_init(&pssTable
[i
].mutex
);
115 rf_FreeParityStripeStatusTable(RF_Raid_t
*raidPtr
,
116 RF_PSStatusHeader_t
*pssTable
)
122 RealPrintPSStatusTable(raidPtr
, pssTable
);
124 for (i
= 0; i
< raidPtr
->pssTableSize
; i
++) {
125 if (pssTable
[i
].chain
) {
126 printf("ERROR: pss hash chain not null at recon shutdown\n");
130 RF_Free(pssTable
, raidPtr
->pssTableSize
* sizeof(RF_PSStatusHeader_t
));
134 /* looks up the status structure for a parity stripe.
135 * if the create_flag is on, uses (and returns) newpssPtr if
136 * a parity status structure doesn't exist
137 * otherwise returns NULL if the status structure does not exist
139 * ASSUMES THE PSS DESCRIPTOR IS LOCKED UPON ENTRY
141 * flags - whether or not to use newpssPtr if the needed PSS
142 * doesn't exist and what flags to set it to initially
144 RF_ReconParityStripeStatus_t
*
145 rf_LookupRUStatus(RF_Raid_t
*raidPtr
, RF_PSStatusHeader_t
*pssTable
,
146 RF_StripeNum_t psID
, RF_ReconUnitNum_t which_ru
,
147 RF_PSSFlags_t flags
, RF_ReconParityStripeStatus_t
*newpssPtr
)
149 RF_PSStatusHeader_t
*hdr
= &pssTable
[RF_HASH_PSID(raidPtr
, psID
)];
150 RF_ReconParityStripeStatus_t
*p
, *pssPtr
= hdr
->chain
;
152 for (p
= pssPtr
; p
; p
= p
->next
) {
153 if (p
->parityStripeID
== psID
&& p
->which_ru
== which_ru
)
157 if (!p
&& (flags
& RF_PSS_CREATE
)) {
159 p
->next
= hdr
->chain
;
162 p
->parityStripeID
= psID
;
163 p
->which_ru
= which_ru
;
169 p
->procWaitList
= NULL
;
170 p
->blockWaitList
= NULL
;
171 p
->bufWaitList
= NULL
;
173 if (p
) { /* we didn't create, but we want to specify
175 p
->flags
|= flags
; /* add in whatever flags we're
178 if (p
&& (flags
& RF_PSS_RECON_BLOCKED
)) {
179 p
->blockCount
++;/* if we're asking to block recon, bump the
181 Dprintf3("raid%d: Blocked recon on psid %ld. count now %d\n",
182 raidPtr
->raidid
, psID
, p
->blockCount
);
186 /* deletes an entry from the parity stripe status table. typically used
187 * when an entry has been allocated solely to block reconstruction, and
188 * no recon was requested while recon was blocked. Assumes the hash
189 * chain is ALREADY LOCKED.
192 rf_PSStatusDelete(RF_Raid_t
*raidPtr
, RF_PSStatusHeader_t
*pssTable
,
193 RF_ReconParityStripeStatus_t
*pssPtr
)
195 RF_PSStatusHeader_t
*hdr
= &(pssTable
[RF_HASH_PSID(raidPtr
, pssPtr
->parityStripeID
)]);
196 RF_ReconParityStripeStatus_t
*p
= hdr
->chain
, *pt
= NULL
;
203 hdr
->chain
= p
->next
;
205 rf_FreePSStatus(raidPtr
, p
);
211 RF_ASSERT(0); /* we must find it here */
213 /* deletes an entry from the ps status table after reconstruction has completed */
215 rf_RemoveFromActiveReconTable(RF_Raid_t
*raidPtr
, RF_StripeNum_t psid
,
216 RF_ReconUnitNum_t which_ru
)
218 RF_PSStatusHeader_t
*hdr
= &(raidPtr
->reconControl
->pssTable
[RF_HASH_PSID(raidPtr
, psid
)]);
219 RF_ReconParityStripeStatus_t
*p
, *pt
;
220 RF_CallbackDesc_t
*cb
, *cb1
;
222 RF_LOCK_MUTEX(hdr
->mutex
);
224 ltsleep(&hdr
->lock
, PRIBIO
, "rf_racrecon", 0, &hdr
->mutex
);
227 RF_UNLOCK_MUTEX(hdr
->mutex
);
228 for (pt
= NULL
, p
= hdr
->chain
; p
; pt
= p
, p
= p
->next
) {
229 if ((p
->parityStripeID
== psid
) && (p
->which_ru
== which_ru
))
233 rf_PrintPSStatusTable(raidPtr
);
235 RF_ASSERT(p
); /* it must be there */
237 Dprintf2("PSS: deleting pss for psid %ld ru %d\n", psid
, which_ru
);
239 /* delete this entry from the hash chain */
243 hdr
->chain
= p
->next
;
246 RF_LOCK_MUTEX(hdr
->mutex
);
248 RF_UNLOCK_MUTEX(hdr
->mutex
);
250 /* wakup anyone waiting on the parity stripe ID */
251 cb
= p
->procWaitList
;
252 p
->procWaitList
= NULL
;
254 Dprintf1("Waking up access waiting on parity stripe ID %ld\n", p
->parityStripeID
);
256 (cb
->callbackFunc
) (cb
->callbackArg
);
257 rf_FreeCallbackDesc(cb
);
261 rf_FreePSStatus(raidPtr
, p
);
264 RF_ReconParityStripeStatus_t
*
265 rf_AllocPSStatus(RF_Raid_t
*raidPtr
)
267 RF_ReconParityStripeStatus_t
*p
;
269 p
= pool_get(&rf_pools
.pss
, PR_WAITOK
);
270 memset(p
, 0, sizeof(RF_ReconParityStripeStatus_t
));
275 rf_FreePSStatus(RF_Raid_t
*raidPtr
, RF_ReconParityStripeStatus_t
*p
)
277 RF_ASSERT(p
->procWaitList
== NULL
);
278 RF_ASSERT(p
->blockWaitList
== NULL
);
279 RF_ASSERT(p
->bufWaitList
== NULL
);
281 pool_put(&rf_pools
.pss
, p
);
285 RealPrintPSStatusTable(RF_Raid_t
*raidPtr
, RF_PSStatusHeader_t
*pssTable
)
287 int i
, j
, procsWaiting
, blocksWaiting
, bufsWaiting
;
288 RF_ReconParityStripeStatus_t
*p
;
289 RF_CallbackDesc_t
*cb
;
291 printf("\nParity Stripe Status Table\n");
292 for (i
= 0; i
< raidPtr
->pssTableSize
; i
++) {
293 for (p
= pssTable
[i
].chain
; p
; p
= p
->next
) {
294 procsWaiting
= blocksWaiting
= bufsWaiting
= 0;
295 for (cb
= p
->procWaitList
; cb
; cb
= cb
->next
)
297 for (cb
= p
->blockWaitList
; cb
; cb
= cb
->next
)
299 for (cb
= p
->bufWaitList
; cb
; cb
= cb
->next
)
301 printf("PSID %ld RU %d : blockCount %d %d/%d/%d proc/block/buf waiting, issued ",
302 (long) p
->parityStripeID
, p
->which_ru
, p
->blockCount
, procsWaiting
, blocksWaiting
, bufsWaiting
);
303 for (j
= 0; j
< raidPtr
->numCol
; j
++)
304 printf("%c", (p
->issued
[j
]) ? '1' : '0');
306 printf(" flags: (none)");
308 if (p
->flags
& RF_PSS_UNDER_RECON
)
309 printf(" under-recon");
310 if (p
->flags
& RF_PSS_FORCED_ON_WRITE
)
312 if (p
->flags
& RF_PSS_FORCED_ON_READ
)
314 if (p
->flags
& RF_PSS_RECON_BLOCKED
)
316 if (p
->flags
& RF_PSS_BUFFERWAIT
)
325 rf_PrintPSStatusTable(RF_Raid_t
*raidPtr
)
327 RF_PSStatusHeader_t
*pssTable
= raidPtr
->reconControl
->pssTable
;
328 RealPrintPSStatusTable(raidPtr
, pssTable
);