Subject: bin/34152: envstat(8) can't find some sensors when there is a hole in sensor numbers
To: None <gnats-admin@netbsd.org, netbsd-bugs@netbsd.org>
From: None <bsh@netbsd.org>
List: netbsd-bugs
Date: 08/07/2006 07:15:01
>Number: 34152
>Category: bin
>Synopsis: envstat(8) can't find some sensors when there is a `hole' in sensor numbers
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: bin-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Mon Aug 07 07:15:00 +0000 2006
>Originator: Hiroyuki Bessho
>Release: NetBSD 3.99.24
>Organization:
>Environment:
System: NetBSD nekozame.a.grotto.jp 3.99.24 NetBSD 3.99.24 (TSUYUBERA) #11: Sat Aug 5 16:42:19 JST 2006 bsh@nekozame.a.grotto.jp:/u1/proj/netbsd/tnf/current/src/sys/arch/i386/compile/obj.i386/TSUYUBERA i386
Architecture: i386
Machine: i386
>Description:
envsys assigns a number to each sensor. envstat(8) assumes
these sensor numbers are continuous beginning from 0. If the lowest
sensor number is not 0, or there is a hole in assigned sensor numbers,
envstat will fail to find some sensors.
It can happen when a driver for the sensors is an LKM, and the
driver is unloaded.
>How-To-Repeat:
Load LKM for envsys sensors, and unload it. run envstat.
If you don't have such LKM (I know you don't :-), try
following patch to lm driver.
Index: nslm7x.c
===================================================================
RCS file: /remote/kamasu/u0/cvsupbase/cvsroot-netbsd/src/sys/dev/ic/nslm7x.c,v
retrieving revision 1.27
diff -u -u -r1.27 nslm7x.c
--- nslm7x.c 8 Jun 2006 10:56:49 -0000 1.27
+++ nslm7x.c 7 Aug 2006 06:46:27 -0000
@@ -218,6 +218,10 @@
if (sysmon_envsys_register(&lmsc->sc_sysmon))
printf("%s: unable to register with sysmon\n",
lmsc->sc_dev.dv_xname);
+
+ /* Make a hole in register numbers for test. */
+ sysmon_envsys_unregister(&lmsc->sc_sysmon);
+ sysmon_envsys_register(&lmsc->sc_sysmon);
}
int
>Fix:
Index: envstat.c
===================================================================
RCS file: /remote/kamasu/u0/cvsupbase/cvsroot-netbsd/src/usr.sbin/envstat/envstat.c,v
retrieving revision 1.22
diff -u -u -r1.22 envstat.c
--- envstat.c 3 Jun 2004 16:48:53 -0000 1.22
+++ envstat.c 7 Aug 2006 06:57:11 -0000
@@ -55,8 +55,8 @@
int main(int, char **);
void listsensors(envsys_basic_info_t *, size_t);
-size_t numsensors(int);
-void fillsensors(int, envsys_tre_data_t *, envsys_basic_info_t *, size_t);
+void getrange(int, envsys_range_t *);
+int fillsensors(int, envsys_tre_data_t *, envsys_basic_info_t *, int, int);
size_t longestname(envsys_basic_info_t *, size_t);
int marksensors(envsys_basic_info_t *, int *, char *, size_t);
int strtosnum(envsys_basic_info_t *, const char *, size_t);
@@ -79,6 +79,7 @@
int *cetds;
char *sensors;
const char *dev;
+ struct envsys_range rng;
fd = -1;
ls = 0;
@@ -133,9 +134,11 @@
* Determine number of sensors, allocate and fill arrays with
* initial information. Determine column width
*/
- if ((ns = numsensors(fd)) == 0)
+ getrange(fd, &rng);
+ if (rng.low > rng.high)
errx(1, "No sensors found");
+ ns = rng.high - rng.low + 1;
cetds = (int *)malloc(ns * sizeof(int));
etds = (envsys_tre_data_t *)malloc(ns * sizeof(envsys_tre_data_t));
ebis = (envsys_basic_info_t *)malloc(ns * sizeof(envsys_basic_info_t));
@@ -143,7 +146,8 @@
if ((cetds == NULL) || (etds == NULL) || (ebis == NULL))
err(1, "Out of memory");
- fillsensors(fd, etds, ebis, ns);
+ if (fillsensors(fd, etds, ebis, rng.low, rng.high) <= 0)
+ errx(1, "No sensors found");
if (ls) {
listsensors(ebis, ns);
@@ -170,7 +174,7 @@
while (1) {
printrow(cetds, etds, ebis, ns, celsius, width);
sleep(interval);
- fillsensors(fd, etds, ebis, ns);
+ fillsensors(fd, etds, ebis, rng.low, rng.high);
printf("\n");
}
}
@@ -199,7 +203,7 @@
sleep(interval);
- fillsensors(fd, etds, ebis, ns);
+ fillsensors(fd, etds, ebis, rng.low, rng.high);
}
/* NOTREACHED */
@@ -373,52 +377,61 @@
/*
* pre: fd contains a valid file descriptor of an envsys(4) supporting device
- * post: returns the number of valid sensors provided by the device
- * or -1 on error
+ * post: returns the lowest and highest number of sensors
*/
-size_t
-numsensors(int fd)
+void
+getrange(int fd, struct envsys_range *rng)
{
- int count = 0, valid = 1;
+ int i;
envsys_tre_data_t etd;
- etd.sensor = 0;
- while (valid) {
+ rng->units = -1; /* All type of sensors */
+ if (ioctl(fd, ENVSYS_GRANGE, rng))
+ err(1, "ioctl(ENVSYS_GRANGE) failed");
+ if (rng->low > rng->high)
+ return;
+
+ for (i=rng->low; i <= rng->high; ++i) {
+ etd.sensor = i;
if (ioctl(fd, ENVSYS_GTREDATA, &etd) == -1)
err(1, "Can't get sensor data");
- valid = etd.validflags & ENVSYS_FVALID;
- if (valid)
- ++count;
-
- ++etd.sensor;
+ if (etd.validflags & ENVSYS_FVALID)
+ break;
+ else if (i == rng->low)
+ rng->low++;
}
-
- return count;
}
/*
* pre: fd contains a valid file descriptor of an envsys(4) supporting device
* && ns is the number of sensors
* && etds and ebis are arrays of sufficient size
- * post: returns 0 and etds and ebis arrays are filled with sensor info
- * or returns -1 on failure
+ * post: return number of valid sensors.
*/
-void
+int
fillsensors(int fd, envsys_tre_data_t *etds, envsys_basic_info_t *ebis,
- size_t ns)
+ int low, int high)
{
- int i;
+ int i, n;
+ int count = 0;
- for (i = 0; i < ns; ++i) {
- ebis[i].sensor = i;
+ for (i=0, n = low; n <= high; ++i, ++n) {
+ ebis[i].sensor = n;
if (ioctl(fd, ENVSYS_GTREINFO, &ebis[i]) == -1)
err(1, "Can't get sensor info for sensor %d", i);
- etds[i].sensor = i;
+ etds[i].sensor = n;
if (ioctl(fd, ENVSYS_GTREDATA, &etds[i]) == -1)
err(1, "Can't get sensor data for sensor %d", i);
+
+ if ((ebis[i].validflags & ENVSYS_FVALID) &&
+ (etds[i].validflags & ENVSYS_FVALID))
+ ++count;
+
}
+
+ return count;
}
@@ -450,6 +463,7 @@
{
size_t i;
char *s;
+ int found=0;
if (sensors == NULL) {
/* No sensors specified, include them all */
@@ -465,8 +479,10 @@
s = strtok(sensors, ",");
while (s != NULL) {
int snum;
- if ((snum = strtosnum(ebis, s, ns)) != -1)
+ if ((snum = strtosnum(ebis, s, ns)) != -1) {
cetds[snum] = 1;
+ found=1;
+ }
else {
warnx("Unknown sensor %s", s);
return (-1);
@@ -476,9 +492,8 @@
}
/* Check if we have at least one sensor selected for output */
- for (i = 0; i < ns; ++i)
- if (cetds[i] == 1)
- return (0);
+ if (found)
+ return (0);
warnx("No sensors selected for display");
return (-1);
@@ -497,7 +512,7 @@
for (i = 0; i < ns; ++i) {
if((ebis[i].validflags & ENVSYS_FVALID) &&
!strcmp(s, ebis[i].desc))
- return ebis[i].sensor;
+ return i;
}
return -1;
>Unformatted: