int afs_UFSHandleLink(register struct vcache *avc, struct vrequest *areq) { register struct dcache *tdc; register char *tp, *rbuf; void *tfile; afs_size_t offset, len; afs_int32 tlen, alen; register afs_int32 code; /* two different formats, one for links protected 644, have a "." at the * end of the file name, which we turn into a null. Others, protected * 755, we add a null to the end of */ AFS_STATCNT(afs_UFSHandleLink); if (!avc->linkData) { tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 0); afs_Trace3(afs_iclSetp, CM_TRACE_UFSLINK, ICL_TYPE_POINTER, avc, ICL_TYPE_POINTER, tdc, ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(avc->f.m.Length)); if (!tdc) { if (AFS_IS_DISCONNECTED) return ENETDOWN; else return EIO; } /* otherwise we have the data loaded, go for it */ if (len > 1024) { afs_PutDCache(tdc); return EFAULT; } if (avc->f.m.Mode & 0111) alen = len + 1; /* regular link */ else alen = len; /* mt point */ rbuf = (char *)osi_AllocLargeSpace(AFS_LRALLOCSIZ); tlen = len; ObtainReadLock(&tdc->lock); #if defined(LINUX_USE_FH) tfile = osi_UFSOpen_fh(&tdc->f.fh, tdc->f.fh_type); #else tfile = osi_UFSOpen(tdc->f.inode); #endif code = afs_osi_Read(tfile, -1, rbuf, tlen); osi_UFSClose(tfile); ReleaseReadLock(&tdc->lock); afs_PutDCache(tdc); rbuf[alen - 1] = '\0'; alen = strlen(rbuf) + 1; tp = afs_osi_Alloc(alen); /* make room for terminating null */ memcpy(tp, rbuf, alen); osi_FreeLargeSpace(rbuf); if (code != tlen) { afs_osi_Free(tp, alen); return EIO; } avc->linkData = tp; } return 0; }
/** * * @param volid Volume ID. If it's 0, get it from the name. * @param aname Volume name. * @param ve Volume entry. * @param tcell The cell containing this volume. * @param agood * @param type Type of volume. * @param areq Request. * @return Volume or NULL if failure. */ static struct volume * afs_SetupVolume(afs_int32 volid, char *aname, void *ve, struct cell *tcell, afs_int32 agood, afs_int32 type, struct vrequest *areq) { struct volume *tv; struct vldbentry *ove = (struct vldbentry *)ve; struct nvldbentry *nve = (struct nvldbentry *)ve; struct uvldbentry *uve = (struct uvldbentry *)ve; int whichType; /* which type of volume to look for */ int i, j, err = 0; if (!volid) { int len; /* special hint from file server to use vlserver */ len = strlen(aname); if (len >= 8 && strcmp(aname + len - 7, ".backup") == 0) whichType = BACKVOL; else if (len >= 10 && strcmp(aname + len - 9, ".readonly") == 0) whichType = ROVOL; else whichType = RWVOL; /* figure out which one we're really interested in (a set is returned) */ volid = afs_vtoi(aname); if (volid == 0) { if (type == 2) { volid = uve->volumeId[whichType]; } else if (type == 1) { volid = nve->volumeId[whichType]; } else { volid = ove->volumeId[whichType]; } } /* end of if (volid == 0) */ } /* end of if (!volid) */ ObtainWriteLock(&afs_xvolume, 108); i = VHash(volid); for (tv = afs_volumes[i]; tv; tv = tv->next) { if (tv->volume == volid && tv->cell == tcell->cellNum) { break; } } if (!tv) { struct fvolume *tf = 0; tv = afs_GetVolSlot(); if (!tv) { ReleaseWriteLock(&afs_xvolume); return NULL; } memset(tv, 0, sizeof(struct volume)); for (j = fvTable[FVHash(tcell->cellNum, volid)]; j != 0; j = tf->next) { if (afs_FVIndex != j) { struct osi_file *tfile; tfile = osi_UFSOpen(&volumeInode); err = afs_osi_Read(tfile, sizeof(struct fvolume) * j, &staticFVolume, sizeof(struct fvolume)); osi_UFSClose(tfile); if (err != sizeof(struct fvolume)) { afs_warn("afs_SetupVolume: error %d reading volumeinfo\n", (int)err); /* put tv back on the free list; the data in it is not valid */ tv->next = afs_freeVolList; afs_freeVolList = tv; /* staticFVolume contents are not valid */ afs_FVIndex = -1; ReleaseWriteLock(&afs_xvolume); return NULL; } afs_FVIndex = j; } tf = &staticFVolume; if (tf->cell == tcell->cellNum && tf->volume == volid) break; } tv->cell = tcell->cellNum; AFS_RWLOCK_INIT(&tv->lock, "volume lock"); tv->next = afs_volumes[i]; /* thread into list */ afs_volumes[i] = tv; tv->volume = volid; if (tf && (j != 0)) { tv->vtix = afs_FVIndex; tv->mtpoint = tf->mtpoint; tv->dotdot = tf->dotdot; tv->rootVnode = tf->rootVnode; tv->rootUnique = tf->rootUnique; } else { tv->vtix = -1; tv->rootVnode = tv->rootUnique = 0; afs_GetDynrootMountFid(&tv->dotdot); afs_GetDynrootMountFid(&tv->mtpoint); tv->mtpoint.Fid.Vnode = VNUM_FROM_TYPEID(VN_TYPE_MOUNT, tcell->cellIndex << 2); tv->mtpoint.Fid.Unique = volid; } } tv->refCount++; tv->states &= ~VRecheck; /* just checked it */ tv->accessTime = osi_Time(); ReleaseWriteLock(&afs_xvolume); if (type == 2) { LockAndInstallUVolumeEntry(tv, uve, tcell->cellNum, tcell, areq); } else if (type == 1) LockAndInstallNVolumeEntry(tv, nve, tcell->cellNum); else LockAndInstallVolumeEntry(tv, ove, tcell->cellNum); if (agood) { if (!tv->name) { tv->name = afs_osi_Alloc(strlen(aname) + 1); osi_Assert(tv->name != NULL); strcpy(tv->name, aname); } } for (i = 0; i < NMAXNSERVERS; i++) { tv->status[i] = not_busy; } ReleaseWriteLock(&tv->lock); return tv; }
/** * UFS specific version of afs_GetVolSlot * @return */ struct volume * afs_UFSGetVolSlot(void) { struct volume *tv = NULL, **lv; struct osi_file *tfile; afs_int32 i = -1, code; afs_int32 bestTime; struct volume *bestVp, *oldLp = NULL, **bestLp = NULL; char *oldname = NULL; afs_int32 oldvtix = -2; /* Initialize to a value that doesn't occur */ AFS_STATCNT(afs_UFSGetVolSlot); if (!afs_freeVolList) { /* get free slot */ bestTime = 0x7fffffff; bestVp = 0; bestLp = 0; for (i = 0; i < NVOLS; i++) { lv = &afs_volumes[i]; for (tv = *lv; tv; lv = &tv->next, tv = *lv) { if (tv->refCount == 0) { /* is this one available? */ if (tv->accessTime < bestTime) { /* best one available? */ bestTime = tv->accessTime; bestLp = lv; bestVp = tv; } } } } if (!bestVp) { afs_warn("afs_UFSGetVolSlot: no vol slots available\n"); goto error; } tv = bestVp; oldLp = *bestLp; *bestLp = tv->next; oldname = tv->name; tv->name = NULL; oldvtix = tv->vtix; /* now write out volume structure to file */ if (tv->vtix < 0) { tv->vtix = afs_volCounter++; /* now put on hash chain */ i = FVHash(tv->cell, tv->volume); staticFVolume.next = fvTable[i]; fvTable[i] = tv->vtix; } else { /* * Haul the guy in from disk so we don't overwrite hash table * next chain */ if (afs_FVIndex != tv->vtix) { tfile = osi_UFSOpen(&volumeInode); code = afs_osi_Read(tfile, sizeof(struct fvolume) * tv->vtix, &staticFVolume, sizeof(struct fvolume)); osi_UFSClose(tfile); if (code != sizeof(struct fvolume)) { afs_warn("afs_UFSGetVolSlot: error %d reading volumeinfo\n", (int)code); goto error; } afs_FVIndex = tv->vtix; } } afs_FVIndex = tv->vtix; staticFVolume.volume = tv->volume; staticFVolume.cell = tv->cell; staticFVolume.mtpoint = tv->mtpoint; staticFVolume.dotdot = tv->dotdot; staticFVolume.rootVnode = tv->rootVnode; staticFVolume.rootUnique = tv->rootUnique; tfile = osi_UFSOpen(&volumeInode); code = afs_osi_Write(tfile, sizeof(struct fvolume) * afs_FVIndex, &staticFVolume, sizeof(struct fvolume)); osi_UFSClose(tfile); if (code != sizeof(struct fvolume)) { afs_warn("afs_UFSGetVolSlot: error %d writing volumeinfo\n", (int)code); goto error; } if (oldname) { afs_osi_Free(oldname, strlen(oldname) + 1); oldname = NULL; } } else { tv = afs_freeVolList; afs_freeVolList = tv->next; } return tv; error: if (tv) { if (oldvtix == -2) { afs_warn("afs_UFSGetVolSlot: oldvtix is uninitialized\n"); return NULL; } if (oldname) { tv->name = oldname; oldname = NULL; } if (oldvtix < 0) { afs_volCounter--; fvTable[i] = staticFVolume.next; } if (bestLp) { *bestLp = oldLp; } tv->vtix = oldvtix; /* we messed with staticFVolume, so make sure someone else * doesn't think it's fine to use */ afs_FVIndex = -1; } return NULL; } /*afs_UFSGetVolSlot */
/*! * \brief Load the list of cells from given inode. * \param inode Source inode. * \param lookupcode * \return 0 for success. < 0 for error. */ int afs_cellname_init(afs_dcache_id_t *inode, int lookupcode) { struct osi_file *tfile; int cc, off = 0; ObtainWriteLock(&afs_xcell, 692); afs_cellnum_next = 1; afs_cellname_dirty = 0; if (cacheDiskType == AFS_FCACHE_TYPE_MEM) { ReleaseWriteLock(&afs_xcell); return 0; } if (lookupcode) { ReleaseWriteLock(&afs_xcell); return lookupcode; } tfile = osi_UFSOpen(inode); if (!tfile) { ReleaseWriteLock(&afs_xcell); return EIO; } afs_copy_inode(&afs_cellname_inode, inode); afs_cellname_inode_set = 1; while (1) { afs_int32 cellnum, clen, magic; struct cell_name *cn; char *cellname; cc = afs_osi_Read(tfile, off, &magic, sizeof(magic)); if (cc != sizeof(magic)) break; if (magic != AFS_CELLINFO_MAGIC) break; off += cc; cc = afs_osi_Read(tfile, off, &cellnum, sizeof(cellnum)); if (cc != sizeof(cellnum)) break; off += cc; cc = afs_osi_Read(tfile, off, &clen, sizeof(clen)); if (cc != sizeof(clen)) break; off += cc; cellname = afs_osi_Alloc(clen + 1); if (!cellname) break; cc = afs_osi_Read(tfile, off, cellname, clen); if (cc != clen) { afs_osi_Free(cellname, clen + 1); break; } off += cc; cellname[clen] = '\0'; if (afs_cellname_lookup_name(cellname) || afs_cellname_lookup_id(cellnum)) { afs_osi_Free(cellname, clen + 1); break; } cn = afs_cellname_new(cellname, cellnum); afs_osi_Free(cellname, clen + 1); } osi_UFSClose(tfile); ReleaseWriteLock(&afs_xcell); return 0; }
/** * UFS specific version of afs_GetVolSlot * @return */ struct volume * afs_UFSGetVolSlot(void) { register struct volume *tv, **lv; struct osi_file *tfile; register afs_int32 i, code; afs_int32 bestTime; struct volume *bestVp, **bestLp; AFS_STATCNT(afs_UFSGetVolSlot); if (!afs_freeVolList) { /* get free slot */ bestTime = 0x7fffffff; bestVp = 0; bestLp = 0; for (i = 0; i < NVOLS; i++) { lv = &afs_volumes[i]; for (tv = *lv; tv; lv = &tv->next, tv = *lv) { if (tv->refCount == 0) { /* is this one available? */ if (tv->accessTime < bestTime) { /* best one available? */ bestTime = tv->accessTime; bestLp = lv; bestVp = tv; } } } } if (!bestVp) osi_Panic("getvolslot none"); tv = bestVp; *bestLp = tv->next; if (tv->name) afs_osi_Free(tv->name, strlen(tv->name) + 1); tv->name = NULL; /* now write out volume structure to file */ if (tv->vtix < 0) { tv->vtix = afs_volCounter++; /* now put on hash chain */ i = FVHash(tv->cell, tv->volume); staticFVolume.next = fvTable[i]; fvTable[i] = tv->vtix; } else { /* * Haul the guy in from disk so we don't overwrite hash table * next chain */ if (afs_FVIndex != tv->vtix) { #if defined(LINUX_USE_FH) tfile = osi_UFSOpen_fh(&volumeinfo_fh, volumeinfo_fh_type); #else tfile = osi_UFSOpen(volumeInode); #endif code = afs_osi_Read(tfile, sizeof(struct fvolume) * tv->vtix, &staticFVolume, sizeof(struct fvolume)); if (code != sizeof(struct fvolume)) osi_Panic("read volumeinfo"); osi_UFSClose(tfile); afs_FVIndex = tv->vtix; } } afs_FVIndex = tv->vtix; staticFVolume.volume = tv->volume; staticFVolume.cell = tv->cell; staticFVolume.mtpoint = tv->mtpoint; staticFVolume.dotdot = tv->dotdot; staticFVolume.rootVnode = tv->rootVnode; staticFVolume.rootUnique = tv->rootUnique; #if defined(LINUX_USE_FH) tfile = osi_UFSOpen_fh(&volumeinfo_fh, volumeinfo_fh_type); #else tfile = osi_UFSOpen(volumeInode); #endif code = afs_osi_Write(tfile, sizeof(struct fvolume) * afs_FVIndex, &staticFVolume, sizeof(struct fvolume)); if (code != sizeof(struct fvolume)) osi_Panic("write volumeinfo"); osi_UFSClose(tfile); } else { tv = afs_freeVolList; afs_freeVolList = tv->next; } return tv; } /*afs_UFSGetVolSlot */