7712 mandoc -Tlint does always exit with error code 0
[unleashed.git] / usr / src / cmd / lvm / md_monitord / probedev.c
blobb2d94caedb4f2812a9d79a11e35993f0d02bdc00
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
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
34 int
35 hotspare_ok(char *bname)
37 int fd;
38 char buf[512];
40 if ((fd = open(bname, O_RDONLY)) < 0)
41 return (0);
42 if (read(fd, buf, sizeof (buf)) < 0) {
43 (void) close(fd);
44 return (0);
46 (void) close(fd);
47 return (1);
50 void
51 delete_hotspares_impl(mdhspname_t *hspnp, md_hsp_t *hspp, boolean_e verbose)
53 md_hs_t *hsp;
54 uint_t hsi;
55 char *cname, *bname, *hs_state;
56 md_error_t e = mdnullerror;
57 int deleted_hs = 0;
59 for (hsi = 0; (hsi < hspp->hotspares.hotspares_len); ++hsi) {
60 mdnamelist_t *nlp;
62 hsp = &hspp->hotspares.hotspares_val[hsi];
63 if (verbose == True)
64 monitord_print(6, "hsi %d\n", hsi);
65 cname = hsp->hsnamep->cname;
66 bname = hsp->hsnamep->bname;
67 nlp = NULL;
68 (void) metanamelist_append(&nlp, hsp->hsnamep);
69 hs_state = hs_state_to_name(hsp, NULL);
70 /* print hotspare */
71 if (verbose == True)
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))
76 continue;
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) {
84 mde_perror(&e, "");
85 mdclrerror(&e);
86 } else {
87 deleted_hs++;
89 } else {
90 if (verbose == True)
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)
106 mdnamelist_t *p;
107 mdname_t *np;
108 md_probedev_t probe_ioc, *iocp;
109 int i, retval = 0;
111 * Allocate space for all the metadevices and fill in
112 * the minor numbers.
115 (void) memset(&probe_ioc, 0, sizeof (probe_ioc));
116 iocp = &probe_ioc;
118 if ((iocp->mnum_list = (uintptr_t)calloc(ndevs, sizeof (minor_t)))
119 == 0) {
120 monitord_print(0, "md_probe_ioctl: calloc");
121 return (-1);
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;
135 if (verbose == True)
136 monitord_print(6, "...ndevs 0x%x\n", ndevs);
138 for (p = nlp, i = 0; p; p = p->next, i++) {
139 np = p->namep;
140 ((minor_t *)(uintptr_t)iocp->mnum_list)[i] =
141 meta_getminor(np->dev);
142 if (verbose == True)
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)
150 retval = -1;
153 Free((void *)(uintptr_t)iocp->mnum_list);
154 return (retval);
158 * - remove p from nlp list
159 * - put it on the toplp list.
160 * - update the p to the next element
163 void
164 add_to_list(mdnamelist_t **curpp, mdnamelist_t **prevpp,
165 mdnamelist_t **newlpp)
167 mdnamelist_t *p, *prevp, *nlp;
169 p = *curpp;
170 prevp = *prevpp;
171 nlp = *newlpp;
173 if (prevp == p) {
174 /* if first element reset prevp */
175 prevp = p->next;
176 p->next = nlp;
177 nlp = p;
178 p = prevp;
179 } else {
180 prevp->next = p->next;
181 p->next = nlp;
182 nlp = p;
183 p = prevp->next;
185 *curpp = p;
186 *prevpp = prevp;
187 *newlpp = nlp;
190 * Scans the given list of metadeivces and returns a list of top level
191 * metadevices.
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;
199 int ntopmd, i;
200 md_common_t *mdp;
201 md_error_t e = mdnullerror;
203 i = ntopmd = 0;
204 prevp = p = *lpp;
205 toplp = NULL;
207 while (p) {
208 if ((mdp = meta_get_unit(sp, p->namep, &e)) == NULL) {
209 mdclrerror(&e);
210 if (verbose == True)
211 monitord_print(6, gettext(
212 "......error on (%d)%s\n"), i,
213 p->namep->devicesname);
214 prevp = p;
215 p = p->next;
216 continue;
219 if (mdp->parent == MD_NO_PARENT) {
220 /* increment the top level md count. */
221 ntopmd++;
222 add_to_list(&p, &prevp, &toplp);
223 } else {
224 prevp = p;
225 p = p->next;
227 i++;
230 *lpp = NULL;
231 *top_pp = toplp;
233 return (ntopmd);
237 get_namelist(mdnamelist_t **transdevlist, mdnamelist_t **devlist,
238 char *dev_type)
240 mdnamelist_t *np, *prevp;
241 md_error_t e = mdnullerror;
242 char *type_name;
243 int i = 0;
245 prevp = np = *transdevlist;
246 while (np) {
247 if ((type_name = metagetmiscname(np->namep, &e)) == NULL) {
248 *devlist = NULL;
249 mdclrerror(&e);
250 return (-1);
252 if (strcmp(type_name, dev_type) == 0) {
253 /* move it to the devlist */
254 add_to_list(&np, &prevp, devlist);
255 i++;
256 } else {
257 prevp = np;
258 np = np->next;
261 return (i);
265 mdnamelist_t *
266 create_nlp()
268 mdnamelist_t *np;
270 if (np = (mdnamelist_t *)malloc(sizeof (mdnamelist_t))) {
271 np->next = NULL;
272 return (np);
273 } else {
274 /* error condition below */
275 monitord_print(0, gettext(
276 "create_nlp: malloc failed\n"));
277 monitord_exit(errno);
279 return (0);
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,
288 boolean_e verbose)
290 mdnamelist_t *p, *tailp, *toplp, *newlp;
291 int ntoptrans;
292 md_error_t e = mdnullerror;
293 md_trans_t *tp;
295 ntoptrans = 0;
296 p = *lpp;
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
301 * toplp list.
304 while (p) {
305 if (tp = meta_get_trans(sp, p->namep, &e)) {
307 * Check the master and log devices to see if they
308 * are metadevices
310 if (metaismeta(tp->masternamep)) {
311 if (verbose == True)
312 monitord_print(6, gettext(
313 "master metadevice\n"));
314 /* get a mdnamelist_t. */
315 newlp = create_nlp();
316 newlp->namep = tp->masternamep;
317 if (toplp == NULL) {
318 toplp = tailp = newlp;
319 } else {
320 tailp->next = newlp;
321 tailp = newlp;
323 ntoptrans++;
326 if (tp->lognamep && metaismeta(tp->lognamep)) {
327 if (verbose == True)
328 monitord_print(6, gettext(
329 "log metadevice\n"));
330 newlp = create_nlp();
331 newlp->namep = tp->lognamep;
332 if (toplp == NULL) {
333 toplp = tailp = newlp;
334 } else {
335 tailp->next = newlp;
336 tailp = newlp;
338 ntoptrans++;
340 p = p->next;
341 } else {
342 mdclrerror(&e);
345 *top_pp = toplp;
346 return (ntoptrans);
349 void
350 probe_mirror_devs(boolean_e verbose)
352 mdnamelist_t *nlp, *toplp;
353 int cnt;
354 md_error_t e = mdnullerror;
356 nlp = toplp = NULL;
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"),
370 cnt);
372 } else {
373 mdclrerror(&e);
376 metafreenamelist(nlp);
377 metafreenamelist(toplp);
380 void
381 probe_raid_devs(boolean_e verbose)
383 mdnamelist_t *nlp, *toplp;
384 int cnt;
385 md_error_t e = mdnullerror;
387 nlp = toplp = NULL;
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(
400 "probe_raid_devs: "
401 "RAID-5 components %d ioctl error\n"),
402 cnt);
403 } else {
404 mdclrerror(&e);
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
414 * probe calls.
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.
419 void
420 probe_trans_devs(boolean_e verbose)
422 mdnamelist_t *nlp, *toplp;
423 mdnamelist_t *trans_raidlp, *trans_mmlp, *trans_stripelp;
424 int cnt;
425 md_error_t e = mdnullerror;
427 nlp = toplp = NULL;
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) {
437 int i;
439 for (i = 0, nlp = toplp; i < cnt; i++) {
440 monitord_print(6, gettext(
441 "tran: underlying drv %s\n"),
442 (nlp->namep)->cname);
443 nlp = nlp->next;
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(
453 "probe_trans_devs: "
454 "RAID-5 components %d ioctl error\n"),
455 cnt);
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(
465 "probe_trans_devs: "
466 "mirror components %d ioctl error\n"),
467 cnt);
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(
476 "probe_trans_devs: "
477 "stripe components %d ioctl error\n"),
478 cnt);
480 metafreenamelist(trans_stripelp);
481 metafreenamelist(nlp);
482 } else {
483 mdclrerror(&e);
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.
493 void
494 probe_hotspare_devs(boolean_e verbose)
496 mdhspnamelist_t *hspnlp = NULL;
497 mdhspnamelist_t *p;
498 md_hsp_t *hspp;
499 md_error_t e = mdnullerror;
501 if (meta_get_hsp_names(sp, &hspnlp, 0, &e) <= 0) {
502 mdclrerror(&e);
503 return;
506 for (p = hspnlp; (p != NULL); p = p->next) {
507 mdhspname_t *hspnp = p->hspnamep;
509 if (verbose == True)
510 monitord_print(6, "%s %s\n", gettext("name"),
511 hspnp->hspname);
513 if ((hspp = meta_get_hsp(sp, hspnp, &e)) == NULL)
514 continue;
516 if (hspp->hotspares.hotspares_len != 0) {
517 if (verbose == True)
518 monitord_print(6, " %u hotspares\n",
519 hspp->hotspares.hotspares_len);
520 delete_hotspares_impl(hspnp, hspp, verbose);
523 mdclrerror(&e);
524 metafreehspnamelist(hspnlp);