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
10 #include <afsconfig.h>
11 #include <afs/param.h>
17 #include <sys/types.h>
20 #include <sys/statfs.h>
27 #include <netinet/in.h>
39 #include <afs/voldefs.h>
42 #include <afs/vlserver.h>
45 #include <afs/cellconfig.h>
48 #include <afs/afsint.h>
52 #include <afs/com_err.h>
54 #include <afs/kautils.h>
57 #define ERRCODE_RANGE 8 /* from error_table.h */
58 #define CLOCKSKEW 2 /* not really skew, but resolution */
60 /* for UV_MoveVolume() recovery */
62 #include <afs/procmgmt.h> /* signal(), kill(), wait(), etc. */
65 #include <volser_prototypes.h>
67 struct ubik_client *cstruct;
72 afs_int32 vldbEntryIndex;
75 /* Utility macros used by rest of this source file */
76 #define EPRINT(ec, es) \
78 fprintf(STDERR, "\n"); \
79 fprintf(STDERR, (es)); \
83 #define EPRINT1(ec, es, ep1) \
85 fprintf(STDERR, "\n"); \
86 fprintf(STDERR, (es), (ep1)); \
90 #define EPRINT2(ec, es, ep1, ep2) \
92 fprintf(STDERR, "\n"); \
93 fprintf(STDERR, (es), (ep1), (ep2)); \
97 #define EPRINT3(ec, es, ep1, ep2, ep3) \
99 fprintf(STDERR, "\n"); \
100 fprintf(STDERR, (es), (ep1), (ep2), (ep3)); \
101 PrintError(" ",ec); \
104 #define EGOTO(where, ec, es) \
113 #define EGOTO1(where, ec, es, ep1) \
116 EPRINT1((ec),(es),(ep1)); \
122 #define EGOTO2(where, ec, es, ep1, ep2) \
125 EPRINT2((ec),(es),(ep1),(ep2)); \
131 #define EGOTO3(where, ec, es, ep1, ep2, ep3) \
134 EPRINT3((ec),(es),(ep1),(ep2),(ep3)); \
141 { if (verbose) { fprintf(STDOUT, (es)); fflush(STDOUT); } }
142 #define VPRINT1(es, p) \
143 { if (verbose) { fprintf(STDOUT, (es), (p)); fflush(STDOUT); } }
144 #define VPRINT2(es, p1, p2) \
145 { if (verbose) { fprintf(STDOUT, (es), (p1), (p2)); fflush(STDOUT); } }
146 #define VPRINT3(es, p1, p2, p3) \
147 { if (verbose) { fprintf(STDOUT, (es), (p1), (p2), (p3)); fflush(STDOUT); } }
149 { if (verbose) { fprintf(STDOUT, " done\n"); fflush(STDOUT); } }
153 /* getting rid of this */
154 #define ERROR_EXIT(code) {error=(code); goto error_exit;}
157 /* Protos for static routines */
158 static afs_int32 CheckAndDeleteVolume(struct rx_connection *aconn,
159 afs_int32 apart, afs_int32 okvol,
161 static int DelVol(struct rx_connection *conn, afs_int32 vid, afs_int32 part,
163 static int GetTrans(struct nvldbentry *vldbEntryPtr, afs_int32 index,
164 struct rx_connection **connPtr, afs_int32 * transPtr,
165 afs_int32 * timePtr);
166 static int SimulateForwardMultiple(struct rx_connection *fromconn,
167 afs_int32 fromtid, afs_int32 fromdate,
168 manyDests * tr, afs_int32 flags,
169 void *cookie, manyResults * results);
170 static int rel_compar(struct release *r1, struct release *r2);
171 static afs_int32 CheckVolume(volintInfo * volumeinfo, afs_int32 aserver,
172 afs_int32 apart, afs_int32 * modentry,
173 afs_uint32 * maxvolid);
176 /*map the partition <partId> into partition name <partName>*/
178 MapPartIdIntoName(afs_int32 partId, char *partName)
180 if (partId < 26) { /* what if partId > = 26 ? */
181 strcpy(partName, "/vicep");
182 partName[6] = partId + 'a';
185 } else if (partId < VOLMAXPARTS) {
186 strcpy(partName, "/vicep");
188 partName[6] = 'a' + (partId / 26);
189 partName[7] = 'a' + (partId % 26);
201 fprintf(STDERR, "Do you want to %s? [yn](n): ", str);
202 response = c = getchar();
203 while (!(c == EOF || c == '\n'))
204 c = getchar(); /*skip to end of line */
205 code = (response == 'y' || response == 'Y');
211 PrintError(char *msg, afs_int32 errcode)
213 fprintf(STDERR, msg);
214 /*replace by a big switch statement */
219 fprintf(STDERR, "Possible communication failure\n");
222 fprintf(STDERR, "Volume needs to be salvaged\n");
225 fprintf(STDERR, "Bad vnode number quoted\n");
229 "Volume not attached, does not exist, or not on line\n");
232 fprintf(STDERR, "Volume already exists\n");
235 fprintf(STDERR, "Volume is not in service\n");
238 fprintf(STDERR, "Volume is off line\n");
241 fprintf(STDERR, "Volume is already on line\n");
244 fprintf(STDERR, "Partition is full\n");
247 fprintf(STDERR, "Volume max quota exceeded\n");
250 fprintf(STDERR, "Volume temporarily unavailable\n");
253 fprintf(STDERR, "Volume has moved to another server\n");
256 fprintf(STDERR, "VLDB: volume Id exists in the vldb\n");
259 fprintf(STDERR, "VLDB: a read terminated too early\n");
262 fprintf(STDERR, "VLDB: volume entry exists in the vldb\n");
265 fprintf(STDERR, "VLDB: internal creation failure\n");
268 fprintf(STDERR, "VLDB: no such entry\n");
271 fprintf(STDERR, "VLDB: vldb database is empty\n");
274 fprintf(STDERR, "VLDB: entry is deleted (soft delete)\n");
277 fprintf(STDERR, "VLDB: volume name is illegal\n");
280 fprintf(STDERR, "VLDB: index was out of range\n");
283 fprintf(STDERR, "VLDB: bad volume type\n");
286 fprintf(STDERR, "VLDB: illegal server number (not within limits)\n");
288 case VL_BADPARTITION:
289 fprintf(STDERR, "VLDB: bad partition number\n");
292 fprintf(STDERR, "VLDB: run out of space for replication sites\n");
295 fprintf(STDERR, "VLDB: no such repsite server exists\n");
297 case VL_DUPREPSERVER:
298 fprintf(STDERR, "VLDB: replication site server already exists\n");
301 fprintf(STDERR, "VLDB: parent r/w entry not found\n");
304 fprintf(STDERR, "VLDB: illegal reference count number\n");
306 case VL_SIZEEXCEEDED:
307 fprintf(STDERR, "VLDB: vldb size for attributes exceeded\n");
310 fprintf(STDERR, "VLDB: bad incoming vldb entry\n");
312 case VL_BADVOLIDBUMP:
313 fprintf(STDERR, "VLDB: illegal max volid increment\n");
315 case VL_IDALREADYHASHED:
316 fprintf(STDERR, "VLDB: (RO/BACK) Id already hashed\n");
319 fprintf(STDERR, "VLDB: vldb entry is already locked\n");
322 fprintf(STDERR, "VLDB: bad volume operation code\n");
324 case VL_BADRELLOCKTYPE:
325 fprintf(STDERR, "VLDB: bad release lock type\n");
328 fprintf(STDERR, "VLDB: status report: last release was aborted\n");
330 case VL_BADSERVERFLAG:
331 fprintf(STDERR, "VLDB: invalid replication site server flag\n");
334 fprintf(STDERR, "VLDB: no permission access for call\n");
336 case VOLSERREAD_DUMPERROR:
338 "VOLSER: Problems encountered in reading the dump file !\n");
340 case VOLSERDUMPERROR:
341 fprintf(STDERR, "VOLSER: Problems encountered in doing the dump !\n");
343 case VOLSERATTACH_ERROR:
344 fprintf(STDERR, "VOLSER: Could not attach the volume\n");
346 case VOLSERDETACH_ERROR:
347 fprintf(STDERR, "VOLSER: Could not detach the volume\n");
349 case VOLSERILLEGAL_PARTITION:
350 fprintf(STDERR, "VOLSER: encountered illegal partition number\n");
352 case VOLSERBAD_ACCESS:
353 fprintf(STDERR, "VOLSER: permission denied, not a super user\n");
355 case VOLSERVLDB_ERROR:
356 fprintf(STDERR, "VOLSER: error detected in the VLDB\n");
359 fprintf(STDERR, "VOLSER: error in volume name\n");
362 fprintf(STDERR, "VOLSER: volume has moved\n");
365 fprintf(STDERR, "VOLSER: illegal operation\n");
367 case VOLSERBADRELEASE:
368 fprintf(STDERR, "VOLSER: release could not be completed\n");
371 fprintf(STDERR, "VOLSER: volume is busy\n");
373 case VOLSERNO_MEMORY:
374 fprintf(STDERR, "VOLSER: volume server is out of memory\n");
378 "VOLSER: no such volume - location specified incorrectly or volume does not exist\n");
380 case VOLSERMULTIRWVOL:
382 "VOLSER: multiple RW volumes with same ID, one of which should be deleted\n");
386 "VOLSER: not all entries were successfully processed\n");
393 initialize_KA_error_table();
394 initialize_RXK_error_table();
395 initialize_KTC_error_table();
396 initialize_ACFG_error_table();
397 initialize_CMD_error_table();
398 initialize_VL_error_table();
400 offset = errcode & ((1 << ERRCODE_RANGE) - 1);
401 fprintf(STDERR, "%s: %s\n", error_table_name(errcode),
402 error_message(errcode));
410 static struct rx_securityClass *uvclass = 0;
411 static int uvindex = -1;
412 /* called by VLDBClient_Init to set the security module to be used in the RPC */
414 UV_SetSecurity(register struct rx_securityClass *as, afs_int32 aindex)
421 /* bind to volser on <port> <aserver> */
422 /* takes server address in network order, port in host order. dumb */
423 struct rx_connection *
424 UV_Bind(afs_int32 aserver, afs_int32 port)
426 register struct rx_connection *tc;
428 tc = rx_NewConnection(aserver, htons(port), VOLSERVICE_ID, uvclass,
433 /* if <okvol> is allright(indicated by beibg able to
434 * start a transaction, delete the <delvol> */
436 CheckAndDeleteVolume(struct rx_connection *aconn, afs_int32 apart,
437 afs_int32 okvol, afs_int32 delvol)
439 afs_int32 error, code, tid, rcode;
445 code = AFSVolTransCreate(aconn, delvol, apart, ITOffline, &tid);
448 code = AFSVolDeleteVolume(aconn, tid);
451 code = AFSVolEndTrans(aconn, tid, &rcode);
458 code = AFSVolTransCreate(aconn, okvol, apart, ITOffline, &tid);
460 code = AFSVolEndTrans(aconn, tid, &rcode);
465 code = AFSVolTransCreate(aconn, delvol, apart, ITOffline, &tid);
468 code = AFSVolDeleteVolume(aconn, tid);
471 code = AFSVolEndTrans(aconn, tid, &rcode);
482 /* called by EmuerateEntry, show vldb entry in a reasonable format */
484 SubEnumerateEntry(struct nvldbentry *entry)
491 fprintf(STDOUT, " readWriteID %-10u ", entry->volumeId[RWVOL]);
492 if (entry->flags & RW_EXISTS)
493 fprintf(STDOUT, " valid \n");
495 fprintf(STDOUT, " invalid \n");
496 fprintf(STDOUT, " readOnlyID %-10u ", entry->volumeId[ROVOL]);
497 if (entry->flags & RO_EXISTS)
498 fprintf(STDOUT, " valid \n");
500 fprintf(STDOUT, " invalid \n");
501 fprintf(STDOUT, " backUpID %-10u ", entry->volumeId[BACKVOL]);
502 if (entry->flags & BACK_EXISTS)
503 fprintf(STDOUT, " valid \n");
505 fprintf(STDOUT, " invalid \n");
506 if ((entry->cloneId != 0) && (entry->flags & RO_EXISTS))
507 fprintf(STDOUT, " releaseClone %-10u \n", entry->cloneId);
509 if (entry->flags & RW_EXISTS)
510 fprintf(STDOUT, " RWrite: %-10u", entry->volumeId[RWVOL]);
511 if (entry->flags & RO_EXISTS)
512 fprintf(STDOUT, " ROnly: %-10u", entry->volumeId[ROVOL]);
513 if (entry->flags & BACK_EXISTS)
514 fprintf(STDOUT, " Backup: %-10u", entry->volumeId[BACKVOL]);
515 if ((entry->cloneId != 0) && (entry->flags & RO_EXISTS))
516 fprintf(STDOUT, " RClone: %-10lu", (unsigned long)entry->cloneId);
517 fprintf(STDOUT, "\n");
519 fprintf(STDOUT, " number of sites -> %lu\n",
520 (unsigned long)entry->nServers);
521 for (i = 0; i < entry->nServers; i++) {
522 if (entry->serverFlags[i] & NEW_REPSITE)
525 for (i = 0; i < entry->nServers; i++) {
526 MapPartIdIntoName(entry->serverPartition[i], pname);
527 fprintf(STDOUT, " server %s partition %s ",
528 hostutil_GetNameByINet(entry->serverNumber[i]), pname);
529 if (entry->serverFlags[i] & ITSRWVOL)
530 fprintf(STDOUT, "RW Site ");
532 fprintf(STDOUT, "RO Site ");
534 if (entry->serverFlags[i] & NEW_REPSITE)
535 fprintf(STDOUT," -- New release");
537 if (!(entry->serverFlags[i] & ITSRWVOL))
538 fprintf(STDOUT," -- Old release");
540 if (entry->serverFlags[i] & RO_DONTUSE)
541 fprintf(STDOUT, " -- Not released");
543 fprintf(STDOUT, "\n");
550 /*enumerate the vldb entry corresponding to <entry> */
552 EnumerateEntry(struct nvldbentry *entry)
555 fprintf(STDOUT, "\n");
556 fprintf(STDOUT, "%s \n", entry->name);
557 SubEnumerateEntry(entry);
561 /* forcibly remove a volume. Very dangerous call */
563 UV_NukeVolume(afs_int32 server, afs_int32 partid, afs_int32 volid)
565 register struct rx_connection *tconn;
566 register afs_int32 code;
568 tconn = UV_Bind(server, AFSCONF_VOLUMEPORT);
570 code = AFSVolNukeVolume(tconn, partid, volid);
571 rx_DestroyConnection(tconn);
577 /* like df. Return usage of <pname> on <server> in <partition> */
579 UV_PartitionInfo(afs_int32 server, char *pname,
580 struct diskPartition *partition)
582 register struct rx_connection *aconn;
586 aconn = (struct rx_connection *)0;
587 aconn = UV_Bind(server, AFSCONF_VOLUMEPORT);
588 code = AFSVolPartitionInfo(aconn, pname, partition);
590 fprintf(STDERR, "Could not get information on partition %s\n", pname);
591 PrintError("", code);
594 rx_DestroyConnection(aconn);
598 /* old interface to create volume */
600 UV_CreateVolume(afs_int32 aserver, afs_int32 apart, char *aname,
604 code = UV_CreateVolume2(aserver, apart, aname, 5000, 0, 0, 0, 0, anewid);
608 /* create a volume, given a server, partition number, volume name --> sends
609 * back new vol id in <anewid>*/
611 UV_CreateVolume2(afs_int32 aserver, afs_int32 apart, char *aname,
612 afs_int32 aquota, afs_int32 aspare1, afs_int32 aspare2,
613 afs_int32 aspare3, afs_int32 aspare4, afs_int32 * anewid)
616 register struct rx_connection *aconn;
618 register afs_int32 code;
620 afs_int32 rcode, vcode;
621 struct nvldbentry entry, storeEntry; /*the new vldb entry */
622 struct volintInfo tstatus;
625 aconn = (struct rx_connection *)0;
627 memset(&tstatus, 0, sizeof(struct volintInfo));
629 tstatus.maxquota = aquota;
631 aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
632 /* next the next 3 available ids from the VLDB */
633 vcode = ubik_Call(VL_GetNewVolumeId, cstruct, 0, 3, anewid);
634 EGOTO1(cfail, vcode, "Could not get an Id for volume %s\n", aname);
637 AFSVolCreateVolume(aconn, apart, aname, volser_RW, 0, anewid, &tid);
638 EGOTO2(cfail, vcode, "Failed to create the volume %s %u \n", aname,
641 code = AFSVolSetInfo(aconn, tid, &tstatus);
643 EPRINT(code, "Could not change quota (error %d), continuing...\n");
645 code = AFSVolSetFlags(aconn, tid, 0); /* bring it online (mark it InService */
646 EGOTO2(cfail, vcode, "Could not bring the volume %s %u online \n", aname,
649 VPRINT2("Volume %s %u created and brought online\n", aname, *anewid);
651 /* set up the vldb entry for this volume */
652 strncpy(entry.name, aname, VOLSER_OLDMAXVOLNAME);
654 entry.serverNumber[0] = aserver; /* this should have another
655 * level of indirection later */
656 entry.serverPartition[0] = apart; /* this should also have
657 * another indirection level */
658 entry.flags = RW_EXISTS; /* this records that rw volume exists */
659 entry.serverFlags[0] = ITSRWVOL; /*this rep site has rw vol */
660 entry.volumeId[RWVOL] = *anewid;
661 entry.volumeId[ROVOL] = *anewid + 1; /* rw,ro, bk id are related in the default case */
662 entry.volumeId[BACKVOL] = *anewid + 2;
664 /*map into right byte order, before passing to xdr, the stuff has to be in host
665 * byte order. Xdr converts it into network order */
666 MapNetworkToHost(&entry, &storeEntry);
667 /* create the vldb entry */
668 vcode = VLDB_CreateEntry(&storeEntry);
671 "Could not create a VLDB entry for the volume %s %lu\n",
672 aname, (unsigned long)*anewid);
673 /*destroy the created volume */
674 VPRINT1("Deleting the newly created volume %u\n", *anewid);
675 AFSVolDeleteVolume(aconn, tid);
679 VPRINT2("Created the VLDB entry for the volume %s %u\n", aname, *anewid);
680 /* volume created, now terminate the transaction and release the connection */
681 code = AFSVolEndTrans(aconn, tid, &rcode); /*if it crashes before this
682 * the volume will come online anyway when transaction timesout , so if
683 * vldb entry exists then the volume is guaranteed to exist too wrt create */
687 "Failed to end the transaction on the volume %s %lu\n", aname,
688 (unsigned long)*anewid);
695 code = AFSVolEndTrans(aconn, tid, &rcode);
697 fprintf(STDERR, "WARNING: could not end transaction\n");
700 rx_DestroyConnection(aconn);
701 PrintError("", error);
707 /* create a volume, given a server, partition number, volume name --> sends
708 * back new vol id in <anewid>*/
710 UV_AddVLDBEntry(afs_int32 aserver, afs_int32 apart, char *aname,
713 register struct rx_connection *aconn;
716 struct nvldbentry entry, storeEntry; /*the new vldb entry */
718 aconn = (struct rx_connection *)0;
721 /* set up the vldb entry for this volume */
722 strncpy(entry.name, aname, VOLSER_OLDMAXVOLNAME);
724 entry.serverNumber[0] = aserver; /* this should have another
725 * level of indirection later */
726 entry.serverPartition[0] = apart; /* this should also have
727 * another indirection level */
728 entry.flags = RW_EXISTS; /* this records that rw volume exists */
729 entry.serverFlags[0] = ITSRWVOL; /*this rep site has rw vol */
730 entry.volumeId[RWVOL] = aid;
732 entry.volumeId[ROVOL] = anewid + 1; /* rw,ro, bk id are related in the default case */
733 entry.volumeId[BACKVOL] = *anewid + 2;
735 entry.volumeId[ROVOL] = 0;
736 entry.volumeId[BACKVOL] = 0;
739 /*map into right byte order, before passing to xdr, the stuff has to be in host
740 * byte order. Xdr converts it into network order */
741 MapNetworkToHost(&entry, &storeEntry);
742 /* create the vldb entry */
743 vcode = VLDB_CreateEntry(&storeEntry);
746 "Could not create a VLDB entry for the volume %s %lu\n",
747 aname, (unsigned long)aid);
751 VPRINT2("Created the VLDB entry for the volume %s %u\n", aname, aid);
755 rx_DestroyConnection(aconn);
756 PrintError("", error);
760 /* Delete the volume <volid>on <aserver> <apart>
761 * the physical entry gets removed from the vldb only if the ref count
765 UV_DeleteVolume(afs_int32 aserver, afs_int32 apart, afs_int32 avolid)
767 struct rx_connection *aconn = (struct rx_connection *)0;
769 afs_int32 code, rcode;
771 struct nvldbentry entry, storeEntry;
773 afs_int32 avoltype = -1, vtype;
774 int notondisk = 0, notinvldb = 0;
776 /* Find and read bhe VLDB entry for this volume */
777 code = ubik_Call(VL_SetLock, cstruct, 0, avolid, avoltype, VLOP_DELETE);
779 if (code != VL_NOENT) {
780 EGOTO1(error_exit, code,
781 "Could not lock VLDB entry for the volume %u\n", avolid);
787 code = VLDB_GetEntryByID(avolid, avoltype, &entry);
788 EGOTO1(error_exit, code, "Could not fetch VLDB entry for volume %u\n",
790 MapHostToNetwork(&entry);
793 EnumerateEntry(&entry);
796 /* Whether volume is in the VLDB or not. Delete the volume on disk */
797 aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
798 code = AFSVolTransCreate(aconn, avolid, apart, ITOffline, &ttid);
800 if (code == VNOVOL) {
803 EGOTO1(error_exit, code, "Transaction on volume %u failed\n",
807 VPRINT1("Trying to delete the volume %u ...", avolid);
809 code = AFSVolDeleteVolume(aconn, ttid);
810 EGOTO1(error_exit, code, "Could not delete the volume %u \n", avolid);
812 code = AFSVolEndTrans(aconn, ttid, &rcode);
813 code = (code ? code : rcode);
815 EGOTO1(error_exit, code,
816 "Could not end the transaction for the volume %u \n", avolid);
820 /* Now update the VLDB entry.
821 * But first, verify we have a VLDB entry.
822 * Whether volume is on disk or not. Delete the volume in VLDB.
827 if (avolid == entry.volumeId[BACKVOL]) {
828 /* Its a backup volume, modify the VLDB entry. Check that the
829 * backup volume is on the server/partition we asked to delete.
831 if (!(entry.flags & BACK_EXISTS) || !Lp_Match(aserver, apart, &entry)) {
832 notinvldb = 2; /* Not on this server and partition */
836 VPRINT1("Marking the backup volume %u deleted in the VLDB\n", avolid);
838 entry.flags &= ~BACK_EXISTS;
842 else if (avolid == entry.volumeId[ROVOL]) {
843 /* Its a read-only volume, modify the VLDB entry. Check that the
844 * readonly volume is on the server/partition we asked to delete.
845 * If flags does not have RO_EIXSTS set, then this may mean the RO
846 * hasn't been released (and could exist in VLDB).
848 if (!Lp_ROMatch(aserver, apart, &entry)) {
849 notinvldb = 2; /* Not found on this server and partition */
855 "Marking the readonly volume %lu deleted in the VLDB\n",
856 (unsigned long)avolid);
858 Lp_SetROValue(&entry, aserver, apart, 0, 0); /* delete the site */
860 if (!Lp_ROMatch(0, 0, &entry))
861 entry.flags &= ~RO_EXISTS; /* This was the last ro volume */
865 else if (avolid == entry.volumeId[RWVOL]) {
866 /* It's a rw volume, delete the backup volume, modify the VLDB entry.
867 * Check that the readwrite volumes is on the server/partition we
870 if (!(entry.flags & RW_EXISTS) || !Lp_Match(aserver, apart, &entry)) {
871 notinvldb = 2; /* Not found on this server and partition */
875 /* Delete backup if it exists */
877 AFSVolTransCreate(aconn, entry.volumeId[BACKVOL], apart,
881 fprintf(STDOUT, "Trying to delete the backup volume %u ...",
882 entry.volumeId[BACKVOL]);
885 code = AFSVolDeleteVolume(aconn, ttid);
886 EGOTO1(error_exit, code, "Could not delete the volume %u \n",
887 entry.volumeId[BACKVOL]);
889 code = AFSVolEndTrans(aconn, ttid, &rcode);
891 code = (code ? code : rcode);
892 EGOTO1(error_exit, code,
893 "Could not end the transaction for the volume %u \n",
894 entry.volumeId[BACKVOL]);
896 fprintf(STDOUT, " done\n");
901 "Marking the readwrite volume %lu%s deleted in the VLDB\n",
902 (unsigned long)avolid,
904 flags & BACK_EXISTS) ? ", and its backup volume," :
907 Lp_SetRWValue(&entry, aserver, apart, 0L, 0L);
909 entry.flags &= ~(BACK_EXISTS | RW_EXISTS);
912 if (entry.flags & RO_EXISTS)
913 fprintf(STDERR, "WARNING: ReadOnly copy(s) may still exist\n");
917 notinvldb = 2; /* Not found on this server and partition */
921 /* Either delete or replace the VLDB entry */
922 if ((entry.nServers <= 0) || !(entry.flags & (RO_EXISTS | RW_EXISTS))) {
925 "Last reference to the VLDB entry for %lu - deleting entry\n",
926 (unsigned long)avolid);
927 code = ubik_Call(VL_DeleteEntry, cstruct, 0, avolid, vtype);
928 EGOTO1(error_exit, code,
929 "Could not delete the VLDB entry for the volume %u \n",
932 MapNetworkToHost(&entry, &storeEntry);
934 VLDB_ReplaceEntry(avolid, vtype, &storeEntry,
935 (LOCKREL_OPCODE | LOCKREL_AFSID |
937 EGOTO1(error_exit, code,
938 "Could not update the VLDB entry for the volume %u \n",
947 if (notondisk && notinvldb) {
948 EPRINT2(VOLSERNOVOL, "Volume %u does not exist %s\n", avolid,
949 ((notinvldb == 2) ? "on server and partition" : ""));
952 } else if (notondisk) {
954 "WARNING: Volume %lu did not exist on the partition\n",
955 (unsigned long)avolid);
956 } else if (notinvldb) {
957 fprintf(STDERR, "WARNING: Volume %lu does not exist in VLDB %s\n",
958 (unsigned long)avolid,
959 ((notinvldb == 2) ? "on server and partition" : ""));
963 code = AFSVolEndTrans(aconn, ttid, &rcode);
964 code = (code ? code : rcode);
966 fprintf(STDERR, "Could not end transaction on the volume %lu\n",
967 (unsigned long)avolid);
968 PrintError("", code);
976 ubik_Call(VL_ReleaseLock, cstruct, 0, avolid, -1,
977 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
980 "Could not release the lock on the VLDB entry for the volume %u \n",
988 rx_DestroyConnection(aconn);
992 /* add recovery to UV_MoveVolume */
994 #define TESTC 0 /* set to test recovery code, clear for production */
1000 sigint_handler(int x)
1005 fprintf(STDOUT, "\nSIGINT handler: vos move operation in progress\n");
1007 "WARNING: may leave AFS storage and metadata in indeterminate state\n");
1008 fprintf(STDOUT, "enter second control-c to exit\n");
1012 (void)signal(SIGINT, sigint_handler);
1017 /* Move volume <afromvol> on <afromserver> <afrompart> to <atoserver>
1018 * <atopart>. The operation is almost idempotent. The following
1019 * flags are recognized:
1021 * RV_NOCLONE - don't use a copy clone
1025 UV_MoveVolume2(afs_int32 afromvol, afs_int32 afromserver, afs_int32 afrompart,
1026 afs_int32 atoserver, afs_int32 atopart, int flags)
1028 struct rx_connection *toconn, *fromconn;
1029 afs_int32 fromtid, totid, clonetid;
1032 char tmpName[VOLSER_MAXVOLNAME + 1];
1035 struct restoreCookie cookie;
1036 register afs_int32 vcode, code;
1037 afs_int32 newVol, volid, backupId;
1038 struct volser_status tstatus;
1039 struct destServer destination;
1041 struct nvldbentry entry, storeEntry;
1042 int i, islocked, pntg;
1044 char in, lf; /* for test code */
1047 #ifdef ENABLE_BUGFIX_1165
1048 volEntries volumeInfo;
1049 struct volintInfo *infop = 0;
1053 fromconn = (struct rx_connection *)0;
1054 toconn = (struct rx_connection *)0;
1064 /* support control-c processing */
1067 (void)signal(SIGINT, sigint_handler);
1071 "\nThere are three tests points - verifies all code paths through recovery.\n");
1072 fprintf(STDOUT, "First test point - operation not started.\n");
1073 fprintf(STDOUT, "...test here (y, n)? ");
1075 fscanf(stdin, "%c", &in);
1076 fscanf(stdin, "%c", &lf); /* toss away */
1078 fprintf(STDOUT, "type control-c\n");
1080 fprintf(stdout, ".");
1085 /* or drop through */
1088 vcode = VLDB_GetEntryByID(afromvol, -1, &entry);
1089 EGOTO1(mfail, vcode,
1090 "Could not fetch the entry for the volume %u from the VLDB \n",
1093 if (entry.volumeId[RWVOL] != afromvol) {
1094 fprintf(STDERR, "Only RW volume can be moved\n");
1098 vcode = ubik_Call(VL_SetLock, cstruct, 0, afromvol, RWVOL, VLOP_MOVE);
1099 EGOTO1(mfail, vcode, "Could not lock entry for volume %u \n", afromvol);
1102 vcode = VLDB_GetEntryByID(afromvol, RWVOL, &entry);
1103 EGOTO1(mfail, vcode,
1104 "Could not fetch the entry for the volume %u from the VLDB \n",
1107 backupId = entry.volumeId[BACKVOL];
1108 MapHostToNetwork(&entry);
1110 if (!Lp_Match(afromserver, afrompart, &entry)) {
1111 /* the from server and partition do not exist in the vldb entry corresponding to volid */
1112 if (!Lp_Match(atoserver, atopart, &entry)) {
1113 /* the to server and partition do not exist in the vldb entry corresponding to volid */
1114 fprintf(STDERR, "The volume %lu is not on the specified site. \n",
1115 (unsigned long)afromvol);
1116 fprintf(STDERR, "The current site is :");
1117 for (i = 0; i < entry.nServers; i++) {
1118 if (entry.serverFlags[i] == ITSRWVOL) {
1120 MapPartIdIntoName(entry.serverPartition[i], pname);
1121 fprintf(STDERR, " server %s partition %s \n",
1122 hostutil_GetNameByINet(entry.serverNumber[i]),
1127 ubik_Call(VL_ReleaseLock, cstruct, 0, afromvol, -1,
1128 (LOCKREL_OPCODE | LOCKREL_AFSID |
1129 LOCKREL_TIMESTAMP));
1130 EGOTO1(mfail, vcode,
1131 " Could not release lock on the VLDB entry for the volume %u \n",
1134 return VOLSERVOLMOVED;
1137 /* delete the volume afromvol on src_server */
1138 /* from-info does not exist but to-info does =>
1139 * we have already done the move, but the volume
1140 * may still be existing physically on from fileserver
1142 fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
1147 AFSVolTransCreate(fromconn, afromvol, afrompart, ITOffline,
1149 if (!code) { /* volume exists - delete it */
1150 VPRINT1("Setting flags on leftover source volume %u ...",
1153 AFSVolSetFlags(fromconn, fromtid,
1154 VTDeleteOnSalvage | VTOutOfService);
1156 "Failed to set flags on the leftover source volume %u\n",
1160 VPRINT1("Deleting leftover source volume %u ...", afromvol);
1161 code = AFSVolDeleteVolume(fromconn, fromtid);
1163 "Failed to delete the leftover source volume %u\n",
1167 VPRINT1("Ending transaction on leftover source volume %u ...",
1169 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1174 "Could not end the transaction for the leftover source volume %u \n",
1179 /*delete the backup volume now */
1182 AFSVolTransCreate(fromconn, backupId, afrompart, ITOffline,
1184 if (!code) { /* backup volume exists - delete it */
1185 VPRINT1("Setting flags on leftover backup volume %u ...",
1188 AFSVolSetFlags(fromconn, fromtid,
1189 VTDeleteOnSalvage | VTOutOfService);
1191 "Failed to set flags on the backup volume %u\n", backupId);
1194 VPRINT1("Deleting leftover backup volume %u ...", backupId);
1195 code = AFSVolDeleteVolume(fromconn, fromtid);
1197 "Could not delete the leftover backup volume %u\n",
1201 VPRINT1("Ending transaction on leftover backup volume %u ...",
1203 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1208 "Could not end the transaction for the leftover backup volume %u\n",
1218 /* From-info matches the vldb info about volid,
1219 * its ok start the move operation, the backup volume
1220 * on the old site is deleted in the process
1222 if (afrompart == atopart) {
1223 same = VLDB_IsSameAddrs(afromserver, atoserver, &error);
1224 EGOTO2(mfail, error,
1225 "Failed to get info about server's %d address(es) from vlserver (err=%d); aborting call!\n",
1226 afromserver, error);
1229 EGOTO1(mfail, VOLSERVOLMOVED,
1230 "Warning: Moving volume %u to its home partition ignored!\n",
1236 toconn = UV_Bind(atoserver, AFSCONF_VOLUMEPORT); /* get connections to the servers */
1237 fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
1238 fromtid = totid = 0; /* initialize to uncreated */
1241 * clone the read/write volume locally.
1244 VPRINT1("Starting transaction on source volume %u ...", afromvol);
1245 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
1246 EGOTO1(mfail, code, "Failed to create transaction on the volume %u\n",
1250 if (!(flags & RV_NOCLONE)) {
1251 /* Get a clone id */
1252 VPRINT1("Allocating new volume id for clone of volume %u ...",
1255 vcode = ubik_Call(VL_GetNewVolumeId, cstruct, 0, 1, &newVol);
1256 EGOTO1(mfail, vcode,
1257 "Could not get an ID for the clone of volume %u from the VLDB\n",
1261 /* Do the clone. Default flags on clone are set to delete on salvage and out of service */
1262 VPRINT1("Cloning source volume %u ...", afromvol);
1263 strcpy(vname, "move-clone-temp");
1265 AFSVolClone(fromconn, fromtid, 0, readonlyVolume, vname, &newVol);
1266 EGOTO1(mfail, code, "Failed to clone the source volume %u\n",
1271 /* lookup the name of the volume we just cloned */
1273 code = AFSVolGetName(fromconn, fromtid, &volName);
1274 EGOTO1(mfail, code, "Failed to get the name of the volume %u\n",
1277 VPRINT1("Ending the transaction on the source volume %u ...", afromvol);
1279 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1284 "Failed to end the transaction on the source volume %u\n",
1289 * Create the destination volume
1292 if (!(flags & RV_NOCLONE)) {
1293 /* All of this is to get the fromDate */
1294 VPRINT1("Starting transaction on the cloned volume %u ...", newVol);
1296 AFSVolTransCreate(fromconn, newVol, afrompart, ITOffline,
1299 "Failed to start a transaction on the cloned volume%u\n",
1303 VPRINT1("Setting flags on cloned volume %u ...", newVol);
1305 AFSVolSetFlags(fromconn, clonetid,
1306 VTDeleteOnSalvage | VTOutOfService); /*redundant */
1307 EGOTO1(mfail, code, "Could not set flags on the cloned volume %u\n",
1311 /* remember time from which we've dumped the volume */
1312 VPRINT1("Getting status of cloned volume %u ...", newVol);
1313 code = AFSVolGetStatus(fromconn, clonetid, &tstatus);
1315 "Failed to get the status of the cloned volume %u\n",
1319 fromDate = tstatus.creationDate - CLOCKSKEW;
1321 /* With RV_NOCLONE, just do a full copy from the source */
1326 #ifdef ENABLE_BUGFIX_1165
1328 * Get the internal volume state from the source volume. We'll use such info (i.e. dayUse)
1329 * to copy it to the new volume (via AFSSetInfo later on) so that when we move volumes we
1330 * don't use this information...
1332 volumeInfo.volEntries_val = (volintInfo *) 0; /*this hints the stub to allocate space */
1333 volumeInfo.volEntries_len = 0;
1334 code = AFSVolListOneVolume(fromconn, afrompart, afromvol, &volumeInfo);
1336 "Failed to get the volint Info of the cloned volume %u\n",
1339 infop = (volintInfo *) volumeInfo.volEntries_val;
1340 infop->maxquota = -1; /* Else it will replace the default quota */
1343 /* create a volume on the target machine */
1345 code = AFSVolTransCreate(toconn, volid, atopart, ITOffline, &totid);
1347 /* Delete the existing volume.
1348 * While we are deleting the volume in these steps, the transaction
1349 * we started against the cloned volume (clonetid above) will be
1350 * sitting idle. It will get cleaned up after 600 seconds
1352 VPRINT1("Deleting pre-existing volume %u on destination ...", volid);
1353 code = AFSVolDeleteVolume(toconn, totid);
1355 "Could not delete the pre-existing volume %u on destination\n",
1360 ("Ending transaction on pre-existing volume %u on destination ...",
1362 code = AFSVolEndTrans(toconn, totid, &rcode);
1367 "Could not end the transaction on pre-existing volume %u on destination\n",
1372 VPRINT1("Creating the destination volume %u ...", volid);
1374 AFSVolCreateVolume(toconn, atopart, volName, volser_RW, volid, &volid,
1376 EGOTO1(mfail, code, "Failed to create the destination volume %u\n",
1380 strncpy(tmpName, volName, VOLSER_OLDMAXVOLNAME);
1384 VPRINT1("Setting volume flags on destination volume %u ...", volid);
1386 AFSVolSetFlags(toconn, totid, (VTDeleteOnSalvage | VTOutOfService));
1388 "Failed to set the flags on the destination volume %u\n", volid);
1392 * Now dump the clone to the new volume
1395 destination.destHost = ntohl(atoserver);
1396 destination.destPort = AFSCONF_VOLUMEPORT;
1397 destination.destSSID = 1;
1399 strncpy(cookie.name, tmpName, VOLSER_OLDMAXVOLNAME);
1400 cookie.type = RWVOL;
1401 cookie.parent = entry.volumeId[RWVOL];
1404 if (!(flags & RV_NOCLONE)) {
1405 /* Copy the clone to the new volume */
1406 VPRINT2("Dumping from clone %u on source to volume %u on destination ...",
1409 AFSVolForward(fromconn, clonetid, 0, &destination, totid,
1411 EGOTO1(mfail, code, "Failed to move data for the volume %u\n", volid);
1414 VPRINT1("Ending transaction on cloned volume %u ...", newVol);
1415 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
1420 "Failed to end the transaction on the cloned volume %u\n",
1426 * reattach to the main-line volume, and incrementally dump it.
1429 VPRINT1("Starting transaction on source volume %u ...", afromvol);
1430 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
1432 "Failed to create a transaction on the source volume %u\n",
1436 /* now do the incremental */
1438 ("Doing the%s dump from source to destination for volume %u ... ",
1439 (flags & RV_NOCLONE) ? "" : " incremental",
1442 AFSVolForward(fromconn, fromtid, fromDate, &destination, totid,
1445 "Failed to do the%s dump from rw volume on old site to rw volume on newsite\n",
1446 (flags & RV_NOCLONE) ? "" : " incremental");
1449 /* now adjust the flags so that the new volume becomes official */
1450 VPRINT1("Setting volume flags on old source volume %u ...", afromvol);
1451 code = AFSVolSetFlags(fromconn, fromtid, VTOutOfService);
1453 "Failed to set the flags to make old source volume offline\n");
1456 VPRINT1("Setting volume flags on new source volume %u ...", afromvol);
1457 code = AFSVolSetFlags(toconn, totid, 0);
1459 "Failed to set the flags to make new source volume online\n");
1462 #ifdef ENABLE_BUGFIX_1165
1463 VPRINT1("Setting volume status on destination volume %u ...", volid);
1464 code = AFSVolSetInfo(toconn, totid, infop);
1466 "Failed to set volume status on the destination volume %u\n",
1471 /* put new volume online */
1472 VPRINT1("Ending transaction on destination volume %u ...", afromvol);
1473 code = AFSVolEndTrans(toconn, totid, &rcode);
1478 "Failed to end the transaction on the volume %u on the new site\n",
1482 Lp_SetRWValue(&entry, afromserver, afrompart, atoserver, atopart);
1483 MapNetworkToHost(&entry, &storeEntry);
1484 storeEntry.flags &= ~BACK_EXISTS;
1488 "Second test point - operation in progress but not complete.\n");
1489 fprintf(STDOUT, "...test here (y, n)? ");
1491 fscanf(stdin, "%c", &in);
1492 fscanf(stdin, "%c", &lf); /* toss away */
1494 fprintf(STDOUT, "type control-c\n");
1496 fprintf(stdout, ".");
1501 /* or drop through */
1504 VPRINT1("Releasing lock on VLDB entry for volume %u ...", afromvol);
1506 VLDB_ReplaceEntry(afromvol, -1, &storeEntry,
1507 (LOCKREL_OPCODE | LOCKREL_AFSID |
1508 LOCKREL_TIMESTAMP));
1511 " Could not release the lock on the VLDB entry for the volume %s %lu \n",
1512 storeEntry.name, (unsigned long)afromvol);
1521 "Third test point - operation complete but no cleanup.\n");
1522 fprintf(STDOUT, "...test here (y, n)? ");
1524 fscanf(stdin, "%c", &in);
1525 fscanf(stdin, "%c", &lf); /* toss away */
1527 fprintf(STDOUT, "type control-c\n");
1529 fprintf(stdout, ".");
1534 /* or drop through */
1537 /* This is tricky. File server is very stupid, and if you mark the volume
1538 * as VTOutOfService, it may mark the *good* instance (if you're moving
1539 * between partitions on the same machine) as out of service. Since
1540 * we're cleaning this code up in DEcorum, we're just going to kludge around
1541 * it for now by removing this call. */
1542 /* already out of service, just zap it now */
1544 AFSVolSetFlags(fromconn, fromtid, VTDeleteOnSalvage | VTOutOfService);
1547 "Failed to set the flags to make the old source volume offline\n");
1551 if (atoserver != afromserver) {
1552 /* set forwarding pointer for moved volumes */
1553 VPRINT1("Setting forwarding pointer for volume %u ...", afromvol);
1554 code = AFSVolSetForwarding(fromconn, fromtid, atoserver);
1556 "Failed to set the forwarding pointer for the volume %u\n",
1561 VPRINT1("Deleting old volume %u on source ...", afromvol);
1562 code = AFSVolDeleteVolume(fromconn, fromtid); /* zap original volume */
1563 EGOTO1(mfail, code, "Failed to delete the old volume %u on source\n",
1567 VPRINT1("Ending transaction on old volume %u on the source ...",
1569 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1574 "Failed to end the transaction on the old volume %u on the source\n",
1578 /* Delete the backup volume on the original site */
1579 VPRINT1("Creating transaction for backup volume %u on source ...",
1582 AFSVolTransCreate(fromconn, backupId, afrompart, ITOffline, &fromtid);
1585 VPRINT1("Setting flags on backup volume %u on source ...", backupId);
1587 AFSVolSetFlags(fromconn, fromtid,
1588 VTDeleteOnSalvage | VTOutOfService);
1590 "Failed to set the flags on the backup volume %u on the source\n",
1594 VPRINT1("Deleting the backup volume %u on the source ...", backupId);
1595 code = AFSVolDeleteVolume(fromconn, fromtid);
1597 "Failed to delete the backup volume %u on the source\n",
1601 VPRINT1("Ending transaction on backup volume %u on source ...",
1603 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1608 "Failed to end the transaction on the backup volume %u on the source\n",
1612 code = 0; /* no backup volume? that's okay */
1615 if (!(flags & RV_NOCLONE)) {
1616 VPRINT1("Starting transaction on the cloned volume %u ...", newVol);
1618 AFSVolTransCreate(fromconn, newVol, afrompart, ITOffline,
1621 "Failed to start a transaction on the cloned volume%u\n",
1625 /* now delete the clone */
1626 VPRINT1("Deleting the cloned volume %u ...", newVol);
1627 code = AFSVolDeleteVolume(fromconn, clonetid);
1628 EGOTO1(mfail, code, "Failed to delete the cloned volume %u\n",
1632 VPRINT1("Ending transaction on cloned volume %u ...", newVol);
1633 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
1638 "Failed to end the transaction on the cloned volume %u\n",
1647 fprintf(STDOUT, "Fourth test point - operation complete.\n");
1648 fprintf(STDOUT, "...test here (y, n)? ");
1650 fscanf(stdin, "%c", &in);
1651 fscanf(stdin, "%c", &lf); /* toss away */
1653 fprintf(STDOUT, "type control-c\n");
1655 fprintf(stdout, ".");
1660 /* or drop through */
1663 /* normal cleanup code */
1665 if (entry.flags & RO_EXISTS)
1666 fprintf(STDERR, "WARNING : readOnly copies still exist \n");
1669 VPRINT1("Cleanup: Releasing VLDB lock on volume %u ...", afromvol);
1671 ubik_Call(VL_ReleaseLock, cstruct, 0, afromvol, -1,
1672 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
1676 " Could not release the lock on the VLDB entry for the volume %lu \n",
1677 (unsigned long)afromvol);
1685 VPRINT1("Cleanup: Ending transaction on source volume %u ...",
1687 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1688 if (code || rcode) {
1691 "Could not end transaction on the source volume %lu\n",
1692 (unsigned long)afromvol);
1694 error = (code ? code : rcode);
1700 VPRINT1("Cleanup: Ending transaction on clone volume %u ...", newVol);
1701 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
1702 if (code || rcode) {
1705 "Could not end transaction on the source's clone volume %lu\n",
1706 (unsigned long)newVol);
1708 error = (code ? code : rcode);
1714 VPRINT1("Cleanup: Ending transaction on destination volume %u ...",
1716 code = AFSVolEndTrans(toconn, totid, &rcode);
1720 "Could not end transaction on destination volume %lu\n",
1721 (unsigned long)afromvol);
1723 error = (code ? code : rcode);
1729 #ifdef ENABLE_BUGFIX_1165
1734 rx_DestroyConnection(fromconn);
1736 rx_DestroyConnection(toconn);
1737 PrintError("", error);
1740 /* come here only when the sky falls */
1745 "vos move: operation interrupted, cleanup in progress...\n");
1746 fprintf(STDOUT, "clear transaction contexts\n");
1750 /* unlock VLDB entry */
1752 VPRINT1("Recovery: Releasing VLDB lock on volume %u ...", afromvol);
1753 ubik_Call(VL_ReleaseLock, cstruct, 0, afromvol, -1,
1754 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
1759 VPRINT("Recovery: Ending transaction on clone volume ...");
1760 AFSVolEndTrans(fromconn, clonetid, &rcode);
1764 VPRINT("Recovery: Ending transaction on destination volume ...");
1765 AFSVolEndTrans(toconn, totid, &rcode);
1768 if (fromtid) { /* put it on-line */
1769 VPRINT("Recovery: Setting volume flags on source volume ...");
1770 AFSVolSetFlags(fromconn, fromtid, 0);
1773 VPRINT("Recovery: Ending transaction on source volume ...");
1774 AFSVolEndTrans(fromconn, fromtid, &rcode);
1778 VPRINT("Recovery: Accessing VLDB.\n");
1779 vcode = VLDB_GetEntryByID(afromvol, -1, &entry);
1781 fprintf(STDOUT, "FATAL: VLDB access error: abort cleanup\n");
1785 MapHostToNetwork(&entry);
1787 /* Delete either the volume on the source location or the target location.
1788 * If the vldb entry still points to the source location, then we know the
1789 * volume move didn't finish so we remove the volume from the target
1790 * location. Otherwise, we remove the volume from the source location.
1792 if (Lp_Match(afromserver, afrompart, &entry)) { /* didn't move - delete target volume */
1795 "move incomplete - attempt cleanup of target partition - no guarantee\n");
1799 if (volid && toconn) {
1801 ("Recovery: Creating transaction for destination volume %u ...",
1804 AFSVolTransCreate(toconn, volid, atopart, ITOffline, &totid);
1810 ("Recovery: Setting flags on destination volume %u ...",
1812 AFSVolSetFlags(toconn, totid,
1813 VTDeleteOnSalvage | VTOutOfService);
1816 VPRINT1("Recovery: Deleting destination volume %u ...",
1818 AFSVolDeleteVolume(toconn, totid);
1822 ("Recovery: Ending transaction on destination volume %u ...",
1824 AFSVolEndTrans(toconn, totid, &rcode);
1828 ("\nRecovery: Unable to start transaction on destination volume %u.\n",
1833 /* put source volume on-line */
1835 VPRINT1("Recovery: Creating transaction on source volume %u ...",
1838 AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy,
1843 VPRINT1("Recovery: Setting flags on source volume %u ...",
1845 AFSVolSetFlags(fromconn, fromtid, 0);
1849 ("Recovery: Ending transaction on source volume %u ...",
1851 AFSVolEndTrans(fromconn, fromtid, &rcode);
1855 ("\nRecovery: Unable to start transaction on source volume %u.\n",
1859 } else { /* yep, move complete */
1862 "move complete - attempt cleanup of source partition - no guarantee\n");
1866 /* delete backup volume */
1868 VPRINT1("Recovery: Creating transaction on backup volume %u ...",
1871 AFSVolTransCreate(fromconn, backupId, afrompart, ITOffline,
1876 VPRINT1("Recovery: Setting flags on backup volume %u ...",
1878 AFSVolSetFlags(fromconn, fromtid,
1879 VTDeleteOnSalvage | VTOutOfService);
1882 VPRINT1("Recovery: Deleting backup volume %u ...", backupId);
1883 AFSVolDeleteVolume(fromconn, fromtid);
1887 ("Recovery: Ending transaction on backup volume %u ...",
1889 AFSVolEndTrans(fromconn, fromtid, &rcode);
1893 ("\nRecovery: Unable to start transaction on backup volume %u.\n",
1897 /* delete source volume */
1898 VPRINT1("Recovery: Creating transaction on source volume %u ...",
1901 AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy,
1906 VPRINT1("Recovery: Setting flags on backup volume %u ...",
1908 AFSVolSetFlags(fromconn, fromtid,
1909 VTDeleteOnSalvage | VTOutOfService);
1912 if (atoserver != afromserver) {
1913 VPRINT("Recovery: Setting volume forwarding pointer ...");
1914 AFSVolSetForwarding(fromconn, fromtid, atoserver);
1918 VPRINT1("Recovery: Deleting source volume %u ...", afromvol);
1919 AFSVolDeleteVolume(fromconn, fromtid);
1923 ("Recovery: Ending transaction on source volume %u ...",
1925 AFSVolEndTrans(fromconn, fromtid, &rcode);
1929 ("\nRecovery: Unable to start transaction on source volume %u.\n",
1935 /* common cleanup - delete local clone */
1937 VPRINT1("Recovery: Creating transaction on clone volume %u ...",
1940 AFSVolTransCreate(fromconn, newVol, afrompart, ITOffline,
1945 VPRINT1("Recovery: Deleting clone volume %u ...", newVol);
1946 AFSVolDeleteVolume(fromconn, clonetid);
1949 VPRINT1("Recovery: Ending transaction on clone volume %u ...",
1951 AFSVolEndTrans(fromconn, clonetid, &rcode);
1955 ("\nRecovery: Unable to start transaction on source volume %u.\n",
1960 /* unlock VLDB entry */
1961 VPRINT1("Recovery: Releasing lock on VLDB entry for volume %u ...",
1963 ubik_Call(VL_ReleaseLock, cstruct, 0, afromvol, -1,
1964 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
1967 done: /* routine cleanup */
1970 #ifdef ENABLE_BUGFIX_1165
1975 rx_DestroyConnection(fromconn);
1977 rx_DestroyConnection(toconn);
1980 fprintf(STDOUT, "cleanup complete - user verify desired result\n");
1988 UV_MoveVolume(afs_int32 afromvol, afs_int32 afromserver, afs_int32 afrompart,
1989 afs_int32 atoserver, afs_int32 atopart)
1991 return UV_MoveVolume2(afromvol, afromserver, afrompart,
1992 atoserver, atopart, 0);
1996 /* Copy volume <afromvol> from <afromserver> <afrompart> to <atoserver>
1997 * <atopart>. The new volume is named by <atovolname>. The new volume
1998 * has ID <atovolid> if that is nonzero; otherwise a new ID is allocated
1999 * from the VLDB. the following flags are supported:
2001 * RV_RDONLY - target volume is RO
2002 * RV_OFFLINE - leave target volume offline
2003 * RV_CPINCR - do incremental dump if target exists
2004 * RV_NOVLDB - don't create/update VLDB entry
2005 * RV_NOCLONE - don't use a copy clone
2008 UV_CopyVolume2(afs_int32 afromvol, afs_int32 afromserver, afs_int32 afrompart,
2009 char *atovolname, afs_int32 atoserver, afs_int32 atopart,
2010 afs_int32 atovolid, int flags)
2012 struct rx_connection *toconn, *fromconn;
2013 afs_int32 fromtid, totid, clonetid;
2016 afs_int32 fromDate, cloneFromDate;
2017 struct restoreCookie cookie;
2018 register afs_int32 vcode, code;
2019 afs_int32 cloneVol, newVol, volflag;
2020 struct volser_status tstatus;
2021 struct destServer destination;
2023 struct nvldbentry entry, newentry, storeEntry;
2029 fromconn = (struct rx_connection *)0;
2030 toconn = (struct rx_connection *)0;
2038 /* support control-c processing */
2041 (void)signal(SIGINT, sigint_handler);
2043 vcode = VLDB_GetEntryByID(afromvol, -1, &entry);
2044 EGOTO1(mfail, vcode,
2045 "Could not fetch the entry for the volume %u from the VLDB \n",
2047 MapHostToNetwork(&entry);
2050 toconn = UV_Bind(atoserver, AFSCONF_VOLUMEPORT); /* get connections to the servers */
2051 fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
2052 fromtid = totid = 0; /* initialize to uncreated */
2055 /* check if we can shortcut and use a local clone instead of a full copy */
2056 if (afromserver == atoserver && afrompart == atopart) {
2061 * clone the read/write volume locally.
2065 if (!(flags & RV_NOCLONE)) {
2066 VPRINT1("Starting transaction on source volume %u ...", afromvol);
2067 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy,
2069 EGOTO1(mfail, code, "Failed to create transaction on the volume %u\n",
2073 /* Get a clone id */
2074 VPRINT1("Allocating new volume id for clone of volume %u ...",
2077 vcode = ubik_Call(VL_GetNewVolumeId, cstruct, 0, 1, &cloneVol);
2078 EGOTO1(mfail, vcode,
2079 "Could not get an ID for the clone of volume %u from the VLDB\n",
2087 /* Get a new volume id */
2088 VPRINT1("Allocating new volume id for copy of volume %u ...", afromvol);
2090 vcode = ubik_Call(VL_GetNewVolumeId, cstruct, 0, 1, &newVol);
2091 EGOTO1(mfail, vcode,
2092 "Could not get an ID for the copy of volume %u from the VLDB\n",
2097 if (!(flags & RV_NOCLONE)) {
2098 /* Do the clone. Default flags on clone are set to delete on salvage and out of service */
2099 VPRINT1("Cloning source volume %u ...", afromvol);
2100 strcpy(vname, "copy-clone-temp");
2102 AFSVolClone(fromconn, fromtid, 0, readonlyVolume, vname,
2104 EGOTO1(mfail, code, "Failed to clone the source volume %u\n",
2108 VPRINT1("Ending the transaction on the source volume %u ...", afromvol);
2110 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
2115 "Failed to end the transaction on the source volume %u\n",
2121 * Create the destination volume
2124 if (!(flags & RV_NOCLONE)) {
2125 VPRINT1("Starting transaction on the cloned volume %u ...", cloneVol);
2127 AFSVolTransCreate(fromconn, cloneVol, afrompart, ITOffline,
2130 "Failed to start a transaction on the cloned volume%u\n",
2134 VPRINT1("Setting flags on cloned volume %u ...", cloneVol);
2136 AFSVolSetFlags(fromconn, clonetid,
2137 VTDeleteOnSalvage | VTOutOfService); /*redundant */
2138 EGOTO1(mfail, code, "Could not set flags on the cloned volume %u\n",
2142 /* remember time from which we've dumped the volume */
2143 VPRINT1("Getting status of cloned volume %u ...", cloneVol);
2144 code = AFSVolGetStatus(fromconn, clonetid, &tstatus);
2146 "Failed to get the status of the cloned volume %u\n",
2150 fromDate = tstatus.creationDate - CLOCKSKEW;
2155 /* create a volume on the target machine */
2157 code = AFSVolTransCreate(toconn, newVol, atopart, ITOffline, &totid);
2159 if ((flags & RV_CPINCR)) {
2160 VPRINT1("Getting status of pre-existing volume %u ...", newVol);
2161 code = AFSVolGetStatus(toconn, totid, &tstatus);
2163 "Failed to get the status of the pre-existing volume %u\n",
2167 /* Using the update date should be OK here, but add some fudge */
2168 cloneFromDate = tstatus.updateDate - CLOCKSKEW;
2169 if ((flags & RV_NOCLONE))
2170 fromDate = cloneFromDate;
2172 /* XXX We should check that the source volume's creationDate is
2173 * XXX not newer than the existing target volume, and if not,
2174 * XXX throw away the existing target and do a full dump. */
2179 /* Delete the existing volume.
2180 * While we are deleting the volume in these steps, the transaction
2181 * we started against the cloned volume (clonetid above) will be
2182 * sitting idle. It will get cleaned up after 600 seconds
2184 VPRINT1("Deleting pre-existing volume %u on destination ...", newVol);
2185 code = AFSVolDeleteVolume(toconn, totid);
2187 "Could not delete the pre-existing volume %u on destination\n",
2192 ("Ending transaction on pre-existing volume %u on destination ...",
2194 code = AFSVolEndTrans(toconn, totid, &rcode);
2199 "Could not end the transaction on pre-existing volume %u on destination\n",
2204 VPRINT1("Creating the destination volume %u ...", newVol);
2206 AFSVolCreateVolume(toconn, atopart, atovolname,
2207 (flags & RV_RDONLY) ? volser_RO : volser_RW,
2208 newVol, &newVol, &totid);
2209 EGOTO1(mfail, code, "Failed to create the destination volume %u\n",
2213 VPRINT1("Setting volume flags on destination volume %u ...", newVol);
2215 AFSVolSetFlags(toconn, totid, (VTDeleteOnSalvage | VTOutOfService));
2217 "Failed to set the flags on the destination volume %u\n", newVol);
2222 destination.destHost = ntohl(atoserver);
2223 destination.destPort = AFSCONF_VOLUMEPORT;
2224 destination.destSSID = 1;
2226 strncpy(cookie.name, atovolname, VOLSER_OLDMAXVOLNAME);
2227 cookie.type = (flags & RV_RDONLY) ? ROVOL : RWVOL;
2232 * Now dump the clone to the new volume
2235 if (!(flags & RV_NOCLONE)) {
2236 /* XXX probably should have some code here that checks to see if
2237 * XXX we are copying to same server and partition - if so, just
2238 * XXX use a clone to save disk space */
2240 /* Copy the clone to the new volume */
2241 VPRINT2("Dumping from clone %u on source to volume %u on destination ...",
2244 AFSVolForward(fromconn, clonetid, cloneFromDate, &destination,
2246 EGOTO1(mfail, code, "Failed to move data for the volume %u\n",
2250 VPRINT1("Ending transaction on cloned volume %u ...", cloneVol);
2251 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
2256 "Failed to end the transaction on the cloned volume %u\n",
2262 * reattach to the main-line volume, and incrementally dump it.
2265 VPRINT1("Starting transaction on source volume %u ...", afromvol);
2266 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
2268 "Failed to create a transaction on the source volume %u\n",
2272 /* now do the incremental */
2274 ("Doing the%s dump from source to destination for volume %u ... ",
2275 (flags & RV_NOCLONE) ? "" : " incremental",
2278 AFSVolForward(fromconn, fromtid, fromDate, &destination, totid,
2281 "Failed to do the%s dump from old site to new site\n",
2285 VPRINT1("Setting volume flags on destination volume %u ...", newVol);
2286 volflag = ((flags & RV_OFFLINE) ? VTOutOfService : 0); /* off or on-line */
2287 code = AFSVolSetFlags(toconn, totid, volflag);
2289 "Failed to set the flags to make destination volume online\n");
2292 /* put new volume online */
2293 VPRINT1("Ending transaction on destination volume %u ...", newVol);
2294 code = AFSVolEndTrans(toconn, totid, &rcode);
2299 "Failed to end the transaction on the destination volume %u\n",
2303 VPRINT1("Ending transaction on source volume %u ...", afromvol);
2304 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
2309 "Failed to end the transaction on the source volume %u\n",
2315 if (!(flags & RV_NOCLONE)) {
2316 VPRINT1("Starting transaction on the cloned volume %u ...", cloneVol);
2318 AFSVolTransCreate(fromconn, cloneVol, afrompart, ITOffline,
2321 "Failed to start a transaction on the cloned volume%u\n",
2325 /* now delete the clone */
2326 VPRINT1("Deleting the cloned volume %u ...", cloneVol);
2327 code = AFSVolDeleteVolume(fromconn, clonetid);
2328 EGOTO1(mfail, code, "Failed to delete the cloned volume %u\n",
2332 VPRINT1("Ending transaction on cloned volume %u ...", cloneVol);
2333 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
2338 "Failed to end the transaction on the cloned volume %u\n",
2343 if (!(flags & RV_NOVLDB)) {
2344 /* create the vldb entry for the copied volume */
2345 strncpy(newentry.name, atovolname, VOLSER_OLDMAXVOLNAME);
2346 newentry.nServers = 1;
2347 newentry.serverNumber[0] = atoserver;
2348 newentry.serverPartition[0] = atopart;
2349 newentry.flags = (flags & RV_RDONLY) ? RO_EXISTS : RW_EXISTS;
2350 newentry.serverFlags[0] = (flags & RV_RDONLY) ? ITSROVOL : ITSRWVOL;
2351 newentry.volumeId[RWVOL] = newVol;
2352 newentry.volumeId[ROVOL] = (flags & RV_RDONLY) ? newVol : 0;
2353 newentry.volumeId[BACKVOL] = 0;
2354 newentry.cloneId = 0;
2355 /*map into right byte order, before passing to xdr, the stuff has to be in host
2356 * byte order. Xdr converts it into network order */
2357 MapNetworkToHost(&newentry, &storeEntry);
2358 /* create the vldb entry */
2359 vcode = VLDB_CreateEntry(&storeEntry);
2362 "Could not create a VLDB entry for the volume %s %lu\n",
2363 atovolname, (unsigned long)newVol);
2364 /*destroy the created volume */
2365 VPRINT1("Deleting the newly created volume %u\n", newVol);
2366 AFSVolDeleteVolume(toconn, totid);
2370 VPRINT2("Created the VLDB entry for the volume %s %u\n", atovolname,
2374 /* normal cleanup code */
2377 VPRINT1("Cleanup: Ending transaction on source volume %u ...",
2379 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
2380 if (code || rcode) {
2383 "Could not end transaction on the source volume %lu\n",
2384 (unsigned long)afromvol);
2386 error = (code ? code : rcode);
2392 VPRINT1("Cleanup: Ending transaction on clone volume %u ...",
2394 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
2395 if (code || rcode) {
2398 "Could not end transaction on the source's clone volume %lu\n",
2399 (unsigned long)cloneVol);
2401 error = (code ? code : rcode);
2407 VPRINT1("Cleanup: Ending transaction on destination volume %u ...",
2409 code = AFSVolEndTrans(toconn, totid, &rcode);
2413 "Could not end transaction on destination volume %lu\n",
2414 (unsigned long)newVol);
2416 error = (code ? code : rcode);
2421 rx_DestroyConnection(fromconn);
2423 rx_DestroyConnection(toconn);
2424 PrintError("", error);
2427 /* come here only when the sky falls */
2432 "vos copy: operation interrupted, cleanup in progress...\n");
2433 fprintf(STDOUT, "clear transaction contexts\n");
2438 VPRINT("Recovery: Ending transaction on clone volume ...");
2439 AFSVolEndTrans(fromconn, clonetid, &rcode);
2443 VPRINT("Recovery: Ending transaction on destination volume ...");
2444 AFSVolEndTrans(toconn, totid, &rcode);
2447 if (fromtid) { /* put it on-line */
2448 VPRINT("Recovery: Ending transaction on source volume ...");
2449 AFSVolEndTrans(fromconn, fromtid, &rcode);
2453 VPRINT("Recovery: Accessing VLDB.\n");
2454 vcode = VLDB_GetEntryByID(afromvol, -1, &entry);
2456 fprintf(STDOUT, "FATAL: VLDB access error: abort cleanup\n");
2460 MapHostToNetwork(&entry);
2462 /* common cleanup - delete local clone */
2464 VPRINT1("Recovery: Creating transaction on clone volume %u ...",
2467 AFSVolTransCreate(fromconn, newVol, afrompart, ITOffline,
2472 VPRINT1("Recovery: Deleting clone volume %u ...", cloneVol);
2473 AFSVolDeleteVolume(fromconn, clonetid);
2476 VPRINT1("Recovery: Ending transaction on clone volume %u ...",
2478 AFSVolEndTrans(fromconn, clonetid, &rcode);
2482 ("\nRecovery: Unable to start transaction on clone volume %u.\n",
2487 done: /* routine cleanup */
2489 rx_DestroyConnection(fromconn);
2491 rx_DestroyConnection(toconn);
2494 fprintf(STDOUT, "cleanup complete - user verify desired result\n");
2502 UV_CopyVolume(afs_int32 afromvol, afs_int32 afromserver, afs_int32 afrompart,
2503 char *atovolname, afs_int32 atoserver, afs_int32 atopart)
2505 return UV_CopyVolume2(afromvol, afromserver, afrompart,
2506 atovolname, atoserver, atopart, 0, 0);
2511 /* Make a new backup of volume <avolid> on <aserver> and <apart>
2512 * if one already exists, update it
2516 UV_BackupVolume(afs_int32 aserver, afs_int32 apart, afs_int32 avolid)
2518 struct rx_connection *aconn = (struct rx_connection *)0;
2519 afs_int32 ttid = 0, btid = 0;
2521 afs_int32 code = 0, rcode = 0;
2522 char vname[VOLSER_MAXVOLNAME + 1];
2523 struct nvldbentry entry, storeEntry;
2524 afs_int32 error = 0;
2525 int vldblocked = 0, vldbmod = 0, backexists = 1;
2527 aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
2529 /* the calls to VLDB will succeed only if avolid is a RW volume,
2530 * since we are following the RW hash chain for searching */
2531 code = VLDB_GetEntryByID(avolid, RWVOL, &entry);
2534 "Could not fetch the entry for the volume %lu from the VLDB \n",
2535 (unsigned long)avolid);
2539 MapHostToNetwork(&entry);
2541 /* These operations require the VLDB be locked since it means the VLDB
2542 * will change or the vldb is already locked.
2544 if (!(entry.flags & BACK_EXISTS) || /* backup volume doesnt exist */
2545 (entry.flags & VLOP_ALLOPERS) || /* vldb lock already held */
2546 (entry.volumeId[BACKVOL] == INVALID_BID)) { /* no assigned backup volume id */
2548 code = ubik_Call(VL_SetLock, cstruct, 0, avolid, RWVOL, VLOP_BACKUP);
2551 "Could not lock the VLDB entry for the volume %lu\n",
2552 (unsigned long)avolid);
2558 /* Reread the vldb entry */
2559 code = VLDB_GetEntryByID(avolid, RWVOL, &entry);
2562 "Could not fetch the entry for the volume %lu from the VLDB \n",
2563 (unsigned long)avolid);
2567 MapHostToNetwork(&entry);
2570 if (!ISNAMEVALID(entry.name)) {
2571 fprintf(STDERR, "Name of the volume %s exceeds the size limit\n",
2573 error = VOLSERBADNAME;
2577 backupID = entry.volumeId[BACKVOL];
2578 if (backupID == INVALID_BID) {
2579 /* Get a backup volume id from the VLDB and update the vldb
2582 code = ubik_Call(VL_GetNewVolumeId, cstruct, 0, 1, &backupID);
2585 "Could not allocate ID for the backup volume of %lu from the VLDB\n",
2586 (unsigned long)avolid);
2590 entry.volumeId[BACKVOL] = backupID;
2594 /* Test to see if the backup volume exists by trying to create
2595 * a transaction on the backup volume. We've assumed the backup exists.
2597 code = AFSVolTransCreate(aconn, backupID, apart, ITOffline, &btid);
2599 if (code != VNOVOL) {
2600 fprintf(STDERR, "Could not reach the backup volume %lu\n",
2601 (unsigned long)backupID);
2605 backexists = 0; /* backup volume does not exist */
2608 code = AFSVolEndTrans(aconn, btid, &rcode);
2610 if (code || rcode) {
2612 "Could not end transaction on the previous backup volume %lu\n",
2613 (unsigned long)backupID);
2614 error = (code ? code : rcode);
2619 /* Now go ahead and try to clone the RW volume.
2620 * First start a transaction on the RW volume
2622 code = AFSVolTransCreate(aconn, avolid, apart, ITBusy, &ttid);
2624 fprintf(STDERR, "Could not start a transaction on the volume %lu\n",
2625 (unsigned long)avolid);
2630 /* Clone or reclone the volume, depending on whether the backup
2631 * volume exists or not
2634 VPRINT1("Re-cloning backup volume %u ...", backupID);
2636 code = AFSVolReClone(aconn, ttid, backupID);
2638 fprintf(STDERR, "Could not re-clone backup volume %lu\n",
2639 (unsigned long)backupID);
2644 VPRINT1("Creating a new backup clone %u ...", backupID);
2646 strcpy(vname, entry.name);
2647 strcat(vname, ".backup");
2649 code = AFSVolClone(aconn, ttid, 0, backupVolume, vname, &backupID);
2651 fprintf(STDERR, "Failed to clone the volume %lu\n",
2652 (unsigned long)avolid);
2658 /* End the transaction on the RW volume */
2659 code = AFSVolEndTrans(aconn, ttid, &rcode);
2661 if (code || rcode) {
2663 "Failed to end the transaction on the rw volume %lu\n",
2664 (unsigned long)avolid);
2665 error = (code ? code : rcode);
2669 /* Mork vldb as backup exists */
2670 if (!(entry.flags & BACK_EXISTS)) {
2671 entry.flags |= BACK_EXISTS;
2675 /* Now go back to the backup volume and bring it on line */
2676 code = AFSVolTransCreate(aconn, backupID, apart, ITOffline, &btid);
2679 "Failed to start a transaction on the backup volume %lu\n",
2680 (unsigned long)backupID);
2685 code = AFSVolSetFlags(aconn, btid, 0);
2687 fprintf(STDERR, "Could not mark the backup volume %lu on line \n",
2688 (unsigned long)backupID);
2693 code = AFSVolEndTrans(aconn, btid, &rcode);
2695 if (code || rcode) {
2697 "Failed to end the transaction on the backup volume %lu\n",
2698 (unsigned long)backupID);
2699 error = (code ? code : rcode);
2705 /* Will update the vldb below */
2709 code = AFSVolEndTrans(aconn, ttid, &rcode);
2710 if (code || rcode) {
2711 fprintf(STDERR, "Could not end transaction on the volume %lu\n",
2712 (unsigned long)avolid);
2714 error = (code ? code : rcode);
2719 code = AFSVolEndTrans(aconn, btid, &rcode);
2720 if (code || rcode) {
2722 "Could not end transaction the backup volume %lu\n",
2723 (unsigned long)backupID);
2725 error = (code ? code : rcode);
2729 /* Now update the vldb - if modified */
2732 MapNetworkToHost(&entry, &storeEntry);
2734 VLDB_ReplaceEntry(avolid, RWVOL, &storeEntry,
2735 (LOCKREL_OPCODE | LOCKREL_AFSID |
2736 LOCKREL_TIMESTAMP));
2739 "Could not update the VLDB entry for the volume %lu \n",
2740 (unsigned long)avolid);
2746 ubik_Call(VL_ReleaseLock, cstruct, 0, avolid, RWVOL,
2747 (LOCKREL_OPCODE | LOCKREL_AFSID |
2748 LOCKREL_TIMESTAMP));
2751 "Could not unlock the VLDB entry for the volume %lu \n",
2752 (unsigned long)avolid);
2760 rx_DestroyConnection(aconn);
2762 PrintError("", error);
2766 /* Make a new clone of volume <avolid> on <aserver> and <apart>
2767 * using volume ID <acloneid>, or a new ID allocated from the VLDB.
2768 * The new volume is named by <aname>, or by appending ".clone" to
2769 * the existing name if <aname> is NULL. The following flags are
2772 * RV_RDONLY - target volume is RO
2773 * RV_OFFLINE - leave target volume offline
2777 UV_CloneVolume(afs_int32 aserver, afs_int32 apart, afs_int32 avolid,
2778 afs_int32 acloneid, char *aname, int flags)
2780 struct rx_connection *aconn = (struct rx_connection *)0;
2781 afs_int32 ttid = 0, btid = 0;
2782 afs_int32 code = 0, rcode = 0;
2783 char vname[VOLSER_MAXVOLNAME + 1];
2784 afs_int32 error = 0;
2786 volEntries volumeInfo;
2788 aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
2791 volumeInfo.volEntries_val = (volintInfo *) 0;
2792 volumeInfo.volEntries_len = 0;
2793 code = AFSVolListOneVolume(aconn, apart, avolid, &volumeInfo);
2795 fprintf(stderr, "Could not get info for volume %lu\n",
2796 (unsigned long)avolid);
2800 strncpy(vname, volumeInfo.volEntries_val[0].name,
2801 VOLSER_OLDMAXVOLNAME - 7);
2802 vname[VOLSER_OLDMAXVOLNAME - 7] = 0;
2803 strcat(vname, ".clone");
2805 if (volumeInfo.volEntries_val)
2806 free(volumeInfo.volEntries_val);
2810 /* Get a clone id */
2811 VPRINT1("Allocating new volume id for clone of volume %u ...",
2813 code = ubik_Call(VL_GetNewVolumeId, cstruct, 0, 1, &acloneid);
2815 "Could not get an ID for the clone of volume %u from the VLDB\n",
2820 /* Test to see if the clone volume exists by trying to create
2821 * a transaction on the clone volume. We've assumed the clone exists.
2823 /* XXX I wonder what happens if the clone has some other parent... */
2824 code = AFSVolTransCreate(aconn, acloneid, apart, ITOffline, &btid);
2826 if (code != VNOVOL) {
2827 fprintf(STDERR, "Could not reach the clone volume %lu\n",
2828 (unsigned long)acloneid);
2832 backexists = 0; /* backup volume does not exist */
2835 code = AFSVolEndTrans(aconn, btid, &rcode);
2837 if (code || rcode) {
2839 "Could not end transaction on the previous clone volume %lu\n",
2840 (unsigned long)acloneid);
2841 error = (code ? code : rcode);
2846 /* Now go ahead and try to clone the RW volume.
2847 * First start a transaction on the RW volume
2849 code = AFSVolTransCreate(aconn, avolid, apart, ITBusy, &ttid);
2851 fprintf(STDERR, "Could not start a transaction on the volume %lu\n",
2852 (unsigned long)avolid);
2857 /* Clone or reclone the volume, depending on whether the backup
2858 * volume exists or not
2861 VPRINT1("Re-cloning clone volume %u ...", acloneid);
2863 code = AFSVolReClone(aconn, ttid, acloneid);
2865 fprintf(STDERR, "Could not re-clone backup volume %lu\n",
2866 (unsigned long)acloneid);
2871 VPRINT1("Creating a new clone %u ...", acloneid);
2873 code = AFSVolClone(aconn, ttid, 0,
2874 (flags & RV_RDONLY) ? readonlyVolume : backupVolume,
2877 fprintf(STDERR, "Failed to clone the volume %lu\n",
2878 (unsigned long)avolid);
2884 /* End the transaction on the RW volume */
2885 code = AFSVolEndTrans(aconn, ttid, &rcode);
2887 if (code || rcode) {
2889 "Failed to end the transaction on the rw volume %lu\n",
2890 (unsigned long)avolid);
2891 error = (code ? code : rcode);
2895 /* Now go back to the backup volume and bring it on line */
2896 if (!(flags & RV_OFFLINE)) {
2897 code = AFSVolTransCreate(aconn, acloneid, apart, ITOffline, &btid);
2900 "Failed to start a transaction on the clone volume %lu\n",
2901 (unsigned long)acloneid);
2906 code = AFSVolSetFlags(aconn, btid, 0);
2908 fprintf(STDERR, "Could not mark the clone volume %lu on line \n",
2909 (unsigned long)acloneid);
2914 code = AFSVolEndTrans(aconn, btid, &rcode);
2916 if (code || rcode) {
2918 "Failed to end the transaction on the clone volume %lu\n",
2919 (unsigned long)acloneid);
2920 error = (code ? code : rcode);
2929 code = AFSVolEndTrans(aconn, ttid, &rcode);
2930 if (code || rcode) {
2931 fprintf(STDERR, "Could not end transaction on the volume %lu\n",
2932 (unsigned long)avolid);
2934 error = (code ? code : rcode);
2939 code = AFSVolEndTrans(aconn, btid, &rcode);
2940 if (code || rcode) {
2942 "Could not end transaction on the clone volume %lu\n",
2943 (unsigned long)acloneid);
2945 error = (code ? code : rcode);
2950 rx_DestroyConnection(aconn);
2952 PrintError("", error);
2957 DelVol(struct rx_connection *conn, afs_int32 vid, afs_int32 part,
2960 afs_int32 acode, ccode, rcode, tid;
2961 ccode = rcode = tid = 0;
2963 acode = AFSVolTransCreate(conn, vid, part, flags, &tid);
2964 if (!acode) { /* It really was there */
2965 acode = AFSVolDeleteVolume(conn, tid);
2967 fprintf(STDERR, "Failed to delete volume %lu.\n",
2968 (unsigned long)vid);
2969 PrintError("", acode);
2971 ccode = AFSVolEndTrans(conn, tid, &rcode);
2975 fprintf(STDERR, "Failed to end transaction on volume %lu.\n",
2976 (unsigned long)vid);
2977 PrintError("", ccode);
2984 #define ONERROR(ec, ep, es) if (ec) { fprintf(STDERR, (es), (ep)); error = (ec); goto rfail; }
2985 #define ERROREXIT(ec) { error = (ec); goto rfail; }
2987 /* Get a "transaction" on this replica. Create the volume
2988 * if necessary. Return the time from which a dump should
2989 * be made (0 if it's a new volume)
2992 GetTrans(struct nvldbentry *vldbEntryPtr, afs_int32 index,
2993 struct rx_connection **connPtr, afs_int32 * transPtr,
2994 afs_int32 * timePtr)
2997 struct volser_status tstatus;
2998 int code, rcode, tcode;
3000 *connPtr = (struct rx_connection *)0;
3004 /* get connection to the replication site */
3005 *connPtr = UV_Bind(vldbEntryPtr->serverNumber[index], AFSCONF_VOLUMEPORT);
3007 goto fail; /* server is down */
3009 volid = vldbEntryPtr->volumeId[ROVOL];
3012 AFSVolTransCreate(*connPtr, volid,
3013 vldbEntryPtr->serverPartition[index], ITOffline,
3016 /* If the volume does not exist, create it */
3017 if (!volid || code) {
3020 if (volid && (code != VNOVOL)) {
3021 PrintError("Failed to start a transaction on the RO volume.\n",
3026 strcpy(volname, vldbEntryPtr->name);
3027 strcat(volname, ".readonly");
3031 "Creating new volume %lu on replication site %s: ",
3032 (unsigned long)volid,
3033 hostutil_GetNameByINet(vldbEntryPtr->
3034 serverNumber[index]));
3039 AFSVolCreateVolume(*connPtr, vldbEntryPtr->serverPartition[index],
3041 vldbEntryPtr->volumeId[RWVOL], &volid,
3044 PrintError("Failed to create the ro volume: ", code);
3047 vldbEntryPtr->volumeId[ROVOL] = volid;
3051 /* The following is a bit redundant, since create sets these flags by default */
3053 AFSVolSetFlags(*connPtr, *transPtr,
3054 VTDeleteOnSalvage | VTOutOfService);
3056 PrintError("Failed to set flags on the ro volume: ", code);
3061 /* Otherwise, the transaction did succeed, so get the creation date of the
3062 * latest RO volume on the replication site
3065 VPRINT2("Updating existing ro volume %u on %s ...\n", volid,
3066 hostutil_GetNameByINet(vldbEntryPtr->serverNumber[index]));
3068 code = AFSVolGetStatus(*connPtr, *transPtr, &tstatus);
3070 PrintError("Failed to get status of volume on destination: ",
3074 *timePtr = tstatus.creationDate - CLOCKSKEW;
3081 tcode = AFSVolEndTrans(*connPtr, *transPtr, &rcode);
3086 PrintError("Could not end transaction on a ro volume: ", tcode);
3093 SimulateForwardMultiple(struct rx_connection *fromconn, afs_int32 fromtid,
3094 afs_int32 fromdate, manyDests * tr, afs_int32 flags,
3095 void *cookie, manyResults * results)
3099 for (i = 0; i < tr->manyDests_len; i++) {
3100 results->manyResults_val[i] =
3101 AFSVolForward(fromconn, fromtid, fromdate,
3102 &(tr->manyDests_val[i].server),
3103 tr->manyDests_val[i].trans, cookie);
3110 rel_compar(struct release *r1, struct release *r2)
3112 return (r1->time - r2->time);
3115 /* UV_ReleaseVolume()
3116 * Release volume <afromvol> on <afromserver> <afrompart> to all
3117 * its RO sites (full release). Unless the previous release was
3118 * incomplete: in which case we bring the remaining incomplete
3119 * volumes up to date with the volumes that were released
3121 * forceflag: Performs a full release.
3123 * Will create a clone from the RW, then dump the clone out to
3124 * the remaining replicas. If there is more than 1 RO sites,
3125 * ensure that the VLDB says at least one RO is available all
3126 * the time: Influences when we write back the VLDB entry.
3130 UV_ReleaseVolume(afs_int32 afromvol, afs_int32 afromserver,
3131 afs_int32 afrompart, int forceflag)
3134 afs_int32 code, vcode, rcode, tcode;
3135 afs_int32 cloneVolId, roVolId;
3136 struct replica *replicas = 0;
3137 struct nvldbentry entry, storeEntry;
3138 int i, volcount, m, fullrelease, vldbindex;
3140 struct restoreCookie cookie;
3141 struct rx_connection **toconns = 0;
3142 struct release *times = 0;
3144 struct rx_connection *fromconn = (struct rx_connection *)0;
3145 afs_int32 error = 0;
3147 afs_int32 clonetid = 0, onlinetid;
3148 afs_int32 fromtid = 0;
3149 afs_uint32 fromdate, thisdate;
3152 manyResults results;
3153 int rwindex, roindex, roclone, roexists;
3154 afs_int32 rwcrdate, clcrdate;
3158 } remembertime[NMAXNSERVERS];
3159 int releasecount = 0;
3160 struct volser_status volstatus;
3162 memset((char *)remembertime, 0, sizeof(remembertime));
3163 memset((char *)&results, 0, sizeof(results));
3165 vcode = ubik_Call(VL_SetLock, cstruct, 0, afromvol, RWVOL, VLOP_RELEASE);
3166 if (vcode != VL_RERELEASE)
3167 ONERROR(vcode, afromvol,
3168 "Could not lock the VLDB entry for the volume %u.\n");
3171 /* Get the vldb entry in readable format */
3172 vcode = VLDB_GetEntryByID(afromvol, RWVOL, &entry);
3173 ONERROR(vcode, afromvol,
3174 "Could not fetch the entry for the volume %u from the VLDB.\n");
3175 MapHostToNetwork(&entry);
3178 EnumerateEntry(&entry);
3180 if (!ISNAMEVALID(entry.name))
3181 ONERROR(VOLSERBADOP, entry.name,
3182 "Volume name %s is too long, rename before releasing.\n");
3183 if (entry.volumeId[RWVOL] != afromvol)
3184 ONERROR(VOLSERBADOP, afromvol,
3185 "The volume %u being released is not a read-write volume.\n");
3186 if (entry.nServers <= 1)
3187 ONERROR(VOLSERBADOP, afromvol,
3188 "Volume %u has no replicas - release operation is meaningless!\n");
3189 if (strlen(entry.name) > (VOLSER_OLDMAXVOLNAME - 10))
3190 ONERROR(VOLSERBADOP, entry.name,
3191 "RO volume name %s exceeds (VOLSER_OLDMAXVOLNAME - 10) character limit\n");
3193 /* roclone is true if one of the RO volumes is on the same
3194 * partition as the RW volume. In this case, we make the RO volume
3195 * on the same partition a clone instead of a complete copy.
3198 roindex = Lp_ROMatch(afromserver, afrompart, &entry) - 1;
3199 roclone = ((roindex == -1) ? 0 : 1);
3200 rwindex = Lp_GetRwIndex(&entry);
3202 ONERROR(VOLSERNOVOL, 0, "There is no RW volume \n");
3204 /* Make sure we have a RO volume id to work with */
3205 if (entry.volumeId[ROVOL] == INVALID_BID) {
3206 /* need to get a new RO volume id */
3207 vcode = ubik_Call(VL_GetNewVolumeId, cstruct, 0, 1, &roVolId);
3208 ONERROR(vcode, entry.name, "Cant allocate ID for RO volume of %s\n");
3210 entry.volumeId[ROVOL] = roVolId;
3211 MapNetworkToHost(&entry, &storeEntry);
3212 vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry, 0);
3213 ONERROR(vcode, entry.name, "Could not update vldb entry for %s.\n");
3216 /* Will we be completing a previously unfinished release. -force overrides */
3217 for (s = 0, m = 0, fullrelease=0, i=0; (i<entry.nServers); i++) {
3218 if (entry.serverFlags[i] & ITSROVOL) {
3220 if (entry.serverFlags[i] & NEW_REPSITE) s++;
3223 if ((forceflag && !fullrelease) || (s == m) || (s == 0))
3226 /* Determine which volume id to use and see if it exists */
3229 || (entry.cloneId == 0)) ? entry.volumeId[ROVOL] : entry.cloneId);
3230 code = VolumeExists(afromserver, afrompart, cloneVolId);
3231 roexists = ((code == ENODEV) ? 0 : 1);
3233 fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
3235 ONERROR(-1, afromserver,
3236 "Cannot establish connection with server 0x%x\n");
3240 fullrelease = 1; /* Do a full release if RO clone does not exist */
3242 /* Begin transaction on RW and mark it busy while we query it */
3243 code = AFSVolTransCreate(
3244 fromconn, afromvol, afrompart, ITBusy, &fromtid
3246 ONERROR(code, afromvol,
3247 "Failed to start transaction on RW volume %u\n");
3249 /* Query the creation date for the RW */
3250 code = AFSVolGetStatus(fromconn, fromtid, &volstatus);
3251 ONERROR(code, afromvol,
3252 "Failed to get the status of RW volume %u\n");
3253 rwcrdate = volstatus.creationDate;
3255 /* End transaction on RW */
3256 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
3258 ONERROR((code ? code : rcode), afromvol,
3259 "Failed to end transaction on RW volume %u\n");
3261 /* Begin transaction on clone and mark it busy while we query it */
3262 code = AFSVolTransCreate(
3263 fromconn, cloneVolId, afrompart, ITBusy, &clonetid
3265 ONERROR(code, cloneVolId,
3266 "Failed to start transaction on RW clone %u\n");
3268 /* Query the creation date for the clone */
3269 code = AFSVolGetStatus(fromconn, clonetid, &volstatus);
3270 ONERROR(code, cloneVolId,
3271 "Failed to get the status of RW clone %u\n");
3272 clcrdate = volstatus.creationDate;
3274 /* End transaction on RW */
3275 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
3277 ONERROR((code ? code : rcode), cloneVolId,
3278 "Failed to end transaction on RW volume %u\n");
3280 if (rwcrdate > clcrdate)
3281 fullrelease = 2;/* Do a full release if RO clone older than RW */
3286 switch (fullrelease) {
3288 fprintf(STDOUT, "RW %lu changed, doing a complete release\n",
3289 (unsigned long)afromvol);
3292 fprintf(STDOUT, "This is a complete release of volume %lu\n",
3293 (unsigned long)afromvol);
3296 fprintf(STDOUT, "This is a completion of a previous release\n");
3302 /* If the RO clone exists, then if the clone is a temporary
3303 * clone, delete it. Or if the RO clone is marked RO_DONTUSE
3304 * (it was recently added), then also delete it. We do not
3305 * want to "reclone" a temporary RO clone.
3308 && (!roclone || (entry.serverFlags[roindex] & RO_DONTUSE))) {
3309 code = DelVol(fromconn, cloneVolId, afrompart, ITOffline);
3310 if (code && (code != VNOVOL))
3315 /* Mark all the ROs in the VLDB entry as RO_DONTUSE. We don't
3316 * write this entry out to the vlserver until after the first
3317 * RO volume is released (temp RO clones don't count).
3319 for (i = 0; i < entry.nServers; i++) {
3320 entry.serverFlags[i] &= ~NEW_REPSITE;
3321 entry.serverFlags[i] |= RO_DONTUSE;
3323 entry.serverFlags[rwindex] |= NEW_REPSITE;
3324 entry.serverFlags[rwindex] &= ~RO_DONTUSE;
3326 /* Begin transaction on RW and mark it busy while we clone it */
3328 AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy,
3330 ONERROR(code, afromvol, "Failed to start transaction on volume %u\n");
3332 /* Clone or reclone the volume */
3334 VPRINT1("Recloning RW volume %u...", cloneVolId);
3335 code = AFSVolReClone(fromconn, clonetid, cloneVolId);
3336 ONERROR(code, afromvol, "Failed to reclone the RW volume %u\n");
3340 strcpy(vname, entry.name);
3341 strcat(vname, ".readonly");
3342 VPRINT("Cloning RW volume %u to permanent RO...");
3344 strcpy(vname, "readonly-clone-temp");
3345 VPRINT("Cloning RW volume %u to temporary RO...");
3348 AFSVolClone(fromconn, clonetid, 0, readonlyVolume, vname,
3350 ONERROR(code, afromvol, "Failed to clone the RW volume %u\n");
3354 /* Get the time the RW was created for future information */
3355 VPRINT1("Getting status of RW volume %u...", cloneVolId);
3356 code = AFSVolGetStatus(fromconn, clonetid, &volstatus);
3357 ONERROR(code, cloneVolId,
3358 "Failed to get the status of the RW volume %u\n");
3360 rwcrdate = volstatus.creationDate;
3362 /* End the transaction on the RW volume */
3363 VPRINT1("Ending cloning transaction on RW volume %u...", cloneVolId);
3364 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
3366 ONERROR((code ? code : rcode), cloneVolId,
3367 "Failed to end cloning transaction on RW %u\n");
3370 /* Remember clone volume ID in case we fail or are interrupted */
3371 entry.cloneId = cloneVolId;
3374 /* Bring the RO clone online - though not if it's a temporary clone */
3375 VPRINT1("Starting transaction on RO clone volume %u...",
3378 AFSVolTransCreate(fromconn, cloneVolId, afrompart, ITOffline,
3380 ONERROR(code, cloneVolId,
3381 "Failed to start transaction on volume %u\n");
3384 VPRINT1("Setting volume flags for volume %u...", cloneVolId);
3385 tcode = AFSVolSetFlags(fromconn, onlinetid, 0);
3388 VPRINT1("Ending transaction on volume %u...", cloneVolId);
3389 code = AFSVolEndTrans(fromconn, onlinetid, &rcode);
3390 ONERROR((code ? code : rcode), cloneVolId,
3391 "Failed to end transaction on RO clone %u\n");
3394 ONERROR(tcode, cloneVolId, "Could not bring volume %u on line\n");
3396 /* Sleep so that a client searching for an online volume won't
3397 * find the clone offline and then the next RO offline while the
3398 * release brings the clone online and the next RO offline (race).
3399 * There is a fix in the 3.4 client that does not need this sleep
3400 * anymore, but we don't know what clients we have.
3402 if (entry.nServers > 2)
3405 /* Mark the RO clone in the VLDB as a good site (already released) */
3406 entry.serverFlags[roindex] |= NEW_REPSITE;
3407 entry.serverFlags[roindex] &= ~RO_DONTUSE;
3408 entry.flags |= RO_EXISTS;
3412 /* Write out the VLDB entry only if the clone is not a temporary
3413 * clone. If we did this to a temporary clone then we would end
3414 * up marking all the ROs as "old release" making the ROs
3415 * temporarily unavailable.
3417 MapNetworkToHost(&entry, &storeEntry);
3418 VPRINT1("Replacing VLDB entry for %s...", entry.name);
3419 vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry, 0);
3420 ONERROR(vcode, entry.name,
3421 "Could not update vldb entry for %s.\n");
3426 /* Now we will release from the clone to the remaining RO replicas.
3427 * The first 2 ROs (counting the non-temporary RO clone) are released
3428 * individually: releasecount. This is to reduce the race condition
3429 * of clients trying to find an on-line RO volume. The remaining ROs
3430 * are released in parallel but no more than half the number of ROs
3431 * (rounded up) at a time: nservers.
3434 strcpy(vname, entry.name);
3435 strcat(vname, ".readonly");
3436 memset(&cookie, 0, sizeof(cookie));
3437 strncpy(cookie.name, vname, VOLSER_OLDMAXVOLNAME);
3438 cookie.type = ROVOL;
3439 cookie.parent = entry.volumeId[RWVOL];
3442 nservers = entry.nServers / 2; /* how many to do at once, excluding clone */
3444 (struct replica *)malloc(sizeof(struct replica) * nservers + 1);
3445 times = (struct release *)malloc(sizeof(struct release) * nservers + 1);
3447 (struct rx_connection **)malloc(sizeof(struct rx_connection *) *
3449 results.manyResults_val =
3450 (afs_int32 *) malloc(sizeof(afs_int32) * nservers + 1);
3451 if (!replicas || !times || !!!results.manyResults_val || !toconns)
3453 "Failed to create transaction on the release clone\n");
3455 memset(replicas, 0, (sizeof(struct replica) * nservers + 1));
3456 memset(times, 0, (sizeof(struct release) * nservers + 1));
3457 memset(toconns, 0, (sizeof(struct rx_connection *) * nservers + 1));
3458 memset(results.manyResults_val, 0, (sizeof(afs_int32) * nservers + 1));
3460 /* Create a transaction on the cloned volume */
3461 VPRINT1("Starting transaction on cloned volume %u...", cloneVolId);
3463 AFSVolTransCreate(fromconn, cloneVolId, afrompart, ITBusy, &fromtid);
3464 if (!fullrelease && code)
3465 ONERROR(VOLSERNOVOL, afromvol,
3466 "Old clone is inaccessible. Try vos release -f %u.\n");
3467 ONERROR(code, 0, "Failed to create transaction on the release clone\n");
3470 /* For each index in the VLDB */
3471 for (vldbindex = 0; vldbindex < entry.nServers;) {
3473 /* Get a transaction on the replicas. Pick replacas which have an old release. */
3475 ((volcount < nservers) && (vldbindex < entry.nServers));
3477 /* The first two RO volumes will be released individually.
3478 * The rest are then released in parallel. This is a hack
3479 * for clients not recognizing right away when a RO volume
3480 * comes back on-line.
3482 if ((volcount == 1) && (releasecount < 2))
3485 if (vldbindex == roindex)
3486 continue; /* the clone */
3487 if ((entry.serverFlags[vldbindex] & NEW_REPSITE)
3488 && !(entry.serverFlags[vldbindex] & RO_DONTUSE))
3490 if (!(entry.serverFlags[vldbindex] & ITSROVOL))
3491 continue; /* not a RO vol */
3494 /* Get a Transaction on this replica. Get a new connection if
3495 * necessary. Create the volume if necessary. Return the
3496 * time from which the dump should be made (0 if it's a new
3497 * volume). Each volume might have a different time.
3499 replicas[volcount].server.destHost =
3500 ntohl(entry.serverNumber[vldbindex]);
3501 replicas[volcount].server.destPort = AFSCONF_VOLUMEPORT;
3502 replicas[volcount].server.destSSID = 1;
3503 times[volcount].vldbEntryIndex = vldbindex;
3506 GetTrans(&entry, vldbindex, &(toconns[volcount]),
3507 &(replicas[volcount].trans),
3508 &(times[volcount].time));
3512 /* Thisdate is the date from which we want to pick up all changes */
3513 if (forceflag || !fullrelease
3514 || (rwcrdate > times[volcount].time)) {
3515 /* If the forceflag is set, then we want to do a full dump.
3516 * If it's not a full release, we can't be sure that the creation
3517 * date is good (so we also do a full dump).
3518 * If the RW volume was replaced (its creation date is newer than
3519 * the last release), then we can't be sure what has changed (so
3520 * we do a full dump).
3523 } else if (remembertime[vldbindex].validtime) {
3524 /* Trans was prev ended. Use the time from the prev trans
3525 * because, prev trans may have created the volume. In which
3526 * case time[volcount].time would be now instead of 0.
3529 (remembertime[vldbindex].time <
3530 times[volcount].time) ? remembertime[vldbindex].
3531 time : times[volcount].time;
3533 thisdate = times[volcount].time;