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 <afs/cellconfig.h>
23 #include <afs/bubasics.h>
25 #include <afs/com_err.h>
26 #include <lock.h> /* for checking TC_ABORTFAILED. PA */
27 #include <afs/tcdata.h> /* for checking TC_ABORTFAILED. PA */
31 #include "error_macros.h"
32 #include "bucoord_internal.h"
33 #include "bucoord_prototypes.h"
35 struct bc_dumpTask bc_dumpTasks[BC_MAXSIMDUMPS];
39 extern afs_int32 lastTaskCode;
41 #define HOSTADDR(sockaddr) (sockaddr)->sin_addr.s_addr
44 * called (indirectly) to make a dump
46 * aindex - index into dumpTask array, contains all the information
47 * relevant to the dump
52 struct rx_connection *tconn;
53 struct bc_volumeDump *tde;
54 afs_int32 count, port;
55 struct tc_dumpDesc *volDesc = NULL;
56 struct tc_dumpArray volArray;
60 struct tc_dumpInterface dumpInterface;
61 struct tc_dumpInterface *tcdiPtr = &dumpInterface;
62 struct bc_dumpTask *dumpTaskPtr;
66 dumpTaskPtr = &bc_dumpTasks[aindex];
68 if (!dumpTaskPtr->portOffset || (dumpTaskPtr->portCount == 0))
71 port = dumpTaskPtr->portOffset[0];
73 code = ConnectButc(dumpTaskPtr->config, port, &tconn);
77 /* count number of volumes to be dumped and
78 * build array of volumes to be sent to backup system
80 for (count = 0, tde = dumpTaskPtr->volumes; tde;
81 tde = tde->next, count++);
83 /* Nothing to dump, so just return success */
87 volDesc = malloc(count * sizeof(struct tc_dumpDesc));
89 afs_com_err(whoami, BC_NOMEM, NULL);
93 for (count = 0, tde = dumpTaskPtr->volumes; tde; tde = tde->next, count++) {
94 strcpy(volDesc[count].name, tde->name);
95 volDesc[count].vid = tde->vid;
96 volDesc[count].vtype = tde->volType;
97 volDesc[count].partition = tde->partition;
98 volDesc[count].hostAddr = HOSTADDR(&tde->server); /* the internet address */
99 volDesc[count].date = tde->date;
100 volDesc[count].cloneDate = tde->cloneDate; /* Not yet known */
103 volArray.tc_dumpArray_len = count; /* element count */
104 volArray.tc_dumpArray_val = volDesc; /* and data */
106 baseNamePtr = tailCompPtr(dumpTaskPtr->dumpName);
108 /* setup the interface structure */
109 memset(tcdiPtr, 0, sizeof(*tcdiPtr));
112 strcpy(tcdiPtr->dumpPath, dumpTaskPtr->dumpName);
113 strcpy(tcdiPtr->volumeSetName, dumpTaskPtr->volSetName);
116 strcpy(tcdiPtr->tapeSet.format, dumpTaskPtr->volSetName);
117 strcat(tcdiPtr->tapeSet.format, ".");
118 strcat(tcdiPtr->tapeSet.format, baseNamePtr);
119 strcat(tcdiPtr->tapeSet.format, ".%d");
120 tcdiPtr->tapeSet.a = 1;
121 tcdiPtr->tapeSet.b = 1;
122 tcdiPtr->tapeSet.maxTapes = 1000000000;
123 tcdiPtr->tapeSet.expDate = dumpTaskPtr->expDate; /* PA */
124 tcdiPtr->tapeSet.expType = dumpTaskPtr->expType;
126 /* construct dump set name */
127 strcpy(tcdiPtr->dumpName, dumpTaskPtr->volSetName);
128 strcat(tcdiPtr->dumpName, ".");
129 strcat(tcdiPtr->dumpName, baseNamePtr);
131 tcdiPtr->parentDumpId = dumpTaskPtr->parentDumpID;
132 tcdiPtr->dumpLevel = dumpTaskPtr->dumpLevel;
133 tcdiPtr->doAppend = dumpTaskPtr->doAppend;
135 /* start the dump on the tape coordinator */
136 printf("Starting dump\n");
137 code = TC_PerformDump(tconn, tcdiPtr, &volArray, &dumpTaskPtr->dumpID);
139 afs_com_err(whoami, code, "; Failed to start dump");
143 afs_com_err(whoami, 0, "Task %u: Dump (%s)", dumpTaskPtr->dumpID,
146 /* create status monitor block */
147 statusPtr = createStatusNode();
149 statusPtr->taskId = dumpTaskPtr->dumpID;
150 statusPtr->port = port;
151 statusPtr->jobNumber = bc_jobNumber();
152 statusPtr->volsTotal = volArray.tc_dumpArray_len;
153 statusPtr->flags &= ~STARTING;
154 sprintf(statusPtr->taskName, "Dump (%s.%s)", dumpTaskPtr->volSetName,
159 /* locally allocated resources */
164 rx_DestroyConnection(tconn);
169 /* freeDumpTaskVolumeList
170 * free the list of volumes used for dumps
174 freeDumpTaskVolumeList(struct bc_volumeDump *vdptr)
176 struct bc_volumeDump *nextVdPtr;
179 nextVdPtr = vdptr->next;
190 * The other half of the dump/restore create process call. In bc_StartDmpRst,
191 * we allocated a dumpTask entry. Here we do the task and then free the entry.
194 bc_DmpRstStart(void *param)
196 afs_int32 aindex = (intptr_t)param;
197 struct bc_dumpTask *tdump;
200 tdump = &bc_dumpTasks[aindex];
202 code = (tdump->callProc) (aindex);
206 /* Cleanup allocated data structures */
207 freeDumpTaskVolumeList(tdump->volumes);
210 free(tdump->dumpName);
213 if (tdump->volSetName)
214 free(tdump->volSetName);
215 if (tdump->portOffset)
216 free(tdump->portOffset);
217 tdump->flags &= ~BC_DI_INUSE;
219 return (void *)(intptr_t)code;
223 * function to start dump running. Packages the relevant information
224 * (from params) into any free dumpTask structure (globally allocated),
225 * and then invokes bc_DmpRstStart to do the work, passing it a single
226 * parameter, the index into the dumpTask array.
229 * aconfig - normally is bc_globalConfig
230 * aproc - bc_Dumper for doing dumps
231 * bc_Restorer for doing restores
235 bc_StartDmpRst(struct bc_config *aconfig, char *adname, char *avname,
236 struct bc_volumeDump *avolsToDump,
237 struct sockaddr_in *adestServer,
238 afs_int32 adestPartition, afs_int32 afromDate, char *anewExt,
239 int aoldFlag, afs_int32 aparent, afs_int32 alevel,
240 int (*aproc) (int), afs_int32 *ports, afs_int32 portCount,
241 struct bc_dumpSchedule *dsptr, int append, int dontExecute)
247 for (i = 0; i < BC_MAXSIMDUMPS; i++)
248 if (!(bc_dumpTasks[i].flags & BC_DI_INUSE))
251 if (i >= BC_MAXSIMDUMPS) {
252 afs_com_err(whoami, BC_NOTLOCKED,
253 "All of the dump/restore slots are in use, try again later");
254 return (BC_NOTLOCKED);
257 memset(&bc_dumpTasks[i], 0, sizeof(struct bc_dumpTask));
258 bc_dumpTasks[i].callProc = aproc;
259 bc_dumpTasks[i].config = aconfig;
260 bc_dumpTasks[i].volumes = avolsToDump;
261 bc_dumpTasks[i].flags = BC_DI_INUSE;
262 bc_dumpTasks[i].dumpName = bc_CopyString(adname);
263 bc_dumpTasks[i].volSetName = bc_CopyString(avname);
264 bc_dumpTasks[i].newExt = bc_CopyString(anewExt);
265 bc_dumpTasks[i].dumpLevel = alevel;
266 bc_dumpTasks[i].parentDumpID = aparent;
267 bc_dumpTasks[i].oldFlag = aoldFlag;
268 bc_dumpTasks[i].fromDate = afromDate;
269 bc_dumpTasks[i].destPartition = adestPartition;
270 bc_dumpTasks[i].portOffset = ports;
271 bc_dumpTasks[i].portCount = portCount;
272 bc_dumpTasks[i].doAppend = append;
273 bc_dumpTasks[i].dontExecute = dontExecute;
276 /* This should be specified for dumps, but will be 0 for restores */
277 bc_dumpTasks[i].expDate = dsptr->expDate;
278 bc_dumpTasks[i].expType = dsptr->expType;
281 memcpy(&bc_dumpTasks[i].destServer, adestServer,
282 sizeof(struct sockaddr_in));
284 memset(&bc_dumpTasks[i].destServer, 0, sizeof(struct sockaddr_in));
287 LWP_CreateProcess(bc_DmpRstStart, 20480, LWP_NORMAL_PRIORITY,
288 (void *)(intptr_t)i, "helper", &junk);
291 afs_com_err(whoami, code, "; Can't start thread");
293 /* Cleanup allocated data structures */
294 freeDumpTaskVolumeList(bc_dumpTasks[i].volumes);
295 bc_dumpTasks[i].dumpID = 0;
296 if (bc_dumpTasks[i].dumpName)
297 free(bc_dumpTasks[i].dumpName);
298 if (bc_dumpTasks[i].newExt)
299 free(bc_dumpTasks[i].newExt);
300 if (bc_dumpTasks[i].volSetName)
301 free(bc_dumpTasks[i].volSetName);
302 if (bc_dumpTasks[i].portOffset)
303 free(bc_dumpTasks[i].portOffset);
304 bc_dumpTasks[i].flags &= ~BC_DI_INUSE;
313 * Returns the dump slot of the dump with dumpID
315 * dumpID - id to look for
316 * port - portoffset for tape coordinator
318 * 0-n - i.e. 0 or positive number, is the dump slot
319 * -1 - failed to find dumpID
323 bc_FindDumpSlot(afs_int32 dumpID, afs_int32 port)
327 for (i = 0; i < BC_MAXSIMDUMPS; i++) {
328 if ((bc_dumpTasks[i].flags & BC_DI_INUSE)
329 && (bc_dumpTasks[i].dumpID == dumpID)
330 && ((afs_int32) bc_dumpTasks[i].portOffset == port)) {
339 * opens a connection to the tape coordinator and requests that it
344 bc_LabelTape(char *afsname, char *pname, afs_int32 size,
345 struct bc_config *config, afs_int32 port)
347 struct rx_connection *tconn;
349 struct tc_tapeLabel label;
353 code = ConnectButc(config, port, &tconn);
357 memset(&label, 0, sizeof(label));
359 strcpy(label.afsname, afsname);
361 strcpy(label.pname, (strcmp(pname, "") ? pname : "<NULL>"));
364 code = TC_LabelTape(tconn, &label, &taskId);
366 afs_com_err(whoami, code, "; Failed to start labeltape");
370 /* create status monitor block */
371 statusPtr = createStatusNode();
373 statusPtr->taskId = taskId;
374 statusPtr->port = port;
375 statusPtr->jobNumber = bc_jobNumber();
376 /* statusPtr->flags |= SILENT; *//* don't report termination */
377 statusPtr->flags &= ~STARTING; /* ok to examine */
379 sprintf(statusPtr->taskName, "Labeltape (%s)",
380 (pname ? pname : (afsname ? afsname : "<NULL>")));
387 * open a connection to the tape coordinator and read the label on
392 bc_ReadLabel(struct bc_config *config, afs_int32 port)
394 struct rx_connection *tconn;
395 struct tc_tapeLabel label;
400 code = ConnectButc(config, port, &tconn);
404 memset(&label, 0, sizeof(label));
405 code = TC_ReadLabel(tconn, &label, &taskId);
407 if (code == BUTM_NOLABEL) {
408 printf("Tape read was unlabelled\n");
411 afs_com_err(whoami, code, "; Failed to start readlabel");
415 if (strcmp(label.pname, ""))
417 else if (strcmp(label.afsname, ""))
418 tname = label.afsname;
421 printf("Tape read was labelled : <NULL> size : %u\n", label.size);
422 } else if (!label.tapeId) {
423 printf("Tape read was labelled : %s size : %lu Kbytes\n", tname,
424 (long unsigned int) label.size);
426 printf("Tape read was labelled : %s (%lu) size : %lu Kbytes\n", tname,
427 (long unsigned int) label.tapeId, (long unsigned int) label.size);
434 bc_ScanDumps(struct bc_config *config, afs_int32 dbAddFlag, afs_int32 port)
436 struct rx_connection *tconn;
441 code = ConnectButc(config, port, &tconn);
445 code = TC_ScanDumps(tconn, dbAddFlag, &taskId);
447 afs_com_err(whoami, code, "; Failed to start scantape");
451 /* create status monitor block */
452 statusPtr = createStatusNode();
454 statusPtr->taskId = taskId;
455 statusPtr->port = port;
456 statusPtr->jobNumber = bc_jobNumber();
457 statusPtr->flags &= ~STARTING; /* ok to examine */
458 sprintf(statusPtr->taskName, "Scantape");
468 /* get a connection to the tape controller */
470 bc_GetConn(struct bc_config *aconfig, afs_int32 aport,
471 struct rx_connection **tconn)
476 static struct rx_securityClass *rxsc;
477 static afs_int32 scIndex;
478 struct bc_hostEntry *te;
480 *tconn = (struct rx_connection *)0;
482 /* use non-secure connections to butc */
484 struct afsconf_dir *dir;
485 afsconf_secflags flags = AFSCONF_SECOPTS_FALLBACK_NULL;
489 flags |= AFSCONF_SECOPTS_NOAUTH;
491 flags |= AFSCONF_SECOPTS_LOCALAUTH;
492 dir = afsconf_Open(AFSDIR_SERVER_ETC_DIRPATH);
494 dir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
496 if (tcell[0] == '\0')
500 /* No need for cell info since butc is not a registered service */
501 code = afsconf_PickClientSecObj(dir, flags, NULL, cname, &rxsc, &scIndex,
508 if (!rxsc || !aconfig)
511 for (te = aconfig->tapeHosts; te; te = te->next) {
512 if (te->portOffset == aport) {
513 /* found the right port */
514 host = te->addr.sin_addr.s_addr;
516 return (BC_NOHOSTENTRY); /* gethostbyname in bc_ParseHosts failed */
518 port = htons(BC_TAPEPORT + aport);
521 *tconn = rx_NewConnection(host, port, 1, rxsc, scIndex);
522 return ((*tconn ? 0 : -1));
525 return (BC_NOHOSTENTRY);
529 * make sure we are talking to a compatible butc process.
532 * -1 - not compatible
536 CheckTCVersion(struct rx_connection *tconn)
538 struct tc_tcInfo tci;
541 code = TC_TCInfo(tconn, &tci);
545 if (tci.tcVersion != CUR_BUTC_VERSION)
546 return (BC_VERSIONFAIL);
552 ConnectButc(struct bc_config *config, afs_int32 port,
553 struct rx_connection **tconn)
557 code = bc_GetConn(config, port, tconn);
559 afs_com_err(whoami, code,
560 "; Can't connect to tape coordinator at port %d", port);
564 code = CheckTCVersion(*tconn);
566 rx_DestroyConnection(*tconn);
568 if (code == BC_VERSIONFAIL)
569 afs_com_err(whoami, code,
570 "; Backup and butc are not the same version");
572 afs_com_err(whoami, code,
573 "; Can't access tape coordinator at port %d", port);