mpt_volume.c revision 256281
1214501Srpaulo/*- 2214501Srpaulo * Copyright (c) 2008 Yahoo!, Inc. 3252726Srpaulo * All rights reserved. 4214501Srpaulo * Written by: John Baldwin <jhb@FreeBSD.org> 5252726Srpaulo * 6252726Srpaulo * Redistribution and use in source and binary forms, with or without 7214501Srpaulo * modification, are permitted provided that the following conditions 8214501Srpaulo * are met: 9214501Srpaulo * 1. Redistributions of source code must retain the above copyright 10214501Srpaulo * notice, this list of conditions and the following disclaimer. 11214501Srpaulo * 2. Redistributions in binary form must reproduce the above copyright 12252726Srpaulo * notice, this list of conditions and the following disclaimer in the 13214501Srpaulo * documentation and/or other materials provided with the distribution. 14214501Srpaulo * 3. Neither the name of the author nor the names of any co-contributors 15214501Srpaulo * may be used to endorse or promote products derived from this software 16214501Srpaulo * without specific prior written permission. 17214501Srpaulo * 18214501Srpaulo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19214501Srpaulo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20214501Srpaulo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21214501Srpaulo * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22214501Srpaulo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23214501Srpaulo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24214501Srpaulo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25214501Srpaulo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26214501Srpaulo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27214501Srpaulo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28214501Srpaulo * SUCH DAMAGE. 29214501Srpaulo */ 30214501Srpaulo 31214501Srpaulo#include <sys/cdefs.h> 32214501Srpaulo__RCSID("$FreeBSD: stable/10/usr.sbin/mptutil/mpt_volume.c 215046 2010-11-09 19:28:06Z jhb $"); 33214501Srpaulo 34214501Srpaulo#include <sys/param.h> 35214501Srpaulo#include <sys/errno.h> 36214501Srpaulo#include <err.h> 37214501Srpaulo#include <libutil.h> 38214501Srpaulo#include <stdio.h> 39214501Srpaulo#include <stdlib.h> 40214501Srpaulo#include <string.h> 41214501Srpaulo#include <unistd.h> 42214501Srpaulo#include <ctype.h> 43214501Srpaulo#include "mptutil.h" 44214501Srpaulo 45214501SrpauloMPT_TABLE(top, volume); 46214501Srpaulo 47214501Srpauloconst char * 48214501Srpaulompt_volstate(U8 State) 49214501Srpaulo{ 50252726Srpaulo static char buf[16]; 51214501Srpaulo 52214501Srpaulo switch (State) { 53214501Srpaulo case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL: 54214501Srpaulo return ("OPTIMAL"); 55214501Srpaulo case MPI_RAIDVOL0_STATUS_STATE_DEGRADED: 56214501Srpaulo return ("DEGRADED"); 57214501Srpaulo case MPI_RAIDVOL0_STATUS_STATE_FAILED: 58214501Srpaulo return ("FAILED"); 59214501Srpaulo case MPI_RAIDVOL0_STATUS_STATE_MISSING: 60214501Srpaulo return ("MISSING"); 61214501Srpaulo default: 62214501Srpaulo sprintf(buf, "VSTATE 0x%02x", State); 63214501Srpaulo return (buf); 64214501Srpaulo } 65214501Srpaulo} 66214501Srpaulo 67214501Srpaulostatic int 68214501Srpaulovolume_name(int ac, char **av) 69214501Srpaulo{ 70214501Srpaulo CONFIG_PAGE_RAID_VOL_1 *vnames; 71214501Srpaulo U8 VolumeBus, VolumeID; 72214501Srpaulo int error, fd; 73214501Srpaulo 74214501Srpaulo if (ac != 3) { 75214501Srpaulo warnx("name: volume and name required"); 76214501Srpaulo return (EINVAL); 77214501Srpaulo } 78214501Srpaulo 79214501Srpaulo if (strlen(av[2]) >= sizeof(vnames->Name)) { 80214501Srpaulo warnx("name: new name is too long"); 81214501Srpaulo return (ENOSPC); 82214501Srpaulo } 83214501Srpaulo 84214501Srpaulo fd = mpt_open(mpt_unit); 85214501Srpaulo if (fd < 0) { 86214501Srpaulo error = errno; 87214501Srpaulo warn("mpt_open"); 88214501Srpaulo return (error); 89214501Srpaulo } 90214501Srpaulo 91214501Srpaulo error = mpt_lookup_volume(fd, av[1], &VolumeBus, &VolumeID); 92214501Srpaulo if (error) { 93214501Srpaulo warnc(error, "Invalid volume: %s", av[1]); 94214501Srpaulo return (error); 95214501Srpaulo } 96214501Srpaulo 97214501Srpaulo vnames = mpt_vol_names(fd, VolumeBus, VolumeID, NULL); 98214501Srpaulo if (vnames == NULL) { 99214501Srpaulo error = errno; 100214501Srpaulo warn("Failed to fetch volume names"); 101214501Srpaulo return (error); 102214501Srpaulo } 103214501Srpaulo 104214501Srpaulo if (vnames->Header.PageType != MPI_CONFIG_PAGEATTR_CHANGEABLE) { 105214501Srpaulo warnx("Volume name is read only"); 106214501Srpaulo return (EOPNOTSUPP); 107214501Srpaulo } 108214501Srpaulo printf("mpt%u changing volume %s name from \"%s\" to \"%s\"\n", 109214501Srpaulo mpt_unit, mpt_volume_name(VolumeBus, VolumeID), vnames->Name, 110214501Srpaulo av[2]); 111214501Srpaulo bzero(vnames->Name, sizeof(vnames->Name)); 112214501Srpaulo strcpy(vnames->Name, av[2]); 113214501Srpaulo 114214501Srpaulo if (mpt_write_config_page(fd, vnames, NULL) < 0) { 115214501Srpaulo error = errno; 116214501Srpaulo warn("Failed to set volume name"); 117214501Srpaulo return (error); 118214501Srpaulo } 119214501Srpaulo 120214501Srpaulo free(vnames); 121214501Srpaulo close(fd); 122252726Srpaulo 123252726Srpaulo return (0); 124252726Srpaulo} 125252726SrpauloMPT_COMMAND(top, name, volume_name); 126252726Srpaulo 127252726Srpaulostatic int 128214501Srpaulovolume_status(int ac, char **av) 129214501Srpaulo{ 130214501Srpaulo MPI_RAID_VOL_INDICATOR prog; 131214501Srpaulo RAID_VOL0_STATUS VolumeStatus; 132214501Srpaulo uint64_t total, remaining; 133214501Srpaulo float pct; 134214501Srpaulo U8 VolumeBus, VolumeID; 135214501Srpaulo int error, fd; 136214501Srpaulo 137214501Srpaulo if (ac != 2) { 138214501Srpaulo warnx("volume status: %s", ac > 2 ? "extra arguments" : 139214501Srpaulo "volume required"); 140214501Srpaulo return (EINVAL); 141214501Srpaulo } 142214501Srpaulo 143214501Srpaulo fd = mpt_open(mpt_unit); 144214501Srpaulo if (fd < 0) { 145214501Srpaulo error = errno; 146214501Srpaulo warn("mpt_open"); 147214501Srpaulo return (error); 148214501Srpaulo } 149214501Srpaulo 150214501Srpaulo error = mpt_lookup_volume(fd, av[1], &VolumeBus, &VolumeID); 151214501Srpaulo if (error) { 152214501Srpaulo warnc(error, "Invalid volume: %s", av[1]); 153214501Srpaulo return (error); 154214501Srpaulo } 155214501Srpaulo 156214501Srpaulo error = mpt_raid_action(fd, MPI_RAID_ACTION_INDICATOR_STRUCT, VolumeBus, 157214501Srpaulo VolumeID, 0, 0, NULL, 0, &VolumeStatus, (U32 *)&prog, sizeof(prog), 158214501Srpaulo NULL, NULL, 0); 159214501Srpaulo if (error) { 160214501Srpaulo warnc(error, "Fetching volume status failed"); 161214501Srpaulo return (error); 162214501Srpaulo } 163214501Srpaulo 164214501Srpaulo printf("Volume %s status:\n", mpt_volume_name(VolumeBus, VolumeID)); 165214501Srpaulo printf(" state: %s\n", mpt_volstate(VolumeStatus.State)); 166214501Srpaulo printf(" flags:"); 167214501Srpaulo if (VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED) 168214501Srpaulo printf(" ENABLED"); 169214501Srpaulo else 170214501Srpaulo printf(" DISABLED"); 171214501Srpaulo if (VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_QUIESCED) 172214501Srpaulo printf(", QUIESCED"); 173214501Srpaulo if (VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) 174214501Srpaulo printf(", REBUILDING"); 175214501Srpaulo if (VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE) 176 printf(", INACTIVE"); 177 if (VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_BAD_BLOCK_TABLE_FULL) 178 printf(", BAD BLOCK TABLE FULL"); 179 printf("\n"); 180 if (VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) { 181 total = (uint64_t)prog.TotalBlocks.High << 32 | 182 prog.TotalBlocks.Low; 183 remaining = (uint64_t)prog.BlocksRemaining.High << 32 | 184 prog.BlocksRemaining.Low; 185 pct = (float)(total - remaining) * 100 / total; 186 printf(" resync: %.2f%% complete\n", pct); 187 } 188 189 close(fd); 190 return (0); 191} 192MPT_COMMAND(volume, status, volume_status); 193 194static int 195volume_cache(int ac, char **av) 196{ 197 CONFIG_PAGE_RAID_VOL_0 *volume; 198 U32 Settings, NewSettings; 199 U8 VolumeBus, VolumeID; 200 char *s1; 201 int error, fd; 202 203 if (ac != 3) { 204 warnx("volume cache: %s", ac > 3 ? "extra arguments" : 205 "missing arguments"); 206 return (EINVAL); 207 } 208 209 for (s1 = av[2]; *s1 != '\0'; s1++) 210 *s1 = tolower(*s1); 211 if ((strcmp(av[2], "enable")) && (strcmp(av[2], "enabled")) && 212 (strcmp(av[2], "disable")) && (strcmp(av[2], "disabled"))) { 213 warnx("volume cache: invalid flag, must be 'enable' or 'disable'\n"); 214 return (EINVAL); 215 } 216 217 fd = mpt_open(mpt_unit); 218 if (fd < 0) { 219 error = errno; 220 warn("mpt_open"); 221 return (error); 222 } 223 224 error = mpt_lookup_volume(fd, av[1], &VolumeBus, &VolumeID); 225 if (error) { 226 warnc(error, "Invalid volume: %s", av[1]); 227 return (error); 228 } 229 230 volume = mpt_vol_info(fd, VolumeBus, VolumeID, NULL); 231 if (volume == NULL) 232 return (errno); 233 234 Settings = volume->VolumeSettings.Settings; 235 236 NewSettings = Settings; 237 if (strncmp(av[2], "enable", sizeof("enable")) == 0) 238 NewSettings |= 0x01; 239 if (strncmp(av[2], "disable", sizeof("disable")) == 0) 240 NewSettings &= ~0x01; 241 242 if (NewSettings == Settings) { 243 warnx("volume cache unchanged"); 244 close(fd); 245 return (0); 246 } 247 248 volume->VolumeSettings.Settings = NewSettings; 249 error = mpt_raid_action(fd, MPI_RAID_ACTION_CHANGE_VOLUME_SETTINGS, 250 VolumeBus, VolumeID, 0, *(U32 *)&volume->VolumeSettings, NULL, 0, 251 NULL, NULL, 0, NULL, NULL, 0); 252 if (error) 253 warnc(error, "volume cache change failed"); 254 255 close(fd); 256 return (error); 257} 258MPT_COMMAND(volume, cache, volume_cache); 259