rf_driver.c revision 1.68 1 1.68 oster /* $NetBSD: rf_driver.c,v 1.68 2002/11/14 03:04:20 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.68 oster __KERNEL_RCSID(0, "$NetBSD: rf_driver.c,v 1.68 2002/11/14 03:04:20 oster Exp $");
77 1.1 oster
78 1.1 oster #include <sys/param.h>
79 1.1 oster #include <sys/systm.h>
80 1.1 oster #include <sys/ioctl.h>
81 1.1 oster #include <sys/fcntl.h>
82 1.1 oster #include <sys/vnode.h>
83 1.1 oster
84 1.1 oster
85 1.1 oster #include "rf_archs.h"
86 1.1 oster #include "rf_threadstuff.h"
87 1.1 oster
88 1.1 oster #include <sys/errno.h>
89 1.1 oster
90 1.1 oster #include "rf_raid.h"
91 1.1 oster #include "rf_dag.h"
92 1.1 oster #include "rf_aselect.h"
93 1.1 oster #include "rf_diskqueue.h"
94 1.1 oster #include "rf_parityscan.h"
95 1.1 oster #include "rf_alloclist.h"
96 1.1 oster #include "rf_dagutils.h"
97 1.1 oster #include "rf_utils.h"
98 1.1 oster #include "rf_etimer.h"
99 1.1 oster #include "rf_acctrace.h"
100 1.1 oster #include "rf_general.h"
101 1.1 oster #include "rf_desc.h"
102 1.1 oster #include "rf_states.h"
103 1.1 oster #include "rf_freelist.h"
104 1.1 oster #include "rf_decluster.h"
105 1.1 oster #include "rf_map.h"
106 1.1 oster #include "rf_revent.h"
107 1.1 oster #include "rf_callback.h"
108 1.1 oster #include "rf_engine.h"
109 1.1 oster #include "rf_mcpair.h"
110 1.1 oster #include "rf_nwayxor.h"
111 1.1 oster #include "rf_copyback.h"
112 1.1 oster #include "rf_driver.h"
113 1.1 oster #include "rf_options.h"
114 1.1 oster #include "rf_shutdown.h"
115 1.24 oster #include "rf_kintf.h"
116 1.1 oster
117 1.1 oster #include <sys/buf.h>
118 1.1 oster
119 1.61 oster #ifndef RF_ACCESS_DEBUG
120 1.61 oster #define RF_ACCESS_DEBUG 0
121 1.61 oster #endif
122 1.61 oster
123 1.1 oster /* rad == RF_RaidAccessDesc_t */
124 1.1 oster static RF_FreeList_t *rf_rad_freelist;
125 1.1 oster #define RF_MAX_FREE_RAD 128
126 1.1 oster #define RF_RAD_INC 16
127 1.1 oster #define RF_RAD_INITIAL 32
128 1.1 oster
129 1.1 oster /* debug variables */
130 1.6 oster char rf_panicbuf[2048]; /* a buffer to hold an error msg when we panic */
131 1.1 oster
132 1.1 oster /* main configuration routines */
133 1.1 oster static int raidframe_booted = 0;
134 1.1 oster
135 1.6 oster static void rf_ConfigureDebug(RF_Config_t * cfgPtr);
136 1.1 oster static void set_debug_option(char *name, long val);
137 1.1 oster static void rf_UnconfigureArray(void);
138 1.1 oster static int init_rad(RF_RaidAccessDesc_t *);
139 1.1 oster static void clean_rad(RF_RaidAccessDesc_t *);
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.20 oster #define IO_BUF_ERR(bp, err) { \
152 1.1 oster bp->b_flags |= B_ERROR; \
153 1.1 oster bp->b_resid = bp->b_bcount; \
154 1.1 oster bp->b_error = err; \
155 1.1 oster biodone(bp); \
156 1.1 oster }
157 1.1 oster
158 1.9 oster static int configureCount = 0; /* number of active configurations */
159 1.9 oster static int isconfigged = 0; /* is basic raidframe (non per-array)
160 1.9 oster * stuff configged */
161 1.55 oster RF_DECLARE_LKMGR_STATIC_MUTEX(configureMutex) /* used to lock the configuration
162 1.6 oster * stuff */
163 1.9 oster static RF_ShutdownList_t *globalShutdown; /* non array-specific
164 1.9 oster * stuff */
165 1.1 oster
166 1.9 oster static int rf_ConfigureRDFreeList(RF_ShutdownList_t ** listp);
167 1.1 oster
168 1.1 oster /* called at system boot time */
169 1.7 oster int
170 1.7 oster rf_BootRaidframe()
171 1.1 oster {
172 1.6 oster int rc;
173 1.1 oster
174 1.6 oster if (raidframe_booted)
175 1.6 oster return (EBUSY);
176 1.6 oster raidframe_booted = 1;
177 1.1 oster
178 1.55 oster rc = rf_lkmgr_mutex_init(&configureMutex);
179 1.6 oster if (rc) {
180 1.58 oster rf_print_unable_to_init_mutex( __FILE__, __LINE__, rc);
181 1.6 oster RF_PANIC();
182 1.6 oster }
183 1.6 oster configureCount = 0;
184 1.6 oster isconfigged = 0;
185 1.6 oster globalShutdown = NULL;
186 1.6 oster return (0);
187 1.1 oster }
188 1.1 oster
189 1.1 oster /*
190 1.1 oster * Called whenever an array is shutdown
191 1.1 oster */
192 1.6 oster static void
193 1.6 oster rf_UnconfigureArray()
194 1.1 oster {
195 1.6 oster int rc;
196 1.1 oster
197 1.55 oster RF_LOCK_LKMGR_MUTEX(configureMutex);
198 1.6 oster if (--configureCount == 0) { /* if no active configurations, shut
199 1.6 oster * everything down */
200 1.6 oster isconfigged = 0;
201 1.6 oster
202 1.6 oster rc = rf_ShutdownList(&globalShutdown);
203 1.6 oster if (rc) {
204 1.6 oster RF_ERRORMSG1("RAIDFRAME: unable to do global shutdown, rc=%d\n", rc);
205 1.6 oster }
206 1.6 oster
207 1.6 oster /*
208 1.6 oster * We must wait until now, because the AllocList module
209 1.6 oster * uses the DebugMem module.
210 1.6 oster */
211 1.60 oster #if RF_DEBUG_MEM
212 1.6 oster if (rf_memDebug)
213 1.6 oster rf_print_unfreed();
214 1.60 oster #endif
215 1.6 oster }
216 1.55 oster RF_UNLOCK_LKMGR_MUTEX(configureMutex);
217 1.9 oster }
218 1.9 oster
219 1.1 oster /*
220 1.1 oster * Called to shut down an array.
221 1.1 oster */
222 1.6 oster int
223 1.6 oster rf_Shutdown(raidPtr)
224 1.6 oster RF_Raid_t *raidPtr;
225 1.1 oster {
226 1.1 oster
227 1.6 oster if (!raidPtr->valid) {
228 1.6 oster RF_ERRORMSG("Attempt to shut down unconfigured RAIDframe driver. Aborting shutdown\n");
229 1.6 oster return (EINVAL);
230 1.6 oster }
231 1.6 oster /*
232 1.6 oster * wait for outstanding IOs to land
233 1.6 oster * As described in rf_raid.h, we use the rad_freelist lock
234 1.6 oster * to protect the per-array info about outstanding descs
235 1.6 oster * since we need to do freelist locking anyway, and this
236 1.6 oster * cuts down on the amount of serialization we've got going
237 1.6 oster * on.
238 1.6 oster */
239 1.6 oster RF_FREELIST_DO_LOCK(rf_rad_freelist);
240 1.6 oster if (raidPtr->waitShutdown) {
241 1.6 oster RF_FREELIST_DO_UNLOCK(rf_rad_freelist);
242 1.6 oster return (EBUSY);
243 1.6 oster }
244 1.6 oster raidPtr->waitShutdown = 1;
245 1.6 oster while (raidPtr->nAccOutstanding) {
246 1.6 oster RF_WAIT_COND(raidPtr->outstandingCond, RF_FREELIST_MUTEX_OF(rf_rad_freelist));
247 1.6 oster }
248 1.6 oster RF_FREELIST_DO_UNLOCK(rf_rad_freelist);
249 1.35 oster
250 1.35 oster /* Wait for any parity re-writes to stop... */
251 1.35 oster while (raidPtr->parity_rewrite_in_progress) {
252 1.35 oster printf("Waiting for parity re-write to exit...\n");
253 1.35 oster tsleep(&raidPtr->parity_rewrite_in_progress, PRIBIO,
254 1.35 oster "rfprwshutdown", 0);
255 1.35 oster }
256 1.6 oster
257 1.6 oster raidPtr->valid = 0;
258 1.6 oster
259 1.37 oster rf_update_component_labels(raidPtr, RF_FINAL_COMPONENT_UPDATE);
260 1.6 oster
261 1.7 oster rf_UnconfigureVnodes(raidPtr);
262 1.7 oster
263 1.7 oster rf_ShutdownList(&raidPtr->shutdownList);
264 1.7 oster
265 1.7 oster rf_UnconfigureArray();
266 1.7 oster
267 1.7 oster return (0);
268 1.7 oster }
269 1.1 oster
270 1.6 oster
271 1.1 oster #define DO_INIT_CONFIGURE(f) { \
272 1.1 oster rc = f (&globalShutdown); \
273 1.1 oster if (rc) { \
274 1.1 oster RF_ERRORMSG2("RAIDFRAME: failed %s with %d\n", RF_STRING(f), rc); \
275 1.1 oster rf_ShutdownList(&globalShutdown); \
276 1.1 oster configureCount--; \
277 1.55 oster RF_UNLOCK_LKMGR_MUTEX(configureMutex); \
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_FAIL() { \
283 1.12 oster rf_UnconfigureVnodes(raidPtr); \
284 1.1 oster rf_ShutdownList(&raidPtr->shutdownList); \
285 1.1 oster rf_UnconfigureArray(); \
286 1.1 oster }
287 1.1 oster
288 1.1 oster #define DO_RAID_INIT_CONFIGURE(f) { \
289 1.1 oster rc = f (&raidPtr->shutdownList, raidPtr, cfgPtr); \
290 1.1 oster if (rc) { \
291 1.1 oster RF_ERRORMSG2("RAIDFRAME: failed %s with %d\n", RF_STRING(f), rc); \
292 1.1 oster DO_RAID_FAIL(); \
293 1.1 oster return(rc); \
294 1.1 oster } \
295 1.1 oster }
296 1.1 oster
297 1.1 oster #define DO_RAID_MUTEX(_m_) { \
298 1.1 oster rc = rf_create_managed_mutex(&raidPtr->shutdownList, (_m_)); \
299 1.1 oster if (rc) { \
300 1.58 oster rf_print_unable_to_init_mutex(__FILE__, __LINE__, rc); \
301 1.1 oster DO_RAID_FAIL(); \
302 1.1 oster return(rc); \
303 1.1 oster } \
304 1.1 oster }
305 1.1 oster
306 1.1 oster #define DO_RAID_COND(_c_) { \
307 1.1 oster rc = rf_create_managed_cond(&raidPtr->shutdownList, (_c_)); \
308 1.1 oster if (rc) { \
309 1.58 oster rf_print_unable_to_init_cond(__FILE__, __LINE__, rc); \
310 1.1 oster DO_RAID_FAIL(); \
311 1.1 oster return(rc); \
312 1.1 oster } \
313 1.1 oster }
314 1.1 oster
315 1.6 oster int
316 1.28 oster rf_Configure(raidPtr, cfgPtr, ac)
317 1.6 oster RF_Raid_t *raidPtr;
318 1.6 oster RF_Config_t *cfgPtr;
319 1.28 oster RF_AutoConfig_t *ac;
320 1.6 oster {
321 1.6 oster RF_RowCol_t row, col;
322 1.6 oster int i, rc;
323 1.6 oster
324 1.55 oster RF_LOCK_LKMGR_MUTEX(configureMutex);
325 1.6 oster configureCount++;
326 1.6 oster if (isconfigged == 0) {
327 1.6 oster rc = rf_create_managed_mutex(&globalShutdown, &rf_printf_mutex);
328 1.6 oster if (rc) {
329 1.58 oster rf_print_unable_to_init_mutex(__FILE__, __LINE__, rc);
330 1.6 oster rf_ShutdownList(&globalShutdown);
331 1.6 oster return (rc);
332 1.6 oster }
333 1.6 oster /* initialize globals */
334 1.6 oster
335 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureAllocList);
336 1.28 oster
337 1.6 oster /*
338 1.28 oster * Yes, this does make debugging general to the whole
339 1.28 oster * system instead of being array specific. Bummer, drag.
340 1.28 oster */
341 1.6 oster rf_ConfigureDebug(cfgPtr);
342 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureDebugMem);
343 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureAccessTrace);
344 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureMapModule);
345 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureReconEvent);
346 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureCallback);
347 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureRDFreeList);
348 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureNWayXor);
349 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureStripeLockFreeList);
350 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureMCPair);
351 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureDAGs);
352 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureDAGFuncs);
353 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureReconstruction);
354 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureCopyback);
355 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureDiskQueueSystem);
356 1.6 oster isconfigged = 1;
357 1.6 oster }
358 1.55 oster RF_UNLOCK_LKMGR_MUTEX(configureMutex);
359 1.6 oster
360 1.6 oster DO_RAID_MUTEX(&raidPtr->mutex);
361 1.6 oster /* set up the cleanup list. Do this after ConfigureDebug so that
362 1.6 oster * value of memDebug will be set */
363 1.6 oster
364 1.6 oster rf_MakeAllocList(raidPtr->cleanupList);
365 1.6 oster if (raidPtr->cleanupList == NULL) {
366 1.6 oster DO_RAID_FAIL();
367 1.6 oster return (ENOMEM);
368 1.6 oster }
369 1.6 oster rc = rf_ShutdownCreate(&raidPtr->shutdownList,
370 1.6 oster (void (*) (void *)) rf_FreeAllocList,
371 1.6 oster raidPtr->cleanupList);
372 1.6 oster if (rc) {
373 1.58 oster rf_print_unable_to_add_shutdown(__FILE__, __LINE__, rc);
374 1.6 oster DO_RAID_FAIL();
375 1.6 oster return (rc);
376 1.6 oster }
377 1.6 oster raidPtr->numRow = cfgPtr->numRow;
378 1.6 oster raidPtr->numCol = cfgPtr->numCol;
379 1.6 oster raidPtr->numSpare = cfgPtr->numSpare;
380 1.6 oster
381 1.6 oster /* XXX we don't even pretend to support more than one row in the
382 1.6 oster * kernel... */
383 1.6 oster if (raidPtr->numRow != 1) {
384 1.6 oster RF_ERRORMSG("Only one row supported in kernel.\n");
385 1.6 oster DO_RAID_FAIL();
386 1.6 oster return (EINVAL);
387 1.6 oster }
388 1.6 oster RF_CallocAndAdd(raidPtr->status, raidPtr->numRow, sizeof(RF_RowStatus_t),
389 1.6 oster (RF_RowStatus_t *), raidPtr->cleanupList);
390 1.6 oster if (raidPtr->status == NULL) {
391 1.6 oster DO_RAID_FAIL();
392 1.6 oster return (ENOMEM);
393 1.6 oster }
394 1.6 oster RF_CallocAndAdd(raidPtr->reconControl, raidPtr->numRow,
395 1.6 oster sizeof(RF_ReconCtrl_t *), (RF_ReconCtrl_t **), raidPtr->cleanupList);
396 1.6 oster if (raidPtr->reconControl == NULL) {
397 1.6 oster DO_RAID_FAIL();
398 1.6 oster return (ENOMEM);
399 1.6 oster }
400 1.6 oster for (i = 0; i < raidPtr->numRow; i++) {
401 1.6 oster raidPtr->status[i] = rf_rs_optimal;
402 1.6 oster raidPtr->reconControl[i] = NULL;
403 1.6 oster }
404 1.64 oster
405 1.64 oster TAILQ_INIT(&(raidPtr->iodone));
406 1.64 oster simple_lock_init(&(raidPtr->iodone_lock));
407 1.6 oster
408 1.6 oster DO_RAID_INIT_CONFIGURE(rf_ConfigureEngine);
409 1.6 oster DO_RAID_INIT_CONFIGURE(rf_ConfigureStripeLocks);
410 1.6 oster
411 1.6 oster DO_RAID_COND(&raidPtr->outstandingCond);
412 1.6 oster
413 1.6 oster raidPtr->nAccOutstanding = 0;
414 1.6 oster raidPtr->waitShutdown = 0;
415 1.6 oster
416 1.6 oster DO_RAID_MUTEX(&raidPtr->access_suspend_mutex);
417 1.6 oster DO_RAID_COND(&raidPtr->quiescent_cond);
418 1.6 oster
419 1.6 oster DO_RAID_COND(&raidPtr->waitForReconCond);
420 1.6 oster
421 1.6 oster DO_RAID_MUTEX(&raidPtr->recon_done_proc_mutex);
422 1.28 oster
423 1.28 oster if (ac!=NULL) {
424 1.28 oster /* We have an AutoConfig structure.. Don't do the
425 1.28 oster normal disk configuration... call the auto config
426 1.28 oster stuff */
427 1.28 oster rf_AutoConfigureDisks(raidPtr, cfgPtr, ac);
428 1.28 oster } else {
429 1.28 oster DO_RAID_INIT_CONFIGURE(rf_ConfigureDisks);
430 1.28 oster DO_RAID_INIT_CONFIGURE(rf_ConfigureSpareDisks);
431 1.28 oster }
432 1.6 oster /* do this after ConfigureDisks & ConfigureSpareDisks to be sure dev
433 1.6 oster * no. is set */
434 1.6 oster DO_RAID_INIT_CONFIGURE(rf_ConfigureDiskQueues);
435 1.6 oster
436 1.6 oster DO_RAID_INIT_CONFIGURE(rf_ConfigureLayout);
437 1.6 oster
438 1.6 oster DO_RAID_INIT_CONFIGURE(rf_ConfigurePSStatus);
439 1.6 oster
440 1.6 oster for (row = 0; row < raidPtr->numRow; row++) {
441 1.6 oster for (col = 0; col < raidPtr->numCol; col++) {
442 1.6 oster /*
443 1.6 oster * XXX better distribution
444 1.6 oster */
445 1.6 oster raidPtr->hist_diskreq[row][col] = 0;
446 1.6 oster }
447 1.6 oster }
448 1.28 oster
449 1.30 oster raidPtr->numNewFailures = 0;
450 1.28 oster raidPtr->copyback_in_progress = 0;
451 1.28 oster raidPtr->parity_rewrite_in_progress = 0;
452 1.66 oster raidPtr->adding_hot_spare = 0;
453 1.28 oster raidPtr->recon_in_progress = 0;
454 1.29 oster raidPtr->maxOutstanding = cfgPtr->maxOutstandingDiskReqs;
455 1.29 oster
456 1.29 oster /* autoconfigure and root_partition will actually get filled in
457 1.29 oster after the config is done */
458 1.29 oster raidPtr->autoconfigure = 0;
459 1.29 oster raidPtr->root_partition = 0;
460 1.29 oster raidPtr->last_unit = raidPtr->raidid;
461 1.29 oster raidPtr->config_order = 0;
462 1.6 oster
463 1.6 oster if (rf_keepAccTotals) {
464 1.6 oster raidPtr->keep_acc_totals = 1;
465 1.6 oster }
466 1.6 oster rf_StartUserStats(raidPtr);
467 1.1 oster
468 1.6 oster raidPtr->valid = 1;
469 1.52 oster
470 1.52 oster printf("raid%d: %s\n", raidPtr->raidid,
471 1.52 oster raidPtr->Layout.map->configName);
472 1.52 oster printf("raid%d: Components:", raidPtr->raidid);
473 1.52 oster for (row = 0; row < raidPtr->numRow; row++) {
474 1.52 oster for (col = 0; col < raidPtr->numCol; col++) {
475 1.52 oster printf(" %s", raidPtr->Disks[row][col].devname);
476 1.52 oster if (RF_DEAD_DISK(raidPtr->Disks[row][col].status)) {
477 1.52 oster printf("[**FAILED**]");
478 1.52 oster }
479 1.52 oster }
480 1.52 oster }
481 1.52 oster printf("\n");
482 1.52 oster printf("raid%d: Total Sectors: %lu (%lu MB)\n",
483 1.52 oster raidPtr->raidid,
484 1.52 oster (unsigned long) raidPtr->totalSectors,
485 1.52 oster (unsigned long) (raidPtr->totalSectors / 1024 *
486 1.52 oster (1 << raidPtr->logBytesPerSector) / 1024));
487 1.50 oster
488 1.6 oster return (0);
489 1.1 oster }
490 1.1 oster
491 1.6 oster static int
492 1.6 oster init_rad(desc)
493 1.6 oster RF_RaidAccessDesc_t *desc;
494 1.1 oster {
495 1.6 oster int rc;
496 1.1 oster
497 1.1 oster rc = rf_mutex_init(&desc->mutex);
498 1.1 oster if (rc) {
499 1.58 oster rf_print_unable_to_init_mutex(__FILE__, __LINE__, rc);
500 1.6 oster return (rc);
501 1.1 oster }
502 1.1 oster rc = rf_cond_init(&desc->cond);
503 1.1 oster if (rc) {
504 1.58 oster rf_print_unable_to_init_cond(__FILE__, __LINE__, rc);
505 1.1 oster rf_mutex_destroy(&desc->mutex);
506 1.6 oster return (rc);
507 1.1 oster }
508 1.6 oster return (0);
509 1.1 oster }
510 1.1 oster
511 1.6 oster static void
512 1.6 oster clean_rad(desc)
513 1.6 oster RF_RaidAccessDesc_t *desc;
514 1.1 oster {
515 1.1 oster rf_mutex_destroy(&desc->mutex);
516 1.1 oster rf_cond_destroy(&desc->cond);
517 1.1 oster }
518 1.1 oster
519 1.6 oster static void
520 1.6 oster rf_ShutdownRDFreeList(ignored)
521 1.6 oster void *ignored;
522 1.1 oster {
523 1.6 oster RF_FREELIST_DESTROY_CLEAN(rf_rad_freelist, next, (RF_RaidAccessDesc_t *), clean_rad);
524 1.1 oster }
525 1.1 oster
526 1.6 oster static int
527 1.6 oster rf_ConfigureRDFreeList(listp)
528 1.6 oster RF_ShutdownList_t **listp;
529 1.1 oster {
530 1.6 oster int rc;
531 1.1 oster
532 1.1 oster RF_FREELIST_CREATE(rf_rad_freelist, RF_MAX_FREE_RAD,
533 1.6 oster RF_RAD_INC, sizeof(RF_RaidAccessDesc_t));
534 1.1 oster if (rf_rad_freelist == NULL) {
535 1.6 oster return (ENOMEM);
536 1.1 oster }
537 1.1 oster rc = rf_ShutdownCreate(listp, rf_ShutdownRDFreeList, NULL);
538 1.1 oster if (rc) {
539 1.58 oster rf_print_unable_to_add_shutdown(__FILE__, __LINE__, rc);
540 1.1 oster rf_ShutdownRDFreeList(NULL);
541 1.6 oster return (rc);
542 1.1 oster }
543 1.6 oster RF_FREELIST_PRIME_INIT(rf_rad_freelist, RF_RAD_INITIAL, next,
544 1.6 oster (RF_RaidAccessDesc_t *), init_rad);
545 1.6 oster return (0);
546 1.6 oster }
547 1.6 oster
548 1.6 oster RF_RaidAccessDesc_t *
549 1.6 oster rf_AllocRaidAccDesc(
550 1.6 oster RF_Raid_t * raidPtr,
551 1.6 oster RF_IoType_t type,
552 1.6 oster RF_RaidAddr_t raidAddress,
553 1.6 oster RF_SectorCount_t numBlocks,
554 1.6 oster caddr_t bufPtr,
555 1.6 oster void *bp,
556 1.6 oster RF_RaidAccessFlags_t flags,
557 1.6 oster RF_AccessState_t * states)
558 1.6 oster {
559 1.6 oster RF_RaidAccessDesc_t *desc;
560 1.6 oster
561 1.6 oster RF_FREELIST_GET_INIT_NOUNLOCK(rf_rad_freelist, desc, next, (RF_RaidAccessDesc_t *), init_rad);
562 1.6 oster if (raidPtr->waitShutdown) {
563 1.6 oster /*
564 1.6 oster * Actually, we're shutting the array down. Free the desc
565 1.6 oster * and return NULL.
566 1.6 oster */
567 1.6 oster RF_FREELIST_DO_UNLOCK(rf_rad_freelist);
568 1.6 oster RF_FREELIST_FREE_CLEAN(rf_rad_freelist, desc, next, clean_rad);
569 1.6 oster return (NULL);
570 1.6 oster }
571 1.6 oster raidPtr->nAccOutstanding++;
572 1.6 oster RF_FREELIST_DO_UNLOCK(rf_rad_freelist);
573 1.6 oster
574 1.6 oster desc->raidPtr = (void *) raidPtr;
575 1.6 oster desc->type = type;
576 1.6 oster desc->raidAddress = raidAddress;
577 1.6 oster desc->numBlocks = numBlocks;
578 1.6 oster desc->bufPtr = bufPtr;
579 1.6 oster desc->bp = bp;
580 1.41 oster desc->paramDAG = NULL;
581 1.41 oster desc->paramASM = NULL;
582 1.6 oster desc->flags = flags;
583 1.6 oster desc->states = states;
584 1.6 oster desc->state = 0;
585 1.6 oster
586 1.6 oster desc->status = 0;
587 1.40 thorpej memset((char *) &desc->tracerec, 0, sizeof(RF_AccTraceEntry_t));
588 1.41 oster desc->callbackFunc = NULL;
589 1.41 oster desc->callbackArg = NULL;
590 1.6 oster desc->next = NULL;
591 1.6 oster desc->head = desc;
592 1.6 oster desc->cleanupList = NULL;
593 1.6 oster rf_MakeAllocList(desc->cleanupList);
594 1.6 oster return (desc);
595 1.6 oster }
596 1.6 oster
597 1.6 oster void
598 1.6 oster rf_FreeRaidAccDesc(RF_RaidAccessDesc_t * desc)
599 1.6 oster {
600 1.6 oster RF_Raid_t *raidPtr = desc->raidPtr;
601 1.6 oster
602 1.6 oster RF_ASSERT(desc);
603 1.6 oster
604 1.6 oster rf_FreeAllocList(desc->cleanupList);
605 1.6 oster RF_FREELIST_FREE_CLEAN_NOUNLOCK(rf_rad_freelist, desc, next, clean_rad);
606 1.6 oster raidPtr->nAccOutstanding--;
607 1.6 oster if (raidPtr->waitShutdown) {
608 1.6 oster RF_SIGNAL_COND(raidPtr->outstandingCond);
609 1.6 oster }
610 1.6 oster RF_FREELIST_DO_UNLOCK(rf_rad_freelist);
611 1.1 oster }
612 1.1 oster /*********************************************************************
613 1.1 oster * Main routine for performing an access.
614 1.1 oster * Accesses are retried until a DAG can not be selected. This occurs
615 1.1 oster * when either the DAG library is incomplete or there are too many
616 1.1 oster * failures in a parity group.
617 1.1 oster ********************************************************************/
618 1.6 oster int
619 1.6 oster rf_DoAccess(
620 1.6 oster RF_Raid_t * raidPtr,
621 1.6 oster RF_IoType_t type,
622 1.6 oster int async_flag,
623 1.6 oster RF_RaidAddr_t raidAddress,
624 1.6 oster RF_SectorCount_t numBlocks,
625 1.6 oster caddr_t bufPtr,
626 1.6 oster void *bp_in,
627 1.41 oster RF_RaidAccessFlags_t flags)
628 1.1 oster /*
629 1.1 oster type should be read or write
630 1.1 oster async_flag should be RF_TRUE or RF_FALSE
631 1.1 oster bp_in is a buf pointer. void * to facilitate ignoring it outside the kernel
632 1.1 oster */
633 1.1 oster {
634 1.6 oster RF_RaidAccessDesc_t *desc;
635 1.6 oster caddr_t lbufPtr = bufPtr;
636 1.6 oster struct buf *bp = (struct buf *) bp_in;
637 1.6 oster
638 1.6 oster raidAddress += rf_raidSectorOffset;
639 1.6 oster
640 1.61 oster #if RF_ACCESS_DEBUG
641 1.6 oster if (rf_accessDebug) {
642 1.1 oster
643 1.6 oster printf("logBytes is: %d %d %d\n", raidPtr->raidid,
644 1.6 oster raidPtr->logBytesPerSector,
645 1.6 oster (int) rf_RaidAddressToByte(raidPtr, numBlocks));
646 1.22 oster printf("raid%d: %s raidAddr %d (stripeid %d-%d) numBlocks %d (%d bytes) buf 0x%lx\n", raidPtr->raidid,
647 1.6 oster (type == RF_IO_TYPE_READ) ? "READ" : "WRITE", (int) raidAddress,
648 1.6 oster (int) rf_RaidAddressToStripeID(&raidPtr->Layout, raidAddress),
649 1.6 oster (int) rf_RaidAddressToStripeID(&raidPtr->Layout, raidAddress + numBlocks - 1),
650 1.6 oster (int) numBlocks,
651 1.6 oster (int) rf_RaidAddressToByte(raidPtr, numBlocks),
652 1.6 oster (long) bufPtr);
653 1.6 oster }
654 1.61 oster #endif
655 1.6 oster if (raidAddress + numBlocks > raidPtr->totalSectors) {
656 1.1 oster
657 1.6 oster printf("DoAccess: raid addr %lu too large to access %lu sectors. Max legal addr is %lu\n",
658 1.6 oster (u_long) raidAddress, (u_long) numBlocks, (u_long) raidPtr->totalSectors);
659 1.1 oster
660 1.20 oster IO_BUF_ERR(bp, ENOSPC);
661 1.16 oster return (ENOSPC);
662 1.6 oster }
663 1.6 oster desc = rf_AllocRaidAccDesc(raidPtr, type, raidAddress,
664 1.41 oster numBlocks, lbufPtr, bp, flags, raidPtr->Layout.map->states);
665 1.1 oster
666 1.6 oster if (desc == NULL) {
667 1.6 oster return (ENOMEM);
668 1.6 oster }
669 1.6 oster RF_ETIMER_START(desc->tracerec.tot_timer);
670 1.1 oster
671 1.6 oster desc->async_flag = async_flag;
672 1.3 explorer
673 1.6 oster rf_ContinueRaidAccess(desc);
674 1.1 oster
675 1.6 oster return (0);
676 1.1 oster }
677 1.46 oster #if 0
678 1.1 oster /* force the array into reconfigured mode without doing reconstruction */
679 1.6 oster int
680 1.6 oster rf_SetReconfiguredMode(raidPtr, row, col)
681 1.6 oster RF_Raid_t *raidPtr;
682 1.6 oster int row;
683 1.6 oster int col;
684 1.6 oster {
685 1.6 oster if (!(raidPtr->Layout.map->flags & RF_DISTRIBUTE_SPARE)) {
686 1.6 oster printf("Can't set reconfigured mode in dedicated-spare array\n");
687 1.6 oster RF_PANIC();
688 1.6 oster }
689 1.6 oster RF_LOCK_MUTEX(raidPtr->mutex);
690 1.6 oster raidPtr->numFailures++;
691 1.6 oster raidPtr->Disks[row][col].status = rf_ds_dist_spared;
692 1.6 oster raidPtr->status[row] = rf_rs_reconfigured;
693 1.37 oster rf_update_component_labels(raidPtr, RF_NORMAL_COMPONENT_UPDATE);
694 1.6 oster /* install spare table only if declustering + distributed sparing
695 1.6 oster * architecture. */
696 1.6 oster if (raidPtr->Layout.map->flags & RF_BD_DECLUSTERED)
697 1.6 oster rf_InstallSpareTable(raidPtr, row, col);
698 1.6 oster RF_UNLOCK_MUTEX(raidPtr->mutex);
699 1.6 oster return (0);
700 1.1 oster }
701 1.46 oster #endif
702 1.1 oster
703 1.6 oster int
704 1.6 oster rf_FailDisk(
705 1.6 oster RF_Raid_t * raidPtr,
706 1.6 oster int frow,
707 1.6 oster int fcol,
708 1.6 oster int initRecon)
709 1.6 oster {
710 1.6 oster RF_LOCK_MUTEX(raidPtr->mutex);
711 1.68 oster if ((raidPtr->Disks[frow][fcol].status == rf_ds_optimal) &&
712 1.68 oster (raidPtr->numFailures > 0)) {
713 1.68 oster /* some other component has failed. Let's not make
714 1.68 oster things worse. XXX wrong for RAID6 */
715 1.68 oster RF_UNLOCK_MUTEX(raidPtr->mutex);
716 1.68 oster return (EINVAL);
717 1.68 oster }
718 1.68 oster if (raidPtr->Disks[frow][fcol].status == rf_ds_spared) {
719 1.68 oster /* Can't fail a spared disk! */
720 1.68 oster RF_UNLOCK_MUTEX(raidPtr->mutex);
721 1.68 oster return (EINVAL);
722 1.68 oster }
723 1.68 oster if (raidPtr->Disks[frow][fcol].status != rf_ds_failed) {
724 1.68 oster /* must be failing something that is valid, or else it's
725 1.68 oster already marked as failed (in which case we don't
726 1.68 oster want to mark it failed again!) */
727 1.68 oster raidPtr->numFailures++;
728 1.68 oster raidPtr->Disks[frow][fcol].status = rf_ds_failed;
729 1.68 oster raidPtr->status[frow] = rf_rs_degraded;
730 1.68 oster }
731 1.65 oster RF_UNLOCK_MUTEX(raidPtr->mutex);
732 1.68 oster
733 1.37 oster rf_update_component_labels(raidPtr, RF_NORMAL_COMPONENT_UPDATE);
734 1.68 oster
735 1.56 oster /* Close the component, so that it's not "locked" if someone
736 1.56 oster else want's to use it! */
737 1.56 oster
738 1.56 oster rf_close_component(raidPtr, raidPtr->raid_cinfo[frow][fcol].ci_vp,
739 1.56 oster raidPtr->Disks[frow][fcol].auto_configured);
740 1.65 oster
741 1.65 oster RF_LOCK_MUTEX(raidPtr->mutex);
742 1.56 oster raidPtr->raid_cinfo[frow][fcol].ci_vp = NULL;
743 1.56 oster
744 1.56 oster /* Need to mark the component as not being auto_configured
745 1.56 oster (in case it was previously). */
746 1.56 oster
747 1.56 oster raidPtr->Disks[frow][fcol].auto_configured = 0;
748 1.65 oster RF_UNLOCK_MUTEX(raidPtr->mutex);
749 1.56 oster
750 1.6 oster if (initRecon)
751 1.6 oster rf_ReconstructFailedDisk(raidPtr, frow, fcol);
752 1.6 oster return (0);
753 1.1 oster }
754 1.1 oster /* releases a thread that is waiting for the array to become quiesced.
755 1.1 oster * access_suspend_mutex should be locked upon calling this
756 1.1 oster */
757 1.6 oster void
758 1.63 oster rf_SignalQuiescenceLock(raidPtr)
759 1.6 oster RF_Raid_t *raidPtr;
760 1.6 oster {
761 1.61 oster #if RF_DEBUG_QUIESCE
762 1.6 oster if (rf_quiesceDebug) {
763 1.22 oster printf("raid%d: Signalling quiescence lock\n",
764 1.22 oster raidPtr->raidid);
765 1.6 oster }
766 1.61 oster #endif
767 1.6 oster raidPtr->access_suspend_release = 1;
768 1.6 oster
769 1.6 oster if (raidPtr->waiting_for_quiescence) {
770 1.6 oster SIGNAL_QUIESCENT_COND(raidPtr);
771 1.6 oster }
772 1.1 oster }
773 1.1 oster /* suspends all new requests to the array. No effect on accesses that are in flight. */
774 1.6 oster int
775 1.6 oster rf_SuspendNewRequestsAndWait(raidPtr)
776 1.6 oster RF_Raid_t *raidPtr;
777 1.6 oster {
778 1.61 oster #if RF_DEBUG_QUIESCE
779 1.6 oster if (rf_quiesceDebug)
780 1.53 oster printf("raid%d: Suspending new reqs\n", raidPtr->raidid);
781 1.61 oster #endif
782 1.6 oster RF_LOCK_MUTEX(raidPtr->access_suspend_mutex);
783 1.6 oster raidPtr->accesses_suspended++;
784 1.6 oster raidPtr->waiting_for_quiescence = (raidPtr->accs_in_flight == 0) ? 0 : 1;
785 1.6 oster
786 1.6 oster if (raidPtr->waiting_for_quiescence) {
787 1.6 oster raidPtr->access_suspend_release = 0;
788 1.6 oster while (!raidPtr->access_suspend_release) {
789 1.53 oster printf("raid%d: Suspending: Waiting for Quiescence\n",
790 1.53 oster raidPtr->raidid);
791 1.6 oster WAIT_FOR_QUIESCENCE(raidPtr);
792 1.6 oster raidPtr->waiting_for_quiescence = 0;
793 1.6 oster }
794 1.6 oster }
795 1.53 oster printf("raid%d: Quiescence reached..\n", raidPtr->raidid);
796 1.1 oster
797 1.6 oster RF_UNLOCK_MUTEX(raidPtr->access_suspend_mutex);
798 1.6 oster return (raidPtr->waiting_for_quiescence);
799 1.1 oster }
800 1.1 oster /* wake up everyone waiting for quiescence to be released */
801 1.6 oster void
802 1.6 oster rf_ResumeNewRequests(raidPtr)
803 1.6 oster RF_Raid_t *raidPtr;
804 1.6 oster {
805 1.6 oster RF_CallbackDesc_t *t, *cb;
806 1.6 oster
807 1.61 oster #if RF_DEBUG_QUIESCE
808 1.6 oster if (rf_quiesceDebug)
809 1.6 oster printf("Resuming new reqs\n");
810 1.61 oster #endif
811 1.6 oster
812 1.6 oster RF_LOCK_MUTEX(raidPtr->access_suspend_mutex);
813 1.6 oster raidPtr->accesses_suspended--;
814 1.6 oster if (raidPtr->accesses_suspended == 0)
815 1.6 oster cb = raidPtr->quiesce_wait_list;
816 1.6 oster else
817 1.6 oster cb = NULL;
818 1.6 oster raidPtr->quiesce_wait_list = NULL;
819 1.6 oster RF_UNLOCK_MUTEX(raidPtr->access_suspend_mutex);
820 1.6 oster
821 1.6 oster while (cb) {
822 1.6 oster t = cb;
823 1.6 oster cb = cb->next;
824 1.6 oster (t->callbackFunc) (t->callbackArg);
825 1.6 oster rf_FreeCallbackDesc(t);
826 1.6 oster }
827 1.1 oster }
828 1.1 oster /*****************************************************************************************
829 1.1 oster *
830 1.1 oster * debug routines
831 1.1 oster *
832 1.1 oster ****************************************************************************************/
833 1.1 oster
834 1.6 oster static void
835 1.6 oster set_debug_option(name, val)
836 1.6 oster char *name;
837 1.6 oster long val;
838 1.6 oster {
839 1.6 oster RF_DebugName_t *p;
840 1.6 oster
841 1.6 oster for (p = rf_debugNames; p->name; p++) {
842 1.6 oster if (!strcmp(p->name, name)) {
843 1.6 oster *(p->ptr) = val;
844 1.6 oster printf("[Set debug variable %s to %ld]\n", name, val);
845 1.6 oster return;
846 1.6 oster }
847 1.6 oster }
848 1.6 oster RF_ERRORMSG1("Unknown debug string \"%s\"\n", name);
849 1.1 oster }
850 1.1 oster
851 1.1 oster
852 1.1 oster /* would like to use sscanf here, but apparently not available in kernel */
853 1.1 oster /*ARGSUSED*/
854 1.6 oster static void
855 1.6 oster rf_ConfigureDebug(cfgPtr)
856 1.6 oster RF_Config_t *cfgPtr;
857 1.6 oster {
858 1.6 oster char *val_p, *name_p, *white_p;
859 1.6 oster long val;
860 1.6 oster int i;
861 1.6 oster
862 1.6 oster rf_ResetDebugOptions();
863 1.6 oster for (i = 0; cfgPtr->debugVars[i][0] && i < RF_MAXDBGV; i++) {
864 1.6 oster name_p = rf_find_non_white(&cfgPtr->debugVars[i][0]);
865 1.6 oster white_p = rf_find_white(name_p); /* skip to start of 2nd
866 1.6 oster * word */
867 1.6 oster val_p = rf_find_non_white(white_p);
868 1.6 oster if (*val_p == '0' && *(val_p + 1) == 'x')
869 1.6 oster val = rf_htoi(val_p + 2);
870 1.6 oster else
871 1.6 oster val = rf_atoi(val_p);
872 1.6 oster *white_p = '\0';
873 1.6 oster set_debug_option(name_p, val);
874 1.6 oster }
875 1.1 oster }
876 1.1 oster /* performance monitoring stuff */
877 1.1 oster
878 1.1 oster #define TIMEVAL_TO_US(t) (((long) t.tv_sec) * 1000000L + (long) t.tv_usec)
879 1.1 oster
880 1.4 oster #if !defined(_KERNEL) && !defined(SIMULATE)
881 1.1 oster
882 1.1 oster /*
883 1.1 oster * Throughput stats currently only used in user-level RAIDframe
884 1.1 oster */
885 1.1 oster
886 1.6 oster static int
887 1.6 oster rf_InitThroughputStats(
888 1.6 oster RF_ShutdownList_t ** listp,
889 1.6 oster RF_Raid_t * raidPtr,
890 1.6 oster RF_Config_t * cfgPtr)
891 1.1 oster {
892 1.6 oster int rc;
893 1.1 oster
894 1.6 oster /* these used by user-level raidframe only */
895 1.6 oster rc = rf_create_managed_mutex(listp, &raidPtr->throughputstats.mutex);
896 1.6 oster if (rc) {
897 1.58 oster rf_print_unable_to_init_mutex(__FILE__, __LINE__, rc);
898 1.6 oster return (rc);
899 1.6 oster }
900 1.6 oster raidPtr->throughputstats.sum_io_us = 0;
901 1.6 oster raidPtr->throughputstats.num_ios = 0;
902 1.6 oster raidPtr->throughputstats.num_out_ios = 0;
903 1.6 oster return (0);
904 1.6 oster }
905 1.6 oster
906 1.6 oster void
907 1.6 oster rf_StartThroughputStats(RF_Raid_t * raidPtr)
908 1.6 oster {
909 1.6 oster RF_LOCK_MUTEX(raidPtr->throughputstats.mutex);
910 1.6 oster raidPtr->throughputstats.num_ios++;
911 1.6 oster raidPtr->throughputstats.num_out_ios++;
912 1.6 oster if (raidPtr->throughputstats.num_out_ios == 1)
913 1.6 oster RF_GETTIME(raidPtr->throughputstats.start);
914 1.6 oster RF_UNLOCK_MUTEX(raidPtr->throughputstats.mutex);
915 1.6 oster }
916 1.6 oster
917 1.6 oster static void
918 1.6 oster rf_StopThroughputStats(RF_Raid_t * raidPtr)
919 1.6 oster {
920 1.6 oster struct timeval diff;
921 1.6 oster
922 1.6 oster RF_LOCK_MUTEX(raidPtr->throughputstats.mutex);
923 1.6 oster raidPtr->throughputstats.num_out_ios--;
924 1.6 oster if (raidPtr->throughputstats.num_out_ios == 0) {
925 1.6 oster RF_GETTIME(raidPtr->throughputstats.stop);
926 1.6 oster RF_TIMEVAL_DIFF(&raidPtr->throughputstats.start, &raidPtr->throughputstats.stop, &diff);
927 1.6 oster raidPtr->throughputstats.sum_io_us += TIMEVAL_TO_US(diff);
928 1.6 oster }
929 1.6 oster RF_UNLOCK_MUTEX(raidPtr->throughputstats.mutex);
930 1.1 oster }
931 1.1 oster
932 1.6 oster static void
933 1.6 oster rf_PrintThroughputStats(RF_Raid_t * raidPtr)
934 1.1 oster {
935 1.6 oster RF_ASSERT(raidPtr->throughputstats.num_out_ios == 0);
936 1.6 oster if (raidPtr->throughputstats.sum_io_us != 0) {
937 1.6 oster printf("[Througphut: %8.2f IOs/second]\n", raidPtr->throughputstats.num_ios
938 1.6 oster / (raidPtr->throughputstats.sum_io_us / 1000000.0));
939 1.6 oster }
940 1.1 oster }
941 1.6 oster #endif /* !KERNEL && !SIMULATE */
942 1.1 oster
943 1.6 oster void
944 1.6 oster rf_StartUserStats(RF_Raid_t * raidPtr)
945 1.1 oster {
946 1.6 oster RF_GETTIME(raidPtr->userstats.start);
947 1.6 oster raidPtr->userstats.sum_io_us = 0;
948 1.6 oster raidPtr->userstats.num_ios = 0;
949 1.6 oster raidPtr->userstats.num_sect_moved = 0;
950 1.1 oster }
951 1.1 oster
952 1.6 oster void
953 1.6 oster rf_StopUserStats(RF_Raid_t * raidPtr)
954 1.1 oster {
955 1.6 oster RF_GETTIME(raidPtr->userstats.stop);
956 1.1 oster }
957 1.1 oster
958 1.6 oster void
959 1.6 oster rf_UpdateUserStats(raidPtr, rt, numsect)
960 1.6 oster RF_Raid_t *raidPtr;
961 1.6 oster int rt; /* resp time in us */
962 1.6 oster int numsect; /* number of sectors for this access */
963 1.1 oster {
964 1.6 oster raidPtr->userstats.sum_io_us += rt;
965 1.6 oster raidPtr->userstats.num_ios++;
966 1.6 oster raidPtr->userstats.num_sect_moved += numsect;
967 1.1 oster }
968 1.1 oster
969 1.6 oster void
970 1.6 oster rf_PrintUserStats(RF_Raid_t * raidPtr)
971 1.1 oster {
972 1.6 oster long elapsed_us, mbs, mbs_frac;
973 1.6 oster struct timeval diff;
974 1.1 oster
975 1.6 oster RF_TIMEVAL_DIFF(&raidPtr->userstats.start, &raidPtr->userstats.stop, &diff);
976 1.6 oster elapsed_us = TIMEVAL_TO_US(diff);
977 1.1 oster
978 1.6 oster /* 2000 sectors per megabyte, 10000000 microseconds per second */
979 1.6 oster if (elapsed_us)
980 1.6 oster mbs = (raidPtr->userstats.num_sect_moved / 2000) / (elapsed_us / 1000000);
981 1.6 oster else
982 1.6 oster mbs = 0;
983 1.1 oster
984 1.6 oster /* this computes only the first digit of the fractional mb/s moved */
985 1.6 oster if (elapsed_us) {
986 1.6 oster mbs_frac = ((raidPtr->userstats.num_sect_moved / 200) / (elapsed_us / 1000000))
987 1.6 oster - (mbs * 10);
988 1.6 oster } else {
989 1.6 oster mbs_frac = 0;
990 1.6 oster }
991 1.1 oster
992 1.6 oster printf("Number of I/Os: %ld\n", raidPtr->userstats.num_ios);
993 1.6 oster printf("Elapsed time (us): %ld\n", elapsed_us);
994 1.6 oster printf("User I/Os per second: %ld\n", RF_DB0_CHECK(raidPtr->userstats.num_ios, (elapsed_us / 1000000)));
995 1.6 oster printf("Average user response time: %ld us\n", RF_DB0_CHECK(raidPtr->userstats.sum_io_us, raidPtr->userstats.num_ios));
996 1.6 oster printf("Total sectors moved: %ld\n", raidPtr->userstats.num_sect_moved);
997 1.6 oster printf("Average access size (sect): %ld\n", RF_DB0_CHECK(raidPtr->userstats.num_sect_moved, raidPtr->userstats.num_ios));
998 1.6 oster printf("Achieved data rate: %ld.%ld MB/sec\n", mbs, mbs_frac);
999 1.39 oster }
1000 1.39 oster
1001 1.39 oster
1002 1.39 oster void
1003 1.39 oster rf_print_panic_message(line,file)
1004 1.39 oster int line;
1005 1.39 oster char *file;
1006 1.39 oster {
1007 1.39 oster sprintf(rf_panicbuf,"raidframe error at line %d file %s",
1008 1.39 oster line, file);
1009 1.39 oster }
1010 1.39 oster
1011 1.62 oster #ifdef RAID_DIAGNOSTIC
1012 1.39 oster void
1013 1.39 oster rf_print_assert_panic_message(line,file,condition)
1014 1.39 oster int line;
1015 1.39 oster char *file;
1016 1.39 oster char *condition;
1017 1.39 oster {
1018 1.39 oster sprintf(rf_panicbuf,
1019 1.39 oster "raidframe error at line %d file %s (failed asserting %s)\n",
1020 1.39 oster line, file, condition);
1021 1.58 oster }
1022 1.62 oster #endif
1023 1.58 oster
1024 1.58 oster void
1025 1.58 oster rf_print_unable_to_init_mutex(file,line,rc)
1026 1.58 oster char *file;
1027 1.58 oster int line;
1028 1.58 oster int rc;
1029 1.58 oster {
1030 1.58 oster RF_ERRORMSG3("Unable to init mutex file %s line %d rc=%d\n",
1031 1.58 oster file, line, rc);
1032 1.58 oster }
1033 1.58 oster
1034 1.58 oster void
1035 1.58 oster rf_print_unable_to_init_cond(file,line,rc)
1036 1.58 oster char *file;
1037 1.58 oster int line;
1038 1.58 oster int rc;
1039 1.58 oster {
1040 1.58 oster RF_ERRORMSG3("Unable to init cond file %s line %d rc=%d\n",
1041 1.58 oster file, line, rc);
1042 1.58 oster }
1043 1.58 oster
1044 1.58 oster void
1045 1.58 oster rf_print_unable_to_add_shutdown(file,line,rc)
1046 1.58 oster char *file;
1047 1.58 oster int line;
1048 1.58 oster int rc;
1049 1.58 oster {
1050 1.58 oster RF_ERRORMSG3("Unable to add to shutdown list file %s line %d rc=%d\n",
1051 1.58 oster file, line, rc);
1052 1.1 oster }
1053