Esempio n. 1
0
/*
 * NAME:	raid_hs_release
 *
 * DESCRIPTION: Release the hotspare.
 *
 * PARAMETERS:	int error - indication of error on hotspare
 *		mr_unit_t  *un - raid unit
 *		mddb_recid_t  *recids - output records to commit revised hs info
 *		int hs_index - component to release
 *
 * LOCKS:	Expects Unit Writer Lock to be held across call.
 */
void
raid_hs_release(
	hs_cmds_t	cmd,
	mr_unit_t	*un,
	mddb_recid_t	*recids,
	int		hs_index
)
{
	mr_column_t	*col;

	col = &un->un_column[hs_index];

	/* close the hotspare device */
	if (col->un_devflags & MD_RAID_DEV_ISOPEN) {
		md_layered_close(col->un_dev, MD_OFLG_NULL);
		col->un_devflags &= ~MD_RAID_DEV_ISOPEN;
	}

	/* return the hotspare to the pool */
	(void) md_hot_spare_ifc(cmd, un->un_hsp_id, 0, 0, recids,
	    &col->un_hs_key, NULL, NULL);

	col->un_hs_pwstart = 0;
	col->un_hs_devstart = 0;
	col->un_hs_id = (mddb_recid_t)0;
	col->un_hs_key = 0;
}
Esempio n. 2
0
static void
stripe_close_all_devs(ms_unit_t *un, int md_cflags)
{
	int		row;
	int		i;
	int		c;
	struct ms_comp	*mdcomp;

	mdcomp = (struct ms_comp *)((void *)&((char *)un)[un->un_ocomp]);
	for (row = 0; row < un->un_nrows; row++) {
		struct ms_row *mdr = &un->un_row[row];
		for (i = 0, c = mdr->un_icomp; i < mdr->un_ncomp; i++) {
			struct ms_comp	*mdc;
			mdc = &mdcomp[c++];
			if (md_cflags & MD_OFLG_PROBEDEV) {

			/*
			 * It is possible that the md_layered_open
			 * failed because the stripe unit structure
			 * contained a NODEV.  In such a case since
			 * there is nothing to open, there is nothing
			 * to close.
			 */
				if (mdc->un_dev == NODEV64)
					continue;
			}
			if ((md_cflags & MD_OFLG_PROBEDEV) &&
			    (mdc->un_mirror.ms_flags & MDM_S_PROBEOPEN)) {
				md_layered_close(mdc->un_dev,
				    md_cflags);
				mdc->un_mirror.ms_flags &= ~MDM_S_PROBEOPEN;
			} else if (mdc->un_mirror.ms_flags & MDM_S_ISOPEN) {
				md_layered_close(mdc->un_dev, md_cflags);
				mdc->un_mirror.ms_flags &= ~MDM_S_ISOPEN;
			}
		}
	}
}
static void
raid_close_alt(mr_unit_t *un, int index)
{
	mr_column_t	*column = &un->un_column[index];
	md_dev64_t	tmpdev = column->un_alt_dev;

	ASSERT(UNIT_WRITER_HELD(un));	/* correct locks */
	ASSERT(! (column->un_devflags & MD_RAID_WRITE_ALT)); /* not writing */
	ASSERT(column->un_devflags & MD_RAID_ALT_ISOPEN); /* already open */
	ASSERT(tmpdev != NODEV64); /* is a device */

	md_layered_close(column->un_alt_dev, MD_OFLG_NULL);
	column->un_devflags &= ~MD_RAID_ALT_ISOPEN;
	column->un_alt_dev = NODEV64;
}
Esempio n. 4
0
/*
 * NAME:	check_comp_4_hs
 *
 * DESCRIPTION: Check whether the input component has an error and can be
 *		backed with a hot spare (RCS_ERRED state), and initiate
 *		a resync if so.
 *
 * PARAMETERS:	mr_unit_t *un - raid unit
 *		int hs_index	- component to check
 *
 * LOCKS:	Expects Unit Writer Lock to be held upon entrance.  Releases
 *		the lock prior to calling raid_resync_unit, then reacquires
 *		it before returning.
 */
static void
check_comp_4_hs(
	mr_unit_t *un,
	int hs_index
)
{
	mddb_recid_t	recids[3];
	minor_t		mnum = MD_SID(un);
	mdi_unit_t	*ui;
	rcs_state_t	state;
	diskaddr_t	size;
	int		err;
	mr_column_t	*col;
	md_error_t	mde = mdnullerror;
	char		devname[MD_MAX_CTDLEN];
	char		hs_devname[MD_MAX_CTDLEN];
	set_t		setno;
	md_dev64_t	tmpdev;
	diskaddr_t	tmpdaddr;


	/* initialize */
	setno = MD_UN2SET(un);
	ui = MDI_UNIT(mnum);
	md_unit_readerexit(ui);
	(void) md_io_writerlock(ui);
	un = (mr_unit_t *)md_unit_writerlock(ui);
	col = &un->un_column[hs_index];

	/*
	 * add a hotspare for erred column only if not resyncing
	 */
	if ((!(COLUMN_STATE(un, hs_index) & RCS_ERRED)) ||
	    (raid_state_cnt(un, (RCS_ERRED | RCS_LAST_ERRED)) != 1) ||
	    (raid_state_cnt(un, RCS_RESYNC) > 0)) {
		goto errout;
	}

	recids[0] = 0;
	recids[1] = 0;
	/* if there is already a hotspare then just return */
	if (HOTSPARED(un, hs_index) && (col->un_devstate & RCS_ERRED)) {
		raid_hs_release(HS_BAD, un, &recids[0], hs_index);
		cmn_err(CE_WARN, "md: %s: %s hotspare errored and released",
		    md_shortname(mnum),
		    md_devname(MD_MIN2SET(mnum), col->un_dev, NULL, 0));
		col->un_dev = col->un_orig_dev;
		col->un_pwstart = col->un_orig_pwstart;
		col->un_devstart = col->un_orig_devstart;
		raid_commit(un, recids);

		SE_NOTIFY(EC_SVM_STATE, ESC_SVM_HS_FREED, SVM_TAG_METADEVICE,
		    setno, MD_SID(un));
	}
	ASSERT(!HOTSPARED(un, hs_index));

	state = col->un_devstate;
	size = col->un_pwstart + un->un_pwsize +
	    (un->un_segsize * un->un_segsincolumn);

again:
	/* quit if resync is already active */
	col->un_devflags |= MD_RAID_REGEN_RESYNC;
	if (resync_request(mnum, hs_index, 0, NULL))
		goto errout;

	recids[0] = 0;
	recids[1] = 0;

	tmpdev = col->un_dev;
	tmpdaddr = col->un_hs_pwstart;

	/* get a hotspare */
	if (md_hot_spare_ifc(HS_GET, un->un_hsp_id, size,
	    ((col->un_orig_pwstart >= 1) &&
	    (col->un_orig_pwstart != MD_DISKADDR_ERROR)),
	    &col->un_hs_id, &col->un_hs_key, &tmpdev, &tmpdaddr) != 0) {
		col->un_dev = tmpdev;
		col->un_hs_pwstart = tmpdaddr;
		release_resync_request(mnum);
		raid_set_state(un, hs_index, state, 1);
		goto errout;
	}

	col->un_hs_pwstart = tmpdaddr;

	/*
	 * record id is filled in by raid_commit, recids[0] filled in by
	 * md_hot_spare_ifc if needed
	 */
	recids[0] = col->un_hs_id;
	recids[1] = 0;

	/*
	 * close the device and open the hot spare.  The device should
	 * never be a hotspare here.
	 */
	if (col->un_devflags & MD_RAID_DEV_ISOPEN) {
		md_layered_close(col->un_orig_dev, MD_OFLG_NULL);
		col->un_devflags &= ~MD_RAID_DEV_ISOPEN;
	}
	/*
	 * Try open by device id
	 */
	tmpdev = md_resolve_bydevid(mnum, tmpdev, col->un_hs_key);
	if (md_layered_open(mnum, &tmpdev, MD_OFLG_NULL)) {
		md_dev64_t hs_dev = tmpdev;
		/* cannot open return to orig */
		raid_hs_release(HS_BAD, un, &recids[0], hs_index);
		release_resync_request(mnum);
		raid_set_state(un, hs_index, state, 1);
		col->un_dev = col->un_orig_dev;
		col->un_devstart = col->un_orig_devstart;
		col->un_pwstart = col->un_orig_pwstart;
		col->un_devflags &= ~MD_RAID_DEV_ISOPEN;
		raid_commit(un, recids);
		cmn_err(CE_WARN, "md: %s: open error of hotspare %s",
		    md_shortname(mnum),
		    md_devname(MD_MIN2SET(mnum), hs_dev, NULL, 0));
		SE_NOTIFY(EC_SVM_STATE, ESC_SVM_HS_FREED, SVM_TAG_HS, setno,
		    MD_SID(un));
		goto again;
	}

	col->un_dev = tmpdev;

	col->un_devflags |= MD_RAID_DEV_ISOPEN;

	/*
	 * move the values into the device fields.  Since in some cases
	 * the pwstart is not zero this must be added into the start of
	 * the hotspare to avoid over writting the label
	 */
	col->un_hs_pwstart += col->un_orig_pwstart;
	col->un_pwstart = col->un_hs_pwstart;
	col->un_hs_devstart = col->un_hs_pwstart + un->un_pwsize;
	col->un_devstart = col->un_hs_devstart;

	/* commit unit and hotspare records and release lock */
	raid_commit(un, recids);
	md_unit_writerexit(ui);
	md_io_writerexit(ui);

	err = raid_resync_unit(mnum, &mde);

	/* if resync fails, transition back to erred state and reset */
	if (err) {
		/* reaquire unit writerr lock */
		un = (mr_unit_t *)md_unit_writerlock(ui);

		raid_set_state(un, hs_index, RCS_ERRED, 0);

		/*
		 * close the hotspare and return it.  Then restore the
		 * original device back to the original state
		 */
		raid_hs_release(HS_FREE, un, &recids[0], hs_index);
		col->un_dev = col->un_orig_dev;
		col->un_devstart = col->un_orig_devstart;
		col->un_pwstart = col->un_orig_pwstart;
		raid_commit(un, recids);
		md_unit_writerexit(ui);
		un = (mr_unit_t *)md_unit_readerlock(ui);
		return;
	}

	setno = MD_MIN2SET(mnum);

	(void) md_devname(setno, col->un_orig_dev, devname,
		sizeof (devname));
	(void) md_devname(setno, col->un_dev, hs_devname,
		sizeof (hs_devname));

	cmn_err(CE_NOTE, "md: %s: hotspared device %s with %s",
	    md_shortname(mnum), devname, hs_devname);
	SE_NOTIFY(EC_SVM_STATE, ESC_SVM_HOTSPARED, SVM_TAG_HS, setno,
	    MD_SID(un));
	(void) md_unit_readerlock(ui);
	return;

errout:
	md_unit_writerexit(ui);
	md_io_writerexit(ui);
	un = (mr_unit_t *)md_unit_readerlock(ui);
}