Implement foreign volume handling. Allows admins to view foreign metadata
and clear or import it for use. PR: kern/172091 Submitted by: smh@freebsd.org Reviewed by: jhb@freebsd.org MFC after: 2 weeks
This commit is contained in:
parent
d5d96494f8
commit
06f1884fa8
@ -230,7 +230,11 @@ typedef enum {
|
||||
MFI_DCMD_CFG_CLEAR = 0x04030000,
|
||||
MFI_DCMD_CFG_MAKE_SPARE = 0x04040000,
|
||||
MFI_DCMD_CFG_REMOVE_SPARE = 0x04050000,
|
||||
MFI_DCMD_CFG_FOREIGN_SCAN = 0x04060100,
|
||||
MFI_DCMD_CFG_FOREIGN_DISPLAY = 0x04060200,
|
||||
MFI_DCMD_CFG_FOREIGN_PREVIEW = 0x04060300,
|
||||
MFI_DCMD_CFG_FOREIGN_IMPORT = 0x04060400,
|
||||
MFI_DCMD_CFG_FOREIGN_CLEAR = 0x04060500,
|
||||
MFI_DCMD_BBU_GET_STATUS = 0x05010000,
|
||||
MFI_DCMD_BBU_GET_CAPACITY_INFO =0x05020000,
|
||||
MFI_DCMD_BBU_GET_DESIGN_INFO = 0x05030000,
|
||||
|
@ -2,7 +2,7 @@
|
||||
PROG= mfiutil
|
||||
|
||||
SRCS= mfiutil.c mfi_bbu.c mfi_cmd.c mfi_config.c mfi_drive.c mfi_evt.c \
|
||||
mfi_flash.c mfi_patrol.c mfi_show.c mfi_volume.c
|
||||
mfi_flash.c mfi_patrol.c mfi_show.c mfi_volume.c mfi_foreign.c
|
||||
MAN8= mfiutil.8
|
||||
|
||||
CFLAGS+= -fno-builtin-strftime
|
||||
|
@ -37,19 +37,13 @@
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <libutil.h>
|
||||
#ifdef DEBUG
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "mfiutil.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
static void dump_config(int fd, struct mfi_config_data *config);
|
||||
#endif
|
||||
|
||||
static int add_spare(int ac, char **av);
|
||||
static int remove_spare(int ac, char **av);
|
||||
|
||||
@ -81,8 +75,16 @@ dehumanize(const char *value)
|
||||
}
|
||||
return (iv);
|
||||
}
|
||||
|
||||
int
|
||||
mfi_config_read(int fd, struct mfi_config_data **configp)
|
||||
{
|
||||
return mfi_config_read_opcode(fd, MFI_DCMD_CFG_READ, configp, NULL, 0);
|
||||
}
|
||||
|
||||
int
|
||||
mfi_config_read_opcode(int fd, uint32_t opcode, struct mfi_config_data **configp,
|
||||
uint8_t *mbox, size_t mboxlen)
|
||||
{
|
||||
struct mfi_config_data *config;
|
||||
uint32_t config_size;
|
||||
@ -98,8 +100,8 @@ mfi_config_read(int fd, struct mfi_config_data **configp)
|
||||
config = reallocf(config, config_size);
|
||||
if (config == NULL)
|
||||
return (-1);
|
||||
if (mfi_dcmd_command(fd, MFI_DCMD_CFG_READ, config,
|
||||
config_size, NULL, 0, NULL) < 0) {
|
||||
if (mfi_dcmd_command(fd, opcode, config,
|
||||
config_size, mbox, mboxlen, NULL) < 0) {
|
||||
error = errno;
|
||||
free(config);
|
||||
errno = error;
|
||||
@ -366,6 +368,13 @@ parse_array(int fd, int raid_type, char *array_str, struct array_info *info)
|
||||
info->drives = NULL;
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
if (pinfo->state.ddf.v.pd_type.is_foreign) {
|
||||
warnx("Drive %u is foreign", device_id);
|
||||
free(info->drives);
|
||||
info->drives = NULL;
|
||||
return (EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
@ -804,7 +813,7 @@ create_volume(int ac, char **av)
|
||||
|
||||
#ifdef DEBUG
|
||||
if (dump)
|
||||
dump_config(fd, config);
|
||||
dump_config(fd, config, NULL);
|
||||
#endif
|
||||
|
||||
/* Send the new config to the controller. */
|
||||
@ -1093,10 +1102,9 @@ remove_spare(int ac, char **av)
|
||||
}
|
||||
MFI_COMMAND(top, remove, remove_spare);
|
||||
|
||||
#ifdef DEBUG
|
||||
/* Display raw data about a config. */
|
||||
static void
|
||||
dump_config(int fd, struct mfi_config_data *config)
|
||||
void
|
||||
dump_config(int fd, struct mfi_config_data *config, const char *msg_prefix)
|
||||
{
|
||||
struct mfi_array *ar;
|
||||
struct mfi_ld_config *ld;
|
||||
@ -1106,9 +1114,12 @@ dump_config(int fd, struct mfi_config_data *config)
|
||||
char *p;
|
||||
int i, j;
|
||||
|
||||
if (NULL == msg_prefix)
|
||||
msg_prefix = "Configuration (Debug)";
|
||||
|
||||
printf(
|
||||
"mfi%d Configuration (Debug): %d arrays, %d volumes, %d spares\n",
|
||||
mfi_unit, config->array_count, config->log_drv_count,
|
||||
"mfi%d %s: %d arrays, %d volumes, %d spares\n", mfi_unit,
|
||||
msg_prefix, config->array_count, config->log_drv_count,
|
||||
config->spares_count);
|
||||
printf(" array size: %u\n", config->array_size);
|
||||
printf(" volume size: %u\n", config->log_drv_size);
|
||||
@ -1186,6 +1197,7 @@ dump_config(int fd, struct mfi_config_data *config)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static int
|
||||
debug_config(int ac, char **av)
|
||||
{
|
||||
@ -1213,7 +1225,7 @@ debug_config(int ac, char **av)
|
||||
}
|
||||
|
||||
/* Dump out the configuration. */
|
||||
dump_config(fd, config);
|
||||
dump_config(fd, config, NULL);
|
||||
free(config);
|
||||
close(fd);
|
||||
|
||||
@ -1265,7 +1277,7 @@ dump(int ac, char **av)
|
||||
close(fd);
|
||||
return (error);
|
||||
}
|
||||
dump_config(fd, config);
|
||||
dump_config(fd, config, NULL);
|
||||
free(config);
|
||||
close(fd);
|
||||
|
||||
|
364
usr.sbin/mfiutil/mfi_foreign.c
Normal file
364
usr.sbin/mfiutil/mfi_foreign.c
Normal file
@ -0,0 +1,364 @@
|
||||
/*
|
||||
* Copyright (c) 2013 smh@freebsd.org
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <libutil.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "mfiutil.h"
|
||||
|
||||
MFI_TABLE(top, foreign);
|
||||
|
||||
static int
|
||||
foreign_clear(__unused int ac, __unused char **av)
|
||||
{
|
||||
int ch, error, fd;
|
||||
|
||||
fd = mfi_open(mfi_unit, O_RDWR);
|
||||
if (fd < 0) {
|
||||
error = errno;
|
||||
warn("mfi_open");
|
||||
return (error);
|
||||
}
|
||||
|
||||
printf(
|
||||
"Are you sure you wish to clear ALL foreign configurations"
|
||||
" on mfi%u? [y/N] ", mfi_unit);
|
||||
|
||||
ch = getchar();
|
||||
if (ch != 'y' && ch != 'Y') {
|
||||
printf("\nAborting\n");
|
||||
close(fd);
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (mfi_dcmd_command(fd, MFI_DCMD_CFG_FOREIGN_CLEAR, NULL, 0, NULL,
|
||||
0, NULL) < 0) {
|
||||
error = errno;
|
||||
warn("Failed to clear foreign configuration");
|
||||
close(fd);
|
||||
return (error);
|
||||
}
|
||||
|
||||
printf("mfi%d: Foreign configuration cleared\n", mfi_unit);
|
||||
close(fd);
|
||||
return (0);
|
||||
}
|
||||
MFI_COMMAND(foreign, clear, foreign_clear);
|
||||
|
||||
static int
|
||||
foreign_scan(__unused int ac, __unused char **av)
|
||||
{
|
||||
struct mfi_foreign_scan_info info;
|
||||
int error, fd;
|
||||
|
||||
fd = mfi_open(mfi_unit, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
error = errno;
|
||||
warn("mfi_open");
|
||||
return (error);
|
||||
}
|
||||
|
||||
if (mfi_dcmd_command(fd, MFI_DCMD_CFG_FOREIGN_SCAN, &info,
|
||||
sizeof(info), NULL, 0, NULL) < 0) {
|
||||
error = errno;
|
||||
warn("Failed to scan foreign configuration");
|
||||
close(fd);
|
||||
return (error);
|
||||
}
|
||||
|
||||
printf("mfi%d: Found %d foreign configurations\n", mfi_unit,
|
||||
info.count);
|
||||
close(fd);
|
||||
return (0);
|
||||
}
|
||||
MFI_COMMAND(foreign, scan, foreign_scan);
|
||||
|
||||
static int
|
||||
foreign_show_cfg(int fd, uint32_t opcode, uint8_t cfgidx, int diagnostic)
|
||||
{
|
||||
struct mfi_config_data *config;
|
||||
char prefix[26];
|
||||
int error;
|
||||
uint8_t mbox[4];
|
||||
|
||||
bzero(mbox, sizeof(mbox));
|
||||
mbox[0] = cfgidx;
|
||||
if (mfi_config_read_opcode(fd, opcode, &config, mbox, sizeof(mbox)) < 0) {
|
||||
error = errno;
|
||||
warn("Failed to get foreign config %d", error);
|
||||
close(fd);
|
||||
return (error);
|
||||
}
|
||||
|
||||
if (opcode == MFI_DCMD_CFG_FOREIGN_PREVIEW)
|
||||
sprintf(prefix, "Foreign configuration preview %d", cfgidx);
|
||||
else
|
||||
sprintf(prefix, "Foreign configuration %d", cfgidx);
|
||||
/*
|
||||
* MegaCli uses DCMD opcodes: 0x03100200 (which fails) followed by
|
||||
* 0x1a721880 which returns what looks to be drive / volume info
|
||||
* but we have no real information on what these are or what they do
|
||||
* so we're currently relying solely on the config returned above
|
||||
*/
|
||||
if (diagnostic)
|
||||
dump_config(fd, config, prefix);
|
||||
else {
|
||||
char *ld_list;
|
||||
int i;
|
||||
|
||||
ld_list = (char *)(config->array);
|
||||
|
||||
printf("%s: %d arrays, %d volumes, %d spares\n", prefix,
|
||||
config->array_count, config->log_drv_count,
|
||||
config->spares_count);
|
||||
|
||||
|
||||
for (i = 0; i < config->array_count; i++)
|
||||
ld_list += config->array_size;
|
||||
|
||||
for (i = 0; i < config->log_drv_count; i++) {
|
||||
const char *level;
|
||||
char size[6], stripe[5];
|
||||
struct mfi_ld_config *ld;
|
||||
|
||||
ld = (struct mfi_ld_config *)ld_list;
|
||||
|
||||
format_stripe(stripe, sizeof(stripe),
|
||||
ld->params.stripe_size);
|
||||
/*
|
||||
* foreign configs don't seem to have a secondary raid level
|
||||
* but, we can use span depth here as if a LD spans multiple
|
||||
* arrays of disks (2 raid 1 sets for example), we will have an
|
||||
* indication based on the spam depth. swb
|
||||
*/
|
||||
level = mfi_raid_level(ld->params.primary_raid_level,
|
||||
(ld->params.span_depth - 1));
|
||||
|
||||
humanize_number(size, sizeof(size), ld->span[0].num_blocks * 512,
|
||||
"", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
|
||||
|
||||
printf(" ID%d ", i);
|
||||
printf("(%6s) %-8s |",
|
||||
size, level);
|
||||
printf("volume spans %d %s\n", ld->params.span_depth,
|
||||
(ld->params.span_depth > 1) ? "arrays" : "array");
|
||||
for (int j = 0; j < ld->params.span_depth; j++) {
|
||||
char *ar_list;
|
||||
struct mfi_array *ar;
|
||||
uint16_t device_id;
|
||||
|
||||
printf(" array %u @ ", ld->span[j].array_ref);
|
||||
humanize_number(size, sizeof(size), ld->span[j].num_blocks * 512,
|
||||
"", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
|
||||
|
||||
printf("(%6s)\n",size);
|
||||
ar_list = (char *)config->array + (ld->span[j].array_ref * config->array_size);
|
||||
|
||||
ar = (struct mfi_array *)ar_list;
|
||||
for (int k = 0; k < ar->num_drives; k++) {
|
||||
device_id = ar->pd[k].ref.v.device_id;
|
||||
if (device_id == 0xffff)
|
||||
printf(" drive MISSING\n");
|
||||
else {
|
||||
printf(" drive %u %s\n", device_id,
|
||||
mfi_pdstate(ar->pd[k].fw_state));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
ld_list += config->log_drv_size;
|
||||
}
|
||||
}
|
||||
|
||||
free(config);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
display_format(int ac, char **av, int diagnostic, mfi_dcmd_t display_cmd)
|
||||
{
|
||||
struct mfi_foreign_scan_info info;
|
||||
uint8_t i;
|
||||
int error, fd;
|
||||
|
||||
if (ac > 2) {
|
||||
warnx("foreign display: extra arguments");
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
fd = mfi_open(mfi_unit, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
error = errno;
|
||||
warn("mfi_open");
|
||||
return (error);
|
||||
}
|
||||
|
||||
if (mfi_dcmd_command(fd, MFI_DCMD_CFG_FOREIGN_SCAN, &info,
|
||||
sizeof(info), NULL, 0, NULL) < 0) {
|
||||
error = errno;
|
||||
warn("Failed to scan foreign configuration");
|
||||
close(fd);
|
||||
return (error);
|
||||
}
|
||||
|
||||
if (info.count == 0) {
|
||||
warnx("foreign display: no foreign configs found");
|
||||
close(fd);
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
if (ac == 1) {
|
||||
for (i = 0; i < info.count; i++) {
|
||||
error = foreign_show_cfg(fd,
|
||||
display_cmd, i, diagnostic);
|
||||
if(error != 0) {
|
||||
close(fd);
|
||||
return (error);
|
||||
}
|
||||
if (i < info.count - 1)
|
||||
printf("\n");
|
||||
}
|
||||
} else if (ac == 2) {
|
||||
error = foreign_show_cfg(fd,
|
||||
display_cmd, atoi(av[1]), diagnostic);
|
||||
if (error != 0) {
|
||||
close(fd);
|
||||
return (error);
|
||||
}
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
foreign_display(int ac, char **av)
|
||||
{
|
||||
return(display_format(ac, av, 1/*diagnostic output*/, MFI_DCMD_CFG_FOREIGN_DISPLAY));
|
||||
}
|
||||
MFI_COMMAND(foreign, diag, foreign_display);
|
||||
|
||||
static int
|
||||
foreign_preview(int ac, char **av)
|
||||
{
|
||||
return(display_format(ac, av, 1/*diagnostic output*/, MFI_DCMD_CFG_FOREIGN_PREVIEW));
|
||||
}
|
||||
MFI_COMMAND(foreign, preview, foreign_preview);
|
||||
|
||||
static int
|
||||
foreign_import(int ac, char **av)
|
||||
{
|
||||
struct mfi_foreign_scan_info info;
|
||||
int ch, error, fd;
|
||||
uint8_t cfgidx;
|
||||
uint8_t mbox[4];
|
||||
|
||||
if (ac > 2) {
|
||||
warnx("foreign preview: extra arguments");
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
fd = mfi_open(mfi_unit, O_RDWR);
|
||||
if (fd < 0) {
|
||||
error = errno;
|
||||
warn("mfi_open");
|
||||
return (error);
|
||||
}
|
||||
|
||||
if (mfi_dcmd_command(fd, MFI_DCMD_CFG_FOREIGN_SCAN, &info,
|
||||
sizeof(info), NULL, 0, NULL) < 0) {
|
||||
error = errno;
|
||||
warn("Failed to scan foreign configuration");
|
||||
close(fd);
|
||||
return (error);
|
||||
}
|
||||
|
||||
if (info.count == 0) {
|
||||
warnx("foreign import: no foreign configs found");
|
||||
close(fd);
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
if (ac == 1) {
|
||||
cfgidx = 0xff;
|
||||
printf("Are you sure you wish to import ALL foreign "
|
||||
"configurations on mfi%u? [y/N] ", mfi_unit);
|
||||
} else {
|
||||
/*
|
||||
* While this is docmmented for MegaCli this failed with
|
||||
* exit code 0x03 on the test controller which was a Supermicro
|
||||
* SMC2108 with firmware 12.12.0-0095 which is a LSI 2108 based
|
||||
* controller.
|
||||
*/
|
||||
cfgidx = atoi(av[1]);
|
||||
if (cfgidx >= info.count) {
|
||||
warnx("Invalid foreign config %d specified max is %d",
|
||||
cfgidx, info.count - 1);
|
||||
close(fd);
|
||||
return (EINVAL);
|
||||
}
|
||||
printf("Are you sure you wish to import the foreign "
|
||||
"configuration %d on mfi%u? [y/N] ", cfgidx, mfi_unit);
|
||||
}
|
||||
|
||||
ch = getchar();
|
||||
if (ch != 'y' && ch != 'Y') {
|
||||
printf("\nAborting\n");
|
||||
close(fd);
|
||||
return (0);
|
||||
}
|
||||
|
||||
bzero(mbox, sizeof(mbox));
|
||||
mbox[0] = cfgidx;
|
||||
if (mfi_dcmd_command(fd, MFI_DCMD_CFG_FOREIGN_IMPORT, NULL, 0, mbox,
|
||||
sizeof(mbox), NULL) < 0) {
|
||||
error = errno;
|
||||
warn("Failed to import foreign configuration");
|
||||
close(fd);
|
||||
return (error);
|
||||
}
|
||||
|
||||
if (ac == 1)
|
||||
printf("mfi%d: All foreign configurations imported\n",
|
||||
mfi_unit);
|
||||
else
|
||||
printf("mfi%d: Foreign configuration %d imported\n", mfi_unit,
|
||||
cfgidx);
|
||||
close(fd);
|
||||
return (0);
|
||||
}
|
||||
MFI_COMMAND(foreign, import, foreign_import);
|
@ -40,9 +40,11 @@
|
||||
#include <unistd.h>
|
||||
#include "mfiutil.h"
|
||||
|
||||
static const char* foreign_state = " (FOREIGN)";
|
||||
|
||||
MFI_TABLE(top, show);
|
||||
|
||||
static void
|
||||
void
|
||||
format_stripe(char *buf, size_t buflen, uint8_t stripe)
|
||||
{
|
||||
|
||||
@ -291,7 +293,7 @@ show_battery(int ac, char **av __unused)
|
||||
}
|
||||
MFI_COMMAND(show, battery, show_battery);
|
||||
|
||||
static void
|
||||
void
|
||||
print_ld(struct mfi_ld_info *info, int state_len)
|
||||
{
|
||||
struct mfi_ld_params *params = &info->ld_config.params;
|
||||
@ -312,19 +314,24 @@ print_ld(struct mfi_ld_info *info, int state_len)
|
||||
mfi_ldstate(params->state));
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
print_pd(struct mfi_pd_info *info, int state_len)
|
||||
{
|
||||
const char *s;
|
||||
char buf[6];
|
||||
char buf[256];
|
||||
|
||||
humanize_number(buf, sizeof(buf), info->raw_size * 512, "",
|
||||
HN_AUTOSCALE, HN_B | HN_NOSPACE |HN_DECIMAL);
|
||||
printf("(%6s) ", buf);
|
||||
if (info->state.ddf.v.pd_type.is_foreign) {
|
||||
sprintf(buf, "%s%s", mfi_pdstate(info->fw_state), foreign_state);
|
||||
s = buf;
|
||||
} else
|
||||
s = mfi_pdstate(info->fw_state);
|
||||
if (state_len > 0)
|
||||
printf("%-*s", state_len, mfi_pdstate(info->fw_state));
|
||||
printf("%-*s", state_len, s);
|
||||
else
|
||||
printf("%s", mfi_pdstate(info->fw_state));
|
||||
printf("%s",s);
|
||||
s = mfi_pd_inq_string(info);
|
||||
if (s != NULL)
|
||||
printf(" %s", s);
|
||||
@ -560,6 +567,8 @@ show_drives(int ac, char **av __unused)
|
||||
goto error;
|
||||
}
|
||||
len = strlen(mfi_pdstate(info.fw_state));
|
||||
if (info.state.ddf.v.pd_type.is_foreign)
|
||||
len += strlen(foreign_state);
|
||||
if (len > state_len)
|
||||
state_len = len;
|
||||
}
|
||||
@ -757,7 +766,7 @@ show_progress(int ac, char **av __unused)
|
||||
printf("drive %s ", mfi_drive_name(NULL, device_id,
|
||||
MFI_DNAME_DEVICE_ID|MFI_DNAME_HONOR_OPTS));
|
||||
mfi_display_progress("Clear", &pinfo.prog_info.clear);
|
||||
busy = 1;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -770,3 +779,10 @@ show_progress(int ac, char **av __unused)
|
||||
return (0);
|
||||
}
|
||||
MFI_COMMAND(show, progress, show_progress);
|
||||
|
||||
static int
|
||||
show_foreign(int ac, char **av)
|
||||
{
|
||||
return(display_format(ac, av, 0/*normal display*/, MFI_DCMD_CFG_FOREIGN_DISPLAY));
|
||||
}
|
||||
MFI_COMMAND(show, foreign, show_foreign);
|
||||
|
@ -63,6 +63,9 @@
|
||||
.Cm show firmware
|
||||
.Nm
|
||||
.Op Fl u Ar unit
|
||||
.Cm show foreign Op Ar volume
|
||||
.Nm
|
||||
.Op Fl u Ar unit
|
||||
.Cm show logstate
|
||||
.Nm
|
||||
.Op Fl d
|
||||
@ -140,6 +143,21 @@
|
||||
.Cm patrol Ar command Op Ar interval Op Ar start
|
||||
.Nm
|
||||
.Op Fl u Ar unit
|
||||
.Cm foreign scan
|
||||
.Nm
|
||||
.Op Fl u Ar unit
|
||||
.Cm foreign clear Op Ar config
|
||||
.Nm
|
||||
.Op Fl u Ar unit
|
||||
.Cm foreign diag Op Ar config
|
||||
.Nm
|
||||
.Op Fl u Ar unit
|
||||
.Cm foreign preview Op Ar config
|
||||
.Nm
|
||||
.Op Fl u Ar unit
|
||||
.Cm foreign import Op Ar config
|
||||
.Nm
|
||||
.Op Fl u Ar unit
|
||||
.Cm flash Ar file
|
||||
.Nm
|
||||
.Op Fl u Ar unit
|
||||
@ -321,6 +339,8 @@ The entry in the event log corresponding to the most recent boot.
|
||||
.El
|
||||
.It Cm show firmware
|
||||
Lists all of the firmware images present on the controller.
|
||||
.It Cm show foreign
|
||||
Displays detected foreign configurations on disks for importation or removal.
|
||||
.It Cm show logstate
|
||||
Display the various sequence numbers associated with the event log.
|
||||
.It Cm show patrol
|
||||
@ -567,6 +587,35 @@ Enable manual patrol reads that are only initiated by the user.
|
||||
Start a patrol read operation.
|
||||
.It Cm stop patrol
|
||||
Stop a currently running patrol read operation.
|
||||
.It Cm foreign scan
|
||||
Scan for foreign configurations and display the number found. The
|
||||
.Ar config
|
||||
argument for the commands below takes the form of a number from 0 to the total
|
||||
configurations found.
|
||||
.It Cm foreign clear Op config
|
||||
Clear the specifed foreign
|
||||
.Ar config
|
||||
or all if no
|
||||
.Ar config
|
||||
argument is provided.
|
||||
.It Cm foreign diag Op config
|
||||
Display a diagnostic display of the specifed foreign
|
||||
.Ar config
|
||||
or all if no
|
||||
.Ar config
|
||||
argument is provided.
|
||||
.It Cm foreign preview Op config
|
||||
Preview the specifed foreign
|
||||
.Ar config
|
||||
after import or all if no
|
||||
.Ar config
|
||||
argument is provided.
|
||||
.It Cm foreign import Op config
|
||||
Import the specifed foreign
|
||||
.Ar config
|
||||
or all if no
|
||||
.Ar config
|
||||
argument is provided.
|
||||
.It Cm flash Ar file
|
||||
Updates the flash on the controller with the firmware stored in
|
||||
.Ar file .
|
||||
@ -634,6 +683,10 @@ Configure the adapter to run periodic patrol reads once a week with the first
|
||||
patrol read starting in 5 minutes:
|
||||
.Pp
|
||||
.Dl Nm Cm patrol auto 604800 300
|
||||
.Pp
|
||||
Display the second detected foreign configuration:
|
||||
.Pp
|
||||
.Dl Nm Cm show foreign 1
|
||||
.Sh SEE ALSO
|
||||
.Xr mfi 4
|
||||
.Sh HISTORY
|
||||
|
@ -60,6 +60,7 @@ usage(void)
|
||||
fprintf(stderr, " show drives - list physical drives\n");
|
||||
fprintf(stderr, " show events - display event log\n");
|
||||
fprintf(stderr, " show firmware - list firmware images\n");
|
||||
fprintf(stderr, " show foreign - display detected foreign volumes\n");
|
||||
fprintf(stderr, " show logstate - display event log sequence numbers\n");
|
||||
fprintf(stderr, " show volumes - list logical volumes\n");
|
||||
fprintf(stderr, " show patrol - display patrol read status\n");
|
||||
@ -83,6 +84,11 @@ usage(void)
|
||||
fprintf(stderr, " patrol <disable|auto|manual> [interval [start]]\n");
|
||||
fprintf(stderr, " start patrol - start a patrol read\n");
|
||||
fprintf(stderr, " stop patrol - stop a patrol read\n");
|
||||
fprintf(stderr, " foreign scan - scan for foreign configurations\n");
|
||||
fprintf(stderr, " foreign clear [volume] - clear foreign configurations (default all)\n");
|
||||
fprintf(stderr, " foreign diag [volume] - diagnostic display foreign configurations (default all)\n");
|
||||
fprintf(stderr, " foreign preview [volume] - preview foreign configurations (default all)\n");
|
||||
fprintf(stderr, " foreign import [volume] - import foreign configurations (default all)\n");
|
||||
fprintf(stderr, " flash <firmware>\n");
|
||||
fprintf(stderr, " start learn - start a BBU relearn\n");
|
||||
fprintf(stderr, " bbu <setting> <value> - set BBU properties\n");
|
||||
|
@ -124,6 +124,16 @@ extern int mfi_unit;
|
||||
|
||||
extern u_int mfi_opts;
|
||||
|
||||
/* We currently don't know the full details of the following struct */
|
||||
struct mfi_foreign_scan_cfg {
|
||||
char data[24];
|
||||
};
|
||||
|
||||
struct mfi_foreign_scan_info {
|
||||
uint32_t count; /* Number of foreign configs found */
|
||||
struct mfi_foreign_scan_cfg cfgs[8];
|
||||
};
|
||||
|
||||
void mbox_store_ldref(uint8_t *mbox, union mfi_ld_ref *ref);
|
||||
void mbox_store_pdref(uint8_t *mbox, union mfi_pd_ref *ref);
|
||||
void mfi_display_progress(const char *label, struct mfi_progress *prog);
|
||||
@ -136,6 +146,8 @@ const char *mfi_pd_inq_string(struct mfi_pd_info *info);
|
||||
const char *mfi_volume_name(int fd, uint8_t target_id);
|
||||
int mfi_volume_busy(int fd, uint8_t target_id);
|
||||
int mfi_config_read(int fd, struct mfi_config_data **configp);
|
||||
int mfi_config_read_opcode(int fd, uint32_t opcode,
|
||||
struct mfi_config_data **configp, uint8_t *mbox, size_t mboxlen);
|
||||
int mfi_lookup_drive(int fd, char *drive, uint16_t *device_id);
|
||||
int mfi_lookup_volume(int fd, const char *name, uint8_t *target_id);
|
||||
int mfi_dcmd_command(int fd, uint32_t opcode, void *buf, size_t bufsize,
|
||||
@ -152,6 +164,10 @@ int mfi_reconfig_supported(void);
|
||||
const char *mfi_status(u_int status_code);
|
||||
const char *mfi_drive_name(struct mfi_pd_info *pinfo, uint16_t device_id,
|
||||
uint32_t def);
|
||||
void format_stripe(char *buf, size_t buflen, uint8_t stripe);
|
||||
void print_ld(struct mfi_ld_info *info, int state_len);
|
||||
void print_pd(struct mfi_pd_info *info, int state_len);
|
||||
void dump_config(int fd, struct mfi_config_data *config, const char *msg_prefix);
|
||||
int mfi_bbu_get_props(int fd, struct mfi_bbu_properties *props,
|
||||
uint8_t *statusp);
|
||||
int mfi_bbu_set_props(int fd, struct mfi_bbu_properties *props,
|
||||
@ -163,4 +179,5 @@ void mfi_autolearn_mode(uint8_t, char *, size_t);
|
||||
void scan_firmware(struct mfi_info_component *comp);
|
||||
void display_firmware(struct mfi_info_component *comp, const char *tag);
|
||||
|
||||
int display_format(int ac, char **av, int diagnostic, mfi_dcmd_t display_cmd);
|
||||
#endif /* !__MFIUTIL_H__ */
|
||||
|
Loading…
Reference in New Issue
Block a user