rf_driver.c revision 1.87 1 1.87 oster /* $NetBSD: rf_driver.c,v 1.87 2004/03/01 23:30:58 oster Exp $ */
2 1.9 oster /*-
3 1.9 oster * Copyright (c) 1999 The NetBSD Foundation, Inc.
4 1.9 oster * All rights reserved.
5 1.9 oster *
6 1.9 oster * This code is derived from software contributed to The NetBSD Foundation
7 1.9 oster * by Greg Oster
8 1.9 oster *
9 1.9 oster * Redistribution and use in source and binary forms, with or without
10 1.9 oster * modification, are permitted provided that the following conditions
11 1.9 oster * are met:
12 1.9 oster * 1. Redistributions of source code must retain the above copyright
13 1.9 oster * notice, this list of conditions and the following disclaimer.
14 1.9 oster * 2. Redistributions in binary form must reproduce the above copyright
15 1.9 oster * notice, this list of conditions and the following disclaimer in the
16 1.9 oster * documentation and/or other materials provided with the distribution.
17 1.9 oster * 3. All advertising materials mentioning features or use of this software
18 1.9 oster * must display the following acknowledgement:
19 1.9 oster * This product includes software developed by the NetBSD
20 1.9 oster * Foundation, Inc. and its contributors.
21 1.9 oster * 4. Neither the name of The NetBSD Foundation nor the names of its
22 1.9 oster * contributors may be used to endorse or promote products derived
23 1.9 oster * from this software without specific prior written permission.
24 1.9 oster *
25 1.9 oster * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
26 1.9 oster * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 1.9 oster * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 1.9 oster * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
29 1.9 oster * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 1.9 oster * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 1.9 oster * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 1.9 oster * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 1.9 oster * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 1.9 oster * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 1.9 oster * POSSIBILITY OF SUCH DAMAGE.
36 1.9 oster */
37 1.9 oster
38 1.1 oster /*
39 1.1 oster * Copyright (c) 1995 Carnegie-Mellon University.
40 1.1 oster * All rights reserved.
41 1.1 oster *
42 1.1 oster * Author: Mark Holland, Khalil Amiri, Claudson Bornstein, William V. Courtright II,
43 1.1 oster * Robby Findler, Daniel Stodolsky, Rachad Youssef, Jim Zelenka
44 1.1 oster *
45 1.1 oster * Permission to use, copy, modify and distribute this software and
46 1.1 oster * its documentation is hereby granted, provided that both the copyright
47 1.1 oster * notice and this permission notice appear in all copies of the
48 1.1 oster * software, derivative works or modified versions, and any portions
49 1.1 oster * thereof, and that both notices appear in supporting documentation.
50 1.1 oster *
51 1.1 oster * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
52 1.1 oster * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
53 1.1 oster * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
54 1.1 oster *
55 1.1 oster * Carnegie Mellon requests users of this software to return to
56 1.1 oster *
57 1.1 oster * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU
58 1.1 oster * School of Computer Science
59 1.1 oster * Carnegie Mellon University
60 1.1 oster * Pittsburgh PA 15213-3890
61 1.1 oster *
62 1.1 oster * any improvements or extensions that they make and grant Carnegie the
63 1.1 oster * rights to redistribute these changes.
64 1.1 oster */
65 1.1 oster
66 1.1 oster /******************************************************************************
67 1.1 oster *
68 1.1 oster * rf_driver.c -- main setup, teardown, and access routines for the RAID driver
69 1.1 oster *
70 1.1 oster * all routines are prefixed with rf_ (raidframe), to avoid conficts.
71 1.1 oster *
72 1.1 oster ******************************************************************************/
73 1.1 oster
74 1.44 lukem
75 1.44 lukem #include <sys/cdefs.h>
76 1.87 oster __KERNEL_RCSID(0, "$NetBSD: rf_driver.c,v 1.87 2004/03/01 23:30:58 oster Exp $");
77 1.71 martin
78 1.71 martin #include "opt_raid_diagnostic.h"
79 1.1 oster
80 1.1 oster #include <sys/param.h>
81 1.1 oster #include <sys/systm.h>
82 1.1 oster #include <sys/ioctl.h>
83 1.1 oster #include <sys/fcntl.h>
84 1.1 oster #include <sys/vnode.h>
85 1.1 oster
86 1.1 oster
87 1.1 oster #include "rf_archs.h"
88 1.1 oster #include "rf_threadstuff.h"
89 1.1 oster
90 1.1 oster #include <sys/errno.h>
91 1.1 oster
92 1.1 oster #include "rf_raid.h"
93 1.1 oster #include "rf_dag.h"
94 1.1 oster #include "rf_aselect.h"
95 1.1 oster #include "rf_diskqueue.h"
96 1.1 oster #include "rf_parityscan.h"
97 1.1 oster #include "rf_alloclist.h"
98 1.1 oster #include "rf_dagutils.h"
99 1.1 oster #include "rf_utils.h"
100 1.1 oster #include "rf_etimer.h"
101 1.1 oster #include "rf_acctrace.h"
102 1.1 oster #include "rf_general.h"
103 1.1 oster #include "rf_desc.h"
104 1.1 oster #include "rf_states.h"
105 1.1 oster #include "rf_decluster.h"
106 1.1 oster #include "rf_map.h"
107 1.1 oster #include "rf_revent.h"
108 1.1 oster #include "rf_callback.h"
109 1.1 oster #include "rf_engine.h"
110 1.1 oster #include "rf_mcpair.h"
111 1.1 oster #include "rf_nwayxor.h"
112 1.1 oster #include "rf_copyback.h"
113 1.1 oster #include "rf_driver.h"
114 1.1 oster #include "rf_options.h"
115 1.1 oster #include "rf_shutdown.h"
116 1.24 oster #include "rf_kintf.h"
117 1.1 oster
118 1.1 oster #include <sys/buf.h>
119 1.1 oster
120 1.61 oster #ifndef RF_ACCESS_DEBUG
121 1.61 oster #define RF_ACCESS_DEBUG 0
122 1.61 oster #endif
123 1.61 oster
124 1.1 oster /* rad == RF_RaidAccessDesc_t */
125 1.73 oster RF_DECLARE_MUTEX(rf_rad_pool_lock)
126 1.73 oster static struct pool rf_rad_pool;
127 1.1 oster #define RF_MAX_FREE_RAD 128
128 1.1 oster #define RF_RAD_INC 16
129 1.1 oster #define RF_RAD_INITIAL 32
130 1.1 oster
131 1.1 oster /* debug variables */
132 1.6 oster char rf_panicbuf[2048]; /* a buffer to hold an error msg when we panic */
133 1.1 oster
134 1.1 oster /* main configuration routines */
135 1.1 oster static int raidframe_booted = 0;
136 1.1 oster
137 1.6 oster static void rf_ConfigureDebug(RF_Config_t * cfgPtr);
138 1.1 oster static void set_debug_option(char *name, long val);
139 1.1 oster static void rf_UnconfigureArray(void);
140 1.1 oster static void rf_ShutdownRDFreeList(void *);
141 1.1 oster static int rf_ConfigureRDFreeList(RF_ShutdownList_t **);
142 1.1 oster
143 1.6 oster RF_DECLARE_MUTEX(rf_printf_mutex) /* debug only: avoids interleaved
144 1.6 oster * printfs by different stripes */
145 1.1 oster
146 1.1 oster #define SIGNAL_QUIESCENT_COND(_raid_) wakeup(&((_raid_)->accesses_suspended))
147 1.1 oster #define WAIT_FOR_QUIESCENCE(_raid_) \
148 1.38 oster ltsleep(&((_raid_)->accesses_suspended), PRIBIO, \
149 1.38 oster "raidframe quiesce", 0, &((_raid_)->access_suspend_mutex))
150 1.1 oster
151 1.9 oster static int configureCount = 0; /* number of active configurations */
152 1.9 oster static int isconfigged = 0; /* is basic raidframe (non per-array)
153 1.9 oster * stuff configged */
154 1.55 oster RF_DECLARE_LKMGR_STATIC_MUTEX(configureMutex) /* used to lock the configuration
155 1.6 oster * stuff */
156 1.9 oster static RF_ShutdownList_t *globalShutdown; /* non array-specific
157 1.9 oster * stuff */
158 1.1 oster
159 1.9 oster static int rf_ConfigureRDFreeList(RF_ShutdownList_t ** listp);
160 1.1 oster
161 1.1 oster /* called at system boot time */
162 1.7 oster int
163 1.7 oster rf_BootRaidframe()
164 1.1 oster {
165 1.1 oster
166 1.6 oster if (raidframe_booted)
167 1.6 oster return (EBUSY);
168 1.6 oster raidframe_booted = 1;
169 1.79 oster lockinit(&configureMutex, PRIBIO, "RAIDframe lock", 0, 0);
170 1.79 oster configureCount = 0;
171 1.6 oster isconfigged = 0;
172 1.6 oster globalShutdown = NULL;
173 1.6 oster return (0);
174 1.1 oster }
175 1.1 oster
176 1.1 oster /*
177 1.1 oster * Called whenever an array is shutdown
178 1.1 oster */
179 1.6 oster static void
180 1.6 oster rf_UnconfigureArray()
181 1.1 oster {
182 1.6 oster int rc;
183 1.1 oster
184 1.55 oster RF_LOCK_LKMGR_MUTEX(configureMutex);
185 1.6 oster if (--configureCount == 0) { /* if no active configurations, shut
186 1.6 oster * everything down */
187 1.6 oster isconfigged = 0;
188 1.6 oster
189 1.6 oster rc = rf_ShutdownList(&globalShutdown);
190 1.6 oster if (rc) {
191 1.6 oster RF_ERRORMSG1("RAIDFRAME: unable to do global shutdown, rc=%d\n", rc);
192 1.6 oster }
193 1.6 oster
194 1.6 oster /*
195 1.6 oster * We must wait until now, because the AllocList module
196 1.6 oster * uses the DebugMem module.
197 1.6 oster */
198 1.60 oster #if RF_DEBUG_MEM
199 1.6 oster if (rf_memDebug)
200 1.6 oster rf_print_unfreed();
201 1.60 oster #endif
202 1.6 oster }
203 1.55 oster RF_UNLOCK_LKMGR_MUTEX(configureMutex);
204 1.9 oster }
205 1.9 oster
206 1.1 oster /*
207 1.1 oster * Called to shut down an array.
208 1.1 oster */
209 1.6 oster int
210 1.80 oster rf_Shutdown(RF_Raid_t *raidPtr)
211 1.1 oster {
212 1.6 oster if (!raidPtr->valid) {
213 1.6 oster RF_ERRORMSG("Attempt to shut down unconfigured RAIDframe driver. Aborting shutdown\n");
214 1.6 oster return (EINVAL);
215 1.6 oster }
216 1.6 oster /*
217 1.6 oster * wait for outstanding IOs to land
218 1.6 oster * As described in rf_raid.h, we use the rad_freelist lock
219 1.6 oster * to protect the per-array info about outstanding descs
220 1.6 oster * since we need to do freelist locking anyway, and this
221 1.6 oster * cuts down on the amount of serialization we've got going
222 1.6 oster * on.
223 1.6 oster */
224 1.73 oster RF_LOCK_MUTEX(rf_rad_pool_lock);
225 1.6 oster if (raidPtr->waitShutdown) {
226 1.73 oster RF_UNLOCK_MUTEX(rf_rad_pool_lock);
227 1.6 oster return (EBUSY);
228 1.6 oster }
229 1.6 oster raidPtr->waitShutdown = 1;
230 1.6 oster while (raidPtr->nAccOutstanding) {
231 1.73 oster RF_WAIT_COND(raidPtr->outstandingCond, rf_rad_pool_lock);
232 1.6 oster }
233 1.73 oster RF_UNLOCK_MUTEX(rf_rad_pool_lock);
234 1.35 oster
235 1.35 oster /* Wait for any parity re-writes to stop... */
236 1.35 oster while (raidPtr->parity_rewrite_in_progress) {
237 1.35 oster printf("Waiting for parity re-write to exit...\n");
238 1.35 oster tsleep(&raidPtr->parity_rewrite_in_progress, PRIBIO,
239 1.35 oster "rfprwshutdown", 0);
240 1.35 oster }
241 1.6 oster
242 1.6 oster raidPtr->valid = 0;
243 1.6 oster
244 1.37 oster rf_update_component_labels(raidPtr, RF_FINAL_COMPONENT_UPDATE);
245 1.6 oster
246 1.7 oster rf_UnconfigureVnodes(raidPtr);
247 1.7 oster
248 1.7 oster rf_ShutdownList(&raidPtr->shutdownList);
249 1.7 oster
250 1.7 oster rf_UnconfigureArray();
251 1.7 oster
252 1.7 oster return (0);
253 1.7 oster }
254 1.1 oster
255 1.6 oster
256 1.1 oster #define DO_INIT_CONFIGURE(f) { \
257 1.1 oster rc = f (&globalShutdown); \
258 1.1 oster if (rc) { \
259 1.1 oster RF_ERRORMSG2("RAIDFRAME: failed %s with %d\n", RF_STRING(f), rc); \
260 1.1 oster rf_ShutdownList(&globalShutdown); \
261 1.1 oster configureCount--; \
262 1.55 oster RF_UNLOCK_LKMGR_MUTEX(configureMutex); \
263 1.1 oster return(rc); \
264 1.1 oster } \
265 1.1 oster }
266 1.1 oster
267 1.1 oster #define DO_RAID_FAIL() { \
268 1.12 oster rf_UnconfigureVnodes(raidPtr); \
269 1.1 oster rf_ShutdownList(&raidPtr->shutdownList); \
270 1.1 oster rf_UnconfigureArray(); \
271 1.1 oster }
272 1.1 oster
273 1.1 oster #define DO_RAID_INIT_CONFIGURE(f) { \
274 1.1 oster rc = f (&raidPtr->shutdownList, raidPtr, cfgPtr); \
275 1.1 oster if (rc) { \
276 1.1 oster RF_ERRORMSG2("RAIDFRAME: failed %s with %d\n", RF_STRING(f), rc); \
277 1.1 oster DO_RAID_FAIL(); \
278 1.1 oster return(rc); \
279 1.1 oster } \
280 1.1 oster }
281 1.1 oster
282 1.1 oster #define DO_RAID_MUTEX(_m_) { \
283 1.75 oster rf_mutex_init((_m_)); \
284 1.1 oster }
285 1.1 oster
286 1.6 oster int
287 1.80 oster rf_Configure(RF_Raid_t *raidPtr, RF_Config_t *cfgPtr, RF_AutoConfig_t *ac)
288 1.6 oster {
289 1.72 oster RF_RowCol_t col;
290 1.85 oster int rc;
291 1.6 oster
292 1.55 oster RF_LOCK_LKMGR_MUTEX(configureMutex);
293 1.6 oster configureCount++;
294 1.6 oster if (isconfigged == 0) {
295 1.75 oster rf_mutex_init(&rf_printf_mutex);
296 1.75 oster
297 1.6 oster /* initialize globals */
298 1.6 oster
299 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureAllocList);
300 1.28 oster
301 1.6 oster /*
302 1.28 oster * Yes, this does make debugging general to the whole
303 1.28 oster * system instead of being array specific. Bummer, drag.
304 1.28 oster */
305 1.6 oster rf_ConfigureDebug(cfgPtr);
306 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureDebugMem);
307 1.87 oster #if RF_ACC_TRACE > 0
308 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureAccessTrace);
309 1.87 oster #endif
310 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureMapModule);
311 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureReconEvent);
312 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureCallback);
313 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureRDFreeList);
314 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureNWayXor);
315 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureStripeLockFreeList);
316 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureMCPair);
317 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureDAGs);
318 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureDAGFuncs);
319 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureReconstruction);
320 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureCopyback);
321 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureDiskQueueSystem);
322 1.6 oster isconfigged = 1;
323 1.6 oster }
324 1.55 oster RF_UNLOCK_LKMGR_MUTEX(configureMutex);
325 1.6 oster
326 1.6 oster DO_RAID_MUTEX(&raidPtr->mutex);
327 1.6 oster /* set up the cleanup list. Do this after ConfigureDebug so that
328 1.6 oster * value of memDebug will be set */
329 1.6 oster
330 1.6 oster rf_MakeAllocList(raidPtr->cleanupList);
331 1.6 oster if (raidPtr->cleanupList == NULL) {
332 1.6 oster DO_RAID_FAIL();
333 1.6 oster return (ENOMEM);
334 1.6 oster }
335 1.86 oster rf_ShutdownCreate(&raidPtr->shutdownList,
336 1.86 oster (void (*) (void *)) rf_FreeAllocList,
337 1.86 oster raidPtr->cleanupList);
338 1.86 oster
339 1.6 oster raidPtr->numCol = cfgPtr->numCol;
340 1.6 oster raidPtr->numSpare = cfgPtr->numSpare;
341 1.6 oster
342 1.72 oster raidPtr->status = rf_rs_optimal;
343 1.72 oster raidPtr->reconControl = NULL;
344 1.72 oster
345 1.64 oster TAILQ_INIT(&(raidPtr->iodone));
346 1.64 oster simple_lock_init(&(raidPtr->iodone_lock));
347 1.6 oster
348 1.6 oster DO_RAID_INIT_CONFIGURE(rf_ConfigureEngine);
349 1.6 oster DO_RAID_INIT_CONFIGURE(rf_ConfigureStripeLocks);
350 1.6 oster
351 1.76 oster raidPtr->outstandingCond = 0;
352 1.6 oster
353 1.6 oster raidPtr->nAccOutstanding = 0;
354 1.6 oster raidPtr->waitShutdown = 0;
355 1.6 oster
356 1.6 oster DO_RAID_MUTEX(&raidPtr->access_suspend_mutex);
357 1.6 oster
358 1.76 oster raidPtr->waitForReconCond = 0;
359 1.6 oster
360 1.28 oster if (ac!=NULL) {
361 1.28 oster /* We have an AutoConfig structure.. Don't do the
362 1.28 oster normal disk configuration... call the auto config
363 1.28 oster stuff */
364 1.28 oster rf_AutoConfigureDisks(raidPtr, cfgPtr, ac);
365 1.28 oster } else {
366 1.28 oster DO_RAID_INIT_CONFIGURE(rf_ConfigureDisks);
367 1.28 oster DO_RAID_INIT_CONFIGURE(rf_ConfigureSpareDisks);
368 1.28 oster }
369 1.6 oster /* do this after ConfigureDisks & ConfigureSpareDisks to be sure dev
370 1.6 oster * no. is set */
371 1.6 oster DO_RAID_INIT_CONFIGURE(rf_ConfigureDiskQueues);
372 1.6 oster
373 1.6 oster DO_RAID_INIT_CONFIGURE(rf_ConfigureLayout);
374 1.6 oster
375 1.6 oster DO_RAID_INIT_CONFIGURE(rf_ConfigurePSStatus);
376 1.6 oster
377 1.82 oster #if RF_INCLUDE_CHAINDECLUSTER > 0
378 1.72 oster for (col = 0; col < raidPtr->numCol; col++) {
379 1.72 oster /*
380 1.72 oster * XXX better distribution
381 1.72 oster */
382 1.72 oster raidPtr->hist_diskreq[col] = 0;
383 1.6 oster }
384 1.82 oster #endif
385 1.30 oster raidPtr->numNewFailures = 0;
386 1.28 oster raidPtr->copyback_in_progress = 0;
387 1.28 oster raidPtr->parity_rewrite_in_progress = 0;
388 1.66 oster raidPtr->adding_hot_spare = 0;
389 1.28 oster raidPtr->recon_in_progress = 0;
390 1.29 oster raidPtr->maxOutstanding = cfgPtr->maxOutstandingDiskReqs;
391 1.29 oster
392 1.29 oster /* autoconfigure and root_partition will actually get filled in
393 1.29 oster after the config is done */
394 1.29 oster raidPtr->autoconfigure = 0;
395 1.29 oster raidPtr->root_partition = 0;
396 1.29 oster raidPtr->last_unit = raidPtr->raidid;
397 1.29 oster raidPtr->config_order = 0;
398 1.6 oster
399 1.6 oster if (rf_keepAccTotals) {
400 1.6 oster raidPtr->keep_acc_totals = 1;
401 1.6 oster }
402 1.6 oster rf_StartUserStats(raidPtr);
403 1.1 oster
404 1.6 oster raidPtr->valid = 1;
405 1.52 oster
406 1.52 oster printf("raid%d: %s\n", raidPtr->raidid,
407 1.52 oster raidPtr->Layout.map->configName);
408 1.52 oster printf("raid%d: Components:", raidPtr->raidid);
409 1.72 oster
410 1.72 oster for (col = 0; col < raidPtr->numCol; col++) {
411 1.72 oster printf(" %s", raidPtr->Disks[col].devname);
412 1.72 oster if (RF_DEAD_DISK(raidPtr->Disks[col].status)) {
413 1.72 oster printf("[**FAILED**]");
414 1.52 oster }
415 1.52 oster }
416 1.52 oster printf("\n");
417 1.52 oster printf("raid%d: Total Sectors: %lu (%lu MB)\n",
418 1.52 oster raidPtr->raidid,
419 1.52 oster (unsigned long) raidPtr->totalSectors,
420 1.52 oster (unsigned long) (raidPtr->totalSectors / 1024 *
421 1.52 oster (1 << raidPtr->logBytesPerSector) / 1024));
422 1.50 oster
423 1.6 oster return (0);
424 1.1 oster }
425 1.1 oster
426 1.6 oster static void
427 1.80 oster rf_ShutdownRDFreeList(void *ignored)
428 1.1 oster {
429 1.73 oster pool_destroy(&rf_rad_pool);
430 1.1 oster }
431 1.1 oster
432 1.6 oster static int
433 1.80 oster rf_ConfigureRDFreeList(RF_ShutdownList_t **listp)
434 1.1 oster {
435 1.1 oster
436 1.73 oster pool_init(&rf_rad_pool, sizeof(RF_RaidAccessDesc_t), 0, 0, 0,
437 1.73 oster "rf_rad_pl", NULL);
438 1.73 oster pool_sethiwat(&rf_rad_pool, RF_MAX_FREE_RAD);
439 1.73 oster pool_prime(&rf_rad_pool, RF_RAD_INITIAL);
440 1.86 oster rf_ShutdownCreate(listp, rf_ShutdownRDFreeList, NULL);
441 1.84 oster simple_lock_init(&rf_rad_pool_lock);
442 1.6 oster return (0);
443 1.6 oster }
444 1.6 oster
445 1.6 oster RF_RaidAccessDesc_t *
446 1.80 oster rf_AllocRaidAccDesc(RF_Raid_t *raidPtr, RF_IoType_t type,
447 1.80 oster RF_RaidAddr_t raidAddress, RF_SectorCount_t numBlocks,
448 1.80 oster caddr_t bufPtr, void *bp, RF_RaidAccessFlags_t flags,
449 1.80 oster RF_AccessState_t *states)
450 1.6 oster {
451 1.6 oster RF_RaidAccessDesc_t *desc;
452 1.6 oster
453 1.73 oster desc = pool_get(&rf_rad_pool, PR_WAITOK);
454 1.74 oster simple_lock_init(&desc->mutex);
455 1.73 oster
456 1.83 oster RF_LOCK_MUTEX(rf_rad_pool_lock);
457 1.6 oster if (raidPtr->waitShutdown) {
458 1.6 oster /*
459 1.6 oster * Actually, we're shutting the array down. Free the desc
460 1.6 oster * and return NULL.
461 1.6 oster */
462 1.73 oster
463 1.73 oster RF_UNLOCK_MUTEX(rf_rad_pool_lock);
464 1.73 oster pool_put(&rf_rad_pool, desc);
465 1.6 oster return (NULL);
466 1.6 oster }
467 1.6 oster raidPtr->nAccOutstanding++;
468 1.73 oster
469 1.73 oster RF_UNLOCK_MUTEX(rf_rad_pool_lock);
470 1.6 oster
471 1.6 oster desc->raidPtr = (void *) raidPtr;
472 1.6 oster desc->type = type;
473 1.6 oster desc->raidAddress = raidAddress;
474 1.6 oster desc->numBlocks = numBlocks;
475 1.6 oster desc->bufPtr = bufPtr;
476 1.6 oster desc->bp = bp;
477 1.41 oster desc->paramDAG = NULL;
478 1.41 oster desc->paramASM = NULL;
479 1.6 oster desc->flags = flags;
480 1.6 oster desc->states = states;
481 1.6 oster desc->state = 0;
482 1.6 oster
483 1.6 oster desc->status = 0;
484 1.87 oster #if RF_ACC_TRACE > 0
485 1.40 thorpej memset((char *) &desc->tracerec, 0, sizeof(RF_AccTraceEntry_t));
486 1.87 oster #endif
487 1.41 oster desc->callbackFunc = NULL;
488 1.41 oster desc->callbackArg = NULL;
489 1.6 oster desc->next = NULL;
490 1.6 oster desc->cleanupList = NULL;
491 1.6 oster rf_MakeAllocList(desc->cleanupList);
492 1.6 oster return (desc);
493 1.6 oster }
494 1.6 oster
495 1.6 oster void
496 1.80 oster rf_FreeRaidAccDesc(RF_RaidAccessDesc_t *desc)
497 1.6 oster {
498 1.6 oster RF_Raid_t *raidPtr = desc->raidPtr;
499 1.85 oster RF_DagList_t *dagList, *temp;
500 1.6 oster
501 1.6 oster RF_ASSERT(desc);
502 1.6 oster
503 1.85 oster /* Cleanup the dagList(s) */
504 1.85 oster dagList = desc->dagList;
505 1.85 oster while(dagList != NULL) {
506 1.85 oster temp = dagList;
507 1.85 oster dagList = dagList->next;
508 1.85 oster rf_FreeDAGList(temp);
509 1.85 oster }
510 1.85 oster
511 1.6 oster rf_FreeAllocList(desc->cleanupList);
512 1.73 oster pool_put(&rf_rad_pool, desc);
513 1.83 oster RF_LOCK_MUTEX(rf_rad_pool_lock);
514 1.6 oster raidPtr->nAccOutstanding--;
515 1.6 oster if (raidPtr->waitShutdown) {
516 1.6 oster RF_SIGNAL_COND(raidPtr->outstandingCond);
517 1.6 oster }
518 1.73 oster RF_UNLOCK_MUTEX(rf_rad_pool_lock);
519 1.1 oster }
520 1.1 oster /*********************************************************************
521 1.1 oster * Main routine for performing an access.
522 1.1 oster * Accesses are retried until a DAG can not be selected. This occurs
523 1.1 oster * when either the DAG library is incomplete or there are too many
524 1.1 oster * failures in a parity group.
525 1.80 oster *
526 1.80 oster * type should be read or write async_flag should be RF_TRUE or
527 1.80 oster * RF_FALSE bp_in is a buf pointer. void * to facilitate ignoring it
528 1.80 oster * outside the kernel
529 1.1 oster ********************************************************************/
530 1.6 oster int
531 1.80 oster rf_DoAccess(RF_Raid_t * raidPtr, RF_IoType_t type, int async_flag,
532 1.80 oster RF_RaidAddr_t raidAddress, RF_SectorCount_t numBlocks,
533 1.80 oster caddr_t bufPtr, void *bp_in, RF_RaidAccessFlags_t flags)
534 1.1 oster {
535 1.6 oster RF_RaidAccessDesc_t *desc;
536 1.6 oster caddr_t lbufPtr = bufPtr;
537 1.6 oster struct buf *bp = (struct buf *) bp_in;
538 1.6 oster
539 1.6 oster raidAddress += rf_raidSectorOffset;
540 1.6 oster
541 1.61 oster #if RF_ACCESS_DEBUG
542 1.6 oster if (rf_accessDebug) {
543 1.1 oster
544 1.6 oster printf("logBytes is: %d %d %d\n", raidPtr->raidid,
545 1.6 oster raidPtr->logBytesPerSector,
546 1.6 oster (int) rf_RaidAddressToByte(raidPtr, numBlocks));
547 1.22 oster printf("raid%d: %s raidAddr %d (stripeid %d-%d) numBlocks %d (%d bytes) buf 0x%lx\n", raidPtr->raidid,
548 1.6 oster (type == RF_IO_TYPE_READ) ? "READ" : "WRITE", (int) raidAddress,
549 1.6 oster (int) rf_RaidAddressToStripeID(&raidPtr->Layout, raidAddress),
550 1.6 oster (int) rf_RaidAddressToStripeID(&raidPtr->Layout, raidAddress + numBlocks - 1),
551 1.6 oster (int) numBlocks,
552 1.6 oster (int) rf_RaidAddressToByte(raidPtr, numBlocks),
553 1.6 oster (long) bufPtr);
554 1.6 oster }
555 1.61 oster #endif
556 1.6 oster if (raidAddress + numBlocks > raidPtr->totalSectors) {
557 1.1 oster
558 1.6 oster printf("DoAccess: raid addr %lu too large to access %lu sectors. Max legal addr is %lu\n",
559 1.6 oster (u_long) raidAddress, (u_long) numBlocks, (u_long) raidPtr->totalSectors);
560 1.1 oster
561 1.77 oster
562 1.77 oster bp->b_flags |= B_ERROR;
563 1.77 oster bp->b_resid = bp->b_bcount;
564 1.77 oster bp->b_error = ENOSPC;
565 1.77 oster biodone(bp);
566 1.16 oster return (ENOSPC);
567 1.6 oster }
568 1.6 oster desc = rf_AllocRaidAccDesc(raidPtr, type, raidAddress,
569 1.41 oster numBlocks, lbufPtr, bp, flags, raidPtr->Layout.map->states);
570 1.1 oster
571 1.6 oster if (desc == NULL) {
572 1.6 oster return (ENOMEM);
573 1.6 oster }
574 1.87 oster #if RF_ACC_TRACE > 0
575 1.6 oster RF_ETIMER_START(desc->tracerec.tot_timer);
576 1.87 oster #endif
577 1.6 oster desc->async_flag = async_flag;
578 1.3 explorer
579 1.6 oster rf_ContinueRaidAccess(desc);
580 1.1 oster
581 1.6 oster return (0);
582 1.1 oster }
583 1.46 oster #if 0
584 1.1 oster /* force the array into reconfigured mode without doing reconstruction */
585 1.6 oster int
586 1.80 oster rf_SetReconfiguredMode(RF_Raid_t *raidPtr, int col)
587 1.6 oster {
588 1.6 oster if (!(raidPtr->Layout.map->flags & RF_DISTRIBUTE_SPARE)) {
589 1.6 oster printf("Can't set reconfigured mode in dedicated-spare array\n");
590 1.6 oster RF_PANIC();
591 1.6 oster }
592 1.6 oster RF_LOCK_MUTEX(raidPtr->mutex);
593 1.6 oster raidPtr->numFailures++;
594 1.72 oster raidPtr->Disks[col].status = rf_ds_dist_spared;
595 1.72 oster raidPtr->status = rf_rs_reconfigured;
596 1.37 oster rf_update_component_labels(raidPtr, RF_NORMAL_COMPONENT_UPDATE);
597 1.6 oster /* install spare table only if declustering + distributed sparing
598 1.6 oster * architecture. */
599 1.6 oster if (raidPtr->Layout.map->flags & RF_BD_DECLUSTERED)
600 1.72 oster rf_InstallSpareTable(raidPtr, col);
601 1.6 oster RF_UNLOCK_MUTEX(raidPtr->mutex);
602 1.6 oster return (0);
603 1.1 oster }
604 1.46 oster #endif
605 1.1 oster
606 1.6 oster int
607 1.80 oster rf_FailDisk(RF_Raid_t *raidPtr, int fcol, int initRecon)
608 1.6 oster {
609 1.6 oster RF_LOCK_MUTEX(raidPtr->mutex);
610 1.72 oster if (raidPtr->Disks[fcol].status != rf_ds_failed) {
611 1.68 oster /* must be failing something that is valid, or else it's
612 1.68 oster already marked as failed (in which case we don't
613 1.68 oster want to mark it failed again!) */
614 1.68 oster raidPtr->numFailures++;
615 1.72 oster raidPtr->Disks[fcol].status = rf_ds_failed;
616 1.72 oster raidPtr->status = rf_rs_degraded;
617 1.68 oster }
618 1.65 oster RF_UNLOCK_MUTEX(raidPtr->mutex);
619 1.68 oster
620 1.37 oster rf_update_component_labels(raidPtr, RF_NORMAL_COMPONENT_UPDATE);
621 1.68 oster
622 1.56 oster /* Close the component, so that it's not "locked" if someone
623 1.56 oster else want's to use it! */
624 1.56 oster
625 1.72 oster rf_close_component(raidPtr, raidPtr->raid_cinfo[fcol].ci_vp,
626 1.72 oster raidPtr->Disks[fcol].auto_configured);
627 1.65 oster
628 1.65 oster RF_LOCK_MUTEX(raidPtr->mutex);
629 1.72 oster raidPtr->raid_cinfo[fcol].ci_vp = NULL;
630 1.56 oster
631 1.56 oster /* Need to mark the component as not being auto_configured
632 1.56 oster (in case it was previously). */
633 1.56 oster
634 1.72 oster raidPtr->Disks[fcol].auto_configured = 0;
635 1.65 oster RF_UNLOCK_MUTEX(raidPtr->mutex);
636 1.56 oster
637 1.6 oster if (initRecon)
638 1.72 oster rf_ReconstructFailedDisk(raidPtr, fcol);
639 1.6 oster return (0);
640 1.1 oster }
641 1.1 oster /* releases a thread that is waiting for the array to become quiesced.
642 1.1 oster * access_suspend_mutex should be locked upon calling this
643 1.1 oster */
644 1.6 oster void
645 1.80 oster rf_SignalQuiescenceLock(RF_Raid_t *raidPtr)
646 1.6 oster {
647 1.61 oster #if RF_DEBUG_QUIESCE
648 1.6 oster if (rf_quiesceDebug) {
649 1.22 oster printf("raid%d: Signalling quiescence lock\n",
650 1.22 oster raidPtr->raidid);
651 1.6 oster }
652 1.61 oster #endif
653 1.6 oster raidPtr->access_suspend_release = 1;
654 1.6 oster
655 1.6 oster if (raidPtr->waiting_for_quiescence) {
656 1.6 oster SIGNAL_QUIESCENT_COND(raidPtr);
657 1.6 oster }
658 1.1 oster }
659 1.1 oster /* suspends all new requests to the array. No effect on accesses that are in flight. */
660 1.6 oster int
661 1.80 oster rf_SuspendNewRequestsAndWait(RF_Raid_t *raidPtr)
662 1.6 oster {
663 1.61 oster #if RF_DEBUG_QUIESCE
664 1.6 oster if (rf_quiesceDebug)
665 1.53 oster printf("raid%d: Suspending new reqs\n", raidPtr->raidid);
666 1.61 oster #endif
667 1.6 oster RF_LOCK_MUTEX(raidPtr->access_suspend_mutex);
668 1.6 oster raidPtr->accesses_suspended++;
669 1.6 oster raidPtr->waiting_for_quiescence = (raidPtr->accs_in_flight == 0) ? 0 : 1;
670 1.6 oster
671 1.6 oster if (raidPtr->waiting_for_quiescence) {
672 1.6 oster raidPtr->access_suspend_release = 0;
673 1.6 oster while (!raidPtr->access_suspend_release) {
674 1.53 oster printf("raid%d: Suspending: Waiting for Quiescence\n",
675 1.53 oster raidPtr->raidid);
676 1.6 oster WAIT_FOR_QUIESCENCE(raidPtr);
677 1.6 oster raidPtr->waiting_for_quiescence = 0;
678 1.6 oster }
679 1.6 oster }
680 1.53 oster printf("raid%d: Quiescence reached..\n", raidPtr->raidid);
681 1.1 oster
682 1.6 oster RF_UNLOCK_MUTEX(raidPtr->access_suspend_mutex);
683 1.6 oster return (raidPtr->waiting_for_quiescence);
684 1.1 oster }
685 1.1 oster /* wake up everyone waiting for quiescence to be released */
686 1.6 oster void
687 1.80 oster rf_ResumeNewRequests(RF_Raid_t *raidPtr)
688 1.6 oster {
689 1.6 oster RF_CallbackDesc_t *t, *cb;
690 1.6 oster
691 1.61 oster #if RF_DEBUG_QUIESCE
692 1.6 oster if (rf_quiesceDebug)
693 1.6 oster printf("Resuming new reqs\n");
694 1.61 oster #endif
695 1.6 oster
696 1.6 oster RF_LOCK_MUTEX(raidPtr->access_suspend_mutex);
697 1.6 oster raidPtr->accesses_suspended--;
698 1.6 oster if (raidPtr->accesses_suspended == 0)
699 1.6 oster cb = raidPtr->quiesce_wait_list;
700 1.6 oster else
701 1.6 oster cb = NULL;
702 1.6 oster raidPtr->quiesce_wait_list = NULL;
703 1.6 oster RF_UNLOCK_MUTEX(raidPtr->access_suspend_mutex);
704 1.6 oster
705 1.6 oster while (cb) {
706 1.6 oster t = cb;
707 1.6 oster cb = cb->next;
708 1.6 oster (t->callbackFunc) (t->callbackArg);
709 1.6 oster rf_FreeCallbackDesc(t);
710 1.6 oster }
711 1.1 oster }
712 1.1 oster /*****************************************************************************************
713 1.1 oster *
714 1.1 oster * debug routines
715 1.1 oster *
716 1.1 oster ****************************************************************************************/
717 1.1 oster
718 1.6 oster static void
719 1.80 oster set_debug_option(char *name, long val)
720 1.6 oster {
721 1.6 oster RF_DebugName_t *p;
722 1.6 oster
723 1.6 oster for (p = rf_debugNames; p->name; p++) {
724 1.6 oster if (!strcmp(p->name, name)) {
725 1.6 oster *(p->ptr) = val;
726 1.6 oster printf("[Set debug variable %s to %ld]\n", name, val);
727 1.6 oster return;
728 1.6 oster }
729 1.6 oster }
730 1.6 oster RF_ERRORMSG1("Unknown debug string \"%s\"\n", name);
731 1.1 oster }
732 1.1 oster
733 1.1 oster
734 1.1 oster /* would like to use sscanf here, but apparently not available in kernel */
735 1.1 oster /*ARGSUSED*/
736 1.6 oster static void
737 1.80 oster rf_ConfigureDebug(RF_Config_t *cfgPtr)
738 1.6 oster {
739 1.6 oster char *val_p, *name_p, *white_p;
740 1.6 oster long val;
741 1.6 oster int i;
742 1.6 oster
743 1.6 oster rf_ResetDebugOptions();
744 1.6 oster for (i = 0; cfgPtr->debugVars[i][0] && i < RF_MAXDBGV; i++) {
745 1.6 oster name_p = rf_find_non_white(&cfgPtr->debugVars[i][0]);
746 1.6 oster white_p = rf_find_white(name_p); /* skip to start of 2nd
747 1.6 oster * word */
748 1.6 oster val_p = rf_find_non_white(white_p);
749 1.6 oster if (*val_p == '0' && *(val_p + 1) == 'x')
750 1.6 oster val = rf_htoi(val_p + 2);
751 1.6 oster else
752 1.6 oster val = rf_atoi(val_p);
753 1.6 oster *white_p = '\0';
754 1.6 oster set_debug_option(name_p, val);
755 1.6 oster }
756 1.1 oster }
757 1.1 oster /* performance monitoring stuff */
758 1.1 oster
759 1.1 oster #define TIMEVAL_TO_US(t) (((long) t.tv_sec) * 1000000L + (long) t.tv_usec)
760 1.1 oster
761 1.4 oster #if !defined(_KERNEL) && !defined(SIMULATE)
762 1.1 oster
763 1.1 oster /*
764 1.1 oster * Throughput stats currently only used in user-level RAIDframe
765 1.1 oster */
766 1.1 oster
767 1.6 oster static int
768 1.80 oster rf_InitThroughputStats(RF_ShutdownList_t **listp, RF_Raid_t *raidPtr,
769 1.80 oster RF_Config_t *cfgPtr)
770 1.1 oster {
771 1.6 oster int rc;
772 1.1 oster
773 1.6 oster /* these used by user-level raidframe only */
774 1.75 oster rf_mutex_init(&raidPtr->throughputstats.mutex);
775 1.6 oster raidPtr->throughputstats.sum_io_us = 0;
776 1.6 oster raidPtr->throughputstats.num_ios = 0;
777 1.6 oster raidPtr->throughputstats.num_out_ios = 0;
778 1.6 oster return (0);
779 1.6 oster }
780 1.6 oster
781 1.6 oster void
782 1.80 oster rf_StartThroughputStats(RF_Raid_t *raidPtr)
783 1.6 oster {
784 1.6 oster RF_LOCK_MUTEX(raidPtr->throughputstats.mutex);
785 1.6 oster raidPtr->throughputstats.num_ios++;
786 1.6 oster raidPtr->throughputstats.num_out_ios++;
787 1.6 oster if (raidPtr->throughputstats.num_out_ios == 1)
788 1.6 oster RF_GETTIME(raidPtr->throughputstats.start);
789 1.6 oster RF_UNLOCK_MUTEX(raidPtr->throughputstats.mutex);
790 1.6 oster }
791 1.6 oster
792 1.6 oster static void
793 1.80 oster rf_StopThroughputStats(RF_Raid_t *raidPtr)
794 1.6 oster {
795 1.6 oster struct timeval diff;
796 1.6 oster
797 1.6 oster RF_LOCK_MUTEX(raidPtr->throughputstats.mutex);
798 1.6 oster raidPtr->throughputstats.num_out_ios--;
799 1.6 oster if (raidPtr->throughputstats.num_out_ios == 0) {
800 1.6 oster RF_GETTIME(raidPtr->throughputstats.stop);
801 1.6 oster RF_TIMEVAL_DIFF(&raidPtr->throughputstats.start, &raidPtr->throughputstats.stop, &diff);
802 1.6 oster raidPtr->throughputstats.sum_io_us += TIMEVAL_TO_US(diff);
803 1.6 oster }
804 1.6 oster RF_UNLOCK_MUTEX(raidPtr->throughputstats.mutex);
805 1.1 oster }
806 1.1 oster
807 1.6 oster static void
808 1.80 oster rf_PrintThroughputStats(RF_Raid_t *raidPtr)
809 1.1 oster {
810 1.6 oster RF_ASSERT(raidPtr->throughputstats.num_out_ios == 0);
811 1.6 oster if (raidPtr->throughputstats.sum_io_us != 0) {
812 1.6 oster printf("[Througphut: %8.2f IOs/second]\n", raidPtr->throughputstats.num_ios
813 1.6 oster / (raidPtr->throughputstats.sum_io_us / 1000000.0));
814 1.6 oster }
815 1.1 oster }
816 1.6 oster #endif /* !KERNEL && !SIMULATE */
817 1.1 oster
818 1.6 oster void
819 1.80 oster rf_StartUserStats(RF_Raid_t *raidPtr)
820 1.1 oster {
821 1.6 oster RF_GETTIME(raidPtr->userstats.start);
822 1.6 oster raidPtr->userstats.sum_io_us = 0;
823 1.6 oster raidPtr->userstats.num_ios = 0;
824 1.6 oster raidPtr->userstats.num_sect_moved = 0;
825 1.1 oster }
826 1.1 oster
827 1.6 oster void
828 1.80 oster rf_StopUserStats(RF_Raid_t *raidPtr)
829 1.1 oster {
830 1.6 oster RF_GETTIME(raidPtr->userstats.stop);
831 1.1 oster }
832 1.1 oster
833 1.80 oster /* rt: resp time in us
834 1.80 oster numsect: number of sectors for this access */
835 1.6 oster void
836 1.80 oster rf_UpdateUserStats(RF_Raid_t *raidPtr, int rt, int numsect)
837 1.1 oster {
838 1.6 oster raidPtr->userstats.sum_io_us += rt;
839 1.6 oster raidPtr->userstats.num_ios++;
840 1.6 oster raidPtr->userstats.num_sect_moved += numsect;
841 1.1 oster }
842 1.1 oster
843 1.6 oster void
844 1.80 oster rf_PrintUserStats(RF_Raid_t *raidPtr)
845 1.1 oster {
846 1.6 oster long elapsed_us, mbs, mbs_frac;
847 1.6 oster struct timeval diff;
848 1.1 oster
849 1.69 oster RF_TIMEVAL_DIFF(&raidPtr->userstats.start,
850 1.69 oster &raidPtr->userstats.stop, &diff);
851 1.6 oster elapsed_us = TIMEVAL_TO_US(diff);
852 1.1 oster
853 1.6 oster /* 2000 sectors per megabyte, 10000000 microseconds per second */
854 1.6 oster if (elapsed_us)
855 1.69 oster mbs = (raidPtr->userstats.num_sect_moved / 2000) /
856 1.69 oster (elapsed_us / 1000000);
857 1.6 oster else
858 1.6 oster mbs = 0;
859 1.1 oster
860 1.6 oster /* this computes only the first digit of the fractional mb/s moved */
861 1.6 oster if (elapsed_us) {
862 1.69 oster mbs_frac = ((raidPtr->userstats.num_sect_moved / 200) /
863 1.69 oster (elapsed_us / 1000000)) - (mbs * 10);
864 1.6 oster } else {
865 1.6 oster mbs_frac = 0;
866 1.6 oster }
867 1.1 oster
868 1.69 oster printf("raid%d: Number of I/Os: %ld\n",
869 1.69 oster raidPtr->raidid, raidPtr->userstats.num_ios);
870 1.69 oster printf("raid%d: Elapsed time (us): %ld\n",
871 1.69 oster raidPtr->raidid, elapsed_us);
872 1.69 oster printf("raid%d: User I/Os per second: %ld\n",
873 1.69 oster raidPtr->raidid, RF_DB0_CHECK(raidPtr->userstats.num_ios,
874 1.69 oster (elapsed_us / 1000000)));
875 1.69 oster printf("raid%d: Average user response time: %ld us\n",
876 1.69 oster raidPtr->raidid, RF_DB0_CHECK(raidPtr->userstats.sum_io_us,
877 1.69 oster raidPtr->userstats.num_ios));
878 1.69 oster printf("raid%d: Total sectors moved: %ld\n",
879 1.69 oster raidPtr->raidid, raidPtr->userstats.num_sect_moved);
880 1.69 oster printf("raid%d: Average access size (sect): %ld\n",
881 1.69 oster raidPtr->raidid, RF_DB0_CHECK(raidPtr->userstats.num_sect_moved,
882 1.69 oster raidPtr->userstats.num_ios));
883 1.69 oster printf("raid%d: Achieved data rate: %ld.%ld MB/sec\n",
884 1.69 oster raidPtr->raidid, mbs, mbs_frac);
885 1.39 oster }
886 1.39 oster
887 1.39 oster
888 1.39 oster void
889 1.80 oster rf_print_panic_message(int line, char *file)
890 1.39 oster {
891 1.39 oster sprintf(rf_panicbuf,"raidframe error at line %d file %s",
892 1.39 oster line, file);
893 1.39 oster }
894 1.39 oster
895 1.62 oster #ifdef RAID_DIAGNOSTIC
896 1.39 oster void
897 1.80 oster rf_print_assert_panic_message(int line, char *file, char *condition)
898 1.39 oster {
899 1.39 oster sprintf(rf_panicbuf,
900 1.39 oster "raidframe error at line %d file %s (failed asserting %s)\n",
901 1.39 oster line, file, condition);
902 1.58 oster }
903 1.62 oster #endif
904 1.58 oster
905 1.58 oster void
906 1.80 oster rf_print_unable_to_init_mutex(char *file, int line, int rc)
907 1.58 oster {
908 1.58 oster RF_ERRORMSG3("Unable to init mutex file %s line %d rc=%d\n",
909 1.58 oster file, line, rc);
910 1.58 oster }
911 1.58 oster
912 1.58 oster void
913 1.80 oster rf_print_unable_to_add_shutdown(char *file, int line, int rc)
914 1.58 oster {
915 1.58 oster RF_ERRORMSG3("Unable to add to shutdown list file %s line %d rc=%d\n",
916 1.58 oster file, line, rc);
917 1.1 oster }
918