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 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 */