changeset 4954:a7443d15b828

6468144 metastat -s <setname> -c of replicated set shows Assertion failed: sp->setno == MD_MIN2SET
author achimm
date Tue, 28 Aug 2007 06:27:49 -0700
parents 0afa9b3bf89e
children f72bbc61cb38
files usr/src/uts/common/io/lvm/mirror/mirror_ioctl.c
diffstat 1 files changed, 78 insertions(+), 50 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/io/lvm/mirror/mirror_ioctl.c	Mon Aug 27 16:34:51 2007 -0700
+++ b/usr/src/uts/common/io/lvm/mirror/mirror_ioctl.c	Tue Aug 28 06:27:49 2007 -0700
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -194,7 +194,7 @@
 		return (mdmderror(&msp->mde, MDE_UNIT_TOO_LARGE, mnum));
 #else
 		recid = mddb_createrec((size_t)msp->size, typ1, MIRROR_REC,
-			MD_CRO_64BIT | MD_CRO_MIRROR | MD_CRO_FN, setno);
+		    MD_CRO_64BIT | MD_CRO_MIRROR | MD_CRO_FN, setno);
 #endif
 	} else {
 		/*
@@ -202,11 +202,11 @@
 		 */
 		msp->size = sizeof (mm_unit32_od_t);
 		recid = mddb_createrec((size_t)msp->size, typ1, MIRROR_REC,
-			MD_CRO_32BIT | MD_CRO_MIRROR | MD_CRO_FN, setno);
+		    MD_CRO_32BIT | MD_CRO_MIRROR | MD_CRO_FN, setno);
 	}
 	if (recid < 0)
 		return (mddbstatus2error(&msp->mde, (int)recid,
-			    mnum, setno));
+		    mnum, setno));
 
 	/* Resize to include incore fields */
 	un = (mm_unit_t *)mddb_getrecaddr_resize(recid, sizeof (*un), 0);
@@ -253,7 +253,7 @@
 		MD_UNIT(mnum) = NULL;
 		mddb_deleterec_wrapper(recid);
 		return (mdmderror(&msp->mde, MDE_IN_USE,
-			    md_getminor(sm->sm_dev)));
+		    md_getminor(sm->sm_dev)));
 	}
 
 	if (err = mirror_build_incore(un, 0)) {
@@ -324,7 +324,7 @@
 	mdclrerror(&mgdph->mde);
 
 	if ((un = mirror_getun(mgdph->mnum,
-		&mgdph->mde, RD_LOCK, lock)) == NULL)
+	    &mgdph->mde, RD_LOCK, lock)) == NULL)
 		return (0);
 
 	udevs = (md_dev64_t *)(uintptr_t)mgdph->devs;
@@ -341,7 +341,7 @@
 			}
 
 			if (ddi_copyout((caddr_t)&unit_dev, (caddr_t)udevs,
-						sizeof (*udevs), mode) != 0)
+			    sizeof (*udevs), mode) != 0)
 				return (EFAULT);
 			++udevs;
 		}
@@ -496,7 +496,7 @@
 
 		get_dev =
 		    (void (*)())md_get_named_service(sm->sm_dev, 0,
-							"get device", 0);
+		    "get device", 0);
 		compcnt = (*(smic->sm_get_component_count))(sm->sm_dev, un);
 
 		/*
@@ -631,11 +631,11 @@
 	}
 
 	get_dev = (void (*)())md_get_named_service(sm->sm_dev, 0,
-							"get device", 0);
+	    "get device", 0);
 	(void) (*get_dev)(sm->sm_dev, sm, ci, &cd);
 
 	repl_dev = (int (*)())md_get_named_service(sm->sm_dev, 0,
-							"replace device", 0);
+	    "replace device", 0);
 
 	smdev = sm->sm_dev;
 	ms_un = MD_UNIT(md_getminor(smdev));
@@ -646,7 +646,7 @@
 		mdkey_t		this_key;
 
 		this_dev = ((cd.cd_orig_dev == 0) ? cd.cd_dev :
-							    cd.cd_orig_dev);
+		    cd.cd_orig_dev);
 		setno = MD_MIN2SET(md_getminor(smdev));
 		side = mddb_getsidenum(setno);
 		comp = (struct ms_comp *)
@@ -701,7 +701,7 @@
 		}
 
 		if ((md_getmajor(this_dev) != md_major) &&
-			(md_devid_found(setno, side, this_key) == 1)) {
+		    (md_devid_found(setno, side, this_key) == 1)) {
 			if (md_update_namespace_did(setno, side,
 			    this_key, &params->mde) != 0) {
 				(void) mddeverror(&params->mde, MDE_NAME_SPACE,
@@ -730,7 +730,7 @@
 		nd.nd_hs_id = 0;
 
 		err = (*repl_dev)(sm->sm_dev, 0, ci, &nd, recids, 6,
-					&repl_done, &repl_data);
+		    &repl_done, &repl_data);
 
 	}
 
@@ -891,14 +891,14 @@
 	}
 
 	indx = md_setshared_name(setno,
-				ddi_major_to_name(md_getmajor(sm_dev)), 0L);
+	    ddi_major_to_name(md_getmajor(sm_dev)), 0L);
 
 	/* Open the sm, only if the mirror is open */
 	if (md_unit_isopen(MDI_UNIT(mnum))) {
 		if (md_layered_open(mnum, &sm_dev, MD_OFLG_NULL)) {
 			(void) md_remshared_name(setno, indx);
 			(void) mdmderror(&att->mde, MDE_SM_OPEN_ERR,
-						md_getminor(att->submirror));
+			    md_getminor(att->submirror));
 			goto errexit;
 		}
 		/* in dryrun mode, don't leave the device open */
@@ -953,7 +953,7 @@
 	compcnt = (*(smic->sm_get_component_count)) (sm->sm_dev, sm);
 	for (i = 0; i < compcnt; i++) {
 		shared = (md_m_shared_t *)(*(smic->sm_shared_by_indx))
-						(sm->sm_dev, sm, i);
+		    (sm->sm_dev, sm, i);
 
 		shared->ms_state = CS_OKAY;
 		shared->ms_flags &= ~MDM_S_NOWRITE;
@@ -986,6 +986,8 @@
 	mm_unit_t		*un;
 	mdi_unit_t		*ui;
 	mm_submirror_t		*sm;
+	mm_submirror_t		*old_sm;
+	mm_submirror_t		*new_sm;
 	mm_submirror_ic_t	*smic;
 	int			smi;
 	md_dev64_t		sm_dev;
@@ -993,6 +995,7 @@
 	sv_dev_t		sv;
 	mddb_recid_t		recids[2];
 	int			nsv = 0;
+	int			smi_remove;
 
 	mdclrerror(&det->mde);
 
@@ -1005,7 +1008,6 @@
 		mirror_resume_writes(un);
 		return (mdmderror(&det->mde, MDE_IN_UNAVAIL_STATE, mnum));
 	}
-
 	/*
 	 * detach cannot be done while a resync is active or we are
 	 * still waiting for an optimized resync to be started
@@ -1016,10 +1018,13 @@
 	}
 
 	for (smi = 0; smi < NMIRROR; smi++) {
-		if (!SMS_BY_INDEX_IS(un, smi, SMS_INUSE))
+		if (!SMS_BY_INDEX_IS(un, smi, SMS_INUSE)) {
 			continue;
-		if (un->un_sm[smi].sm_dev == det->submirror)
+		}
+		if (un->un_sm[smi].sm_dev == det->submirror) {
+			smi_remove = smi;
 			break;
+		}
 	}
 
 	if (smi == NMIRROR) {
@@ -1087,6 +1092,28 @@
 		SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_DETACH, SVM_TAG_METADEVICE,
 		    MD_UN2SET(un), MD_SID(un));
 	}
+
+	/*
+	 * Reshuffle the submirror devices in the array as we potentially
+	 * have a dead record in the middle of it.
+	 */
+	for (smi = 0; nsv && (smi < NMIRROR); smi++) {
+		if (smi < smi_remove) {
+			continue;
+		}
+		if (smi > smi_remove) {
+			old_sm = &un->un_sm[smi];
+			new_sm = &un->un_sm[smi - 1];
+			new_sm->sm_key = old_sm->sm_key;
+			new_sm->sm_dev = old_sm->sm_dev;
+			new_sm->sm_state = old_sm->sm_state;
+			new_sm->sm_flags = old_sm->sm_flags;
+			new_sm->sm_shared = old_sm->sm_shared;
+			new_sm->sm_hsp_id = old_sm->sm_hsp_id;
+			new_sm->sm_timestamp = old_sm->sm_timestamp;
+		}
+	}
+	mirror_commit(un, 0, NULL);
 	mirror_resume_writes(un);
 	return (0);
 }
@@ -1357,7 +1384,7 @@
 		old_vtoc = un->c.un_vtoc_id;
 		if (old_vtoc != 0) {
 			un->c.un_vtoc_id =
-				md_vtoc_to_efi_record(old_vtoc, setno);
+			    md_vtoc_to_efi_record(old_vtoc, setno);
 		}
 		MD_RECID(un) = recid;
 		dep = mddb_getrecdep(recid);
@@ -1414,7 +1441,7 @@
 	mdclrerror(&mgph->mde);
 
 	if ((un = mirror_getun(mgph->mnum,
-		&mgph->mde, WR_LOCK, lock)) == NULL)
+	    &mgph->mde, WR_LOCK, lock)) == NULL)
 		return (0);
 
 	if (MD_STATUS(un) & MD_UN_GROW_PENDING)
@@ -1636,7 +1663,7 @@
 			/* Sets node owner of un_rr_dirty record */
 			if (un->un_rr_dirty_recid)
 				(void) mddb_setowner(un->un_rr_dirty_recid,
-					md_mn_mynode_id);
+				    md_mn_mynode_id);
 			/*
 			 * Release the block on the current resync region if it
 			 * is blocked
@@ -1873,7 +1900,7 @@
 
 		mutex_exit(&un->un_owner_mx);
 	} else if ((un->un_mirror_owner == md_mn_mynode_id) ||
-		un->un_owner_state & MM_MN_BECOME_OWNER) {
+	    un->un_owner_state & MM_MN_BECOME_OWNER) {
 		mutex_exit(&un->un_owner_mx);
 
 		/*
@@ -2030,8 +2057,8 @@
 #ifdef DEBUG
 			if (mirror_debug_flag) {
 				printf("mirror_set_state: short circuit "
-					"hs_id=0x%x, ms_hs_id=0x%x\n",
-					p->hs_id, shared->ms_hs_id);
+				    "hs_id=0x%x, ms_hs_id=0x%x\n",
+				    p->hs_id, shared->ms_hs_id);
 			}
 #endif
 			/* release the block on writes to the mirror */
@@ -2306,8 +2333,8 @@
 
 	kres = kmem_alloc(sizeof (md_mn_kresult_t), KM_SLEEP);
 	rval = mdmn_ksend_message(setno, MD_MN_MSG_GET_MIRROR_STATE,
-		MD_MSGF_NO_BCAST | MD_MSGF_NO_LOG, (char *)&msg,
-		sizeof (msg), kres);
+	    MD_MSGF_NO_BCAST | MD_MSGF_NO_LOG, (char *)&msg,
+	    sizeof (msg), kres);
 
 	/* if the node hasn't yet joined, it's Ok. */
 	if ((!MDMN_KSEND_MSG_OK(rval, kres)) &&
@@ -2685,7 +2712,7 @@
 		    sizeof (md_driver_t));
 
 		if ((p->probe.nmdevs < 1) ||
-			(strstr(p->probe.test_name, "probe") == NULL)) {
+		    (strstr(p->probe.test_name, "probe") == NULL)) {
 			err = EINVAL;
 			goto free_mem;
 		}
@@ -2715,7 +2742,8 @@
 		for (i = 0; i < p->probe.nmdevs; i++) {
 			sema_p(PROBE_SEMA(p));
 		}
-		while (md_ioctl_lock_enter() == EINTR);
+		while (md_ioctl_lock_enter() == EINTR)
+		;
 
 		/*
 		 * clean up. The hdr list is freed in the probe routines
@@ -3061,7 +3089,7 @@
 
 		if ((mode & DATAMODEL_MASK) == DATAMODEL_NATIVE) {
 			if (ddi_copyout((caddr_t)&dmp, data, sizeof (dmp),
-				mode) != 0)
+			    mode) != 0)
 				err = EFAULT;
 		}
 #ifdef _SYSCALL32
@@ -3072,7 +3100,7 @@
 			dmp32.dkl_nblk = dmp.dkl_nblk;
 
 			if (ddi_copyout((caddr_t)&dmp32, data, sizeof (dmp32),
-				mode) != 0)
+			    mode) != 0)
 				err = EFAULT;
 		}
 #endif /* _SYSCALL32 */
@@ -3570,10 +3598,10 @@
 		child_min = md_getminor(sm->sm_dev);
 
 		p = new = md_build_rendelta(MDRR_CHILD,
-				to_min == child_min? MDRR_SELF: MDRR_CHILD,
-				sm->sm_dev, p,
-				MD_UNIT(child_min), MDI_UNIT(child_min),
-				&rtxnp->mde);
+		    to_min == child_min? MDRR_SELF: MDRR_CHILD,
+		    sm->sm_dev, p,
+		    MD_UNIT(child_min), MDI_UNIT(child_min),
+		    &rtxnp->mde);
 
 		if (!new) {
 			if (mdisok(&rtxnp->mde)) {
@@ -3608,7 +3636,7 @@
 
 	if (!un || !ui) {
 		(void) mdmderror(&rtxnp->mde, MDE_RENAME_CONFIG_ERROR,
-								from_min);
+		    from_min);
 		return (EINVAL);
 	}
 
@@ -3646,7 +3674,7 @@
 		}
 		if (!related) {
 			(void) mdmderror(&rtxnp->mde,
-					MDE_RENAME_TARGET_UNRELATED, to_min);
+			    MDE_RENAME_TARGET_UNRELATED, to_min);
 			return (EINVAL);
 		}
 
@@ -3660,14 +3688,14 @@
 
 		if (toplevel && md_unit_isopen(ui)) {
 			(void) mdmderror(&rtxnp->mde, MDE_RENAME_BUSY,
-								from_min);
+			    from_min);
 			return (EBUSY);
 		}
 		break;
 
 	default:
 		(void) mdmderror(&rtxnp->mde, MDE_RENAME_CONFIG_ERROR,
-								from_min);
+		    from_min);
 		return (EINVAL);
 	}
 
@@ -3714,7 +3742,7 @@
 		ASSERT(smic->sm_get_component_count);
 		if (!smic->sm_get_component_count) {
 			(void) mdmderror(&rtxnp->mde, MDE_RENAME_CONFIG_ERROR,
-						md_getminor(delta->dev));
+			    md_getminor(delta->dev));
 			return (ENXIO);
 		}
 
@@ -3725,8 +3753,8 @@
 			ASSERT(smic->sm_shared_by_indx);
 			if (!smic->sm_shared_by_indx) {
 				(void) mdmderror(&rtxnp->mde,
-						MDE_RENAME_CONFIG_ERROR,
-						md_getminor(delta->dev));
+				    MDE_RENAME_CONFIG_ERROR,
+				    md_getminor(delta->dev));
 				return (ENXIO);
 			}
 
@@ -3736,15 +3764,15 @@
 			ASSERT(shared);
 			if (!shared) {
 				(void) mdmderror(&rtxnp->mde,
-						MDE_RENAME_CONFIG_ERROR,
-						md_getminor(delta->dev));
+				    MDE_RENAME_CONFIG_ERROR,
+				    md_getminor(delta->dev));
 				return (ENXIO);
 			}
 
 			if (shared->ms_hs_id != 0) {
 				(void) mdmderror(&rtxnp->mde,
-						MDE_SM_FAILED_COMPS,
-						md_getminor(delta->dev));
+				    MDE_SM_FAILED_COMPS,
+				    md_getminor(delta->dev));
 				return (EIO);
 			}
 
@@ -3754,14 +3782,14 @@
 
 			case CS_RESYNC:
 				(void) mdmderror(&rtxnp->mde,
-						MDE_RESYNC_ACTIVE,
-						md_getminor(delta->dev));
+				    MDE_RESYNC_ACTIVE,
+				    md_getminor(delta->dev));
 				return (EBUSY);
 
 			default:
 				(void) mdmderror(&rtxnp->mde,
-						MDE_SM_FAILED_COMPS,
-						md_getminor(delta->dev));
+				    MDE_SM_FAILED_COMPS,
+				    md_getminor(delta->dev));
 				return (EINVAL);
 			}