]> git.decadent.org.uk Git - nfs-utils.git/blobdiff - utils/nfsstat/nfsstat.c
Added list mounted nfs filesystems (-m) option
[nfs-utils.git] / utils / nfsstat / nfsstat.c
index afd323ede6f1f269fba68e6d9ecf998cf8c78229..3b695f253612d3ba562a5eb98b5345f53739fb33 100644 (file)
@@ -9,6 +9,8 @@
 #define NFSSVCSTAT     "/proc/net/rpc/nfsd"
 #define NFSCLTSTAT     "/proc/net/rpc/nfs"
 
+#define MOUNTSFILE     "/proc/mounts"
+
 #include <stdlib.h>
 #include <stdio.h>
 #include <unistd.h>
@@ -59,8 +61,8 @@ static unsigned int   svcfhinfo[6];   /* (for kernels >= 2.4.0)
                                         * 0  stale
                                         * 1  FH lookups
                                         * 2  'anon' FHs
-                                        * 3  noncached non-directories
-                                        * 4  noncached directories
+                                        * 3  noncached directories
+                                        * 4  noncached non-directories
                                         * leave hole to relocate stale for order
                                         *    compatability.
                                         */
@@ -110,6 +112,7 @@ static int          parse_statfile(const char *, struct statinfo *);
 
 static statinfo                *get_stat_info(const char *, struct statinfo *);
 
+static int             mounts(const char *);
 
 #define PRNT_CALLS     0x0001
 #define PRNT_RPC       0x0002
@@ -124,10 +127,12 @@ 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;
 
-       while ((c = getopt(argc, argv, "acno:rsz")) != -1) {
+       while ((c = getopt(argc, argv, "acmno:rsz")) != -1) {
                switch (c) {
                case 'a':
                        opt_all = 1;
@@ -165,6 +170,8 @@ main(int argc, char **argv)
                        fprintf(stderr, "nfsstat: zeroing of nfs statistics "
                                        "not yet supported\n");
                        return 2;
+               case 'm':
+                       return mounts(MOUNTSFILE);
                }
        }
 
@@ -184,9 +191,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) {
@@ -214,11 +237,17 @@ main(int argc, char **argv)
                /*
                 * 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 :-(  We keep it at the end.
+                *     'stale' to the start and swaps dir and nondir :-(  
+                *     We preseve the 2.2 order
                 */
                if (opt_prt & PRNT_FH) {
                        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",
@@ -301,7 +330,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);
@@ -313,9 +343,10 @@ 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");
@@ -332,8 +363,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) {
@@ -362,3 +393,51 @@ parse_statfile(const char *name, struct statinfo *statp)
        fclose(fp);
        return 1;
 }
+
+static int
+mounts(const char *name)
+{
+       char    buffer[4096], *next;
+       FILE    *fp;
+
+       /* Being unable to read e.g. the nfsd stats file shouldn't
+        * 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;
+       }
+
+       while (fgets(buffer, sizeof(buffer), fp) != NULL) {
+               char          *line = buffer;
+               char          *device, *mount, *type, *flags;
+
+               if ((next = strchr(line, '\n')) != NULL)
+                       *next = '\0';
+
+               if (!(device = strtok(line, " \t")))
+                       continue;
+
+               if (!(mount = strtok(NULL, " \t")))
+                       continue;
+
+               if (!(type = strtok(NULL, " \t")))
+                       continue;
+
+               if (strcmp(type, "nfs")) {
+                   continue;
+               }
+
+               if (!(flags = strtok(NULL, " \t")))
+                       continue;
+
+               printf("%s from %s\n", mount, device);
+               printf(" Flags:\t%s\n", flags);
+               printf("\n");
+
+               continue;
+       }
+
+       fclose(fp);
+       return 0;
+}