From: Andrew Deason Date: Thu, 23 Feb 2012 21:53:32 +0000 (-0600) Subject: Revert offline-less vos release X-Git-Tag: upstream/1.6.1.pre4^2~8 X-Git-Url: https://git.michaelhowe.org/gitweb/?a=commitdiff_plain;h=94c4502fd3f589c85860d40b811aca4a54193bcd;p=packages%2Fo%2Fopenafs.git Revert offline-less vos release This reverts commits: 3cc6da964e3705b070f8886686484d6a1eb700c8 8b25f9cc99308ffcd2ee3f4d2bc7d58a85f2b96b f4e73067cdef990262c69c38ac98761620a63f25 7a42c8f7ec6e6865a770c9bd7dbafa48947018a8 27661857721e92f2ff99ebe7f3a72bac6f01fa50 6b66b3b705b78c959b3ae321a8cb06e2fe166086 Wait until we have an actual stable release to merge these. Change-Id: I842fbbc7523230465aa8a9a38ee8ce65387fb1cc Reviewed-on: http://gerrit.openafs.org/6839 Reviewed-by: Derrick Brashear Tested-by: Derrick Brashear --- diff --git a/doc/man-pages/pod1/vos_release.pod b/doc/man-pages/pod1/vos_release.pod index 2421c5083..0115dff10 100644 --- a/doc/man-pages/pod1/vos_release.pod +++ b/doc/man-pages/pod1/vos_release.pod @@ -9,11 +9,11 @@ vos_release - Updates read-only volumes to match the read/write source volume B S<<< B<-id> > >>> [B<-force>] S<<< [B<-cell> >] >>> - [B<-noauth>] [B<-localauth>] [B<-stayonline>] + [B<-noauth>] [B<-localauth>] [B<-verbose>] [B<-encrypt>] [B<-noresolve>] [B<-help>] B S<<< B<-i> > >>> - [B<-f>] S<<< [B<-c> >] >>> [B<-stayon>] + [B<-f>] S<<< [B<-c> >] >>> [B<-noa>] [B<-l>] [B<-v>] [B<-e>] [B<-nor>] [B<-h>] =for html @@ -165,12 +165,6 @@ Produces on the standard output stream a detailed trace of the command's execution. If this argument is omitted, only warnings and error messages appear. -=item B<-stayonline> - -Avoids taking replica sites offline by cloning both the source -and destinations to temporary clones, applying updates, and then -bringing all clones online as updated readonly volumes. - =item B<-encrypt> Encrypts the command so that the operation's results are not transmitted diff --git a/src/vol/clone.c b/src/vol/clone.c index 3d20b8a7c..0841302fe 100644 --- a/src/vol/clone.c +++ b/src/vol/clone.c @@ -176,12 +176,7 @@ DoCloneIndex(Volume * rwvp, Volume * clvp, VnodeClass class, int reclone) afs_ino_str_t stmp; struct VnodeClassInfo *vcp = &VnodeClassInfo[class]; - /* - * The fileserver's -readonly switch should make this false, but we - * have no useful way to know in the volserver. - * This doesn't make client data mutable. - */ - int ReadWriteOriginal = 1; + int ReadWriteOriginal = VolumeWriteable(rwvp); /* Correct number of files in volume: this assumes indexes are always cloned starting with vLarge */ diff --git a/src/volser/volprocs.c b/src/volser/volprocs.c index 7f7aaa6fb..95339ad57 100644 --- a/src/volser/volprocs.c +++ b/src/volser/volprocs.c @@ -743,6 +743,12 @@ VolClone(struct rx_call *acid, afs_int32 atrans, afs_uint32 purgeId, purgevp = NULL; } originalvp = tt->volume; + if ((V_type(originalvp) == backupVolume) + || (V_type(originalvp) == readonlyVolume)) { + Log("1 Volser: Clone: The volume to be cloned must be a read/write; aborted\n"); + error = EROFS; + goto fail; + } if ((V_destroyMe(originalvp) == DESTROY_ME) || !V_inService(originalvp)) { Log("1 Volser: Clone: Volume %d is offline and cannot be cloned\n", V_id(originalvp)); @@ -772,17 +778,13 @@ VolClone(struct rx_call *acid, afs_int32 atrans, afs_uint32 purgeId, salv_vp = originalvp; #endif - if (purgeId == newId) { - newvp = purgevp; - } else { - newvp = - VCreateVolume(&error, originalvp->partition->name, newId, - V_parentId(originalvp)); - if (error) { - Log("1 Volser: Clone: Couldn't create new volume; clone aborted\n"); - newvp = (Volume *) 0; - goto fail; - } + newvp = + VCreateVolume(&error, originalvp->partition->name, newId, + V_parentId(originalvp)); + if (error) { + Log("1 Volser: Clone: Couldn't create new volume; clone aborted\n"); + newvp = (Volume *) 0; + goto fail; } if (newType == readonlyVolume) V_cloneId(originalvp) = newId; diff --git a/src/volser/volser_internal.h b/src/volser/volser_internal.h index 1678ac047..26a9e8516 100644 --- a/src/volser/volser_internal.h +++ b/src/volser/volser_internal.h @@ -61,7 +61,7 @@ extern int UV_MoveVolume2(afs_uint32 afromvol, afs_uint32 afromserver, extern int UV_BackupVolume(afs_uint32 aserver, afs_int32 apart, afs_uint32 avolid); extern int UV_ReleaseVolume(afs_uint32 afromvol, afs_uint32 afromserver, - afs_int32 afrompart, int forceflag, int upflag); + afs_int32 afrompart, int forceflag); extern void dump_sig_handler(int x); extern int UV_DumpVolume(afs_uint32 afromvol, afs_uint32 afromserver, afs_int32 afrompart, afs_int32 fromdate, diff --git a/src/volser/vos.c b/src/volser/vos.c index 90b9e55c1..3ee98e4ee 100644 --- a/src/volser/vos.c +++ b/src/volser/vos.c @@ -2856,12 +2856,9 @@ ReleaseVolume(struct cmd_syndesc *as, void *arock) afs_uint32 aserver; afs_int32 apart, vtype, code, err; int force = 0; - int stayUp = 0; if (as->parms[1].items) force = 1; - if (as->parms[2].items) - stayUp = 1; avolid = vsu_GetVolumeID(as->parms[0].items->data, cstruct, &err); if (avolid == 0) { if (err) @@ -2887,8 +2884,7 @@ ReleaseVolume(struct cmd_syndesc *as, void *arock) return E2BIG; } - code = UV_ReleaseVolume(avolid, aserver, apart, force, stayUp); - + code = UV_ReleaseVolume(avolid, aserver, apart, force); if (code) { PrintDiagnostics("release", code); return code; @@ -6006,8 +6002,6 @@ main(int argc, char **argv) cmd_AddParm(ts, "-id", CMD_SINGLE, 0, "volume name or ID"); cmd_AddParm(ts, "-force", CMD_FLAG, CMD_OPTIONAL, "force a complete release"); - cmd_AddParm(ts, "-stayonline", CMD_FLAG, CMD_OPTIONAL, - "release to cloned temp vol, then clone back to repsite RO"); COMMONPARMS; ts = cmd_CreateSyntax("dump", DumpVolumeCmd, NULL, "dump a volume"); diff --git a/src/volser/vsprocs.c b/src/volser/vsprocs.c index 4630e9d66..cd362952a 100644 --- a/src/volser/vsprocs.c +++ b/src/volser/vsprocs.c @@ -173,23 +173,16 @@ static afs_int32 CheckAndDeleteVolume(struct rx_connection *aconn, afs_int32 apart, afs_uint32 okvol, afs_uint32 delvol); #endif +static int DelVol(struct rx_connection *conn, afs_uint32 vid, afs_int32 part, + afs_int32 flags); static int GetTrans(struct nvldbentry *vldbEntryPtr, afs_int32 index, struct rx_connection **connPtr, afs_int32 * transPtr, afs_uint32 * crtimePtr, afs_uint32 * uptimePtr, - afs_int32 *origflags, afs_uint32 tmpVolId); + afs_int32 *origflags); static int SimulateForwardMultiple(struct rx_connection *fromconn, afs_int32 fromtid, afs_int32 fromdate, manyDests * tr, afs_int32 flags, void *cookie, manyResults * results); -static int DoVolOnline(struct nvldbentry *vldbEntryPtr, afs_uint32 avolid, - int index, char *vname, struct rx_connection *connPtr); -static int DoVolClone(struct rx_connection *aconn, afs_uint32 avolid, - afs_int32 apart, int type, afs_uint32 cloneid, - char *typestring, char *pname, char *vname, char *suffix, - struct volser_status *volstatus, afs_int32 *transPtr); -static int DoVolDelete(struct rx_connection *aconn, afs_uint32 avolid, - afs_int32 apart, char *typestring, afs_uint32 atoserver, - struct volser_status *volstatus, char *pprefix); static afs_int32 CheckVolume(volintInfo * volumeinfo, afs_uint32 aserver, afs_int32 apart, afs_int32 * modentry, afs_uint32 * maxvolid, struct nvldbentry *aentry); @@ -947,15 +940,26 @@ UV_DeleteVolume(afs_uint32 aserver, afs_int32 apart, afs_uint32 avolid) /* Whether volume is in the VLDB or not. Delete the volume on disk */ aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT); - - code = DoVolDelete(aconn, avolid, apart, "the", 0, NULL, NULL); + code = AFSVolTransCreate_retry(aconn, avolid, apart, ITOffline, &ttid); if (code) { - if (code == VNOVOL) + if (code == VNOVOL) { notondisk = 1; - else { - error = code; - goto error_exit; + } else { + EGOTO1(error_exit, code, "Transaction on volume %u failed\n", + avolid); } + } else { + VPRINT1("Trying to delete the volume %u ...", avolid); + + code = AFSVolDeleteVolume(aconn, ttid); + EGOTO1(error_exit, code, "Could not delete the volume %u \n", avolid); + + code = AFSVolEndTrans(aconn, ttid, &rcode); + code = (code ? code : rcode); + ttid = 0; + EGOTO1(error_exit, code, + "Could not end the transaction for the volume %u \n", avolid); + VDONE; } /* Now update the VLDB entry. @@ -1014,11 +1018,28 @@ UV_DeleteVolume(afs_uint32 aserver, afs_int32 apart, afs_uint32 avolid) } /* Delete backup if it exists */ - code = DoVolDelete(aconn, entry.volumeId[BACKVOL], apart, - "the backup", 0, NULL, NULL); - if (code && code != VNOVOL) { - error = code; - goto error_exit; + code = + AFSVolTransCreate_retry(aconn, entry.volumeId[BACKVOL], apart, + ITOffline, &ttid); + + if (!code) { + if (verbose) { + fprintf(STDOUT, "Trying to delete the backup volume %u ...", + entry.volumeId[BACKVOL]); + fflush(STDOUT); + } + code = AFSVolDeleteVolume(aconn, ttid); + EGOTO1(error_exit, code, "Could not delete the volume %u \n", + entry.volumeId[BACKVOL]); + + code = AFSVolEndTrans(aconn, ttid, &rcode); + ttid = 0; + code = (code ? code : rcode); + EGOTO1(error_exit, code, + "Could not end the transaction for the volume %u \n", + entry.volumeId[BACKVOL]); + if (verbose) + fprintf(STDOUT, " done\n"); } if (verbose) @@ -1157,193 +1178,6 @@ sigint_handler(int x) (void)signal(SIGINT, sigint_handler); } -static int -DoVolDelete(struct rx_connection *aconn, afs_uint32 avolid, - afs_int32 apart, char *ptypestring, afs_uint32 atoserver, - struct volser_status *volstatus, char *pprefix) -{ - afs_int32 ttid = 0, code, rcode, error = 0; - char *prefix, *typestring; - int beverbose = 0; - - if (pprefix) - prefix = pprefix; - else - prefix = ""; - - if (ptypestring) { - typestring = ptypestring; - beverbose = 1; - } else - typestring = "the"; - - if (beverbose) - VPRINT3("%sDeleting %s volume %u ...", prefix, typestring, avolid); - - code = - AFSVolTransCreate_retry(aconn, avolid, apart, ITOffline, &ttid); - - EGOTO2(dfail, code, "%sFailed to start transaction on %u\n", - prefix, avolid); - - if (volstatus) { - code = AFSVolGetStatus(aconn, ttid, volstatus); - EGOTO2(dfail, code, "%sCould not get timestamp from volume %u\n", - prefix, avolid); - } - - code = - AFSVolSetFlags(aconn, ttid, - VTDeleteOnSalvage | VTOutOfService); - - EGOTO2(dfail, code, "%sCould not set flags on volume %u \n", - prefix, avolid); - - if (atoserver) { - VPRINT1("%sSetting volume forwarding pointer ...", prefix); - AFSVolSetForwarding(aconn, ttid, atoserver); - VDONE; - } - - code = AFSVolDeleteVolume(aconn, ttid); - EGOTO2(dfail, code, "%sCould not delete volume %u\n", prefix, avolid); - -dfail: - if (ttid) { - code = AFSVolEndTrans(aconn, ttid, &rcode); - ttid = 0; - if (!code) - code = rcode; - if (code) { - fprintf(STDERR, "%sCould not end transaction on %s volume %lu \n", - prefix, typestring, (unsigned long)avolid); - if (!error) - error = code; - } - } - - if (beverbose && !error) - VDONE; - return error; -} - -static int -DoVolClone(struct rx_connection *aconn, afs_uint32 avolid, - afs_int32 apart, int type, afs_uint32 cloneid, - char *typestring, char *pname, char *vname, char *suffix, - struct volser_status *volstatus, afs_int32 *transPtr) -{ - char cname[64]; - afs_int32 ttid = 0, btid = 0; - afs_int32 code = 0, rcode = 0; - afs_int32 error = 0; - int cloneexists = 1; - - /* Test to see if the clone volume exists by trying to create - * a transaction on the clone volume. We've assumed the clone exists. - */ - code = AFSVolTransCreate_retry(aconn, cloneid, apart, ITOffline, &btid); - if (code) { - if (code != VNOVOL) { - EPRINT2(code, "Could not reach the %s volume %lu\n", - typestring, (unsigned long)cloneid); - error = code; - goto cfail; - } - cloneexists = 0; /* clone volume does not exist */ - } - if (btid) { - code = AFSVolEndTrans(aconn, btid, &rcode); - btid = 0; - if (code || rcode) { - fprintf(STDERR, - "Could not end transaction on the previous %s volume %lu\n", - typestring, (unsigned long)cloneid); - error = (code ? code : rcode); - goto cfail; - } - } - - /* Now go ahead and try to clone the RW volume. - * First start a transaction on the RW volume - */ - code = AFSVolTransCreate_retry(aconn, avolid, apart, ITBusy, &ttid); - if (code) { - fprintf(STDERR, "Could not start a transaction on the volume %lu\n", - (unsigned long)avolid); - error = code; - goto cfail; - } - - /* Clone or reclone the volume, depending on whether the clone - * volume exists or not - */ - if (cloneexists) { - VPRINT2("Re-cloning %s volume %u ...", typestring, cloneid); - - code = AFSVolReClone(aconn, ttid, cloneid); - if (code) { - EPRINT2(code, "Could not re-clone %s volume %lu\n", - typestring, (unsigned long)cloneid); - error = code; - goto cfail; - } - } else { - VPRINT2("Creating a new %s clone %u ...", typestring, cloneid); - - if (!vname) { - strcpy(cname, pname); - strcat(cname, suffix); - } - - code = AFSVolClone(aconn, ttid, 0, type, vname?vname:cname, - &cloneid); - if (code) { - fprintf(STDERR, "Failed to clone the volume %lu\n", - (unsigned long)avolid); - error = code; - goto cfail; - } - } - - VDONE; - - if (volstatus) { - VPRINT1("Getting status of parent volume %u...", avolid); - code = AFSVolGetStatus(aconn, ttid, volstatus); - if (code) { - fprintf(STDERR, "Failed to get the status of the parent volume %lu\n", - (unsigned long)avolid); - error = code; - goto cfail; - } - VDONE; - } - -cfail: - if (ttid) { - code = AFSVolEndTrans(aconn, ttid, &rcode); - if (code || rcode) { - fprintf(STDERR, "Could not end transaction on the volume %lu\n", - (unsigned long)avolid); - if (!error) - error = (code ? code : rcode); - } - } - - if (btid) { - code = AFSVolEndTrans(aconn, btid, &rcode); - if (code || rcode) { - fprintf(STDERR, - "Could not end transaction on the %s volume %lu\n", - typestring, (unsigned long)cloneid); - if (!error) - error = (code ? code : rcode); - } - } - return error; -} - /* Move volume on to * . The operation is almost idempotent. The following * flags are recognized: @@ -1484,20 +1318,79 @@ UV_MoveVolume2(afs_uint32 afromvol, afs_uint32 afromserver, afs_int32 afrompart, * may still be existing physically on from fileserver */ fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT); + fromtid = 0; pntg = 1; - code = DoVolDelete(fromconn, afromvol, afrompart, - "leftover", 0, NULL, NULL); - if (code && code != VNOVOL) { - error = code; - goto mfail; + tmp = fromtid; + code = + AFSVolTransCreate_retry(fromconn, afromvol, afrompart, ITOffline, + &tmp); + fromtid = tmp; + + if (!code) { /* volume exists - delete it */ + VPRINT1("Setting flags on leftover source volume %u ...", + afromvol); + code = + AFSVolSetFlags(fromconn, fromtid, + VTDeleteOnSalvage | VTOutOfService); + EGOTO1(mfail, code, + "Failed to set flags on the leftover source volume %u\n", + afromvol); + VDONE; + + VPRINT1("Deleting leftover source volume %u ...", afromvol); + code = AFSVolDeleteVolume(fromconn, fromtid); + EGOTO1(mfail, code, + "Failed to delete the leftover source volume %u\n", + afromvol); + VDONE; + + VPRINT1("Ending transaction on leftover source volume %u ...", + afromvol); + code = AFSVolEndTrans(fromconn, fromtid, &rcode); + fromtid = 0; + if (!code) + code = rcode; + EGOTO1(mfail, code, + "Could not end the transaction for the leftover source volume %u \n", + afromvol); + VDONE; } - code = DoVolDelete(fromconn, backupId, afrompart, - "leftover backup", 0, NULL, NULL); - if (code && code != VNOVOL) { - error = code; - goto mfail; + /*delete the backup volume now */ + fromtid = 0; + code = + AFSVolTransCreate_retry(fromconn, backupId, afrompart, ITOffline, + &tmp); + fromtid = tmp; + + if (!code) { /* backup volume exists - delete it */ + VPRINT1("Setting flags on leftover backup volume %u ...", + backupId); + code = + AFSVolSetFlags(fromconn, fromtid, + VTDeleteOnSalvage | VTOutOfService); + EGOTO1(mfail, code, + "Failed to set flags on the backup volume %u\n", backupId); + VDONE; + + VPRINT1("Deleting leftover backup volume %u ...", backupId); + code = AFSVolDeleteVolume(fromconn, fromtid); + EGOTO1(mfail, code, + "Could not delete the leftover backup volume %u\n", + backupId); + VDONE; + + VPRINT1("Ending transaction on leftover backup volume %u ...", + backupId); + code = AFSVolEndTrans(fromconn, fromtid, &rcode); + fromtid = 0; + if (!code) + code = rcode; + EGOTO1(mfail, code, + "Could not end the transaction for the leftover backup volume %u\n", + backupId); + VDONE; } fromtid = 0; @@ -1639,11 +1532,33 @@ UV_MoveVolume2(afs_uint32 afromvol, afs_uint32 afromserver, afs_int32 afrompart, /* create a volume on the target machine */ volid = afromvol; - code = DoVolDelete(toconn, volid, atopart, - "pre-existing destination", 0, NULL, NULL); - if (code && code != VNOVOL) { - error = code; - goto mfail; + tmp = totid; + code = AFSVolTransCreate_retry(toconn, volid, atopart, ITOffline, &tmp); + totid = tmp; + if (!code) { + /* Delete the existing volume. + * While we are deleting the volume in these steps, the transaction + * we started against the cloned volume (clonetid above) will be + * sitting idle. It will get cleaned up after 600 seconds + */ + VPRINT1("Deleting pre-existing volume %u on destination ...", volid); + code = AFSVolDeleteVolume(toconn, totid); + EGOTO1(mfail, code, + "Could not delete the pre-existing volume %u on destination\n", + volid); + VDONE; + + VPRINT1 + ("Ending transaction on pre-existing volume %u on destination ...", + volid); + code = AFSVolEndTrans(toconn, totid, &rcode); + totid = 0; + if (!code) + code = rcode; + EGOTO1(mfail, code, + "Could not end the transaction on pre-existing volume %u on destination\n", + volid); + VDONE; } VPRINT1("Creating the destination volume %u ...", volid); @@ -1858,23 +1773,73 @@ UV_MoveVolume2(afs_uint32 afromvol, afs_uint32 afromserver, afs_int32 afrompart, afromvol); VDONE; - code = DoVolDelete(fromconn, backupId, afrompart, - "source backup", 0, NULL, NULL); - if (code && code != VNOVOL) { - error = code; - goto mfail; - } + /* Delete the backup volume on the original site */ + VPRINT1("Creating transaction for backup volume %u on source ...", + backupId); + tmp = fromtid; + code = + AFSVolTransCreate_retry(fromconn, backupId, afrompart, ITOffline, &tmp); + fromtid = tmp; + VDONE; + if (!code) { + VPRINT1("Setting flags on backup volume %u on source ...", backupId); + code = + AFSVolSetFlags(fromconn, fromtid, + VTDeleteOnSalvage | VTOutOfService); + EGOTO1(mfail, code, + "Failed to set the flags on the backup volume %u on the source\n", + backupId); + VDONE; - code = 0; /* no backup volume? that's okay */ + VPRINT1("Deleting the backup volume %u on the source ...", backupId); + code = AFSVolDeleteVolume(fromconn, fromtid); + EGOTO1(mfail, code, + "Failed to delete the backup volume %u on the source\n", + backupId); + VDONE; + + VPRINT1("Ending transaction on backup volume %u on source ...", + backupId); + code = AFSVolEndTrans(fromconn, fromtid, &rcode); + fromtid = 0; + if (!code) + code = rcode; + EGOTO1(mfail, code, + "Failed to end the transaction on the backup volume %u on the source\n", + backupId); + VDONE; + } else + code = 0; /* no backup volume? that's okay */ fromtid = 0; if (!(flags & RV_NOCLONE)) { - code = DoVolDelete(fromconn, newVol, afrompart, - "cloned", 0, NULL, NULL); - if (code) { - error = code; - goto mfail; - } + VPRINT1("Starting transaction on the cloned volume %u ...", newVol); + tmp = clonetid; + code = + AFSVolTransCreate_retry(fromconn, newVol, afrompart, ITOffline, + &tmp); + clonetid = tmp; + EGOTO1(mfail, code, + "Failed to start a transaction on the cloned volume%u\n", + newVol); + VDONE; + + /* now delete the clone */ + VPRINT1("Deleting the cloned volume %u ...", newVol); + code = AFSVolDeleteVolume(fromconn, clonetid); + EGOTO1(mfail, code, "Failed to delete the cloned volume %u\n", + newVol); + VDONE; + + VPRINT1("Ending transaction on cloned volume %u ...", newVol); + code = AFSVolEndTrans(fromconn, clonetid, &rcode); + if (!code) + code = rcode; + clonetid = 0; + EGOTO1(mfail, code, + "Failed to end the transaction on the cloned volume %u\n", + newVol); + VDONE; } /* fall through */ @@ -2034,9 +1999,41 @@ UV_MoveVolume2(afs_uint32 afromvol, afs_uint32 afromserver, afs_int32 afrompart, fflush(STDOUT); } - if (volid && toconn) - code = DoVolDelete(toconn, volid, atopart, - "destination", 0, NULL, "Recovery:"); + if (volid && toconn) { + VPRINT1 + ("Recovery: Creating transaction for destination volume %u ...", + volid); + tmp = totid; + code = + AFSVolTransCreate_retry(toconn, volid, atopart, ITOffline, &tmp); + totid = tmp; + + if (!code) { + VDONE; + + VPRINT1 + ("Recovery: Setting flags on destination volume %u ...", + volid); + AFSVolSetFlags(toconn, totid, + VTDeleteOnSalvage | VTOutOfService); + VDONE; + + VPRINT1("Recovery: Deleting destination volume %u ...", + volid); + AFSVolDeleteVolume(toconn, totid); + VDONE; + + VPRINT1 + ("Recovery: Ending transaction on destination volume %u ...", + volid); + AFSVolEndTrans(toconn, totid, &rcode); + VDONE; + } else { + VPRINT1 + ("\nRecovery: Unable to start transaction on destination volume %u.\n", + afromvol); + } + } /* put source volume on-line */ if (fromconn) { @@ -2075,19 +2072,102 @@ UV_MoveVolume2(afs_uint32 afromvol, afs_uint32 afromserver, afs_int32 afrompart, /* delete backup volume */ if (fromconn) { - code = DoVolDelete(fromconn, backupId, afrompart, - "backup", 0, NULL, "Recovery:"); + VPRINT1("Recovery: Creating transaction on backup volume %u ...", + backupId); + tmp = fromtid; + code = + AFSVolTransCreate_retry(fromconn, backupId, afrompart, ITOffline, + &tmp); + fromtid = tmp; + if (!code) { + VDONE; + + VPRINT1("Recovery: Setting flags on backup volume %u ...", + backupId); + AFSVolSetFlags(fromconn, fromtid, + VTDeleteOnSalvage | VTOutOfService); + VDONE; - code = DoVolDelete(fromconn, afromvol, afrompart, "source", - (atoserver != afromserver)?atoserver:0, - NULL, NULL); + VPRINT1("Recovery: Deleting backup volume %u ...", backupId); + AFSVolDeleteVolume(fromconn, fromtid); + VDONE; + + VPRINT1 + ("Recovery: Ending transaction on backup volume %u ...", + backupId); + AFSVolEndTrans(fromconn, fromtid, &rcode); + VDONE; + } else { + VPRINT1 + ("\nRecovery: Unable to start transaction on backup volume %u.\n", + backupId); + } + + /* delete source volume */ + VPRINT1("Recovery: Creating transaction on source volume %u ...", + afromvol); + tmp = fromtid; + code = + AFSVolTransCreate_retry(fromconn, afromvol, afrompart, ITBusy, + &tmp); + fromtid = tmp; + if (!code) { + VDONE; + + VPRINT1("Recovery: Setting flags on backup volume %u ...", + afromvol); + AFSVolSetFlags(fromconn, fromtid, + VTDeleteOnSalvage | VTOutOfService); + VDONE; + + if (atoserver != afromserver) { + VPRINT("Recovery: Setting volume forwarding pointer ..."); + AFSVolSetForwarding(fromconn, fromtid, atoserver); + VDONE; + } + + VPRINT1("Recovery: Deleting source volume %u ...", afromvol); + AFSVolDeleteVolume(fromconn, fromtid); + VDONE; + + VPRINT1 + ("Recovery: Ending transaction on source volume %u ...", + afromvol); + AFSVolEndTrans(fromconn, fromtid, &rcode); + VDONE; + } else { + VPRINT1 + ("\nRecovery: Unable to start transaction on source volume %u.\n", + afromvol); + } } } /* common cleanup - delete local clone */ if (newVol) { - code = DoVolDelete(fromconn, newVol, afrompart, - "clone", 0, NULL, "Recovery:"); + VPRINT1("Recovery: Creating transaction on clone volume %u ...", + newVol); + tmp = clonetid; + code = + AFSVolTransCreate_retry(fromconn, newVol, afrompart, ITOffline, + &tmp); + clonetid = tmp; + if (!code) { + VDONE; + + VPRINT1("Recovery: Deleting clone volume %u ...", newVol); + AFSVolDeleteVolume(fromconn, clonetid); + VDONE; + + VPRINT1("Recovery: Ending transaction on clone volume %u ...", + newVol); + AFSVolEndTrans(fromconn, clonetid, &rcode); + VDONE; + } else { + VPRINT1 + ("\nRecovery: Unable to start transaction on source volume %u.\n", + afromvol); + } } /* unlock VLDB entry */ @@ -2463,12 +2543,33 @@ cpincr: fromtid = 0; if (!(flags & RV_NOCLONE)) { - code = DoVolDelete(fromconn, cloneVol, afrompart, - "cloned", 0, NULL, NULL); - if (code) { - error = code; - goto mfail; - } + VPRINT1("Starting transaction on the cloned volume %u ...", cloneVol); + tmp = clonetid; + code = + AFSVolTransCreate_retry(fromconn, cloneVol, afrompart, ITOffline, + &tmp); + clonetid = tmp; + EGOTO1(mfail, code, + "Failed to start a transaction on the cloned volume%u\n", + cloneVol); + VDONE; + + /* now delete the clone */ + VPRINT1("Deleting the cloned volume %u ...", cloneVol); + code = AFSVolDeleteVolume(fromconn, clonetid); + EGOTO1(mfail, code, "Failed to delete the cloned volume %u\n", + cloneVol); + VDONE; + + VPRINT1("Ending transaction on cloned volume %u ...", cloneVol); + code = AFSVolEndTrans(fromconn, clonetid, &rcode); + if (!code) + code = rcode; + clonetid = 0; + EGOTO1(mfail, code, + "Failed to end the transaction on the cloned volume %u\n", + cloneVol); + VDONE; } if (!(flags & RV_NOVLDB)) { @@ -2591,9 +2692,31 @@ cpincr: MapHostToNetwork(&entry); /* common cleanup - delete local clone */ - if (cloneVol) - code = DoVolDelete(fromconn, cloneVol, afrompart, - "clone", 0, NULL, "Recovery:"); + if (cloneVol) { + VPRINT1("Recovery: Creating transaction on clone volume %u ...", + cloneVol); + tmp = clonetid; + code = + AFSVolTransCreate_retry(fromconn, cloneVol, afrompart, ITOffline, + &tmp); + clonetid = tmp; + if (!code) { + VDONE; + + VPRINT1("Recovery: Deleting clone volume %u ...", cloneVol); + AFSVolDeleteVolume(fromconn, clonetid); + VDONE; + + VPRINT1("Recovery: Ending transaction on clone volume %u ...", + cloneVol); + AFSVolEndTrans(fromconn, clonetid, &rcode); + VDONE; + } else { + VPRINT1 + ("\nRecovery: Unable to start transaction on clone volume %u.\n", + cloneVol); + } + } done: /* routine cleanup */ if (fromconn) @@ -2630,9 +2753,10 @@ UV_BackupVolume(afs_uint32 aserver, afs_int32 apart, afs_uint32 avolid) afs_int32 ttid = 0, btid = 0; afs_uint32 backupID; afs_int32 code = 0, rcode = 0; + char vname[VOLSER_MAXVOLNAME + 1]; struct nvldbentry entry, storeEntry; afs_int32 error = 0; - int vldblocked = 0, vldbmod = 0; + int vldblocked = 0, vldbmod = 0, backexists = 1; aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT); @@ -2701,14 +2825,82 @@ UV_BackupVolume(afs_uint32 aserver, afs_int32 apart, afs_uint32 avolid) vldbmod = 1; } - code = DoVolClone(aconn, avolid, apart, backupVolume, backupID, "backup", - entry.name, NULL, ".backup", NULL, NULL); + /* Test to see if the backup volume exists by trying to create + * a transaction on the backup volume. We've assumed the backup exists. + */ + code = AFSVolTransCreate_retry(aconn, backupID, apart, ITOffline, &btid); + if (code) { + if (code != VNOVOL) { + fprintf(STDERR, "Could not reach the backup volume %lu\n", + (unsigned long)backupID); + error = code; + goto bfail; + } + backexists = 0; /* backup volume does not exist */ + } + if (btid) { + code = AFSVolEndTrans(aconn, btid, &rcode); + btid = 0; + if (code || rcode) { + fprintf(STDERR, + "Could not end transaction on the previous backup volume %lu\n", + (unsigned long)backupID); + error = (code ? code : rcode); + goto bfail; + } + } + + /* Now go ahead and try to clone the RW volume. + * First start a transaction on the RW volume + */ + code = AFSVolTransCreate_retry(aconn, avolid, apart, ITBusy, &ttid); if (code) { + fprintf(STDERR, "Could not start a transaction on the volume %lu\n", + (unsigned long)avolid); error = code; goto bfail; } - /* Mark vldb as backup exists */ + /* Clone or reclone the volume, depending on whether the backup + * volume exists or not + */ + if (backexists) { + VPRINT1("Re-cloning backup volume %u ...", backupID); + + code = AFSVolReClone(aconn, ttid, backupID); + if (code) { + fprintf(STDERR, "Could not re-clone backup volume %lu\n", + (unsigned long)backupID); + error = code; + goto bfail; + } + } else { + VPRINT1("Creating a new backup clone %u ...", backupID); + + strcpy(vname, entry.name); + strcat(vname, ".backup"); + + code = AFSVolClone(aconn, ttid, 0, backupVolume, vname, &backupID); + if (code) { + fprintf(STDERR, "Failed to clone the volume %lu\n", + (unsigned long)avolid); + error = code; + goto bfail; + } + } + + /* End the transaction on the RW volume */ + code = AFSVolEndTrans(aconn, ttid, &rcode); + ttid = 0; + if (code || rcode) { + fprintf(STDERR, + "Failed to end the transaction on the rw volume %lu\n", + (unsigned long)avolid); + error = (code ? code : rcode); + goto bfail; + } + + /* Mork vldb as backup exists */ if (!(entry.flags & BACK_EXISTS)) { entry.flags |= BACK_EXISTS; vldbmod = 1; @@ -2824,6 +3016,7 @@ UV_CloneVolume(afs_uint32 aserver, afs_int32 apart, afs_uint32 avolid, afs_int32 code = 0, rcode = 0; char vname[VOLSER_MAXVOLNAME + 1]; afs_int32 error = 0; + int backexists = 1; volEntries volumeInfo; int type = 0; @@ -2848,28 +3041,94 @@ UV_CloneVolume(afs_uint32 aserver, afs_int32 apart, afs_uint32 avolid, free(volumeInfo.volEntries_val); } - if (!acloneid) { - /* Get a clone id */ - VPRINT1("Allocating new volume id for clone of volume %u ...", - avolid); - code = ubik_VL_GetNewVolumeId(cstruct, 0, 1, &acloneid); - EGOTO1(bfail, code, - "Could not get an ID for the clone of volume %u from the VLDB\n", - avolid); - VDONE; + if (!acloneid) { + /* Get a clone id */ + VPRINT1("Allocating new volume id for clone of volume %u ...", + avolid); + code = ubik_VL_GetNewVolumeId(cstruct, 0, 1, &acloneid); + EGOTO1(bfail, code, + "Could not get an ID for the clone of volume %u from the VLDB\n", + avolid); + VDONE; + } + + /* Test to see if the clone volume exists by trying to create + * a transaction on the clone volume. We've assumed the clone exists. + */ + /* XXX I wonder what happens if the clone has some other parent... */ + code = AFSVolTransCreate_retry(aconn, acloneid, apart, ITOffline, &btid); + if (code) { + if (code != VNOVOL) { + fprintf(STDERR, "Could not reach the clone volume %lu\n", + (unsigned long)acloneid); + error = code; + goto bfail; + } + backexists = 0; /* backup volume does not exist */ + } + if (btid) { + code = AFSVolEndTrans(aconn, btid, &rcode); + btid = 0; + if (code || rcode) { + fprintf(STDERR, + "Could not end transaction on the previous clone volume %lu\n", + (unsigned long)acloneid); + error = (code ? code : rcode); + goto bfail; + } + } + + /* Now go ahead and try to clone the RW volume. + * First start a transaction on the RW volume + */ + code = AFSVolTransCreate_retry(aconn, avolid, apart, ITBusy, &ttid); + if (code) { + fprintf(STDERR, "Could not start a transaction on the volume %lu\n", + (unsigned long)avolid); + error = code; + goto bfail; + } + + /* Clone or reclone the volume, depending on whether the backup + * volume exists or not + */ + if (backexists) { + VPRINT1("Re-cloning clone volume %u ...", acloneid); + + code = AFSVolReClone(aconn, ttid, acloneid); + if (code) { + fprintf(STDERR, "Could not re-clone backup volume %lu\n", + (unsigned long)acloneid); + error = code; + goto bfail; + } + } else { + VPRINT1("Creating a new clone %u ...", acloneid); + + if (flags & RV_RWONLY) + type = readwriteVolume; + else if (flags & RV_RDONLY) + type = readonlyVolume; + else + type = backupVolume; + + code = AFSVolClone(aconn, ttid, 0, type, aname, &acloneid); + if (code) { + fprintf(STDERR, "Failed to clone the volume %lu\n", + (unsigned long)avolid); + error = code; + goto bfail; + } } - if (flags & RV_RWONLY) - type = readwriteVolume; - else if (flags & RV_RDONLY) - type = readonlyVolume; - else - type = backupVolume; - - code = DoVolClone(aconn, avolid, apart, type, acloneid, "clone", - NULL, ".clone", NULL, NULL, NULL); - if (code) { - error = code; + /* End the transaction on the RW volume */ + code = AFSVolEndTrans(aconn, ttid, &rcode); + ttid = 0; + if (code || rcode) { + fprintf(STDERR, + "Failed to end the transaction on the rw volume %lu\n", + (unsigned long)avolid); + error = (code ? code : rcode); goto bfail; } @@ -2934,6 +3193,34 @@ UV_CloneVolume(afs_uint32 aserver, afs_int32 apart, afs_uint32 avolid, return error; } +static int +DelVol(struct rx_connection *conn, afs_uint32 vid, afs_int32 part, + afs_int32 flags) +{ + afs_int32 acode, ccode, rcode, tid; + ccode = rcode = tid = 0; + + acode = AFSVolTransCreate_retry(conn, vid, part, flags, &tid); + if (!acode) { /* It really was there */ + acode = AFSVolDeleteVolume(conn, tid); + if (acode) { + fprintf(STDERR, "Failed to delete volume %lu.\n", + (unsigned long)vid); + PrintError("", acode); + } + ccode = AFSVolEndTrans(conn, tid, &rcode); + if (!ccode) + ccode = rcode; + if (ccode) { + fprintf(STDERR, "Failed to end transaction on volume %lu.\n", + (unsigned long)vid); + PrintError("", ccode); + } + } + + return acode; +} + #define ONERROR(ec, ep, es) do { \ if (ec) { \ fprintf(STDERR, (es), (ep)); \ @@ -2961,7 +3248,7 @@ static int GetTrans(struct nvldbentry *vldbEntryPtr, afs_int32 index, struct rx_connection **connPtr, afs_int32 * transPtr, afs_uint32 * crtimePtr, afs_uint32 * uptimePtr, - afs_int32 *origflags, afs_uint32 tmpVolId) + afs_int32 *origflags) { afs_uint32 volid; struct volser_status tstatus; @@ -2980,7 +3267,6 @@ GetTrans(struct nvldbentry *vldbEntryPtr, afs_int32 index, goto fail; /* server is down */ volid = vldbEntryPtr->volumeId[ROVOL]; - if (volid) { code = AFSVolTransCreate_retry(*connPtr, volid, @@ -3038,15 +3324,12 @@ GetTrans(struct nvldbentry *vldbEntryPtr, afs_int32 index, } strcpy(volname, vldbEntryPtr->name); - if (tmpVolId) - strcat(volname, ".roclone"); - else - strcat(volname, ".readonly"); + strcat(volname, ".readonly"); if (verbose) { fprintf(STDOUT, "Creating new volume %lu on replication site %s: ", - tmpVolId?(unsigned long)tmpVolId:(unsigned long)volid, + (unsigned long)volid, noresolve ? afs_inet_ntoa_r(vldbEntryPtr-> serverNumber[index], hoststr) : hostutil_GetNameByINet(vldbEntryPtr-> @@ -3055,11 +3338,10 @@ GetTrans(struct nvldbentry *vldbEntryPtr, afs_int32 index, } code = - AFSVolCreateVolume(*connPtr, vldbEntryPtr->serverPartition[index], - volname, volser_RO, - vldbEntryPtr->volumeId[RWVOL], - tmpVolId?&tmpVolId:&volid, - transPtr); + AFSVolCreateVolume(*connPtr, vldbEntryPtr->serverPartition[index], + volname, volser_RO, + vldbEntryPtr->volumeId[RWVOL], &volid, + transPtr); if (code) { PrintError("Failed to create the ro volume: ", code); goto fail; @@ -3093,20 +3375,6 @@ GetTrans(struct nvldbentry *vldbEntryPtr, afs_int32 index, code); goto fail; } - if (tmpVolId) { - code = AFSVolEndTrans(*connPtr, *transPtr, &rcode); - *transPtr = 0; - if (!code) - code = rcode; - if (!code) - code = DoVolClone(*connPtr, volid, - vldbEntryPtr->serverPartition[index], - readonlyVolume, tmpVolId, "temporary", - vldbEntryPtr->name, NULL, ".roclone", NULL, - transPtr); - if (code) - goto fail; - } *crtimePtr = CLOCKADJ(tstatus.creationDate); *uptimePtr = CLOCKADJ(tstatus.updateDate); } @@ -3119,7 +3387,7 @@ GetTrans(struct nvldbentry *vldbEntryPtr, afs_int32 index, *transPtr = 0; if (!tcode) tcode = rcode; - if (tcode && tcode != ENOENT) + if (tcode) PrintError("Could not end transaction on a ro volume: ", tcode); } @@ -3208,73 +3476,6 @@ CheckTrans(struct rx_connection *aconn, afs_int32 *atid, afs_int32 apart, return 0; } -static void -PutTrans(afs_int32 *vldbindex, struct replica *replicas, - struct rx_connection **toconns, struct release *times, - afs_int32 volcount) -{ - afs_int32 s, code = 0, rcode = 0; - /* End the transactions and destroy the connections */ - for (s = 0; s < volcount; s++) { - if (replicas[s].trans) { - code = AFSVolEndTrans(toconns[s], replicas[s].trans, &rcode); - - replicas[s].trans = 0; - if (!code) - code = rcode; - if (code) { - if ((s == 0) || (code != ENOENT)) { - PrintError("Could not end transaction on a ro volume: ", - code); - } else { - PrintError - ("Transaction timed out on a ro volume. Will retry.\n", - 0); - if (times[s].vldbEntryIndex < *vldbindex) - *vldbindex = times[s].vldbEntryIndex; - } - } - } - if (toconns[s]) - rx_DestroyConnection(toconns[s]); - toconns[s] = 0; - } -} - -static int -DoVolOnline(struct nvldbentry *vldbEntryPtr, afs_uint32 avolid, int index, - char *vname, struct rx_connection *connPtr) -{ - afs_int32 code = 0, rcode = 0, onlinetid = 0; - - code = - AFSVolTransCreate_retry(connPtr, avolid, - vldbEntryPtr->serverPartition[index], - ITOffline, - &onlinetid); - if (code) - EPRINT(code, "Could not create transaction on readonly...\n"); - - else { - code = AFSVolSetFlags(connPtr, onlinetid, 0); - if (code) - EPRINT(code, "Could not set flags on readonly...\n"); - } - - if (!code) { - code = - AFSVolSetIdsTypes(connPtr, onlinetid, vname, - ROVOL, vldbEntryPtr->volumeId[RWVOL], - 0, 0); - if (code) - EPRINT(code, "Could not set ids on readonly...\n"); - } - if (!code) - code = AFSVolEndTrans(connPtr, onlinetid, &rcode); - if (!code) - code = rcode; - return code; -} /* UV_ReleaseVolume() * Release volume on to all @@ -3292,15 +3493,15 @@ DoVolOnline(struct nvldbentry *vldbEntryPtr, afs_uint32 avolid, int index, int UV_ReleaseVolume(afs_uint32 afromvol, afs_uint32 afromserver, - afs_int32 afrompart, int forceflag, int stayUp) + afs_int32 afrompart, int forceflag) { char vname[64]; afs_int32 code = 0; afs_int32 vcode, rcode, tcode; - afs_uint32 cloneVolId = 0, roVolId; + afs_uint32 cloneVolId, roVolId; struct replica *replicas = 0; struct nvldbentry entry, storeEntry; - int i, volcount = 0, m, fullrelease, vldbindex; + int i, volcount, m, fullrelease, vldbindex; int failure; struct restoreCookie cookie; struct rx_connection **toconns = 0; @@ -3403,29 +3604,6 @@ UV_ReleaseVolume(afs_uint32 afromvol, afs_uint32 afromserver, code = VolumeExists(afromserver, afrompart, cloneVolId); roexists = ((code == ENODEV) ? 0 : 1); - /* For stayUp case, if roclone is the only site, bypass special handling */ - if (stayUp && roclone) { - int e; - error = 0; - - for (e = 0; (e < entry.nServers) && !error; e++) { - if ((entry.serverFlags[e] & ITSROVOL)) { - if (!(VLDB_IsSameAddrs(entry.serverNumber[e], afromserver, - &error))) - break; - } - } - if (e >= entry.nServers) - stayUp = 0; - } - - /* If we had a previous release to complete, do so, else: */ - if (stayUp && (cloneVolId == entry.volumeId[ROVOL])) { - code = ubik_VL_GetNewVolumeId(cstruct, 0, 1, &cloneVolId); - ONERROR(code, afromvol, - "Cannot get temporary clone id for volume %u\n"); - } - fromconn = UV_Bind(afromserver, AFSCONF_VOLUMEPORT); if (!fromconn) ONERROR(-1, afromserver, @@ -3500,22 +3678,9 @@ UV_ReleaseVolume(afs_uint32 afromvol, afs_uint32 afromserver, * (it was recently added), then also delete it. We do not * want to "reclone" a temporary RO clone. */ - if (stayUp) { - code = VolumeExists(afromserver, afrompart, cloneVolId); - if (!code) { - code = DoVolDelete(fromconn, cloneVolId, afrompart, "previous clone", 0, - NULL, NULL); - if (code && (code != VNOVOL)) - ERROREXIT(code); - VDONE; - } - } - /* clean up any previous tmp clone before starting if staying up */ if (roexists && (!roclone || (entry.serverFlags[roindex] & RO_DONTUSE))) { - code = DoVolDelete(fromconn, - stayUp ? entry.volumeId[ROVOL] : cloneVolId, - afrompart, "the", 0, NULL, NULL); + code = DelVol(fromconn, cloneVolId, afrompart, ITOffline); if (code && (code != VNOVOL)) ERROREXIT(code); roexists = 0; @@ -3532,30 +3697,54 @@ UV_ReleaseVolume(afs_uint32 afromvol, afs_uint32 afromserver, entry.serverFlags[rwindex] |= NEW_REPSITE; entry.serverFlags[rwindex] &= ~RO_DONTUSE; - if (roclone) { - strcpy(vname, entry.name); - if (stayUp) - strcat(vname, ".roclone"); - else - strcat(vname, ".readonly"); + /* Begin transaction on RW and mark it busy while we clone it */ + code = + AFSVolTransCreate_retry(fromconn, afromvol, afrompart, ITBusy, + &clonetid); + ONERROR(code, afromvol, "Failed to start transaction on volume %u\n"); + + /* Clone or reclone the volume */ + if (roexists) { + VPRINT1("Recloning RW volume %u...", cloneVolId); + code = AFSVolReClone(fromconn, clonetid, cloneVolId); + ONERROR(code, afromvol, "Failed to reclone the RW volume %u\n"); + VDONE; } else { - strcpy(vname, "readonly-clone-temp"); - } - - code = DoVolClone(fromconn, afromvol, afrompart, readonlyVolume, - cloneVolId, (roclone && !stayUp)?"permanent RO": - "temporary RO", NULL, vname, NULL, &volstatus, NULL); - if (code) { - error = code; - goto rfail; + if (roclone) { + strcpy(vname, entry.name); + strcat(vname, ".readonly"); + VPRINT1("Cloning RW volume %u to permanent RO...", afromvol); + } else { + strcpy(vname, "readonly-clone-temp"); + VPRINT1("Cloning RW volume %u to temporary RO...", afromvol); + } + code = + AFSVolClone(fromconn, clonetid, 0, readonlyVolume, vname, + &cloneVolId); + ONERROR(code, afromvol, "Failed to clone the RW volume %u\n"); + VDONE; } + /* Get the time the RW was created for future information */ + VPRINT1("Getting status of RW volume %u...", afromvol); + code = AFSVolGetStatus(fromconn, clonetid, &volstatus); + ONERROR(code, afromvol, + "Failed to get the status of the RW volume %u\n"); + VDONE; rwcrdate = volstatus.creationDate; + /* End the transaction on the RW volume */ + VPRINT1("Ending cloning transaction on RW volume %u...", afromvol); + code = AFSVolEndTrans(fromconn, clonetid, &rcode); + clonetid = 0; + ONERROR((code ? code : rcode), afromvol, + "Failed to end cloning transaction on RW %u\n"); + VDONE; + /* Remember clone volume ID in case we fail or are interrupted */ entry.cloneId = cloneVolId; - if (roclone && !stayUp) { + if (roclone) { /* Bring the RO clone online - though not if it's a temporary clone */ VPRINT1("Starting transaction on RO clone volume %u...", cloneVolId); @@ -3617,21 +3806,14 @@ UV_ReleaseVolume(afs_uint32 afromvol, afs_uint32 afromserver, */ strcpy(vname, entry.name); - if (stayUp) - strcat(vname, ".roclone"); - else - strcat(vname, ".readonly"); + strcat(vname, ".readonly"); memset(&cookie, 0, sizeof(cookie)); strncpy(cookie.name, vname, VOLSER_OLDMAXVOLNAME); cookie.type = ROVOL; cookie.parent = entry.volumeId[RWVOL]; cookie.clone = 0; - /* how many to do at once, excluding clone */ - if (stayUp) - nservers = entry.nServers; /* can do all, none offline */ - else - nservers = entry.nServers / 2; + nservers = entry.nServers / 2; /* how many to do at once, excluding clone */ replicas = (struct replica *)malloc(sizeof(struct replica) * nservers + 1); times = (struct release *)malloc(sizeof(struct release) * nservers + 1); @@ -3663,30 +3845,20 @@ UV_ReleaseVolume(afs_uint32 afromvol, afs_uint32 afromserver, ONERROR0(code, "Failed to create transaction on the release clone\n"); VDONE; - /* if we have a clone, treat this as done, for now */ - if (stayUp && !fullrelease) { - entry.serverFlags[roindex] |= NEW_REPSITE; - entry.serverFlags[roindex] &= ~RO_DONTUSE; - entry.flags |= RO_EXISTS; - - releasecount++; - } - /* For each index in the VLDB */ for (vldbindex = 0; vldbindex < entry.nServers;) { - /* Get a transaction on the replicas. Pick replicas which have an old release. */ + + /* Get a transaction on the replicas. Pick replacas which have an old release. */ for (volcount = 0; ((volcount < nservers) && (vldbindex < entry.nServers)); vldbindex++) { - if (!stayUp) { - /* The first two RO volumes will be released individually. - * The rest are then released in parallel. This is a hack - * for clients not recognizing right away when a RO volume - * comes back on-line. - */ - if ((volcount == 1) && (releasecount < 2)) - break; - } + /* The first two RO volumes will be released individually. + * The rest are then released in parallel. This is a hack + * for clients not recognizing right away when a RO volume + * comes back on-line. + */ + if ((volcount == 1) && (releasecount < 2)) + break; if (vldbindex == roindex) continue; /* the clone */ @@ -3713,7 +3885,7 @@ UV_ReleaseVolume(afs_uint32 afromvol, afs_uint32 afromserver, &(replicas[volcount].trans), &(times[volcount].crtime), &(times[volcount].uptime), - origflags, stayUp?cloneVolId:0); + origflags); if (code) continue; @@ -3771,8 +3943,7 @@ UV_ReleaseVolume(afs_uint32 afromvol, afs_uint32 afromserver, if (verbose) { fprintf(STDOUT, "Starting ForwardMulti from %lu to %u on %s", - (unsigned long)cloneVolId, stayUp? - cloneVolId:entry.volumeId[ROVOL], + (unsigned long)cloneVolId, entry.volumeId[ROVOL], noresolve ? afs_inet_ntoa_r(entry.serverNumber[times[0]. vldbEntryIndex], hoststr) : hostutil_GetNameByINet(entry. @@ -3859,166 +4030,36 @@ UV_ReleaseVolume(afs_uint32 afromvol, afs_uint32 afromserver, } } - if (!stayUp) { - PutTrans(&vldbindex, replicas, toconns, times, volcount); - MapNetworkToHost(&entry, &storeEntry); - vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry, 0); - ONERROR(vcode, afromvol, - " Could not update VLDB entry for volume %u\n"); - } - } /* for each index in the vldb */ - - /* for the stayup case, put back at the end */ - if (stayUp) { - afs_uint32 tmpVol = entry.volumeId[ROVOL]; - strcpy(vname, entry.name); - strcat(vname, ".readonly"); - - if (roclone) { - /* have to clear flags to ensure new vol goes online - */ - code = AFSVolSetFlags(fromconn, fromtid, 0); - if (code && (code != ENOENT)) { - PrintError("Failed to set flags on ro volume: ", - code); - } - - VPRINT3("%sloning to permanent RO %u on %s...", roexists?"Re-c":"C", tmpVol, - noresolve ? - afs_inet_ntoa_r(entry.serverNumber[roindex], - hoststr) : - hostutil_GetNameByINet(entry.serverNumber[roindex])); - - code = AFSVolClone(fromconn, fromtid, roexists?tmpVol:0, - readonlyVolume, vname, &tmpVol); - - if (!code) { - VDONE; - VPRINT("Bringing readonly online..."); - code = DoVolOnline(&entry, tmpVol, roindex, vname, - fromconn); - } - if (code) { - EPRINT(code, "Failed: "); - entry.serverFlags[roindex] &= ~NEW_REPSITE; - entry.serverFlags[roindex] |= RO_DONTUSE; - } else { - entry.serverFlags[roindex] |= NEW_REPSITE; - entry.serverFlags[roindex] &= ~RO_DONTUSE; - entry.flags |= RO_EXISTS; - VDONE; - } - - } + /* End the transactions and destroy the connections */ for (s = 0; s < volcount; s++) { - if (replicas[s].trans) { - vldbindex = times[s].vldbEntryIndex; - - /* ok, so now we have to end the previous transaction */ + if (replicas[s].trans) code = AFSVolEndTrans(toconns[s], replicas[s].trans, &rcode); - if (!code) - code = rcode; - - if (!code) { - code = AFSVolTransCreate_retry(toconns[s], - cloneVolId, - entry.serverPartition[vldbindex], - ITBusy, - &(replicas[s].trans)); - if (code) { - PrintError("Unable to begin transaction on temporary clone: ", code); - } - } else { - PrintError("Unable to end transaction on temporary clone: ", code); - } - - VPRINT3("%sloning to permanent RO %u on %s...", times[s].crtime?"Re-c":"C", - tmpVol, noresolve ? - afs_inet_ntoa_r(htonl(replicas[s].server.destHost), - hoststr) : - hostutil_GetNameByINet(htonl(replicas[s].server.destHost))); - if (times[s].crtime) - code = AFSVolClone(toconns[s], replicas[s].trans, tmpVol, - readonlyVolume, vname, &tmpVol); - else - code = AFSVolClone(toconns[s], replicas[s].trans, 0, - readonlyVolume, vname, &tmpVol); - - if (code) { - if (!times[s].crtime) { - entry.serverFlags[vldbindex] |= RO_DONTUSE; - } - entry.serverFlags[vldbindex] &= ~NEW_REPSITE; - PrintError("Failed: ", + replicas[s].trans = 0; + if (!code) + code = rcode; + if (code) { + if ((s == 0) || (code != ENOENT)) { + PrintError("Could not end transaction on a ro volume: ", code); - } else - VDONE; - - if (entry.serverFlags[vldbindex] != RO_DONTUSE) { - /* bring it online (mark it InService) */ - VPRINT1("Bringing readonly online on %s...", - noresolve ? - afs_inet_ntoa_r( - htonl(replicas[s].server.destHost), - hoststr) : - hostutil_GetNameByINet( - htonl(replicas[s].server.destHost))); - - code = DoVolOnline(&entry, tmpVol, vldbindex, vname, - toconns[s]); - /* needed to come online for cloning */ - if (code) { - /* technically it's still new, just not online */ - entry.serverFlags[s] &= ~NEW_REPSITE; - entry.serverFlags[s] |= RO_DONTUSE; - if (code != ENOENT) { - PrintError("Failed to set correct names and ids: ", - code); - } - } else - VDONE; - } - - VPRINT("Marking temporary clone for deletion...\n"); - code = AFSVolSetFlags(toconns[s], - replicas[s].trans, - VTDeleteOnSalvage | - VTOutOfService); - if (code) - EPRINT(code, "Failed: "); - else - VDONE; - - VPRINT("Ending transaction on temporary clone...\n"); - code = AFSVolEndTrans(toconns[s], replicas[s].trans, &rcode); - if (!code) - rcode = code; - if (code) - PrintError("Failed: ", code); - else { - VDONE; - /* ended successfully */ - replicas[s].trans = 0; - - VPRINT2("Deleting temporary clone %u on %s...", cloneVolId, - noresolve ? - afs_inet_ntoa_r(htonl(replicas[s].server.destHost), - hoststr) : - hostutil_GetNameByINet(htonl(replicas[s].server.destHost))); - code = DoVolDelete(toconns[s], cloneVolId, - entry.serverPartition[vldbindex], - NULL, 0, NULL, NULL); - if (code) { - EPRINT(code, "Failed: "); - } else - VDONE; + } else { + PrintError + ("Transaction timed out on a ro volume. Will retry.\n", + 0); + if (times[s].vldbEntryIndex < vldbindex) + vldbindex = times[s].vldbEntryIndex; } } + + if (toconns[s]) + rx_DestroyConnection(toconns[s]); + toconns[s] = 0; } - /* done. put the vldb entry in the success tail case*/ - PutTrans(&vldbindex, replicas, toconns, times, volcount); - } + MapNetworkToHost(&entry, &storeEntry); + vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry, 0); + ONERROR(vcode, afromvol, + " Could not update VLDB entry for volume %u\n"); + } /* for each index in the vldb */ /* End the transaction on the cloned volume */ code = AFSVolEndTrans(fromconn, fromtid, &rcode); @@ -4046,6 +4087,7 @@ UV_ReleaseVolume(afs_uint32 afromvol, afs_uint32 afromserver, hostutil_GetNameByINet(entry.serverNumber[i]), pname); } } + MapNetworkToHost(&entry, &storeEntry); vcode = VLDB_ReplaceEntry(afromvol, RWVOL, &storeEntry, @@ -4056,19 +4098,18 @@ UV_ReleaseVolume(afs_uint32 afromvol, afs_uint32 afromserver, ERROREXIT(VOLSERBADRELEASE); } - entry.cloneId = 0; /* All the ROs were release successfully. Remove the temporary clone */ - if (!roclone || stayUp) { + if (!roclone) { if (verbose) { fprintf(STDOUT, "Deleting the releaseClone %lu ...", (unsigned long)cloneVolId); fflush(STDOUT); } - code = DoVolDelete(fromconn, cloneVolId, afrompart, NULL, 0, NULL, - NULL); + code = DelVol(fromconn, cloneVolId, afrompart, ITOffline); ONERROR(code, cloneVolId, "Failed to delete volume %u.\n"); VDONE; } + entry.cloneId = 0; for (i = 0; i < entry.nServers; i++) entry.serverFlags[i] &= ~NEW_REPSITE; @@ -4527,12 +4568,36 @@ UV_RestoreVolume2(afs_uint32 toserver, afs_int32 topart, afs_uint32 tovolid, &totid); if (code) { if (flags & RV_FULLRST) { /* full restore: delete then create anew */ - code = DoVolDelete(toconn, pvolid, topart, "the previous", 0, - &tstatus, NULL); - if (code && code != VNOVOL) { - error = code; - goto refail; - } + VPRINT1("Deleting the previous volume %u ...", pvolid); + + code = + AFSVolTransCreate_retry(toconn, pvolid, topart, ITOffline, &totid); + EGOTO1(refail, code, "Failed to start transaction on %u\n", + pvolid); + + code = AFSVolGetStatus(toconn, totid, &tstatus); + EGOTO1(refail, code, "Could not get timestamp from volume %u\n", + pvolid); + + oldCreateDate = tstatus.creationDate; + oldUpdateDate = tstatus.updateDate; + + code = + AFSVolSetFlags(toconn, totid, + VTDeleteOnSalvage | VTOutOfService); + EGOTO1(refail, code, "Could not set flags on volume %u \n", + pvolid); + + code = AFSVolDeleteVolume(toconn, totid); + EGOTO1(refail, code, "Could not delete volume %u\n", pvolid); + + code = AFSVolEndTrans(toconn, totid, &rcode); + totid = 0; + if (!code) + code = rcode; + EGOTO1(refail, code, "Could not end transaction on %u\n", pvolid); + + VDONE; code = AFSVolCreateVolume(toconn, topart, tovolreal, volsertype, pparentid, @@ -4548,9 +4613,9 @@ UV_RestoreVolume2(afs_uint32 toserver, afs_int32 topart, afs_uint32 tovolid, EGOTO1(refail, code, "Could not get timestamp from volume %u\n", pvolid); + oldCreateDate = tstatus.creationDate; + oldUpdateDate = tstatus.updateDate; } - oldCreateDate = tstatus.creationDate; - oldUpdateDate = tstatus.updateDate; } else { oldCreateDate = 0; oldUpdateDate = 0; @@ -4762,15 +4827,45 @@ UV_RestoreVolume2(afs_uint32 toserver, afs_int32 topart, afs_uint32 tovolid, noresolve ? afs_inet_ntoa_r(entry.serverNumber[index], hoststr) : hostutil_GetNameByINet(entry.serverNumber[index]), apartName); - code = DoVolDelete(tempconn, pvolid, - entry.serverPartition[index], - "the", 0, NULL, NULL); - if (code && code != VNOVOL) { - error = code; - goto refail; + code = + AFSVolTransCreate_retry(tempconn, pvolid, + entry.serverPartition[index], + ITOffline, &temptid); + if (!code) { + code = + AFSVolSetFlags(tempconn, temptid, + VTDeleteOnSalvage | + VTOutOfService); + if (code) { + fprintf(STDERR, + "Could not set flags on volume %lu on the older site\n", + (unsigned long)pvolid); + error = code; + goto refail; + } + code = AFSVolDeleteVolume(tempconn, temptid); + if (code) { + fprintf(STDERR, + "Could not delete volume %lu on the older site\n", + (unsigned long)pvolid); + error = code; + goto refail; + } + code = AFSVolEndTrans(tempconn, temptid, &rcode); + temptid = 0; + if (!code) + code = rcode; + if (code) { + fprintf(STDERR, + "Could not end transaction on volume %lu on the older site\n", + (unsigned long)pvolid); + error = code; + goto refail; + } + VDONE; + MapPartIdIntoName(entry.serverPartition[index], + partName); } - MapPartIdIntoName(entry.serverPartition[index], - partName); } } entry.serverNumber[index] = toserver; @@ -5224,7 +5319,9 @@ UV_ZapVolumeClones(afs_uint32 aserver, afs_int32 apart, struct volDescription *curPtr; int curPos; afs_int32 code = 0; + afs_int32 rcode = 0; afs_int32 success = 1; + afs_int32 tid; aconn = (struct rx_connection *)0; aconn = UV_Bind(aserver, AFSCONF_VOLUMEPORT); @@ -5233,12 +5330,19 @@ UV_ZapVolumeClones(afs_uint32 aserver, afs_int32 apart, if (curPtr->volFlags & CLONEVALID) { curPtr->volFlags &= ~CLONEZAPPED; success = 1; - - code = DoVolDelete(aconn, curPtr->volCloneId, apart, - "clone", 0, NULL, NULL); + code = + AFSVolTransCreate_retry(aconn, curPtr->volCloneId, apart, ITOffline, + &tid); if (code) success = 0; - + else { + code = AFSVolDeleteVolume(aconn, tid); + if (code) + success = 0; + code = AFSVolEndTrans(aconn, tid, &rcode); + if (code || rcode) + success = 0; + } if (success) curPtr->volFlags |= CLONEZAPPED; if (!success) @@ -5248,6 +5352,7 @@ UV_ZapVolumeClones(afs_uint32 aserver, afs_int32 apart, VPRINT2("Clone of %s %u deleted\n", curPtr->volName, curPtr->volCloneId); curPos++; + tid = 0; } } if (aconn) @@ -7161,13 +7266,46 @@ UV_VolserStatus(afs_uint32 server, transDebugInfo ** rpntr, afs_int32 * rcount) int UV_VolumeZap(afs_uint32 server, afs_int32 part, afs_uint32 volid) { - afs_int32 error; + afs_int32 rcode, ttid, error, code; struct rx_connection *aconn; - aconn = UV_Bind(server, AFSCONF_VOLUMEPORT); - error = DoVolDelete(aconn, volid, part, - "the", 0, NULL, NULL); + code = 0; + error = 0; + ttid = 0; + aconn = UV_Bind(server, AFSCONF_VOLUMEPORT); + code = AFSVolTransCreate_retry(aconn, volid, part, ITOffline, &ttid); + if (code) { + fprintf(STDERR, "Could not start transaction on volume %lu\n", + (unsigned long)volid); + error = code; + goto zfail; + } + code = AFSVolDeleteVolume(aconn, ttid); + if (code) { + fprintf(STDERR, "Could not delete volume %lu\n", + (unsigned long)volid); + error = code; + goto zfail; + } + code = AFSVolEndTrans(aconn, ttid, &rcode); + ttid = 0; + if (!code) + code = rcode; + if (code) { + fprintf(STDERR, "Could not end transaction on volume %lu\n", + (unsigned long)volid); + error = code; + goto zfail; + } + zfail: + if (ttid) { + code = AFSVolEndTrans(aconn, ttid, &rcode); + if (!code) + code = rcode; + if (!error) + error = code; + } PrintError("", error); if (aconn) rx_DestroyConnection(aconn);