From 355b8c73ed5adc5c182cf29561cc360ef4674f9e Mon Sep 17 00:00:00 2001 From: Michael Meffie Date: Sat, 28 Jul 2012 11:37:59 -0400 Subject: [PATCH] vlserver: fix vldb header initialization 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 Reviewed-by: Alistair Ferguson Tested-by: BuildBot --- src/vlserver/vlprocs.c | 7 ++++++- src/vlserver/vlutils.c | 20 +++++++++++--------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/vlserver/vlprocs.c b/src/vlserver/vlprocs.c index 0fba51c89..ec0329cc4 100644 --- a/src/vlserver/vlprocs.c +++ b/src/vlserver/vlprocs.c @@ -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 */ } diff --git a/src/vlserver/vlutils.c b/src/vlserver/vlutils.c index cabe98d3d..44b1fe0eb 100644 --- a/src/vlserver/vlutils.c +++ b/src/vlserver/vlutils.c @@ -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); } -- 2.39.5