reindent-20030715
[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
14     ("$Header$");
15
16
17 #include <sys/types.h>
18 #include <netinet/in.h>
19 #include <sys/socket.h>
20 #include <netdb.h>
21 #include <stdio.h>
22 #ifdef HAVE_STRING_H
23 #include <string.h>
24 #else
25 #ifdef HAVE_STRINGS_H
26 #include <strings.h>
27 #endif
28 #endif
29 #ifdef  AFS_AIX32_ENV
30 #include <signal.h>
31 #endif
32 #include <afs/afscbint.h>
33 #include <afs/cmd.h>
34 #include <rx/rx.h>
35 #include <lock.h>
36 #include <afs/afs_args.h>
37
38 extern struct hostent *hostutil_GetHostByName();
39
40 static
41 PrintCacheConfig(aconn)
42      struct rx_connection *aconn;
43 {
44     struct cacheConfig c;
45     afs_uint32 srv_ver, conflen;
46     int code;
47
48     c.cacheConfig_len = 0;
49     c.cacheConfig_val = NULL;
50     code = RXAFSCB_GetCacheConfig(aconn, 1, &srv_ver, &conflen, &c);
51     if (code) {
52         printf("cmdebug: error checking cache config: %s\n",
53                error_message(code));
54         return 0;
55     }
56
57     if (srv_ver == AFS_CLIENT_RETRIEVAL_FIRST_EDITION) {
58         struct cm_initparams_v1 *c1;
59
60         if (c.cacheConfig_len != sizeof(*c1) / sizeof(afs_uint32)) {
61             printf("cmdebug: configuration data size mismatch (%d != %d)\n",
62                    c.cacheConfig_len, sizeof(*c1) / sizeof(afs_uint32));
63             return 0;
64         }
65
66         c1 = (struct cm_initparams_v1 *)c.cacheConfig_val;
67         printf("Chunk files:   %d\n", c1->nChunkFiles);
68         printf("Stat caches:   %d\n", c1->nStatCaches);
69         printf("Data caches:   %d\n", c1->nDataCaches);
70         printf("Volume caches: %d\n", c1->nVolumeCaches);
71         printf("Chunk size:    %d", c1->otherChunkSize);
72         if (c1->firstChunkSize != c1->otherChunkSize)
73             printf(" (first: %d)", c1->firstChunkSize);
74         printf("\n");
75         printf("Cache size:    %d kB\n", c1->cacheSize);
76         printf("Set time:      %s\n", c1->setTime ? "yes" : "no");
77         printf("Cache type:    %s\n", c1->memCache ? "memory" : "disk");
78     } else {
79         printf("cmdebug: unsupported server version %d\n", srv_ver);
80     }
81 }
82
83 static
84 PrintInterfaces(aconn)
85      struct rx_connection *aconn;
86 {
87     struct interfaceAddr addr;
88     int i, code;
89
90     code = RXAFSCB_WhoAreYou(aconn, &addr);
91     if (code) {
92         printf("cmdebug: error checking interfaces: %s\n",
93                error_message(code));
94         return 0;
95     }
96
97     printf("Host interfaces:\n");
98     for (i = 0; i < addr.numberOfInterfaces; i++) {
99         printf("%s", afs_inet_ntoa(htonl(addr.addr_in[i])));
100         if (addr.subnetmask[i])
101             printf(", netmask %s", afs_inet_ntoa(htonl(addr.subnetmask[i])));
102         if (addr.mtu[i])
103             printf(", MTU %d", addr.mtu[i]);
104         printf("\n");
105     }
106
107     return 0;
108 }
109
110 static
111 IsLocked(alock)
112      register struct AFSDBLockDesc *alock;
113 {
114     if (alock->waitStates || alock->exclLocked || alock->numWaiting
115         || alock->readersReading)
116         return 1;
117     return 0;
118 }
119
120 static
121 PrintLock(alock)
122      register struct AFSDBLockDesc *alock;
123 {
124     printf("(");
125     if (alock->waitStates) {
126         if (alock->waitStates & READ_LOCK)
127             printf("reader_waiting");
128         if (alock->waitStates & WRITE_LOCK)
129             printf("writer_waiting");
130         if (alock->waitStates & SHARED_LOCK)
131             printf("upgrade_waiting");
132     } else
133         printf("none_waiting");
134     if (alock->exclLocked) {
135         if (alock->exclLocked & WRITE_LOCK)
136             printf(", write_locked");
137         if (alock->exclLocked & SHARED_LOCK)
138             printf(", upgrade_locked");
139         printf("(pid:%d at:%d)", alock->pid_writer, alock->src_indicator);
140     }
141     if (alock->readersReading)
142         printf(", %d read_locks(pid:%d)", alock->readersReading,
143                alock->pid_last_reader);
144     if (alock->numWaiting)
145         printf(", %d waiters", alock->numWaiting);
146     printf(")");
147     return 0;
148 }
149
150 static
151 PrintLocks(aconn, aint32)
152      int aint32;
153      register struct rx_connection *aconn;
154 {
155     register int i;
156     struct AFSDBLock lock;
157     afs_int32 code;
158
159     for (i = 0; i < 1000; i++) {
160         code = RXAFSCB_GetLock(aconn, i, &lock);
161         if (code) {
162             if (code == 1)
163                 break;
164             /* otherwise we have an unrecognized error */
165             printf("cmdebug: error checking locks: %s\n",
166                    error_message(code));
167             return code;
168         }
169         /* here we have the lock information, so display it, perhaps */
170         if (aint32 || IsLocked(&lock.lock)) {
171             printf("Lock %s status: ", lock.name);
172             PrintLock(&lock.lock);
173             printf("\n");
174         }
175     }
176     return 0;
177 }
178
179 struct cell_cache {
180     afs_int32 cellnum;
181     char *cellname;
182     struct cell_cache *next;
183 };
184
185 static char *
186 GetCellName(struct rx_connection *aconn, afs_int32 cellnum)
187 {
188     static int no_getcellbynum;
189     static struct cell_cache *cache;
190     struct cell_cache *tcp;
191     int code;
192     char *cellname;
193     serverList sl;
194
195     if (no_getcellbynum)
196         return NULL;
197
198     for (tcp = cache; tcp; tcp = tcp->next)
199         if (tcp->cellnum == cellnum)
200             return tcp->cellname;
201
202     cellname = NULL;
203     sl.serverList_len = 0;
204     sl.serverList_val = NULL;
205     code = RXAFSCB_GetCellByNum(aconn, cellnum, &cellname, &sl);
206     if (code) {
207         if (code == RXGEN_OPCODE)
208             no_getcellbynum = 1;
209         return NULL;
210     }
211
212     if (sl.serverList_val)
213         free(sl.serverList_val);
214     tcp = malloc(sizeof(struct cell_cache));
215     tcp->next = cache;
216     tcp->cellnum = cellnum;
217     tcp->cellname = cellname;
218     cache = tcp;
219
220     return cellname;
221 }
222
223 static int
224 PrintCacheEntries32(struct rx_connection *aconn, int aint32)
225 {
226     register int i;
227     register afs_int32 code;
228     struct AFSDBCacheEntry centry;
229     char *cellname;
230
231     for (i = 0; i < 10000; i++) {
232         code = RXAFSCB_GetCE(aconn, i, &centry);
233         if (code) {
234             if (code == 1)
235                 break;
236             printf("cmdebug: failed to get cache entry %d (%s)\n", i,
237                    error_message(code));
238             return code;
239         }
240
241         if (centry.addr == 0) {
242             /* PS output */
243             printf("Proc %4d sleeping at %08x, pri %3d\n",
244                    centry.netFid.Vnode, centry.netFid.Volume,
245                    centry.netFid.Unique - 25);
246             continue;
247         }
248
249         if (!aint32 && !IsLocked(&centry.lock))
250             continue;
251
252         /* otherwise print this entry */
253         printf("** Cache entry @ 0x%08x for %d.%d.%d.%d", centry.addr,
254                centry.cell, centry.netFid.Volume, centry.netFid.Vnode,
255                centry.netFid.Unique);
256
257         cellname = GetCellName(aconn, centry.cell);
258         if (cellname)
259             printf(" [%s]\n", cellname);
260         else
261             printf("\n");
262
263         if (IsLocked(&centry.lock)) {
264             printf("    locks: ");
265             PrintLock(&centry.lock);
266             printf("\n");
267         }
268         printf("    %d bytes\tDV %d refcnt %d\n", centry.Length,
269                centry.DataVersion, centry.refCount);
270         printf("    callback %08x\texpires %u\n", centry.callback,
271                centry.cbExpires);
272         printf("    %d opens\t%d writers\n", centry.opens, centry.writers);
273
274         /* now display states */
275         printf("    ");
276         if (centry.mvstat == 0)
277             printf("normal file");
278         else if (centry.mvstat == 1)
279             printf("mount point");
280         else if (centry.mvstat == 2)
281             printf("volume root");
282         else
283             printf("bogus mvstat %d", centry.mvstat);
284         printf("\n    states (0x%x)", centry.states);
285         if (centry.states & 1)
286             printf(", stat'd");
287         if (centry.states & 2)
288             printf(", backup");
289         if (centry.states & 4)
290             printf(", read-only");
291         if (centry.states & 8)
292             printf(", mt pt valid");
293         if (centry.states & 0x10)
294             printf(", pending core");
295         if (centry.states & 0x40)
296             printf(", wait-for-store");
297         if (centry.states & 0x80)
298             printf(", mapped");
299         printf("\n");
300     }
301     return 0;
302 }
303
304 static int
305 PrintCacheEntries64(struct rx_connection *aconn, int aint32)
306 {
307     register int i;
308     register afs_int32 code;
309     struct AFSDBCacheEntry64 centry;
310     char *cellname;
311     int ce64 = 0;
312
313     for (i = 0; i < 10000; i++) {
314         code = RXAFSCB_GetCE64(aconn, i, &centry);
315         if (code) {
316             if (code == 1)
317                 break;
318             printf("cmdebug: failed to get cache entry %d (%s)\n", i,
319                    error_message(code));
320             return code;
321         }
322
323         if (centry.addr == 0) {
324             /* PS output */
325             printf("Proc %4d sleeping at %08x, pri %3d\n",
326                    centry.netFid.Vnode, centry.netFid.Volume,
327                    centry.netFid.Unique - 25);
328             continue;
329         }
330
331         if (!aint32 && !IsLocked(&centry.lock))
332             continue;
333
334         /* otherwise print this entry */
335         printf("** Cache entry @ 0x%08x for %d.%d.%d.%d", centry.addr,
336                centry.cell, centry.netFid.Volume, centry.netFid.Vnode,
337                centry.netFid.Unique);
338
339         cellname = GetCellName(aconn, centry.cell);
340         if (cellname)
341             printf(" [%s]\n", cellname);
342         else
343             printf("\n");
344
345         if (IsLocked(&centry.lock)) {
346             printf("    locks: ");
347             PrintLock(&centry.lock);
348             printf("\n");
349         }
350 #ifdef AFS_64BIT_ENV
351         printf("    %lld bytes\tDV %d refcnt %d\n", centry.Length,
352                centry.DataVersion, centry.refCount);
353 #else
354         printf("    %d bytes\tDV %d refcnt %d\n", centry.Length,
355                centry.DataVersion, centry.refCount);
356 #endif
357         printf("    callback %08x\texpires %u\n", centry.callback,
358                centry.cbExpires);
359         printf("    %d opens\t%d writers\n", centry.opens, centry.writers);
360
361         /* now display states */
362         printf("    ");
363         if (centry.mvstat == 0)
364             printf("normal file");
365         else if (centry.mvstat == 1)
366             printf("mount point");
367         else if (centry.mvstat == 2)
368             printf("volume root");
369         else
370             printf("bogus mvstat %d", centry.mvstat);
371         printf("\n    states (0x%x)", centry.states);
372         if (centry.states & 1)
373             printf(", stat'd");
374         if (centry.states & 2)
375             printf(", backup");
376         if (centry.states & 4)
377             printf(", read-only");
378         if (centry.states & 8)
379             printf(", mt pt valid");
380         if (centry.states & 0x10)
381             printf(", pending core");
382         if (centry.states & 0x40)
383             printf(", wait-for-store");
384         if (centry.states & 0x80)
385             printf(", mapped");
386         printf("\n");
387     }
388     return 0;
389 }
390
391 static int
392 PrintCacheEntries(struct rx_connection *aconn, int aint32)
393 {
394     register afs_int32 code;
395     struct AFSDBCacheEntry64 centry64;
396
397     code = RXAFSCB_GetCE64(aconn, 0, &centry64);
398     if (code != RXGEN_OPCODE)
399         return PrintCacheEntries64(aconn, aint32);
400     else
401         return PrintCacheEntries32(aconn, aint32);
402 }
403
404 static
405 CommandProc(as)
406      struct cmd_syndesc *as;
407 {
408     struct rx_connection *conn;
409     register char *hostName;
410     register struct hostent *thp;
411     afs_int32 port;
412     struct rx_securityClass *secobj;
413     int int32p;
414     afs_int32 addr;
415
416     hostName = as->parms[0].items->data;
417     if (as->parms[1].items)
418         port = atoi(as->parms[1].items->data);
419     else
420         port = 7001;
421     thp = hostutil_GetHostByName(hostName);
422     if (!thp) {
423         printf("cmdebug: can't resolve address for host %s.\n", hostName);
424         exit(1);
425     }
426     memcpy(&addr, thp->h_addr, sizeof(afs_int32));
427     secobj = rxnull_NewServerSecurityObject();
428     conn = rx_NewConnection(addr, htons(port), 1, secobj, 0);
429     if (!conn) {
430         printf("cmdebug: failed to create connection for host %s\n",
431                hostName);
432         exit(1);
433     }
434     if (as->parms[3].items) {
435         /* -addrs */
436         PrintInterfaces(conn);
437         return 0;
438     }
439     if (as->parms[4].items) {
440         /* -cache */
441         PrintCacheConfig(conn);
442         return 0;
443     }
444     if (as->parms[2].items)
445         int32p = 1;
446     else
447         int32p = 0;
448     PrintLocks(conn, int32p);
449     PrintCacheEntries(conn, int32p);
450     return 0;
451 }
452
453 #include "AFS_component_version_number.c"
454
455 main(argc, argv)
456      int argc;
457      char **argv;
458 {
459     register struct cmd_syndesc *ts;
460
461 #ifdef  AFS_AIX32_ENV
462     /*
463      * The following signal action for AIX is necessary so that in case of a 
464      * crash (i.e. core is generated) we can include the user's data section 
465      * in the core dump. Unfortunately, by default, only a partial core is
466      * generated which, in many cases, isn't too useful.
467      */
468     struct sigaction nsa;
469
470     sigemptyset(&nsa.sa_mask);
471     nsa.sa_handler = SIG_DFL;
472     nsa.sa_flags = SA_FULLDUMP;
473     sigaction(SIGSEGV, &nsa, NULL);
474 #endif
475     rx_Init(0);
476
477     ts = cmd_CreateSyntax(NULL, CommandProc, 0, "probe unik server");
478     cmd_AddParm(ts, "-servers", CMD_SINGLE, CMD_REQUIRED, "server machine");
479     cmd_AddParm(ts, "-port", CMD_SINGLE, CMD_OPTIONAL, "IP port");
480     cmd_AddParm(ts, "-long", CMD_FLAG, CMD_OPTIONAL, "print all info");
481     cmd_AddParm(ts, "-addrs", CMD_FLAG, CMD_OPTIONAL,
482                 "print only host interfaces");
483     cmd_AddParm(ts, "-cache", CMD_FLAG, CMD_OPTIONAL,
484                 "print only cache configuration");
485
486     cmd_Dispatch(argc, argv);
487     exit(0);
488 }