/** * @param aname Volume name. * @param acell Cell id. * @param agood * @param areq Request type. * @param locktype Type of lock to be used. * @return Volume or NULL if failure. */ static struct volume * afs_NewVolumeByName(char *aname, afs_int32 acell, int agood, struct vrequest *areq, afs_int32 locktype) { afs_int32 code, type = 0; struct volume *tv, *tv1; struct vldbentry *tve; struct nvldbentry *ntve; struct uvldbentry *utve; struct cell *tcell; char *tbuffer, *ve; struct afs_conn *tconn; struct vrequest treq; struct rx_connection *rxconn; if (strlen(aname) > VL_MAXNAMELEN) /* Invalid volume name */ return NULL; tcell = afs_GetCell(acell, READ_LOCK); if (!tcell) { return NULL; } /* allow null request if we don't care about ENODEV/ETIMEDOUT distinction */ if (!areq) areq = &treq; afs_Trace2(afs_iclSetp, CM_TRACE_GETVOL, ICL_TYPE_STRING, aname, ICL_TYPE_POINTER, aname); tbuffer = osi_AllocLargeSpace(AFS_LRALLOCSIZ); tve = (struct vldbentry *)(tbuffer + 1024); ntve = (struct nvldbentry *)tve; utve = (struct uvldbentry *)tve; afs_InitReq(&treq, afs_osi_credp); /* *must* be unauth for vldb */ do { tconn = afs_ConnByMHosts(tcell->cellHosts, tcell->vlport, tcell->cellNum, &treq, SHARED_LOCK, 0, &rxconn); if (tconn) { if (tconn->srvr->server->flags & SNO_LHOSTS) { type = 0; RX_AFS_GUNLOCK(); code = VL_GetEntryByNameO(rxconn, aname, tve); RX_AFS_GLOCK(); } else if (tconn->srvr->server->flags & SYES_LHOSTS) { type = 1; RX_AFS_GUNLOCK(); code = VL_GetEntryByNameN(rxconn, aname, ntve); RX_AFS_GLOCK(); } else { type = 2; RX_AFS_GUNLOCK(); code = VL_GetEntryByNameU(rxconn, aname, utve); RX_AFS_GLOCK(); if (!(tconn->srvr->server->flags & SVLSRV_UUID)) { if (code == RXGEN_OPCODE) { type = 1; RX_AFS_GUNLOCK(); code = VL_GetEntryByNameN(rxconn, aname, ntve); RX_AFS_GLOCK(); if (code == RXGEN_OPCODE) { type = 0; tconn->srvr->server->flags |= SNO_LHOSTS; RX_AFS_GUNLOCK(); code = VL_GetEntryByNameO(rxconn, aname, tve); RX_AFS_GLOCK(); } else if (!code) tconn->srvr->server->flags |= SYES_LHOSTS; } else if (!code) tconn->srvr->server->flags |= SVLSRV_UUID; } lastnvcode = code; } } else code = -1; } while (afs_Analyze(tconn, rxconn, code, NULL, &treq, -1, /* no op code for this */ SHARED_LOCK, tcell)); if (code) { /* If the client has yet to contact this cell and contact failed due * to network errors, mark the VLDB servers as back up. * That the client tried and failed can be determined from the * fact that there was a downtime incident, but CHasVolRef is not set. */ /* RT 48959 - unclear if this should really go */ #if 0 if (areq->networkError && !(tcell->states & CHasVolRef)) { int i; struct server *sp; struct srvAddr *sap; for (i = 0; i < AFS_MAXCELLHOSTS; i++) { if ((sp = tcell->cellHosts[i]) == NULL) break; for (sap = sp->addr; sap; sap = sap->next_sa) afs_MarkServerUpOrDown(sap, 0); } } #endif afs_CopyError(&treq, areq); osi_FreeLargeSpace(tbuffer); afs_PutCell(tcell, READ_LOCK); return NULL; } /* * Check to see if this cell has not yet referenced a volume. If * it hasn't, it's just about to change its status, and we need to mark * this fact down. Note that it is remotely possible that afs_SetupVolume * could fail and we would still not have a volume reference. */ if (!(tcell->states & CHasVolRef)) { tcell->states |= CHasVolRef; afs_stats_cmperf.numCellsContacted++; } /*First time a volume in this cell has been referenced */ if (type == 2) ve = (char *)utve; else if (type == 1) ve = (char *)ntve; else ve = (char *)tve; tv = afs_SetupVolume(0, aname, ve, tcell, agood, type, &treq); if ((agood == 3) && tv && tv->backVol) { /* * This means that very soon we'll ask for the BK volume so * we'll prefetch it (well we did already.) */ tv1 = afs_SetupVolume(tv->backVol, (char *)0, ve, tcell, 0, type, &treq); if (tv1) { tv1->refCount--; } } if ((agood >= 2) && tv && tv->roVol) { /* * This means that very soon we'll ask for the RO volume so * we'll prefetch it (well we did already.) */ tv1 = afs_SetupVolume(tv->roVol, NULL, ve, tcell, 0, type, &treq); if (tv1) { tv1->refCount--; } } osi_FreeLargeSpace(tbuffer); afs_PutCell(tcell, READ_LOCK); return tv; } /*afs_NewVolumeByName */
static int VLDB_Same(struct VenusFid *afid, struct vrequest *areq) { struct vrequest treq; struct afs_conn *tconn; int i, type = 0; union { struct vldbentry tve; struct nvldbentry ntve; struct uvldbentry utve; } *v; struct volume *tvp; struct cell *tcell; char *bp, tbuf[CVBS]; /* biggest volume id is 2^32, ~ 4*10^9 */ unsigned int changed; struct server *(oldhosts[NMAXNSERVERS]); AFS_STATCNT(CheckVLDB); afs_FinalizeReq(areq); if ((i = afs_InitReq(&treq, afs_osi_credp))) return DUNNO; v = afs_osi_Alloc(sizeof(*v)); tcell = afs_GetCell(afid->Cell, READ_LOCK); bp = afs_cv2string(&tbuf[CVBS], afid->Fid.Volume); do { VSleep(2); /* Better safe than sorry. */ tconn = afs_ConnByMHosts(tcell->cellHosts, tcell->vlport, tcell->cellNum, &treq, SHARED_LOCK); if (tconn) { if (tconn->srvr->server->flags & SNO_LHOSTS) { type = 0; RX_AFS_GUNLOCK(); i = VL_GetEntryByNameO(tconn->id, bp, &v->tve); RX_AFS_GLOCK(); } else if (tconn->srvr->server->flags & SYES_LHOSTS) { type = 1; RX_AFS_GUNLOCK(); i = VL_GetEntryByNameN(tconn->id, bp, &v->ntve); RX_AFS_GLOCK(); } else { type = 2; RX_AFS_GUNLOCK(); i = VL_GetEntryByNameU(tconn->id, bp, &v->utve); RX_AFS_GLOCK(); if (!(tconn->srvr->server->flags & SVLSRV_UUID)) { if (i == RXGEN_OPCODE) { type = 1; RX_AFS_GUNLOCK(); i = VL_GetEntryByNameN(tconn->id, bp, &v->ntve); RX_AFS_GLOCK(); if (i == RXGEN_OPCODE) { type = 0; tconn->srvr->server->flags |= SNO_LHOSTS; RX_AFS_GUNLOCK(); i = VL_GetEntryByNameO(tconn->id, bp, &v->tve); RX_AFS_GLOCK(); } else if (!i) tconn->srvr->server->flags |= SYES_LHOSTS; } else if (!i) tconn->srvr->server->flags |= SVLSRV_UUID; } lastcode = i; } } else i = -1; } while (afs_Analyze(tconn, i, NULL, &treq, -1, /* no op code for this */ SHARED_LOCK, tcell)); afs_PutCell(tcell, READ_LOCK); afs_Trace2(afs_iclSetp, CM_TRACE_CHECKVLDB, ICL_TYPE_FID, &afid, ICL_TYPE_INT32, i); if (i) { afs_osi_Free(v, sizeof(*v)); return DUNNO; } /* have info, copy into serverHost array */ changed = 0; tvp = afs_FindVolume(afid, WRITE_LOCK); if (tvp) { ObtainWriteLock(&tvp->lock, 107); for (i = 0; i < NMAXNSERVERS && tvp->serverHost[i]; i++) { oldhosts[i] = tvp->serverHost[i]; } if (type == 2) { InstallUVolumeEntry(tvp, &v->utve, afid->Cell, tcell, &treq); } else if (type == 1) { InstallNVolumeEntry(tvp, &v->ntve, afid->Cell); } else { InstallVolumeEntry(tvp, &v->tve, afid->Cell); } if (i < NMAXNSERVERS && tvp->serverHost[i]) { changed = 1; } for (--i; !changed && i >= 0; i--) { if (tvp->serverHost[i] != oldhosts[i]) { changed = 1; /* also happens if prefs change. big deal. */ } } ReleaseWriteLock(&tvp->lock); afs_PutVolume(tvp, WRITE_LOCK); } else { /* can't find volume */ tvp = afs_GetVolume(afid, &treq, WRITE_LOCK); if (tvp) { afs_PutVolume(tvp, WRITE_LOCK); afs_osi_Free(v, sizeof(*v)); return DIFFERENT; } else { afs_osi_Free(v, sizeof(*v)); return DUNNO; } } afs_osi_Free(v, sizeof(*v)); return (changed ? DIFFERENT : SAME); } /*VLDB_Same */