volser: document 'vos restore -readonly' restriction
[openafs.git] / src / volser / vsprocs.c
index b879ebc..a2c00ca 100644 (file)
@@ -159,11 +159,6 @@ do { \
 
 
 /* Protos for static routines */
-#if 0
-static afs_int32 CheckAndDeleteVolume(struct rx_connection *aconn,
-                                     afs_int32 apart, afs_uint32 okvol,
-                                     afs_uint32 delvol);
-#endif
 static int GetTrans(struct nvldbentry *vldbEntryPtr, afs_int32 index,
                    struct rx_connection **connPtr, afs_int32 * transPtr,
                    afs_uint32 * crtimePtr, afs_uint32 * uptimePtr,
@@ -485,57 +480,6 @@ AFSVolTransCreate_retry(struct rx_connection *z_conn,
     return code;
 }
 
-#if 0
-/* if <okvol> is allright(indicated by beibg able to
- * start a transaction, delete the <delvol> */
-static afs_int32
-CheckAndDeleteVolume(struct rx_connection *aconn, afs_int32 apart,
-                    afs_uint32 okvol, afs_uint32 delvol)
-{
-    afs_int32 error, code, tid, rcode;
-    error = 0;
-    code = 0;
-
-    if (okvol == 0) {
-       code = AFSVolTransCreate_retry(aconn, delvol, apart, ITOffline, &tid);
-       if (!error && code)
-           error = code;
-       code = AFSVolDeleteVolume(aconn, tid);
-       if (!error && code)
-           error = code;
-       code = AFSVolEndTrans(aconn, tid, &rcode);
-       if (!code)
-           code = rcode;
-       if (!error && code)
-           error = code;
-       return error;
-    } else {
-       code = AFSVolTransCreate_retry(aconn, okvol, apart, ITOffline, &tid);
-       if (!code) {
-           code = AFSVolEndTrans(aconn, tid, &rcode);
-           if (!code)
-               code = rcode;
-           if (!error && code)
-               error = code;
-           code = AFSVolTransCreate_retry(aconn, delvol, apart, ITOffline, &tid);
-           if (!error && code)
-               error = code;
-           code = AFSVolDeleteVolume(aconn, tid);
-           if (!error && code)
-               error = code;
-           code = AFSVolEndTrans(aconn, tid, &rcode);
-           if (!code)
-               code = rcode;
-           if (!error && code)
-               error = code;
-       } else
-           error = code;
-       return error;
-    }
-}
-
-#endif
-
 /* called by EmuerateEntry, show vldb entry in a reasonable format */
 void
 SubEnumerateEntry(struct nvldbentry *entry)
@@ -545,25 +489,6 @@ SubEnumerateEntry(struct nvldbentry *entry)
     int isMixed = 0;
     char hoststr[16];
 
-#ifdef notdef
-    fprintf(STDOUT, "  readWriteID %-10u ", entry->volumeId[RWVOL]);
-    if (entry->flags & VLF_RWEXISTS)
-       fprintf(STDOUT, " valid \n");
-    else
-       fprintf(STDOUT, " invalid \n");
-    fprintf(STDOUT, "  readOnlyID  %-10u ", entry->volumeId[ROVOL]);
-    if (entry->flags & VLF_ROEXISTS)
-       fprintf(STDOUT, " valid \n");
-    else
-       fprintf(STDOUT, " invalid \n");
-    fprintf(STDOUT, "  backUpID    %-10u ", entry->volumeId[BACKVOL]);
-    if (entry->flags & VLF_BACKEXISTS)
-       fprintf(STDOUT, " valid \n");
-    else
-       fprintf(STDOUT, " invalid \n");
-    if ((entry->cloneId != 0) && (entry->flags & VLF_ROEXISTS))
-       fprintf(STDOUT, "    releaseClone %-10u \n", entry->cloneId);
-#else
     if (entry->flags & VLF_RWEXISTS)
        fprintf(STDOUT, "    RWrite: %-10u", entry->volumeId[RWVOL]);
     if (entry->flags & VLF_ROEXISTS)
@@ -573,7 +498,6 @@ SubEnumerateEntry(struct nvldbentry *entry)
     if ((entry->cloneId != 0) && (entry->flags & VLF_ROEXISTS))
        fprintf(STDOUT, "    RClone: %-10lu", (unsigned long)entry->cloneId);
     fprintf(STDOUT, "\n");
-#endif
     fprintf(STDOUT, "    number of sites -> %lu\n",
            (unsigned long)entry->nServers);
     for (i = 0; i < entry->nServers; i++) {
@@ -868,13 +792,8 @@ UV_AddVLDBEntry(afs_uint32 aserver, afs_int32 apart, char *aname,
     entry.flags = VLF_RWEXISTS;        /* this records that rw volume exists */
     entry.serverFlags[0] = VLSF_RWVOL; /*this rep site has rw  vol */
     entry.volumeId[RWVOL] = aid;
-#ifdef notdef
-    entry.volumeId[ROVOL] = anewid + 1;        /* rw,ro, bk id are related in the default case */
-    entry.volumeId[BACKVOL] = *anewid + 2;
-#else
     entry.volumeId[ROVOL] = 0;
     entry.volumeId[BACKVOL] = 0;
-#endif
     entry.cloneId = 0;
     /*map into right byte order, before passing to xdr, the stuff has to be in host
      * byte order. Xdr converts it into network order */
@@ -1978,21 +1897,6 @@ UV_MoveVolume2(afs_uint32 afromvol, afs_uint32 afromserver, afs_int32 afrompart,
        }
        /* or drop through */
     }
-#ifdef notdef
-    /* This is tricky.  File server is very stupid, and if you mark the volume
-     * as VTOutOfService, it may mark the *good* instance (if you're moving
-     * between partitions on the same machine) as out of service.  Since
-     * we're cleaning this code up in DEcorum, we're just going to kludge around
-     * it for now by removing this call. */
-    /* already out of service, just zap it now */
-    code =
-       AFSVolSetFlags(fromconn, fromtid, VTDeleteOnSalvage | VTOutOfService);
-    if (code) {
-       fprintf(STDERR,
-               "Failed to set the flags to make the old source volume offline\n");
-       goto mfail;
-    }
-#endif
     if (atoserver != afromserver) {
        /* set forwarding pointer for moved volumes */
        VPRINT1("Setting forwarding pointer for volume %u ...", afromvol);
@@ -2033,13 +1937,12 @@ UV_MoveVolume2(afs_uint32 afromvol, afs_uint32 afromserver, afs_int32 afrompart,
     if (!(flags & RV_NOCLONE)) {
        code = DoVolDelete(fromconn, newVol, afrompart,
                           "cloned", 0, NULL, NULL);
-       if (code) {
-           if (code == VNOVOL) {
-               EPRINT1(code, "Failed to start transaction on %u\n", newVol);
-           }
+       if (code && code != VNOVOL) {
            error = code;
            goto mfail;
        }
+
+       code = 0;       /* clone missing? that's okay */
     }
 
     /* fall through */
@@ -2645,13 +2548,12 @@ cpincr:
     if (!(flags & RV_NOCLONE)) {
        code = DoVolDelete(fromconn, cloneVol, afrompart,
                           "cloned", 0, NULL, NULL);
-       if (code) {
-           if (code == VNOVOL) {
-               EPRINT1(code, "Failed to start transaction on %u\n", cloneVol);
-           }
+       if (code && code != VNOVOL) {
            error = code;
            goto mfail;
        }
+
+       code = 0;               /* clone missing? that's ok */
     }
 
     if (!(flags & RV_NOVLDB)) {
@@ -2775,11 +2677,8 @@ cpincr:
 
     /* common cleanup - delete local clone */
     if (cloneVol) {
-       code = DoVolDelete(fromconn, cloneVol, afrompart,
-                          "clone", 0, NULL, "Recovery:");
-       if (code == VNOVOL) {
-           EPRINT1(code, "Recovery: Failed to start transaction on %u\n", cloneVol);
-       }
+       DoVolDelete(fromconn, cloneVol, afrompart, "clone", 0, NULL,
+                   "Recovery:");
     }
 
   done:                        /* routine cleanup */
@@ -3552,7 +3451,7 @@ UV_ReleaseVolume(afs_uint32 afromvol, afs_uint32 afromserver,
     if (entry.volumeId[ROVOL] == INVALID_BID) {
        /* need to get a new RO volume id */
        vcode = ubik_VL_GetNewVolumeId(cstruct, 0, 1, &roVolId);
-       ONERROR(vcode, entry.name, "Cant allocate ID for RO volume of %s\n");
+       ONERROR(vcode, entry.name, "Can't allocate ID for RO volume of %s\n");
 
        entry.volumeId[ROVOL] = roVolId;
        MapNetworkToHost(&entry, &storeEntry);
@@ -4219,7 +4118,8 @@ UV_ReleaseVolume(afs_uint32 afromvol, afs_uint32 afromserver,
        }
        code = DoVolDelete(fromconn, cloneVolId, afrompart, NULL, 0, NULL,
                           NULL);
-       ONERROR(code, cloneVolId, "Failed to delete volume %u.\n");
+       if (code && code != VNOVOL)
+           ONERROR(code, cloneVolId, "Failed to delete volume %u.\n");
        VDONE;
     }
 
@@ -4636,7 +4536,13 @@ UV_RestoreVolume2(afs_uint32 toserver, afs_int32 topart, afs_uint32 tovolid,
                goto refail;
            }
            reuseID = 0;
+       } else if (vcode) {
+           fprintf(STDERR, "Could not fetch the VLDB entry for the volume %s\n",
+                   tovolname);
+           error = vcode;
+           goto refail;
        } else if (flags & RV_RDONLY) {
+           /* -readonly restore is prohibited if an RW already exists */
            if (entry.flags & VLF_RWEXISTS) {
                fprintf(STDERR,
                        "Entry for ReadWrite volume %s already exists!\n",
@@ -4681,41 +4587,40 @@ UV_RestoreVolume2(afs_uint32 toserver, afs_int32 topart, afs_uint32 tovolid,
             noresolve ? afs_inet_ntoa_r(toserver, hoststr) :
            hostutil_GetNameByINet(toserver), partName);
     fflush(STDOUT);
-    code =
-       AFSVolCreateVolume(toconn, topart, tovolreal, volsertype, pparentid, &pvolid,
-                          &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;
-           }
 
-           code =
-               AFSVolCreateVolume(toconn, topart, tovolreal, volsertype, pparentid,
-                                  &pvolid, &totid);
+    /*
+     * Obtain a transaction and get the status of the target volume. Create a new
+     * volume if the target volume does not already exist.
+     */
+    memset(&tstatus, 0, sizeof(tstatus));
+    if ((flags & RV_FULLRST) != 0) {
+       /* Full restore: Delete existing volume then create anew. */
+       code = DoVolDelete(toconn, pvolid, topart, "the previous", 0, &tstatus, NULL);
+       if (code && code != VNOVOL) {
+           error = code;
+           goto refail;
+       }
+       code = AFSVolCreateVolume(toconn, topart, tovolreal, volsertype, pparentid,
+                                 &pvolid, &totid);
+       EGOTO1(refail, code, "Could not create new volume %u\n", pvolid);
+    } else {
+       /* Incremental restore: Obtain a transaction on the existing volume. */
+       code = AFSVolTransCreate_retry(toconn, pvolid, topart, ITOffline, &totid);
+       if (code == 0) {
+           code = AFSVolGetStatus(toconn, totid, &tstatus);
+           EGOTO1(refail, code, "Could not get timestamp from volume %u\n", pvolid);
+       } else if (code == VNOVOL) {
+           code = AFSVolCreateVolume(toconn, topart, tovolreal, volsertype,
+                                     pparentid, &pvolid, &totid);
            EGOTO1(refail, code, "Could not create new volume %u\n", pvolid);
        } else {
-           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);
-
+           EGOTO1(refail, code, "Failed to start transaction on %u\n", pvolid);
        }
-       oldCreateDate = tstatus.creationDate;
-       oldUpdateDate = tstatus.updateDate;
-       oldCloneId = tstatus.cloneID;
-       oldBackupId = tstatus.backupID;
-    } else {
-       oldCreateDate = 0;
-       oldUpdateDate = 0;
     }
+    oldCreateDate = tstatus.creationDate;
+    oldUpdateDate = tstatus.updateDate;
+    oldCloneId = tstatus.cloneID;
+    oldBackupId = tstatus.backupID;
 
     cookie.parent = pparentid;
     cookie.type = voltype;
@@ -5252,7 +5157,8 @@ UV_RemoveSite(afs_uint32 server, afs_int32 part, afs_uint32 volid)
                      LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
            return (vcode);
        }
-       VDONE;
+       fprintf(STDOUT, " done\n");
+       fflush(STDOUT);
     }
     return 0;
 }
@@ -5457,7 +5363,7 @@ UV_GenerateVolumeClones(afs_uint32 aserver, afs_int32 apart,
                VPRINT2("Clone for volume %s %u failed \n", curPtr->volName,
                        curPtr->volId);
            if (code) {
-               curPtr->volFlags &= ~CLONEVALID;        /*cant clone */
+               curPtr->volFlags &= ~CLONEVALID;        /* can't clone */
                curPos++;
                continue;
            }
@@ -5512,7 +5418,6 @@ UV_ListVolumes(afs_uint32 aserver, afs_int32 apart, int all,
     afs_int32 code = 0;
     volEntries volumeInfo;
 
-    code = 0;
     *size = 0;
     *resultPtr = (volintInfo *) 0;
     volumeInfo.volEntries_val = (volintInfo *) 0;      /*this hints the stub to allocate space */
@@ -7074,7 +6979,39 @@ UV_RenameVolume(struct nvldbentry *entry, char oldname[], char newname[])
        goto rvfail;
     }
     islocked = 1;
+
+    /*
+     * Match the flags we just set via SetLock,
+     * so we don't invalidate our compare below.
+     */
+    entry->flags &= ~VLOP_ALLOPERS;
+    entry->flags |= VLOP_ADDSITE;
+
+    /*
+     * Now get the entry again (under lock) and
+     * verify the volume hasn't otherwise changed.
+     */
+    vcode = VLDB_GetEntryByID(entry->volumeId[RWVOL], RWVOL, &storeEntry);
+    if (vcode) {
+       fprintf(STDERR,
+               "Could not obtain the VLDB entry for the volume %u\n",
+               entry->volumeId[RWVOL]);
+       error = vcode;
+       goto rvfail;
+    }
+    /* Convert to net order to match entry, which was passed in net order. */
+    MapHostToNetwork(&storeEntry);
+    if (memcmp(entry, &storeEntry, sizeof(*entry)) != 0) {
+       fprintf(STDERR,
+               "VLDB entry for volume %u has changed; "
+               "please reissue the command.\n",
+               entry->volumeId[RWVOL]);
+       error = VL_BADENTRY;    /* an arbitrary choice, but closest to the truth */
+       goto rvfail;
+    }
+
     strncpy(entry->name, newname, VOLSER_OLDMAXVOLNAME);
+    /* Note that we are reusing storeEntry. */
     MapNetworkToHost(entry, &storeEntry);
     vcode = VLDB_ReplaceEntry(entry->volumeId[RWVOL], RWVOL, &storeEntry, 0);
     if (vcode) {