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 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 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 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 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 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 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 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 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 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 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