/* if it's from DNS, see if it has expired * and check to make sure we have a valid set of volume servers * this function must not be called with a lock on cm_cellLock */ cm_cell_t *cm_UpdateCell(cm_cell_t * cp, afs_uint32 flags) { long code = 0; cm_cell_rock_t rock; afs_uint32 mxheld = 0; if (cp == NULL) return NULL; lock_ObtainMutex(&cp->mx); mxheld = 1; #ifdef AFS_FREELANCE_CLIENT if (cp->flags & CM_CELLFLAG_FREELANCE) { lock_ReleaseMutex(&cp->mx); return cp; } #endif if (cm_IsServerListEmpty(cp->vlServersp) || (time(0) > cp->timeout) || (cm_dnsEnabled && (cp->flags & CM_CELLFLAG_DNS) && ((cp->flags & CM_CELLFLAG_VLSERVER_INVALID)))) { lock_ReleaseMutex(&cp->mx); mxheld = 0; /* must empty cp->vlServersp */ if (cp->vlServersp) cm_FreeServerList(&cp->vlServersp, CM_FREESERVERLIST_DELETE); rock.cellp = cp; rock.flags = flags; code = cm_SearchCellRegistry(1, cp->name, NULL, cp->linkedName, cm_AddCellProc, &rock); if (code && code != CM_ERROR_FORCE_DNS_LOOKUP) code = cm_SearchCellFileEx(cp->name, NULL, cp->linkedName, cm_AddCellProc, &rock); if (code == 0) { lock_ObtainMutex(&cp->mx); mxheld = 1; cp->timeout = time(0) + 7200; } else { if (cm_dnsEnabled) { int ttl; code = cm_SearchCellByDNS(cp->name, NULL, &ttl, cm_AddCellProc, &rock); if (code == 0) { /* got cell from DNS */ lock_ObtainMutex(&cp->mx); mxheld = 1; _InterlockedOr(&cp->flags, CM_CELLFLAG_DNS); _InterlockedAnd(&cp->flags, ~CM_CELLFLAG_VLSERVER_INVALID); cp->timeout = time(0) + ttl; #ifdef DEBUG fprintf(stderr, "cell %s: ttl=%d\n", cp->name, ttl); #endif } else { /* if we fail to find it this time, we'll just do nothing and leave the * current entry alone */ lock_ObtainMutex(&cp->mx); mxheld = 1; _InterlockedOr(&cp->flags, CM_CELLFLAG_VLSERVER_INVALID); } } } } if (code == 0) cm_RandomizeServer(&cp->vlServersp); if (mxheld) lock_ReleaseMutex(&cp->mx); return code ? NULL : cp; }
/* search for a cell, and either return an error code if we don't find it, * or return 0 if we do, in which case we also fill in the addresses in * the cellp field. * * new feature: we can handle abbreviations and are insensitive to case. * If the caller wants the "real" cell name, it puts a non-null pointer in * newCellNamep. Anomaly: if cellNamep is ambiguous, we may modify * newCellNamep but return an error code. * * Linked Cells: the CellServDB format permits linked cells * >cell [linked-cell] #Description * * newCellNamep and linkedNamep are required to be CELL_MAXNAMELEN in size. */ long cm_SearchCellFile(char *cellNamep, char *newCellNamep, cm_configProc_t *procp, void *rockp) { return cm_SearchCellFileEx(cellNamep, newCellNamep, NULL, procp, rockp); }
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,CM_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_ReleaseWrite(&cm_cellLock); lock_ObtainMutex(&cp->mx); lock_ObtainWrite(&cm_cellLock); 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_SearchCellRegistry(1, namep, fullname, linkedName, cm_AddCellProc, &rock); if (code && code != CM_ERROR_FORCE_DNS_LOOKUP) 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)); 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)); lock_ObtainMutex(&cp->mx); lock_ObtainWrite(&cm_cellLock); hasWriteLock = 1; cm_RemoveCellFromIDHashTable(cp); cm_RemoveCellFromNameHashTable(cp); lock_ReleaseMutex(&cp->mx); cm_FreeCell(cp); cp = NULL; goto done; } else { /* got cell from DNS */ lock_ObtainMutex(&cp->mx); hasMutex = 1; _InterlockedOr(&cp->flags, CM_CELLFLAG_DNS); _InterlockedAnd(&cp->flags, ~CM_CELLFLAG_VLSERVER_INVALID); cp->timeout = time(0) + ttl; } } else { lock_ObtainMutex(&cp->mx); lock_ObtainWrite(&cm_cellLock); hasWriteLock = 1; cm_RemoveCellFromIDHashTable(cp); cm_RemoveCellFromNameHashTable(cp); lock_ReleaseMutex(&cp->mx); 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 */ lock_ObtainRead(&cm_cellLock); 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_ObtainMutex(&cp->mx); hasMutex = 1; } lock_ConvertRToW(&cm_cellLock); hasWriteLock = 1; cm_RemoveCellFromIDHashTable(cp); cm_RemoveCellFromNameHashTable(cp); lock_ReleaseMutex(&cp->mx); hasMutex = 0; cm_FreeCell(cp); cp = cp2; goto done; } lock_ReleaseRead(&cm_cellLock); /* 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'; lock_ObtainWrite(&cm_cellLock); hasWriteLock = 1; 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; }
/* if it's from DNS, see if it has expired * and check to make sure we have a valid set of volume servers * this function must be called with a Write Lock on cm_cellLock */ cm_cell_t *cm_UpdateCell(cm_cell_t * cp, afs_uint32 flags) { long code = 0; cm_cell_rock_t rock; if (cp == NULL) return NULL; lock_ObtainMutex(&cp->mx); if ((cp->vlServersp == NULL #ifdef AFS_FREELANCE_CLIENT && !(cp->flags & CM_CELLFLAG_FREELANCE) #endif ) || (time(0) > cp->timeout) #ifdef AFS_AFSDB_ENV || (cm_dnsEnabled && (cp->flags & CM_CELLFLAG_DNS) && ((cp->flags & CM_CELLFLAG_VLSERVER_INVALID))) #endif ) { lock_ReleaseMutex(&cp->mx); /* must empty cp->vlServersp */ if (cp->vlServersp) { cm_FreeServerList(&cp->vlServersp, CM_FREESERVERLIST_DELETE); cp->vlServersp = NULL; } rock.cellp = cp; rock.flags = flags; code = cm_SearchCellFileEx(cp->name, NULL, cp->linkedName, cm_AddCellProc, &rock); if (code == 0) { lock_ObtainMutex(&cp->mx); cp->timeout = time(0) + 7200; lock_ReleaseMutex(&cp->mx); } #ifdef AFS_AFSDB_ENV else { if (cm_dnsEnabled) { int ttl; code = cm_SearchCellByDNS(cp->name, NULL, &ttl, cm_AddCellProc, &rock); if (code == 0) { /* got cell from DNS */ lock_ObtainMutex(&cp->mx); cp->flags |= CM_CELLFLAG_DNS; cp->flags &= ~CM_CELLFLAG_VLSERVER_INVALID; cp->timeout = time(0) + ttl; lock_ReleaseMutex(&cp->mx); #ifdef DEBUG fprintf(stderr, "cell %s: ttl=%d\n", cp->name, ttl); #endif } else { /* if we fail to find it this time, we'll just do nothing and leave the * current entry alone */ lock_ObtainMutex(&cp->mx); cp->flags |= CM_CELLFLAG_VLSERVER_INVALID; lock_ReleaseMutex(&cp->mx); } } } #endif /* AFS_AFSDB_ENV */ } else { lock_ReleaseMutex(&cp->mx); } return code ? NULL : cp; }