vlserver: fix vldb header initialization
authorMichael Meffie <mmeffie@sinenomine.net>
Sat, 28 Jul 2012 15:37:59 +0000 (11:37 -0400)
committerDerrick Brashear <shadow@dementix.org>
Tue, 14 Aug 2012 13:20:16 +0000 (06:20 -0700)
Avoid creating new vldb files with zeroed header data.

The code path is as follows; The call to Init_VLdbase makes several
passes. On the first pass, the header is found to be empty, and so a
write lock is obtained on the second pass.  On this second pass,
UpdateCache creates a newly initialized header and writes it to the
db.  The rd_cheader is set to the newly created header data, and the
wr_cheader is still cleared at this point.

When the transaction on the second pass ended in Init_VLdbase, the
data is committed and vlsynccache() is called.  In this call to
vlsynccache(), the cleared write header buffer (wr_cheader) is
copied over the newly initialized rd_cheader buffer.  Init_VLdbase
then returns to the caller, and if the caller writes to the db, the
header on disk is then cleared.

Instead of initializing the read header buffer when rebuilding the
db header, initialize the write header buffer. When the ubik
transaction is ended, the call to vlsynccache() updates the contents
of the read header buffer with contents of the new/rebuilt header.

This error was introduced with commits:
  a0f416e3504929b304fefb5ca65e2d6a254ade2e
  1f532d099b8b084d43dd0140890448464325b602

Change-Id: If9c178bf28c55c50311554b12ffff9404785d052
Reviewed-on: http://gerrit.openafs.org/7894
Reviewed-by: Derrick Brashear <shadow@dementix.org>
Reviewed-by: Alistair Ferguson <alistair.ferguson@mac.com>
Tested-by: BuildBot <buildbot@rampaginggeek.com>

src/vlserver/vlprocs.c
src/vlserver/vlutils.c

index 0fba51c..ec0329c 100644 (file)
@@ -243,7 +243,12 @@ Init_VLdbase(struct vl_ctx *ctx,
                return code;
        } else {                /* No code */
            if (pass == 2) {
-               ubik_EndTrans(ctx->trans);      /* Rebuilt db. End trans, then retake original lock */
+               /* The database header was rebuilt; end the write transaction.
+                * This will call vlsynccache() to copy the write header buffers
+                * to the read header buffers, before calling vlsetache().
+                * Do a third pass to re-acquire the original lock, which
+                * may be a read lock. */
+               ubik_EndTrans(ctx->trans);
            } else {
                break;          /* didn't rebuild and successful - exit */
            }
index cabe98d..44b1fe0 100644 (file)
@@ -328,22 +328,24 @@ UpdateCache(struct ubik_trans *trans, void *rock)
            printf("Can't read VLDB header, re-initialising...\n");
 
            /* try to write a good header */
-           memset(&rd_cheader, 0, sizeof(rd_cheader));
-           rd_cheader.vital_header.vldbversion = htonl(VLDBVERSION);
-           rd_cheader.vital_header.headersize = htonl(sizeof(rd_cheader));
+           /* The read cache will be sync'ed to this new header
+            * when the ubik transaction is ended by vlsynccache(). */
+           memset(&wr_cheader, 0, sizeof(wr_cheader));
+           wr_cheader.vital_header.vldbversion = htonl(VLDBVERSION);
+           wr_cheader.vital_header.headersize = htonl(sizeof(wr_cheader));
            /* DANGER: Must get this from a master place!! */
-           rd_cheader.vital_header.MaxVolumeId = htonl(0x20000000);
-           rd_cheader.vital_header.eofPtr = htonl(sizeof(rd_cheader));
+           wr_cheader.vital_header.MaxVolumeId = htonl(0x20000000);
+           wr_cheader.vital_header.eofPtr = htonl(sizeof(wr_cheader));
            for (i = 0; i < MAXSERVERID + 1; i++) {
-               rd_cheader.IpMappedAddr[i] = 0;
-               rd_HostAddress[i] = 0;
+               wr_cheader.IpMappedAddr[i] = 0;
+               wr_HostAddress[i] = 0;
            }
-           code = vlwrite(trans, 0, (char *)&rd_cheader, sizeof(rd_cheader));
+           code = vlwrite(trans, 0, (char *)&wr_cheader, sizeof(wr_cheader));
            if (code) {
                printf("Can't write VLDB header (error = %d)\n", code);
                ERROR_EXIT(VL_IO);
            }
-           vldbversion = ntohl(rd_cheader.vital_header.vldbversion);
+           vldbversion = ntohl(wr_cheader.vital_header.vldbversion);
        } else {
            ERROR_EXIT(VL_EMPTY);
        }