/*! * Set the primary cell name to the given cell name. * \param acellName Cell name. * \return 0 for success, < 0 for error. */ afs_int32 afs_SetPrimaryCell(char *acellName) { ObtainWriteLock(&afs_xcell, 691); if (afs_thiscell) afs_osi_FreeStr(afs_thiscell); afs_thiscell = afs_strdup(acellName); ReleaseWriteLock(&afs_xcell); return 0; }
/*! * Look up AFSDB for given cell name and create locally. * \param acellName Cell name. */ void afs_LookupAFSDB(char *acellName) { int code; char *cellName = afs_strdup(acellName); code = afs_GetCellHostsAFSDB(cellName); afs_Trace2(afs_iclSetp, CM_TRACE_AFSDB, ICL_TYPE_STRING, cellName, ICL_TYPE_INT32, code); afs_osi_FreeStr(cellName); }
/*! * Create new cell alias entry and update dynroot vnode. * \param alias * \param cell * \return */ afs_int32 afs_NewCellAlias(char *alias, char *cell) { struct cell_alias *tc; ObtainSharedLock(&afs_xcell, 681); if (afs_CellOrAliasExists_nl(alias)) { ReleaseSharedLock(&afs_xcell); return EEXIST; } UpgradeSToWLock(&afs_xcell, 682); tc = (struct cell_alias *)afs_osi_Alloc(sizeof(struct cell_alias)); tc->alias = afs_strdup(alias); tc->cell = afs_strdup(cell); tc->next = afs_cellalias_head; tc->index = afs_cellalias_index++; afs_cellalias_head = tc; ReleaseWriteLock(&afs_xcell); afs_DynrootInvalidate(); return 0; }
int SRXAFSCB_GetCellByNum(struct rx_call *a_call, afs_int32 a_cellnum, char **a_name, serverList * a_hosts) { afs_int32 i, sn; struct cell *tcell; RX_AFS_GLOCK(); AFS_STATCNT(SRXAFSCB_GetCellByNum); a_hosts->serverList_val = 0; a_hosts->serverList_len = 0; tcell = afs_GetCellStale(a_cellnum, READ_LOCK); if (!tcell) { *a_name = afs_strdup(""); RX_AFS_GUNLOCK(); return 0; } ObtainReadLock(&tcell->lock); *a_name = afs_strdup(tcell->cellName); for (sn = 0; sn < AFSMAXCELLHOSTS && tcell->cellHosts[sn]; sn++); a_hosts->serverList_len = sn; a_hosts->serverList_val = afs_osi_Alloc(sn * sizeof(afs_int32)); osi_Assert(a_hosts->serverList_val != NULL); for (i = 0; i < sn; i++) a_hosts->serverList_val[i] = ntohl(tcell->cellHosts[i]->addr->sa_ip); ReleaseReadLock(&tcell->lock); afs_PutCell(tcell, READ_LOCK); RX_AFS_GUNLOCK(); return 0; }
/*! * Create a new cell name, optional cell number. * \param name Name of cell. * \param cellnum Cellname number. * \return Initialized structure. */ static struct cell_name * afs_cellname_new(char *name, afs_int32 cellnum) { struct cell_name *cn; if (cellnum == 0) cellnum = afs_cellnum_next; cn = (struct cell_name *)afs_osi_Alloc(sizeof(*cn)); cn->next = afs_cellname_head; cn->cellnum = cellnum; cn->cellname = afs_strdup(name); cn->used = 0; afs_cellname_head = cn; if (cellnum >= afs_cellnum_next) afs_cellnum_next = cellnum + 1; return cn; }
/* * Inform dynroot that a new vnode is being created. Return value * is non-zero if this vnode is handled by dynroot, in which case * FetchStatus will be filled in. */ int afs_DynrootNewVnode(struct vcache *avc, struct AFSFetchStatus *status) { char *bp, tbuf[CVBS]; if (_afs_IsDynrootFid(&avc->f.fid)) { if (!afs_dynrootEnable) return 0; afs_GetDynroot(0, 0, status); afs_PutDynroot(); return 1; } if (afs_IsDynrootMount(avc)) { afs_GetDynrootMount(0, 0, status); afs_PutDynroot(); return 1; } /* * Check if this is an entry under /afs, e.g. /afs/cellname. */ if (avc->f.fid.Cell == afs_dynrootCell && avc->f.fid.Fid.Volume == AFS_DYNROOT_VOLUME) { struct cell *c; struct cell_alias *ca; int namelen, linklen, cellidx, rw; memset(status, 0, sizeof(struct AFSFetchStatus)); status->FileType = SymbolicLink; status->LinkCount = 1; status->DataVersion = 1; status->CallerAccess = PRSFS_LOOKUP | PRSFS_READ; status->AnonymousAccess = PRSFS_LOOKUP | PRSFS_READ; status->ParentVnode = 1; status->ParentUnique = 1; if (VNUM_TO_VNTYPE(avc->f.fid.Fid.Vnode) == VN_TYPE_SYMLINK) { struct afs_dynSymlink *ts; int index = VNUM_TO_VNID(avc->f.fid.Fid.Vnode); ObtainReadLock(&afs_dynSymlinkLock); ts = afs_dynSymlinkBase; while (ts) { if (ts->index == index) break; ts = ts->next; } if (ts) { linklen = strlen(ts->target); avc->linkData = afs_osi_Alloc(linklen + 1); strcpy(avc->linkData, ts->target); status->Length = linklen; status->UnixModeBits = 0755; } ReleaseReadLock(&afs_dynSymlinkLock); return ts ? 1 : 0; } if (VNUM_TO_VNTYPE(avc->f.fid.Fid.Vnode) != VN_TYPE_CELL && VNUM_TO_VNTYPE(avc->f.fid.Fid.Vnode) != VN_TYPE_ALIAS && VNUM_TO_VNTYPE(avc->f.fid.Fid.Vnode) != VN_TYPE_MOUNT) { afs_warn("dynroot vnode inconsistency, unknown VNTYPE %d\n", VNUM_TO_VNTYPE(avc->f.fid.Fid.Vnode)); return 0; } cellidx = VNUM_TO_CIDX(avc->f.fid.Fid.Vnode); rw = VNUM_TO_RW(avc->f.fid.Fid.Vnode); if (VNUM_TO_VNTYPE(avc->f.fid.Fid.Vnode) == VN_TYPE_ALIAS) { char *realName; ca = afs_GetCellAlias(cellidx); if (!ca) { afs_warn("dynroot vnode inconsistency, can't find alias %d\n", cellidx); return 0; } /* * linkData needs to contain the name of the cell * we're aliasing for. */ realName = ca->cell; if (!realName) { afs_warn("dynroot: alias %s missing real cell name\n", ca->alias); avc->linkData = afs_strdup("unknown"); linklen = 7; } else { int namelen = strlen(realName); linklen = rw + namelen; avc->linkData = afs_osi_Alloc(linklen + 1); strcpy(avc->linkData, rw ? "." : ""); afs_strcat(avc->linkData, realName); } status->UnixModeBits = 0755; afs_PutCellAlias(ca); } else if (VNUM_TO_VNTYPE(avc->f.fid.Fid.Vnode) == VN_TYPE_MOUNT) { c = afs_GetCellByIndex(cellidx, READ_LOCK); if (!c) { afs_warn("dynroot vnode inconsistency, can't find cell %d\n", cellidx); return 0; } /* * linkData needs to contain "%cell:volumeid" */ namelen = strlen(c->cellName); bp = afs_cv2string(&tbuf[CVBS], avc->f.fid.Fid.Unique); linklen = 2 + namelen + strlen(bp); avc->linkData = afs_osi_Alloc(linklen + 1); strcpy(avc->linkData, "%"); afs_strcat(avc->linkData, c->cellName); afs_strcat(avc->linkData, ":"); afs_strcat(avc->linkData, bp); status->UnixModeBits = 0644; status->ParentVnode = AFS_DYNROOT_MOUNT_VNODE; afs_PutCell(c, READ_LOCK); } else { c = afs_GetCellByIndex(cellidx, READ_LOCK); if (!c) { afs_warn("dynroot vnode inconsistency, can't find cell %d\n", cellidx); return 0; } /* * linkData needs to contain "#cell:root.cell" or "%cell:root.cell" */ namelen = strlen(c->cellName); linklen = 1 + namelen + 10; avc->linkData = afs_osi_Alloc(linklen + 1); strcpy(avc->linkData, rw ? "%" : "#"); afs_strcat(avc->linkData, c->cellName); afs_strcat(avc->linkData, ":root.cell"); status->UnixModeBits = 0644; afs_PutCell(c, READ_LOCK); } status->Length = linklen; return 1; } return 0; }
/*! * Create or update a cell entry. * \param acellName Name of cell. * \param acellHosts Array of hosts that this cell has. * \param aflags Cell flags. * \param linkedcname * \param fsport File server port. * \param vlport Volume server port. * \param timeout Cell timeout value, 0 means static AFSDB entry. * \return */ afs_int32 afs_NewCell(char *acellName, afs_int32 * acellHosts, int aflags, char *linkedcname, u_short fsport, u_short vlport, int timeout) { struct cell *tc, *tcl = 0; afs_int32 i, newc = 0, code = 0; AFS_STATCNT(afs_NewCell); ObtainWriteLock(&afs_xcell, 103); tc = afs_FindCellByName_nl(acellName, READ_LOCK); if (tc) { aflags &= ~CNoSUID; } else { tc = afs_osi_Alloc(sizeof(struct cell)); osi_Assert(tc != NULL); memset(tc, 0, sizeof(*tc)); tc->cellName = afs_strdup(acellName); tc->fsport = AFS_FSPORT; tc->vlport = AFS_VLPORT; AFS_MD5_String(tc->cellHandle, tc->cellName, strlen(tc->cellName)); AFS_RWLOCK_INIT(&tc->lock, "cell lock"); newc = 1; aflags |= CNoSUID; } ObtainWriteLock(&tc->lock, 688); /* If the cell we've found has the correct name but no timeout, * and we're called with a non-zero timeout, bail out: never * override static configuration entries with AFSDB ones. * One exception: if the original cell entry had no servers, * it must get servers from AFSDB. */ if (timeout && !tc->timeout && tc->cellHosts[0]) { code = EEXIST; /* This code is checked for in afs_LookupAFSDB */ goto bad; } /* we don't want to keep pinging old vlservers which were down, * since they don't matter any more. It's easier to do this than * to remove the server from its various hash tables. */ for (i = 0; i < AFS_MAXCELLHOSTS; i++) { if (!tc->cellHosts[i]) break; tc->cellHosts[i]->flags &= ~SRVR_ISDOWN; tc->cellHosts[i]->flags |= SRVR_ISGONE; } if (fsport) tc->fsport = fsport; if (vlport) tc->vlport = vlport; if (aflags & CLinkedCell) { if (!linkedcname) { code = EINVAL; goto bad; } tcl = afs_FindCellByName_nl(linkedcname, READ_LOCK); if (!tcl) { code = ENOENT; goto bad; } if (tcl->lcellp) { /* XXX Overwriting if one existed before! XXX */ tcl->lcellp->lcellp = (struct cell *)0; tcl->lcellp->states &= ~CLinkedCell; } tc->lcellp = tcl; tcl->lcellp = tc; } tc->states |= aflags; tc->timeout = timeout; memset(tc->cellHosts, 0, sizeof(tc->cellHosts)); for (i = 0; i < AFS_MAXCELLHOSTS; i++) { /* Get server for each host and link this cell in.*/ struct server *ts; afs_uint32 temp = acellHosts[i]; if (!temp) break; ts = afs_GetServer(&temp, 1, 0, tc->vlport, WRITE_LOCK, NULL, 0); ts->cell = tc; ts->flags &= ~SRVR_ISGONE; /* Set the server as a host of the new cell. */ tc->cellHosts[i] = ts; afs_PutServer(ts, WRITE_LOCK); } afs_SortServers(tc->cellHosts, AFS_MAXCELLHOSTS); /* randomize servers */ /* New cell: Build and add to LRU cell queue. */ if (newc) { struct cell_name *cn; cn = afs_cellname_lookup_name(acellName); if (!cn) cn = afs_cellname_new(acellName, 0); tc->cnamep = cn; tc->cellNum = cn->cellnum; tc->cellIndex = afs_cellindex++; afs_stats_cmperf.numCellsVisible++; QAdd(&CellLRU, &tc->lruq); } ReleaseWriteLock(&tc->lock); ReleaseWriteLock(&afs_xcell); afs_PutCell(tc, 0); if (!(aflags & CHush)) afs_DynrootInvalidate(); return 0; bad: if (newc) { afs_osi_FreeStr(tc->cellName); afs_osi_Free(tc, sizeof(struct cell)); } ReleaseWriteLock(&tc->lock); ReleaseWriteLock(&afs_xcell); return code; }