int afs_MemHandleLink(struct vcache *avc, struct vrequest *areq) { struct dcache *tdc; char *tp, *rbuf; afs_size_t offset, len; afs_int32 tlen, alen; afs_int32 code; AFS_STATCNT(afs_MemHandleLink); /* 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 */ if (!avc->linkData) { void *addr; tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 0); if (!tdc) { 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 = osi_AllocLargeSpace(AFS_LRALLOCSIZ); ObtainReadLock(&tdc->lock); addr = afs_MemCacheOpen(&tdc->f.inode); tlen = len; code = afs_MemReadBlk(addr, 0, rbuf, tlen); afs_MemCacheClose(addr); ReleaseReadLock(&tdc->lock); afs_PutDCache(tdc); rbuf[alen - 1] = 0; alen = strlen(rbuf) + 1; tp = afs_osi_Alloc(alen); /* make room for terminating null */ osi_Assert(tp != NULL); memcpy(tp, rbuf, alen); osi_FreeLargeSpace(rbuf); if (code != len) { afs_osi_Free(tp, alen); return EIO; } avc->linkData = tp; } return 0; }
int afs_MemReadUIO(afs_dcache_id_t *ainode, struct uio *uioP) { struct memCacheEntry *mceP = (struct memCacheEntry *)afs_MemCacheOpen(ainode); int length = mceP->size - AFS_UIO_OFFSET(uioP); afs_int32 code; AFS_STATCNT(afs_MemReadUIO); ObtainReadLock(&mceP->afs_memLock); length = (length < AFS_UIO_RESID(uioP)) ? length : AFS_UIO_RESID(uioP); AFS_UIOMOVE(mceP->data + AFS_UIO_OFFSET(uioP), length, UIO_READ, uioP, code); ReleaseReadLock(&mceP->afs_memLock); return code; }
int afs_MemWriteUIO(afs_dcache_id_t *ainode, struct uio *uioP) { struct memCacheEntry *mceP = (struct memCacheEntry *)afs_MemCacheOpen(ainode); afs_int32 code; AFS_STATCNT(afs_MemWriteUIO); ObtainWriteLock(&mceP->afs_memLock, 312); if (AFS_UIO_RESID(uioP) + AFS_UIO_OFFSET(uioP) > mceP->dataSize) { char *oldData = mceP->data; mceP->data = afs_osi_Alloc(AFS_UIO_RESID(uioP) + AFS_UIO_OFFSET(uioP)); if (mceP->data == NULL) { /* no available memory */ mceP->data = oldData; /* revert back change that was made */ ReleaseWriteLock(&mceP->afs_memLock); afs_warn("afs: afs_MemWriteBlk mem alloc failure (%ld bytes)\n", (long)(AFS_UIO_RESID(uioP) + AFS_UIO_OFFSET(uioP))); return -ENOMEM; } AFS_GUNLOCK(); memcpy(mceP->data, oldData, mceP->size); AFS_GLOCK(); afs_osi_Free(oldData, mceP->dataSize); mceP->dataSize = AFS_UIO_RESID(uioP) + AFS_UIO_OFFSET(uioP); } if (mceP->size < AFS_UIO_OFFSET(uioP)) memset(mceP->data + mceP->size, 0, (int)(AFS_UIO_OFFSET(uioP) - mceP->size)); AFS_UIOMOVE(mceP->data + AFS_UIO_OFFSET(uioP), AFS_UIO_RESID(uioP), UIO_WRITE, uioP, code); if (AFS_UIO_OFFSET(uioP) > mceP->size) mceP->size = AFS_UIO_OFFSET(uioP); ReleaseWriteLock(&mceP->afs_memLock); return code; }