Home | History | Annotate | Download | only in md_monitord
      1      0    stevel /*
      2      0    stevel  * CDDL HEADER START
      3      0    stevel  *
      4      0    stevel  * The contents of this file are subject to the terms of the
      5   6630  sk102515  * Common Development and Distribution License (the "License").
      6   6630  sk102515  * You may not use this file except in compliance with the License.
      7      0    stevel  *
      8      0    stevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9      0    stevel  * or http://www.opensolaris.org/os/licensing.
     10      0    stevel  * See the License for the specific language governing permissions
     11      0    stevel  * and limitations under the License.
     12      0    stevel  *
     13      0    stevel  * When distributing Covered Code, include this CDDL HEADER in each
     14      0    stevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15      0    stevel  * If applicable, add the following below this CDDL HEADER, with the
     16      0    stevel  * fields enclosed by brackets "[]" replaced with your own identifying
     17      0    stevel  * information: Portions Copyright [yyyy] [name of copyright owner]
     18      0    stevel  *
     19      0    stevel  * CDDL HEADER END
     20      0    stevel  */
     21      0    stevel /*
     22   9818    Andrew  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23      0    stevel  * Use is subject to license terms.
     24      0    stevel  */
     25      0    stevel 
     26      0    stevel 
     27      0    stevel #include "md_monitord.h"
     28      0    stevel 
     29      0    stevel #define	MD_PROBE_OPEN_T "probe open test"
     30      0    stevel 
     31      0    stevel /*
     32      0    stevel  * Failure return's a 1
     33      0    stevel  */
     34      0    stevel int
     35      0    stevel hotspare_ok(char *bname)
     36      0    stevel {
     37      0    stevel 	int fd;
     38      0    stevel 	char buf[512];
     39      0    stevel 
     40      0    stevel 	if ((fd = open(bname, O_RDONLY)) < 0)
     41      0    stevel 		return (0);
     42   6630  sk102515 	if (read(fd, buf, sizeof (buf)) < 0) {
     43   6630  sk102515 		(void) close(fd);
     44      0    stevel 		return (0);
     45   6630  sk102515 	}
     46   6630  sk102515 	(void) close(fd);
     47      0    stevel 	return (1);
     48      0    stevel }
     49      0    stevel 
     50      0    stevel void
     51      0    stevel delete_hotspares_impl(mdhspname_t *hspnp, md_hsp_t *hspp, boolean_e verbose)
     52      0    stevel {
     53      0    stevel 	md_hs_t *hsp;
     54      0    stevel 	uint_t		hsi;
     55      0    stevel 	char    *cname, *bname, *hs_state;
     56      0    stevel 	md_error_t e = mdnullerror;
     57      0    stevel 	int deleted_hs = 0;
     58      0    stevel 
     59      0    stevel 	for (hsi = 0; (hsi < hspp->hotspares.hotspares_len); ++hsi) {
     60      0    stevel 		mdnamelist_t *nlp;
     61      0    stevel 
     62      0    stevel 		hsp = &hspp->hotspares.hotspares_val[hsi];
     63      0    stevel 		if (verbose == True)
     64      0    stevel 			monitord_print(6, "hsi %d\n", hsi);
     65      0    stevel 		cname = hsp->hsnamep->cname;
     66      0    stevel 		bname = hsp->hsnamep->bname;
     67      0    stevel 		nlp = NULL;
     68  11053     Surya 		(void) metanamelist_append(&nlp, hsp->hsnamep);
     69      0    stevel 		hs_state = hs_state_to_name(hsp, NULL);
     70      0    stevel 		/* print hotspare */
     71      0    stevel 		if (verbose == True)
     72      0    stevel 			monitord_print(6, "\t%-19s\t%-19s\t%-12s\n",
     73      0    stevel 			    cname, bname, hs_state);
     74      0    stevel 		if (hsp->state == HSS_AVAILABLE) {
     75      0    stevel 			if (hotspare_ok(bname))
     76      0    stevel 				continue;
     77      0    stevel 
     78      0    stevel 			monitord_print(6, gettext(
     79   6630  sk102515 			    "NOTICE: Hotspare %s in %s has failed.\n"
     80   6630  sk102515 			    "\tDeleting %s since it is not in use\n\n"),
     81   6630  sk102515 			    bname, hspnp->hspname, bname);
     82      0    stevel 
     83      0    stevel 			if (meta_hs_delete(sp, hspnp, nlp, 0, &e) != NULL) {
     84      0    stevel 				mde_perror(&e, "");
     85   9818    Andrew 				mdclrerror(&e);
     86      0    stevel 			} else {
     87      0    stevel 				deleted_hs++;
     88      0    stevel 			}
     89      0    stevel 		} else {
     90      0    stevel 			if (verbose == True)
     91      0    stevel 				monitord_print(6, gettext(
     92   6630  sk102515 				    "%s in use - skipping\n"), cname);
     93      0    stevel 		}
     94      0    stevel 	}
     95      0    stevel }
     96      0    stevel 
     97      0    stevel 
     98      0    stevel 
     99      0    stevel /*
    100      0    stevel  * Generic routine to issue probe ioctls
    101      0    stevel  */
    102      0    stevel 
    103      0    stevel int
    104      0    stevel md_probe_ioctl(mdnamelist_t *nlp, int ndevs, char *drvname, boolean_e verbose)
    105      0    stevel {
    106      0    stevel 	mdnamelist_t	*p;
    107      0    stevel 	mdname_t	*np;
    108   6630  sk102515 	md_probedev_t	probe_ioc, *iocp;
    109   6630  sk102515 	int		i, retval = 0;
    110      0    stevel 	/*
    111      0    stevel 	 * Allocate space for all the metadevices and fill in
    112      0    stevel 	 * the minor numbers.
    113      0    stevel 	 */
    114      0    stevel 
    115  11053     Surya 	(void) memset(&probe_ioc, 0, sizeof (probe_ioc));
    116      0    stevel 	iocp = &probe_ioc;
    117      0    stevel 
    118      0    stevel 	if ((iocp->mnum_list = (uintptr_t)calloc(ndevs, sizeof (minor_t)))
    119      0    stevel 	    == 0) {
    120      0    stevel 		monitord_print(0, "md_probe_ioctl: calloc");
    121      0    stevel 		return (-1);
    122      0    stevel 	}
    123      0    stevel 
    124      0    stevel 	(void) strcpy(iocp->test_name, MD_PROBE_OPEN_T);
    125      0    stevel 	MD_SETDRIVERNAME(&probe_ioc, drvname, sp->setno);
    126      0    stevel 
    127      0    stevel 	if (verbose == True) {
    128      0    stevel 		monitord_print(6, "\n\nmd_probe_ioctl: %s: %s\n",
    129      0    stevel 		    (strcmp(sp->setname, MD_LOCAL_NAME) == 0) ?
    130      0    stevel 		    gettext("local_set") :
    131      0    stevel 		    sp->setname, iocp->md_driver.md_drivername);
    132      0    stevel 	}
    133      0    stevel 
    134      0    stevel 	iocp->nmdevs = ndevs;
    135      0    stevel 	if (verbose == True)
    136      0    stevel 		monitord_print(6, "...ndevs 0x%x\n", ndevs);
    137      0    stevel 
    138      0    stevel 	for (p = nlp, i = 0; p; p = p->next, i++) {
    139      0    stevel 		np = p->namep;
    140     62     jeanm 		((minor_t *)(uintptr_t)iocp->mnum_list)[i] =
    141     62     jeanm 		    meta_getminor(np->dev);
    142      0    stevel 		if (verbose == True)
    143      0    stevel 			monitord_print(6, "...%s 0x%lx\n", np->cname,
    144     62     jeanm 			    ((minor_t *)(uintptr_t)iocp->mnum_list)[i]);
    145      0    stevel 	}
    146      0    stevel 
    147      0    stevel 
    148      0    stevel 	if (issue_ioctl == True) {
    149      0    stevel 		if (metaioctl(MD_IOCPROBE_DEV, iocp, &(iocp->mde), NULL) != 0)
    150      0    stevel 			retval = -1;
    151      0    stevel 	}
    152   9818    Andrew 
    153   9818    Andrew 	Free((void *)(uintptr_t)iocp->mnum_list);
    154      0    stevel 	return (retval);
    155      0    stevel }
    156      0    stevel /*
    157      0    stevel  *
    158      0    stevel  *  - remove p from nlp list
    159      0    stevel  *  - put it on the toplp list.
    160      0    stevel  *  - update the p to the next element
    161      0    stevel  */
    162      0    stevel 
    163      0    stevel void
    164      0    stevel add_to_list(mdnamelist_t **curpp, mdnamelist_t **prevpp,
    165      0    stevel 		mdnamelist_t **newlpp)
    166      0    stevel {
    167      0    stevel 	mdnamelist_t	*p, *prevp, *nlp;
    168      0    stevel 
    169      0    stevel 	p = *curpp;
    170      0    stevel 	prevp = *prevpp;
    171      0    stevel 	nlp = *newlpp;
    172      0    stevel 
    173      0    stevel 	if (prevp == p) {
    174      0    stevel 		/* if first element reset prevp */
    175      0    stevel 			prevp = p->next;
    176      0    stevel 			p->next = nlp;
    177      0    stevel 			nlp = p;
    178      0    stevel 			p = prevp;
    179      0    stevel 	} else {
    180      0    stevel 		prevp->next = p->next;
    181      0    stevel 		p->next = nlp;
    182      0    stevel 		nlp = p;
    183      0    stevel 		p = prevp->next;
    184      0    stevel 	}
    185      0    stevel 	*curpp = p;
    186      0    stevel 	*prevpp = prevp;
    187      0    stevel 	*newlpp = nlp;
    188      0    stevel }
    189      0    stevel /*
    190      0    stevel  * Scans the given list of metadeivces and returns a list of top level
    191      0    stevel  * metadevices.
    192      0    stevel  * Note: The orignal list is not valid at the end and is set to NULL.
    193      0    stevel  */
    194      0    stevel 
    195      0    stevel int
    196      0    stevel get_toplevel_mds(mdnamelist_t **lpp, mdnamelist_t **top_pp, boolean_e verbose)
    197      0    stevel {
    198      0    stevel 	mdnamelist_t	*p, *prevp, *toplp;
    199      0    stevel 	int		ntopmd, i;
    200      0    stevel 	md_common_t	*mdp;
    201      0    stevel 	md_error_t	e = mdnullerror;
    202      0    stevel 
    203      0    stevel 	i = ntopmd = 0;
    204      0    stevel 	prevp = p = *lpp;
    205      0    stevel 	toplp = NULL;
    206      0    stevel 
    207      0    stevel 	while (p) {
    208      0    stevel 		if ((mdp = meta_get_unit(sp, p->namep, &e)) == NULL) {
    209   9818    Andrew 			mdclrerror(&e);
    210      0    stevel 			if (verbose == True)
    211      0    stevel 				monitord_print(6, gettext(
    212   6630  sk102515 				    "......error on (%d)%s\n"), i,
    213   6630  sk102515 				    p->namep->devicesname);
    214      0    stevel 				prevp = p;
    215      0    stevel 				p = p->next;
    216      0    stevel 				continue;
    217      0    stevel 		}
    218      0    stevel 
    219      0    stevel 		if (mdp->parent == MD_NO_PARENT) {
    220      0    stevel 			/* increment the top level md count. */
    221      0    stevel 			ntopmd++;
    222      0    stevel 			add_to_list(&p, &prevp, &toplp);
    223      0    stevel 		} else {
    224      0    stevel 			prevp = p;
    225      0    stevel 			p = p->next;
    226      0    stevel 		}
    227      0    stevel 		i++;
    228      0    stevel 	}
    229      0    stevel 
    230      0    stevel 	*lpp = NULL;
    231      0    stevel 	*top_pp = toplp;
    232      0    stevel 
    233      0    stevel 	return (ntopmd);
    234      0    stevel }
    235      0    stevel 
    236      0    stevel int
    237      0    stevel get_namelist(mdnamelist_t **transdevlist, mdnamelist_t **devlist,
    238      0    stevel 					char *dev_type)
    239      0    stevel {
    240      0    stevel 	mdnamelist_t *np, *prevp;
    241      0    stevel 	md_error_t	e = mdnullerror;
    242      0    stevel 	char		*type_name;
    243      0    stevel 	int		i = 0;
    244      0    stevel 
    245      0    stevel 	prevp = np = *transdevlist;
    246      0    stevel 	while (np) {
    247      0    stevel 		if ((type_name = metagetmiscname(np->namep, &e)) == NULL) {
    248      0    stevel 			*devlist = NULL;
    249   9818    Andrew 			mdclrerror(&e);
    250      0    stevel 			return (-1);
    251      0    stevel 		}
    252      0    stevel 		if (strcmp(type_name, dev_type) == 0) {
    253      0    stevel 			/* move it to the devlist */
    254      0    stevel 			add_to_list(&np, &prevp, devlist);
    255      0    stevel 			i++;
    256      0    stevel 		} else {
    257      0    stevel 			prevp = np;
    258      0    stevel 			np = np->next;
    259      0    stevel 		}
    260      0    stevel 	}
    261      0    stevel 	return (i);
    262      0    stevel }
    263      0    stevel 
    264      0    stevel 
    265      0    stevel mdnamelist_t *
    266      0    stevel create_nlp()
    267      0    stevel {
    268      0    stevel 	mdnamelist_t *np;
    269      0    stevel 
    270      0    stevel 	if (np = (mdnamelist_t *)malloc(sizeof (mdnamelist_t))) {
    271      0    stevel 		np->next = NULL;
    272      0    stevel 		return (np);
    273      0    stevel 	} else {
    274      0    stevel 		/* error condition below */
    275      0    stevel 		monitord_print(0, gettext(
    276      0    stevel 		    "create_nlp: malloc failed\n"));
    277      0    stevel 		monitord_exit(errno);
    278      0    stevel 	}
    279     62     jeanm 	return (0);
    280      0    stevel }
    281      0    stevel 
    282      0    stevel /*
    283      0    stevel  * Create a list of metadevices associated with trans. top_pp points to
    284      0    stevel  * this list. The number of components in the list are also returned.
    285      0    stevel  */
    286      0    stevel int
    287      0    stevel create_trans_compslist(mdnamelist_t **lpp, mdnamelist_t **top_pp,
    288      0    stevel 							boolean_e verbose)
    289      0    stevel {
    290      0    stevel 	mdnamelist_t	*p, *tailp, *toplp, *newlp;
    291      0    stevel 	int		ntoptrans;
    292      0    stevel 	md_error_t	e = mdnullerror;
    293      0    stevel 	md_trans_t	*tp;
    294      0    stevel 
    295      0    stevel 	ntoptrans = 0;
    296      0    stevel 	p = *lpp;
    297      0    stevel 	tailp = toplp = NULL;
    298      0    stevel 	/*
    299      0    stevel 	 * Scan the current list of trans devices. From that
    300      0    stevel 	 * extract all the lower level metadevices and put them on
    301      0    stevel 	 * toplp list.
    302      0    stevel 	 */
    303      0    stevel 
    304      0    stevel 	while (p) {
    305      0    stevel 		if (tp = meta_get_trans(sp, p->namep, &e)) {
    306      0    stevel 			/*
    307      0    stevel 			 * Check the master and log devices to see if they
    308      0    stevel 			 * are metadevices
    309      0    stevel 			 */
    310      0    stevel 			if (metaismeta(tp->masternamep)) {
    311      0    stevel 				if (verbose == True)
    312      0    stevel 					monitord_print(6, gettext(
    313      0    stevel 					    "master metadevice\n"));
    314      0    stevel 				/* get a mdnamelist_t. */
    315      0    stevel 				newlp = create_nlp();
    316      0    stevel 				newlp->namep = tp->masternamep;
    317      0    stevel 				if (toplp == NULL) {
    318      0    stevel 					toplp = tailp = newlp;
    319      0    stevel 				} else {
    320      0    stevel 					tailp->next = newlp;
    321      0    stevel 					tailp = newlp;
    322      0    stevel 				}
    323      0    stevel 				ntoptrans++;
    324      0    stevel 			}
    325      0    stevel 
    326      0    stevel 			if (tp->lognamep && metaismeta(tp->lognamep)) {
    327      0    stevel 				if (verbose == True)
    328      0    stevel 					monitord_print(6, gettext(
    329      0    stevel 					    "log metadevice\n"));
    330      0    stevel 				newlp = create_nlp();
    331      0    stevel 				newlp->namep = tp->lognamep;
    332      0    stevel 				if (toplp == NULL) {
    333      0    stevel 					toplp = tailp = newlp;
    334      0    stevel 				} else {
    335      0    stevel 					tailp->next = newlp;
    336      0    stevel 					tailp = newlp;
    337      0    stevel 				}
    338      0    stevel 				ntoptrans++;
    339      0    stevel 			}
    340      0    stevel 			p = p->next;
    341   9818    Andrew 		} else {
    342   9818    Andrew 			mdclrerror(&e);
    343      0    stevel 		}
    344      0    stevel 	}
    345      0    stevel 	*top_pp = toplp;
    346      0    stevel 	return (ntoptrans);
    347      0    stevel }
    348      0    stevel 
    349      0    stevel void
    350      0    stevel probe_mirror_devs(boolean_e verbose)
    351      0    stevel {
    352      0    stevel 	mdnamelist_t	*nlp, *toplp;
    353      0    stevel 	int		cnt;
    354      0    stevel 	md_error_t	e = mdnullerror;
    355      0    stevel 
    356      0    stevel 	nlp = toplp = NULL;
    357      0    stevel 
    358      0    stevel 	if (meta_get_mirror_names(sp, &nlp, 0, &e) > 0) {
    359      0    stevel 		/*
    360      0    stevel 		 * We have some mirrors to probe
    361      0    stevel 		 * get a list of top-level mirrors
    362      0    stevel 		 */
    363      0    stevel 
    364      0    stevel 		cnt = get_toplevel_mds(&nlp, &toplp, verbose);
    365      0    stevel 		if (cnt && (md_probe_ioctl(toplp, cnt,
    366   6630  sk102515 		    MD_MIRROR, verbose) < 0))
    367      0    stevel 			monitord_print(0, gettext(
    368      0    stevel 			    "probe_mirror_devs: "
    369      0    stevel 			    "mirror components %d ioctl error\n"),
    370      0    stevel 			    cnt);
    371      0    stevel 
    372   9818    Andrew 	} else {
    373   9818    Andrew 		mdclrerror(&e);
    374      0    stevel 	}
    375      0    stevel 
    376      0    stevel 	metafreenamelist(nlp);
    377      0    stevel 	metafreenamelist(toplp);
    378      0    stevel }
    379      0    stevel 
    380      0    stevel void
    381      0    stevel probe_raid_devs(boolean_e verbose)
    382      0    stevel {
    383      0    stevel 	mdnamelist_t	*nlp, *toplp;
    384      0    stevel 	int		cnt;
    385      0    stevel 	md_error_t	e = mdnullerror;
    386      0    stevel 
    387      0    stevel 	nlp = toplp = NULL;
    388      0    stevel 
    389      0    stevel 	if (meta_get_raid_names(sp, &nlp, 0, &e) > 0) {
    390      0    stevel 		/*
    391      0    stevel 		 * We have some mirrors to probe
    392      0    stevel 		 * get a list of top-level mirrors
    393      0    stevel 		 */
    394      0    stevel 
    395      0    stevel 		cnt = get_toplevel_mds(&nlp, &toplp, verbose);
    396      0    stevel 
    397      0    stevel 		if (cnt && (md_probe_ioctl(toplp, cnt,
    398   6630  sk102515 		    MD_RAID, verbose) < 0))
    399      0    stevel 			monitord_print(0, gettext(
    400      0    stevel 			    "probe_raid_devs: "
    401      0    stevel 			    "RAID-5 components %d ioctl error\n"),
    402      0    stevel 			    cnt);
    403   9818    Andrew 	} else {
    404   9818    Andrew 		mdclrerror(&e);
    405      0    stevel 	}
    406      0    stevel 
    407      0    stevel 	metafreenamelist(nlp);
    408      0    stevel 	metafreenamelist(toplp);
    409      0    stevel }
    410      0    stevel 
    411      0    stevel /*
    412      0    stevel  * Trans probes are different. -- so whats new.
    413      0    stevel  * we separate out the master and log device and then issue the
    414      0    stevel  * probe calls.
    415      0    stevel  * Since the underlying device could be disk, stripe, RAID or miror,
    416      0    stevel  * we have to sort them out and then call the ioctl for each.
    417      0    stevel  */
    418      0    stevel 
    419      0    stevel void
    420      0    stevel probe_trans_devs(boolean_e verbose)
    421      0    stevel {
    422      0    stevel 	mdnamelist_t	*nlp, *toplp;
    423      0    stevel 	mdnamelist_t	*trans_raidlp, *trans_mmlp, *trans_stripelp;
    424      0    stevel 	int		cnt;
    425      0    stevel 	md_error_t	e = mdnullerror;
    426      0    stevel 
    427      0    stevel 	nlp = toplp = NULL;
    428      0    stevel 	trans_raidlp = trans_mmlp = trans_stripelp = NULL;
    429      0    stevel 
    430      0    stevel 	if (meta_get_trans_names(sp, &nlp, 0, &e) > 0) {
    431      0    stevel 		/*
    432      0    stevel 		 * get a list of master and log metadevices.
    433      0    stevel 		 */
    434      0    stevel 
    435      0    stevel 		cnt = create_trans_compslist(&nlp, &toplp, verbose);
    436      0    stevel 		if (verbose == True) {
    437      0    stevel 			int i;
    438      0    stevel 
    439      0    stevel 			for (i = 0, nlp = toplp; i < cnt; i++) {
    440      0    stevel 				monitord_print(6, gettext(
    441      0    stevel 				    "tran: underlying drv %s\n"),
    442      0    stevel 				    (nlp->namep)->cname);
    443      0    stevel 				nlp = nlp->next;
    444      0    stevel 			}
    445      0    stevel 		}
    446      0    stevel 
    447      0    stevel 		/* underlying RAID-5 components */
    448      0    stevel 
    449      0    stevel 		cnt = get_namelist(&toplp, &trans_raidlp, MD_RAID);
    450      0    stevel 		if ((cnt > 0) && (md_probe_ioctl(trans_raidlp, cnt,
    451      0    stevel 		    MD_RAID, verbose) < 0))
    452      0    stevel 			monitord_print(0, gettext(
    453      0    stevel 			    "probe_trans_devs: "
    454      0    stevel 			    "RAID-5 components %d ioctl error\n"),
    455      0    stevel 			    cnt);
    456      0    stevel 		metafreenamelist(trans_raidlp);
    457      0    stevel 
    458      0    stevel 		/* underlying mirror components */
    459      0    stevel 
    460      0    stevel 		cnt = get_namelist(&toplp, &trans_mmlp, MD_MIRROR);
    461      0    stevel 
    462      0    stevel 		if ((cnt > 0) && (md_probe_ioctl(trans_mmlp, cnt,
    463      0    stevel 		    MD_MIRROR, verbose) < 0))
    464      0    stevel 			monitord_print(0, gettext(
    465      0    stevel 			    "probe_trans_devs: "
    466      0    stevel 			    "mirror components %d ioctl error\n"),
    467      0    stevel 			    cnt);
    468      0    stevel 		metafreenamelist(trans_mmlp);
    469      0    stevel 
    470      0    stevel 		/* underlying stripe components */
    471      0    stevel 
    472      0    stevel 		cnt = get_namelist(&toplp, &trans_stripelp, MD_STRIPE);
    473      0    stevel 		if ((cnt > 0) && (md_probe_ioctl(trans_stripelp, cnt,
    474      0    stevel 		    MD_STRIPE, verbose) < 0))
    475      0    stevel 			monitord_print(0, gettext(
    476      0    stevel 			    "probe_trans_devs: "
    477      0    stevel 			    "stripe components %d ioctl error\n"),
    478      0    stevel 			    cnt);
    479      0    stevel 
    480      0    stevel 		metafreenamelist(trans_stripelp);
    481      0    stevel 		metafreenamelist(nlp);
    482   9818    Andrew 	} else {
    483   9818    Andrew 		mdclrerror(&e);
    484      0    stevel 	}
    485      0    stevel }
    486      0    stevel 
    487      0    stevel /*
    488      0    stevel  * probe hot spares. This is differs from other approaches since
    489      0    stevel  * there are no read/write routines through md. We check at the physical
    490      0    stevel  * component level and then delete it if its bad.
    491      0    stevel  */
    492      0    stevel 
    493      0    stevel void
    494      0    stevel probe_hotspare_devs(boolean_e verbose)
    495      0    stevel {
    496      0    stevel 	mdhspnamelist_t *hspnlp = NULL;
    497      0    stevel 	mdhspnamelist_t	*p;
    498      0    stevel 	md_hsp_t	*hspp;
    499      0    stevel 	md_error_t	e = mdnullerror;
    500      0    stevel 
    501   9818    Andrew 	if (meta_get_hsp_names(sp, &hspnlp, 0, &e) <= 0) {
    502   9818    Andrew 		mdclrerror(&e);
    503      0    stevel 		return;
    504      0    stevel 	}
    505   9818    Andrew 
    506      0    stevel 	for (p = hspnlp; (p != NULL); p = p->next) {
    507      0    stevel 		mdhspname_t	*hspnp = p->hspnamep;
    508      0    stevel 
    509      0    stevel 		if (verbose == True)
    510      0    stevel 			monitord_print(6, "%s %s\n", gettext("name"),
    511      0    stevel 			    hspnp->hspname);
    512      0    stevel 
    513      0    stevel 		if ((hspp = meta_get_hsp(sp, hspnp, &e)) == NULL)
    514      0    stevel 			continue;
    515      0    stevel 
    516      0    stevel 		if (hspp->hotspares.hotspares_len != 0) {
    517      0    stevel 			if (verbose == True)
    518      0    stevel 				monitord_print(6, " %u hotspares\n",
    519   6630  sk102515 				    hspp->hotspares.hotspares_len);
    520      0    stevel 			delete_hotspares_impl(hspnp, hspp, verbose);
    521      0    stevel 		}
    522      0    stevel 	}
    523   9818    Andrew 	mdclrerror(&e);
    524      0    stevel 	metafreehspnamelist(hspnlp);
    525      0    stevel }
    526