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>
23 #include <sys/param.h>
24 #include <sys/socket.h>
25 #include <netinet/in.h>
31 #include <afs/bubasics.h>
33 #include <afs/com_err.h>
34 #include <lock.h> /* for checking TC_ABORTFAILED. PA */
35 #include <afs/tcdata.h> /* for checking TC_ABORTFAILED. PA */
39 #include "error_macros.h"
40 #include "bucoord_internal.h"
41 #include "bucoord_prototypes.h"
43 struct bc_dumpTask bc_dumpTasks[BC_MAXSIMDUMPS];
47 extern afs_int32 lastTaskCode;
49 #define HOSTADDR(sockaddr) (sockaddr)->sin_addr.s_addr
52 * called (indirectly) to make a dump
54 * aindex - index into dumpTask array, contains all the information
55 * relevant to the dump
60 struct rx_connection *tconn;
61 register struct bc_volumeDump *tde;
62 afs_int32 count, port;
63 struct tc_dumpDesc *volDesc = 0;
64 struct tc_dumpArray volArray;
68 struct tc_dumpInterface dumpInterface;
69 struct tc_dumpInterface *tcdiPtr = &dumpInterface;
70 register struct bc_dumpTask *dumpTaskPtr;
72 register afs_int32 code = 0;
74 dumpTaskPtr = &bc_dumpTasks[aindex];
76 if (!dumpTaskPtr->portOffset || (dumpTaskPtr->portCount == 0))
79 port = dumpTaskPtr->portOffset[0];
81 code = ConnectButc(dumpTaskPtr->config, port, &tconn);
85 /* count number of volumes to be dumped and
86 * build array of volumes to be sent to backup system
88 for (count = 0, tde = dumpTaskPtr->volumes; tde;
89 tde = tde->next, count++);
91 (struct tc_dumpDesc *)malloc(count * sizeof(struct tc_dumpDesc));
93 afs_com_err(whoami, BC_NOMEM, NULL);
97 for (count = 0, tde = dumpTaskPtr->volumes; tde; tde = tde->next, count++) {
98 strcpy(volDesc[count].name, tde->name);
99 volDesc[count].vid = tde->vid;
100 volDesc[count].vtype = tde->volType;
101 volDesc[count].partition = tde->partition;
102 volDesc[count].hostAddr = HOSTADDR(&tde->server); /* the internet address */
103 volDesc[count].date = tde->date;
104 volDesc[count].cloneDate = tde->cloneDate; /* Not yet known */
107 volArray.tc_dumpArray_len = count; /* element count */
108 volArray.tc_dumpArray_val = volDesc; /* and data */
110 baseNamePtr = tailCompPtr(dumpTaskPtr->dumpName);
112 /* setup the interface structure */
113 memset(tcdiPtr, 0, sizeof(*tcdiPtr));
116 strcpy(tcdiPtr->dumpPath, dumpTaskPtr->dumpName);
117 strcpy(tcdiPtr->volumeSetName, dumpTaskPtr->volSetName);
120 strcpy(tcdiPtr->tapeSet.format, dumpTaskPtr->volSetName);
121 strcat(tcdiPtr->tapeSet.format, ".");
122 strcat(tcdiPtr->tapeSet.format, baseNamePtr);
123 strcat(tcdiPtr->tapeSet.format, ".%d");
124 tcdiPtr->tapeSet.a = 1;
125 tcdiPtr->tapeSet.b = 1;
126 tcdiPtr->tapeSet.maxTapes = 1000000000;
127 tcdiPtr->tapeSet.expDate = dumpTaskPtr->expDate; /* PA */
128 tcdiPtr->tapeSet.expType = dumpTaskPtr->expType;
130 /* construct dump set name */
131 strcpy(tcdiPtr->dumpName, dumpTaskPtr->volSetName);
132 strcat(tcdiPtr->dumpName, ".");
133 strcat(tcdiPtr->dumpName, baseNamePtr);
135 tcdiPtr->parentDumpId = dumpTaskPtr->parentDumpID;
136 tcdiPtr->dumpLevel = dumpTaskPtr->dumpLevel;
137 tcdiPtr->doAppend = dumpTaskPtr->doAppend;
139 /* start the dump on the tape coordinator */
140 printf("Starting dump\n");
141 code = TC_PerformDump(tconn, tcdiPtr, &volArray, &dumpTaskPtr->dumpID);
143 afs_com_err(whoami, code, "; Failed to start dump");
147 afs_com_err(whoami, 0, "Task %u: Dump (%s)", dumpTaskPtr->dumpID,
150 /* create status monitor block */
151 statusPtr = createStatusNode();
153 statusPtr->taskId = dumpTaskPtr->dumpID;
154 statusPtr->port = port;
155 statusPtr->jobNumber = bc_jobNumber();
156 statusPtr->volsTotal = volArray.tc_dumpArray_len;
157 statusPtr->flags &= ~STARTING;
158 sprintf(statusPtr->taskName, "Dump (%s.%s)", dumpTaskPtr->volSetName,
163 /* locally allocated resources */
168 rx_DestroyConnection(tconn);
173 /* freeDumpTaskVolumeList
174 * free the list of volumes used for dumps
178 freeDumpTaskVolumeList(struct bc_volumeDump *vdptr)
180 struct bc_volumeDump *nextVdPtr;
183 nextVdPtr = vdptr->next;
194 * The other half of the dump/restore create process call. In bc_StartDmpRst,
195 * we allocated a dumpTask entry. Here we do the task and then free the entry.
198 bc_DmpRstStart(void *param)
200 afs_int32 aindex = (intptr_t)param;
201 register struct bc_dumpTask *tdump;
202 register afs_int32 code;
204 tdump = &bc_dumpTasks[aindex];
206 code = (tdump->callProc) (aindex);
210 /* Cleanup allocated data structures */
211 freeDumpTaskVolumeList(tdump->volumes);
214 free(tdump->dumpName);
217 if (tdump->volSetName)
218 free(tdump->volSetName);
219 if (tdump->portOffset)
220 free(tdump->portOffset);
221 tdump->flags &= ~BC_DI_INUSE;
223 return (void *)(intptr_t)code;
227 * function to start dump running. Packages the relevant information
228 * (from params) into any free dumpTask structure (globally allocated),
229 * and then invokes bc_DmpRstStart to do the work, passing it a single
230 * parameter, the index into the dumpTask array.
233 * aconfig - normally is bc_globalConfig
234 * aproc - bc_Dumper for doing dumps
235 * bc_Restorer for doing restores
239 bc_StartDmpRst(struct bc_config *aconfig, char *adname, char *avname,
240 struct bc_volumeDump *avolsToDump,
241 struct sockaddr_in *adestServer,
242 afs_int32 adestPartition, afs_int32 afromDate, char *anewExt,
243 int aoldFlag, afs_int32 aparent, afs_int32 alevel,
244 int (*aproc) (int), afs_int32 *ports, afs_int32 portCount,
245 struct bc_dumpSchedule *dsptr, int append, int dontExecute)
248 register afs_int32 code;
251 for (i = 0; i < BC_MAXSIMDUMPS; i++)
252 if (!(bc_dumpTasks[i].flags & BC_DI_INUSE))
255 if (i >= BC_MAXSIMDUMPS) {
256 afs_com_err(whoami, BC_NOTLOCKED,
257 "All of the dump/restore slots are in use, try again later");
258 return (BC_NOTLOCKED);
261 memset(&bc_dumpTasks[i], 0, sizeof(struct bc_dumpTask));
262 bc_dumpTasks[i].callProc = aproc;
263 bc_dumpTasks[i].config = aconfig;
264 bc_dumpTasks[i].volumes = avolsToDump;
265 bc_dumpTasks[i].flags = BC_DI_INUSE;
266 bc_dumpTasks[i].dumpName = bc_CopyString(adname);
267 bc_dumpTasks[i].volSetName = bc_CopyString(avname);
268 bc_dumpTasks[i].newExt = bc_CopyString(anewExt);
269 bc_dumpTasks[i].dumpLevel = alevel;
270 bc_dumpTasks[i].parentDumpID = aparent;
271 bc_dumpTasks[i].oldFlag = aoldFlag;
272 bc_dumpTasks[i].fromDate = afromDate;
273 bc_dumpTasks[i].destPartition = adestPartition;
274 bc_dumpTasks[i].portOffset = ports;
275 bc_dumpTasks[i].portCount = portCount;
276 bc_dumpTasks[i].doAppend = append;
277 bc_dumpTasks[i].dontExecute = dontExecute;
280 /* This should be specified for dumps, but will be 0 for restores */
281 bc_dumpTasks[i].expDate = dsptr->expDate;
282 bc_dumpTasks[i].expType = dsptr->expType;
285 memcpy(&bc_dumpTasks[i].destServer, adestServer,
286 sizeof(struct sockaddr_in));
288 memset(&bc_dumpTasks[i].destServer, 0, sizeof(struct sockaddr_in));
291 LWP_CreateProcess(bc_DmpRstStart, 20480, LWP_NORMAL_PRIORITY,
292 (void *)(intptr_t)i, "helper", junk);
295 afs_com_err(whoami, code, "; Can't start thread");
297 /* Cleanup allocated data structures */
298 freeDumpTaskVolumeList(bc_dumpTasks[i].volumes);
299 bc_dumpTasks[i].dumpID = 0;
300 if (bc_dumpTasks[i].dumpName)
301 free(bc_dumpTasks[i].dumpName);
302 if (bc_dumpTasks[i].newExt)
303 free(bc_dumpTasks[i].newExt);
304 if (bc_dumpTasks[i].volSetName)
305 free(bc_dumpTasks[i].volSetName);
306 if (bc_dumpTasks[i].portOffset)
307 free(bc_dumpTasks[i].portOffset);
308 bc_dumpTasks[i].flags &= ~BC_DI_INUSE;
317 * Returns the dump slot of the dump with dumpID
319 * dumpID - id to look for
320 * port - portoffset for tape coordinator
322 * 0-n - i.e. 0 or positive number, is the dump slot
323 * -1 - failed to find dumpID
327 bc_FindDumpSlot(afs_int32 dumpID, afs_int32 port)
331 for (i = 0; i < BC_MAXSIMDUMPS; i++) {
332 if ((bc_dumpTasks[i].flags & BC_DI_INUSE)
333 && (bc_dumpTasks[i].dumpID == dumpID)
334 && ((afs_int32) bc_dumpTasks[i].portOffset == port)) {
343 * opens a connection to the tape coordinator and requests that it
348 bc_LabelTape(char *afsname, char *pname, afs_int32 size,
349 struct bc_config *config, afs_int32 port)
351 struct rx_connection *tconn;
353 struct tc_tapeLabel label;
357 code = ConnectButc(config, port, &tconn);
361 memset(&label, 0, sizeof(label));
363 strcpy(label.afsname, afsname);
365 strcpy(label.pname, (strcmp(pname, "") ? pname : "<NULL>"));
368 code = TC_LabelTape(tconn, &label, &taskId);
370 afs_com_err(whoami, code, "; Failed to start labeltape");
374 /* create status monitor block */
375 statusPtr = createStatusNode();
377 statusPtr->taskId = taskId;
378 statusPtr->port = port;
379 statusPtr->jobNumber = bc_jobNumber();
380 /* statusPtr->flags |= SILENT; *//* don't report termination */
381 statusPtr->flags &= ~STARTING; /* ok to examine */
383 sprintf(statusPtr->taskName, "Labeltape (%s)",
384 (pname ? pname : (afsname ? afsname : "<NULL>")));
391 * open a connection to the tape coordinator and read the label on
396 bc_ReadLabel(struct bc_config *config, afs_int32 port)
398 struct rx_connection *tconn;
399 struct tc_tapeLabel label;
404 code = ConnectButc(config, port, &tconn);
408 memset(&label, 0, sizeof(label));
409 code = TC_ReadLabel(tconn, &label, &taskId);
411 if (code == BUTM_NOLABEL) {
412 printf("Tape read was unlabelled\n");
415 afs_com_err(whoami, code, "; Failed to start readlabel");
419 if (strcmp(label.pname, ""))
421 else if (strcmp(label.afsname, ""))
422 tname = label.afsname;
425 printf("Tape read was labelled : <NULL> size : %u\n", label.size);
426 } else if (!label.tapeId) {
427 printf("Tape read was labelled : %s size : %lu Kbytes\n", tname,
428 (long unsigned int) label.size);
430 printf("Tape read was labelled : %s (%lu) size : %lu Kbytes\n", tname,
431 (long unsigned int) label.tapeId, (long unsigned int) label.size);
438 bc_ScanDumps(struct bc_config *config, afs_int32 dbAddFlag, afs_int32 port)
440 struct rx_connection *tconn;
445 code = ConnectButc(config, port, &tconn);
449 code = TC_ScanDumps(tconn, dbAddFlag, &taskId);
451 afs_com_err(whoami, code, "; Failed to start scantape");
455 /* create status monitor block */
456 statusPtr = createStatusNode();
458 statusPtr->taskId = taskId;
459 statusPtr->port = port;
460 statusPtr->jobNumber = bc_jobNumber();
461 statusPtr->flags &= ~STARTING; /* ok to examine */
462 sprintf(statusPtr->taskName, "Scantape");
472 /* get a connection to the tape controller */
474 bc_GetConn(struct bc_config *aconfig, afs_int32 aport,
475 struct rx_connection **tconn)
479 static struct rx_securityClass *rxsc;
480 struct bc_hostEntry *te;
482 *tconn = (struct rx_connection *)0;
484 /* use non-secure connections to butc */
486 rxsc = rxnull_NewClientSecurityObject();
487 if (!rxsc || !aconfig)
490 for (te = aconfig->tapeHosts; te; te = te->next) {
491 if (te->portOffset == aport) {
492 /* found the right port */
493 host = te->addr.sin_addr.s_addr;
495 return (BC_NOHOSTENTRY); /* gethostbyname in bc_ParseHosts failed */
497 port = htons(BC_TAPEPORT + aport);
499 /* servers is 1; sec index is 0 */
500 *tconn = rx_NewConnection(host, port, 1, rxsc, 0);
501 return ((*tconn ? 0 : -1));
504 return (BC_NOHOSTENTRY);
508 * make sure we are talking to a compatible butc process.
511 * -1 - not compatible
515 CheckTCVersion(struct rx_connection *tconn)
517 struct tc_tcInfo tci;
520 code = TC_TCInfo(tconn, &tci);
524 if (tci.tcVersion != CUR_BUTC_VERSION)
525 return (BC_VERSIONFAIL);
531 ConnectButc(struct bc_config *config, afs_int32 port,
532 struct rx_connection **tconn)
536 code = bc_GetConn(config, port, tconn);
538 afs_com_err(whoami, code,
539 "; Can't connect to tape coordinator at port %d", port);
543 code = CheckTCVersion(*tconn);
545 rx_DestroyConnection(*tconn);
547 if (code == BC_VERSIONFAIL)
548 afs_com_err(whoami, code,
549 "; Backup and butc are not the same version");
551 afs_com_err(whoami, code,
552 "; Can't access tape coordinator at port %d", port);