volser: document 'vos restore -readonly' restriction
[openafs.git] / src / volser / vsprocs.c
index cddacac..a2c00ca 100644 (file)
@@ -1342,14 +1342,6 @@ UV_ConvertRO(afs_uint32 server, afs_uint32 partition, afs_uint32 volid,
        }
     }
 
-    /* volume must be inaccessible during this process */
-    code = UV_SetVolume(server, partition, volid, ITOffline, VTOutOfService, 0);
-    if (code != 0) {
-       fprintf(STDERR, "Taking RO volume %u offline failed with code %d.\n",
-               volid, code);
-       goto error_exit;
-    }
-
     aconn = UV_Bind(server, AFSCONF_VOLUMEPORT);
     code = AFSVolConvertROtoRWvolume(aconn, partition, volid);
     if (code) {
@@ -1359,18 +1351,6 @@ UV_ConvertRO(afs_uint32 server, afs_uint32 partition, afs_uint32 volid,
        PrintError("convertROtoRW ", code);
        goto error_exit;
     }
-
-    /*
-     * Since the inService flag is copied from the RO volume, the new RW copy is
-     * offline. Change the status of this RW volume to online.
-     */
-    code = UV_SetVolume(server, partition, entry->volumeId[RWVOL], ITOffline,
-                       0 /* online */, 0);
-    if (code != 0) {
-       fprintf(STDERR, "Warning: Attempt to set RW volume %u as online failed "
-                       "with code %d.\n", entry->volumeId[RWVOL], code);
-    }
-
     /* Update the VLDB to match what we did on disk as much as possible.  */
     /* If the converted RO was in the VLDB, make it look like the new RW. */
     if (roserver) {
@@ -3471,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);
@@ -4556,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",
@@ -4601,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;
@@ -5172,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;
 }
@@ -5377,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;
            }
@@ -6993,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) {