2 * Copyright 2000, International Business Machines Corporation and others.
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
14 #include <afsconfig.h>
15 #include <afs/param.h>
22 #include <afs/bubasics.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 */
30 #include "error_macros.h"
31 #include "bucoord_internal.h"
32 #include "bucoord_prototypes.h"
34 struct bc_dumpTask bc_dumpTasks[BC_MAXSIMDUMPS];
38 extern afs_int32 lastTaskCode;
40 #define HOSTADDR(sockaddr) (sockaddr)->sin_addr.s_addr
43 * called (indirectly) to make a dump
45 * aindex - index into dumpTask array, contains all the information
46 * relevant to the dump
51 struct rx_connection *tconn;
52 struct bc_volumeDump *tde;
53 afs_int32 count, port;
54 struct tc_dumpDesc *volDesc = 0;
55 struct tc_dumpArray volArray;
59 struct tc_dumpInterface dumpInterface;
60 struct tc_dumpInterface *tcdiPtr = &dumpInterface;
61 struct bc_dumpTask *dumpTaskPtr;
65 dumpTaskPtr = &bc_dumpTasks[aindex];
67 if (!dumpTaskPtr->portOffset || (dumpTaskPtr->portCount == 0))
70 port = dumpTaskPtr->portOffset[0];
72 code = ConnectButc(dumpTaskPtr->config, port, &tconn);
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 (struct tc_dumpDesc *)malloc(count * sizeof(struct tc_dumpDesc));
84 afs_com_err(whoami, BC_NOMEM, NULL);
88 for (count = 0, tde = dumpTaskPtr->volumes; tde; tde = tde->next, count++) {
89 strcpy(volDesc[count].name, tde->name);
90 volDesc[count].vid = tde->vid;
91 volDesc[count].vtype = tde->volType;
92 volDesc[count].partition = tde->partition;
93 volDesc[count].hostAddr = HOSTADDR(&tde->server); /* the internet address */
94 volDesc[count].date = tde->date;
95 volDesc[count].cloneDate = tde->cloneDate; /* Not yet known */
98 volArray.tc_dumpArray_len = count; /* element count */
99 volArray.tc_dumpArray_val = volDesc; /* and data */
101 baseNamePtr = tailCompPtr(dumpTaskPtr->dumpName);
103 /* setup the interface structure */
104 memset(tcdiPtr, 0, sizeof(*tcdiPtr));
107 strcpy(tcdiPtr->dumpPath, dumpTaskPtr->dumpName);
108 strcpy(tcdiPtr->volumeSetName, dumpTaskPtr->volSetName);
111 strcpy(tcdiPtr->tapeSet.format, dumpTaskPtr->volSetName);
112 strcat(tcdiPtr->tapeSet.format, ".");
113 strcat(tcdiPtr->tapeSet.format, baseNamePtr);
114 strcat(tcdiPtr->tapeSet.format, ".%d");
115 tcdiPtr->tapeSet.a = 1;
116 tcdiPtr->tapeSet.b = 1;
117 tcdiPtr->tapeSet.maxTapes = 1000000000;
118 tcdiPtr->tapeSet.expDate = dumpTaskPtr->expDate; /* PA */
119 tcdiPtr->tapeSet.expType = dumpTaskPtr->expType;
121 /* construct dump set name */
122 strcpy(tcdiPtr->dumpName, dumpTaskPtr->volSetName);
123 strcat(tcdiPtr->dumpName, ".");
124 strcat(tcdiPtr->dumpName, baseNamePtr);
126 tcdiPtr->parentDumpId = dumpTaskPtr->parentDumpID;
127 tcdiPtr->dumpLevel = dumpTaskPtr->dumpLevel;
128 tcdiPtr->doAppend = dumpTaskPtr->doAppend;
130 /* start the dump on the tape coordinator */
131 printf("Starting dump\n");
132 code = TC_PerformDump(tconn, tcdiPtr, &volArray, &dumpTaskPtr->dumpID);
134 afs_com_err(whoami, code, "; Failed to start dump");
138 afs_com_err(whoami, 0, "Task %u: Dump (%s)", dumpTaskPtr->dumpID,
141 /* create status monitor block */
142 statusPtr = createStatusNode();
144 statusPtr->taskId = dumpTaskPtr->dumpID;
145 statusPtr->port = port;
146 statusPtr->jobNumber = bc_jobNumber();
147 statusPtr->volsTotal = volArray.tc_dumpArray_len;
148 statusPtr->flags &= ~STARTING;
149 sprintf(statusPtr->taskName, "Dump (%s.%s)", dumpTaskPtr->volSetName,
154 /* locally allocated resources */
159 rx_DestroyConnection(tconn);
164 /* freeDumpTaskVolumeList
165 * free the list of volumes used for dumps
169 freeDumpTaskVolumeList(struct bc_volumeDump *vdptr)
171 struct bc_volumeDump *nextVdPtr;
174 nextVdPtr = vdptr->next;
185 * The other half of the dump/restore create process call. In bc_StartDmpRst,
186 * we allocated a dumpTask entry. Here we do the task and then free the entry.
189 bc_DmpRstStart(void *param)
191 afs_int32 aindex = (intptr_t)param;
192 struct bc_dumpTask *tdump;
195 tdump = &bc_dumpTasks[aindex];
197 code = (tdump->callProc) (aindex);
201 /* Cleanup allocated data structures */
202 freeDumpTaskVolumeList(tdump->volumes);
205 free(tdump->dumpName);
208 if (tdump->volSetName)
209 free(tdump->volSetName);
210 if (tdump->portOffset)
211 free(tdump->portOffset);
212 tdump->flags &= ~BC_DI_INUSE;
214 return (void *)(intptr_t)code;
218 * function to start dump running. Packages the relevant information
219 * (from params) into any free dumpTask structure (globally allocated),
220 * and then invokes bc_DmpRstStart to do the work, passing it a single
221 * parameter, the index into the dumpTask array.
224 * aconfig - normally is bc_globalConfig
225 * aproc - bc_Dumper for doing dumps
226 * bc_Restorer for doing restores
230 bc_StartDmpRst(struct bc_config *aconfig, char *adname, char *avname,
231 struct bc_volumeDump *avolsToDump,
232 struct sockaddr_in *adestServer,
233 afs_int32 adestPartition, afs_int32 afromDate, char *anewExt,
234 int aoldFlag, afs_int32 aparent, afs_int32 alevel,
235 int (*aproc) (int), afs_int32 *ports, afs_int32 portCount,
236 struct bc_dumpSchedule *dsptr, int append, int dontExecute)
242 for (i = 0; i < BC_MAXSIMDUMPS; i++)
243 if (!(bc_dumpTasks[i].flags & BC_DI_INUSE))
246 if (i >= BC_MAXSIMDUMPS) {
247 afs_com_err(whoami, BC_NOTLOCKED,
248 "All of the dump/restore slots are in use, try again later");
249 return (BC_NOTLOCKED);
252 memset(&bc_dumpTasks[i], 0, sizeof(struct bc_dumpTask));
253 bc_dumpTasks[i].callProc = aproc;
254 bc_dumpTasks[i].config = aconfig;
255 bc_dumpTasks[i].volumes = avolsToDump;
256 bc_dumpTasks[i].flags = BC_DI_INUSE;
257 bc_dumpTasks[i].dumpName = bc_CopyString(adname);
258 bc_dumpTasks[i].volSetName = bc_CopyString(avname);
259 bc_dumpTasks[i].newExt = bc_CopyString(anewExt);
260 bc_dumpTasks[i].dumpLevel = alevel;
261 bc_dumpTasks[i].parentDumpID = aparent;
262 bc_dumpTasks[i].oldFlag = aoldFlag;
263 bc_dumpTasks[i].fromDate = afromDate;
264 bc_dumpTasks[i].destPartition = adestPartition;
265 bc_dumpTasks[i].portOffset = ports;
266 bc_dumpTasks[i].portCount = portCount;
267 bc_dumpTasks[i].doAppend = append;
268 bc_dumpTasks[i].dontExecute = dontExecute;
271 /* This should be specified for dumps, but will be 0 for restores */
272 bc_dumpTasks[i].expDate = dsptr->expDate;
273 bc_dumpTasks[i].expType = dsptr->expType;
276 memcpy(&bc_dumpTasks[i].destServer, adestServer,
277 sizeof(struct sockaddr_in));
279 memset(&bc_dumpTasks[i].destServer, 0, sizeof(struct sockaddr_in));
282 LWP_CreateProcess(bc_DmpRstStart, 20480, LWP_NORMAL_PRIORITY,
283 (void *)(intptr_t)i, "helper", &junk);
286 afs_com_err(whoami, code, "; Can't start thread");
288 /* Cleanup allocated data structures */
289 freeDumpTaskVolumeList(bc_dumpTasks[i].volumes);
290 bc_dumpTasks[i].dumpID = 0;
291 if (bc_dumpTasks[i].dumpName)
292 free(bc_dumpTasks[i].dumpName);
293 if (bc_dumpTasks[i].newExt)
294 free(bc_dumpTasks[i].newExt);
295 if (bc_dumpTasks[i].volSetName)
296 free(bc_dumpTasks[i].volSetName);
297 if (bc_dumpTasks[i].portOffset)
298 free(bc_dumpTasks[i].portOffset);
299 bc_dumpTasks[i].flags &= ~BC_DI_INUSE;
308 * Returns the dump slot of the dump with dumpID
310 * dumpID - id to look for
311 * port - portoffset for tape coordinator
313 * 0-n - i.e. 0 or positive number, is the dump slot
314 * -1 - failed to find dumpID
318 bc_FindDumpSlot(afs_int32 dumpID, afs_int32 port)
322 for (i = 0; i < BC_MAXSIMDUMPS; i++) {
323 if ((bc_dumpTasks[i].flags & BC_DI_INUSE)
324 && (bc_dumpTasks[i].dumpID == dumpID)
325 && ((afs_int32) bc_dumpTasks[i].portOffset == port)) {
334 * opens a connection to the tape coordinator and requests that it
339 bc_LabelTape(char *afsname, char *pname, afs_int32 size,
340 struct bc_config *config, afs_int32 port)
342 struct rx_connection *tconn;
344 struct tc_tapeLabel label;
348 code = ConnectButc(config, port, &tconn);
352 memset(&label, 0, sizeof(label));
354 strcpy(label.afsname, afsname);
356 strcpy(label.pname, (strcmp(pname, "") ? pname : "<NULL>"));
359 code = TC_LabelTape(tconn, &label, &taskId);
361 afs_com_err(whoami, code, "; Failed to start labeltape");
365 /* create status monitor block */
366 statusPtr = createStatusNode();
368 statusPtr->taskId = taskId;
369 statusPtr->port = port;
370 statusPtr->jobNumber = bc_jobNumber();
371 /* statusPtr->flags |= SILENT; *//* don't report termination */
372 statusPtr->flags &= ~STARTING; /* ok to examine */
374 sprintf(statusPtr->taskName, "Labeltape (%s)",
375 (pname ? pname : (afsname ? afsname : "<NULL>")));
382 * open a connection to the tape coordinator and read the label on
387 bc_ReadLabel(struct bc_config *config, afs_int32 port)
389 struct rx_connection *tconn;
390 struct tc_tapeLabel label;
395 code = ConnectButc(config, port, &tconn);
399 memset(&label, 0, sizeof(label));
400 code = TC_ReadLabel(tconn, &label, &taskId);
402 if (code == BUTM_NOLABEL) {
403 printf("Tape read was unlabelled\n");
406 afs_com_err(whoami, code, "; Failed to start readlabel");
410 if (strcmp(label.pname, ""))
412 else if (strcmp(label.afsname, ""))
413 tname = label.afsname;
416 printf("Tape read was labelled : <NULL> size : %u\n", label.size);
417 } else if (!label.tapeId) {
418 printf("Tape read was labelled : %s size : %lu Kbytes\n", tname,
419 (long unsigned int) label.size);
421 printf("Tape read was labelled : %s (%lu) size : %lu Kbytes\n", tname,
422 (long unsigned int) label.tapeId, (long unsigned int) label.size);
429 bc_ScanDumps(struct bc_config *config, afs_int32 dbAddFlag, afs_int32 port)
431 struct rx_connection *tconn;
436 code = ConnectButc(config, port, &tconn);
440 code = TC_ScanDumps(tconn, dbAddFlag, &taskId);
442 afs_com_err(whoami, code, "; Failed to start scantape");
446 /* create status monitor block */
447 statusPtr = createStatusNode();
449 statusPtr->taskId = taskId;
450 statusPtr->port = port;
451 statusPtr->jobNumber = bc_jobNumber();
452 statusPtr->flags &= ~STARTING; /* ok to examine */
453 sprintf(statusPtr->taskName, "Scantape");
463 /* get a connection to the tape controller */
465 bc_GetConn(struct bc_config *aconfig, afs_int32 aport,
466 struct rx_connection **tconn)
470 static struct rx_securityClass *rxsc;
471 struct bc_hostEntry *te;
473 *tconn = (struct rx_connection *)0;
475 /* use non-secure connections to butc */
477 rxsc = rxnull_NewClientSecurityObject();
478 if (!rxsc || !aconfig)
481 for (te = aconfig->tapeHosts; te; te = te->next) {
482 if (te->portOffset == aport) {
483 /* found the right port */
484 host = te->addr.sin_addr.s_addr;
486 return (BC_NOHOSTENTRY); /* gethostbyname in bc_ParseHosts failed */
488 port = htons(BC_TAPEPORT + aport);
490 /* servers is 1; sec index is 0 */
491 *tconn = rx_NewConnection(host, port, 1, rxsc, 0);
492 return ((*tconn ? 0 : -1));
495 return (BC_NOHOSTENTRY);
499 * make sure we are talking to a compatible butc process.
502 * -1 - not compatible
506 CheckTCVersion(struct rx_connection *tconn)
508 struct tc_tcInfo tci;
511 code = TC_TCInfo(tconn, &tci);
515 if (tci.tcVersion != CUR_BUTC_VERSION)
516 return (BC_VERSIONFAIL);
522 ConnectButc(struct bc_config *config, afs_int32 port,
523 struct rx_connection **tconn)
527 code = bc_GetConn(config, port, tconn);
529 afs_com_err(whoami, code,
530 "; Can't connect to tape coordinator at port %d", port);
534 code = CheckTCVersion(*tconn);
536 rx_DestroyConnection(*tconn);
538 if (code == BC_VERSIONFAIL)
539 afs_com_err(whoami, code,
540 "; Backup and butc are not the same version");
542 afs_com_err(whoami, code,
543 "; Can't access tape coordinator at port %d", port);