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
);