cellp = cellrockp->cellp;
probe = !(cellrockp->flags & CM_FLAG_NOPROBE);
- /* if this server was previously created by fs setserverprefs */
- if ( tsp = cm_FindServer(addrp, CM_SERVER_VLDB, FALSE))
- {
- if ( !tsp->cellp )
- tsp->cellp = cellp;
- else if (tsp->cellp != cellp) {
- osi_Log3(afsd_logp, "found a vlserver %s associated with two cells named %s and %s",
- osi_LogSaveString(afsd_logp,hostnamep),
- osi_LogSaveString(afsd_logp,tsp->cellp->name),
- osi_LogSaveString(afsd_logp,cellp->name));
- }
- }
- else
- tsp = cm_NewServer(addrp, CM_SERVER_VLDB, cellp, NULL, probe ? 0 : CM_FLAG_NOPROBE);
+ tsp = cm_NewServer(addrp, CM_SERVER_VLDB, cellp, NULL,
+ probe ? 0 : CM_FLAG_NOPROBE);
if (adminRank)
tsp->adminRank = adminRank;
}
if (cp2) {
+ cm_server_t *tsp;
+
if (!hasMutex) {
lock_ObtainMutex(&cp->mx);
hasMutex = 1;
cm_RemoveCellFromNameHashTable(cp);
lock_ReleaseMutex(&cp->mx);
hasMutex = 0;
- cm_FreeCell(cp);
+
+ /* Replace cells references in servers */
+ lock_ObtainRead(&cm_serverLock);
+ for (tsp = cm_serversAllFirstp;
+ tsp;
+ tsp = (cm_server_t *)osi_QNext(&tsp->allq)) {
+ if (tsp->cellp == cp) {
+ osi_Log4(afsd_logp, "cm_GetCell_gen race: replacing cell (%u) %s with cell (%u) %s",
+ cp->cellID,
+ osi_LogSaveString(afsd_logp,cp->name),
+ cp2->cellID,
+ osi_LogSaveString(afsd_logp,cp2->name));
+ tsp->cellp = cp2;
+ }
+ }
+ lock_ReleaseRead(&cm_serverLock);
+
+ cm_FreeCell(cp);
cp = cp2;
goto done;
}
afs_uint32 count1, count2;
for (cellp = cm_data.allCellsp, count1 = 0; cellp; cellp=cellp->allNextp, count1++) {
+
+ if ( cellp < (cm_cell_t *)cm_data.cellBaseAddress ||
+ cellp >= (cm_cell_t *)cm_data.aclBaseAddress) {
+ afsi_log("cm_ValidateCell failure: out of range cm_cell_t pointers");
+ fprintf(stderr, "cm_ValidateCell failure: out of range cm_cell_t pointers\n");
+ return -10;
+ }
+
if ( cellp->magic != CM_CELL_MAGIC ) {
afsi_log("cm_ValidateCell failure: cellp->magic != CM_CELL_MAGIC");
fprintf(stderr, "cm_ValidateCell failure: cellp->magic != CM_CELL_MAGIC\n");
}
for (cellp = cm_data.freeCellsp, count2 = 0; cellp; cellp=cellp->freeNextp, count2++) {
+
+ if ( cellp < (cm_cell_t *)cm_data.cellBaseAddress ||
+ cellp >= (cm_cell_t *)cm_data.aclBaseAddress) {
+ afsi_log("cm_ValidateCell failure: out of range cm_cell_t pointers");
+ fprintf(stderr, "cm_ValidateCell failure: out of range cm_cell_t pointers\n");
+ return -11;
+ }
+
if ( count2 != 0 && cellp == cm_data.freeCellsp ||
count2 > cm_data.maxCells ) {
afsi_log("cm_ValidateCell failure: cm_data.freeCellsp infinite loop");
rock.cellp = cm_GetCell(cellname, CM_FLAG_CREATE | CM_FLAG_NOPROBE);
rock.flags = 0;
- cm_FreeServerList(&rock.cellp->vlServersp, CM_FREESERVERLIST_DELETE);
-
if (!(flags & CM_CELLFLAG_DNS)) {
+ int first = 1;
+
for (i = 0; i < host_count; i++) {
thp = gethostbyname(hostname[i]);
+ if (first) {
+ /*
+ * If there is at least one resolved vlserver or an authoritative,
+ * host not found response, destroy the prior list.
+ */
+ if (thp != NULL || WSAGetLastError() == WSAHOST_NOT_FOUND) {
+ cm_FreeServerList(&rock.cellp->vlServersp, CM_FREESERVERLIST_DELETE);
+ first = 0;
+ }
+ }
+
if (thp) {
- int foundAddr = 0;
+ if (thp->h_addrtype != AF_INET)
+ continue;
+
for (j=0 ; thp->h_addr_list[j]; j++) {
- if (thp->h_addrtype != AF_INET)
- continue;
memcpy(&vlSockAddr.sin_addr.s_addr,
thp->h_addr_list[j],
sizeof(long));
_InterlockedAnd(&rock.cellp->flags, ~CM_CELLFLAG_DNS);
} else if (cm_dnsEnabled) {
int ttl;
+ cm_serverRef_t * vlServersp = NULL;
+
+ lock_ObtainWrite(&cm_serverLock);
+ vlServersp = rock.cellp->vlServersp;
+ rock.cellp->vlServersp = NULL;
+ lock_ReleaseWrite(&cm_serverLock);
code = cm_SearchCellByDNS(rock.cellp->name, NULL, &ttl, cm_AddCellProc, &rock);
lock_ObtainMutex(&rock.cellp->mx);
#ifdef DEBUG
fprintf(stderr, "cell %s: ttl=%d\n", rock.cellp->name, ttl);
#endif
- }
+ } else {
+ lock_ObtainWrite(&cm_serverLock);
+ if (rock.cellp->vlServersp == NULL) {
+ rock.cellp->vlServersp = vlServersp;
+ vlServersp = NULL;
+ }
+ lock_ReleaseWrite(&cm_serverLock);
+ }
+
+ cm_FreeServerList(&vlServersp, CM_FREESERVERLIST_DELETE);
+ if (vlServersp != NULL) {
+ /*
+ * We moved the vlServer list out of the way and
+ * in the meantime it was replaced. If the vlServerp
+ * list is non-Empty after cm_FreeServerList was called
+ * it means that there are deleted entries with active
+ * references. Must put them back onto the list to
+ * avoid leaking the memory.
+ */
+ cm_AppendServerList(rock.cellp->vlServersp, &vlServersp);
+ }
} else {
+ cm_FreeServerList(&rock.cellp->vlServersp, CM_FREESERVERLIST_DELETE);
lock_ObtainMutex(&rock.cellp->mx);
rock.cellp->flags &= ~CM_CELLFLAG_DNS;
}