xref: /onnv-gate/usr/src/lib/libdiskmgt/common/inuse_svm.c (revision 1623:7bac4a816ebe)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*1623Stw21770  * Common Development and Distribution License (the "License").
6*1623Stw21770  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*1623Stw21770  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate 
280Sstevel@tonic-gate /*
290Sstevel@tonic-gate  * Creates and maintains a cache of slices used by SVM.
300Sstevel@tonic-gate  */
310Sstevel@tonic-gate 
320Sstevel@tonic-gate #include <meta.h>
330Sstevel@tonic-gate #include <stdlib.h>
340Sstevel@tonic-gate #include <stdio.h>
350Sstevel@tonic-gate #include <string.h>
361107Ssjelinek #include <libintl.h>
370Sstevel@tonic-gate #include <synch.h>
380Sstevel@tonic-gate #include <thread.h>
390Sstevel@tonic-gate #include <dlfcn.h>
400Sstevel@tonic-gate #include <link.h>
410Sstevel@tonic-gate #include <libsysevent.h>
421107Ssjelinek #include <syslog.h>
430Sstevel@tonic-gate #include <sys/types.h>
440Sstevel@tonic-gate #include <sys/sysevent/eventdefs.h>
450Sstevel@tonic-gate 
460Sstevel@tonic-gate #include "libdiskmgt.h"
470Sstevel@tonic-gate #include "disks_private.h"
480Sstevel@tonic-gate 
490Sstevel@tonic-gate /*
500Sstevel@tonic-gate  * The list of SVM slices in use.
510Sstevel@tonic-gate  */
520Sstevel@tonic-gate 
530Sstevel@tonic-gate struct svm_list {
540Sstevel@tonic-gate 	struct svm_list	*next;
550Sstevel@tonic-gate 	char		*slice;
560Sstevel@tonic-gate 	char		*name;
570Sstevel@tonic-gate 	char		*type;
580Sstevel@tonic-gate };
590Sstevel@tonic-gate 
600Sstevel@tonic-gate static struct svm_list	*svm_listp = NULL;
610Sstevel@tonic-gate static rwlock_t		svm_lock = DEFAULTRWLOCK;
620Sstevel@tonic-gate static int		initialized = 0;
630Sstevel@tonic-gate static mutex_t		init_lock = DEFAULTMUTEX;
640Sstevel@tonic-gate 
650Sstevel@tonic-gate static int	add_use_record(char *devname, char *type, char *mname);
660Sstevel@tonic-gate static int	diskset_info(mdsetname_t *sp);
670Sstevel@tonic-gate static int	drive_in_diskset(char *dpath, char *setname);
680Sstevel@tonic-gate static void	event_handler();
690Sstevel@tonic-gate static void	free_names(mdnamelist_t *nlp);
700Sstevel@tonic-gate static void	free_svm(struct svm_list *listp);
710Sstevel@tonic-gate static int	init_svm();
720Sstevel@tonic-gate static int	load_svm();
730Sstevel@tonic-gate static int	new_entry(char *sname, char *type, char *mname,
740Sstevel@tonic-gate 			    mdsetname_t *sp);
750Sstevel@tonic-gate 
760Sstevel@tonic-gate /*
770Sstevel@tonic-gate  * Pointers to libmeta functions that we dynamically resolve.
780Sstevel@tonic-gate  */
790Sstevel@tonic-gate static set_t		(*mdl_get_max_sets)(md_error_t *ep);
800Sstevel@tonic-gate static void		(*mdl_mdclrerror)(md_error_t *ep);
810Sstevel@tonic-gate static md_error_t	*mdl_mdnullerror;
820Sstevel@tonic-gate static void		(*mdl_metaflushnames)(int flush_sr_cache);
830Sstevel@tonic-gate static void		(*mdl_metaflushsetname)(mdsetname_t *sp);
840Sstevel@tonic-gate static void		(*mdl_metafreenamelist)(mdnamelist_t *nlp);
850Sstevel@tonic-gate static void		(*mdl_metafreereplicalist)(md_replicalist_t *rlp);
860Sstevel@tonic-gate static md_drive_desc	*(*mdl_metaget_drivedesc)(mdsetname_t *sp, int flags,
870Sstevel@tonic-gate 			    md_error_t *ep);
880Sstevel@tonic-gate static mdname_t		*(*mdl_metaname)(mdsetname_t **spp, char *uname,
89*1623Stw21770 			    meta_device_type_t uname_type, md_error_t *ep);
900Sstevel@tonic-gate static int		(*mdl_metareplicalist)(mdsetname_t *sp, int flags,
910Sstevel@tonic-gate 			    md_replicalist_t **rlpp, md_error_t *ep);
920Sstevel@tonic-gate static mdsetname_t	*(*mdl_metasetnosetname)(set_t setno, md_error_t *ep);
930Sstevel@tonic-gate static int		(*mdl_meta_get_hotspare_names)(mdsetname_t *sp,
940Sstevel@tonic-gate 			    mdnamelist_t **nlpp, int options, md_error_t *ep);
950Sstevel@tonic-gate static md_raid_t	*(*mdl_meta_get_raid)(mdsetname_t *sp, mdname_t *raidnp,
960Sstevel@tonic-gate 			    md_error_t *ep);
970Sstevel@tonic-gate static int		(*mdl_meta_get_raid_names)(mdsetname_t *sp,
980Sstevel@tonic-gate 			    mdnamelist_t **nlpp, int options, md_error_t *ep);
990Sstevel@tonic-gate static md_sp_t		*(*mdl_meta_get_sp)(mdsetname_t *sp, mdname_t *np,
1000Sstevel@tonic-gate 			    md_error_t *ep);
1010Sstevel@tonic-gate static int		(*mdl_meta_get_sp_names)(mdsetname_t *sp,
1020Sstevel@tonic-gate 			    mdnamelist_t **nlpp, int options, md_error_t *ep);
1030Sstevel@tonic-gate static md_stripe_t	*(*mdl_meta_get_stripe)(mdsetname_t *sp,
1040Sstevel@tonic-gate 			    mdname_t *stripenp, md_error_t *ep);
1050Sstevel@tonic-gate static int		(*mdl_meta_get_stripe_names)(mdsetname_t *sp,
1060Sstevel@tonic-gate 			    mdnamelist_t **nlpp, int options, md_error_t *ep);
1070Sstevel@tonic-gate static int		(*mdl_meta_get_trans_names)(mdsetname_t *sp,
1080Sstevel@tonic-gate 			    mdnamelist_t **nlpp, int options, md_error_t *ep);
1090Sstevel@tonic-gate static void		(*mdl_meta_invalidate_name)(mdname_t *np);
1100Sstevel@tonic-gate static void		(*mdl_sdssc_bind_library)();
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate /*
1130Sstevel@tonic-gate  * Search the list of devices under SVM for the specified device.
1140Sstevel@tonic-gate  */
1150Sstevel@tonic-gate int
inuse_svm(char * slice,nvlist_t * attrs,int * errp)1160Sstevel@tonic-gate inuse_svm(char *slice, nvlist_t *attrs, int *errp)
1170Sstevel@tonic-gate {
1180Sstevel@tonic-gate 	struct svm_list	*listp;
1190Sstevel@tonic-gate 	int		found = 0;
1200Sstevel@tonic-gate 
1210Sstevel@tonic-gate 	*errp = 0;
1220Sstevel@tonic-gate 	if (slice == NULL) {
1230Sstevel@tonic-gate 	    return (found);
1240Sstevel@tonic-gate 	}
1250Sstevel@tonic-gate 
1260Sstevel@tonic-gate 	(void) mutex_lock(&init_lock);
1270Sstevel@tonic-gate 	if (!initialized) {
128767Ssjelinek 		/* dynamically load libmeta */
129767Ssjelinek 		if (init_svm()) {
130767Ssjelinek 			/*
131767Ssjelinek 			 * need to initialize the cluster library to
132767Ssjelinek 			 * avoid seg faults
133767Ssjelinek 			 */
134767Ssjelinek 			(mdl_sdssc_bind_library)();
135767Ssjelinek 
136767Ssjelinek 			/* load the SVM cache */
137767Ssjelinek 			*errp = load_svm();
1380Sstevel@tonic-gate 
139767Ssjelinek 			if (*errp == 0) {
140767Ssjelinek 				/* start a thread to monitor the svm config */
141767Ssjelinek 				sysevent_handle_t *shp;
142767Ssjelinek 				const char *subclass_list[1];
143767Ssjelinek 				/*
144767Ssjelinek 				 * Only start the svmevent thread if
145767Ssjelinek 				 * we are not doing an install
146767Ssjelinek 				 */
147767Ssjelinek 
148767Ssjelinek 				if (getenv("_LIBDISKMGT_INSTALL") == NULL) {
149767Ssjelinek 					shp = sysevent_bind_handle(
150767Ssjelinek 					    event_handler);
151767Ssjelinek 					if (shp != NULL) {
152767Ssjelinek 						subclass_list[0] = EC_SUB_ALL;
153767Ssjelinek 						if (sysevent_subscribe_event(
154767Ssjelinek 						    shp, EC_SVM_CONFIG,
155767Ssjelinek 						    subclass_list, 1) != 0) {
156767Ssjelinek 							*errp = errno;
157767Ssjelinek 						}
158767Ssjelinek 					} else {
159767Ssjelinek 						*errp = errno;
160767Ssjelinek 					}
1611107Ssjelinek 					if (*errp) {
1621107Ssjelinek 						/*
1631107Ssjelinek 						 * If the sysevent thread fails,
1641107Ssjelinek 						 * log the error but continue
1651107Ssjelinek 						 * on. This failing to start
1661107Ssjelinek 						 * is not catastrophic in
1671107Ssjelinek 						 * particular for short lived
1681107Ssjelinek 						 * consumers of libdiskmgt.
1691107Ssjelinek 						 */
1701107Ssjelinek 						syslog(LOG_WARNING,
1711107Ssjelinek 						    dgettext(TEXT_DOMAIN,
1721107Ssjelinek 						    "libdiskmgt: sysevent "
1731107Ssjelinek 						    "thread for SVM failed "
1741107Ssjelinek 						    "to start\n"));
1751107Ssjelinek 						*errp = 0;
1761107Ssjelinek 					}
177767Ssjelinek 				}
178767Ssjelinek 			}
179767Ssjelinek 		}
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate 		if (*errp == 0) {
182767Ssjelinek 			initialized = 1;
1830Sstevel@tonic-gate 		}
1840Sstevel@tonic-gate 	}
1850Sstevel@tonic-gate 	(void) mutex_unlock(&init_lock);
1860Sstevel@tonic-gate 
1870Sstevel@tonic-gate 	(void) rw_rdlock(&svm_lock);
1880Sstevel@tonic-gate 	listp = svm_listp;
1890Sstevel@tonic-gate 	while (listp != NULL) {
1900Sstevel@tonic-gate 	    if (strcmp(slice, listp->slice) == 0) {
1910Sstevel@tonic-gate 		libdiskmgt_add_str(attrs, DM_USED_BY, DM_USE_SVM, errp);
1920Sstevel@tonic-gate 		if (strcmp(listp->type, "mdb") == 0 ||
1930Sstevel@tonic-gate 		    strcmp(listp->type, "hs") == 0) {
1940Sstevel@tonic-gate 
1950Sstevel@tonic-gate 		    libdiskmgt_add_str(attrs, DM_USED_NAME, listp->type, errp);
1960Sstevel@tonic-gate 		} else {
1970Sstevel@tonic-gate 		    char name[MAXPATHLEN];
1980Sstevel@tonic-gate 		    (void) snprintf(name, MAXPATHLEN, "%s:%s", listp->type,
1990Sstevel@tonic-gate 			listp->name);
2000Sstevel@tonic-gate 		    libdiskmgt_add_str(attrs, DM_USED_NAME, name, errp);
2010Sstevel@tonic-gate 		}
2020Sstevel@tonic-gate 		found = 1;
2030Sstevel@tonic-gate 		break;
2040Sstevel@tonic-gate 	    }
2050Sstevel@tonic-gate 	    listp = listp->next;
2060Sstevel@tonic-gate 	}
2070Sstevel@tonic-gate 	(void) rw_unlock(&svm_lock);
2080Sstevel@tonic-gate 
2090Sstevel@tonic-gate 	return (found);
2100Sstevel@tonic-gate }
2110Sstevel@tonic-gate 
2120Sstevel@tonic-gate static int
add_use_record(char * devname,char * type,char * mname)2130Sstevel@tonic-gate add_use_record(char *devname, char *type, char *mname)
2140Sstevel@tonic-gate {
2150Sstevel@tonic-gate 	struct svm_list *sp;
2160Sstevel@tonic-gate 
2170Sstevel@tonic-gate 	/* If prev. record is a dup, skip it. */
2180Sstevel@tonic-gate 	if (svm_listp != NULL && strcmp(svm_listp->slice, devname) == 0 &&
2190Sstevel@tonic-gate 	    strcmp(svm_listp->type, type) == 0) {
2200Sstevel@tonic-gate 	    return (0);
2210Sstevel@tonic-gate 	}
2220Sstevel@tonic-gate 
2230Sstevel@tonic-gate 	sp = (struct svm_list *)malloc(sizeof (struct svm_list));
2240Sstevel@tonic-gate 	if (sp == NULL) {
2250Sstevel@tonic-gate 	    return (ENOMEM);
2260Sstevel@tonic-gate 	}
2270Sstevel@tonic-gate 
2280Sstevel@tonic-gate 	if ((sp->slice = strdup(devname)) == NULL) {
2290Sstevel@tonic-gate 	    free(sp);
2300Sstevel@tonic-gate 	    return (ENOMEM);
2310Sstevel@tonic-gate 	}
2320Sstevel@tonic-gate 
2330Sstevel@tonic-gate 	if ((sp->name = strdup(mname)) == NULL) {
2340Sstevel@tonic-gate 	    free(sp->slice);
2350Sstevel@tonic-gate 	    free(sp);
2360Sstevel@tonic-gate 	    return (ENOMEM);
2370Sstevel@tonic-gate 	}
2380Sstevel@tonic-gate 
2390Sstevel@tonic-gate 	if ((sp->type = strdup(type)) == NULL) {
2400Sstevel@tonic-gate 	    free(sp->slice);
2410Sstevel@tonic-gate 	    free(sp->name);
2420Sstevel@tonic-gate 	    free(sp);
2430Sstevel@tonic-gate 	    return (ENOMEM);
2440Sstevel@tonic-gate 	}
2450Sstevel@tonic-gate 
2460Sstevel@tonic-gate 	sp->next = svm_listp;
2470Sstevel@tonic-gate 	svm_listp = sp;
2480Sstevel@tonic-gate 
2490Sstevel@tonic-gate 	return (0);
2500Sstevel@tonic-gate }
2510Sstevel@tonic-gate 
2520Sstevel@tonic-gate static int
diskset_info(mdsetname_t * sp)2530Sstevel@tonic-gate diskset_info(mdsetname_t *sp)
2540Sstevel@tonic-gate {
2550Sstevel@tonic-gate 	md_error_t		error = *mdl_mdnullerror;
2560Sstevel@tonic-gate 	md_replicalist_t	*replica_list = NULL;
2570Sstevel@tonic-gate 	mdnamelist_t		*trans_list = NULL;
2580Sstevel@tonic-gate 	mdnamelist_t		*raid_list = NULL;
2590Sstevel@tonic-gate 	mdnamelist_t		*stripe_list = NULL;
2600Sstevel@tonic-gate 	mdnamelist_t		*sp_list = NULL;
2610Sstevel@tonic-gate 	mdnamelist_t		*spare_list = NULL;
2620Sstevel@tonic-gate 
2630Sstevel@tonic-gate 	if ((mdl_metareplicalist)(sp, MD_BASICNAME_OK, &replica_list, &error)
2640Sstevel@tonic-gate 	    >= 0) {
2650Sstevel@tonic-gate 	    md_replicalist_t	*nlp;
2660Sstevel@tonic-gate 
2670Sstevel@tonic-gate 	    for (nlp = replica_list; nlp != NULL; nlp = nlp->rl_next) {
2680Sstevel@tonic-gate 		if (new_entry(nlp->rl_repp->r_namep->bname, "mdb",
2690Sstevel@tonic-gate 		    nlp->rl_repp->r_namep->cname, sp)) {
2700Sstevel@tonic-gate 		    (mdl_metafreereplicalist)(replica_list);
2710Sstevel@tonic-gate 		    return (ENOMEM);
2720Sstevel@tonic-gate 		}
2730Sstevel@tonic-gate 	    }
2740Sstevel@tonic-gate 	    (mdl_metafreereplicalist)(replica_list);
2750Sstevel@tonic-gate 
2760Sstevel@tonic-gate 	} else {
2770Sstevel@tonic-gate 	    (mdl_mdclrerror)(&error);
2780Sstevel@tonic-gate 	    /* there are no metadb's; that is ok, no need to check the rest */
2790Sstevel@tonic-gate 	    return (0);
2800Sstevel@tonic-gate 	}
2810Sstevel@tonic-gate 	(mdl_mdclrerror)(&error);
2820Sstevel@tonic-gate 
2830Sstevel@tonic-gate 	if ((mdl_meta_get_trans_names)(sp, &trans_list, 0, &error) >= 0) {
2840Sstevel@tonic-gate 	    mdnamelist_t *nlp;
2850Sstevel@tonic-gate 
2860Sstevel@tonic-gate 	    for (nlp = trans_list; nlp != NULL; nlp = nlp->next) {
2870Sstevel@tonic-gate 		if (new_entry(nlp->namep->bname, "trans", nlp->namep->cname,
2880Sstevel@tonic-gate 		    sp)) {
2890Sstevel@tonic-gate 		    free_names(trans_list);
2900Sstevel@tonic-gate 		    return (ENOMEM);
2910Sstevel@tonic-gate 		}
2920Sstevel@tonic-gate 	    }
2930Sstevel@tonic-gate 
2940Sstevel@tonic-gate 	    free_names(trans_list);
2950Sstevel@tonic-gate 	}
2960Sstevel@tonic-gate 	(mdl_mdclrerror)(&error);
2970Sstevel@tonic-gate 
2980Sstevel@tonic-gate 	if ((mdl_meta_get_raid_names)(sp, &raid_list, 0, &error) >= 0) {
2990Sstevel@tonic-gate 	    mdnamelist_t *nlp;
3000Sstevel@tonic-gate 
3010Sstevel@tonic-gate 	    for (nlp = raid_list; nlp != NULL; nlp = nlp->next) {
3020Sstevel@tonic-gate 		mdname_t	*mdn;
3030Sstevel@tonic-gate 		md_raid_t	*raid;
3040Sstevel@tonic-gate 
305*1623Stw21770 		mdn = (mdl_metaname)(&sp, nlp->namep->cname,
306*1623Stw21770 		    META_DEVICE, &error);
3070Sstevel@tonic-gate 		(mdl_mdclrerror)(&error);
3080Sstevel@tonic-gate 		if (mdn == NULL) {
3090Sstevel@tonic-gate 		    continue;
3100Sstevel@tonic-gate 		}
3110Sstevel@tonic-gate 
3120Sstevel@tonic-gate 		raid = (mdl_meta_get_raid)(sp, mdn, &error);
3130Sstevel@tonic-gate 		(mdl_mdclrerror)(&error);
3140Sstevel@tonic-gate 
3150Sstevel@tonic-gate 		if (raid != NULL) {
3160Sstevel@tonic-gate 		    int i;
3170Sstevel@tonic-gate 
3180Sstevel@tonic-gate 		    for (i = 0; i < raid->cols.cols_len; i++) {
3190Sstevel@tonic-gate 			if (new_entry(raid->cols.cols_val[i].colnamep->bname,
3200Sstevel@tonic-gate 			    "raid", nlp->namep->cname, sp)) {
3210Sstevel@tonic-gate 			    free_names(raid_list);
3220Sstevel@tonic-gate 			    return (ENOMEM);
3230Sstevel@tonic-gate 			}
3240Sstevel@tonic-gate 		    }
3250Sstevel@tonic-gate 		}
3260Sstevel@tonic-gate 	    }
3270Sstevel@tonic-gate 
3280Sstevel@tonic-gate 	    free_names(raid_list);
3290Sstevel@tonic-gate 	}
3300Sstevel@tonic-gate 	(mdl_mdclrerror)(&error);
3310Sstevel@tonic-gate 
3320Sstevel@tonic-gate 	if ((mdl_meta_get_stripe_names)(sp, &stripe_list, 0, &error) >= 0) {
3330Sstevel@tonic-gate 	    mdnamelist_t *nlp;
3340Sstevel@tonic-gate 
3350Sstevel@tonic-gate 	    for (nlp = stripe_list; nlp != NULL; nlp = nlp->next) {
3360Sstevel@tonic-gate 		mdname_t	*mdn;
3370Sstevel@tonic-gate 		md_stripe_t	*stripe;
3380Sstevel@tonic-gate 
339*1623Stw21770 		mdn = (mdl_metaname)(&sp, nlp->namep->cname,
340*1623Stw21770 		    META_DEVICE, &error);
3410Sstevel@tonic-gate 		(mdl_mdclrerror)(&error);
3420Sstevel@tonic-gate 		if (mdn == NULL) {
3430Sstevel@tonic-gate 		    continue;
3440Sstevel@tonic-gate 		}
3450Sstevel@tonic-gate 
3460Sstevel@tonic-gate 		stripe = (mdl_meta_get_stripe)(sp, mdn, &error);
3470Sstevel@tonic-gate 		(mdl_mdclrerror)(&error);
3480Sstevel@tonic-gate 
3490Sstevel@tonic-gate 		if (stripe != NULL) {
3500Sstevel@tonic-gate 		    int i;
3510Sstevel@tonic-gate 
3520Sstevel@tonic-gate 		    for (i = 0; i < stripe->rows.rows_len; i++) {
3530Sstevel@tonic-gate 			md_row_t	*rowp;
3540Sstevel@tonic-gate 			int		j;
3550Sstevel@tonic-gate 
3560Sstevel@tonic-gate 			rowp = &stripe->rows.rows_val[i];
3570Sstevel@tonic-gate 
3580Sstevel@tonic-gate 			for (j = 0; j < rowp->comps.comps_len; j++) {
3590Sstevel@tonic-gate 			    md_comp_t	*component;
3600Sstevel@tonic-gate 
3610Sstevel@tonic-gate 			    component = &rowp->comps.comps_val[j];
3620Sstevel@tonic-gate 			    if (new_entry(component->compnamep->bname, "stripe",
3630Sstevel@tonic-gate 				nlp->namep->cname, sp)) {
3640Sstevel@tonic-gate 				free_names(stripe_list);
3650Sstevel@tonic-gate 				return (ENOMEM);
3660Sstevel@tonic-gate 			    }
3670Sstevel@tonic-gate 			}
3680Sstevel@tonic-gate 		    }
3690Sstevel@tonic-gate 		}
3700Sstevel@tonic-gate 	    }
3710Sstevel@tonic-gate 
3720Sstevel@tonic-gate 	    free_names(stripe_list);
3730Sstevel@tonic-gate 	}
3740Sstevel@tonic-gate 	(mdl_mdclrerror)(&error);
3750Sstevel@tonic-gate 
3760Sstevel@tonic-gate 	if ((mdl_meta_get_sp_names)(sp, &sp_list, 0, &error) >= 0) {
3770Sstevel@tonic-gate 	    mdnamelist_t *nlp;
3780Sstevel@tonic-gate 
3790Sstevel@tonic-gate 	    for (nlp = sp_list; nlp != NULL; nlp = nlp->next) {
3800Sstevel@tonic-gate 		mdname_t	*mdn;
3810Sstevel@tonic-gate 		md_sp_t		*soft_part;
3820Sstevel@tonic-gate 
383*1623Stw21770 		mdn = (mdl_metaname)(&sp, nlp->namep->cname,
384*1623Stw21770 		    META_DEVICE, &error);
3850Sstevel@tonic-gate 		(mdl_mdclrerror)(&error);
3860Sstevel@tonic-gate 		if (mdn == NULL) {
3870Sstevel@tonic-gate 		    continue;
3880Sstevel@tonic-gate 		}
3890Sstevel@tonic-gate 
3900Sstevel@tonic-gate 		soft_part = (mdl_meta_get_sp)(sp, mdn, &error);
3910Sstevel@tonic-gate 		(mdl_mdclrerror)(&error);
3920Sstevel@tonic-gate 
3930Sstevel@tonic-gate 		if (soft_part != NULL) {
3940Sstevel@tonic-gate 		    if (new_entry(soft_part->compnamep->bname, "sp",
3950Sstevel@tonic-gate 			nlp->namep->cname, sp)) {
3960Sstevel@tonic-gate 			free_names(sp_list);
3970Sstevel@tonic-gate 			return (ENOMEM);
3980Sstevel@tonic-gate 		    }
3990Sstevel@tonic-gate 		}
4000Sstevel@tonic-gate 	    }
4010Sstevel@tonic-gate 
4020Sstevel@tonic-gate 	    free_names(sp_list);
4030Sstevel@tonic-gate 	}
4040Sstevel@tonic-gate 	(mdl_mdclrerror)(&error);
4050Sstevel@tonic-gate 
4060Sstevel@tonic-gate 	if ((mdl_meta_get_hotspare_names)(sp, &spare_list, 0, &error) >= 0) {
4070Sstevel@tonic-gate 	    mdnamelist_t *nlp;
4080Sstevel@tonic-gate 
4090Sstevel@tonic-gate 	    for (nlp = spare_list; nlp != NULL; nlp = nlp->next) {
4100Sstevel@tonic-gate 		if (new_entry(nlp->namep->bname, "hs", nlp->namep->cname, sp)) {
4110Sstevel@tonic-gate 		    free_names(spare_list);
4120Sstevel@tonic-gate 		    return (ENOMEM);
4130Sstevel@tonic-gate 		}
4140Sstevel@tonic-gate 	    }
4150Sstevel@tonic-gate 
4160Sstevel@tonic-gate 	    free_names(spare_list);
4170Sstevel@tonic-gate 	}
4180Sstevel@tonic-gate 
4190Sstevel@tonic-gate 	(mdl_mdclrerror)(&error);
4200Sstevel@tonic-gate 
4210Sstevel@tonic-gate 	return (0);
4220Sstevel@tonic-gate }
4230Sstevel@tonic-gate 
4240Sstevel@tonic-gate /*
4250Sstevel@tonic-gate  * SVM uses "drive names" (ctd name without trailing slice) for drives
4260Sstevel@tonic-gate  * in disksets.  Since it massages these names there is no direct correspondence
4270Sstevel@tonic-gate  * with the slice device names in /dev.  So, we need to massage these names
4280Sstevel@tonic-gate  * back to something we can match on when a slice comes in.  We create an
4290Sstevel@tonic-gate  * entry for each possible slice since we don't know what slices actually
4300Sstevel@tonic-gate  * exist.  Slice 0 & 7 are probably enough, but the user could have
4310Sstevel@tonic-gate  * repartitioned the drive after they added it to the diskset and removed the
4320Sstevel@tonic-gate  * mdb.
4330Sstevel@tonic-gate  */
4340Sstevel@tonic-gate static int
drive_in_diskset(char * dpath,char * setname)4350Sstevel@tonic-gate drive_in_diskset(char *dpath, char *setname)
4360Sstevel@tonic-gate {
4370Sstevel@tonic-gate 	int i;
4380Sstevel@tonic-gate 	char path[MAXPATHLEN];
4390Sstevel@tonic-gate 
4400Sstevel@tonic-gate 	(void) strlcpy(path, dpath, sizeof (path));
4410Sstevel@tonic-gate 	if (strncmp(path, "/dev/rdsk/", 10) == 0) {
4420Sstevel@tonic-gate 	    /* change rdsk to dsk */
4430Sstevel@tonic-gate 	    char *p;
4440Sstevel@tonic-gate 
4450Sstevel@tonic-gate 	    /* start p pointing to r in rdsk */
4460Sstevel@tonic-gate 	    for (p = path + 5; *p; p++) {
4470Sstevel@tonic-gate 		*p = *(p + 1);
4480Sstevel@tonic-gate 	    }
4490Sstevel@tonic-gate 	} else if (strncmp(path, "/dev/did/rdsk/", 14) == 0) {
4500Sstevel@tonic-gate 	    /* change rdsk to dsk */
4510Sstevel@tonic-gate 	    char *p;
4520Sstevel@tonic-gate 
4530Sstevel@tonic-gate 	    /* start p pointing to r in rdsk */
4540Sstevel@tonic-gate 	    for (p = path + 9; *p; p++) {
4550Sstevel@tonic-gate 		*p = *(p + 1);
4560Sstevel@tonic-gate 	    }
4570Sstevel@tonic-gate 	}
4580Sstevel@tonic-gate 
4590Sstevel@tonic-gate 	for (i = 0; i < 8; i++) {
4600Sstevel@tonic-gate 	    char slice[MAXPATHLEN];
4610Sstevel@tonic-gate 
4620Sstevel@tonic-gate 	    (void) snprintf(slice, sizeof (slice), "%ss%d", path, i);
4630Sstevel@tonic-gate 	    if (add_use_record(slice, "diskset", setname)) {
4640Sstevel@tonic-gate 		return (ENOMEM);
4650Sstevel@tonic-gate 	    }
4660Sstevel@tonic-gate 	}
4670Sstevel@tonic-gate 
4680Sstevel@tonic-gate 	return (0);
4690Sstevel@tonic-gate }
4700Sstevel@tonic-gate 
4710Sstevel@tonic-gate static void
event_handler()4720Sstevel@tonic-gate event_handler()
4730Sstevel@tonic-gate {
4740Sstevel@tonic-gate 	(void) rw_wrlock(&svm_lock);
4750Sstevel@tonic-gate 	free_svm(svm_listp);
4760Sstevel@tonic-gate 	svm_listp = NULL;
4770Sstevel@tonic-gate 	(mdl_metaflushnames)(0);
4780Sstevel@tonic-gate 	(void) load_svm();
4790Sstevel@tonic-gate 	(void) rw_unlock(&svm_lock);
4800Sstevel@tonic-gate }
4810Sstevel@tonic-gate 
4820Sstevel@tonic-gate static void
free_names(mdnamelist_t * nlp)4830Sstevel@tonic-gate free_names(mdnamelist_t *nlp)
4840Sstevel@tonic-gate {
4850Sstevel@tonic-gate 	mdnamelist_t *p;
4860Sstevel@tonic-gate 
4870Sstevel@tonic-gate 	for (p = nlp; p != NULL; p = p->next) {
4880Sstevel@tonic-gate 	    (mdl_meta_invalidate_name)(p->namep);
4890Sstevel@tonic-gate 	    p->namep = NULL;
4900Sstevel@tonic-gate 	}
4910Sstevel@tonic-gate 	(mdl_metafreenamelist)(nlp);
4920Sstevel@tonic-gate }
4930Sstevel@tonic-gate 
4940Sstevel@tonic-gate /*
4950Sstevel@tonic-gate  * Free the list of SVM entries.
4960Sstevel@tonic-gate  */
4970Sstevel@tonic-gate static void
free_svm(struct svm_list * listp)4980Sstevel@tonic-gate free_svm(struct svm_list *listp) {
4990Sstevel@tonic-gate 
5000Sstevel@tonic-gate 	struct svm_list	*nextp;
5010Sstevel@tonic-gate 
5020Sstevel@tonic-gate 	while (listp != NULL) {
5030Sstevel@tonic-gate 	    nextp = listp->next;
5040Sstevel@tonic-gate 	    free((void *)listp->slice);
5050Sstevel@tonic-gate 	    free((void *)listp->name);
5060Sstevel@tonic-gate 	    free((void *)listp->type);
5070Sstevel@tonic-gate 	    free((void *)listp);
5080Sstevel@tonic-gate 	    listp = nextp;
5090Sstevel@tonic-gate 	}
5100Sstevel@tonic-gate }
5110Sstevel@tonic-gate 
5120Sstevel@tonic-gate /*
5130Sstevel@tonic-gate  * Try to dynamically link the libmeta functions we need.
5140Sstevel@tonic-gate  */
5150Sstevel@tonic-gate static int
init_svm()5160Sstevel@tonic-gate init_svm()
5170Sstevel@tonic-gate {
5180Sstevel@tonic-gate 	void	*lh;
5190Sstevel@tonic-gate 
5200Sstevel@tonic-gate 	if ((lh = dlopen("/usr/lib/libmeta.so", RTLD_NOW)) == NULL) {
5210Sstevel@tonic-gate 	    return (0);
5220Sstevel@tonic-gate 	}
5230Sstevel@tonic-gate 
5240Sstevel@tonic-gate 	mdl_get_max_sets = (set_t (*)(md_error_t *))dlsym(lh, "get_max_sets");
5250Sstevel@tonic-gate 
5260Sstevel@tonic-gate 	mdl_mdclrerror = (void(*)(md_error_t *))dlsym(lh, "mdclrerror");
5270Sstevel@tonic-gate 
5280Sstevel@tonic-gate 	mdl_mdnullerror = (md_error_t *)dlsym(lh, "mdnullerror");
5290Sstevel@tonic-gate 
5300Sstevel@tonic-gate 	mdl_metaflushnames = (void (*)(int))dlsym(lh, "metaflushnames");
5310Sstevel@tonic-gate 
5320Sstevel@tonic-gate 	mdl_metaflushsetname = (void (*)(mdsetname_t *))dlsym(lh,
5330Sstevel@tonic-gate 	    "metaflushsetname");
5340Sstevel@tonic-gate 
5350Sstevel@tonic-gate 	mdl_metafreenamelist = (void (*)(mdnamelist_t *))dlsym(lh,
5360Sstevel@tonic-gate 	    "metafreenamelist");
5370Sstevel@tonic-gate 
5380Sstevel@tonic-gate 	mdl_metafreereplicalist = (void (*)(md_replicalist_t *))dlsym(lh,
5390Sstevel@tonic-gate 	    "metafreereplicalist");
5400Sstevel@tonic-gate 
5410Sstevel@tonic-gate 	mdl_metaget_drivedesc = (md_drive_desc *(*)(mdsetname_t *, int,
5420Sstevel@tonic-gate 	    md_error_t *))dlsym(lh, "metaget_drivedesc");
5430Sstevel@tonic-gate 
544*1623Stw21770 	mdl_metaname = (mdname_t *(*)(mdsetname_t **, char *,
545*1623Stw21770 	    meta_device_type_t, md_error_t *))dlsym(lh, "metaname");
5460Sstevel@tonic-gate 
5470Sstevel@tonic-gate 	mdl_metareplicalist = (int (*)(mdsetname_t *, int, md_replicalist_t **,
5480Sstevel@tonic-gate 	    md_error_t *))dlsym(lh, "metareplicalist");
5490Sstevel@tonic-gate 
5500Sstevel@tonic-gate 	mdl_metasetnosetname = (mdsetname_t *(*)(set_t, md_error_t *))dlsym(lh,
5510Sstevel@tonic-gate 	    "metasetnosetname");
5520Sstevel@tonic-gate 
5530Sstevel@tonic-gate 	mdl_meta_get_hotspare_names = (int (*)(mdsetname_t *, mdnamelist_t **,
5540Sstevel@tonic-gate 	    int, md_error_t *))dlsym(lh, "meta_get_hotspare_names");
5550Sstevel@tonic-gate 
5560Sstevel@tonic-gate 	mdl_meta_get_raid = (md_raid_t *(*)(mdsetname_t *, mdname_t *,
5570Sstevel@tonic-gate 	    md_error_t *))dlsym(lh, "meta_get_raid");
5580Sstevel@tonic-gate 
5590Sstevel@tonic-gate 	mdl_meta_get_raid_names = (int (*)(mdsetname_t *, mdnamelist_t **,
5600Sstevel@tonic-gate 	    int, md_error_t *))dlsym(lh, "meta_get_raid_names");
5610Sstevel@tonic-gate 
5620Sstevel@tonic-gate 	mdl_meta_get_sp = (md_sp_t *(*)(mdsetname_t *, mdname_t *,
5630Sstevel@tonic-gate 	    md_error_t *))dlsym(lh, "meta_get_sp");
5640Sstevel@tonic-gate 
5650Sstevel@tonic-gate 	mdl_meta_get_sp_names = (int (*)(mdsetname_t *, mdnamelist_t **,
5660Sstevel@tonic-gate 	    int, md_error_t *))dlsym(lh, "meta_get_sp_names");
5670Sstevel@tonic-gate 
5680Sstevel@tonic-gate 	mdl_meta_get_stripe = (md_stripe_t *(*)(mdsetname_t *, mdname_t *,
5690Sstevel@tonic-gate 	    md_error_t *))dlsym(lh, "meta_get_stripe");
5700Sstevel@tonic-gate 
5710Sstevel@tonic-gate 	mdl_meta_get_stripe_names = (int (*)(mdsetname_t *, mdnamelist_t **,
5720Sstevel@tonic-gate 	    int, md_error_t *))dlsym(lh, "meta_get_stripe_names");
5730Sstevel@tonic-gate 
5740Sstevel@tonic-gate 	mdl_meta_get_trans_names = (int (*)(mdsetname_t *, mdnamelist_t **,
5750Sstevel@tonic-gate 	    int, md_error_t *))dlsym(lh, "meta_get_trans_names");
5760Sstevel@tonic-gate 
5770Sstevel@tonic-gate 	mdl_meta_invalidate_name = (void (*)(mdname_t *))dlsym(lh,
5780Sstevel@tonic-gate 	    "meta_invalidate_name");
5790Sstevel@tonic-gate 
5800Sstevel@tonic-gate 	mdl_sdssc_bind_library = (void (*)())dlsym(lh, "sdssc_bind_library");
5810Sstevel@tonic-gate 
5820Sstevel@tonic-gate 	return (1);
5830Sstevel@tonic-gate }
5840Sstevel@tonic-gate 
5850Sstevel@tonic-gate /*
5860Sstevel@tonic-gate  * Create a list of SVM devices
5870Sstevel@tonic-gate  */
5880Sstevel@tonic-gate static int
load_svm()5890Sstevel@tonic-gate load_svm()
5900Sstevel@tonic-gate {
5910Sstevel@tonic-gate 	int		max_sets;
5920Sstevel@tonic-gate 	md_error_t	error = *mdl_mdnullerror;
5930Sstevel@tonic-gate 	int		i;
5940Sstevel@tonic-gate 
5950Sstevel@tonic-gate 	if ((max_sets = (mdl_get_max_sets)(&error)) == 0) {
5960Sstevel@tonic-gate 	    return (0);
5970Sstevel@tonic-gate 	}
5980Sstevel@tonic-gate 
5990Sstevel@tonic-gate 	if (!mdisok(&error)) {
6000Sstevel@tonic-gate 	    (mdl_mdclrerror)(&error);
6010Sstevel@tonic-gate 	    return (0);
6020Sstevel@tonic-gate 	}
6030Sstevel@tonic-gate 
6040Sstevel@tonic-gate 	/* for each possible set number, see if we really have a diskset */
6050Sstevel@tonic-gate 	for (i = 0; i < max_sets; i++) {
6060Sstevel@tonic-gate 	    mdsetname_t	*sp;
6070Sstevel@tonic-gate 
6080Sstevel@tonic-gate 	    if ((sp = (mdl_metasetnosetname)(i, &error)) == NULL) {
6090Sstevel@tonic-gate 
6100Sstevel@tonic-gate 		if (!mdisok(&error) &&
6110Sstevel@tonic-gate 		    mdisrpcerror(&error, RPC_PROGNOTREGISTERED)) {
6120Sstevel@tonic-gate 		    /* metad rpc program not registered - no metasets */
6130Sstevel@tonic-gate 		    break;
6140Sstevel@tonic-gate 		}
6150Sstevel@tonic-gate 
6160Sstevel@tonic-gate 		(mdl_mdclrerror)(&error);
6170Sstevel@tonic-gate 		continue;
6180Sstevel@tonic-gate 	    }
6190Sstevel@tonic-gate 	    (mdl_mdclrerror)(&error);
6200Sstevel@tonic-gate 
6210Sstevel@tonic-gate 	    /* pick up drives in disksets with no mdbs/metadevices */
6220Sstevel@tonic-gate 	    if (sp->setno != 0) {
6230Sstevel@tonic-gate 		md_drive_desc	*dd;
6240Sstevel@tonic-gate 
6250Sstevel@tonic-gate 		dd = (mdl_metaget_drivedesc)(sp, MD_BASICNAME_OK | PRINT_FAST,
6260Sstevel@tonic-gate 		    &error);
6270Sstevel@tonic-gate 		(mdl_mdclrerror)(&error);
6280Sstevel@tonic-gate 		for (; dd != NULL; dd = dd->dd_next) {
6290Sstevel@tonic-gate 		    if (drive_in_diskset(dd->dd_dnp->rname, sp->setname)) {
6300Sstevel@tonic-gate 			(mdl_metaflushsetname)(sp);
6310Sstevel@tonic-gate 			return (ENOMEM);
6320Sstevel@tonic-gate 		    }
6330Sstevel@tonic-gate 		}
6340Sstevel@tonic-gate 	    }
6350Sstevel@tonic-gate 
6360Sstevel@tonic-gate 	    if (diskset_info(sp)) {
6370Sstevel@tonic-gate 		(mdl_metaflushsetname)(sp);
6380Sstevel@tonic-gate 		return (ENOMEM);
6390Sstevel@tonic-gate 	    }
6400Sstevel@tonic-gate 
6410Sstevel@tonic-gate 	    (mdl_metaflushsetname)(sp);
6420Sstevel@tonic-gate 	}
6430Sstevel@tonic-gate 
6440Sstevel@tonic-gate 	(mdl_mdclrerror)(&error);
6450Sstevel@tonic-gate 
6460Sstevel@tonic-gate 	return (0);
6470Sstevel@tonic-gate }
6480Sstevel@tonic-gate 
6490Sstevel@tonic-gate static int
new_entry(char * sname,char * type,char * mname,mdsetname_t * sp)6500Sstevel@tonic-gate new_entry(char *sname, char *type, char *mname, mdsetname_t *sp)
6510Sstevel@tonic-gate {
6520Sstevel@tonic-gate 	mdname_t	*mdn;
6530Sstevel@tonic-gate 	md_error_t	 error = *mdl_mdnullerror;
6540Sstevel@tonic-gate 
655*1623Stw21770 	mdn = (mdl_metaname)(&sp, sname, UNKNOWN, &error);
6560Sstevel@tonic-gate 	if (!mdisok(&error)) {
6570Sstevel@tonic-gate 	    (mdl_mdclrerror)(&error);
6580Sstevel@tonic-gate 	    return (0);
6590Sstevel@tonic-gate 	}
6600Sstevel@tonic-gate 
6610Sstevel@tonic-gate 	if (mdn != NULL && (
6620Sstevel@tonic-gate 	    mdn->drivenamep->type == MDT_ACCES ||
6630Sstevel@tonic-gate 	    mdn->drivenamep->type == MDT_COMP ||
6640Sstevel@tonic-gate 	    mdn->drivenamep->type == MDT_FAST_COMP)) {
6650Sstevel@tonic-gate 
6660Sstevel@tonic-gate 	    return (add_use_record(mdn->bname, type, mname));
6670Sstevel@tonic-gate 	}
6680Sstevel@tonic-gate 
6690Sstevel@tonic-gate 	return (0);
6700Sstevel@tonic-gate }
671