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 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 /*
30 * Just in case we're not in a build environment, make sure that
31 * TEXT_DOMAIN gets set to something.
32 */
33 #if !defined(TEXT_DOMAIN)
34 #define TEXT_DOMAIN "SYS_TEST"
35 #endif
36
37 /*
38 * MH ioctl functions
39 */
40
41 #include <meta.h>
42 #include <metamhd.h>
43 #include <string.h>
44
45 #include "meta_runtime.h"
46
47 #define DEFAULTDEV "/dev/rdsk"
48 /*
49 * default timeout values
50 */
51 mhd_mhiargs_t defmhiargs = {
52 1000, /* failfast */
53 { 6000, 6000, 30000 } /* take ownership */
54 };
55
56 /* RPC timeouts */
57 static md_timeval32_t tk_own_timeout = { 24 * 60 * 60, 0 }; /* 1 day */
58 static md_timeval32_t rel_own_timeout = { 24 * 60 * 60, 0 }; /* 1 day */
59
60 /*
61 * RPC handle
62 */
63 typedef struct {
64 char *hostname;
65 CLIENT *clientp;
66 } mhd_handle_t;
67
68 /*
69 * close RPC connection
70 */
71 static void
close_metamhd(mhd_handle_t * hp)72 close_metamhd(
73 mhd_handle_t *hp
74 )
75 {
76 assert(hp != NULL);
77 if (hp->hostname != NULL) {
78 Free(hp->hostname);
79 }
80 if (hp->clientp != NULL) {
81 auth_destroy(hp->clientp->cl_auth);
82 clnt_destroy(hp->clientp);
83 }
84 Free(hp);
85 }
86
87 /*
88 * open RPC connection to rpc.metamhd
89 */
90 static mhd_handle_t *
open_metamhd(char * hostname,md_error_t * ep)91 open_metamhd(
92 char *hostname,
93 md_error_t *ep
94 )
95 {
96 CLIENT *clientp;
97 mhd_handle_t *hp;
98
99 /* default to local host */
100 if ((hostname == NULL) || (*hostname == '\0'))
101 hostname = mynode();
102
103 /* open RPC connection */
104 assert(hostname != NULL);
105 if ((clientp = meta_client_create(hostname, METAMHD, METAMHD_VERSION,
106 "tcp")) == NULL) {
107 clnt_pcreateerror(hostname);
108 (void) mdrpccreateerror(ep, hostname, "metamhd clnt_create");
109 return (NULL);
110 } else {
111 auth_destroy(clientp->cl_auth);
112 clientp->cl_auth = authsys_create_default();
113 assert(clientp->cl_auth != NULL);
114 }
115
116 /* return connection */
117 hp = Zalloc(sizeof (*hp));
118 hp->hostname = Strdup(hostname);
119 hp->clientp = clientp;
120 return (hp);
121 }
122
123 /*
124 * steal and convert mherror_t
125 */
126 int
mhstealerror(mhd_error_t * mhep,md_error_t * ep)127 mhstealerror(
128 mhd_error_t *mhep,
129 md_error_t *ep
130 )
131 {
132 int rval = -1;
133
134 /* no error */
135 if (mhep->errnum == 0) {
136 /* assert(mhep->name == NULL); */
137 rval = 0;
138 goto out;
139 }
140
141 /* steal error */
142 switch (mhep->errnum) {
143 case MHD_E_MAJORITY:
144 (void) mderror(ep, MDE_TAKE_OWN, mhep->name);
145 break;
146 case MHD_E_RESERVED:
147 (void) mderror(ep, MDE_RESERVED, mhep->name);
148 break;
149 default:
150 (void) mdsyserror(ep, mhep->errnum, mhep->name);
151 break;
152 }
153
154 /* cleanup, return success */
155 out:
156 if (mhep->name != NULL)
157 Free(mhep->name);
158 (void) memset(mhep, 0, sizeof (*mhep));
159 return (rval);
160 }
161
162 /*
163 * should we do MHIOCTLs ?
164 */
165 static int
do_mhioctl()166 do_mhioctl()
167 {
168 if (getenv("MD_NOMHIOCTL") != NULL) {
169 (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
170 "NOT doing MH ioctls\n"));
171 (void) fflush(stderr);
172 return (0);
173 }
174 return (1);
175 }
176
177 /*
178 * take ownership of drives
179 */
180 int
meta_take_own(char * sname,mddrivenamelist_t * dnlp,mhd_mhiargs_t * mhiargsp,int partial_set,md_error_t * ep)181 meta_take_own(
182 char *sname,
183 mddrivenamelist_t *dnlp,
184 mhd_mhiargs_t *mhiargsp,
185 int partial_set,
186 md_error_t *ep
187 )
188 {
189 mddrivenamelist_t *p;
190 uint_t ndev = 0;
191 mhd_tkown_args_t args;
192 mhd_error_t mherror;
193 mhd_set_t *mhsp = &args.set;
194 uint_t i;
195 char *e;
196 mhd_handle_t *hp = NULL;
197 int rval = -1;
198
199 /*
200 * RFE 4126509. Check the runtime parameters to see if
201 * they're set to disable MHIOCTKOWN ioctl() operations
202 * on the disks. If so, return immediately without
203 * performing the operations.
204 */
205
206 if (do_owner_ioctls() == B_FALSE) {
207 return (0);
208 }
209
210 /* count drives, get set */
211 for (p = dnlp; (p != NULL); p = p->next)
212 ++ndev;
213 if (ndev == 0)
214 return (0);
215
216 /* initialize */
217 (void) memset(&args, 0, sizeof (args));
218 (void) memset(&mherror, 0, sizeof (mherror));
219
220 /* build arguments */
221 mhsp->setname = Strdup(sname);
222 mhsp->drives.drives_len = ndev;
223 mhsp->drives.drives_val
224 = Calloc(ndev, sizeof (*mhsp->drives.drives_val));
225 for (p = dnlp, i = 0; (i < ndev); p = p->next, ++i) {
226 mhsp->drives.drives_val[i] = Strdup(p->drivenamep->rname);
227 }
228 args.timeouts = *mhiargsp;
229 args.ff_mode = MHD_FF_DRIVER;
230 if (((e = getenv("MD_DEBUG")) != NULL) &&
231 ((e = strstr(e, "FAILFAST=")) != NULL) &&
232 ((e = strchr(e, '=')) != NULL)) {
233 ++e;
234 if (strcmp(e, "NONE") == 0)
235 args.ff_mode = MHD_FF_NONE;
236 else if (strcmp(e, "DRIVER") == 0)
237 args.ff_mode = MHD_FF_DRIVER;
238 else if (strcmp(e, "DEBUG") == 0)
239 args.ff_mode = MHD_FF_DEBUG;
240 else if (strcmp(e, "HALT") == 0)
241 args.ff_mode = MHD_FF_HALT;
242 else if (strcmp(e, "PANIC") == 0)
243 args.ff_mode = MHD_FF_PANIC;
244 }
245 if (partial_set)
246 args.options |= MHD_PARTIAL_SET;
247 if (((e = getenv("MD_DEBUG")) != NULL) &&
248 (strstr(e, "NOTHREAD") != NULL)) {
249 args.options |= MHD_SERIAL;
250 }
251
252 /* open connection */
253 if ((hp = open_metamhd(NULL, ep)) == NULL)
254 return (-1);
255 clnt_control(hp->clientp, CLSET_TIMEOUT, (char *)&tk_own_timeout);
256
257 /* take ownership */
258 if (mhd_tkown_1(&args, &mherror, hp->clientp) != RPC_SUCCESS) {
259 (void) mdrpcerror(ep, hp->clientp, hp->hostname,
260 "metamhd tkown");
261 } else if (mhstealerror(&mherror, ep) == 0) {
262 rval = 0; /* success */
263 }
264
265 /* cleanup, return success */
266 out:
267 xdr_free(xdr_mhd_tkown_args_t, (char *)&args);
268 xdr_free(xdr_mhd_error_t, (char *)&mherror);
269 if (hp != NULL)
270 close_metamhd(hp);
271 return (rval);
272 }
273
274 /*
275 * take ownership of drives
276 */
277 int
tk_own_bydd(mdsetname_t * sp,md_drive_desc * ddlp,mhd_mhiargs_t * mhiargsp,int partial_set,md_error_t * ep)278 tk_own_bydd(
279 mdsetname_t *sp,
280 md_drive_desc *ddlp,
281 mhd_mhiargs_t *mhiargsp,
282 int partial_set,
283 md_error_t *ep
284 )
285 {
286 mddrivenamelist_t *dnlp = NULL;
287 mddrivenamelist_t **tailpp = &dnlp;
288 md_drive_desc *p;
289 int rval;
290
291 /*
292 * Add the drivename struct to the end of the
293 * drivenamelist but keep a pointer to the last
294 * element so that we don't incur the overhead
295 * of traversing the list each time
296 */
297 for (p = ddlp; (p != NULL); p = p->dd_next)
298 tailpp = meta_drivenamelist_append_wrapper(tailpp, p->dd_dnp);
299
300 /* take ownership */
301 rval = meta_take_own(sp->setname, dnlp, mhiargsp, partial_set, ep);
302
303 /* cleanup, return success */
304 metafreedrivenamelist(dnlp);
305 return (rval);
306 }
307
308 /*
309 * release ownership of drives
310 */
311 int
meta_rel_own(char * sname,mddrivenamelist_t * dnlp,int partial_set,md_error_t * ep)312 meta_rel_own(
313 char *sname,
314 mddrivenamelist_t *dnlp,
315 int partial_set,
316 md_error_t *ep
317 )
318 {
319 mddrivenamelist_t *p;
320 uint_t ndev = 0;
321 mhd_relown_args_t args;
322 mhd_error_t mherror;
323 mhd_set_t *mhsp = &args.set;
324 uint_t i;
325 char *e;
326 mhd_handle_t *hp = NULL;
327 int rval = -1;
328
329 /*
330 * RFE 4126509. Check the runtime parameters to see if
331 * they're set to disable MHIOCRELEASE and MHIOCENFAILFAST
332 * ioctl() operations on the disks. If so, return
333 * immediately without performing the operations.
334 */
335
336 if (do_owner_ioctls() == B_FALSE) {
337 return (0);
338 }
339
340 /*
341 * if not doing ioctls (HK 98/10/28: the following code tests
342 * an environment variable, and was apparently inserted to
343 * make testing easier.)
344 */
345
346 if (! do_mhioctl())
347 return (0);
348
349 /* count drives, get set */
350 for (p = dnlp; (p != NULL); p = p->next)
351 ++ndev;
352 if (ndev == 0)
353 return (0);
354
355 /* initialize */
356 (void) memset(&args, 0, sizeof (args));
357 (void) memset(&mherror, 0, sizeof (mherror));
358
359 /* build arguments */
360 mhsp->setname = Strdup(sname);
361 mhsp->drives.drives_len = ndev;
362 mhsp->drives.drives_val
363 = Calloc(ndev, sizeof (*mhsp->drives.drives_val));
364 for (p = dnlp, i = 0; (i < ndev); p = p->next, ++i) {
365 mhsp->drives.drives_val[i] = Strdup(p->drivenamep->rname);
366 }
367 if (partial_set)
368 args.options |= MHD_PARTIAL_SET;
369 if (((e = getenv("MD_DEBUG")) != NULL) &&
370 (strstr(e, "NOTHREAD") != NULL)) {
371 args.options |= MHD_SERIAL;
372 }
373
374 /* open connection */
375 if ((hp = open_metamhd(NULL, ep)) == NULL)
376 return (-1);
377 clnt_control(hp->clientp, CLSET_TIMEOUT, (char *)&rel_own_timeout);
378
379 /* take ownership */
380 if (mhd_relown_1(&args, &mherror, hp->clientp) != RPC_SUCCESS) {
381 (void) mdrpcerror(ep, hp->clientp, hp->hostname,
382 "metamhd relown");
383 } else if (mhstealerror(&mherror, ep) == 0) {
384 rval = 0; /* success */
385 }
386
387 /* cleanup, return success */
388 out:
389 xdr_free(xdr_mhd_relown_args_t, (char *)&args);
390 xdr_free(xdr_mhd_error_t, (char *)&mherror);
391 if (hp != NULL)
392 close_metamhd(hp);
393 return (rval);
394 }
395
396 /*
397 * release ownership of drives
398 */
399 int
rel_own_bydd(mdsetname_t * sp,md_drive_desc * ddlp,int partial_set,md_error_t * ep)400 rel_own_bydd(
401 mdsetname_t *sp,
402 md_drive_desc *ddlp,
403 int partial_set,
404 md_error_t *ep
405 )
406 {
407 mddrivenamelist_t *dnlp = NULL;
408 mddrivenamelist_t **tailpp = &dnlp;
409 md_drive_desc *p;
410 int rval;
411
412 /*
413 * Add the drivename struct to the end of the
414 * drivenamelist but keep a pointer to the last
415 * element so that we don't incur the overhead
416 * of traversing the list each time
417 */
418 for (p = ddlp; (p != NULL); p = p->dd_next)
419 tailpp = meta_drivenamelist_append_wrapper(tailpp, p->dd_dnp);
420
421 /* release ownership */
422 rval = meta_rel_own(sp->setname, dnlp, partial_set, ep);
423
424 /* cleanup, return success */
425 metafreedrivenamelist(dnlp);
426 return (rval);
427 }
428
429 /*
430 * get status of drives
431 */
432 int
meta_status_own(char * sname,md_disk_status_list_t * dslp,int partial_set,md_error_t * ep)433 meta_status_own(
434 char *sname,
435 md_disk_status_list_t *dslp,
436 int partial_set,
437 md_error_t *ep
438 )
439 {
440 md_disk_status_list_t *p;
441 uint_t ndev = 0;
442 mhd_status_args_t args;
443 mhd_status_res_t results;
444 mhd_error_t *mhep = &results.status;
445 mhd_set_t *mhsp = &args.set;
446 uint_t i;
447 char *e;
448 mhd_handle_t *hp = NULL;
449 int rval = -1;
450
451 /* if not doing ioctls */
452 if (! do_mhioctl())
453 return (0);
454
455 /* count drives, get set */
456 for (p = dslp; (p != NULL); p = p->next)
457 ++ndev;
458 if (ndev == 0)
459 return (0);
460
461 /* initialize */
462 (void) memset(&args, 0, sizeof (args));
463 (void) memset(&results, 0, sizeof (results));
464
465 /* build arguments */
466 mhsp->setname = Strdup(sname);
467 mhsp->drives.drives_len = ndev;
468 mhsp->drives.drives_val
469 = Calloc(ndev, sizeof (*mhsp->drives.drives_val));
470 for (p = dslp, i = 0; (i < ndev); p = p->next, ++i) {
471 mhsp->drives.drives_val[i] = Strdup(p->drivenamep->rname);
472 }
473 if (partial_set)
474 args.options |= MHD_PARTIAL_SET;
475 if (((e = getenv("MD_DEBUG")) != NULL) &&
476 (strstr(e, "NOTHREAD") != NULL)) {
477 args.options |= MHD_SERIAL;
478 }
479
480 /* open connection */
481 if ((hp = open_metamhd(NULL, ep)) == NULL)
482 return (-1);
483 clnt_control(hp->clientp, CLSET_TIMEOUT, (char *)&tk_own_timeout);
484
485 /* get status */
486 if (mhd_status_1(&args, &results, hp->clientp) != RPC_SUCCESS) {
487 (void) mdrpcerror(ep, hp->clientp, hp->hostname,
488 dgettext(TEXT_DOMAIN, "metamhd status"));
489 goto out;
490 } else if (mhstealerror(mhep, ep) != 0) {
491 goto out;
492 }
493
494 /* do something with it */
495 assert(results.results.results_len == ndev);
496 for (p = dslp, i = 0; (i < ndev); p = p->next, ++i) {
497 mhd_drive_status_t *resp = &results.results.results_val[i];
498 mddrivename_t *dp = p->drivenamep;
499 mhd_error_t mherror;
500
501 /* make sure we have the right drive */
502 assert(strcmp(dp->rname, resp->drive) == 0);
503
504 /* copy status */
505 if (resp->errnum != 0) {
506 (void) memset(&mherror, 0, sizeof (mherror));
507 mherror.errnum = resp->errnum;
508 mherror.name = Strdup(resp->drive);
509 (void) mhstealerror(&mherror, &p->status);
510 }
511 }
512 rval = 0; /* success */
513
514 /* cleanup, return success */
515 out:
516 xdr_free(xdr_mhd_status_args_t, (char *)&args);
517 xdr_free(xdr_mhd_status_res_t, (char *)&results);
518 if (hp != NULL)
519 close_metamhd(hp);
520 return (rval);
521 }
522
523 /*
524 * build disk status list from drivename list
525 */
526 md_disk_status_list_t *
meta_drive_to_disk_status_list(mddrivenamelist_t * dnlp)527 meta_drive_to_disk_status_list(
528 mddrivenamelist_t *dnlp
529 )
530 {
531 md_disk_status_list_t *head = NULL;
532 md_disk_status_list_t **tailp = &head;
533 mddrivenamelist_t *p;
534
535 /* copy list */
536 for (p = dnlp; (p != NULL); p = p->next) {
537 md_disk_status_list_t *dsp;
538
539 dsp = *tailp = Zalloc(sizeof (*dsp));
540 tailp = &dsp->next;
541 dsp->drivenamep = p->drivenamep;
542 }
543
544 /* return list */
545 return (head);
546 }
547
548 /*
549 * free disk status list
550 */
551 void
meta_free_disk_status_list(md_disk_status_list_t * dslp)552 meta_free_disk_status_list(
553 md_disk_status_list_t *dslp
554 )
555 {
556 md_disk_status_list_t *next = NULL;
557
558 for (/* void */; (dslp != NULL); dslp = next) {
559 next = dslp->next;
560 mdclrerror(&dslp->status);
561 Free(dslp);
562 }
563 }
564
565 /*
566 * free drive info list
567 */
568 void
meta_free_drive_info_list(mhd_drive_info_list_t * listp)569 meta_free_drive_info_list(
570 mhd_drive_info_list_t *listp
571 )
572 {
573 xdr_free(xdr_mhd_drive_info_list_t, (char *)listp);
574 (void) memset(listp, 0, sizeof (*listp));
575 }
576
577 /*
578 * sort drive info list
579 */
580 static int
compare_drives(const void * p1,const void * p2)581 compare_drives(
582 const void *p1,
583 const void *p2
584 )
585 {
586 const mhd_drive_info_t *di1 = p1;
587 const mhd_drive_info_t *di2 = p2;
588 const char *n1 = di1->dif_name;
589 const char *n2 = di2->dif_name;
590 uint_t c1 = 0, t1 = 0, d1 = 0, s1 = 0;
591 uint_t c2 = 0, t2 = 0, d2 = 0, s2 = 0;
592 uint_t l, cl;
593
594 if (n1 == NULL)
595 n1 = "";
596 if (n2 == NULL)
597 n2 = "";
598
599 /* attempt to sort correctly for c0t1d0s0 .vs. c0t18d0s0 */
600 if ((n1 = strrchr(n1, '/')) == NULL)
601 goto u;
602 n1 += (n1[1] != 'c') ? 2 : 1;
603 cl = strlen(n1);
604 if ((sscanf(n1, "c%ut%ud%us%u%n", &c1, &t1, &d1, &s1, &l) != 4 &&
605 sscanf(n1, "c%ud%us%u%n", &c1, &d1, &s1, &l) != 3 &&
606 sscanf(n1, "c%ut%ud%u%n", &c1, &t1, &d1, &l) != 3 &&
607 sscanf(n1, "c%ud%u%n", &c1, &d1, &l) != 2) || (l != cl))
608 goto u;
609
610 if ((n2 = strrchr(n2, '/')) == NULL)
611 goto u;
612 n2 += (n2[1] != 'c') ? 2 : 1;
613 cl = strlen(n2);
614 if ((sscanf(n2, "c%ut%ud%us%u%n", &c2, &t2, &d2, &s2, &l) != 4 &&
615 sscanf(n2, "c%ud%us%u%n", &c2, &d2, &s2, &l) != 3 &&
616 sscanf(n2, "c%ut%ud%u%n", &c2, &t2, &d2, &l) != 3 &&
617 sscanf(n2, "c%ud%u%n", &c2, &d2, &l) != 2) || (l != cl))
618 goto u;
619 if (c1 != c2)
620 return ((c1 > c2) ? 1 : -1);
621 if (t1 != t2)
622 return ((t1 > t2) ? 1 : -1);
623 if (d1 != d2)
624 return ((d1 > d2) ? 1 : -1);
625 if (s1 != s2)
626 return ((s1 > s2) ? 1 : -1);
627 return (0);
628
629 u: return (strcmp(di1->dif_name, di2->dif_name));
630 }
631
632 static void
sort_drives(mhd_drive_info_list_t * listp)633 sort_drives(
634 mhd_drive_info_list_t *listp
635 )
636 {
637 qsort(listp->mhd_drive_info_list_t_val,
638 listp->mhd_drive_info_list_t_len,
639 sizeof (*listp->mhd_drive_info_list_t_val),
640 compare_drives);
641 }
642
643 /*
644 * return list of all drives
645 */
646 int
meta_list_drives(char * hostname,char * path,mhd_did_flags_t flags,mhd_drive_info_list_t * listp,md_error_t * ep)647 meta_list_drives(
648 char *hostname,
649 char *path,
650 mhd_did_flags_t flags,
651 mhd_drive_info_list_t *listp,
652 md_error_t *ep
653 )
654 {
655 mhd_list_args_t args;
656 mhd_list_res_t results;
657 mhd_error_t *mhep = &results.status;
658 mhd_handle_t *hp = NULL;
659 int rval = -1;
660
661 /* if not doing ioctls */
662 if (! do_mhioctl())
663 return (0);
664
665 /* initialize */
666 (void) memset(&args, 0, sizeof (args));
667 (void) memset(&results, 0, sizeof (results));
668
669 /* build arguments */
670 if (path == NULL)
671 path = getenv("MD_DRIVE_ROOT");
672 if ((path != NULL) && (*path != '\0'))
673 args.path = Strdup(path);
674 args.flags = flags;
675
676 /* open connection */
677 if ((hp = open_metamhd(hostname, ep)) == NULL)
678 return (-1);
679 clnt_control(hp->clientp, CLSET_TIMEOUT, (char *)&tk_own_timeout);
680
681 /* get list */
682 if (mhd_list_1(&args, &results, hp->clientp) != RPC_SUCCESS) {
683 (void) mdrpcerror(ep, hp->clientp, hp->hostname,
684 dgettext(TEXT_DOMAIN, "metamhd list"));
685 goto out;
686 } else if (mhstealerror(mhep, ep) != 0) {
687 goto out;
688 }
689
690 /* sort list */
691 sort_drives(&results.results);
692
693 /* steal list */
694 *listp = results.results;
695 results.results.mhd_drive_info_list_t_len = 0;
696 results.results.mhd_drive_info_list_t_val = NULL;
697 rval = listp->mhd_drive_info_list_t_len; /* success */
698
699 /* cleanup, return success */
700 out:
701 xdr_free(xdr_mhd_list_args_t, (char *)&args);
702 xdr_free(xdr_mhd_list_res_t, (char *)&results);
703 if (hp != NULL)
704 close_metamhd(hp);
705 return (rval);
706 }
707
708 static void
load_paths_to_metamhd()709 load_paths_to_metamhd()
710 {
711 FILE *cfp; /* config file pointer */
712 char buf[BUFSIZ],
713 *p,
714 *x;
715 mhd_drive_info_list_t list;
716 md_error_t ep;
717 mhd_did_flags_t flags = MHD_DID_SERIAL;
718
719 if ((cfp = fopen(METADEVPATH, "r")) != NULL) {
720 /*
721 * Read each line from the file. Lines will be either
722 * comments or path names to pass to rpc.metamhd. If
723 * path names check to see if their a colon seperate
724 * list of names which must be processed one at a time.
725 */
726
727 while (fgets(buf, BUFSIZ, cfp) != NULL) {
728 if (buf[0] == '#') {
729 /*
730 * Ignore comment lines
731 */
732 continue;
733
734 } else if (strchr(buf, ':') != NULL) {
735 p = buf;
736 while ((x = strchr(p, ':')) != NULL) {
737 *x = '\0';
738 (void) memset(&ep, '\0', sizeof (ep));
739 (void) meta_list_drives(NULL, p, 0,
740 &list, &ep);
741 meta_free_drive_info_list(&list);
742 p = x + 1;
743 }
744 /*
745 * We won't pick up the last path name
746 * because the line ends with a newline
747 * not a ':'. So p will still point to
748 * a valid path in this case. Copy the
749 * data that p points to to the beginning
750 * of the buf and let the default case
751 * handle this buffer.
752 * NOTE:
753 * If the file does end with a ":\n", p at
754 * will point to the newline. The default
755 * cause would then set the newline to a
756 * NULL which is okay because meta_list_drives
757 * interprets a null string as /dev/rdsk.
758 */
759 (void) memcpy(buf, p, strlen(p));
760 }
761 /*
762 * Remove any newlines in the buffer.
763 */
764 if ((p = strchr(buf, '\n')) != NULL)
765 *p = '\0';
766 (void) memset(&ep, '\0', sizeof (ep));
767 (void) memset(&list, '\0', sizeof (list));
768 (void) meta_list_drives(NULL, buf, flags, &list, &ep);
769 meta_free_drive_info_list(&list);
770 }
771 (void) fclose(cfp);
772 }
773 }
774
775 /*
776 * build list of all drives in set
777 */
778 /*ARGSUSED*/
779 int
meta_get_drive_names(mdsetname_t * sp,mddrivenamelist_t ** dnlpp,int options,md_error_t * ep)780 meta_get_drive_names(
781 mdsetname_t *sp,
782 mddrivenamelist_t **dnlpp,
783 int options,
784 md_error_t *ep
785 )
786 {
787 mhd_did_flags_t flags = MHD_DID_SERIAL;
788 mhd_drive_info_list_t list;
789 mhd_drive_info_t *mp;
790 uint_t i;
791 unsigned cnt = 0;
792 int rval = -1;
793 mddrivenamelist_t **tailpp = dnlpp;
794
795 /* must have a set */
796 assert(sp != NULL);
797
798 load_paths_to_metamhd();
799 (void) memset(&list, 0, sizeof (list));
800 if ((meta_list_drives(NULL, NULL, flags, &list, ep)) < 0)
801 return (-1);
802
803 /* find drives in set */
804 for (i = 0; (i < list.mhd_drive_info_list_t_len); ++i) {
805 mddrivename_t *dnp;
806 mdname_t *np;
807
808 mp = &list.mhd_drive_info_list_t_val[i];
809
810 if (mp->dif_id.did_flags & MHD_DID_DUPLICATE)
811 continue;
812
813 /* quietly skip drives which don't conform */
814 if ((dnp = metadrivename(&sp, mp->dif_name, ep)) == NULL) {
815 mdclrerror(ep);
816 continue;
817 }
818
819 /* check in set */
820 if ((np = metaslicename(dnp, MD_SLICE0, ep)) == NULL)
821 goto out;
822 if (meta_check_inset(sp, np, ep) != 0) {
823 mdclrerror(ep);
824 continue;
825 }
826
827 /*
828 * Add the drivename struct to the end of the
829 * drivenamelist but keep a pointer to the last
830 * element so that we don't incur the overhead
831 * of traversing the list each time
832 */
833 tailpp = meta_drivenamelist_append_wrapper(tailpp, dnp);
834 ++cnt;
835 }
836 rval = cnt;
837
838 /* cleanup, return error */
839 out:
840 meta_free_drive_info_list(&list);
841 return (rval);
842 }
843