]> git.decadent.org.uk Git - nfs-utils.git/blobdiff - utils/nfsstat/nfsstat.c
See Changelog
[nfs-utils.git] / utils / nfsstat / nfsstat.c
index 55b5cd08d90c06dec6e7dfbfa260b1258ddffd39..55c40967f4b9b606a48c05d21e435322e52d8355 100644 (file)
@@ -20,8 +20,8 @@
 
 static unsigned int    svcv2info[19];  /* NFSv2 call counts ([0] == 18) */
 static unsigned int    cltv2info[19];  /* NFSv2 call counts ([0] == 18) */
-static unsigned int    svcv3info[22];  /* NFSv3 call counts ([0] == 22) */
-static unsigned int    cltv3info[22];  /* NFSv3 call counts ([0] == 22) */
+static unsigned int    svcv3info[23];  /* NFSv3 call counts ([0] == 22) */
+static unsigned int    cltv3info[23];  /* NFSv3 call counts ([0] == 22) */
 static unsigned int    svcnetinfo[4];  /* 0  # of received packets
                                         * 1  UDP packets
                                         * 2  TCP packets
@@ -47,15 +47,24 @@ static unsigned int cltrpcinfo[3];  /* 0  total # of RPC calls
 static unsigned int    svcrcinfo[8];   /* 0  repcache hits
                                         * 1  repcache hits
                                         * 2  uncached reqs
-                                        *
-                                        * including fh info:
-                                        * 3  cached fh's
-                                        * 4  valid fh's
-                                        * 5  fixup required
-                                        * 6  lookup (?)
+                                        * (for pre-2.4 kernels:)
+                                        * 3  FH lookups
+                                        * 4  'anon' FHs
+                                        * 5  noncached non-directories
+                                        * 6  noncached directories
                                         * 7  stale
                                         */
 
+static unsigned int    svcfhinfo[6];   /* (for kernels >= 2.4.0)
+                                        * 0  stale
+                                        * 1  FH lookups
+                                        * 2  'anon' FHs
+                                        * 3  noncached directories
+                                        * 4  noncached non-directories
+                                        * leave hole to relocate stale for order
+                                        *    compatability.
+                                        */
+
 static const char *    nfsv2name[18] = {
        "null", "getattr", "setattr", "root",   "lookup",  "readlink",
        "read", "wrcache", "write",   "create", "remove",  "rename",
@@ -73,15 +82,13 @@ typedef struct statinfo {
        char            *tag;
        int             nrvals;
        unsigned int *  valptr;
-
-       /* Filled in by parse_statfile */
-       int *           foundp;
 } statinfo;
 
 static statinfo                svcinfo[] = {
        { "net",        4,      svcnetinfo      },
        { "rpc",        5,      svcrpcinfo      },
-       { "rc",         8,      svcrcinfo       },      /* including fh_* */
+       { "rc",         8,      svcrcinfo       },
+       { "fh",         5,      svcfhinfo       },
        { "proc2",      19,     svcv2info       },
        { "proc3",      23,     svcv3info       },
        { NULL,         0,      0               }
@@ -101,6 +108,9 @@ static void         print_callstats(const char *, const char **,
                                        unsigned int *, unsigned int);
 static int             parse_statfile(const char *, struct statinfo *);
 
+static statinfo                *get_stat_info(const char *, struct statinfo *);
+
+
 #define PRNT_CALLS     0x0001
 #define PRNT_RPC       0x0002
 #define PRNT_NET       0x0004
@@ -114,6 +124,8 @@ main(int argc, char **argv)
        int             opt_all = 0,
                        opt_srv = 0,
                        opt_clt = 0,
+                       srv_info = 0,
+                       clt_info = 0,
                        opt_prt = 0;
        int             c;
 
@@ -174,9 +186,25 @@ main(int argc, char **argv)
                        "server.\n");
        }
 
-       if ((opt_srv && !parse_statfile(NFSSVCSTAT, svcinfo))
-        || (opt_clt && !parse_statfile(NFSCLTSTAT, cltinfo)))
-               return 2;
+       if (opt_srv) {
+               srv_info = parse_statfile(NFSSVCSTAT, svcinfo);
+               if (srv_info == 0 && opt_clt == 0) {
+                       fprintf(stderr, "Warning: No Server Stats (%s: %m).\n", NFSSVCSTAT);
+                       return 2;
+               }
+               if (srv_info == 0)
+                       opt_srv = 0;
+       }
+
+       if (opt_clt) {
+               clt_info = parse_statfile(NFSCLTSTAT, cltinfo);
+               if (opt_srv == 0 && clt_info == 0) {
+                       fprintf(stderr, "Warning: No Client Stats (%s: %m).\n", NFSCLTSTAT);
+                       return 2;
+               }
+               if (clt_info == 0)
+                       opt_clt = 0;
+       }
 
        if (opt_srv) {
                if (opt_prt & PRNT_NET) {
@@ -200,11 +228,30 @@ main(int argc, char **argv)
                        svcrcinfo, 3
                        );
                }
+
+               /*
+                * 2.2 puts all fh-related info after the 'rc' header
+                * 2.4 puts all fh-related info after the 'fh' header, but relocates
+                *     'stale' to the start and swaps dir and nondir :-(  
+                *     We preseve the 2.2 order
+                */
                if (opt_prt & PRNT_FH) {
-                       print_numbers(
-                       "Server file handle cache:\n"
-                       "cached     valid      fixup      lookup     stale\n",
-                       svcrcinfo + 3, 5);
+                       if (get_stat_info("fh", svcinfo)) {     /* >= 2.4 */
+                               int t = svcfhinfo[3];
+                               svcfhinfo[3]=svcfhinfo[4];
+                               svcfhinfo[4]=t;
+                               
+                               svcfhinfo[5]=svcfhinfo[0]; /* relocate 'stale' */
+                               
+                               print_numbers(
+                                       "Server file handle cache:\n"
+                                       "lookup     anon       ncachedir ncachedir  stale\n",
+                                       svcfhinfo + 1, 5);
+                       } else                                  /* < 2.4 */
+                               print_numbers(
+                                       "Server file handle cache:\n"
+                                       "lookup     anon       ncachedir ncachedir  stale\n",
+                                       svcrcinfo + 3, 5);
                }
                if (opt_prt & PRNT_CALLS) {
                        print_callstats(
@@ -250,6 +297,19 @@ main(int argc, char **argv)
        return 0;
 }
 
+static statinfo *
+get_stat_info(const char *sp, struct statinfo *statp)
+{
+       struct statinfo *ip;
+
+       for (ip = statp; ip->tag; ip++) {
+               if (!strcmp(sp, ip->tag))
+                       return ip;
+       }
+
+       return NULL;
+}
+
 static void
 print_numbers(const char *hdr, unsigned int *info, unsigned int nr)
 {
@@ -265,7 +325,8 @@ static void
 print_callstats(const char *hdr, const char **names,
                                 unsigned int *info, unsigned int nr)
 {
-       unsigned int    total;
+       unsigned long long      total;
+       unsigned long long      pct;
        int             i, j;
 
        fputs(hdr, stdout);
@@ -277,14 +338,16 @@ print_callstats(const char *hdr, const char **names,
                for (j = 0; j < 6 && i + j < nr; j++)
                        printf("%-11s", names[i+j]);
                printf("\n");
-               for (j = 0; j < 6 && i + j < nr; j++)
-                       printf("%-6d %2d%% ",
-                               info[i+j], 100 * info[i+j] / total);
+               for (j = 0; j < 6 && i + j < nr; j++) {
+                       pct = ((unsigned long long) info[i+j]*100)/total;
+                       printf("%-6d %2llu%% ", info[i+j], pct);
+               }
                printf("\n");
        }
        printf("\n");
 }
 
+
 static int
 parse_statfile(const char *name, struct statinfo *statp)
 {
@@ -295,8 +358,8 @@ parse_statfile(const char *name, struct statinfo *statp)
         * be a fatal error -- it usually means the module isn't loaded.
         */
        if ((fp = fopen(name, "r")) == NULL) {
-               fprintf(stderr, "Warning: %s: %m\n", name);
-               return 1;
+               // fprintf(stderr, "Warning: %s: %m\n", name);
+               return 0;
        }
 
        while (fgets(buffer, sizeof(buffer), fp) != NULL) {
@@ -308,12 +371,11 @@ parse_statfile(const char *name, struct statinfo *statp)
                        *next++ = '\0';
                if (!(sp = strtok(line, " \t")))
                        continue;
-               for (ip = statp; ip->tag; ip++) {
-                       if (!strcmp(sp, ip->tag))
-                               break;
-               }
-               if (!ip->tag)
+
+               ip = get_stat_info(sp, statp);
+               if (!ip)
                        continue;
+
                cnt = ip->nrvals;
 
                for (i = 0; i < cnt; i++) {