Revert offline-less vos release
authorAndrew Deason <adeason@sinenomine.net>
Thu, 23 Feb 2012 21:53:32 +0000 (15:53 -0600)
committerDerrick Brashear <shadow@dementix.org>
Sun, 26 Feb 2012 16:32:33 +0000 (08:32 -0800)
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 <shadow@dementix.org>
Tested-by: Derrick Brashear <shadow@dementix.org>

doc/man-pages/pod1/vos_release.pod
src/vol/clone.c
src/volser/volprocs.c
src/volser/volser_internal.h
src/volser/vos.c
src/volser/vsprocs.c

index 2421c50..0115dff 100644 (file)
@@ -9,11 +9,11 @@ vos_release - Updates read-only volumes to match the read/write source volume
 
 B<vos release> S<<< B<-id> <I<volume name or ID>> >>> [B<-force>]
     S<<< [B<-cell> <I<cell name>>] >>>
-    [B<-noauth>] [B<-localauth>] [B<-stayonline>]
+    [B<-noauth>] [B<-localauth>]
     [B<-verbose>] [B<-encrypt>] [B<-noresolve>] [B<-help>]
 
 B<vos rel> S<<< B<-i> <I<volume name or ID>> >>>
-    [B<-f>] S<<< [B<-c> <I<cell name>>] >>> [B<-stayon>]
+    [B<-f>] S<<< [B<-c> <I<cell name>>] >>>
     [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
index 3d20b8a..0841302 100644 (file)
@@ -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 */
index 7f7aaa6..95339ad 100644 (file)
@@ -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;
index 1678ac0..26a9e85 100644 (file)
@@ -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,
index 90b9e55..3ee98e4 100644 (file)
@@ -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");
index 4630e9d..cd36295 100644 (file)
@@ -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 <afromvol> on <afromserver> <afrompart> to <atoserver>
  * <atopart>.  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 <afromvol> on <afromserver> <afrompart> 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);