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>
19 #include <sys/types.h>
24 #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 struct bc_config *bc_globalConfig;
46 extern char *bc_CopyString();
47 extern void bc_HandleMisc();
49 extern char *tailCompPtr();
50 extern statusP createStatusNode();
51 extern afs_int32 bc_jobNumber();
53 extern afs_int32 lastTaskCode;
56 #define HOSTADDR(sockaddr) (sockaddr)->sin_addr.S_un.S_addr
58 #define HOSTADDR(sockaddr) (sockaddr)->sin_addr.s_addr
62 * called (indirectly) to make a dump
64 * aindex - index into dumpTask array, contains all the information
65 * relevant to the dump
69 struct rx_connection *tconn;
70 struct tc_dumpStat dumpStat;
71 register struct bc_volumeDump *tde;
72 afs_int32 count, port;
74 struct tc_dumpDesc *volDesc = 0;
75 struct tc_dumpArray volArray;
79 struct tc_dumpInterface dumpInterface;
80 struct tc_dumpInterface *tcdiPtr = &dumpInterface;
81 register struct bc_dumpTask *dumpTaskPtr;
83 register afs_int32 code = 0;
85 dumpTaskPtr = &bc_dumpTasks[aindex];
87 if (!dumpTaskPtr->portOffset || (dumpTaskPtr->portCount == 0))
90 port = dumpTaskPtr->portOffset[0];
92 code = ConnectButc(dumpTaskPtr->config, port, &tconn);
93 if (code) return(code);
95 /* count number of volumes to be dumped and
96 * build array of volumes to be sent to backup system
98 for (count=0, tde=dumpTaskPtr->volumes; tde; tde=tde->next, count++);
99 volDesc = (struct tc_dumpDesc *) malloc(count*sizeof(struct tc_dumpDesc));
102 com_err(whoami,BC_NOMEM,"");
106 for (count=0, tde=dumpTaskPtr->volumes; tde; tde=tde->next, count++)
108 strcpy(volDesc[count].name, tde->name);
109 volDesc[count].vid = tde->vid;
110 volDesc[count].vtype = tde->volType;
111 volDesc[count].partition = tde->partition;
112 volDesc[count].hostAddr = HOSTADDR(&tde->server); /* the internet address */
113 volDesc[count].date = tde->date;
114 volDesc[count].cloneDate = tde->cloneDate; /* Not yet known */
117 volArray.tc_dumpArray_len = count; /* element count */
118 volArray.tc_dumpArray_val = volDesc; /* and data */
120 baseNamePtr = tailCompPtr(dumpTaskPtr->dumpName);
122 /* setup the interface structure */
123 memset(tcdiPtr, 0, sizeof(*tcdiPtr));
126 strcpy(tcdiPtr->dumpPath, dumpTaskPtr->dumpName);
127 strcpy(tcdiPtr->volumeSetName, dumpTaskPtr->volSetName);
130 strcpy(tcdiPtr->tapeSet.format, dumpTaskPtr->volSetName);
131 strcat(tcdiPtr->tapeSet.format, ".");
132 strcat(tcdiPtr->tapeSet.format, baseNamePtr);
133 strcat(tcdiPtr->tapeSet.format, ".%d");
134 tcdiPtr->tapeSet.a = 1;
135 tcdiPtr->tapeSet.b = 1;
136 tcdiPtr->tapeSet.maxTapes = 1000000000;
137 tcdiPtr->tapeSet.expDate = dumpTaskPtr->expDate; /* PA */
138 tcdiPtr->tapeSet.expType = dumpTaskPtr->expType;
140 /* construct dump set name */
141 strcpy(tcdiPtr->dumpName, dumpTaskPtr->volSetName);
142 strcat(tcdiPtr->dumpName, ".");
143 strcat(tcdiPtr->dumpName, baseNamePtr);
145 tcdiPtr->parentDumpId = dumpTaskPtr->parentDumpID;
146 tcdiPtr->dumpLevel = dumpTaskPtr->dumpLevel;
147 tcdiPtr->doAppend = dumpTaskPtr->doAppend;
149 /* start the dump on the tape coordinator */
150 printf("Starting dump\n");
151 code = TC_PerformDump(tconn, tcdiPtr, &volArray, &dumpTaskPtr->dumpID);
154 com_err(whoami, code, "; Failed to start dump");
158 com_err(whoami,0,"Task %u: Dump (%s)", dumpTaskPtr->dumpID, tcdiPtr->dumpName);
160 /* create status monitor block */
161 statusPtr = createStatusNode();
163 statusPtr->taskId = dumpTaskPtr->dumpID;
164 statusPtr->port = port;
165 statusPtr->jobNumber = bc_jobNumber();
166 statusPtr->volsTotal = volArray.tc_dumpArray_len;
167 statusPtr->flags &= ~STARTING;
168 sprintf(statusPtr->taskName, "Dump (%s.%s)", dumpTaskPtr->volSetName, baseNamePtr);
172 /* locally allocated resources */
173 if (volDesc) free(volDesc);
176 rx_DestroyConnection(tconn);
181 /* freeDumpTaskVolumeList
182 * free the list of volumes used for dumps
185 freeDumpTaskVolumeList(vdptr)
186 struct bc_volumeDump *vdptr;
188 struct bc_volumeDump *nextVdPtr;
192 nextVdPtr = vdptr->next;
203 * The other half of the dump/restore create process call. In bc_StartDmpRst,
204 * we allocated a dumpTask entry. Here we do the task and then free the entry.
206 bc_DmpRstStart(aindex)
209 register struct bc_dumpTask *tdump;
210 register afs_int32 code;
212 tdump = &bc_dumpTasks[aindex];
214 code = (tdump->callProc)(aindex);
215 if (code) lastTaskCode = code;
217 /* Cleanup allocated data structures */
218 freeDumpTaskVolumeList(tdump->volumes);
220 if (tdump->dumpName) free(tdump->dumpName);
221 if (tdump->newExt) free(tdump->newExt);
222 if (tdump->volSetName) free(tdump->volSetName);
223 if (tdump->portOffset) free(tdump->portOffset);
224 tdump->flags &= ~BC_DI_INUSE;
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
241 bc_StartDmpRst(aconfig, adname, avname, avolsToDump, adestServer, adestPartition,
242 afromDate, anewExt, aoldFlag, aparent, alevel, aproc, ports,
243 portCount, dsptr, append, dontExecute)
244 struct bc_config *aconfig;
247 struct bc_volumeDump *avolsToDump;
248 struct sockaddr_in *adestServer;
249 afs_int32 adestPartition;
253 afs_int32 aparent, alevel;
257 struct bc_dumpSchedule *dsptr;
258 int append, dontExecute;
261 register afs_int32 code;
264 struct bc_volumeDump *tvol, *temp;
266 for (i=0; i<BC_MAXSIMDUMPS; i++)
267 if (!(bc_dumpTasks[i].flags & BC_DI_INUSE)) break;
269 if (i >= BC_MAXSIMDUMPS)
271 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;
296 /* This should be specified for dumps, but will be 0 for restores */
297 bc_dumpTasks[i].expDate = dsptr->expDate;
298 bc_dumpTasks[i].expType = dsptr->expType;
301 memcpy(&bc_dumpTasks[i].destServer, adestServer, sizeof(struct sockaddr_in));
303 memset(&bc_dumpTasks[i].destServer, 0, sizeof(struct sockaddr_in));
305 code = LWP_CreateProcess(bc_DmpRstStart, 20480, LWP_NORMAL_PRIORITY,
306 (void *) i, "helper", &junk);
310 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) free(bc_dumpTasks[i].dumpName);
316 if (bc_dumpTasks[i].newExt) free(bc_dumpTasks[i].newExt);
317 if (bc_dumpTasks[i].volSetName) free(bc_dumpTasks[i].volSetName);
318 if (bc_dumpTasks[i].portOffset) free(bc_dumpTasks[i].portOffset);
319 bc_dumpTasks[i].flags &= ~BC_DI_INUSE;
328 * Returns the dump slot of the dump with dumpID
330 * dumpID - id to look for
331 * port - portoffset for tape coordinator
333 * 0-n - i.e. 0 or positive number, is the dump slot
334 * -1 - failed to find dumpID
338 bc_FindDumpSlot(dumpID, port)
344 for ( i = 0; i < BC_MAXSIMDUMPS; i++ )
346 if ( (bc_dumpTasks[i].flags & BC_DI_INUSE) &&
347 (bc_dumpTasks[i].dumpID == dumpID) &&
348 ((afs_int32)bc_dumpTasks[i].portOffset == port) )
358 * opens a connection to the tape coordinator and requests that it
362 bc_LabelTape (afsname, pname, size, config, port)
363 char *afsname, *pname;
364 struct bc_config *config;
368 struct rx_connection *tconn;
370 struct tc_tapeLabel label;
374 code = ConnectButc(config, port, &tconn);
375 if (code) return(code);
377 memset(&label, 0, sizeof(label));
379 strcpy(label.afsname, afsname);
381 strcpy(label.pname, (strcmp(pname,"")?pname:"<NULL>"));
384 code = TC_LabelTape(tconn, &label, &taskId);
387 com_err(whoami,code,"; Failed to start labeltape");
391 /* create status monitor block */
392 statusPtr = createStatusNode();
394 statusPtr->taskId = taskId;
395 statusPtr->port = port;
396 statusPtr->jobNumber = bc_jobNumber();
397 /* statusPtr->flags |= SILENT; */ /* don't report termination */
398 statusPtr->flags &= ~STARTING; /* ok to examine */
400 sprintf(statusPtr->taskName, "Labeltape (%s)",
401 (pname ? pname : (afsname ? afsname : "<NULL>")));
408 * open a connection to the tape coordinator and read the label on
412 bc_ReadLabel(config,port)
413 struct bc_config *config;
416 struct rx_connection *tconn;
417 struct tc_tapeLabel label;
422 code = ConnectButc(config, port, &tconn);
423 if (code) return(code);
425 memset(&label, 0, sizeof(label));
426 code = TC_ReadLabel(tconn, &label, &taskId);
428 if (code == BUTM_NOLABEL) {
429 printf("Tape read was unlabelled\n");
432 com_err(whoami,code,"; Failed to start readlabel");
436 if (strcmp(label.pname,""))
438 else if (strcmp(label.afsname,""))
439 tname = label.afsname;
442 printf("Tape read was labelled : <NULL> size : %u\n",label.size);
444 else if (!label.tapeId) {
445 printf("Tape read was labelled : %s size : %lu Kbytes\n", tname, label.size);
448 printf("Tape read was labelled : %s (%lu) size : %lu Kbytes\n",
449 tname, label.tapeId, label.size);
455 bc_ScanDumps(config, dbAddFlag, port)
456 struct bc_config *config;
460 struct rx_connection *tconn;
465 code = ConnectButc(config, port, &tconn);
466 if (code) return(code);
468 code = TC_ScanDumps(tconn, dbAddFlag, &taskId);
471 com_err(whoami, code, "; Failed to start scantape");
475 /* create status monitor block */
476 statusPtr = createStatusNode();
478 statusPtr->taskId = taskId;
479 statusPtr->port = port;
480 statusPtr->jobNumber = bc_jobNumber();
481 statusPtr->flags &= ~STARTING; /* ok to examine */
482 sprintf(statusPtr->taskName, "Scantape");
492 /* get a connection to the tape controller */
494 bc_GetConn (aconfig, aport, tconn)
495 struct bc_config *aconfig;
497 struct rx_connection **tconn;
502 static struct rx_securityClass *rxsc;
503 struct bc_hostEntry *te;
505 *tconn = (struct rx_connection *)0;
507 /* use non-secure connections to butc */
509 rxsc = rxnull_NewClientSecurityObject();
510 if (!rxsc || !aconfig) return(-1);
512 for (te = aconfig->tapeHosts; te; te = te->next)
514 if ( te->portOffset == aport )
516 /* found the right port */
517 host = te->addr.sin_addr.s_addr;
518 if (!host) return (BC_NOHOSTENTRY); /* gethostbyname in bc_ParseHosts failed */
520 port = htons(BC_TAPEPORT + aport);
522 /* servers is 1; sec index is 0 */
523 *tconn = rx_NewConnection(host, port, 1, rxsc, 0);
524 return((*tconn ? 0 : -1));
527 return(BC_NOHOSTENTRY);
531 * make sure we are talking to a compatible butc process.
534 * -1 - not compatible
537 CheckTCVersion(tconn)
538 struct rx_connection *tconn;
540 struct tc_tcInfo tci;
543 code = TC_TCInfo(tconn, &tci);
544 if (code) return(code);
546 if (tci.tcVersion != CUR_BUTC_VERSION)
547 return(BC_VERSIONFAIL);
551 ConnectButc(config, port, tconn)
552 struct bc_config *config;
554 struct rx_connection **tconn;
558 code = bc_GetConn(config, port, tconn);
561 com_err(whoami,code,"; Can't connect to tape coordinator at port %d", port);
565 code = CheckTCVersion(*tconn);
568 rx_DestroyConnection(*tconn);
570 if (code == BC_VERSIONFAIL)
571 com_err(whoami, code, "; Backup and butc are not the same version");
573 com_err(whoami, code, "; Can't access tape coordinator at port %d", port);