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