1196212Sscottl/*- 2196212Sscottl * Copyright (c) 2008 Yahoo!, Inc. 3196212Sscottl * All rights reserved. 4196212Sscottl * Written by: John Baldwin <jhb@FreeBSD.org> 5196212Sscottl * 6196212Sscottl * Redistribution and use in source and binary forms, with or without 7196212Sscottl * modification, are permitted provided that the following conditions 8196212Sscottl * are met: 9196212Sscottl * 1. Redistributions of source code must retain the above copyright 10196212Sscottl * notice, this list of conditions and the following disclaimer. 11196212Sscottl * 2. Redistributions in binary form must reproduce the above copyright 12196212Sscottl * notice, this list of conditions and the following disclaimer in the 13196212Sscottl * documentation and/or other materials provided with the distribution. 14196212Sscottl * 3. Neither the name of the author nor the names of any co-contributors 15196212Sscottl * may be used to endorse or promote products derived from this software 16196212Sscottl * without specific prior written permission. 17196212Sscottl * 18196212Sscottl * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19196212Sscottl * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20196212Sscottl * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21196212Sscottl * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22196212Sscottl * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23196212Sscottl * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24196212Sscottl * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25196212Sscottl * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26196212Sscottl * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27196212Sscottl * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28196212Sscottl * SUCH DAMAGE. 29196212Sscottl */ 30196212Sscottl 31196212Sscottl#include <sys/cdefs.h> 32196212Sscottl__RCSID("$FreeBSD$"); 33196212Sscottl 34196212Sscottl#include <sys/param.h> 35196212Sscottl#include <sys/errno.h> 36196212Sscottl#include <err.h> 37196212Sscottl#include <libutil.h> 38196212Sscottl#include <stdio.h> 39196212Sscottl#include <stdlib.h> 40196212Sscottl#include <string.h> 41196212Sscottl#include <unistd.h> 42196212Sscottl#include <ctype.h> 43196212Sscottl#include "mptutil.h" 44196212Sscottl 45196212SscottlMPT_TABLE(top, volume); 46196212Sscottl 47196212Sscottlconst char * 48196212Sscottlmpt_volstate(U8 State) 49196212Sscottl{ 50196212Sscottl static char buf[16]; 51196212Sscottl 52196212Sscottl switch (State) { 53196212Sscottl case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL: 54196212Sscottl return ("OPTIMAL"); 55196212Sscottl case MPI_RAIDVOL0_STATUS_STATE_DEGRADED: 56196212Sscottl return ("DEGRADED"); 57196212Sscottl case MPI_RAIDVOL0_STATUS_STATE_FAILED: 58196212Sscottl return ("FAILED"); 59196212Sscottl case MPI_RAIDVOL0_STATUS_STATE_MISSING: 60196212Sscottl return ("MISSING"); 61196212Sscottl default: 62196212Sscottl sprintf(buf, "VSTATE 0x%02x", State); 63196212Sscottl return (buf); 64196212Sscottl } 65196212Sscottl} 66196212Sscottl 67196212Sscottlstatic int 68196212Sscottlvolume_name(int ac, char **av) 69196212Sscottl{ 70196212Sscottl CONFIG_PAGE_RAID_VOL_1 *vnames; 71196212Sscottl U8 VolumeBus, VolumeID; 72215046Sjhb int error, fd; 73196212Sscottl 74196212Sscottl if (ac != 3) { 75196212Sscottl warnx("name: volume and name required"); 76196212Sscottl return (EINVAL); 77196212Sscottl } 78196212Sscottl 79196212Sscottl if (strlen(av[2]) >= sizeof(vnames->Name)) { 80196212Sscottl warnx("name: new name is too long"); 81196212Sscottl return (ENOSPC); 82196212Sscottl } 83196212Sscottl 84196212Sscottl fd = mpt_open(mpt_unit); 85196212Sscottl if (fd < 0) { 86215046Sjhb error = errno; 87196212Sscottl warn("mpt_open"); 88215046Sjhb return (error); 89196212Sscottl } 90196212Sscottl 91215046Sjhb error = mpt_lookup_volume(fd, av[1], &VolumeBus, &VolumeID); 92215046Sjhb if (error) { 93215046Sjhb warnc(error, "Invalid volume: %s", av[1]); 94215046Sjhb return (error); 95196212Sscottl } 96196212Sscottl 97196212Sscottl vnames = mpt_vol_names(fd, VolumeBus, VolumeID, NULL); 98196212Sscottl if (vnames == NULL) { 99215046Sjhb error = errno; 100196212Sscottl warn("Failed to fetch volume names"); 101215046Sjhb return (error); 102196212Sscottl } 103196212Sscottl 104196212Sscottl if (vnames->Header.PageType != MPI_CONFIG_PAGEATTR_CHANGEABLE) { 105196212Sscottl warnx("Volume name is read only"); 106196212Sscottl return (EOPNOTSUPP); 107196212Sscottl } 108196212Sscottl printf("mpt%u changing volume %s name from \"%s\" to \"%s\"\n", 109196212Sscottl mpt_unit, mpt_volume_name(VolumeBus, VolumeID), vnames->Name, 110196212Sscottl av[2]); 111196212Sscottl bzero(vnames->Name, sizeof(vnames->Name)); 112196212Sscottl strcpy(vnames->Name, av[2]); 113196212Sscottl 114196212Sscottl if (mpt_write_config_page(fd, vnames, NULL) < 0) { 115215046Sjhb error = errno; 116196212Sscottl warn("Failed to set volume name"); 117215046Sjhb return (error); 118196212Sscottl } 119196212Sscottl 120196212Sscottl free(vnames); 121196212Sscottl close(fd); 122196212Sscottl 123196212Sscottl return (0); 124196212Sscottl} 125196212SscottlMPT_COMMAND(top, name, volume_name); 126196212Sscottl 127196212Sscottlstatic int 128196212Sscottlvolume_status(int ac, char **av) 129196212Sscottl{ 130196212Sscottl MPI_RAID_VOL_INDICATOR prog; 131196212Sscottl RAID_VOL0_STATUS VolumeStatus; 132196212Sscottl uint64_t total, remaining; 133196212Sscottl float pct; 134196212Sscottl U8 VolumeBus, VolumeID; 135215046Sjhb int error, fd; 136196212Sscottl 137196212Sscottl if (ac != 2) { 138196212Sscottl warnx("volume status: %s", ac > 2 ? "extra arguments" : 139196212Sscottl "volume required"); 140196212Sscottl return (EINVAL); 141196212Sscottl } 142196212Sscottl 143196212Sscottl fd = mpt_open(mpt_unit); 144196212Sscottl if (fd < 0) { 145215046Sjhb error = errno; 146196212Sscottl warn("mpt_open"); 147215046Sjhb return (error); 148196212Sscottl } 149196212Sscottl 150215046Sjhb error = mpt_lookup_volume(fd, av[1], &VolumeBus, &VolumeID); 151215046Sjhb if (error) { 152215046Sjhb warnc(error, "Invalid volume: %s", av[1]); 153215046Sjhb return (error); 154196212Sscottl } 155196212Sscottl 156215046Sjhb error = mpt_raid_action(fd, MPI_RAID_ACTION_INDICATOR_STRUCT, VolumeBus, 157196212Sscottl VolumeID, 0, 0, NULL, 0, &VolumeStatus, (U32 *)&prog, sizeof(prog), 158215046Sjhb NULL, NULL, 0); 159215046Sjhb if (error) { 160215046Sjhb warnc(error, "Fetching volume status failed"); 161215046Sjhb return (error); 162196212Sscottl } 163196212Sscottl 164196212Sscottl printf("Volume %s status:\n", mpt_volume_name(VolumeBus, VolumeID)); 165196212Sscottl printf(" state: %s\n", mpt_volstate(VolumeStatus.State)); 166196212Sscottl printf(" flags:"); 167196212Sscottl if (VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_ENABLED) 168196212Sscottl printf(" ENABLED"); 169196212Sscottl else 170196212Sscottl printf(" DISABLED"); 171196212Sscottl if (VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_QUIESCED) 172196212Sscottl printf(", QUIESCED"); 173196212Sscottl if (VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) 174196212Sscottl printf(", REBUILDING"); 175196212Sscottl if (VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE) 176196212Sscottl printf(", INACTIVE"); 177196212Sscottl if (VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_BAD_BLOCK_TABLE_FULL) 178196212Sscottl printf(", BAD BLOCK TABLE FULL"); 179196212Sscottl printf("\n"); 180196212Sscottl if (VolumeStatus.Flags & MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) { 181196212Sscottl total = (uint64_t)prog.TotalBlocks.High << 32 | 182196212Sscottl prog.TotalBlocks.Low; 183196212Sscottl remaining = (uint64_t)prog.BlocksRemaining.High << 32 | 184196212Sscottl prog.BlocksRemaining.Low; 185196212Sscottl pct = (float)(total - remaining) * 100 / total; 186196212Sscottl printf(" resync: %.2f%% complete\n", pct); 187196212Sscottl } 188196212Sscottl 189196212Sscottl close(fd); 190196212Sscottl return (0); 191196212Sscottl} 192196212SscottlMPT_COMMAND(volume, status, volume_status); 193196212Sscottl 194196212Sscottlstatic int 195196212Sscottlvolume_cache(int ac, char **av) 196196212Sscottl{ 197196212Sscottl CONFIG_PAGE_RAID_VOL_0 *volume; 198196212Sscottl U32 Settings, NewSettings; 199196212Sscottl U8 VolumeBus, VolumeID; 200196212Sscottl char *s1; 201215046Sjhb int error, fd; 202196212Sscottl 203196212Sscottl if (ac != 3) { 204196212Sscottl warnx("volume cache: %s", ac > 3 ? "extra arguments" : 205215046Sjhb "missing arguments"); 206196212Sscottl return (EINVAL); 207196212Sscottl } 208196212Sscottl 209196212Sscottl for (s1 = av[2]; *s1 != '\0'; s1++) 210196212Sscottl *s1 = tolower(*s1); 211196212Sscottl if ((strcmp(av[2], "enable")) && (strcmp(av[2], "enabled")) && 212196212Sscottl (strcmp(av[2], "disable")) && (strcmp(av[2], "disabled"))) { 213196212Sscottl warnx("volume cache: invalid flag, must be 'enable' or 'disable'\n"); 214196212Sscottl return (EINVAL); 215196212Sscottl } 216196212Sscottl 217196212Sscottl fd = mpt_open(mpt_unit); 218196212Sscottl if (fd < 0) { 219215046Sjhb error = errno; 220196212Sscottl warn("mpt_open"); 221215046Sjhb return (error); 222196212Sscottl } 223196212Sscottl 224215046Sjhb error = mpt_lookup_volume(fd, av[1], &VolumeBus, &VolumeID); 225215046Sjhb if (error) { 226215046Sjhb warnc(error, "Invalid volume: %s", av[1]); 227215046Sjhb return (error); 228196212Sscottl } 229196212Sscottl 230196212Sscottl volume = mpt_vol_info(fd, VolumeBus, VolumeID, NULL); 231196212Sscottl if (volume == NULL) 232215046Sjhb return (errno); 233196212Sscottl 234196212Sscottl Settings = volume->VolumeSettings.Settings; 235196212Sscottl 236196212Sscottl NewSettings = Settings; 237196212Sscottl if (strncmp(av[2], "enable", sizeof("enable")) == 0) 238196212Sscottl NewSettings |= 0x01; 239196212Sscottl if (strncmp(av[2], "disable", sizeof("disable")) == 0) 240196212Sscottl NewSettings &= ~0x01; 241196212Sscottl 242196212Sscottl if (NewSettings == Settings) { 243215046Sjhb warnx("volume cache unchanged"); 244196212Sscottl close(fd); 245196212Sscottl return (0); 246196212Sscottl } 247196212Sscottl 248196212Sscottl volume->VolumeSettings.Settings = NewSettings; 249215046Sjhb error = mpt_raid_action(fd, MPI_RAID_ACTION_CHANGE_VOLUME_SETTINGS, 250196212Sscottl VolumeBus, VolumeID, 0, *(U32 *)&volume->VolumeSettings, NULL, 0, 251215046Sjhb NULL, NULL, 0, NULL, NULL, 0); 252215046Sjhb if (error) 253215046Sjhb warnc(error, "volume cache change failed"); 254196212Sscottl 255196212Sscottl close(fd); 256215046Sjhb return (error); 257196212Sscottl} 258196212SscottlMPT_COMMAND(volume, cache, volume_cache); 259