openafs-void-star-pointers-20071031
[openafs.git] / src / vol / fssync-debug.c
1 /*
2  * Copyright 2006, Sine Nomine Associates 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 /* Main program file. Define globals. */
11 #define MAIN 1
12
13 /*
14  * fssync administration tool
15  */
16
17
18 #include <afsconfig.h>
19 #include <afs/param.h>
20
21 RCSID
22     ("$Header$");
23
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <dirent.h>
28 #include <sys/stat.h>
29 #include <time.h>
30 #include <errno.h>
31 #ifdef AFS_NT40_ENV
32 #include <io.h>
33 #include <WINNT/afsevent.h>
34 #else
35 #include <sys/param.h>
36 #include <sys/file.h>
37 #ifndef ITIMER_REAL
38 #include <sys/time.h>
39 #endif /* ITIMER_REAL */
40 #endif
41 #include <rx/xdr.h>
42 #include <afs/afsint.h>
43 #include <afs/assert.h>
44
45
46 #include <fcntl.h>
47
48 #ifndef AFS_NT40_ENV
49 #include <afs/osi_inode.h>
50 #endif
51
52 #include <afs/cmd.h>
53 #include <afs/afsutil.h>
54 #include <afs/fileutil.h>
55
56 #include "nfs.h"
57 #include "lwp.h"
58 #include "lock.h"
59 #include "ihandle.h"
60 #include "vnode.h"
61 #include "volume.h"
62 #include "partition.h"
63 #include "daemon_com.h"
64 #include "fssync.h"
65 #ifdef AFS_NT40_ENV
66 #include <pthread.h>
67 #endif
68
69 int VolumeChanged; /* hack to make dir package happy */
70
71
72 struct volop_state {
73     afs_uint32 volume;
74     char partName[16];
75 };
76
77 struct state {
78     afs_int32 reason;
79     struct volop_state * vop;
80 };
81
82 static int common_prolog(struct cmd_syndesc *, struct state *);
83 static int common_volop_prolog(struct cmd_syndesc *, struct state *);
84
85 static int do_volop(struct state *, afs_int32 command, SYNC_response * res);
86
87 static char * response_code_to_string(afs_int32);
88 static char * command_code_to_string(afs_int32);
89 static char * reason_code_to_string(afs_int32);
90 static char * program_type_to_string(afs_int32);
91
92 static int VolOnline(struct cmd_syndesc * as, void * rock);
93 static int VolOffline(struct cmd_syndesc * as, void * rock);
94 static int VolMode(struct cmd_syndesc * as, void * rock);
95 static int VolDetach(struct cmd_syndesc * as, void * rock);
96 static int VolBreakCBKs(struct cmd_syndesc * as, void * rock);
97 static int VolMove(struct cmd_syndesc * as, void * rock);
98 static int VolList(struct cmd_syndesc * as, void * rock);
99 static int VolQuery(struct cmd_syndesc * as, void * rock);
100 static int VolHdrQuery(struct cmd_syndesc * as, void * rock);
101 static int VolOpQuery(struct cmd_syndesc * as, void * rock);
102 static int StatsQuery(struct cmd_syndesc * as, void * rock);
103
104
105 static void print_vol_stats_general(VolPkgStats * stats);
106 static void print_vol_stats_viceP(struct DiskPartitionStats * stats);
107 static void print_vol_stats_hash(struct VolumeHashChainStats * stats);
108 #ifdef AFS_DEMAND_ATTACH_FS
109 static void print_vol_stats_hdr(struct volume_hdr_LRU_stats * stats);
110 #endif
111
112 #ifndef AFS_NT40_ENV
113 #include "AFS_component_version_number.c"
114 #endif
115 #define MAX_ARGS 128
116
117 #define COMMON_PARMS_OFFSET    12
118 #define COMMON_PARMS(ts) \
119     cmd_Seek(ts, COMMON_PARMS_OFFSET); \
120     cmd_AddParm(ts, "-reason", CMD_SINGLE, CMD_OPTIONAL, "sync protocol reason code"); \
121     cmd_AddParm(ts, "-programtype", CMD_SINGLE, CMD_OPTIONAL, "program type code")
122
123 #define COMMON_VOLOP_PARMS_OFFSET    10
124 #define COMMON_VOLOP_PARMS(ts) \
125     cmd_Seek(ts, COMMON_VOLOP_PARMS_OFFSET); \
126     cmd_AddParm(ts, "-volumeid", CMD_SINGLE, 0, "volume id"); \
127     cmd_AddParm(ts, "-partition", CMD_SINGLE, CMD_OPTIONAL, "partition name")
128
129 #define CUSTOM_PARMS_OFFSET 1
130
131
132 #define VOLOP_PARMS_DECL(ts) \
133     COMMON_VOLOP_PARMS(ts); \
134     COMMON_PARMS(ts)
135 #define COMMON_PARMS_DECL(ts) \
136     COMMON_PARMS(ts)
137
138 int
139 main(int argc, char **argv)
140 {
141     struct cmd_syndesc *ts;
142     int err = 0;
143     int i;
144     extern char cml_version_number[];
145
146     /* Initialize directory paths */
147     if (!(initAFSDirPath() & AFSDIR_SERVER_PATHS_OK)) {
148 #ifdef AFS_NT40_ENV
149         ReportErrorEventAlt(AFSEVT_SVR_NO_INSTALL_DIR, 0, argv[0], 0);
150 #endif
151         fprintf(stderr, "%s: Unable to obtain AFS server directory.\n",
152                 argv[0]);
153         exit(2);
154     }
155
156     
157     ts = cmd_CreateSyntax("online", VolOnline, NULL, "bring a volume online (FSYNC_VOL_ON opcode)");
158     VOLOP_PARMS_DECL(ts);
159
160     ts = cmd_CreateSyntax("offline", VolOffline, NULL, "take a volume offline (FSYNC_VOL_OFF opcode)");
161     VOLOP_PARMS_DECL(ts);
162
163     ts = cmd_CreateSyntax("mode", VolMode, NULL, "change volume attach mode (FSYNC_VOL_NEEDVOLUME opcode)");
164     VOLOP_PARMS_DECL(ts);
165     cmd_CreateAlias(ts, "needvolume");
166
167     ts = cmd_CreateSyntax("detach", VolDetach, NULL, "detach a volume (FSYNC_VOL_DONE opcode)");
168     VOLOP_PARMS_DECL(ts);
169
170     ts = cmd_CreateSyntax("callback", VolBreakCBKs, NULL, "break callbacks for volume (FSYNC_VOL_BREAKCBKS opcode)");
171     VOLOP_PARMS_DECL(ts);
172     cmd_CreateAlias(ts, "cbk");
173
174     ts = cmd_CreateSyntax("move", VolMove, NULL, "set volume moved flag (FSYNC_VOL_MOVE opcode)");
175     VOLOP_PARMS_DECL(ts);
176
177     ts = cmd_CreateSyntax("list", VolList, NULL, "sync local volume list (FSYNC_VOL_LISTVOLUMES opcode)");
178     VOLOP_PARMS_DECL(ts);
179     cmd_CreateAlias(ts, "ls");
180
181     ts = cmd_CreateSyntax("query", VolQuery, NULL, "get volume structure (FSYNC_VOL_QUERY opcode)");
182     VOLOP_PARMS_DECL(ts);
183     cmd_CreateAlias(ts, "qry");
184
185     ts = cmd_CreateSyntax("header", VolHdrQuery, NULL, "get volume disk data structure (FSYNC_VOL_QUERY_HDR opcode)");
186     VOLOP_PARMS_DECL(ts);
187     cmd_CreateAlias(ts, "hdr");
188
189     ts = cmd_CreateSyntax("volop", VolOpQuery, NULL, "get pending volume operation info (FSYNC_VOL_QUERY_VOP opcode)");
190     VOLOP_PARMS_DECL(ts);
191     cmd_CreateAlias(ts, "vop");
192
193     ts = cmd_CreateSyntax("stats", StatsQuery, NULL, "see 'stats help' for more information");
194     cmd_Seek(ts, CUSTOM_PARMS_OFFSET);
195     cmd_AddParm(ts, "-cmd", CMD_SINGLE, 0, "subcommand");
196     cmd_AddParm(ts, "-arg1", CMD_SINGLE, CMD_OPTIONAL, "arg1");
197     cmd_AddParm(ts, "-arg2", CMD_SINGLE, CMD_OPTIONAL, "arg2");
198     COMMON_PARMS_DECL(ts);
199
200     err = cmd_Dispatch(argc, argv);
201     exit(err);
202 }
203
204 static int
205 common_prolog(struct cmd_syndesc * as, struct state * state)
206 {
207     register struct cmd_item *ti;
208
209 #ifdef AFS_NT40_ENV
210     if (afs_winsockInit() < 0) {
211         Exit(1);
212     }
213 #endif
214
215     VInitVolumePackage(debugUtility, 1, 1,
216                        DONT_CONNECT_FS, 0);
217     DInit(1);
218
219     if ((ti = as->parms[COMMON_PARMS_OFFSET].items)) {  /* -reason */
220         state->reason = atoi(ti->data);
221     }
222     if ((ti = as->parms[COMMON_PARMS_OFFSET+1].items)) {        /* -programtype */
223         if (!strcmp(ti->data, "fileServer")) {
224             programType = fileServer;
225         } else if (!strcmp(ti->data, "volumeUtility")) {
226             programType = volumeUtility;
227         } else if (!strcmp(ti->data, "salvager")) {
228             programType = salvager;
229         } else if (!strcmp(ti->data, "salvageServer")) {
230             programType = salvageServer;
231         } else {
232             programType = (ProgramType) atoi(ti->data);
233         }
234     }
235
236     VConnectFS();
237
238     return 0;
239 }
240
241 static int
242 common_volop_prolog(struct cmd_syndesc * as, struct state * state)
243 {
244     register struct cmd_item *ti;
245     char pname[100], *temp;
246
247     state->vop = (struct volop_state *) calloc(1, sizeof(struct volop_state));
248     assert(state->vop != NULL);
249
250     if ((ti = as->parms[COMMON_VOLOP_PARMS_OFFSET].items)) {    /* -volumeid */
251         state->vop->volume = atoi(ti->data);
252     } else {
253         fprintf(stderr, "required argument -volumeid not given\n");
254     }
255
256     if ((ti = as->parms[COMMON_VOLOP_PARMS_OFFSET+1].items)) {  /* -partition */
257         strlcpy(state->vop->partName, ti->data, sizeof(state->vop->partName));
258     } else {
259         memset(state->vop->partName, 0, sizeof(state->vop->partName));
260     }
261
262     return 0;
263 }
264
265 static int
266 do_volop(struct state * state, afs_int32 command, SYNC_response * res)
267 {
268     afs_int32 code;
269     SYNC_PROTO_BUF_DECL(res_buf);
270     SYNC_response res_l;
271
272     if (!res) {
273         res = &res_l;
274         res->payload.len = SYNC_PROTO_MAX_LEN;
275         res->payload.buf = res_buf;
276     }
277
278     fprintf(stderr, "calling FSYNC_VolOp with command code %d (%s)\n", 
279             command, command_code_to_string(command));
280
281     code = FSYNC_VolOp(state->vop->volume,
282                        state->vop->partName,
283                        command,
284                        state->reason,
285                        res);
286
287     switch (code) {
288     case SYNC_OK:
289     case SYNC_DENIED:
290         break;
291     default:
292         fprintf(stderr, "possible sync protocol error. return code was %d\n", code);
293     }
294
295     fprintf(stderr, "FSYNC_VolOp returned %d (%s)\n", code, response_code_to_string(code));
296     fprintf(stderr, "protocol response code was %d (%s)\n", 
297             res->hdr.response, response_code_to_string(res->hdr.response));
298     fprintf(stderr, "protocol reason code was %d (%s)\n", 
299             res->hdr.reason, reason_code_to_string(res->hdr.reason));
300
301     VDisconnectFS();
302 }
303
304 static char *
305 response_code_to_string(afs_int32 response)
306 {
307     switch (response) {
308     case SYNC_OK:
309         return "SYNC_OK";
310     case SYNC_DENIED:
311         return "SYNC_DENIED";
312     case SYNC_COM_ERROR:
313         return "SYNC_COM_ERROR";
314     case SYNC_BAD_COMMAND:
315         return "SYNC_BAD_COMMAND";
316     case SYNC_FAILED:
317         return "SYNC_FAILED";
318     default:
319         return "**UNKNOWN**";
320     }
321 }
322
323 static char *
324 command_code_to_string(afs_int32 command)
325 {
326     switch (command) {
327     case SYNC_COM_CHANNEL_CLOSE:
328         return "SYNC_COM_CHANNEL_CLOSE";
329     case FSYNC_VOL_ON:
330         return "FSYNC_VOL_ON";
331     case FSYNC_VOL_OFF:
332         return "FSYNC_VOL_OFF";
333     case FSYNC_VOL_LISTVOLUMES:
334         return "FSYNC_VOL_LISTVOLUMES";
335     case FSYNC_VOL_NEEDVOLUME:
336         return "FSYNC_VOL_NEEDVOLUME";
337     case FSYNC_VOL_MOVE:
338         return "FSYNC_VOL_MOVE";
339     case FSYNC_VOL_BREAKCBKS:
340         return "FSYNC_VOL_BREAKCBKS";
341     case FSYNC_VOL_DONE:
342         return "FSYNC_VOL_DONE";
343     case FSYNC_VOL_QUERY:
344         return "FSYNC_VOL_QUERY";
345     case FSYNC_VOL_QUERY_HDR:
346         return "FSYNC_VOL_QUERY_HDR";
347     case FSYNC_VOL_QUERY_VOP:
348         return "FSYNC_VOL_QUERY_VOP";
349     case FSYNC_VOL_STATS_GENERAL:
350         return "FSYNC_VOL_STATS_GENERAL";
351     case FSYNC_VOL_STATS_VICEP:
352         return "FSYNC_VOL_STATS_VICEP";
353     case FSYNC_VOL_STATS_HASH:
354         return "FSYNC_VOL_STATS_HASH";
355     case FSYNC_VOL_STATS_HDR:
356         return "FSYNC_VOL_STATS_HDR";
357     case FSYNC_VOL_STATS_VLRU:
358         return "FSYNC_VOL_STATS_VLRU";
359     default:
360         return "**UNKNOWN**";
361     }
362 }
363
364 static char *
365 reason_code_to_string(afs_int32 reason)
366 {
367     switch (reason) {
368     case SYNC_REASON_NONE:
369         return "SYNC_REASON_NONE";
370     case SYNC_REASON_MALFORMED_PACKET:
371         return "SYNC_REASON_MALFORMED_PACKET";
372     case FSYNC_WHATEVER:
373         return "FSYNC_WHATEVER";
374     case FSYNC_SALVAGE:
375         return "FSYNC_SALVAGE";
376     case FSYNC_MOVE:
377         return "FSYNC_MOVE";
378     case FSYNC_OPERATOR:
379         return "FSYNC_OPERATOR";
380     case FSYNC_EXCLUSIVE:
381         return "FSYNC_EXCLUSIVE";
382     case FSYNC_UNKNOWN_VOLID:
383         return "FSYNC_UNKNOWN_VOLID";
384     case FSYNC_HDR_NOT_ATTACHED:
385         return "FSYNC_HDR_NOT_ATTACHED";
386     case FSYNC_NO_PENDING_VOL_OP:
387         return "FSYNC_NO_PENDING_VOL_OP";
388     case FSYNC_VOL_PKG_ERROR:
389         return "FSYNC_VOL_PKG_ERROR";
390     default:
391         return "**UNKNOWN**";
392     }
393 }
394
395 static char *
396 program_type_to_string(afs_int32 type)
397 {
398     switch ((ProgramType)type) {
399     case fileServer:
400         return "fileServer";
401     case volumeUtility:
402         return "volumeUtility";
403     case salvager:
404         return "salvager";
405     case salvageServer:
406         return "salvageServer";
407     case debugUtility:
408       return "debugUtility";
409     default:
410         return "**UNKNOWN**";
411     }
412 }
413
414 static int 
415 VolOnline(struct cmd_syndesc * as, void * rock)
416 {
417     struct state state;
418
419     common_prolog(as, &state);
420     common_volop_prolog(as, &state);
421
422     do_volop(&state, FSYNC_VOL_ON, NULL);
423
424     return 0;
425 }
426
427 static int 
428 VolOffline(struct cmd_syndesc * as, void * rock)
429 {
430     struct state state;
431
432     common_prolog(as, &state);
433     common_volop_prolog(as, &state);
434
435     do_volop(&state, FSYNC_VOL_OFF, NULL);
436
437     return 0;
438 }
439
440 static int
441 VolMode(struct cmd_syndesc * as, void * rock)
442 {
443     struct state state;
444
445     common_prolog(as, &state);
446     common_volop_prolog(as, &state);
447
448     do_volop(&state, FSYNC_VOL_NEEDVOLUME, NULL);
449
450     return 0;
451 }
452
453 static int
454 VolDetach(struct cmd_syndesc * as, void * rock)
455 {
456     struct state state;
457
458     common_prolog(as, &state);
459     common_volop_prolog(as, &state);
460
461     do_volop(&state, FSYNC_VOL_DONE, NULL);
462
463     return 0;
464 }
465
466 static int
467 VolBreakCBKs(struct cmd_syndesc * as, void * rock)
468 {
469     struct state state;
470
471     common_prolog(as, &state);
472     common_volop_prolog(as, &state);
473
474     do_volop(&state, FSYNC_VOL_BREAKCBKS, NULL);
475
476     return 0;
477 }
478
479 static int
480 VolMove(struct cmd_syndesc * as, void * rock)
481 {
482     struct state state;
483
484     common_prolog(as, &state);
485     common_volop_prolog(as, &state);
486
487     do_volop(&state, FSYNC_VOL_MOVE, NULL);
488
489     return 0;
490 }
491
492 static int
493 VolList(struct cmd_syndesc * as, void * rock)
494 {
495     struct state state;
496
497     common_prolog(as, &state);
498     common_volop_prolog(as, &state);
499
500     do_volop(&state, FSYNC_VOL_LISTVOLUMES, NULL);
501
502     return 0;
503 }
504
505 #ifdef AFS_DEMAND_ATTACH_FS
506 static char *
507 vol_state_to_string(VolState state)
508 {
509     switch (state) {
510     case VOL_STATE_UNATTACHED:
511         return "VOL_STATE_UNATTACHED";
512     case VOL_STATE_PREATTACHED:
513         return "VOL_STATE_PREATTACHED";
514     case VOL_STATE_ATTACHING:
515         return "VOL_STATE_ATTACHING";
516     case VOL_STATE_ATTACHED:
517         return "VOL_STATE_ATTACHED";
518     case VOL_STATE_UPDATING:
519         return "VOL_STATE_UPDATING";
520     case VOL_STATE_GET_BITMAP:
521         return "VOL_STATE_GET_BITMAP";
522     case VOL_STATE_HDR_LOADING:
523         return "VOL_STATE_HDR_LOADING";
524     case VOL_STATE_HDR_ATTACHING:
525         return "VOL_STATE_HDR_ATTACHING";
526     case VOL_STATE_SHUTTING_DOWN:
527         return "VOL_STATE_SHUTTING_DOWN";
528     case VOL_STATE_GOING_OFFLINE:
529         return "VOL_STATE_GOING_OFFLINE";
530     case VOL_STATE_OFFLINING:
531         return "VOL_STATE_OFFLINING";
532     case VOL_STATE_DETACHING:
533         return "VOL_STATE_DETACHING";
534     case VOL_STATE_SALVSYNC_REQ:
535       return "VOL_STATE_SALVSYNC_REQ";
536     case VOL_STATE_SALVAGING:
537         return "VOL_STATE_SALVAGING";
538     case VOL_STATE_ERROR:
539         return "VOL_STATE_ERROR";
540     case VOL_STATE_FREED:
541         return "VOL_STATE_FREED";
542     default:
543         return "**UNKNOWN**";
544     }
545 }
546
547 static char *
548 vol_flags_to_string(afs_uint16 flags)
549 {
550     static char str[128];
551     int count = 0;
552     str[0]='\0';
553
554     if (flags & VOL_HDR_ATTACHED) {
555         strlcat(str, "VOL_HDR_ATTACHED", sizeof(str));
556         count++;
557     }
558
559     if (flags & VOL_HDR_LOADED) {
560         if (count) {
561             strlcat(str, " | ", sizeof(str));
562         }
563         strlcat(str, "VOL_HDR_LOADED", sizeof(str));
564         count++;
565     }
566
567     if (flags & VOL_HDR_IN_LRU) {
568         if (count) {
569             strlcat(str, " | ", sizeof(str));
570         }
571         strlcat(str, "VOL_HDR_IN_LRU", sizeof(str));
572         count++;
573     }
574
575     if (flags & VOL_IN_HASH) {
576         if (count) {
577             strlcat(str, " | ", sizeof(str));
578         }
579         strlcat(str, "VOL_IN_HASH", sizeof(str));
580         count++;
581     }
582
583     if (flags & VOL_ON_VBYP_LIST) {
584         if (count) {
585             strlcat(str, " | ", sizeof(str));
586         }
587         strlcat(str, "VOL_ON_VBYP_LIST", sizeof(str));
588         count++;
589     }
590
591     if (flags & VOL_IS_BUSY) {
592         if (count) {
593             strlcat(str, " | ", sizeof(str));
594         }
595         strlcat(str, "VOL_IS_BUSY", sizeof(str));
596         count++;
597     }
598
599     if (flags & VOL_ON_VLRU) {
600         if (count) {
601             strlcat(str, " | ", sizeof(str));
602         }
603         strlcat(str, "VOL_ON_VLRU", sizeof(str));
604     }
605
606     if (flags & VOL_HDR_DONTSALV) {
607         if (count) {
608             strlcat(str, " | ", sizeof(str));
609         }
610         strlcat(str, "VOL_HDR_DONTSALV", sizeof(str));
611     }
612
613     return str;
614 }
615
616 static char *
617 vlru_idx_to_string(int idx)
618 {
619     switch (idx) {
620     case VLRU_QUEUE_NEW:
621         return "VLRU_QUEUE_NEW";
622     case VLRU_QUEUE_MID:
623         return "VLRU_QUEUE_MID";
624     case VLRU_QUEUE_OLD:
625         return "VLRU_QUEUE_OLD";
626     case VLRU_QUEUE_CANDIDATE:
627         return "VLRU_QUEUE_CANDIDATE";
628     case VLRU_QUEUE_HELD:
629         return "VLRU_QUEUE_HELD";
630     case VLRU_QUEUE_INVALID:
631         return "VLRU_QUEUE_INVALID";
632     default:
633         return "**UNKNOWN**";
634     }
635 }
636 #endif
637
638 static int
639 VolQuery(struct cmd_syndesc * as, void * rock)
640 {
641     struct state state;
642     SYNC_PROTO_BUF_DECL(res_buf);
643     SYNC_response res;
644     Volume v;
645     int hi, lo;
646
647     res.hdr.response_len = sizeof(res.hdr);
648     res.payload.buf = res_buf;
649     res.payload.len = SYNC_PROTO_MAX_LEN;
650
651     common_prolog(as, &state);
652     common_volop_prolog(as, &state);
653
654     do_volop(&state, FSYNC_VOL_QUERY, &res);
655
656     if (res.hdr.response == SYNC_OK) {
657         memcpy(&v, res.payload.buf, sizeof(Volume));
658
659         printf("volume = {\n");
660         printf("\thashid          = %u\n", v.hashid);
661         printf("\theader          = 0x%x\n", v.header);
662         printf("\tdevice          = %d\n", v.device);
663         printf("\tpartition       = 0x%x\n", v.partition);
664         printf("\tlinkHandle      = 0x%x\n", v.linkHandle);
665         printf("\tnextVnodeUnique = %u\n", v.nextVnodeUnique);
666         printf("\tdiskDataHandle  = 0x%x\n", v.diskDataHandle);
667         printf("\tvnodeHashOffset = %u\n", v.vnodeHashOffset);
668         printf("\tshuttingDown    = %d\n", v.shuttingDown);
669         printf("\tgoingOffline    = %d\n", v.goingOffline);
670         printf("\tcacheCheck      = %u\n", v.cacheCheck);
671         printf("\tnUsers          = %d\n", v.nUsers);
672         printf("\tneedsPutBack    = %d\n", v.needsPutBack);
673         printf("\tspecialStatus   = %d\n", v.specialStatus);
674         printf("\tupdateTime      = %u\n", v.updateTime);
675         
676         printf("\tvnodeIndex[vSmall] = {\n");
677         printf("\t\thandle       = 0x%x\n", v.vnodeIndex[vSmall].handle);
678         printf("\t\tbitmap       = 0x%x\n", v.vnodeIndex[vSmall].bitmap);
679         printf("\t\tbitmapSize   = %u\n", v.vnodeIndex[vSmall].bitmapSize);
680         printf("\t\tbitmapOffset = %u\n", v.vnodeIndex[vSmall].bitmapOffset);
681         printf("\t}\n");
682         printf("\tvnodeIndex[vLarge] = {\n");
683         printf("\t\thandle       = 0x%x\n", v.vnodeIndex[vLarge].handle);
684         printf("\t\tbitmap       = 0x%x\n", v.vnodeIndex[vLarge].bitmap);
685         printf("\t\tbitmapSize   = %u\n", v.vnodeIndex[vLarge].bitmapSize);
686         printf("\t\tbitmapOffset = %u\n", v.vnodeIndex[vLarge].bitmapOffset);
687         printf("\t}\n");
688 #ifdef AFS_DEMAND_ATTACH_FS
689         if (res.hdr.flags & SYNC_FLAG_DAFS_EXTENSIONS) {
690             printf("\tupdateTime      = %u\n", v.updateTime);
691             printf("\tattach_state    = %s\n", vol_state_to_string(v.attach_state));
692             printf("\tattach_flags    = %s\n", vol_flags_to_string(v.attach_flags));
693             printf("\tnWaiters        = %d\n", v.nWaiters);
694             printf("\tchainCacheCheck = %d\n", v.chainCacheCheck);
695             
696             /* online salvage structure */
697             printf("\tsalvage = {\n");
698             printf("\t\tprio      = %u\n", v.salvage.prio);
699             printf("\t\treason    = %d\n", v.salvage.reason);
700             printf("\t\trequested = %d\n", v.salvage.requested);
701             printf("\t\tscheduled = %d\n", v.salvage.scheduled);
702             printf("\t}\n");
703             
704             /* statistics structure */
705             printf("\tstats = {\n");
706
707             printf("\t\thash_lookups = {\n");
708             SplitInt64(v.stats.hash_lookups,hi,lo);
709             printf("\t\t\thi = %u\n", hi);
710             printf("\t\t\tlo = %u\n", lo);
711             printf("\t\t}\n");
712
713             printf("\t\thash_short_circuits = {\n");
714             SplitInt64(v.stats.hash_short_circuits,hi,lo);
715             printf("\t\t\thi = %u\n", hi);
716             printf("\t\t\tlo = %u\n", lo);
717             printf("\t\t}\n");
718
719             printf("\t\thdr_loads = {\n");
720             SplitInt64(v.stats.hdr_loads,hi,lo);
721             printf("\t\t\thi = %u\n", hi);
722             printf("\t\t\tlo = %u\n", lo);
723             printf("\t\t}\n");
724
725             printf("\t\thdr_gets = {\n");
726             SplitInt64(v.stats.hdr_gets,hi,lo);
727             printf("\t\t\thi = %u\n", hi);
728             printf("\t\t\tlo = %u\n", lo);
729             printf("\t\t}\n");
730             
731             printf("\t\tattaches         = %u\n", v.stats.attaches);
732             printf("\t\tsoft_detaches    = %u\n", v.stats.soft_detaches);
733             printf("\t\tsalvages         = %u\n", v.stats.salvages);
734             printf("\t\tvol_ops          = %u\n", v.stats.vol_ops);
735             
736             printf("\t\tlast_attach      = %u\n", v.stats.last_attach);
737             printf("\t\tlast_get         = %u\n", v.stats.last_get);
738             printf("\t\tlast_promote     = %u\n", v.stats.last_promote);
739             printf("\t\tlast_hdr_get     = %u\n", v.stats.last_hdr_get);
740             printf("\t\tlast_salvage     = %u\n", v.stats.last_salvage);
741             printf("\t\tlast_salvage_req = %u\n", v.stats.last_salvage_req);
742             printf("\t\tlast_vol_op      = %u\n", v.stats.last_vol_op);
743             printf("\t}\n");
744             
745             /* VLRU state */
746             printf("\tvlru = {\n");
747             printf("\t\tidx = %d (%s)\n", 
748                    v.vlru.idx, vlru_idx_to_string(v.vlru.idx));
749             printf("\t}\n");
750
751             /* volume op state */
752             printf("\tpending_vol_op  = 0x%x\n", v.pending_vol_op);
753         }
754 #else /* !AFS_DEMAND_ATTACH_FS */
755         if (res.hdr.flags & SYNC_FLAG_DAFS_EXTENSIONS) {
756             printf("*** server asserted demand attach extensions. fssync-debug not built to\n");
757             printf("*** recognize those extensions. please recompile fssync-debug if you need\n");
758             printf("*** to dump dafs extended state\n");
759         }
760 #endif /* !AFS_DEMAND_ATTACH_FS */
761         printf("}\n");
762     }
763
764     return 0;
765 }
766
767 static int
768 VolHdrQuery(struct cmd_syndesc * as, void * rock)
769 {
770     struct state state;
771     SYNC_PROTO_BUF_DECL(res_buf);
772     SYNC_response res;
773     VolumeDiskData v;
774     int i;
775
776     res.hdr.response_len = sizeof(res.hdr);
777     res.payload.buf = res_buf;
778     res.payload.len = SYNC_PROTO_MAX_LEN;
779
780     common_prolog(as, &state);
781     common_volop_prolog(as, &state);
782
783     do_volop(&state, FSYNC_VOL_QUERY_HDR, &res);
784
785     if (res.hdr.response == SYNC_OK) {
786         memcpy(&v, res.payload.buf, sizeof(VolumeDiskData));
787
788         printf("VolumeDiskData = {\n");
789         printf("\tstamp = {\n");
790         printf("\t\tmagic   = 0x%x\n", v.stamp.magic);
791         printf("\t\tversion = %u\n", v.stamp.version);
792         printf("\t}\n");
793         
794         printf("\tid               = %u\n", v.id);
795         printf("\tname             = '%s'\n", v.name);
796         printf("\tinUse            = %d\n", v.inUse);
797         printf("\tinService        = %d\n", v.inService);
798         printf("\tblessed          = %d\n", v.blessed);
799         printf("\tneedsSalvaged    = %d\n", v.needsSalvaged);
800         printf("\tuniquifier       = %u\n", v.uniquifier);
801         printf("\ttype             = %d\n", v.type);
802         printf("\tparentId         = %u\n", v.parentId);
803         printf("\tcloneId          = %u\n", v.cloneId);
804         printf("\tbackupId         = %u\n", v.backupId);
805         printf("\trestoredFromId   = %u\n", v.restoredFromId);
806         printf("\tneedsCallback    = %d\n", v.needsCallback);
807         printf("\tdestroyMe        = %d\n", v.destroyMe);
808         printf("\tdontSalvage      = %d\n", v.dontSalvage);
809         printf("\tmaxquota         = %d\n", v.maxquota);
810         printf("\tminquota         = %d\n", v.minquota);
811         printf("\tmaxfiles         = %d\n", v.maxfiles);
812         printf("\taccountNumber    = %u\n", v.accountNumber);
813         printf("\towner            = %u\n", v.owner);
814         printf("\tfilecount        = %d\n", v.filecount);
815         printf("\tdiskused         = %d\n", v.diskused);
816         printf("\tdayUse           = %d\n", v.dayUse);
817         for (i = 0; i < 7; i++) {
818             printf("\tweekUse[%d]       = %d\n", i, v.weekUse[i]);
819         }
820         printf("\tdayUseDate       = %u\n", v.dayUseDate);
821         printf("\tcreationDate     = %u\n", v.creationDate);
822         printf("\taccessDate       = %u\n", v.accessDate);
823         printf("\tupdateDate       = %u\n", v.updateDate);
824         printf("\texpirationDate   = %u\n", v.expirationDate);
825         printf("\tbackupDate       = %u\n", v.backupDate);
826         printf("\tcopyDate         = %u\n", v.copyDate);
827 #ifdef OPENAFS_VOL_STATS
828         printf("\tstat_initialized = %d\n", v.stat_initialized);
829 #else
830         printf("\tmtd              = '%s'\n", v.motd);
831 #endif
832         printf("}\n");
833     }
834
835     return 0;
836 }
837
838 static int
839 VolOpQuery(struct cmd_syndesc * as, void * rock)
840 {
841     struct state state;
842     SYNC_PROTO_BUF_DECL(res_buf);
843     SYNC_response res;
844     FSSYNC_VolOp_info vop;
845     int i;
846
847     res.hdr.response_len = sizeof(res.hdr);
848     res.payload.buf = res_buf;
849     res.payload.len = SYNC_PROTO_MAX_LEN;
850
851     common_prolog(as, &state);
852     common_volop_prolog(as, &state);
853
854     do_volop(&state, FSYNC_VOL_QUERY_VOP, &res);
855
856     if (!(res.hdr.flags & SYNC_FLAG_DAFS_EXTENSIONS)) {
857         printf("*** file server not compiled with demand attach extensions.\n");
858         printf("*** pending volume operation metadata not available.\n");
859     }
860
861     if (res.hdr.response == SYNC_OK) {
862         memcpy(&vop, res.payload.buf, sizeof(FSSYNC_VolOp_info));
863
864         printf("pending_vol_op = {\n");
865
866         printf("\tcom = {\n");
867         printf("\t\tproto_version  = %u\n", vop.com.proto_version);
868         printf("\t\tprogramType    = %d (%s)\n", 
869                vop.com.programType, program_type_to_string(vop.com.programType));
870         printf("\t\tcommand        = %d (%s)\n", 
871                vop.com.command, command_code_to_string(vop.com.command));
872         printf("\t\treason         = %d (%s)\n", 
873                vop.com.reason, reason_code_to_string(vop.com.reason));
874         printf("\t\tcommand_len    = %u\n", vop.com.command_len);
875         printf("\t\tflags          = 0x%x\n", vop.com.flags);
876         printf("\t}\n");
877
878         printf("\tvop = {\n");
879         printf("\t\tvolume         = %u\n", vop.vop.volume);
880         if (afs_strnlen(vop.vop.partName, sizeof(vop.vop.partName)) <
881             sizeof(vop.vop.partName)) {
882             printf("\t\tpartName       = '%s'\n", vop.vop.partName);
883         } else {
884             printf("\t\tpartName       = (illegal string)\n");
885         }
886         printf("\t}\n");
887
888         printf("}\n");
889     }
890
891     return 0;
892 }
893
894 static int
895 StatsQuery(struct cmd_syndesc * as, void * rock)
896 {
897     afs_int32 code;
898     int command;
899     struct cmd_item *ti;
900     struct state state;
901     SYNC_PROTO_BUF_DECL(res_buf);
902     SYNC_response res;
903     FSSYNC_StatsOp_hdr scom;
904     union {
905         void * ptr;
906         struct VolPkgStats * vol_stats;
907         struct VolumeHashChainStats * hash_stats;
908 #ifdef AFS_DEMAND_ATTACH_FS
909         struct volume_hdr_LRU_stats * hdr_stats;
910 #endif
911         struct DiskPartitionStats * vicep_stats;
912     } sres;
913
914     sres.ptr = res_buf;
915     res.hdr.response_len = sizeof(res.hdr);
916     res.payload.buf = res_buf;
917     res.payload.len = SYNC_PROTO_MAX_LEN;
918
919     if ((ti = as->parms[CUSTOM_PARMS_OFFSET].items)) {  /* -subcommand */
920         if (!strcasecmp(ti->data, "vicep")) {
921             command = FSYNC_VOL_STATS_VICEP;
922         } else if (!strcasecmp(ti->data, "hash")) {
923             command = FSYNC_VOL_STATS_HASH;
924 #ifdef AFS_DEMAND_ATTACH_FS
925         } else if (!strcasecmp(ti->data, "hdr")) {
926             command = FSYNC_VOL_STATS_HDR;
927         } else if (!strcasecmp(ti->data, "vlru")) {
928             command = FSYNC_VOL_STATS_VLRU;
929 #endif
930         } else if (!strcasecmp(ti->data, "pkg")) {
931             command = FSYNC_VOL_STATS_GENERAL;
932         } else if (!strcasecmp(ti->data, "help")) {
933             fprintf(stderr, "fssync-debug stats subcommands:\n");
934             fprintf(stderr, "\tpkg\tgeneral volume package stats\n");
935             fprintf(stderr, "\tvicep\tvice partition stats\n");
936             fprintf(stderr, "\thash\tvolume hash chain stats\n");
937 #ifdef AFS_DEMAND_ATTACH_FS
938             fprintf(stderr, "\thdr\tvolume header cache stats\n");
939             fprintf(stderr, "\tvlru\tvlru generation stats\n");
940 #endif
941             exit(0);
942         } else {
943             fprintf(stderr, "invalid stats subcommand");
944             exit(1);
945         }
946     } else {
947         command = FSYNC_VOL_STATS_GENERAL;
948     }
949
950     if ((ti = as->parms[CUSTOM_PARMS_OFFSET+1].items)) {        /* -arg1 */
951         switch (command) {
952         case FSYNC_VOL_STATS_VICEP:
953             strlcpy(scom.args.partName, ti->data, sizeof(state.vop->partName));
954             break;
955         case FSYNC_VOL_STATS_HASH:
956             scom.args.hash_bucket = atoi(ti->data);
957             break;
958         case FSYNC_VOL_STATS_VLRU:
959             scom.args.vlru_generation = atoi(ti->data);
960             break;
961         default:
962             fprintf(stderr, "unrecognized arguments\n");
963             exit(1);
964         }
965     } else {
966         switch (command) {
967         case FSYNC_VOL_STATS_VICEP:
968         case FSYNC_VOL_STATS_HASH:
969         case FSYNC_VOL_STATS_VLRU:
970             fprintf(stderr, "this subcommand requires more parameters\n");
971             exit(1);
972         }
973     }
974
975     common_prolog(as, &state);
976
977     fprintf(stderr, "calling FSYNC_askfs with command code %d (%s)\n", 
978             command, command_code_to_string(command));
979
980     code = FSYNC_StatsOp(&scom, command, FSYNC_WHATEVER, &res);
981
982     switch (code) {
983     case SYNC_OK:
984     case SYNC_DENIED:
985         break;
986     default:
987         fprintf(stderr, "possible sync protocol error. return code was %d\n", code);
988     }
989
990     fprintf(stderr, "FSYNC_VolOp returned %d (%s)\n", code, response_code_to_string(code));
991     fprintf(stderr, "protocol response code was %d (%s)\n", 
992             res.hdr.response, response_code_to_string(res.hdr.response));
993     fprintf(stderr, "protocol reason code was %d (%s)\n", 
994             res.hdr.reason, reason_code_to_string(res.hdr.reason));
995
996     VDisconnectFS();
997
998     if (res.hdr.response == SYNC_OK) {
999         switch (command) {
1000         case FSYNC_VOL_STATS_GENERAL:
1001             print_vol_stats_general(sres.vol_stats);
1002             break;
1003         case FSYNC_VOL_STATS_VICEP:
1004             print_vol_stats_viceP(sres.vicep_stats);
1005             break;
1006         case FSYNC_VOL_STATS_HASH:
1007             print_vol_stats_hash(sres.hash_stats);
1008             break;
1009 #ifdef AFS_DEMAND_ATTACH_FS
1010         case FSYNC_VOL_STATS_HDR:
1011             print_vol_stats_hdr(sres.hdr_stats);
1012             break;
1013 #endif /* AFS_DEMAND_ATTACH_FS */
1014         }
1015     }
1016
1017     return 0;
1018 }
1019
1020 static void
1021 print_vol_stats_general(VolPkgStats * stats)
1022 {
1023     int i;
1024     afs_uint32 hi, lo;
1025
1026     printf("VolPkgStats = {\n");
1027 #ifdef AFS_DEMAND_ATTACH_FS
1028     for (i = 0; i < VOL_STATE_COUNT; i++) {
1029         printf("\tvol_state_count[%s] = %d\n", 
1030                vol_state_to_string(i),
1031                stats->state_levels[i]);
1032     }
1033
1034     SplitInt64(stats->hash_looks, hi, lo);
1035     printf("\thash_looks = {\n");
1036     printf("\t\thi = %u\n", hi);
1037     printf("\t\tlo = %u\n", lo);
1038     printf("\t}\n");
1039
1040     SplitInt64(stats->hash_reorders, hi, lo);
1041     printf("\thash_reorders = {\n");
1042     printf("\t\thi = %u\n", hi);
1043     printf("\t\tlo = %u\n", lo);
1044     printf("\t}\n");
1045
1046     SplitInt64(stats->salvages, hi, lo);
1047     printf("\tsalvages = {\n");
1048     printf("\t\thi = %u\n", hi);
1049     printf("\t\tlo = %u\n", lo);
1050     printf("\t}\n");
1051
1052     SplitInt64(stats->vol_ops, hi, lo);
1053     printf("\tvol_ops = {\n");
1054     printf("\t\thi = %u\n", hi);
1055     printf("\t\tlo = %u\n", lo);
1056     printf("\t}\n");
1057 #endif
1058     SplitInt64(stats->hdr_loads, hi, lo);
1059     printf("\thdr_loads = {\n");
1060     printf("\t\thi = %u\n", hi);
1061     printf("\t\tlo = %u\n", lo);
1062     printf("\t}\n");
1063
1064     SplitInt64(stats->hdr_gets, hi, lo);
1065     printf("\thdr_gets = {\n");
1066     printf("\t\thi = %u\n", hi);
1067     printf("\t\tlo = %u\n", lo);
1068     printf("\t}\n");
1069
1070     SplitInt64(stats->attaches, hi, lo);
1071     printf("\tattaches = {\n");
1072     printf("\t\thi = %u\n", hi);
1073     printf("\t\tlo = %u\n", lo);
1074     printf("\t}\n");
1075
1076     SplitInt64(stats->soft_detaches, hi, lo);
1077     printf("\tsoft_detaches = {\n");
1078     printf("\t\thi = %u\n", hi);
1079     printf("\t\tlo = %u\n", lo);
1080     printf("\t}\n");
1081
1082     printf("\thdr_cache_size = %d\n", stats->hdr_cache_size);
1083             
1084     printf("}\n");
1085 }
1086
1087 static void
1088 print_vol_stats_viceP(struct DiskPartitionStats * stats)
1089 {
1090     printf("DiskPartitionStats = {\n");
1091     printf("\tfree = %d\n", stats->free);
1092     printf("\tminFree = %d\n", stats->minFree);
1093     printf("\ttotalUsable = %d\n", stats->totalUsable);
1094     printf("\tf_files = %d\n", stats->f_files);
1095 #ifdef AFS_DEMAND_ATTACH_FS
1096     printf("\tvol_list_len = %d\n", stats->vol_list_len);
1097 #endif
1098     printf("}\n");
1099 }
1100
1101 static void
1102 print_vol_stats_hash(struct VolumeHashChainStats * stats)
1103 {
1104     afs_uint32 hi, lo;
1105
1106     printf("DiskPartitionStats = {\n");
1107     printf("\ttable_size = %d\n", stats->table_size);
1108     printf("\tchain_len = %d\n", stats->chain_len);
1109
1110 #ifdef AFS_DEMAND_ATTACH_FS
1111     printf("\tchain_cacheCheck = %d\n", stats->chain_cacheCheck);
1112     printf("\tchain_busy = %d\n", stats->chain_busy);
1113
1114     SplitInt64(stats->chain_looks, hi, lo);
1115     printf("\tchain_looks = {\n");
1116     printf("\t\thi = %u\n", hi);
1117     printf("\t\tlo = %u\n", lo);
1118     printf("\t}\n");
1119
1120     SplitInt64(stats->chain_gets, hi, lo);
1121     printf("\tchain_gets = {\n");
1122     printf("\t\thi = %u\n", hi);
1123     printf("\t\tlo = %u\n", lo);
1124     printf("\t}\n");
1125
1126     SplitInt64(stats->chain_reorders, hi, lo);
1127     printf("\tchain_reorders = {\n");
1128     printf("\t\thi = %u\n", hi);
1129     printf("\t\tlo = %u\n", lo);
1130     printf("\t}\n");
1131 #endif /* AFS_DEMAND_ATTACH_FS */
1132
1133     printf("}\n");
1134 }
1135
1136
1137 #ifdef AFS_DEMAND_ATTACH_FS
1138 static void
1139 print_vol_stats_hdr(struct volume_hdr_LRU_stats * stats)
1140 {
1141     printf("volume_hdr_LRU_stats = {\n");
1142     printf("\tfree = %d\n", stats->free);
1143     printf("\tused = %d\n", stats->used);
1144     printf("\tattached = %d\n", stats->attached);
1145     printf("}\n");
1146 }
1147 #endif /* AFS_DEMAND_ATTACH_FS */
1148