From 5a5cdfa229a4a633b28890bfe4f9dfcc4909f9b5 Mon Sep 17 00:00:00 2001 From: sevan Date: Wed, 26 Dec 2018 01:47:37 +0000 Subject: [PATCH] Extend "systat vm" output to provide better insight about buffercache and document it. From Greg A. Woods in PR bin/36542 --- usr.bin/systat/bufcache.c | 8 +-- usr.bin/systat/cmdtab.c | 7 +- usr.bin/systat/main.c | 26 ++++---- usr.bin/systat/systat.1 | 106 +++++++++++++++++++++++++----- usr.bin/systat/systat.h | 1 - usr.bin/systat/vmstat.c | 133 +++++++++++++++++++++++++++++--------- 6 files changed, 214 insertions(+), 67 deletions(-) diff --git a/usr.bin/systat/bufcache.c b/usr.bin/systat/bufcache.c index 5e8a3efed2be..43c9c112a952 100644 --- a/usr.bin/systat/bufcache.c +++ b/usr.bin/systat/bufcache.c @@ -1,4 +1,4 @@ -/* $NetBSD: bufcache.c,v 1.28 2017/06/09 00:13:29 chs Exp $ */ +/* $NetBSD: bufcache.c,v 1.29 2018/12/26 01:47:37 sevan Exp $ */ /*- * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ #include #ifndef lint -__RCSID("$NetBSD: bufcache.c,v 1.28 2017/06/09 00:13:29 chs Exp $"); +__RCSID("$NetBSD: bufcache.c,v 1.29 2018/12/26 01:47:37 sevan Exp $"); #endif /* not lint */ #include @@ -117,8 +117,8 @@ labelbufcache(void) wmove(wnd, i, 0); wclrtoeol(wnd); } - mvwaddstr(wnd, PAGEINFO_ROWS + 1, 0, "File System Bufs used" - " % kB in use % Bufsize kB % Util %"); + mvwaddstr(wnd, PAGEINFO_ROWS + 1, 0, +"File System Bufs used % kB in use % Bufsize kB % Util %"); wclrtoeol(wnd); } diff --git a/usr.bin/systat/cmdtab.c b/usr.bin/systat/cmdtab.c index ab8f78880a5c..70da34d4f7e1 100644 --- a/usr.bin/systat/cmdtab.c +++ b/usr.bin/systat/cmdtab.c @@ -1,4 +1,4 @@ -/* $NetBSD: cmdtab.c,v 1.25 2016/08/02 15:56:09 scole Exp $ */ +/* $NetBSD: cmdtab.c,v 1.26 2018/12/26 01:47:37 sevan Exp $ */ /*- * Copyright (c) 1980, 1992, 1993 @@ -34,7 +34,7 @@ #if 0 static char sccsid[] = "@(#)cmdtab.c 8.1 (Berkeley) 6/6/93"; #endif -__RCSID("$NetBSD: cmdtab.c,v 1.25 2016/08/02 15:56:09 scole Exp $"); +__RCSID("$NetBSD: cmdtab.c,v 1.26 2018/12/26 01:47:37 sevan Exp $"); #endif /* not lint */ #include "systat.h" @@ -52,6 +52,7 @@ struct command global_commands[] = { { "quit", global_quit, "exit systat"}, { "start", global_interval, "restart updating display"}, { "stop", global_stop, "stop updating display"}, + { "?", global_help, "show help"}, { .c_name = NULL } }; @@ -114,7 +115,7 @@ struct command netstat_commands[] = { { "names", netstat_names, "show names instead of addresses"}, { "numbers", netstat_numbers, "show addresses instead of names"}, { "reset", netstat_reset, "return to default display"}, - { "show", netstat_show, "show current display/ignore settings"}, + { "show", netstat_show, "show current display/ignore settings"}, { "tcp", netstat_tcp, "show only tcp connections"}, { "udp", netstat_udp, "show only udp connections"}, { .c_name = NULL } diff --git a/usr.bin/systat/main.c b/usr.bin/systat/main.c index faeb714f8b1b..3325d5f147bc 100644 --- a/usr.bin/systat/main.c +++ b/usr.bin/systat/main.c @@ -1,4 +1,4 @@ -/* $NetBSD: main.c,v 1.53 2017/11/22 02:52:42 snj Exp $ */ +/* $NetBSD: main.c,v 1.54 2018/12/26 01:47:37 sevan Exp $ */ /*- * Copyright (c) 1980, 1992, 1993 @@ -36,7 +36,7 @@ __COPYRIGHT("@(#) Copyright (c) 1980, 1992, 1993\ #if 0 static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/6/93"; #endif -__RCSID("$NetBSD: main.c,v 1.53 2017/11/22 02:52:42 snj Exp $"); +__RCSID("$NetBSD: main.c,v 1.54 2018/12/26 01:47:37 sevan Exp $"); #endif /* not lint */ #include @@ -66,7 +66,7 @@ char *nlistf = NULL; sig_t sigtstpdfl; double avenrun[3]; int col; -double naptime = 5; +double naptime = 1; int verbose = 1; /* to report kvm read errs */ int hz, stathz, maxslp; char c; @@ -173,10 +173,8 @@ main(int argc, char **argv) (void)setegid(egid); kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf); - if (kd == NULL) { - error("%s", errbuf); - exit(1); - } + if (kd == NULL) + errx(1, "%s", errbuf); /* Get rid of privs for now. */ if (nlistf == NULL && memf == NULL) @@ -194,19 +192,24 @@ main(int argc, char **argv) * routines to minimize update work by curses. */ if (initscr() == NULL) - { - warnx("couldn't initialize screen"); - exit(0); - } + errx(1, "couldn't initialize screen"); CMDLINE = LINES - 1; wnd = (*curmode->c_open)(); if (wnd == NULL) { + move(CMDLINE, 0); + clrtoeol(); + refresh(); + endwin(); warnx("couldn't initialize display"); die(0); } wload = newwin(1, 0, 3, 20); if (wload == NULL) { + move(CMDLINE, 0); + clrtoeol(); + refresh(); + endwin(); warnx("couldn't set up load average window"); die(0); } @@ -411,7 +414,6 @@ nlisterr(struct nlist name_list[]) move(CMDLINE, 0); clrtoeol(); refresh(); - sleep(5); endwin(); exit(1); } diff --git a/usr.bin/systat/systat.1 b/usr.bin/systat/systat.1 index 1ce04b71daa0..a356947927ff 100644 --- a/usr.bin/systat/systat.1 +++ b/usr.bin/systat/systat.1 @@ -1,4 +1,4 @@ -.\" $NetBSD: systat.1,v 1.48 2017/07/03 21:34:21 wiz Exp $ +.\" $NetBSD: systat.1,v 1.49 2018/12/26 01:47:37 sevan Exp $ .\" .\" Copyright (c) 1985, 1990, 1993 .\" The Regents of the University of California. All rights reserved. @@ -29,7 +29,7 @@ .\" .\" @(#)systat.1 8.2 (Berkeley) 12/30/93 .\" -.Dd November 16, 2016 +.Dd December 26, 2018 .Dt SYSTAT 1 .Os .Sh NAME @@ -454,7 +454,22 @@ etc. The upper left quadrant of the screen shows the number of users logged in and the load average over the last one, five, and fifteen minute intervals. -Below this is a list of the +Below this are statistics on memory utilization. +The first row of the table reports memory usage only among +active processes, that is processes that have run in the previous +twenty seconds. +The second row reports on memory usage of all processes. +The first column reports on the number of physical pages +claimed by processes. +The second column reports the number of physical pages that +are devoted to read only text pages. +The third and fourth columns report the same two figures for +virtual pages, that is the number of pages that would be +needed if all processes had all of their pages. +Finally the last column shows the number of physical pages +on the free list. +.Pp +Below the memory display is a list of the average number of processes (over the last refresh interval) that are runnable (`r'), in page wait (`p'), in disk wait other than paging (`d'), sleeping (`s'). @@ -465,9 +480,9 @@ nice (shown as `-'), and idle time (shown as ` '). .Pp To the right of the process statistics is a column that lists the average number of context switches (`Csw'), -traps (`Trp'; includes page faults), system calls (`Sys'), interrupts (`Int'), -network software interrupts (`Sof'), -page faults (`Flt'). +traps (`Traps'; includes page faults), system calls (`SysCa'), interrupts (`Intr'), +network software interrupts (`Soft'), +page faults (`Fault'). .Pp Below this are statistics on memory utilization. The first row of the table reports memory usage only among @@ -509,16 +524,75 @@ the second row of the display shows the average number of pages transferred per second over the last refresh interval. .Pp Below the paging statistics is another columns of paging data. -From top to bottom, these represent average numbers of copy on write faults -(`cow'), object cache lookups (`objlk'), object cache hits (`objht'), -pages zero filled on demand (`zfodw'), number zfod's created (`nzfod'), -percentage of zfod's used (`%zfod'), number of kernel pages (`kern'), -number of wired pages (`wire'), number of active pages (`act'), number -of inactive pages (`inact'), number of free pages (`free'), pages freed -by daemon (`daefr'), pages freed by exiting processes (`prcfr'), number -of pages reactivated from freelist (`react'), scans in page out daemon -(`scan'), revolutions of the hand (`hdrev'), and in-transit blocking page -faults (`intrn'), per second over the refresh period. +From top to bottom, these represent: +.Pp +.Bl -tag -width Fl -compact +.It Ic Sq forks +number of fork() calls +.It Ic Sq fkppw +number of fork() calls where parent waits +.It Ic Sq fksvm +number of fork() calls where vmspace is shared +.It Ic Sq pwait +number of times fault had to wait on a page +.It Ic Sq relck +number of times uvmfault_relock() is called +.It Ic Sq rlkok +number of times uvmfault_relock() is a success +.It Ic Sq noram +number of times fault was out of RAM +.It Ic Sq ndcpy +number of times fault clears ``needs copy'' +.It Ic Sq fltcp +number of times fault promotes with copy (2b) +.It Ic Sq zfod +number of times fault promotes with zerofill (2b) +.It Ic Sq cow +number of times faulted for anonymous for Copy-On-Write (case 1b) +.It Ic Sq fmin +min number of free pages +.It Ic Sq ftarg +target number of free pages +.It Ic Sq itarg +target number of inactive pages +.\".It Ic Sq objlk +.\"object cache lookups +.\".It Ic Sq objht +.\"object cache hits +.\".It Ic Sq zfodw +.\"pages zero filled on demand +.\".It Ic Sq nzfod +.\"number of zfod's created +.\".It Ic Sq %zfod +.\"percentage of zfod's used +.\".It Ic Sq kern +.\"number of kernel pages +.It Ic Sq flnan +number of times fault was out of anonymous pages +.\".It Ic Sq act +.\"number of active pages +.\".It Ic Sq inact +.\"number of inactive pages +.\".It Ic Sq free +.\"number of free pages +.\".It Ic Sq daefr +.\"pages freed by daemon +.\".It Ic Sq prcfr +.\"pages freed by exiting processes +.\".It Ic Sq react +.\"number of pages reactivated from freelist +.\".It Ic Sq scan +.\"scans in page out daemon +.\".It Ic Sq hdrev +.\"revolutions of the hand +.\".It Ic Sq intrn +.\"in-transit blocking page faults per second over the refresh period. +.It Ic Sq pdfre +number of pages daemon freed since boot +.It Ic Sq pdscn +number of pages daemon scaned since boot +.El +.Pp Note that the `%zfod' percentage is usually less than 100%, however it may exceed 100% if a large number of requests are actually used long after they were set up during a diff --git a/usr.bin/systat/systat.h b/usr.bin/systat/systat.h index a8a8da752b07..97db3b133c21 100644 --- a/usr.bin/systat/systat.h +++ b/usr.bin/systat/systat.h @@ -61,4 +61,3 @@ struct command { #define NVAL(indx) namelist[(indx)].n_value #define NPTR(indx) (void *)NVAL((indx)) #define NREAD(indx, buf, len) kvm_ckread(NPTR((indx)), (buf), (len), # indx) -#define LONG (sizeof (long)) diff --git a/usr.bin/systat/vmstat.c b/usr.bin/systat/vmstat.c index 06bd123e42c8..7af1bd99c2fc 100644 --- a/usr.bin/systat/vmstat.c +++ b/usr.bin/systat/vmstat.c @@ -1,4 +1,4 @@ -/* $NetBSD: vmstat.c,v 1.82 2017/07/15 08:22:23 mlelstv Exp $ */ +/* $NetBSD: vmstat.c,v 1.83 2018/12/26 01:47:37 sevan Exp $ */ /*- * Copyright (c) 1983, 1989, 1992, 1993 @@ -34,7 +34,7 @@ #if 0 static char sccsid[] = "@(#)vmstat.c 8.2 (Berkeley) 1/12/94"; #endif -__RCSID("$NetBSD: vmstat.c,v 1.82 2017/07/15 08:22:23 mlelstv Exp $"); +__RCSID("$NetBSD: vmstat.c,v 1.83 2018/12/26 01:47:37 sevan Exp $"); #endif /* not lint */ /* @@ -87,6 +87,7 @@ static long *intrloc; static char **intrname; static int nextintsrow; static int disk_horiz = 1; +static u_int nbuf; WINDOW * openvmstat(void) @@ -124,7 +125,7 @@ static struct nlist namelist[] = { */ #define STATROW 0 /* uses 1 row and 68 cols */ #define STATCOL 2 -#define MEMROW 9 /* uses 4 rows and 31 cols */ +#define MEMROW 9 /* uses 5 rows and 31 cols */ #define MEMCOL 0 #define PAGEROW 2 /* uses 4 rows and 26 cols */ #define PAGECOL 54 @@ -139,11 +140,11 @@ static struct nlist namelist[] = { #define VMSTATCOL 64 #define GRAPHROW 5 /* uses 3 rows and 51 cols */ #define GRAPHCOL 0 -#define NAMEIROW 14 /* uses 3 rows and 38 cols */ +#define NAMEIROW 15 /* uses 3 rows and 38 cols (must be MEMROW + 5 + 1) */ #define NAMEICOL 0 -#define DISKROW 18 /* uses 5 rows and 50 cols (for 9 drives) */ +#define DISKROW 19 /* uses 5 rows and 50 cols (for 9 drives) */ #define DISKCOL 0 -#define DISKCOLWIDTH 6 +#define DISKCOLWIDTH 8 #define DISKCOLEND INTSCOL typedef struct intr_evcnt intr_evcnt_t; @@ -318,7 +319,7 @@ labelvmstat_top(void) mvprintw(STATROW, STATCOL + 4, "users Load"); - mvprintw(GENSTATROW, GENSTATCOL, " Csw Trp Sys Int Sof Flt"); + mvprintw(GENSTATROW, GENSTATCOL, " Csw Traps SysCal Intr Soft Fault"); mvprintw(GRAPHROW, GRAPHCOL, " . %% Sy . %% Us . %% Ni . %% In . %% Id"); @@ -328,8 +329,8 @@ labelvmstat_top(void) mvprintw(PAGEROW, PAGECOL + 8, "PAGING SWAPPING "); mvprintw(PAGEROW + 1, PAGECOL, " in out in out "); - mvprintw(PAGEROW + 2, PAGECOL + 2, "ops"); - mvprintw(PAGEROW + 3, PAGECOL, "pages"); + mvprintw(PAGEROW + 2, PAGECOL, " ops "); + mvprintw(PAGEROW + 3, PAGECOL, "pages "); } void @@ -343,26 +344,28 @@ labelvmstat(void) /* Left hand column */ - mvprintw(MEMROW, MEMCOL, " memory totals (in kB)"); - mvprintw(MEMROW + 1, MEMCOL, " real virtual free"); - mvprintw(MEMROW + 2, MEMCOL, "Active"); - mvprintw(MEMROW + 3, MEMCOL, "All"); + mvprintw(MEMROW + 0, MEMCOL, "Anon %% zero "); + mvprintw(MEMROW + 1, MEMCOL, "Exec %% wired "); + mvprintw(MEMROW + 2, MEMCOL, "File %% inact "); + mvprintw(MEMROW + 3, MEMCOL, "Meta %% bufs "); + mvprintw(MEMROW + 4, MEMCOL, " (kB) real swaponly free"); + mvprintw(MEMROW + 5, MEMCOL, "Active "); mvprintw(NAMEIROW, NAMEICOL, "Namei Sys-cache Proc-cache"); mvprintw(NAMEIROW + 1, NAMEICOL, " Calls hits %% hits %%"); - mvprintw(DISKROW, DISKCOL, "Disks:"); + mvprintw(DISKROW, DISKCOL, "%*s", DISKCOLWIDTH, "Disks:"); if (disk_horiz) { mvprintw(DISKROW + 1, DISKCOL + 1, "seeks"); mvprintw(DISKROW + 2, DISKCOL + 1, "xfers"); mvprintw(DISKROW + 3, DISKCOL + 1, "bytes"); mvprintw(DISKROW + 4, DISKCOL + 1, "%%busy"); } else { - mvprintw(DISKROW, DISKCOL + 1 + 1 * DISKCOLWIDTH, "seeks"); - mvprintw(DISKROW, DISKCOL + 1 + 2 * DISKCOLWIDTH, "xfers"); - mvprintw(DISKROW, DISKCOL + 1 + 3 * DISKCOLWIDTH, "bytes"); - mvprintw(DISKROW, DISKCOL + 1 + 4 * DISKCOLWIDTH, "%%busy"); + mvprintw(DISKROW, DISKCOL + 1 * DISKCOLWIDTH, "%*s", DISKCOLWIDTH, "seeks"); + mvprintw(DISKROW, DISKCOL + 2 * DISKCOLWIDTH, "%*s", DISKCOLWIDTH, "xfers"); + mvprintw(DISKROW, DISKCOL + 3 * DISKCOLWIDTH, "%*s", DISKCOLWIDTH, "bytes"); + mvprintw(DISKROW, DISKCOL + 4 * DISKCOLWIDTH, "%*s", DISKCOLWIDTH, "%%busy"); } /* Middle column */ @@ -396,7 +399,7 @@ labelvmstat(void) mvprintw(VMSTATROW + 11, VMSTATCOL + 10, "fmin"); mvprintw(VMSTATROW + 12, VMSTATCOL + 10, "ftarg"); mvprintw(VMSTATROW + 13, VMSTATCOL + 10, "itarg"); - mvprintw(VMSTATROW + 14, VMSTATCOL + 10, "wired"); + mvprintw(VMSTATROW + 14, VMSTATCOL + 10, "flnan"); mvprintw(VMSTATROW + 15, VMSTATCOL + 10, "pdfre"); if (LINES - 1 > VMSTATROW + 16) @@ -447,6 +450,11 @@ show_vmstat_top(vmtotal_t *Total, uvmexp_sysctl_t *uvm, uvmexp_sysctl_t *uvm1) PUTRATE(us, us1, uvmexp->softs, GENSTATROW + 1, GENSTATCOL + 27, 6); PUTRATE(us, us1, uvmexp->faults, GENSTATROW + 1, GENSTATCOL + 34, 6); + /* + * XXX it sure would be nice if this did what top(1) does and showed + * the utilization of each CPU on a separate line, though perhaps IFF + * the screen is tall enough + */ /* Last CPU state not calculated yet. */ for (f2 = 0.0, psiz = 0, c = 0; c < CPUSTATES; c++) { i = cpuorder[c]; @@ -476,6 +484,11 @@ showvmstat(void) static int relabel = 0; static int last_disks = 0; static char pigs[] = "pigs"; + static u_long bufmem; + struct buf_sysctl *buffers; + int mib[6]; + size_t size; + int extraslop = 0; if (relabel) { labelvmstat(); @@ -507,16 +520,74 @@ showvmstat(void) /* Memory totals */ #define pgtokb(pg) ((pg) * (s.uvmexp.pagesize / 1024)) - putint(pgtokb(s.uvmexp.active), MEMROW + 2, MEMCOL + 6, 9); - putint(pgtokb(s.uvmexp.active + s.uvmexp.swpginuse), /* XXX */ - MEMROW + 2, MEMCOL + 16, 9); - putint(pgtokb(s.uvmexp.npages - s.uvmexp.free), - MEMROW + 3, MEMCOL + 6, 9); - putint(pgtokb(s.uvmexp.npages - s.uvmexp.free + s.uvmexp.swpginuse), - MEMROW + 3, MEMCOL + 16, 9); - putint(pgtokb(s.uvmexp.free), MEMROW + 2, MEMCOL + 26, 9); - putint(pgtokb(s.uvmexp.free + s.uvmexp.swpages - s.uvmexp.swpginuse), - MEMROW + 3, MEMCOL + 26, 9); + + putint(pgtokb(s.uvmexp.anonpages), MEMROW + 0, MEMCOL + 7, 10); + putint((s.uvmexp.anonpages * 100 + 0.5) / s.uvmexp.npages, MEMROW + 0, MEMCOL + 17, 4); + + putint(pgtokb(s.uvmexp.zeropages), MEMROW + 0, MEMCOL + 30, 8); + + putint(pgtokb(s.uvmexp.execpages), MEMROW + 1, MEMCOL + 7, 10); + putint((s.uvmexp.execpages * 100 + 0.5) / s.uvmexp.npages, MEMROW + 1, MEMCOL + 17, 4); + + putint(pgtokb(s.uvmexp.wired), MEMROW + 1, MEMCOL + 30, 8); + + putint(pgtokb(s.uvmexp.filepages), MEMROW + 2, MEMCOL + 7, 10); + putint((s.uvmexp.filepages * 100 + 0.5) / s.uvmexp.npages, MEMROW + 2, MEMCOL + 17, 4); + + putint(pgtokb(s.uvmexp.inactive), MEMROW + 2, MEMCOL + 30, 8); + + /* Get total size of metadata buffers */ + size = sizeof(bufmem); + if (sysctlbyname("vm.bufmem", &bufmem, &size, NULL, 0) < 0) { + error("can't get buffers size: %s\n", strerror(errno)); + return; + } + + /* Get number of metadata buffers */ + size = 0; + buffers = NULL; + mib[0] = CTL_KERN; + mib[1] = KERN_BUF; + mib[2] = KERN_BUF_ALL; + mib[3] = KERN_BUF_ALL; + mib[4] = (int)sizeof(struct buf_sysctl); + mib[5] = INT_MAX; /* we want them all */ +again: + if (sysctl(mib, 6, NULL, &size, NULL, 0) < 0) { + error("can't get buffers size: %s\n", strerror(errno)); + return; + } + if (size == 0) { + error("buffers size is zero: %s\n", strerror(errno)); + return; + } + size += extraslop * sizeof(struct buf_sysctl); + buffers = malloc(size); + if (buffers == NULL) { + error("can't allocate buffers: %s\n", strerror(errno)); + return; + } + if (sysctl(mib, 6, buffers, &size, NULL, 0) < 0) { + free(buffers); + if (extraslop == 0) { + extraslop = 100; + goto again; + } + error("can't get buffers: %s\n", strerror(errno)); + return; + } + free(buffers); /* XXX there must be a better way! */ + nbuf = size / sizeof(struct buf_sysctl); + + putint((int) (bufmem / 1024), MEMROW + 3, MEMCOL + 5, 12); + putint((int) ((bufmem * 100) + 0.5) / s.uvmexp.pagesize / s.uvmexp.npages, + MEMROW + 3, MEMCOL + 17, 4); + putint(nbuf, MEMROW + 3, MEMCOL + 30, 8); + + putint(pgtokb(s.uvmexp.active), MEMROW + 5, MEMCOL + 7, 10); + putint(pgtokb(s.uvmexp.swpgonly), MEMROW + 5, MEMCOL + 18, 10); + putint(pgtokb(s.uvmexp.free), MEMROW + 5, MEMCOL + 28, 10); + #undef pgtokb /* Namei cache */ @@ -633,7 +704,7 @@ showvmstat(void) putint(s.uvmexp.freemin, VMSTATROW + 11, VMSTATCOL, 9); putint(s.uvmexp.freetarg, VMSTATROW + 12, VMSTATCOL, 9); putint(s.uvmexp.inactarg, VMSTATROW + 13, VMSTATCOL, 9); - putint(s.uvmexp.wired, VMSTATROW + 14, VMSTATCOL, 9); + putint(s.uvmexp.fltnoanon, VMSTATROW + 14, VMSTATCOL, 9); PUTRATE(s, s1, uvmexp.pdfreed, VMSTATROW + 15, VMSTATCOL, 9); if (LINES - 1 > VMSTATROW + 16) PUTRATE(s, s1, uvmexp.pdscans, VMSTATROW + 16, VMSTATCOL, 9); @@ -776,7 +847,7 @@ getinfo(struct Info *stats) memset(&stats->nchstats, 0, sizeof(stats->nchstats)); } if (nintr) - NREAD(X_INTRCNT, stats->intrcnt, nintr * LONG); + NREAD(X_INTRCNT, stats->intrcnt, nintr * sizeof(long)); for (i = 0; i < nevcnt; i++) KREAD(ie_head[i].ie_count, &stats->evcnt[i], sizeof stats->evcnt[i]);