X-Git-Url: https://git.decadent.org.uk/gitweb/?p=nfs-utils.git;a=blobdiff_plain;f=utils%2Fnfsstat%2Fnfsstat.c;h=d5bdad7365cadd908362d4fc612670f4e7e56a6a;hp=aa6c961cefdae65ae7012c43a41865aa1ba04ea9;hb=ca8eb17798fb9b4936a38cc58fe379e9e8d379f9;hpb=b587496ba83ac7da31a33a0e1fd533773f3240ce diff --git a/utils/nfsstat/nfsstat.c b/utils/nfsstat/nfsstat.c index aa6c961..d5bdad7 100644 --- a/utils/nfsstat/nfsstat.c +++ b/utils/nfsstat/nfsstat.c @@ -167,10 +167,16 @@ DECLARE_SRV(srvinfo, _old); DECLARE_CLT(cltinfo); DECLARE_CLT(cltinfo, _old); +static void print_all_stats(int, int, int); +static void print_server_stats(int, int); +static void print_client_stats(int, int); +static void print_stats_list(int); static void print_numbers(const char *, unsigned int *, unsigned int); static void print_callstats(const char *, const char **, unsigned int *, unsigned int); +static void print_callstats_list(const char *, const char **, + unsigned int *, unsigned int); static int parse_raw_statfile(const char *, struct statinfo *); static int parse_pretty_statfile(const char *, struct statinfo *); @@ -181,8 +187,10 @@ static int mounts(const char *); static void get_stats(const char *, struct statinfo *, int *, int, int); static int has_stats(const unsigned int *); +static int has_rpcstats(const unsigned int *, int); static void diff_stats(struct statinfo *, struct statinfo *, int); static void unpause(int); +static void update_old_counters(struct statinfo *, struct statinfo *); static time_t starttime; @@ -207,26 +215,30 @@ void usage(char *name) { printf("Usage: %s [OPTION]...\n\ \n\ - -m, --mounts\t\tShow statistics on mounted NFS filesystems\n\ - -c, --client\t\tShow NFS client statistics\n\ - -s, --server\t\tShow NFS server statistics\n\ - -2\t\t\tShow NFS version 2 statistics\n\ - -3\t\t\tShow NFS version 3 statistics\n\ - -4\t\t\tShow NFS version 4 statistics\n\ - -o [facility]\t\tShow statistics on particular facilities.\n\ - nfs\tNFS protocol information\n\ - rpc\tGeneral RPC information\n\ - net\tNetwork layer statistics\n\ - fh\t\tUsage information on the server's file handle cache\n\ - rc\t\tUsage information on the server's request reply cache\n\ - all\tSelect all of the above\n\ - -v, --verbose, --all\tSame as '-o all'\n\ - -r, --rpc\t\tShow RPC statistics\n\ - -n, --nfs\t\tShow NFS statistics\n\ - -Z, --sleep\t\tSaves stats, pauses, diffs current and saved\n\ - -S, --since file\tShows difference between current stats and those in 'file'\n\ - --version\t\tShow program version\n\ - --help\t\tWhat you just did\n\ + -m, --mounts Show statistics on mounted NFS filesystems\n\ + -c, --client Show NFS client statistics\n\ + -s, --server Show NFS server statistics\n\ + -2 Show NFS version 2 statistics\n\ + -3 Show NFS version 3 statistics\n\ + -4 Show NFS version 4 statistics\n\ + -o [facility] Show statistics on particular facilities.\n\ + nfs NFS protocol information\n\ + rpc General RPC information\n\ + net Network layer statistics\n\ + fh Usage information on the server's file handle cache\n\ + rc Usage information on the server's request reply cache\n\ + all Select all of the above\n\ + -v, --verbose, --all Same as '-o all'\n\ + -r, --rpc Show RPC statistics\n\ + -n, --nfs Show NFS statistics\n\ + -Z[#], --sleep[=#] Collects stats until interrupted.\n\ + Cumulative stats are then printed\n\ + If # is provided, stats will be output every\n\ + # seconds.\n\ + -S, --since file Shows difference between current stats and those in 'file'\n\ + -l, --list Prints stats in list format\n\ + --version Show program version\n\ + --help What you just did\n\ \n", name); exit(0); } @@ -245,10 +257,12 @@ static struct option longopts[] = { "zero", 0, 0, 'z' }, { "help", 0, 0, '\1' }, { "version", 0, 0, '\2' }, - { "sleep", 0, 0, 'Z' }, + { "sleep", 2, 0, 'Z' }, { "since", 1, 0, 'S' }, + { "list", 0, 0, 'l' }, { NULL, 0, 0, 0 } }; +int opt_sleep; int main(int argc, char **argv) @@ -257,7 +271,8 @@ main(int argc, char **argv) opt_srv = 0, opt_clt = 0, opt_prt = 0, - opt_sleep = 0, + sleep_time = 0, + opt_list =0, opt_since = 0; int c; char *progname, @@ -279,7 +294,7 @@ main(int argc, char **argv) else progname = argv[0]; - while ((c = getopt_long(argc, argv, "234acmno:ZS:vrsz\1\2", longopts, NULL)) != EOF) { + while ((c = getopt_long(argc, argv, "234acmno:Z::S:vrslz\1\2", longopts, NULL)) != EOF) { switch (c) { case 'a': fprintf(stderr, "nfsstat: nfs acls are not yet supported.\n"); @@ -311,6 +326,9 @@ main(int argc, char **argv) break; case 'Z': opt_sleep = 1; + if (optarg) { + sleep_time = atoi(optarg); + } break; case 'S': opt_since = 1; @@ -334,6 +352,9 @@ main(int argc, char **argv) case 's': opt_srv = 1; break; + case 'l': + opt_list = 1; + break; case 'z': fprintf(stderr, "nfsstat: zeroing of nfs statistics " "not yet supported\n"); @@ -384,7 +405,7 @@ main(int argc, char **argv) if (opt_clt) get_stats(clientfile, clientinfo, &opt_clt, opt_srv, 0); - if (opt_sleep) { + if (opt_sleep && !sleep_time) { starttime = time(NULL); printf("Collecting statistics; press CTRL-C to view results from interval (i.e., from pause to CTRL-C).\n"); if (sigaction(SIGINT, &act, NULL) != 0) { @@ -404,7 +425,47 @@ main(int argc, char **argv) diff_stats(clientinfo_tmp, clientinfo, 0); } } + if(sleep_time) { + while(1) { + if (opt_srv) { + get_stats(NFSSRVSTAT, serverinfo_tmp , &opt_srv, opt_clt, 1); + diff_stats(serverinfo_tmp, serverinfo, 1); + } + if (opt_clt) { + get_stats(NFSCLTSTAT, clientinfo_tmp, &opt_clt, opt_srv, 0); + diff_stats(clientinfo_tmp, clientinfo, 0); + } + if (opt_list) { + print_stats_list(opt_prt); + } else { + print_all_stats(opt_srv, opt_clt, opt_prt); + } + fflush(stdout); + + update_old_counters(clientinfo_tmp, clientinfo); + sleep(sleep_time); + } + } else { + if (opt_list) { + print_stats_list(opt_prt); + } else { + print_all_stats(opt_srv, opt_clt, opt_prt); + } + } + return 0; +} + +static void +print_all_stats (int opt_srv, int opt_clt, int opt_prt) +{ + print_server_stats(opt_srv, opt_prt); + print_client_stats(opt_clt, opt_prt); +} + +static void +print_server_stats(int opt_srv, int opt_prt) +{ if (opt_srv) { if (opt_prt & PRNT_NET) { print_numbers( @@ -415,12 +476,14 @@ main(int argc, char **argv) printf("\n"); } if (opt_prt & PRNT_RPC) { - print_numbers( - LABEL_srvrpc - "calls badcalls badauth badclnt xdrcall\n", - srvrpcinfo, 5 - ); - printf("\n"); + if (!opt_sleep && !has_rpcstats(srvrpcinfo, 5)) { + print_numbers( + LABEL_srvrpc + "calls badcalls badauth badclnt xdrcall\n", + srvrpcinfo, 5 + ); + printf("\n"); + } } if (opt_prt & PRNT_RC) { print_numbers( @@ -479,7 +542,10 @@ main(int argc, char **argv) } } } - +} +static void +print_client_stats(int opt_clt, int opt_prt) +{ if (opt_clt) { if (opt_prt & PRNT_NET) { print_numbers( @@ -490,12 +556,14 @@ main(int argc, char **argv) printf("\n"); } if (opt_prt & PRNT_RPC) { - print_numbers( - LABEL_cltrpc - "calls retrans authrefrsh\n", - cltrpcinfo, 3 - ); - printf("\n"); + if (!opt_sleep && !has_rpcstats(cltrpcinfo, 3)) { + print_numbers( + LABEL_cltrpc + "calls retrans authrefrsh\n", + cltrpcinfo, 3 + ); + printf("\n"); + } } if (opt_prt & PRNT_CALLS) { if ((opt_prt & PRNT_V2) || ((opt_prt & PRNT_AUTO) && has_stats(cltproc2info))) @@ -515,8 +583,47 @@ main(int argc, char **argv) ); } } +} - return 0; +static void +print_stats_list(int opt_prt) +{ + if (opt_prt & PRNT_CALLS) { + if ((opt_prt & PRNT_V2) || ((opt_prt & PRNT_AUTO) && has_stats(cltproc2info))) { + print_callstats_list( + "nfs v2 server", + nfsv2name, srvproc2info + 1, sizeof(nfsv2name)/sizeof(char *)); + printf("\n"); + print_callstats_list( + "nfs v2 client", + nfsv2name, cltproc2info + 1, sizeof(nfsv2name)/sizeof(char *)); + printf("\n"); + } + if ((opt_prt & PRNT_V3) || ((opt_prt & PRNT_AUTO) && has_stats(cltproc3info))) { + print_callstats_list( + "nfs v3 server", + nfsv3name, srvproc3info + 1, sizeof(nfsv3name)/sizeof(char *)); + printf("\n"); + print_callstats_list( + "nfs v3 client", + nfsv3name, cltproc3info + 1, sizeof(nfsv3name)/sizeof(char *)); + printf("\n"); + } + if ((opt_prt & PRNT_V4) || ((opt_prt & PRNT_AUTO) && has_stats(cltproc4info))) { + print_callstats_list( + "nfs v4 server", + nfssrvproc4name, srvproc4info + 1, sizeof(nfssrvproc4name)/sizeof(char *)); + printf("\n"); + print_callstats_list( + "nfs v4 ops", + nfssrvproc4opname, srvproc4opsinfo + 1, sizeof(nfssrvproc4opname)/sizeof(char *)); + printf("\n"); + print_callstats_list( + "nfs v4 client", + nfscltproc4name, cltproc4info + 1, sizeof(nfscltproc4name)/sizeof(char *)); + printf("\n"); + } + } } static statinfo * @@ -539,7 +646,7 @@ print_numbers(const char *hdr, unsigned int *info, unsigned int nr) fputs(hdr, stdout); for (i = 0; i < nr; i++) - printf("%s%-8d", i? " " : "", info[i]); + printf("%s%-8u", i? " " : "", info[i]); printf("\n"); } @@ -562,13 +669,32 @@ print_callstats(const char *hdr, const char **names, printf("\n"); for (j = 0; j < 6 && i + j < nr; j++) { pct = ((unsigned long long) info[i+j]*100)/total; - printf("%-8d%3llu%% ", info[i+j], pct); + printf("%-8u%3llu%% ", info[i+j], pct); } printf("\n"); } printf("\n"); } +static void +print_callstats_list(const char *hdr, const char **names, + unsigned int *callinfo, unsigned int nr) +{ + unsigned long long calltotal; + int i; + + for (i = 0, calltotal = 0; i < nr; i++) { + calltotal += callinfo[i]; + } + printf("%13s %13s %8llu \n", hdr, "total:", calltotal); + printf("------------- ------------- --------\n"); + for (i = 0; i < nr; i++) { + printf("%13s %12s: %8u \n", hdr, names[i], callinfo[i]); + } + +} + + /* returns 0 on success, 1 otherwise */ static int parse_raw_statfile(const char *name, struct statinfo *statp) @@ -604,7 +730,7 @@ parse_raw_statfile(const char *name, struct statinfo *statp) for (i = 0; i < cnt; i++) { if (!(sp = strtok(NULL, " \t"))) break; - ip->valptr[i] = atoi(sp); + ip->valptr[i] = (unsigned int) strtoul(sp, NULL, 0); total += ip->valptr[i]; } ip->valptr[cnt - 1] = total; @@ -618,7 +744,8 @@ parse_raw_statfile(const char *name, struct statinfo *statp) static int parse_pretty_statfile(const char *filename, struct statinfo *info) { - int numvals, curindex, numconsumed, n, sum, err = 1; + int numvals, curindex, numconsumed, n, err = 1; + unsigned int sum; char buf[4096], *bufp, *fmt, is_proc; FILE *fp = NULL; struct statinfo *ip; @@ -716,7 +843,7 @@ mounts(const char *name) if (!(type = strtok(NULL, " \t"))) continue; - if (strcmp(type, "nfs")) { + if (strcmp(type, "nfs") && strcmp(type,"nfs4")) { continue; } @@ -791,6 +918,15 @@ has_stats(const unsigned int *info) { return (info[0] && info[info[0] + 1] > info[0]); } +static int +has_rpcstats(const unsigned int *info, int size) +{ + int i, cnt; + + for (i=0, cnt=0; i < size; i++) + cnt += info[i]; + return cnt; +} /* * take the difference of each individual stat value in 'new' and 'old' @@ -845,3 +981,13 @@ unpause(int sig) seconds = (int)time_diff % 60; printf("Signal received; displaying (only) statistics gathered over the last %d minutes, %d seconds:\n\n", minutes, seconds); } + +static void +update_old_counters(struct statinfo *new, struct statinfo *old) +{ + int z, i; + for (z = 0; old[z].tag; z++) + for (i = 0; i <= old[z].nrvals; i++) + old[z].valptr[i] += new[z].valptr[i]; + +}