Bug Summary

File:butc/dump.c
Location:line 1207, column 2
Description:Assigned value is always the same as the existing value

Annotated Source Code

1/*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
4 *
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
8 */
9
10#include <afsconfig.h>
11#include <afs/param.h>
12
13#include <roken.h>
14
15#include <rx/xdr.h>
16#include <rx/rx.h>
17#include <lwp.h>
18#include <lock.h>
19#include <afs/tcdata.h>
20#include <afs/bubasics.h>
21#include <afs/budb_client.h>
22#include <afs/butm_prototypes.h>
23#include <afs/vldbint.h>
24#include <afs/ktime.h>
25#include <afs/vlserver.h>
26#include <afs/volser.h>
27#include <afs/volser_prototypes.h>
28#include <afs/volint.h>
29#include <afs/cellconfig.h>
30#include <afs/bucoord_prototypes.h>
31
32#include "butc_internal.h"
33#include "error_macros.h"
34#include "butc_xbsa.h"
35#include "afs/butx.h"
36
37/* GLOBAL CONFIGURATION PARAMETERS */
38extern int dump_namecheck;
39extern int queryoperator;
40extern int isafile;
41extern int forcemultiple;
42
43extern struct ubik_client *cstruct;
44dlqlinkT savedEntries;
45dlqlinkT entries_to_flush;
46
47extern afs_int32 groupId;
48extern afs_int32 BufferSize;
49extern afs_int32 statusSize;
50extern FILE *centralLogIO;
51afs_int32 lastPass = 0;
52#ifdef xbsa
53extern afs_int32 xbsaType;
54char *butcdumpIdStr = "/backup_afs_volume_dumps";
55extern struct butx_transactionInfo butxInfo;
56extern char *xbsaObjectOwner;
57extern char *appObjectOwner;
58extern char *xbsaSecToken;
59extern char *xbsalGName;
60extern char *globalButcLog;
61#endif /*xbsa */
62
63afs_int32 dataSize; /* Size of data to read on each rx_Read() call */
64afs_int32 tapeblocks; /* Number of 16K tape datablocks in buffer (!CONF_XBSA) */
65
66/* TBD
67 *
68 * Done 1) dump id generation
69 * Done xx) volume fragment number accounting !! I think.
70 * 2) check abort - check after subroutine calls
71 * Done 3) trailer anomaly
72 * 4) trailer damage indicator after partial dumps ( affects scandump )
73 * Done 5) Ensure mount failure logged
74 * 6) Ensure bucoord status calls work
75 *
76 * notes
77 * pass 3:
78 * keep token timeout. If no user reponse (idle time > some period)
79 * and tokens about to time out, terminate dump. This provides at
80 * least something usable.
81 */
82
83#define DUMPNAME(dumpname, name, dbDumpId)if (dbDumpId == 0) sprintf(dumpname, "%s", name); else sprintf
(dumpname, "%s (DumpId %u)", name, dbDumpId);
\
84 if (dbDumpId == 0) \
85 sprintf(dumpname, "%s", name); \
86 else \
87 sprintf(dumpname, "%s (DumpId %u)", name, dbDumpId);
88
89struct dumpRock {
90 /* status only */
91 int tapeSeq;
92 int curVolume; /* index in dumpNode of volume */
93 int curVolumeStatus; /* more explicit dump state */
94 afs_uint32 curVolStartPos; /* Starting position of the current volume */
95 afs_uint32 databaseDumpId; /* real dump id, for db */
96 afs_uint32 initialDumpId; /* the initial dump, for appended dumps */
97 afs_int32 volumesDumped; /* # volumes successfully dumped */
98 afs_int32 volumesFailed; /* # volumes that failed to dump */
99 afs_int32 volumesNotDumped; /* # volumes that were not dumped (didn't fail) */
100
101 /* tape management */
102 char tapeName[TC_MAXTAPENAMELEN100];
103 struct butm_tapeInfo *tapeInfoPtr;
104 struct butm_tapeLabel tapeLabel;
105 int wroteLabel; /* If the tape label is written */
106
107 /* database information */
108 struct budb_dumpEntry lastDump; /* the last dump of this volset */
109 struct budb_dumpEntry dump; /* current dump */
110 struct budb_tapeEntry tape; /* current tape, not used -VA */
111
112 /* links to existing info */
113 struct dumpNode *node;
114};
115
116/* Forward declarations */
117
118int makeVolumeHeader(struct volumeHeader *, struct dumpRock *, int);
119int volumeHeader_hton(struct volumeHeader *, struct volumeHeader *);
120char retryPrompt(char *, afs_int32, afs_uint32);
121int getDumpTape(struct dumpRock *, int, afs_int32);
122int getXBSATape(struct dumpRock *);
123afs_int32 createDump(struct dumpRock *);
124
125/* configuration variables */
126#define HITEOT(code)((code == (156568837L)) || (code == (156568842L)) || (code ==
(156568848L)))
((code == BUTM_IO(156568837L)) || (code == BUTM_EOT(156568842L)) || (code == BUTM_IOCTL(156568848L)))
127extern int autoQuery;
128extern int maxpass;
129
130afs_int32 tc_EndMargin;
131afs_int32 tc_KEndMargin;
132static char *bufferBlock;
133
134/* compute the absolute expiration date */
135afs_int32
136calcExpirationDate(afs_int32 expType, afs_int32 expDate, afs_int32 createTime)
137{
138 struct ktime_date kd;
139
140 switch (expType) {
141 case BC_REL_EXPDATE2:
142 /* expiration date is relative to the creation time of the dump.
143 * This is the only case that requires any work
144 */
145 Int32To_ktimeRelDate(expDate, &kd);
146 return (Add_RelDate_to_Time(&kd, createTime));
147
148 case BC_ABS_EXPDATE1:
149 return (expDate);
150
151 case BC_NO_EXPDATE0:
152 default:
153 return (0);
154 }
155}
156
157afs_uint32 curr_bserver = 0;
158struct rx_connection *curr_fromconn = (struct rx_connection *)0;
159
160struct rx_connection *
161Bind(afs_uint32 server)
162{
163 if (curr_fromconn) {
164 if (curr_bserver == server) /* Keep connection if have it */
165 return (curr_fromconn);
166
167 rx_DestroyConnection(curr_fromconn); /* Otherwise get rid of it */
168 curr_fromconn = (struct rx_connection *)0;
169 curr_bserver = 0;
170 }
171
172 if (server) {
173 curr_fromconn = UV_Bind(server, AFSCONF_VOLUMEPORT7005); /* Establish new connection */
174 if (curr_fromconn)
175 curr_bserver = server;
176 }
177
178 return (curr_fromconn);
179}
180
181/* notes
182 * 1) save the chunksize or otherwise ensure tape space remaining is
183 * check frequently enough
184 * 2) This is called once. For partial dumps, need to
185 * ensure that the tape device is left in the correct state for
186 * further dumps.
187 *
188 */
189#define BIGCHUNK102400 102400
190
191afs_int32
192dumpVolume(struct tc_dumpDesc * curDump, struct dumpRock * dparamsPtr)
193{
194 struct butm_tapeInfo *tapeInfoPtr = dparamsPtr->tapeInfoPtr;
195 struct dumpNode *nodePtr = dparamsPtr->node;
196 afs_int32 taskId = nodePtr->taskID;
197 char *buffer;
198 int fragmentNumber;
199 afs_int32 volumeFlags;
200 afs_int32 kRemaining;
201 afs_int32 rc, code = 0;
202 afs_int32 toread;
203 afs_uint32 volBytesRead;
204 afs_uint32 chunkSize;
205 afs_int32 bytesread; /* rx reads */
206 int endofvolume = 0; /* Have we read all volume data */
207 int indump = 0;
208 int fragmentvolume;
209 struct volumeHeader hostVolumeHeader;
210
211 struct rx_call *fromcall = (struct rx_call *)0;
212 struct rx_connection *fromconn;
213 afs_int32 updatedate, fromtid = 0;
214 volEntries volumeInfo;
215 afs_int32 bytesWritten;
216 afs_uint32 statuscount = statusSize, tsize = 0;
217
218 dparamsPtr->curVolumeStatus = DUMP_NOTHING6;
219
220 fromconn = Bind(htonl(curDump->hostAddr)(__builtin_constant_p(curDump->hostAddr) ? ((((__uint32_t)
(curDump->hostAddr)) >> 24) | ((((__uint32_t)(curDump
->hostAddr)) & (0xff << 16)) >> 8) | ((((__uint32_t
)(curDump->hostAddr)) & (0xff << 8)) << 8)
| (((__uint32_t)(curDump->hostAddr)) << 24)) : __bswap32_var
(curDump->hostAddr))
); /* get connection to the server */
221
222 /* Determine when the volume was last cloned and updated */
223 volumeInfo.volEntries_val = (volintInfo *) 0;
224 volumeInfo.volEntries_len = 0;
225 rc = AFSVolListOneVolume(fromconn, curDump->partition, curDump->vid,
226 &volumeInfo);
227 if (rc)
228 ERROR_EXIT(rc)do { code = rc; goto error_exit; } while (0);
229 updatedate = volumeInfo.volEntries_val[0].updateDate;
230 curDump->cloneDate =
231 ((curDump->vtype ==
232 RWVOL0) ? time(0) : volumeInfo.volEntries_val[0].creationDate);
233
234 if (curDump->date >= curDump->cloneDate)
235 ERROR_EXIT(0)do { code = 0; goto error_exit; } while (0); /* not recloned since last dump */
236 if (curDump->date > updatedate) {
237 dparamsPtr->curVolumeStatus = DUMP_NODUMP7; /* not modified since last dump */
238 ERROR_EXIT(0)do { code = 0; goto error_exit; } while (0);
239 }
240
241 /* Start the volserver transaction and dump */
242 rc = AFSVolTransCreate(fromconn, curDump->vid, curDump->partition, ITBusy2,
243 &fromtid);
244 if (rc)
245 ERROR_EXIT(rc)do { code = rc; goto error_exit; } while (0);
246 fromcall = rx_NewCall(fromconn);
247
248 rc = StartAFSVolDump(fromcall, fromtid, curDump->date);
249 if (rc)
250 ERROR_EXIT(rc)do { code = rc; goto error_exit; } while (0);
251
252 dparamsPtr->curVolumeStatus = DUMP_PARTIAL2;
253 dparamsPtr->curVolStartPos = tapeInfoPtr->position;
254
255 /* buffer is place in bufferBlock to write volume data.
256 * butm_writeFileData() assumes the previous BUTM_HDRSIZE bytes
257 * is available to write the tape block header.
258 */
259 buffer = bufferBlock + BUTM_HDRSIZE((5*sizeof(afs_int32)) + sizeof(int));
260
261 /* Dump one volume fragment at a time until we dump the full volume.
262 * A volume with more than 1 fragment means the volume will 'span'
263 * 2 or more tapes.
264 */
265 for (fragmentNumber = 1; !endofvolume; fragmentNumber++) { /*frag */
266 rc = butm_WriteFileBegin(tapeInfoPtr)(*((tapeInfoPtr)->ops.writeFileBegin))(tapeInfoPtr);
267 if (rc) {
268 ErrorLog(1, taskId, rc, tapeInfoPtr->error,
269 "Can't write FileBegin on tape\n");
270 ERROR_EXIT(rc)do { code = rc; goto error_exit; } while (0);
271 }
272 indump = 1; /* first write to tape */
273
274 /* Create and Write the volume header */
275 makeVolumeHeader(&hostVolumeHeader, dparamsPtr, fragmentNumber);
276 hostVolumeHeader.contd = ((fragmentNumber == 1) ? 0 : TC_VOLCONTD0xffffffff);
277 volumeHeader_hton(&hostVolumeHeader, (struct volumeHeader *)buffer);
278
279 rc = butm_WriteFileData(tapeInfoPtr, buffer, 1,(*((tapeInfoPtr)->ops.writeFileData))(tapeInfoPtr,buffer,1
,sizeof(hostVolumeHeader))
280 sizeof(hostVolumeHeader))(*((tapeInfoPtr)->ops.writeFileData))(tapeInfoPtr,buffer,1
,sizeof(hostVolumeHeader))
;
281 if (rc) {
282 ErrorLog(1, taskId, rc, tapeInfoPtr->error,
283 "Can't write VolumeHeader on tape\n");
284 ERROR_EXIT(rc)do { code = rc; goto error_exit; } while (0);
285 }
286
287 bytesWritten = BUTM_BLOCKSIZE16384; /* Wrote one tapeblock */
288 tsize += bytesWritten;
289
290 /* Start reading volume data, rx_Read(), and dumping to the tape
291 * until we've dumped the entire volume (endofvolume == 1). We can
292 * exit this loop early if we find we are close to the end of the
293 * tape; in which case we dump the next fragment on the next tape.
294 */
295 volBytesRead = 0;
296 chunkSize = 0;
297 fragmentvolume = 0;
298 while (!endofvolume && !fragmentvolume) { /*w */
299 bytesread = 0;
300
301 /* Check for abort in the middle of writing data */
302 if (volBytesRead >= chunkSize) {
303 chunkSize += BIGCHUNK102400;
304 if (checkAbortByTaskId(taskId))
305 ABORT_EXIT(TC_ABORTEDBYREQUEST)do { code = (156566278L); goto abort_exit; } while (0);
306
307 /* set bytes dumped for backup */
308 lock_Status();
309 nodePtr->statusNodePtr->nKBytes = tapeInfoPtr->kBytes;
310 unlock_Status();
311 }
312
313 /* Determine how much data to read in upcoming RX_Read() call */
314 toread = dataSize;
315 /* Check if we are close to the EOT. There should at least be some
316 * data on the tape before it is switched. HACK: we have to split a
317 * volume across tapes because the volume trailer says the dump
318 * continues on the next tape (and not the filemark). This could
319 * result in a volume starting on one tape (no volume data dumped) and
320 * continued on the next tape. It'll work, just requires restore to
321 * switch tapes. This allows many small volumes (<16K) to be dumped.
322 */
323 kRemaining = butm_remainingKSpace(tapeInfoPtr)((tapeInfoPtr)->tapeSize - ((tapeInfoPtr)->kBytes*(tapeInfoPtr
)->coefBytes ))
;
324 if ((kRemaining < tc_KEndMargin)
325 && (volBytesRead
326 || (tapeInfoPtr->position > (isafile ? 3 : 2)))) {
327 fragmentvolume = 1;
328 }
329
330
331 /* Guess at how much data to read. So we don't write off end of tape */
332 if (kRemaining < (tapeblocks * 16)) {
333 if (kRemaining < 0) {
334 toread = BUTM_BLKSIZE(16384 - ((5*sizeof(afs_int32)) + sizeof(int)));
335 } else {
336 toread = ((kRemaining / 16) + 1) * BUTM_BLKSIZE(16384 - ((5*sizeof(afs_int32)) + sizeof(int)));
337 if (toread > dataSize)
338 toread = dataSize;
339 }
340 }
341
342#ifdef xbsa
343 /* Set aside space for the trailing volume header when using large buffers. */
344 if (XBSAMAXBUFFER < toread + sizeof(hostVolumeHeader)) {
345 toread = XBSAMAXBUFFER - sizeof(hostVolumeHeader);
346 }
347#endif
348
349 /* Read some volume data. */
350 if (fragmentvolume) {
351 bytesread = 0;
352 } else {
353 bytesread = rx_Read(fromcall, buffer, toread)rx_ReadProc(fromcall, buffer, toread);
354 volBytesRead += bytesread;
355 if (bytesread != toread) {
356 /* Make sure were at end of volume and not a communication error */
357 rc = rx_Error(fromcall)((fromcall)->error);
358 if (rc)
359 ERROR_EXIT(rc)do { code = rc; goto error_exit; } while (0);
360 endofvolume = 1;
361 }
362 }
363
364 if (fragmentvolume || endofvolume) {
365 /* Create a volume trailer appending it to this data block */
366 makeVolumeHeader(&hostVolumeHeader, dparamsPtr,
367 fragmentNumber);
368 hostVolumeHeader.contd = (endofvolume ? 0 : TC_VOLCONTD0xffffffff);
369 hostVolumeHeader.magic = TC_VOLENDMAGIC0x9167345a;
370 hostVolumeHeader.endTime = (endofvolume ? time(0) : 0);
371 volumeHeader_hton(&hostVolumeHeader, (struct volumeHeader *)&buffer[bytesread]);
372 bytesread += sizeof(hostVolumeHeader);
373 }
374
375 /* Write the datablock out */
376 /* full data buffer - write it to tape */
377 rc = butm_WriteFileData(tapeInfoPtr, buffer, tapeblocks,(*((tapeInfoPtr)->ops.writeFileData))(tapeInfoPtr,buffer,tapeblocks
,bytesread)
378 bytesread)(*((tapeInfoPtr)->ops.writeFileData))(tapeInfoPtr,buffer,tapeblocks
,bytesread)
;
379 if (rc) {
380 ErrorLog(1, taskId, rc, tapeInfoPtr->error,
381 "Can't write VolumeData on tape\n");
382 ERROR_EXIT(rc)do { code = rc; goto error_exit; } while (0);
383 }
384 bytesWritten = tapeblocks * BUTM_BLOCKSIZE16384;
385 tsize += bytesWritten;
386
387 /* Display a status line every statusSize or at end of volume */
388 if (statusSize
389 && ((tsize >= statuscount) || endofvolume
390 || fragmentvolume)) {
391 time_t t = time(0);
392 struct tm tm;
393 localtime_r(&t, &tm);
394 printf("%02d:%02d:%02d: Task %u: %u KB: %s: %u B\n",
395 tm.tm_hour, tm.tm_min, tm.tm_sec, taskId,
396 tapeInfoPtr->kBytes, hostVolumeHeader.volumeName,
397 tsize);
398 statuscount = tsize + statusSize;
399 }
400 } /*w */
401
402 /* End the dump before recording it in BUDB as successfully dumped */
403 rc = butm_WriteFileEnd(tapeInfoPtr)(*((tapeInfoPtr)->ops.writeFileEnd))(tapeInfoPtr);
404 indump = 0;
405 if (rc) {
406 ErrorLog(1, taskId, rc, tapeInfoPtr->error,
407 "Can't write FileEnd on tape\n");
408 ERROR_EXIT(rc)do { code = rc; goto error_exit; } while (0);
409 }
410
411 /* Record in BUDB the volume fragment as succcessfully dumped */
412 volumeFlags = ((fragmentNumber == 1) ? BUDB_VOL_FIRSTFRAG(1<<3) : 0);
413 if (endofvolume)
414 volumeFlags |= BUDB_VOL_LASTFRAG(1<<4);
415 rc = addVolume(0, dparamsPtr->databaseDumpId, dparamsPtr->tapeName,
416 nodePtr->dumps[dparamsPtr->curVolume].name,
417 nodePtr->dumps[dparamsPtr->curVolume].vid,
418 nodePtr->dumps[dparamsPtr->curVolume].cloneDate,
419 dparamsPtr->curVolStartPos, volBytesRead,
420 (fragmentNumber - 1), volumeFlags);
421 if (rc)
422 ABORT_EXIT(rc)do { code = rc; goto abort_exit; } while (0);
423
424 /* If haven't finished dumping the volume, end this
425 * tape and get the next tape.
426 */
427 if (!endofvolume) {
428 /* Write an EOT marker.
429 * Log the error but ignore it since the dump is effectively done.
430 * Scantape will detect continued volume and not read the EOT.
431 */
432 rc = butm_WriteEOT(tapeInfoPtr)(*((tapeInfoPtr)->ops.writeEOT))(tapeInfoPtr);
433 if (rc)
434 TapeLog(1, taskId, rc, tapeInfoPtr->error,
435 "Warning: Can't write End-Of-Dump on tape\n");
436
437 /* Unmount the tape */
438 unmountTape(taskId, tapeInfoPtr);
439
440 /* Tell the database the tape is complete (and ok) */
441 rc = finishTape(&dparamsPtr->tape,
442 dparamsPtr->tapeInfoPtr->kBytes +
443 (dparamsPtr->tapeInfoPtr->nBytes ? 1 : 0));
444 if (rc)
445 ABORT_EXIT(rc)do { code = rc; goto abort_exit; } while (0);
446
447 /* get the next tape. Prompt, mount, and add it into the database */
448 dparamsPtr->tapeSeq++;
449 rc = getDumpTape(dparamsPtr, 1, 0); /* interactive - no append */
450 if (rc)
451 ABORT_EXIT(rc)do { code = rc; goto abort_exit; } while (0);
452
453 dparamsPtr->curVolStartPos = tapeInfoPtr->position;
454 }
455 } /*frag */
456
457 dparamsPtr->curVolumeStatus = DUMP_SUCCESS3;
458
459 error_exit:
460 /*
461 * If we hit the end, see if this is the first volume on the tape or not.
462 * Also, mark the tape as finished if the tape contains other dumps.
463 */
464 if (!code)
465 code = rc;
466 if (HITEOT(code)((code == (156568837L)) || (code == (156568842L)) || (code ==
(156568848L)))
) {
467 ErrorLog(2, taskId, code, tapeInfoPtr->error,
468 "Warning: Dump (%s) hit end-of-tape inferred\n",
469 nodePtr->dumpSetName);
470
471 if (tapeInfoPtr->position == 2) {
472 dparamsPtr->curVolumeStatus = DUMP_NORETRYEOT5;
473 } else {
474 dparamsPtr->curVolumeStatus = DUMP_RETRY4;
475 rc = finishTape(&dparamsPtr->tape,
476 dparamsPtr->tapeInfoPtr->kBytes +
477 (dparamsPtr->tapeInfoPtr->nBytes ? 1 : 0));
478 if (rc)
479 ABORT_EXIT(rc)do { code = rc; goto abort_exit; } while (0);
480 }
481 }
482
483 /*
484 * This is used when an error occurs part way into a volume dump. Clean
485 * the tape state by writing an FileEnd mark. Forgo this action if we hit
486 * the end of tape.
487 */
488 else if (indump) {
489 rc = butm_WriteFileEnd(tapeInfoPtr)(*((tapeInfoPtr)->ops.writeFileEnd))(tapeInfoPtr);
490 indump = 0;
491 if (rc) {
492 ErrorLog(1, taskId, rc, tapeInfoPtr->error,
493 "Can't write FileEnd on tape\n");
494 }
495 }
496
497 if (fromcall) {
498 rc = rx_EndCall(fromcall, 0);
499 if (!code)
500 code = rc;
501 }
502
503 if (fromtid) {
504 afs_int32 rcode;
505 rc = AFSVolEndTrans(fromconn, fromtid, &rcode);
506 if (!code)
507 code = (rc ? rc : rcode);
508 }
509
510 return (code);
511
512 abort_exit:
513 dparamsPtr->curVolumeStatus = DUMP_FAILED1;
514 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
515}
516
517afs_int32
518xbsaDumpVolume(struct tc_dumpDesc * curDump, struct dumpRock * dparamsPtr)
519{
520#ifdef xbsa
521 struct butm_tapeInfo *tapeInfoPtr = dparamsPtr->tapeInfoPtr;
522 struct dumpNode *nodePtr = dparamsPtr->node;
523 char *buffer = bufferBlock;
524 afs_int32 taskId = nodePtr->taskID;
525 afs_int32 rc, code = 0;
526 afs_int32 toread;
527 afs_uint32 volBytesRead;
528 afs_uint32 chunkSize;
529 afs_int32 bytesread; /* rx reads */
530 int endofvolume = 0; /* Have we read all volume data */
531 int begindump = 0, indump = 0; /* if dump transaction started; if dumping data */
532 struct volumeHeader hostVolumeHeader;
533
534 struct rx_call *fromcall = (struct rx_call *)0;
535 struct rx_connection *fromconn;
536 afs_int32 updatedate, fromtid = 0;
537 volEntries volumeInfo;
538 afs_int32 bytesWritten;
539 afs_uint32 statuscount = statusSize, tsize = 0, esize;
540 afs_hyper_t estSize;
541
542 char dumpIdStr[XBSA_MAX_OSNAME];
543 char volumeNameStr[XBSA_MAX_PATHNAME];
544 static char *dumpDescription = "AFS volume dump";
545 static char *objectDescription = "XBSA - butc";
546
547 dparamsPtr->curVolumeStatus = DUMP_NOTHING6;
548
549 fromconn = Bind(htonl(curDump->hostAddr)(__builtin_constant_p(curDump->hostAddr) ? ((((__uint32_t)
(curDump->hostAddr)) >> 24) | ((((__uint32_t)(curDump
->hostAddr)) & (0xff << 16)) >> 8) | ((((__uint32_t
)(curDump->hostAddr)) & (0xff << 8)) << 8)
| (((__uint32_t)(curDump->hostAddr)) << 24)) : __bswap32_var
(curDump->hostAddr))
); /* get connection to the server */
550
551 /* Determine when the volume was last cloned and updated */
552 volumeInfo.volEntries_val = (volintInfo *) 0;
553 volumeInfo.volEntries_len = 0;
554 rc = AFSVolListOneVolume(fromconn, curDump->partition, curDump->vid,
555 &volumeInfo);
556 if (rc)
557 ERROR_EXIT(rc)do { code = rc; goto error_exit; } while (0);
558 updatedate = volumeInfo.volEntries_val[0].updateDate;
559 curDump->cloneDate =
560 ((curDump->vtype ==
561 RWVOL0) ? time(0) : volumeInfo.volEntries_val[0].creationDate);
562
563 /* Get the volume size (in KB) and increase by 25%. Then set as a hyper */
564 esize = volumeInfo.volEntries_val[0].size;
565 esize += (esize / 4) + 1;
566
567 if (curDump->date >= curDump->cloneDate)
568 ERROR_EXIT(0)do { code = 0; goto error_exit; } while (0); /* not recloned since last dump */
569 if (curDump->date > updatedate) {
570 dparamsPtr->curVolumeStatus = DUMP_NODUMP7; /* not modified since last dump */
571 ERROR_EXIT(0)do { code = 0; goto error_exit; } while (0);
572 }
573
574 /* Start a new XBSA Transaction */
575 rc = xbsa_BeginTrans(&butxInfo);
576 if (rc != XBSA_SUCCESS) {
577 ErrorLog(1, taskId, rc, 0, "Unable to create a new transaction\n");
578 ERROR_EXIT(rc)do { code = rc; goto error_exit; } while (0);
579 }
580 begindump = 1; /* Will need to do an xbsa_EndTrans */
581
582 /* Start the volserver transaction and dump. Once started, the
583 * volume status is "partial dump". Also, the transaction with
584 * the volserver is idle until the first read. An idle transaction
585 * will time out in 600 seconds. After the first rx_Read,
586 * the transaction is not idle. See GCTrans().
587 */
588 rc = AFSVolTransCreate(fromconn, curDump->vid, curDump->partition, ITBusy2,
589 &fromtid);
590 if (rc)
591 ERROR_EXIT(rc)do { code = rc; goto error_exit; } while (0);
592 fromcall = rx_NewCall(fromconn);
593
594 rc = StartAFSVolDump(fromcall, fromtid, curDump->date);
595 if (rc)
596 ERROR_EXIT(rc)do { code = rc; goto error_exit; } while (0);
597
598 dparamsPtr->curVolumeStatus = DUMP_PARTIAL2;
599 dparamsPtr->curVolStartPos = tapeInfoPtr->position;
600
601 /* Tell XBSA what the name and size of volume to write */
602 strcpy(dumpIdStr, butcdumpIdStr); /* "backup_afs_volume_dumps" */
603 sprintf(volumeNameStr, "/%d", dparamsPtr->databaseDumpId);
604 strcat(volumeNameStr, "/");
605 strcat(volumeNameStr, curDump->name); /* <dumpid>/<volname> */
606 hset32(estSize, esize)((estSize).high = 0, (estSize).low = (esize));
607 hshlft(estSize, 10){ int s = sizeof((estSize).low) * 8; if ((10) <= 0) { } else
if ((10) >= 2*s) { (estSize).high = (estSize).low = 0; } else
if ((10) < s) { (estSize).high = ((estSize).high<<(
10)) | (((estSize).low>>(s-(10))) & (1<<(10))
-1); (estSize).low = (estSize).low << (10); } else if (
(10) >= s) { (estSize).high = (estSize).low << ((10)
-s); (estSize).low=0; } }
; /* Multiply by 1024 so its in KB */
608
609 rc = xbsa_WriteObjectBegin(&butxInfo, dumpIdStr, volumeNameStr,
610 xbsalGName, estSize, dumpDescription,
611 objectDescription);
612 if (rc != XBSA_SUCCESS) {
613 ErrorLog(1, taskId, rc, 0,
614 "Unable to begin writing of the fileset data to the server\n");
615 ERROR_EXIT(rc)do { code = rc; goto error_exit; } while (0);
616 }
617 indump = 1; /* Will need to do an xbsa_WriteObjectEnd */
618
619 /* Create and Write the volume header */
620 makeVolumeHeader(&hostVolumeHeader, dparamsPtr, 1);
621 hostVolumeHeader.contd = 0;
622 volumeHeader_hton(&hostVolumeHeader, (struct volumeHeader *)buffer);
623
624 rc = xbsa_WriteObjectData(&butxInfo, (struct volumeHeader *)buffer,
625 sizeof(struct volumeHeader), &bytesWritten);
626 if (rc != XBSA_SUCCESS) {
627 ErrorLog(1, taskId, rc, 0,
628 "Unable to write VolumeHeader data to the server\n");
629 ERROR_EXIT(rc)do { code = rc; goto error_exit; } while (0);
630 }
631 /* There is a bug in the ADSM library where the bytesWritten is
632 * not filled in, so we set it as correct anyway.
633 */
634 bytesWritten = sizeof(struct volumeHeader);
635 if (bytesWritten != sizeof(struct volumeHeader)) {
636 ErrorLog(1, taskId, rc, 0,
637 "The size of VolumeHeader written (%d) does not equal its actual size (%d)\n",
638 bytesWritten, sizeof(struct volumeHeader));
639 ERROR_EXIT(TC_INTERNALERROR)do { code = (156566288L); goto error_exit; } while (0);
640 }
641
642 incSize(tapeInfoPtr, sizeof(struct volumeHeader)); /* Increment amount we've written */
643 tsize += bytesWritten;
644
645 /* Start reading volume data, rx_Read(), and dumping to the tape
646 * until we've dumped the entire volume (endofvolume == 1).
647 */
648 volBytesRead = 0;
649 chunkSize = 0;
650 while (!endofvolume) { /*w */
651 bytesread = 0;
652
653 /* Check for abort in the middle of writing data */
654 if (volBytesRead >= chunkSize) {
655 chunkSize += BIGCHUNK102400;
656 if (checkAbortByTaskId(taskId))
657 ABORT_EXIT(TC_ABORTEDBYREQUEST)do { code = (156566278L); goto abort_exit; } while (0);
658
659 /* set bytes dumped for backup */
660 lock_Status();
661 nodePtr->statusNodePtr->nKBytes = tapeInfoPtr->kBytes;
662 unlock_Status();
663 }
664
665 /* Determine how much data to read in upcoming RX_Read() call */
666 toread = dataSize;
667
668 /* Read some volume data. */
669 bytesread = rx_Read(fromcall, buffer, toread)rx_ReadProc(fromcall, buffer, toread);
670 volBytesRead += bytesread;
671 if (bytesread != toread) {
672 afs_int32 rcode;
673
674 /* Make sure were at end of volume and not a communication error */
675 rc = rx_Error(fromcall)((fromcall)->error);
676 if (rc)
677 ERROR_EXIT(rc)do { code = rc; goto error_exit; } while (0);
678
679 endofvolume = 1;
680
681 /* Create a volume trailer appending it to this data block (if not XBSA) */
682 makeVolumeHeader(&hostVolumeHeader, dparamsPtr, 1);
683 hostVolumeHeader.contd = 0;
684 hostVolumeHeader.magic = TC_VOLENDMAGIC0x9167345a;
685 hostVolumeHeader.endTime = time(0);
686 volumeHeader_hton(&hostVolumeHeader, &buffer[bytesread]);
687 bytesread += sizeof(hostVolumeHeader);
688
689 /* End the dump and transaction with the volserver. We end it now, before
690 * we make the XBSA call because if XBSA blocks, we could time out on the
691 * volserver (After last read, the transaction with the volserver is idle).
692 */
693 rc = rx_EndCall(fromcall, 0);
694 fromcall = 0;
695 if (rc)
696 ERROR_EXIT(rc)do { code = rc; goto error_exit; } while (0);
697
698 rc = AFSVolEndTrans(fromconn, fromtid, &rcode);
699 fromtid = 0;
700 if (rc)
701 ERROR_EXIT(rc)do { code = rc; goto error_exit; } while (0);
702 }
703
704 /* Write the datablock out */
705 rc = xbsa_WriteObjectData(&butxInfo, buffer, bytesread,
706 &bytesWritten);
707 if (rc != XBSA_SUCCESS) {
708 ErrorLog(1, taskId, rc, 0,
709 "Unable to write data to the server\n");
710 ERROR_EXIT(rc)do { code = rc; goto error_exit; } while (0);
711 }
712 /* There is a bug in the ADSM library where the bytesWritten is
713 * not filled in, so we set it as correct anyway.
714 */
715 bytesWritten = bytesread;
716 if (bytesWritten != bytesread) {
717 ErrorLog(1, taskId, rc, 0,
718 "The size of data written (%d) does not equal size read (%d)\n",
719 bytesWritten, bytesread);
720 ERROR_EXIT(TC_INTERNALERROR)do { code = (156566288L); goto error_exit; } while (0);
721 }
722
723 incSize(tapeInfoPtr, bytesread); /* Increment amount we've written */
724 tsize += bytesWritten;
725
726 /* Display a status line every statusSize or at end of volume */
727 if (statusSize && ((tsize >= statuscount) || endofvolume)) {
728 time_t t = time(0);
729 struct tm tm;
730 localtime_r(&t, &tm);
731 printf("%02d:%02d:%02d: Task %u: %u KB: %s: %u B\n", tm.tm_hour,
732 tm.tm_min, tm.tm_sec, taskId, tapeInfoPtr->kBytes,
733 hostVolumeHeader.volumeName, tsize);
734 statuscount = tsize + statusSize;
735 }
736 } /*w */
737
738 /* End the XBSA transaction before recording it in BUDB as successfully dumped */
739 rc = xbsa_WriteObjectEnd(&butxInfo);
740 indump = 0;
741 if (rc != XBSA_SUCCESS) {
742 ErrorLog(1, taskId, rc, 0,
743 "Unable to terminate writing of the volume data to the server");
744 ERROR_EXIT(rc)do { code = rc; goto error_exit; } while (0);
745 }
746 rc = xbsa_EndTrans(&butxInfo);
747 begindump = 0;
748 tapeInfoPtr->position++;
749 if (rc != XBSA_SUCCESS) {
750 ErrorLog(1, taskId, rc, 0,
751 "Unable to terminate the current transaction");
752 ERROR_EXIT(rc)do { code = rc; goto error_exit; } while (0);
753 }
754
755 /* Record in BUDB the volume fragment as succcessfully dumped */
756 rc = addVolume(0, dparamsPtr->databaseDumpId, dparamsPtr->tapeName,
757 nodePtr->dumps[dparamsPtr->curVolume].name,
758 nodePtr->dumps[dparamsPtr->curVolume].vid,
759 nodePtr->dumps[dparamsPtr->curVolume].cloneDate,
760 dparamsPtr->curVolStartPos, volBytesRead, 0 /*frag0 */ ,
761 (BUDB_VOL_FIRSTFRAG(1<<3) | BUDB_VOL_LASTFRAG(1<<4)));
762 if (rc)
763 ABORT_EXIT(rc)do { code = rc; goto abort_exit; } while (0);
764
765 dparamsPtr->curVolumeStatus = DUMP_SUCCESS3;
766
767 error_exit:
768 /* Cleanup after an error occurs part way into a volume dump */
769 if (fromcall) {
770 rc = rx_EndCall(fromcall, 0);
771 if (!code)
772 code = rc;
773 }
774
775 if (fromtid) {
776 afs_int32 rcode;
777 rc = AFSVolEndTrans(fromconn, fromtid, &rcode);
778 if (!code)
779 code = (rc ? rc : rcode);
780 }
781
782 /* If this dump failed, what happens to successive retries
783 * of the volume? How do they get recorded in the XBSA database
784 * (overwritten)? If not, we don't record this in the BUDB database
785 * so it will not be removed when we delete the dump. What to do?
786 * Also if the volume was never recorded in the DB (partial dump).
787 */
788 if (indump) {
789 /* End the Write */
790 rc = xbsa_WriteObjectEnd(&butxInfo);
791 indump = 0;
792 if (rc != XBSA_SUCCESS) {
793 ErrorLog(1, taskId, rc, 0,
794 "Unable to terminate writing of the volume data to the server");
795 }
796 tapeInfoPtr->position++;
797 }
798
799 if (begindump) {
800 /* End the XBSA Transaction */
801 rc = xbsa_EndTrans(&butxInfo);
802 begindump = 0;
803 if (rc != XBSA_SUCCESS) {
804 ErrorLog(1, taskId, rc, 0,
805 "Unable to terminate the current transaction");
806 }
807 }
808
809 return (code);
810
811 abort_exit:
812 dparamsPtr->curVolumeStatus = DUMP_FAILED1;
813 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
814#else
815 return 0;
816#endif
817}
818
819#define HOSTADDR(sockaddr)(sockaddr)->sin_addr.s_addr (sockaddr)->sin_addr.s_addr
820
821/* dumpPass
822 * Go through the list of volumes to dump, dumping each one. The action
823 * taken when a volume dump fails, depends on the passNumber. At minimum,
824 * the failed volume is remembered.
825 * notes:
826 * flushSavedEntries - inconsistent treatment for errors. What should
827 * be done for user aborts?
828 */
829
830afs_int32
831dumpPass(struct dumpRock * dparamsPtr, int passNumber)
832{
833 struct dumpNode *nodePtr = dparamsPtr->node;
834 struct butm_tapeInfo *tapeInfoPtr = dparamsPtr->tapeInfoPtr;
835 afs_int32 taskId = nodePtr->taskID;
836 struct tc_dumpDesc *curDump;
837 int action, e;
838 afs_int32 code = 0, tcode, dvcode;
839 char ch;
840 struct vldbentry vldbEntry;
841 struct sockaddr_in server;
842 afs_int32 tapepos;
843
844 TapeLog(2, taskId, 0, 0, "Starting pass %d\n", passNumber);
845
846 /* while there are more volumes to dump */
847 for (dparamsPtr->curVolume = 0; dparamsPtr->curVolume < nodePtr->arraySize; dparamsPtr->curVolume++) { /*w */
848 curDump = &nodePtr->dumps[dparamsPtr->curVolume];
849 if (curDump->hostAddr == 0)
850 continue;
851
852 /* set name of current volume being dumped */
853 lock_Status();
854 strcpy(nodePtr->statusNodePtr->volumeName, curDump->name);
855 unlock_Status();
856
857 /* Determine location of the volume.
858 * In case the volume moved has moved.
859 */
860 if (passNumber > 1) { /*pass */
861 tcode =
862 bc_GetEntryByID(cstruct, curDump->vid, curDump->vtype,
863 &vldbEntry);
864 if (tcode) {
865 ErrorLog(0, taskId, tcode, 0,
866 "Volume %s (%u) failed - Can't find volume in VLDB\n",
867 curDump->name, curDump->vid);
868 curDump->hostAddr = 0;
869 dparamsPtr->volumesFailed++;
870 continue;
871 }
872
873 switch (curDump->vtype) {
874 case BACKVOL2:
875 if (!(vldbEntry.flags & BACK_EXISTS0x4000)) {
876 ErrorLog(0, taskId, 0, 0,
877 "Volume %s (%u) failed - Backup volume no longer exists\n",
878 curDump->name, curDump->vid);
879 curDump->hostAddr = 0;
880 dparamsPtr->volumesFailed++;
881 continue;
882 }
883 /* Fall into RWVOL case */
884
885 case RWVOL0:
886 for (e = 0; e < vldbEntry.nServers; e++) { /* Find the RW volume */
887 if (vldbEntry.serverFlags[e] & ITSRWVOL0x04)
888 break;
889 }
890 break;
891
892 case ROVOL1:
893 /* Try to use the server and partition we found the volume on
894 * Otherwise, use the first RO volume.
895 */
896 for (e = 0; e < vldbEntry.nServers; e++) { /* Find the RO volume */
897 if ((curDump->hostAddr == vldbEntry.serverNumber[e])
898 && (curDump->partition ==
899 vldbEntry.serverPartition[e]))
900 break;
901 }
902
903 if (e >= vldbEntry.nServers) { /* Didn't find RO volume */
904 for (e = 0; e < vldbEntry.nServers; e++) { /* Find the first RO volume */
905 if (vldbEntry.serverFlags[e] & ITSROVOL0x02)
906 break;
907 }
908 }
909 break;
910
911 default:
912 ErrorLog(0, taskId, 0, 0,
913 "Volume %s (%u) failed - Unknown volume type\n",
914 curDump->name, curDump->vid);
915 curDump->hostAddr = 0;
916 continue;
917 }
918
919 if (e >= vldbEntry.nServers) {
920 ErrorLog(0, taskId, 0, 0,
921 "Volume %s (%u) failed - Can't find volume entry in VLDB\n",
922 curDump->name, curDump->vid);
923 curDump->hostAddr = 0;
924 dparamsPtr->volumesFailed++;
925 continue;
926 }
927
928 /* Remember the server and partition the volume exists on */
929 memset(&server, 0, sizeof(server));
930 server.sin_addr.s_addr = vldbEntry.serverNumber[e];
931 server.sin_port = 0;
932 server.sin_family = AF_INET2;
933#ifdef STRUCT_SOCKADDR_HAS_SA_LEN1
934 server.sin_len = sizeof(struct sockaddr_in);
935#endif
936 curDump->hostAddr = HOSTADDR(&server)(&server)->sin_addr.s_addr;
937 curDump->partition = vldbEntry.serverPartition[e];
938
939 /* Determine date from which to do an incremental dump
940 */
941 if (nodePtr->parent) {
942 tcode =
943 bcdb_FindClone(nodePtr->parent, curDump->name,
944 &curDump->date);
945 if (tcode)
946 curDump->date = 0;
947 } else {
948 curDump->date = 0; /* do a full dump */
949 }
950 }
951 /*pass */
952 if (checkAbortByTaskId(taskId))
953 ERROR_EXIT(TC_ABORTEDBYREQUEST)do { code = (156566278L); goto error_exit; } while (0);
954
955 /* Establish connection to volume - UV_ routine expects
956 * host address in network order
957 */
958 if (CONF_XBSA0) {
959 dvcode = xbsaDumpVolume(curDump, dparamsPtr);
960 } else {
961 dvcode = dumpVolume(curDump, dparamsPtr);
962 }
963 action = dparamsPtr->curVolumeStatus;
964
965 /* Flush volume and tape entries to the database */
966 tcode = flushSavedEntries(action);
967 if (tcode)
968 ERROR_EXIT(tcode)do { code = tcode; goto error_exit; } while (0);
969
970 switch (action) {
971 case DUMP_SUCCESS3:
972 TapeLog(1, taskId, 0, 0, "Volume %s (%u) successfully dumped\n",
973 curDump->name, curDump->vid);
974 if (dvcode)
975 ErrorLog(1, taskId, dvcode, 0,
976 "Warning: Termination processing error on volume %s (%u)\n",
977 curDump->name, curDump->vid);
978
979 curDump->hostAddr = 0;
980 dparamsPtr->volumesDumped++;
981 break;
982
983 case DUMP_PARTIAL2:
984 case DUMP_NOTHING6:
985 if (action == DUMP_PARTIAL2) {
986 ErrorLog(1, taskId, dvcode, 0,
987 "Volume %s (%u) failed - partially dumped\n",
988 curDump->name, curDump->vid);
989 } else if (dvcode) {
990 ErrorLog(0, taskId, dvcode, 0, "Volume %s (%u) failed\n",
991 curDump->name, curDump->vid);
992 } else {
993 ErrorLog(0, taskId, dvcode, 0,
994 "Volume %s (%u) not dumped - has not been re-cloned since last dump\n",
995 curDump->name, curDump->vid);
996 }
997
998 if (passNumber == maxpass) {
999 if (!queryoperator)
1000 ch = 'o';
1001 else
1002 ch = retryPrompt(curDump->name, curDump->vid, taskId);
1003
1004 switch (ch) {
1005 case 'r': /* retry */
1006 dparamsPtr->curVolume--; /* redump this volume */
1007 continue;
1008 case 'o': /* omit */
1009 ErrorLog(1, taskId, 0, 0, "Volume %s (%u) omitted\n",
1010 curDump->name, curDump->vid);
1011 dparamsPtr->volumesFailed++;
1012 break;
1013 case 'a': /* abort */
1014 TapeLog(1, taskId, 0, 0, "Dump aborted\n");
1015 ERROR_EXIT(TC_ABORTEDBYREQUEST)do { code = (156566278L); goto error_exit; } while (0);
1016 break;
1017 default:
1018 ERROR_EXIT(TC_INTERNALERROR)do { code = (156566288L); goto error_exit; } while (0);
1019 break;
1020 }
1021 }
1022 break;
1023
1024 case DUMP_RETRY4:
1025 TapeLog(1, taskId, dvcode, 0,
1026 "Volume %s (%u) hit end-of-tape inferred - will retry on next tape\n",
1027 curDump->name, curDump->vid);
1028
1029 /* Get the next tape */
1030 unmountTape(taskId, tapeInfoPtr);
1031
1032 dparamsPtr->tapeSeq++;
1033 tcode = getDumpTape(dparamsPtr, 1, 0); /* interactive - no appends */
1034 if (tcode)
1035 ERROR_EXIT(tcode)do { code = tcode; goto error_exit; } while (0);
1036
1037 dparamsPtr->curVolume--; /* redump this volume */
1038 continue;
1039
1040 case DUMP_NORETRYEOT5:
1041 ErrorLog(1, taskId, 0, 0,
1042 "Volume %s (%u) failed - volume larger than tape\n",
1043 curDump->name, curDump->vid);
1044
1045 /* rewrite the label on the tape - rewind - no need to switch tapes */
1046 tcode = butm_Create(tapeInfoPtr, &dparamsPtr->tapeLabel, 1)(*((tapeInfoPtr)->ops.create))(tapeInfoPtr,&dparamsPtr
->tapeLabel,1)
;
1047 if (tcode) {
1048 ErrorLog(0, taskId, tcode, tapeInfoPtr->error,
1049 "Can't relabel tape\n");
1050
1051 unmountTape(taskId, tapeInfoPtr);
1052 tcode = getDumpTape(dparamsPtr, 1, 0); /* interactive - no appends */
1053 if (tcode)
1054 ERROR_EXIT(tcode)do { code = tcode; goto error_exit; } while (0);
1055 } else { /* Record the tape in database */
1056 tapepos = tapeInfoPtr->position;
1057 tcode =
1058 useTape(&dparamsPtr->tape, dparamsPtr->databaseDumpId,
1059 dparamsPtr->tapeName,
1060 (dparamsPtr->tapeSeq + dparamsPtr->dump.tapes.b),
1061 dparamsPtr->tapeLabel.useCount,
1062 dparamsPtr->tapeLabel.creationTime,
1063 dparamsPtr->tapeLabel.expirationDate, tapepos);
1064 }
1065
1066 curDump->hostAddr = 0;
1067 dparamsPtr->volumesFailed++;
1068 break;
1069
1070 case DUMP_NODUMP7:
1071 TapeLog(1, taskId, dvcode, 0,
1072 "Volume %s (%u) not dumped - has not been modified since last dump\n",
1073 curDump->name, curDump->vid);
1074
1075 curDump->hostAddr = 0;
1076 dparamsPtr->volumesNotDumped++;
1077 break;
1078
1079 default:
1080 ErrorLog(1, taskId, dvcode, 0, "Volume %s (%u) failed\n",
1081 curDump->name, curDump->vid);
1082 ERROR_EXIT(dvcode)do { code = dvcode; goto error_exit; } while (0);
1083 break;
1084 }
1085 } /*w */
1086
1087 error_exit:
1088 /* check if we terminated while processing a volume */
1089 if (dparamsPtr->curVolume < nodePtr->arraySize) {
1090 TapeLog(2, taskId, 0, 0,
1091 "Terminated while processing Volume %s (%u)\n", curDump->name,
1092 curDump->vid);
1093 }
1094
1095 /* print a summary of this pass */
1096 TapeLog(2, taskId, 0, 0, "End of pass %d: Volumes remaining = %d\n",
1097 passNumber,
1098 nodePtr->arraySize - (dparamsPtr->volumesDumped +
1099 dparamsPtr->volumesFailed +
1100 dparamsPtr->volumesNotDumped));
1101 return (code);
1102}
1103
1104void *
1105Dumper(void *param)
1106{
1107 struct dumpNode *nodePtr = (struct dumpNode *)param;
1108 struct dumpRock dparams;
1109 struct butm_tapeInfo tapeInfo;
1110 int pass;
1111 int action;
1112 afs_int32 taskId;
1113 afs_int32 code = 0;
1114
1115 /* for volume setup */
1116 int i;
1117 int failedvolumes = 0;
1118 int dumpedvolumes = 0;
1119 int nodumpvolumes = 0;
1120 char strlevel[5];
1121 char msg[20];
1122 char finishedMsg1[50];
1123 char finishedMsg2[50];
1124 time_t startTime = 0;
1125 time_t endTime = 0;
1126 afs_int32 allocbufferSize;
1127
1128 extern struct deviceSyncNode *deviceLatch;
1129 extern struct tapeConfig globalTapeConfig;
1130
1131 afs_pthread_setname_self("dumper")(void)0;
1132 taskId = nodePtr->taskID; /* Get task Id */
1133 setStatus(taskId, DRIVE_WAIT0x100);
1134 EnterDeviceQueue(deviceLatch);
1135 clearStatus(taskId, DRIVE_WAIT0x100);
1136
1137 printf("\n\n");
1138 TapeLog(2, taskId, 0, 0, "Dump %s\n", nodePtr->dumpSetName);
1139
1140 /* setup the dump parameters */
1141 memset(&dparams, 0, sizeof(dparams));
1142 dparams.node = nodePtr;
1143 dparams.tapeInfoPtr = &tapeInfo;
1144 dlqInit(&savedEntries);
1145
1146 if (!CONF_XBSA0) {
1
Taking true branch
1147 /* Instantiate the tape module */
1148 tapeInfo.structVersion = BUTM_MAJORVERSION2;
1149 code = butm_file_Instantiate(&tapeInfo, &globalTapeConfig);
1150 if (code) {
2
Taking false branch
1151 ErrorLog(0, taskId, code, tapeInfo.error,
1152 "Can't initialize the tape module\n");
1153 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
1154 }
1155 }
1156
1157 /* check if abort requested while waiting on device latch */
1158 if (checkAbortByTaskId(taskId))
3
Taking false branch
1159 ERROR_EXIT(TC_ABORTEDBYREQUEST)do { code = (156566278L); goto error_exit; } while (0);
1160
1161 /* Are there volumes to dump */
1162 if (nodePtr->arraySize == 0) {
4
Taking false branch
1163 TLog(taskId, "Dump (%s), no volumes to dump\n", nodePtr->dumpSetName);
1164 ERROR_EXIT(0)do { code = 0; goto error_exit; } while (0);
1165 }
1166
1167 /* Allocate a buffer for the dumps. Leave room for header and vol-trailer.
1168 * dataSize is amount of data to read in each rx_Read() call.
1169 */
1170 if (CONF_XBSA0) {
5
Taking false branch
1171 /* XBSA dumps have not header */
1172 dataSize = BufferSize;
1173 allocbufferSize = dataSize + sizeof(struct volumeHeader);
1174 } else {
1175 tapeblocks = BufferSize / BUTM_BLOCKSIZE16384; /* # of 16K tapeblocks */
1176 dataSize = (tapeblocks * BUTM_BLKSIZE(16384 - ((5*sizeof(afs_int32)) + sizeof(int))));
1177 allocbufferSize =
1178 BUTM_HDRSIZE((5*sizeof(afs_int32)) + sizeof(int)) + dataSize + sizeof(struct volumeHeader);
1179 }
1180 bufferBlock = NULL((void *)0);
1181 bufferBlock = malloc(allocbufferSize);
1182 if (!bufferBlock) {
6
Taking false branch
1183 ErrorLog(0, taskId, TC_NOMEMORY(156566290L), 0,
1184 "Can't allocate BUFFERSIZE for dumps\n");
1185 ERROR_EXIT(TC_NOMEMORY)do { code = (156566290L); goto error_exit; } while (0);
1186 }
1187
1188 /* Determine the dumpid of the most recent dump of this volumeset and dumplevel
1189 * Used when requesting a tape. Done now because once we create the dump, the
1190 * routine will then find the newly created dump.
1191 */
1192 sprintf(strlevel, "%d", nodePtr->level);
1193 code =
1194 bcdb_FindLatestDump(nodePtr->volumeSetName, strlevel,
1195 &dparams.lastDump);
1196 if (code) {
7
Taking false branch
1197 if (code != BUDB_NODUMPNAME(156303874L)) {
1198 ErrorLog(0, taskId, code, 0, "Can't read backup database\n");
1199 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
1200 }
1201 memset(&dparams.lastDump, 0, sizeof(dparams.lastDump));
1202 }
1203
1204 code = createDump(&dparams); /* enter dump into database */
1205 if (code) {
8
Taking true branch
1206 ErrorLog(0, taskId, code, 0, "Can't create dump in database\n");
1207 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
9
Within the expansion of the macro 'ERROR_EXIT':
a
Assigned value is always the same as the existing value
1208 }
1209
1210 TLog(taskId, "Dump %s (DumpID %u)\n", nodePtr->dumpSetName,
1211 dparams.databaseDumpId);
1212
1213 if (!CONF_XBSA0) {
1214 /* mount the tape and write its label */
1215 code = getDumpTape(&dparams, autoQuery, nodePtr->doAppend);
1216 } else {
1217 /* Create a dummy tape to satisfy backup databae */
1218 code = getXBSATape(&dparams);
1219 tapeInfo.position = 1;
1220 }
1221 if (code) {
1222 /* If didn't write the label, remove dump from the database */
1223 if (!dparams.wroteLabel) {
1224 i = bcdb_deleteDump(dparams.databaseDumpId, 0, 0, 0);
1225 if (i && (i != BUDB_NOENT(156303877L)))
1226 ErrorLog(1, taskId, i, 0,
1227 "Warning: Can't delete dump %u from database\n",
1228 dparams.databaseDumpId);
1229 else
1230 dparams.databaseDumpId = 0;
1231 }
1232 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0); /* exit with code from getTape */
1233 }
1234
1235 startTime = time(0);
1236 for (pass = 1; pass <= maxpass; pass++) {
1237 lastPass = (pass == maxpass);
1238 code = dumpPass(&dparams, pass);
1239 if (code)
1240 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
1241
1242 /* if no failed volumes, we're done */
1243 if ((dparams.volumesDumped + dparams.volumesFailed +
1244 dparams.volumesNotDumped) == nodePtr->arraySize)
1245 break;
1246 }
1247
1248 /*
1249 * Log the error but ignore it since the dump is effectively done.
1250 * Scantape may assume another volume and ask for next tape.
1251 */
1252 if (!CONF_XBSA0) {
1253 code = butm_WriteEOT(&tapeInfo)(*((&tapeInfo)->ops.writeEOT))(&tapeInfo);
1254 if (code)
1255 TapeLog(0, taskId, code, tapeInfo.error,
1256 "Warning: Can't write end-of-dump on tape\n");
1257 }
1258
1259 code =
1260 finishTape(&dparams.tape,
1261 dparams.tapeInfoPtr->kBytes +
1262 (dparams.tapeInfoPtr->nBytes ? 1 : 0));
1263 if (code)
1264 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
1265
1266 code = finishDump(&dparams.dump);
1267 if (code)
1268 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
1269
1270 action = dparams.curVolumeStatus;
1271 code = flushSavedEntries(action);
1272 if (code)
1273 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
1274
1275 error_exit:
1276 endTime = time(0);
1277 Bind(0);
1278 if (bufferBlock)
1279 free(bufferBlock);
1280
1281 if (!CONF_XBSA0) {
1282 unmountTape(taskId, &tapeInfo);
1283 }
1284 waitDbWatcher();
1285
1286 dumpedvolumes = dparams.volumesDumped;
1287 nodumpvolumes = dparams.volumesNotDumped;
1288 failedvolumes = nodePtr->arraySize - (dumpedvolumes + nodumpvolumes);
1289
1290 /* pass back the number of volumes we failed to dump */
1291 lock_Status();
1292 nodePtr->statusNodePtr->volsFailed = failedvolumes;
1293 unlock_Status();
1294
1295 lastPass = 1; /* In case we aborted */
1296
1297 DUMPNAME(finishedMsg1, nodePtr->dumpSetName, dparams.databaseDumpId)if (dparams.databaseDumpId == 0) sprintf(finishedMsg1, "%s", nodePtr
->dumpSetName); else sprintf(finishedMsg1, "%s (DumpId %u)"
, nodePtr->dumpSetName, dparams.databaseDumpId);
;
1298 sprintf(finishedMsg2, "%d volumes dumped", dumpedvolumes);
1299 if (failedvolumes) {
1300 sprintf(msg, ", %d failed", failedvolumes);
1301 strcat(finishedMsg2, msg);
1302 }
1303 if (nodumpvolumes) {
1304 sprintf(msg, ", %d unchanged", nodumpvolumes);
1305 strcat(finishedMsg2, msg);
1306 }
1307
1308 if (code == TC_ABORTEDBYREQUEST(156566278L)) {
1309 ErrorLog(0, taskId, 0, 0, "%s: Aborted by request. %s\n",
1310 finishedMsg1, finishedMsg2);
1311 clearStatus(taskId, ABORT_REQUEST0x2);
1312 setStatus(taskId, ABORT_DONE0x8);
1313 } else if (code) {
1314 ErrorLog(0, taskId, code, 0, "%s: Finished with errors. %s\n",
1315 finishedMsg1, finishedMsg2);
1316 setStatus(taskId, TASK_ERROR0x80);
1317 } else {
1318 TLog(taskId, "%s: Finished. %s\n", finishedMsg1, finishedMsg2);
1319 }
1320 lastPass = 0;
1321
1322 /* Record how long the dump took */
1323 if (centralLogIO && startTime) {
1324 long timediff;
1325 afs_int32 hrs, min, sec, tmp;
1326 char line[1024];
1327 struct tm tmstart, tmend;
1328
1329 localtime_r(&startTime, &tmstart);
1330 localtime_r(&endTime, &tmend);
1331 timediff = (int)endTime - (int)startTime;
1332 hrs = timediff / 3600;
1333 tmp = timediff % 3600;
1334 min = tmp / 60;
1335 sec = tmp % 60;
1336
1337 sprintf(line,
1338 "%-5d %02d/%02d/%04d %02d:%02d:%02d "
1339 "%02d/%02d/%04d %02d:%02d:%02d " "%02d:%02d:%02d "
1340 "%s %d of %d volumes dumped (%lu KB)\n", taskId,
1341 tmstart.tm_mon + 1, tmstart.tm_mday, tmstart.tm_year + 1900,
1342 tmstart.tm_hour, tmstart.tm_min, tmstart.tm_sec,
1343 tmend.tm_mon + 1, tmend.tm_mday, tmend.tm_year + 1900,
1344 tmend.tm_hour, tmend.tm_min, tmend.tm_sec, hrs, min, sec,
1345 nodePtr->volumeSetName, dumpedvolumes,
1346 dumpedvolumes + failedvolumes,
1347 afs_printable_uint32_lu(dparams.tapeInfoPtr->kBytes + 1));
1348
1349 fwrite(line, strlen(line), 1, centralLogIO);
1350 fflush(centralLogIO);
1351 }
1352
1353 setStatus(taskId, TASK_DONE0x20);
1354
1355 FreeNode(taskId); /* free the dump node */
1356 LeaveDeviceQueue(deviceLatch);
1357 return (void *)(intptr_t)(code);
1358}
1359
1360#define BELLTIME60 60 /* 60 seconds before a bell rings */
1361#define BELLCHAR7 7 /* ascii for bell */
1362
1363/* retryPrompt
1364 * prompt the user to decide how to handle a failed volume dump. The
1365 * volume parameters describe the volume that failed
1366 * entry:
1367 * volumeName - name of volume
1368 * volumeId - volume id
1369 * taskId - for job contrl
1370 * fn return:
1371 * character typed by user, one of r, o or a
1372 */
1373
1374char
1375retryPrompt(char *volumeName, afs_int32 volumeId, afs_uint32 taskId)
1376{
1377 afs_int32 start;
1378 char ch;
1379 afs_int32 code = 0;
1380
1381 setStatus(taskId, OPR_WAIT0x200);
1382 printf("\nDump of volume %s (%u) failed\n\n", volumeName, volumeId);
1383
1384 printf("Please select action to be taken for this volume\n");
1385
1386 again:
1387 printf("r - retry, try dumping this volume again\n");
1388 printf("o - omit, this volume from this dump\n");
1389 printf("a - abort, the entire dump\n");
1390
1391 while (1) {
1392 FFlushInput();
1393 putchar(BELLCHAR)(!__isthreaded ? __sputc(7, __stdoutp) : (putc)(7, __stdoutp)
)
;
1394 fflush(stdout__stdoutp);
1395
1396 start = time(0);
1397 while (1) {
1398 code = LWP_GetResponseKey(5, &ch); /* ch stores key pressed */
1399 if (code == 1)
1400 break; /* input is available */
1401
1402 if (checkAbortByTaskId(taskId)) {
1403 clearStatus(taskId, OPR_WAIT0x200);
1404 printf
1405 ("This tape operation has been aborted by the coordinator\n");
1406 return 'a';
1407 }
1408
1409 if (time(0) > start + BELLTIME60)
1410 break;
1411 }
1412 /* otherwise, we should beep again, check for abort and go back,
1413 * since the GetResponseKey() timed out.
1414 */
1415 if (code == 1)
1416 break; /* input is available */
1417 }
1418 clearStatus(taskId, OPR_WAIT0x200);
1419 if (ch != 'r' && ch != 'o' && ch != 'a') {
1420 printf("Please select one of the 3 options, r, o or a\n");
1421 goto again;
1422 }
1423
1424 return ch;
1425}
1426
1427/* For testing: it prints the tape label */
1428int
1429printTapeLabel(struct butm_tapeLabel *tl)
1430{
1431 printf("Tape Label\n");
1432 printf(" structVersion = %d\n", tl->structVersion);
1433 printf(" creationTime = %u\n", tl->creationTime);
1434 printf(" expirationDate = %u\n", tl->expirationDate);
1435 printf(" AFSName = %s\n", tl->AFSName);
1436 printf(" cell = %s\n", tl->cell);
1437 printf(" dumpid = %d\n", tl->dumpid);
1438 printf(" useCount = %d\n", tl->useCount);
1439 printf(" comment = %s\n", tl->comment);
1440 printf(" pName = %s\n", tl->pName);
1441 printf(" size = %u\n", tl->size);
1442 printf(" dumpPath = %s\n", tl->dumpPath);
1443 return 0;
1444}
1445
1446/* getXBSATape
1447 * Create a tape structure to be satisfy the backup database
1448 * even though we don't really use a tape with XBSA.
1449 */
1450int
1451getXBSATape(struct dumpRock *dparamsPtr)
1452{
1453 struct dumpNode *nodePtr = dparamsPtr->node;
1454 struct butm_tapeInfo *tapeInfoPtr = dparamsPtr->tapeInfoPtr;
1455 struct butm_tapeLabel *tapeLabelPtr = &dparamsPtr->tapeLabel;
1456 afs_int32 code = 0;
1457
1458 tc_MakeTapeName(dparamsPtr->tapeName, &nodePtr->tapeSetDesc,sprintf (dparamsPtr->tapeName, (&nodePtr->tapeSetDesc
)->format, (dparamsPtr->tapeSeq) + (&nodePtr->tapeSetDesc
)->b)
1459 dparamsPtr->tapeSeq)sprintf (dparamsPtr->tapeName, (&nodePtr->tapeSetDesc
)->format, (dparamsPtr->tapeSeq) + (&nodePtr->tapeSetDesc
)->b)
;
1460
1461 GetNewLabel(tapeInfoPtr, "" /*pName */ , dparamsPtr->tapeName,
1462 tapeLabelPtr);
1463 strcpy(tapeLabelPtr->dumpPath, nodePtr->dumpName);
1464 tapeLabelPtr->dumpid = dparamsPtr->databaseDumpId;
1465 tapeLabelPtr->expirationDate =
1466 calcExpirationDate(nodePtr->tapeSetDesc.expType,
1467 nodePtr->tapeSetDesc.expDate, time(0));
1468
1469 /* printTapeLabel(tapeLabelPtr); For testing */
1470
1471 code =
1472 useTape(&dparamsPtr->tape, dparamsPtr->databaseDumpId,
1473 dparamsPtr->tapeName,
1474 (dparamsPtr->tapeSeq + dparamsPtr->dump.tapes.b),
1475 tapeLabelPtr->useCount, tapeLabelPtr->creationTime,
1476 tapeLabelPtr->expirationDate, 0 /*tape position */ );
1477 return (code);
1478}
1479
1480/* getDumpTape
1481 * iterate until the desired tape (as specified by the dump structures)
1482 * is mounted.
1483 * entry:
1484 * interactiveFlag
1485 * 0 - assume the tape is there. Prompt if assumption false
1486 * 1 - prompt regardless
1487 */
1488
1489int
1490getDumpTape(struct dumpRock *dparamsPtr, int interactiveFlag,
1491 afs_int32 append)
1492{
1493 struct dumpNode *nodePtr = dparamsPtr->node;
1494 struct butm_tapeInfo *tapeInfoPtr = dparamsPtr->tapeInfoPtr;
1495 struct butm_tapeLabel *newTapeLabelPtr = &dparamsPtr->tapeLabel;
1496 char AFSTapeName[TC_MAXTAPENAMELEN100];
1497 afs_int32 taskId = nodePtr->taskID;
1498 struct butm_tapeLabel oldTapeLabel;
1499 struct budb_dumpEntry dumpEntry;
1500 struct budb_tapeEntry tapeEntry;
1501 struct budb_volumeEntry volEntry;
1502 Dateafs_uint32 expir;
1503 afs_int32 doAppend;
1504 afs_int32 code = 0;
1505 int askForTape;
1506 int tapecount = 1;
1507 char strlevel[5];
1508 afs_int32 tapepos, lastpos;
1509
1510 extern struct tapeConfig globalTapeConfig;
1511
1512 askForTape = interactiveFlag;
1513 dparamsPtr->wroteLabel = 0;
1514
1515 /* Keep prompting for a tape until we get it right */
1516 while (1) {
1517 /* What the name of the tape would be if not appending to it */
1518 tc_MakeTapeName(AFSTapeName, &nodePtr->tapeSetDesc,sprintf (AFSTapeName, (&nodePtr->tapeSetDesc)->format
, (dparamsPtr->tapeSeq) + (&nodePtr->tapeSetDesc)->
b)
1519 dparamsPtr->tapeSeq)sprintf (AFSTapeName, (&nodePtr->tapeSetDesc)->format
, (dparamsPtr->tapeSeq) + (&nodePtr->tapeSetDesc)->
b)
;
1520
1521 doAppend = append;
1522
1523 if (askForTape) {
1524 code =
1525 PromptForTape((doAppend ? APPENDOPCODE5 : WRITEOPCODE1),
1526 AFSTapeName, dparamsPtr->databaseDumpId, taskId,
1527 tapecount);
1528 if (code)
1529 ERROR_EXIT(code)do { code = code; goto error_exit; } while (0);
1530 }
1531 askForTape = 1;
1532 tapecount++;
1533
1534 /* open the tape device */
1535 code = butm_Mount(tapeInfoPtr, AFSTapeName)(*((tapeInfoPtr)->ops.mount))(tapeInfoPtr,AFSTapeName);
1536 if (code) {
1537 TapeLog(0, taskId, code, tapeInfoPtr->error, "Can't open tape\n");
1538 goto getNewTape;
1539 }
1540
1541 /* Read the tape label */
1542 code = butm_ReadLabel(tapeInfoPtr, &oldTapeLabel, 1)(*((tapeInfoPtr)->ops.readLabel))(tapeInfoPtr,&oldTapeLabel
,1)
; /* rewind */
1543 if (code) {
1544 if (tapeInfoPtr->error) {
1545 ErrorLog(0, taskId, code, tapeInfoPtr->error,
1546 "Warning: Tape error while reading label (will proceed with dump)\n");
1547 }
1548 memset(&oldTapeLabel, 0, sizeof(oldTapeLabel));
1549 }
1550
1551 /* Check if null tape. Prior 3.3, backup tapes have no dump id */
1552 if ((strcmp(oldTapeLabel.AFSName, "") == 0)
1553 && (oldTapeLabel.dumpid == 0)) {
1554 if (doAppend) {
1555 TLog(taskId,
1556 "Dump not found on tape. Proceeding with initial dump\n");
1557 doAppend = 0;
1558 }
1559 } else if (doAppend) { /* appending */
1560 /* Check that we don't have a database dump tape */
1561 if (databaseTape(oldTapeLabel.AFSName)) {
1562 char gotName[BU_MAXTAPELEN32 + 32];
1563
1564 /* label does not match */
1565 LABELNAME(gotName, &oldTapeLabel)if (!strcmp("", ( strcmp((&oldTapeLabel)->pName,"") ? (
&oldTapeLabel)->pName : ( strcmp((&oldTapeLabel)->
AFSName,"") ? (&oldTapeLabel)->AFSName : "<NULL>"
) ))) sprintf(gotName, "<NULL>"); else if ((&oldTapeLabel
)->dumpid == 0) sprintf(gotName, "%s", ( strcmp((&oldTapeLabel
)->pName,"") ? (&oldTapeLabel)->pName : ( strcmp((&
oldTapeLabel)->AFSName,"") ? (&oldTapeLabel)->AFSName
: "<NULL>" ) )); else sprintf(gotName, "%s (%u)", ( strcmp
((&oldTapeLabel)->pName,"") ? (&oldTapeLabel)->
pName : ( strcmp((&oldTapeLabel)->AFSName,"") ? (&
oldTapeLabel)->AFSName : "<NULL>" ) ), (&oldTapeLabel
)->dumpid);
;
1566 TLog(taskId, "Can't append to database tape %s\n", gotName);
1567 goto getNewTape;
1568 }
1569
1570 /* Verify that the tape is of version 4 (AFS 3.3) or greater */
1571 if (oldTapeLabel.structVersion < TAPE_VERSION_44) {
1572 TLog(taskId,
1573 "Can't append: requires tape version %d or greater\n",
1574 TAPE_VERSION_44);
1575 goto getNewTape;
1576 }
1577
1578 /* Verify that the last tape of the dump set is in the drive.
1579 * volEntry will be zeroed if last dump has no volume entries.
1580 */
1581 code =
1582 bcdb_FindLastTape(oldTapeLabel.dumpid, &dumpEntry, &tapeEntry,
1583 &volEntry);
1584 if (code) {
1585 ErrorLog(0, taskId, code, 0,
1586 "Can't append: Can't find last volume of dumpId %u in database\n",
1587 oldTapeLabel.dumpid);
1588 printf("Please scan the dump in or choose another tape\n");
1589 goto getNewTape;
1590 }
1591 lastpos =
1592 (volEntry.position ? volEntry.position : tapeEntry.labelpos);
1593
1594 if (strcmp(TNAME(&oldTapeLabel)( strcmp((&oldTapeLabel)->pName,"") ? (&oldTapeLabel
)->pName : ( strcmp((&oldTapeLabel)->AFSName,"") ? (
&oldTapeLabel)->AFSName : "<NULL>" ) )
, tapeEntry.name)) {
1595 char expName[BU_MAXTAPELEN32 + 32], gotName[BU_MAXTAPELEN32 + 32];
1596
1597 TAPENAME(expName, tapeEntry.name, oldTapeLabel.dumpid)if (!strcmp("", tapeEntry.name)) sprintf(expName, "<NULL>"
); else if (oldTapeLabel.dumpid == 0) sprintf(expName, "%s", tapeEntry
.name); else sprintf(expName, "%s (%u)", tapeEntry.name, oldTapeLabel
.dumpid);
;
1598 LABELNAME(gotName, &oldTapeLabel)if (!strcmp("", ( strcmp((&oldTapeLabel)->pName,"") ? (
&oldTapeLabel)->pName : ( strcmp((&oldTapeLabel)->
AFSName,"") ? (&oldTapeLabel)->AFSName : "<NULL>"
) ))) sprintf(gotName, "<NULL>"); else if ((&oldTapeLabel
)->dumpid == 0) sprintf(gotName, "%s", ( strcmp((&oldTapeLabel
)->pName,"") ? (&oldTapeLabel)->pName : ( strcmp((&
oldTapeLabel)->AFSName,"") ? (&oldTapeLabel)->AFSName
: "<NULL>" ) )); else sprintf(gotName, "%s (%u)", ( strcmp
((&oldTapeLabel)->pName,"") ? (&oldTapeLabel)->
pName : ( strcmp((&oldTapeLabel)->AFSName,"") ? (&
oldTapeLabel)->AFSName : "<NULL>" ) ), (&oldTapeLabel
)->dumpid);
;
1599
1600 TLog(taskId,
1601 "Can't append: Last tape in dump-set is %s, label seen %s\n",
1602 expName, gotName);
1603 goto getNewTape;
1604 }
1605
1606 /* After reading the tape label, we now know what it is */
1607 strcpy(AFSTapeName, oldTapeLabel.AFSName); /* the real name */
1608 strcpy(tapeInfoPtr->name, oldTapeLabel.AFSName); /* the real name */
1609
1610 /* Position after last volume on the tape */
1611 code = butm_SeekEODump(tapeInfoPtr, lastpos)(*((tapeInfoPtr)->ops.seekEODump))(tapeInfoPtr,lastpos);
1612 if (code) {
1613 ErrorLog(0, taskId, code, tapeInfoPtr->error,
1614 "Can't append: Can't position to end of dump on tape %s\n",
1615 tapeEntry.name);
1616 goto getNewTape;
1617 }
1618
1619 /* Track size of tape - set after seek since seek changes the value */
1620 tapeInfoPtr->kBytes = tapeEntry.useKBytes;
1621 } else { /* not appending */
1622
1623 afs_uint32 tapeid;
1624 afs_uint32 dmp;
1625 struct budb_dumpEntry de, de2;
1626
1627 /* Check if tape name is not what expected - null tapes are acceptable
1628 * Don't do check if the tape has a user defined label.
1629 */
1630 if (dump_namecheck && (strcmp(oldTapeLabel.pName, "") == 0)) {
1631 if (strcmp(oldTapeLabel.AFSName, "") && /* not null tape */
1632 strcmp(oldTapeLabel.AFSName, AFSTapeName)) { /* not expected name */
1633 TLog(taskId, "Tape label expected %s, label seen %s\n",
1634 AFSTapeName, oldTapeLabel.AFSName);
1635 goto getNewTape;
1636 }
1637
1638 /* Check that we don't have a database dump tape */
1639 if (databaseTape(oldTapeLabel.AFSName)) {
1640 /* label does not match */
1641 TLog(taskId,
1642 "Tape label expected %s, can't dump to database tape %s\n",
1643 AFSTapeName, oldTapeLabel.AFSName);
1644 goto getNewTape;
1645 }
1646 }
1647
1648 /* Verify the tape has not expired - only check if not appending */
1649 if (!tapeExpired(&oldTapeLabel)) {
1650 TLog(taskId, "This tape has not expired\n");
1651 goto getNewTape;
1652 }
1653
1654 /* Given a tape dump with good data, verify we don't overwrite recent dumps
1655 * and also verify that the volume will be restorable - if not print warnings
1656 */
1657 if (oldTapeLabel.dumpid) {
1658 /* Do not overwrite a tape that belongs to the dump's dumpset */
1659 tapeid =
1660 (dparamsPtr->initialDumpId ? dparamsPtr->
1661 initialDumpId : dparamsPtr->databaseDumpId);
1662 if (oldTapeLabel.dumpid == tapeid) {
1663 ErrorLog(0, taskId, 0, 0,
1664 "Can't overwrite tape containing the dump in progress\n");
1665 goto getNewTape;
1666 }
1667
1668 /* Since the dumpset on this tape will be deleted from database, check if
1669 * any of the dump's parent-dumps are on this tape.
1670 */
1671 for (dmp = nodePtr->parent; dmp; dmp = de.parent) {
1672 code = bcdb_FindDumpByID(dmp, &de);
1673 if (code) {
1674 ErrorLog(0, taskId, 0, 0,
1675 "Warning: Can't find parent dump %u in backup database\n",
1676 dmp);
1677 break;
1678 }
1679
1680 tapeid = (de.initialDumpID ? de.initialDumpID : de.id);
1681 if (oldTapeLabel.dumpid == tapeid) {
1682 ErrorLog(0, taskId, 0, 0,
1683 "Can't overwrite the parent dump %s (DumpID %u)\n",
1684 de.name, de.id);
1685 goto getNewTape;
1686 }
1687 }
1688
1689 /* Since the dumpset on this tape will be deleted from database, check if
1690 * any of the dumps in this dumpset are most-recent-dumps.
1691 */
1692 for (dmp = oldTapeLabel.dumpid; dmp; dmp = de.appendedDumpID) {
1693 if (dmp == dparamsPtr->lastDump.id) {
1694 memcpy(&de, &dparamsPtr->lastDump, sizeof(de));
1695 memcpy(&de2, &dparamsPtr->lastDump, sizeof(de2));
1696 } else {
1697 code = bcdb_FindDumpByID(dmp, &de);
1698 if (code)
1699 break;
1700 sprintf(strlevel, "%d", de.level);
1701 code =
1702 bcdb_FindLatestDump(de.volumeSetName, strlevel,
1703 &de2);
1704 if (code)
1705 continue;
1706 }
1707
1708 /* If dump on the tape is the latest dump at this level */
1709 if (de.id == de2.id) {
1710 if (strcmp(DUMP_TAPE_NAME"Ubik_db_dump", de2.name) == 0) {
1711 ErrorLog(0, taskId, 0, 0,
1712 "Warning: Overwriting most recent dump %s (DumpID %u)\n",
1713 de.name, de.id);
1714 } else {
1715 ErrorLog(0, taskId, 0, 0,
1716 "Warning: Overwriting most recent dump of the '%s' volumeset: %s (DumpID %u)\n",
1717 de.volumeSetName, de.name, de.id);
1718 }
1719 }
1720 }
1721 } /* if (oldTapeLabel.dumpid) */
1722 } /* else not appending */
1723
1724 /*
1725 * Now have the right tape. Create a new label for the tape
1726 * Appended labels have the dump's dumpId - labels at beginnings of
1727 * tape have the initial dump's dumpId.
1728 * Appended labels do not increment the useCount.
1729 * Labels at beginnings of tape use the most future expiration of the dump set.
1730 */
1731 GetNewLabel(tapeInfoPtr, oldTapeLabel.pName, AFSTapeName,
1732 newTapeLabelPtr);
1733 strcpy(newTapeLabelPtr->dumpPath, nodePtr->dumpName);
1734 newTapeLabelPtr->expirationDate =
1735 calcExpirationDate(nodePtr->tapeSetDesc.expType,
1736 nodePtr->tapeSetDesc.expDate, time(0));
1737 newTapeLabelPtr->dumpid = dparamsPtr->databaseDumpId;
1738 newTapeLabelPtr->useCount = oldTapeLabel.useCount;
1739
1740 if (!doAppend) {
1741 newTapeLabelPtr->useCount++;
1742 if (dparamsPtr->initialDumpId) {
1743 newTapeLabelPtr->dumpid = dparamsPtr->initialDumpId;
1744 expir = ExpirationDate(dparamsPtr->initialDumpId);
1745 if (expir > newTapeLabelPtr->expirationDate)
1746 newTapeLabelPtr->expirationDate = expir;
1747 }
1748 }
1749
1750 /* write the label on the tape - rewind if not appending and vice-versa */
1751 code = butm_Create(tapeInfoPtr, newTapeLabelPtr, !doAppend)(*((tapeInfoPtr)->ops.create))(tapeInfoPtr,newTapeLabelPtr
,!doAppend)
;
1752 if (code) {
1753 char gotName[BU_MAXTAPELEN32 + 32];
1754
1755 LABELNAME(gotName, newTapeLabelPtr)if (!strcmp("", ( strcmp((newTapeLabelPtr)->pName,"") ? (newTapeLabelPtr
)->pName : ( strcmp((newTapeLabelPtr)->AFSName,"") ? (newTapeLabelPtr
)->AFSName : "<NULL>" ) ))) sprintf(gotName, "<NULL>"
); else if ((newTapeLabelPtr)->dumpid == 0) sprintf(gotName
, "%s", ( strcmp((newTapeLabelPtr)->pName,"") ? (newTapeLabelPtr
)->pName : ( strcmp((newTapeLabelPtr)->AFSName,"") ? (newTapeLabelPtr
)->AFSName : "<NULL>" ) )); else sprintf(gotName, "%s (%u)"
, ( strcmp((newTapeLabelPtr)->pName,"") ? (newTapeLabelPtr
)->pName : ( strcmp((newTapeLabelPtr)->AFSName,"") ? (newTapeLabelPtr
)->AFSName : "<NULL>" ) ), (newTapeLabelPtr)->dumpid
);
;
1756 TapeLog(0, taskId, code, tapeInfoPtr->error,
1757 "Can't label tape as %s\n", gotName);
1758 goto getNewTape;
1759 }
1760 dparamsPtr->wroteLabel = 1; /* Remember we wrote the label */
1761 tapepos = tapeInfoPtr->position - 1;
1762
1763 strcpy(dparamsPtr->tapeName, TNAME(newTapeLabelPtr)( strcmp((newTapeLabelPtr)->pName,"") ? (newTapeLabelPtr)->
pName : ( strcmp((newTapeLabelPtr)->AFSName,"") ? (newTapeLabelPtr
)->AFSName : "<NULL>" ) )
);
1764
1765 /* If appending, set dumpentry in the database as appended. */
1766 if (doAppend) {
1767 char gotName[BU_MAXTAPELEN32 + 32];
1768
1769 nodePtr->tapeSetDesc.b = extractTapeSeq(AFSTapeName);
1770 dparamsPtr->dump.tapes.b = nodePtr->tapeSetDesc.b;
1771 dparamsPtr->initialDumpId = oldTapeLabel.dumpid;
1772 strcpy(nodePtr->tapeSetDesc.format, dumpEntry.tapes.format);
1773
1774 code =
1775 bcdb_MakeDumpAppended(dparamsPtr->databaseDumpId,
1776 dparamsPtr->initialDumpId,
1777 nodePtr->tapeSetDesc.b);
1778 if (code)
1779 ErrorLog(2, taskId, code, 0,
1780 "Warning: Can't append dump %u to dump %u in database\n",
1781 dparamsPtr->databaseDumpId,
1782 dparamsPtr->initialDumpId);
1783
1784 LABELNAME(gotName, &oldTapeLabel)if (!strcmp("", ( strcmp((&oldTapeLabel)->pName,"") ? (
&oldTapeLabel)->pName : ( strcmp((&oldTapeLabel)->
AFSName,"") ? (&oldTapeLabel)->AFSName : "<NULL>"
) ))) sprintf(gotName, "<NULL>"); else if ((&oldTapeLabel
)->dumpid == 0) sprintf(gotName, "%s", ( strcmp((&oldTapeLabel
)->pName,"") ? (&oldTapeLabel)->pName : ( strcmp((&
oldTapeLabel)->AFSName,"") ? (&oldTapeLabel)->AFSName
: "<NULL>" ) )); else sprintf(gotName, "%s (%u)", ( strcmp
((&oldTapeLabel)->pName,"") ? (&oldTapeLabel)->
pName : ( strcmp((&oldTapeLabel)->AFSName,"") ? (&
oldTapeLabel)->AFSName : "<NULL>" ) ), (&oldTapeLabel
)->dumpid);
;
1785 TLog(taskId, "Appending dump %s (DumpID %u) to tape %s\n",
1786 nodePtr->dumpSetName, dparamsPtr->databaseDumpId, gotName);
1787 }
1788
1789 /* If not appending, delete overwritten dump from the database */
1790 else {
1791 if ((oldTapeLabel.structVersion >= TAPE_VERSION_33)
1792 && oldTapeLabel.dumpid) {
1793 code = bcdb_deleteDump(oldTapeLabel.dumpid, 0, 0, 0);
1794 if (code && (code != BUDB_NOENT(156303877L)))
1795 ErrorLog(0, taskId, code, 0,
1796 "Warning: Can't delete old dump %u from database\n",
1797 oldTapeLabel.dumpid);
1798 }
1799 }
1800
1801 code =
1802 useTape(&dparamsPtr->tape, dparamsPtr->databaseDumpId,
1803 dparamsPtr->tapeName,
1804 (dparamsPtr->tapeSeq + dparamsPtr->dump.tapes.b),
1805 newTapeLabelPtr->useCount, newTapeLabelPtr->creationTime,
1806 newTapeLabelPtr->expirationDate, tapepos);
1807
1808 /*
1809 * The margin of space to check for end of tape is set to the
1810 * amount of space used to write an end-of-tape multiplied by 2.
1811 * The amount of space is size of a 16K volume trailer, a 16K File
1812 * End mark, its EOF marker, a 16K EODump marker, its EOF marker,
1813 * and up to two EOF markers done on close (3 16K blocks + 4 EOF
1814 * markers).
1815 */
1816 tc_EndMargin = (3 * 16384 + 4 * globalTapeConfig.fileMarkSize) * 2;
1817 tc_KEndMargin = tc_EndMargin / 1024;
1818 break;
1819
1820 getNewTape:
1821 unmountTape(taskId, tapeInfoPtr);
1822 }
1823
1824 error_exit:
1825 return (code);
1826}
1827
1828int
1829makeVolumeHeader(struct volumeHeader *vhptr, struct dumpRock *dparamsPtr,
1830 int fragmentNumber)
1831{
1832 struct dumpNode *nodePtr = dparamsPtr->node;
1833 struct tc_dumpDesc *curDump;
1834 afs_int32 code = 0;
1835
1836 curDump = &nodePtr->dumps[dparamsPtr->curVolume];
1837
1838 memset(vhptr, 0, sizeof(*vhptr));
1839 strcpy(vhptr->volumeName, curDump->name);
1840 vhptr->volumeID = curDump->vid;
1841 vhptr->cloneDate = curDump->cloneDate;
1842 vhptr->server = curDump->hostAddr;
1843 vhptr->part = curDump->partition;
1844 vhptr->from = curDump->date;
1845 vhptr->frag = fragmentNumber;
1846 vhptr->contd = 0;
1847 vhptr->magic = TC_VOLBEGINMAGIC0xb0258191;
1848 vhptr->dumpID = dparamsPtr->databaseDumpId; /* real dump id */
1849 vhptr->level = nodePtr->level;
1850 vhptr->parentID = nodePtr->parent;
1851 vhptr->endTime = 0;
1852 vhptr->versionflags = CUR_TAPE_VERSION4;
1853 strcpy(vhptr->dumpSetName, nodePtr->dumpSetName);
1854 strcpy(vhptr->preamble, "H++NAME#");
1855 strcpy(vhptr->postamble, "T--NAME#");
1856
1857 return (code);
1858}
1859
1860int
1861volumeHeader_hton(struct volumeHeader *hostPtr, struct volumeHeader *netPtr)
1862{
1863 struct volumeHeader volHdr;
1864
1865 strcpy(volHdr.preamble, hostPtr->preamble);
1866 strcpy(volHdr.postamble, hostPtr->postamble);
1867 strcpy(volHdr.volumeName, hostPtr->volumeName);
1868 strcpy(volHdr.dumpSetName, hostPtr->dumpSetName);
1869 volHdr.volumeID = htonl(hostPtr->volumeID)(__builtin_constant_p(hostPtr->volumeID) ? ((((__uint32_t)
(hostPtr->volumeID)) >> 24) | ((((__uint32_t)(hostPtr
->volumeID)) & (0xff << 16)) >> 8) | ((((__uint32_t
)(hostPtr->volumeID)) & (0xff << 8)) << 8)
| (((__uint32_t)(hostPtr->volumeID)) << 24)) : __bswap32_var
(hostPtr->volumeID))
;
1870 volHdr.server = htonl(hostPtr->server)(__builtin_constant_p(hostPtr->server) ? ((((__uint32_t)(hostPtr
->server)) >> 24) | ((((__uint32_t)(hostPtr->server
)) & (0xff << 16)) >> 8) | ((((__uint32_t)(hostPtr
->server)) & (0xff << 8)) << 8) | (((__uint32_t
)(hostPtr->server)) << 24)) : __bswap32_var(hostPtr->
server))
;
1871 volHdr.part = htonl(hostPtr->part)(__builtin_constant_p(hostPtr->part) ? ((((__uint32_t)(hostPtr
->part)) >> 24) | ((((__uint32_t)(hostPtr->part))
& (0xff << 16)) >> 8) | ((((__uint32_t)(hostPtr
->part)) & (0xff << 8)) << 8) | (((__uint32_t
)(hostPtr->part)) << 24)) : __bswap32_var(hostPtr->
part))
;
1872 volHdr.from = htonl(hostPtr->from)(__builtin_constant_p(hostPtr->from) ? ((((__uint32_t)(hostPtr
->from)) >> 24) | ((((__uint32_t)(hostPtr->from))
& (0xff << 16)) >> 8) | ((((__uint32_t)(hostPtr
->from)) & (0xff << 8)) << 8) | (((__uint32_t
)(hostPtr->from)) << 24)) : __bswap32_var(hostPtr->
from))
;
1873 volHdr.frag = htonl(hostPtr->frag)(__builtin_constant_p(hostPtr->frag) ? ((((__uint32_t)(hostPtr
->frag)) >> 24) | ((((__uint32_t)(hostPtr->frag))
& (0xff << 16)) >> 8) | ((((__uint32_t)(hostPtr
->frag)) & (0xff << 8)) << 8) | (((__uint32_t
)(hostPtr->frag)) << 24)) : __bswap32_var(hostPtr->
frag))
;
1874 volHdr.magic = htonl(hostPtr->magic)(__builtin_constant_p(hostPtr->magic) ? ((((__uint32_t)(hostPtr
->magic)) >> 24) | ((((__uint32_t)(hostPtr->magic
)) & (0xff << 16)) >> 8) | ((((__uint32_t)(hostPtr
->magic)) & (0xff << 8)) << 8) | (((__uint32_t
)(hostPtr->magic)) << 24)) : __bswap32_var(hostPtr->
magic))
;
1875 volHdr.contd = htonl(hostPtr->contd)(__builtin_constant_p(hostPtr->contd) ? ((((__uint32_t)(hostPtr
->contd)) >> 24) | ((((__uint32_t)(hostPtr->contd
)) & (0xff << 16)) >> 8) | ((((__uint32_t)(hostPtr
->contd)) & (0xff << 8)) << 8) | (((__uint32_t
)(hostPtr->contd)) << 24)) : __bswap32_var(hostPtr->
contd))
;
1876 volHdr.dumpID = htonl(hostPtr->dumpID)(__builtin_constant_p(hostPtr->dumpID) ? ((((__uint32_t)(hostPtr
->dumpID)) >> 24) | ((((__uint32_t)(hostPtr->dumpID
)) & (0xff << 16)) >> 8) | ((((__uint32_t)(hostPtr
->dumpID)) & (0xff << 8)) << 8) | (((__uint32_t
)(hostPtr->dumpID)) << 24)) : __bswap32_var(hostPtr->
dumpID))
;
1877 volHdr.level = htonl(hostPtr->level)(__builtin_constant_p(hostPtr->level) ? ((((__uint32_t)(hostPtr
->level)) >> 24) | ((((__uint32_t)(hostPtr->level
)) & (0xff << 16)) >> 8) | ((((__uint32_t)(hostPtr
->level)) & (0xff << 8)) << 8) | (((__uint32_t
)(hostPtr->level)) << 24)) : __bswap32_var(hostPtr->
level))
;
1878 volHdr.parentID = htonl(hostPtr->parentID)(__builtin_constant_p(hostPtr->parentID) ? ((((__uint32_t)
(hostPtr->parentID)) >> 24) | ((((__uint32_t)(hostPtr
->parentID)) & (0xff << 16)) >> 8) | ((((__uint32_t
)(hostPtr->parentID)) & (0xff << 8)) << 8)
| (((__uint32_t)(hostPtr->parentID)) << 24)) : __bswap32_var
(hostPtr->parentID))
;
1879 volHdr.endTime = htonl(hostPtr->endTime)(__builtin_constant_p(hostPtr->endTime) ? ((((__uint32_t)(
hostPtr->endTime)) >> 24) | ((((__uint32_t)(hostPtr->
endTime)) & (0xff << 16)) >> 8) | ((((__uint32_t
)(hostPtr->endTime)) & (0xff << 8)) << 8) |
(((__uint32_t)(hostPtr->endTime)) << 24)) : __bswap32_var
(hostPtr->endTime))
;
1880 volHdr.versionflags = htonl(hostPtr->versionflags)(__builtin_constant_p(hostPtr->versionflags) ? ((((__uint32_t
)(hostPtr->versionflags)) >> 24) | ((((__uint32_t)(hostPtr
->versionflags)) & (0xff << 16)) >> 8) | (
(((__uint32_t)(hostPtr->versionflags)) & (0xff <<
8)) << 8) | (((__uint32_t)(hostPtr->versionflags)) <<
24)) : __bswap32_var(hostPtr->versionflags))
;
1881 volHdr.cloneDate = htonl(hostPtr->cloneDate)(__builtin_constant_p(hostPtr->cloneDate) ? ((((__uint32_t
)(hostPtr->cloneDate)) >> 24) | ((((__uint32_t)(hostPtr
->cloneDate)) & (0xff << 16)) >> 8) | ((((
__uint32_t)(hostPtr->cloneDate)) & (0xff << 8)) <<
8) | (((__uint32_t)(hostPtr->cloneDate)) << 24)) : __bswap32_var
(hostPtr->cloneDate))
;
1882
1883 memcpy(netPtr, &volHdr, sizeof(struct volumeHeader));
1884 return 0;
1885}
1886
1887/* database related routines */
1888
1889afs_int32
1890createDump(struct dumpRock *dparamsPtr)
1891{
1892 struct dumpNode *nodePtr = dparamsPtr->node;
1893 struct budb_dumpEntry *dumpPtr;
1894 afs_int32 code = 0;
1895
1896 dumpPtr = &dparamsPtr->dump;
1897 memset(dumpPtr, 0, sizeof(*dumpPtr));
1898
1899 /* id filled in by database */
1900 dumpPtr->parent = nodePtr->parent;
1901 dumpPtr->level = nodePtr->level;
1902 dumpPtr->flags = 0;
1903#ifdef xbsa
1904 if (CONF_XBSA0) {
1905 if (xbsaType == XBSA_SERVER_TYPE_ADSM0x02) {
1906 strcpy(dumpPtr->tapes.tapeServer, butxInfo.serverName);
1907 dumpPtr->flags = BUDB_DUMP_ADSM(1<<12);
1908 }
1909 if (!(butxInfo.serverType & XBSA_SERVER_FLAG_MULTIPLE)) {
1910 /* The current server (API) doesn't provide the function required
1911 * to specify a server at startup time. For that reason, we can't
1912 * be sure that the server name supplied by the user in the user-
1913 * defined configuration file is correct. We set a flag here so
1914 * we know at restore time that the servername info in the backup
1915 * database may be incorrect. We will not allow a server switch
1916 * at that time, even if the server at restore time supports
1917 * multiple servers.
1918 */
1919 dumpPtr->flags |= BUDB_DUMP_XBSA_NSS(1<<8);
1920 }
1921 }
1922#endif
1923 strcpy(dumpPtr->volumeSetName, nodePtr->volumeSetName);
1924 strcpy(dumpPtr->dumpPath, nodePtr->dumpName);
1925 strcpy(dumpPtr->name, nodePtr->dumpSetName);
1926 dumpPtr->created = 0; /* let database assign it */
1927 dumpPtr->incTime = 0; /* not really used */
1928 dumpPtr->nVolumes = 0;
1929 dumpPtr->initialDumpID = 0;
1930
1931 dumpPtr->tapes.id = groupId;
1932 dumpPtr->tapes.b = 1;
1933 dumpPtr->tapes.maxTapes = 0;
1934 strcpy(dumpPtr->tapes.format, nodePtr->tapeSetDesc.format);
1935
1936 /* principal filled in by database */
1937
1938 /* now call the database to create the entry */
1939 code = bcdb_CreateDump(dumpPtr);
1940 if (code == 0)
1941 dparamsPtr->databaseDumpId = dumpPtr->id;
1942
1943 return (code);
1944}
1945
1946#ifdef xbsa
1947/* InitToServer:
1948 * Initialize to a specific server. The first time, we remember the
1949 * server as the original server and go back to it each time we pass 0
1950 * as the server.
1951 */
1952afs_int32
1953InitToServer(afs_int32 taskId, struct butx_transactionInfo * butxInfoP,
1954 char *server)
1955{
1956 static char origserver[BSA_MAX_DESC];
1957 static int init = 0;
1958 afs_int32 rc, code = 0;
1959
1960 if (!init) {
1961 strcpy(origserver, "");
1962 init = 1;
1963 }
1964
1965 if (!server)
1966 server = origserver; /* return to original server */
1967 if (strcmp(server, "") == 0)
1968 return 0; /* No server, do nothing */
1969 if (strcmp(butxInfoP->serverName, server) == 0)
1970 return 0; /* same server, do nothing */
1971 if (strcmp(origserver, "") == 0)
1972 strcpy(origserver, server); /* remember original server */
1973
1974 if (strcmp(butxInfoP->serverName, "") != 0) {
1975 /* If already connected to a server, disconnect from it.
1976 * Check to see if our server does not support switching.
1977 */
1978 if (!(butxInfo.serverType & XBSA_SERVER_FLAG_MULTIPLE)) {
1979 ErrorLog(0, taskId, TC_BADTASK(156566293L), 0,
1980 "This version of XBSA libraries does not support switching "
1981 "from server %s to server %s\n", butxInfoP->serverName,
1982 server);
1983 return (TC_BADTASK(156566293L));
1984 }
1985
1986 rc = xbsa_Finalize(&butxInfo);
1987 if (rc != XBSA_SUCCESS) {
1988 ErrorLog(0, taskId, rc, 0,
1989 "InitToServer: Unable to terminate the connection to server %s\n",
1990 butxInfoP->serverName);
1991 ERROR_EXIT(rc)do { code = rc; goto error_exit; } while (0);
1992 }
1993 }
1994
1995 /* initialize to the new server */
1996 rc = xbsa_Initialize(&butxInfo, xbsaObjectOwner, appObjectOwner,
1997 xbsaSecToken, server);
1998 if (rc != XBSA_SUCCESS) {
1999 ErrorLog(0, taskId, rc, 0,
2000 "InitToServer: Unable to initialize the XBSA library to server %s\n",
2001 server);
2002 ERROR_EXIT(rc)do { code = rc; goto error_exit; } while (0);
2003 }
2004
2005 error_exit:
2006 return (code);
2007}
2008
2009
2010/* DeleteDump
2011 *
2012 */
2013void *
2014DeleteDump(void *param)
2015{
2016 struct deleteDumpIf *ptr = (struct deleteDumpIf *)param;
2017
2018 afs_int32 taskId;
2019 afs_int32 rc, code = 0;
2020 afs_uint32 dumpid;
2021 afs_int32 index, next, dbTime;
2022 budb_volumeList vl;
2023 struct budb_dumpEntry dumpEntry;
2024 char tapeName[BU_MAXTAPELEN32];
2025 char dumpIdStr[XBSA_MAX_OSNAME];
2026 char volumeNameStr[XBSA_MAX_PATHNAME];
2027 afs_int32 i;
2028 int intrans = 0;
2029 int allnotfound = 1, onenotfound = 0;
2030 extern struct udbHandleS udbHandle;
2031 extern struct deviceSyncNode *deviceLatch;
2032
2033 afs_pthread_setname_self("deletedump")(void)0;
2034 setStatus(taskId, DRIVE_WAIT0x100);
2035 EnterDeviceQueue(deviceLatch);
2036 clearStatus(taskId, DRIVE_WAIT0x100);
2037
2038 dumpid = ptr->dumpID;
2039 taskId = ptr->taskId; /* Get task Id */
2040
2041 printf("\n\n");
2042 TapeLog(2, taskId, 0, 0, "Delete Dump %u\n", dumpid);
2043
2044 vl.budb_volumeList_len = 0;
2045 vl.budb_volumeList_val = 0;
2046 tapeName[0] = '\0';
2047
2048 /* Get the dump info for the dump we are deleting */
2049 rc = bcdb_FindDumpByID(dumpid, &dumpEntry);
2050 if (rc) {
2051 ErrorLog(0, taskId, rc, 0,
2052 "Unable to locate dump ID %u in database\n", dumpid);
2053 setStatus(taskId, TASK_ERROR0x80);
2054 ERROR_EXIT(rc)do { code = rc; goto error_exit; } while (0);
2055 }
2056
2057 /* we must make sure that we are configured with the correct type of
2058 * XBSA server for this dump delete! Only those dumped to an ADSM server.
2059 */
2060 if ((xbsaType == XBSA_SERVER_TYPE_ADSM0x02)
2061 && !((dumpEntry.flags & (BUDB_DUMP_ADSM(1<<12) | BUDB_DUMP_BUTA(1<<11))))) {
2062 ErrorLog(0, taskId, TC_BADTASK(156566293L), 0,
2063 "The dump %u requested for deletion is incompatible with this instance of butc\n",
2064 dumpid);
2065 setStatus(taskId, TASK_ERROR0x80);
2066 ERROR_EXIT(TC_BADTASK)do { code = (156566293L); goto error_exit; } while (0);
2067 }
2068
2069 /* Make sure we are connected to the correct server. If not, switch to it if appropriate */
2070 if ((strlen((char *)dumpEntry.tapes.tapeServer) != 0)
2071 && (strcmp((char *)dumpEntry.tapes.tapeServer, butxInfo.serverName) !=
2072 0)) {
2073
2074 /* Check to see if the tapeServer name is trustworthy */
2075 if ((dumpEntry.flags & (BUDB_DUMP_XBSA_NSS(1<<8) | BUDB_DUMP_BUTA(1<<11)))
2076 && !forcemultiple) {
2077 /* The dump was made with a version of the XBSA interface
2078 * that didn't allow switching of servers, we can't be sure
2079 * that the servername in the backup database is correct. So,
2080 * we will check the servername and log it if they don't match;
2081 * but we will try to do the delete without switching servers.
2082 */
2083 TLog(taskId,
2084 "The dump %d requested for deletion is on server %s "
2085 "but butc is connected to server %s "
2086 "(Attempting to delete the dump anyway)\n", dumpid,
2087 (char *)dumpEntry.tapes.tapeServer, butxInfo.serverName);
2088 } else {
2089 TLog(taskId,
2090 "The dump %u requested for deletion is on server %s "
2091 "but butc is connected to server %s "
2092 "(switching servers)\n", dumpid,
2093 (char *)dumpEntry.tapes.tapeServer, butxInfo.serverName);
2094
2095 rc = InitToServer(taskId, &butxInfo,
2096 (char *)dumpEntry.tapes.tapeServer);
2097 if (rc != XBSA_SUCCESS) {
2098 setStatus(taskId, TASK_ERROR0x80);
2099 ERROR_EXIT(rc)do { code = rc; goto error_exit; } while (0);
2100 }
2101 }
2102 }
2103
2104 /* Start a new Transaction */
2105 rc = xbsa_BeginTrans(&butxInfo);
2106 if (rc != XBSA_SUCCESS) {
2107 ErrorLog(0, taskId, rc, 0, "Unable to create a new transaction\n");
2108 setStatus(taskId, TASK_ERROR0x80);
2109 ERROR_EXIT(rc)do { code = rc; goto error_exit; } while (0);
2110 }
2111 intrans = 1;
2112
2113 /* Query the backup database for list of volumes to delete */
2114 for (index = next = 0; index != -1; index = next) {
2115 rc = ubik_Call_SingleServer(BUDB_GetVolumes, udbHandle.uh_client,
2116 UF_SINGLESERVER1, BUDB_MAJORVERSION2,
2117 BUDB_OP_DUMPID(2<<3), tapeName, dumpid, 0,
2118 index, &next, &dbTime, &vl);
2119 if (rc) {
2120 if (rc == BUDB_ENDOFLIST(156303886L))
2121 break;
2122 ErrorLog(0, taskId, rc, 0, "Can't find volume info for dump %d\n",
2123 dumpid);
2124 setStatus(taskId, TASK_ERROR0x80);
2125 ERROR_EXIT(rc)do { code = rc; goto error_exit; } while (0);
2126 }
2127
2128 /* Delete all volumes on the list */
2129 for (i = 0; i < vl.budb_volumeList_len; i++) {
2130 if (dumpEntry.flags & BUDB_DUMP_BUTA(1<<11)) {
2131 /* dump was from buta, use old buta style names */
2132 sprintf(dumpIdStr, "/%d", dumpid);
2133 strcpy(volumeNameStr, "/");
2134 strcat(volumeNameStr, (char *)vl.budb_volumeList_val[i].name);
2135 } else { /* BUDB_DUMP_ADSM */
2136 /* dump was from butc to ADSM, use butc names */
2137 strcpy(dumpIdStr, butcdumpIdStr);
2138 sprintf(volumeNameStr, "/%d", dumpid);
2139 strcat(volumeNameStr, "/");
2140 strcat(volumeNameStr, (char *)vl.budb_volumeList_val[i].name);
2141 }
2142
2143 rc = xbsa_DeleteObject(&butxInfo, dumpIdStr, volumeNameStr);
2144 if (rc != XBSA_SUCCESS) {
2145 ErrorLog(0, taskId, rc, 0,
2146 "Unable to delete the object %s of dump %s from the server\n",
2147 volumeNameStr, dumpIdStr);
2148 /* Don't exit if volume was not found */
2149 if (rc != BUTX_DELETENOVOL(156571678L)) {
2150 allnotfound = 0;
2151 ERROR_EXIT(rc)do { code = rc; goto error_exit; } while (0);
2152 }
2153 onenotfound = 1;
2154 } else {
2155 allnotfound = 0;
2156 TLog(0,
2157 "Deleted volume %s (%u) in dumpID %u from the backup server\n",
2158 vl.budb_volumeList_val[i].name,
2159 vl.budb_volumeList_val[i].id, dumpid);
2160 }
2161 }
2162
2163 /* free the memory allocated by RPC for this list */
2164 if (vl.budb_volumeList_val)
2165 free(vl.budb_volumeList_val);
2166 vl.budb_volumeList_len = 0;
2167 vl.budb_volumeList_val = 0;
2168 }
2169
2170 error_exit:
2171 if (intrans) {
2172 rc = xbsa_EndTrans(&butxInfo);
2173 if (rc != XBSA_SUCCESS) {
2174 ErrorLog(0, taskId, rc, 0,
2175 "Unable to terminate the current transaction\n");
2176 setStatus(taskId, TASK_ERROR0x80);
2177 ERROR_EXIT(rc)do { code = rc; goto error_exit; } while (0);
2178 }
2179 }
2180
2181 /* Switch back to the original server */
2182 rc = InitToServer(taskId, &butxInfo, NULL((void *)0));
2183
2184 if (vl.budb_volumeList_val)
2185 free(vl.budb_volumeList_val);
2186
2187 setStatus(taskId, TASK_DONE0x20);
2188 FreeNode(taskId); /* free the dump node */
2189 LeaveDeviceQueue(deviceLatch);
2190
2191 /* If we don't find any dumps on the server, rather than returning
2192 * a success, return a failure.
2193 */
2194 if (!code && onenotfound && allnotfound) {
2195 code = BUTX_DELETENOVOL(156571678L);
2196 setStatus(taskId, TASK_ERROR0x80);
2197 }
2198 return (void *)(code);
2199}
2200#endif