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>
18 #include <sys/types.h>
26 #include <sys/param.h>
27 #include <sys/socket.h>
28 #include <netinet/in.h>
34 #include <afs/bubasics.h>
36 #include <afs/com_err.h>
37 #include <lock.h> /* for checking TC_ABORTFAILED. PA */
38 #include <afs/tcdata.h> /* for checking TC_ABORTFAILED. PA */
42 #include "error_macros.h"
43 #include "bucoord_internal.h"
44 #include "bucoord_prototypes.h"
46 struct bc_dumpTask bc_dumpTasks[BC_MAXSIMDUMPS];
50 extern afs_int32 lastTaskCode;
52 #define HOSTADDR(sockaddr) (sockaddr)->sin_addr.s_addr
55 * called (indirectly) to make a dump
57 * aindex - index into dumpTask array, contains all the information
58 * relevant to the dump
63 struct rx_connection *tconn;
64 register struct bc_volumeDump *tde;
65 afs_int32 count, port;
66 struct tc_dumpDesc *volDesc = 0;
67 struct tc_dumpArray volArray;
71 struct tc_dumpInterface dumpInterface;
72 struct tc_dumpInterface *tcdiPtr = &dumpInterface;
73 register struct bc_dumpTask *dumpTaskPtr;
75 register afs_int32 code = 0;
77 dumpTaskPtr = &bc_dumpTasks[aindex];
79 if (!dumpTaskPtr->portOffset || (dumpTaskPtr->portCount == 0))
82 port = dumpTaskPtr->portOffset[0];
84 code = ConnectButc(dumpTaskPtr->config, port, &tconn);
88 /* count number of volumes to be dumped and
89 * build array of volumes to be sent to backup system
91 for (count = 0, tde = dumpTaskPtr->volumes; tde;
92 tde = tde->next, count++);
94 (struct tc_dumpDesc *)malloc(count * sizeof(struct tc_dumpDesc));
96 afs_com_err(whoami, BC_NOMEM, NULL);
100 for (count = 0, tde = dumpTaskPtr->volumes; tde; tde = tde->next, count++) {
101 strcpy(volDesc[count].name, tde->name);
102 volDesc[count].vid = tde->vid;
103 volDesc[count].vtype = tde->volType;
104 volDesc[count].partition = tde->partition;
105 volDesc[count].hostAddr = HOSTADDR(&tde->server); /* the internet address */
106 volDesc[count].date = tde->date;
107 volDesc[count].cloneDate = tde->cloneDate; /* Not yet known */
110 volArray.tc_dumpArray_len = count; /* element count */
111 volArray.tc_dumpArray_val = volDesc; /* and data */
113 baseNamePtr = tailCompPtr(dumpTaskPtr->dumpName);
115 /* setup the interface structure */
116 memset(tcdiPtr, 0, sizeof(*tcdiPtr));
119 strcpy(tcdiPtr->dumpPath, dumpTaskPtr->dumpName);
120 strcpy(tcdiPtr->volumeSetName, dumpTaskPtr->volSetName);
123 strcpy(tcdiPtr->tapeSet.format, dumpTaskPtr->volSetName);
124 strcat(tcdiPtr->tapeSet.format, ".");
125 strcat(tcdiPtr->tapeSet.format, baseNamePtr);
126 strcat(tcdiPtr->tapeSet.format, ".%d");
127 tcdiPtr->tapeSet.a = 1;
128 tcdiPtr->tapeSet.b = 1;
129 tcdiPtr->tapeSet.maxTapes = 1000000000;
130 tcdiPtr->tapeSet.expDate = dumpTaskPtr->expDate; /* PA */
131 tcdiPtr->tapeSet.expType = dumpTaskPtr->expType;
133 /* construct dump set name */
134 strcpy(tcdiPtr->dumpName, dumpTaskPtr->volSetName);
135 strcat(tcdiPtr->dumpName, ".");
136 strcat(tcdiPtr->dumpName, baseNamePtr);
138 tcdiPtr->parentDumpId = dumpTaskPtr->parentDumpID;
139 tcdiPtr->dumpLevel = dumpTaskPtr->dumpLevel;
140 tcdiPtr->doAppend = dumpTaskPtr->doAppend;
142 /* start the dump on the tape coordinator */
143 printf("Starting dump\n");
144 code = TC_PerformDump(tconn, tcdiPtr, &volArray, &dumpTaskPtr->dumpID);
146 afs_com_err(whoami, code, "; Failed to start dump");
150 afs_com_err(whoami, 0, "Task %u: Dump (%s)", dumpTaskPtr->dumpID,
153 /* create status monitor block */
154 statusPtr = createStatusNode();
156 statusPtr->taskId = dumpTaskPtr->dumpID;
157 statusPtr->port = port;
158 statusPtr->jobNumber = bc_jobNumber();
159 statusPtr->volsTotal = volArray.tc_dumpArray_len;
160 statusPtr->flags &= ~STARTING;
161 sprintf(statusPtr->taskName, "Dump (%s.%s)", dumpTaskPtr->volSetName,
166 /* locally allocated resources */
171 rx_DestroyConnection(tconn);
176 /* freeDumpTaskVolumeList
177 * free the list of volumes used for dumps
181 freeDumpTaskVolumeList(struct bc_volumeDump *vdptr)
183 struct bc_volumeDump *nextVdPtr;
186 nextVdPtr = vdptr->next;
197 * The other half of the dump/restore create process call. In bc_StartDmpRst,
198 * we allocated a dumpTask entry. Here we do the task and then free the entry.
201 bc_DmpRstStart(void *param)
203 afs_int32 aindex = (intptr_t)param;
204 register struct bc_dumpTask *tdump;
205 register afs_int32 code;
207 tdump = &bc_dumpTasks[aindex];
209 code = (tdump->callProc) (aindex);
213 /* Cleanup allocated data structures */
214 freeDumpTaskVolumeList(tdump->volumes);
217 free(tdump->dumpName);
220 if (tdump->volSetName)
221 free(tdump->volSetName);
222 if (tdump->portOffset)
223 free(tdump->portOffset);
224 tdump->flags &= ~BC_DI_INUSE;
226 return (void *)(intptr_t)code;
230 * function to start dump running. Packages the relevant information
231 * (from params) into any free dumpTask structure (globally allocated),
232 * and then invokes bc_DmpRstStart to do the work, passing it a single
233 * parameter, the index into the dumpTask array.
236 * aconfig - normally is bc_globalConfig
237 * aproc - bc_Dumper for doing dumps
238 * bc_Restorer for doing restores
242 bc_StartDmpRst(struct bc_config *aconfig, char *adname, char *avname,
243 struct bc_volumeDump *avolsToDump,
244 struct sockaddr_in *adestServer,
245 afs_int32 adestPartition, afs_int32 afromDate, char *anewExt,
246 int aoldFlag, afs_int32 aparent, afs_int32 alevel,
247 int (*aproc) (int), afs_int32 *ports, afs_int32 portCount,
248 struct bc_dumpSchedule *dsptr, int append, int dontExecute)
251 register afs_int32 code;
254 for (i = 0; i < BC_MAXSIMDUMPS; i++)
255 if (!(bc_dumpTasks[i].flags & BC_DI_INUSE))
258 if (i >= BC_MAXSIMDUMPS) {
259 afs_com_err(whoami, BC_NOTLOCKED,
260 "All of the dump/restore slots are in use, try again later");
261 return (BC_NOTLOCKED);
264 memset(&bc_dumpTasks[i], 0, sizeof(struct bc_dumpTask));
265 bc_dumpTasks[i].callProc = aproc;
266 bc_dumpTasks[i].config = aconfig;
267 bc_dumpTasks[i].volumes = avolsToDump;
268 bc_dumpTasks[i].flags = BC_DI_INUSE;
269 bc_dumpTasks[i].dumpName = bc_CopyString(adname);
270 bc_dumpTasks[i].volSetName = bc_CopyString(avname);
271 bc_dumpTasks[i].newExt = bc_CopyString(anewExt);
272 bc_dumpTasks[i].dumpLevel = alevel;
273 bc_dumpTasks[i].parentDumpID = aparent;
274 bc_dumpTasks[i].oldFlag = aoldFlag;
275 bc_dumpTasks[i].fromDate = afromDate;
276 bc_dumpTasks[i].destPartition = adestPartition;
277 bc_dumpTasks[i].portOffset = ports;
278 bc_dumpTasks[i].portCount = portCount;
279 bc_dumpTasks[i].doAppend = append;
280 bc_dumpTasks[i].dontExecute = dontExecute;
283 /* This should be specified for dumps, but will be 0 for restores */
284 bc_dumpTasks[i].expDate = dsptr->expDate;
285 bc_dumpTasks[i].expType = dsptr->expType;
288 memcpy(&bc_dumpTasks[i].destServer, adestServer,
289 sizeof(struct sockaddr_in));
291 memset(&bc_dumpTasks[i].destServer, 0, sizeof(struct sockaddr_in));
294 LWP_CreateProcess(bc_DmpRstStart, 20480, LWP_NORMAL_PRIORITY,
295 (void *)(intptr_t)i, "helper", junk);
298 afs_com_err(whoami, code, "; Can't start thread");
300 /* Cleanup allocated data structures */
301 freeDumpTaskVolumeList(bc_dumpTasks[i].volumes);
302 bc_dumpTasks[i].dumpID = 0;
303 if (bc_dumpTasks[i].dumpName)
304 free(bc_dumpTasks[i].dumpName);
305 if (bc_dumpTasks[i].newExt)
306 free(bc_dumpTasks[i].newExt);
307 if (bc_dumpTasks[i].volSetName)
308 free(bc_dumpTasks[i].volSetName);
309 if (bc_dumpTasks[i].portOffset)
310 free(bc_dumpTasks[i].portOffset);
311 bc_dumpTasks[i].flags &= ~BC_DI_INUSE;
320 * Returns the dump slot of the dump with dumpID
322 * dumpID - id to look for
323 * port - portoffset for tape coordinator
325 * 0-n - i.e. 0 or positive number, is the dump slot
326 * -1 - failed to find dumpID
330 bc_FindDumpSlot(afs_int32 dumpID, afs_int32 port)
334 for (i = 0; i < BC_MAXSIMDUMPS; i++) {
335 if ((bc_dumpTasks[i].flags & BC_DI_INUSE)
336 && (bc_dumpTasks[i].dumpID == dumpID)
337 && ((afs_int32) bc_dumpTasks[i].portOffset == port)) {
346 * opens a connection to the tape coordinator and requests that it
351 bc_LabelTape(char *afsname, char *pname, afs_int32 size,
352 struct bc_config *config, afs_int32 port)
354 struct rx_connection *tconn;
356 struct tc_tapeLabel label;
360 code = ConnectButc(config, port, &tconn);
364 memset(&label, 0, sizeof(label));
366 strcpy(label.afsname, afsname);
368 strcpy(label.pname, (strcmp(pname, "") ? pname : "<NULL>"));
371 code = TC_LabelTape(tconn, &label, &taskId);
373 afs_com_err(whoami, code, "; Failed to start labeltape");
377 /* create status monitor block */
378 statusPtr = createStatusNode();
380 statusPtr->taskId = taskId;
381 statusPtr->port = port;
382 statusPtr->jobNumber = bc_jobNumber();
383 /* statusPtr->flags |= SILENT; *//* don't report termination */
384 statusPtr->flags &= ~STARTING; /* ok to examine */
386 sprintf(statusPtr->taskName, "Labeltape (%s)",
387 (pname ? pname : (afsname ? afsname : "<NULL>")));
394 * open a connection to the tape coordinator and read the label on
399 bc_ReadLabel(struct bc_config *config, afs_int32 port)
401 struct rx_connection *tconn;
402 struct tc_tapeLabel label;
407 code = ConnectButc(config, port, &tconn);
411 memset(&label, 0, sizeof(label));
412 code = TC_ReadLabel(tconn, &label, &taskId);
414 if (code == BUTM_NOLABEL) {
415 printf("Tape read was unlabelled\n");
418 afs_com_err(whoami, code, "; Failed to start readlabel");
422 if (strcmp(label.pname, ""))
424 else if (strcmp(label.afsname, ""))
425 tname = label.afsname;
428 printf("Tape read was labelled : <NULL> size : %u\n", label.size);
429 } else if (!label.tapeId) {
430 printf("Tape read was labelled : %s size : %lu Kbytes\n", tname,
431 (long unsigned int) label.size);
433 printf("Tape read was labelled : %s (%lu) size : %lu Kbytes\n", tname,
434 (long unsigned int) label.tapeId, (long unsigned int) label.size);
441 bc_ScanDumps(struct bc_config *config, afs_int32 dbAddFlag, afs_int32 port)
443 struct rx_connection *tconn;
448 code = ConnectButc(config, port, &tconn);
452 code = TC_ScanDumps(tconn, dbAddFlag, &taskId);
454 afs_com_err(whoami, code, "; Failed to start scantape");
458 /* create status monitor block */
459 statusPtr = createStatusNode();
461 statusPtr->taskId = taskId;
462 statusPtr->port = port;
463 statusPtr->jobNumber = bc_jobNumber();
464 statusPtr->flags &= ~STARTING; /* ok to examine */
465 sprintf(statusPtr->taskName, "Scantape");
475 /* get a connection to the tape controller */
477 bc_GetConn(struct bc_config *aconfig, afs_int32 aport,
478 struct rx_connection **tconn)
482 static struct rx_securityClass *rxsc;
483 struct bc_hostEntry *te;
485 *tconn = (struct rx_connection *)0;
487 /* use non-secure connections to butc */
489 rxsc = rxnull_NewClientSecurityObject();
490 if (!rxsc || !aconfig)
493 for (te = aconfig->tapeHosts; te; te = te->next) {
494 if (te->portOffset == aport) {
495 /* found the right port */
496 host = te->addr.sin_addr.s_addr;
498 return (BC_NOHOSTENTRY); /* gethostbyname in bc_ParseHosts failed */
500 port = htons(BC_TAPEPORT + aport);
502 /* servers is 1; sec index is 0 */
503 *tconn = rx_NewConnection(host, port, 1, rxsc, 0);
504 return ((*tconn ? 0 : -1));
507 return (BC_NOHOSTENTRY);
511 * make sure we are talking to a compatible butc process.
514 * -1 - not compatible
518 CheckTCVersion(struct rx_connection *tconn)
520 struct tc_tcInfo tci;
523 code = TC_TCInfo(tconn, &tci);
527 if (tci.tcVersion != CUR_BUTC_VERSION)
528 return (BC_VERSIONFAIL);
534 ConnectButc(struct bc_config *config, afs_int32 port,
535 struct rx_connection **tconn)
539 code = bc_GetConn(config, port, tconn);
541 afs_com_err(whoami, code,
542 "; Can't connect to tape coordinator at port %d", port);
546 code = CheckTCVersion(*tconn);
548 rx_DestroyConnection(*tconn);
550 if (code == BC_VERSIONFAIL)
551 afs_com_err(whoami, code,
552 "; Backup and butc are not the same version");
554 afs_com_err(whoami, code,
555 "; Can't access tape coordinator at port %d", port);