#include <afsconfig.h>
#include "afs/param.h"
-RCSID
- ("$Header$");
#include "afs/sysincludes.h" /* Standard vendor system headers */
#include "afsincludes.h" /* Afs-based standard headers */
#include "afs/afs_cbqueue.h"
#include "afs/nfsclient.h"
#include "afs/afs_osidnlc.h"
+#include "afs/afs_osi.h"
extern char afs_zeros[AFS_ZEROS];
-afs_int32 maxIHint;
-afs_int32 nihints; /* # of above actually in-use */
-afs_int32 usedihint;
-
-
/* Imported variables */
extern afs_rwlock_t afs_xdcache;
extern unsigned char *afs_indexFlags;
/* Forward declarations */
void afs_PrefetchChunk(struct vcache *avc, struct dcache *adc,
- struct AFS_UCRED *acred, struct vrequest *areq);
+ afs_ucred_t *acred, struct vrequest *areq);
int
-afs_MemRead(register struct vcache *avc, struct uio *auio,
- struct AFS_UCRED *acred, daddr_t albn, struct buf **abpp,
- int noLock)
+afs_read(struct vcache *avc, struct uio *auio, afs_ucred_t *acred,
+ int noLock)
{
afs_size_t totalLength;
afs_size_t transferLength;
afs_int32 trimlen;
struct dcache *tdc = 0;
afs_int32 error, trybusy = 1;
- struct uio tuio;
- struct iovec *tvec;
+ struct uio *tuiop = NULL;
afs_int32 code;
struct vrequest treq;
- AFS_STATCNT(afs_MemRead);
+ AFS_STATCNT(afs_read);
+
if (avc->vc_error)
return EIO;
+ AFS_DISCON_LOCK();
+
/* check that we have the latest status info in the vnode cache */
if ((code = afs_InitReq(&treq, acred)))
- return code;
+ goto out;
+
if (!noLock) {
+ if (!avc)
+ osi_Panic("null avc in afs_GenericRead");
+
code = afs_VerifyVCache(avc, &treq);
if (code) {
code = afs_CheckCode(code, &treq, 8); /* failed to get it */
- return code;
+ goto out;
}
}
#ifndef AFS_VM_RDWR_ENV
if (!afs_AccessOK
(avc, PRSFS_READ, &treq,
CHECK_MODE_BITS | CMB_ALLOW_EXEC_AS_READ)) {
- return afs_CheckCode(EACCES, &treq, 9);
+ code = afs_CheckCode(EACCES, &treq, 9);
+ goto out;
}
}
#endif
- tvec = (struct iovec *)osi_AllocSmallSpace(sizeof(struct iovec));
- totalLength = auio->afsio_resid;
- filePos = auio->afsio_offset;
+ totalLength = AFS_UIO_RESID(auio);
+ filePos = AFS_UIO_OFFSET(auio);
afs_Trace4(afs_iclSetp, CM_TRACE_READ, ICL_TYPE_POINTER, avc,
ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(filePos), ICL_TYPE_INT32,
totalLength, ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(avc->m.Length));
+ ICL_HANDLE_OFFSET(avc->f.m.Length));
error = 0;
transferLength = 0;
if (!noLock)
ObtainReadLock(&avc->lock);
#if defined(AFS_TEXT_ENV) && !defined(AFS_VM_RDWR_ENV)
if (avc->flushDV.high == AFS_MAXDV && avc->flushDV.low == AFS_MAXDV) {
- hset(avc->flushDV, avc->m.DataVersion);
+ hset(avc->flushDV, avc->f.m.DataVersion);
}
#endif
* Locks held:
* avc->lock(R)
*/
- while (totalLength > 0) {
+ if (filePos >= avc->f.m.Length) {
+ if (len > AFS_ZEROS)
+ len = sizeof(afs_zeros); /* and in 0 buffer */
+ len = 0;
+ trimlen = len;
+ tuiop = afsio_partialcopy(auio, trimlen);
+ AFS_UIOMOVE(afs_zeros, trimlen, UIO_READ, tuiop, code);
+ }
+
+ while (avc->f.m.Length > 0 && totalLength > 0) {
/* read all of the cached info */
- if (filePos >= avc->m.Length)
+ if (filePos >= avc->f.m.Length)
break; /* all done */
if (noLock) {
if (tdc) {
if (tdc) {
ObtainReadLock(&tdc->lock);
offset = filePos - AFS_CHUNKTOBASE(tdc->f.chunk);
- len = tdc->f.chunkBytes - offset;
+ len = tdc->validPos - filePos;
}
} else {
/* a tricky question: does the presence of the DFFetching flag
afs_PutDCache(tdc); /* before reusing tdc */
}
tdc = afs_GetDCache(avc, filePos, &treq, &offset, &len, 2);
+ if (!tdc) {
+ error = ENETDOWN;
+ break;
+ }
+
ObtainReadLock(&tdc->lock);
/* now, first try to start transfer, if we'll need the data. If
* data already coming, we don't need to do this, obviously. Type
* 2 requests never return a null dcache entry, btw.
*/
if (!(tdc->dflags & DFFetching)
- && !hsame(avc->m.DataVersion, tdc->f.versionNo)) {
+ && !hsame(avc->f.m.DataVersion, tdc->f.versionNo)) {
/* have cache entry, it is not coming in now,
* and we'll need new data */
tagain:
tdc->mflags |= DFFetchReq;
bp = afs_BQueue(BOP_FETCH, avc, B_DONTWAIT, 0, acred,
(afs_size_t) filePos, (afs_size_t) 0,
- tdc);
+ tdc, NULL, NULL);
if (!bp) {
+ /* Bkg table full; retry deadlocks */
tdc->mflags &= ~DFFetchReq;
trybusy = 0; /* Avoid bkg daemon since they're too busy */
ReleaseWriteLock(&tdc->mflock);
} else {
/* no longer fetching, verify data version
* (avoid new GetDCache call) */
- if (hsame(avc->m.DataVersion, tdc->f.versionNo)
+ if (hsame(avc->f.m.DataVersion, tdc->f.versionNo)
&& ((len = tdc->validPos - filePos) > 0)) {
offset = filePos - AFS_CHUNKTOBASE(tdc->f.chunk);
} else {
/* don't have current data, so get it below */
afs_Trace3(afs_iclSetp, CM_TRACE_VERSIONNO,
ICL_TYPE_INT64, ICL_HANDLE_OFFSET(filePos),
- ICL_TYPE_HYPER, &avc->m.DataVersion,
+ ICL_TYPE_HYPER, &avc->f.m.DataVersion,
ICL_TYPE_HYPER, &tdc->f.versionNo);
ReleaseReadLock(&tdc->lock);
afs_PutDCache(tdc);
len = AFS_CHUNKTOSIZE(tdc->f.chunk) - offset; /* bytes left in chunk addr space */
if (len > totalLength)
len = totalLength; /* and still within xfr request */
- tlen = avc->m.Length - offset; /* and still within file */
+ tlen = avc->f.m.Length - offset; /* and still within file */
if (len > tlen)
len = tlen;
if (len > AFS_ZEROS)
len = sizeof(afs_zeros); /* and in 0 buffer */
- afsio_copy(auio, &tuio, tvec);
trimlen = len;
- afsio_trim(&tuio, trimlen);
- AFS_UIOMOVE(afs_zeros, trimlen, UIO_READ, &tuio, code);
+ tuiop = afsio_partialcopy(auio, trimlen);
+ AFS_UIOMOVE(afs_zeros, trimlen, UIO_READ, tuiop, code);
if (code) {
error = code;
break;
}
} else {
- /* get the data from the mem cache */
+ /* get the data from the cache */
/* mung uio structure to be right for this transfer */
- afsio_copy(auio, &tuio, tvec);
trimlen = len;
- afsio_trim(&tuio, trimlen);
- tuio.afsio_offset = offset;
+ tuiop = afsio_partialcopy(auio, trimlen);
+ AFS_UIO_SETOFFSET(tuiop, offset);
- code = afs_MemReadUIO(tdc->f.inode, &tuio);
+ code = (*(afs_cacheType->vreadUIO))(&tdc->f.inode, tuiop);
if (code) {
error = code;
}
}
/* otherwise we've read some, fixup length, etc and continue with next seg */
- len = len - tuio.afsio_resid; /* compute amount really transferred */
+ len = len - AFS_UIO_RESID(tuiop); /* compute amount really transferred */
trimlen = len;
afsio_skip(auio, trimlen); /* update input uio structure */
totalLength -= len;
if (len <= 0)
break; /* surprise eof */
+ if (tuiop) {
+ afsio_free(tuiop);
+ tuiop = NULL;
+ }
} /* the whole while loop */
/*
#if !defined(AFS_VM_RDWR_ENV)
/* try to queue prefetch, if needed */
if (!noLock) {
- afs_PrefetchChunk(avc, tdc, acred, &treq);
+ if (!(tdc->mflags &DFNextStarted))
+ afs_PrefetchChunk(avc, tdc, acred, &treq);
}
#endif
afs_PutDCache(tdc);
}
if (!noLock)
ReleaseReadLock(&avc->lock);
- osi_FreeSmallSpace(tvec);
- error = afs_CheckCode(error, &treq, 10);
- return error;
+
+ code = afs_CheckCode(error, &treq, 10);
+
+ if (tuiop)
+ afsio_free(tuiop);
+
+out:
+ AFS_DISCON_UNLOCK();
+ return code;
}
/* called with the dcache entry triggering the fetch, the vcache entry involved,
*/
void
afs_PrefetchChunk(struct vcache *avc, struct dcache *adc,
- struct AFS_UCRED *acred, struct vrequest *areq)
+ afs_ucred_t *acred, struct vrequest *areq)
{
- register struct dcache *tdc;
+ struct dcache *tdc;
afs_size_t offset;
afs_size_t j1, j2; /* junk vbls for GetDCache to trash */
offset = AFS_CHUNKTOBASE(offset); /* base of next chunk */
ObtainReadLock(&adc->lock);
ObtainSharedLock(&adc->mflock, 662);
- if (offset < avc->m.Length && !(adc->mflags & DFNextStarted)
+ if (offset < avc->f.m.Length && !(adc->mflags & DFNextStarted)
&& !afs_BBusy()) {
struct brequest *bp;
ReleaseReadLock(&adc->lock);
tdc = afs_GetDCache(avc, offset, areq, &j1, &j2, 2); /* type 2 never returns 0 */
+ /*
+ * In disconnected mode, type 2 can return 0 because it doesn't
+ * make any sense to allocate a dcache we can never fill
+ */
+ if (tdc == NULL)
+ return;
+
ObtainSharedLock(&tdc->mflock, 651);
if (!(tdc->mflags & DFFetchReq)) {
/* ask the daemon to do the work */
* since we don't want to wait for it to finish before doing so ourselves.
*/
bp = afs_BQueue(BOP_FETCH, avc, B_DONTWAIT, 0, acred,
- (afs_size_t) offset, (afs_size_t) 1, tdc);
+ (afs_size_t) offset, (afs_size_t) 1, tdc,
+ (void *)0, (void *)0);
if (!bp) {
/* Bkg table full; just abort non-important prefetching to avoid deadlocks */
tdc->mflags &= ~DFFetchReq;
}
int
-afs_UFSRead(register struct vcache *avc, struct uio *auio,
- struct AFS_UCRED *acred, daddr_t albn, struct buf **abpp,
- int noLock)
+afs_UFSReadUIO(afs_dcache_id_t *cacheId, struct uio *tuiop)
{
- afs_size_t totalLength;
- afs_size_t transferLength;
- afs_size_t filePos;
- afs_size_t offset, len, tlen;
- afs_int32 trimlen;
- struct dcache *tdc = 0;
- afs_int32 error;
- struct uio tuio;
- struct iovec *tvec;
+ int code;
struct osi_file *tfile;
- afs_int32 code;
- int trybusy = 1;
- struct vrequest treq;
- AFS_STATCNT(afs_UFSRead);
- if (avc && avc->vc_error)
- return EIO;
+ tfile = (struct osi_file *) osi_UFSOpen(cacheId);
- /* check that we have the latest status info in the vnode cache */
- if ((code = afs_InitReq(&treq, acred)))
- return code;
- if (!noLock) {
- if (!avc)
- osi_Panic("null avc in afs_UFSRead");
- else {
- code = afs_VerifyVCache(avc, &treq);
- if (code) {
- code = afs_CheckCode(code, &treq, 11); /* failed to get it */
- return code;
- }
- }
- }
-#ifndef AFS_VM_RDWR_ENV
- if (AFS_NFSXLATORREQ(acred)) {
- if (!afs_AccessOK
- (avc, PRSFS_READ, &treq,
- CHECK_MODE_BITS | CMB_ALLOW_EXEC_AS_READ)) {
- return afs_CheckCode(EACCES, &treq, 12);
- }
- }
-#endif
-
- tvec = (struct iovec *)osi_AllocSmallSpace(sizeof(struct iovec));
- totalLength = auio->afsio_resid;
- filePos = auio->afsio_offset;
- afs_Trace4(afs_iclSetp, CM_TRACE_READ, ICL_TYPE_POINTER, avc,
- ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(filePos), ICL_TYPE_INT32,
- totalLength, ICL_TYPE_OFFSET,
- ICL_HANDLE_OFFSET(avc->m.Length));
- error = 0;
- transferLength = 0;
- if (!noLock)
- ObtainReadLock(&avc->lock);
-#if defined(AFS_TEXT_ENV) && !defined(AFS_VM_RDWR_ENV)
- if (avc->flushDV.high == AFS_MAXDV && avc->flushDV.low == AFS_MAXDV) {
- hset(avc->flushDV, avc->m.DataVersion);
- }
-#endif
-
- while (totalLength > 0) {
- /* read all of the cached info */
- if (filePos >= avc->m.Length)
- break; /* all done */
- if (noLock) {
- if (tdc) {
- ReleaseReadLock(&tdc->lock);
- afs_PutDCache(tdc);
- }
- tdc = afs_FindDCache(avc, filePos);
- if (tdc) {
- ObtainReadLock(&tdc->lock);
- offset = filePos - AFS_CHUNKTOBASE(tdc->f.chunk);
- len = tdc->validPos - filePos;
- }
- } else {
- /* a tricky question: does the presence of the DFFetching flag
- * mean that we're fetching the latest version of the file? No.
- * The server could update the file as soon as the fetch responsible
- * for the setting of the DFFetching flag completes.
- *
- * However, the presence of the DFFetching flag (visible under
- * a dcache read lock since it is set and cleared only under a
- * dcache write lock) means that we're fetching as good a version
- * as was known to this client at the time of the last call to
- * afs_VerifyVCache, since the latter updates the stat cache's
- * m.DataVersion field under a vcache write lock, and from the
- * time that the DFFetching flag goes on in afs_GetDCache (before
- * the fetch starts), to the time it goes off (after the fetch
- * completes), afs_GetDCache keeps at least a read lock on the
- * vcache entry.
- *
- * This means that if the DFFetching flag is set, we can use that
- * data for any reads that must come from the current version of
- * the file (current == m.DataVersion).
- *
- * Another way of looking at this same point is this: if we're
- * fetching some data and then try do an afs_VerifyVCache, the
- * VerifyVCache operation will not complete until after the
- * DFFetching flag is turned off and the dcache entry's f.versionNo
- * field is updated.
- *
- * Note, by the way, that if DFFetching is set,
- * m.DataVersion > f.versionNo (the latter is not updated until
- * after the fetch completes).
- */
- if (tdc) {
- ReleaseReadLock(&tdc->lock);
- afs_PutDCache(tdc); /* before reusing tdc */
- }
- tdc = afs_GetDCache(avc, filePos, &treq, &offset, &len, 2);
- ObtainReadLock(&tdc->lock);
- /* now, first try to start transfer, if we'll need the data. If
- * data already coming, we don't need to do this, obviously. Type
- * 2 requests never return a null dcache entry, btw. */
- if (!(tdc->dflags & DFFetching)
- && !hsame(avc->m.DataVersion, tdc->f.versionNo)) {
- /* have cache entry, it is not coming in now, and we'll need new data */
- tagain:
- if (trybusy && !afs_BBusy()) {
- struct brequest *bp;
- /* daemon is not busy */
- ObtainSharedLock(&tdc->mflock, 667);
- if (!(tdc->mflags & DFFetchReq)) {
- UpgradeSToWLock(&tdc->mflock, 668);
- tdc->mflags |= DFFetchReq;
- bp = afs_BQueue(BOP_FETCH, avc, B_DONTWAIT, 0, acred,
- (afs_size_t) filePos, (afs_size_t) 0,
- tdc);
- if (!bp) {
- /* Bkg table full; retry deadlocks */
- tdc->mflags &= ~DFFetchReq;
- trybusy = 0; /* Avoid bkg daemon since they're too busy */
- ReleaseWriteLock(&tdc->mflock);
- goto tagain;
- }
- ConvertWToSLock(&tdc->mflock);
- }
- code = 0;
- ConvertSToRLock(&tdc->mflock);
- while (!code && tdc->mflags & DFFetchReq) {
- afs_Trace4(afs_iclSetp, CM_TRACE_DCACHEWAIT,
- ICL_TYPE_STRING, __FILE__, ICL_TYPE_INT32,
- __LINE__, ICL_TYPE_POINTER, tdc,
- ICL_TYPE_INT32, tdc->dflags);
- /* don't need waiting flag on this one */
- ReleaseReadLock(&tdc->mflock);
- ReleaseReadLock(&tdc->lock);
- ReleaseReadLock(&avc->lock);
- code = afs_osi_SleepSig(&tdc->validPos);
- ObtainReadLock(&avc->lock);
- ObtainReadLock(&tdc->lock);
- ObtainReadLock(&tdc->mflock);
- }
- ReleaseReadLock(&tdc->mflock);
- if (code) {
- error = code;
- break;
- }
- }
- }
- /* now data may have started flowing in (if DFFetching is on). If
- * data is now streaming in, then wait for some interesting stuff.
- */
- code = 0;
- while (!code && (tdc->dflags & DFFetching)
- && tdc->validPos <= filePos) {
- /* too early: wait for DFFetching flag to vanish,
- * or data to appear */
- afs_Trace4(afs_iclSetp, CM_TRACE_DCACHEWAIT, ICL_TYPE_STRING,
- __FILE__, ICL_TYPE_INT32, __LINE__,
- ICL_TYPE_POINTER, tdc, ICL_TYPE_INT32,
- tdc->dflags);
- ReleaseReadLock(&tdc->lock);
- ReleaseReadLock(&avc->lock);
- code = afs_osi_SleepSig(&tdc->validPos);
- ObtainReadLock(&avc->lock);
- ObtainReadLock(&tdc->lock);
- }
- if (code) {
- error = code;
- break;
- }
- /* fetching flag gone, data is here, or we never tried
- * (BBusy for instance) */
- if (tdc->dflags & DFFetching) {
- /* still fetching, some new data is here:
- * compute length and offset */
- offset = filePos - AFS_CHUNKTOBASE(tdc->f.chunk);
- len = tdc->validPos - filePos;
- } else {
- /* no longer fetching, verify data version (avoid new
- * GetDCache call) */
- if (hsame(avc->m.DataVersion, tdc->f.versionNo)
- && ((len = tdc->validPos - filePos) > 0)) {
- offset = filePos - AFS_CHUNKTOBASE(tdc->f.chunk);
- } else {
- /* don't have current data, so get it below */
- afs_Trace3(afs_iclSetp, CM_TRACE_VERSIONNO,
- ICL_TYPE_INT64, ICL_HANDLE_OFFSET(filePos),
- ICL_TYPE_HYPER, &avc->m.DataVersion,
- ICL_TYPE_HYPER, &tdc->f.versionNo);
- ReleaseReadLock(&tdc->lock);
- afs_PutDCache(tdc);
- tdc = NULL;
- }
- }
-
- if (!tdc) {
- /* If we get, it was not possible to start the
- * background daemon. With flag == 1 afs_GetDCache
- * does the FetchData rpc synchronously.
- */
- ReleaseReadLock(&avc->lock);
- tdc = afs_GetDCache(avc, filePos, &treq, &offset, &len, 1);
- ObtainReadLock(&avc->lock);
- if (tdc)
- ObtainReadLock(&tdc->lock);
- }
- }
-
- if (!tdc) {
- error = EIO;
- break;
- }
- len = tdc->validPos - filePos;
- afs_Trace3(afs_iclSetp, CM_TRACE_VNODEREAD, ICL_TYPE_POINTER, tdc,
- ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(offset),
- ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(len));
- if (len > totalLength)
- len = totalLength; /* will read len bytes */
- if (len <= 0) { /* shouldn't get here if DFFetching is on */
- afs_Trace4(afs_iclSetp, CM_TRACE_VNODEREAD2, ICL_TYPE_POINTER,
- tdc, ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(tdc->validPos),
- ICL_TYPE_INT32, tdc->f.chunkBytes, ICL_TYPE_INT32,
- tdc->dflags);
- /* read past the end of a chunk, may not be at next chunk yet, and yet
- * also not at eof, so may have to supply fake zeros */
- len = AFS_CHUNKTOSIZE(tdc->f.chunk) - offset; /* bytes left in chunk addr space */
- if (len > totalLength)
- len = totalLength; /* and still within xfr request */
- tlen = avc->m.Length - offset; /* and still within file */
- if (len > tlen)
- len = tlen;
- if (len > AFS_ZEROS)
- len = sizeof(afs_zeros); /* and in 0 buffer */
- afsio_copy(auio, &tuio, tvec);
- trimlen = len;
- afsio_trim(&tuio, trimlen);
- AFS_UIOMOVE(afs_zeros, trimlen, UIO_READ, &tuio, code);
- if (code) {
- error = code;
- break;
- }
- } else {
- /* get the data from the file */
-#ifdef IHINT
- if (tfile = tdc->ihint) {
- if (tdc->f.inode != tfile->inum) {
- afs_warn("afs_UFSRead: %x hint mismatch tdc %d inum %d\n",
- tdc, tdc->f.inode, tfile->inum);
- osi_UFSClose(tfile);
- tdc->ihint = tfile = 0;
- nihints--;
- }
- }
- if (tfile != 0) {
- usedihint++;
- } else
-#endif /* IHINT */
-
- tfile = (struct osi_file *)osi_UFSOpen(tdc->f.inode);
- /* mung uio structure to be right for this transfer */
- afsio_copy(auio, &tuio, tvec);
- trimlen = len;
- afsio_trim(&tuio, trimlen);
- tuio.afsio_offset = offset;
#if defined(AFS_AIX41_ENV)
- AFS_GUNLOCK();
- code =
- VNOP_RDWR(tfile->vnode, UIO_READ, FREAD, &tuio, NULL, NULL,
- NULL, &afs_osi_cred);
- AFS_GLOCK();
+ AFS_GUNLOCK();
+ code =
+ VNOP_RDWR(tfile->vnode, UIO_READ, FREAD, tuiop, NULL, NULL,
+ NULL, afs_osi_credp);
+ AFS_GLOCK();
#elif defined(AFS_AIX32_ENV)
- code =
- VNOP_RDWR(tfile->vnode, UIO_READ, FREAD, &tuio, NULL, NULL);
- /* Flush all JFS pages now for big performance gain in big file cases
- * If we do something like this, must check to be sure that AFS file
- * isn't mmapped... see afs_gn_map() for why.
- */
-/*
- if (tfile->vnode->v_gnode && tfile->vnode->v_gnode->gn_seg) {
- many different ways to do similar things:
+ code =
+ VNOP_RDWR(tfile->vnode, UIO_READ, FREAD, tuiop, NULL, NULL);
+ /* Flush all JFS pages now for big performance gain in big file cases
+ * If we do something like this, must check to be sure that AFS file
+ * isn't mmapped... see afs_gn_map() for why.
+ */
+ /*
+ if (tfile->vnode->v_gnode && tfile->vnode->v_gnode->gn_seg) {
+ any different ways to do similar things:
so far, the best performing one is #2, but #1 might match it if we
straighten out the confusion regarding which pages to flush. It
really does matter.
}
*/
#elif defined(AFS_AIX_ENV)
- code =
- VNOP_RDWR(tfile->vnode, UIO_READ, FREAD, (off_t) & offset,
- &tuio, NULL, NULL, -1);
+ code =
+ VNOP_RDWR(tfile->vnode, UIO_READ, FREAD, (off_t) & offset,
+ tuiop, NULL, NULL, -1);
#elif defined(AFS_SUN5_ENV)
- AFS_GUNLOCK();
- VOP_RWLOCK(tfile->vnode, 0);
- code = VOP_READ(tfile->vnode, &tuio, 0, &afs_osi_cred);
- VOP_RWUNLOCK(tfile->vnode, 0);
- AFS_GLOCK();
+ AFS_GUNLOCK();
+#ifdef AFS_SUN510_ENV
+ {
+ caller_context_t ct;
+ VOP_RWLOCK(tfile->vnode, 0, &ct);
+ code = VOP_READ(tfile->vnode, tuiop, 0, afs_osi_credp, &ct);
+ VOP_RWUNLOCK(tfile->vnode, 0, &ct);
+ }
+#else
+ VOP_RWLOCK(tfile->vnode, 0);
+ code = VOP_READ(tfile->vnode, tuiop, 0, afs_osi_credp);
+ VOP_RWUNLOCK(tfile->vnode, 0);
+#endif
+ AFS_GLOCK();
#elif defined(AFS_SGI_ENV)
- AFS_GUNLOCK();
- AFS_VOP_RWLOCK(tfile->vnode, VRWLOCK_READ);
- AFS_VOP_READ(tfile->vnode, &tuio, IO_ISLOCKED, &afs_osi_cred,
- code);
- AFS_VOP_RWUNLOCK(tfile->vnode, VRWLOCK_READ);
- AFS_GLOCK();
-#elif defined(AFS_OSF_ENV)
- tuio.uio_rw = UIO_READ;
- AFS_GUNLOCK();
- VOP_READ(tfile->vnode, &tuio, 0, &afs_osi_cred, code);
- AFS_GLOCK();
-#elif defined(AFS_SUN_ENV)
- code = VOP_RDWR(tfile->vnode, &tuio, UIO_READ, 0, &afs_osi_cred);
+ AFS_GUNLOCK();
+ AFS_VOP_RWLOCK(tfile->vnode, VRWLOCK_READ);
+ AFS_VOP_READ(tfile->vnode, tuiop, IO_ISLOCKED, afs_osi_credp,
+ code);
+ AFS_VOP_RWUNLOCK(tfile->vnode, VRWLOCK_READ);
+ AFS_GLOCK();
#elif defined(AFS_HPUX100_ENV)
- AFS_GUNLOCK();
- code = VOP_RDWR(tfile->vnode, &tuio, UIO_READ, 0, &afs_osi_cred);
- AFS_GLOCK();
+ AFS_GUNLOCK();
+ code = VOP_RDWR(tfile->vnode, tuiop, UIO_READ, 0, afs_osi_credp);
+ AFS_GLOCK();
#elif defined(AFS_LINUX20_ENV)
- AFS_GUNLOCK();
- code = osi_file_uio_rdwr(tfile, &tuio, UIO_READ);
- AFS_GLOCK();
+ AFS_GUNLOCK();
+ code = osi_rdwr(tfile, tuiop, UIO_READ);
+ AFS_GLOCK();
+#elif defined(AFS_DARWIN80_ENV)
+ AFS_GUNLOCK();
+ code = VNOP_READ(tfile->vnode, tuiop, 0, afs_osi_ctxtp);
+ AFS_GLOCK();
#elif defined(AFS_DARWIN_ENV)
- AFS_GUNLOCK();
- VOP_LOCK(tfile->vnode, LK_EXCLUSIVE, current_proc());
- code = VOP_READ(tfile->vnode, &tuio, 0, &afs_osi_cred);
- VOP_UNLOCK(tfile->vnode, 0, current_proc());
- AFS_GLOCK();
-#elif defined(AFS_FBSD50_ENV)
- AFS_GUNLOCK();
- VOP_LOCK(tfile->vnode, LK_EXCLUSIVE, curthread);
- code = VOP_READ(tfile->vnode, &tuio, 0, &afs_osi_cred);
- VOP_UNLOCK(tfile->vnode, 0, curthread);
- AFS_GLOCK();
+ AFS_GUNLOCK();
+ VOP_LOCK(tfile->vnode, LK_EXCLUSIVE, current_proc());
+ code = VOP_READ(tfile->vnode, tuiop, 0, afs_osi_credp);
+ VOP_UNLOCK(tfile->vnode, 0, current_proc());
+ AFS_GLOCK();
+#elif defined(AFS_FBSD80_ENV)
+ AFS_GUNLOCK();
+ VOP_LOCK(tfile->vnode, LK_EXCLUSIVE);
+ code = VOP_READ(tfile->vnode, tuiop, 0, afs_osi_credp);
+ VOP_UNLOCK(tfile->vnode, 0);
+ AFS_GLOCK();
+#elif defined(AFS_FBSD_ENV)
+ AFS_GUNLOCK();
+ VOP_LOCK(tfile->vnode, LK_EXCLUSIVE, curthread);
+ code = VOP_READ(tfile->vnode, tuiop, 0, afs_osi_credp);
+ VOP_UNLOCK(tfile->vnode, 0, curthread);
+ AFS_GLOCK();
+#elif defined(AFS_NBSD_ENV)
+ tuiop->uio_rw = UIO_READ;
+ AFS_GUNLOCK();
+ VOP_LOCK(tfile->vnode, LK_EXCLUSIVE);
+ code = VOP_READ(tfile->vnode, tuiop, 0, afs_osi_credp);
+# if defined(AFS_NBSD60_ENV)
+ VOP_UNLOCK(tfile->vnode);
+# else
+ VOP_UNLOCK(tfile->vnode, 0);
+# endif
+ AFS_GLOCK();
#elif defined(AFS_XBSD_ENV)
- AFS_GUNLOCK();
- VOP_LOCK(tfile->vnode, LK_EXCLUSIVE, curproc);
- code = VOP_READ(tfile->vnode, &tuio, 0, &afs_osi_cred);
- VOP_UNLOCK(tfile->vnode, 0, curproc);
- AFS_GLOCK();
+ AFS_GUNLOCK();
+ VOP_LOCK(tfile->vnode, LK_EXCLUSIVE, curproc);
+ code = VOP_READ(tfile->vnode, tuiop, 0, afs_osi_credp);
+ VOP_UNLOCK(tfile->vnode, 0, curproc);
+ AFS_GLOCK();
#else
- code = VOP_RDWR(tfile->vnode, &tuio, UIO_READ, 0, &afs_osi_cred);
-#endif
-
-#ifdef IHINT
- if (!tdc->ihint && nihints < maxIHint) {
- tdc->ihint = tfile;
- nihints++;
- } else
-#endif /* IHINT */
- osi_UFSClose(tfile);
-
- if (code) {
- error = code;
- break;
- }
- }
- /* otherwise we've read some, fixup length, etc and continue with next seg */
- len = len - tuio.afsio_resid; /* compute amount really transferred */
- trimlen = len;
- afsio_skip(auio, trimlen); /* update input uio structure */
- totalLength -= len;
- transferLength += len;
- filePos += len;
- if (len <= 0)
- break; /* surprise eof */
- }
-
- /* if we make it here with tdc non-zero, then it is the last chunk we
- * dealt with, and we have to release it when we're done. We hold on
- * to it in case we need to do a prefetch, obviously.
- */
- if (tdc) {
- ReleaseReadLock(&tdc->lock);
-#if !defined(AFS_VM_RDWR_ENV)
- /* try to queue prefetch, if needed */
- if (!noLock) {
- if (!(tdc->mflags & DFNextStarted))
- afs_PrefetchChunk(avc, tdc, acred, &treq);
- }
+ code = VOP_RDWR(tfile->vnode, tuiop, UIO_READ, 0, afs_osi_credp);
#endif
- afs_PutDCache(tdc);
- }
- if (!noLock)
- ReleaseReadLock(&avc->lock);
+ osi_UFSClose(tfile);
- osi_FreeSmallSpace(tvec);
- error = afs_CheckCode(error, &treq, 13);
- return error;
+ return code;
}