Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/mptutil/mpt_config.c
Show First 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | dehumanize(const char *value) | ||||
return (0); | return (0); | ||||
iv = strtoq(value, &vtp, 0); | iv = strtoq(value, &vtp, 0); | ||||
if (vtp == value || (vtp[0] != '\0' && vtp[1] != '\0')) { | if (vtp == value || (vtp[0] != '\0' && vtp[1] != '\0')) { | ||||
return (0); | return (0); | ||||
} | } | ||||
switch (vtp[0]) { | switch (vtp[0]) { | ||||
case 't': case 'T': | case 't': case 'T': | ||||
iv *= 1024; | iv *= 1024; | ||||
/* FALLTHROUGH */ | |||||
case 'g': case 'G': | case 'g': case 'G': | ||||
iv *= 1024; | iv *= 1024; | ||||
/* FALLTHROUGH */ | |||||
case 'm': case 'M': | case 'm': case 'M': | ||||
iv *= 1024; | iv *= 1024; | ||||
/* FALLTHROUGH */ | |||||
case 'k': case 'K': | case 'k': case 'K': | ||||
iv *= 1024; | iv *= 1024; | ||||
/* FALLTHROUGH */ | |||||
case '\0': | case '\0': | ||||
break; | break; | ||||
default: | default: | ||||
return (0); | return (0); | ||||
} | } | ||||
return (iv); | return (iv); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 155 Lines • ▼ Show 20 Lines | if (fd < 0) { | ||||
warn("mpt_open"); | warn("mpt_open"); | ||||
return (error); | return (error); | ||||
} | } | ||||
ioc2 = mpt_read_ioc_page(fd, 2, NULL); | ioc2 = mpt_read_ioc_page(fd, 2, NULL); | ||||
if (ioc2 == NULL) { | if (ioc2 == NULL) { | ||||
error = errno; | error = errno; | ||||
warn("Failed to fetch volume list"); | warn("Failed to fetch volume list"); | ||||
close(fd); | |||||
return (error); | return (error); | ||||
} | } | ||||
/* Lock all the volumes first. */ | /* Lock all the volumes first. */ | ||||
vol = ioc2->RaidVolume; | vol = ioc2->RaidVolume; | ||||
for (i = 0; i < ioc2->NumActiveVolumes; vol++, i++) { | for (i = 0; i < ioc2->NumActiveVolumes; vol++, i++) { | ||||
if (mpt_lock_volume(vol->VolumeBus, vol->VolumeID) < 0) { | if (mpt_lock_volume(vol->VolumeBus, vol->VolumeID) < 0) { | ||||
warnx("Volume %s is busy and cannot be deleted", | warnx("Volume %s is busy and cannot be deleted", | ||||
mpt_volume_name(vol->VolumeBus, vol->VolumeID)); | mpt_volume_name(vol->VolumeBus, vol->VolumeID)); | ||||
free(ioc2); | |||||
close(fd); | |||||
return (EBUSY); | return (EBUSY); | ||||
} | } | ||||
} | } | ||||
printf( | printf( | ||||
"Are you sure you wish to clear the configuration on mpt%u? [y/N] ", | "Are you sure you wish to clear the configuration on mpt%u? [y/N] ", | ||||
mpt_unit); | mpt_unit); | ||||
ch = getchar(); | ch = getchar(); | ||||
if (ch != 'y' && ch != 'Y') { | if (ch != 'y' && ch != 'Y') { | ||||
printf("\nAborting\n"); | printf("\nAborting\n"); | ||||
free(ioc2); | |||||
close(fd); | |||||
return (0); | return (0); | ||||
} | } | ||||
/* Delete all the volumes. */ | /* Delete all the volumes. */ | ||||
vol = ioc2->RaidVolume; | vol = ioc2->RaidVolume; | ||||
for (i = 0; i < ioc2->NumActiveVolumes; vol++, i++) { | for (i = 0; i < ioc2->NumActiveVolumes; vol++, i++) { | ||||
error = mpt_raid_action(fd, MPI_RAID_ACTION_DELETE_VOLUME, | error = mpt_raid_action(fd, MPI_RAID_ACTION_DELETE_VOLUME, | ||||
vol->VolumeBus, vol->VolumeID, 0, | vol->VolumeBus, vol->VolumeID, 0, | ||||
▲ Show 20 Lines • Show All 278 Lines • ▼ Show 20 Lines | build_volume(int fd, struct volume_info *info, int raid_type, long stripe_size, | ||||
* chop off the max to be simple. | * chop off the max to be simple. | ||||
*/ | */ | ||||
MinLBA -= (512 * 1024 * 1024) / 512; | MinLBA -= (512 * 1024 * 1024) / 512; | ||||
switch (raid_type) { | switch (raid_type) { | ||||
case RT_RAID0: | case RT_RAID0: | ||||
vol->VolumeType = MPI_RAID_VOL_TYPE_IS; | vol->VolumeType = MPI_RAID_VOL_TYPE_IS; | ||||
vol->StripeSize = stripe_size / 512; | vol->StripeSize = stripe_size / 512; | ||||
MaxLBA = MinLBA * info->drive_count; | MaxLBA = (uint64_t)MinLBA * info->drive_count; | ||||
break; | break; | ||||
case RT_RAID1: | case RT_RAID1: | ||||
vol->VolumeType = MPI_RAID_VOL_TYPE_IM; | vol->VolumeType = MPI_RAID_VOL_TYPE_IM; | ||||
MaxLBA = MinLBA * (info->drive_count / 2); | MaxLBA = (uint64_t)MinLBA * (info->drive_count / 2); | ||||
break; | break; | ||||
case RT_RAID1E: | case RT_RAID1E: | ||||
vol->VolumeType = MPI_RAID_VOL_TYPE_IME; | vol->VolumeType = MPI_RAID_VOL_TYPE_IME; | ||||
vol->StripeSize = stripe_size / 512; | vol->StripeSize = stripe_size / 512; | ||||
MaxLBA = MinLBA * info->drive_count / 2; | MaxLBA = (uint64_t)MinLBA * info->drive_count / 2; | ||||
break; | break; | ||||
default: | default: | ||||
/* Pacify gcc. */ | /* Pacify gcc. */ | ||||
abort(); | abort(); | ||||
} | } | ||||
/* | /* | ||||
* If the controller doesn't support 64-bit addressing and the | * If the controller doesn't support 64-bit addressing and the | ||||
▲ Show 20 Lines • Show All 62 Lines • ▼ Show 20 Lines | #endif | ||||
for (i = 0; raid_type_table[i].name != NULL; i++) | for (i = 0; raid_type_table[i].name != NULL; i++) | ||||
if (strcasecmp(raid_type_table[i].name, av[1]) == 0) { | if (strcasecmp(raid_type_table[i].name, av[1]) == 0) { | ||||
raid_type = raid_type_table[i].raid_type; | raid_type = raid_type_table[i].raid_type; | ||||
break; | break; | ||||
} | } | ||||
if (raid_type == -1) { | if (raid_type == -1) { | ||||
warnx("Unknown or unsupported volume type %s", av[1]); | warnx("Unknown or unsupported volume type %s", av[1]); | ||||
close(fd); | |||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
/* Parse any options. */ | /* Parse any options. */ | ||||
optind = 2; | optind = 2; | ||||
#ifdef DEBUG | #ifdef DEBUG | ||||
dump = 0; | dump = 0; | ||||
#endif | #endif | ||||
Show All 10 Lines | |||||
#endif | #endif | ||||
case 'q': | case 'q': | ||||
quick = 1; | quick = 1; | ||||
break; | break; | ||||
case 's': | case 's': | ||||
stripe_size = dehumanize(optarg); | stripe_size = dehumanize(optarg); | ||||
if ((stripe_size < 512) || (!powerof2(stripe_size))) { | if ((stripe_size < 512) || (!powerof2(stripe_size))) { | ||||
warnx("Invalid stripe size %s", optarg); | warnx("Invalid stripe size %s", optarg); | ||||
close(fd); | |||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
break; | break; | ||||
case 'v': | case 'v': | ||||
verbose = 1; | verbose = 1; | ||||
break; | break; | ||||
case '?': | case '?': | ||||
default: | default: | ||||
close(fd); | |||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
} | } | ||||
ac -= optind; | ac -= optind; | ||||
av += optind; | av += optind; | ||||
/* Fetch existing config data. */ | /* Fetch existing config data. */ | ||||
state.ioc2 = mpt_read_ioc_page(fd, 2, NULL); | state.ioc2 = mpt_read_ioc_page(fd, 2, NULL); | ||||
if (state.ioc2 == NULL) { | if (state.ioc2 == NULL) { | ||||
error = errno; | error = errno; | ||||
warn("Failed to read volume list"); | warn("Failed to read volume list"); | ||||
close(fd); | |||||
return (error); | return (error); | ||||
} | } | ||||
state.list = mpt_pd_list(fd); | state.list = mpt_pd_list(fd); | ||||
if (state.list == NULL) | if (state.list == NULL) { | ||||
close(fd); | |||||
return (errno); | return (errno); | ||||
} | |||||
error = mpt_fetch_disks(fd, &state.nsdisks, &state.sdisks); | error = mpt_fetch_disks(fd, &state.nsdisks, &state.sdisks); | ||||
if (error) { | if (error) { | ||||
warn("Failed to fetch standalone disk list"); | warn("Failed to fetch standalone disk list"); | ||||
close(fd); | |||||
return (error); | return (error); | ||||
} | } | ||||
state.target_id = 0xff; | state.target_id = 0xff; | ||||
/* Parse the drive list. */ | /* Parse the drive list. */ | ||||
if (ac != 1) { | if (ac != 1) { | ||||
warnx("Exactly one drive list is required"); | warnx("Exactly one drive list is required"); | ||||
close(fd); | |||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
info = calloc(1, sizeof(*info)); | info = calloc(1, sizeof(*info)); | ||||
if (info == NULL) | if (info == NULL) { | ||||
close(fd); | |||||
return (ENOMEM); | return (ENOMEM); | ||||
} | |||||
error = parse_volume(fd, raid_type, &state, av[0], info); | error = parse_volume(fd, raid_type, &state, av[0], info); | ||||
if (error) | if (error) { | ||||
free(info); | |||||
close(fd); | |||||
return (error); | return (error); | ||||
} | |||||
/* Create RAID physdisk pages for standalone disks. */ | /* Create RAID physdisk pages for standalone disks. */ | ||||
error = add_drives(fd, info, verbose); | error = add_drives(fd, info, verbose); | ||||
if (error) | if (error) { | ||||
free(info); | |||||
close(fd); | |||||
return (error); | return (error); | ||||
} | |||||
/* Build the volume. */ | /* Build the volume. */ | ||||
vol = build_volume(fd, info, raid_type, stripe_size, &state, verbose); | vol = build_volume(fd, info, raid_type, stripe_size, &state, verbose); | ||||
if (vol == NULL) | if (vol == NULL) { | ||||
free(info); | |||||
close(fd); | |||||
return (errno); | return (errno); | ||||
} | |||||
#ifdef DEBUG | #ifdef DEBUG | ||||
if (dump) { | if (dump) { | ||||
dump_config(vol); | dump_config(vol); | ||||
goto skip; | goto skip; | ||||
} | } | ||||
#endif | #endif | ||||
/* Send the new volume to the controller. */ | /* Send the new volume to the controller. */ | ||||
error = mpt_raid_action(fd, MPI_RAID_ACTION_CREATE_VOLUME, vol->VolumeBus, | error = mpt_raid_action(fd, MPI_RAID_ACTION_CREATE_VOLUME, vol->VolumeBus, | ||||
vol->VolumeID, 0, quick ? MPI_RAID_ACTION_ADATA_DO_NOT_SYNC : 0, | vol->VolumeID, 0, quick ? MPI_RAID_ACTION_ADATA_DO_NOT_SYNC : 0, | ||||
vol, vol->Header.PageLength * 4, NULL, NULL, 0, NULL, NULL, 1); | vol, vol->Header.PageLength * 4, NULL, NULL, 0, NULL, NULL, 1); | ||||
if (error) { | if (error) { | ||||
errno = error; | errno = error; | ||||
warn("Failed to add volume"); | warn("Failed to add volume"); | ||||
free(info); | |||||
close(fd); | |||||
return (error); | return (error); | ||||
} | } | ||||
#ifdef DEBUG | #ifdef DEBUG | ||||
skip: | skip: | ||||
#endif | #endif | ||||
mpt_rescan_bus(vol->VolumeBus, vol->VolumeID); | mpt_rescan_bus(vol->VolumeBus, vol->VolumeID); | ||||
Show All 25 Lines | if (fd < 0) { | ||||
error = errno; | error = errno; | ||||
warn("mpt_open"); | warn("mpt_open"); | ||||
return (error); | return (error); | ||||
} | } | ||||
error = mpt_lookup_volume(fd, av[1], &VolumeBus, &VolumeID); | error = mpt_lookup_volume(fd, av[1], &VolumeBus, &VolumeID); | ||||
if (error) { | if (error) { | ||||
warnc(error, "Invalid volume %s", av[1]); | warnc(error, "Invalid volume %s", av[1]); | ||||
close(fd); | |||||
return (error); | return (error); | ||||
} | } | ||||
if (mpt_lock_volume(VolumeBus, VolumeID) < 0) | if (mpt_lock_volume(VolumeBus, VolumeID) < 0) { | ||||
close(fd); | |||||
return (errno); | return (errno); | ||||
} | |||||
error = mpt_raid_action(fd, MPI_RAID_ACTION_DELETE_VOLUME, VolumeBus, | error = mpt_raid_action(fd, MPI_RAID_ACTION_DELETE_VOLUME, VolumeBus, | ||||
VolumeID, 0, MPI_RAID_ACTION_ADATA_DEL_PHYS_DISKS | | VolumeID, 0, MPI_RAID_ACTION_ADATA_DEL_PHYS_DISKS | | ||||
MPI_RAID_ACTION_ADATA_ZERO_LBA0, NULL, 0, NULL, NULL, 0, NULL, | MPI_RAID_ACTION_ADATA_ZERO_LBA0, NULL, 0, NULL, NULL, 0, NULL, | ||||
NULL, 0); | NULL, 0); | ||||
if (error) { | if (error) { | ||||
warnc(error, "Failed to delete volume"); | warnc(error, "Failed to delete volume"); | ||||
close(fd); | |||||
return (error); | return (error); | ||||
} | } | ||||
mpt_rescan_bus(-1, -1); | mpt_rescan_bus(-1, -1); | ||||
close(fd); | close(fd); | ||||
return (0); | return (0); | ||||
} | } | ||||
Show All 21 Lines | find_volume_spare_pool(int fd, const char *name, int *pool) | ||||
/* | /* | ||||
* Check for an existing pool other than pool 0 (used for | * Check for an existing pool other than pool 0 (used for | ||||
* global spares). | * global spares). | ||||
*/ | */ | ||||
if ((info->VolumeSettings.HotSparePool & ~MPI_RAID_HOT_SPARE_POOL_0) != | if ((info->VolumeSettings.HotSparePool & ~MPI_RAID_HOT_SPARE_POOL_0) != | ||||
0) { | 0) { | ||||
*pool = 1 << (ffs(info->VolumeSettings.HotSparePool & | *pool = 1 << (ffs(info->VolumeSettings.HotSparePool & | ||||
~MPI_RAID_HOT_SPARE_POOL_0) - 1); | ~MPI_RAID_HOT_SPARE_POOL_0) - 1); | ||||
free(info); | |||||
return (0); | return (0); | ||||
} | } | ||||
free(info); | free(info); | ||||
/* | /* | ||||
* Try to find a free pool. First, figure out which pools are | * Try to find a free pool. First, figure out which pools are | ||||
* in use. | * in use. | ||||
*/ | */ | ||||
Show All 29 Lines | if (info == NULL) | ||||
return (error); | return (error); | ||||
info->VolumeSettings.HotSparePool |= (1 << new_pool); | info->VolumeSettings.HotSparePool |= (1 << new_pool); | ||||
error = mpt_raid_action(fd, MPI_RAID_ACTION_CHANGE_VOLUME_SETTINGS, | error = mpt_raid_action(fd, MPI_RAID_ACTION_CHANGE_VOLUME_SETTINGS, | ||||
VolumeBus, VolumeID, 0, *(U32 *)&info->VolumeSettings, NULL, 0, | VolumeBus, VolumeID, 0, *(U32 *)&info->VolumeSettings, NULL, 0, | ||||
NULL, NULL, 0, NULL, NULL, 0); | NULL, NULL, 0, NULL, NULL, 0); | ||||
if (error) { | if (error) { | ||||
warnx("Failed to add spare pool %d to %s", new_pool, | warnx("Failed to add spare pool %d to %s", new_pool, | ||||
mpt_volume_name(VolumeBus, VolumeID)); | mpt_volume_name(VolumeBus, VolumeID)); | ||||
free(info); | |||||
return (error); | return (error); | ||||
} | } | ||||
free(info); | free(info); | ||||
*pool = (1 << new_pool); | *pool = (1 << new_pool); | ||||
return (0); | return (0); | ||||
} | } | ||||
Show All 19 Lines | add_spare(int ac, char **av) | ||||
if (fd < 0) { | if (fd < 0) { | ||||
error = errno; | error = errno; | ||||
warn("mpt_open"); | warn("mpt_open"); | ||||
return (error); | return (error); | ||||
} | } | ||||
if (ac == 3) { | if (ac == 3) { | ||||
error = find_volume_spare_pool(fd, av[2], &pool); | error = find_volume_spare_pool(fd, av[2], &pool); | ||||
if (error) | if (error) { | ||||
close(fd); | |||||
return (error); | return (error); | ||||
} | |||||
} else | } else | ||||
pool = MPI_RAID_HOT_SPARE_POOL_0; | pool = MPI_RAID_HOT_SPARE_POOL_0; | ||||
list = mpt_pd_list(fd); | list = mpt_pd_list(fd); | ||||
if (list == NULL) | if (list == NULL) | ||||
return (errno); | return (errno); | ||||
error = mpt_lookup_drive(list, av[1], &PhysDiskNum); | error = mpt_lookup_drive(list, av[1], &PhysDiskNum); | ||||
if (error) { | if (error) { | ||||
error = mpt_fetch_disks(fd, &nsdisks, &sdisks); | error = mpt_fetch_disks(fd, &nsdisks, &sdisks); | ||||
if (error != 0) { | if (error != 0) { | ||||
warn("Failed to fetch standalone disk list"); | warn("Failed to fetch standalone disk list"); | ||||
mpt_free_pd_list(list); | |||||
mpt_free_pd_list(list); | |||||
close(fd); | |||||
return (error); | return (error); | ||||
} | } | ||||
if (mpt_lookup_standalone_disk(av[1], sdisks, nsdisks, &i) < | if (mpt_lookup_standalone_disk(av[1], sdisks, nsdisks, &i) < | ||||
0) { | 0) { | ||||
error = errno; | error = errno; | ||||
warn("Unable to lookup drive %s", av[1]); | warn("Unable to lookup drive %s", av[1]); | ||||
mpt_free_pd_list(list); | |||||
mpt_free_pd_list(list); | |||||
close(fd); | |||||
return (error); | return (error); | ||||
} | } | ||||
if (mpt_lock_physdisk(&sdisks[i]) < 0) | if (mpt_lock_physdisk(&sdisks[i]) < 0) { | ||||
mpt_free_pd_list(list); | |||||
mpt_free_pd_list(list); | |||||
close(fd); | |||||
return (errno); | return (errno); | ||||
} | |||||
if (mpt_create_physdisk(fd, &sdisks[i], &PhysDiskNum) < 0) { | if (mpt_create_physdisk(fd, &sdisks[i], &PhysDiskNum) < 0) { | ||||
error = errno; | error = errno; | ||||
warn("Failed to create physical disk page"); | warn("Failed to create physical disk page"); | ||||
mpt_free_pd_list(list); | |||||
mpt_free_pd_list(list); | |||||
close(fd); | |||||
return (error); | return (error); | ||||
} | } | ||||
free(sdisks); | free(sdisks); | ||||
} | } | ||||
mpt_free_pd_list(list); | mpt_free_pd_list(list); | ||||
info = mpt_pd_info(fd, PhysDiskNum, NULL); | info = mpt_pd_info(fd, PhysDiskNum, NULL); | ||||
if (info == NULL) { | if (info == NULL) { | ||||
error = errno; | error = errno; | ||||
warn("Failed to fetch drive info"); | warn("Failed to fetch drive info"); | ||||
close(fd); | |||||
return (error); | return (error); | ||||
} | } | ||||
info->PhysDiskSettings.HotSparePool = pool; | info->PhysDiskSettings.HotSparePool = pool; | ||||
error = mpt_raid_action(fd, MPI_RAID_ACTION_CHANGE_PHYSDISK_SETTINGS, 0, | error = mpt_raid_action(fd, MPI_RAID_ACTION_CHANGE_PHYSDISK_SETTINGS, 0, | ||||
0, PhysDiskNum, *(U32 *)&info->PhysDiskSettings, NULL, 0, NULL, | 0, PhysDiskNum, *(U32 *)&info->PhysDiskSettings, NULL, 0, NULL, | ||||
NULL, 0, NULL, NULL, 0); | NULL, 0, NULL, NULL, 0); | ||||
if (error) { | if (error) { | ||||
warnc(error, "Failed to assign spare"); | warnc(error, "Failed to assign spare"); | ||||
close(fd); | |||||
return (error); | return (error); | ||||
} | } | ||||
free(info); | free(info); | ||||
close(fd); | close(fd); | ||||
return (0); | return (0); | ||||
} | } | ||||
Show All 15 Lines | remove_spare(int ac, char **av) | ||||
fd = mpt_open(mpt_unit); | fd = mpt_open(mpt_unit); | ||||
if (fd < 0) { | if (fd < 0) { | ||||
error = errno; | error = errno; | ||||
warn("mpt_open"); | warn("mpt_open"); | ||||
return (error); | return (error); | ||||
} | } | ||||
list = mpt_pd_list(fd); | list = mpt_pd_list(fd); | ||||
if (list == NULL) | if (list == NULL) { | ||||
close(fd); | |||||
return (errno); | return (errno); | ||||
} | |||||
error = mpt_lookup_drive(list, av[1], &PhysDiskNum); | error = mpt_lookup_drive(list, av[1], &PhysDiskNum); | ||||
if (error) { | if (error) { | ||||
warn("Failed to find drive %s", av[1]); | warn("Failed to find drive %s", av[1]); | ||||
close(fd); | |||||
return (error); | return (error); | ||||
} | } | ||||
mpt_free_pd_list(list); | mpt_free_pd_list(list); | ||||
info = mpt_pd_info(fd, PhysDiskNum, NULL); | info = mpt_pd_info(fd, PhysDiskNum, NULL); | ||||
if (info == NULL) { | if (info == NULL) { | ||||
error = errno; | error = errno; | ||||
warn("Failed to fetch drive info"); | warn("Failed to fetch drive info"); | ||||
close(fd); | |||||
return (error); | return (error); | ||||
} | } | ||||
if (info->PhysDiskSettings.HotSparePool == 0) { | if (info->PhysDiskSettings.HotSparePool == 0) { | ||||
warnx("Drive %u is not a hot spare", PhysDiskNum); | warnx("Drive %u is not a hot spare", PhysDiskNum); | ||||
free(info); | |||||
close(fd); | |||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
if (mpt_delete_physdisk(fd, PhysDiskNum) < 0) { | if (mpt_delete_physdisk(fd, PhysDiskNum) < 0) { | ||||
error = errno; | error = errno; | ||||
warn("Failed to delete physical disk page"); | warn("Failed to delete physical disk page"); | ||||
free(info); | |||||
close(fd); | |||||
return (error); | return (error); | ||||
} | } | ||||
mpt_rescan_bus(info->PhysDiskBus, info->PhysDiskID); | mpt_rescan_bus(info->PhysDiskBus, info->PhysDiskID); | ||||
free(info); | free(info); | ||||
close(fd); | close(fd); | ||||
return (0); | return (0); | ||||
▲ Show 20 Lines • Show All 177 Lines • Show Last 20 Lines |