Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F146411314
D3580.id8556.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
17 KB
Referenced Files
None
Subscribers
None
D3580.id8556.diff
View Options
Index: usr.sbin/sesutil/Makefile
===================================================================
--- usr.sbin/sesutil/Makefile
+++ usr.sbin/sesutil/Makefile
@@ -1,6 +1,7 @@
# $FreeBSD$
PROG= sesutil
+SRCS= sesutil.c eltsub.c
MAN= sesutil.8
.include <bsd.prog.mk>
Index: usr.sbin/sesutil/eltsub.h
===================================================================
--- usr.sbin/sesutil/eltsub.h
+++ usr.sbin/sesutil/eltsub.h
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/share/examples/ses/srcs/eltsub.h 198934 2009-11-04 23:36:23Z delphij $ */
+/* $FreeBSD: 198934 2009-11-04 23:36:23Z delphij $ */
/*
* Copyright (c) 2000 by Matthew Jacob
* All rights reserved.
Index: usr.sbin/sesutil/eltsub.c
===================================================================
--- usr.sbin/sesutil/eltsub.c
+++ usr.sbin/sesutil/eltsub.c
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/share/examples/ses/srcs/eltsub.c 242647 2012-11-06 01:29:26Z mav $ */
+/* $FreeBSD: 242647 2012-11-06 01:29:26Z mav $ */
/*
* Copyright (c) 2000 by Matthew Jacob
* All rights reserved.
@@ -180,11 +180,13 @@
static char ebuf[256], *scode;
scode = scode2ascii(cstat[0]);
- sprintf(ebuf, "status: %s%s%s%s (0x%02x 0x%02x 0x%02x 0x%02x)",
+ sprintf(ebuf, "%s%s%s%s%s%s (0x%02x 0x%02x 0x%02x 0x%02x)",
scode,
(cstat[0] & 0x40) ? ", Prd.Fail" : "",
(cstat[0] & 0x20) ? ", Disabled" : "",
(cstat[0] & 0x10) ? ", Swapped" : "",
+ (cstat[2] & 0x02) ? ", LED=Locate" : "",
+ (cstat[3] & 0x20) ? ", LED=Fault" : "",
cstat[0], cstat[1], cstat[2], cstat[3]);
return (ebuf);
}
Index: usr.sbin/sesutil/sesutil.8
===================================================================
--- usr.sbin/sesutil/sesutil.8
+++ usr.sbin/sesutil/sesutil.8
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd September 1, 2015
+.Dd September 6, 2015
.Dt SESUTIL 8
.Os
.Sh NAME
@@ -32,34 +32,99 @@
.Nd Utility for managing SCSI Enclosure Services (SES) device
.Sh SYNOPSIS
.Nm
-.Cm locate Ar disk Bq on|off
+.Cm fault
+.Oo
+.Fl u Ar /dev/sesN
+.Oc
+.Oo
+.Ar disk |
+.Ar sesid |
+.Ql all
+.Oc
+.Op Ar on | off
+.Nm
+.Cm map
+.Op Fl u Ar /dev/sesN
+.Nm
+.Cm locate
+.Oo
+.Fl u Ar /dev/sesN
+.Oc
+.Oo
+.Ar disk |
+.Ar sesid |
+.Ql all
+.Oc
+.Op Ar on | off
+.Nm
+.Cm status
+.Op Fl u Ar /dev/sesN
.Sh DESCRIPTION
The
.Nm
-utility can be used to modify various parameter on SCSI Enclosure Services
-(SES) device.
+utility can be used to query and modify various parameter of SCSI Enclosure
+Services (SES) devices.
.Pp
List of supported commands:
.Bl -tag -width indent
-.It Cm locate Ar disk Bq on|off
-Change the state of the external LED associated with
+.It Cm fault Ar disk Op on | off
+Change the state of the external fault LED associated with
+.Ar disk .
+.Ar disk
+can be the device name of the disk, like
+.Cm da12 ,
+or
+.Cm Ql all .
+to indicate all disks attached to SES controllers.
+.It Cm fault Fl u Ar /dev/sesN Ar sesid Op on | off
+Change the state of the external fault LED associated with an element
+connected to the SES controller.
+.Ar sesid
+must be the element ID of a valid item attached to the controller.
+Use the
+.Cm map
+command to list the elements attached to a controller.
+.It Cm map Op Fl u Ar /dev/sesN
+Display a map of all elements connected to the specified
+.Xr ses 4
+controller.
+If no controller is specified, all controllers are mapped.
+.It Cm locate Ar disk Op on | off
+Change the state of the external locate LED associated with
.Ar disk .
.Ar disk
can be the device name of the disk, like
.Cm da12 ,
or
-.Cm all .
+.Cm Ql all .
to indicate all disks attached to SES controllers.
+.It Cm locate Fl u Ar /dev/sesN Ar sesid Op on | off
+Change the state of the external locate LED associated with an element
+connected to the SES controller.
+.Ar sesid
+must be the element ID of a valid item attached to the controller.
+Use the
+.Cm map
+command to list the elements attached to a controller.
+.It Cm status Op Fl u Ar /dev/sesN
+Display the status of the specified
+.Xr ses 4
+controller.
+If no controller is specified, the status of each controller is returned.
.El
.Sh EXAMPLES
-Turn off all external LEDs:
+Turn off all locate LEDs:
.Pp
.Dl Nm Cm locate all off
.Pp
-Turn on the external LED of drive
+Turn on the locate LED for the drive bay corresponding to
.Pa da15 :
.Pp
.Dl Nm Cm locate da15 on
+.Pp
+Turn on the fault LED for a drive bay not associated with a device:
+.Pp
+.Dl Nm Cm fault -u /dev/ses2 7 on
.Sh SEE ALSO
.Xr ses 4
.Sh HISTORY
@@ -68,6 +133,10 @@
utility first appeared in
.Fx 11.0 .
.Sh AUTHORS
+.An -nosplit
The
-.Nm utility was written by
-.An Baptiste Daroussin Aq Mt bapt@FreeBSD.org .
+.Nm
+utility was written by
+.An Baptiste Daroussin Aq Mt bapt@FreeBSD.org
+and
+.An Allan Jude Aq Mt allanjude@FreeBSD.org .
Index: usr.sbin/sesutil/sesutil.c
===================================================================
--- usr.sbin/sesutil/sesutil.c
+++ usr.sbin/sesutil/sesutil.c
@@ -1,5 +1,7 @@
/*-
* Copyright (c) 2015 Baptiste Daroussin <bapt@FreeBSD.org>
+ * Copyright (c) 2015 Allan Jude <allanjude@FreeBSD.org>
+ * Copyright (c) 2000 by Matthew Jacob
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -45,21 +47,66 @@
#include <cam/scsi/scsi_all.h>
#include <cam/scsi/scsi_enc.h>
+#include "eltsub.h"
+
+static int encstatus(int argc, char **argv);
+static int fault(int argc, char **argv);
static int locate(int argc, char **argv);
+static int objmap(int argc, char **argv);
+static int sesled(int argc, char **argv, bool fault);
static struct command {
const char *name;
+ const char *param;
const char *desc;
int (*exec)(int argc, char **argv);
} cmds[] = {
- { "locate", "Change the state of the external LED associated with a"
- " disk", locate} ,
+ { "fault",
+ "(<disk>|<sesid>|all) (on|off)",
+ "Change the state of the fault LED associated with a disk",
+ fault },
+ { "map", "",
+ "Print a map of the devices managed by the enclosure", objmap } ,
+ { "locate",
+ "(<disk>|<sesid>|all) (on|off)",
+ "Change the state of the locate LED associated with a disk",
+ locate },
+ { "status", "", "Print the status of the enclosure",
+ encstatus },
};
static const int nbcmds = nitems(cmds);
+static const char *uflag;
+
+static void
+usage(FILE *out, const char *subcmd)
+{
+ int i;
+
+ if (subcmd == NULL) {
+ fprintf(out, "Usage: %s [-u /dev/ses<N>] <command> [options]\n",
+ getprogname());
+ fprintf(out, "Commands supported:\n");
+ }
+ for (i = 0; i < nbcmds; i++) {
+ if (subcmd != NULL) {
+ if (strcmp(subcmd, cmds[i].name) == 0) {
+ fprintf(out, "Usage: %s %s [-u /dev/ses<N>] "
+ "%s\n\t%s\n", getprogname(), subcmd,
+ cmds[i].param, cmds[i].desc);
+ break;
+ }
+ continue;
+ }
+ fprintf(out, " %-12s%s\n\t\t%s\n\n", cmds[i].name,
+ cmds[i].param, cmds[i].desc);
+ }
+
+ exit(EXIT_FAILURE);
+}
static void
-do_locate(int fd, unsigned int idx, bool onoff)
+do_led(int fd, unsigned int idx, bool onoff, bool fault)
{
encioc_elm_status_t o;
@@ -69,10 +116,11 @@
err(EXIT_FAILURE, "ENCIOC_GETELMSTAT");
}
o.cstat[0] |= 0x80;
- if (onoff)
- o.cstat[2] |= 0x02;
- else
- o.cstat[2] &= 0xfd;
+ if (onoff) {
+ o.cstat[2] |= (fault ? 0x20 : 0x02);
+ } else {
+ o.cstat[2] &= (fault ? 0xdf : 0xfd);
+ }
if (ioctl(fd, ENCIOC_SETELMSTAT, (caddr_t) &o) < 0) {
close(fd);
@@ -87,39 +135,53 @@
dname = devnames;
while ((dname = strstr(dname, disk)) != NULL) {
- if (dname[len] == '\0' || dname[len] == ',')
+ if (dname[len] == '\0' || dname[len] == ',') {
return (true);
+ }
dname++;
}
+
return (false);
}
static int
-locate(int argc, char **argv)
+sesled(int argc, char **argv, bool fault)
{
encioc_elm_devnames_t objdn;
encioc_element_t *objp;
glob_t g;
- char *disk;
- size_t len, i;
- int fd, nobj, j;
- bool all = false;
- bool onoff;
-
- if (argc != 2) {
- errx(EXIT_FAILURE, "usage: %s locate [disk] [on|off]",
- getprogname());
+ char *disk, *endptr;
+ size_t len, i, ndisks;
+ int fd;
+ unsigned int nobj, j, sesid;
+ bool all, isses, onoff;
+
+ isses = false;
+ all = false;
+ onoff = false;
+
+ if (argc != 3) {
+ usage(stderr, (fault ? "fault" : "locate"));
+ }
+
+ disk = argv[1];
+
+ sesid = strtoul(disk, &endptr, 10);
+ if (*endptr == '\0') {
+ if (uflag == NULL) {
+ warnx("Must specifying a SES device (-u) to use a SES "
+ "id# to identify a disk");
+ usage(stderr, (fault ? "fault" : "locate"));
+ }
+ isses = true;
}
- disk = argv[0];
-
- if (strcmp(argv[1], "on") == 0) {
+ if (strcmp(argv[2], "on") == 0) {
onoff = true;
- } else if (strcmp(argv[1], "off") == 0) {
+ } else if (strcmp(argv[2], "off") == 0) {
onoff = false;
} else {
- errx(EXIT_FAILURE, "usage: %s locate [disk] [on|off]",
- getprogname());
+ usage(stderr, (fault ? "fault" : "locate"));
}
if (strcmp(disk, "all") == 0) {
@@ -128,97 +190,347 @@
len = strlen(disk);
/* Get the list of ses devices */
- if (glob("/dev/ses[0-9]*", 0, NULL, &g) == GLOB_NOMATCH) {
+ if (glob((uflag != NULL ? uflag : "/dev/ses[0-9]*"), 0, NULL, &g) ==
+ GLOB_NOMATCH) {
globfree(&g);
errx(EXIT_FAILURE, "No SES devices found");
}
+
+ ndisks = 0;
for (i = 0; i < g.gl_pathc; i++) {
/* ensure we only got numbers after ses */
if (strspn(g.gl_pathv[i] + 8, "0123456789") !=
- strlen(g.gl_pathv[i] + 8))
+ strlen(g.gl_pathv[i] + 8)) {
continue;
+ }
if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) {
- if (errno == EACCES)
- err(EXIT_FAILURE, "enable to access SES device");
- break;
+ /*
+ * Don't treat non-access errors as critical if we are
+ * accessing all devices
+ */
+ if (errno == EACCES && g.gl_pathc > 1) {
+ err(EXIT_FAILURE, "unable to access SES device");
+ }
+ warn("unable to access SES device: %s", g.gl_pathv[i]);
+ continue;
}
- if (ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj) < 0)
+ if (ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj) < 0) {
+ close(fd);
err(EXIT_FAILURE, "ENCIOC_GETNELM");
+ }
objp = calloc(nobj, sizeof(encioc_element_t));
- if (objp == NULL)
+ if (objp == NULL) {
+ close(fd);
err(EXIT_FAILURE, "calloc()");
+ }
- if (ioctl(fd, ENCIOC_GETELMMAP, (caddr_t) objp) < 0)
+ if (ioctl(fd, ENCIOC_GETELMMAP, (caddr_t) objp) < 0) {
+ close(fd);
err(EXIT_FAILURE, "ENCIOC_GETELMMAP");
+ }
+ if (isses) {
+ if (sesid > nobj) {
+ close(fd);
+ errx(EXIT_FAILURE,
+ "Requested SES ID does not exist");
+ }
+ do_led(fd, sesid, onoff, fault);
+ ndisks++;
+ close(fd);
+ break;
+ }
for (j = 0; j < nobj; j++) {
memset(&objdn, 0, sizeof(objdn));
objdn.elm_idx = objp[j].elm_idx;
objdn.elm_names_size = 128;
objdn.elm_devnames = calloc(128, sizeof(char));
- if (objdn.elm_devnames == NULL)
+ if (objdn.elm_devnames == NULL) {
+ close(fd);
err(EXIT_FAILURE, "calloc()");
+ }
if (ioctl(fd, ENCIOC_GETELMDEVNAMES,
- (caddr_t) &objdn) <0)
+ (caddr_t) &objdn) <0) {
continue;
+ }
if (objdn.elm_names_len > 0) {
if (all) {
- do_locate(fd, objdn.elm_idx, onoff);
+ do_led(fd, objdn.elm_idx,
+ onoff, fault);
continue;
}
if (disk_match(objdn.elm_devnames, disk, len)) {
- do_locate(fd, objdn.elm_idx, onoff);
+ do_led(fd, objdn.elm_idx,
+ onoff, fault);
+ ndisks++;
break;
}
}
- }
+ }
close(fd);
}
globfree(&g);
+ if (ndisks == 0 && all == false) {
+ errx(EXIT_FAILURE, "Count not find the SES id of device '%s'",
+ disk);
+ }
return (EXIT_SUCCESS);
}
-static void
-usage(FILE *out)
+static int
+locate(int argc, char **argv)
{
- int i;
- fprintf(out, "Usage: %s [command] [options]\n", getprogname());
- fprintf(out, "Commands supported:\n");
- for (i = 0; i < nbcmds; i++)
- fprintf(out, "\t%-15s%s\n", cmds[i].name, cmds[i].desc);
+ return (sesled(argc, argv, false));
+}
+
+static int
+fault(int argc, char **argv)
+{
+
+ return (sesled(argc, argv, true));
+}
+
+static int
+objmap(int argc, char **argv __unused)
+{
+ encioc_elm_devnames_t e_devname;
+ encioc_elm_status_t e_status;
+ encioc_elm_desc_t e_desc;
+ encioc_element_t *e_ptr;
+ glob_t g;
+ int fd;
+ unsigned int j, nobj;
+ size_t i;
+
+ if (argc != 1) {
+ usage(stderr, "map");
+ }
+
+ /* Get the list of ses devices */
+ if (glob(uflag, 0, NULL, &g) == GLOB_NOMATCH) {
+ globfree(&g);
+ errx(EXIT_FAILURE, "No SES devices found");
+ }
+ for (i = 0; i < g.gl_pathc; i++) {
+ /* ensure we only got numbers after ses */
+ if (strspn(g.gl_pathv[i] + 8, "0123456789") !=
+ strlen(g.gl_pathv[i] + 8)) {
+ continue;
+ }
+ if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) {
+ /*
+ * Don't treat non-access errors as critical if we are
+ * accessing all devices
+ */
+ if (errno == EACCES && g.gl_pathc > 1) {
+ err(EXIT_FAILURE, "unable to access SES device");
+ }
+ warn("unable to access SES device: %s", g.gl_pathv[i]);
+ continue;
+ }
+
+ if (ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj) < 0) {
+ close(fd);
+ err(EXIT_FAILURE, "ENCIOC_GETNELM");
+ }
+
+ e_ptr = calloc(nobj, sizeof(encioc_element_t));
+ if (e_ptr == NULL) {
+ close(fd);
+ err(EXIT_FAILURE, "calloc()");
+ }
+
+ if (ioctl(fd, ENCIOC_GETELMMAP, (caddr_t) e_ptr) < 0) {
+ close(fd);
+ err(EXIT_FAILURE, "ENCIOC_GETELMMAP");
+ }
+
+ printf("%s:\n", g.gl_pathv[i] + 5);
+ for (j = 0; j < nobj; j++) {
+ /* Get the status of the element */
+ memset(&e_status, 0, sizeof(e_status));
+ e_status.elm_idx = e_ptr[j].elm_idx;
+ if (ioctl(fd, ENCIOC_GETELMSTAT,
+ (caddr_t) &e_status) < 0) {
+ close(fd);
+ err(EXIT_FAILURE, "ENCIOC_GETELMSTAT");
+ }
+ /* Get the description of the element */
+ memset(&e_desc, 0, sizeof(e_desc));
+ e_desc.elm_idx = e_ptr[j].elm_idx;
+ e_desc.elm_desc_len = UINT16_MAX;
+ e_desc.elm_desc_str = calloc(UINT16_MAX, sizeof(char));
+ if (e_desc.elm_desc_str == NULL) {
+ close(fd);
+ err(EXIT_FAILURE, "calloc()");
+ }
+ if (ioctl(fd, ENCIOC_GETELMDESC,
+ (caddr_t) &e_desc) < 0) {
+ close(fd);
+ err(EXIT_FAILURE, "ENCIOC_GETELMDESC");
+ }
+ /* Get the device name(s) of the element */
+ memset(&e_devname, 0, sizeof(e_devname));
+ e_devname.elm_idx = e_ptr[j].elm_idx;
+ e_devname.elm_names_size = 128;
+ e_devname.elm_devnames = calloc(128, sizeof(char));
+ if (e_devname.elm_devnames == NULL) {
+ close(fd);
+ err(EXIT_FAILURE, "calloc()");
+ }
+ if (ioctl(fd, ENCIOC_GETELMDEVNAMES,
+ (caddr_t) &e_devname) <0) {
+ /* We don't care if this fails */
+ e_devname.elm_devnames[0] = '\0';
+ }
+ printf("\tElement %u, Type: %s\n", e_ptr[j].elm_idx,
+ geteltnm(e_ptr[j].elm_type));
+ printf("\t\tStatus: %s\n",
+ stat2ascii(e_ptr[i].elm_type, e_status.cstat));
+ if (e_desc.elm_desc_len > 0) {
+ printf("\t\tDescription: %s\n",
+ e_desc.elm_desc_str);
+ }
+ if (e_devname.elm_names_len > 0) {
+ printf("\t\tDevice Names: %s\n",
+ e_devname.elm_devnames);
+ }
+ free(e_devname.elm_devnames);
+ }
+ close(fd);
+ }
+ globfree(&g);
+
+ return (EXIT_SUCCESS);
+}
+
+static int
+encstatus(int argc, char **argv __unused)
+{
+ glob_t g;
+ int fd, status;
+ size_t i, e;
+ u_char estat;
+
+ status = 0;
+ if (argc != 1) {
+ usage(stderr, "status");
+ }
+
+ /* Get the list of ses devices */
+ if (glob(uflag, 0, NULL, &g) == GLOB_NOMATCH) {
+ globfree(&g);
+ errx(EXIT_FAILURE, "No SES devices found");
+ }
+ for (i = 0; i < g.gl_pathc; i++) {
+ /* ensure we only got numbers after ses */
+ if (strspn(g.gl_pathv[i] + 8, "0123456789") !=
+ strlen(g.gl_pathv[i] + 8)) {
+ continue;
+ }
+ if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) {
+ /*
+ * Don't treat non-access errors as critical if we are
+ * accessing all devices
+ */
+ if (errno == EACCES && g.gl_pathc > 1) {
+ err(EXIT_FAILURE, "unable to access SES device");
+ }
+ warn("unable to access SES device: %s", g.gl_pathv[i]);
+ continue;
+ }
+
+ if (ioctl(fd, ENCIOC_GETENCSTAT, (caddr_t) &estat) < 0) {
+ close(fd);
+ err(EXIT_FAILURE, "ENCIOC_GETENCSTAT");
+ }
+
+ printf("%s: ", g.gl_pathv[i] + 5);
+ e = 0;
+ if (estat == 0) {
+ if (status == 0) {
+ status = 1;
+ }
+ printf("OK");
+ } else {
+ if (estat & SES_ENCSTAT_INFO) {
+ printf("INFO");
+ e++;
+ }
+ if (estat & SES_ENCSTAT_NONCRITICAL) {
+ if (e)
+ printf(",");
+ printf("NONCRITICAL");
+ e++;
+ }
+ if (estat & SES_ENCSTAT_CRITICAL) {
+ if (e)
+ printf(",");
+ printf("CRITICAL");
+ e++;
+ status = -1;
+ }
+ if (estat & SES_ENCSTAT_UNRECOV) {
+ if (e)
+ printf(",");
+ printf("UNRECOV");
+ e++;
+ status = -1;
+ }
+ }
+ printf("\n");
+
+ close(fd);
+ }
+ globfree(&g);
+
+ if (status == 1) {
+ return (EXIT_SUCCESS);
+ } else {
+ return (EXIT_FAILURE);
+ }
}
int
main(int argc, char **argv)
{
- int i;
+ int i, ch;
struct command *cmd = NULL;
- if (argc < 2) {
+ uflag = "/dev/ses[0-9]*";
+ while ((ch = getopt(argc, argv, "u:")) != -1) {
+ switch (ch) {
+ case 'u':
+ uflag = optarg;
+ break;
+ case '?':
+ default:
+ usage(stderr, NULL);
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 1) {
warnx("Missing command");
- usage(stderr);
- return (EXIT_FAILURE);
+ usage(stderr, NULL);
}
for (i = 0; i < nbcmds; i++) {
- if (strcmp(argv[1], cmds[i].name) == 0) {
+ if (strcmp(argv[0], cmds[i].name) == 0) {
cmd = &cmds[i];
break;
}
}
if (cmd == NULL) {
- warnx("unknown command %s", argv[1]);
- usage(stderr);
- return (EXIT_FAILURE);
+ warnx("unknown command %s", argv[0]);
+ usage(stderr, NULL);
}
- argc-=2;
- argv+=2;
-
return (cmd->exec(argc, argv));
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Mar 3, 11:44 AM (21 h, 30 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29198048
Default Alt Text
D3580.id8556.diff (17 KB)
Attached To
Mode
D3580: Improve and expand sesutil(8)
Attached
Detach File
Event Timeline
Log In to Comment