rf_driver.c revision 1.113.2.2 1 1.113.2.1 bouyer /* $NetBSD: rf_driver.c,v 1.113.2.2 2008/12/27 19:32:58 bouyer 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.113.2.1 bouyer __KERNEL_RCSID(0, "$NetBSD: rf_driver.c,v 1.113.2.2 2008/12/27 19:32:58 bouyer 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.91 oster RF_DECLARE_MUTEX(rf_rad_lock)
126 1.1 oster #define RF_MAX_FREE_RAD 128
127 1.88 oster #define RF_MIN_FREE_RAD 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 void rf_ShutdownRDFreeList(void *);
139 1.1 oster static int rf_ConfigureRDFreeList(RF_ShutdownList_t **);
140 1.1 oster
141 1.6 oster RF_DECLARE_MUTEX(rf_printf_mutex) /* debug only: avoids interleaved
142 1.6 oster * printfs by different stripes */
143 1.1 oster
144 1.1 oster #define SIGNAL_QUIESCENT_COND(_raid_) wakeup(&((_raid_)->accesses_suspended))
145 1.1 oster #define WAIT_FOR_QUIESCENCE(_raid_) \
146 1.38 oster ltsleep(&((_raid_)->accesses_suspended), PRIBIO, \
147 1.38 oster "raidframe quiesce", 0, &((_raid_)->access_suspend_mutex))
148 1.1 oster
149 1.9 oster static int configureCount = 0; /* number of active configurations */
150 1.9 oster static int isconfigged = 0; /* is basic raidframe (non per-array)
151 1.9 oster * stuff configged */
152 1.55 oster RF_DECLARE_LKMGR_STATIC_MUTEX(configureMutex) /* used to lock the configuration
153 1.6 oster * stuff */
154 1.9 oster static RF_ShutdownList_t *globalShutdown; /* non array-specific
155 1.9 oster * stuff */
156 1.1 oster
157 1.9 oster static int rf_ConfigureRDFreeList(RF_ShutdownList_t ** listp);
158 1.103 oster static int rf_AllocEmergBuffers(RF_Raid_t *);
159 1.103 oster static void rf_FreeEmergBuffers(RF_Raid_t *);
160 1.1 oster
161 1.1 oster /* called at system boot time */
162 1.107 perry 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.107 perry static void
180 1.6 oster rf_UnconfigureArray()
181 1.1 oster {
182 1.1 oster
183 1.55 oster RF_LOCK_LKMGR_MUTEX(configureMutex);
184 1.6 oster if (--configureCount == 0) { /* if no active configurations, shut
185 1.6 oster * everything down */
186 1.6 oster isconfigged = 0;
187 1.92 oster rf_ShutdownList(&globalShutdown);
188 1.6 oster
189 1.6 oster /*
190 1.6 oster * We must wait until now, because the AllocList module
191 1.6 oster * uses the DebugMem module.
192 1.6 oster */
193 1.60 oster #if RF_DEBUG_MEM
194 1.6 oster if (rf_memDebug)
195 1.6 oster rf_print_unfreed();
196 1.60 oster #endif
197 1.6 oster }
198 1.55 oster RF_UNLOCK_LKMGR_MUTEX(configureMutex);
199 1.9 oster }
200 1.9 oster
201 1.1 oster /*
202 1.1 oster * Called to shut down an array.
203 1.1 oster */
204 1.107 perry int
205 1.80 oster rf_Shutdown(RF_Raid_t *raidPtr)
206 1.1 oster {
207 1.100 oster
208 1.6 oster if (!raidPtr->valid) {
209 1.6 oster RF_ERRORMSG("Attempt to shut down unconfigured RAIDframe driver. Aborting shutdown\n");
210 1.6 oster return (EINVAL);
211 1.6 oster }
212 1.6 oster /*
213 1.6 oster * wait for outstanding IOs to land
214 1.6 oster * As described in rf_raid.h, we use the rad_freelist lock
215 1.6 oster * to protect the per-array info about outstanding descs
216 1.6 oster * since we need to do freelist locking anyway, and this
217 1.6 oster * cuts down on the amount of serialization we've got going
218 1.6 oster * on.
219 1.6 oster */
220 1.91 oster RF_LOCK_MUTEX(rf_rad_lock);
221 1.6 oster if (raidPtr->waitShutdown) {
222 1.91 oster RF_UNLOCK_MUTEX(rf_rad_lock);
223 1.6 oster return (EBUSY);
224 1.6 oster }
225 1.6 oster raidPtr->waitShutdown = 1;
226 1.6 oster while (raidPtr->nAccOutstanding) {
227 1.91 oster RF_WAIT_COND(raidPtr->outstandingCond, rf_rad_lock);
228 1.6 oster }
229 1.91 oster RF_UNLOCK_MUTEX(rf_rad_lock);
230 1.35 oster
231 1.35 oster /* Wait for any parity re-writes to stop... */
232 1.35 oster while (raidPtr->parity_rewrite_in_progress) {
233 1.113.2.2 bouyer printf("raid%d: Waiting for parity re-write to exit...\n",
234 1.113.2.2 bouyer raidPtr->raidid);
235 1.35 oster tsleep(&raidPtr->parity_rewrite_in_progress, PRIBIO,
236 1.35 oster "rfprwshutdown", 0);
237 1.35 oster }
238 1.6 oster
239 1.113.2.2 bouyer /* Wait for any reconstruction to stop... */
240 1.113.2.2 bouyer while (raidPtr->reconInProgress) {
241 1.113.2.2 bouyer printf("raid%d: Waiting for reconstruction to stop...\n",
242 1.113.2.2 bouyer raidPtr->raidid);
243 1.113.2.2 bouyer tsleep(&raidPtr->waitForReconCond, PRIBIO,
244 1.113.2.2 bouyer "rfreshutdown",0);
245 1.113.2.2 bouyer }
246 1.113.2.2 bouyer
247 1.6 oster raidPtr->valid = 0;
248 1.6 oster
249 1.37 oster rf_update_component_labels(raidPtr, RF_FINAL_COMPONENT_UPDATE);
250 1.6 oster
251 1.7 oster rf_UnconfigureVnodes(raidPtr);
252 1.7 oster
253 1.103 oster rf_FreeEmergBuffers(raidPtr);
254 1.100 oster
255 1.7 oster rf_ShutdownList(&raidPtr->shutdownList);
256 1.7 oster
257 1.7 oster rf_UnconfigureArray();
258 1.7 oster
259 1.7 oster return (0);
260 1.7 oster }
261 1.1 oster
262 1.6 oster
263 1.1 oster #define DO_INIT_CONFIGURE(f) { \
264 1.1 oster rc = f (&globalShutdown); \
265 1.1 oster if (rc) { \
266 1.1 oster RF_ERRORMSG2("RAIDFRAME: failed %s with %d\n", RF_STRING(f), rc); \
267 1.1 oster rf_ShutdownList(&globalShutdown); \
268 1.1 oster configureCount--; \
269 1.55 oster RF_UNLOCK_LKMGR_MUTEX(configureMutex); \
270 1.1 oster return(rc); \
271 1.1 oster } \
272 1.1 oster }
273 1.1 oster
274 1.1 oster #define DO_RAID_FAIL() { \
275 1.12 oster rf_UnconfigureVnodes(raidPtr); \
276 1.103 oster rf_FreeEmergBuffers(raidPtr); \
277 1.1 oster rf_ShutdownList(&raidPtr->shutdownList); \
278 1.1 oster rf_UnconfigureArray(); \
279 1.1 oster }
280 1.1 oster
281 1.1 oster #define DO_RAID_INIT_CONFIGURE(f) { \
282 1.1 oster rc = f (&raidPtr->shutdownList, raidPtr, cfgPtr); \
283 1.1 oster if (rc) { \
284 1.1 oster RF_ERRORMSG2("RAIDFRAME: failed %s with %d\n", RF_STRING(f), rc); \
285 1.1 oster DO_RAID_FAIL(); \
286 1.1 oster return(rc); \
287 1.1 oster } \
288 1.1 oster }
289 1.1 oster
290 1.1 oster #define DO_RAID_MUTEX(_m_) { \
291 1.75 oster rf_mutex_init((_m_)); \
292 1.1 oster }
293 1.1 oster
294 1.107 perry int
295 1.80 oster rf_Configure(RF_Raid_t *raidPtr, RF_Config_t *cfgPtr, RF_AutoConfig_t *ac)
296 1.6 oster {
297 1.72 oster RF_RowCol_t col;
298 1.103 oster int rc;
299 1.6 oster
300 1.55 oster RF_LOCK_LKMGR_MUTEX(configureMutex);
301 1.6 oster configureCount++;
302 1.6 oster if (isconfigged == 0) {
303 1.75 oster rf_mutex_init(&rf_printf_mutex);
304 1.75 oster
305 1.6 oster /* initialize globals */
306 1.6 oster
307 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureAllocList);
308 1.28 oster
309 1.6 oster /*
310 1.28 oster * Yes, this does make debugging general to the whole
311 1.107 perry * system instead of being array specific. Bummer, drag.
312 1.28 oster */
313 1.6 oster rf_ConfigureDebug(cfgPtr);
314 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureDebugMem);
315 1.87 oster #if RF_ACC_TRACE > 0
316 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureAccessTrace);
317 1.87 oster #endif
318 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureMapModule);
319 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureReconEvent);
320 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureCallback);
321 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureRDFreeList);
322 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureNWayXor);
323 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureStripeLockFreeList);
324 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureMCPair);
325 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureDAGs);
326 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureDAGFuncs);
327 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureReconstruction);
328 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureCopyback);
329 1.6 oster DO_INIT_CONFIGURE(rf_ConfigureDiskQueueSystem);
330 1.110 oster DO_INIT_CONFIGURE(rf_ConfigurePSStatus);
331 1.6 oster isconfigged = 1;
332 1.6 oster }
333 1.55 oster RF_UNLOCK_LKMGR_MUTEX(configureMutex);
334 1.6 oster
335 1.6 oster DO_RAID_MUTEX(&raidPtr->mutex);
336 1.6 oster /* set up the cleanup list. Do this after ConfigureDebug so that
337 1.6 oster * value of memDebug will be set */
338 1.6 oster
339 1.6 oster rf_MakeAllocList(raidPtr->cleanupList);
340 1.6 oster if (raidPtr->cleanupList == NULL) {
341 1.6 oster DO_RAID_FAIL();
342 1.6 oster return (ENOMEM);
343 1.6 oster }
344 1.86 oster rf_ShutdownCreate(&raidPtr->shutdownList,
345 1.86 oster (void (*) (void *)) rf_FreeAllocList,
346 1.86 oster raidPtr->cleanupList);
347 1.86 oster
348 1.6 oster raidPtr->numCol = cfgPtr->numCol;
349 1.6 oster raidPtr->numSpare = cfgPtr->numSpare;
350 1.6 oster
351 1.72 oster raidPtr->status = rf_rs_optimal;
352 1.72 oster raidPtr->reconControl = NULL;
353 1.107 perry
354 1.64 oster TAILQ_INIT(&(raidPtr->iodone));
355 1.64 oster simple_lock_init(&(raidPtr->iodone_lock));
356 1.6 oster
357 1.6 oster DO_RAID_INIT_CONFIGURE(rf_ConfigureEngine);
358 1.6 oster DO_RAID_INIT_CONFIGURE(rf_ConfigureStripeLocks);
359 1.6 oster
360 1.76 oster raidPtr->outstandingCond = 0;
361 1.6 oster
362 1.6 oster raidPtr->nAccOutstanding = 0;
363 1.6 oster raidPtr->waitShutdown = 0;
364 1.6 oster
365 1.6 oster DO_RAID_MUTEX(&raidPtr->access_suspend_mutex);
366 1.6 oster
367 1.76 oster raidPtr->waitForReconCond = 0;
368 1.6 oster
369 1.28 oster if (ac!=NULL) {
370 1.28 oster /* We have an AutoConfig structure.. Don't do the
371 1.28 oster normal disk configuration... call the auto config
372 1.28 oster stuff */
373 1.28 oster rf_AutoConfigureDisks(raidPtr, cfgPtr, ac);
374 1.28 oster } else {
375 1.28 oster DO_RAID_INIT_CONFIGURE(rf_ConfigureDisks);
376 1.28 oster DO_RAID_INIT_CONFIGURE(rf_ConfigureSpareDisks);
377 1.28 oster }
378 1.6 oster /* do this after ConfigureDisks & ConfigureSpareDisks to be sure dev
379 1.6 oster * no. is set */
380 1.6 oster DO_RAID_INIT_CONFIGURE(rf_ConfigureDiskQueues);
381 1.6 oster
382 1.6 oster DO_RAID_INIT_CONFIGURE(rf_ConfigureLayout);
383 1.6 oster
384 1.110 oster /* Initialize per-RAID PSS bits */
385 1.110 oster rf_InitPSStatus(raidPtr);
386 1.6 oster
387 1.82 oster #if RF_INCLUDE_CHAINDECLUSTER > 0
388 1.72 oster for (col = 0; col < raidPtr->numCol; col++) {
389 1.72 oster /*
390 1.72 oster * XXX better distribution
391 1.72 oster */
392 1.72 oster raidPtr->hist_diskreq[col] = 0;
393 1.6 oster }
394 1.82 oster #endif
395 1.30 oster raidPtr->numNewFailures = 0;
396 1.28 oster raidPtr->copyback_in_progress = 0;
397 1.28 oster raidPtr->parity_rewrite_in_progress = 0;
398 1.66 oster raidPtr->adding_hot_spare = 0;
399 1.28 oster raidPtr->recon_in_progress = 0;
400 1.29 oster raidPtr->maxOutstanding = cfgPtr->maxOutstandingDiskReqs;
401 1.29 oster
402 1.107 perry /* autoconfigure and root_partition will actually get filled in
403 1.29 oster after the config is done */
404 1.29 oster raidPtr->autoconfigure = 0;
405 1.29 oster raidPtr->root_partition = 0;
406 1.29 oster raidPtr->last_unit = raidPtr->raidid;
407 1.29 oster raidPtr->config_order = 0;
408 1.6 oster
409 1.6 oster if (rf_keepAccTotals) {
410 1.6 oster raidPtr->keep_acc_totals = 1;
411 1.6 oster }
412 1.1 oster
413 1.97 oster /* Allocate a bunch of buffers to be used in low-memory conditions */
414 1.97 oster raidPtr->iobuf = NULL;
415 1.103 oster
416 1.107 perry rc = rf_AllocEmergBuffers(raidPtr);
417 1.103 oster if (rc) {
418 1.103 oster printf("raid%d: Unable to allocate emergency buffers.\n",
419 1.103 oster raidPtr->raidid);
420 1.103 oster DO_RAID_FAIL();
421 1.103 oster return(rc);
422 1.103 oster }
423 1.103 oster
424 1.103 oster raidPtr->valid = 1;
425 1.103 oster
426 1.103 oster printf("raid%d: %s\n", raidPtr->raidid,
427 1.103 oster raidPtr->Layout.map->configName);
428 1.103 oster printf("raid%d: Components:", raidPtr->raidid);
429 1.103 oster
430 1.103 oster for (col = 0; col < raidPtr->numCol; col++) {
431 1.103 oster printf(" %s", raidPtr->Disks[col].devname);
432 1.103 oster if (RF_DEAD_DISK(raidPtr->Disks[col].status)) {
433 1.103 oster printf("[**FAILED**]");
434 1.103 oster }
435 1.103 oster }
436 1.103 oster printf("\n");
437 1.113.2.1 bouyer printf("raid%d: Total Sectors: %" PRIu64 " (%" PRIu64 " MB)\n",
438 1.103 oster raidPtr->raidid,
439 1.113.2.1 bouyer raidPtr->totalSectors,
440 1.113.2.1 bouyer (raidPtr->totalSectors / 1024 *
441 1.103 oster (1 << raidPtr->logBytesPerSector) / 1024));
442 1.103 oster
443 1.103 oster return (0);
444 1.103 oster }
445 1.103 oster
446 1.103 oster
447 1.103 oster /*
448 1.103 oster
449 1.103 oster Routines to allocate and free the "emergency buffers" for a given
450 1.103 oster RAID set. These emergency buffers will be used when the kernel runs
451 1.107 perry out of kernel memory.
452 1.107 perry
453 1.103 oster */
454 1.103 oster
455 1.107 perry static int
456 1.103 oster rf_AllocEmergBuffers(RF_Raid_t *raidPtr)
457 1.103 oster {
458 1.103 oster void *tmpbuf;
459 1.103 oster RF_VoidPointerListElem_t *vple;
460 1.103 oster int i;
461 1.103 oster
462 1.97 oster /* XXX next line needs tuning... */
463 1.97 oster raidPtr->numEmergencyBuffers = 10 * raidPtr->numCol;
464 1.97 oster #if DEBUG
465 1.97 oster printf("raid%d: allocating %d buffers of %d bytes.\n",
466 1.97 oster raidPtr->raidid,
467 1.107 perry raidPtr->numEmergencyBuffers,
468 1.107 perry (int)(raidPtr->Layout.sectorsPerStripeUnit <<
469 1.97 oster raidPtr->logBytesPerSector));
470 1.97 oster #endif
471 1.97 oster for (i = 0; i < raidPtr->numEmergencyBuffers; i++) {
472 1.107 perry tmpbuf = malloc( raidPtr->Layout.sectorsPerStripeUnit <<
473 1.107 perry raidPtr->logBytesPerSector,
474 1.111 oster M_RAIDFRAME, M_WAITOK);
475 1.97 oster if (tmpbuf) {
476 1.99 oster vple = rf_AllocVPListElem();
477 1.99 oster vple->p= tmpbuf;
478 1.99 oster vple->next = raidPtr->iobuf;
479 1.99 oster raidPtr->iobuf = vple;
480 1.97 oster raidPtr->iobuf_count++;
481 1.97 oster } else {
482 1.97 oster printf("raid%d: failed to allocate emergency buffer!\n",
483 1.97 oster raidPtr->raidid);
484 1.111 oster return 1;
485 1.97 oster }
486 1.97 oster }
487 1.97 oster
488 1.99 oster /* XXX next line needs tuning too... */
489 1.99 oster raidPtr->numEmergencyStripeBuffers = 10;
490 1.99 oster for (i = 0; i < raidPtr->numEmergencyStripeBuffers; i++) {
491 1.99 oster tmpbuf = malloc( raidPtr->numCol * (raidPtr->Layout.sectorsPerStripeUnit <<
492 1.99 oster raidPtr->logBytesPerSector),
493 1.111 oster M_RAIDFRAME, M_WAITOK);
494 1.99 oster if (tmpbuf) {
495 1.99 oster vple = rf_AllocVPListElem();
496 1.99 oster vple->p= tmpbuf;
497 1.99 oster vple->next = raidPtr->stripebuf;
498 1.99 oster raidPtr->stripebuf = vple;
499 1.99 oster raidPtr->stripebuf_count++;
500 1.99 oster } else {
501 1.99 oster printf("raid%d: failed to allocate emergency stripe buffer!\n",
502 1.99 oster raidPtr->raidid);
503 1.111 oster return 1;
504 1.99 oster }
505 1.99 oster }
506 1.107 perry
507 1.103 oster return (0);
508 1.103 oster }
509 1.99 oster
510 1.103 oster static void
511 1.103 oster rf_FreeEmergBuffers(RF_Raid_t *raidPtr)
512 1.103 oster {
513 1.103 oster RF_VoidPointerListElem_t *tmp;
514 1.99 oster
515 1.103 oster /* Free the emergency IO buffers */
516 1.103 oster while (raidPtr->iobuf != NULL) {
517 1.103 oster tmp = raidPtr->iobuf;
518 1.103 oster raidPtr->iobuf = raidPtr->iobuf->next;
519 1.103 oster free(tmp->p, M_RAIDFRAME);
520 1.103 oster rf_FreeVPListElem(tmp);
521 1.103 oster }
522 1.52 oster
523 1.103 oster /* Free the emergency stripe buffers */
524 1.103 oster while (raidPtr->stripebuf != NULL) {
525 1.103 oster tmp = raidPtr->stripebuf;
526 1.103 oster raidPtr->stripebuf = raidPtr->stripebuf->next;
527 1.103 oster free(tmp->p, M_RAIDFRAME);
528 1.103 oster rf_FreeVPListElem(tmp);
529 1.52 oster }
530 1.103 oster }
531 1.50 oster
532 1.1 oster
533 1.107 perry static void
534 1.113 christos rf_ShutdownRDFreeList(void *ignored)
535 1.1 oster {
536 1.89 oster pool_destroy(&rf_pools.rad);
537 1.1 oster }
538 1.1 oster
539 1.107 perry static int
540 1.80 oster rf_ConfigureRDFreeList(RF_ShutdownList_t **listp)
541 1.1 oster {
542 1.1 oster
543 1.89 oster rf_pool_init(&rf_pools.rad, sizeof(RF_RaidAccessDesc_t),
544 1.89 oster "rf_rad_pl", RF_MIN_FREE_RAD, RF_MAX_FREE_RAD);
545 1.86 oster rf_ShutdownCreate(listp, rf_ShutdownRDFreeList, NULL);
546 1.91 oster simple_lock_init(&rf_rad_lock);
547 1.6 oster return (0);
548 1.6 oster }
549 1.6 oster
550 1.6 oster RF_RaidAccessDesc_t *
551 1.80 oster rf_AllocRaidAccDesc(RF_Raid_t *raidPtr, RF_IoType_t type,
552 1.80 oster RF_RaidAddr_t raidAddress, RF_SectorCount_t numBlocks,
553 1.80 oster caddr_t bufPtr, void *bp, RF_RaidAccessFlags_t flags,
554 1.102 drochner const RF_AccessState_t *states)
555 1.6 oster {
556 1.6 oster RF_RaidAccessDesc_t *desc;
557 1.6 oster
558 1.89 oster desc = pool_get(&rf_pools.rad, PR_WAITOK);
559 1.73 oster
560 1.91 oster RF_LOCK_MUTEX(rf_rad_lock);
561 1.6 oster if (raidPtr->waitShutdown) {
562 1.6 oster /*
563 1.6 oster * Actually, we're shutting the array down. Free the desc
564 1.6 oster * and return NULL.
565 1.6 oster */
566 1.73 oster
567 1.91 oster RF_UNLOCK_MUTEX(rf_rad_lock);
568 1.89 oster pool_put(&rf_pools.rad, desc);
569 1.6 oster return (NULL);
570 1.6 oster }
571 1.6 oster raidPtr->nAccOutstanding++;
572 1.73 oster
573 1.91 oster RF_UNLOCK_MUTEX(rf_rad_lock);
574 1.6 oster
575 1.6 oster desc->raidPtr = (void *) raidPtr;
576 1.6 oster desc->type = type;
577 1.6 oster desc->raidAddress = raidAddress;
578 1.6 oster desc->numBlocks = numBlocks;
579 1.6 oster desc->bufPtr = bufPtr;
580 1.6 oster desc->bp = bp;
581 1.6 oster desc->flags = flags;
582 1.6 oster desc->states = states;
583 1.6 oster desc->state = 0;
584 1.99 oster desc->dagList = NULL;
585 1.6 oster
586 1.6 oster desc->status = 0;
587 1.105 oster desc->numRetries = 0;
588 1.87 oster #if RF_ACC_TRACE > 0
589 1.40 thorpej memset((char *) &desc->tracerec, 0, sizeof(RF_AccTraceEntry_t));
590 1.87 oster #endif
591 1.41 oster desc->callbackFunc = NULL;
592 1.41 oster desc->callbackArg = NULL;
593 1.6 oster desc->next = NULL;
594 1.99 oster desc->iobufs = NULL;
595 1.99 oster desc->stripebufs = NULL;
596 1.99 oster
597 1.6 oster return (desc);
598 1.6 oster }
599 1.6 oster
600 1.107 perry void
601 1.80 oster rf_FreeRaidAccDesc(RF_RaidAccessDesc_t *desc)
602 1.6 oster {
603 1.6 oster RF_Raid_t *raidPtr = desc->raidPtr;
604 1.85 oster RF_DagList_t *dagList, *temp;
605 1.99 oster RF_VoidPointerListElem_t *tmp;
606 1.6 oster
607 1.6 oster RF_ASSERT(desc);
608 1.6 oster
609 1.85 oster /* Cleanup the dagList(s) */
610 1.85 oster dagList = desc->dagList;
611 1.85 oster while(dagList != NULL) {
612 1.85 oster temp = dagList;
613 1.85 oster dagList = dagList->next;
614 1.85 oster rf_FreeDAGList(temp);
615 1.85 oster }
616 1.85 oster
617 1.99 oster while (desc->iobufs) {
618 1.99 oster tmp = desc->iobufs;
619 1.99 oster desc->iobufs = desc->iobufs->next;
620 1.99 oster rf_FreeIOBuffer(raidPtr, tmp);
621 1.99 oster }
622 1.99 oster
623 1.99 oster while (desc->stripebufs) {
624 1.99 oster tmp = desc->stripebufs;
625 1.99 oster desc->stripebufs = desc->stripebufs->next;
626 1.99 oster rf_FreeStripeBuffer(raidPtr, tmp);
627 1.99 oster }
628 1.99 oster
629 1.89 oster pool_put(&rf_pools.rad, desc);
630 1.91 oster RF_LOCK_MUTEX(rf_rad_lock);
631 1.6 oster raidPtr->nAccOutstanding--;
632 1.6 oster if (raidPtr->waitShutdown) {
633 1.6 oster RF_SIGNAL_COND(raidPtr->outstandingCond);
634 1.6 oster }
635 1.91 oster RF_UNLOCK_MUTEX(rf_rad_lock);
636 1.1 oster }
637 1.1 oster /*********************************************************************
638 1.1 oster * Main routine for performing an access.
639 1.1 oster * Accesses are retried until a DAG can not be selected. This occurs
640 1.1 oster * when either the DAG library is incomplete or there are too many
641 1.1 oster * failures in a parity group.
642 1.80 oster *
643 1.80 oster * type should be read or write async_flag should be RF_TRUE or
644 1.80 oster * RF_FALSE bp_in is a buf pointer. void * to facilitate ignoring it
645 1.80 oster * outside the kernel
646 1.1 oster ********************************************************************/
647 1.107 perry int
648 1.80 oster rf_DoAccess(RF_Raid_t * raidPtr, RF_IoType_t type, int async_flag,
649 1.80 oster RF_RaidAddr_t raidAddress, RF_SectorCount_t numBlocks,
650 1.106 oster caddr_t bufPtr, struct buf *bp, RF_RaidAccessFlags_t flags)
651 1.1 oster {
652 1.6 oster RF_RaidAccessDesc_t *desc;
653 1.6 oster caddr_t lbufPtr = bufPtr;
654 1.6 oster
655 1.6 oster raidAddress += rf_raidSectorOffset;
656 1.6 oster
657 1.61 oster #if RF_ACCESS_DEBUG
658 1.6 oster if (rf_accessDebug) {
659 1.1 oster
660 1.6 oster printf("logBytes is: %d %d %d\n", raidPtr->raidid,
661 1.6 oster raidPtr->logBytesPerSector,
662 1.6 oster (int) rf_RaidAddressToByte(raidPtr, numBlocks));
663 1.22 oster printf("raid%d: %s raidAddr %d (stripeid %d-%d) numBlocks %d (%d bytes) buf 0x%lx\n", raidPtr->raidid,
664 1.6 oster (type == RF_IO_TYPE_READ) ? "READ" : "WRITE", (int) raidAddress,
665 1.6 oster (int) rf_RaidAddressToStripeID(&raidPtr->Layout, raidAddress),
666 1.6 oster (int) rf_RaidAddressToStripeID(&raidPtr->Layout, raidAddress + numBlocks - 1),
667 1.6 oster (int) numBlocks,
668 1.6 oster (int) rf_RaidAddressToByte(raidPtr, numBlocks),
669 1.6 oster (long) bufPtr);
670 1.6 oster }
671 1.61 oster #endif
672 1.1 oster
673 1.6 oster desc = rf_AllocRaidAccDesc(raidPtr, type, raidAddress,
674 1.41 oster numBlocks, lbufPtr, bp, flags, raidPtr->Layout.map->states);
675 1.1 oster
676 1.6 oster if (desc == NULL) {
677 1.6 oster return (ENOMEM);
678 1.6 oster }
679 1.87 oster #if RF_ACC_TRACE > 0
680 1.6 oster RF_ETIMER_START(desc->tracerec.tot_timer);
681 1.87 oster #endif
682 1.6 oster desc->async_flag = async_flag;
683 1.3 explorer
684 1.6 oster rf_ContinueRaidAccess(desc);
685 1.1 oster
686 1.6 oster return (0);
687 1.1 oster }
688 1.46 oster #if 0
689 1.1 oster /* force the array into reconfigured mode without doing reconstruction */
690 1.107 perry int
691 1.80 oster rf_SetReconfiguredMode(RF_Raid_t *raidPtr, int col)
692 1.6 oster {
693 1.6 oster if (!(raidPtr->Layout.map->flags & RF_DISTRIBUTE_SPARE)) {
694 1.6 oster printf("Can't set reconfigured mode in dedicated-spare array\n");
695 1.6 oster RF_PANIC();
696 1.6 oster }
697 1.6 oster RF_LOCK_MUTEX(raidPtr->mutex);
698 1.6 oster raidPtr->numFailures++;
699 1.72 oster raidPtr->Disks[col].status = rf_ds_dist_spared;
700 1.72 oster raidPtr->status = rf_rs_reconfigured;
701 1.37 oster rf_update_component_labels(raidPtr, RF_NORMAL_COMPONENT_UPDATE);
702 1.6 oster /* install spare table only if declustering + distributed sparing
703 1.6 oster * architecture. */
704 1.6 oster if (raidPtr->Layout.map->flags & RF_BD_DECLUSTERED)
705 1.72 oster rf_InstallSpareTable(raidPtr, col);
706 1.6 oster RF_UNLOCK_MUTEX(raidPtr->mutex);
707 1.6 oster return (0);
708 1.1 oster }
709 1.46 oster #endif
710 1.1 oster
711 1.107 perry int
712 1.80 oster rf_FailDisk(RF_Raid_t *raidPtr, int fcol, int initRecon)
713 1.6 oster {
714 1.98 oster
715 1.98 oster /* need to suspend IO's here -- if there are DAGs in flight
716 1.107 perry and we pull the rug out from under ci_vp, Bad Things
717 1.98 oster can happen. */
718 1.98 oster
719 1.98 oster rf_SuspendNewRequestsAndWait(raidPtr);
720 1.98 oster
721 1.6 oster RF_LOCK_MUTEX(raidPtr->mutex);
722 1.72 oster if (raidPtr->Disks[fcol].status != rf_ds_failed) {
723 1.68 oster /* must be failing something that is valid, or else it's
724 1.107 perry already marked as failed (in which case we don't
725 1.68 oster want to mark it failed again!) */
726 1.68 oster raidPtr->numFailures++;
727 1.72 oster raidPtr->Disks[fcol].status = rf_ds_failed;
728 1.107 perry raidPtr->status = rf_rs_degraded;
729 1.68 oster }
730 1.65 oster RF_UNLOCK_MUTEX(raidPtr->mutex);
731 1.107 perry
732 1.37 oster rf_update_component_labels(raidPtr, RF_NORMAL_COMPONENT_UPDATE);
733 1.107 perry
734 1.107 perry /* Close the component, so that it's not "locked" if someone
735 1.56 oster else want's to use it! */
736 1.56 oster
737 1.72 oster rf_close_component(raidPtr, raidPtr->raid_cinfo[fcol].ci_vp,
738 1.72 oster raidPtr->Disks[fcol].auto_configured);
739 1.65 oster
740 1.65 oster RF_LOCK_MUTEX(raidPtr->mutex);
741 1.72 oster raidPtr->raid_cinfo[fcol].ci_vp = NULL;
742 1.56 oster
743 1.107 perry /* Need to mark the component as not being auto_configured
744 1.56 oster (in case it was previously). */
745 1.56 oster
746 1.72 oster raidPtr->Disks[fcol].auto_configured = 0;
747 1.65 oster RF_UNLOCK_MUTEX(raidPtr->mutex);
748 1.98 oster /* now we can allow IO to continue -- we'll be suspending it
749 1.98 oster again in rf_ReconstructFailedDisk() if we have to.. */
750 1.98 oster
751 1.98 oster rf_ResumeNewRequests(raidPtr);
752 1.56 oster
753 1.6 oster if (initRecon)
754 1.72 oster rf_ReconstructFailedDisk(raidPtr, fcol);
755 1.6 oster return (0);
756 1.1 oster }
757 1.1 oster /* releases a thread that is waiting for the array to become quiesced.
758 1.1 oster * access_suspend_mutex should be locked upon calling this
759 1.1 oster */
760 1.107 perry void
761 1.80 oster rf_SignalQuiescenceLock(RF_Raid_t *raidPtr)
762 1.6 oster {
763 1.61 oster #if RF_DEBUG_QUIESCE
764 1.6 oster if (rf_quiesceDebug) {
765 1.107 perry printf("raid%d: Signalling quiescence lock\n",
766 1.22 oster raidPtr->raidid);
767 1.6 oster }
768 1.61 oster #endif
769 1.6 oster raidPtr->access_suspend_release = 1;
770 1.6 oster
771 1.6 oster if (raidPtr->waiting_for_quiescence) {
772 1.6 oster SIGNAL_QUIESCENT_COND(raidPtr);
773 1.6 oster }
774 1.1 oster }
775 1.1 oster /* suspends all new requests to the array. No effect on accesses that are in flight. */
776 1.107 perry int
777 1.80 oster rf_SuspendNewRequestsAndWait(RF_Raid_t *raidPtr)
778 1.6 oster {
779 1.61 oster #if RF_DEBUG_QUIESCE
780 1.6 oster if (rf_quiesceDebug)
781 1.53 oster printf("raid%d: Suspending new reqs\n", raidPtr->raidid);
782 1.61 oster #endif
783 1.6 oster RF_LOCK_MUTEX(raidPtr->access_suspend_mutex);
784 1.6 oster raidPtr->accesses_suspended++;
785 1.6 oster raidPtr->waiting_for_quiescence = (raidPtr->accs_in_flight == 0) ? 0 : 1;
786 1.6 oster
787 1.6 oster if (raidPtr->waiting_for_quiescence) {
788 1.6 oster raidPtr->access_suspend_release = 0;
789 1.6 oster while (!raidPtr->access_suspend_release) {
790 1.93 oster #if RF_DEBUG_QUIESCE
791 1.53 oster printf("raid%d: Suspending: Waiting for Quiescence\n",
792 1.53 oster raidPtr->raidid);
793 1.93 oster #endif
794 1.6 oster WAIT_FOR_QUIESCENCE(raidPtr);
795 1.6 oster raidPtr->waiting_for_quiescence = 0;
796 1.6 oster }
797 1.6 oster }
798 1.93 oster #if RF_DEBUG_QUIESCE
799 1.53 oster printf("raid%d: Quiescence reached..\n", raidPtr->raidid);
800 1.93 oster #endif
801 1.1 oster
802 1.6 oster RF_UNLOCK_MUTEX(raidPtr->access_suspend_mutex);
803 1.6 oster return (raidPtr->waiting_for_quiescence);
804 1.1 oster }
805 1.1 oster /* wake up everyone waiting for quiescence to be released */
806 1.107 perry void
807 1.80 oster rf_ResumeNewRequests(RF_Raid_t *raidPtr)
808 1.6 oster {
809 1.6 oster RF_CallbackDesc_t *t, *cb;
810 1.6 oster
811 1.61 oster #if RF_DEBUG_QUIESCE
812 1.6 oster if (rf_quiesceDebug)
813 1.6 oster printf("Resuming new reqs\n");
814 1.61 oster #endif
815 1.6 oster
816 1.6 oster RF_LOCK_MUTEX(raidPtr->access_suspend_mutex);
817 1.6 oster raidPtr->accesses_suspended--;
818 1.6 oster if (raidPtr->accesses_suspended == 0)
819 1.6 oster cb = raidPtr->quiesce_wait_list;
820 1.6 oster else
821 1.6 oster cb = NULL;
822 1.6 oster raidPtr->quiesce_wait_list = NULL;
823 1.6 oster RF_UNLOCK_MUTEX(raidPtr->access_suspend_mutex);
824 1.6 oster
825 1.6 oster while (cb) {
826 1.6 oster t = cb;
827 1.6 oster cb = cb->next;
828 1.6 oster (t->callbackFunc) (t->callbackArg);
829 1.6 oster rf_FreeCallbackDesc(t);
830 1.6 oster }
831 1.1 oster }
832 1.1 oster /*****************************************************************************************
833 1.1 oster *
834 1.1 oster * debug routines
835 1.1 oster *
836 1.1 oster ****************************************************************************************/
837 1.1 oster
838 1.107 perry static void
839 1.80 oster set_debug_option(char *name, long val)
840 1.6 oster {
841 1.6 oster RF_DebugName_t *p;
842 1.6 oster
843 1.6 oster for (p = rf_debugNames; p->name; p++) {
844 1.6 oster if (!strcmp(p->name, name)) {
845 1.6 oster *(p->ptr) = val;
846 1.6 oster printf("[Set debug variable %s to %ld]\n", name, val);
847 1.6 oster return;
848 1.6 oster }
849 1.6 oster }
850 1.6 oster RF_ERRORMSG1("Unknown debug string \"%s\"\n", name);
851 1.1 oster }
852 1.1 oster
853 1.1 oster
854 1.1 oster /* would like to use sscanf here, but apparently not available in kernel */
855 1.1 oster /*ARGSUSED*/
856 1.107 perry static void
857 1.80 oster rf_ConfigureDebug(RF_Config_t *cfgPtr)
858 1.6 oster {
859 1.6 oster char *val_p, *name_p, *white_p;
860 1.6 oster long val;
861 1.6 oster int i;
862 1.6 oster
863 1.6 oster rf_ResetDebugOptions();
864 1.6 oster for (i = 0; cfgPtr->debugVars[i][0] && i < RF_MAXDBGV; i++) {
865 1.6 oster name_p = rf_find_non_white(&cfgPtr->debugVars[i][0]);
866 1.6 oster white_p = rf_find_white(name_p); /* skip to start of 2nd
867 1.6 oster * word */
868 1.6 oster val_p = rf_find_non_white(white_p);
869 1.6 oster if (*val_p == '0' && *(val_p + 1) == 'x')
870 1.6 oster val = rf_htoi(val_p + 2);
871 1.6 oster else
872 1.6 oster val = rf_atoi(val_p);
873 1.6 oster *white_p = '\0';
874 1.6 oster set_debug_option(name_p, val);
875 1.6 oster }
876 1.1 oster }
877 1.39 oster
878 1.39 oster void
879 1.108 christos rf_print_panic_message(int line, const char *file)
880 1.39 oster {
881 1.101 itojun snprintf(rf_panicbuf, sizeof(rf_panicbuf),
882 1.101 itojun "raidframe error at line %d file %s", line, file);
883 1.39 oster }
884 1.39 oster
885 1.62 oster #ifdef RAID_DIAGNOSTIC
886 1.39 oster void
887 1.108 christos rf_print_assert_panic_message(int line, const char *file, const char *condition)
888 1.39 oster {
889 1.101 itojun snprintf(rf_panicbuf, sizeof(rf_panicbuf),
890 1.39 oster "raidframe error at line %d file %s (failed asserting %s)\n",
891 1.39 oster line, file, condition);
892 1.58 oster }
893 1.62 oster #endif
894 1.58 oster
895 1.58 oster void
896 1.108 christos rf_print_unable_to_init_mutex(const char *file, int line, int rc)
897 1.58 oster {
898 1.58 oster RF_ERRORMSG3("Unable to init mutex file %s line %d rc=%d\n",
899 1.58 oster file, line, rc);
900 1.58 oster }
901 1.58 oster
902 1.58 oster void
903 1.108 christos rf_print_unable_to_add_shutdown(const char *file, int line, int rc)
904 1.58 oster {
905 1.58 oster RF_ERRORMSG3("Unable to add to shutdown list file %s line %d rc=%d\n",
906 1.58 oster file, line, rc);
907 1.1 oster }
908