/* * Copyright 2000, International Business Machines Corporation and others. * All Rights Reserved. * * This software has been released under the terms of the IBM Public * License. For details, see the LICENSE file in the top-level source * directory or online at http://www.openafs.org/dl/license10.html */ #include #include #include #include #include #include #ifdef AFS_AIX32_ENV #include #endif #include #include #include #include extern struct rx_securityClass *rxnull_NewServerSecurityObject(); extern struct hostent *hostutil_GetHostByName(); static IsLocked(alock) register struct AFSDBLockDesc *alock; { if (alock->waitStates || alock->exclLocked || alock->numWaiting || alock->readersReading) return 1; return 0; } static PrintLock(alock) register struct AFSDBLockDesc *alock; { printf("("); if (alock->waitStates) { if (alock->waitStates & READ_LOCK) printf("reader_waiting"); if (alock->waitStates & WRITE_LOCK) printf("writer_waiting"); if (alock->waitStates & SHARED_LOCK) printf("upgrade_waiting"); } else printf("none_waiting"); if (alock->exclLocked) { if (alock->exclLocked & WRITE_LOCK) printf(", write_locked"); if (alock->exclLocked & SHARED_LOCK) printf(", upgrade_locked"); printf("(pid:%d at:%d)", alock->pid_writer, alock->src_indicator); } if (alock->readersReading) printf(", %d read_locks(pid:%d)", alock->readersReading,alock->pid_last_reader); if (alock->numWaiting) printf(", %d waiters", alock->numWaiting); printf(")"); return 0; } static PrintLocks(aconn, aint32) int aint32; register struct rx_connection *aconn; { register int i; struct AFSDBLock lock; afs_int32 code; for(i=0;i<1000;i++) { code = RXAFSCB_GetLock(aconn, i, &lock); if (code) { if (code == 1) break; /* otherwise we have an unrecognized error */ printf("cmdebug: error checking locks: %s\n", error_message(code)); return code; } /* here we have the lock information, so display it, perhaps */ if (aint32 || IsLocked(&lock.lock)) { printf("Lock %s status: ", lock.name); PrintLock(&lock.lock); printf("\n"); } } return 0; } static PrintCacheEntries(aconn, aint32) int aint32; register struct rx_connection *aconn; { register int i; register afs_int32 code; struct AFSDBCacheEntry centry; for(i=0;i<10000;i++) { code = RXAFSCB_GetCE(aconn, i, ¢ry); if (code) { if (code == 1) break; printf("cmdebug: failed to get cache entry %d (%s)\n", i, error_message(code)); return code; } if (centry.addr == 0) { /* PS output */ printf("Proc %4d sleeping at %08x, pri %3d\n", centry.netFid.Vnode, centry.netFid.Volume, centry.netFid.Unique-25); continue; } if (!aint32 && !IsLocked(¢ry.lock)) continue; /* otherwise print this entry */ printf("** Cache entry @ 0x%08x for %d.%d.%d.%d\n", centry.addr, centry.cell, centry.netFid.Volume, centry.netFid.Vnode, centry.netFid.Unique); if (IsLocked(¢ry.lock)) { printf(" locks: "); PrintLock(¢ry.lock); printf("\n"); } printf(" %d bytes\tDV %d refcnt %d\n", centry.Length, centry.DataVersion, centry.refCount); printf(" callback %08x\texpires %u\n", centry.callback, centry.cbExpires); printf(" %d opens\t%d writers\n", centry.opens, centry.writers); /* now display states */ printf(" "); if (centry.mvstat == 0) printf("normal file"); else if (centry.mvstat == 1) printf("mount point"); else if (centry.mvstat == 2) printf("volume root"); else printf("bogus mvstat %d", centry.mvstat); printf("\n states (0x%x)", centry.states); if (centry.states & 1) printf(", stat'd"); if (centry.states & 2) printf(", backup"); if (centry.states & 4) printf(", read-only"); if (centry.states & 8) printf(", mt pt valid"); if (centry.states & 0x10) printf(", pending core"); if (centry.states & 0x40) printf(", wait-for-store"); if (centry.states & 0x80) printf(", mapped"); printf("\n"); } return 0; } static CommandProc(as) struct cmd_syndesc *as; { struct rx_connection *conn; register char *hostName; register struct hostent *thp; afs_int32 port; struct rx_securityClass *secobj; int int32p; afs_int32 addr; hostName = as->parms[0].items->data; if (as->parms[1].items) port = atoi(as->parms[1].items->data); else port = 7001; thp = hostutil_GetHostByName(hostName); if (!thp) { printf("cmdebug: can't resolve address for host %s.\n", hostName); exit(1); } bcopy(thp->h_addr, &addr, sizeof(afs_int32)); secobj = rxnull_NewServerSecurityObject(); conn = rx_NewConnection(addr, htons(port), 1, secobj, 0); if (!conn) { printf("cmdebug: failed to create connection for host %s\n", hostName); exit(1); } if (as->parms[2].items) int32p = 1; else int32p = 0; PrintLocks(conn, int32p); PrintCacheEntries(conn, int32p); return 0; } #include "AFS_component_version_number.c" main(argc, argv) int argc; char **argv; { register struct cmd_syndesc *ts; #ifdef AFS_AIX32_ENV /* * The following signal action for AIX is necessary so that in case of a * crash (i.e. core is generated) we can include the user's data section * in the core dump. Unfortunately, by default, only a partial core is * generated which, in many cases, isn't too useful. */ struct sigaction nsa; sigemptyset(&nsa.sa_mask); nsa.sa_handler = SIG_DFL; nsa.sa_flags = SA_FULLDUMP; sigaction(SIGSEGV, &nsa, NULL); #endif rx_Init(0); ts = cmd_CreateSyntax((char *) 0, CommandProc, 0, "probe unik server"); cmd_AddParm(ts, "-servers", CMD_SINGLE, CMD_REQUIRED, "server machine"); cmd_AddParm(ts, "-port", CMD_SINGLE, CMD_OPTIONAL, "IP port"); cmd_AddParm(ts, "-long", CMD_FLAG, CMD_OPTIONAL, "print all info"); cmd_Dispatch(argc, argv); exit(0); }