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 */
59 #define CLOCKADJ(x) (((x) < CLOCKSKEW) ? 0 : (x) - CLOCKSKEW)
61 /* for UV_MoveVolume() recovery */
63 #include <afs/procmgmt.h> /* signal(), kill(), wait(), etc. */
66 #include <volser_prototypes.h>
68 struct ubik_client *cstruct;
74 afs_int32 vldbEntryIndex;
77 /* Utility macros used by rest of this source file */
78 #define EPRINT(ec, es) \
80 fprintf(STDERR, "\n"); \
81 fprintf(STDERR, (es)); \
85 #define EPRINT1(ec, es, ep1) \
87 fprintf(STDERR, "\n"); \
88 fprintf(STDERR, (es), (ep1)); \
92 #define EPRINT2(ec, es, ep1, ep2) \
94 fprintf(STDERR, "\n"); \
95 fprintf(STDERR, (es), (ep1), (ep2)); \
99 #define EPRINT3(ec, es, ep1, ep2, ep3) \
101 fprintf(STDERR, "\n"); \
102 fprintf(STDERR, (es), (ep1), (ep2), (ep3)); \
103 PrintError(" ",ec); \
106 #define EGOTO(where, ec, es) \
115 #define EGOTO1(where, ec, es, ep1) \
118 EPRINT1((ec),(es),(ep1)); \
124 #define EGOTO2(where, ec, es, ep1, ep2) \
127 EPRINT2((ec),(es),(ep1),(ep2)); \
133 #define EGOTO3(where, ec, es, ep1, ep2, ep3) \
136 EPRINT3((ec),(es),(ep1),(ep2),(ep3)); \
143 { if (verbose) { fprintf(STDOUT, (es)); fflush(STDOUT); } }
144 #define VPRINT1(es, p) \
145 { if (verbose) { fprintf(STDOUT, (es), (p)); fflush(STDOUT); } }
146 #define VPRINT2(es, p1, p2) \
147 { if (verbose) { fprintf(STDOUT, (es), (p1), (p2)); fflush(STDOUT); } }
148 #define VPRINT3(es, p1, p2, p3) \
149 { if (verbose) { fprintf(STDOUT, (es), (p1), (p2), (p3)); fflush(STDOUT); } }
151 { if (verbose) { fprintf(STDOUT, " done\n"); fflush(STDOUT); } }
155 /* getting rid of this */
156 #define ERROR_EXIT(code) {error=(code); goto error_exit;}
159 /* Protos for static routines */
160 static afs_int32 CheckAndDeleteVolume(struct rx_connection *aconn,
161 afs_int32 apart, afs_int32 okvol,
163 static int DelVol(struct rx_connection *conn, afs_int32 vid, afs_int32 part,
165 static int GetTrans(struct nvldbentry *vldbEntryPtr, afs_int32 index,
166 struct rx_connection **connPtr, afs_int32 * transPtr,
167 afs_int32 * crtimePtr, afs_int32 * uptimePtr);
168 static int SimulateForwardMultiple(struct rx_connection *fromconn,
169 afs_int32 fromtid, afs_int32 fromdate,
170 manyDests * tr, afs_int32 flags,
171 void *cookie, manyResults * results);
172 static afs_int32 CheckVolume(volintInfo * volumeinfo, afs_int32 aserver,
173 afs_int32 apart, afs_int32 * modentry,
174 afs_uint32 * maxvolid);
177 /*map the partition <partId> into partition name <partName>*/
179 MapPartIdIntoName(afs_int32 partId, char *partName)
181 if (partId < 26) { /* what if partId > = 26 ? */
182 strcpy(partName, "/vicep");
183 partName[6] = partId + 'a';
186 } else if (partId < VOLMAXPARTS) {
187 strcpy(partName, "/vicep");
189 partName[6] = 'a' + (partId / 26);
190 partName[7] = 'a' + (partId % 26);
202 fprintf(STDERR, "Do you want to %s? [yn](n): ", str);
203 response = c = getchar();
204 while (!(c == EOF || c == '\n'))
205 c = getchar(); /*skip to end of line */
206 code = (response == 'y' || response == 'Y');
212 PrintError(char *msg, afs_int32 errcode)
214 fprintf(STDERR, msg);
215 /*replace by a big switch statement */
220 fprintf(STDERR, "Possible communication failure\n");
223 fprintf(STDERR, "Volume needs to be salvaged\n");
226 fprintf(STDERR, "Bad vnode number quoted\n");
230 "Volume not attached, does not exist, or not on line\n");
233 fprintf(STDERR, "Volume already exists\n");
236 fprintf(STDERR, "Volume is not in service\n");
239 fprintf(STDERR, "Volume is off line\n");
242 fprintf(STDERR, "Volume is already on line\n");
245 fprintf(STDERR, "Partition is full\n");
248 fprintf(STDERR, "Volume max quota exceeded\n");
251 fprintf(STDERR, "Volume temporarily unavailable\n");
254 fprintf(STDERR, "Volume has moved to another server\n");
257 fprintf(STDERR, "VLDB: volume Id exists in the vldb\n");
260 fprintf(STDERR, "VLDB: a read terminated too early\n");
263 fprintf(STDERR, "VLDB: volume entry exists in the vldb\n");
266 fprintf(STDERR, "VLDB: internal creation failure\n");
269 fprintf(STDERR, "VLDB: no such entry\n");
272 fprintf(STDERR, "VLDB: vldb database is empty\n");
275 fprintf(STDERR, "VLDB: entry is deleted (soft delete)\n");
278 fprintf(STDERR, "VLDB: volume name is illegal\n");
281 fprintf(STDERR, "VLDB: index was out of range\n");
284 fprintf(STDERR, "VLDB: bad volume type\n");
287 fprintf(STDERR, "VLDB: illegal server number (not within limits)\n");
289 case VL_BADPARTITION:
290 fprintf(STDERR, "VLDB: bad partition number\n");
293 fprintf(STDERR, "VLDB: run out of space for replication sites\n");
296 fprintf(STDERR, "VLDB: no such repsite server exists\n");
298 case VL_DUPREPSERVER:
299 fprintf(STDERR, "VLDB: replication site server already exists\n");
302 fprintf(STDERR, "VLDB: parent r/w entry not found\n");
305 fprintf(STDERR, "VLDB: illegal reference count number\n");
307 case VL_SIZEEXCEEDED:
308 fprintf(STDERR, "VLDB: vldb size for attributes exceeded\n");
311 fprintf(STDERR, "VLDB: bad incoming vldb entry\n");
313 case VL_BADVOLIDBUMP:
314 fprintf(STDERR, "VLDB: illegal max volid increment\n");
316 case VL_IDALREADYHASHED:
317 fprintf(STDERR, "VLDB: (RO/BACK) Id already hashed\n");
320 fprintf(STDERR, "VLDB: vldb entry is already locked\n");
323 fprintf(STDERR, "VLDB: bad volume operation code\n");
325 case VL_BADRELLOCKTYPE:
326 fprintf(STDERR, "VLDB: bad release lock type\n");
329 fprintf(STDERR, "VLDB: status report: last release was aborted\n");
331 case VL_BADSERVERFLAG:
332 fprintf(STDERR, "VLDB: invalid replication site server flag\n");
335 fprintf(STDERR, "VLDB: no permission access for call\n");
337 case VOLSERREAD_DUMPERROR:
339 "VOLSER: Problems encountered in reading the dump file !\n");
341 case VOLSERDUMPERROR:
342 fprintf(STDERR, "VOLSER: Problems encountered in doing the dump !\n");
344 case VOLSERATTACH_ERROR:
345 fprintf(STDERR, "VOLSER: Could not attach the volume\n");
347 case VOLSERDETACH_ERROR:
348 fprintf(STDERR, "VOLSER: Could not detach the volume\n");
350 case VOLSERILLEGAL_PARTITION:
351 fprintf(STDERR, "VOLSER: encountered illegal partition number\n");
353 case VOLSERBAD_ACCESS:
354 fprintf(STDERR, "VOLSER: permission denied, not a super user\n");
356 case VOLSERVLDB_ERROR:
357 fprintf(STDERR, "VOLSER: error detected in the VLDB\n");
360 fprintf(STDERR, "VOLSER: error in volume name\n");
363 fprintf(STDERR, "VOLSER: volume has moved\n");
366 fprintf(STDERR, "VOLSER: illegal operation\n");
368 case VOLSERBADRELEASE:
369 fprintf(STDERR, "VOLSER: release could not be completed\n");
372 fprintf(STDERR, "VOLSER: volume is busy\n");
374 case VOLSERNO_MEMORY:
375 fprintf(STDERR, "VOLSER: volume server is out of memory\n");
379 "VOLSER: no such volume - location specified incorrectly or volume does not exist\n");
381 case VOLSERMULTIRWVOL:
383 "VOLSER: multiple RW volumes with same ID, one of which should be deleted\n");
387 "VOLSER: not all entries were successfully processed\n");
394 initialize_KA_error_table();
395 initialize_RXK_error_table();
396 initialize_KTC_error_table();
397 initialize_ACFG_error_table();
398 initialize_CMD_error_table();
399 initialize_VL_error_table();
401 offset = errcode & ((1 << ERRCODE_RANGE) - 1);
402 fprintf(STDERR, "%s: %s\n", error_table_name(errcode),
403 error_message(errcode));
410 void init_volintInfo(struct volintInfo *vinfo) {
411 memset(vinfo, 0, sizeof(struct volintInfo));
413 vinfo->maxquota = -1;
415 vinfo->creationDate = -1;
416 vinfo->updateDate = -1;
424 static struct rx_securityClass *uvclass = 0;
425 static int uvindex = -1;
426 /* called by VLDBClient_Init to set the security module to be used in the RPC */
428 UV_SetSecurity(register struct rx_securityClass *as, afs_int32 aindex)
435 /* bind to volser on <port> <aserver> */
436 /* takes server address in network order, port in host order. dumb */
437 struct rx_connection *
438 UV_Bind(afs_int32 aserver, afs_int32 port)
440 register struct rx_connection *tc;
442 tc = rx_NewConnection(aserver, htons(port), VOLSERVICE_ID, uvclass,
447 /* if <okvol> is allright(indicated by beibg able to
448 * start a transaction, delete the <delvol> */
450 CheckAndDeleteVolume(struct rx_connection *aconn, afs_int32 apart,
451 afs_int32 okvol, afs_int32 delvol)
453 afs_int32 error, code, tid, rcode;
459 code = AFSVolTransCreate(aconn, delvol, apart, ITOffline, &tid);
462 code = AFSVolDeleteVolume(aconn, tid);
465 code = AFSVolEndTrans(aconn, tid, &rcode);
472 code = AFSVolTransCreate(aconn, okvol, apart, ITOffline, &tid);
474 code = AFSVolEndTrans(aconn, tid, &rcode);
479 code = AFSVolTransCreate(aconn, delvol, apart, ITOffline, &tid);
482 code = AFSVolDeleteVolume(aconn, tid);
485 code = AFSVolEndTrans(aconn, tid, &rcode);
496 /* called by EmuerateEntry, show vldb entry in a reasonable format */
498 SubEnumerateEntry(struct nvldbentry *entry)
505 fprintf(STDOUT, " readWriteID %-10u ", entry->volumeId[RWVOL]);
506 if (entry->flags & RW_EXISTS)
507 fprintf(STDOUT, " valid \n");
509 fprintf(STDOUT, " invalid \n");
510 fprintf(STDOUT, " readOnlyID %-10u ", entry->volumeId[ROVOL]);
511 if (entry->flags & RO_EXISTS)
512 fprintf(STDOUT, " valid \n");
514 fprintf(STDOUT, " invalid \n");
515 fprintf(STDOUT, " backUpID %-10u ", entry->volumeId[BACKVOL]);
516 if (entry->flags & BACK_EXISTS)
517 fprintf(STDOUT, " valid \n");
519 fprintf(STDOUT, " invalid \n");
520 if ((entry->cloneId != 0) && (entry->flags & RO_EXISTS))
521 fprintf(STDOUT, " releaseClone %-10u \n", entry->cloneId);
523 if (entry->flags & RW_EXISTS)
524 fprintf(STDOUT, " RWrite: %-10u", entry->volumeId[RWVOL]);
525 if (entry->flags & RO_EXISTS)
526 fprintf(STDOUT, " ROnly: %-10u", entry->volumeId[ROVOL]);
527 if (entry->flags & BACK_EXISTS)
528 fprintf(STDOUT, " Backup: %-10u", entry->volumeId[BACKVOL]);
529 if ((entry->cloneId != 0) && (entry->flags & RO_EXISTS))
530 fprintf(STDOUT, " RClone: %-10lu", (unsigned long)entry->cloneId);
531 fprintf(STDOUT, "\n");
533 fprintf(STDOUT, " number of sites -> %lu\n",
534 (unsigned long)entry->nServers);
535 for (i = 0; i < entry->nServers; i++) {
536 if (entry->serverFlags[i] & NEW_REPSITE)
539 for (i = 0; i < entry->nServers; i++) {
540 MapPartIdIntoName(entry->serverPartition[i], pname);
541 fprintf(STDOUT, " server %s partition %s ",
542 hostutil_GetNameByINet(entry->serverNumber[i]), pname);
543 if (entry->serverFlags[i] & ITSRWVOL)
544 fprintf(STDOUT, "RW Site ");
546 fprintf(STDOUT, "RO Site ");
548 if (entry->serverFlags[i] & NEW_REPSITE)
549 fprintf(STDOUT," -- New release");
551 if (!(entry->serverFlags[i] & ITSRWVOL))
552 fprintf(STDOUT," -- Old release");
554 if (entry->serverFlags[i] & RO_DONTUSE)
555 fprintf(STDOUT, " -- Not released");
557 fprintf(STDOUT, "\n");
564 /*enumerate the vldb entry corresponding to <entry> */
566 EnumerateEntry(struct nvldbentry *entry)
569 fprintf(STDOUT, "\n");
570 fprintf(STDOUT, "%s \n", entry->name);
571 SubEnumerateEntry(entry);
575 /* forcibly remove a volume. Very dangerous call */
577 UV_NukeVolume(afs_int32 server, afs_int32 partid, afs_int32 volid)
579 register struct rx_connection *tconn;
580 register afs_int32 code;
582 tconn = UV_Bind(server, AFSCONF_VOLUMEPORT);
584 code = AFSVolNukeVolume(tconn, partid, volid);
585 rx_DestroyConnection(tconn);
591 /* like df. Return usage of <pname> on <server> in <partition> */
593 UV_PartitionInfo(afs_int32 server, char *pname,
594 struct diskPartition *partition)
596 register struct rx_connection *aconn;
600 aconn = (struct rx_connection *)0;
601 aconn = UV_Bind(server, AFSCONF_VOLUMEPORT);
602 code = AFSVolPartitionInfo(aconn, pname, partition);
604 fprintf(STDERR, "Could not get information on partition %s\n", pname);
605 PrintError("", code);
608 rx_DestroyConnection(aconn);
612 /* old interface to create volume */
614 UV_CreateVolume(afs_int32 aserver, afs_int32 apart, char *aname,
618 code = UV_CreateVolume2(aserver, apart, aname, 5000, 0, 0, 0, 0, anewid);
622 /* create a volume, given a server, partition number, volume name --> sends
623 * back new vol id in <anewid>*/
625 UV_CreateVolume2(afs_int32 aserver, afs_int32 apart, char *aname,
626 afs_int32 aquota, afs_int32 aspare1, afs_int32 aspare2,
627 afs_int32 aspare3, afs_int32 aspare4, afs_int32 * anewid)
630 register struct rx_connection *aconn;
632 register afs_int32 code;
634 afs_int32 rcode, vcode;
635 struct nvldbentry entry, storeEntry; /*the new vldb entry */
636 struct volintInfo tstatus;
639 aconn = (struct rx_connection *)0;
642 init_volintInfo(&tstatus);
643 tstatus.maxquota = aquota;
645 aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
646 /* next the next 3 available ids from the VLDB */
647 vcode = ubik_Call(VL_GetNewVolumeId, cstruct, 0, 3, anewid);
648 EGOTO1(cfail, vcode, "Could not get an Id for volume %s\n", aname);
651 AFSVolCreateVolume(aconn, apart, aname, volser_RW, 0, anewid, &tid);
652 EGOTO2(cfail, vcode, "Failed to create the volume %s %u \n", aname,
655 code = AFSVolSetInfo(aconn, tid, &tstatus);
657 EPRINT(code, "Could not change quota (error %d), continuing...\n");
659 code = AFSVolSetFlags(aconn, tid, 0); /* bring it online (mark it InService */
660 EGOTO2(cfail, vcode, "Could not bring the volume %s %u online \n", aname,
663 VPRINT2("Volume %s %u created and brought online\n", aname, *anewid);
665 /* set up the vldb entry for this volume */
666 strncpy(entry.name, aname, VOLSER_OLDMAXVOLNAME);
668 entry.serverNumber[0] = aserver; /* this should have another
669 * level of indirection later */
670 entry.serverPartition[0] = apart; /* this should also have
671 * another indirection level */
672 entry.flags = RW_EXISTS; /* this records that rw volume exists */
673 entry.serverFlags[0] = ITSRWVOL; /*this rep site has rw vol */
674 entry.volumeId[RWVOL] = *anewid;
675 entry.volumeId[ROVOL] = *anewid + 1; /* rw,ro, bk id are related in the default case */
676 entry.volumeId[BACKVOL] = *anewid + 2;
678 /*map into right byte order, before passing to xdr, the stuff has to be in host
679 * byte order. Xdr converts it into network order */
680 MapNetworkToHost(&entry, &storeEntry);
681 /* create the vldb entry */
682 vcode = VLDB_CreateEntry(&storeEntry);
685 "Could not create a VLDB entry for the volume %s %lu\n",
686 aname, (unsigned long)*anewid);
687 /*destroy the created volume */
688 VPRINT1("Deleting the newly created volume %u\n", *anewid);
689 AFSVolDeleteVolume(aconn, tid);
693 VPRINT2("Created the VLDB entry for the volume %s %u\n", aname, *anewid);
694 /* volume created, now terminate the transaction and release the connection */
695 code = AFSVolEndTrans(aconn, tid, &rcode); /*if it crashes before this
696 * the volume will come online anyway when transaction timesout , so if
697 * vldb entry exists then the volume is guaranteed to exist too wrt create */
701 "Failed to end the transaction on the volume %s %lu\n", aname,
702 (unsigned long)*anewid);
709 code = AFSVolEndTrans(aconn, tid, &rcode);
711 fprintf(STDERR, "WARNING: could not end transaction\n");
714 rx_DestroyConnection(aconn);
715 PrintError("", error);
721 /* create a volume, given a server, partition number, volume name --> sends
722 * back new vol id in <anewid>*/
724 UV_AddVLDBEntry(afs_int32 aserver, afs_int32 apart, char *aname,
727 register struct rx_connection *aconn;
730 struct nvldbentry entry, storeEntry; /*the new vldb entry */
732 aconn = (struct rx_connection *)0;
735 /* set up the vldb entry for this volume */
736 strncpy(entry.name, aname, VOLSER_OLDMAXVOLNAME);
738 entry.serverNumber[0] = aserver; /* this should have another
739 * level of indirection later */
740 entry.serverPartition[0] = apart; /* this should also have
741 * another indirection level */
742 entry.flags = RW_EXISTS; /* this records that rw volume exists */
743 entry.serverFlags[0] = ITSRWVOL; /*this rep site has rw vol */
744 entry.volumeId[RWVOL] = aid;
746 entry.volumeId[ROVOL] = anewid + 1; /* rw,ro, bk id are related in the default case */
747 entry.volumeId[BACKVOL] = *anewid + 2;
749 entry.volumeId[ROVOL] = 0;
750 entry.volumeId[BACKVOL] = 0;
753 /*map into right byte order, before passing to xdr, the stuff has to be in host
754 * byte order. Xdr converts it into network order */
755 MapNetworkToHost(&entry, &storeEntry);
756 /* create the vldb entry */
757 vcode = VLDB_CreateEntry(&storeEntry);
760 "Could not create a VLDB entry for the volume %s %lu\n",
761 aname, (unsigned long)aid);
765 VPRINT2("Created the VLDB entry for the volume %s %u\n", aname, aid);
769 rx_DestroyConnection(aconn);
770 PrintError("", error);
774 /* Delete the volume <volid>on <aserver> <apart>
775 * the physical entry gets removed from the vldb only if the ref count
779 UV_DeleteVolume(afs_int32 aserver, afs_int32 apart, afs_int32 avolid)
781 struct rx_connection *aconn = (struct rx_connection *)0;
783 afs_int32 code, rcode;
785 struct nvldbentry entry, storeEntry;
787 afs_int32 avoltype = -1, vtype;
788 int notondisk = 0, notinvldb = 0;
790 /* Find and read bhe VLDB entry for this volume */
791 code = ubik_Call(VL_SetLock, cstruct, 0, avolid, avoltype, VLOP_DELETE);
793 if (code != VL_NOENT) {
794 EGOTO1(error_exit, code,
795 "Could not lock VLDB entry for the volume %u\n", avolid);
801 code = VLDB_GetEntryByID(avolid, avoltype, &entry);
802 EGOTO1(error_exit, code, "Could not fetch VLDB entry for volume %u\n",
804 MapHostToNetwork(&entry);
807 EnumerateEntry(&entry);
810 /* Whether volume is in the VLDB or not. Delete the volume on disk */
811 aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
812 code = AFSVolTransCreate(aconn, avolid, apart, ITOffline, &ttid);
814 if (code == VNOVOL) {
817 EGOTO1(error_exit, code, "Transaction on volume %u failed\n",
821 VPRINT1("Trying to delete the volume %u ...", avolid);
823 code = AFSVolDeleteVolume(aconn, ttid);
824 EGOTO1(error_exit, code, "Could not delete the volume %u \n", avolid);
826 code = AFSVolEndTrans(aconn, ttid, &rcode);
827 code = (code ? code : rcode);
829 EGOTO1(error_exit, code,
830 "Could not end the transaction for the volume %u \n", avolid);
834 /* Now update the VLDB entry.
835 * But first, verify we have a VLDB entry.
836 * Whether volume is on disk or not. Delete the volume in VLDB.
841 if (avolid == entry.volumeId[BACKVOL]) {
842 /* Its a backup volume, modify the VLDB entry. Check that the
843 * backup volume is on the server/partition we asked to delete.
845 if (!(entry.flags & BACK_EXISTS) || !Lp_Match(aserver, apart, &entry)) {
846 notinvldb = 2; /* Not on this server and partition */
850 VPRINT1("Marking the backup volume %u deleted in the VLDB\n", avolid);
852 entry.flags &= ~BACK_EXISTS;
856 else if (avolid == entry.volumeId[ROVOL]) {
857 /* Its a read-only volume, modify the VLDB entry. Check that the
858 * readonly volume is on the server/partition we asked to delete.
859 * If flags does not have RO_EIXSTS set, then this may mean the RO
860 * hasn't been released (and could exist in VLDB).
862 if (!Lp_ROMatch(aserver, apart, &entry)) {
863 notinvldb = 2; /* Not found on this server and partition */
869 "Marking the readonly volume %lu deleted in the VLDB\n",
870 (unsigned long)avolid);
872 Lp_SetROValue(&entry, aserver, apart, 0, 0); /* delete the site */
874 if (!Lp_ROMatch(0, 0, &entry))
875 entry.flags &= ~RO_EXISTS; /* This was the last ro volume */
879 else if (avolid == entry.volumeId[RWVOL]) {
880 /* It's a rw volume, delete the backup volume, modify the VLDB entry.
881 * Check that the readwrite volumes is on the server/partition we
884 if (!(entry.flags & RW_EXISTS) || !Lp_Match(aserver, apart, &entry)) {
885 notinvldb = 2; /* Not found on this server and partition */
889 /* Delete backup if it exists */
891 AFSVolTransCreate(aconn, entry.volumeId[BACKVOL], apart,
895 fprintf(STDOUT, "Trying to delete the backup volume %u ...",
896 entry.volumeId[BACKVOL]);
899 code = AFSVolDeleteVolume(aconn, ttid);
900 EGOTO1(error_exit, code, "Could not delete the volume %u \n",
901 entry.volumeId[BACKVOL]);
903 code = AFSVolEndTrans(aconn, ttid, &rcode);
905 code = (code ? code : rcode);
906 EGOTO1(error_exit, code,
907 "Could not end the transaction for the volume %u \n",
908 entry.volumeId[BACKVOL]);
910 fprintf(STDOUT, " done\n");
915 "Marking the readwrite volume %lu%s deleted in the VLDB\n",
916 (unsigned long)avolid,
918 flags & BACK_EXISTS) ? ", and its backup volume," :
921 Lp_SetRWValue(&entry, aserver, apart, 0L, 0L);
923 entry.flags &= ~(BACK_EXISTS | RW_EXISTS);
926 if (entry.flags & RO_EXISTS)
927 fprintf(STDERR, "WARNING: ReadOnly copy(s) may still exist\n");
931 notinvldb = 2; /* Not found on this server and partition */
935 /* Either delete or replace the VLDB entry */
936 if ((entry.nServers <= 0) || !(entry.flags & (RO_EXISTS | RW_EXISTS))) {
939 "Last reference to the VLDB entry for %lu - deleting entry\n",
940 (unsigned long)avolid);
941 code = ubik_Call(VL_DeleteEntry, cstruct, 0, avolid, vtype);
942 EGOTO1(error_exit, code,
943 "Could not delete the VLDB entry for the volume %u \n",
946 MapNetworkToHost(&entry, &storeEntry);
948 VLDB_ReplaceEntry(avolid, vtype, &storeEntry,
949 (LOCKREL_OPCODE | LOCKREL_AFSID |
951 EGOTO1(error_exit, code,
952 "Could not update the VLDB entry for the volume %u \n",
961 if (notondisk && notinvldb) {
962 EPRINT2(VOLSERNOVOL, "Volume %u does not exist %s\n", avolid,
963 ((notinvldb == 2) ? "on server and partition" : ""));
966 } else if (notondisk) {
968 "WARNING: Volume %lu did not exist on the partition\n",
969 (unsigned long)avolid);
970 } else if (notinvldb) {
971 fprintf(STDERR, "WARNING: Volume %lu does not exist in VLDB %s\n",
972 (unsigned long)avolid,
973 ((notinvldb == 2) ? "on server and partition" : ""));
977 code = AFSVolEndTrans(aconn, ttid, &rcode);
978 code = (code ? code : rcode);
980 fprintf(STDERR, "Could not end transaction on the volume %lu\n",
981 (unsigned long)avolid);
982 PrintError("", code);
990 ubik_Call(VL_ReleaseLock, cstruct, 0, avolid, -1,
991 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
994 "Could not release the lock on the VLDB entry for the volume %u \n",
1002 rx_DestroyConnection(aconn);
1006 /* add recovery to UV_MoveVolume */
1008 #define TESTC 0 /* set to test recovery code, clear for production */
1014 sigint_handler(int x)
1019 fprintf(STDOUT, "\nSIGINT handler: vos move operation in progress\n");
1021 "WARNING: may leave AFS storage and metadata in indeterminate state\n");
1022 fprintf(STDOUT, "enter second control-c to exit\n");
1026 (void)signal(SIGINT, sigint_handler);
1031 /* Move volume <afromvol> on <afromserver> <afrompart> to <atoserver>
1032 * <atopart>. The operation is almost idempotent. The following
1033 * flags are recognized:
1035 * RV_NOCLONE - don't use a copy clone
1039 UV_MoveVolume2(afs_int32 afromvol, afs_int32 afromserver, afs_int32 afrompart,
1040 afs_int32 atoserver, afs_int32 atopart, int flags)
1042 struct rx_connection *toconn, *fromconn;
1043 afs_int32 fromtid, totid, clonetid;
1046 char tmpName[VOLSER_MAXVOLNAME + 1];
1049 struct restoreCookie cookie;
1050 register afs_int32 vcode, code;
1051 afs_int32 newVol, volid, backupId;
1052 struct volser_status tstatus;
1053 struct destServer destination;
1055 struct nvldbentry entry, storeEntry;
1056 int i, islocked, pntg;
1058 char in, lf; /* for test code */
1061 #ifdef ENABLE_BUGFIX_1165
1062 volEntries volumeInfo;
1063 struct volintInfo *infop = 0;
1067 fromconn = (struct rx_connection *)0;
1068 toconn = (struct rx_connection *)0;
1078 /* support control-c processing */
1081 (void)signal(SIGINT, sigint_handler);
1085 "\nThere are three tests points - verifies all code paths through recovery.\n");
1086 fprintf(STDOUT, "First test point - operation not started.\n");
1087 fprintf(STDOUT, "...test here (y, n)? ");
1089 fscanf(stdin, "%c", &in);
1090 fscanf(stdin, "%c", &lf); /* toss away */
1092 fprintf(STDOUT, "type control-c\n");
1094 fprintf(stdout, ".");
1099 /* or drop through */
1102 vcode = VLDB_GetEntryByID(afromvol, -1, &entry);
1103 EGOTO1(mfail, vcode,
1104 "Could not fetch the entry for the volume %u from the VLDB \n",
1107 if (entry.volumeId[RWVOL] != afromvol) {
1108 fprintf(STDERR, "Only RW volume can be moved\n");
1112 vcode = ubik_Call(VL_SetLock, cstruct, 0, afromvol, RWVOL, VLOP_MOVE);
1113 EGOTO1(mfail, vcode, "Could not lock entry for volume %u \n", afromvol);
1116 vcode = VLDB_GetEntryByID(afromvol, RWVOL, &entry);
1117 EGOTO1(mfail, vcode,
1118 "Could not fetch the entry for the volume %u from the VLDB \n",
1121 backupId = entry.volumeId[BACKVOL];
1122 MapHostToNetwork(&entry);
1124 if (!Lp_Match(afromserver, afrompart, &entry)) {
1125 /* the from server and partition do not exist in the vldb entry corresponding to volid */
1126 if (!Lp_Match(atoserver, atopart, &entry)) {
1127 /* the to server and partition do not exist in the vldb entry corresponding to volid */
1128 fprintf(STDERR, "The volume %lu is not on the specified site. \n",
1129 (unsigned long)afromvol);
1130 fprintf(STDERR, "The current site is :");
1131 for (i = 0; i < entry.nServers; i++) {
1132 if (entry.serverFlags[i] == ITSRWVOL) {
1134 MapPartIdIntoName(entry.serverPartition[i], pname);
1135 fprintf(STDERR, " server %s partition %s \n",
1136 hostutil_GetNameByINet(entry.serverNumber[i]),
1141 ubik_Call(VL_ReleaseLock, cstruct, 0, afromvol, -1,
1142 (LOCKREL_OPCODE | LOCKREL_AFSID |
1143 LOCKREL_TIMESTAMP));
1144 EGOTO1(mfail, vcode,
1145 " Could not release lock on the VLDB entry for the volume %u \n",
1148 return VOLSERVOLMOVED;
1151 /* delete the volume afromvol on src_server */
1152 /* from-info does not exist but to-info does =>
1153 * we have already done the move, but the volume
1154 * may still be existing physically on from fileserver
1156 fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
1161 AFSVolTransCreate(fromconn, afromvol, afrompart, ITOffline,
1163 if (!code) { /* volume exists - delete it */
1164 VPRINT1("Setting flags on leftover source volume %u ...",
1167 AFSVolSetFlags(fromconn, fromtid,
1168 VTDeleteOnSalvage | VTOutOfService);
1170 "Failed to set flags on the leftover source volume %u\n",
1174 VPRINT1("Deleting leftover source volume %u ...", afromvol);
1175 code = AFSVolDeleteVolume(fromconn, fromtid);
1177 "Failed to delete the leftover source volume %u\n",
1181 VPRINT1("Ending transaction on leftover source volume %u ...",
1183 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1188 "Could not end the transaction for the leftover source volume %u \n",
1193 /*delete the backup volume now */
1196 AFSVolTransCreate(fromconn, backupId, afrompart, ITOffline,
1198 if (!code) { /* backup volume exists - delete it */
1199 VPRINT1("Setting flags on leftover backup volume %u ...",
1202 AFSVolSetFlags(fromconn, fromtid,
1203 VTDeleteOnSalvage | VTOutOfService);
1205 "Failed to set flags on the backup volume %u\n", backupId);
1208 VPRINT1("Deleting leftover backup volume %u ...", backupId);
1209 code = AFSVolDeleteVolume(fromconn, fromtid);
1211 "Could not delete the leftover backup volume %u\n",
1215 VPRINT1("Ending transaction on leftover backup volume %u ...",
1217 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1222 "Could not end the transaction for the leftover backup volume %u\n",
1232 /* From-info matches the vldb info about volid,
1233 * its ok start the move operation, the backup volume
1234 * on the old site is deleted in the process
1236 if (afrompart == atopart) {
1237 same = VLDB_IsSameAddrs(afromserver, atoserver, &error);
1238 EGOTO2(mfail, error,
1239 "Failed to get info about server's %d address(es) from vlserver (err=%d); aborting call!\n",
1240 afromserver, error);
1243 EGOTO1(mfail, VOLSERVOLMOVED,
1244 "Warning: Moving volume %u to its home partition ignored!\n",
1250 toconn = UV_Bind(atoserver, AFSCONF_VOLUMEPORT); /* get connections to the servers */
1251 fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
1252 fromtid = totid = 0; /* initialize to uncreated */
1255 * clone the read/write volume locally.
1258 VPRINT1("Starting transaction on source volume %u ...", afromvol);
1259 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
1260 EGOTO1(mfail, code, "Failed to create transaction on the volume %u\n",
1264 if (!(flags & RV_NOCLONE)) {
1265 /* Get a clone id */
1266 VPRINT1("Allocating new volume id for clone of volume %u ...",
1269 vcode = ubik_Call(VL_GetNewVolumeId, cstruct, 0, 1, &newVol);
1270 EGOTO1(mfail, vcode,
1271 "Could not get an ID for the clone of volume %u from the VLDB\n",
1275 /* Do the clone. Default flags on clone are set to delete on salvage and out of service */
1276 VPRINT1("Cloning source volume %u ...", afromvol);
1277 strcpy(vname, "move-clone-temp");
1279 AFSVolClone(fromconn, fromtid, 0, readonlyVolume, vname, &newVol);
1280 EGOTO1(mfail, code, "Failed to clone the source volume %u\n",
1285 /* lookup the name of the volume we just cloned */
1287 code = AFSVolGetName(fromconn, fromtid, &volName);
1288 EGOTO1(mfail, code, "Failed to get the name of the volume %u\n",
1291 VPRINT1("Ending the transaction on the source volume %u ...", afromvol);
1293 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1298 "Failed to end the transaction on the source volume %u\n",
1303 * Create the destination volume
1306 if (!(flags & RV_NOCLONE)) {
1307 /* All of this is to get the fromDate */
1308 VPRINT1("Starting transaction on the cloned volume %u ...", newVol);
1310 AFSVolTransCreate(fromconn, newVol, afrompart, ITOffline,
1313 "Failed to start a transaction on the cloned volume%u\n",
1317 VPRINT1("Setting flags on cloned volume %u ...", newVol);
1319 AFSVolSetFlags(fromconn, clonetid,
1320 VTDeleteOnSalvage | VTOutOfService); /*redundant */
1321 EGOTO1(mfail, code, "Could not set flags on the cloned volume %u\n",
1325 /* remember time from which we've dumped the volume */
1326 VPRINT1("Getting status of cloned volume %u ...", newVol);
1327 code = AFSVolGetStatus(fromconn, clonetid, &tstatus);
1329 "Failed to get the status of the cloned volume %u\n",
1333 fromDate = CLOCKADJ(tstatus.creationDate);
1335 /* With RV_NOCLONE, just do a full copy from the source */
1340 #ifdef ENABLE_BUGFIX_1165
1342 * Get the internal volume state from the source volume. We'll use such info (i.e. dayUse)
1343 * to copy it to the new volume (via AFSSetInfo later on) so that when we move volumes we
1344 * don't use this information...
1346 volumeInfo.volEntries_val = (volintInfo *) 0; /*this hints the stub to allocate space */
1347 volumeInfo.volEntries_len = 0;
1348 code = AFSVolListOneVolume(fromconn, afrompart, afromvol, &volumeInfo);
1350 "Failed to get the volint Info of the cloned volume %u\n",
1353 infop = (volintInfo *) volumeInfo.volEntries_val;
1354 infop->maxquota = -1; /* Else it will replace the default quota */
1355 infop->creationDate = -1; /* Else it will use the source creation date */
1356 infop->updateDate = -1; /* Else it will use the source update date */
1359 /* create a volume on the target machine */
1361 code = AFSVolTransCreate(toconn, volid, atopart, ITOffline, &totid);
1363 /* Delete the existing volume.
1364 * While we are deleting the volume in these steps, the transaction
1365 * we started against the cloned volume (clonetid above) will be
1366 * sitting idle. It will get cleaned up after 600 seconds
1368 VPRINT1("Deleting pre-existing volume %u on destination ...", volid);
1369 code = AFSVolDeleteVolume(toconn, totid);
1371 "Could not delete the pre-existing volume %u on destination\n",
1376 ("Ending transaction on pre-existing volume %u on destination ...",
1378 code = AFSVolEndTrans(toconn, totid, &rcode);
1383 "Could not end the transaction on pre-existing volume %u on destination\n",
1388 VPRINT1("Creating the destination volume %u ...", volid);
1390 AFSVolCreateVolume(toconn, atopart, volName, volser_RW, volid, &volid,
1392 EGOTO1(mfail, code, "Failed to create the destination volume %u\n",
1396 strncpy(tmpName, volName, VOLSER_OLDMAXVOLNAME);
1400 VPRINT1("Setting volume flags on destination volume %u ...", volid);
1402 AFSVolSetFlags(toconn, totid, (VTDeleteOnSalvage | VTOutOfService));
1404 "Failed to set the flags on the destination volume %u\n", volid);
1408 * Now dump the clone to the new volume
1411 destination.destHost = ntohl(atoserver);
1412 destination.destPort = AFSCONF_VOLUMEPORT;
1413 destination.destSSID = 1;
1415 strncpy(cookie.name, tmpName, VOLSER_OLDMAXVOLNAME);
1416 cookie.type = RWVOL;
1417 cookie.parent = entry.volumeId[RWVOL];
1420 if (!(flags & RV_NOCLONE)) {
1421 /* Copy the clone to the new volume */
1422 VPRINT2("Dumping from clone %u on source to volume %u on destination ...",
1425 AFSVolForward(fromconn, clonetid, 0, &destination, totid,
1427 EGOTO1(mfail, code, "Failed to move data for the volume %u\n", volid);
1430 VPRINT1("Ending transaction on cloned volume %u ...", newVol);
1431 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
1436 "Failed to end the transaction on the cloned volume %u\n",
1442 * reattach to the main-line volume, and incrementally dump it.
1445 VPRINT1("Starting transaction on source volume %u ...", afromvol);
1446 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
1448 "Failed to create a transaction on the source volume %u\n",
1452 /* now do the incremental */
1454 ("Doing the%s dump from source to destination for volume %u ... ",
1455 (flags & RV_NOCLONE) ? "" : " incremental",
1458 AFSVolForward(fromconn, fromtid, fromDate, &destination, totid,
1461 "Failed to do the%s dump from rw volume on old site to rw volume on newsite\n",
1462 (flags & RV_NOCLONE) ? "" : " incremental");
1465 /* now adjust the flags so that the new volume becomes official */
1466 VPRINT1("Setting volume flags on old source volume %u ...", afromvol);
1467 code = AFSVolSetFlags(fromconn, fromtid, VTOutOfService);
1469 "Failed to set the flags to make old source volume offline\n");
1472 VPRINT1("Setting volume flags on new source volume %u ...", afromvol);
1473 code = AFSVolSetFlags(toconn, totid, 0);
1475 "Failed to set the flags to make new source volume online\n");
1478 #ifdef ENABLE_BUGFIX_1165
1479 VPRINT1("Setting volume status on destination volume %u ...", volid);
1480 code = AFSVolSetInfo(toconn, totid, infop);
1482 "Failed to set volume status on the destination volume %u\n",
1487 /* put new volume online */
1488 VPRINT1("Ending transaction on destination volume %u ...", afromvol);
1489 code = AFSVolEndTrans(toconn, totid, &rcode);
1494 "Failed to end the transaction on the volume %u on the new site\n",
1498 Lp_SetRWValue(&entry, afromserver, afrompart, atoserver, atopart);
1499 MapNetworkToHost(&entry, &storeEntry);
1500 storeEntry.flags &= ~BACK_EXISTS;
1504 "Second test point - operation in progress but not complete.\n");
1505 fprintf(STDOUT, "...test here (y, n)? ");
1507 fscanf(stdin, "%c", &in);
1508 fscanf(stdin, "%c", &lf); /* toss away */
1510 fprintf(STDOUT, "type control-c\n");
1512 fprintf(stdout, ".");
1517 /* or drop through */
1520 VPRINT1("Releasing lock on VLDB entry for volume %u ...", afromvol);
1522 VLDB_ReplaceEntry(afromvol, -1, &storeEntry,
1523 (LOCKREL_OPCODE | LOCKREL_AFSID |
1524 LOCKREL_TIMESTAMP));
1527 " Could not release the lock on the VLDB entry for the volume %s %lu \n",
1528 storeEntry.name, (unsigned long)afromvol);
1537 "Third test point - operation complete but no cleanup.\n");
1538 fprintf(STDOUT, "...test here (y, n)? ");
1540 fscanf(stdin, "%c", &in);
1541 fscanf(stdin, "%c", &lf); /* toss away */
1543 fprintf(STDOUT, "type control-c\n");
1545 fprintf(stdout, ".");
1550 /* or drop through */
1553 /* This is tricky. File server is very stupid, and if you mark the volume
1554 * as VTOutOfService, it may mark the *good* instance (if you're moving
1555 * between partitions on the same machine) as out of service. Since
1556 * we're cleaning this code up in DEcorum, we're just going to kludge around
1557 * it for now by removing this call. */
1558 /* already out of service, just zap it now */
1560 AFSVolSetFlags(fromconn, fromtid, VTDeleteOnSalvage | VTOutOfService);
1563 "Failed to set the flags to make the old source volume offline\n");
1567 if (atoserver != afromserver) {
1568 /* set forwarding pointer for moved volumes */
1569 VPRINT1("Setting forwarding pointer for volume %u ...", afromvol);
1570 code = AFSVolSetForwarding(fromconn, fromtid, atoserver);
1572 "Failed to set the forwarding pointer for the volume %u\n",
1577 VPRINT1("Deleting old volume %u on source ...", afromvol);
1578 code = AFSVolDeleteVolume(fromconn, fromtid); /* zap original volume */
1579 EGOTO1(mfail, code, "Failed to delete the old volume %u on source\n",
1583 VPRINT1("Ending transaction on old volume %u on the source ...",
1585 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1590 "Failed to end the transaction on the old volume %u on the source\n",
1594 /* Delete the backup volume on the original site */
1595 VPRINT1("Creating transaction for backup volume %u on source ...",
1598 AFSVolTransCreate(fromconn, backupId, afrompart, ITOffline, &fromtid);
1601 VPRINT1("Setting flags on backup volume %u on source ...", backupId);
1603 AFSVolSetFlags(fromconn, fromtid,
1604 VTDeleteOnSalvage | VTOutOfService);
1606 "Failed to set the flags on the backup volume %u on the source\n",
1610 VPRINT1("Deleting the backup volume %u on the source ...", backupId);
1611 code = AFSVolDeleteVolume(fromconn, fromtid);
1613 "Failed to delete the backup volume %u on the source\n",
1617 VPRINT1("Ending transaction on backup volume %u on source ...",
1619 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1624 "Failed to end the transaction on the backup volume %u on the source\n",
1628 code = 0; /* no backup volume? that's okay */
1631 if (!(flags & RV_NOCLONE)) {
1632 VPRINT1("Starting transaction on the cloned volume %u ...", newVol);
1634 AFSVolTransCreate(fromconn, newVol, afrompart, ITOffline,
1637 "Failed to start a transaction on the cloned volume%u\n",
1641 /* now delete the clone */
1642 VPRINT1("Deleting the cloned volume %u ...", newVol);
1643 code = AFSVolDeleteVolume(fromconn, clonetid);
1644 EGOTO1(mfail, code, "Failed to delete the cloned volume %u\n",
1648 VPRINT1("Ending transaction on cloned volume %u ...", newVol);
1649 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
1654 "Failed to end the transaction on the cloned volume %u\n",
1663 fprintf(STDOUT, "Fourth test point - operation complete.\n");
1664 fprintf(STDOUT, "...test here (y, n)? ");
1666 fscanf(stdin, "%c", &in);
1667 fscanf(stdin, "%c", &lf); /* toss away */
1669 fprintf(STDOUT, "type control-c\n");
1671 fprintf(stdout, ".");
1676 /* or drop through */
1679 /* normal cleanup code */
1681 if (entry.flags & RO_EXISTS)
1682 fprintf(STDERR, "WARNING : readOnly copies still exist \n");
1685 VPRINT1("Cleanup: Releasing VLDB lock on volume %u ...", afromvol);
1687 ubik_Call(VL_ReleaseLock, cstruct, 0, afromvol, -1,
1688 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
1692 " Could not release the lock on the VLDB entry for the volume %lu \n",
1693 (unsigned long)afromvol);
1701 VPRINT1("Cleanup: Ending transaction on source volume %u ...",
1703 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
1704 if (code || rcode) {
1707 "Could not end transaction on the source volume %lu\n",
1708 (unsigned long)afromvol);
1710 error = (code ? code : rcode);
1716 VPRINT1("Cleanup: Ending transaction on clone volume %u ...", newVol);
1717 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
1718 if (code || rcode) {
1721 "Could not end transaction on the source's clone volume %lu\n",
1722 (unsigned long)newVol);
1724 error = (code ? code : rcode);
1730 VPRINT1("Cleanup: Ending transaction on destination volume %u ...",
1732 code = AFSVolEndTrans(toconn, totid, &rcode);
1736 "Could not end transaction on destination volume %lu\n",
1737 (unsigned long)afromvol);
1739 error = (code ? code : rcode);
1745 #ifdef ENABLE_BUGFIX_1165
1750 rx_DestroyConnection(fromconn);
1752 rx_DestroyConnection(toconn);
1753 PrintError("", error);
1756 /* come here only when the sky falls */
1761 "vos move: operation interrupted, cleanup in progress...\n");
1762 fprintf(STDOUT, "clear transaction contexts\n");
1766 /* unlock VLDB entry */
1768 VPRINT1("Recovery: Releasing VLDB lock on volume %u ...", afromvol);
1769 ubik_Call(VL_ReleaseLock, cstruct, 0, afromvol, -1,
1770 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
1775 VPRINT("Recovery: Ending transaction on clone volume ...");
1776 AFSVolEndTrans(fromconn, clonetid, &rcode);
1780 VPRINT("Recovery: Ending transaction on destination volume ...");
1781 AFSVolEndTrans(toconn, totid, &rcode);
1784 if (fromtid) { /* put it on-line */
1785 VPRINT("Recovery: Setting volume flags on source volume ...");
1786 AFSVolSetFlags(fromconn, fromtid, 0);
1789 VPRINT("Recovery: Ending transaction on source volume ...");
1790 AFSVolEndTrans(fromconn, fromtid, &rcode);
1794 VPRINT("Recovery: Accessing VLDB.\n");
1795 vcode = VLDB_GetEntryByID(afromvol, -1, &entry);
1797 fprintf(STDOUT, "FATAL: VLDB access error: abort cleanup\n");
1801 MapHostToNetwork(&entry);
1803 /* Delete either the volume on the source location or the target location.
1804 * If the vldb entry still points to the source location, then we know the
1805 * volume move didn't finish so we remove the volume from the target
1806 * location. Otherwise, we remove the volume from the source location.
1808 if (Lp_Match(afromserver, afrompart, &entry)) { /* didn't move - delete target volume */
1811 "move incomplete - attempt cleanup of target partition - no guarantee\n");
1815 if (volid && toconn) {
1817 ("Recovery: Creating transaction for destination volume %u ...",
1820 AFSVolTransCreate(toconn, volid, atopart, ITOffline, &totid);
1826 ("Recovery: Setting flags on destination volume %u ...",
1828 AFSVolSetFlags(toconn, totid,
1829 VTDeleteOnSalvage | VTOutOfService);
1832 VPRINT1("Recovery: Deleting destination volume %u ...",
1834 AFSVolDeleteVolume(toconn, totid);
1838 ("Recovery: Ending transaction on destination volume %u ...",
1840 AFSVolEndTrans(toconn, totid, &rcode);
1844 ("\nRecovery: Unable to start transaction on destination volume %u.\n",
1849 /* put source volume on-line */
1851 VPRINT1("Recovery: Creating transaction on source volume %u ...",
1854 AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy,
1859 VPRINT1("Recovery: Setting flags on source volume %u ...",
1861 AFSVolSetFlags(fromconn, fromtid, 0);
1865 ("Recovery: Ending transaction on source volume %u ...",
1867 AFSVolEndTrans(fromconn, fromtid, &rcode);
1871 ("\nRecovery: Unable to start transaction on source volume %u.\n",
1875 } else { /* yep, move complete */
1878 "move complete - attempt cleanup of source partition - no guarantee\n");
1882 /* delete backup volume */
1884 VPRINT1("Recovery: Creating transaction on backup volume %u ...",
1887 AFSVolTransCreate(fromconn, backupId, afrompart, ITOffline,
1892 VPRINT1("Recovery: Setting flags on backup volume %u ...",
1894 AFSVolSetFlags(fromconn, fromtid,
1895 VTDeleteOnSalvage | VTOutOfService);
1898 VPRINT1("Recovery: Deleting backup volume %u ...", backupId);
1899 AFSVolDeleteVolume(fromconn, fromtid);
1903 ("Recovery: Ending transaction on backup volume %u ...",
1905 AFSVolEndTrans(fromconn, fromtid, &rcode);
1909 ("\nRecovery: Unable to start transaction on backup volume %u.\n",
1913 /* delete source volume */
1914 VPRINT1("Recovery: Creating transaction on source volume %u ...",
1917 AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy,
1922 VPRINT1("Recovery: Setting flags on backup volume %u ...",
1924 AFSVolSetFlags(fromconn, fromtid,
1925 VTDeleteOnSalvage | VTOutOfService);
1928 if (atoserver != afromserver) {
1929 VPRINT("Recovery: Setting volume forwarding pointer ...");
1930 AFSVolSetForwarding(fromconn, fromtid, atoserver);
1934 VPRINT1("Recovery: Deleting source volume %u ...", afromvol);
1935 AFSVolDeleteVolume(fromconn, fromtid);
1939 ("Recovery: Ending transaction on source volume %u ...",
1941 AFSVolEndTrans(fromconn, fromtid, &rcode);
1945 ("\nRecovery: Unable to start transaction on source volume %u.\n",
1951 /* common cleanup - delete local clone */
1953 VPRINT1("Recovery: Creating transaction on clone volume %u ...",
1956 AFSVolTransCreate(fromconn, newVol, afrompart, ITOffline,
1961 VPRINT1("Recovery: Deleting clone volume %u ...", newVol);
1962 AFSVolDeleteVolume(fromconn, clonetid);
1965 VPRINT1("Recovery: Ending transaction on clone volume %u ...",
1967 AFSVolEndTrans(fromconn, clonetid, &rcode);
1971 ("\nRecovery: Unable to start transaction on source volume %u.\n",
1976 /* unlock VLDB entry */
1977 VPRINT1("Recovery: Releasing lock on VLDB entry for volume %u ...",
1979 ubik_Call(VL_ReleaseLock, cstruct, 0, afromvol, -1,
1980 (LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP));
1983 done: /* routine cleanup */
1986 #ifdef ENABLE_BUGFIX_1165
1991 rx_DestroyConnection(fromconn);
1993 rx_DestroyConnection(toconn);
1996 fprintf(STDOUT, "cleanup complete - user verify desired result\n");
2004 UV_MoveVolume(afs_int32 afromvol, afs_int32 afromserver, afs_int32 afrompart,
2005 afs_int32 atoserver, afs_int32 atopart)
2007 return UV_MoveVolume2(afromvol, afromserver, afrompart,
2008 atoserver, atopart, 0);
2012 /* Copy volume <afromvol> from <afromserver> <afrompart> to <atoserver>
2013 * <atopart>. The new volume is named by <atovolname>. The new volume
2014 * has ID <atovolid> if that is nonzero; otherwise a new ID is allocated
2015 * from the VLDB. the following flags are supported:
2017 * RV_RDONLY - target volume is RO
2018 * RV_OFFLINE - leave target volume offline
2019 * RV_CPINCR - do incremental dump if target exists
2020 * RV_NOVLDB - don't create/update VLDB entry
2021 * RV_NOCLONE - don't use a copy clone
2024 UV_CopyVolume2(afs_int32 afromvol, afs_int32 afromserver, afs_int32 afrompart,
2025 char *atovolname, afs_int32 atoserver, afs_int32 atopart,
2026 afs_int32 atovolid, int flags)
2028 struct rx_connection *toconn, *fromconn;
2029 afs_int32 fromtid, totid, clonetid;
2032 afs_int32 fromDate, cloneFromDate;
2033 struct restoreCookie cookie;
2034 register afs_int32 vcode, code;
2035 afs_int32 cloneVol, newVol, volflag;
2036 struct volser_status tstatus;
2037 struct destServer destination;
2039 struct nvldbentry entry, newentry, storeEntry;
2045 fromconn = (struct rx_connection *)0;
2046 toconn = (struct rx_connection *)0;
2054 /* support control-c processing */
2057 (void)signal(SIGINT, sigint_handler);
2059 vcode = VLDB_GetEntryByID(afromvol, -1, &entry);
2060 EGOTO1(mfail, vcode,
2061 "Could not fetch the entry for the volume %u from the VLDB \n",
2063 MapHostToNetwork(&entry);
2066 toconn = UV_Bind(atoserver, AFSCONF_VOLUMEPORT); /* get connections to the servers */
2067 fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
2068 fromtid = totid = 0; /* initialize to uncreated */
2071 /* check if we can shortcut and use a local clone instead of a full copy */
2072 if (afromserver == atoserver && afrompart == atopart) {
2077 * clone the read/write volume locally.
2081 if (!(flags & RV_NOCLONE)) {
2082 VPRINT1("Starting transaction on source volume %u ...", afromvol);
2083 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy,
2085 EGOTO1(mfail, code, "Failed to create transaction on the volume %u\n",
2089 /* Get a clone id */
2090 VPRINT1("Allocating new volume id for clone of volume %u ...",
2093 vcode = ubik_Call(VL_GetNewVolumeId, cstruct, 0, 1, &cloneVol);
2094 EGOTO1(mfail, vcode,
2095 "Could not get an ID for the clone of volume %u from the VLDB\n",
2103 /* Get a new volume id */
2104 VPRINT1("Allocating new volume id for copy of volume %u ...", afromvol);
2106 vcode = ubik_Call(VL_GetNewVolumeId, cstruct, 0, 1, &newVol);
2107 EGOTO1(mfail, vcode,
2108 "Could not get an ID for the copy of volume %u from the VLDB\n",
2113 if (!(flags & RV_NOCLONE)) {
2114 /* Do the clone. Default flags on clone are set to delete on salvage and out of service */
2115 VPRINT1("Cloning source volume %u ...", afromvol);
2116 strcpy(vname, "copy-clone-temp");
2118 AFSVolClone(fromconn, fromtid, 0, readonlyVolume, vname,
2120 EGOTO1(mfail, code, "Failed to clone the source volume %u\n",
2124 VPRINT1("Ending the transaction on the source volume %u ...", afromvol);
2126 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
2131 "Failed to end the transaction on the source volume %u\n",
2137 * Create the destination volume
2140 if (!(flags & RV_NOCLONE)) {
2141 VPRINT1("Starting transaction on the cloned volume %u ...", cloneVol);
2143 AFSVolTransCreate(fromconn, cloneVol, afrompart, ITOffline,
2146 "Failed to start a transaction on the cloned volume%u\n",
2150 VPRINT1("Setting flags on cloned volume %u ...", cloneVol);
2152 AFSVolSetFlags(fromconn, clonetid,
2153 VTDeleteOnSalvage | VTOutOfService); /*redundant */
2154 EGOTO1(mfail, code, "Could not set flags on the cloned volume %u\n",
2158 /* remember time from which we've dumped the volume */
2159 VPRINT1("Getting status of cloned volume %u ...", cloneVol);
2160 code = AFSVolGetStatus(fromconn, clonetid, &tstatus);
2162 "Failed to get the status of the cloned volume %u\n",
2166 fromDate = CLOCKADJ(tstatus.creationDate);
2171 /* create a volume on the target machine */
2173 code = AFSVolTransCreate(toconn, newVol, atopart, ITOffline, &totid);
2175 if ((flags & RV_CPINCR)) {
2176 VPRINT1("Getting status of pre-existing volume %u ...", newVol);
2177 code = AFSVolGetStatus(toconn, totid, &tstatus);
2179 "Failed to get the status of the pre-existing volume %u\n",
2183 /* Using the update date should be OK here, but add some fudge */
2184 cloneFromDate = CLOCKADJ(tstatus.updateDate);
2185 if ((flags & RV_NOCLONE))
2186 fromDate = cloneFromDate;
2188 /* XXX We should check that the source volume's creationDate is
2189 * XXX not newer than the existing target volume, and if not,
2190 * XXX throw away the existing target and do a full dump. */
2195 /* Delete the existing volume.
2196 * While we are deleting the volume in these steps, the transaction
2197 * we started against the cloned volume (clonetid above) will be
2198 * sitting idle. It will get cleaned up after 600 seconds
2200 VPRINT1("Deleting pre-existing volume %u on destination ...", newVol);
2201 code = AFSVolDeleteVolume(toconn, totid);
2203 "Could not delete the pre-existing volume %u on destination\n",
2208 ("Ending transaction on pre-existing volume %u on destination ...",
2210 code = AFSVolEndTrans(toconn, totid, &rcode);
2215 "Could not end the transaction on pre-existing volume %u on destination\n",
2220 VPRINT1("Creating the destination volume %u ...", newVol);
2222 AFSVolCreateVolume(toconn, atopart, atovolname,
2223 (flags & RV_RDONLY) ? volser_RO : volser_RW,
2224 newVol, &newVol, &totid);
2225 EGOTO1(mfail, code, "Failed to create the destination volume %u\n",
2229 VPRINT1("Setting volume flags on destination volume %u ...", newVol);
2231 AFSVolSetFlags(toconn, totid, (VTDeleteOnSalvage | VTOutOfService));
2233 "Failed to set the flags on the destination volume %u\n", newVol);
2238 destination.destHost = ntohl(atoserver);
2239 destination.destPort = AFSCONF_VOLUMEPORT;
2240 destination.destSSID = 1;
2242 strncpy(cookie.name, atovolname, VOLSER_OLDMAXVOLNAME);
2243 cookie.type = (flags & RV_RDONLY) ? ROVOL : RWVOL;
2248 * Now dump the clone to the new volume
2251 if (!(flags & RV_NOCLONE)) {
2252 /* XXX probably should have some code here that checks to see if
2253 * XXX we are copying to same server and partition - if so, just
2254 * XXX use a clone to save disk space */
2256 /* Copy the clone to the new volume */
2257 VPRINT2("Dumping from clone %u on source to volume %u on destination ...",
2260 AFSVolForward(fromconn, clonetid, cloneFromDate, &destination,
2262 EGOTO1(mfail, code, "Failed to move data for the volume %u\n",
2266 VPRINT1("Ending transaction on cloned volume %u ...", cloneVol);
2267 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
2272 "Failed to end the transaction on the cloned volume %u\n",
2278 * reattach to the main-line volume, and incrementally dump it.
2281 VPRINT1("Starting transaction on source volume %u ...", afromvol);
2282 code = AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy, &fromtid);
2284 "Failed to create a transaction on the source volume %u\n",
2288 /* now do the incremental */
2290 ("Doing the%s dump from source to destination for volume %u ... ",
2291 (flags & RV_NOCLONE) ? "" : " incremental",
2294 AFSVolForward(fromconn, fromtid, fromDate, &destination, totid,
2297 "Failed to do the%s dump from old site to new site\n",
2301 VPRINT1("Setting volume flags on destination volume %u ...", newVol);
2302 volflag = ((flags & RV_OFFLINE) ? VTOutOfService : 0); /* off or on-line */
2303 code = AFSVolSetFlags(toconn, totid, volflag);
2305 "Failed to set the flags to make destination volume online\n");
2308 /* put new volume online */
2309 VPRINT1("Ending transaction on destination volume %u ...", newVol);
2310 code = AFSVolEndTrans(toconn, totid, &rcode);
2315 "Failed to end the transaction on the destination volume %u\n",
2319 VPRINT1("Ending transaction on source volume %u ...", afromvol);
2320 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
2325 "Failed to end the transaction on the source volume %u\n",
2331 if (!(flags & RV_NOCLONE)) {
2332 VPRINT1("Starting transaction on the cloned volume %u ...", cloneVol);
2334 AFSVolTransCreate(fromconn, cloneVol, afrompart, ITOffline,
2337 "Failed to start a transaction on the cloned volume%u\n",
2341 /* now delete the clone */
2342 VPRINT1("Deleting the cloned volume %u ...", cloneVol);
2343 code = AFSVolDeleteVolume(fromconn, clonetid);
2344 EGOTO1(mfail, code, "Failed to delete the cloned volume %u\n",
2348 VPRINT1("Ending transaction on cloned volume %u ...", cloneVol);
2349 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
2354 "Failed to end the transaction on the cloned volume %u\n",
2359 if (!(flags & RV_NOVLDB)) {
2360 /* create the vldb entry for the copied volume */
2361 strncpy(newentry.name, atovolname, VOLSER_OLDMAXVOLNAME);
2362 newentry.nServers = 1;
2363 newentry.serverNumber[0] = atoserver;
2364 newentry.serverPartition[0] = atopart;
2365 newentry.flags = (flags & RV_RDONLY) ? RO_EXISTS : RW_EXISTS;
2366 newentry.serverFlags[0] = (flags & RV_RDONLY) ? ITSROVOL : ITSRWVOL;
2367 newentry.volumeId[RWVOL] = newVol;
2368 newentry.volumeId[ROVOL] = (flags & RV_RDONLY) ? newVol : 0;
2369 newentry.volumeId[BACKVOL] = 0;
2370 newentry.cloneId = 0;
2371 /*map into right byte order, before passing to xdr, the stuff has to be in host
2372 * byte order. Xdr converts it into network order */
2373 MapNetworkToHost(&newentry, &storeEntry);
2374 /* create the vldb entry */
2375 vcode = VLDB_CreateEntry(&storeEntry);
2378 "Could not create a VLDB entry for the volume %s %lu\n",
2379 atovolname, (unsigned long)newVol);
2380 /*destroy the created volume */
2381 VPRINT1("Deleting the newly created volume %u\n", newVol);
2382 AFSVolDeleteVolume(toconn, totid);
2386 VPRINT2("Created the VLDB entry for the volume %s %u\n", atovolname,
2390 /* normal cleanup code */
2393 VPRINT1("Cleanup: Ending transaction on source volume %u ...",
2395 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
2396 if (code || rcode) {
2399 "Could not end transaction on the source volume %lu\n",
2400 (unsigned long)afromvol);
2402 error = (code ? code : rcode);
2408 VPRINT1("Cleanup: Ending transaction on clone volume %u ...",
2410 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
2411 if (code || rcode) {
2414 "Could not end transaction on the source's clone volume %lu\n",
2415 (unsigned long)cloneVol);
2417 error = (code ? code : rcode);
2423 VPRINT1("Cleanup: Ending transaction on destination volume %u ...",
2425 code = AFSVolEndTrans(toconn, totid, &rcode);
2429 "Could not end transaction on destination volume %lu\n",
2430 (unsigned long)newVol);
2432 error = (code ? code : rcode);
2437 rx_DestroyConnection(fromconn);
2439 rx_DestroyConnection(toconn);
2440 PrintError("", error);
2443 /* come here only when the sky falls */
2448 "vos copy: operation interrupted, cleanup in progress...\n");
2449 fprintf(STDOUT, "clear transaction contexts\n");
2454 VPRINT("Recovery: Ending transaction on clone volume ...");
2455 AFSVolEndTrans(fromconn, clonetid, &rcode);
2459 VPRINT("Recovery: Ending transaction on destination volume ...");
2460 AFSVolEndTrans(toconn, totid, &rcode);
2463 if (fromtid) { /* put it on-line */
2464 VPRINT("Recovery: Ending transaction on source volume ...");
2465 AFSVolEndTrans(fromconn, fromtid, &rcode);
2469 VPRINT("Recovery: Accessing VLDB.\n");
2470 vcode = VLDB_GetEntryByID(afromvol, -1, &entry);
2472 fprintf(STDOUT, "FATAL: VLDB access error: abort cleanup\n");
2476 MapHostToNetwork(&entry);
2478 /* common cleanup - delete local clone */
2480 VPRINT1("Recovery: Creating transaction on clone volume %u ...",
2483 AFSVolTransCreate(fromconn, newVol, afrompart, ITOffline,
2488 VPRINT1("Recovery: Deleting clone volume %u ...", cloneVol);
2489 AFSVolDeleteVolume(fromconn, clonetid);
2492 VPRINT1("Recovery: Ending transaction on clone volume %u ...",
2494 AFSVolEndTrans(fromconn, clonetid, &rcode);
2498 ("\nRecovery: Unable to start transaction on clone volume %u.\n",
2503 done: /* routine cleanup */
2505 rx_DestroyConnection(fromconn);
2507 rx_DestroyConnection(toconn);
2510 fprintf(STDOUT, "cleanup complete - user verify desired result\n");
2518 UV_CopyVolume(afs_int32 afromvol, afs_int32 afromserver, afs_int32 afrompart,
2519 char *atovolname, afs_int32 atoserver, afs_int32 atopart)
2521 return UV_CopyVolume2(afromvol, afromserver, afrompart,
2522 atovolname, atoserver, atopart, 0, 0);
2527 /* Make a new backup of volume <avolid> on <aserver> and <apart>
2528 * if one already exists, update it
2532 UV_BackupVolume(afs_int32 aserver, afs_int32 apart, afs_int32 avolid)
2534 struct rx_connection *aconn = (struct rx_connection *)0;
2535 afs_int32 ttid = 0, btid = 0;
2537 afs_int32 code = 0, rcode = 0;
2538 char vname[VOLSER_MAXVOLNAME + 1];
2539 struct nvldbentry entry, storeEntry;
2540 afs_int32 error = 0;
2541 int vldblocked = 0, vldbmod = 0, backexists = 1;
2543 aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
2545 /* the calls to VLDB will succeed only if avolid is a RW volume,
2546 * since we are following the RW hash chain for searching */
2547 code = VLDB_GetEntryByID(avolid, RWVOL, &entry);
2550 "Could not fetch the entry for the volume %lu from the VLDB \n",
2551 (unsigned long)avolid);
2555 MapHostToNetwork(&entry);
2557 /* These operations require the VLDB be locked since it means the VLDB
2558 * will change or the vldb is already locked.
2560 if (!(entry.flags & BACK_EXISTS) || /* backup volume doesnt exist */
2561 (entry.flags & VLOP_ALLOPERS) || /* vldb lock already held */
2562 (entry.volumeId[BACKVOL] == INVALID_BID)) { /* no assigned backup volume id */
2564 code = ubik_Call(VL_SetLock, cstruct, 0, avolid, RWVOL, VLOP_BACKUP);
2567 "Could not lock the VLDB entry for the volume %lu\n",
2568 (unsigned long)avolid);
2574 /* Reread the vldb entry */
2575 code = VLDB_GetEntryByID(avolid, RWVOL, &entry);
2578 "Could not fetch the entry for the volume %lu from the VLDB \n",
2579 (unsigned long)avolid);
2583 MapHostToNetwork(&entry);
2586 if (!ISNAMEVALID(entry.name)) {
2587 fprintf(STDERR, "Name of the volume %s exceeds the size limit\n",
2589 error = VOLSERBADNAME;
2593 backupID = entry.volumeId[BACKVOL];
2594 if (backupID == INVALID_BID) {
2595 /* Get a backup volume id from the VLDB and update the vldb
2598 code = ubik_Call(VL_GetNewVolumeId, cstruct, 0, 1, &backupID);
2601 "Could not allocate ID for the backup volume of %lu from the VLDB\n",
2602 (unsigned long)avolid);
2606 entry.volumeId[BACKVOL] = backupID;
2610 /* Test to see if the backup volume exists by trying to create
2611 * a transaction on the backup volume. We've assumed the backup exists.
2613 code = AFSVolTransCreate(aconn, backupID, apart, ITOffline, &btid);
2615 if (code != VNOVOL) {
2616 fprintf(STDERR, "Could not reach the backup volume %lu\n",
2617 (unsigned long)backupID);
2621 backexists = 0; /* backup volume does not exist */
2624 code = AFSVolEndTrans(aconn, btid, &rcode);
2626 if (code || rcode) {
2628 "Could not end transaction on the previous backup volume %lu\n",
2629 (unsigned long)backupID);
2630 error = (code ? code : rcode);
2635 /* Now go ahead and try to clone the RW volume.
2636 * First start a transaction on the RW volume
2638 code = AFSVolTransCreate(aconn, avolid, apart, ITBusy, &ttid);
2640 fprintf(STDERR, "Could not start a transaction on the volume %lu\n",
2641 (unsigned long)avolid);
2646 /* Clone or reclone the volume, depending on whether the backup
2647 * volume exists or not
2650 VPRINT1("Re-cloning backup volume %u ...", backupID);
2652 code = AFSVolReClone(aconn, ttid, backupID);
2654 fprintf(STDERR, "Could not re-clone backup volume %lu\n",
2655 (unsigned long)backupID);
2660 VPRINT1("Creating a new backup clone %u ...", backupID);
2662 strcpy(vname, entry.name);
2663 strcat(vname, ".backup");
2665 code = AFSVolClone(aconn, ttid, 0, backupVolume, vname, &backupID);
2667 fprintf(STDERR, "Failed to clone the volume %lu\n",
2668 (unsigned long)avolid);
2674 /* End the transaction on the RW volume */
2675 code = AFSVolEndTrans(aconn, ttid, &rcode);
2677 if (code || rcode) {
2679 "Failed to end the transaction on the rw volume %lu\n",
2680 (unsigned long)avolid);
2681 error = (code ? code : rcode);
2685 /* Mork vldb as backup exists */
2686 if (!(entry.flags & BACK_EXISTS)) {
2687 entry.flags |= BACK_EXISTS;
2691 /* Now go back to the backup volume and bring it on line */
2692 code = AFSVolTransCreate(aconn, backupID, apart, ITOffline, &btid);
2695 "Failed to start a transaction on the backup volume %lu\n",
2696 (unsigned long)backupID);
2701 code = AFSVolSetFlags(aconn, btid, 0);
2703 fprintf(STDERR, "Could not mark the backup volume %lu on line \n",
2704 (unsigned long)backupID);
2709 code = AFSVolEndTrans(aconn, btid, &rcode);
2711 if (code || rcode) {
2713 "Failed to end the transaction on the backup volume %lu\n",
2714 (unsigned long)backupID);
2715 error = (code ? code : rcode);
2721 /* Will update the vldb below */
2725 code = AFSVolEndTrans(aconn, ttid, &rcode);
2726 if (code || rcode) {
2727 fprintf(STDERR, "Could not end transaction on the volume %lu\n",
2728 (unsigned long)avolid);
2730 error = (code ? code : rcode);
2735 code = AFSVolEndTrans(aconn, btid, &rcode);
2736 if (code || rcode) {
2738 "Could not end transaction the backup volume %lu\n",
2739 (unsigned long)backupID);
2741 error = (code ? code : rcode);
2745 /* Now update the vldb - if modified */
2748 MapNetworkToHost(&entry, &storeEntry);
2750 VLDB_ReplaceEntry(avolid, RWVOL, &storeEntry,
2751 (LOCKREL_OPCODE | LOCKREL_AFSID |
2752 LOCKREL_TIMESTAMP));
2755 "Could not update the VLDB entry for the volume %lu \n",
2756 (unsigned long)avolid);
2762 ubik_Call(VL_ReleaseLock, cstruct, 0, avolid, RWVOL,
2763 (LOCKREL_OPCODE | LOCKREL_AFSID |
2764 LOCKREL_TIMESTAMP));
2767 "Could not unlock the VLDB entry for the volume %lu \n",
2768 (unsigned long)avolid);
2776 rx_DestroyConnection(aconn);
2778 PrintError("", error);
2782 /* Make a new clone of volume <avolid> on <aserver> and <apart>
2783 * using volume ID <acloneid>, or a new ID allocated from the VLDB.
2784 * The new volume is named by <aname>, or by appending ".clone" to
2785 * the existing name if <aname> is NULL. The following flags are
2788 * RV_RDONLY - target volume is RO
2789 * RV_OFFLINE - leave target volume offline
2793 UV_CloneVolume(afs_int32 aserver, afs_int32 apart, afs_int32 avolid,
2794 afs_int32 acloneid, char *aname, int flags)
2796 struct rx_connection *aconn = (struct rx_connection *)0;
2797 afs_int32 ttid = 0, btid = 0;
2798 afs_int32 code = 0, rcode = 0;
2799 char vname[VOLSER_MAXVOLNAME + 1];
2800 afs_int32 error = 0;
2802 volEntries volumeInfo;
2804 aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT);
2807 volumeInfo.volEntries_val = (volintInfo *) 0;
2808 volumeInfo.volEntries_len = 0;
2809 code = AFSVolListOneVolume(aconn, apart, avolid, &volumeInfo);
2811 fprintf(stderr, "Could not get info for volume %lu\n",
2812 (unsigned long)avolid);
2816 strncpy(vname, volumeInfo.volEntries_val[0].name,
2817 VOLSER_OLDMAXVOLNAME - 7);
2818 vname[VOLSER_OLDMAXVOLNAME - 7] = 0;
2819 strcat(vname, ".clone");
2821 if (volumeInfo.volEntries_val)
2822 free(volumeInfo.volEntries_val);
2826 /* Get a clone id */
2827 VPRINT1("Allocating new volume id for clone of volume %u ...",
2829 code = ubik_Call(VL_GetNewVolumeId, cstruct, 0, 1, &acloneid);
2831 "Could not get an ID for the clone of volume %u from the VLDB\n",
2836 /* Test to see if the clone volume exists by trying to create
2837 * a transaction on the clone volume. We've assumed the clone exists.
2839 /* XXX I wonder what happens if the clone has some other parent... */
2840 code = AFSVolTransCreate(aconn, acloneid, apart, ITOffline, &btid);
2842 if (code != VNOVOL) {
2843 fprintf(STDERR, "Could not reach the clone volume %lu\n",
2844 (unsigned long)acloneid);
2848 backexists = 0; /* backup volume does not exist */
2851 code = AFSVolEndTrans(aconn, btid, &rcode);
2853 if (code || rcode) {
2855 "Could not end transaction on the previous clone volume %lu\n",
2856 (unsigned long)acloneid);
2857 error = (code ? code : rcode);
2862 /* Now go ahead and try to clone the RW volume.
2863 * First start a transaction on the RW volume
2865 code = AFSVolTransCreate(aconn, avolid, apart, ITBusy, &ttid);
2867 fprintf(STDERR, "Could not start a transaction on the volume %lu\n",
2868 (unsigned long)avolid);
2873 /* Clone or reclone the volume, depending on whether the backup
2874 * volume exists or not
2877 VPRINT1("Re-cloning clone volume %u ...", acloneid);
2879 code = AFSVolReClone(aconn, ttid, acloneid);
2881 fprintf(STDERR, "Could not re-clone backup volume %lu\n",
2882 (unsigned long)acloneid);
2887 VPRINT1("Creating a new clone %u ...", acloneid);
2889 code = AFSVolClone(aconn, ttid, 0,
2890 (flags & RV_RDONLY) ? readonlyVolume : backupVolume,
2893 fprintf(STDERR, "Failed to clone the volume %lu\n",
2894 (unsigned long)avolid);
2900 /* End the transaction on the RW volume */
2901 code = AFSVolEndTrans(aconn, ttid, &rcode);
2903 if (code || rcode) {
2905 "Failed to end the transaction on the rw volume %lu\n",
2906 (unsigned long)avolid);
2907 error = (code ? code : rcode);
2911 /* Now go back to the backup volume and bring it on line */
2912 if (!(flags & RV_OFFLINE)) {
2913 code = AFSVolTransCreate(aconn, acloneid, apart, ITOffline, &btid);
2916 "Failed to start a transaction on the clone volume %lu\n",
2917 (unsigned long)acloneid);
2922 code = AFSVolSetFlags(aconn, btid, 0);
2924 fprintf(STDERR, "Could not mark the clone volume %lu on line \n",
2925 (unsigned long)acloneid);
2930 code = AFSVolEndTrans(aconn, btid, &rcode);
2932 if (code || rcode) {
2934 "Failed to end the transaction on the clone volume %lu\n",
2935 (unsigned long)acloneid);
2936 error = (code ? code : rcode);
2945 code = AFSVolEndTrans(aconn, ttid, &rcode);
2946 if (code || rcode) {
2947 fprintf(STDERR, "Could not end transaction on the volume %lu\n",
2948 (unsigned long)avolid);
2950 error = (code ? code : rcode);
2955 code = AFSVolEndTrans(aconn, btid, &rcode);
2956 if (code || rcode) {
2958 "Could not end transaction on the clone volume %lu\n",
2959 (unsigned long)acloneid);
2961 error = (code ? code : rcode);
2966 rx_DestroyConnection(aconn);
2968 PrintError("", error);
2973 DelVol(struct rx_connection *conn, afs_int32 vid, afs_int32 part,
2976 afs_int32 acode, ccode, rcode, tid;
2977 ccode = rcode = tid = 0;
2979 acode = AFSVolTransCreate(conn, vid, part, flags, &tid);
2980 if (!acode) { /* It really was there */
2981 acode = AFSVolDeleteVolume(conn, tid);
2983 fprintf(STDERR, "Failed to delete volume %lu.\n",
2984 (unsigned long)vid);
2985 PrintError("", acode);
2987 ccode = AFSVolEndTrans(conn, tid, &rcode);
2991 fprintf(STDERR, "Failed to end transaction on volume %lu.\n",
2992 (unsigned long)vid);
2993 PrintError("", ccode);
3000 #define ONERROR(ec, ep, es) if (ec) { fprintf(STDERR, (es), (ep)); error = (ec); goto rfail; }
3001 #define ERROREXIT(ec) { error = (ec); goto rfail; }
3003 /* Get a "transaction" on this replica. Create the volume
3004 * if necessary. Return the time from which a dump should
3005 * be made (0 if it's a new volume)
3008 GetTrans(struct nvldbentry *vldbEntryPtr, afs_int32 index,
3009 struct rx_connection **connPtr, afs_int32 * transPtr,
3010 afs_int32 * crtimePtr, afs_int32 * uptimePtr)
3013 struct volser_status tstatus;
3014 int code, rcode, tcode;
3016 *connPtr = (struct rx_connection *)0;
3021 /* get connection to the replication site */
3022 *connPtr = UV_Bind(vldbEntryPtr->serverNumber[index], AFSCONF_VOLUMEPORT);
3024 goto fail; /* server is down */
3026 volid = vldbEntryPtr->volumeId[ROVOL];
3029 AFSVolTransCreate(*connPtr, volid,
3030 vldbEntryPtr->serverPartition[index], ITOffline,
3033 /* If the volume does not exist, create it */
3034 if (!volid || code) {
3037 if (volid && (code != VNOVOL)) {
3038 PrintError("Failed to start a transaction on the RO volume.\n",
3043 strcpy(volname, vldbEntryPtr->name);
3044 strcat(volname, ".readonly");
3048 "Creating new volume %lu on replication site %s: ",
3049 (unsigned long)volid,
3050 hostutil_GetNameByINet(vldbEntryPtr->
3051 serverNumber[index]));
3056 AFSVolCreateVolume(*connPtr, vldbEntryPtr->serverPartition[index],
3058 vldbEntryPtr->volumeId[RWVOL], &volid,
3061 PrintError("Failed to create the ro volume: ", code);
3064 vldbEntryPtr->volumeId[ROVOL] = volid;
3068 /* The following is a bit redundant, since create sets these flags by default */
3070 AFSVolSetFlags(*connPtr, *transPtr,
3071 VTDeleteOnSalvage | VTOutOfService);
3073 PrintError("Failed to set flags on the ro volume: ", code);
3078 /* Otherwise, the transaction did succeed, so get the creation date of the
3079 * latest RO volume on the replication site
3082 VPRINT2("Updating existing ro volume %u on %s ...\n", volid,
3083 hostutil_GetNameByINet(vldbEntryPtr->serverNumber[index]));
3085 code = AFSVolGetStatus(*connPtr, *transPtr, &tstatus);
3087 PrintError("Failed to get status of volume on destination: ",
3091 *crtimePtr = CLOCKADJ(tstatus.creationDate);
3092 *uptimePtr = CLOCKADJ(tstatus.updateDate);
3099 tcode = AFSVolEndTrans(*connPtr, *transPtr, &rcode);
3104 PrintError("Could not end transaction on a ro volume: ", tcode);
3111 SimulateForwardMultiple(struct rx_connection *fromconn, afs_int32 fromtid,
3112 afs_int32 fromdate, manyDests * tr, afs_int32 flags,
3113 void *cookie, manyResults * results)
3117 for (i = 0; i < tr->manyDests_len; i++) {
3118 results->manyResults_val[i] =
3119 AFSVolForward(fromconn, fromtid, fromdate,
3120 &(tr->manyDests_val[i].server),
3121 tr->manyDests_val[i].trans, cookie);
3127 /* UV_ReleaseVolume()
3128 * Release volume <afromvol> on <afromserver> <afrompart> to all
3129 * its RO sites (full release). Unless the previous release was
3130 * incomplete: in which case we bring the remaining incomplete
3131 * volumes up to date with the volumes that were released
3133 * forceflag: Performs a full release.
3135 * Will create a clone from the RW, then dump the clone out to
3136 * the remaining replicas. If there is more than 1 RO sites,
3137 * ensure that the VLDB says at least one RO is available all
3138 * the time: Influences when we write back the VLDB entry.
3142 UV_ReleaseVolume(afs_int32 afromvol, afs_int32 afromserver,
3143 afs_int32 afrompart, int forceflag)
3146 afs_int32 code, vcode, rcode, tcode;
3147 afs_int32 cloneVolId, roVolId;
3148 struct replica *replicas = 0;
3149 struct nvldbentry entry, storeEntry;
3150 int i, volcount, m, fullrelease, vldbindex;
3152 struct restoreCookie cookie;
3153 struct rx_connection **toconns = 0;
3154 struct release *times = 0;
3156 struct rx_connection *fromconn = (struct rx_connection *)0;
3157 afs_int32 error = 0;
3159 afs_int32 clonetid = 0, onlinetid;
3160 afs_int32 fromtid = 0;
3161 afs_uint32 fromdate, thisdate;
3164 manyResults results;
3165 int rwindex, roindex, roclone, roexists;
3166 afs_int32 rwcrdate, rwupdate, clcrdate;
3170 } remembertime[NMAXNSERVERS];
3171 int releasecount = 0;
3172 struct volser_status volstatus;
3174 memset((char *)remembertime, 0, sizeof(remembertime));
3175 memset((char *)&results, 0, sizeof(results));
3177 vcode = ubik_Call(VL_SetLock, cstruct, 0, afromvol, RWVOL, VLOP_RELEASE);
3178 if (vcode != VL_RERELEASE)
3179 ONERROR(vcode, afromvol,
3180 "Could not lock the VLDB entry for the volume %u.\n");
3183 /* Get the vldb entry in readable format */
3184 vcode = VLDB_GetEntryByID(afromvol, RWVOL, &entry);
3185 ONERROR(vcode, afromvol,
3186 "Could not fetch the entry for the volume %u from the VLDB.\n");
3187 MapHostToNetwork(&entry);
3190 EnumerateEntry(&entry);
3192 if (!ISNAMEVALID(entry.name))
3193 ONERROR(VOLSERBADOP, entry.name,
3194 "Volume name %s is too long, rename before releasing.\n");
3195 if (entry.volumeId[RWVOL] != afromvol)
3196 ONERROR(VOLSERBADOP, afromvol,
3197 "The volume %u being released is not a read-write volume.\n");
3198 if (entry.nServers <= 1)
3199 ONERROR(VOLSERBADOP, afromvol,
3200 "Volume %u has no replicas - release operation is meaningless!\n");
3201 if (strlen(entry.name) > (VOLSER_OLDMAXVOLNAME - 10))
3202 ONERROR(VOLSERBADOP, entry.name,
3203 "RO volume name %s exceeds (VOLSER_OLDMAXVOLNAME - 10) character limit\n");
3205 /* roclone is true if one of the RO volumes is on the same
3206 * partition as the RW volume. In this case, we make the RO volume
3207 * on the same partition a clone instead of a complete copy.
3210 roindex = Lp_ROMatch(afromserver, afrompart, &entry) - 1;
3211 roclone = ((roindex == -1) ? 0 : 1);
3212 rwindex = Lp_GetRwIndex(&entry);
3214 ONERROR(VOLSERNOVOL, 0, "There is no RW volume \n");
3216 /* Make sure we have a RO volume id to work with */
3217 if (entry.volumeId[ROVOL] == INVALID_BID) {
3218 /* need to get a new RO volume id */
3219 vcode = ubik_Call(VL_GetNewVolumeId, cstruct, 0, 1, &roVolId);
3220 ONERROR(vcode, entry.name, "Cant allocate ID for RO volume of %s\n");
3222 entry.volumeId[ROVOL] = roVolId;
3223 MapNetworkToHost(&entry, &storeEntry);
3224 vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry, 0);
3225 ONERROR(vcode, entry.name, "Could not update vldb entry for %s.\n");
3228 /* Will we be completing a previously unfinished release. -force overrides */
3229 for (s = 0, m = 0, fullrelease=0, i=0; (i<entry.nServers); i++) {
3230 if (entry.serverFlags[i] & ITSROVOL) {
3232 if (entry.serverFlags[i] & NEW_REPSITE) s++;
3235 if ((forceflag && !fullrelease) || (s == m) || (s == 0))
3238 /* Determine which volume id to use and see if it exists */
3241 || (entry.cloneId == 0)) ? entry.volumeId[ROVOL] : entry.cloneId);
3242 code = VolumeExists(afromserver, afrompart, cloneVolId);
3243 roexists = ((code == ENODEV) ? 0 : 1);
3245 fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT);
3247 ONERROR(-1, afromserver,
3248 "Cannot establish connection with server 0x%x\n");
3252 fullrelease = 1; /* Do a full release if RO clone does not exist */
3254 /* Begin transaction on RW and mark it busy while we query it */
3255 code = AFSVolTransCreate(
3256 fromconn, afromvol, afrompart, ITBusy, &fromtid
3258 ONERROR(code, afromvol,
3259 "Failed to start transaction on RW volume %u\n");
3261 /* Query the creation date for the RW */
3262 code = AFSVolGetStatus(fromconn, fromtid, &volstatus);
3263 ONERROR(code, afromvol,
3264 "Failed to get the status of RW volume %u\n");
3265 rwcrdate = volstatus.creationDate;
3266 rwupdate = volstatus.updateDate;
3268 /* End transaction on RW */
3269 code = AFSVolEndTrans(fromconn, fromtid, &rcode);
3271 ONERROR((code ? code : rcode), afromvol,
3272 "Failed to end transaction on RW volume %u\n");
3274 /* Begin transaction on clone and mark it busy while we query it */
3275 code = AFSVolTransCreate(
3276 fromconn, cloneVolId, afrompart, ITBusy, &clonetid
3278 ONERROR(code, cloneVolId,
3279 "Failed to start transaction on RW clone %u\n");
3281 /* Query the creation date for the clone */
3282 code = AFSVolGetStatus(fromconn, clonetid, &volstatus);
3283 ONERROR(code, cloneVolId,
3284 "Failed to get the status of RW clone %u\n");
3285 clcrdate = volstatus.creationDate;
3287 /* End transaction on clone */
3288 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
3290 ONERROR((code ? code : rcode), cloneVolId,
3291 "Failed to end transaction on RW clone %u\n");
3293 if (rwcrdate > clcrdate)
3294 fullrelease = 2;/* Do a full release if RO clone older than RW */
3299 switch (fullrelease) {
3301 fprintf(STDOUT, "RW %lu changed, doing a complete release\n",
3302 (unsigned long)afromvol);
3305 fprintf(STDOUT, "This is a complete release of volume %lu\n",
3306 (unsigned long)afromvol);
3309 fprintf(STDOUT, "This is a completion of a previous release\n");
3315 /* If the RO clone exists, then if the clone is a temporary
3316 * clone, delete it. Or if the RO clone is marked RO_DONTUSE
3317 * (it was recently added), then also delete it. We do not
3318 * want to "reclone" a temporary RO clone.
3321 && (!roclone || (entry.serverFlags[roindex] & RO_DONTUSE))) {
3322 code = DelVol(fromconn, cloneVolId, afrompart, ITOffline);
3323 if (code && (code != VNOVOL))
3328 /* Mark all the ROs in the VLDB entry as RO_DONTUSE. We don't
3329 * write this entry out to the vlserver until after the first
3330 * RO volume is released (temp RO clones don't count).
3332 for (i = 0; i < entry.nServers; i++) {
3333 entry.serverFlags[i] &= ~NEW_REPSITE;
3334 entry.serverFlags[i] |= RO_DONTUSE;
3336 entry.serverFlags[rwindex] |= NEW_REPSITE;
3337 entry.serverFlags[rwindex] &= ~RO_DONTUSE;
3339 /* Begin transaction on RW and mark it busy while we clone it */
3341 AFSVolTransCreate(fromconn, afromvol, afrompart, ITBusy,
3343 ONERROR(code, afromvol, "Failed to start transaction on volume %u\n");
3345 /* Clone or reclone the volume */
3347 VPRINT1("Recloning RW volume %u...", cloneVolId);
3348 code = AFSVolReClone(fromconn, clonetid, cloneVolId);
3349 ONERROR(code, afromvol, "Failed to reclone the RW volume %u\n");
3353 strcpy(vname, entry.name);
3354 strcat(vname, ".readonly");
3355 VPRINT1("Cloning RW volume %u to permanent RO...", afromvol);
3357 strcpy(vname, "readonly-clone-temp");
3358 VPRINT1("Cloning RW volume %u to temporary RO...", afromvol);
3361 AFSVolClone(fromconn, clonetid, 0, readonlyVolume, vname,
3363 ONERROR(code, afromvol, "Failed to clone the RW volume %u\n");
3367 /* Get the time the RW was created for future information */
3368 VPRINT1("Getting status of RW volume %u...", afromvol);
3369 code = AFSVolGetStatus(fromconn, clonetid, &volstatus);
3370 ONERROR(code, afromvol,
3371 "Failed to get the status of the RW volume %u\n");
3373 rwcrdate = volstatus.creationDate;
3374 rwupdate = volstatus.updateDate;
3376 /* End the transaction on the RW volume */
3377 VPRINT1("Ending cloning transaction on RW volume %u...", afromvol);
3378 code = AFSVolEndTrans(fromconn, clonetid, &rcode);
3380 ONERROR((code ? code : rcode), afromvol,
3381 "Failed to end cloning transaction on RW %u\n");
3384 /* Remember clone volume ID in case we fail or are interrupted */
3385 entry.cloneId = cloneVolId;
3388 /* Bring the RO clone online - though not if it's a temporary clone */
3389 VPRINT1("Starting transaction on RO clone volume %u...",
3392 AFSVolTransCreate(fromconn, cloneVolId, afrompart, ITOffline,
3394 ONERROR(code, cloneVolId,
3395 "Failed to start transaction on volume %u\n");
3398 VPRINT1("Setting volume flags for volume %u...", cloneVolId);
3399 tcode = AFSVolSetFlags(fromconn, onlinetid, 0);
3402 VPRINT1("Ending transaction on volume %u...", cloneVolId);
3403 code = AFSVolEndTrans(fromconn, onlinetid, &rcode);
3404 ONERROR((code ? code : rcode), cloneVolId,
3405 "Failed to end transaction on RO clone %u\n");
3408 ONERROR(tcode, cloneVolId, "Could not bring volume %u on line\n");
3410 /* Sleep so that a client searching for an online volume won't
3411 * find the clone offline and then the next RO offline while the
3412 * release brings the clone online and the next RO offline (race).
3413 * There is a fix in the 3.4 client that does not need this sleep
3414 * anymore, but we don't know what clients we have.
3416 if (entry.nServers > 2)
3419 /* Mark the RO clone in the VLDB as a good site (already released) */
3420 entry.serverFlags[roindex] |= NEW_REPSITE;
3421 entry.serverFlags[roindex] &= ~RO_DONTUSE;
3422 entry.flags |= RO_EXISTS;
3426 /* Write out the VLDB entry only if the clone is not a temporary
3427 * clone. If we did this to a temporary clone then we would end
3428 * up marking all the ROs as "old release" making the ROs
3429 * temporarily unavailable.
3431 MapNetworkToHost(&entry, &storeEntry);
3432 VPRINT1("Replacing VLDB entry for %s...", entry.name);
3433 vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry, 0);
3434 ONERROR(vcode, entry.name,
3435 "Could not update vldb entry for %s.\n");
3440 /* Now we will release from the clone to the remaining RO replicas.
3441 * The first 2 ROs (counting the non-temporary RO clone) are released
3442 * individually: releasecount. This is to reduce the race condition
3443 * of clients trying to find an on-line RO volume. The remaining ROs
3444 * are released in parallel but no more than half the number of ROs
3445 * (rounded up) at a time: nservers.
3448 strcpy(vname, entry.name);
3449 strcat(vname, ".readonly");
3450 memset(&cookie, 0, sizeof(cookie));
3451 strncpy(cookie.name, vname, VOLSER_OLDMAXVOLNAME);
3452 cookie.type = ROVOL;
3453 cookie.parent = entry.volumeId[RWVOL];
3456 nservers = entry.nServers / 2; /* how many to do at once, excluding clone */
3458 (struct replica *)malloc(sizeof(struct replica) * nservers + 1);
3459 times = (struct release *)malloc(sizeof(struct release) * nservers + 1);
3461 (struct rx_connection **)malloc(sizeof(struct rx_connection *) *
3463 results.manyResults_val =
3464 (afs_int32 *) malloc(sizeof(afs_int32) * nservers + 1);
3465 if (!replicas || !times || !!!results.manyResults_val || !toconns)
3467 "Failed to create transaction on the release clone\n");
3469 memset(replicas, 0, (sizeof(struct replica) * nservers + 1));
3470 memset(times, 0, (sizeof(struct release) * nservers + 1));
3471 memset(toconns, 0, (sizeof(struct rx_connection *) * nservers + 1));
3472 memset(results.manyResults_val, 0, (sizeof(afs_int32) * nservers + 1));
3474 /* Create a transaction on the cloned volume */
3475 VPRINT1("Starting transaction on cloned volume %u...", cloneVolId);
3477 AFSVolTransCreate(fromconn, cloneVolId, afrompart, ITBusy, &fromtid);
3478 if (!fullrelease && code)
3479 ONERROR(VOLSERNOVOL, afromvol,
3480 "Old clone is inaccessible. Try vos release -f %u.\n");
3481 ONERROR(code, 0, "Failed to create transaction on the release clone\n");
3484 /* For each index in the VLDB */
3485 for (vldbindex = 0; vldbindex < entry.nServers;) {
3487 /* Get a transaction on the replicas. Pick replacas which have an old release. */
3489 ((volcount < nservers) && (vldbindex < entry.nServers));
3491 /* The first two RO volumes will be released individually.
3492 * The rest are then released in parallel. This is a hack
3493 * for clients not recognizing right away when a RO volume
3494 * comes back on-line.
3496 if ((volcount == 1) && (releasecount < 2))
3499 if (vldbindex == roindex)
3500 continue; /* the clone */
3501 if ((entry.serverFlags[vldbindex] & NEW_REPSITE)
3502 && !(entry.serverFlags[vldbindex] & RO_DONTUSE))
3504 if (!(entry.serverFlags[vldbindex] & ITSROVOL))
3505 continue; /* not a RO vol */
3508 /* Get a Transaction on this replica. Get a new connection if
3509 * necessary. Create the volume if necessary. Return the
3510 * time from which the dump should be made (0 if it's a new
3511 * volume). Each volume might have a different time.
3513 replicas[volcount].server.destHost =
3514 ntohl(entry.serverNumber[vldbindex]);
3515 replicas[volcount].server.destPort = AFSCONF_VOLUMEPORT;
3516 replicas[volcount].server.destSSID = 1;
3517 times[volcount].vldbEntryIndex = vldbindex;
3520 GetTrans(&entry, vldbindex, &(toconns[volcount]),
3521 &(replicas[volcount].trans),
3522 &(times[volcount].crtime),
3523 &(times[volcount].uptime));
3527 /* Thisdate is the date from which we want to pick up all changes */
3528 if (forceflag || !fullrelease
3529 || (rwcrdate > times[volcount].crtime)) {
3530 /* If the forceflag is set, then we want to do a full dump.
3531 * If it's not a full release, we can't be sure that the creation
3532 * date is good (so we also do a full dump).
3533 * If the RW volume was replaced (its creation date is newer than
3534 * the last release), then we can't be sure what has changed (so
3535 * we do a full dump).