a598dc3fc8dee4610c391f97c58a50cd6e4909b1
[openafs.git] / src / venus / cmdebug.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12
13 RCSID("$Header$");
14
15
16 #include <sys/types.h>
17 #include <netinet/in.h>
18 #include <sys/socket.h>
19 #include <netdb.h>
20 #include <stdio.h>
21 #ifdef  AFS_AIX32_ENV
22 #include <signal.h>
23 #endif
24 #include <afs/afscbint.h>
25 #include <afs/cmd.h>
26 #include <rx/rx.h>
27 #include <lock.h>
28
29 /* XXX is this kosher? */
30 #include <afs_args.h>
31
32 extern struct rx_securityClass *rxnull_NewServerSecurityObject();
33 extern struct hostent *hostutil_GetHostByName();
34
35 static PrintCacheConfig(aconn)
36     struct rx_connection *aconn;
37 {
38     struct cacheConfig c;
39     afs_uint32 srv_ver, conflen;
40     int code;
41
42     c.cacheConfig_len = 0;
43     code = RXAFSCB_GetCacheConfig(aconn, 1, &srv_ver, &conflen, &c);
44     if (code) {
45         printf("cmdebug: error checking cache config: %s\n",
46                error_message(code));
47         return 0;
48     }
49
50     if (srv_ver == AFS_CLIENT_RETRIEVAL_FIRST_EDITION) {
51         struct cm_initparams_v1 *c1;
52
53         if (c.cacheConfig_len != sizeof(*c1) / sizeof(afs_uint32)) {
54             printf("cmdebug: configuration data size mismatch (%d != %d)\n",
55                    c.cacheConfig_len, sizeof(*c1) / sizeof(afs_uint32));
56             return 0;
57         }
58
59         c1 = (struct cm_initparams_v1 *) c.cacheConfig_val;
60         printf("Chunk files:   %d\n", c1->nChunkFiles);
61         printf("Stat caches:   %d\n", c1->nStatCaches);
62         printf("Data caches:   %d\n", c1->nDataCaches);
63         printf("Volume caches: %d\n", c1->nVolumeCaches);
64         printf("Chunk size:    %d", c1->otherChunkSize);
65         if (c1->firstChunkSize != c1->otherChunkSize)
66             printf(" (first: %d)", c1->firstChunkSize);
67         printf("\n");
68         printf("Cache size:    %d kB\n", c1->cacheSize);
69         printf("Set time:      %s\n", c1->setTime ? "yes" : "no");
70         printf("Cache type:    %s\n", c1->memCache ? "memory" : "disk");
71     } else {
72         printf("cmdebug: unsupported server version %d\n", srv_ver);
73     }
74 }
75
76 static PrintInterfaces(aconn)
77     struct rx_connection *aconn;
78 {
79     struct interfaceAddr addr;
80     int i, code;
81
82     code = RXAFSCB_WhoAreYou(aconn, &addr);
83     if (code) {
84         printf("cmdebug: error checking interfaces: %s\n", error_message(code));
85         return 0;
86     }
87
88     printf("Host interfaces:\n");
89     for (i=0; i<addr.numberOfInterfaces; i++) {
90         printf("%s", inet_ntoa(&addr.addr_in[i]));
91         if (addr.subnetmask[i])
92             printf(", netmask %s", inet_ntoa(&addr.subnetmask[i]));
93         if (addr.mtu[i])
94             printf(", MTU %d", addr.mtu[i]);
95         printf("\n");
96     }
97
98     return 0;
99 }
100
101 static IsLocked(alock)
102 register struct AFSDBLockDesc *alock; {
103     if (alock->waitStates || alock->exclLocked
104         || alock->numWaiting || alock->readersReading)
105         return 1;
106     return 0;
107 }
108
109 static PrintLock(alock)
110 register struct AFSDBLockDesc *alock; {
111     printf("(");
112     if (alock->waitStates) {
113         if (alock->waitStates & READ_LOCK)
114             printf("reader_waiting");
115         if (alock->waitStates & WRITE_LOCK)
116             printf("writer_waiting");
117         if (alock->waitStates & SHARED_LOCK)
118             printf("upgrade_waiting");
119     }
120     else
121         printf("none_waiting");
122     if (alock->exclLocked) {
123         if (alock->exclLocked & WRITE_LOCK)
124             printf(", write_locked");
125         if (alock->exclLocked & SHARED_LOCK)
126             printf(", upgrade_locked");
127         printf("(pid:%d at:%d)", alock->pid_writer, alock->src_indicator);
128     }
129     if (alock->readersReading)
130         printf(", %d read_locks(pid:%d)", alock->readersReading,alock->pid_last_reader);
131     if (alock->numWaiting) printf(", %d waiters", alock->numWaiting);
132     printf(")");
133     return 0;
134 }
135
136 static PrintLocks(aconn, aint32)
137 int aint32;
138 register struct rx_connection *aconn; {
139     register int i;
140     struct AFSDBLock lock;
141     afs_int32 code;
142
143     for(i=0;i<1000;i++) {
144         code = RXAFSCB_GetLock(aconn, i, &lock);
145         if (code) {
146             if (code == 1) break;
147             /* otherwise we have an unrecognized error */
148             printf("cmdebug: error checking locks: %s\n", error_message(code));
149             return code;
150         }
151         /* here we have the lock information, so display it, perhaps */
152         if (aint32 || IsLocked(&lock.lock)) {
153             printf("Lock %s status: ", lock.name);
154             PrintLock(&lock.lock);
155             printf("\n");
156         }
157     }
158     return 0;
159 }
160
161 static PrintCacheEntries(aconn, aint32)
162 int aint32;
163 register struct rx_connection *aconn; {
164     register int i;
165     register afs_int32 code;
166     struct AFSDBCacheEntry centry;
167
168     for(i=0;i<10000;i++) {
169         code = RXAFSCB_GetCE(aconn, i, &centry);
170         if (code) {
171             if (code == 1) break;
172             printf("cmdebug: failed to get cache entry %d (%s)\n", i,
173                    error_message(code));
174             return code;
175         }
176
177         if (centry.addr == 0) {
178             /* PS output */
179             printf("Proc %4d sleeping at %08x, pri %3d\n",
180                    centry.netFid.Vnode, centry.netFid.Volume, centry.netFid.Unique-25);
181             continue;
182         }
183
184         if (!aint32 && !IsLocked(&centry.lock)) continue;
185
186         /* otherwise print this entry */
187         printf("** Cache entry @ 0x%08x for %d.%d.%d.%d\n", centry.addr, centry.cell,
188                centry.netFid.Volume, centry.netFid.Vnode, centry.netFid.Unique);
189         if (IsLocked(&centry.lock)) {
190             printf("    locks: ");
191             PrintLock(&centry.lock);
192             printf("\n");
193         }
194         printf("    %d bytes\tDV %d refcnt %d\n", centry.Length, centry.DataVersion, centry.refCount);
195         printf("    callback %08x\texpires %u\n", centry.callback, centry.cbExpires);
196         printf("    %d opens\t%d writers\n", centry.opens, centry.writers);
197
198         /* now display states */
199         printf("    ");
200         if (centry.mvstat == 0) printf("normal file");
201         else if (centry.mvstat == 1) printf("mount point");
202         else if (centry.mvstat == 2) printf("volume root");
203         else printf("bogus mvstat %d", centry.mvstat);
204         printf("\n    states (0x%x)", centry.states);
205         if (centry.states & 1) printf(", stat'd");
206         if (centry.states & 2) printf(", backup");
207         if (centry.states & 4) printf(", read-only");
208         if (centry.states & 8) printf(", mt pt valid");
209         if (centry.states & 0x10) printf(", pending core");
210         if (centry.states & 0x40) printf(", wait-for-store");
211         if (centry.states & 0x80) printf(", mapped");
212         printf("\n");
213     }
214     return 0;
215 }
216
217 static CommandProc(as)
218 struct cmd_syndesc *as; {
219     struct rx_connection *conn;
220     register char *hostName;
221     register struct hostent *thp;
222     afs_int32 port;
223     struct rx_securityClass *secobj;
224     int int32p;
225     afs_int32 addr;
226
227     hostName = as->parms[0].items->data;
228     if (as->parms[1].items)
229         port = atoi(as->parms[1].items->data);
230     else
231         port = 7001;
232     thp = hostutil_GetHostByName(hostName);
233     if (!thp) {
234         printf("cmdebug: can't resolve address for host %s.\n", hostName);
235         exit(1);
236     }
237     memcpy(&addr, thp->h_addr, sizeof(afs_int32));
238     secobj = rxnull_NewServerSecurityObject();
239     conn = rx_NewConnection(addr, htons(port), 1, secobj, 0);
240     if (!conn) {
241         printf("cmdebug: failed to create connection for host %s\n", hostName);
242         exit(1);
243     }
244     if (as->parms[3].items) {
245         /* -addrs */
246         PrintInterfaces(conn);
247         return 0;
248     }
249     if (as->parms[4].items) {
250         /* -cache */
251         PrintCacheConfig(conn);
252         return 0;
253     }
254     if (as->parms[2].items) int32p = 1;
255     else int32p = 0;
256     PrintLocks(conn, int32p);
257     PrintCacheEntries(conn, int32p);
258     return 0;
259 }
260
261 #include "AFS_component_version_number.c"
262
263 main(argc, argv)
264 int argc;
265 char **argv; {
266     register struct cmd_syndesc *ts;
267
268 #ifdef  AFS_AIX32_ENV
269     /*
270      * The following signal action for AIX is necessary so that in case of a 
271      * crash (i.e. core is generated) we can include the user's data section 
272      * in the core dump. Unfortunately, by default, only a partial core is
273      * generated which, in many cases, isn't too useful.
274      */
275     struct sigaction nsa;
276     
277     sigemptyset(&nsa.sa_mask);
278     nsa.sa_handler = SIG_DFL;
279     nsa.sa_flags = SA_FULLDUMP;
280     sigaction(SIGSEGV, &nsa, NULL);
281 #endif
282     rx_Init(0);
283
284     ts = cmd_CreateSyntax((char *) 0, CommandProc, 0, "probe unik server");
285     cmd_AddParm(ts, "-servers", CMD_SINGLE, CMD_REQUIRED, "server machine");
286     cmd_AddParm(ts, "-port", CMD_SINGLE, CMD_OPTIONAL, "IP port");
287     cmd_AddParm(ts, "-long", CMD_FLAG, CMD_OPTIONAL, "print all info");
288     cmd_AddParm(ts, "-addrs", CMD_FLAG, CMD_OPTIONAL, "print only host interfaces");
289     cmd_AddParm(ts, "-cache", CMD_FLAG, CMD_OPTIONAL, "print only cache configuration");
290
291     cmd_Dispatch(argc, argv);
292     exit(0);
293 }