vos: convertROtoRW - prevent VLDB corruption
authorMark Vitale <mvitale@sinenomine.net>
Mon, 27 Aug 2012 19:11:32 +0000 (15:11 -0400)
committerDerrick Brashear <shadow@dementix.org>
Wed, 5 Sep 2012 16:56:26 +0000 (09:56 -0700)
vos convertROtoRW incorrectly marks the first VLDB entry as the
new RW if the converted RO is not in the VLDB.  Correct this
by creating a new valid RW site in the VLDB entry.

Change-Id: I683ac10db90c2c41717c11c0d86eadc81a935e52
Reviewed-on: http://gerrit.openafs.org/8037
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Derrick Brashear <shadow@dementix.org>

src/volser/vos.c

index 6d2c0b2..273b6f6 100644 (file)
@@ -5650,9 +5650,29 @@ ConvertRO(struct cmd_syndesc *as, void *arock)
        PrintError("convertROtoRW ", code);
        goto error_exit;
     }
-    entry.serverFlags[roindex] = ITSRWVOL;
+    /* 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) {
+       entry.serverFlags[roindex] = ITSRWVOL;
+    } else {
+       /* Add a new site entry for the newly created RW.  It's possible
+        * (but unlikely) that we are already at MAXNSERVERS and that this
+        * new site will invalidate the whole VLDB entry;  however,
+        * VLDB_ReplaceEntry will detect this and return VL_BADSERVER,
+        * so we need no extra guard logic here.
+        */
+       afs_int32 newrwindex = entry.nServers;
+       (entry.nServers)++;
+       entry.serverNumber[newrwindex] = server;
+       entry.serverPartition[newrwindex] = partition;
+       entry.serverFlags[newrwindex] = ITSRWVOL;
+    }
     entry.flags |= RW_EXISTS;
     entry.flags &= ~BACK_EXISTS;
+
+    /* if the old RW was in the VLDB, remove it by decrementing the number */
+    /* of servers, replacing the RW entry with the last entry, and zeroing */
+    /* out the last entry. */
     if (rwserver) {
        (entry.nServers)--;
        if (rwindex != entry.nServers) {