1
0
Files
irix-657m-src/eoe/cmd/sun/nfsstat.c
2022-09-29 17:59:04 +03:00

951 lines
19 KiB
C

#ifndef lint
static char sccsid[] = "@(#)nfsstat.c 1.2 88/05/17 4.0NFSSRC Copyr 1988 Sun Micro";
#endif
/*
* Copyright (c) 1984 by Sun Microsystems, Inc.
*/
/*
* nfsstat: Network File System statistics
*/
#include <stdio.h>
#include <stdarg.h>
#include <getopt.h>
#include <errno.h>
#include <curses.h>
#include <string.h>
#include <sys/time.h>
#include <sys/times.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <sys/signal.h>
#include <sys/sysmp.h>
# include <sys/immu.h>
/*
* client side rpc statistics
* NOTE: These data structures must match the kernel ones in nfs_stat.h!
*/
struct rcstat {
int rccalls;
int rcbadcalls;
int rcretrans;
int rcbadxids;
int rctimeouts;
int rcwaits;
int rcnewcreds;
int rcbadverfs;
} rcstat;
/*
* client side nfs statistics
*/
struct clstat {
int nclsleeps; /* client handle waits */
int nclgets; /* client handle gets */
int ncalls; /* client requests */
int nbadcalls; /* rpc failures */
int reqs[32]; /* count of each request */
} clstat, clstat3;
/*
* Server side rpc statistics
*/
struct rsstat {
int rscalls;
int rsbadcalls;
int rsnullrecv;
int rsbadlen;
int rsxdrcall;
int rsduphits; /* duplicate request cache hits */
int rsdupage; /* average age of recycled cache entries */
} rsstat;
/*
* server side nfs statistics
*/
struct svstat {
int ncalls; /* number of calls received */
int nbadcalls; /* calls that failed */
int reqs[32]; /* count for each request */
} svstat, svstat3;
static int ccode = 1; /* SGI doesn't separate these two */
static int scode = 1; /* Identify server and client code present */
static int Interval = 1; /* seconds for below */
static int Cflag = 0; /* Continuous stat display */
static int gotstats = 0;
static void disp(int);
static void getstats(void);
static void putstats(void);
static void cr_print(int);
static void sr_print(int);
static void cn_print(int);
static void cn_print3(int);
static void sn_print(int);
static void sn_print3(int);
static void req_print(u_int *, u_int, char **, int);
static void usage(void);
main(argc, argv)
char *argv[];
{
int cflag = 0; /* client stats */
int sflag = 0; /* server stats */
int nflag = 0; /* nfs stats */
int rflag = 0; /* rpc stats */
int zflag = 0; /* zero stats after printing */
int c;
opterr = 0;
while ((c = getopt(argc, argv, "Ccnrsz")) != EOF)
switch (c) {
case 'C':
Cflag++;
break;
case 'c':
cflag++;
break;
case 'n':
nflag++;
break;
case 'r':
rflag++;
break;
case 's':
sflag++;
break;
case 'z':
if (getuid()) {
fprintf(stderr,
"Must be root for z flag\n");
exit(1);
}
zflag++;
break;
default:
usage();
}
if (optind < argc) {
Interval = atoi(argv[optind]);
if (Interval > 0)
optind++;
}
if (optind < argc)
usage();
if (Cflag)
disp(sflag ? 1 : 0);
getstats();
if (sflag && (!scode)) {
fprintf(stderr,"nfsstat: kernel is not configured with the server nfs and rpc code.\n");
}
if ((sflag || (!sflag && !cflag)) && scode) {
if (rflag || (!rflag && !nflag)) {
sr_print(zflag);
}
if (nflag || (!rflag && !nflag)) {
sn_print(zflag);
sn_print3(zflag);
}
}
if (cflag && (!ccode)) {
fprintf(stderr,"nfsstat: kernel is not configured with the client nfs and rpc code.\n");
}
if ((cflag || (!sflag && !cflag)) && ccode) {
if (rflag || (!rflag && !nflag)) {
cr_print(zflag);
}
if (nflag || (!rflag && !nflag)) {
cn_print(zflag);
cn_print3(zflag);
}
}
if (zflag) {
putstats();
}
exit(0);
}
static void
getstats()
{
gotstats++;
if (ccode) {
if (sysmp(MP_SAGET, MPSA_RCSTAT, &rcstat, sizeof(rcstat))
== -1) {
fprintf(stderr,"can't read rcstat\n");
exit(1);
}
if (sysmp(MP_SAGET, MPSA_CLSTAT, &clstat, sizeof(clstat))
== -1) {
fprintf(stderr,"can't read clstat\n");
exit(1);
}
if (sysmp(MP_SAGET, MPSA_CLSTAT3, &clstat3, sizeof(clstat))
== -1) {
fprintf(stderr,"can't read clstat3\n");
exit(1);
}
}
if (scode) {
if (sysmp(MP_SAGET, MPSA_RSSTAT, &rsstat, sizeof(rsstat))
== -1) {
fprintf(stderr,"can't read rsstat\n");
exit(1);
}
if (sysmp(MP_SAGET, MPSA_SVSTAT, &svstat, sizeof(svstat))
== -1) {
fprintf(stderr,"can't read svstat\n");
exit(1);
}
if (sysmp(MP_SAGET, MPSA_SVSTAT3, &svstat3, sizeof(svstat))
== -1) {
fprintf(stderr,"can't read svstat3\n");
exit(1);
}
}
}
static void
putstats()
{
if (sysmp(MP_CLEARNFSSTAT) == -1) {
fprintf(stderr,"can't clear nfsstat\n");
exit(1);
}
}
static void
cr_print(zflag)
int zflag;
{
fprintf(stdout, "\nClient RPC:\n");
fprintf(stdout,
"calls badcalls retrans badxid timeout wait newcred badversions\n");
fprintf(stdout,
"%-11d%-11d%-11d%-11d%-11d%-11d%-11d%-11d\n",
rcstat.rccalls,
rcstat.rcbadcalls,
rcstat.rcretrans,
rcstat.rcbadxids,
rcstat.rctimeouts,
rcstat.rcwaits,
rcstat.rcnewcreds,
rcstat.rcbadverfs);
if (zflag) {
bzero(&rcstat, sizeof rcstat);
}
}
static void
sr_print(zflag)
int zflag;
{
fprintf(stdout, "\nServer RPC:\n");
fprintf(stdout,
"calls badcalls nullrecv badlen xdrcall duphits dupage\n");
fprintf(stdout,
"%-11d%-11d%-11d%-11d%-11d%-11d%-8.2f\n",
rsstat.rscalls,
rsstat.rsbadcalls,
rsstat.rsnullrecv,
rsstat.rsbadlen,
rsstat.rsxdrcall,
rsstat.rsduphits,
rsstat.rsdupage/(HZ*1.0));
if (zflag) {
bzero(&rsstat, sizeof rsstat);
}
}
#define RFS_NPROC 18
char *nfsstr[RFS_NPROC] = {
"null",
"getattr",
"setattr",
"root",
"lookup",
"readlink",
"read",
"wrcache",
"write",
"create",
"remove",
"rename",
"link",
"symlink",
"mkdir",
"rmdir",
"readdir",
"fsstat" };
#define RFS3_NPROC 22
char *nfs3str[RFS3_NPROC] = {
"null",
"getattr",
"setattr",
"lookup",
"access",
"readlink",
"read",
"write",
"create",
"mkdir",
"symlink",
"mknod",
"remove",
"rmdir",
"rename",
"link",
"readdir",
"readdir+",
"fsstat",
"fsinfo",
"pathconf",
"commit"
};
static void
cn_print(zflag)
int zflag;
{
int i;
fprintf(stdout, "\nClient NFS V2:\n");
fprintf(stdout,
"%-13s%-13s%-13s%-13s\n",
"calls", "badcalls", "nclget", "nclsleep");
fprintf(stdout,
"%-13d%-13d%-13d%-13d\n",
clstat.ncalls,
clstat.nbadcalls,
clstat.nclgets,
clstat.nclsleeps);
req_print((int *)clstat.reqs, clstat.ncalls, &nfsstr[0], RFS_NPROC);
if (zflag) {
bzero(&clstat, sizeof clstat);
}
}
static void
cn_print3(zflag)
int zflag;
{
int i;
fprintf(stdout, "\nClient NFS V3:\n");
fprintf(stdout,
"%-13s%-13s%-13s%-13s\n",
"calls", "badcalls", "nclget", "nclsleep");
fprintf(stdout,
"%-13d%-13d%-13d%-13d\n",
clstat3.ncalls,
clstat3.nbadcalls,
clstat3.nclgets,
clstat3.nclsleeps);
req_print((int *)clstat3.reqs, clstat3.ncalls, &nfs3str[0], RFS3_NPROC);
if (zflag) {
bzero(&clstat3, sizeof clstat);
}
}
static void
sn_print3(zflag)
int zflag;
{
fprintf(stdout, "\nServer NFS V3:\n");
fprintf(stdout, "%-13s%-13s\n", "calls", "badcalls");
fprintf(stdout, "%-13d%-13d\n", svstat3.ncalls, svstat3.nbadcalls);
req_print((int *)svstat3.reqs, svstat3.ncalls, &nfs3str[0], RFS3_NPROC);
if (zflag) {
bzero(&svstat3, sizeof svstat);
}
}
static void
sn_print(zflag)
int zflag;
{
fprintf(stdout, "\nServer NFS V2:\n");
fprintf(stdout, "%-13s%-13s\n", "calls", "badcalls");
fprintf(stdout, "%-13d%-13d\n", svstat.ncalls, svstat.nbadcalls);
req_print((int *)svstat.reqs, svstat.ncalls, &nfsstr[0], RFS_NPROC);
if (zflag) {
bzero(&svstat, sizeof svstat);
}
}
static void
req_print(req, tot, str, len)
int *req;
int tot;
char **str;
int len;
{
int i, j, p;
char fixlen[128];
for (i=0; i<=len / 6; i++) {
for (j=i*6; j<min(i*6+6, len); j++) {
fprintf(stdout, "%-13s", str[j]);
}
fprintf(stdout, "\n");
for (j=i*6; j<min(i*6+6, len); j++) {
if (tot) {
p = ((double)req[j]*100)/tot;
} else {
p = 0;
}
sprintf(fixlen, "%d %2d%% ", req[j], p);
fprintf(stdout, "%-13s", fixlen);
}
fprintf(stdout, "\n");
}
}
static void
usage()
{
fprintf(stderr, "nfsstat [-Ccnrsz] [interval]\n");
exit(1);
}
min(a,b)
int a,b;
{
if (a<b) {
return(a);
}
return(b);
}
/*----------------------------------------------------------------------*/
/* Curses mode specific to SGI */
extern int printw(const char *, ...);
const int BOS = 23; /* Index of last line on screen */
static void
quit(int stat)
{
if (Cflag) {
move(BOS, 0);
clrtoeol();
refresh();
endwin();
}
exit(stat);
}
static void
fail(char *fmt, ...)
{
va_list args;
if (Cflag) {
move(BOS, 0);
clrtoeol();
refresh();
endwin();
}
va_start(args, fmt);
fprintf(stderr, "smtstat: ");
vfprintf(stderr, fmt, args);
va_end(args);
exit(1);
}
static int Cfirst = 1;
static enum cmode {NORM, ZERO, DELTA} cmode;
static char hostname[MAXHOSTNAMELEN+1];
const char ctrl_l = 'L' & 037;
#define LABEL_LEN 14
#define NUM_LEN 12
#define P(lab,fmt,val) \
{ \
if (Cfirst) { move(y,x); printw("%-.*s", LABEL_LEN, lab); } \
move(y,x); \
printw(fmt,(val)); \
y++; \
}
#define PL(lab) \
{ \
if (Cfirst) { move(y,x); printw("%-s",lab); } \
y++; \
}
static struct rsstat zrsstat, drsstat;
static struct svstat zsvstat, dsvstat;
static struct svstat zsvstat3, dsvstat3;
static void
initserver(int initall)
{
if (initall) {
bzero(&drsstat, sizeof(drsstat));
bzero(&dsvstat, sizeof(dsvstat));
bzero(&dsvstat3, sizeof(dsvstat3));
}
bzero(&zrsstat, sizeof(zrsstat));
bzero(&zsvstat, sizeof(zsvstat));
bzero(&zsvstat3, sizeof(zsvstat3));
}
static void
zeroserver()
{
zrsstat = drsstat;
zsvstat = dsvstat;
zsvstat3 = dsvstat3;
}
/* Scale a value if necessary */
static int
DSP(value)
int value;
{
if (cmode == DELTA) {
value += (Interval-1); /* round UP */
value /= Interval;
}
return (value);
}
static void
spr_server3(int cmd, register int y, char *tmb)
{
register int i, j;
register int x = 0;
register int *req, *zreq;
register int tot;
register struct rsstat *rsp;
register struct svstat *svp;
if (cmode == DELTA) {
rsp = &drsstat;
svp = &dsvstat3;
} else {
rsp = &zrsstat;
svp = &zsvstat3;
}
move(0,0);
printw(" %d: Server %.26s %s",cmd,hostname,tmb); y++;
PL("Server RPC:");
PL("calls badcalls nullrecv badlen xdrcall duphits dupage");
move(y,x);
if (gotstats > 1)
printw("%-11d%-11d%-11d%-11d%-11d%-11d%-8.2f",
DSP(rsstat.rscalls - rsp->rscalls),
DSP(rsstat.rsbadcalls - rsp->rsbadcalls),
DSP(rsstat.rsnullrecv - rsp->rsnullrecv),
DSP(rsstat.rsbadlen - rsp->rsbadlen),
DSP(rsstat.rsxdrcall - rsp->rsxdrcall),
DSP(rsstat.rsduphits - rsp->rsduphits),
rsstat.rsdupage/(HZ*1.0));
y++;
y++; /* skip a blank line */
PL("Server NFS V3:");
PL("calls badcalls");
move(y,x);
if (gotstats > 1)
printw("%-13d%-13d",
DSP(svstat3.ncalls - svp->ncalls),
DSP(svstat3.nbadcalls - svp->nbadcalls));
y++;
req = (int *)svstat3.reqs;
zreq = (int *)(svp->reqs);
tot = svstat3.ncalls - svp->ncalls;
for (i = 0; i <= RFS3_NPROC / 6; i++) {
if (Cfirst) {
move(y,x);
for (j = i*6; j < min(i*6+6, RFS3_NPROC); j++) {
printw("%-13s", nfs3str[j]);
}
}
y++;
move(y,x);
for (j = i*6; j < min(i*6+6, RFS3_NPROC); j++) {
char fixlen[128];
int curreq = req[j] - zreq[j];
int p;
if (gotstats <= 1)
break;
if (tot) {
p = ((double)curreq*100)/tot;
} else {
p = 0;
}
sprintf(fixlen, "%d %2d%% ", DSP(curreq), p);
printw("%-13s", fixlen);
}
y++;
}
drsstat = rsstat;
dsvstat3 = svstat3;
}
static void
spr_server(int cmd, register int y, char *tmb)
{
register int i, j;
register int x = 0;
register int *req, *zreq;
register int tot;
register struct rsstat *rsp;
register struct svstat *svp;
if (cmode == DELTA) {
rsp = &drsstat;
svp = &dsvstat;
} else {
rsp = &zrsstat;
svp = &zsvstat;
}
move(0,0);
printw(" %d: Server %.26s %s",cmd,hostname,tmb); y++;
PL("Server RPC:");
PL("calls badcalls nullrecv badlen xdrcall duphits dupage");
move(y,x);
if (gotstats > 1)
printw("%-11d%-11d%-11d%-11d%-11d%-11d%-8.2f",
DSP(rsstat.rscalls - rsp->rscalls),
DSP(rsstat.rsbadcalls - rsp->rsbadcalls),
DSP(rsstat.rsnullrecv - rsp->rsnullrecv),
DSP(rsstat.rsbadlen - rsp->rsbadlen),
DSP(rsstat.rsxdrcall - rsp->rsxdrcall),
DSP(rsstat.rsduphits - rsp->rsduphits),
rsstat.rsdupage/(HZ*1.0));
y++;
y++; /* skip a blank line */
PL("Server NFS V2:");
PL("calls badcalls");
move(y,x);
if (gotstats > 1)
printw("%-13d%-13d",
DSP(svstat.ncalls - svp->ncalls),
DSP(svstat.nbadcalls - svp->nbadcalls));
y++;
req = (int *)svstat.reqs;
zreq = (int *)(svp->reqs);
tot = svstat.ncalls - svp->ncalls;
for (i = 0; i <= RFS_NPROC / 6; i++) {
if (Cfirst) {
move(y,x);
for (j = i*6; j < min(i*6+6, RFS_NPROC); j++) {
printw("%-13s", nfsstr[j]);
}
}
y++;
move(y,x);
for (j = i*6; j < min(i*6+6, RFS_NPROC); j++) {
char fixlen[128];
int curreq = req[j] - zreq[j];
int p;
if (gotstats <= 1)
break;
if (tot) {
p = ((double)curreq*100)/tot;
} else {
p = 0;
}
sprintf(fixlen, "%d %2d%% ", DSP(curreq), p);
printw("%-13s", fixlen);
}
y++;
}
drsstat = rsstat;
dsvstat = svstat;
}
static struct rcstat zrcstat, drcstat;
static struct clstat zclstat, dclstat;
static struct clstat zclstat3, dclstat3;
static void
initclient(int initall)
{
if (initall) {
bzero(&drcstat, sizeof(drcstat));
bzero(&dclstat, sizeof(dclstat));
bzero(&dclstat3, sizeof(dclstat3));
}
bzero(&zrcstat, sizeof(zrcstat));
bzero(&zclstat, sizeof(zclstat));
bzero(&zclstat3, sizeof(zclstat3));
}
static void
zeroclient()
{
zrcstat = drcstat;
zclstat = dclstat;
zclstat3 = dclstat3;
}
static void
_spr_client(int cmd, register int y, char *tmb, char *legend,
struct rcstat *rcp, struct clstat *clp, struct clstat *cls,
char **str, int strcnt)
{
register int i, j;
register int x = 0;
register int *req, *zreq;
register int tot;
move(0,0);
printw(" %d: Client %.26s %s",cmd,hostname,tmb);y++;
PL("Client RPC:");
PL("calls badcalls retrans badxid timeout wait newcred");
move(y,x);
if (gotstats > 1)
printw("%-11d%-11d%-11d%-11d%-11d%-11d%-11d\n",
DSP(rcstat.rccalls - rcp->rccalls),
DSP(rcstat.rcbadcalls - rcp->rcbadcalls),
DSP(rcstat.rcretrans - rcp->rcretrans),
DSP(rcstat.rcbadxids - rcp->rcbadxids),
DSP(rcstat.rctimeouts - rcp->rctimeouts),
DSP(rcstat.rcwaits - rcp->rcwaits),
DSP(rcstat.rcnewcreds - rcp->rcnewcreds));
y++;
y++; /* skip a blank line */
PL(legend);
PL("calls badcalls nclget nclsleep");
move(y,x);
if (gotstats > 1)
printw("%-13d%-13d%-13d%-13d",
DSP(cls->ncalls - clp->ncalls),
DSP(cls->nbadcalls - clp->nbadcalls),
DSP(cls->nclgets - clp->nclgets),
DSP(cls->nclsleeps - clp->nclsleeps));
y++;
req = (int *)cls->reqs;
zreq = (int *)(clp->reqs);
tot = cls->ncalls - clp->ncalls;
for (i = 0; i <= strcnt / 6; i++) {
if (Cfirst) {
move(y,x);
for (j = i*6; j < min(i*6+6, strcnt); j++) {
printw("%-13s", str[j]);
}
}
y++;
move(y,x);
for (j = i*6; j < min(i*6+6, strcnt); j++) {
char fixlen[128];
int curreq = req[j] - zreq[j];
int p;
if (gotstats <= 1)
break;
if (tot) {
p = ((double)curreq*100)/tot;
} else {
p = 0;
}
sprintf(fixlen, "%d %2d%% ", DSP(curreq), p);
printw("%-13s", fixlen);
}
y++;
}
}
static void
spr_client(int cmd, register int y, char *tmb)
{
register struct rcstat *rcp;
register struct clstat *clp;
if (cmode == DELTA) {
rcp = &drcstat;
clp = &dclstat;
} else {
rcp = &zrcstat;
clp = &zclstat;
}
_spr_client(cmd, y, tmb, "Client NFS:", rcp, clp,
&clstat, &nfsstr[0], RFS_NPROC);
drcstat = rcstat;
dclstat = clstat;
}
static void
spr_client3(int cmd, register int y, char *tmb)
{
register struct rcstat *rcp;
register struct clstat *clp;
if (cmode == DELTA) {
rcp = &drcstat;
clp = &dclstat3;
} else {
rcp = &zrcstat;
clp = &zclstat3;
}
_spr_client(cmd, y, tmb, "Client NFS3:", rcp, clp,
&clstat3, &nfs3str[0], RFS3_NPROC);
drcstat = rcstat;
dclstat3 = clstat3;
}
#define NUMFUNCS 4
static void (*sprfuncs[NUMFUNCS])(int, int, char *) = {
spr_client,
spr_server,
spr_client3,
spr_server3,
};
static void (*sprinitfuncs[NUMFUNCS])(int) = {
initclient,
initserver,
initclient,
initserver,
};
static void (*sprzerofuncs[NUMFUNCS])() = {
zeroclient,
zeroserver,
zeroclient,
zeroserver,
};
const char min_cmd_num = '1';
const char max_cmd_num = '1' + NUMFUNCS - 1;
/*
* Print a description of the station.
*/
static void
disp(int scmd)
{
time_t now;
char tmb[26];
struct timeval wait;
fd_set rmask;
struct termio tb;
int c, n;
int intrchar; /* user's interrupt character */
int suspchar; /* job control character */
static char dtitle[] = "D: Delta/second";
static char rtitle[] = "R: Normal mode";
static char ztitle0[] = "Z: Delta -- %b %d %T";
static char ztitle[] = "Z: Delta -- MMM DD HH:MM:SS";
cmode = DELTA;
(void) gethostname(hostname, sizeof(hostname));
for (n = 0; n < NUMFUNCS; n++)
sprinitfuncs[n](1);
initscr();
raw();
noecho();
keypad(stdscr, TRUE);
leaveok(stdscr, FALSE);
move(0, 0);
(void) ioctl(0, TCGETA, &tb);
intrchar = tb.c_cc[VINTR];
suspchar = tb.c_cc[VSUSP];
FD_ZERO(&rmask);
while (1) {
if (Cfirst)
clear();
getstats();
now = time(0);
cftime(tmb,"%b %e %T", &now);
sprfuncs[scmd](scmd+1, 1, tmb);
if (Cfirst) {
standout();
move(BOS, 0);
printw(
"1: Client[V2] 2: Server[V2] 3: Client[V3] 4: Server[V3] DZR:mode");
standend();
switch (cmode) {
case DELTA:
move(0, 80-sizeof(dtitle));
printw(dtitle);
break;
case ZERO:
move(0, 80-sizeof(ztitle));
printw(ztitle);
break;
case NORM:
move(0, 80-sizeof(rtitle));
printw(rtitle);
break;
}
}
move(0, 0);
refresh();
Cfirst = 0;
FD_SET(0, &rmask);
wait.tv_sec = Interval;
wait.tv_usec = 0;
n = select(1, &rmask, NULL, NULL, &wait);
if (n < 0) {
fail("select: %s", strerror(errno));
break;
} else if (n == 1) {
c = getch();
if (c == intrchar || c == 'q' || c == 'Q') {
quit(0);
break;
} else if (c == suspchar) {
reset_shell_mode();
kill(getpid(), SIGTSTP);
reset_prog_mode();
} else if (c == 'z' || c == 'Z') {
now = time(0);
cftime(ztitle,ztitle0,&now);
for (n = 0; n < NUMFUNCS; n++)
sprzerofuncs[n]();
cmode = ZERO;
} else if (c == 'r' || c == 'R') {
for (n = 0; n < NUMFUNCS; n++)
sprinitfuncs[n](0);
cmode = NORM;
} else if (c == 'd' || c == 'D') {
cmode = DELTA;
} else if ((c >= min_cmd_num) && (c <= max_cmd_num)) {
scmd = c - '1';
}
Cfirst = 1;
}
}
}