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>
20 #include <sys/types.h>
25 #include <sys/param.h>
26 #include <sys/socket.h>
27 #include <netinet/in.h>
33 #include <afs/bubasics.h>
35 #include <afs/com_err.h>
36 #include <lock.h> /* for checking TC_ABORTFAILED. PA */
37 #include <afs/tcdata.h> /* for checking TC_ABORTFAILED. PA */
41 #include "error_macros.h"
43 struct bc_dumpTask bc_dumpTasks[BC_MAXSIMDUMPS];
45 extern char *bc_CopyString();
46 extern void bc_HandleMisc();
48 extern char *tailCompPtr();
49 extern statusP createStatusNode();
50 extern afs_int32 bc_jobNumber();
52 extern afs_int32 lastTaskCode;
54 #define HOSTADDR(sockaddr) (sockaddr)->sin_addr.s_addr
57 * called (indirectly) to make a dump
59 * aindex - index into dumpTask array, contains all the information
60 * relevant to the dump
64 struct rx_connection *tconn;
65 register struct bc_volumeDump *tde;
66 afs_int32 count, port;
67 struct tc_dumpDesc *volDesc = 0;
68 struct tc_dumpArray volArray;
72 struct tc_dumpInterface dumpInterface;
73 struct tc_dumpInterface *tcdiPtr = &dumpInterface;
74 register struct bc_dumpTask *dumpTaskPtr;
76 register afs_int32 code = 0;
78 dumpTaskPtr = &bc_dumpTasks[aindex];
80 if (!dumpTaskPtr->portOffset || (dumpTaskPtr->portCount == 0))
83 port = dumpTaskPtr->portOffset[0];
85 code = ConnectButc(dumpTaskPtr->config, port, &tconn);
89 /* count number of volumes to be dumped and
90 * build array of volumes to be sent to backup system
92 for (count = 0, tde = dumpTaskPtr->volumes; tde;
93 tde = tde->next, count++);
95 (struct tc_dumpDesc *)malloc(count * sizeof(struct tc_dumpDesc));
97 afs_com_err(whoami, BC_NOMEM, "");
101 for (count = 0, tde = dumpTaskPtr->volumes; tde; tde = tde->next, count++) {
102 strcpy(volDesc[count].name, tde->name);
103 volDesc[count].vid = tde->vid;
104 volDesc[count].vtype = tde->volType;
105 volDesc[count].partition = tde->partition;
106 volDesc[count].hostAddr = HOSTADDR(&tde->server); /* the internet address */
107 volDesc[count].date = tde->date;
108 volDesc[count].cloneDate = tde->cloneDate; /* Not yet known */
111 volArray.tc_dumpArray_len = count; /* element count */
112 volArray.tc_dumpArray_val = volDesc; /* and data */
114 baseNamePtr = tailCompPtr(dumpTaskPtr->dumpName);
116 /* setup the interface structure */
117 memset(tcdiPtr, 0, sizeof(*tcdiPtr));
120 strcpy(tcdiPtr->dumpPath, dumpTaskPtr->dumpName);
121 strcpy(tcdiPtr->volumeSetName, dumpTaskPtr->volSetName);
124 strcpy(tcdiPtr->tapeSet.format, dumpTaskPtr->volSetName);
125 strcat(tcdiPtr->tapeSet.format, ".");
126 strcat(tcdiPtr->tapeSet.format, baseNamePtr);
127 strcat(tcdiPtr->tapeSet.format, ".%d");
128 tcdiPtr->tapeSet.a = 1;
129 tcdiPtr->tapeSet.b = 1;
130 tcdiPtr->tapeSet.maxTapes = 1000000000;
131 tcdiPtr->tapeSet.expDate = dumpTaskPtr->expDate; /* PA */
132 tcdiPtr->tapeSet.expType = dumpTaskPtr->expType;
134 /* construct dump set name */
135 strcpy(tcdiPtr->dumpName, dumpTaskPtr->volSetName);
136 strcat(tcdiPtr->dumpName, ".");
137 strcat(tcdiPtr->dumpName, baseNamePtr);
139 tcdiPtr->parentDumpId = dumpTaskPtr->parentDumpID;
140 tcdiPtr->dumpLevel = dumpTaskPtr->dumpLevel;
141 tcdiPtr->doAppend = dumpTaskPtr->doAppend;
143 /* start the dump on the tape coordinator */
144 printf("Starting dump\n");
145 code = TC_PerformDump(tconn, tcdiPtr, &volArray, &dumpTaskPtr->dumpID);
147 afs_com_err(whoami, code, "; Failed to start dump");
151 afs_com_err(whoami, 0, "Task %u: Dump (%s)", dumpTaskPtr->dumpID,
154 /* create status monitor block */
155 statusPtr = createStatusNode();
157 statusPtr->taskId = dumpTaskPtr->dumpID;
158 statusPtr->port = port;
159 statusPtr->jobNumber = bc_jobNumber();
160 statusPtr->volsTotal = volArray.tc_dumpArray_len;
161 statusPtr->flags &= ~STARTING;
162 sprintf(statusPtr->taskName, "Dump (%s.%s)", dumpTaskPtr->volSetName,
167 /* locally allocated resources */
172 rx_DestroyConnection(tconn);
177 /* freeDumpTaskVolumeList
178 * free the list of volumes used for dumps
182 freeDumpTaskVolumeList(vdptr)
183 struct bc_volumeDump *vdptr;
185 struct bc_volumeDump *nextVdPtr;
188 nextVdPtr = vdptr->next;
199 * The other half of the dump/restore create process call. In bc_StartDmpRst,
200 * we allocated a dumpTask entry. Here we do the task and then free the entry.
203 bc_DmpRstStart(void *param)
205 afs_int32 aindex = (afs_int32) param;
206 register struct bc_dumpTask *tdump;
207 register afs_int32 code;
209 tdump = &bc_dumpTasks[aindex];
211 code = (tdump->callProc) (aindex);
215 /* Cleanup allocated data structures */
216 freeDumpTaskVolumeList(tdump->volumes);
219 free(tdump->dumpName);
222 if (tdump->volSetName)
223 free(tdump->volSetName);
224 if (tdump->portOffset)
225 free(tdump->portOffset);
226 tdump->flags &= ~BC_DI_INUSE;
232 * function to start dump running. Packages the relevant information
233 * (from params) into any free dumpTask structure (globally allocated),
234 * and then invokes bc_DmpRstStart to do the work, passing it a single
235 * parameter, the index into the dumpTask array.
238 * aconfig - normally is bc_globalConfig
239 * aproc - bc_Dumper for doing dumps
240 * bc_Restorer for doing restores
243 bc_StartDmpRst(aconfig, adname, avname, avolsToDump, adestServer,
244 adestPartition, afromDate, anewExt, aoldFlag, aparent, alevel,
245 aproc, ports, portCount, dsptr, append, dontExecute)
246 struct bc_config *aconfig;
249 struct bc_volumeDump *avolsToDump;
250 struct sockaddr_in *adestServer;
251 afs_int32 adestPartition;
255 afs_int32 aparent, alevel;
259 struct bc_dumpSchedule *dsptr;
260 int append, dontExecute;
263 register afs_int32 code;
266 for (i = 0; i < BC_MAXSIMDUMPS; i++)
267 if (!(bc_dumpTasks[i].flags & BC_DI_INUSE))
270 if (i >= BC_MAXSIMDUMPS) {
271 afs_com_err(whoami, BC_NOTLOCKED,
272 "All of the dump/restore slots are in use, try again later");
273 return (BC_NOTLOCKED);
276 memset(&bc_dumpTasks[i], 0, sizeof(struct bc_dumpTask));
277 bc_dumpTasks[i].callProc = aproc;
278 bc_dumpTasks[i].config = aconfig;
279 bc_dumpTasks[i].volumes = avolsToDump;
280 bc_dumpTasks[i].flags = BC_DI_INUSE;
281 bc_dumpTasks[i].dumpName = bc_CopyString(adname);
282 bc_dumpTasks[i].volSetName = bc_CopyString(avname);
283 bc_dumpTasks[i].newExt = bc_CopyString(anewExt);
284 bc_dumpTasks[i].dumpLevel = alevel;
285 bc_dumpTasks[i].parentDumpID = aparent;
286 bc_dumpTasks[i].oldFlag = aoldFlag;
287 bc_dumpTasks[i].fromDate = afromDate;
288 bc_dumpTasks[i].destPartition = adestPartition;
289 bc_dumpTasks[i].portOffset = ports;
290 bc_dumpTasks[i].portCount = portCount;
291 bc_dumpTasks[i].doAppend = append;
292 bc_dumpTasks[i].dontExecute = dontExecute;
295 /* This should be specified for dumps, but will be 0 for restores */
296 bc_dumpTasks[i].expDate = dsptr->expDate;
297 bc_dumpTasks[i].expType = dsptr->expType;
300 memcpy(&bc_dumpTasks[i].destServer, adestServer,
301 sizeof(struct sockaddr_in));
303 memset(&bc_dumpTasks[i].destServer, 0, sizeof(struct sockaddr_in));
306 LWP_CreateProcess(bc_DmpRstStart, 20480, LWP_NORMAL_PRIORITY,
307 (void *)i, "helper", &junk);
310 afs_com_err(whoami, code, "; Can't start thread");
312 /* Cleanup allocated data structures */
313 freeDumpTaskVolumeList(bc_dumpTasks[i].volumes);
314 bc_dumpTasks[i].dumpID = 0;
315 if (bc_dumpTasks[i].dumpName)
316 free(bc_dumpTasks[i].dumpName);
317 if (bc_dumpTasks[i].newExt)
318 free(bc_dumpTasks[i].newExt);
319 if (bc_dumpTasks[i].volSetName)
320 free(bc_dumpTasks[i].volSetName);
321 if (bc_dumpTasks[i].portOffset)
322 free(bc_dumpTasks[i].portOffset);
323 bc_dumpTasks[i].flags &= ~BC_DI_INUSE;
332 * Returns the dump slot of the dump with dumpID
334 * dumpID - id to look for
335 * port - portoffset for tape coordinator
337 * 0-n - i.e. 0 or positive number, is the dump slot
338 * -1 - failed to find dumpID
342 bc_FindDumpSlot(dumpID, port)
348 for (i = 0; i < BC_MAXSIMDUMPS; i++) {
349 if ((bc_dumpTasks[i].flags & BC_DI_INUSE)
350 && (bc_dumpTasks[i].dumpID == dumpID)
351 && ((afs_int32) bc_dumpTasks[i].portOffset == port)) {
360 * opens a connection to the tape coordinator and requests that it
364 bc_LabelTape(afsname, pname, size, config, port)
365 char *afsname, *pname;
366 struct bc_config *config;
370 struct rx_connection *tconn;
372 struct tc_tapeLabel label;
376 code = ConnectButc(config, port, &tconn);
380 memset(&label, 0, sizeof(label));
382 strcpy(label.afsname, afsname);
384 strcpy(label.pname, (strcmp(pname, "") ? pname : "<NULL>"));
387 code = TC_LabelTape(tconn, &label, &taskId);
389 afs_com_err(whoami, code, "; Failed to start labeltape");
393 /* create status monitor block */
394 statusPtr = createStatusNode();
396 statusPtr->taskId = taskId;
397 statusPtr->port = port;
398 statusPtr->jobNumber = bc_jobNumber();
399 /* statusPtr->flags |= SILENT; *//* don't report termination */
400 statusPtr->flags &= ~STARTING; /* ok to examine */
402 sprintf(statusPtr->taskName, "Labeltape (%s)",
403 (pname ? pname : (afsname ? afsname : "<NULL>")));
410 * open a connection to the tape coordinator and read the label on
414 bc_ReadLabel(config, port)
415 struct bc_config *config;
418 struct rx_connection *tconn;
419 struct tc_tapeLabel label;
424 code = ConnectButc(config, port, &tconn);
428 memset(&label, 0, sizeof(label));
429 code = TC_ReadLabel(tconn, &label, &taskId);
431 if (code == BUTM_NOLABEL) {
432 printf("Tape read was unlabelled\n");
435 afs_com_err(whoami, code, "; Failed to start readlabel");
439 if (strcmp(label.pname, ""))
441 else if (strcmp(label.afsname, ""))
442 tname = label.afsname;
445 printf("Tape read was labelled : <NULL> size : %u\n", label.size);
446 } else if (!label.tapeId) {
447 printf("Tape read was labelled : %s size : %lu Kbytes\n", tname,
450 printf("Tape read was labelled : %s (%lu) size : %lu Kbytes\n", tname,
451 label.tapeId, label.size);
457 bc_ScanDumps(config, dbAddFlag, port)
458 struct bc_config *config;
462 struct rx_connection *tconn;
467 code = ConnectButc(config, port, &tconn);
471 code = TC_ScanDumps(tconn, dbAddFlag, &taskId);
473 afs_com_err(whoami, code, "; Failed to start scantape");
477 /* create status monitor block */
478 statusPtr = createStatusNode();
480 statusPtr->taskId = taskId;
481 statusPtr->port = port;
482 statusPtr->jobNumber = bc_jobNumber();
483 statusPtr->flags &= ~STARTING; /* ok to examine */
484 sprintf(statusPtr->taskName, "Scantape");
494 /* get a connection to the tape controller */
496 bc_GetConn(aconfig, aport, tconn)
497 struct bc_config *aconfig;
499 struct rx_connection **tconn;
504 static struct rx_securityClass *rxsc;
505 struct bc_hostEntry *te;
507 *tconn = (struct rx_connection *)0;
509 /* use non-secure connections to butc */
511 rxsc = rxnull_NewClientSecurityObject();
512 if (!rxsc || !aconfig)
515 for (te = aconfig->tapeHosts; te; te = te->next) {
516 if (te->portOffset == aport) {
517 /* found the right port */
518 host = te->addr.sin_addr.s_addr;
520 return (BC_NOHOSTENTRY); /* gethostbyname in bc_ParseHosts failed */
522 port = htons(BC_TAPEPORT + aport);
524 /* servers is 1; sec index is 0 */
525 *tconn = rx_NewConnection(host, port, 1, rxsc, 0);
526 return ((*tconn ? 0 : -1));
529 return (BC_NOHOSTENTRY);
533 * make sure we are talking to a compatible butc process.
536 * -1 - not compatible
539 CheckTCVersion(tconn)
540 struct rx_connection *tconn;
542 struct tc_tcInfo tci;
545 code = TC_TCInfo(tconn, &tci);
549 if (tci.tcVersion != CUR_BUTC_VERSION)
550 return (BC_VERSIONFAIL);
555 ConnectButc(config, port, tconn)
556 struct bc_config *config;
558 struct rx_connection **tconn;
562 code = bc_GetConn(config, port, tconn);
564 afs_com_err(whoami, code,
565 "; Can't connect to tape coordinator at port %d", port);
569 code = CheckTCVersion(*tconn);
571 rx_DestroyConnection(*tconn);
573 if (code == BC_VERSIONFAIL)
574 afs_com_err(whoami, code,
575 "; Backup and butc are not the same version");
577 afs_com_err(whoami, code,
578 "; Can't access tape coordinator at port %d", port);