コード例 #1
0
ファイル: mpt_drive.c プロジェクト: 2trill2spill/freebsd
/*
 * There are several ways to enumerate physical disks.  Unfortunately,
 * none of them are truly complete, so we have to build a union of all of
 * them.  Specifically:
 * 
 * - IOC2 : This gives us a list of volumes, and by walking the volumes we
 *          can enumerate all of the drives attached to volumes including
 *          online drives and failed drives.
 * - IOC3 : This gives us a list of all online physical drives including
 *          drives that are not part of a volume nor a spare drive.  It
 *          does not include any failed drives.
 * - IOC5 : This gives us a list of all spare drives including failed
 *          spares.
 *
 * The specific edge cases are that 1) a failed volume member can only be
 * found via IOC2, 2) a drive that is neither a volume member nor a spare
 * can only be found via IOC3, and 3) a failed spare can only be found via
 * IOC5.
 *
 * To handle this, walk all of the three lists and use the following
 * routine to add each drive encountered.  It quietly succeeds if the
 * drive is already present in the list.  It also sorts the list as it
 * inserts new drives.
 */
static int
mpt_pd_insert(int fd, struct mpt_drive_list *list, U8 PhysDiskNum)
{
	int i, j;

	/*
	 * First, do a simple linear search to see if we have already
	 * seen this drive.
	 */
	for (i = 0; i < list->ndrives; i++) {
		if (list->drives[i]->PhysDiskNum == PhysDiskNum)
			return (0);
		if (list->drives[i]->PhysDiskNum > PhysDiskNum)
			break;
	}

	/*
	 * 'i' is our slot for the 'new' drive.  Make room and then
	 * read the drive info.
	 */
	for (j = list->ndrives - 1; j >= i; j--)
		list->drives[j + 1] = list->drives[j];
	list->drives[i] = mpt_pd_info(fd, PhysDiskNum, NULL);
	if (list->drives[i] == NULL)
		return (errno);
	list->ndrives++;
	return (0);
}
コード例 #2
0
ファイル: mpt_drive.c プロジェクト: FreeBSDFoundation/freebsd
/* Helper function to set a drive to a given state. */
static int
drive_set_state(char *drive, U8 Action, U8 State, const char *name)
{
	CONFIG_PAGE_RAID_PHYS_DISK_0 *info;
	struct mpt_drive_list *list;
	U8 PhysDiskNum;
	int error, fd;

	fd = mpt_open(mpt_unit);
	if (fd < 0) {
		error = errno;
		warn("mpt_open");
		return (error);
	}

	list = mpt_pd_list(fd);
	if (list == NULL) {
		close(fd);
		return (errno);
	}

	if (mpt_lookup_drive(list, drive, &PhysDiskNum) < 0) {
		error = errno;
		warn("Failed to find drive %s", drive);
		close(fd);
		return (error);
	}
	mpt_free_pd_list(list);

	/* Get the info for this drive. */
	info = mpt_pd_info(fd, PhysDiskNum, NULL);
	if (info == NULL) {
		error = errno;
		warn("Failed to fetch info for drive %u", PhysDiskNum);
		close(fd);
		return (error);
	}

	/* Try to change the state. */
	if (info->PhysDiskStatus.State == State) {
		warnx("Drive %u is already in the desired state", PhysDiskNum);
		free(info);
		close(fd);
		return (EINVAL);
	}

	error = mpt_raid_action(fd, Action, 0, 0, PhysDiskNum, 0, NULL, 0, NULL,
	    NULL, 0, NULL, NULL, 0);
	if (error) {
		warnc(error, "Failed to set drive %u to %s", PhysDiskNum, name);
		free(info);
		close(fd);
		return (error);
	}

	free(info);
	close(fd);

	return (0);
}
コード例 #3
0
ファイル: mpt_show.c プロジェクト: 2trill2spill/freebsd
static int
show_physdisks(int ac, char **av)
{
	CONFIG_PAGE_RAID_PHYS_DISK_0 *pinfo;
	U16 IOCStatus;
	int error, fd, i;

	if (ac != 1) {
		warnx("show drives: extra arguments");
		return (EINVAL);
	}

	fd = mpt_open(mpt_unit);
	if (fd < 0) {
		error = errno;
		warn("mpt_open");
		return (error);
	}

	/* Try to find each possible phys disk page. */
	for (i = 0; i <= 0xff; i++) {
		pinfo = mpt_pd_info(fd, i, &IOCStatus);
		if (pinfo == NULL) {
			if ((IOCStatus & MPI_IOCSTATUS_MASK) !=
			    MPI_IOCSTATUS_CONFIG_INVALID_PAGE)
				warnx("mpt_pd_info(%d): %s", i,
				    mpt_ioc_status(IOCStatus));
			continue;
		}
		printf("%3u ", i);
		print_pd(pinfo, -1, 1);
		printf("\n");
	}

	close(fd);

	return (0);
}
コード例 #4
0
ファイル: mpt_show.c プロジェクト: 2trill2spill/freebsd
static int
show_config(int ac, char **av)
{
	CONFIG_PAGE_IOC_2 *ioc2;
	CONFIG_PAGE_IOC_2_RAID_VOL *vol;
	CONFIG_PAGE_IOC_5 *ioc5;
	IOC_5_HOT_SPARE *spare;
	CONFIG_PAGE_RAID_VOL_0 *vinfo;
	RAID_VOL0_PHYS_DISK *disk;
	CONFIG_PAGE_RAID_VOL_1 *vnames;
	CONFIG_PAGE_RAID_PHYS_DISK_0 *pinfo;
	struct mpt_standalone_disk *sdisks;
	int error, fd, i, j, nsdisks;

	if (ac != 1) {
		warnx("show config: extra arguments");
		return (EINVAL);
	}

	fd = mpt_open(mpt_unit);
	if (fd < 0) {
		error = errno;
		warn("mpt_open");
		return (error);
	}

	/* Get the config from the controller. */
	ioc2 = mpt_read_ioc_page(fd, 2, NULL);
	ioc5 = mpt_read_ioc_page(fd, 5, NULL);
	if (ioc2 == NULL || ioc5 == NULL) {
		error = errno;
		warn("Failed to get config");
		return (error);
	}
	if (mpt_fetch_disks(fd, &nsdisks, &sdisks) < 0) {
		error = errno;
		warn("Failed to get standalone drive list");
		return (error);
	}

	/* Dump out the configuration. */
	printf("mpt%d Configuration: %d volumes, %d drives\n",
	    mpt_unit, ioc2->NumActiveVolumes, ioc2->NumActivePhysDisks +
	    nsdisks);
	vol = ioc2->RaidVolume;
	for (i = 0; i < ioc2->NumActiveVolumes; vol++, i++) {
		printf("    volume %s ", mpt_volume_name(vol->VolumeBus,
		    vol->VolumeID));
		vinfo = mpt_vol_info(fd, vol->VolumeBus, vol->VolumeID, NULL);
		if (vinfo == NULL) {
			printf("%s UNKNOWN", mpt_raid_level(vol->VolumeType));
		} else
			print_vol(vinfo, -1);
		vnames = mpt_vol_names(fd, vol->VolumeBus, vol->VolumeID, NULL);
		if (vnames != NULL) {
			if (vnames->Name[0] != '\0')
				printf(" <%s>", vnames->Name);
			free(vnames);
		}
		if (vinfo == NULL) {
			printf("\n");
			continue;
		}
		printf(" spans:\n");
		disk = vinfo->PhysDisk;
		for (j = 0; j < vinfo->NumPhysDisks; disk++, j++) {
			printf("        drive %u ", disk->PhysDiskNum);
			pinfo = mpt_pd_info(fd, disk->PhysDiskNum, NULL);
			if (pinfo != NULL) {
				print_pd(pinfo, -1, 0);
				free(pinfo);
			}
			printf("\n");
		}
		if (vinfo->VolumeSettings.HotSparePool != 0) {
			printf("        spare pools: ");
			print_spare_pools(vinfo->VolumeSettings.HotSparePool);
			printf("\n");
		}
		free(vinfo);
	}

	spare = ioc5->HotSpare;
	for (i = 0; i < ioc5->NumHotSpares; spare++, i++) {
		printf("    spare %u ", spare->PhysDiskNum);
		pinfo = mpt_pd_info(fd, spare->PhysDiskNum, NULL);
		if (pinfo != NULL) {
			print_pd(pinfo, -1, 0);
			free(pinfo);
		}
		printf(" backs pool %d\n", ffs(spare->HotSparePool) - 1);
	}
	for (i = 0; i < nsdisks; i++) {
		printf("    drive %s ", sdisks[i].devname);
		print_standalone(&sdisks[i], -1, 0);
		printf("\n");
	}
	free(ioc2);
	free(ioc5);
	free(sdisks);
	close(fd);

	return (0);
}