From: Michael Meffie Date: Wed, 15 Aug 2012 21:19:07 +0000 (-0400) Subject: vldb_check: fix cross-linked mh entries X-Git-Tag: upstream/1.8.0_pre1^2~2071 X-Git-Url: https://git.michaelhowe.org/gitweb/?a=commitdiff_plain;h=911f751d1edfb18ddd5f6a699746ba14730d553d;p=packages%2Fo%2Fopenafs.git vldb_check: fix cross-linked mh entries When run with -fix, consolidate server numbers in vl entries which point to the same multi-homed entry. Use the lowest server number from the set of server numbers which point to the same multi-homed entry. Remove unreferenced address entries which are duplicate multi-homed indexes. Two passes of vldb_check -fix may be required; first to fix the vl entry server numbers; then to remove the duplicate address entries. Change-Id: I794cec4c176e8aab98a236a9700f58b1269a99bb Reviewed-on: http://gerrit.openafs.org/7999 Tested-by: BuildBot Reviewed-by: Derrick Brashear --- diff --git a/src/vlserver/vldb_check.c b/src/vlserver/vldb_check.c index dc6dedf77..d944f4949 100644 --- a/src/vlserver/vldb_check.c +++ b/src/vlserver/vldb_check.c @@ -78,6 +78,7 @@ struct er { afs_int32 maxentries; int serveraddrs[MAXSERVERID + 2]; u_char serverxref[MAXSERVERID + 2]; /**< to resolve cross-linked mh entries */ +int serverref[MAXSERVERID + 2]; /**< which addrs are referenced by vl entries */ struct mhinfo { afs_uint32 addr; /**< vldb file record */ @@ -1125,6 +1126,47 @@ reportHashChanges(struct vlheader *header, afs_uint32 oldnamehash[HASHSIZE], afs } } +/** + * Remove unreferenced, duplicate multi-home address indices. + * + * Removes entries from IpMappedAddr which where found to be + * duplicates. Only entries which are not referenced by vl entries + * are removed on this pass. + * + * @param[inout] header the vldb header to be updated. + */ +void +removeCrossLinkedAddresses(struct vlheader *header) +{ + int i; + + for (i = 0; i <= MAXSERVERID; i++) { + if (serverref[i] == 0 + && (header->IpMappedAddr[i] & 0xff000000) == 0xff000000 + && serverxref[i] != BADSERVERID) { + if (serverxref[i] == i) { + log_error(VLDB_CHECK_ERROR, + "INTERNAL VLDB_CHECK_ERROR: serverxref points to self; index %d\n", + i); + } else if (header->IpMappedAddr[serverxref[i]] == 0) { + log_error(VLDB_CHECK_ERROR, + "INTERNAL VLDB_CHECK_ERROR: serverxref points to empty addr; index %d, value %d\n", + i, serverxref[i]); + } else if (header->IpMappedAddr[serverxref[i]] != header->IpMappedAddr[i]) { + log_error(VLDB_CHECK_ERROR, + "INTERNAL VLDB_CHECK_ERROR: invalid serverxref; index %d, value %d\n", + i, serverxref[i]); + } else { + quiet_println + ("FIX: Removing unreferenced address index %d, which cross-links MH block %d, index %d\n", + i, (header->IpMappedAddr[i] & 0x00ff0000) >> 16, + (header->IpMappedAddr[i] & 0x0000ffff)); + header->IpMappedAddr[i] = 0; + } + } + } +} + int WorkerBee(struct cmd_syndesc *as, void *arock) { @@ -1132,7 +1174,7 @@ WorkerBee(struct cmd_syndesc *as, void *arock) afs_int32 type; struct vlheader header; struct nvlentry vlentry, vlentry2; - int i, j; + int i, j, k; afs_uint32 oldnamehash[HASHSIZE]; afs_uint32 oldidhash[MAXTYPES][HASHSIZE]; @@ -1173,6 +1215,7 @@ WorkerBee(struct cmd_syndesc *as, void *arock) record = calloc(maxentries, sizeof(struct er)); memset(serveraddrs, 0, sizeof(serveraddrs)); memset(mhinfo, 0, sizeof(mhinfo)); + memset(serverref, 0, sizeof(serverref)); for (i = 0; i <= MAXSERVERID; i++) { serverxref[i] = BADSERVERID; } @@ -1318,11 +1361,17 @@ WorkerBee(struct cmd_syndesc *as, void *arock) } for (j = 0; j < NMAXNSERVERS; j++) { - if ((vlentry.serverNumber[j] != 255) - && (serveraddrs[vlentry.serverNumber[j]] == 0)) { - log_error - (VLDB_CHECK_ERROR,"Volume '%s', index %d points to empty server entry %d\n", - vlentry.name, j, vlentry.serverNumber[j]); + if (vlentry.serverNumber[j] != BADSERVERID) { + serverref[vlentry.serverNumber[j]] = 1; + if (serveraddrs[vlentry.serverNumber[j]] == 0) { + log_error + (VLDB_CHECK_ERROR,"Volume '%s', index %d points to empty server entry %d\n", + vlentry.name, j, vlentry.serverNumber[j]); + } else if (serverxref[vlentry.serverNumber[j]] != BADSERVERID) { + log_error + (VLDB_CHECK_ERROR,"Volume '%s', index %d points to server entry %d, which is cross-linked by %d\n", + vlentry.name, j, vlentry.serverNumber[j], serverxref[vlentry.serverNumber[j]]); + } } } @@ -1443,6 +1492,36 @@ WorkerBee(struct cmd_syndesc *as, void *arock) } } + /* Consolidate server numbers which point to the same mh entry. + * The serverref flags are not reset here, since we want to make + * sure the data is actually written before the server number is + * considered unreferenced. */ + for (k = 0; k < NMAXNSERVERS; k++) { + if (vlentry.serverNumber[k] != BADSERVERID + && serverxref[vlentry.serverNumber[k]] != BADSERVERID) { + u_char oldsn = vlentry.serverNumber[k]; + u_char newsn = serverxref[oldsn]; + if (newsn == oldsn) { + log_error(VLDB_CHECK_ERROR, + "INTERNAL VLDB_CHECK_ERROR: serverxref points to self; index %d\n", + oldsn); + } else if (header.IpMappedAddr[oldsn] == 0) { + log_error(VLDB_CHECK_ERROR, + "INTERNAL VLDB_CHECK_ERROR: serverxref; points to empty address; index %d, value %d\n", + oldsn, newsn); + } else if (header.IpMappedAddr[newsn] != header.IpMappedAddr[oldsn]) { + log_error(VLDB_CHECK_ERROR, + "INTERNAL VLDB_CHECK_ERROR: invalid serverxref; index %d\n", + oldsn); + } else { + quiet_println + ("FIX: Volume '%s', index %d, server number was %d, is now %d\n", + vlentry.name, k, oldsn, newsn); + vlentry.serverNumber[k] = newsn; + } + } + } + vlentry.nextIdHash[j] = header.VolidHash[j][hash]; header.VolidHash[j][hash] = record[i].addr; } @@ -1476,6 +1555,7 @@ WorkerBee(struct cmd_syndesc *as, void *arock) } if (fix) { reportHashChanges(&header, oldnamehash, oldidhash); + removeCrossLinkedAddresses(&header); writeheader(&header); }