cm_cell_t *cm_GetCell_Gen(char *namep, char *newnamep, afs_uint32 flags) { cm_cell_t *cp, *cp2; long code; char fullname[CELL_MAXNAMELEN]=""; char linkedName[CELL_MAXNAMELEN]=""; char name[CELL_MAXNAMELEN]=""; int hasWriteLock = 0; int hasMutex = 0; afs_uint32 hash; cm_cell_rock_t rock; size_t len; if (namep == NULL || !namep[0] || !strcmp(namep,SMB_IOCTL_FILENAME_NOSLASH)) return NULL; /* * Strip off any trailing dots at the end of the cell name. * Failure to do so results in an undesireable alias as the * result of DNS AFSDB record lookups where a trailing dot * has special meaning. */ strncpy(name, namep, CELL_MAXNAMELEN); for (len = strlen(namep); len > 0 && namep[len-1] == '.'; len--) { name[len-1] = '\0'; } if (len == 0) return NULL; namep = name; hash = CM_CELL_NAME_HASH(namep); lock_ObtainRead(&cm_cellLock); for (cp = cm_data.cellNameHashTablep[hash]; cp; cp=cp->nameNextp) { if (cm_stricmp_utf8(namep, cp->name) == 0) { strncpy(fullname, cp->name, CELL_MAXNAMELEN); fullname[CELL_MAXNAMELEN-1] = '\0'; break; } } if (!cp) { for (cp = cm_data.allCellsp; cp; cp=cp->allNextp) { if (strnicmp(namep, cp->name, strlen(namep)) == 0) { strncpy(fullname, cp->name, CELL_MAXNAMELEN); fullname[CELL_MAXNAMELEN-1] = '\0'; break; } } } if (cp) { lock_ReleaseRead(&cm_cellLock); cm_UpdateCell(cp, flags); } else if (flags & CM_FLAG_CREATE) { lock_ConvertRToW(&cm_cellLock); hasWriteLock = 1; /* when we dropped the lock the cell could have been added * to the list so check again while holding the write lock */ for (cp = cm_data.cellNameHashTablep[hash]; cp; cp=cp->nameNextp) { if (cm_stricmp_utf8(namep, cp->name) == 0) { strncpy(fullname, cp->name, CELL_MAXNAMELEN); fullname[CELL_MAXNAMELEN-1] = '\0'; break; } } if (cp) goto done; for (cp = cm_data.allCellsp; cp; cp=cp->allNextp) { if (strnicmp(namep, cp->name, strlen(namep)) == 0) { strncpy(fullname, cp->name, CELL_MAXNAMELEN); fullname[CELL_MAXNAMELEN-1] = '\0'; break; } } if (cp) { lock_ObtainMutex(&cp->mx); cm_AddCellToNameHashTable(cp); cm_AddCellToIDHashTable(cp); lock_ReleaseMutex(&cp->mx); goto done; } if ( cm_data.freeCellsp != NULL ) { cp = cm_data.freeCellsp; cm_data.freeCellsp = cp->freeNextp; /* * The magic, cellID, and mx fields are already set. */ } else { if ( cm_data.currentCells >= cm_data.maxCells ) osi_panic("Exceeded Max Cells", __FILE__, __LINE__); /* don't increment currentCells until we know that we * are going to keep this entry */ cp = &cm_data.cellBaseAddress[cm_data.currentCells]; memset(cp, 0, sizeof(cm_cell_t)); cp->magic = CM_CELL_MAGIC; /* the cellID cannot be 0 */ cp->cellID = ++cm_data.currentCells; /* otherwise we found the cell, and so we're nearly done */ lock_InitializeMutex(&cp->mx, "cm_cell_t mutex", LOCK_HIERARCHY_CELL); } lock_ReleaseWrite(&cm_cellLock); hasWriteLock = 0; rock.cellp = cp; rock.flags = flags; code = cm_SearchCellFileEx(namep, fullname, linkedName, cm_AddCellProc, &rock); if (code) { osi_Log4(afsd_logp,"in cm_GetCell_gen cm_SearchCellFileEx(%s) returns code= %d fullname= %s linkedName= %s", osi_LogSaveString(afsd_logp,namep), code, osi_LogSaveString(afsd_logp,fullname), osi_LogSaveString(afsd_logp,linkedName)); #ifdef AFS_AFSDB_ENV if (cm_dnsEnabled) { int ttl; code = cm_SearchCellByDNS(namep, fullname, &ttl, cm_AddCellProc, &rock); if ( code ) { osi_Log3(afsd_logp,"in cm_GetCell_gen cm_SearchCellByDNS(%s) returns code= %d fullname= %s", osi_LogSaveString(afsd_logp,namep), code, osi_LogSaveString(afsd_logp,fullname)); cm_FreeCell(cp); cp = NULL; goto done; } else { /* got cell from DNS */ lock_ObtainMutex(&cp->mx); hasMutex = 1; cp->flags |= CM_CELLFLAG_DNS; cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID; cp->timeout = time(0) + ttl; } } else #endif { cm_FreeCell(cp); cp = NULL; goto done; } } else { lock_ObtainMutex(&cp->mx); hasMutex = 1; cp->timeout = time(0) + 7200; /* two hour timeout */ } /* we have now been given the fullname of the cell. It may * be that we already have a cell with that name. If so, * we should use it instead of completing the allocation * of a new cm_cell_t */ hash = CM_CELL_NAME_HASH(fullname); for (cp2 = cm_data.cellNameHashTablep[hash]; cp2; cp2=cp2->nameNextp) { if (cm_stricmp_utf8(fullname, cp2->name) == 0) { break; } } if (cp2) { if (hasMutex) { lock_ReleaseMutex(&cp->mx); hasMutex = 0; } cm_FreeCell(cp); cp = cp2; goto done; } /* randomise among those vlservers having the same rank*/ cm_RandomizeServer(&cp->vlServersp); if (!hasMutex) lock_ObtainMutex(&cp->mx); /* copy in name */ strncpy(cp->name, fullname, CELL_MAXNAMELEN); cp->name[CELL_MAXNAMELEN-1] = '\0'; strncpy(cp->linkedName, linkedName, CELL_MAXNAMELEN); cp->linkedName[CELL_MAXNAMELEN-1] = '\0'; cm_AddCellToNameHashTable(cp); cm_AddCellToIDHashTable(cp); lock_ReleaseMutex(&cp->mx); hasMutex = 0; /* append cell to global list */ if (cm_data.allCellsp == NULL) { cm_data.allCellsp = cp; } else { for (cp2 = cm_data.allCellsp; cp2->allNextp; cp2=cp2->allNextp) ; cp2->allNextp = cp; } cp->allNextp = NULL; } else { lock_ReleaseRead(&cm_cellLock); } done: if (hasMutex && cp) lock_ReleaseMutex(&cp->mx); if (hasWriteLock) lock_ReleaseWrite(&cm_cellLock); /* fullname is not valid if cp == NULL */ if (newnamep) { if (cp) { strncpy(newnamep, fullname, CELL_MAXNAMELEN); newnamep[CELL_MAXNAMELEN-1]='\0'; } else { newnamep[0] = '\0'; } } if (cp && cp->linkedName[0]) { cm_cell_t * linkedCellp = NULL; if (!strcmp(cp->name, cp->linkedName)) { cp->linkedName[0] = '\0'; } else if (!(flags & CM_FLAG_NOMOUNTCHASE)) { linkedCellp = cm_GetCell(cp->linkedName, CM_FLAG_CREATE|CM_FLAG_NOPROBE|CM_FLAG_NOMOUNTCHASE); lock_ObtainWrite(&cm_cellLock); if (!linkedCellp || (linkedCellp->linkedName[0] && strcmp(cp->name, linkedCellp->linkedName))) { cp->linkedName[0] = '\0'; } else { strncpy(linkedCellp->linkedName, cp->name, CELL_MAXNAMELEN); linkedCellp->linkedName[CELL_MAXNAMELEN-1]='\0'; } lock_ReleaseWrite(&cm_cellLock); } } return cp; }
void cm_PingServer(cm_server_t *tsp) { long code; int wasDown = 0; cm_conn_t *connp; struct rx_connection * rxconnp; Capabilities caps = {0, 0}; char hoststr[16]; cm_req_t req; lock_ObtainMutex(&tsp->mx); if (tsp->flags & CM_SERVERFLAG_PINGING) { tsp->waitCount++; osi_SleepM((LONG_PTR)tsp, &tsp->mx); lock_ObtainMutex(&tsp->mx); tsp->waitCount--; if (tsp->waitCount == 0) _InterlockedAnd(&tsp->flags, ~CM_SERVERFLAG_PINGING); else osi_Wakeup((LONG_PTR)tsp); lock_ReleaseMutex(&tsp->mx); return; } _InterlockedOr(&tsp->flags, CM_SERVERFLAG_PINGING); wasDown = tsp->flags & CM_SERVERFLAG_DOWN; afs_inet_ntoa_r(tsp->addr.sin_addr.S_un.S_addr, hoststr); lock_ReleaseMutex(&tsp->mx); if (cm_noIPAddr > 0) code = cm_ConnByServer(tsp, cm_rootUserp, FALSE, &connp); else code = RX_CALL_DEAD; /* No network */ if (code == 0) { /* now call the appropriate ping call. Drop the timeout if * the server is known to be down, so that we don't waste a * lot of time retiming out down servers. */ osi_Log4(afsd_logp, "cm_PingServer server %s (%s) was %s with caps 0x%x", osi_LogSaveString(afsd_logp, hoststr), tsp->type == CM_SERVER_VLDB ? "vldb" : "file", wasDown ? "down" : "up", tsp->capabilities); rxconnp = cm_GetRxConn(connp); if (wasDown) rx_SetConnHardDeadTime(rxconnp, 10); if (tsp->type == CM_SERVER_VLDB) { code = VL_ProbeServer(rxconnp); } else { /* file server */ code = RXAFS_GetCapabilities(rxconnp, &caps); } if (wasDown) rx_SetConnHardDeadTime(rxconnp, HardDeadtimeout); rx_PutConnection(rxconnp); cm_PutConn(connp); } /* got an unauthenticated connection to this server */ lock_ObtainMutex(&tsp->mx); if (code >= 0 || code == RXGEN_OPCODE || code == RX_CALL_BUSY) { /* mark server as up */ _InterlockedAnd(&tsp->flags, ~CM_SERVERFLAG_DOWN); tsp->downTime = 0; /* we currently handle 32-bits of capabilities */ if (code != RXGEN_OPCODE && code != RX_CALL_BUSY && caps.Capabilities_len > 0) { tsp->capabilities = caps.Capabilities_val[0]; xdr_free((xdrproc_t) xdr_Capabilities, &caps); caps.Capabilities_len = 0; caps.Capabilities_val = 0; } else { tsp->capabilities = 0; } osi_Log3(afsd_logp, "cm_PingServer server %s (%s) is up with caps 0x%x", osi_LogSaveString(afsd_logp, hoststr), tsp->type == CM_SERVER_VLDB ? "vldb" : "file", tsp->capabilities); /* Now update the volume status if necessary */ if (wasDown) { cm_server_vols_t * tsrvp; cm_volume_t * volp; int i; for (tsrvp = tsp->vols; tsrvp; tsrvp = tsrvp->nextp) { for (i=0; i<NUM_SERVER_VOLS; i++) { if (tsrvp->ids[i] != 0) { cm_InitReq(&req); lock_ReleaseMutex(&tsp->mx); code = cm_FindVolumeByID(tsp->cellp, tsrvp->ids[i], cm_rootUserp, &req, CM_GETVOL_FLAG_NO_LRU_UPDATE, &volp); lock_ObtainMutex(&tsp->mx); if (code == 0) { cm_UpdateVolumeStatus(volp, tsrvp->ids[i]); cm_PutVolume(volp); } } } } cm_RankServer(tsp); } } else { cm_MarkServerDown(tsp, code, wasDown); osi_Log3(afsd_logp, "cm_PingServer server %s (%s) is down with caps 0x%x", osi_LogSaveString(afsd_logp, hoststr), tsp->type == CM_SERVER_VLDB ? "vldb" : "file", tsp->capabilities); } if (tsp->waitCount == 0) _InterlockedAnd(&tsp->flags, ~CM_SERVERFLAG_PINGING); else osi_Wakeup((LONG_PTR)tsp); lock_ReleaseMutex(&tsp->mx); }