4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 #include "md_monitord.h"
29 #define MD_PROBE_OPEN_T "probe open test"
32 * Failure return's a 1
35 hotspare_ok(char *bname
)
40 if ((fd
= open(bname
, O_RDONLY
)) < 0)
42 if (read(fd
, buf
, sizeof (buf
)) < 0) {
51 delete_hotspares_impl(mdhspname_t
*hspnp
, md_hsp_t
*hspp
, boolean_e verbose
)
55 char *cname
, *bname
, *hs_state
;
56 md_error_t e
= mdnullerror
;
59 for (hsi
= 0; (hsi
< hspp
->hotspares
.hotspares_len
); ++hsi
) {
62 hsp
= &hspp
->hotspares
.hotspares_val
[hsi
];
64 monitord_print(6, "hsi %d\n", hsi
);
65 cname
= hsp
->hsnamep
->cname
;
66 bname
= hsp
->hsnamep
->bname
;
68 (void) metanamelist_append(&nlp
, hsp
->hsnamep
);
69 hs_state
= hs_state_to_name(hsp
, NULL
);
72 monitord_print(6, "\t%-19s\t%-19s\t%-12s\n",
73 cname
, bname
, hs_state
);
74 if (hsp
->state
== HSS_AVAILABLE
) {
75 if (hotspare_ok(bname
))
78 monitord_print(6, gettext(
79 "NOTICE: Hotspare %s in %s has failed.\n"
80 "\tDeleting %s since it is not in use\n\n"),
81 bname
, hspnp
->hspname
, bname
);
83 if (meta_hs_delete(sp
, hspnp
, nlp
, 0, &e
) != NULL
) {
91 monitord_print(6, gettext(
92 "%s in use - skipping\n"), cname
);
100 * Generic routine to issue probe ioctls
104 md_probe_ioctl(mdnamelist_t
*nlp
, int ndevs
, char *drvname
, boolean_e verbose
)
108 md_probedev_t probe_ioc
, *iocp
;
111 * Allocate space for all the metadevices and fill in
115 (void) memset(&probe_ioc
, 0, sizeof (probe_ioc
));
118 if ((iocp
->mnum_list
= (uintptr_t)calloc(ndevs
, sizeof (minor_t
)))
120 monitord_print(0, "md_probe_ioctl: calloc");
124 (void) strcpy(iocp
->test_name
, MD_PROBE_OPEN_T
);
125 MD_SETDRIVERNAME(&probe_ioc
, drvname
, sp
->setno
);
127 if (verbose
== True
) {
128 monitord_print(6, "\n\nmd_probe_ioctl: %s: %s\n",
129 (strcmp(sp
->setname
, MD_LOCAL_NAME
) == 0) ?
130 gettext("local_set") :
131 sp
->setname
, iocp
->md_driver
.md_drivername
);
134 iocp
->nmdevs
= ndevs
;
136 monitord_print(6, "...ndevs 0x%x\n", ndevs
);
138 for (p
= nlp
, i
= 0; p
; p
= p
->next
, i
++) {
140 ((minor_t
*)(uintptr_t)iocp
->mnum_list
)[i
] =
141 meta_getminor(np
->dev
);
143 monitord_print(6, "...%s 0x%lx\n", np
->cname
,
144 ((minor_t
*)(uintptr_t)iocp
->mnum_list
)[i
]);
148 if (issue_ioctl
== True
) {
149 if (metaioctl(MD_IOCPROBE_DEV
, iocp
, &(iocp
->mde
), NULL
) != 0)
153 Free((void *)(uintptr_t)iocp
->mnum_list
);
158 * - remove p from nlp list
159 * - put it on the toplp list.
160 * - update the p to the next element
164 add_to_list(mdnamelist_t
**curpp
, mdnamelist_t
**prevpp
,
165 mdnamelist_t
**newlpp
)
167 mdnamelist_t
*p
, *prevp
, *nlp
;
174 /* if first element reset prevp */
180 prevp
->next
= p
->next
;
190 * Scans the given list of metadeivces and returns a list of top level
192 * Note: The orignal list is not valid at the end and is set to NULL.
196 get_toplevel_mds(mdnamelist_t
**lpp
, mdnamelist_t
**top_pp
, boolean_e verbose
)
198 mdnamelist_t
*p
, *prevp
, *toplp
;
201 md_error_t e
= mdnullerror
;
208 if ((mdp
= meta_get_unit(sp
, p
->namep
, &e
)) == NULL
) {
211 monitord_print(6, gettext(
212 "......error on (%d)%s\n"), i
,
213 p
->namep
->devicesname
);
219 if (mdp
->parent
== MD_NO_PARENT
) {
220 /* increment the top level md count. */
222 add_to_list(&p
, &prevp
, &toplp
);
237 get_namelist(mdnamelist_t
**transdevlist
, mdnamelist_t
**devlist
,
240 mdnamelist_t
*np
, *prevp
;
241 md_error_t e
= mdnullerror
;
245 prevp
= np
= *transdevlist
;
247 if ((type_name
= metagetmiscname(np
->namep
, &e
)) == NULL
) {
252 if (strcmp(type_name
, dev_type
) == 0) {
253 /* move it to the devlist */
254 add_to_list(&np
, &prevp
, devlist
);
270 if (np
= (mdnamelist_t
*)malloc(sizeof (mdnamelist_t
))) {
274 /* error condition below */
275 monitord_print(0, gettext(
276 "create_nlp: malloc failed\n"));
277 monitord_exit(errno
);
283 * Create a list of metadevices associated with trans. top_pp points to
284 * this list. The number of components in the list are also returned.
287 create_trans_compslist(mdnamelist_t
**lpp
, mdnamelist_t
**top_pp
,
290 mdnamelist_t
*p
, *tailp
, *toplp
, *newlp
;
292 md_error_t e
= mdnullerror
;
297 tailp
= toplp
= NULL
;
299 * Scan the current list of trans devices. From that
300 * extract all the lower level metadevices and put them on
305 if (tp
= meta_get_trans(sp
, p
->namep
, &e
)) {
307 * Check the master and log devices to see if they
310 if (metaismeta(tp
->masternamep
)) {
312 monitord_print(6, gettext(
313 "master metadevice\n"));
314 /* get a mdnamelist_t. */
315 newlp
= create_nlp();
316 newlp
->namep
= tp
->masternamep
;
318 toplp
= tailp
= newlp
;
326 if (tp
->lognamep
&& metaismeta(tp
->lognamep
)) {
328 monitord_print(6, gettext(
329 "log metadevice\n"));
330 newlp
= create_nlp();
331 newlp
->namep
= tp
->lognamep
;
333 toplp
= tailp
= newlp
;
350 probe_mirror_devs(boolean_e verbose
)
352 mdnamelist_t
*nlp
, *toplp
;
354 md_error_t e
= mdnullerror
;
358 if (meta_get_mirror_names(sp
, &nlp
, 0, &e
) > 0) {
360 * We have some mirrors to probe
361 * get a list of top-level mirrors
364 cnt
= get_toplevel_mds(&nlp
, &toplp
, verbose
);
365 if (cnt
&& (md_probe_ioctl(toplp
, cnt
,
366 MD_MIRROR
, verbose
) < 0))
367 monitord_print(0, gettext(
368 "probe_mirror_devs: "
369 "mirror components %d ioctl error\n"),
376 metafreenamelist(nlp
);
377 metafreenamelist(toplp
);
381 probe_raid_devs(boolean_e verbose
)
383 mdnamelist_t
*nlp
, *toplp
;
385 md_error_t e
= mdnullerror
;
389 if (meta_get_raid_names(sp
, &nlp
, 0, &e
) > 0) {
391 * We have some mirrors to probe
392 * get a list of top-level mirrors
395 cnt
= get_toplevel_mds(&nlp
, &toplp
, verbose
);
397 if (cnt
&& (md_probe_ioctl(toplp
, cnt
,
398 MD_RAID
, verbose
) < 0))
399 monitord_print(0, gettext(
401 "RAID-5 components %d ioctl error\n"),
407 metafreenamelist(nlp
);
408 metafreenamelist(toplp
);
412 * Trans probes are different. -- so whats new.
413 * we separate out the master and log device and then issue the
415 * Since the underlying device could be disk, stripe, RAID or miror,
416 * we have to sort them out and then call the ioctl for each.
420 probe_trans_devs(boolean_e verbose
)
422 mdnamelist_t
*nlp
, *toplp
;
423 mdnamelist_t
*trans_raidlp
, *trans_mmlp
, *trans_stripelp
;
425 md_error_t e
= mdnullerror
;
428 trans_raidlp
= trans_mmlp
= trans_stripelp
= NULL
;
430 if (meta_get_trans_names(sp
, &nlp
, 0, &e
) > 0) {
432 * get a list of master and log metadevices.
435 cnt
= create_trans_compslist(&nlp
, &toplp
, verbose
);
436 if (verbose
== True
) {
439 for (i
= 0, nlp
= toplp
; i
< cnt
; i
++) {
440 monitord_print(6, gettext(
441 "tran: underlying drv %s\n"),
442 (nlp
->namep
)->cname
);
447 /* underlying RAID-5 components */
449 cnt
= get_namelist(&toplp
, &trans_raidlp
, MD_RAID
);
450 if ((cnt
> 0) && (md_probe_ioctl(trans_raidlp
, cnt
,
451 MD_RAID
, verbose
) < 0))
452 monitord_print(0, gettext(
454 "RAID-5 components %d ioctl error\n"),
456 metafreenamelist(trans_raidlp
);
458 /* underlying mirror components */
460 cnt
= get_namelist(&toplp
, &trans_mmlp
, MD_MIRROR
);
462 if ((cnt
> 0) && (md_probe_ioctl(trans_mmlp
, cnt
,
463 MD_MIRROR
, verbose
) < 0))
464 monitord_print(0, gettext(
466 "mirror components %d ioctl error\n"),
468 metafreenamelist(trans_mmlp
);
470 /* underlying stripe components */
472 cnt
= get_namelist(&toplp
, &trans_stripelp
, MD_STRIPE
);
473 if ((cnt
> 0) && (md_probe_ioctl(trans_stripelp
, cnt
,
474 MD_STRIPE
, verbose
) < 0))
475 monitord_print(0, gettext(
477 "stripe components %d ioctl error\n"),
480 metafreenamelist(trans_stripelp
);
481 metafreenamelist(nlp
);
488 * probe hot spares. This is differs from other approaches since
489 * there are no read/write routines through md. We check at the physical
490 * component level and then delete it if its bad.
494 probe_hotspare_devs(boolean_e verbose
)
496 mdhspnamelist_t
*hspnlp
= NULL
;
499 md_error_t e
= mdnullerror
;
501 if (meta_get_hsp_names(sp
, &hspnlp
, 0, &e
) <= 0) {
506 for (p
= hspnlp
; (p
!= NULL
); p
= p
->next
) {
507 mdhspname_t
*hspnp
= p
->hspnamep
;
510 monitord_print(6, "%s %s\n", gettext("name"),
513 if ((hspp
= meta_get_hsp(sp
, hspnp
, &e
)) == NULL
)
516 if (hspp
->hotspares
.hotspares_len
!= 0) {
518 monitord_print(6, " %u hotspares\n",
519 hspp
->hotspares
.hotspares_len
);
520 delete_hotspares_impl(hspnp
, hspp
, verbose
);
524 metafreehspnamelist(hspnlp
);