* Implements:
* afs_MemRead
* afs_PrefetchChunk
- * afs_UFSReadFast
* afs_UFSRead
*
*/
#include <afsconfig.h>
-#include "../afs/param.h"
+#include "afs/param.h"
-RCSID("$Header$");
+RCSID
+ ("$Header$");
-#include "../afs/sysincludes.h" /* Standard vendor system headers */
-#include "../afs/afsincludes.h" /* Afs-based standard headers */
-#include "../afs/afs_stats.h" /* statistics */
-#include "../afs/afs_cbqueue.h"
-#include "../afs/nfsclient.h"
-#include "../afs/afs_osidnlc.h"
+#include "afs/sysincludes.h" /* Standard vendor system headers */
+#include "afsincludes.h" /* Afs-based standard headers */
+#include "afs/afs_stats.h" /* statistics */
+#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 nihints; /* # of above actually in-use */
afs_int32 usedihint;
/* Imported variables */
extern afs_rwlock_t afs_xdcache;
extern unsigned char *afs_indexFlags;
-extern afs_hyper_t *afs_indexTimes; /* Dcache entry Access times */
-extern afs_hyper_t afs_indexCounter; /* Fake time for marking index */
+extern afs_hyper_t *afs_indexTimes; /* Dcache entry Access times */
+extern afs_hyper_t afs_indexCounter; /* Fake time for marking index */
/* Forward declarations */
void afs_PrefetchChunk(struct vcache *avc, struct dcache *adc,
- struct AFS_UCRED *acred, struct vrequest *areq);
-
-afs_MemRead(avc, auio, acred, albn, abpp, noLock)
- register struct vcache *avc;
- struct uio *auio;
- struct AFS_UCRED *acred;
- daddr_t albn;
- int noLock;
- struct buf **abpp;
+ struct AFS_UCRED *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_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, trybusy=1;
+ struct dcache *tdc = 0;
+ afs_int32 error, trybusy = 1;
struct uio tuio;
struct iovec *tvec;
- char *tfile;
afs_int32 code;
struct vrequest treq;
return EIO;
/* check that we have the latest status info in the vnode cache */
- if (code = afs_InitReq(&treq, acred)) return code;
+ if ((code = afs_InitReq(&treq, acred)))
+ return code;
if (!noLock) {
code = afs_VerifyVCache(avc, &treq);
if (code) {
- code = afs_CheckCode(code, &treq, 8); /* failed to get it */
- return code;
+ code = afs_CheckCode(code, &treq, 8); /* 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)) {
+ if (!afs_AccessOK
+ (avc, PRSFS_READ, &treq,
+ CHECK_MODE_BITS | CMB_ALLOW_EXEC_AS_READ)) {
return afs_CheckCode(EACCES, &treq, 9);
}
}
#endif
- tvec = (struct iovec *) osi_AllocSmallSpace(sizeof(struct iovec));
+ 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));
+ 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)
*/
while (totalLength > 0) {
/* read all of the cached info */
- if (filePos >= avc->m.Length) break; /* all done */
+ if (filePos >= avc->m.Length)
+ break; /* all done */
if (noLock) {
if (tdc) {
ReleaseReadLock(&tdc->lock);
}
} 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).
+ * 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);
&& !hsame(avc->m.DataVersion, tdc->f.versionNo)) {
/* have cache entry, it is not coming in now,
* and we'll need new data */
-tagain:
+ tagain:
if (trybusy && !afs_BBusy()) {
struct brequest *bp;
/* daemon is not busy */
UpgradeSToWLock(&tdc->mflock, 666);
tdc->mflags |= DFFetchReq;
bp = afs_BQueue(BOP_FETCH, avc, B_DONTWAIT, 0, acred,
- (afs_size_t)filePos, (afs_size_t) 0,
+ (afs_size_t) filePos, (afs_size_t) 0,
tdc);
if (!bp) {
tdc->mflags &= ~DFFetchReq;
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);
* data is now streaming in, then wait for some interesting stuff.
*/
code = 0;
- while (!code && (tdc->dflags & DFFetching) &&
- tdc->validPos <= filePos) {
+ 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);
+ 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);
error = code;
break;
}
- /* fetching flag gone, data is here, or we never tried (BBusy for instance) */
+ /* 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 */
+ /* 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)) {
+ } 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);
- len = tdc->f.chunkBytes - offset;
- }
- else {
+ } 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 = (struct dcache *) 0;
+ 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)
+ ObtainReadLock(&tdc->lock);
}
}
+ 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 (!tdc) {
error = EIO;
break;
* tdc->lock(R)
*/
- if (len > totalLength) len = totalLength; /* will read len bytes */
- if (len <= 0) { /* shouldn't get here if DFFetching is on */
+ if (len > totalLength)
+ len = totalLength; /* will read len bytes */
+ if (len <= 0) { /* shouldn't get here if DFFetching is on */
/* 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 */
+ * 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);
error = code;
break;
}
- }
- else {
+ } else {
/* get the data from the mem cache */
/* mung uio structure to be right for this transfer */
}
}
/* otherwise we've read some, fixup length, etc and continue with next seg */
- len = len - tuio.afsio_resid; /* compute amount really transferred */
+ len = len - tuio.afsio_resid; /* compute amount really transferred */
trimlen = len;
- afsio_skip(auio, trimlen); /* update input uio structure */
+ afsio_skip(auio, trimlen); /* update input uio structure */
totalLength -= len;
transferLength += len;
filePos += len;
- if (len <= 0) break; /* surprise eof */
- } /* the whole while loop */
+ if (len <= 0)
+ break; /* surprise eof */
+ } /* the whole while loop */
/*
* Locks held:
* This function must be called with the vnode at least read-locked, and
* no locks on the dcache, because it plays around with dcache entries.
*/
-void afs_PrefetchChunk(struct vcache *avc, struct dcache *adc,
- struct AFS_UCRED *acred, struct vrequest *areq)
+void
+afs_PrefetchChunk(struct vcache *avc, struct dcache *adc,
+ struct AFS_UCRED *acred, struct vrequest *areq)
{
register struct dcache *tdc;
afs_size_t offset;
- afs_size_t j1, j2; /* junk vbls for GetDCache to trash */
+ afs_size_t j1, j2; /* junk vbls for GetDCache to trash */
- offset = adc->f.chunk+1; /* next chunk we'll need */
- offset = AFS_CHUNKTOBASE(offset); /* base of next chunk */
+ offset = adc->f.chunk + 1; /* next chunk we'll need */
+ offset = AFS_CHUNKTOBASE(offset); /* base of next chunk */
ObtainReadLock(&adc->lock);
ObtainSharedLock(&adc->mflock, 662);
- if (offset < avc->m.Length && !(adc->mflags & DFNextStarted) && !afs_BBusy()) {
+ if (offset < avc->m.Length && !(adc->mflags & DFNextStarted)
+ && !afs_BBusy()) {
struct brequest *bp;
UpgradeSToWLock(&adc->mflock, 663);
}
}
-
-/* if the vcache is up-to-date, and the request fits entirely into the chunk
- * that the hint here references, then we just use it quickly, otherwise we
- * have to call the slow read.
- *
- * This could be generalized in several ways to take advantage of partial
- * state even when all the chips don't fall the right way. For instance,
- * if the hint is good and the first part of the read request can be
- * satisfied from the chunk, then just do the read. After the read has
- * completed, check to see if there's more. (Chances are there won't be.)
- * If there is more, then just call afs_UFSReadSlow and let it do the rest.
- *
- * For the time being, I'm ignoring quick.f, but it should be used at
- * some future date.
- * do this in the future avc->quick.f = tfile; but I think it
- * has to be done under a write lock, but don't want to wait on the
- * write lock
- */
- /* everywhere that a dcache can be freed (look for NULLIDX)
- * probably does it under a write lock on xdcache. Need to invalidate
- * stamp there, too.
- * Also need to worry about DFFetching, and IFFree, I think. */
-static struct dcache *savedc = 0;
-
-afs_UFSReadFast(avc, auio, acred, albn, abpp, noLock)
- register struct vcache *avc;
- struct uio *auio;
- struct AFS_UCRED *acred;
- int noLock;
- daddr_t albn;
- struct buf **abpp;
-{
- struct vrequest treq;
- int offDiff;
- struct dcache *tdc;
- struct vnode *vp;
- struct osi_file *tfile;
- afs_int32 code = 0;
-
- if (!noLock)
- ObtainReadLock(&avc->lock);
- ObtainReadLock(&afs_xdcache);
-
- if ((avc->states & CStatd) /* up to date */
- && (tdc = avc->quick.dc) && (tdc->index != NULLIDX)
- && !(afs_indexFlags[tdc->index] & (IFFree | IFDiscarded))) {
-
- int readLocked = 0;
-
- afs_RefDCache(tdc);
- ReleaseReadLock(&afs_xdcache);
- if (tdc->stamp == avc->quick.stamp) {
- readLocked = 1;
- ObtainReadLock(&tdc->lock);
- }
-
- if ((tdc->stamp == avc->quick.stamp) /* hint matches */
- && ((offDiff = (auio->afsio_offset - avc->quick.minLoc)) >= 0)
- && (tdc->f.chunkBytes >= auio->afsio_resid + offDiff)
- && !(tdc->dflags & DFFetching)) { /* fits in chunk */
-
- auio->afsio_offset -= avc->quick.minLoc;
-
- afs_Trace4(afs_iclSetp, CM_TRACE_READFAST, ICL_TYPE_POINTER, avc,
- ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(auio->afsio_offset),
- ICL_TYPE_INT32, auio->afsio_resid,
- ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(avc->m.Length));
-
- tfile = (struct osi_file *)osi_UFSOpen(tdc->f.inode);
-
-#ifdef AFS_AIX_ENV
-#ifdef AFS_AIX41_ENV
- AFS_GUNLOCK();
- code = VNOP_RDWR(tfile->vnode, UIO_READ, FREAD, auio, NULL, NULL, NULL, &afs_osi_cred);
- AFS_GLOCK();
-#else
-#ifdef AFS_AIX32_ENV
- code = VNOP_RDWR(tfile->vnode, UIO_READ, FREAD, auio, NULL, NULL);
-#else
- code = VNOP_RDWR(tfile->vnode, UIO_READ, FREAD, (off_t)&auio->afsio_offset, auio, NULL, NULL, -1);
-#endif
-#endif
-#else
-#ifdef AFS_SUN5_ENV
- AFS_GUNLOCK();
- VOP_RWLOCK(tfile->vnode, 0);
- code = VOP_READ(tfile->vnode, auio, 0, &afs_osi_cred);
- VOP_RWUNLOCK(tfile->vnode, 0);
- AFS_GLOCK();
-#else
-#if defined(AFS_SGI_ENV)
- AFS_GUNLOCK();
- AFS_VOP_RWLOCK(tfile->vnode, VRWLOCK_READ);
- AFS_VOP_READ(tfile->vnode, auio, IO_ISLOCKED, &afs_osi_cred, code);
- AFS_VOP_RWUNLOCK(tfile->vnode, VRWLOCK_READ);
- AFS_GLOCK();
-#else
-#ifdef AFS_OSF_ENV
- auio->uio_rw = UIO_READ;
- AFS_GUNLOCK();
- VOP_READ(tfile->vnode, auio, 0, &afs_osi_cred, code);
- AFS_GLOCK();
-#else /* AFS_OSF_ENV */
-#if defined(AFS_HPUX100_ENV)
- AFS_GUNLOCK();
- code = VOP_RDWR(tfile->vnode, auio, UIO_READ, 0, &afs_osi_cred);
- AFS_GLOCK();
-#else
-#if defined(AFS_LINUX20_ENV)
- AFS_GUNLOCK();
- code = osi_file_uio_rdwr(tfile, auio, UIO_READ);
- AFS_GLOCK();
-#else
-#if defined(AFS_DARWIN_ENV)
- AFS_GUNLOCK();
- VOP_LOCK(tfile->vnode, LK_EXCLUSIVE, current_proc());
- code = VOP_READ(tfile->vnode, auio, 0, &afs_osi_cred);
- VOP_UNLOCK(tfile->vnode, 0, current_proc());
- AFS_GLOCK();
-#else
-#if defined(AFS_FBSD_ENV)
- AFS_GUNLOCK();
- VOP_LOCK(tfile->vnode, LK_EXCLUSIVE, curproc);
- code = VOP_READ(tfile->vnode, auio, 0, &afs_osi_cred);
- VOP_UNLOCK(tfile->vnode, 0, curproc);
- AFS_GLOCK();
-#else
- code = VOP_RDWR(tfile->vnode, auio, UIO_READ, 0, &afs_osi_cred);
-#endif
-#endif
-#endif
-#endif
-#endif
-#endif
-#endif
-#endif
- auio->afsio_offset += avc->quick.minLoc;
- osi_UFSClose(tfile);
- /* Fix up LRU info */
- hset(afs_indexTimes[tdc->index], afs_indexCounter);
- hadd32(afs_indexCounter, 1);
-
- if (!noLock) {
- ReleaseReadLock(&avc->lock);
-#if !defined(AFS_VM_RDWR_ENV)
- if (!(code = afs_InitReq(&treq, acred))) {
- if (!(tdc->mflags & DFNextStarted))
- afs_PrefetchChunk(avc, tdc, acred, &treq);
- }
-#endif
- }
- if (readLocked) ReleaseReadLock(&tdc->lock);
- afs_PutDCache(tdc);
- return (code);
- }
- if (!tdc->f.chunkBytes) { /* debugging f.chunkBytes == 0 problem */
- savedc = tdc;
- }
- if (readLocked) ReleaseReadLock(&tdc->lock);
- afs_PutDCache(tdc);
- } else {
- ReleaseReadLock(&afs_xdcache);
- }
-
- /* come here if fast path doesn't work for some reason or other */
- if (!noLock)
- ReleaseReadLock(&avc->lock);
- return afs_UFSRead(avc, auio, acred, albn, abpp, noLock);
-}
-
-afs_UFSRead(avc, auio, acred, albn, abpp, noLock)
- struct vcache *avc;
- struct uio *auio;
- struct AFS_UCRED *acred;
- daddr_t albn;
- int noLock;
- struct buf **abpp;
+int
+afs_UFSRead(register struct vcache *avc, struct uio *auio,
+ struct AFS_UCRED *acred, daddr_t albn, struct buf **abpp,
+ int noLock)
{
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;
+ struct dcache *tdc = 0;
afs_int32 error;
struct uio tuio;
struct iovec *tvec;
struct osi_file *tfile;
afs_int32 code;
- int trybusy=1;
- struct vnode *vp;
+ int trybusy = 1;
struct vrequest treq;
AFS_STATCNT(afs_UFSRead);
return EIO;
/* check that we have the latest status info in the vnode cache */
- if (code = afs_InitReq(&treq, acred)) return code;
+ 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;
+ 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)) {
+ 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));
+ 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));
+ 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)
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 (filePos >= avc->m.Length)
+ break; /* all done */
if (noLock) {
if (tdc) {
ReleaseReadLock(&tdc->lock);
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
- 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).
+ * 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);
}
tdc = afs_GetDCache(avc, filePos, &treq, &offset, &len, 2);
ObtainReadLock(&tdc->lock);
- if (tdc == savedc) {
- savedc = 0;
- }
/* 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:
+ tagain:
if (trybusy && !afs_BBusy()) {
struct brequest *bp;
/* daemon is not busy */
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);
* data is now streaming in, then wait for some interesting stuff.
*/
code = 0;
- while (!code && (tdc->dflags & DFFetching) &&
- tdc->validPos <= filePos) {
+ 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);
+ 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);
* compute length and offset */
offset = filePos - AFS_CHUNKTOBASE(tdc->f.chunk);
len = tdc->validPos - filePos;
- }
- else {
+ } else {
/* no longer fetching, verify data version (avoid new
* GetDCache call) */
- if (hsame(avc->m.DataVersion, tdc->f.versionNo)) {
+ if (hsame(avc->m.DataVersion, tdc->f.versionNo)
+ && ((len = tdc->validPos - filePos) > 0)) {
offset = filePos - AFS_CHUNKTOBASE(tdc->f.chunk);
- len = tdc->f.chunkBytes - offset;
- }
- else {
+ } 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 = (struct dcache *) 0;
+ 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)
+ ObtainReadLock(&tdc->lock);
}
}
-
- 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 (!tdc) {
error = EIO;
break;
}
- if (len > totalLength) len = totalLength; /* will read len bytes */
- if (len <= 0) { /* shouldn't get here if DFFetching is on */
+ 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 */
+ * 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);
error = code;
break;
}
- }
- else {
+ } 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);
+ 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
+ }
+ }
+ if (tfile != 0) {
+ usedihint++;
+ } else
#endif /* IHINT */
- tfile = (struct osi_file *)osi_UFSOpen(tdc->f.inode);
+ 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;
-#ifdef AFS_AIX_ENV
-#ifdef AFS_AIX41_ENV
- AFS_GUNLOCK();
- code = VNOP_RDWR(tfile->vnode, UIO_READ, FREAD, &tuio, NULL, NULL,
- NULL, &afs_osi_cred);
- AFS_GLOCK();
-#else
-#ifdef 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 defined(AFS_AIX41_ENV)
+ AFS_GUNLOCK();
+ code =
+ VNOP_RDWR(tfile->vnode, UIO_READ, FREAD, &tuio, 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:
(len + PAGESIZE-1)/PAGESIZE);
}
*/
+#elif defined(AFS_AIX_ENV)
+ code =
+ VNOP_RDWR(tfile->vnode, UIO_READ, FREAD, (off_t) & offset,
+ &tuio, NULL, NULL, -1);
+#elif defined(AFS_SUN5_ENV)
+ AFS_GUNLOCK();
+#ifdef AFS_SUN510_ENV
+ {
+ caller_context_t ct;
+
+ VOP_RWLOCK(tfile->vnode, 0, &ct);
+ code = VOP_READ(tfile->vnode, &tuio, 0, afs_osi_credp, &ct);
+ VOP_RWUNLOCK(tfile->vnode, 0, &ct);
+ }
#else
- code = VNOP_RDWR(tfile->vnode, UIO_READ, FREAD, (off_t)&offset, &tuio, NULL, NULL, -1);
-#endif
-#endif
-#else
-#ifdef AFS_SUN5_ENV
- AFS_GUNLOCK();
VOP_RWLOCK(tfile->vnode, 0);
- code = VOP_READ(tfile->vnode, &tuio, 0, &afs_osi_cred);
+ code = VOP_READ(tfile->vnode, &tuio, 0, afs_osi_credp);
VOP_RWUNLOCK(tfile->vnode, 0);
- AFS_GLOCK();
-#else
-#if defined(AFS_SGI_ENV)
+#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,
+ AFS_VOP_READ(tfile->vnode, &tuio, IO_ISLOCKED, afs_osi_credp,
code);
AFS_VOP_RWUNLOCK(tfile->vnode, VRWLOCK_READ);
AFS_GLOCK();
-#else
-#ifdef AFS_OSF_ENV
+#elif defined(AFS_OSF_ENV)
tuio.uio_rw = UIO_READ;
AFS_GUNLOCK();
- VOP_READ(tfile->vnode, &tuio, 0, &afs_osi_cred, code);
+ VOP_READ(tfile->vnode, &tuio, 0, afs_osi_credp, code);
AFS_GLOCK();
-#else /* AFS_OSF_ENV */
-#ifdef AFS_SUN_ENV
- code = VOP_RDWR(tfile->vnode, &tuio, UIO_READ, 0, &afs_osi_cred);
-#else
-#if defined(AFS_HPUX100_ENV)
+#elif defined(AFS_SUN_ENV)
+ code = VOP_RDWR(tfile->vnode, &tuio, UIO_READ, 0, afs_osi_credp);
+#elif defined(AFS_HPUX100_ENV)
AFS_GUNLOCK();
- code = VOP_RDWR(tfile->vnode, &tuio, UIO_READ, 0, &afs_osi_cred);
+ code = VOP_RDWR(tfile->vnode, &tuio, UIO_READ, 0, afs_osi_credp);
AFS_GLOCK();
-#else
-#if defined(AFS_LINUX20_ENV)
+#elif defined(AFS_LINUX20_ENV)
AFS_GUNLOCK();
code = osi_file_uio_rdwr(tfile, &tuio, UIO_READ);
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_credp);
+ 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_credp);
+ VOP_UNLOCK(tfile->vnode, 0, curthread);
+ 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_credp);
+ VOP_UNLOCK(tfile->vnode, 0, curproc);
+ AFS_GLOCK();
#else
-#if 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();
-#else
-#if defined(AFS_FBSD_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();
-#else
- code = VOP_RDWR(tfile->vnode, &tuio, UIO_READ, 0, &afs_osi_cred);
-#endif
-#endif
-#endif
-#endif
-#endif
-#endif
-#endif
-#endif
+ code = VOP_RDWR(tfile->vnode, &tuio, UIO_READ, 0, afs_osi_credp);
#endif
#ifdef IHINT
- if (!tdc->ihint && nihints < maxIHint) {
- tdc->ihint = tfile;
- nihints++;
- }
- else
+ if (!tdc->ihint && nihints < maxIHint) {
+ tdc->ihint = tfile;
+ nihints++;
+ } else
#endif /* IHINT */
- osi_UFSClose(tfile);
+ osi_UFSClose(tfile);
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 - tuio.afsio_resid; /* compute amount really transferred */
trimlen = len;
- afsio_skip(auio, trimlen); /* update input uio structure */
+ afsio_skip(auio, trimlen); /* update input uio structure */
totalLength -= len;
transferLength += len;
filePos += len;
- if (len <= 0) break; /* surprise eof */
+ if (len <= 0)
+ break; /* surprise eof */
}
/* if we make it here with tdc non-zero, then it is the last chunk we