|
1 /* |
|
2 * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. |
|
3 * |
|
4 * U.S. Government Rights - Commercial software. Government users are subject |
|
5 * to the Sun Microsystems, Inc. standard license agreement and applicable |
|
6 * provisions of the FAR and its supplements. |
|
7 * |
|
8 * |
|
9 * This distribution may include materials developed by third parties. Sun, |
|
10 * Sun Microsystems, the Sun logo and Solaris are trademarks or registered |
|
11 * trademarks of Sun Microsystems, Inc. in the U.S. and other countries. |
|
12 * |
|
13 */ |
|
14 |
|
15 |
|
16 |
|
17 /* |
|
18 * nfsstat: Network File System statistics for client RPC |
|
19 * |
|
20 */ |
|
21 |
|
22 #include <stdio.h> |
|
23 #include <stdlib.h> |
|
24 #include <unistd.h> |
|
25 #include <stdarg.h> |
|
26 #include <string.h> |
|
27 #include <errno.h> |
|
28 #include <fcntl.h> |
|
29 #include <kvm.h> |
|
30 #include <kstat.h> |
|
31 #include <sys/param.h> |
|
32 #include <sys/types.h> |
|
33 #include <sys/t_lock.h> |
|
34 #include <sys/tiuser.h> |
|
35 #include <sys/statvfs.h> |
|
36 #include <sys/mntent.h> |
|
37 #include <sys/mnttab.h> |
|
38 #include <sys/sysmacros.h> |
|
39 #include <sys/mkdev.h> |
|
40 #include <rpc/types.h> |
|
41 #include <rpc/xdr.h> |
|
42 #include <rpc/auth.h> |
|
43 #include <rpc/clnt.h> |
|
44 #include <nfs/nfs.h> |
|
45 #include <nfs/nfs_clnt.h> |
|
46 |
|
47 static kstat_ctl_t *kc = NULL; /* libkstat cookie */ |
|
48 static kstat_t *rpc_clts_client_kstat; |
|
49 static kstat_t *rpc_cots_client_kstat; |
|
50 |
|
51 static void getstats(void); |
|
52 static void setup(); |
|
53 static void clear_setup_data(); |
|
54 static void fail(int, char *, ...); |
|
55 |
|
56 static kid_t safe_kstat_read(kstat_ctl_t *, kstat_t *, void *); |
|
57 |
|
58 #define MAX_COLUMNS 80 |
|
59 |
|
60 static int field_width = 0; |
|
61 static int ncolumns; |
|
62 |
|
63 int cflag = 0; /* client stats */ |
|
64 int rflag = 0; /* rpc stats */ |
|
65 int zflag = 0; /* zero stats after printing */ |
|
66 |
|
67 static void stat_width(kstat_t *); |
|
68 |
|
69 static void |
|
70 getstats(void) |
|
71 { |
|
72 |
|
73 if (rpc_clts_client_kstat != NULL) { |
|
74 safe_kstat_read(kc, rpc_clts_client_kstat, NULL); |
|
75 stat_width(rpc_clts_client_kstat); |
|
76 } |
|
77 if (rpc_cots_client_kstat != NULL) { |
|
78 safe_kstat_read(kc, rpc_cots_client_kstat, NULL); |
|
79 stat_width(rpc_cots_client_kstat); |
|
80 } |
|
81 } |
|
82 |
|
83 |
|
84 |
|
85 static void |
|
86 clear_setup_data() |
|
87 { |
|
88 /* |
|
89 * Verify and close the kstat control structure |
|
90 */ |
|
91 if (kc) |
|
92 kstat_close(kc); |
|
93 |
|
94 /* |
|
95 * Set all the related variables to null |
|
96 */ |
|
97 kc = (kstat_ctl_t *)NULL; |
|
98 rpc_clts_client_kstat = (kstat_t *)NULL; |
|
99 rpc_cots_client_kstat = (kstat_t *)NULL; |
|
100 } |
|
101 |
|
102 |
|
103 static void |
|
104 setup() |
|
105 { |
|
106 /* Initialize kstat control structures */ |
|
107 if ((kc = kstat_open()) == NULL) |
|
108 fail(1, "kstat_open(): can't open /dev/kstat"); |
|
109 |
|
110 /* Find a kstat by name */ |
|
111 rpc_clts_client_kstat = kstat_lookup(kc, "unix", 0, "rpc_clts_client"); |
|
112 rpc_cots_client_kstat = kstat_lookup(kc, "unix", 0, "rpc_cots_client"); |
|
113 } |
|
114 |
|
115 static void |
|
116 stat_width(kstat_t *req) |
|
117 { |
|
118 int i, nreq, len; |
|
119 char fixlen[128]; |
|
120 kstat_named_t *knp; |
|
121 |
|
122 knp = KSTAT_NAMED_PTR(req); |
|
123 nreq = req->ks_ndata; |
|
124 |
|
125 for (i = 0; i < nreq; i++) { |
|
126 len = strlen(knp[i].name) + 1; |
|
127 if (field_width < len) |
|
128 field_width = len; |
|
129 (void) sprintf(fixlen, "%lu", knp[i].value.ul); |
|
130 len = strlen(fixlen) + 1; |
|
131 if (field_width < len) |
|
132 field_width = len; |
|
133 } |
|
134 } |
|
135 |
|
136 /* |
|
137 * Get Client RPC data |
|
138 * This function is called by Health Monitoring Module |
|
139 */ |
|
140 krgetclientrpcdetail(double *calls, int *badcalls, int *retrans, int *badxids, int *timeouts, int *newcreds, int *badverfs, int *timers, int *nomem, int *cantsend) |
|
141 { |
|
142 int i, j, nreq; |
|
143 char fixlen[128]; |
|
144 char buf[1024]; |
|
145 kstat_named_t *knp; |
|
146 cflag++; |
|
147 rflag++; |
|
148 |
|
149 buf[0]= '\0'; |
|
150 |
|
151 setup(); |
|
152 |
|
153 getstats(); |
|
154 |
|
155 ncolumns = (MAX_COLUMNS - 1) / field_width; |
|
156 |
|
157 /* Kstat lookup client rpc info */ |
|
158 if (rpc_clts_client_kstat != NULL) { |
|
159 |
|
160 knp = KSTAT_NAMED_PTR(rpc_clts_client_kstat); |
|
161 nreq = rpc_clts_client_kstat->ks_ndata; |
|
162 |
|
163 for (i = 0; i < nreq; i += ncolumns) { |
|
164 /* Don't print heading */ |
|
165 /* |
|
166 for (j = i; j < MIN(i + ncolumns, nreq); j++) { |
|
167 printf("%-*s", field_width, knp[j].name); |
|
168 } |
|
169 printf("\n"); |
|
170 */ |
|
171 for (j = i; j < MIN(i + ncolumns, nreq); j++) { |
|
172 #if (defined SOLARIS2_5 || defined SOLARIS2_6) |
|
173 (void) sprintf(fixlen, "%lu ", knp[j].value.ul); |
|
174 #else |
|
175 (void) sprintf(fixlen, "%llu ", knp[j].value.ui64); |
|
176 #endif |
|
177 |
|
178 strcat(buf, fixlen); |
|
179 } |
|
180 } |
|
181 |
|
182 } |
|
183 *calls = atof(strtok(buf, " ")); |
|
184 *badcalls = atoi (strtok(NULL, " ")); |
|
185 *retrans = atoi (strtok(NULL, " ")); |
|
186 *badxids = atoi (strtok(NULL, " ")); |
|
187 *timeouts = atoi (strtok(NULL, " ")); |
|
188 *newcreds = atoi (strtok(NULL, " ")); |
|
189 *badverfs = atoi (strtok(NULL, " ")); |
|
190 *timers = atoi (strtok(NULL, " ")); |
|
191 *nomem = atoi (strtok(NULL, " ")); |
|
192 *cantsend = atoi (strtok(NULL, " ")); |
|
193 |
|
194 /* |
|
195 * The following function closes the kstat control structure |
|
196 * and sets the related variables to NULL. |
|
197 */ |
|
198 clear_setup_data(); |
|
199 |
|
200 return (0); |
|
201 } |
|
202 |
|
203 #define MIN(a, b) ((a) < (b) ? (a) : (b)) |
|
204 |
|
205 static void |
|
206 fail(int do_perror, char *message, ...) |
|
207 { |
|
208 va_list args; |
|
209 |
|
210 va_start(args, message); |
|
211 fprintf(stderr, "nfsstat: "); |
|
212 vfprintf(stderr, message, args); |
|
213 va_end(args); |
|
214 if (do_perror) |
|
215 fprintf(stderr, ": %s", strerror(errno)); |
|
216 fprintf(stderr, "\n"); |
|
217 exit(1); |
|
218 } |
|
219 |
|
220 kid_t |
|
221 safe_kstat_read(kstat_ctl_t *kc, kstat_t *ksp, void *data) |
|
222 { |
|
223 kid_t kstat_chain_id = kstat_read(kc, ksp, data); |
|
224 |
|
225 if (kstat_chain_id == -1) |
|
226 fail(1, "kstat_read(%x, '%s') failed", kc, ksp->ks_name); |
|
227 return (kstat_chain_id); |
|
228 } |
|
229 |
|
230 |