Mercurial > illumos > onarm
comparison usr/src/cmd/lvm/rpc.metamhd/mhd_set.c @ 0:c9caec207d52 b86
Initial porting based on b86
author | Koji Uno <koji.uno@sun.com> |
---|---|
date | Tue, 02 Jun 2009 18:56:50 +0900 |
parents | |
children | 1a15d5aaf794 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:c9caec207d52 |
---|---|
1 /* | |
2 * CDDL HEADER START | |
3 * | |
4 * The contents of this file are subject to the terms of the | |
5 * Common Development and Distribution License, Version 1.0 only | |
6 * (the "License"). You may not use this file except in compliance | |
7 * with the License. | |
8 * | |
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE | |
10 * or http://www.opensolaris.org/os/licensing. | |
11 * See the License for the specific language governing permissions | |
12 * and limitations under the License. | |
13 * | |
14 * When distributing Covered Code, include this CDDL HEADER in each | |
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. | |
16 * If applicable, add the following below this CDDL HEADER, with the | |
17 * fields enclosed by brackets "[]" replaced with your own identifying | |
18 * information: Portions Copyright [yyyy] [name of copyright owner] | |
19 * | |
20 * CDDL HEADER END | |
21 */ | |
22 /* | |
23 * Copyright 2003 Sun Microsystems, Inc. All rights reserved. | |
24 * Use is subject to license terms. | |
25 */ | |
26 | |
27 #pragma ident "@(#)mhd_set.c 2.6 05/06/08 SMI" | |
28 | |
29 #include "mhd_local.h" | |
30 | |
31 /* | |
32 * manipulate set list | |
33 */ | |
34 | |
35 /* | |
36 * global set list | |
37 */ | |
38 static mutex_t mhd_set_mx = DEFAULTMUTEX; | |
39 static uint_t mhd_nset = 0; | |
40 static mhd_drive_set_t **mhd_sets = NULL; | |
41 | |
42 /* | |
43 * add drive to set | |
44 */ | |
45 void | |
46 mhd_add_drive_to_set( | |
47 mhd_drive_set_t *sp, | |
48 mhd_drive_t *dp | |
49 ) | |
50 { | |
51 mhd_drive_list_t *dlp = &sp->sr_drives; | |
52 | |
53 /* check locks */ | |
54 assert(MUTEX_HELD(&mhd_set_mx)); | |
55 assert(MUTEX_HELD(&sp->sr_mx)); | |
56 assert(DRIVE_IS_IDLE(dp)); | |
57 | |
58 /* add to set */ | |
59 mhd_add_drive(dlp, dp); | |
60 | |
61 /* adjust backlink */ | |
62 dp->dr_sp = sp; | |
63 } | |
64 | |
65 /* | |
66 * delete drive from set | |
67 */ | |
68 void | |
69 mhd_del_drive_from_set( | |
70 mhd_drive_t *dp | |
71 ) | |
72 { | |
73 mhd_drive_set_t *sp = dp->dr_sp; | |
74 mhd_drive_list_t *dlp = &sp->sr_drives; | |
75 | |
76 /* check locks */ | |
77 assert(MUTEX_HELD(&mhd_set_mx)); | |
78 assert(MUTEX_HELD(&sp->sr_mx)); | |
79 assert(DRIVE_IS_IDLE(dp)); | |
80 | |
81 /* delete from set */ | |
82 mhd_del_drive(dlp, dp); | |
83 | |
84 /* adjust backlink */ | |
85 dp->dr_sp = NULL; | |
86 } | |
87 | |
88 /* | |
89 * find set in list | |
90 */ | |
91 static mhd_drive_set_t * | |
92 mhd_find_set( | |
93 char *setname | |
94 ) | |
95 { | |
96 uint_t i; | |
97 | |
98 /* check lock */ | |
99 assert(MUTEX_HELD(&mhd_set_mx)); | |
100 | |
101 /* look for set */ | |
102 for (i = 0; (i < mhd_nset); ++i) { | |
103 mhd_drive_set_t *sp = mhd_sets[i]; | |
104 | |
105 if (strcmp(setname, sp->sr_name) == 0) | |
106 return (sp); | |
107 } | |
108 | |
109 /* not found */ | |
110 return (NULL); | |
111 } | |
112 | |
113 /* | |
114 * wait for operation to complete | |
115 */ | |
116 static void | |
117 mhd_wait_set( | |
118 mhd_drive_set_t *sp, | |
119 mhd_drive_list_t *dlp, | |
120 mhd_state_t state | |
121 ) | |
122 { | |
123 /* check lock */ | |
124 assert(MUTEX_HELD(&mhd_set_mx)); | |
125 assert(MUTEX_HELD(&sp->sr_mx)); | |
126 | |
127 /* wait for complete */ | |
128 for (;;) { | |
129 uint_t cnt = 0; | |
130 uint_t i; | |
131 | |
132 /* kick threads */ | |
133 for (i = 0; (i < dlp->dl_ndrive); ++i) { | |
134 mhd_drive_t *dp = dlp->dl_drives[i]; | |
135 | |
136 /* IDLE or ERRORED */ | |
137 if (state == DRIVE_IDLE) { | |
138 if (DRIVE_IS_IDLE(dp)) | |
139 continue; | |
140 } | |
141 | |
142 /* operation complete */ | |
143 else { | |
144 if (! (dp->dr_state & state)) | |
145 continue; | |
146 } | |
147 | |
148 /* kick thread */ | |
149 mhd_cv_broadcast(&dp->dr_cv); | |
150 ++cnt; | |
151 } | |
152 | |
153 /* if complete, quit */ | |
154 if (cnt == 0) | |
155 break; | |
156 | |
157 /* wait for something to happen */ | |
158 (void) mhd_cv_wait(&sp->sr_cv, &sp->sr_mx); | |
159 } | |
160 } | |
161 | |
162 /* | |
163 * idle set | |
164 */ | |
165 static int | |
166 mhd_idle_set( | |
167 mhd_drive_set_t *sp, | |
168 mhd_drive_list_t *dlp, | |
169 mhd_error_t *mhep | |
170 ) | |
171 { | |
172 uint_t i; | |
173 | |
174 /* check lock */ | |
175 assert(MUTEX_HELD(&mhd_set_mx)); | |
176 assert(MUTEX_HELD(&sp->sr_mx)); | |
177 | |
178 /* disarm any failfast */ | |
179 if (dlp->dl_ndrive >= sp->sr_drives.dl_ndrive) { | |
180 if (mhd_ff_disarm(sp, mhep) != 0) | |
181 return (-1); | |
182 } | |
183 | |
184 /* set IDLING */ | |
185 for (i = 0; (i < dlp->dl_ndrive); ++i) { | |
186 mhd_drive_t *dp = dlp->dl_drives[i]; | |
187 | |
188 if (! DRIVE_IS_IDLE(dp)) { | |
189 if (mhd_state(dp, DRIVE_IDLING, mhep) != 0) | |
190 return (-1); | |
191 } | |
192 } | |
193 | |
194 /* wait for IDLE */ | |
195 mhd_wait_set(sp, dlp, DRIVE_IDLE); | |
196 | |
197 /* return success */ | |
198 return (0); | |
199 } | |
200 | |
201 /* | |
202 * create or update new set | |
203 */ | |
204 mhd_drive_set_t * | |
205 mhd_create_set( | |
206 mhd_set_t *mhsp, | |
207 mhd_opts_t options, | |
208 mhd_drive_list_t *dlp, | |
209 mhd_error_t *mhep | |
210 ) | |
211 { | |
212 char *setname; | |
213 mhd_drive_set_t *sp; | |
214 mhd_drive_list_t *sp_dlp; | |
215 mhd_drive_set_t *null_sp; | |
216 uint_t i; | |
217 | |
218 /* check locks */ | |
219 assert(MUTEX_HELD(&mhd_set_mx)); | |
220 | |
221 /* get setname */ | |
222 if (mhsp == NULL) | |
223 setname = ""; | |
224 else | |
225 setname = mhsp->setname; | |
226 | |
227 /* find or create set */ | |
228 if ((sp = mhd_find_set(setname)) == NULL) { | |
229 /* allocate and initialize set */ | |
230 sp = Zalloc(sizeof (*sp)); | |
231 sp->sr_name = Strdup(setname); | |
232 mhd_mx_init(&sp->sr_mx); | |
233 mhd_cv_init(&sp->sr_cv); | |
234 sp->sr_ff = -1; | |
235 | |
236 /* append to set list */ | |
237 ++mhd_nset; | |
238 mhd_sets = Realloc(mhd_sets, (mhd_nset * sizeof (*mhd_sets))); | |
239 mhd_sets[mhd_nset - 1] = sp; | |
240 } | |
241 sp_dlp = &sp->sr_drives; | |
242 | |
243 /* if just grabbing null set, return */ | |
244 if (mhsp == NULL) | |
245 return (sp); | |
246 assert(strcmp(setname, "") != 0); | |
247 assert(mhep != NULL); | |
248 | |
249 /* get null set */ | |
250 null_sp = mhd_create_set(NULL, 0, NULL, NULL); | |
251 assert(null_sp != NULL); | |
252 assert(sp != null_sp); | |
253 | |
254 /* grab set lock */ | |
255 mhd_mx_lock(&sp->sr_mx); | |
256 | |
257 /* save options */ | |
258 if (options & MHD_SERIAL) | |
259 sp->sr_options |= MHD_SERIAL; | |
260 else | |
261 sp->sr_options &= ~MHD_SERIAL; | |
262 | |
263 /* move drives no longer in set to null set */ | |
264 if (! (options & MHD_PARTIAL_SET)) { | |
265 for (i = 0; (i < sp_dlp->dl_ndrive); /* void */) { | |
266 mhd_drive_t *dp = sp_dlp->dl_drives[i]; | |
267 uint_t j; | |
268 | |
269 /* check still there */ | |
270 for (j = 0; (j < mhsp->drives.drives_len); ++j) { | |
271 mhd_drivename_t mhdp; | |
272 | |
273 mhdp = mhsp->drives.drives_val[j]; | |
274 if (strcmp(dp->dr_rname, mhdp) == 0) | |
275 break; | |
276 } | |
277 if (j < mhsp->drives.drives_len) { | |
278 ++i; | |
279 continue; | |
280 } | |
281 | |
282 /* idle the drive */ | |
283 if (mhd_idle(dp, mhep) != 0) | |
284 mhd_clrerror(mhep); | |
285 | |
286 /* move to null set */ | |
287 mhd_del_drive_from_set(dp); | |
288 mhd_mx_unlock(&sp->sr_mx); | |
289 mhd_mx_lock(&null_sp->sr_mx); | |
290 mhd_add_drive_to_set(null_sp, dp); | |
291 mhd_mx_unlock(&null_sp->sr_mx); | |
292 mhd_mx_lock(&sp->sr_mx); | |
293 } | |
294 } | |
295 | |
296 /* add new drives to lists */ | |
297 for (i = 0; (i < mhsp->drives.drives_len); ++i) { | |
298 mhd_drivename_t mhdp = mhsp->drives.drives_val[i]; | |
299 uint_t j; | |
300 mhd_drive_t *dp; | |
301 | |
302 /* check already there */ | |
303 for (j = 0; (j < dlp->dl_ndrive); ++j) { | |
304 dp = dlp->dl_drives[j]; | |
305 if (strcmp(mhdp, dp->dr_rname) == 0) | |
306 break; | |
307 } | |
308 if (j < dlp->dl_ndrive) { | |
309 mhd_add_drive(dlp, dp); | |
310 continue; | |
311 } | |
312 | |
313 /* add drive to set */ | |
314 if ((dp = mhd_create_drive(sp, mhdp, NULL, mhep)) == NULL) { | |
315 mhde_perror(mhep, "mhd_create_drive: %s", mhdp); | |
316 continue; | |
317 } | |
318 mhd_add_drive(dlp, dp); | |
319 } | |
320 | |
321 /* debug */ | |
322 #ifdef MHD_DEBUG | |
323 if (mhd_debug > 0) { | |
324 for (i = 0; (i < mhd_nset); ++i) { | |
325 mhd_drive_set_t *sp = mhd_sets[i]; | |
326 mhd_drive_list_t *dlp = &sp->sr_drives; | |
327 char buf[10240]; | |
328 uint_t j; | |
329 | |
330 (void) snprintf(buf, sizeof (buf), "set '%s':", | |
331 sp->sr_name); | |
332 for (j = 0; (j < dlp->dl_ndrive); ++j) { | |
333 mhd_drive_t *dp = dlp->dl_drives[j]; | |
334 char *p; | |
335 | |
336 if ((p = strrchr(dp->dr_rname, '/')) != NULL) | |
337 ++p; | |
338 else | |
339 p = dp->dr_rname; | |
340 (void) strncat(buf, " ", sizeof (buf)); | |
341 (void) strncat(buf, p, sizeof (buf)); | |
342 } | |
343 buf[sizeof (buf) - 1] = '\0'; | |
344 mhd_eprintf("%s\n", buf); | |
345 } | |
346 } | |
347 #endif /* MHD_DEBUG */ | |
348 | |
349 /* unlock, return set */ | |
350 mhd_mx_unlock(&sp->sr_mx); | |
351 return (sp); | |
352 } | |
353 | |
354 /* | |
355 * find drive | |
356 */ | |
357 mhd_drive_t * | |
358 mhd_find_drive( | |
359 char *rname | |
360 ) | |
361 { | |
362 uint_t i; | |
363 | |
364 /* check locks */ | |
365 assert(MUTEX_HELD(&mhd_set_mx)); | |
366 | |
367 /* for each set */ | |
368 for (i = 0; (i < mhd_nset); ++i) { | |
369 mhd_drive_set_t *sp = mhd_sets[i]; | |
370 mhd_drive_list_t *dlp = &sp->sr_drives; | |
371 uint_t j; | |
372 | |
373 /* for each drive */ | |
374 for (j = 0; (j < dlp->dl_ndrive); ++j) { | |
375 mhd_drive_t *dp = dlp->dl_drives[j]; | |
376 | |
377 if (strcmp(rname, dp->dr_rname) == 0) | |
378 return (dp); | |
379 } | |
380 } | |
381 | |
382 /* not found */ | |
383 return (NULL); | |
384 } | |
385 | |
386 /* | |
387 * list all the drives | |
388 */ | |
389 int | |
390 mhd_list_drives( | |
391 char *path, | |
392 mhd_did_flags_t flags, | |
393 mhd_list_res_t *resultsp, | |
394 mhd_error_t *mhep | |
395 ) | |
396 { | |
397 mhd_state_t state; | |
398 uint_t ndrive, i, j, c; | |
399 | |
400 /* grab lock */ | |
401 mhd_mx_lock(&mhd_set_mx); | |
402 | |
403 /* add path to list */ | |
404 if (mhd_create_drives(path, mhep) != 0) { | |
405 mhd_mx_unlock(&mhd_set_mx); | |
406 return (-1); | |
407 } | |
408 | |
409 /* get what we want */ | |
410 state = 0; | |
411 if (flags & MHD_DID_SERIAL) | |
412 state |= DRIVE_SERIALING; | |
413 if (flags & MHD_DID_TIME) | |
414 state |= DRIVE_VTOCING; | |
415 if (flags & MHD_DID_CINFO) | |
416 state |= DRIVE_CINFOING; | |
417 | |
418 /* ident and count drives */ | |
419 for (ndrive = 0, i = 0; (i < mhd_nset); ++i) { | |
420 mhd_drive_set_t *sp = mhd_sets[i]; | |
421 mhd_drive_list_t *dlp = &sp->sr_drives; | |
422 | |
423 /* count drives */ | |
424 ndrive += dlp->dl_ndrive; | |
425 | |
426 /* ident drives */ | |
427 if (state != 0) { | |
428 mhd_mx_lock(&sp->sr_mx); | |
429 for (j = 0; (j < dlp->dl_ndrive); ++j) { | |
430 mhd_drive_t *dp = dlp->dl_drives[j]; | |
431 | |
432 if (mhd_state_set(dp, state, mhep) != 0) { | |
433 mhd_mx_unlock(&sp->sr_mx); | |
434 mhd_mx_unlock(&mhd_set_mx); | |
435 return (-1); | |
436 } | |
437 } | |
438 mhd_wait_set(sp, dlp, state); | |
439 mhd_mx_unlock(&sp->sr_mx); | |
440 } | |
441 } | |
442 | |
443 /* build list */ | |
444 assert(resultsp->results.mhd_drive_info_list_t_len == 0); | |
445 assert(resultsp->results.mhd_drive_info_list_t_val == NULL); | |
446 resultsp->results.mhd_drive_info_list_t_len = ndrive; | |
447 resultsp->results.mhd_drive_info_list_t_val = Zalloc( | |
448 ndrive * sizeof (*resultsp->results.mhd_drive_info_list_t_val)); | |
449 for (c = 0, i = 0; (i < mhd_nset); ++i) { | |
450 mhd_drive_set_t *sp = mhd_sets[i]; | |
451 mhd_drive_list_t *dlp = &sp->sr_drives; | |
452 | |
453 mhd_mx_lock(&sp->sr_mx); | |
454 for (j = 0; (j < dlp->dl_ndrive); ++j) { | |
455 mhd_drive_t *dp = dlp->dl_drives[j]; | |
456 mhd_drive_info_t *ip = | |
457 &resultsp->results.mhd_drive_info_list_t_val[c++]; | |
458 | |
459 ip->dif_name = Strdup(dp->dr_rname); | |
460 ip->dif_id = dp->dr_drive_id; | |
461 } | |
462 mhd_mx_unlock(&sp->sr_mx); | |
463 } | |
464 assert(c == ndrive); | |
465 | |
466 /* unlock, return count */ | |
467 mhd_mx_unlock(&mhd_set_mx); | |
468 return (ndrive); | |
469 } | |
470 | |
471 /* | |
472 * release drives | |
473 */ | |
474 static int | |
475 mhd_release_set( | |
476 mhd_drive_set_t *sp, | |
477 mhd_drive_list_t *dlp, | |
478 mhd_error_t *mhep | |
479 ) | |
480 { | |
481 uint_t i; | |
482 | |
483 /* check locks */ | |
484 assert(MUTEX_HELD(&mhd_set_mx)); | |
485 assert(MUTEX_HELD(&sp->sr_mx)); | |
486 | |
487 /* idle set */ | |
488 if (mhd_idle_set(sp, dlp, mhep) != 0) | |
489 return (-1); | |
490 | |
491 /* release drives */ | |
492 for (i = 0; (i < dlp->dl_ndrive); i++) { | |
493 mhd_drive_t *dp = dlp->dl_drives[i]; | |
494 | |
495 if (mhd_state(dp, DRIVE_RELEASING, mhep) != 0) | |
496 return (-1); | |
497 } | |
498 mhd_wait_set(sp, dlp, DRIVE_IDLE); | |
499 | |
500 /* return success */ | |
501 return (0); | |
502 } | |
503 | |
504 /* | |
505 * release drives in set | |
506 */ | |
507 int | |
508 mhd_release_drives( | |
509 mhd_set_t *mhsp, | |
510 mhd_opts_t options, | |
511 mhd_error_t *mhep | |
512 ) | |
513 { | |
514 mhd_drive_list_t dl = mhd_null_list; | |
515 mhd_drive_set_t *sp; | |
516 int rval; | |
517 | |
518 /* grab global lock */ | |
519 mhd_mx_lock(&mhd_set_mx); | |
520 | |
521 /* create or update set */ | |
522 if ((sp = mhd_create_set(mhsp, options, &dl, mhep)) == NULL) { | |
523 mhd_mx_unlock(&mhd_set_mx); | |
524 mhd_free_list(&dl); | |
525 return (-1); | |
526 } | |
527 | |
528 /* lock set */ | |
529 mhd_mx_lock(&sp->sr_mx); | |
530 | |
531 /* release drives */ | |
532 rval = mhd_release_set(sp, &dl, mhep); | |
533 | |
534 /* unlock, return success */ | |
535 out: | |
536 mhd_mx_unlock(&sp->sr_mx); | |
537 mhd_mx_unlock(&mhd_set_mx); | |
538 mhd_free_list(&dl); | |
539 return (rval); | |
540 } | |
541 | |
542 /* | |
543 * reserve drives | |
544 */ | |
545 static int | |
546 mhd_reserve_set( | |
547 mhd_drive_set_t *sp, | |
548 mhd_drive_list_t *dlp, | |
549 mhd_error_t *mhep | |
550 ) | |
551 { | |
552 mhd_msec_t ff = sp->sr_timeouts.mh_ff; | |
553 uint_t retry, i, ok; | |
554 int rval = 0; | |
555 | |
556 /* check locks */ | |
557 assert(MUTEX_HELD(&mhd_set_mx)); | |
558 assert(MUTEX_HELD(&sp->sr_mx)); | |
559 | |
560 /* idle set, idle everyone if cancelling failfast */ | |
561 if (ff == 0) { | |
562 if (mhd_idle_set(sp, &sp->sr_drives, mhep) != 0) | |
563 return (-1); | |
564 } else { | |
565 if (mhd_idle_set(sp, dlp, mhep) != 0) | |
566 return (-1); | |
567 } | |
568 | |
569 /* | |
570 * Try to take ownership of the drives twice. This helps | |
571 * to avoid the situation where the other machine retakes | |
572 * ownership of a majority drives back, but then kills itself | |
573 * leaving no owners. | |
574 */ | |
575 for (retry = 0; (retry < 2); ++retry) { | |
576 for (i = 0; (i < dlp->dl_ndrive); i++) { | |
577 mhd_drive_t *dp = dlp->dl_drives[i]; | |
578 | |
579 if ((retry == 0) || | |
580 ((dp->dr_state == DRIVE_ERRORED) && | |
581 (dp->dr_errnum == EACCES))) { | |
582 if (mhd_state(dp, DRIVE_RESERVING, mhep) != 0) | |
583 return (-1); | |
584 } | |
585 } | |
586 mhd_wait_set(sp, dlp, DRIVE_IDLE); | |
587 } | |
588 | |
589 /* | |
590 * Did the take ownership succeed on a majority of the drives? | |
591 */ | |
592 ok = 0; | |
593 for (i = 0; (i < dlp->dl_ndrive); ++i) { | |
594 mhd_drive_t *dp = dlp->dl_drives[i]; | |
595 | |
596 if (dp->dr_state == DRIVE_IDLE) | |
597 ++ok; | |
598 } | |
599 | |
600 /* | |
601 * Let the replica majority be the deciding factor, if able to get | |
602 * at least a single drive reserved. | |
603 */ | |
604 if (ok == 0) { | |
605 rval = mhd_error(mhep, MHD_E_MAJORITY, sp->sr_name); | |
606 goto out; | |
607 } | |
608 | |
609 /* | |
610 * Enable the failfast probes if we haven't given up yet. | |
611 */ | |
612 switch (sp->sr_ff_mode) { | |
613 | |
614 /* do nothing */ | |
615 default: | |
616 assert(0); | |
617 /* FALLTHROUGH */ | |
618 case MHD_FF_NONE: | |
619 goto out; | |
620 | |
621 /* old style per drive failfast */ | |
622 case MHD_FF_DRIVER: | |
623 for (i = 0; (i < dlp->dl_ndrive); i++) { | |
624 mhd_drive_t *dp = dlp->dl_drives[i]; | |
625 | |
626 if (dp->dr_state != DRIVE_ERRORED) { | |
627 if (mhd_state(dp, DRIVE_FAILFASTING, | |
628 mhep) != 0) { | |
629 rval = -1; | |
630 goto out; | |
631 } | |
632 } | |
633 } | |
634 mhd_wait_set(sp, dlp, DRIVE_IDLE); | |
635 break; | |
636 | |
637 /* failfast probe threads */ | |
638 case MHD_FF_DEBUG: | |
639 case MHD_FF_HALT: | |
640 case MHD_FF_PANIC: | |
641 if (ff != 0) { | |
642 if (mhd_ff_open(sp, mhep) != 0) { | |
643 rval = -1; | |
644 goto out; | |
645 } | |
646 for (i = 0; (i < dlp->dl_ndrive); i++) { | |
647 mhd_drive_t *dp = dlp->dl_drives[i]; | |
648 | |
649 if (mhd_state_set(dp, DRIVE_PROBING, | |
650 mhep) != 0) { | |
651 rval = -1; | |
652 goto out; | |
653 } | |
654 dp->dr_time = mhd_time(); | |
655 } | |
656 (void) mhd_ff_rearm(sp, mhep); | |
657 } | |
658 break; | |
659 } | |
660 | |
661 /* cleanup, return success */ | |
662 out: | |
663 if (rval != 0) { | |
664 mhd_error_t status = mhd_null_error; | |
665 | |
666 (void) mhd_release_set(sp, dlp, &status); | |
667 mhd_clrerror(&status); | |
668 } | |
669 return (rval); | |
670 } | |
671 | |
672 /* | |
673 * reserve drives in set | |
674 */ | |
675 int | |
676 mhd_reserve_drives( | |
677 mhd_set_t *mhsp, | |
678 mhd_mhiargs_t *timeoutp, | |
679 mhd_ff_mode_t ff_mode, | |
680 mhd_opts_t options, | |
681 mhd_error_t *mhep | |
682 ) | |
683 { | |
684 mhd_drive_list_t dl = mhd_null_list; | |
685 mhd_drive_set_t *sp; | |
686 int rval; | |
687 | |
688 /* grab global lock */ | |
689 mhd_mx_lock(&mhd_set_mx); | |
690 | |
691 /* create or update set */ | |
692 if ((sp = mhd_create_set(mhsp, options, &dl, mhep)) == NULL) { | |
693 mhd_mx_unlock(&mhd_set_mx); | |
694 mhd_free_list(&dl); | |
695 return (-1); | |
696 } | |
697 | |
698 /* lock set */ | |
699 mhd_mx_lock(&sp->sr_mx); | |
700 | |
701 /* can't change mode or timeouts of partial set */ | |
702 if ((dl.dl_ndrive != sp->sr_drives.dl_ndrive) && | |
703 (options & MHD_PARTIAL_SET)) { | |
704 if (ff_mode != sp->sr_ff_mode) { | |
705 mhd_eprintf("%s: invalid ff_mode %d now %d\n", | |
706 sp->sr_name, ff_mode, sp->sr_ff_mode); | |
707 ff_mode = sp->sr_ff_mode; | |
708 } | |
709 if (timeoutp->mh_ff < sp->sr_timeouts.mh_ff) { | |
710 mhd_eprintf("%s: invalid mh_ff %d now %d\n", | |
711 sp->sr_name, timeoutp->mh_ff, | |
712 sp->sr_timeouts.mh_ff); | |
713 timeoutp->mh_ff = sp->sr_timeouts.mh_ff; | |
714 } | |
715 } | |
716 | |
717 /* save timouts and mode */ | |
718 sp->sr_timeouts = *timeoutp; | |
719 sp->sr_ff_mode = ff_mode; | |
720 | |
721 /* reserve drives */ | |
722 rval = mhd_reserve_set(sp, &dl, mhep); | |
723 | |
724 /* unlock, return success */ | |
725 out: | |
726 mhd_mx_unlock(&sp->sr_mx); | |
727 mhd_mx_unlock(&mhd_set_mx); | |
728 mhd_free_list(&dl); | |
729 return (rval); | |
730 } | |
731 | |
732 /* | |
733 * status drives | |
734 */ | |
735 static int | |
736 mhd_status_set( | |
737 mhd_drive_set_t *sp, | |
738 mhd_drive_list_t *dlp, | |
739 mhd_error_t *mhep | |
740 ) | |
741 { | |
742 uint_t i; | |
743 | |
744 /* check locks */ | |
745 assert(MUTEX_HELD(&mhd_set_mx)); | |
746 assert(MUTEX_HELD(&sp->sr_mx)); | |
747 | |
748 /* status drives */ | |
749 for (i = 0; (i < dlp->dl_ndrive); i++) { | |
750 mhd_drive_t *dp = dlp->dl_drives[i]; | |
751 | |
752 if (mhd_state_set(dp, DRIVE_STATUSING, mhep) != 0) | |
753 return (-1); | |
754 } | |
755 mhd_wait_set(sp, dlp, DRIVE_STATUSING); | |
756 | |
757 /* return success */ | |
758 return (0); | |
759 } | |
760 | |
761 /* | |
762 * status drives in set | |
763 */ | |
764 int | |
765 mhd_status_drives( | |
766 mhd_set_t *mhsp, | |
767 mhd_opts_t options, | |
768 mhd_drive_status_t **status, | |
769 mhd_error_t *mhep | |
770 ) | |
771 { | |
772 mhd_drive_list_t dl = mhd_null_list; | |
773 mhd_drive_list_t *dlp = &dl; | |
774 mhd_drive_set_t *sp; | |
775 uint_t i; | |
776 int rval = 0; | |
777 | |
778 /* grab global lock */ | |
779 mhd_mx_lock(&mhd_set_mx); | |
780 | |
781 /* create or update set */ | |
782 if ((sp = mhd_create_set(mhsp, options, &dl, mhep)) == NULL) { | |
783 mhd_mx_unlock(&mhd_set_mx); | |
784 mhd_free_list(&dl); | |
785 return (-1); | |
786 } | |
787 | |
788 /* lock set */ | |
789 mhd_mx_lock(&sp->sr_mx); | |
790 | |
791 /* status drives */ | |
792 if (mhd_status_set(sp, &dl, mhep) != 0) { | |
793 rval = -1; | |
794 goto out; | |
795 } | |
796 | |
797 /* build list */ | |
798 *status = Zalloc(dlp->dl_ndrive * sizeof (**status)); | |
799 for (i = 0; (i < dlp->dl_ndrive); ++i) { | |
800 mhd_drive_t *dp = dlp->dl_drives[i]; | |
801 mhd_drive_status_t *statusp = &(*status)[i]; | |
802 | |
803 statusp->drive = Strdup(dp->dr_rname); | |
804 statusp->errnum = dp->dr_errnum; | |
805 } | |
806 assert(i == dlp->dl_ndrive); | |
807 rval = dlp->dl_ndrive; | |
808 | |
809 /* unlock, return count */ | |
810 out: | |
811 mhd_mx_unlock(&sp->sr_mx); | |
812 mhd_mx_unlock(&mhd_set_mx); | |
813 mhd_free_list(&dl); | |
814 return (rval); | |
815 } |