xref: /onnv-gate/usr/src/lib/lvm/libmeta/common/meta_metad_subr.c (revision 3165:63d5bf0b6167)
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
51094Sjkennedy  * Common Development and Distribution License (the "License").
61094Sjkennedy  * 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 /*
222063Shshaw  * 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  * Just in case we're not in a build environment, make sure that
300Sstevel@tonic-gate  * TEXT_DOMAIN gets set to something.
310Sstevel@tonic-gate  */
320Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
330Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"
340Sstevel@tonic-gate #endif
350Sstevel@tonic-gate 
360Sstevel@tonic-gate /*
370Sstevel@tonic-gate  * interface between user land and the set records
380Sstevel@tonic-gate  */
390Sstevel@tonic-gate 
400Sstevel@tonic-gate #include <meta.h>
410Sstevel@tonic-gate #include <metad.h>
420Sstevel@tonic-gate #include <sdssc.h>
430Sstevel@tonic-gate #include <syslog.h>
440Sstevel@tonic-gate #include <sys/cladm.h>
450Sstevel@tonic-gate #include "meta_set_prv.h"
460Sstevel@tonic-gate 
470Sstevel@tonic-gate #include <sys/sysevent/eventdefs.h>
480Sstevel@tonic-gate #include <sys/sysevent/svm.h>
490Sstevel@tonic-gate 
500Sstevel@tonic-gate static	md_set_record	*setrecords = NULL; /* head of cache linked list */
510Sstevel@tonic-gate static	int		setsnarfdone = 0;
520Sstevel@tonic-gate 
530Sstevel@tonic-gate typedef struct key_lst_t {
540Sstevel@tonic-gate 	side_t			kl_side;
550Sstevel@tonic-gate 	mdkey_t			kl_key;
560Sstevel@tonic-gate 	struct key_lst_t	*kl_next;
570Sstevel@tonic-gate } key_lst_t;
580Sstevel@tonic-gate 
590Sstevel@tonic-gate typedef struct ur_recid_lst {
600Sstevel@tonic-gate 	mddb_recid_t		url_recid;
610Sstevel@tonic-gate 	struct	ur_recid_lst	*url_nx;
620Sstevel@tonic-gate } ur_recid_lst_t;
630Sstevel@tonic-gate 
640Sstevel@tonic-gate static ur_recid_lst_t		*url_used = NULL;
650Sstevel@tonic-gate static ur_recid_lst_t		*url_tode = NULL;
660Sstevel@tonic-gate 
670Sstevel@tonic-gate static void
url_addl(ur_recid_lst_t ** urlpp,mddb_recid_t recid)680Sstevel@tonic-gate url_addl(ur_recid_lst_t **urlpp, mddb_recid_t recid)
690Sstevel@tonic-gate {
700Sstevel@tonic-gate 	/* Run to the end of the list */
710Sstevel@tonic-gate 	for (/* void */; (*urlpp != NULL); urlpp = &(*urlpp)->url_nx)
720Sstevel@tonic-gate 		if ((*urlpp)->url_recid == recid)
730Sstevel@tonic-gate 			return;
740Sstevel@tonic-gate 
750Sstevel@tonic-gate 	/* Add the new member */
760Sstevel@tonic-gate 	*urlpp = Zalloc(sizeof (**urlpp));
770Sstevel@tonic-gate 	if (*urlpp == NULL)
780Sstevel@tonic-gate 		return;
790Sstevel@tonic-gate 
800Sstevel@tonic-gate 	(*urlpp)->url_recid = recid;
810Sstevel@tonic-gate }
820Sstevel@tonic-gate 
830Sstevel@tonic-gate static int
url_findl(ur_recid_lst_t * urlp,mddb_recid_t recid)840Sstevel@tonic-gate url_findl(ur_recid_lst_t *urlp, mddb_recid_t recid)
850Sstevel@tonic-gate {
860Sstevel@tonic-gate 	while (urlp != NULL) {
870Sstevel@tonic-gate 		if (urlp->url_recid == recid)
880Sstevel@tonic-gate 			return (1);
890Sstevel@tonic-gate 		urlp = urlp->url_nx;
900Sstevel@tonic-gate 	}
910Sstevel@tonic-gate 	return (0);
920Sstevel@tonic-gate }
930Sstevel@tonic-gate 
940Sstevel@tonic-gate static void
url_freel(ur_recid_lst_t ** urlpp)950Sstevel@tonic-gate url_freel(ur_recid_lst_t **urlpp)
960Sstevel@tonic-gate {
970Sstevel@tonic-gate 	ur_recid_lst_t	*urlp;
980Sstevel@tonic-gate 	ur_recid_lst_t	*turlp;
990Sstevel@tonic-gate 
1000Sstevel@tonic-gate 	for (turlp = *urlpp; turlp != NULL; turlp = urlp) {
1010Sstevel@tonic-gate 		urlp = turlp->url_nx;
1020Sstevel@tonic-gate 		Free(turlp);
1030Sstevel@tonic-gate 	}
1040Sstevel@tonic-gate 	*urlpp = (ur_recid_lst_t *)NULL;
1050Sstevel@tonic-gate }
1060Sstevel@tonic-gate 
1070Sstevel@tonic-gate static int
ckncvt_set_record(mddb_userreq_t * reqp,md_error_t * ep)1080Sstevel@tonic-gate ckncvt_set_record(mddb_userreq_t *reqp, md_error_t *ep)
1090Sstevel@tonic-gate {
1100Sstevel@tonic-gate 	mddb_userreq_t	req;
1110Sstevel@tonic-gate 	md_set_record	*sr;
1120Sstevel@tonic-gate 	int		recs[3];
1130Sstevel@tonic-gate 
1140Sstevel@tonic-gate 	if (reqp->ur_size == sizeof (*sr))
1150Sstevel@tonic-gate 		return (0);
1160Sstevel@tonic-gate 
1170Sstevel@tonic-gate 	if (! md_in_daemon) {
1180Sstevel@tonic-gate 		if (reqp->ur_size >= sizeof (*sr))
1190Sstevel@tonic-gate 			return (0);
1200Sstevel@tonic-gate 
12162Sjeanm 		reqp->ur_data = (uintptr_t)Realloc((void *)(uintptr_t)
12262Sjeanm 		    reqp->ur_data, sizeof (*sr));
12362Sjeanm 		(void) memset(
12462Sjeanm 		    ((char *)(uintptr_t)reqp->ur_data) + reqp->ur_size,
12562Sjeanm 		    '\0', sizeof (*sr) - reqp->ur_size);
1260Sstevel@tonic-gate 		reqp->ur_size = sizeof (*sr);
1270Sstevel@tonic-gate 		return (0);
1280Sstevel@tonic-gate 	}
1290Sstevel@tonic-gate 
1300Sstevel@tonic-gate 	/*
1310Sstevel@tonic-gate 	 * If here, then the daemon is calling, and so the automatic
1320Sstevel@tonic-gate 	 * conversion will be performed.
1330Sstevel@tonic-gate 	 */
1340Sstevel@tonic-gate 
1350Sstevel@tonic-gate 	/* shorthand */
1360Sstevel@tonic-gate 	req = *reqp;			/* structure assignment */
13762Sjeanm 	sr = (md_set_record *)(uintptr_t)req.ur_data;
1380Sstevel@tonic-gate 
1390Sstevel@tonic-gate 	if (sr->sr_flags & MD_SR_CVT)
1400Sstevel@tonic-gate 		return (0);
1410Sstevel@tonic-gate 
1420Sstevel@tonic-gate 	/* Leave multi-node set records alone */
1430Sstevel@tonic-gate 	if (MD_MNSET_REC(sr)) {
1440Sstevel@tonic-gate 		return (0);
1450Sstevel@tonic-gate 	}
1460Sstevel@tonic-gate 
1470Sstevel@tonic-gate 	/* Mark the old record as converted */
1480Sstevel@tonic-gate 	sr->sr_flags |= MD_SR_CVT;
1490Sstevel@tonic-gate 
1500Sstevel@tonic-gate 	METAD_SETUP_SR(MD_DB_SETDATA, sr->sr_selfid)
1510Sstevel@tonic-gate 
1520Sstevel@tonic-gate 	if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL) != 0)
1530Sstevel@tonic-gate 		return (mdstealerror(ep, &req.ur_mde));
1540Sstevel@tonic-gate 
1550Sstevel@tonic-gate 	/* Create space for the new record */
1560Sstevel@tonic-gate 	METAD_SETUP_SR(MD_DB_CREATE, 0);
1570Sstevel@tonic-gate 	req.ur_size = sizeof (*sr);
1580Sstevel@tonic-gate 
1590Sstevel@tonic-gate 	if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL) != 0)
1600Sstevel@tonic-gate 		return (mdstealerror(ep, &req.ur_mde));
1610Sstevel@tonic-gate 
1620Sstevel@tonic-gate 	/* Allocate the new record */
1630Sstevel@tonic-gate 	sr = Zalloc(sizeof (*sr));
1640Sstevel@tonic-gate 
1650Sstevel@tonic-gate 	/* copy all the data from the record being converted */
16662Sjeanm 	(void) memmove(sr, (void *)(uintptr_t)reqp->ur_data, reqp->ur_size);
1670Sstevel@tonic-gate 	sr->sr_flags &= ~MD_SR_CVT;
1680Sstevel@tonic-gate 
1690Sstevel@tonic-gate 	/* adjust the selfid to point to the new record */
1700Sstevel@tonic-gate 	sr->sr_selfid = req.ur_recid;
1710Sstevel@tonic-gate 
1720Sstevel@tonic-gate 	METAD_SETUP_SR(MD_DB_SETDATA, sr->sr_selfid)
1730Sstevel@tonic-gate 	req.ur_size = sizeof (*sr);
1740Sstevel@tonic-gate 	req.ur_data = (uintptr_t)sr;
1750Sstevel@tonic-gate 
1760Sstevel@tonic-gate 	if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL) != 0) {
1770Sstevel@tonic-gate 		Free(sr);
1780Sstevel@tonic-gate 		return (mdstealerror(ep, &req.ur_mde));
1790Sstevel@tonic-gate 	}
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate 	/* Commit the old and the new */
18262Sjeanm 	recs[0] = ((md_set_record *)(uintptr_t)reqp->ur_data)->sr_selfid;
1830Sstevel@tonic-gate 	recs[1] = sr->sr_selfid;
1840Sstevel@tonic-gate 	recs[2] = 0;
1850Sstevel@tonic-gate 
1860Sstevel@tonic-gate 	METAD_SETUP_UR(MD_DB_COMMIT_MANY, 0, 0);
1870Sstevel@tonic-gate 	req.ur_size = sizeof (recs);
1880Sstevel@tonic-gate 	req.ur_data = (uintptr_t)recs;
1890Sstevel@tonic-gate 
1900Sstevel@tonic-gate 	if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL) != 0) {
1910Sstevel@tonic-gate 		Free(sr);
1920Sstevel@tonic-gate 		return (mdstealerror(ep, &req.ur_mde));
1930Sstevel@tonic-gate 	}
1940Sstevel@tonic-gate 
1950Sstevel@tonic-gate 	/* Add the the old record to the list of records to delete */
19662Sjeanm 	url_addl(&url_tode,
19762Sjeanm 	    ((md_set_record *)(uintptr_t)reqp->ur_data)->sr_selfid);
1980Sstevel@tonic-gate 
1990Sstevel@tonic-gate 	/* Free the old records space */
20062Sjeanm 	Free((void *)(uintptr_t)reqp->ur_data);
2010Sstevel@tonic-gate 
2020Sstevel@tonic-gate 	/* Adjust the reqp structure to point to the new record and size */
2030Sstevel@tonic-gate 	reqp->ur_recid = sr->sr_selfid;
2040Sstevel@tonic-gate 	reqp->ur_size = sizeof (*sr);
2050Sstevel@tonic-gate 	reqp->ur_data = (uintptr_t)sr;
2060Sstevel@tonic-gate 
2070Sstevel@tonic-gate 	return (0);
2080Sstevel@tonic-gate }
2090Sstevel@tonic-gate 
2100Sstevel@tonic-gate mddb_userreq_t *
get_db_rec(md_ur_get_cmd_t cmd,set_t setno,mddb_type_t type,uint_t type2,mddb_recid_t * idp,md_error_t * ep)2110Sstevel@tonic-gate get_db_rec(
2120Sstevel@tonic-gate 	md_ur_get_cmd_t	cmd,
2130Sstevel@tonic-gate 	set_t		setno,
2140Sstevel@tonic-gate 	mddb_type_t	type,
2150Sstevel@tonic-gate 	uint_t		type2,
2160Sstevel@tonic-gate 	mddb_recid_t	*idp,
2170Sstevel@tonic-gate 	md_error_t	*ep
2180Sstevel@tonic-gate )
2190Sstevel@tonic-gate {
2200Sstevel@tonic-gate 	mddb_userreq_t	*reqp = Zalloc(sizeof (*reqp));
2211094Sjkennedy 	mdsetname_t	*sp;
2221094Sjkennedy 	md_set_desc	*sd;
2231094Sjkennedy 	int		ureq;
2241094Sjkennedy 
2251094Sjkennedy 	if ((sp = metasetnosetname(setno, ep)) == NULL) {
2261094Sjkennedy 		Free(reqp);
2271094Sjkennedy 		return (NULL);
2281094Sjkennedy 	}
2291094Sjkennedy 
2301094Sjkennedy 	if (metaislocalset(sp)) {
2311094Sjkennedy 		ureq = MD_DB_USERREQ;
2321094Sjkennedy 	} else {
2331094Sjkennedy 		if ((sd = metaget_setdesc(sp, ep)) == NULL) {
2341094Sjkennedy 			Free(reqp);
2351094Sjkennedy 			return (NULL);
2361094Sjkennedy 		}
2371094Sjkennedy 		ureq = MD_MNSET_DESC(sd) ? MD_MN_DB_USERREQ : MD_DB_USERREQ;
2381094Sjkennedy 	}
2390Sstevel@tonic-gate 
2400Sstevel@tonic-gate 	reqp->ur_setno = setno;
2410Sstevel@tonic-gate 	reqp->ur_type = type;
2420Sstevel@tonic-gate 	reqp->ur_type2 = type2;
2430Sstevel@tonic-gate 
2440Sstevel@tonic-gate 	switch (cmd) {
2450Sstevel@tonic-gate 	    case MD_UR_GET_NEXT:
2460Sstevel@tonic-gate 		    reqp->ur_cmd = MD_DB_GETNEXTREC;
2470Sstevel@tonic-gate 		    reqp->ur_recid = *idp;
2481094Sjkennedy 		    if (metaioctl(ureq, reqp, &reqp->ur_mde, NULL)
2490Sstevel@tonic-gate 			!= 0) {
2500Sstevel@tonic-gate 			    (void) mdstealerror(ep, &reqp->ur_mde);
2510Sstevel@tonic-gate 			    Free(reqp);
2520Sstevel@tonic-gate 			    return (NULL);
2530Sstevel@tonic-gate 		    }
2540Sstevel@tonic-gate 		    *idp = reqp->ur_recid;
2550Sstevel@tonic-gate 		    break;
2560Sstevel@tonic-gate 	    case MD_UR_GET_WKEY:
2570Sstevel@tonic-gate 		    reqp->ur_recid = *idp;
2580Sstevel@tonic-gate 		    break;
2590Sstevel@tonic-gate 	}
2600Sstevel@tonic-gate 
2610Sstevel@tonic-gate 	if (*idp <= 0) {
2620Sstevel@tonic-gate 		Free(reqp);
2630Sstevel@tonic-gate 		return (NULL);
2640Sstevel@tonic-gate 	}
2650Sstevel@tonic-gate 
2660Sstevel@tonic-gate 	reqp->ur_cmd = MD_DB_GETSIZE;
2671094Sjkennedy 	if (metaioctl(ureq, reqp, &reqp->ur_mde, NULL) != 0) {
2680Sstevel@tonic-gate 		(void) mdstealerror(ep, &reqp->ur_mde);
2690Sstevel@tonic-gate 		Free(reqp);
2700Sstevel@tonic-gate 
2710Sstevel@tonic-gate 		*idp = 0;
2720Sstevel@tonic-gate 		return (NULL);
2730Sstevel@tonic-gate 	}
2740Sstevel@tonic-gate 
2750Sstevel@tonic-gate 	reqp->ur_cmd = MD_DB_GETDATA;
2760Sstevel@tonic-gate 	reqp->ur_data = (uintptr_t)Zalloc(reqp->ur_size);
2771094Sjkennedy 	if (metaioctl(ureq, reqp, &reqp->ur_mde, NULL) != 0) {
2780Sstevel@tonic-gate 		(void) mdstealerror(ep, &reqp->ur_mde);
27962Sjeanm 		Free((void *)(uintptr_t)reqp->ur_data);
2800Sstevel@tonic-gate 		Free(reqp);
2810Sstevel@tonic-gate 		*idp = 0;
2820Sstevel@tonic-gate 		return (NULL);
2830Sstevel@tonic-gate 	}
2840Sstevel@tonic-gate 
2850Sstevel@tonic-gate 	switch (reqp->ur_type) {
2860Sstevel@tonic-gate 	    case MDDB_USER:
2870Sstevel@tonic-gate 		    switch (reqp->ur_type2) {
2880Sstevel@tonic-gate 			case MDDB_UR_SR:
2890Sstevel@tonic-gate 				if (ckncvt_set_record(reqp, ep)) {
29062Sjeanm 					Free((void *)(uintptr_t)reqp->ur_data);
2910Sstevel@tonic-gate 					Free(reqp);
2920Sstevel@tonic-gate 					return (NULL);
2930Sstevel@tonic-gate 				}
2940Sstevel@tonic-gate 				break;
2950Sstevel@tonic-gate 		    }
2960Sstevel@tonic-gate 		    break;
2970Sstevel@tonic-gate 	}
2980Sstevel@tonic-gate 
2990Sstevel@tonic-gate 	return (reqp);
3000Sstevel@tonic-gate }
3010Sstevel@tonic-gate 
3020Sstevel@tonic-gate void *
get_ur_rec(set_t setno,md_ur_get_cmd_t cmd,uint_t type2,mddb_recid_t * idp,md_error_t * ep)3030Sstevel@tonic-gate get_ur_rec(
3040Sstevel@tonic-gate 	set_t		setno,
3050Sstevel@tonic-gate 	md_ur_get_cmd_t	cmd,
3060Sstevel@tonic-gate 	uint_t		type2,
3070Sstevel@tonic-gate 	mddb_recid_t	*idp,
3080Sstevel@tonic-gate 	md_error_t	*ep
3090Sstevel@tonic-gate )
3100Sstevel@tonic-gate {
3110Sstevel@tonic-gate 	mddb_userreq_t	*reqp = NULL;
3120Sstevel@tonic-gate 	void		*ret_val;
3130Sstevel@tonic-gate 
3140Sstevel@tonic-gate 	assert(idp != NULL);
3150Sstevel@tonic-gate 
3160Sstevel@tonic-gate 	reqp = get_db_rec(cmd, setno, MDDB_USER, type2, idp, ep);
3170Sstevel@tonic-gate 	if (reqp == NULL)
3180Sstevel@tonic-gate 		return (NULL);
3190Sstevel@tonic-gate 
32062Sjeanm 	ret_val = (void *)(uintptr_t)reqp->ur_data;
3210Sstevel@tonic-gate 	Free(reqp);
3220Sstevel@tonic-gate 	return (ret_val);
3230Sstevel@tonic-gate }
3240Sstevel@tonic-gate 
3250Sstevel@tonic-gate /*
3260Sstevel@tonic-gate  * Called by rpc.metad on startup of disksets to cleanup
3270Sstevel@tonic-gate  * the host entries associated with a diskset.  This is needed if
3280Sstevel@tonic-gate  * a node failed or the metaset command was killed during the addition
3290Sstevel@tonic-gate  * of a node to a diskset.
3300Sstevel@tonic-gate  *
3310Sstevel@tonic-gate  * This is called for all traditional disksets.
3320Sstevel@tonic-gate  * This is only called for MNdisksets when in there is only one node
3330Sstevel@tonic-gate  * in all of the MN disksets and this node is not running SunCluster.
3340Sstevel@tonic-gate  * (Otherwise, the cleanup of the host entries is handled by a
3350Sstevel@tonic-gate  * reconfig cycle that the SunCluster software calls).
3360Sstevel@tonic-gate  */
3370Sstevel@tonic-gate static int
sr_hosts(md_set_record * sr)3380Sstevel@tonic-gate sr_hosts(md_set_record *sr)
3390Sstevel@tonic-gate {
3400Sstevel@tonic-gate 	int		i,
341*3165Spetede 			nid = 0,
3420Sstevel@tonic-gate 			self_in_set = FALSE;
3430Sstevel@tonic-gate 	md_error_t	xep = mdnullerror;
3440Sstevel@tonic-gate 	md_mnnode_record	*nr;
3450Sstevel@tonic-gate 	md_mnset_record		*mnsr;
3460Sstevel@tonic-gate 
3470Sstevel@tonic-gate 	if (MD_MNSET_REC(sr)) {
3480Sstevel@tonic-gate 		mnsr = (struct md_mnset_record *)sr;
3490Sstevel@tonic-gate 		nr = mnsr->sr_nodechain;
3500Sstevel@tonic-gate 		/*
3510Sstevel@tonic-gate 		 * Already guaranteed to be only 1 node in set which
3520Sstevel@tonic-gate 		 * is mynode (done in sr_validate).
3530Sstevel@tonic-gate 		 * Now, check if node is in the OK state.  If not in
3540Sstevel@tonic-gate 		 * the OK state, leave self_in_set FALSE so that
3550Sstevel@tonic-gate 		 * set will be removed.
3560Sstevel@tonic-gate 		 */
3570Sstevel@tonic-gate 		if (nr->nr_flags & MD_MN_NODE_OK)
3580Sstevel@tonic-gate 			self_in_set = TRUE;
3590Sstevel@tonic-gate 	} else {
3600Sstevel@tonic-gate 		for (i = 0; i < MD_MAXSIDES; i++) {
3610Sstevel@tonic-gate 			/* Skip empty slots */
3620Sstevel@tonic-gate 			if (sr->sr_nodes[i][0] == '\0')
3630Sstevel@tonic-gate 				continue;
3640Sstevel@tonic-gate 
3650Sstevel@tonic-gate 			/* Make sure we are in the set and skip this node */
3660Sstevel@tonic-gate 			if (strcmp(sr->sr_nodes[i], mynode()) == 0) {
3670Sstevel@tonic-gate 				self_in_set = TRUE;
3680Sstevel@tonic-gate 				break;
3690Sstevel@tonic-gate 			}
3700Sstevel@tonic-gate 		}
3710Sstevel@tonic-gate 	}
3720Sstevel@tonic-gate 
3732063Shshaw 	if ((self_in_set == FALSE) && (!(MD_MNSET_REC(sr)))) {
3740Sstevel@tonic-gate 		/*
375*3165Spetede 		 * Under some circumstances (/etc/cluster/nodeid file is
376*3165Spetede 		 * missing) it is possible for the call to _cladm() to
377*3165Spetede 		 * return 0 and a nid of 0. In this instance do not remove
378*3165Spetede 		 * the set as it is Sun Cluster error that needs to be fixed.
3790Sstevel@tonic-gate 		 */
380*3165Spetede 		if (_cladm(CL_CONFIG, CL_NODEID, &nid) == 0 && nid > 0) {
381*3165Spetede 
382*3165Spetede 			/*
383*3165Spetede 			 * See if we've got a node which has been booted in
384*3165Spetede 			 * non-cluster mode. If true the nodeid will match
385*3165Spetede 			 * one of the sr_nodes values because the conversion
386*3165Spetede 			 * from nodeid to hostname failed to occur.
387*3165Spetede 			 */
388*3165Spetede 			for (i = 0; i < MD_MAXSIDES; i++) {
389*3165Spetede 				if (sr->sr_nodes[i][0] == 0)
390*3165Spetede 					continue;
391*3165Spetede 				if (atoi(sr->sr_nodes[i]) == nid)
392*3165Spetede 					self_in_set = TRUE;
393*3165Spetede 			}
3940Sstevel@tonic-gate 
395*3165Spetede 			/* If we aren't in the set, delete the set */
396*3165Spetede 			if (self_in_set == FALSE) {
397*3165Spetede 				syslog(LOG_ERR, dgettext(TEXT_DOMAIN,
398*3165Spetede 				    "Removing set %s from database\n"),
399*3165Spetede 				    sr->sr_setname);
400*3165Spetede 				s_delset(sr->sr_setname, &xep);
401*3165Spetede 				if (! mdisok(&xep))
402*3165Spetede 					mdclrerror(&xep);
403*3165Spetede 				return (1);
404*3165Spetede 			}
405*3165Spetede 		} else {
406*3165Spetede 			/*
407*3165Spetede 			 * Send a message to syslog and return without
408*3165Spetede 			 * deleting any sets
409*3165Spetede 			 */
4102063Shshaw 			syslog(LOG_ERR, dgettext(TEXT_DOMAIN,
411*3165Spetede 			    "Call to _cladm failed for set %s nodeid %d\n"),
412*3165Spetede 			    sr->sr_setname, nid);
4132063Shshaw 			return (1);
4142063Shshaw 		}
4150Sstevel@tonic-gate 	}
4160Sstevel@tonic-gate 	return (0);
4170Sstevel@tonic-gate }
4180Sstevel@tonic-gate 
4190Sstevel@tonic-gate void
sr_del_drv(md_set_record * sr,mddb_recid_t recid)4200Sstevel@tonic-gate sr_del_drv(md_set_record *sr, mddb_recid_t recid)
4210Sstevel@tonic-gate {
4220Sstevel@tonic-gate 	mddb_userreq_t		req;
4230Sstevel@tonic-gate 	md_error_t		xep = mdnullerror;
4240Sstevel@tonic-gate 
4250Sstevel@tonic-gate 	if (!s_ownset(sr->sr_setno, &xep)) {
4260Sstevel@tonic-gate 		if (! mdisok(&xep))
4270Sstevel@tonic-gate 			mdclrerror(&xep);
4280Sstevel@tonic-gate 		goto skip;
4290Sstevel@tonic-gate 	}
4300Sstevel@tonic-gate 
4310Sstevel@tonic-gate 	/* delete the replicas? */
4320Sstevel@tonic-gate 	/* release ownership of the drive? */
4330Sstevel@tonic-gate 	/* NOTE: We may not have a name, so both of the above are ugly! */
4340Sstevel@tonic-gate 
4350Sstevel@tonic-gate skip:
4360Sstevel@tonic-gate 	(void) memset(&req, 0, sizeof (req));
4370Sstevel@tonic-gate 	METAD_SETUP_DR(MD_DB_DELETE, recid)
4380Sstevel@tonic-gate 	if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL) != 0)
4390Sstevel@tonic-gate 		mdclrerror(&req.ur_mde);
4400Sstevel@tonic-gate 
4410Sstevel@tonic-gate 	dr_cache_del(sr, recid);
4420Sstevel@tonic-gate }
4430Sstevel@tonic-gate 
4440Sstevel@tonic-gate static void
sr_drvs(md_set_record * sr)4450Sstevel@tonic-gate sr_drvs(md_set_record *sr)
4460Sstevel@tonic-gate {
4470Sstevel@tonic-gate 	md_drive_record		*dr;
4480Sstevel@tonic-gate 	int			i;
4490Sstevel@tonic-gate 	int			modified = 0;
4500Sstevel@tonic-gate 	int			sidesok;
4510Sstevel@tonic-gate 	mdnm_params_t		nm;
4520Sstevel@tonic-gate 	static	char		device_name[MAXPATHLEN];
4530Sstevel@tonic-gate 	md_error_t		xep = mdnullerror;
4540Sstevel@tonic-gate 	md_mnnode_record	*nr;
4550Sstevel@tonic-gate 	md_mnset_record		*mnsr;
4560Sstevel@tonic-gate 
4570Sstevel@tonic-gate 	for (dr = sr->sr_drivechain; dr != NULL; dr = dr->dr_next) {
4580Sstevel@tonic-gate 		/* If we were mid-add, cleanup */
4590Sstevel@tonic-gate 		if ((dr->dr_flags & MD_DR_ADD)) {
4600Sstevel@tonic-gate 			sr_del_drv(sr, dr->dr_selfid);
4610Sstevel@tonic-gate 			modified++;
4620Sstevel@tonic-gate 			continue;
4630Sstevel@tonic-gate 		}
4640Sstevel@tonic-gate 
4650Sstevel@tonic-gate 		sidesok = TRUE;
4660Sstevel@tonic-gate 		if (MD_MNSET_REC(sr)) {
4670Sstevel@tonic-gate 			mnsr = (md_mnset_record *)sr;
4680Sstevel@tonic-gate 			nr = mnsr->sr_nodechain;
4690Sstevel@tonic-gate 			/*
4700Sstevel@tonic-gate 			 * MultiNode disksets only have entries for
4710Sstevel@tonic-gate 			 * their side in the local set.  Verify
4720Sstevel@tonic-gate 			 * that drive has a name associated with
4730Sstevel@tonic-gate 			 * this node's side.
4740Sstevel@tonic-gate 			 */
4750Sstevel@tonic-gate 			while (nr) {
4760Sstevel@tonic-gate 				/* Find my node */
4770Sstevel@tonic-gate 				if (strcmp(mynode(), nr->nr_nodename) != 0) {
4780Sstevel@tonic-gate 					nr = nr->nr_next;
4790Sstevel@tonic-gate 					continue;
4800Sstevel@tonic-gate 				}
4810Sstevel@tonic-gate 
4820Sstevel@tonic-gate 				(void) memset(&nm, '\0', sizeof (nm));
4830Sstevel@tonic-gate 				nm.setno = MD_LOCAL_SET;
4840Sstevel@tonic-gate 				nm.side = nr->nr_nodeid;
4850Sstevel@tonic-gate 				nm.key = dr->dr_key;
4860Sstevel@tonic-gate 				nm.devname = (uint64_t)device_name;
4870Sstevel@tonic-gate 
4880Sstevel@tonic-gate 				if (metaioctl(MD_IOCGET_NM, &nm, &nm.mde,
4890Sstevel@tonic-gate 				    NULL) != 0) {
4900Sstevel@tonic-gate 					if (! mdissyserror(&nm.mde, ENOENT)) {
4910Sstevel@tonic-gate 						mdclrerror(&nm.mde);
4920Sstevel@tonic-gate 						return;
4930Sstevel@tonic-gate 					}
4940Sstevel@tonic-gate 				}
4950Sstevel@tonic-gate 
4960Sstevel@tonic-gate 				/*
4970Sstevel@tonic-gate 				 * If entry is found for this node, then
4980Sstevel@tonic-gate 				 * break out of loop walking through
4990Sstevel@tonic-gate 				 * node list.  For a multi-node diskset,
5000Sstevel@tonic-gate 				 * there should only be an entry for
5010Sstevel@tonic-gate 				 * this node.
5020Sstevel@tonic-gate 				 */
5030Sstevel@tonic-gate 				if (nm.key != MD_KEYWILD &&
5040Sstevel@tonic-gate 				    ! mdissyserror(&nm.mde, ENOENT)) {
5050Sstevel@tonic-gate 					break;
5060Sstevel@tonic-gate 				}
5070Sstevel@tonic-gate 
5080Sstevel@tonic-gate 				/*
5090Sstevel@tonic-gate 				 * If entry is not found for this node,
5100Sstevel@tonic-gate 				 * then delete the drive.  No need to
5110Sstevel@tonic-gate 				 * continue through the node loop since
5120Sstevel@tonic-gate 				 * our node has already been found.
5130Sstevel@tonic-gate 				 */
5140Sstevel@tonic-gate 				sidesok = FALSE;
5150Sstevel@tonic-gate 				mdclrerror(&nm.mde);
5160Sstevel@tonic-gate 
5170Sstevel@tonic-gate 				/* If we are missing a sidename, cleanup */
5180Sstevel@tonic-gate 				sr_del_drv(sr, dr->dr_selfid);
5190Sstevel@tonic-gate 				modified++;
5200Sstevel@tonic-gate 
5210Sstevel@tonic-gate 				break;
5220Sstevel@tonic-gate 			}
5230Sstevel@tonic-gate 		} else  {
5240Sstevel@tonic-gate 			for (i = 0; i < MD_MAXSIDES; i++) {
5250Sstevel@tonic-gate 				/* Skip empty slots */
5260Sstevel@tonic-gate 				if (sr->sr_nodes[i][0] == '\0')
5270Sstevel@tonic-gate 					continue;
5280Sstevel@tonic-gate 
5290Sstevel@tonic-gate 				(void) memset(&nm, '\0', sizeof (nm));
5300Sstevel@tonic-gate 				nm.setno = MD_LOCAL_SET;
5310Sstevel@tonic-gate 				nm.side = i + SKEW;
5320Sstevel@tonic-gate 				nm.key = dr->dr_key;
5330Sstevel@tonic-gate 				nm.devname = (uint64_t)device_name;
5340Sstevel@tonic-gate 
5350Sstevel@tonic-gate 				if (metaioctl(MD_IOCGET_NM, &nm, &nm.mde,
5360Sstevel@tonic-gate 				    NULL) != 0) {
5370Sstevel@tonic-gate 					if (! mdissyserror(&nm.mde, ENOENT)) {
5380Sstevel@tonic-gate 						mdclrerror(&nm.mde);
5390Sstevel@tonic-gate 						return;
5400Sstevel@tonic-gate 					}
5410Sstevel@tonic-gate 				}
5420Sstevel@tonic-gate 
5430Sstevel@tonic-gate 				if (nm.key != MD_KEYWILD &&
5440Sstevel@tonic-gate 				    ! mdissyserror(&nm.mde, ENOENT))
5450Sstevel@tonic-gate 					continue;
5460Sstevel@tonic-gate 
5470Sstevel@tonic-gate 				sidesok = FALSE;
5480Sstevel@tonic-gate 				mdclrerror(&nm.mde);
5490Sstevel@tonic-gate 
5500Sstevel@tonic-gate 				/* If we are missing a sidename, cleanup */
5510Sstevel@tonic-gate 				sr_del_drv(sr, dr->dr_selfid);
5520Sstevel@tonic-gate 				modified++;
5530Sstevel@tonic-gate 
5540Sstevel@tonic-gate 				break;
5550Sstevel@tonic-gate 			}
5560Sstevel@tonic-gate 		}
5570Sstevel@tonic-gate 
5580Sstevel@tonic-gate 		if (sidesok == FALSE)
5590Sstevel@tonic-gate 			continue;
5600Sstevel@tonic-gate 
5610Sstevel@tonic-gate 		/*
5620Sstevel@tonic-gate 		 * If we got this far, the drive record is either in the OK
5630Sstevel@tonic-gate 		 * or DEL state, if it is in the DEL state and the sidenames
5640Sstevel@tonic-gate 		 * all checked out, then we will make it OK.
5650Sstevel@tonic-gate 		 */
5660Sstevel@tonic-gate 		if ((dr->dr_flags & MD_DR_OK))
5670Sstevel@tonic-gate 			continue;
5680Sstevel@tonic-gate 
5690Sstevel@tonic-gate 		dr->dr_flags = MD_DR_OK;
5700Sstevel@tonic-gate 
5710Sstevel@tonic-gate 		modified++;
5720Sstevel@tonic-gate 	}
5730Sstevel@tonic-gate 
5740Sstevel@tonic-gate 	if (modified) {
5750Sstevel@tonic-gate 		commitset(sr, FALSE, &xep);
5760Sstevel@tonic-gate 		if (! mdisok(&xep))
5770Sstevel@tonic-gate 			mdclrerror(&xep);
5780Sstevel@tonic-gate 	}
5790Sstevel@tonic-gate }
5800Sstevel@tonic-gate 
5810Sstevel@tonic-gate static void
add_key_to_lst(key_lst_t ** klpp,side_t side,mdkey_t key)5820Sstevel@tonic-gate add_key_to_lst(key_lst_t **klpp, side_t side, mdkey_t key)
5830Sstevel@tonic-gate {
5840Sstevel@tonic-gate 	key_lst_t	*klp;
5850Sstevel@tonic-gate 
5860Sstevel@tonic-gate 	assert(klpp != NULL);
5870Sstevel@tonic-gate 
5880Sstevel@tonic-gate 	for (/* void */; *klpp != NULL; klpp = &(*klpp)->kl_next)
5890Sstevel@tonic-gate 		/* void */;
5900Sstevel@tonic-gate 
5910Sstevel@tonic-gate 	/* allocate new list element */
5920Sstevel@tonic-gate 	klp = *klpp = Zalloc(sizeof (*klp));
5930Sstevel@tonic-gate 
5940Sstevel@tonic-gate 	klp->kl_side = side;
5950Sstevel@tonic-gate 	klp->kl_key  = key;
5960Sstevel@tonic-gate }
5970Sstevel@tonic-gate 
5980Sstevel@tonic-gate #ifdef DUMPKEYLST
5990Sstevel@tonic-gate static void
pr_key_lst(char * tag,key_lst_t * klp)6000Sstevel@tonic-gate pr_key_lst(char *tag, key_lst_t *klp)
6010Sstevel@tonic-gate {
6020Sstevel@tonic-gate 	key_lst_t	*tklp;
6030Sstevel@tonic-gate 
6040Sstevel@tonic-gate 	md_eprintf("Tag=%s\n", tag);
6050Sstevel@tonic-gate 	for (tklp = klp; tklp != NULL; tklp = tklp->kl_next)
6060Sstevel@tonic-gate 		md_eprintf("side=%d, key=%lu\n", tklp->kl_side, tklp->kl_key);
6070Sstevel@tonic-gate }
6080Sstevel@tonic-gate #endif	/* DUMPKEYLST */
6090Sstevel@tonic-gate 
6100Sstevel@tonic-gate static int
key_in_key_lst(key_lst_t * klp,side_t side,mdkey_t key)6110Sstevel@tonic-gate key_in_key_lst(key_lst_t *klp, side_t side, mdkey_t key)
6120Sstevel@tonic-gate {
6130Sstevel@tonic-gate 	key_lst_t	*tklp;
6140Sstevel@tonic-gate 
6150Sstevel@tonic-gate 	for (tklp = klp; tklp != NULL; tklp = tklp->kl_next)
6160Sstevel@tonic-gate 		if (tklp->kl_side == side && tklp->kl_key == key)
6170Sstevel@tonic-gate 			return (1);
6180Sstevel@tonic-gate 
6190Sstevel@tonic-gate 	return (0);
6200Sstevel@tonic-gate }
6210Sstevel@tonic-gate 
6220Sstevel@tonic-gate static void
destroy_key_lst(key_lst_t ** klpp)6230Sstevel@tonic-gate destroy_key_lst(key_lst_t **klpp)
6240Sstevel@tonic-gate {
6250Sstevel@tonic-gate 	key_lst_t	*tklp, *klp;
6260Sstevel@tonic-gate 
6270Sstevel@tonic-gate 	assert(klpp != NULL);
6280Sstevel@tonic-gate 
6290Sstevel@tonic-gate 	tklp = klp = *klpp;
6300Sstevel@tonic-gate 	while (klp != NULL) {
6310Sstevel@tonic-gate 		tklp = klp;
6320Sstevel@tonic-gate 		klp = klp->kl_next;
6330Sstevel@tonic-gate 		Free(tklp);
6340Sstevel@tonic-gate 	}
6350Sstevel@tonic-gate 	*klpp = NULL;
6360Sstevel@tonic-gate }
6370Sstevel@tonic-gate 
6380Sstevel@tonic-gate static void
sr_sidenms(void)6390Sstevel@tonic-gate sr_sidenms(void)
6400Sstevel@tonic-gate {
6410Sstevel@tonic-gate 	md_drive_record		*dr;
6420Sstevel@tonic-gate 	md_set_record		*sr;
6430Sstevel@tonic-gate 	key_lst_t		*use = NULL;
6440Sstevel@tonic-gate 	mdnm_params_t		nm;
6450Sstevel@tonic-gate 	int			i;
6460Sstevel@tonic-gate 	md_mnset_record		*mnsr;
6470Sstevel@tonic-gate 	md_mnnode_record	*nr;
6480Sstevel@tonic-gate 	side_t			myside = 0;
6490Sstevel@tonic-gate 
6500Sstevel@tonic-gate 	/*
6510Sstevel@tonic-gate 	 * We now go through the list of set and drive records collecting
6520Sstevel@tonic-gate 	 * the key/side pairs that are being used.
6530Sstevel@tonic-gate 	 */
6540Sstevel@tonic-gate 	for (sr = setrecords; sr != NULL; sr = sr->sr_next) {
6550Sstevel@tonic-gate 		/*
6560Sstevel@tonic-gate 		 * To handle the multi-node diskset case, get the sideno
6570Sstevel@tonic-gate 		 * associated with this node.  This sideno will be the
6580Sstevel@tonic-gate 		 * same across all multi-node disksets.
6590Sstevel@tonic-gate 		 */
6600Sstevel@tonic-gate 		if ((myside == 0) && (MD_MNSET_REC(sr))) {
6610Sstevel@tonic-gate 			mnsr = (struct md_mnset_record *)sr;
6620Sstevel@tonic-gate 			nr = mnsr->sr_nodechain;
6630Sstevel@tonic-gate 			while (nr) {
6640Sstevel@tonic-gate 				if (strcmp(mynode(), nr->nr_nodename) == 0) {
6650Sstevel@tonic-gate 					myside = nr->nr_nodeid;
6660Sstevel@tonic-gate 					break;
6670Sstevel@tonic-gate 				}
6680Sstevel@tonic-gate 				nr = nr->nr_next;
6690Sstevel@tonic-gate 			}
6700Sstevel@tonic-gate 			/*
6710Sstevel@tonic-gate 			 * If this node is not in this MNset -
6720Sstevel@tonic-gate 			 * then skip this set.
6730Sstevel@tonic-gate 			 */
6740Sstevel@tonic-gate 			if (!nr) {
6750Sstevel@tonic-gate 				continue;
6760Sstevel@tonic-gate 			}
6770Sstevel@tonic-gate 		}
6780Sstevel@tonic-gate 
6790Sstevel@tonic-gate 		for (dr = sr->sr_drivechain; dr != NULL; dr = dr->dr_next) {
6800Sstevel@tonic-gate 			if (MD_MNSET_REC(sr)) {
6810Sstevel@tonic-gate 				/*
6820Sstevel@tonic-gate 				 * There are no non-local sidenames in the
6830Sstevel@tonic-gate 				 * local set for a multi-node diskset.
6840Sstevel@tonic-gate 				 */
6850Sstevel@tonic-gate 				add_key_to_lst(&use, myside, dr->dr_key);
6860Sstevel@tonic-gate 			} else {
6870Sstevel@tonic-gate 				for (i = 0; i < MD_MAXSIDES; i++) {
6880Sstevel@tonic-gate 					/* Skip empty slots */
6890Sstevel@tonic-gate 					if (sr->sr_nodes[i][0] == '\0')
6900Sstevel@tonic-gate 						continue;
6910Sstevel@tonic-gate 
6920Sstevel@tonic-gate 					add_key_to_lst(&use, i + SKEW,
6930Sstevel@tonic-gate 						dr->dr_key);
6940Sstevel@tonic-gate 				}
6950Sstevel@tonic-gate 			}
6960Sstevel@tonic-gate 		}
6970Sstevel@tonic-gate 	}
6980Sstevel@tonic-gate 
6990Sstevel@tonic-gate #ifdef DUMPKEYLST
7000Sstevel@tonic-gate 	pr_key_lst("use", use);
7010Sstevel@tonic-gate #endif	/* DUMPKEYLST */
7020Sstevel@tonic-gate 
7030Sstevel@tonic-gate 	/*
7040Sstevel@tonic-gate 	 * We take the list above and get all non-local sidenames, checking
7050Sstevel@tonic-gate 	 * each to see if they are in use, if they are not used, we delete them.
7060Sstevel@tonic-gate 	 * Do the check for myside to cover multinode disksets.
7070Sstevel@tonic-gate 	 * Then do the check for MD_MAXSIDES to cover non-multinode disksets.
7080Sstevel@tonic-gate 	 * If any multi-node disksets were present, myside would be non-zero.
7090Sstevel@tonic-gate 	 * myside is the same for all multi-node disksets for this node.
7100Sstevel@tonic-gate 	 */
7110Sstevel@tonic-gate 	if (myside) {
7120Sstevel@tonic-gate 		(void) memset(&nm, '\0', sizeof (nm));
7130Sstevel@tonic-gate 		nm.setno = MD_LOCAL_SET;
7140Sstevel@tonic-gate 		nm.side = myside;
7150Sstevel@tonic-gate 		nm.key = MD_KEYWILD;
7160Sstevel@tonic-gate 
7170Sstevel@tonic-gate 		/*CONSTCOND*/
7180Sstevel@tonic-gate 		while (1) {
7190Sstevel@tonic-gate 			if (metaioctl(MD_IOCNXTKEY_NM, &nm, &nm.mde,
7200Sstevel@tonic-gate 			    NULL) != 0) {
7210Sstevel@tonic-gate 				mdclrerror(&nm.mde);
7220Sstevel@tonic-gate 				break;
7230Sstevel@tonic-gate 			}
7240Sstevel@tonic-gate 
7250Sstevel@tonic-gate 			if (nm.key == MD_KEYWILD)
7260Sstevel@tonic-gate 				break;
7270Sstevel@tonic-gate 
7280Sstevel@tonic-gate 			if (! key_in_key_lst(use, nm.side, nm.key)) {
7290Sstevel@tonic-gate 				if (metaioctl(MD_IOCREM_NM, &nm, &nm.mde,
7300Sstevel@tonic-gate 				    NULL) != 0) {
7310Sstevel@tonic-gate 					mdclrerror(&nm.mde);
7320Sstevel@tonic-gate 					continue;
7330Sstevel@tonic-gate 				}
7340Sstevel@tonic-gate 			}
7350Sstevel@tonic-gate 		}
7360Sstevel@tonic-gate 	}
7370Sstevel@tonic-gate 	/* Now handle the non-multinode disksets */
7380Sstevel@tonic-gate 	for (i = 0; i < MD_MAXSIDES; i++) {
7390Sstevel@tonic-gate 		(void) memset(&nm, '\0', sizeof (nm));
7400Sstevel@tonic-gate 		nm.setno = MD_LOCAL_SET;
7410Sstevel@tonic-gate 		nm.side = i + SKEW;
7420Sstevel@tonic-gate 		nm.key = MD_KEYWILD;
7430Sstevel@tonic-gate 
7440Sstevel@tonic-gate 		/*CONSTCOND*/
7450Sstevel@tonic-gate 		while (1) {
7460Sstevel@tonic-gate 			if (metaioctl(MD_IOCNXTKEY_NM, &nm, &nm.mde,
7470Sstevel@tonic-gate 			    NULL) != 0) {
7480Sstevel@tonic-gate 				mdclrerror(&nm.mde);
7490Sstevel@tonic-gate 				break;
7500Sstevel@tonic-gate 			}
7510Sstevel@tonic-gate 
7520Sstevel@tonic-gate 			if (nm.key == MD_KEYWILD)
7530Sstevel@tonic-gate 				break;
7540Sstevel@tonic-gate 
7550Sstevel@tonic-gate 			if (! key_in_key_lst(use, nm.side, nm.key)) {
7560Sstevel@tonic-gate 				if (metaioctl(MD_IOCREM_NM, &nm, &nm.mde,
7570Sstevel@tonic-gate 				    NULL) != 0) {
7580Sstevel@tonic-gate 					mdclrerror(&nm.mde);
7590Sstevel@tonic-gate 					continue;
7600Sstevel@tonic-gate 				}
7610Sstevel@tonic-gate 			}
7620Sstevel@tonic-gate 		}
7630Sstevel@tonic-gate 	}
7640Sstevel@tonic-gate 
7650Sstevel@tonic-gate 	/* Cleanup */
7660Sstevel@tonic-gate 	destroy_key_lst(&use);
7670Sstevel@tonic-gate }
7680Sstevel@tonic-gate 
7690Sstevel@tonic-gate void
sr_validate(void)7700Sstevel@tonic-gate sr_validate(void)
7710Sstevel@tonic-gate {
7720Sstevel@tonic-gate 	md_set_record			*sr;
7730Sstevel@tonic-gate 	md_error_t			xep = mdnullerror;
7740Sstevel@tonic-gate 	int				mnset_single_node;
7750Sstevel@tonic-gate 	md_mnnode_record		*nr;
7760Sstevel@tonic-gate 	md_mnset_record			*mnsr;
7770Sstevel@tonic-gate 
7780Sstevel@tonic-gate 	assert(setsnarfdone != 0);
7790Sstevel@tonic-gate 
7800Sstevel@tonic-gate 	/* We have validated the records already */
7810Sstevel@tonic-gate 	if (setsnarfdone == 3)
7820Sstevel@tonic-gate 		return;
7830Sstevel@tonic-gate 
7840Sstevel@tonic-gate 	/*
7850Sstevel@tonic-gate 	 * Check if we are in a single node non-SC3.x environmemnt
7860Sstevel@tonic-gate 	 */
7870Sstevel@tonic-gate 	mnset_single_node = meta_mn_singlenode();
7880Sstevel@tonic-gate 	/*
7890Sstevel@tonic-gate 	 * If a possible single_node situation, verify that all
7900Sstevel@tonic-gate 	 * MN disksets have only one node (which is mynode()).
7910Sstevel@tonic-gate 	 */
7920Sstevel@tonic-gate 	if (mnset_single_node) {
7930Sstevel@tonic-gate 		for (sr = setrecords; sr != NULL; sr = sr->sr_next) {
7940Sstevel@tonic-gate 			if (MD_MNSET_REC(sr)) {
7950Sstevel@tonic-gate 				mnsr = (struct md_mnset_record *)sr;
7960Sstevel@tonic-gate 				nr = mnsr->sr_nodechain;
7970Sstevel@tonic-gate 				/*
7980Sstevel@tonic-gate 				 * If next pointer is non-null (more than
7990Sstevel@tonic-gate 				 * one node in list) or if the single node
8000Sstevel@tonic-gate 				 * isn't my node - reset single node flag.
8010Sstevel@tonic-gate 				 */
8020Sstevel@tonic-gate 				if ((nr->nr_next) ||
8030Sstevel@tonic-gate 				    (strcmp(nr->nr_nodename, mynode()) != 0)) {
8040Sstevel@tonic-gate 					mnset_single_node = 0;
8050Sstevel@tonic-gate 					break;
8060Sstevel@tonic-gate 				}
8070Sstevel@tonic-gate 			}
8080Sstevel@tonic-gate 		}
8090Sstevel@tonic-gate 	}
8100Sstevel@tonic-gate 
8110Sstevel@tonic-gate 	for (sr = setrecords; sr != NULL; sr = sr->sr_next) {
8120Sstevel@tonic-gate 		/*
8130Sstevel@tonic-gate 		 * If a MN diskset and not in the single node
8140Sstevel@tonic-gate 		 * situation, then don't validate the MN set.
8150Sstevel@tonic-gate 		 * This is done during a reconfig cycle since all
8160Sstevel@tonic-gate 		 * nodes must take the same action.
8170Sstevel@tonic-gate 		 */
8180Sstevel@tonic-gate 		if (MD_MNSET_REC(sr) && (mnset_single_node == 0))
8190Sstevel@tonic-gate 			continue;
8200Sstevel@tonic-gate 
8210Sstevel@tonic-gate 		/* Since we do "partial" snarf's, we only check new entries */
8220Sstevel@tonic-gate 		if (! (sr->sr_flags & MD_SR_CHECK))
8230Sstevel@tonic-gate 			continue;
8240Sstevel@tonic-gate 
8250Sstevel@tonic-gate 		/* If we were mid-add, cleanup */
8260Sstevel@tonic-gate 		if ((sr->sr_flags & MD_SR_ADD)) {
8270Sstevel@tonic-gate 			s_delset(sr->sr_setname, &xep);
8280Sstevel@tonic-gate 			if (! mdisok(&xep))
8290Sstevel@tonic-gate 				mdclrerror(&xep);
8300Sstevel@tonic-gate 			continue;
8310Sstevel@tonic-gate 		}
8320Sstevel@tonic-gate 
8330Sstevel@tonic-gate 		/* Make sure we are in the set. */
8340Sstevel@tonic-gate 		if (sr_hosts(sr))
8350Sstevel@tonic-gate 			continue;
8360Sstevel@tonic-gate 
8370Sstevel@tonic-gate 		/* Check has been done, clear the flag */
8380Sstevel@tonic-gate 		if ((sr->sr_flags & MD_SR_CHECK))
8390Sstevel@tonic-gate 			sr->sr_flags &= ~MD_SR_CHECK;
8400Sstevel@tonic-gate 
8410Sstevel@tonic-gate 		/*
8420Sstevel@tonic-gate 		 * If we got here, we are in the set, make sure the flags make
8430Sstevel@tonic-gate 		 * sense.
8440Sstevel@tonic-gate 		 */
8450Sstevel@tonic-gate 		if (! (sr->sr_flags & MD_SR_OK)) {
8460Sstevel@tonic-gate 			sr->sr_flags &= ~MD_SR_STATE_FLAGS;
8470Sstevel@tonic-gate 			sr->sr_flags |= MD_SR_OK;
8480Sstevel@tonic-gate 			commitset(sr, FALSE, &xep);
8490Sstevel@tonic-gate 			if (! mdisok(&xep))
8500Sstevel@tonic-gate 				mdclrerror(&xep);
8510Sstevel@tonic-gate 		}
8520Sstevel@tonic-gate 
8530Sstevel@tonic-gate 		/* Make sure all the drives are in a stable state. */
8540Sstevel@tonic-gate 		sr_drvs(sr);
8550Sstevel@tonic-gate 	}
8560Sstevel@tonic-gate 
8570Sstevel@tonic-gate 	/* Cleanup any stray sidenames */
8580Sstevel@tonic-gate 	sr_sidenms();
8590Sstevel@tonic-gate 
8600Sstevel@tonic-gate 	setsnarfdone = 3;
8610Sstevel@tonic-gate }
8620Sstevel@tonic-gate 
8630Sstevel@tonic-gate static md_set_record *
sr_in_cache(mddb_recid_t recid)8640Sstevel@tonic-gate sr_in_cache(mddb_recid_t recid)
8650Sstevel@tonic-gate {
8660Sstevel@tonic-gate 	md_set_record *tsr;
8670Sstevel@tonic-gate 
8680Sstevel@tonic-gate 	for (tsr = setrecords; tsr != NULL; tsr = tsr->sr_next)
8690Sstevel@tonic-gate 		if (tsr->sr_selfid == recid)
8700Sstevel@tonic-gate 			return (tsr);
8710Sstevel@tonic-gate 	return ((md_set_record *)NULL);
8720Sstevel@tonic-gate }
8730Sstevel@tonic-gate 
8740Sstevel@tonic-gate int
set_snarf(md_error_t * ep)8750Sstevel@tonic-gate set_snarf(md_error_t *ep)
8760Sstevel@tonic-gate {
8770Sstevel@tonic-gate 	md_set_record			*sr;
8780Sstevel@tonic-gate 	md_mnset_record			*mnsr;
8790Sstevel@tonic-gate 	md_set_record			*tsr;
8800Sstevel@tonic-gate 	md_drive_record			*dr;
8810Sstevel@tonic-gate 	mddb_userreq_t			*reqp;
8820Sstevel@tonic-gate 	ur_recid_lst_t			*urlp;
8830Sstevel@tonic-gate 	mddb_recid_t			id;
8840Sstevel@tonic-gate 	mddb_recid_t			*p;
8850Sstevel@tonic-gate 	md_error_t			xep = mdnullerror;
8860Sstevel@tonic-gate 	md_mnnode_record		*nr;
8870Sstevel@tonic-gate 	mddb_set_node_params_t		snp;
8880Sstevel@tonic-gate 	int				nodecnt;
8890Sstevel@tonic-gate 	mndiskset_membershiplist_t	 *nl, *nl2;
8900Sstevel@tonic-gate 
8910Sstevel@tonic-gate 	/* We have done the snarf call */
8920Sstevel@tonic-gate 	if (setsnarfdone != 0)
8930Sstevel@tonic-gate 		return (0);
8940Sstevel@tonic-gate 
8950Sstevel@tonic-gate 	if (meta_setup_db_locations(ep) != 0) {
8960Sstevel@tonic-gate 		if (! mdismddberror(ep, MDE_DB_STALE))
8970Sstevel@tonic-gate 			return (-1);
8980Sstevel@tonic-gate 		mdclrerror(ep);
8990Sstevel@tonic-gate 	}
9000Sstevel@tonic-gate 
9010Sstevel@tonic-gate 	/*
9020Sstevel@tonic-gate 	 * Get membershiplist from API routine.
9030Sstevel@tonic-gate 	 * If there's an error, just use a NULL
9040Sstevel@tonic-gate 	 * nodelist.
9050Sstevel@tonic-gate 	 */
9060Sstevel@tonic-gate 	if (meta_read_nodelist(&nodecnt, &nl, ep) == -1) {
9070Sstevel@tonic-gate 		nodecnt = 0;  /* no nodes are alive */
9080Sstevel@tonic-gate 		nl = NULL;
9090Sstevel@tonic-gate 		mdclrerror(ep);
9100Sstevel@tonic-gate 	}
9110Sstevel@tonic-gate 
9120Sstevel@tonic-gate 	/* Let sr_cache_add and dr_cache_add know we are doing the snarf */
9130Sstevel@tonic-gate 	setsnarfdone = 1;
9140Sstevel@tonic-gate 
9150Sstevel@tonic-gate 	/* Go get the set records */
9160Sstevel@tonic-gate 	id = 0;
9170Sstevel@tonic-gate 	while ((sr = get_ur_rec(MD_LOCAL_SET, MD_UR_GET_NEXT, MDDB_UR_SR,
9180Sstevel@tonic-gate 							&id, ep)) != NULL) {
9190Sstevel@tonic-gate 		sr->sr_next = NULL;
9200Sstevel@tonic-gate 		sr->sr_drivechain = NULL;
9210Sstevel@tonic-gate 
9220Sstevel@tonic-gate 		/*
9230Sstevel@tonic-gate 		 * Cluster nodename support
9240Sstevel@tonic-gate 		 * Convert nodeid -> nodename
9250Sstevel@tonic-gate 		 * Don't do this for MN disksets since we've already stored
9260Sstevel@tonic-gate 		 * both the nodeid and name.
9270Sstevel@tonic-gate 		 */
9280Sstevel@tonic-gate 		if (!(MD_MNSET_REC(sr)))
9290Sstevel@tonic-gate 			sdssc_cm_sr_nid2nm(sr);
9300Sstevel@tonic-gate 
9310Sstevel@tonic-gate 		/* If we were mid-cvt, cleanup */
9320Sstevel@tonic-gate 		if (sr->sr_flags & MD_SR_CVT) {
9330Sstevel@tonic-gate 			/* If the daemon is calling, cleanup */
9340Sstevel@tonic-gate 			if (md_in_daemon)
9350Sstevel@tonic-gate 				url_addl(&url_tode, sr->sr_selfid);
9360Sstevel@tonic-gate 			continue;
9370Sstevel@tonic-gate 		}
9380Sstevel@tonic-gate 
9390Sstevel@tonic-gate 		if (md_in_daemon)
9400Sstevel@tonic-gate 			url_addl(&url_used, sr->sr_selfid);
9410Sstevel@tonic-gate 
9420Sstevel@tonic-gate 		/* Skip cached records */
9430Sstevel@tonic-gate 		tsr = sr_in_cache(sr->sr_selfid);
9440Sstevel@tonic-gate 		if (tsr != (md_set_record *)NULL) {
9450Sstevel@tonic-gate 			if (MD_MNSET_REC(sr)) {
9460Sstevel@tonic-gate 				mnsr = (struct md_mnset_record *)sr;
9470Sstevel@tonic-gate 				Free(mnsr);
9480Sstevel@tonic-gate 			} else {
9490Sstevel@tonic-gate 				Free(sr);
9500Sstevel@tonic-gate 			}
9510Sstevel@tonic-gate 			if (md_in_daemon)
9520Sstevel@tonic-gate 				for (dr = tsr->sr_drivechain;
9530Sstevel@tonic-gate 				    dr != (md_drive_record *)NULL;
9540Sstevel@tonic-gate 				    dr = dr->dr_next)
9550Sstevel@tonic-gate 					url_addl(&url_used, dr->dr_selfid);
9560Sstevel@tonic-gate 			continue;
9570Sstevel@tonic-gate 		}
9580Sstevel@tonic-gate 
9590Sstevel@tonic-gate 		/* Mark the record as one to be checked */
9600Sstevel@tonic-gate 		sr->sr_flags |= MD_SR_CHECK;
9610Sstevel@tonic-gate 
9620Sstevel@tonic-gate 		sr_cache_add(sr);
9630Sstevel@tonic-gate 
9640Sstevel@tonic-gate 		/* If MNdiskset, go get the node records */
9650Sstevel@tonic-gate 		if (MD_MNSET_REC(sr)) {
9660Sstevel@tonic-gate 			mnsr = (struct md_mnset_record *)sr;
9670Sstevel@tonic-gate 			mnsr->sr_nodechain = NULL;
9680Sstevel@tonic-gate 			p = &mnsr->sr_noderec;
9690Sstevel@tonic-gate 			while ((nr = get_ur_rec(MD_LOCAL_SET, MD_UR_GET_WKEY,
9700Sstevel@tonic-gate 					MDDB_UR_NR, p, ep)) != NULL) {
9710Sstevel@tonic-gate 				nr->nr_next = NULL;
9720Sstevel@tonic-gate 
9730Sstevel@tonic-gate 				if (md_in_daemon)
9740Sstevel@tonic-gate 					url_addl(&url_used, nr->nr_selfid);
9750Sstevel@tonic-gate 
9760Sstevel@tonic-gate 				/*
9770Sstevel@tonic-gate 				 * Turn off ALIVE node flag based on member
9780Sstevel@tonic-gate 				 * list.
9790Sstevel@tonic-gate 				 * If ALIVE flag is not set, reset OWN flag.
9800Sstevel@tonic-gate 				 * If this node is mynode, set the OWN flag
9810Sstevel@tonic-gate 				 * to match the ownership of the diskset.
9820Sstevel@tonic-gate 				 */
9830Sstevel@tonic-gate 				if (md_in_daemon) {
9840Sstevel@tonic-gate 					nr->nr_flags &= ~MD_MN_NODE_ALIVE;
9850Sstevel@tonic-gate 					nl2 = nl;
9860Sstevel@tonic-gate 					while (nl2) {
9870Sstevel@tonic-gate 						/*
9880Sstevel@tonic-gate 						 * If in member list,
9890Sstevel@tonic-gate 						 * set alive.
9900Sstevel@tonic-gate 						 */
9910Sstevel@tonic-gate 						if (nl2->msl_node_id ==
9920Sstevel@tonic-gate 						    nr->nr_nodeid) {
9930Sstevel@tonic-gate 							nr->nr_flags |=
9940Sstevel@tonic-gate 							    MD_MN_NODE_ALIVE;
9950Sstevel@tonic-gate 							break;
9960Sstevel@tonic-gate 						}
9970Sstevel@tonic-gate 						nl2 = nl2->next;
9980Sstevel@tonic-gate 					}
9990Sstevel@tonic-gate 					/*
10000Sstevel@tonic-gate 					 * If mynode is in member list, then
10010Sstevel@tonic-gate 					 * check to see if set is snarfed.
10020Sstevel@tonic-gate 					 * If set snarfed, set own flag;
10030Sstevel@tonic-gate 					 * otherwise reset it.
10040Sstevel@tonic-gate 					 * Don't change master even if
10050Sstevel@tonic-gate 					 * node isn't an owner node, since
10060Sstevel@tonic-gate 					 * node may be master, but hasn't
10070Sstevel@tonic-gate 					 * joined the set yet.
10080Sstevel@tonic-gate 					 */
10090Sstevel@tonic-gate 					if (nr->nr_flags & MD_MN_NODE_ALIVE) {
10100Sstevel@tonic-gate 					    if (strcmp(nr->nr_nodename,
10110Sstevel@tonic-gate 						mynode()) == 0) {
10120Sstevel@tonic-gate 						    if (s_ownset(
10130Sstevel@tonic-gate 							mnsr->sr_setno, ep)) {
10140Sstevel@tonic-gate 							nr->nr_flags |=
10150Sstevel@tonic-gate 							    MD_MN_NODE_OWN;
10160Sstevel@tonic-gate 						    } else {
10170Sstevel@tonic-gate 							nr->nr_flags &=
10180Sstevel@tonic-gate 							    ~MD_MN_NODE_OWN;
10190Sstevel@tonic-gate 						    }
10200Sstevel@tonic-gate 					    }
10210Sstevel@tonic-gate 					} else {
10220Sstevel@tonic-gate 					    if (strcmp(nr->nr_nodename,
10230Sstevel@tonic-gate 						mynode()) == 0) {
10240Sstevel@tonic-gate 						/*
10250Sstevel@tonic-gate 						 * If my node isn't in member
10260Sstevel@tonic-gate 						 * list then reset master.
10270Sstevel@tonic-gate 						 */
10280Sstevel@tonic-gate 						mnsr = (struct
10290Sstevel@tonic-gate 						    md_mnset_record *)sr;
10300Sstevel@tonic-gate 						mnsr->sr_master_nodeid =
10310Sstevel@tonic-gate 							MD_MN_INVALID_NID;
10320Sstevel@tonic-gate 						mnsr->sr_master_nodenm[0] =
10330Sstevel@tonic-gate 							'\0';
10340Sstevel@tonic-gate 					    }
10350Sstevel@tonic-gate 					    nr->nr_flags &= ~MD_MN_NODE_OWN;
10360Sstevel@tonic-gate 					}
10370Sstevel@tonic-gate 				}
10380Sstevel@tonic-gate 
10390Sstevel@tonic-gate 				/*
10400Sstevel@tonic-gate 				 * Must grab nr_nextrec now since
10410Sstevel@tonic-gate 				 * mnnr_cache_add may change it
10420Sstevel@tonic-gate 				 * (mnnr_cache_add is storing the nodes in
10430Sstevel@tonic-gate 				 * an ascending nodeid order list in order
10440Sstevel@tonic-gate 				 * to support reconfig).
10450Sstevel@tonic-gate 				 */
10460Sstevel@tonic-gate 				if (nr->nr_nextrec != 0)
10470Sstevel@tonic-gate 					p = &nr->nr_nextrec;
10480Sstevel@tonic-gate 				else
10490Sstevel@tonic-gate 					p = NULL;
10500Sstevel@tonic-gate 
10510Sstevel@tonic-gate 				mnnr_cache_add((struct md_mnset_record *)sr,
10520Sstevel@tonic-gate 					nr);
10530Sstevel@tonic-gate 
10540Sstevel@tonic-gate 				if ((md_in_daemon) &&
10550Sstevel@tonic-gate 				    (strcmp(nr->nr_nodename, mynode()) == 0)) {
10560Sstevel@tonic-gate 					(void) memset(&snp, 0, sizeof (snp));
10570Sstevel@tonic-gate 					snp.sn_nodeid = nr->nr_nodeid;
10580Sstevel@tonic-gate 					snp.sn_setno = mnsr->sr_setno;
10590Sstevel@tonic-gate 					if (metaioctl(MD_MN_SET_NODEID, &snp,
10600Sstevel@tonic-gate 					    &snp.sn_mde, NULL) != 0) {
10610Sstevel@tonic-gate 						(void) mdstealerror(ep,
10620Sstevel@tonic-gate 							&snp.sn_mde);
10630Sstevel@tonic-gate 					}
10640Sstevel@tonic-gate 				}
10650Sstevel@tonic-gate 
10660Sstevel@tonic-gate 				if (p == NULL)
10670Sstevel@tonic-gate 					break;
10680Sstevel@tonic-gate 			}
10690Sstevel@tonic-gate 			if (! mdisok(ep)) {
10700Sstevel@tonic-gate 				if (! mdissyserror(ep, ENOENT))
10710Sstevel@tonic-gate 					goto out;
10720Sstevel@tonic-gate 				mdclrerror(ep);
10730Sstevel@tonic-gate 			}
10740Sstevel@tonic-gate 		}
10750Sstevel@tonic-gate 
10760Sstevel@tonic-gate 		if (sr->sr_driverec == 0)
10770Sstevel@tonic-gate 			continue;
10780Sstevel@tonic-gate 
10790Sstevel@tonic-gate 		/* Go get the drive records */
10800Sstevel@tonic-gate 		p = &sr->sr_driverec;
10810Sstevel@tonic-gate 		while ((dr = get_ur_rec(MD_LOCAL_SET, MD_UR_GET_WKEY,
10820Sstevel@tonic-gate 				MDDB_UR_DR, p, ep)) != NULL) {
10830Sstevel@tonic-gate 			dr->dr_next = NULL;
10840Sstevel@tonic-gate 
10850Sstevel@tonic-gate 			if (md_in_daemon)
10860Sstevel@tonic-gate 				url_addl(&url_used, dr->dr_selfid);
10870Sstevel@tonic-gate 
10880Sstevel@tonic-gate 			dr_cache_add(sr, dr);
10890Sstevel@tonic-gate 
10900Sstevel@tonic-gate 			if (dr->dr_nextrec == 0)
10910Sstevel@tonic-gate 				break;
10920Sstevel@tonic-gate 
10930Sstevel@tonic-gate 			p = &dr->dr_nextrec;
10940Sstevel@tonic-gate 		}
10950Sstevel@tonic-gate 		if (! mdisok(ep)) {
10960Sstevel@tonic-gate 			if (! mdissyserror(ep, ENOENT))
10970Sstevel@tonic-gate 				goto out;
10980Sstevel@tonic-gate 			mdclrerror(ep);
10990Sstevel@tonic-gate 			/*
11000Sstevel@tonic-gate 			 * If dr_nextrec was not valid, or we had some
11010Sstevel@tonic-gate 			 * problem getting the record, we end up here.
11020Sstevel@tonic-gate 			 * get_ur_rec() zeroes the recid we passed in,
11030Sstevel@tonic-gate 			 * if we had a failure getting a record using a key,
11040Sstevel@tonic-gate 			 * so we simply commit the set record and valid
11050Sstevel@tonic-gate 			 * drive records, if this fails, we hand an error
11060Sstevel@tonic-gate 			 * back to the caller.
11070Sstevel@tonic-gate 			 */
11080Sstevel@tonic-gate 			commitset(sr, FALSE, ep);
11090Sstevel@tonic-gate 			if (! mdisok(ep))
11100Sstevel@tonic-gate 				goto out;
11110Sstevel@tonic-gate 		}
11120Sstevel@tonic-gate 	}
11130Sstevel@tonic-gate 	if (! mdisok(ep)) {
11140Sstevel@tonic-gate 		if (! mdissyserror(ep, ENOENT))
11150Sstevel@tonic-gate 			goto out;
11160Sstevel@tonic-gate 		mdclrerror(ep);
11170Sstevel@tonic-gate 	}
11180Sstevel@tonic-gate 
11190Sstevel@tonic-gate 	/*
11200Sstevel@tonic-gate 	 * If the daemon called, go through the USER records and cleanup
11210Sstevel@tonic-gate 	 * any that are not used by valid sets.
11220Sstevel@tonic-gate 	 */
11230Sstevel@tonic-gate 	if (md_in_daemon) {
11240Sstevel@tonic-gate 		id = 0;
11250Sstevel@tonic-gate 		/* Make a list of records to delete */
11260Sstevel@tonic-gate 		while ((reqp = get_db_rec(MD_UR_GET_NEXT, MD_LOCAL_SET,
11270Sstevel@tonic-gate 		    MDDB_USER, 0, &id, ep)) != NULL) {
11280Sstevel@tonic-gate 			if (reqp->ur_type2 != MDDB_UR_SR &&
11290Sstevel@tonic-gate 			    reqp->ur_type2 != MDDB_UR_DR) {
113062Sjeanm 				Free((void *)(uintptr_t)reqp->ur_data);
11310Sstevel@tonic-gate 				Free(reqp);
11320Sstevel@tonic-gate 				continue;
11330Sstevel@tonic-gate 			}
11340Sstevel@tonic-gate 			if (! url_findl(url_used, reqp->ur_recid))
11350Sstevel@tonic-gate 				url_addl(&url_tode, reqp->ur_recid);
113662Sjeanm 			Free((void *)(uintptr_t)reqp->ur_data);
11370Sstevel@tonic-gate 			Free(reqp);
11380Sstevel@tonic-gate 		}
11390Sstevel@tonic-gate 		if (! mdisok(ep)) {
11400Sstevel@tonic-gate 			if (! mdissyserror(ep, ENOENT))
11410Sstevel@tonic-gate 				goto out;
11420Sstevel@tonic-gate 			mdclrerror(ep);
11430Sstevel@tonic-gate 		}
11440Sstevel@tonic-gate 
11450Sstevel@tonic-gate 		/* Delete all the delete listed records */
11460Sstevel@tonic-gate 		for (urlp = url_tode; urlp != NULL; urlp = urlp->url_nx) {
11470Sstevel@tonic-gate 			s_delrec(urlp->url_recid, &xep);
11480Sstevel@tonic-gate 			if (! mdisok(&xep))
11490Sstevel@tonic-gate 				mdclrerror(&xep);
11500Sstevel@tonic-gate 		}
11510Sstevel@tonic-gate 	}
11520Sstevel@tonic-gate 
11530Sstevel@tonic-gate 	url_freel(&url_used);
11540Sstevel@tonic-gate 	url_freel(&url_tode);
11550Sstevel@tonic-gate 
11560Sstevel@tonic-gate 	if (nodecnt)
11570Sstevel@tonic-gate 		meta_free_nodelist(nl);
11580Sstevel@tonic-gate 
11590Sstevel@tonic-gate 	/* Mark the snarf complete */
11600Sstevel@tonic-gate 	setsnarfdone = 2;
11610Sstevel@tonic-gate 	return (0);
11620Sstevel@tonic-gate 
11630Sstevel@tonic-gate out:
11640Sstevel@tonic-gate 	url_freel(&url_used);
11650Sstevel@tonic-gate 	url_freel(&url_tode);
11660Sstevel@tonic-gate 
11670Sstevel@tonic-gate 	sr_cache_flush(1);
11680Sstevel@tonic-gate 
11690Sstevel@tonic-gate 	if (nodecnt)
11700Sstevel@tonic-gate 		meta_free_nodelist(nl);
11710Sstevel@tonic-gate 
11720Sstevel@tonic-gate 	/* Snarf failed, reset state */
11730Sstevel@tonic-gate 	setsnarfdone = 0;
11740Sstevel@tonic-gate 
11750Sstevel@tonic-gate 	return (-1);
11760Sstevel@tonic-gate }
11770Sstevel@tonic-gate 
11780Sstevel@tonic-gate void
sr_cache_add(md_set_record * sr)11790Sstevel@tonic-gate sr_cache_add(md_set_record *sr)
11800Sstevel@tonic-gate {
11810Sstevel@tonic-gate 	md_set_record *tsr;
11820Sstevel@tonic-gate 
11830Sstevel@tonic-gate 	assert(setsnarfdone != 0);
11840Sstevel@tonic-gate 
11850Sstevel@tonic-gate 	if (setrecords == NULL) {
11860Sstevel@tonic-gate 		setrecords = sr;
11870Sstevel@tonic-gate 		return;
11880Sstevel@tonic-gate 	}
11890Sstevel@tonic-gate 
11900Sstevel@tonic-gate 	for (tsr = setrecords; tsr->sr_next != NULL; tsr = tsr->sr_next)
11910Sstevel@tonic-gate 		/* void */;
11920Sstevel@tonic-gate 	tsr->sr_next = sr;
11930Sstevel@tonic-gate }
11940Sstevel@tonic-gate 
11950Sstevel@tonic-gate void
sr_cache_del(mddb_recid_t recid)11960Sstevel@tonic-gate sr_cache_del(mddb_recid_t recid)
11970Sstevel@tonic-gate {
11980Sstevel@tonic-gate 	md_set_record	*sr, *tsr;
11990Sstevel@tonic-gate 	md_mnset_record	*mnsr;
12000Sstevel@tonic-gate 
12010Sstevel@tonic-gate 	assert(setsnarfdone != 0);
12020Sstevel@tonic-gate 
12030Sstevel@tonic-gate 	for (sr = tsr = setrecords; sr != NULL; tsr = sr, sr = sr->sr_next) {
12040Sstevel@tonic-gate 		if (sr->sr_selfid != recid)
12050Sstevel@tonic-gate 			continue;
12060Sstevel@tonic-gate 		if (sr == setrecords)
12070Sstevel@tonic-gate 			setrecords = sr->sr_next;
12080Sstevel@tonic-gate 		else
12090Sstevel@tonic-gate 			tsr->sr_next = sr->sr_next;
12100Sstevel@tonic-gate 		if (MD_MNSET_REC(sr)) {
12110Sstevel@tonic-gate 			mnsr = (struct md_mnset_record *)sr;
12120Sstevel@tonic-gate 			Free(mnsr);
12130Sstevel@tonic-gate 		} else {
12140Sstevel@tonic-gate 			Free(sr);
12150Sstevel@tonic-gate 		}
12160Sstevel@tonic-gate 		break;
12170Sstevel@tonic-gate 	}
12180Sstevel@tonic-gate 	if (setrecords == NULL)
12190Sstevel@tonic-gate 		setsnarfdone = 0;
12200Sstevel@tonic-gate }
12210Sstevel@tonic-gate 
12220Sstevel@tonic-gate void
dr_cache_add(md_set_record * sr,md_drive_record * dr)12230Sstevel@tonic-gate dr_cache_add(md_set_record *sr, md_drive_record *dr)
12240Sstevel@tonic-gate {
12250Sstevel@tonic-gate 	md_drive_record	*tdr;
12260Sstevel@tonic-gate 
12270Sstevel@tonic-gate 	assert(setsnarfdone != 0);
12280Sstevel@tonic-gate 
12290Sstevel@tonic-gate 	assert(sr != NULL);
12300Sstevel@tonic-gate 
12310Sstevel@tonic-gate 	if (sr->sr_drivechain == NULL) {
12320Sstevel@tonic-gate 		sr->sr_drivechain = dr;
12330Sstevel@tonic-gate 		sr->sr_driverec = dr->dr_selfid;
12340Sstevel@tonic-gate 		return;
12350Sstevel@tonic-gate 	}
12360Sstevel@tonic-gate 
12370Sstevel@tonic-gate 	for (tdr = sr->sr_drivechain; tdr->dr_next != NULL; tdr = tdr->dr_next)
12380Sstevel@tonic-gate 		/* void */;
12390Sstevel@tonic-gate 
12400Sstevel@tonic-gate 	tdr->dr_next = dr;
12410Sstevel@tonic-gate 	tdr->dr_nextrec = dr->dr_selfid;
12420Sstevel@tonic-gate }
12430Sstevel@tonic-gate 
12440Sstevel@tonic-gate void
dr_cache_del(md_set_record * sr,mddb_recid_t recid)12450Sstevel@tonic-gate dr_cache_del(md_set_record *sr, mddb_recid_t recid)
12460Sstevel@tonic-gate {
12470Sstevel@tonic-gate 	md_drive_record *dr;
12480Sstevel@tonic-gate 	md_drive_record *tdr;
12490Sstevel@tonic-gate 
12500Sstevel@tonic-gate 	assert(setsnarfdone != 0);
12510Sstevel@tonic-gate 
12520Sstevel@tonic-gate 	assert(sr != NULL);
12530Sstevel@tonic-gate 
12540Sstevel@tonic-gate 	for (dr = tdr = sr->sr_drivechain; dr != NULL;
12550Sstevel@tonic-gate 	    tdr = dr, dr = dr->dr_next) {
12560Sstevel@tonic-gate 		if (dr->dr_selfid != recid)
12570Sstevel@tonic-gate 			continue;
12580Sstevel@tonic-gate 
12590Sstevel@tonic-gate 		if (dr == sr->sr_drivechain) {
12600Sstevel@tonic-gate 			sr->sr_drivechain = dr->dr_next;
12610Sstevel@tonic-gate 			sr->sr_driverec = dr->dr_nextrec;
12620Sstevel@tonic-gate 		} else {
12630Sstevel@tonic-gate 			tdr->dr_next = dr->dr_next;
12640Sstevel@tonic-gate 			tdr->dr_nextrec = dr->dr_nextrec;
12650Sstevel@tonic-gate 		}
12660Sstevel@tonic-gate 		Free(dr);
12670Sstevel@tonic-gate 		break;
12680Sstevel@tonic-gate 	}
12690Sstevel@tonic-gate }
12700Sstevel@tonic-gate 
12710Sstevel@tonic-gate /*
12720Sstevel@tonic-gate  * Nodes must be kept in ascending node id order in order to
12730Sstevel@tonic-gate  * support reconfig.
12740Sstevel@tonic-gate  *
12750Sstevel@tonic-gate  * This routine may change nr->nr_next and nr->nr_nextrec.
12760Sstevel@tonic-gate  */
12770Sstevel@tonic-gate void
mnnr_cache_add(md_mnset_record * mnsr,md_mnnode_record * nr)12780Sstevel@tonic-gate mnnr_cache_add(md_mnset_record *mnsr, md_mnnode_record *nr)
12790Sstevel@tonic-gate {
12800Sstevel@tonic-gate 	md_mnnode_record	*tnr, *tnr_prev;
12810Sstevel@tonic-gate 
12820Sstevel@tonic-gate 	assert(mnsr != NULL);
12830Sstevel@tonic-gate 
12840Sstevel@tonic-gate 	if (mnsr->sr_nodechain == NULL) {
12850Sstevel@tonic-gate 		mnsr->sr_nodechain = nr;
12860Sstevel@tonic-gate 		mnsr->sr_noderec = nr->nr_selfid;
12870Sstevel@tonic-gate 		return;
12880Sstevel@tonic-gate 	}
12890Sstevel@tonic-gate 
12900Sstevel@tonic-gate 	/*
12910Sstevel@tonic-gate 	 * If new_record->nodeid < first_record->nodeid,
12920Sstevel@tonic-gate 	 * put new_record at beginning of list.
12930Sstevel@tonic-gate 	 */
12940Sstevel@tonic-gate 	if (nr->nr_nodeid < mnsr->sr_nodechain->nr_nodeid) {
12950Sstevel@tonic-gate 		nr->nr_next = mnsr->sr_nodechain;
12960Sstevel@tonic-gate 		nr->nr_nextrec = mnsr->sr_noderec;
12970Sstevel@tonic-gate 		mnsr->sr_nodechain = nr;
12980Sstevel@tonic-gate 		mnsr->sr_noderec = nr->nr_selfid;
12990Sstevel@tonic-gate 		return;
13000Sstevel@tonic-gate 	}
13010Sstevel@tonic-gate 
13020Sstevel@tonic-gate 	/*
13030Sstevel@tonic-gate 	 * Walk list looking for place to insert record.
13040Sstevel@tonic-gate 	 */
13050Sstevel@tonic-gate 
13060Sstevel@tonic-gate 	tnr_prev = mnsr->sr_nodechain;
13070Sstevel@tonic-gate 	tnr = tnr_prev->nr_next;
13080Sstevel@tonic-gate 	while (tnr) {
13090Sstevel@tonic-gate 		/* Insert new record between tnr_prev and tnr */
13100Sstevel@tonic-gate 		if (nr->nr_nodeid < tnr->nr_nodeid) {
13110Sstevel@tonic-gate 			nr->nr_next = tnr;
13120Sstevel@tonic-gate 			nr->nr_nextrec = tnr->nr_selfid; /* tnr's recid */
13130Sstevel@tonic-gate 			tnr_prev->nr_next = nr;
13140Sstevel@tonic-gate 			tnr_prev->nr_nextrec = nr->nr_selfid;
13150Sstevel@tonic-gate 			return;
13160Sstevel@tonic-gate 		}
13170Sstevel@tonic-gate 		tnr_prev = tnr;
13180Sstevel@tonic-gate 		tnr = tnr->nr_next;
13190Sstevel@tonic-gate 	}
13200Sstevel@tonic-gate 
13210Sstevel@tonic-gate 	/*
13220Sstevel@tonic-gate 	 * Add record to end of list.
13230Sstevel@tonic-gate 	 */
13240Sstevel@tonic-gate 	tnr_prev->nr_next = nr;
13250Sstevel@tonic-gate 	tnr_prev->nr_nextrec = nr->nr_selfid;
13260Sstevel@tonic-gate }
13270Sstevel@tonic-gate 
13280Sstevel@tonic-gate void
mnnr_cache_del(md_mnset_record * mnsr,mddb_recid_t recid)13290Sstevel@tonic-gate mnnr_cache_del(md_mnset_record *mnsr, mddb_recid_t recid)
13300Sstevel@tonic-gate {
13310Sstevel@tonic-gate 	md_mnnode_record *nr;
13320Sstevel@tonic-gate 	md_mnnode_record *tnr;
13330Sstevel@tonic-gate 
13340Sstevel@tonic-gate 	assert(mnsr != NULL);
13350Sstevel@tonic-gate 
13360Sstevel@tonic-gate 	tnr = 0;
13370Sstevel@tonic-gate 	nr = mnsr->sr_nodechain;
13380Sstevel@tonic-gate 	while (nr) {
13390Sstevel@tonic-gate 		if (nr->nr_selfid != recid) {
13400Sstevel@tonic-gate 			tnr = nr;
13410Sstevel@tonic-gate 			nr = nr->nr_next;
13420Sstevel@tonic-gate 			continue;
13430Sstevel@tonic-gate 		}
13440Sstevel@tonic-gate 
13450Sstevel@tonic-gate 		if (nr == mnsr->sr_nodechain) {
13460Sstevel@tonic-gate 			mnsr->sr_nodechain = nr->nr_next;
13470Sstevel@tonic-gate 			mnsr->sr_noderec = nr->nr_nextrec;
13480Sstevel@tonic-gate 		} else {
13490Sstevel@tonic-gate 			tnr->nr_next = nr->nr_next;
13500Sstevel@tonic-gate 			tnr->nr_nextrec = nr->nr_nextrec;
13510Sstevel@tonic-gate 		}
13520Sstevel@tonic-gate 		Free(nr);
13530Sstevel@tonic-gate 		break;
13540Sstevel@tonic-gate 	}
13550Sstevel@tonic-gate }
13560Sstevel@tonic-gate 
13570Sstevel@tonic-gate int
metad_isautotakebyname(char * setname)13580Sstevel@tonic-gate metad_isautotakebyname(char *setname)
13590Sstevel@tonic-gate {
13600Sstevel@tonic-gate 	md_error_t	error = mdnullerror;
13610Sstevel@tonic-gate 	md_set_record	*sr;
13620Sstevel@tonic-gate 
13630Sstevel@tonic-gate 	if (md_in_daemon)
13640Sstevel@tonic-gate 	    assert(setsnarfdone != 0);
13650Sstevel@tonic-gate 	else if (set_snarf(&error)) {
13660Sstevel@tonic-gate 	    mdclrerror(&error);
13670Sstevel@tonic-gate 	    return (0);
13680Sstevel@tonic-gate 	}
13690Sstevel@tonic-gate 
13700Sstevel@tonic-gate 	for (sr = setrecords; sr != NULL; sr = sr->sr_next) {
13710Sstevel@tonic-gate 	    if (strcmp(setname, sr->sr_setname) == 0) {
13720Sstevel@tonic-gate 		if (sr->sr_flags & MD_SR_AUTO_TAKE)
13730Sstevel@tonic-gate 		    return (1);
13740Sstevel@tonic-gate 		return (0);
13750Sstevel@tonic-gate 	    }
13760Sstevel@tonic-gate 	}
13770Sstevel@tonic-gate 
13780Sstevel@tonic-gate 	return (0);
13790Sstevel@tonic-gate }
13800Sstevel@tonic-gate 
13810Sstevel@tonic-gate int
metad_isautotakebynum(set_t setno)13820Sstevel@tonic-gate metad_isautotakebynum(set_t setno)
13830Sstevel@tonic-gate {
13840Sstevel@tonic-gate 	md_error_t	error = mdnullerror;
13850Sstevel@tonic-gate 	md_set_record	*sr;
13860Sstevel@tonic-gate 
13870Sstevel@tonic-gate 	if (md_in_daemon)
13880Sstevel@tonic-gate 	    assert(setsnarfdone != 0);
13890Sstevel@tonic-gate 	else if (set_snarf(&error)) {
13900Sstevel@tonic-gate 	    mdclrerror(&error);
13910Sstevel@tonic-gate 	    return (0);
13920Sstevel@tonic-gate 	}
13930Sstevel@tonic-gate 
13940Sstevel@tonic-gate 	for (sr = setrecords; sr != NULL; sr = sr->sr_next) {
13950Sstevel@tonic-gate 	    if (setno == sr->sr_setno) {
13960Sstevel@tonic-gate 		if (sr->sr_flags & MD_SR_AUTO_TAKE)
13970Sstevel@tonic-gate 		    return (1);
13980Sstevel@tonic-gate 		return (0);
13990Sstevel@tonic-gate 	    }
14000Sstevel@tonic-gate 	}
14010Sstevel@tonic-gate 
14020Sstevel@tonic-gate 	return (0);
14030Sstevel@tonic-gate }
14040Sstevel@tonic-gate 
14050Sstevel@tonic-gate md_set_record *
metad_getsetbyname(char * setname,md_error_t * ep)14060Sstevel@tonic-gate metad_getsetbyname(char *setname, md_error_t *ep)
14070Sstevel@tonic-gate {
14080Sstevel@tonic-gate 	md_set_record	*sr;
14090Sstevel@tonic-gate 	char		buf[100];
14100Sstevel@tonic-gate 
14110Sstevel@tonic-gate 	assert(setsnarfdone != 0);
14120Sstevel@tonic-gate 
14130Sstevel@tonic-gate 	for (sr = setrecords; sr != NULL; sr = sr->sr_next)
14140Sstevel@tonic-gate 		if (strcmp(setname, sr->sr_setname) == 0)
14150Sstevel@tonic-gate 			return (sr);
14160Sstevel@tonic-gate 
14170Sstevel@tonic-gate 	(void) snprintf(buf, sizeof (buf), "setname \"%s\"", setname);
14180Sstevel@tonic-gate 	(void) mderror(ep, MDE_NO_SET, buf);
14190Sstevel@tonic-gate 	return (NULL);
14200Sstevel@tonic-gate }
14210Sstevel@tonic-gate 
14220Sstevel@tonic-gate md_set_record *
metad_getsetbynum(set_t setno,md_error_t * ep)14230Sstevel@tonic-gate metad_getsetbynum(set_t setno, md_error_t *ep)
14240Sstevel@tonic-gate {
14250Sstevel@tonic-gate 	md_set_record	*sr;
14260Sstevel@tonic-gate 	char		buf[100];
14270Sstevel@tonic-gate 
14280Sstevel@tonic-gate 	if (md_in_daemon)
14290Sstevel@tonic-gate 		assert(setsnarfdone != 0);
14300Sstevel@tonic-gate 	else if (set_snarf(ep))		/* BYPASS DAEMON mode */
14310Sstevel@tonic-gate 		return (NULL);
14320Sstevel@tonic-gate 
14330Sstevel@tonic-gate 	for (sr = setrecords; sr != NULL; sr = sr->sr_next)
14340Sstevel@tonic-gate 		if (setno == sr->sr_setno)
14350Sstevel@tonic-gate 			return (sr);
14360Sstevel@tonic-gate 
14370Sstevel@tonic-gate 	(void) sprintf(buf, "setno %u", setno);
14380Sstevel@tonic-gate 	(void) mderror(ep, MDE_NO_SET, buf);
14390Sstevel@tonic-gate 	return (NULL);
14400Sstevel@tonic-gate }
14410Sstevel@tonic-gate 
14420Sstevel@tonic-gate 
14430Sstevel@tonic-gate /*
14440Sstevel@tonic-gate  * Commit the set record and all of its associated records
14450Sstevel@tonic-gate  * (drive records, node records for a MNset) to the local mddb.
14460Sstevel@tonic-gate  */
14470Sstevel@tonic-gate void
commitset(md_set_record * sr,int inc_genid,md_error_t * ep)14480Sstevel@tonic-gate commitset(md_set_record *sr, int inc_genid, md_error_t *ep)
14490Sstevel@tonic-gate {
14500Sstevel@tonic-gate 	int		drc, nrc, rc;
14510Sstevel@tonic-gate 	int		*recs;
14520Sstevel@tonic-gate 	uint_t		size;
14530Sstevel@tonic-gate 	md_drive_record	*dr;
14540Sstevel@tonic-gate 	mddb_userreq_t	req;
14550Sstevel@tonic-gate 	md_mnset_record	*mnsr;
14560Sstevel@tonic-gate 	md_mnnode_record	*nr;
14570Sstevel@tonic-gate 
14580Sstevel@tonic-gate 	assert(setsnarfdone != 0);
14590Sstevel@tonic-gate 
14600Sstevel@tonic-gate 	/*
14610Sstevel@tonic-gate 	 * Cluster nodename support
14620Sstevel@tonic-gate 	 * Convert nodename -> nodeid
14630Sstevel@tonic-gate 	 * Don't do this for MN disksets since we've already stored
14640Sstevel@tonic-gate 	 * both the nodeid and name.
14650Sstevel@tonic-gate 	 */
14660Sstevel@tonic-gate 	if (!(MD_MNSET_REC(sr)))
14670Sstevel@tonic-gate 		sdssc_cm_sr_nm2nid(sr);
14680Sstevel@tonic-gate 
14690Sstevel@tonic-gate 	/* Send down to kernel the data in mddb USER set record */
14700Sstevel@tonic-gate 	if (inc_genid)
14710Sstevel@tonic-gate 		sr->sr_genid++;
14720Sstevel@tonic-gate 	(void) memset(&req, 0, sizeof (req));
14730Sstevel@tonic-gate 	METAD_SETUP_SR(MD_DB_SETDATA, sr->sr_selfid)
14740Sstevel@tonic-gate 	if (MD_MNSET_REC(sr)) {
14750Sstevel@tonic-gate 		req.ur_size = sizeof (*mnsr);
14760Sstevel@tonic-gate 	} else {
14770Sstevel@tonic-gate 		req.ur_size = sizeof (*sr);
14780Sstevel@tonic-gate 	}
14790Sstevel@tonic-gate 	req.ur_data = (uintptr_t)sr;
14800Sstevel@tonic-gate 	if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL) != 0) {
14810Sstevel@tonic-gate 		(void) mdstealerror(ep, &req.ur_mde);
14820Sstevel@tonic-gate 		return;
14830Sstevel@tonic-gate 	}
14840Sstevel@tonic-gate 
14850Sstevel@tonic-gate 	/*
14860Sstevel@tonic-gate 	 * Walk through the drive records associated with this set record
14870Sstevel@tonic-gate 	 * and send down to kernel the data in mddb USER drive record.
14880Sstevel@tonic-gate 	 */
14890Sstevel@tonic-gate 	drc = 0;
14900Sstevel@tonic-gate 	dr = sr->sr_drivechain;
14910Sstevel@tonic-gate 	while (dr) {
14920Sstevel@tonic-gate 		if (inc_genid)
14930Sstevel@tonic-gate 			dr->dr_genid++;
14940Sstevel@tonic-gate 		METAD_SETUP_DR(MD_DB_SETDATA, dr->dr_selfid)
14950Sstevel@tonic-gate 		req.ur_size = sizeof (*dr);
14960Sstevel@tonic-gate 		req.ur_data = (uintptr_t)dr;
14970Sstevel@tonic-gate 		if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL) != 0) {
14980Sstevel@tonic-gate 			(void) mdstealerror(ep, &req.ur_mde);
14990Sstevel@tonic-gate 			return;
15000Sstevel@tonic-gate 		}
15010Sstevel@tonic-gate 		drc++;
15020Sstevel@tonic-gate 		dr = dr->dr_next;
15030Sstevel@tonic-gate 	}
15040Sstevel@tonic-gate 
15050Sstevel@tonic-gate 
15060Sstevel@tonic-gate 	/*
15070Sstevel@tonic-gate 	 * If this set is a multi-node set -
15080Sstevel@tonic-gate 	 * walk through the node records associated with this set record
15090Sstevel@tonic-gate 	 * and send down to kernel the data in mddb USER node record.
15100Sstevel@tonic-gate 	 */
15110Sstevel@tonic-gate 	nrc = 0;
15120Sstevel@tonic-gate 	if (MD_MNSET_REC(sr)) {
15130Sstevel@tonic-gate 		mnsr = (struct md_mnset_record *)sr;
15140Sstevel@tonic-gate 		nr = mnsr->sr_nodechain;
15150Sstevel@tonic-gate 		while (nr) {
15160Sstevel@tonic-gate 			if (inc_genid)
15170Sstevel@tonic-gate 				nr->nr_genid++;
15180Sstevel@tonic-gate 			METAD_SETUP_NR(MD_DB_SETDATA, nr->nr_selfid)
15190Sstevel@tonic-gate 			req.ur_size = sizeof (*nr);
152062Sjeanm 			req.ur_data = (uint64_t)(uintptr_t)nr;
15210Sstevel@tonic-gate 			if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL)
15220Sstevel@tonic-gate 			    != 0) {
15230Sstevel@tonic-gate 				(void) mdstealerror(ep, &req.ur_mde);
15240Sstevel@tonic-gate 				return;
15250Sstevel@tonic-gate 			}
15260Sstevel@tonic-gate 			nrc++;
15270Sstevel@tonic-gate 			nr = nr->nr_next;
15280Sstevel@tonic-gate 		}
15290Sstevel@tonic-gate 	}
15300Sstevel@tonic-gate 
15310Sstevel@tonic-gate 	/*
15320Sstevel@tonic-gate 	 * Set up list of mddb USER recids containing set and drive records
15330Sstevel@tonic-gate 	 * and node records if a MNset.
15340Sstevel@tonic-gate 	 */
15350Sstevel@tonic-gate 	rc = 0;
15360Sstevel@tonic-gate 	size = (nrc + drc + 2) * sizeof (int);
15370Sstevel@tonic-gate 	recs = Zalloc(size);
15380Sstevel@tonic-gate 	/* First recid in list is the set record's id */
15390Sstevel@tonic-gate 	recs[rc] = sr->sr_selfid;
15400Sstevel@tonic-gate 	rc++;
15410Sstevel@tonic-gate 	dr = sr->sr_drivechain;
15420Sstevel@tonic-gate 	while (dr) {
15430Sstevel@tonic-gate 		/* Now, fill in the drive record ids */
15440Sstevel@tonic-gate 		recs[rc] = dr->dr_selfid;
15450Sstevel@tonic-gate 		dr = dr->dr_next;
15460Sstevel@tonic-gate 		rc++;
15470Sstevel@tonic-gate 	}
15480Sstevel@tonic-gate 	if (MD_MNSET_REC(sr)) {
15490Sstevel@tonic-gate 		nr = mnsr->sr_nodechain;
15500Sstevel@tonic-gate 		while (nr) {
15510Sstevel@tonic-gate 			/* If a MNset, fill in the node record ids */
15520Sstevel@tonic-gate 			recs[rc] = nr->nr_selfid;
15530Sstevel@tonic-gate 			nr = nr->nr_next;
15540Sstevel@tonic-gate 			rc++;
15550Sstevel@tonic-gate 		}
15560Sstevel@tonic-gate 	}
15570Sstevel@tonic-gate 	/* Set last record to null recid */
15580Sstevel@tonic-gate 	recs[rc] = 0;
15590Sstevel@tonic-gate 
15600Sstevel@tonic-gate 	/* Write out the set and drive and node records to the local mddb */
15610Sstevel@tonic-gate 	METAD_SETUP_UR(MD_DB_COMMIT_MANY, 0, 0);
15620Sstevel@tonic-gate 	req.ur_size = size;
15630Sstevel@tonic-gate 	req.ur_data = (uintptr_t)recs;
15640Sstevel@tonic-gate 	if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL) != 0) {
15650Sstevel@tonic-gate 		(void) mdstealerror(ep, &req.ur_mde);
15660Sstevel@tonic-gate 		return;
15670Sstevel@tonic-gate 	}
15680Sstevel@tonic-gate 
15690Sstevel@tonic-gate 	/*
15700Sstevel@tonic-gate 	 * Cluster nodename support
15710Sstevel@tonic-gate 	 * Convert nodeid -> nodename
15720Sstevel@tonic-gate 	 * Don't do this for MN disksets since we've already stored
15730Sstevel@tonic-gate 	 * both the nodeid and name.
15740Sstevel@tonic-gate 	 */
15750Sstevel@tonic-gate 	if (!(MD_MNSET_REC(sr)))
15760Sstevel@tonic-gate 		sdssc_cm_sr_nid2nm(sr);
15770Sstevel@tonic-gate 
15780Sstevel@tonic-gate 	Free(recs);
15790Sstevel@tonic-gate }
15800Sstevel@tonic-gate 
15810Sstevel@tonic-gate /*
15820Sstevel@tonic-gate  * This routine only handles returns a md_set_record structure even
15830Sstevel@tonic-gate  * if the set record describes a MN set.  This will allow pre-MN
15840Sstevel@tonic-gate  * SVM RPC code to access a MN set record and to display it.
15850Sstevel@tonic-gate  *
15860Sstevel@tonic-gate  * The MN SVM RPC code detects if the set record returned describes
15870Sstevel@tonic-gate  * a MN set and then will copy it using mnsetdup.
15880Sstevel@tonic-gate  */
15890Sstevel@tonic-gate md_set_record *
setdup(md_set_record * sr)15900Sstevel@tonic-gate setdup(md_set_record *sr)
15910Sstevel@tonic-gate {
15920Sstevel@tonic-gate 	md_set_record		*tsr = NULL;
15930Sstevel@tonic-gate 	md_drive_record		**tdrpp = NULL;
15940Sstevel@tonic-gate 
15950Sstevel@tonic-gate 	if (sr && (tsr = Malloc(sizeof (*sr))) != NULL) {
15960Sstevel@tonic-gate 		(void) memmove(tsr, sr, sizeof (*sr));
15970Sstevel@tonic-gate 		tsr->sr_next = NULL;
15980Sstevel@tonic-gate 		tdrpp = &tsr->sr_drivechain;
15990Sstevel@tonic-gate 		while (*tdrpp) {
16000Sstevel@tonic-gate 			*tdrpp = drdup(*tdrpp);
16010Sstevel@tonic-gate 			tdrpp = &(*tdrpp)->dr_next;
16020Sstevel@tonic-gate 		}
16030Sstevel@tonic-gate 	}
16040Sstevel@tonic-gate 	return (tsr);
16050Sstevel@tonic-gate }
16060Sstevel@tonic-gate 
16070Sstevel@tonic-gate /*
16080Sstevel@tonic-gate  * This routine only copies MN set records.   If a non-MN set
16090Sstevel@tonic-gate  * record was passed in NULL pointer will be returned.
16100Sstevel@tonic-gate  */
16110Sstevel@tonic-gate md_mnset_record *
mnsetdup(md_mnset_record * mnsr)16120Sstevel@tonic-gate mnsetdup(md_mnset_record *mnsr)
16130Sstevel@tonic-gate {
16140Sstevel@tonic-gate 	md_mnset_record		*tmnsr = NULL;
16150Sstevel@tonic-gate 	md_drive_record		**tdrpp = NULL;
16160Sstevel@tonic-gate 	md_mnnode_record	**tnrpp = NULL;
16170Sstevel@tonic-gate 
16180Sstevel@tonic-gate 	if (!MD_MNSET_REC(mnsr)) {
16190Sstevel@tonic-gate 		return (NULL);
16200Sstevel@tonic-gate 	}
16210Sstevel@tonic-gate 
16220Sstevel@tonic-gate 	if (mnsr && (tmnsr = Malloc(sizeof (*mnsr))) != NULL) {
16230Sstevel@tonic-gate 		(void) memmove(tmnsr, mnsr, sizeof (*mnsr));
16240Sstevel@tonic-gate 		tmnsr->sr_next = NULL;
16250Sstevel@tonic-gate 		tdrpp = &tmnsr->sr_drivechain;
16260Sstevel@tonic-gate 		while (*tdrpp) {
16270Sstevel@tonic-gate 			*tdrpp = drdup(*tdrpp);
16280Sstevel@tonic-gate 			tdrpp = &(*tdrpp)->dr_next;
16290Sstevel@tonic-gate 		}
16300Sstevel@tonic-gate 		tnrpp = &tmnsr->sr_nodechain;
16310Sstevel@tonic-gate 		while (*tnrpp) {
16320Sstevel@tonic-gate 			*tnrpp = nrdup(*tnrpp);
16330Sstevel@tonic-gate 			tnrpp = &(*tnrpp)->nr_next;
16340Sstevel@tonic-gate 		}
16350Sstevel@tonic-gate 	}
16360Sstevel@tonic-gate 	return (tmnsr);
16370Sstevel@tonic-gate }
16380Sstevel@tonic-gate 
16390Sstevel@tonic-gate md_drive_record *
drdup(md_drive_record * dr)16400Sstevel@tonic-gate drdup(md_drive_record *dr)
16410Sstevel@tonic-gate {
16420Sstevel@tonic-gate 	md_drive_record		*tdr = NULL;
16430Sstevel@tonic-gate 
16440Sstevel@tonic-gate 	if (dr && (tdr = Malloc(sizeof (*dr))) != NULL)
16450Sstevel@tonic-gate 		(void) memmove(tdr, dr, sizeof (*dr));
16460Sstevel@tonic-gate 	return (tdr);
16470Sstevel@tonic-gate }
16480Sstevel@tonic-gate 
16490Sstevel@tonic-gate md_mnnode_record *
nrdup(md_mnnode_record * nr)16500Sstevel@tonic-gate nrdup(md_mnnode_record *nr)
16510Sstevel@tonic-gate {
16520Sstevel@tonic-gate 	md_mnnode_record	*tnr = NULL;
16530Sstevel@tonic-gate 
16540Sstevel@tonic-gate 	if (nr && (tnr = Malloc(sizeof (*nr))) != NULL)
16550Sstevel@tonic-gate 		(void) memmove(tnr, nr, sizeof (*nr));
16560Sstevel@tonic-gate 	return (tnr);
16570Sstevel@tonic-gate }
16580Sstevel@tonic-gate 
16590Sstevel@tonic-gate /*
16600Sstevel@tonic-gate  * Duplicate parts of the drive decriptor list for this node.
16610Sstevel@tonic-gate  * Only duplicate the drive name string in the mddrivename structure, don't
16620Sstevel@tonic-gate  * need to copy any other pointers since only interested in the flags and
16630Sstevel@tonic-gate  * the drive name (i.e. other pointers will be set to NULL).
16640Sstevel@tonic-gate  *	Returns NULL if failure due to Malloc failure.
16650Sstevel@tonic-gate  *	Returns pointer (non-NULL) to dup'd list if successful.
16660Sstevel@tonic-gate  */
16670Sstevel@tonic-gate md_drive_desc *
dd_list_dup(md_drive_desc * dd)16680Sstevel@tonic-gate dd_list_dup(md_drive_desc *dd)
16690Sstevel@tonic-gate {
16700Sstevel@tonic-gate 	md_drive_desc	*orig_dd;
16710Sstevel@tonic-gate 	md_drive_desc	*copy_dd = NULL, *copy_dd_prev = NULL;
16720Sstevel@tonic-gate 	md_drive_desc	*copy_dd_head = NULL;
16730Sstevel@tonic-gate 	mddrivename_t	*copy_dnp;
16740Sstevel@tonic-gate 	char		*copy_cname;
16750Sstevel@tonic-gate 	char		*copy_devid;
16760Sstevel@tonic-gate 
16770Sstevel@tonic-gate 	if (dd == NULL)
16780Sstevel@tonic-gate 		return (NULL);
16790Sstevel@tonic-gate 
16800Sstevel@tonic-gate 	orig_dd = dd;
16810Sstevel@tonic-gate 
16820Sstevel@tonic-gate 	while (orig_dd) {
16830Sstevel@tonic-gate 		copy_dd = Zalloc(sizeof (*copy_dd));
16840Sstevel@tonic-gate 		copy_dnp = Zalloc(sizeof (mddrivename_t));
16850Sstevel@tonic-gate 		copy_cname = Zalloc(sizeof (orig_dd->dd_dnp->cname));
16860Sstevel@tonic-gate 		if (orig_dd->dd_dnp->devid) {
16870Sstevel@tonic-gate 			copy_devid = Zalloc(sizeof (orig_dd->dd_dnp->devid));
16880Sstevel@tonic-gate 		} else {
16890Sstevel@tonic-gate 			copy_devid = NULL;
16900Sstevel@tonic-gate 		}
16910Sstevel@tonic-gate 		copy_dd->dd_next = NULL;
16920Sstevel@tonic-gate 		if ((copy_dd == NULL) || (copy_dnp == NULL) ||
16930Sstevel@tonic-gate 		    (copy_cname == NULL)) {
16940Sstevel@tonic-gate 			while (copy_dd_head) {
16950Sstevel@tonic-gate 				copy_dd = copy_dd_head->dd_next;
16960Sstevel@tonic-gate 				Free(copy_dd_head);
16970Sstevel@tonic-gate 				copy_dd_head = copy_dd;
16980Sstevel@tonic-gate 			}
16990Sstevel@tonic-gate 			if (copy_dnp)
17000Sstevel@tonic-gate 				Free(copy_dnp);
17010Sstevel@tonic-gate 			if (copy_dd)
17020Sstevel@tonic-gate 				Free(copy_dd);
17030Sstevel@tonic-gate 			if (copy_cname)
17040Sstevel@tonic-gate 				Free(copy_cname);
17050Sstevel@tonic-gate 			if (copy_devid)
17060Sstevel@tonic-gate 				Free(copy_devid);
17070Sstevel@tonic-gate 			return (NULL);
17080Sstevel@tonic-gate 		}
17090Sstevel@tonic-gate 		(void) memmove(copy_dd, orig_dd, sizeof (*orig_dd));
17100Sstevel@tonic-gate 		(void) strlcpy(copy_cname, orig_dd->dd_dnp->cname,
17110Sstevel@tonic-gate 		    sizeof (orig_dd->dd_dnp->cname));
17120Sstevel@tonic-gate 		copy_dd->dd_next = NULL;
17130Sstevel@tonic-gate 		copy_dd->dd_dnp = copy_dnp;
17140Sstevel@tonic-gate 		copy_dd->dd_dnp->cname = copy_cname;
17150Sstevel@tonic-gate 		if (copy_devid) {
17160Sstevel@tonic-gate 			(void) strlcpy(copy_devid, orig_dd->dd_dnp->devid,
17170Sstevel@tonic-gate 			    sizeof (orig_dd->dd_dnp->devid));
17180Sstevel@tonic-gate 		}
17190Sstevel@tonic-gate 
17200Sstevel@tonic-gate 		if (copy_dd_prev == NULL) {
17210Sstevel@tonic-gate 			copy_dd_head = copy_dd;
17220Sstevel@tonic-gate 			copy_dd_prev = copy_dd;
17230Sstevel@tonic-gate 		} else {
17240Sstevel@tonic-gate 			copy_dd_prev->dd_next = copy_dd;
17250Sstevel@tonic-gate 			copy_dd_prev = copy_dd;
17260Sstevel@tonic-gate 		}
17270Sstevel@tonic-gate 		orig_dd = orig_dd->dd_next;
17280Sstevel@tonic-gate 	}
17290Sstevel@tonic-gate 	copy_dd->dd_next = NULL;
17300Sstevel@tonic-gate 	return (copy_dd_head);
17310Sstevel@tonic-gate }
17320Sstevel@tonic-gate 
17330Sstevel@tonic-gate void
sr_cache_flush(int flushnames)17340Sstevel@tonic-gate sr_cache_flush(int flushnames)
17350Sstevel@tonic-gate {
17360Sstevel@tonic-gate 	md_set_record	*sr, *tsr;
17370Sstevel@tonic-gate 	md_mnset_record	*mnsr;
17380Sstevel@tonic-gate 	md_drive_record *dr, *tdr;
17390Sstevel@tonic-gate 	md_mnnode_record *nr, *tnr;
17400Sstevel@tonic-gate 
17410Sstevel@tonic-gate 	sr = tsr = setrecords;
17420Sstevel@tonic-gate 	while (sr != NULL) {
17430Sstevel@tonic-gate 		dr = tdr = sr->sr_drivechain;
17440Sstevel@tonic-gate 		while (dr != NULL) {
17450Sstevel@tonic-gate 			tdr = dr;
17460Sstevel@tonic-gate 			dr = dr->dr_next;
17470Sstevel@tonic-gate 			Free(tdr);
17480Sstevel@tonic-gate 		}
17490Sstevel@tonic-gate 		tsr = sr;
17500Sstevel@tonic-gate 		sr = sr->sr_next;
17510Sstevel@tonic-gate 		if (MD_MNSET_REC(tsr)) {
17520Sstevel@tonic-gate 			mnsr = (struct md_mnset_record *)tsr;
17530Sstevel@tonic-gate 			nr = tnr = mnsr->sr_nodechain;
17540Sstevel@tonic-gate 			while (nr != NULL) {
17550Sstevel@tonic-gate 				tnr = nr;
17560Sstevel@tonic-gate 				nr = nr->nr_next;
17570Sstevel@tonic-gate 				Free(tnr);
17580Sstevel@tonic-gate 			}
17590Sstevel@tonic-gate 			Free(mnsr);
17600Sstevel@tonic-gate 		} else {
17610Sstevel@tonic-gate 			Free(tsr);
17620Sstevel@tonic-gate 		}
17630Sstevel@tonic-gate 	}
17640Sstevel@tonic-gate 
17650Sstevel@tonic-gate 	setrecords = NULL;
17660Sstevel@tonic-gate 
17670Sstevel@tonic-gate 	setsnarfdone = 0;
17680Sstevel@tonic-gate 
17690Sstevel@tonic-gate 	/* This will cause the other caches to be cleared */
17700Sstevel@tonic-gate 	if (flushnames)
17710Sstevel@tonic-gate 		metaflushnames(0);
17720Sstevel@tonic-gate }
17730Sstevel@tonic-gate 
17740Sstevel@tonic-gate void
sr_cache_flush_setno(set_t setno)17750Sstevel@tonic-gate sr_cache_flush_setno(set_t setno)
17760Sstevel@tonic-gate {
17770Sstevel@tonic-gate 	md_set_record	*sr, *tsr;
17780Sstevel@tonic-gate 	md_mnset_record	*mnsr;
17790Sstevel@tonic-gate 	md_drive_record *dr, *tdr;
17800Sstevel@tonic-gate 
17810Sstevel@tonic-gate 	assert(setsnarfdone != 0);
17820Sstevel@tonic-gate 
17830Sstevel@tonic-gate 	for (sr = tsr = setrecords; sr; tsr = sr, sr = sr->sr_next) {
17840Sstevel@tonic-gate 		if (sr->sr_setno != setno)
17850Sstevel@tonic-gate 			continue;
17860Sstevel@tonic-gate 
17870Sstevel@tonic-gate 		dr = tdr = sr->sr_drivechain;
17880Sstevel@tonic-gate 		while (dr != NULL) {
17890Sstevel@tonic-gate 			tdr = dr;
17900Sstevel@tonic-gate 			dr = dr->dr_next;
17910Sstevel@tonic-gate 			Free(tdr);
17920Sstevel@tonic-gate 		}
17930Sstevel@tonic-gate 		if (sr == setrecords)
17940Sstevel@tonic-gate 			setrecords = sr->sr_next;
17950Sstevel@tonic-gate 		else
17960Sstevel@tonic-gate 			tsr->sr_next = sr->sr_next;
17970Sstevel@tonic-gate 		if (MD_MNSET_REC(sr)) {
17980Sstevel@tonic-gate 			mnsr = (struct md_mnset_record *)sr;
17990Sstevel@tonic-gate 			Free(mnsr);
18000Sstevel@tonic-gate 		} else {
18010Sstevel@tonic-gate 			Free(sr);
18020Sstevel@tonic-gate 		}
18030Sstevel@tonic-gate 		break;
18040Sstevel@tonic-gate 	}
18050Sstevel@tonic-gate 
18060Sstevel@tonic-gate 	setsnarfdone = 0;
18070Sstevel@tonic-gate 
18080Sstevel@tonic-gate 	/* This will cause the other caches to be cleared */
18090Sstevel@tonic-gate 	metaflushnames(0);
18100Sstevel@tonic-gate }
18110Sstevel@tonic-gate 
18120Sstevel@tonic-gate int
s_ownset(set_t setno,md_error_t * ep)18130Sstevel@tonic-gate s_ownset(set_t setno, md_error_t *ep)
18140Sstevel@tonic-gate {
18150Sstevel@tonic-gate 	mddb_ownset_t		ownset_arg;
18160Sstevel@tonic-gate 
18170Sstevel@tonic-gate 	ownset_arg.setno = setno;
18180Sstevel@tonic-gate 	ownset_arg.owns_set = MD_SETOWNER_NONE;
18190Sstevel@tonic-gate 
18200Sstevel@tonic-gate 	if (metaioctl(MD_DB_OWNSET, &ownset_arg, ep, NULL) != 0)
18210Sstevel@tonic-gate 		return (0);
18220Sstevel@tonic-gate 
18230Sstevel@tonic-gate 	return (ownset_arg.owns_set);
18240Sstevel@tonic-gate }
18250Sstevel@tonic-gate 
18260Sstevel@tonic-gate void
s_delset(char * setname,md_error_t * ep)18270Sstevel@tonic-gate s_delset(char *setname, md_error_t *ep)
18280Sstevel@tonic-gate {
18290Sstevel@tonic-gate 	md_set_record		*sr;
18300Sstevel@tonic-gate 	md_set_record		*tsr;
18310Sstevel@tonic-gate 	md_drive_record		*dr;
18320Sstevel@tonic-gate 	md_drive_record		*tdr;
18330Sstevel@tonic-gate 	md_mnnode_record	*nr, *tnr;
18340Sstevel@tonic-gate 	mddb_userreq_t		req;
18350Sstevel@tonic-gate 	char			stringbuf[100];
18360Sstevel@tonic-gate 	int			i;
18370Sstevel@tonic-gate 	mdsetname_t		*sp = NULL;
18380Sstevel@tonic-gate 	mddrivename_t		*dn = NULL;
18390Sstevel@tonic-gate 	mdname_t		*np = NULL;
18400Sstevel@tonic-gate 	md_dev64_t		dev;
18410Sstevel@tonic-gate 	side_t			myside = MD_SIDEWILD;
18420Sstevel@tonic-gate 	md_error_t		xep = mdnullerror;
18430Sstevel@tonic-gate 	md_mnset_record		*mnsr;
18440Sstevel@tonic-gate 	int			num_sets = 0;
18450Sstevel@tonic-gate 	int			num_mn_sets = 0;
18460Sstevel@tonic-gate 
18470Sstevel@tonic-gate 	(void) memset(&req, 0, sizeof (mddb_userreq_t));
18480Sstevel@tonic-gate 
18490Sstevel@tonic-gate 	if ((sr = getsetbyname(setname, ep)) == NULL)
18500Sstevel@tonic-gate 		return;
18510Sstevel@tonic-gate 
18520Sstevel@tonic-gate 	sp = metasetnosetname(sr->sr_setno, &xep);
18530Sstevel@tonic-gate 	mdclrerror(&xep);
18540Sstevel@tonic-gate 
18550Sstevel@tonic-gate 	if (MD_MNSET_REC(sr)) {
18560Sstevel@tonic-gate 		/*
18570Sstevel@tonic-gate 		 * If this node is a set owner, halt the set before
18580Sstevel@tonic-gate 		 * deleting the set records.  Ignore any errors since
18590Sstevel@tonic-gate 		 * s_ownset and halt_set could fail if panic had occurred
18600Sstevel@tonic-gate 		 * during the add/delete of a node.
18610Sstevel@tonic-gate 		 */
18620Sstevel@tonic-gate 		if (s_ownset(sr->sr_setno, &xep)) {
18630Sstevel@tonic-gate 			mdclrerror(&xep);
18640Sstevel@tonic-gate 			if (halt_set(sp, &xep))
18650Sstevel@tonic-gate 				mdclrerror(&xep);
18660Sstevel@tonic-gate 		}
18670Sstevel@tonic-gate 	}
18680Sstevel@tonic-gate 
18690Sstevel@tonic-gate 	(void) snprintf(stringbuf, sizeof (stringbuf), "/dev/md/%s", setname);
18700Sstevel@tonic-gate 	(void) unlink(stringbuf);
18710Sstevel@tonic-gate 	(void) unlink(meta_lock_name(sr->sr_setno));
18720Sstevel@tonic-gate 
18730Sstevel@tonic-gate 	if (MD_MNSET_REC(sr)) {
18740Sstevel@tonic-gate 		mnsr = (struct md_mnset_record *)sr;
18750Sstevel@tonic-gate 		nr = mnsr->sr_nodechain;
18760Sstevel@tonic-gate 		while (nr) {
18770Sstevel@tonic-gate 			/* Setting myside for later use */
18780Sstevel@tonic-gate 			if (strcmp(mynode(), nr->nr_nodename) == 0)
18790Sstevel@tonic-gate 				myside = nr->nr_nodeid;
18800Sstevel@tonic-gate 
18810Sstevel@tonic-gate 			(void) memset(&req, 0, sizeof (req));
18820Sstevel@tonic-gate 			METAD_SETUP_NR(MD_DB_DELETE, nr->nr_selfid)
18830Sstevel@tonic-gate 			if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde,
18840Sstevel@tonic-gate 			    NULL) != 0) {
18850Sstevel@tonic-gate 				(void) mdstealerror(ep, &req.ur_mde);
18860Sstevel@tonic-gate 				free_sr(sr);
18870Sstevel@tonic-gate 				return;
18880Sstevel@tonic-gate 			}
18890Sstevel@tonic-gate 			tnr = nr;
18900Sstevel@tonic-gate 			nr = nr->nr_next;
18910Sstevel@tonic-gate 
18920Sstevel@tonic-gate 			SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_REMOVE, SVM_TAG_HOST,
18930Sstevel@tonic-gate 			    sr->sr_setno, tnr->nr_nodeid);
18940Sstevel@tonic-gate 
18950Sstevel@tonic-gate 			mnnr_cache_del((struct md_mnset_record *)sr,
18960Sstevel@tonic-gate 			    tnr->nr_selfid);
18970Sstevel@tonic-gate 		}
18980Sstevel@tonic-gate 	} else {
18990Sstevel@tonic-gate 		for (i = 0; i < MD_MAXSIDES; i++) {
19000Sstevel@tonic-gate 			/* Skip empty slots */
19010Sstevel@tonic-gate 			if (sr->sr_nodes[i][0] == '\0')
19020Sstevel@tonic-gate 				continue;
19030Sstevel@tonic-gate 
19040Sstevel@tonic-gate 			if (strcmp(mynode(), sr->sr_nodes[i]) == 0)
19050Sstevel@tonic-gate 				myside = i;
19060Sstevel@tonic-gate 
19070Sstevel@tonic-gate 			SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_REMOVE, SVM_TAG_HOST,
19080Sstevel@tonic-gate 			    sr->sr_setno, i);
19090Sstevel@tonic-gate 		}
19100Sstevel@tonic-gate 	}
19110Sstevel@tonic-gate 
19120Sstevel@tonic-gate 	dr = sr->sr_drivechain;
19130Sstevel@tonic-gate 	while (dr) {
19140Sstevel@tonic-gate 		(void) memset(&req, 0, sizeof (req));
19150Sstevel@tonic-gate 		METAD_SETUP_DR(MD_DB_DELETE, dr->dr_selfid)
19160Sstevel@tonic-gate 		if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL) != 0) {
19170Sstevel@tonic-gate 			(void) mdstealerror(ep, &req.ur_mde);
19180Sstevel@tonic-gate 			free_sr(sr);
19190Sstevel@tonic-gate 			return;
19200Sstevel@tonic-gate 		}
19210Sstevel@tonic-gate 		tdr = dr;
19220Sstevel@tonic-gate 		dr = dr->dr_next;
19230Sstevel@tonic-gate 
19240Sstevel@tonic-gate 		dev = NODEV64;
19250Sstevel@tonic-gate 		if (myside != MD_SIDEWILD && sp != NULL) {
19260Sstevel@tonic-gate 			dn = metadrivename_withdrkey(sp, myside,
19270Sstevel@tonic-gate 			    tdr->dr_key, MD_BASICNAME_OK, &xep);
19280Sstevel@tonic-gate 			if (dn != NULL) {
19290Sstevel@tonic-gate 				uint_t	rep_slice;
19300Sstevel@tonic-gate 
19310Sstevel@tonic-gate 				np = NULL;
19320Sstevel@tonic-gate 				if (meta_replicaslice(dn, &rep_slice,
19330Sstevel@tonic-gate 				    &xep) == 0) {
19340Sstevel@tonic-gate 					np = metaslicename(dn, rep_slice, &xep);
19350Sstevel@tonic-gate 				}
19360Sstevel@tonic-gate 
19370Sstevel@tonic-gate 				if (np != NULL)
19380Sstevel@tonic-gate 					dev = np->dev;
19390Sstevel@tonic-gate 				else
19400Sstevel@tonic-gate 					mdclrerror(&xep);
19410Sstevel@tonic-gate 			} else
19420Sstevel@tonic-gate 				mdclrerror(&xep);
19430Sstevel@tonic-gate 		} else
19440Sstevel@tonic-gate 			mdclrerror(&xep);
19450Sstevel@tonic-gate 
19460Sstevel@tonic-gate 		SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_REMOVE, SVM_TAG_DRIVE,
19470Sstevel@tonic-gate 		    sr->sr_setno, dev);
19480Sstevel@tonic-gate 		SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_ADD, SVM_TAG_DRIVE,
19490Sstevel@tonic-gate 		    MD_LOCAL_SET, dev);
19500Sstevel@tonic-gate 
19510Sstevel@tonic-gate 		dr_cache_del(sr, tdr->dr_selfid);
19520Sstevel@tonic-gate 
19530Sstevel@tonic-gate 	}
19540Sstevel@tonic-gate 
19550Sstevel@tonic-gate 	(void) memset(&req, 0, sizeof (req));
19560Sstevel@tonic-gate 	METAD_SETUP_SR(MD_DB_DELETE, sr->sr_selfid)
19570Sstevel@tonic-gate 	if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL) != 0) {
19580Sstevel@tonic-gate 		(void) mdstealerror(ep, &req.ur_mde);
19590Sstevel@tonic-gate 		free_sr(sr);
19600Sstevel@tonic-gate 		return;
19610Sstevel@tonic-gate 	}
19620Sstevel@tonic-gate 
19630Sstevel@tonic-gate 	SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_DELETE, SVM_TAG_SET, sr->sr_setno,
19640Sstevel@tonic-gate 	    NODEV64);
19650Sstevel@tonic-gate 
19660Sstevel@tonic-gate 	for (tsr = setrecords; tsr; tsr = tsr->sr_next) {
19670Sstevel@tonic-gate 		if (tsr == sr)
19680Sstevel@tonic-gate 			continue;
19690Sstevel@tonic-gate 
19700Sstevel@tonic-gate 		num_sets++;
19710Sstevel@tonic-gate 		if (MD_MNSET_REC(tsr))
19720Sstevel@tonic-gate 			num_mn_sets++;
19730Sstevel@tonic-gate 	}
19740Sstevel@tonic-gate 
19750Sstevel@tonic-gate 	if (num_mn_sets == 0)
19762063Shshaw 		(void) meta_smf_disable(META_SMF_MN_DISKSET, NULL);
19770Sstevel@tonic-gate 
19780Sstevel@tonic-gate 	/* The set we just deleted is the only one left */
19790Sstevel@tonic-gate 	if (num_sets == 0)
19802063Shshaw 		(void) meta_smf_disable(META_SMF_DISKSET, NULL);
19810Sstevel@tonic-gate 
19820Sstevel@tonic-gate 	sr_cache_del(sr->sr_selfid);
19830Sstevel@tonic-gate 	free_sr(sr);
19840Sstevel@tonic-gate 
19850Sstevel@tonic-gate }
19860Sstevel@tonic-gate 
19870Sstevel@tonic-gate void
s_delrec(mddb_recid_t recid,md_error_t * ep)19880Sstevel@tonic-gate s_delrec(mddb_recid_t recid, md_error_t *ep)
19890Sstevel@tonic-gate {
19900Sstevel@tonic-gate 	mddb_userreq_t		req;
19910Sstevel@tonic-gate 
19920Sstevel@tonic-gate 	(void) memset(&req, 0, sizeof (req));
19930Sstevel@tonic-gate 
19940Sstevel@tonic-gate 	METAD_SETUP_SR(MD_DB_DELETE, recid)
19950Sstevel@tonic-gate 
19960Sstevel@tonic-gate 	if (metaioctl(MD_DB_USERREQ, &req, &req.ur_mde, NULL) != 0)
19970Sstevel@tonic-gate 		(void) mdstealerror(ep, &req.ur_mde);
19980Sstevel@tonic-gate }
19990Sstevel@tonic-gate 
20000Sstevel@tonic-gate /*
20010Sstevel@tonic-gate  * resnarf the imported set
20020Sstevel@tonic-gate  */
20030Sstevel@tonic-gate int
resnarf_set(set_t setno,md_error_t * ep)20040Sstevel@tonic-gate resnarf_set(
20050Sstevel@tonic-gate 	set_t			setno,
20060Sstevel@tonic-gate 	md_error_t		*ep
20070Sstevel@tonic-gate )
20080Sstevel@tonic-gate {
20090Sstevel@tonic-gate 	md_set_record	*sr;
20100Sstevel@tonic-gate 	md_drive_record	*dr;
20110Sstevel@tonic-gate 	mddb_recid_t	id, *p;
20120Sstevel@tonic-gate 
20130Sstevel@tonic-gate 	if (meta_setup_db_locations(ep) != 0) {
20140Sstevel@tonic-gate 		if (! mdismddberror(ep, MDE_DB_STALE))
20150Sstevel@tonic-gate 			return (-1);
20160Sstevel@tonic-gate 		mdclrerror(ep);
20170Sstevel@tonic-gate 	}
20180Sstevel@tonic-gate 
20190Sstevel@tonic-gate 	setsnarfdone = 1;
20200Sstevel@tonic-gate 
20210Sstevel@tonic-gate 	id = 0;
20220Sstevel@tonic-gate 	while ((sr = get_ur_rec(MD_LOCAL_SET, MD_UR_GET_NEXT, MDDB_UR_SR, &id,
20230Sstevel@tonic-gate 	    ep)) != NULL) {
20240Sstevel@tonic-gate 
20250Sstevel@tonic-gate 		if (sr->sr_setno != setno)
20260Sstevel@tonic-gate 			continue;
20270Sstevel@tonic-gate 
20280Sstevel@tonic-gate 		/* Don't allow resnarf of a multi-node diskset */
20290Sstevel@tonic-gate 		if (MD_MNSET_REC(sr))
20300Sstevel@tonic-gate 			goto out;
20310Sstevel@tonic-gate 
20320Sstevel@tonic-gate 		sr->sr_next = NULL;
20330Sstevel@tonic-gate 		sr->sr_drivechain = NULL;
20340Sstevel@tonic-gate 
20350Sstevel@tonic-gate 		if (md_in_daemon)
20360Sstevel@tonic-gate 			url_addl(&url_used, sr->sr_selfid);
20370Sstevel@tonic-gate 
20380Sstevel@tonic-gate 		sr->sr_flags |= MD_SR_CHECK;
20390Sstevel@tonic-gate 
20400Sstevel@tonic-gate 		sr_cache_add(sr);
20410Sstevel@tonic-gate 
20420Sstevel@tonic-gate 		if (sr->sr_driverec == 0)
20430Sstevel@tonic-gate 			break;
20440Sstevel@tonic-gate 
20450Sstevel@tonic-gate 		p = &sr->sr_driverec;
20460Sstevel@tonic-gate 		while ((dr = get_ur_rec(MD_LOCAL_SET, MD_UR_GET_WKEY,
20470Sstevel@tonic-gate 		    MDDB_UR_DR, p, ep)) != NULL) {
20480Sstevel@tonic-gate 			dr->dr_next = NULL;
20490Sstevel@tonic-gate 
20500Sstevel@tonic-gate 			if (md_in_daemon)
20510Sstevel@tonic-gate 				url_addl(&url_used, dr->dr_selfid);
20520Sstevel@tonic-gate 
20530Sstevel@tonic-gate 			dr_cache_add(sr, dr);
20540Sstevel@tonic-gate 
20550Sstevel@tonic-gate 			if (dr->dr_nextrec == 0)
20560Sstevel@tonic-gate 				break;
20570Sstevel@tonic-gate 
20580Sstevel@tonic-gate 			p = &dr->dr_nextrec;
20590Sstevel@tonic-gate 		}
20600Sstevel@tonic-gate 		if (! mdisok(ep)) {
20610Sstevel@tonic-gate 			if (! mdissyserror(ep, ENOENT))
20620Sstevel@tonic-gate 				goto out;
20630Sstevel@tonic-gate 			mdclrerror(ep);
20640Sstevel@tonic-gate 			commitset(sr, FALSE, ep);
20650Sstevel@tonic-gate 			if (! mdisok(ep))
20660Sstevel@tonic-gate 				goto out;
20670Sstevel@tonic-gate 		}
20680Sstevel@tonic-gate 	}
20690Sstevel@tonic-gate 	if (! mdisok(ep)) {
20700Sstevel@tonic-gate 		if (! mdissyserror(ep, ENOENT))
20710Sstevel@tonic-gate 			goto out;
20720Sstevel@tonic-gate 		mdclrerror(ep);
20730Sstevel@tonic-gate 	}
20740Sstevel@tonic-gate 
20750Sstevel@tonic-gate 	setsnarfdone = 2;
20760Sstevel@tonic-gate 
20770Sstevel@tonic-gate 	url_freel(&url_used);
20780Sstevel@tonic-gate 	url_freel(&url_tode);
20790Sstevel@tonic-gate 	return (0);
20800Sstevel@tonic-gate 
20810Sstevel@tonic-gate out:
20820Sstevel@tonic-gate 	url_freel(&url_used);
20830Sstevel@tonic-gate 	url_freel(&url_tode);
20840Sstevel@tonic-gate 
20850Sstevel@tonic-gate 	sr_cache_flush(1);
20860Sstevel@tonic-gate 
20870Sstevel@tonic-gate 	setsnarfdone = 0;
20880Sstevel@tonic-gate 
20890Sstevel@tonic-gate 	return (-1);
20900Sstevel@tonic-gate }
2091