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>
22 #include <afs/bubasics.h>
24 #include <afs/com_err.h>
25 #include <lock.h> /* for checking TC_ABORTFAILED. PA */
26 #include <afs/tcdata.h> /* for checking TC_ABORTFAILED. PA */
30 #include "error_macros.h"
31 #include "bucoord_internal.h"
32 #include "bucoord_prototypes.h"
34 struct bc_dumpTask bc_dumpTasks
[BC_MAXSIMDUMPS
];
38 extern afs_int32 lastTaskCode
;
40 #define HOSTADDR(sockaddr) (sockaddr)->sin_addr.s_addr
43 * called (indirectly) to make a dump
45 * aindex - index into dumpTask array, contains all the information
46 * relevant to the dump
51 struct rx_connection
*tconn
;
52 struct bc_volumeDump
*tde
;
53 afs_int32 count
, port
;
54 struct tc_dumpDesc
*volDesc
= NULL
;
55 struct tc_dumpArray volArray
;
59 struct tc_dumpInterface dumpInterface
;
60 struct tc_dumpInterface
*tcdiPtr
= &dumpInterface
;
61 struct bc_dumpTask
*dumpTaskPtr
;
65 dumpTaskPtr
= &bc_dumpTasks
[aindex
];
67 if (!dumpTaskPtr
->portOffset
|| (dumpTaskPtr
->portCount
== 0))
70 port
= dumpTaskPtr
->portOffset
[0];
72 code
= ConnectButc(dumpTaskPtr
->config
, port
, &tconn
);
76 /* count number of volumes to be dumped and
77 * build array of volumes to be sent to backup system
79 for (count
= 0, tde
= dumpTaskPtr
->volumes
; tde
;
80 tde
= tde
->next
, count
++);
82 /* Nothing to dump, so just return success */
86 volDesc
= malloc(count
* sizeof(struct tc_dumpDesc
));
88 afs_com_err(whoami
, BC_NOMEM
, NULL
);
92 for (count
= 0, tde
= dumpTaskPtr
->volumes
; tde
; tde
= tde
->next
, count
++) {
93 strcpy(volDesc
[count
].name
, tde
->name
);
94 volDesc
[count
].vid
= tde
->vid
;
95 volDesc
[count
].vtype
= tde
->volType
;
96 volDesc
[count
].partition
= tde
->partition
;
97 volDesc
[count
].hostAddr
= HOSTADDR(&tde
->server
); /* the internet address */
98 volDesc
[count
].date
= tde
->date
;
99 volDesc
[count
].cloneDate
= tde
->cloneDate
; /* Not yet known */
102 volArray
.tc_dumpArray_len
= count
; /* element count */
103 volArray
.tc_dumpArray_val
= volDesc
; /* and data */
105 baseNamePtr
= tailCompPtr(dumpTaskPtr
->dumpName
);
107 /* setup the interface structure */
108 memset(tcdiPtr
, 0, sizeof(*tcdiPtr
));
111 strcpy(tcdiPtr
->dumpPath
, dumpTaskPtr
->dumpName
);
112 strcpy(tcdiPtr
->volumeSetName
, dumpTaskPtr
->volSetName
);
115 strcpy(tcdiPtr
->tapeSet
.format
, dumpTaskPtr
->volSetName
);
116 strcat(tcdiPtr
->tapeSet
.format
, ".");
117 strcat(tcdiPtr
->tapeSet
.format
, baseNamePtr
);
118 strcat(tcdiPtr
->tapeSet
.format
, ".%d");
119 tcdiPtr
->tapeSet
.a
= 1;
120 tcdiPtr
->tapeSet
.b
= 1;
121 tcdiPtr
->tapeSet
.maxTapes
= 1000000000;
122 tcdiPtr
->tapeSet
.expDate
= dumpTaskPtr
->expDate
; /* PA */
123 tcdiPtr
->tapeSet
.expType
= dumpTaskPtr
->expType
;
125 /* construct dump set name */
126 strcpy(tcdiPtr
->dumpName
, dumpTaskPtr
->volSetName
);
127 strcat(tcdiPtr
->dumpName
, ".");
128 strcat(tcdiPtr
->dumpName
, baseNamePtr
);
130 tcdiPtr
->parentDumpId
= dumpTaskPtr
->parentDumpID
;
131 tcdiPtr
->dumpLevel
= dumpTaskPtr
->dumpLevel
;
132 tcdiPtr
->doAppend
= dumpTaskPtr
->doAppend
;
134 /* start the dump on the tape coordinator */
135 printf("Starting dump\n");
136 code
= TC_PerformDump(tconn
, tcdiPtr
, &volArray
, &dumpTaskPtr
->dumpID
);
138 afs_com_err(whoami
, code
, "; Failed to start dump");
142 afs_com_err(whoami
, 0, "Task %u: Dump (%s)", dumpTaskPtr
->dumpID
,
145 /* create status monitor block */
146 statusPtr
= createStatusNode();
148 statusPtr
->taskId
= dumpTaskPtr
->dumpID
;
149 statusPtr
->port
= port
;
150 statusPtr
->jobNumber
= bc_jobNumber();
151 statusPtr
->volsTotal
= volArray
.tc_dumpArray_len
;
152 statusPtr
->flags
&= ~STARTING
;
153 sprintf(statusPtr
->taskName
, "Dump (%s.%s)", dumpTaskPtr
->volSetName
,
158 /* locally allocated resources */
163 rx_DestroyConnection(tconn
);
168 /* freeDumpTaskVolumeList
169 * free the list of volumes used for dumps
173 freeDumpTaskVolumeList(struct bc_volumeDump
*vdptr
)
175 struct bc_volumeDump
*nextVdPtr
;
178 nextVdPtr
= vdptr
->next
;
189 * The other half of the dump/restore create process call. In bc_StartDmpRst,
190 * we allocated a dumpTask entry. Here we do the task and then free the entry.
193 bc_DmpRstStart(void *param
)
195 afs_int32 aindex
= (intptr_t)param
;
196 struct bc_dumpTask
*tdump
;
199 tdump
= &bc_dumpTasks
[aindex
];
201 code
= (tdump
->callProc
) (aindex
);
205 /* Cleanup allocated data structures */
206 freeDumpTaskVolumeList(tdump
->volumes
);
209 free(tdump
->dumpName
);
212 if (tdump
->volSetName
)
213 free(tdump
->volSetName
);
214 if (tdump
->portOffset
)
215 free(tdump
->portOffset
);
216 tdump
->flags
&= ~BC_DI_INUSE
;
218 return (void *)(intptr_t)code
;
222 * function to start dump running. Packages the relevant information
223 * (from params) into any free dumpTask structure (globally allocated),
224 * and then invokes bc_DmpRstStart to do the work, passing it a single
225 * parameter, the index into the dumpTask array.
228 * aconfig - normally is bc_globalConfig
229 * aproc - bc_Dumper for doing dumps
230 * bc_Restorer for doing restores
234 bc_StartDmpRst(struct bc_config
*aconfig
, char *adname
, char *avname
,
235 struct bc_volumeDump
*avolsToDump
,
236 struct sockaddr_in
*adestServer
,
237 afs_int32 adestPartition
, afs_int32 afromDate
, char *anewExt
,
238 int aoldFlag
, afs_int32 aparent
, afs_int32 alevel
,
239 int (*aproc
) (int), afs_int32
*ports
, afs_int32 portCount
,
240 struct bc_dumpSchedule
*dsptr
, int append
, int dontExecute
)
246 for (i
= 0; i
< BC_MAXSIMDUMPS
; i
++)
247 if (!(bc_dumpTasks
[i
].flags
& BC_DI_INUSE
))
250 if (i
>= BC_MAXSIMDUMPS
) {
251 afs_com_err(whoami
, BC_NOTLOCKED
,
252 "All of the dump/restore slots are in use, try again later");
253 return (BC_NOTLOCKED
);
256 memset(&bc_dumpTasks
[i
], 0, sizeof(struct bc_dumpTask
));
257 bc_dumpTasks
[i
].callProc
= aproc
;
258 bc_dumpTasks
[i
].config
= aconfig
;
259 bc_dumpTasks
[i
].volumes
= avolsToDump
;
260 bc_dumpTasks
[i
].flags
= BC_DI_INUSE
;
261 bc_dumpTasks
[i
].dumpName
= bc_CopyString(adname
);
262 bc_dumpTasks
[i
].volSetName
= bc_CopyString(avname
);
263 bc_dumpTasks
[i
].newExt
= bc_CopyString(anewExt
);
264 bc_dumpTasks
[i
].dumpLevel
= alevel
;
265 bc_dumpTasks
[i
].parentDumpID
= aparent
;
266 bc_dumpTasks
[i
].oldFlag
= aoldFlag
;
267 bc_dumpTasks
[i
].fromDate
= afromDate
;
268 bc_dumpTasks
[i
].destPartition
= adestPartition
;
269 bc_dumpTasks
[i
].portOffset
= ports
;
270 bc_dumpTasks
[i
].portCount
= portCount
;
271 bc_dumpTasks
[i
].doAppend
= append
;
272 bc_dumpTasks
[i
].dontExecute
= dontExecute
;
275 /* This should be specified for dumps, but will be 0 for restores */
276 bc_dumpTasks
[i
].expDate
= dsptr
->expDate
;
277 bc_dumpTasks
[i
].expType
= dsptr
->expType
;
280 memcpy(&bc_dumpTasks
[i
].destServer
, adestServer
,
281 sizeof(struct sockaddr_in
));
283 memset(&bc_dumpTasks
[i
].destServer
, 0, sizeof(struct sockaddr_in
));
286 LWP_CreateProcess(bc_DmpRstStart
, 20480, LWP_NORMAL_PRIORITY
,
287 (void *)(intptr_t)i
, "helper", &junk
);
290 afs_com_err(whoami
, code
, "; Can't start thread");
292 /* Cleanup allocated data structures */
293 freeDumpTaskVolumeList(bc_dumpTasks
[i
].volumes
);
294 bc_dumpTasks
[i
].dumpID
= 0;
295 if (bc_dumpTasks
[i
].dumpName
)
296 free(bc_dumpTasks
[i
].dumpName
);
297 if (bc_dumpTasks
[i
].newExt
)
298 free(bc_dumpTasks
[i
].newExt
);
299 if (bc_dumpTasks
[i
].volSetName
)
300 free(bc_dumpTasks
[i
].volSetName
);
301 if (bc_dumpTasks
[i
].portOffset
)
302 free(bc_dumpTasks
[i
].portOffset
);
303 bc_dumpTasks
[i
].flags
&= ~BC_DI_INUSE
;
312 * Returns the dump slot of the dump with dumpID
314 * dumpID - id to look for
315 * port - portoffset for tape coordinator
317 * 0-n - i.e. 0 or positive number, is the dump slot
318 * -1 - failed to find dumpID
322 bc_FindDumpSlot(afs_int32 dumpID
, afs_int32 port
)
326 for (i
= 0; i
< BC_MAXSIMDUMPS
; i
++) {
327 if ((bc_dumpTasks
[i
].flags
& BC_DI_INUSE
)
328 && (bc_dumpTasks
[i
].dumpID
== dumpID
)
329 && ((afs_int32
) bc_dumpTasks
[i
].portOffset
== port
)) {
338 * opens a connection to the tape coordinator and requests that it
343 bc_LabelTape(char *afsname
, char *pname
, afs_int32 size
,
344 struct bc_config
*config
, afs_int32 port
)
346 struct rx_connection
*tconn
;
348 struct tc_tapeLabel label
;
352 code
= ConnectButc(config
, port
, &tconn
);
356 memset(&label
, 0, sizeof(label
));
358 strcpy(label
.afsname
, afsname
);
360 strcpy(label
.pname
, (strcmp(pname
, "") ? pname
: "<NULL>"));
363 code
= TC_LabelTape(tconn
, &label
, &taskId
);
365 afs_com_err(whoami
, code
, "; Failed to start labeltape");
369 /* create status monitor block */
370 statusPtr
= createStatusNode();
372 statusPtr
->taskId
= taskId
;
373 statusPtr
->port
= port
;
374 statusPtr
->jobNumber
= bc_jobNumber();
375 /* statusPtr->flags |= SILENT; *//* don't report termination */
376 statusPtr
->flags
&= ~STARTING
; /* ok to examine */
378 sprintf(statusPtr
->taskName
, "Labeltape (%s)",
379 (pname
? pname
: (afsname
? afsname
: "<NULL>")));
386 * open a connection to the tape coordinator and read the label on
391 bc_ReadLabel(struct bc_config
*config
, afs_int32 port
)
393 struct rx_connection
*tconn
;
394 struct tc_tapeLabel label
;
399 code
= ConnectButc(config
, port
, &tconn
);
403 memset(&label
, 0, sizeof(label
));
404 code
= TC_ReadLabel(tconn
, &label
, &taskId
);
406 if (code
== BUTM_NOLABEL
) {
407 printf("Tape read was unlabelled\n");
410 afs_com_err(whoami
, code
, "; Failed to start readlabel");
414 if (strcmp(label
.pname
, ""))
416 else if (strcmp(label
.afsname
, ""))
417 tname
= label
.afsname
;
420 printf("Tape read was labelled : <NULL> size : %u\n", label
.size
);
421 } else if (!label
.tapeId
) {
422 printf("Tape read was labelled : %s size : %lu Kbytes\n", tname
,
423 (long unsigned int) label
.size
);
425 printf("Tape read was labelled : %s (%lu) size : %lu Kbytes\n", tname
,
426 (long unsigned int) label
.tapeId
, (long unsigned int) label
.size
);
433 bc_ScanDumps(struct bc_config
*config
, afs_int32 dbAddFlag
, afs_int32 port
)
435 struct rx_connection
*tconn
;
440 code
= ConnectButc(config
, port
, &tconn
);
444 code
= TC_ScanDumps(tconn
, dbAddFlag
, &taskId
);
446 afs_com_err(whoami
, code
, "; Failed to start scantape");
450 /* create status monitor block */
451 statusPtr
= createStatusNode();
453 statusPtr
->taskId
= taskId
;
454 statusPtr
->port
= port
;
455 statusPtr
->jobNumber
= bc_jobNumber();
456 statusPtr
->flags
&= ~STARTING
; /* ok to examine */
457 sprintf(statusPtr
->taskName
, "Scantape");
467 /* get a connection to the tape controller */
469 bc_GetConn(struct bc_config
*aconfig
, afs_int32 aport
,
470 struct rx_connection
**tconn
)
474 static struct rx_securityClass
*rxsc
;
475 struct bc_hostEntry
*te
;
477 *tconn
= (struct rx_connection
*)0;
479 /* use non-secure connections to butc */
481 rxsc
= rxnull_NewClientSecurityObject();
482 if (!rxsc
|| !aconfig
)
485 for (te
= aconfig
->tapeHosts
; te
; te
= te
->next
) {
486 if (te
->portOffset
== aport
) {
487 /* found the right port */
488 host
= te
->addr
.sin_addr
.s_addr
;
490 return (BC_NOHOSTENTRY
); /* gethostbyname in bc_ParseHosts failed */
492 port
= htons(BC_TAPEPORT
+ aport
);
494 /* servers is 1; sec index is 0 */
495 *tconn
= rx_NewConnection(host
, port
, 1, rxsc
, 0);
496 return ((*tconn
? 0 : -1));
499 return (BC_NOHOSTENTRY
);
503 * make sure we are talking to a compatible butc process.
506 * -1 - not compatible
510 CheckTCVersion(struct rx_connection
*tconn
)
512 struct tc_tcInfo tci
;
515 code
= TC_TCInfo(tconn
, &tci
);
519 if (tci
.tcVersion
!= CUR_BUTC_VERSION
)
520 return (BC_VERSIONFAIL
);
526 ConnectButc(struct bc_config
*config
, afs_int32 port
,
527 struct rx_connection
**tconn
)
531 code
= bc_GetConn(config
, port
, tconn
);
533 afs_com_err(whoami
, code
,
534 "; Can't connect to tape coordinator at port %d", port
);
538 code
= CheckTCVersion(*tconn
);
540 rx_DestroyConnection(*tconn
);
542 if (code
== BC_VERSIONFAIL
)
543 afs_com_err(whoami
, code
,
544 "; Backup and butc are not the same version");
546 afs_com_err(whoami
, code
,
547 "; Can't access tape coordinator at port %d", port
);