void LockAndInstallNVolumeEntry(struct volume *av, struct nvldbentry *ve, int acell) { struct server *ts; struct cell *cellp; int i, j; afs_int32 mask; afs_uint32 temp; char types = 0; struct server *serverHost[AFS_MAXHOSTS]; AFS_STATCNT(InstallVolumeEntry); memset(serverHost, 0, sizeof(serverHost)); /* Determine type of volume we want */ if ((ve->flags & VLF_RWEXISTS) && (av->volume == ve->volumeId[RWVOL])) { mask = VLSF_RWVOL; } else if ((ve->flags & VLF_ROEXISTS) && (av->volume == ve->volumeId[ROVOL])) { mask = VLSF_ROVOL; types |= VRO; } else if ((ve->flags & VLF_BACKEXISTS) && (av->volume == ve->volumeId[BACKVOL])) { /* backup always is on the same volume as parent */ mask = VLSF_RWVOL; types |= (VRO | VBackup); } else { mask = 0; /* Can't find volume in vldb entry */ } cellp = afs_GetCell(acell, 0); /* Step through the VLDB entry making sure each server listed is there */ for (i = 0, j = 0; i < ve->nServers; i++) { if (((ve->serverFlags[i] & mask) == 0) || (ve->serverFlags[i] & VLSF_DONTUSE)) { continue; /* wrong volume or don't use this volume */ } temp = htonl(ve->serverNumber[i]); ts = afs_GetServer(&temp, 1, acell, cellp->fsport, WRITE_LOCK, (afsUUID *) 0, 0, av); serverHost[j] = ts; /* * The cell field could be 0 if the server entry was created * first with the 'fs setserverprefs' call which doesn't set * the cell field. Thus if the afs_GetServer call above * follows later on it will find the server entry thus it will * simply return without setting any fields, so we set the * field ourselves below. */ if (!ts->cell) ts->cell = cellp; afs_PutServer(ts, WRITE_LOCK); j++; } ObtainWriteLock(&av->lock, 110); memcpy(av->serverHost, serverHost, sizeof(serverHost)); /* from above */ av->states |= types; /* fill in volume types */ av->rwVol = ((ve->flags & VLF_RWEXISTS) ? ve->volumeId[RWVOL] : 0); av->roVol = ((ve->flags & VLF_ROEXISTS) ? ve->volumeId[ROVOL] : 0); av->backVol = ((ve->flags & VLF_BACKEXISTS) ? ve->volumeId[BACKVOL] : 0); if (ve->flags & VLF_DFSFILESET) av->states |= VForeign; afs_SortServers(av->serverHost, AFS_MAXHOSTS); } /*InstallNVolumeEntry */
void LockAndInstallUVolumeEntry(struct volume *av, struct uvldbentry *ve, int acell, struct cell *tcell, struct vrequest *areq) { struct server *ts; struct afs_conn *tconn; struct cell *cellp; int i, j; afs_uint32 serverid; afs_int32 mask; int k; char type = 0; struct server *serverHost[AFS_MAXHOSTS]; AFS_STATCNT(InstallVolumeEntry); memset(serverHost, 0, sizeof(serverHost)); /* Determine type of volume we want */ if ((ve->flags & VLF_RWEXISTS) && (av->volume == ve->volumeId[RWVOL])) { mask = VLSF_RWVOL; } else if ((ve->flags & VLF_ROEXISTS) && av->volume == ve->volumeId[ROVOL]) { mask = VLSF_ROVOL; type |= VRO; } else if ((ve->flags & VLF_BACKEXISTS) && (av->volume == ve->volumeId[BACKVOL])) { /* backup always is on the same volume as parent */ mask = VLSF_RWVOL; type |= (VRO | VBackup); } else { mask = 0; /* Can't find volume in vldb entry */ } cellp = afs_GetCell(acell, 0); /* Gather the list of servers the VLDB says the volume is on * and initialize the ve->serverHost[] array. If a server struct * is not found, then get the list of addresses for the * server, VL_GetAddrsU(), and create a server struct, afs_GetServer(). */ for (i = 0, j = 0; i < ve->nServers; i++) { if (((ve->serverFlags[i] & mask) == 0) || (ve->serverFlags[i] & VLSF_DONTUSE)) { continue; /* wrong volume don't use this volume */ } if (!(ve->serverFlags[i] & VLSERVER_FLAG_UUID)) { /* The server has no uuid */ serverid = htonl(ve->serverNumber[i].time_low); ts = afs_GetServer(&serverid, 1, acell, cellp->fsport, WRITE_LOCK, (afsUUID *) 0, 0, av); } else { ts = afs_FindServer(0, cellp->fsport, &ve->serverNumber[i], 0); if (ts && (ts->sr_addr_uniquifier == ve->serverUnique[i]) && ts->addr) { /* uuid, uniquifier, and portal are the same */ } else { afs_uint32 *addrp, code; afs_int32 nentries, unique; bulkaddrs addrs; ListAddrByAttributes attrs; afsUUID uuid; struct rx_connection *rxconn; memset(&attrs, 0, sizeof(attrs)); attrs.Mask = VLADDR_UUID; attrs.uuid = ve->serverNumber[i]; memset(&uuid, 0, sizeof(uuid)); memset(&addrs, 0, sizeof(addrs)); do { tconn = afs_ConnByMHosts(tcell->cellHosts, tcell->vlport, tcell->cellNum, areq, SHARED_LOCK, 0, &rxconn); if (tconn) { RX_AFS_GUNLOCK(); code = VL_GetAddrsU(rxconn, &attrs, &uuid, &unique, &nentries, &addrs); RX_AFS_GLOCK(); } else { code = -1; } /* Handle corrupt VLDB (defect 7393) */ if (code == 0 && nentries == 0) code = VL_NOENT; } while (afs_Analyze (tconn, rxconn, code, NULL, areq, -1, SHARED_LOCK, tcell)); if (code) { /* Better handing of such failures; for now we'll simply retry this call */ areq->volumeError = 1; return; } addrp = addrs.bulkaddrs_val; for (k = 0; k < nentries; k++) { addrp[k] = htonl(addrp[k]); } ts = afs_GetServer(addrp, nentries, acell, cellp->fsport, WRITE_LOCK, &ve->serverNumber[i], ve->serverUnique[i], av); xdr_free((xdrproc_t) xdr_bulkaddrs, &addrs); } #if defined(AFS_LINUX26_ENV) && !defined(UKERNEL) if (afs_compare_serveruuid(&ve->serverNumber[i])) av->states |= VPartVisible; #endif } serverHost[j] = ts; /* The cell field could be 0 if the server entry was created * first with the 'fs setserverprefs' call which doesn't set * the cell field. Thus if the afs_GetServer call above * follows later on it will find the server entry thus it will * simply return without setting any fields, so we set the * field ourselves below. */ if (!ts->cell) ts->cell = cellp; afs_PutServer(ts, WRITE_LOCK); j++; } ObtainWriteLock(&av->lock, 111); memcpy(av->serverHost, serverHost, sizeof(serverHost)); /* from above */ av->states |= type; /* fill in volume types */ av->rwVol = ((ve->flags & VLF_RWEXISTS) ? ve->volumeId[RWVOL] : 0); av->roVol = ((ve->flags & VLF_ROEXISTS) ? ve->volumeId[ROVOL] : 0); av->backVol = ((ve->flags & VLF_BACKEXISTS) ? ve->volumeId[BACKVOL] : 0); if (ve->flags & VLF_DFSFILESET) av->states |= VForeign; afs_SortServers(av->serverHost, AFS_MAXHOSTS); } /*InstallVolumeEntry */
void InstallNVolumeEntry(struct volume *av, struct nvldbentry *ve, int acell) { register struct server *ts; struct cell *cellp; register int i, j; afs_int32 mask; afs_uint32 temp; AFS_STATCNT(InstallVolumeEntry); /* Determine type of volume we want */ if ((ve->flags & VLF_RWEXISTS) && (av->volume == ve->volumeId[RWVOL])) { mask = VLSF_RWVOL; } else if ((ve->flags & VLF_ROEXISTS) && (av->volume == ve->volumeId[ROVOL])) { mask = VLSF_ROVOL; av->states |= VRO; } else if ((ve->flags & VLF_BACKEXISTS) && (av->volume == ve->volumeId[BACKVOL])) { /* backup always is on the same volume as parent */ mask = VLSF_RWVOL; av->states |= (VRO | VBackup); } else { mask = 0; /* Can't find volume in vldb entry */ } /* fill in volume types */ av->rwVol = ((ve->flags & VLF_RWEXISTS) ? ve->volumeId[RWVOL] : 0); av->roVol = ((ve->flags & VLF_ROEXISTS) ? ve->volumeId[ROVOL] : 0); av->backVol = ((ve->flags & VLF_BACKEXISTS) ? ve->volumeId[BACKVOL] : 0); if (ve->flags & VLF_DFSFILESET) av->states |= VForeign; cellp = afs_GetCell(acell, 0); /* This volume, av, is locked. Zero out the serverHosts[] array * so that if afs_GetServer() decides to replace the server * struct, we don't deadlock trying to afs_ResetVolumeInfo() * this volume. */ for (j = 0; j < MAXHOSTS; j++) { av->serverHost[j] = 0; } /* Step through the VLDB entry making sure each server listed is there */ for (i = 0, j = 0; i < ve->nServers; i++) { if (((ve->serverFlags[i] & mask) == 0) || (ve->serverFlags[i] & VLSF_DONTUSE)) { continue; /* wrong volume or don't use this volume */ } temp = htonl(ve->serverNumber[i]); ts = afs_GetServer(&temp, 1, acell, cellp->fsport, WRITE_LOCK, (afsUUID *) 0, 0); av->serverHost[j] = ts; /* * The cell field could be 0 if the server entry was created * first with the 'fs setserverprefs' call which doesn't set * the cell field. Thus if the afs_GetServer call above * follows later on it will find the server entry thus it will * simply return without setting any fields, so we set the * field ourselves below. */ if (!ts->cell) ts->cell = cellp; afs_PutServer(ts, WRITE_LOCK); j++; } if (j < MAXHOSTS) { av->serverHost[j++] = 0; } afs_SortServers(av->serverHost, MAXHOSTS); } /*InstallNVolumeEntry */
/*! * 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; }
void InstallUVolumeEntry(struct volume *av, struct uvldbentry *ve, int acell, struct cell *tcell, struct vrequest *areq) { register struct server *ts; struct afs_conn *tconn; struct cell *cellp; register int i, j; afs_uint32 serverid; afs_int32 mask; int k; AFS_STATCNT(InstallVolumeEntry); /* Determine type of volume we want */ if ((ve->flags & VLF_RWEXISTS) && (av->volume == ve->volumeId[RWVOL])) { mask = VLSF_RWVOL; } else if ((ve->flags & VLF_ROEXISTS) && av->volume == ve->volumeId[ROVOL]) { mask = VLSF_ROVOL; av->states |= VRO; } else if ((ve->flags & VLF_BACKEXISTS) && (av->volume == ve->volumeId[BACKVOL])) { /* backup always is on the same volume as parent */ mask = VLSF_RWVOL; av->states |= (VRO | VBackup); } else { mask = 0; /* Can't find volume in vldb entry */ } /* fill in volume types */ av->rwVol = ((ve->flags & VLF_RWEXISTS) ? ve->volumeId[RWVOL] : 0); av->roVol = ((ve->flags & VLF_ROEXISTS) ? ve->volumeId[ROVOL] : 0); av->backVol = ((ve->flags & VLF_BACKEXISTS) ? ve->volumeId[BACKVOL] : 0); if (ve->flags & VLF_DFSFILESET) av->states |= VForeign; cellp = afs_GetCell(acell, 0); /* This volume, av, is locked. Zero out the serverHosts[] array * so that if afs_GetServer() decides to replace the server * struct, we don't deadlock trying to afs_ResetVolumeInfo() * this volume. */ for (j = 0; j < MAXHOSTS; j++) { av->serverHost[j] = 0; } /* Gather the list of servers the VLDB says the volume is on * and initialize the ve->serverHost[] array. If a server struct * is not found, then get the list of addresses for the * server, VL_GetAddrsU(), and create a server struct, afs_GetServer(). */ for (i = 0, j = 0; i < ve->nServers; i++) { if (((ve->serverFlags[i] & mask) == 0) || (ve->serverFlags[i] & VLSF_DONTUSE)) { continue; /* wrong volume don't use this volume */ } if (!(ve->serverFlags[i] & VLSERVER_FLAG_UUID)) { /* The server has no uuid */ serverid = htonl(ve->serverNumber[i].time_low); ts = afs_GetServer(&serverid, 1, acell, cellp->fsport, WRITE_LOCK, (afsUUID *) 0, 0); } else { ts = afs_FindServer(0, cellp->fsport, &ve->serverNumber[i], 0); if (ts && (ts->sr_addr_uniquifier == ve->serverUnique[i]) && ts->addr) { /* uuid, uniquifier, and portal are the same */ } else { afs_uint32 *addrp, nentries, code, unique; bulkaddrs addrs; ListAddrByAttributes attrs; afsUUID uuid; memset((char *)&attrs, 0, sizeof(attrs)); attrs.Mask = VLADDR_UUID; attrs.uuid = ve->serverNumber[i]; memset((char *)&uuid, 0, sizeof(uuid)); memset((char *)&addrs, 0, sizeof(addrs)); do { tconn = afs_ConnByMHosts(tcell->cellHosts, tcell->vlport, tcell->cellNum, areq, SHARED_LOCK); if (tconn) { RX_AFS_GUNLOCK(); code = VL_GetAddrsU(tconn->id, &attrs, &uuid, &unique, &nentries, &addrs); RX_AFS_GLOCK(); } else { code = -1; } /* Handle corrupt VLDB (defect 7393) */ if (code == 0 && nentries == 0) code = VL_NOENT; } while (afs_Analyze (tconn, code, NULL, areq, -1, SHARED_LOCK, tcell)); if (code) { /* Better handing of such failures; for now we'll simply retry this call */ areq->volumeError = 1; return; } addrp = addrs.bulkaddrs_val; for (k = 0; k < nentries; k++) { addrp[k] = htonl(addrp[k]); } ts = afs_GetServer(addrp, nentries, acell, cellp->fsport, WRITE_LOCK, &ve->serverNumber[i], ve->serverUnique[i]); afs_osi_Free(addrs.bulkaddrs_val, addrs.bulkaddrs_len * sizeof(*addrp)); } } av->serverHost[j] = ts; /* The cell field could be 0 if the server entry was created * first with the 'fs setserverprefs' call which doesn't set * the cell field. Thus if the afs_GetServer call above * follows later on it will find the server entry thus it will * simply return without setting any fields, so we set the * field ourselves below. */ if (!ts->cell) ts->cell = cellp; afs_PutServer(ts, WRITE_LOCK); j++; } afs_SortServers(av->serverHost, MAXHOSTS); } /*InstallVolumeEntry */