Пример #1
0
static int
raid_open_alt(mr_unit_t *un, int index)
{
	mr_column_t	*column = &un->un_column[index];
	set_t		setno = MD_MIN2SET(MD_SID(un));
	side_t		side = mddb_getsidenum(setno);
	md_dev64_t	tmpdev = column->un_alt_dev;

	/* correct locks */
	ASSERT(UNIT_WRITER_HELD(un));
	/* not already writing to */
	ASSERT(! (column->un_devflags & MD_RAID_WRITE_ALT));
	/* not already open */
	ASSERT(! (column->un_devflags & MD_RAID_ALT_ISOPEN));

	if (tmpdev != NODEV64) {
		/*
		 * Open by device id. We use orig_key since alt_dev
		 * has been set by the caller to be the same as orig_dev.
		 */
		if ((md_getmajor(tmpdev) != md_major) &&
			md_devid_found(setno, side, column->un_orig_key) == 1) {
			tmpdev = md_resolve_bydevid(MD_SID(un), tmpdev,
				column->un_orig_key);
		}
		if (md_layered_open(MD_SID(un), &tmpdev, MD_OFLG_NULL)) {
			/* failed open */
			column->un_alt_dev = tmpdev;
			return (1);
		} else {
			/* open suceeded */
			column->un_alt_dev = tmpdev;
			column->un_devflags |= MD_RAID_ALT_ISOPEN;
			return (0);
		}
	} else
		/* no alt device to open */
		return (1);
}
Пример #2
0
static int
seths_replace(set_hs_params_t *shs)
{
	hot_spare_t		*hs;
	hot_spare_t		*prev_hs;
	hot_spare_t		*new_hs;
	hot_spare_pool_t	*hsp;
	int			new_found = 0;
	mddb_recid_t		recid;
	mddb_recid_t		recids[5];
	int			i;
	sv_dev_t		sv;
	int			delete_hs = 0;
	set_t			setno;
	mddb_type_t		typ1;
	mdkey_t			key_old;
	int			num_keys_old = 0;

	setno = HSP_SET(shs->shs_hot_spare_pool);
	typ1 = (mddb_type_t)md_getshared_key(setno,
	    hotspares_md_ops.md_driver.md_drivername);

	/* Scan the hot spare list */
	hs = (hot_spare_t *)md_set[setno].s_hs;
	prev_hs = (hot_spare_t *)0;
	while (hs) {
		if (hs->hs_devnum == shs->shs_component_old) {
			break;
		}
		prev_hs = hs;
		hs = hs->hs_next;
	}

	if (hs == NULL) {
		/*
		 * Unable to find device using devnum so use
		 * key associated with shs_component_old instead.
		 * If unable to find a unique key for shs_component_old
		 * then fail since namespace has multiple entries
		 * for this old component and we're unable to determine
		 * which key is the valid match for shs_component_old.
		 *
		 * Only need to compare keys when hs_devnum is NODEV.
		 */
		if (md_getkeyfromdev(setno, mddb_getsidenum(setno),
		    shs->shs_component_old, &key_old, &num_keys_old) != 0) {
			return (mddeverror(&shs->mde, MDE_NAME_SPACE,
			    shs->shs_component_old));
		}

		/*
		 * If more than one key matches given old_dev - fail command
		 * since unable to determine which key is correct.
		 */
		if (num_keys_old > 1) {
			return (mddeverror(&shs->mde, MDE_MULTNM,
			    shs->shs_component_old));
		}
		/*
		 * If there is no key for this entry then fail since
		 * a key for this entry should exist.
		 */
		if (num_keys_old == 0) {
			return (mddeverror(&shs->mde, MDE_INVAL_HS,
			    shs->shs_component_old));
		}
		/* Scan the hot spare list again */
		hs = (hot_spare_t *)md_set[setno].s_hs;
		prev_hs = (hot_spare_t *)0;
		while (hs) {
			/*
			 * Only need to compare keys when hs_devnum is NODEV.
			 */
			if ((hs->hs_devnum == NODEV64) &&
			    (hs->hs_key == key_old)) {
				break;
			}
			prev_hs = hs;
			hs = hs->hs_next;
		}
	}

	if (hs == NULL) {
		return (mddeverror(&shs->mde, MDE_INVAL_HS,
		    shs->shs_component_old));
	}

	/* check the force flag and the state of the hot spare */
	if (((shs->shs_options & HS_OPT_FORCE) == 0) &&
	    (hs->hs_state == HSS_RESERVED)) {
		return (mdhserror(&shs->mde, MDE_HS_RESVD,
		    shs->shs_hot_spare_pool,
		    hs->hs_devnum));
	}

	/* Scan the hot spare pool list */
	hsp = find_hot_spare_pool(setno, shs->shs_hot_spare_pool);
	if (hsp == (hot_spare_pool_t *)0) {
		return (mdhsperror(&shs->mde, MDE_INVAL_HSP,
		    shs->shs_hot_spare_pool));
	}

	/*
	 * Make sure the old device is in the pool.
	 */
	for (i = 0; i < hsp->hsp_nhotspares; i++) {
		if (hsp->hsp_hotspares[i] == hs->hs_record_id) {
			break;
		}
	}
	if (i >= hsp->hsp_nhotspares) {
		return (mddeverror(&shs->mde, MDE_INVAL_HS,
		    hs->hs_devnum));
	}

	/* Scan the hot spare list for the new hs */
	new_hs = (hot_spare_t *)md_set[setno].s_hs;
	new_found = 0;
	while (new_hs) {
		if (new_hs->hs_devnum == shs->shs_component_new) {
			new_found = 1;
			break;
		}
		new_hs = new_hs->hs_next;
	}

	/*
	 * Make sure the new device is not already in the pool.
	 * We don't have to search the hs in this hsp, if the
	 * new hs was just created. Only if the hot spare was found.
	 */
	if (new_found) {
		for (i = 0; i < hsp->hsp_nhotspares; i++)
			if (hsp->hsp_hotspares[i] == new_hs->hs_record_id) {
				return (mdhserror(&shs->mde, MDE_HS_INUSE,
				    shs->shs_hot_spare_pool,
				    new_hs->hs_devnum));
			}
	}

	/* In case of a dryrun, we're done here */
	if (shs->shs_options & HS_OPT_DRYRUN) {
		return (0);
	}

	/*
	 * Create the new hotspare
	 */
	if (!new_found) {
		/* create a hot spare record */
		if (shs->shs_size_option & MD_CRO_64BIT) {
#if defined(_ILP32)
			return (mdhserror(&shs->mde, MDE_HS_UNIT_TOO_LARGE,
			    shs->shs_hot_spare_pool, shs->shs_component_new));
#else
			recid = mddb_createrec(HS_ONDSK_STR_SIZE, typ1, HS_REC,
				MD_CRO_64BIT | MD_CRO_HOTSPARE, setno);
#endif
		} else {
			recid = mddb_createrec(HS_ONDSK_STR_SIZE, typ1, HS_REC,
				MD_CRO_32BIT | MD_CRO_HOTSPARE, setno);
		}

		if (recid < 0) {
			return (mdhserror(&shs->mde, MDE_HS_CREATE_FAILURE,
			    shs->shs_hot_spare_pool,
			    shs->shs_component_new));
		}

		/* get the addr */
		new_hs = (hot_spare_t *)mddb_getrecaddr_resize(recid,
			sizeof (*new_hs), 0);

		new_hs->hs_record_id = recid;
		new_hs->hs_devnum = shs->shs_component_new;
		new_hs->hs_key = shs->shs_key_new;
		new_hs->hs_start_blk = shs->shs_start_blk;
		new_hs->hs_has_label = shs->shs_has_label;
		new_hs->hs_number_blks = shs->shs_number_blks;
		set_hot_spare_state(new_hs, HSS_AVAILABLE);
		new_hs->hs_refcount = 0;
		new_hs->hs_isopen = 1;
	}

	/* lock the db records */
	recids[0] = hs->hs_record_id;
	recids[1] = new_hs->hs_record_id;
	recids[2] = hsp->hsp_record_id;
	recids[3] = 0;

	sv.setno = setno;
	sv.key = hs->hs_key;

	hs->hs_refcount--;
	if (hs->hs_refcount == 0) {
		/*
		 * NOTE: We do not commit the previous hot spare record.
		 *	 There is no need, the link we get rebuilt at boot time.
		 */
		if (prev_hs) {
			prev_hs->hs_next = hs->hs_next;
		} else
			md_set[setno].s_hs = (void *) hs->hs_next;

		/* mark hs to be deleted in the correct order */
		delete_hs = 1;

		recids[0] = new_hs->hs_record_id;
		recids[1] = hsp->hsp_record_id;
		recids[2] = 0;
	}

	/* link into the hs list */
	new_hs->hs_refcount++;
	if (!new_found) {
		/* do this AFTER the old dev is possibly removed */
		new_hs->hs_next = (hot_spare_t *)md_set[setno].s_hs;
		md_set[setno].s_hs = (void *) new_hs;
	}

	/* find the location of the old hs in the hsp */
	for (i = 0; i < hsp->hsp_nhotspares; i++) {
		if (hsp->hsp_hotspares[i] == hs->hs_record_id) {
			hsp->hsp_hotspares[i] = new_hs->hs_record_id;
			break;
		}
	}

	if (shs->shs_size_option & MD_CRO_64BIT) {
		new_hs->hs_revision |= MD_64BIT_META_DEV;
	} else {
		new_hs->hs_revision &= ~MD_64BIT_META_DEV;
	}

	/* commit the db records */
	mddb_commitrecs_wrapper(recids);

	if (delete_hs)
		mddb_deleterec_wrapper(hs->hs_record_id);

	md_rem_names(&sv, 1);

	SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_REPLACE, SVM_TAG_HSP, setno,
	    md_expldev(hsp->hsp_self_id));
	return (0);
}
Пример #3
0
static int
seths_enable(set_hs_params_t *shs)
{
	hot_spare_t	*hs;
	mddb_recid_t	recids[2];
	set_t		setno = shs->md_driver.md_setno;
	mdkey_t		key_old;
	int		num_keys_old = 0;


	/*
	 * Find device by using key associated with shs_component_old.
	 * If unable to find a unique key for shs_component_old
	 * then fail since namespace has multiple entries
	 * for this old component and we're unable to determine
	 * which key is the valid match for shs_component_old.
	 * This failure keeps a hotspare from being enabled on a slice
	 * that may already be in use by another metadevice.
	 */
	if (md_getkeyfromdev(setno, mddb_getsidenum(setno),
	    shs->shs_component_old, &key_old, &num_keys_old) != 0) {
		return (mddeverror(&shs->mde, MDE_NAME_SPACE,
		    shs->shs_component_old));
	}

	/*
	 * If more than one key matches given old_dev - fail command
	 * since unable to determine which key is correct.
	 */
	if (num_keys_old > 1) {
		return (mddeverror(&shs->mde, MDE_MULTNM,
		    shs->shs_component_old));
	}
	/*
	 * If there is no key for this entry then fail since
	 * a key for this entry should exist.
	 */
	if (num_keys_old == 0) {
		return (mddeverror(&shs->mde, MDE_INVAL_HS,
		    shs->shs_component_old));
	}

	/* Scan the hot spare list for the hs */
	hs = (hot_spare_t *)md_set[setno].s_hs;
	while (hs) {
		/*
		 * Since component may or may not be currently in the system,
		 * use the keys to find a match (not the devt).
		 */
		if (hs->hs_key == key_old) {
			break;
		}
		hs = hs->hs_next;
	}

	if (hs == NULL) {
		return (mddeverror(&shs->mde, MDE_INVAL_HS,
			shs->shs_component_old));
	}

	/* make sure it's broken */
	if (hs->hs_state != HSS_BROKEN) {
		return (mddeverror(&shs->mde, MDE_FIX_INVAL_HS_STATE,
		    hs->hs_devnum));
	}

	/* In case of a dryrun, we're done here */
	if (shs->shs_options & HS_OPT_DRYRUN) {
		return (0);
	}

	/* fix it */
	set_hot_spare_state(hs, HSS_AVAILABLE);
	hs->hs_start_blk = shs->shs_start_blk;
	hs->hs_has_label = shs->shs_has_label;
	hs->hs_number_blks = shs->shs_number_blks;

	/* commit the db records */
	recids[0] = hs->hs_record_id;
	recids[1] = 0;
	mddb_commitrecs_wrapper(recids);
	SE_NOTIFY(EC_SVM_STATE, ESC_SVM_ENABLE, SVM_TAG_HS, setno,
	    shs->shs_component_old);

	return (0);
}
Пример #4
0
static int
seths_delete(set_hs_params_t *shs)
{
	hot_spare_t		*hs;
	hot_spare_t		*prev_hs;
	hot_spare_pool_t	*hsp;
	mddb_recid_t		recids[4];
	int			i;
	set_t			setno;
	sv_dev_t		sv;
	int			delete_hs = 0;
	mdkey_t			key_old;
	int			num_keys_old = 0;

	/* delete the hot spare pool */
	if (shs->shs_options & HS_OPT_POOL) {
		return (seths_delete_hsp(shs));
	}

	setno = HSP_SET(shs->shs_hot_spare_pool);

	/* Scan the hot spare list */
	hs = (hot_spare_t *)md_set[setno].s_hs;
	prev_hs = (hot_spare_t *)0;
	while (hs) {
		if (hs->hs_devnum == shs->shs_component_old) {
			break;
		}
		prev_hs = hs;
		hs = hs->hs_next;
	}

	if (hs == NULL) {
		/*
		 * Unable to find device using devnum so use
		 * key associated with shs_component_old instead.
		 * If unable to find a unique key for shs_component_old
		 * then fail since namespace has multiple entries
		 * for this old component and we're unable to determine
		 * which key is the valid match for shs_component_old.
		 *
		 * Only need to compare keys when hs_devnum is NODEV.
		 */
		if (md_getkeyfromdev(setno, mddb_getsidenum(setno),
		    shs->shs_component_old, &key_old, &num_keys_old) != 0) {
			return (mddeverror(&shs->mde, MDE_NAME_SPACE,
			    shs->shs_component_old));
		}

		/*
		 * If more than one key matches given old_dev - fail command
		 * since shouldn't add new hotspare if namespace has
		 * multiple entries.
		 */
		if (num_keys_old > 1) {
			return (mddeverror(&shs->mde, MDE_MULTNM,
			    shs->shs_component_old));
		}
		/*
		 * If there is no key for this entry then fail since
		 * a key for this entry should exist.
		 */
		if (num_keys_old == 0) {
			return (mddeverror(&shs->mde, MDE_INVAL_HS,
			    shs->shs_component_old));
		}
		/* Scan the hot spare list again */
		hs = (hot_spare_t *)md_set[setno].s_hs;
		prev_hs = (hot_spare_t *)0;
		while (hs) {
			/*
			 * Only need to compare keys when hs_devnum is NODEV.
			 */
			if ((hs->hs_devnum == NODEV64) &&
			    (hs->hs_key == key_old)) {
				break;
			}
			prev_hs = hs;
			hs = hs->hs_next;
		}
	}

	if (hs == NULL) {
		return (mddeverror(&shs->mde, MDE_INVAL_HS,
		    shs->shs_component_old));
	}

	/* Scan the hot spare pool list */
	hsp = find_hot_spare_pool(setno, shs->shs_hot_spare_pool);
	if (hsp == (hot_spare_pool_t *)0) {
		return (mdhsperror(&shs->mde, MDE_INVAL_HSP,
		    shs->shs_hot_spare_pool));
	}

	/* check for force flag and state of hot spare */
	if (((shs->shs_options & HS_OPT_FORCE) == 0) &&
	    (hs->hs_state == HSS_RESERVED)) {
		return (mdhserror(&shs->mde, MDE_HS_RESVD,
		    shs->shs_hot_spare_pool, shs->shs_component_old));
	}

	if (hsp->hsp_refcount && (hs->hs_state == HSS_RESERVED)) {
		return (mdhserror(&shs->mde, MDE_HS_RESVD,
		    shs->shs_hot_spare_pool, shs->shs_component_old));
	}

	/*
	 * Make sure the device is in the pool.
	 */
	for (i = 0; i < hsp->hsp_nhotspares; i++) {
		if (hsp->hsp_hotspares[i] == hs->hs_record_id) {
			break;
		}
	}

	if (i >= hsp->hsp_nhotspares) {
		return (mddeverror(&shs->mde, MDE_INVAL_HS,
		    hs->hs_devnum));
	}

	/* In case of a dryrun, we're done here */
	if (shs->shs_options & HS_OPT_DRYRUN) {
		return (0);
	}

	/* lock the db records */
	recids[0] = hs->hs_record_id;
	recids[1] = hsp->hsp_record_id;
	recids[2] = 0;

	sv.setno = setno;
	sv.key = hs->hs_key;

	hs->hs_refcount--;
	if (hs->hs_refcount == 0) {
		/*
		 * NOTE: We do not commit the previous hot spare record.
		 *	 There is no need, the link we get rebuilt at boot time.
		 */
		if (prev_hs) {
			prev_hs->hs_next = hs->hs_next;
		} else
			md_set[setno].s_hs = (void *) hs->hs_next;

		/* mark the hot spare to be deleted */
		delete_hs = 1;
		recids[0] = hsp->hsp_record_id;
		recids[1] = 0;
	}

	/* find the location of the hs in the hsp */
	for (i = 0; i < hsp->hsp_nhotspares; i++) {
		if (hsp->hsp_hotspares[i] == hs->hs_record_id)
			break;
	}

	/* remove the hs from the hsp */
	for (i++; i < hsp->hsp_nhotspares; i++)
		hsp->hsp_hotspares[i - 1] = hsp->hsp_hotspares[i];

	hsp->hsp_nhotspares--;

	/* commit the db records */
	mddb_commitrecs_wrapper(recids);

	if (delete_hs)
		mddb_deleterec_wrapper(hs->hs_record_id);

	md_rem_names(&sv, 1);

	SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_REMOVE, SVM_TAG_HSP, setno,
	    md_expldev(hsp->hsp_self_id));

	return (0);
}
Пример #5
0
static int
seths_add(set_hs_params_t *shs)
{
	hot_spare_t		*hs;
	hot_spare_pool_t	*hsp;
	hot_spare_pool_t	*prev_hsp;
	hot_spare_pool_t	*new_hsp;
	hot_spare_pool_t	*old_hsp;
	md_create_rec_option_t	options;
	mddb_recid_t		recid;
	mddb_recid_t		recids[5];
	size_t			new_size;
	int			i;
	int			delete_hsp = 0;
	int			irecid;
	set_t			setno;
	mddb_type_t		typ1;
	int			hsp_created = 0;
	mdkey_t			key_old;
	int			num_keys_old = 0;

	/* Not much to do here in case of a dryrun */
	if (shs->shs_options & HS_OPT_DRYRUN) {
		return (0);
	}

	/* create an empty hot spare pool */
	if (shs->shs_options & HS_OPT_POOL) {
		return (seths_create_hsp(shs));
	}

	setno = HSP_SET(shs->shs_hot_spare_pool);
	typ1 = (mddb_type_t)md_getshared_key(setno,
	    hotspares_md_ops.md_driver.md_drivername);

	/* Scan the hot spare list */
	hs = (hot_spare_t *)md_set[setno].s_hs;
	while (hs) {
		if (hs->hs_devnum == shs->shs_component_old) {
			break;
		}
		hs = hs->hs_next;
	}

	if (hs == NULL) {
		/*
		 * Did not find match for device using devnum so use
		 * key associated with shs_component_old just
		 * in case there is a match but the match's dev is NODEV.
		 * If unable to find a unique key for shs_component_old
		 * then fail since namespace has multiple entries
		 * for this old component and we shouldn't allow
		 * an addition of a hotspare in this case.
		 */
		if (md_getkeyfromdev(setno, mddb_getsidenum(setno),
		    shs->shs_component_old, &key_old, &num_keys_old) != 0) {
			return (mddeverror(&shs->mde, MDE_NAME_SPACE,
			    shs->shs_component_old));
		}

		/*
		 * If more than one key matches given old_dev - fail command
		 * since shouldn't add new hotspare if namespace has
		 * multiple entries.
		 */
		if (num_keys_old > 1) {
			return (mddeverror(&shs->mde, MDE_MULTNM,
			    shs->shs_component_old));
		}
		/*
		 * If there is no key for this entry then fail since
		 * a key for this entry should exist.
		 */
		if (num_keys_old == 0) {
			return (mddeverror(&shs->mde, MDE_INVAL_HS,
			    shs->shs_component_old));
		}
		/* Scan the hot spare list again */
		hs = (hot_spare_t *)md_set[setno].s_hs;
		while (hs) {
			/*
			 * Only need to compare keys when hs_devnum is NODEV.
			 */
			if ((hs->hs_devnum == NODEV64) &&
			    (hs->hs_key == key_old)) {
				break;
			}
			hs = hs->hs_next;
		}
	}

	if (hs == NULL) {
		/* create a hot spare record */
		if (shs->shs_size_option & MD_CRO_64BIT) {
#if defined(_ILP32)
			return (mdhserror(&shs->mde, MDE_HS_UNIT_TOO_LARGE,
			    shs->shs_hot_spare_pool, shs->shs_component_old));
#else
			recid = mddb_createrec(HS_ONDSK_STR_SIZE, typ1, HS_REC,
				MD_CRO_64BIT | MD_CRO_HOTSPARE, setno);
#endif
		} else {
			recid = mddb_createrec(HS_ONDSK_STR_SIZE, typ1, HS_REC,
				MD_CRO_32BIT | MD_CRO_HOTSPARE, setno);
		}

		if (recid < 0) {
			return (mdhserror(&shs->mde, MDE_HS_CREATE_FAILURE,
			    shs->shs_hot_spare_pool,
			    shs->shs_component_old));
		}

		/* get the addr */
		hs = (hot_spare_t *)mddb_getrecaddr_resize(recid, sizeof (*hs),
			0);

		hs->hs_record_id = recid;

		hs->hs_devnum = shs->shs_component_old;
		hs->hs_key = shs->shs_key_old;
		hs->hs_start_blk = shs->shs_start_blk;
		hs->hs_has_label = shs->shs_has_label;
		hs->hs_number_blks = shs->shs_number_blks;
		set_hot_spare_state(hs, HSS_AVAILABLE);
		hs->hs_refcount = 0;
		hs->hs_next = (hot_spare_t *)md_set[setno].s_hs;
		md_set[setno].s_hs = (void *) hs;
	}

	/* Scan the hot spare pool list */
	hsp = (hot_spare_pool_t *)md_set[setno].s_hsp;
	prev_hsp = (hot_spare_pool_t *)0;
	while (hsp) {
		if (hsp->hsp_self_id == shs->shs_hot_spare_pool) {
			break;
		}
		prev_hsp = hsp;
		hsp = hsp->hsp_next;
	}

	if (hsp == NULL) {
		/* create a hot spare pool record */
		recid = mddb_createrec(sizeof (hot_spare_pool_ond_t),
		    typ1, HSP_REC,
		    MD_CRO_32BIT | MD_CRO_HOTSPARE_POOL | MD_CRO_FN, setno);

		if (recid < 0) {
			return (mdhsperror(&shs->mde, MDE_HSP_CREATE_FAILURE,
			    shs->shs_hot_spare_pool));
		}

		/* get the record addr */
		hsp = (hot_spare_pool_t *)mddb_getrecaddr_resize(recid,
			sizeof (*hsp), HSP_ONDSK_STR_OFF);

		hsp->hsp_self_id = shs->shs_hot_spare_pool;
		hsp->hsp_record_id = recid;
		hsp->hsp_next = (hot_spare_pool_t *)md_set[setno].s_hsp;
		hsp->hsp_refcount = 0;
		hsp->hsp_nhotspares = 0;
		hsp->hsp_revision |= MD_FN_META_DEV;

		/* force prev_hsp to NULL, this will cause hsp to be linked */
		prev_hsp = (hot_spare_pool_t *)0;

		rw_enter(&hotspares_md_ops.md_link_rw.lock, RW_WRITER);
		hsp->hsp_link.ln_next = hotspares_md_ops.md_head;
		hsp->hsp_link.ln_setno = setno;
		hsp->hsp_link.ln_id = hsp->hsp_self_id;
		hotspares_md_ops.md_head = &hsp->hsp_link;
		rw_exit(&hotspares_md_ops.md_link_rw.lock);
		hsp_created = 1;
	} else {

		/*
		 * Make sure the hot spare is not already in the pool.
		 */
		for (i = 0; i < hsp->hsp_nhotspares; i++)
			if (hsp->hsp_hotspares[i] == hs->hs_record_id) {
				return (mdhserror(&shs->mde, MDE_HS_INUSE,
					shs->shs_hot_spare_pool,
					hs->hs_devnum));
			}
		/*
		 * Create a new hot spare pool record
		 * This gives us the one extra hs slot,
		 * because there is one slot in the
		 * hot_spare_pool struct
		 */
		new_size = sizeof (hot_spare_pool_ond_t) +
			(sizeof (mddb_recid_t) * hsp->hsp_nhotspares);

		/*
		 * The Friendly Name status of the new HSP should duplicate
		 * the status of the existing one.
		 */
		if (hsp->hsp_revision & MD_FN_META_DEV) {
			options =
				MD_CRO_32BIT | MD_CRO_HOTSPARE_POOL | MD_CRO_FN;
		} else {
			options = MD_CRO_32BIT | MD_CRO_HOTSPARE_POOL;
		}
		recid = mddb_createrec(new_size, typ1, HSP_REC, options, setno);

		if (recid < 0) {
			return (mdhsperror(&shs->mde, MDE_HSP_CREATE_FAILURE,
			    hsp->hsp_self_id));
		}
		new_size = sizeof (hot_spare_pool_t) +
			(sizeof (mddb_recid_t) * hsp->hsp_nhotspares);

		/* get the record addr */
		new_hsp = (hot_spare_pool_t *)mddb_getrecaddr_resize(recid,
			new_size, HSP_ONDSK_STR_OFF);

		/* copy the old record into the new one */
		bcopy((caddr_t)hsp, (caddr_t)new_hsp,
		    (size_t)((sizeof (hot_spare_pool_t) +
		    (sizeof (mddb_recid_t) * hsp->hsp_nhotspares)
		    - sizeof (mddb_recid_t))));
		new_hsp->hsp_record_id = recid;

		md_rem_link(setno, hsp->hsp_self_id,
		    &hotspares_md_ops.md_link_rw.lock,
		    &hotspares_md_ops.md_head);

		rw_enter(&hotspares_md_ops.md_link_rw.lock, RW_WRITER);
		new_hsp->hsp_link.ln_next = hotspares_md_ops.md_head;
		new_hsp->hsp_link.ln_setno = setno;
		new_hsp->hsp_link.ln_id = new_hsp->hsp_self_id;
		hotspares_md_ops.md_head = &new_hsp->hsp_link;
		rw_exit(&hotspares_md_ops.md_link_rw.lock);

		/* mark the old hsp to be deleted */
		delete_hsp = 1;
		old_hsp = hsp;
		hsp = new_hsp;
	}

	if (shs->shs_size_option & MD_CRO_64BIT) {
		hs->hs_revision |= MD_64BIT_META_DEV;
	} else {
		hs->hs_revision &= ~MD_64BIT_META_DEV;
	}

	/* lock the db records */
	recids[0] = hs->hs_record_id;
	recids[1] = hsp->hsp_record_id;
	irecid = 2;
	if (delete_hsp)
		recids[irecid++] = old_hsp->hsp_record_id;
	recids[irecid] = 0;

	/* increment the reference count */
	hs->hs_refcount++;

	/* add the hs at the end of the hot spare pool */
	hsp->hsp_hotspares[hsp->hsp_nhotspares] = hs->hs_record_id;
	hsp->hsp_nhotspares++;

	/*
	 * NOTE: We do not commit the previous hot spare pool record.
	 *	 There is no need, the link gets rebuilt at boot time.
	 */
	if (prev_hsp)
		prev_hsp->hsp_next = hsp;
	else
		md_set[setno].s_hsp = (void *) hsp;

	if (delete_hsp)
		old_hsp->hsp_self_id = MD_HSP_NONE;

	/* commit the db records */
	mddb_commitrecs_wrapper(recids);

	if (delete_hsp) {
		/* delete the old hot spare pool record */
		mddb_deleterec_wrapper(old_hsp->hsp_record_id);
	}

	if (hsp_created) {
		SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_CREATE, SVM_TAG_HSP, setno,
		    md_expldev(hsp->hsp_self_id));
	}
	SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_ADD, SVM_TAG_HSP, setno,
	    md_expldev(hsp->hsp_self_id));

	return (0);
}
Пример #6
0
static void
load_hotspare(set_t setno, mddb_recid_t recid)
{
	hot_spare_t	*hs;
	mddb_de_ic_t	*dep;
	mddb_rb32_t	*rbp;
	size_t		newreqsize;
	hot_spare_t	*b_hs;
	hot_spare32_od_t *s_hs;

	mddb_setrecprivate(recid, MD_PRV_GOTIT);

	dep = mddb_getrecdep(recid);
	dep->de_flags = MDDB_F_HOTSPARE;
	rbp = dep->de_rb;
	switch (rbp->rb_revision) {
	case MDDB_REV_RB:
	case MDDB_REV_RBFN:
		/*
		 * Needs to convert to internal 64 bit
		 */
		s_hs = (hot_spare32_od_t *)mddb_getrecaddr(recid);
		newreqsize = sizeof (hot_spare_t);
		b_hs = (hot_spare_t *)kmem_zalloc(newreqsize, KM_SLEEP);
		hs_convert((caddr_t)s_hs, (caddr_t)b_hs, SMALL_2_BIG);
		kmem_free(s_hs, dep->de_reqsize);
		dep->de_rb_userdata = b_hs;
		dep->de_reqsize = newreqsize;
		hs = b_hs;
		break;
	case MDDB_REV_RB64:
	case MDDB_REV_RB64FN:
		hs = (hot_spare_t *)mddb_getrecaddr_resize
			(recid, sizeof (*hs), 0);
		break;
	}
	MDDB_NOTE_FN(rbp->rb_revision, hs->hs_revision);

#if defined(_ILP32)
	if (hs->hs_revision & MD_64BIT_META_DEV) {
		char	devname[MD_MAX_CTDLEN];

		set_hot_spare_state(hs, HSS_BROKEN);
		(void) md_devname(setno, hs->hs_devnum, devname,
		    sizeof (devname));
		cmn_err(CE_NOTE, "%s is unavailable because 64 bit hotspares "
		    "are not accessible on a 32 bit kernel\n", devname);
	}
#endif

	ASSERT(hs != NULL);

	if (hs->hs_refcount == 0) {
		mddb_setrecprivate(recid, MD_PRV_PENDDEL);
		return;
	}

	hs->hs_next = (hot_spare_t *)md_set[setno].s_hs;
	md_set[setno].s_hs = (void *)hs;

	hs->hs_isopen = 0;

	hs->hs_devnum = md_getdevnum(setno, mddb_getsidenum(setno),
		hs->hs_key, MD_NOTRUST_DEVT);
}
Пример #7
0
int
stripe_build_incore(void *p, int snarfing)
{
	ms_unit_t *un = (ms_unit_t *)p;
	struct ms_comp	*mdcomp;
	minor_t		mnum;
	int		row;
	int		i;
	int		c;
	int		ncomps;

	mnum = MD_SID(un);

	if (MD_UNIT(mnum) != NULL)
		return (0);

	MD_STATUS(un) = 0;

	/*
	 * Reset all the is_open flags, these are probably set
	 * cause they just came out of the database.
	 */
	mdcomp = (struct ms_comp *)((void *)&((char *)un)[un->un_ocomp]);

	ncomps = 0;
	for (row = 0; row < un->un_nrows; row++) {
		struct ms_row *mdr = &un->un_row[row];
		ncomps += mdr->un_ncomp;
	}

	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;
			set_t			setno;
			md_dev64_t		tmpdev;

			mdc = &mdcomp[c++];
			mdc->un_mirror.ms_flags &=
			    ~(MDM_S_ISOPEN | MDM_S_IOERR | MDM_S_RS_TRIED);

			if (!snarfing)
				continue;

			setno = MD_MIN2SET(mnum);

			tmpdev = md_getdevnum(setno, mddb_getsidenum(setno),
			    mdc->un_key, MD_NOTRUST_DEVT);
			mdc->un_dev = tmpdev;
			/*
			 * Check for hotspares. If the hotspares haven't been
			 * snarfed yet, stripe_open_all_devs() will do the
			 * remapping of the dev's later.
			 */
			if (mdc->un_mirror.ms_hs_id != 0) {
				mdc->un_mirror.ms_orig_dev = mdc->un_dev;
				(void) md_hot_spare_ifc(HS_MKDEV, 0, 0,
				    0, &mdc->un_mirror.ms_hs_id, NULL,
				    &tmpdev, NULL);
				mdc->un_dev = tmpdev;
			}
		}
	}

	/* place various information in the in-core data structures */
	md_nblocks_set(mnum, un->c.un_total_blocks);
	MD_UNIT(mnum) = un;

	return (0);
}
Пример #8
0
static int
stripe_open_all_devs(ms_unit_t *un, int md_oflags)
{
	minor_t		mnum = MD_SID(un);
	int		row;
	int		i;
	int		c;
	struct ms_comp	*mdcomp;
	int		err;
	int		cont_on_errors = (md_oflags & MD_OFLG_CONT_ERRS);
	int		probe_err_cnt = 0;
	int		total_comp_cnt = 0;
	set_t		setno = MD_MIN2SET(MD_SID(un));
	side_t		side = mddb_getsidenum(setno);
	mdkey_t		key;

	mdcomp = (struct ms_comp *)((void *)&((char *)un)[un->un_ocomp]);

	/*
	 * For a probe call, if any component of a stripe or a concat
	 * can be opened, it is considered to be a success. The total number
	 * of components in a stripe are computed prior to starting a probe.
	 * This number is then compared against the number of components
	 * that could be be successfully opened. If none of the components
	 * in a stripe can be opened, only then an ENXIO is returned for a
	 * probe type open.
	 */

	for (row = 0; row < un->un_nrows; row++) {
		struct ms_row *mdr = &un->un_row[row];

		if (md_oflags & MD_OFLG_PROBEDEV)
			total_comp_cnt += mdr->un_ncomp;

		for (i = 0, c = mdr->un_icomp; i < mdr->un_ncomp; i++) {
			struct ms_comp	*mdc;
			md_dev64_t tmpdev;

			mdc = &mdcomp[c++];
			tmpdev = mdc->un_dev;
			/*
			 * Do the open by device id
			 * Check if this comp is hotspared and
			 * if it is then use the key for hotspare.
			 * MN disksets don't use devids, so we better don't use
			 * md_devid_found/md_resolve_bydevid there. Rather do,
			 * what's done in stripe_build_incore()
			 */
			if (MD_MNSET_SETNO(setno)) {
				if (mdc->un_mirror.ms_hs_id != 0) {
					(void) md_hot_spare_ifc(HS_MKDEV, 0, 0,
					    0, &mdc->un_mirror.ms_hs_id, NULL,
					    &tmpdev, NULL);
				}
			} else {
				key = mdc->un_mirror.ms_hs_id ?
				    mdc->un_mirror.ms_hs_key : mdc->un_key;
				if ((md_getmajor(tmpdev) != md_major) &&
				    md_devid_found(setno, side, key) == 1) {
					tmpdev = md_resolve_bydevid(mnum,
					    tmpdev, key);
				}
			}

			/*
			 * For a submirror, we only want to open those devices
			 * that are not errored. If the device is errored then
			 * then there is no reason to open it and leaving it
			 * closed allows the RCM/DR code to work so that the
			 * errored device can be replaced.
			 */
			if ((md_oflags & MD_OFLG_PROBEDEV) ||
			    ! (mdc->un_mirror.ms_state & CS_ERRED)) {

				err = md_layered_open(mnum, &tmpdev, md_oflags);
			} else {
				err = ENXIO;
			}

			/*
			 * Only set the un_dev if the tmpdev != NODEV64. If
			 * it is NODEV64 then the md_layered_open() will have
			 * failed in some manner.
			 */
			if (tmpdev != NODEV64)
				mdc->un_dev = tmpdev;

			if (err) {
				if (!cont_on_errors) {
					stripe_close_all_devs(un, md_oflags);
					return (ENXIO);
				}

				if (md_oflags & MD_OFLG_PROBEDEV)
					probe_err_cnt++;
			} else {
				if (md_oflags & MD_OFLG_PROBEDEV) {
					mdc->un_mirror.ms_flags |=
					    MDM_S_PROBEOPEN;
				} else
					mdc->un_mirror.ms_flags |= MDM_S_ISOPEN;
			}
		}
	}

	/* If every component in a stripe could not be opened fail */
	if ((md_oflags & MD_OFLG_PROBEDEV) &&
	    (probe_err_cnt == total_comp_cnt))
		return (ENXIO);
	else
		return (0);
}