Some doc path fixes from Anders
[pkg-k5-afs_openafs.git] / src / bucoord / dump.c
blob5d1f58aa3aa22428b8f68e00c373cea8d9ee0259
1 /*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
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 */
11 * ALL RIGHTS RESERVED
14 #include <afsconfig.h>
15 #include <afs/param.h>
17 #include <roken.h>
19 #include <afs/cmd.h>
20 #include <lwp.h>
21 #include <rx/rx.h>
22 #include <afs/bubasics.h>
23 #include <afs/butc.h>
24 #include <afs/com_err.h>
25 #include <lock.h> /* for checking TC_ABORTFAILED. PA */
26 #include <afs/tcdata.h> /* for checking TC_ABORTFAILED. PA */
27 #include <afs/butc.h>
29 #include "bc.h"
30 #include "error_macros.h"
31 #include "bucoord_internal.h"
32 #include "bucoord_prototypes.h"
34 struct bc_dumpTask bc_dumpTasks[BC_MAXSIMDUMPS];
36 extern char *whoami;
38 extern afs_int32 lastTaskCode;
40 #define HOSTADDR(sockaddr) (sockaddr)->sin_addr.s_addr
42 /* bc_Dumper
43 * called (indirectly) to make a dump
44 * entry:
45 * aindex - index into dumpTask array, contains all the information
46 * relevant to the dump
48 int
49 bc_Dumper(int aindex)
51 struct rx_connection *tconn;
52 struct bc_volumeDump *tde;
53 afs_int32 count, port;
54 struct tc_dumpDesc *volDesc = NULL;
55 struct tc_dumpArray volArray;
56 char *baseNamePtr;
57 statusP statusPtr;
59 struct tc_dumpInterface dumpInterface;
60 struct tc_dumpInterface *tcdiPtr = &dumpInterface;
61 struct bc_dumpTask *dumpTaskPtr;
63 afs_int32 code = 0;
65 dumpTaskPtr = &bc_dumpTasks[aindex];
67 if (!dumpTaskPtr->portOffset || (dumpTaskPtr->portCount == 0))
68 port = 0;
69 else
70 port = dumpTaskPtr->portOffset[0];
72 code = ConnectButc(dumpTaskPtr->config, port, &tconn);
73 if (code)
74 return (code);
76 /* count number of volumes to be dumped and
77 * build array of volumes to be sent to backup system
79 for (count = 0, tde = dumpTaskPtr->volumes; tde;
80 tde = tde->next, count++);
82 /* Nothing to dump, so just return success */
83 if (count == 0)
84 goto error_exit;
86 volDesc = malloc(count * sizeof(struct tc_dumpDesc));
87 if (!volDesc) {
88 afs_com_err(whoami, BC_NOMEM, NULL);
89 ERROR(BC_NOMEM);
92 for (count = 0, tde = dumpTaskPtr->volumes; tde; tde = tde->next, count++) {
93 strcpy(volDesc[count].name, tde->name);
94 volDesc[count].vid = tde->vid;
95 volDesc[count].vtype = tde->volType;
96 volDesc[count].partition = tde->partition;
97 volDesc[count].hostAddr = HOSTADDR(&tde->server); /* the internet address */
98 volDesc[count].date = tde->date;
99 volDesc[count].cloneDate = tde->cloneDate; /* Not yet known */
102 volArray.tc_dumpArray_len = count; /* element count */
103 volArray.tc_dumpArray_val = volDesc; /* and data */
105 baseNamePtr = tailCompPtr(dumpTaskPtr->dumpName);
107 /* setup the interface structure */
108 memset(tcdiPtr, 0, sizeof(*tcdiPtr));
110 /* general */
111 strcpy(tcdiPtr->dumpPath, dumpTaskPtr->dumpName);
112 strcpy(tcdiPtr->volumeSetName, dumpTaskPtr->volSetName);
114 /* tapeset */
115 strcpy(tcdiPtr->tapeSet.format, dumpTaskPtr->volSetName);
116 strcat(tcdiPtr->tapeSet.format, ".");
117 strcat(tcdiPtr->tapeSet.format, baseNamePtr);
118 strcat(tcdiPtr->tapeSet.format, ".%d");
119 tcdiPtr->tapeSet.a = 1;
120 tcdiPtr->tapeSet.b = 1;
121 tcdiPtr->tapeSet.maxTapes = 1000000000;
122 tcdiPtr->tapeSet.expDate = dumpTaskPtr->expDate; /* PA */
123 tcdiPtr->tapeSet.expType = dumpTaskPtr->expType;
125 /* construct dump set name */
126 strcpy(tcdiPtr->dumpName, dumpTaskPtr->volSetName);
127 strcat(tcdiPtr->dumpName, ".");
128 strcat(tcdiPtr->dumpName, baseNamePtr);
130 tcdiPtr->parentDumpId = dumpTaskPtr->parentDumpID;
131 tcdiPtr->dumpLevel = dumpTaskPtr->dumpLevel;
132 tcdiPtr->doAppend = dumpTaskPtr->doAppend;
134 /* start the dump on the tape coordinator */
135 printf("Starting dump\n");
136 code = TC_PerformDump(tconn, tcdiPtr, &volArray, &dumpTaskPtr->dumpID);
137 if (code) {
138 afs_com_err(whoami, code, "; Failed to start dump");
139 ERROR(code);
142 afs_com_err(whoami, 0, "Task %u: Dump (%s)", dumpTaskPtr->dumpID,
143 tcdiPtr->dumpName);
145 /* create status monitor block */
146 statusPtr = createStatusNode();
147 lock_Status();
148 statusPtr->taskId = dumpTaskPtr->dumpID;
149 statusPtr->port = port;
150 statusPtr->jobNumber = bc_jobNumber();
151 statusPtr->volsTotal = volArray.tc_dumpArray_len;
152 statusPtr->flags &= ~STARTING;
153 sprintf(statusPtr->taskName, "Dump (%s.%s)", dumpTaskPtr->volSetName,
154 baseNamePtr);
155 unlock_Status();
157 error_exit:
158 /* locally allocated resources */
159 if (volDesc)
160 free(volDesc);
162 if (tconn)
163 rx_DestroyConnection(tconn);
165 return (code);
168 /* freeDumpTaskVolumeList
169 * free the list of volumes used for dumps
172 void
173 freeDumpTaskVolumeList(struct bc_volumeDump *vdptr)
175 struct bc_volumeDump *nextVdPtr;
177 while (vdptr != 0) {
178 nextVdPtr = vdptr->next;
180 if (vdptr->name)
181 free(vdptr->name);
182 free(vdptr);
184 vdptr = nextVdPtr;
188 /* bc_DmpRstStart
189 * The other half of the dump/restore create process call. In bc_StartDmpRst,
190 * we allocated a dumpTask entry. Here we do the task and then free the entry.
192 void *
193 bc_DmpRstStart(void *param)
195 afs_int32 aindex = (intptr_t)param;
196 struct bc_dumpTask *tdump;
197 afs_int32 code;
199 tdump = &bc_dumpTasks[aindex];
201 code = (tdump->callProc) (aindex);
202 if (code)
203 lastTaskCode = code;
205 /* Cleanup allocated data structures */
206 freeDumpTaskVolumeList(tdump->volumes);
207 tdump->dumpID = 0;
208 if (tdump->dumpName)
209 free(tdump->dumpName);
210 if (tdump->newExt)
211 free(tdump->newExt);
212 if (tdump->volSetName)
213 free(tdump->volSetName);
214 if (tdump->portOffset)
215 free(tdump->portOffset);
216 tdump->flags &= ~BC_DI_INUSE;
218 return (void *)(intptr_t)code;
221 /* bc_StartDmpRst
222 * function to start dump running. Packages the relevant information
223 * (from params) into any free dumpTask structure (globally allocated),
224 * and then invokes bc_DmpRstStart to do the work, passing it a single
225 * parameter, the index into the dumpTask array.
227 * entry:
228 * aconfig - normally is bc_globalConfig
229 * aproc - bc_Dumper for doing dumps
230 * bc_Restorer for doing restores
234 bc_StartDmpRst(struct bc_config *aconfig, char *adname, char *avname,
235 struct bc_volumeDump *avolsToDump,
236 struct sockaddr_in *adestServer,
237 afs_int32 adestPartition, afs_int32 afromDate, char *anewExt,
238 int aoldFlag, afs_int32 aparent, afs_int32 alevel,
239 int (*aproc) (int), afs_int32 *ports, afs_int32 portCount,
240 struct bc_dumpSchedule *dsptr, int append, int dontExecute)
242 int i;
243 afs_int32 code;
244 PROCESS junk;
246 for (i = 0; i < BC_MAXSIMDUMPS; i++)
247 if (!(bc_dumpTasks[i].flags & BC_DI_INUSE))
248 break;
250 if (i >= BC_MAXSIMDUMPS) {
251 afs_com_err(whoami, BC_NOTLOCKED,
252 "All of the dump/restore slots are in use, try again later");
253 return (BC_NOTLOCKED);
256 memset(&bc_dumpTasks[i], 0, sizeof(struct bc_dumpTask));
257 bc_dumpTasks[i].callProc = aproc;
258 bc_dumpTasks[i].config = aconfig;
259 bc_dumpTasks[i].volumes = avolsToDump;
260 bc_dumpTasks[i].flags = BC_DI_INUSE;
261 bc_dumpTasks[i].dumpName = bc_CopyString(adname);
262 bc_dumpTasks[i].volSetName = bc_CopyString(avname);
263 bc_dumpTasks[i].newExt = bc_CopyString(anewExt);
264 bc_dumpTasks[i].dumpLevel = alevel;
265 bc_dumpTasks[i].parentDumpID = aparent;
266 bc_dumpTasks[i].oldFlag = aoldFlag;
267 bc_dumpTasks[i].fromDate = afromDate;
268 bc_dumpTasks[i].destPartition = adestPartition;
269 bc_dumpTasks[i].portOffset = ports;
270 bc_dumpTasks[i].portCount = portCount;
271 bc_dumpTasks[i].doAppend = append;
272 bc_dumpTasks[i].dontExecute = dontExecute;
274 if (dsptr) {
275 /* This should be specified for dumps, but will be 0 for restores */
276 bc_dumpTasks[i].expDate = dsptr->expDate;
277 bc_dumpTasks[i].expType = dsptr->expType;
279 if (adestServer)
280 memcpy(&bc_dumpTasks[i].destServer, adestServer,
281 sizeof(struct sockaddr_in));
282 else
283 memset(&bc_dumpTasks[i].destServer, 0, sizeof(struct sockaddr_in));
285 code =
286 LWP_CreateProcess(bc_DmpRstStart, 20480, LWP_NORMAL_PRIORITY,
287 (void *)(intptr_t)i, "helper", &junk);
288 if (code) {
289 bc_HandleMisc(code);
290 afs_com_err(whoami, code, "; Can't start thread");
292 /* Cleanup allocated data structures */
293 freeDumpTaskVolumeList(bc_dumpTasks[i].volumes);
294 bc_dumpTasks[i].dumpID = 0;
295 if (bc_dumpTasks[i].dumpName)
296 free(bc_dumpTasks[i].dumpName);
297 if (bc_dumpTasks[i].newExt)
298 free(bc_dumpTasks[i].newExt);
299 if (bc_dumpTasks[i].volSetName)
300 free(bc_dumpTasks[i].volSetName);
301 if (bc_dumpTasks[i].portOffset)
302 free(bc_dumpTasks[i].portOffset);
303 bc_dumpTasks[i].flags &= ~BC_DI_INUSE;
304 return (code);
307 return 0;
310 #ifdef notdef
311 /* bc_FindDumpSlot
312 * Returns the dump slot of the dump with dumpID
313 * entry:
314 * dumpID - id to look for
315 * port - portoffset for tape coordinator
316 * exit:
317 * 0-n - i.e. 0 or positive number, is the dump slot
318 * -1 - failed to find dumpID
321 afs_int32
322 bc_FindDumpSlot(afs_int32 dumpID, afs_int32 port)
324 int i;
326 for (i = 0; i < BC_MAXSIMDUMPS; i++) {
327 if ((bc_dumpTasks[i].flags & BC_DI_INUSE)
328 && (bc_dumpTasks[i].dumpID == dumpID)
329 && ((afs_int32) bc_dumpTasks[i].portOffset == port)) {
330 return (i);
333 return (-1);
335 #endif
337 /* bc_LabelTape
338 * opens a connection to the tape coordinator and requests that it
339 * label a tape
343 bc_LabelTape(char *afsname, char *pname, afs_int32 size,
344 struct bc_config *config, afs_int32 port)
346 struct rx_connection *tconn;
347 afs_int32 code = 0;
348 struct tc_tapeLabel label;
349 statusP statusPtr;
350 afs_uint32 taskId;
352 code = ConnectButc(config, port, &tconn);
353 if (code)
354 return (code);
356 memset(&label, 0, sizeof(label));
357 if (afsname)
358 strcpy(label.afsname, afsname);
359 if (pname)
360 strcpy(label.pname, (strcmp(pname, "") ? pname : "<NULL>"));
361 label.size = size;
363 code = TC_LabelTape(tconn, &label, &taskId);
364 if (code) {
365 afs_com_err(whoami, code, "; Failed to start labeltape");
366 return (code);
369 /* create status monitor block */
370 statusPtr = createStatusNode();
371 lock_Status();
372 statusPtr->taskId = taskId;
373 statusPtr->port = port;
374 statusPtr->jobNumber = bc_jobNumber();
375 /* statusPtr->flags |= SILENT; *//* don't report termination */
376 statusPtr->flags &= ~STARTING; /* ok to examine */
378 sprintf(statusPtr->taskName, "Labeltape (%s)",
379 (pname ? pname : (afsname ? afsname : "<NULL>")));
380 unlock_Status();
382 return 0;
385 /* bc_ReadLabel
386 * open a connection to the tape coordinator and read the label on
387 * a tape
391 bc_ReadLabel(struct bc_config *config, afs_int32 port)
393 struct rx_connection *tconn;
394 struct tc_tapeLabel label;
395 afs_uint32 taskId;
396 afs_int32 code = 0;
397 char *tname = 0;
399 code = ConnectButc(config, port, &tconn);
400 if (code)
401 return (code);
403 memset(&label, 0, sizeof(label));
404 code = TC_ReadLabel(tconn, &label, &taskId);
405 if (code) {
406 if (code == BUTM_NOLABEL) {
407 printf("Tape read was unlabelled\n");
408 return 0;
410 afs_com_err(whoami, code, "; Failed to start readlabel");
411 return (code);
414 if (strcmp(label.pname, ""))
415 tname = label.pname;
416 else if (strcmp(label.afsname, ""))
417 tname = label.afsname;
419 if (!tname) {
420 printf("Tape read was labelled : <NULL> size : %u\n", label.size);
421 } else if (!label.tapeId) {
422 printf("Tape read was labelled : %s size : %lu Kbytes\n", tname,
423 (long unsigned int) label.size);
424 } else {
425 printf("Tape read was labelled : %s (%lu) size : %lu Kbytes\n", tname,
426 (long unsigned int) label.tapeId, (long unsigned int) label.size);
429 return 0;
433 bc_ScanDumps(struct bc_config *config, afs_int32 dbAddFlag, afs_int32 port)
435 struct rx_connection *tconn;
436 statusP statusPtr;
437 afs_uint32 taskId;
438 afs_int32 code = 0;
440 code = ConnectButc(config, port, &tconn);
441 if (code)
442 return (code);
444 code = TC_ScanDumps(tconn, dbAddFlag, &taskId);
445 if (code) {
446 afs_com_err(whoami, code, "; Failed to start scantape");
447 return (code);
450 /* create status monitor block */
451 statusPtr = createStatusNode();
452 lock_Status();
453 statusPtr->taskId = taskId;
454 statusPtr->port = port;
455 statusPtr->jobNumber = bc_jobNumber();
456 statusPtr->flags &= ~STARTING; /* ok to examine */
457 sprintf(statusPtr->taskName, "Scantape");
458 unlock_Status();
460 return (0);
463 /*************/
464 /* utilities */
465 /*************/
467 /* get a connection to the tape controller */
468 afs_int32
469 bc_GetConn(struct bc_config *aconfig, afs_int32 aport,
470 struct rx_connection **tconn)
472 afs_uint32 host;
473 unsigned short port;
474 static struct rx_securityClass *rxsc;
475 struct bc_hostEntry *te;
477 *tconn = (struct rx_connection *)0;
479 /* use non-secure connections to butc */
480 if (!rxsc)
481 rxsc = rxnull_NewClientSecurityObject();
482 if (!rxsc || !aconfig)
483 return (-1);
485 for (te = aconfig->tapeHosts; te; te = te->next) {
486 if (te->portOffset == aport) {
487 /* found the right port */
488 host = te->addr.sin_addr.s_addr;
489 if (!host)
490 return (BC_NOHOSTENTRY); /* gethostbyname in bc_ParseHosts failed */
492 port = htons(BC_TAPEPORT + aport);
494 /* servers is 1; sec index is 0 */
495 *tconn = rx_NewConnection(host, port, 1, rxsc, 0);
496 return ((*tconn ? 0 : -1));
499 return (BC_NOHOSTENTRY);
502 /* CheckTCVersion
503 * make sure we are talking to a compatible butc process.
504 * exit:
505 * 0 - ok
506 * -1 - not compatible
510 CheckTCVersion(struct rx_connection *tconn)
512 struct tc_tcInfo tci;
513 afs_int32 code;
515 code = TC_TCInfo(tconn, &tci);
516 if (code)
517 return (code);
519 if (tci.tcVersion != CUR_BUTC_VERSION)
520 return (BC_VERSIONFAIL);
522 return 0;
526 ConnectButc(struct bc_config *config, afs_int32 port,
527 struct rx_connection **tconn)
529 afs_int32 code;
531 code = bc_GetConn(config, port, tconn);
532 if (code) {
533 afs_com_err(whoami, code,
534 "; Can't connect to tape coordinator at port %d", port);
535 return (code);
538 code = CheckTCVersion(*tconn);
539 if (code) {
540 rx_DestroyConnection(*tconn);
542 if (code == BC_VERSIONFAIL)
543 afs_com_err(whoami, code,
544 "; Backup and butc are not the same version");
545 else
546 afs_com_err(whoami, code,
547 "; Can't access tape coordinator at port %d", port);
549 return (code);
552 return (0);