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