Give a default reason in *sync-debug
[openafs.git] / src / tsalvaged / salvsync-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  * salvsync debug tool
15  */
16
17
18 #include <afsconfig.h>
19 #include <afs/param.h>
20
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <dirent.h>
25 #include <sys/stat.h>
26 #include <time.h>
27 #include <errno.h>
28 #ifdef AFS_NT40_ENV
29 #include <io.h>
30 #include <WINNT/afsevent.h>
31 #else
32 #include <sys/param.h>
33 #include <sys/file.h>
34 #ifndef ITIMER_REAL
35 #include <sys/time.h>
36 #endif /* ITIMER_REAL */
37 #endif
38
39 #include <roken.h>
40
41 #include <rx/xdr.h>
42 #include <afs/afsint.h>
43 #include <afs/afs_assert.h>
44 #include <afs/dir.h>
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 <afs/nfs.h>
57 #include <lwp.h>
58 #include <lock.h>
59 #include <afs/ihandle.h>
60 #include <afs/vnode.h>
61 #include <afs/volume.h>
62 #include <afs/partition.h>
63 #include <afs/daemon_com.h>
64 #include <afs/salvsync.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 #ifndef AFS_DEMAND_ATTACH_FS
73 int
74 main(int argc, char ** argv)
75 {
76     fprintf(stderr, "*** salvsync-debug is only supported for OpenAFS builds with the demand-attach fileserver extension\n");
77     return -1;
78 }
79 #else /* AFS_DEMAND_ATTACH_FS */
80
81 struct salv_state {
82     afs_uint32 prio;
83     afs_uint32 volume;
84     char partName[16];
85 };
86
87 struct state {
88     afs_int32 reason;
89     struct salv_state * sop;
90 };
91
92 static int common_prolog(struct cmd_syndesc *, struct state *);
93 static int common_salv_prolog(struct cmd_syndesc *, struct state *);
94
95 static int do_salvop(struct state *, afs_int32 command, SYNC_response * res);
96
97 static char * response_code_to_string(afs_int32);
98 static char * command_code_to_string(afs_int32);
99 static char * reason_code_to_string(afs_int32);
100 static char * state_code_to_string(afs_int32);
101
102
103 static int OpStats(struct cmd_syndesc * as, void * rock);
104 static int OpSalvage(struct cmd_syndesc * as, void * rock);
105 static int OpCancel(struct cmd_syndesc * as, void * rock);
106 static int OpCancelAll(struct cmd_syndesc * as, void * rock);
107 static int OpRaisePrio(struct cmd_syndesc * as, void * rock);
108 static int OpQuery(struct cmd_syndesc * as, void * rock);
109
110
111 #ifndef AFS_NT40_ENV
112 #include "AFS_component_version_number.c"
113 #endif
114 #define MAX_ARGS 128
115
116 #define COMMON_PARMS_OFFSET    13
117 #define COMMON_PARMS(ts) \
118     cmd_Seek(ts, COMMON_PARMS_OFFSET); \
119     cmd_AddParm(ts, "-reason", CMD_SINGLE, CMD_OPTIONAL, "sync protocol reason code"); \
120     cmd_AddParm(ts, "-programtype", CMD_SINGLE, CMD_OPTIONAL, "program type code")
121
122 #define COMMON_SALV_PARMS_OFFSET    10
123 #define COMMON_SALV_PARMS(ts) \
124     cmd_Seek(ts, COMMON_SALV_PARMS_OFFSET); \
125     cmd_AddParm(ts, "-volumeid", CMD_SINGLE, 0, "volume id"); \
126     cmd_AddParm(ts, "-partition", CMD_SINGLE, CMD_OPTIONAL, "partition name"); \
127     cmd_AddParm(ts, "-priority", CMD_SINGLE, CMD_OPTIONAL, "priority")
128
129 #define SALV_PARMS_DECL(ts) \
130     COMMON_SALV_PARMS(ts); \
131     COMMON_PARMS(ts)
132
133 #define COMMON_PARMS_DECL(ts) \
134     COMMON_PARMS(ts)
135
136 int
137 main(int argc, char **argv)
138 {
139     struct cmd_syndesc *ts;
140     int err = 0;
141
142     /* Initialize directory paths */
143     if (!(initAFSDirPath() & AFSDIR_SERVER_PATHS_OK)) {
144 #ifdef AFS_NT40_ENV
145         ReportErrorEventAlt(AFSEVT_SVR_NO_INSTALL_DIR, 0, argv[0], 0);
146 #endif
147         fprintf(stderr, "%s: Unable to obtain AFS server directory.\n",
148                 argv[0]);
149         exit(2);
150     }
151
152
153     ts = cmd_CreateSyntax("stats", OpStats, NULL, "get salvageserver statistics (SALVSYNC_NOP opcode)");
154     COMMON_PARMS_DECL(ts);
155     cmd_CreateAlias(ts, "nop");
156
157     ts = cmd_CreateSyntax("salvage", OpSalvage, NULL, "schedule a salvage (SALVSYNC_SALVAGE opcode)");
158     SALV_PARMS_DECL(ts);
159
160     ts = cmd_CreateSyntax("cancel", OpCancel, NULL, "cancel a salvage (SALVSYNC_CANCEL opcode)");
161     SALV_PARMS_DECL(ts);
162
163     ts = cmd_CreateSyntax("raiseprio", OpRaisePrio, NULL, "raise a salvage priority (SALVSYNC_RAISEPRIO opcode)");
164     SALV_PARMS_DECL(ts);
165     cmd_CreateAlias(ts, "rp");
166
167     ts = cmd_CreateSyntax("query", OpQuery, NULL, "query salvage status (SALVSYNC_QUERY opcode)");
168     SALV_PARMS_DECL(ts);
169     cmd_CreateAlias(ts, "qry");
170
171     ts = cmd_CreateSyntax("kill", OpCancelAll, NULL, "cancel all scheduled salvages (SALVSYNC_CANCELALL opcode)");
172     COMMON_PARMS_DECL(ts);
173
174     err = cmd_Dispatch(argc, argv);
175     exit(err);
176 }
177
178 static int
179 common_prolog(struct cmd_syndesc * as, struct state * state)
180 {
181     struct cmd_item *ti;
182     VolumePackageOptions opts;
183
184 #ifdef AFS_NT40_ENV
185     if (afs_winsockInit() < 0) {
186         Exit(1);
187     }
188 #endif
189
190     VOptDefaults(debugUtility, &opts);
191     if (VInitVolumePackage2(debugUtility, &opts)) {
192         /* VInitVolumePackage2 can fail on e.g. partition attachment errors,
193          * but we don't really care, since all we're doing is trying to use
194          * SALVSYNC */
195         fprintf(stderr, "errors encountered initializing volume package, but "
196                         "trying to continue anyway\n");
197     }
198     DInit(1);
199
200     if ((ti = as->parms[COMMON_PARMS_OFFSET].items)) {  /* -reason */
201         state->reason = atoi(ti->data);
202     } else {
203         state->reason = SALVSYNC_REASON_WHATEVER;
204     }
205
206     if ((ti = as->parms[COMMON_PARMS_OFFSET+1].items)) {        /* -programtype */
207         if (!strcmp(ti->data, "fileServer")) {
208             programType = fileServer;
209         } else if (!strcmp(ti->data, "volumeUtility")) {
210             programType = volumeUtility;
211         } else if (!strcmp(ti->data, "salvager")) {
212             programType = salvager;
213         } else if (!strcmp(ti->data, "salvageServer")) {
214             programType = salvageServer;
215         } else if (!strcmp(ti->data, "volumeServer")) {
216             programType = volumeServer;
217         } else if (!strcmp(ti->data, "volumeSalvager")) {
218             programType = volumeSalvager;
219         } else {
220             programType = (ProgramType) atoi(ti->data);
221         }
222     }
223
224     VConnectSALV();
225
226     return 0;
227 }
228
229 static int
230 common_salv_prolog(struct cmd_syndesc * as, struct state * state)
231 {
232     struct cmd_item *ti;
233
234     state->sop = (struct salv_state *) calloc(1, sizeof(struct salv_state));
235     assert(state->sop != NULL);
236
237     if ((ti = as->parms[COMMON_SALV_PARMS_OFFSET].items)) {     /* -volumeid */
238         state->sop->volume = atoi(ti->data);
239     } else {
240         fprintf(stderr, "required argument -volumeid not given\n");
241     }
242
243     if ((ti = as->parms[COMMON_SALV_PARMS_OFFSET+1].items)) {   /* -partition */
244         strlcpy(state->sop->partName, ti->data, sizeof(state->sop->partName));
245     } else {
246         memset(state->sop->partName, 0, sizeof(state->sop->partName));
247     }
248
249     if ((ti = as->parms[COMMON_SALV_PARMS_OFFSET+2].items)) {   /* -prio */
250         state->sop->prio = atoi(ti->data);
251     } else {
252         state->sop->prio = 0;
253     }
254
255     return 0;
256 }
257
258 static int
259 do_salvop(struct state * state, afs_int32 command, SYNC_response * res)
260 {
261     afs_int32 code;
262     SALVSYNC_response_hdr hdr_l, *hdr;
263     SYNC_response res_l;
264
265     if (!res) {
266         res = &res_l;
267         res->payload.len = sizeof(hdr_l);
268         res->payload.buf = hdr = &hdr_l;
269     } else {
270         hdr = (SALVSYNC_response_hdr *) res->payload.buf;
271     }
272
273     fprintf(stderr, "calling SALVSYNC_SalvageVolume with command code %d (%s)\n",
274             command, command_code_to_string(command));
275
276     code = SALVSYNC_SalvageVolume(state->sop->volume,
277                                   state->sop->partName,
278                                   command,
279                                   state->reason,
280                                   state->sop->prio,
281                                   res);
282
283     switch (code) {
284     case SYNC_OK:
285     case SYNC_DENIED:
286         break;
287     default:
288         fprintf(stderr, "possible sync protocol error. return code was %d\n", code);
289     }
290
291     fprintf(stderr, "SALVSYNC_SalvageVolume returned %d (%s)\n", code, response_code_to_string(code));
292     fprintf(stderr, "protocol response code was %d (%s)\n",
293             res->hdr.response, response_code_to_string(res->hdr.response));
294     fprintf(stderr, "protocol reason code was %d (%s)\n",
295             res->hdr.reason, reason_code_to_string(res->hdr.reason));
296
297     printf("state = {\n");
298     if (res->hdr.flags & SALVSYNC_FLAG_VOL_STATS_VALID) {
299         printf("\tstate = %d (%s)\n",
300                hdr->state, state_code_to_string(hdr->state));
301         printf("\tprio = %d\n", hdr->prio);
302     }
303     printf("\tsq_len = %d\n", hdr->sq_len);
304     printf("\tpq_len = %d\n", hdr->pq_len);
305     printf("}\n");
306
307     VDisconnectSALV();
308
309     return 0;
310 }
311
312 static char *
313 response_code_to_string(afs_int32 response)
314 {
315     switch (response) {
316     case SYNC_OK:
317         return "SYNC_OK";
318     case SYNC_DENIED:
319         return "SYNC_DENIED";
320     case SYNC_COM_ERROR:
321         return "SYNC_COM_ERROR";
322     case SYNC_BAD_COMMAND:
323         return "SYNC_BAD_COMMAND";
324     case SYNC_FAILED:
325         return "SYNC_FAILED";
326     default:
327         return "**UNKNOWN**";
328     }
329 }
330
331 static char *
332 command_code_to_string(afs_int32 command)
333 {
334     switch (command) {
335     case SYNC_COM_CHANNEL_CLOSE:
336         return "SYNC_COM_CHANNEL_CLOSE";
337     case SALVSYNC_NOP:
338         return "SALVSYNC_NOP";
339     case SALVSYNC_SALVAGE:
340         return "SALVSYNC_SALVAGE";
341     case SALVSYNC_CANCEL:
342         return "SALVSYNC_CANCEL";
343     case SALVSYNC_RAISEPRIO:
344         return "SALVSYNC_RAISEPRIO";
345     case SALVSYNC_QUERY:
346         return "SALVSYNC_QUERY";
347     case SALVSYNC_CANCELALL:
348         return "SALVSYNC_CANCELLALL";
349     default:
350         return "**UNKNOWN**";
351     }
352 }
353
354 static char *
355 reason_code_to_string(afs_int32 reason)
356 {
357     switch (reason) {
358     case SALVSYNC_WHATEVER:
359         return "SALVSYNC_WHATEVER";
360     case SALVSYNC_ERROR:
361         return "SALVSYNC_ERROR";
362     case SALVSYNC_OPERATOR:
363         return "SALVSYNC_OPERATOR";
364     case SALVSYNC_SHUTDOWN:
365         return "SALVSYNC_SHUTDOWN";
366     case SALVSYNC_NEEDED:
367         return "SALVSYNC_NEEDED";
368     default:
369         return "**UNKNOWN**";
370     }
371 }
372
373 #if 0
374 static char *
375 program_type_to_string(afs_int32 type)
376 {
377     switch ((ProgramType)type) {
378     case fileServer:
379         return "fileServer";
380     case volumeUtility:
381         return "volumeUtility";
382     case salvager:
383         return "salvager";
384     case salvageServer:
385         return "salvageServer";
386     default:
387         return "**UNKNOWN**";
388     }
389 }
390 #endif
391
392 static char *
393 state_code_to_string(afs_int32 state)
394 {
395     switch (state) {
396     case SALVSYNC_STATE_UNKNOWN:
397         return "SALVSYNC_STATE_UNKNOWN";
398     case SALVSYNC_STATE_QUEUED:
399         return "SALVSYNC_STATE_QUEUED";
400     case SALVSYNC_STATE_SALVAGING:
401         return "SALVSYNC_STATE_SALVAGING";
402     case SALVSYNC_STATE_ERROR:
403         return "SALVSYNC_STATE_ERROR";
404     case SALVSYNC_STATE_DONE:
405         return "SALVSYNC_STATE_DONE";
406     default:
407         return "**UNKNOWN**";
408     }
409 }
410
411 static int
412 OpStats(struct cmd_syndesc * as, void * rock)
413 {
414     struct state state;
415
416     common_prolog(as, &state);
417     common_salv_prolog(as, &state);
418
419     do_salvop(&state, SALVSYNC_NOP, NULL);
420
421     return 0;
422 }
423
424 static int
425 OpSalvage(struct cmd_syndesc * as, void * rock)
426 {
427     struct state state;
428
429     common_prolog(as, &state);
430     common_salv_prolog(as, &state);
431
432     do_salvop(&state, SALVSYNC_SALVAGE, NULL);
433
434     return 0;
435 }
436
437 static int
438 OpCancel(struct cmd_syndesc * as, void * rock)
439 {
440     struct state state;
441
442     common_prolog(as, &state);
443     common_salv_prolog(as, &state);
444
445     do_salvop(&state, SALVSYNC_CANCEL, NULL);
446
447     return 0;
448 }
449
450 static int
451 OpCancelAll(struct cmd_syndesc * as, void * rock)
452 {
453     struct state state;
454
455     common_prolog(as, &state);
456     common_salv_prolog(as, &state);
457
458     do_salvop(&state, SALVSYNC_CANCELALL, NULL);
459
460     return 0;
461 }
462
463 static int
464 OpRaisePrio(struct cmd_syndesc * as, void * rock)
465 {
466     struct state state;
467
468     common_prolog(as, &state);
469     common_salv_prolog(as, &state);
470
471     do_salvop(&state, SALVSYNC_RAISEPRIO, NULL);
472
473     return 0;
474 }
475
476 static int
477 OpQuery(struct cmd_syndesc * as, void * rock)
478 {
479     struct state state;
480
481     common_prolog(as, &state);
482     common_salv_prolog(as, &state);
483
484     do_salvop(&state, SALVSYNC_QUERY, NULL);
485
486     return 0;
487 }
488
489 #endif /* AFS_DEMAND_ATTACH_FS */