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