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