2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
18 #include <afsconfig.h>
19 #include "afs/param.h"
22 #include "afs/sysincludes.h" /* Standard vendor system headers */
23 #include "afsincludes.h" /* Afs-based standard headers */
24 #include "afs/afs_stats.h" /* statistics */
25 #include "afs/afs_cbqueue.h"
26 #include "afs/nfsclient.h"
27 #include "afs/afs_osidnlc.h"
28 #include "afs/afs_osi.h"
31 extern char afs_zeros[AFS_ZEROS];
33 /* Imported variables */
34 extern afs_rwlock_t afs_xdcache;
35 extern unsigned char *afs_indexFlags;
36 extern afs_hyper_t *afs_indexTimes; /* Dcache entry Access times */
37 extern afs_hyper_t afs_indexCounter; /* Fake time for marking index */
40 /* Forward declarations */
41 void afs_PrefetchChunk(struct vcache *avc, struct dcache *adc,
42 afs_ucred_t *acred, struct vrequest *areq);
45 afs_MemRead(register struct vcache *avc, struct uio *auio,
46 afs_ucred_t *acred, daddr_t albn, struct buf **abpp,
49 afs_size_t totalLength;
50 afs_size_t transferLength;
52 afs_size_t offset, len, tlen;
54 struct dcache *tdc = 0;
55 afs_int32 error, trybusy = 1;
56 #ifdef AFS_DARWIN80_ENV
60 struct uio *tuiop = &tuio;
66 AFS_STATCNT(afs_MemRead);
70 /* check that we have the latest status info in the vnode cache */
71 if ((code = afs_InitReq(&treq, acred)))
74 code = afs_VerifyVCache(avc, &treq);
76 code = afs_CheckCode(code, &treq, 8); /* failed to get it */
80 #ifndef AFS_VM_RDWR_ENV
81 if (AFS_NFSXLATORREQ(acred)) {
83 (avc, PRSFS_READ, &treq,
84 CHECK_MODE_BITS | CMB_ALLOW_EXEC_AS_READ)) {
85 return afs_CheckCode(EACCES, &treq, 9);
90 #ifndef AFS_DARWIN80_ENV
91 tvec = (struct iovec *)osi_AllocSmallSpace(sizeof(struct iovec));
93 totalLength = AFS_UIO_RESID(auio);
94 filePos = AFS_UIO_OFFSET(auio);
95 afs_Trace4(afs_iclSetp, CM_TRACE_READ, ICL_TYPE_POINTER, avc,
96 ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(filePos), ICL_TYPE_INT32,
97 totalLength, ICL_TYPE_OFFSET,
98 ICL_HANDLE_OFFSET(avc->f.m.Length));
102 ObtainReadLock(&avc->lock);
103 #if defined(AFS_TEXT_ENV) && !defined(AFS_VM_RDWR_ENV)
104 if (avc->flushDV.high == AFS_MAXDV && avc->flushDV.low == AFS_MAXDV) {
105 hset(avc->flushDV, avc->f.m.DataVersion);
113 if (filePos >= avc->f.m.Length) {
115 len = sizeof(afs_zeros); /* and in 0 buffer */
117 #ifdef AFS_DARWIN80_ENV
119 tuiop = afsio_darwin_partialcopy(auio, trimlen);
121 afsio_copy(auio, &tuio, tvec);
123 afsio_trim(&tuio, trimlen);
125 AFS_UIOMOVE(afs_zeros, trimlen, UIO_READ, tuiop, code);
128 while (avc->f.m.Length > 0 && totalLength > 0) {
129 /* read all of the cached info */
130 if (filePos >= avc->f.m.Length)
131 break; /* all done */
134 ReleaseReadLock(&tdc->lock);
137 tdc = afs_FindDCache(avc, filePos);
139 ObtainReadLock(&tdc->lock);
140 offset = filePos - AFS_CHUNKTOBASE(tdc->f.chunk);
141 len = tdc->f.chunkBytes - offset;
144 /* a tricky question: does the presence of the DFFetching flag
145 * mean that we're fetching the latest version of the file? No.
146 * The server could update the file as soon as the fetch responsible
147 * for the setting of the DFFetching flag completes.
149 * However, the presence of the DFFetching flag (visible under
150 * a dcache read lock since it is set and cleared only under a
151 * dcache write lock) means that we're fetching as good a version
152 * as was known to this client at the time of the last call to
153 * afs_VerifyVCache, since the latter updates the stat cache's
154 * m.DataVersion field under a vcache write lock, and from the
155 * time that the DFFetching flag goes on in afs_GetDCache (before
156 * the fetch starts), to the time it goes off (after the fetch
157 * completes), afs_GetDCache keeps at least a read lock on the
160 * This means that if the DFFetching flag is set, we can use that
161 * data for any reads that must come from the current version of
162 * the file (current == m.DataVersion).
164 * Another way of looking at this same point is this: if we're
165 * fetching some data and then try do an afs_VerifyVCache, the
166 * VerifyVCache operation will not complete until after the
167 * DFFetching flag is turned off and the dcache entry's f.versionNo
170 * Note, by the way, that if DFFetching is set,
171 * m.DataVersion > f.versionNo (the latter is not updated until
172 * after the fetch completes).
175 ReleaseReadLock(&tdc->lock);
176 afs_PutDCache(tdc); /* before reusing tdc */
178 tdc = afs_GetDCache(avc, filePos, &treq, &offset, &len, 2);
179 ObtainReadLock(&tdc->lock);
180 /* now, first try to start transfer, if we'll need the data. If
181 * data already coming, we don't need to do this, obviously. Type
182 * 2 requests never return a null dcache entry, btw.
184 if (!(tdc->dflags & DFFetching)
185 && !hsame(avc->f.m.DataVersion, tdc->f.versionNo)) {
186 /* have cache entry, it is not coming in now,
187 * and we'll need new data */
189 if (trybusy && !afs_BBusy()) {
191 /* daemon is not busy */
192 ObtainSharedLock(&tdc->mflock, 665);
193 if (!(tdc->mflags & DFFetchReq)) {
194 /* start the daemon (may already be running, however) */
195 UpgradeSToWLock(&tdc->mflock, 666);
196 tdc->mflags |= DFFetchReq;
197 bp = afs_BQueue(BOP_FETCH, avc, B_DONTWAIT, 0, acred,
198 (afs_size_t) filePos, (afs_size_t) 0,
199 tdc, (void *)0, (void *)0);
201 tdc->mflags &= ~DFFetchReq;
202 trybusy = 0; /* Avoid bkg daemon since they're too busy */
203 ReleaseWriteLock(&tdc->mflock);
206 ConvertWToSLock(&tdc->mflock);
207 /* don't use bp pointer! */
210 ConvertSToRLock(&tdc->mflock);
211 while (!code && tdc->mflags & DFFetchReq) {
212 afs_Trace4(afs_iclSetp, CM_TRACE_DCACHEWAIT,
213 ICL_TYPE_STRING, __FILE__, ICL_TYPE_INT32,
214 __LINE__, ICL_TYPE_POINTER, tdc,
215 ICL_TYPE_INT32, tdc->dflags);
216 /* don't need waiting flag on this one */
217 ReleaseReadLock(&tdc->mflock);
218 ReleaseReadLock(&tdc->lock);
219 ReleaseReadLock(&avc->lock);
220 code = afs_osi_SleepSig(&tdc->validPos);
221 ObtainReadLock(&avc->lock);
222 ObtainReadLock(&tdc->lock);
223 ObtainReadLock(&tdc->mflock);
225 ReleaseReadLock(&tdc->mflock);
232 /* now data may have started flowing in (if DFFetching is on). If
233 * data is now streaming in, then wait for some interesting stuff.
236 while (!code && (tdc->dflags & DFFetching)
237 && tdc->validPos <= filePos) {
238 /* too early: wait for DFFetching flag to vanish,
239 * or data to appear */
240 afs_Trace4(afs_iclSetp, CM_TRACE_DCACHEWAIT, ICL_TYPE_STRING,
241 __FILE__, ICL_TYPE_INT32, __LINE__,
242 ICL_TYPE_POINTER, tdc, ICL_TYPE_INT32,
244 ReleaseReadLock(&tdc->lock);
245 ReleaseReadLock(&avc->lock);
246 code = afs_osi_SleepSig(&tdc->validPos);
247 ObtainReadLock(&avc->lock);
248 ObtainReadLock(&tdc->lock);
254 /* fetching flag gone, data is here, or we never tried
255 * (BBusy for instance) */
256 if (tdc->dflags & DFFetching) {
257 /* still fetching, some new data is here:
258 * compute length and offset */
259 offset = filePos - AFS_CHUNKTOBASE(tdc->f.chunk);
260 len = tdc->validPos - filePos;
262 /* no longer fetching, verify data version
263 * (avoid new GetDCache call) */
264 if (hsame(avc->f.m.DataVersion, tdc->f.versionNo)
265 && ((len = tdc->validPos - filePos) > 0)) {
266 offset = filePos - AFS_CHUNKTOBASE(tdc->f.chunk);
268 /* don't have current data, so get it below */
269 afs_Trace3(afs_iclSetp, CM_TRACE_VERSIONNO,
270 ICL_TYPE_INT64, ICL_HANDLE_OFFSET(filePos),
271 ICL_TYPE_HYPER, &avc->f.m.DataVersion,
272 ICL_TYPE_HYPER, &tdc->f.versionNo);
273 ReleaseReadLock(&tdc->lock);
280 /* If we get, it was not possible to start the
281 * background daemon. With flag == 1 afs_GetDCache
282 * does the FetchData rpc synchronously.
284 ReleaseReadLock(&avc->lock);
285 tdc = afs_GetDCache(avc, filePos, &treq, &offset, &len, 1);
286 ObtainReadLock(&avc->lock);
288 ObtainReadLock(&tdc->lock);
292 afs_Trace3(afs_iclSetp, CM_TRACE_VNODEREAD, ICL_TYPE_POINTER, tdc,
293 ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(offset),
294 ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(len));
306 if (len > totalLength)
307 len = totalLength; /* will read len bytes */
308 if (len <= 0) { /* shouldn't get here if DFFetching is on */
309 /* read past the end of a chunk, may not be at next chunk yet, and yet
310 * also not at eof, so may have to supply fake zeros */
311 len = AFS_CHUNKTOSIZE(tdc->f.chunk) - offset; /* bytes left in chunk addr space */
312 if (len > totalLength)
313 len = totalLength; /* and still within xfr request */
314 tlen = avc->f.m.Length - offset; /* and still within file */
318 len = sizeof(afs_zeros); /* and in 0 buffer */
319 #ifdef AFS_DARWIN80_ENV
321 tuiop = afsio_darwin_partialcopy(auio, trimlen);
323 afsio_copy(auio, &tuio, tvec);
325 afsio_trim(&tuio, trimlen);
327 AFS_UIOMOVE(afs_zeros, trimlen, UIO_READ, tuiop, code);
333 /* get the data from the mem cache */
335 /* mung uio structure to be right for this transfer */
336 #ifdef AFS_DARWIN80_ENV
338 tuiop = afsio_darwin_partialcopy(auio, trimlen);
339 uio_setoffset(tuiop, offset);
341 afsio_copy(auio, &tuio, tvec);
343 afsio_trim(&tuio, trimlen);
344 tuio.afsio_offset = offset;
347 code = afs_MemReadUIO(&tdc->f.inode, tuiop);
354 /* otherwise we've read some, fixup length, etc and continue with next seg */
355 len = len - AFS_UIO_RESID(tuiop); /* compute amount really transferred */
357 afsio_skip(auio, trimlen); /* update input uio structure */
359 transferLength += len;
363 break; /* surprise eof */
364 #ifdef AFS_DARWIN80_ENV
370 } /* the whole while loop */
375 * tdc->lock(R) if tdc
378 /* if we make it here with tdc non-zero, then it is the last chunk we
379 * dealt with, and we have to release it when we're done. We hold on
380 * to it in case we need to do a prefetch.
383 ReleaseReadLock(&tdc->lock);
384 /* try to queue prefetch, if needed */
386 #ifndef AFS_VM_RDWR_ENV
392 afs_PrefetchChunk(avc, tdc, acred, &treq);
397 ReleaseReadLock(&avc->lock);
398 #ifdef AFS_DARWIN80_ENV
402 osi_FreeSmallSpace(tvec);
404 error = afs_CheckCode(error, &treq, 10);
408 /* called with the dcache entry triggering the fetch, the vcache entry involved,
409 * and a vrequest for the read call. Marks the dcache entry as having already
410 * triggered a prefetch, starts the prefetch going and sets the DFFetchReq
411 * flag in the prefetched block, so that the next call to read knows to wait
412 * for the daemon to start doing things.
414 * This function must be called with the vnode at least read-locked, and
415 * no locks on the dcache, because it plays around with dcache entries.
418 afs_PrefetchChunk(struct vcache *avc, struct dcache *adc,
419 afs_ucred_t *acred, struct vrequest *areq)
421 register struct dcache *tdc;
423 afs_size_t j1, j2; /* junk vbls for GetDCache to trash */
425 offset = adc->f.chunk + 1; /* next chunk we'll need */
426 offset = AFS_CHUNKTOBASE(offset); /* base of next chunk */
427 ObtainReadLock(&adc->lock);
428 ObtainSharedLock(&adc->mflock, 662);
429 if (offset < avc->f.m.Length && !(adc->mflags & DFNextStarted)
433 UpgradeSToWLock(&adc->mflock, 663);
434 adc->mflags |= DFNextStarted; /* we've tried to prefetch for this guy */
435 ReleaseWriteLock(&adc->mflock);
436 ReleaseReadLock(&adc->lock);
438 tdc = afs_GetDCache(avc, offset, areq, &j1, &j2, 2); /* type 2 never returns 0 */
439 #ifdef AFS_DISCON_ENV
441 * In disconnected mode, type 2 can return 0 because it doesn't
442 * make any sense to allocate a dcache we can never fill
446 #endif /* AFS_DISCON_ENV */
448 ObtainSharedLock(&tdc->mflock, 651);
449 if (!(tdc->mflags & DFFetchReq)) {
450 /* ask the daemon to do the work */
451 UpgradeSToWLock(&tdc->mflock, 652);
452 tdc->mflags |= DFFetchReq; /* guaranteed to be cleared by BKG or GetDCache */
453 /* last parm (1) tells bkg daemon to do an afs_PutDCache when it is done,
454 * since we don't want to wait for it to finish before doing so ourselves.
456 bp = afs_BQueue(BOP_FETCH, avc, B_DONTWAIT, 0, acred,
457 (afs_size_t) offset, (afs_size_t) 1, tdc,
458 (void *)0, (void *)0);
460 /* Bkg table full; just abort non-important prefetching to avoid deadlocks */
461 tdc->mflags &= ~DFFetchReq;
462 ReleaseWriteLock(&tdc->mflock);
466 * DCLOCKXXX: This is a little sketchy, since someone else
467 * could have already started a prefetch.. In practice,
468 * this probably doesn't matter; at most it would cause an
469 * extra slot in the BKG table to be used up when someone
470 * prefetches this for the second time.
472 ObtainReadLock(&adc->lock);
473 ObtainWriteLock(&adc->mflock, 664);
474 adc->mflags &= ~DFNextStarted;
475 ReleaseWriteLock(&adc->mflock);
476 ReleaseReadLock(&adc->lock);
478 ReleaseWriteLock(&tdc->mflock);
481 ReleaseSharedLock(&tdc->mflock);
485 ReleaseSharedLock(&adc->mflock);
486 ReleaseReadLock(&adc->lock);
491 afs_UFSRead(register struct vcache *avc, struct uio *auio,
492 afs_ucred_t *acred, daddr_t albn, struct buf **abpp,
495 afs_size_t totalLength;
496 afs_size_t transferLength;
498 afs_size_t offset, len, tlen;
500 struct dcache *tdc = 0;
502 #ifdef AFS_DARWIN80_ENV
506 struct uio *tuiop = &tuio;
509 struct osi_file *tfile;
512 struct vrequest treq;
514 AFS_STATCNT(afs_UFSRead);
515 if (avc && avc->vc_error)
520 /* check that we have the latest status info in the vnode cache */
521 if ((code = afs_InitReq(&treq, acred)))
525 osi_Panic("null avc in afs_UFSRead");
527 code = afs_VerifyVCache(avc, &treq);
529 code = afs_CheckCode(code, &treq, 11); /* failed to get it */
535 #ifndef AFS_VM_RDWR_ENV
536 if (AFS_NFSXLATORREQ(acred)) {
538 (avc, PRSFS_READ, &treq,
539 CHECK_MODE_BITS | CMB_ALLOW_EXEC_AS_READ)) {
541 return afs_CheckCode(EACCES, &treq, 12);
546 #ifndef AFS_DARWIN80_ENV
547 tvec = (struct iovec *)osi_AllocSmallSpace(sizeof(struct iovec));
549 totalLength = AFS_UIO_RESID(auio);
550 filePos = AFS_UIO_OFFSET(auio);
551 afs_Trace4(afs_iclSetp, CM_TRACE_READ, ICL_TYPE_POINTER, avc,
552 ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(filePos), ICL_TYPE_INT32,
553 totalLength, ICL_TYPE_OFFSET,
554 ICL_HANDLE_OFFSET(avc->f.m.Length));
558 ObtainReadLock(&avc->lock);
559 #if defined(AFS_TEXT_ENV) && !defined(AFS_VM_RDWR_ENV)
560 if (avc->flushDV.high == AFS_MAXDV && avc->flushDV.low == AFS_MAXDV) {
561 hset(avc->flushDV, avc->f.m.DataVersion);
565 if (filePos >= avc->f.m.Length) {
567 len = sizeof(afs_zeros); /* and in 0 buffer */
569 #ifdef AFS_DARWIN80_ENV
571 tuiop = afsio_darwin_partialcopy(auio, trimlen);
573 afsio_copy(auio, &tuio, tvec);
575 afsio_trim(&tuio, trimlen);
577 AFS_UIOMOVE(afs_zeros, trimlen, UIO_READ, tuiop, code);
580 while (avc->f.m.Length > 0 && totalLength > 0) {
581 /* read all of the cached info */
582 if (filePos >= avc->f.m.Length)
583 break; /* all done */
586 ReleaseReadLock(&tdc->lock);
589 tdc = afs_FindDCache(avc, filePos);
591 ObtainReadLock(&tdc->lock);
592 offset = filePos - AFS_CHUNKTOBASE(tdc->f.chunk);
593 len = tdc->validPos - filePos;
596 /* a tricky question: does the presence of the DFFetching flag
597 * mean that we're fetching the latest version of the file? No.
598 * The server could update the file as soon as the fetch responsible
599 * for the setting of the DFFetching flag completes.
601 * However, the presence of the DFFetching flag (visible under
602 * a dcache read lock since it is set and cleared only under a
603 * dcache write lock) means that we're fetching as good a version
604 * as was known to this client at the time of the last call to
605 * afs_VerifyVCache, since the latter updates the stat cache's
606 * m.DataVersion field under a vcache write lock, and from the
607 * time that the DFFetching flag goes on in afs_GetDCache (before
608 * the fetch starts), to the time it goes off (after the fetch
609 * completes), afs_GetDCache keeps at least a read lock on the
612 * This means that if the DFFetching flag is set, we can use that
613 * data for any reads that must come from the current version of
614 * the file (current == m.DataVersion).
616 * Another way of looking at this same point is this: if we're
617 * fetching some data and then try do an afs_VerifyVCache, the
618 * VerifyVCache operation will not complete until after the
619 * DFFetching flag is turned off and the dcache entry's f.versionNo
622 * Note, by the way, that if DFFetching is set,
623 * m.DataVersion > f.versionNo (the latter is not updated until
624 * after the fetch completes).
627 ReleaseReadLock(&tdc->lock);
628 afs_PutDCache(tdc); /* before reusing tdc */
630 tdc = afs_GetDCache(avc, filePos, &treq, &offset, &len, 2);
631 #ifdef AFS_DISCON_ENV
633 printf("Network down in afs_read");
637 #endif /* AFS_DISCON_ENV */
639 ObtainReadLock(&tdc->lock);
640 /* now, first try to start transfer, if we'll need the data. If
641 * data already coming, we don't need to do this, obviously. Type
642 * 2 requests never return a null dcache entry, btw. */
643 if (!(tdc->dflags & DFFetching)
644 && !hsame(avc->f.m.DataVersion, tdc->f.versionNo)) {
645 /* have cache entry, it is not coming in now, and we'll need new data */
647 if (trybusy && !afs_BBusy()) {
649 /* daemon is not busy */
650 ObtainSharedLock(&tdc->mflock, 667);
651 if (!(tdc->mflags & DFFetchReq)) {
652 UpgradeSToWLock(&tdc->mflock, 668);
653 tdc->mflags |= DFFetchReq;
654 bp = afs_BQueue(BOP_FETCH, avc, B_DONTWAIT, 0, acred,
655 (afs_size_t) filePos, (afs_size_t) 0,
656 tdc, (void *)0, (void *)0);
658 /* Bkg table full; retry deadlocks */
659 tdc->mflags &= ~DFFetchReq;
660 trybusy = 0; /* Avoid bkg daemon since they're too busy */
661 ReleaseWriteLock(&tdc->mflock);
664 ConvertWToSLock(&tdc->mflock);
667 ConvertSToRLock(&tdc->mflock);
668 while (!code && tdc->mflags & DFFetchReq) {
669 afs_Trace4(afs_iclSetp, CM_TRACE_DCACHEWAIT,
670 ICL_TYPE_STRING, __FILE__, ICL_TYPE_INT32,
671 __LINE__, ICL_TYPE_POINTER, tdc,
672 ICL_TYPE_INT32, tdc->dflags);
673 /* don't need waiting flag on this one */
674 ReleaseReadLock(&tdc->mflock);
675 ReleaseReadLock(&tdc->lock);
676 ReleaseReadLock(&avc->lock);
677 code = afs_osi_SleepSig(&tdc->validPos);
678 ObtainReadLock(&avc->lock);
679 ObtainReadLock(&tdc->lock);
680 ObtainReadLock(&tdc->mflock);
682 ReleaseReadLock(&tdc->mflock);
689 /* now data may have started flowing in (if DFFetching is on). If
690 * data is now streaming in, then wait for some interesting stuff.
693 while (!code && (tdc->dflags & DFFetching)
694 && tdc->validPos <= filePos) {
695 /* too early: wait for DFFetching flag to vanish,
696 * or data to appear */
697 afs_Trace4(afs_iclSetp, CM_TRACE_DCACHEWAIT, ICL_TYPE_STRING,
698 __FILE__, ICL_TYPE_INT32, __LINE__,
699 ICL_TYPE_POINTER, tdc, ICL_TYPE_INT32,
701 ReleaseReadLock(&tdc->lock);
702 ReleaseReadLock(&avc->lock);
703 code = afs_osi_SleepSig(&tdc->validPos);
704 ObtainReadLock(&avc->lock);
705 ObtainReadLock(&tdc->lock);
711 /* fetching flag gone, data is here, or we never tried
712 * (BBusy for instance) */
713 if (tdc->dflags & DFFetching) {
714 /* still fetching, some new data is here:
715 * compute length and offset */
716 offset = filePos - AFS_CHUNKTOBASE(tdc->f.chunk);
717 len = tdc->validPos - filePos;
719 /* no longer fetching, verify data version (avoid new
721 if (hsame(avc->f.m.DataVersion, tdc->f.versionNo)
722 && ((len = tdc->validPos - filePos) > 0)) {
723 offset = filePos - AFS_CHUNKTOBASE(tdc->f.chunk);
725 /* don't have current data, so get it below */
726 afs_Trace3(afs_iclSetp, CM_TRACE_VERSIONNO,
727 ICL_TYPE_INT64, ICL_HANDLE_OFFSET(filePos),
728 ICL_TYPE_HYPER, &avc->f.m.DataVersion,
729 ICL_TYPE_HYPER, &tdc->f.versionNo);
730 ReleaseReadLock(&tdc->lock);
737 /* If we get, it was not possible to start the
738 * background daemon. With flag == 1 afs_GetDCache
739 * does the FetchData rpc synchronously.
741 ReleaseReadLock(&avc->lock);
742 tdc = afs_GetDCache(avc, filePos, &treq, &offset, &len, 1);
743 ObtainReadLock(&avc->lock);
745 ObtainReadLock(&tdc->lock);
753 len = tdc->validPos - filePos;
754 afs_Trace3(afs_iclSetp, CM_TRACE_VNODEREAD, ICL_TYPE_POINTER, tdc,
755 ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(offset),
756 ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(len));
757 if (len > totalLength)
758 len = totalLength; /* will read len bytes */
759 if (len <= 0) { /* shouldn't get here if DFFetching is on */
760 afs_Trace4(afs_iclSetp, CM_TRACE_VNODEREAD2, ICL_TYPE_POINTER,
761 tdc, ICL_TYPE_OFFSET, ICL_HANDLE_OFFSET(tdc->validPos),
762 ICL_TYPE_INT32, tdc->f.chunkBytes, ICL_TYPE_INT32,
764 /* read past the end of a chunk, may not be at next chunk yet, and yet
765 * also not at eof, so may have to supply fake zeros */
766 len = AFS_CHUNKTOSIZE(tdc->f.chunk) - offset; /* bytes left in chunk addr space */
767 if (len > totalLength)
768 len = totalLength; /* and still within xfr request */
769 tlen = avc->f.m.Length - offset; /* and still within file */
773 len = sizeof(afs_zeros); /* and in 0 buffer */
774 #ifdef AFS_DARWIN80_ENV
776 tuiop = afsio_darwin_partialcopy(auio, trimlen);
778 afsio_copy(auio, &tuio, tvec);
780 afsio_trim(&tuio, trimlen);
782 AFS_UIOMOVE(afs_zeros, trimlen, UIO_READ, tuiop, code);
788 /* get the data from the file */
789 tfile = (struct osi_file *)osi_UFSOpen(&tdc->f.inode);
790 #ifdef AFS_DARWIN80_ENV
792 tuiop = afsio_darwin_partialcopy(auio, trimlen);
793 uio_setoffset(tuiop, offset);
795 /* mung uio structure to be right for this transfer */
796 afsio_copy(auio, &tuio, tvec);
798 afsio_trim(&tuio, trimlen);
799 tuio.afsio_offset = offset;
802 #if defined(AFS_AIX41_ENV)
805 VNOP_RDWR(tfile->vnode, UIO_READ, FREAD, &tuio, NULL, NULL,
806 NULL, afs_osi_credp);
808 #elif defined(AFS_AIX32_ENV)
810 VNOP_RDWR(tfile->vnode, UIO_READ, FREAD, &tuio, NULL, NULL);
811 /* Flush all JFS pages now for big performance gain in big file cases
812 * If we do something like this, must check to be sure that AFS file
813 * isn't mmapped... see afs_gn_map() for why.
816 if (tfile->vnode->v_gnode && tfile->vnode->v_gnode->gn_seg) {
817 many different ways to do similar things:
818 so far, the best performing one is #2, but #1 might match it if we
819 straighten out the confusion regarding which pages to flush. It
821 1. vm_flushp(tfile->vnode->v_gnode->gn_seg, 0, len/PAGESIZE - 1);
822 2. vm_releasep(tfile->vnode->v_gnode->gn_seg, offset/PAGESIZE,
823 (len + PAGESIZE-1)/PAGESIZE);
824 3. vms_inactive(tfile->vnode->v_gnode->gn_seg) Doesn't work correctly
825 4. vms_delete(tfile->vnode->v_gnode->gn_seg) probably also fails
826 tfile->vnode->v_gnode->gn_seg = NULL;
830 Unfortunately, this seems to cause frequent "cache corruption" episodes.
831 vm_releasep(tfile->vnode->v_gnode->gn_seg, offset/PAGESIZE,
832 (len + PAGESIZE-1)/PAGESIZE);
835 #elif defined(AFS_AIX_ENV)
837 VNOP_RDWR(tfile->vnode, UIO_READ, FREAD, (off_t) & offset,
838 &tuio, NULL, NULL, -1);
839 #elif defined(AFS_SUN5_ENV)
841 #ifdef AFS_SUN510_ENV
845 VOP_RWLOCK(tfile->vnode, 0, &ct);
846 code = VOP_READ(tfile->vnode, &tuio, 0, afs_osi_credp, &ct);
847 VOP_RWUNLOCK(tfile->vnode, 0, &ct);
850 VOP_RWLOCK(tfile->vnode, 0);
851 code = VOP_READ(tfile->vnode, &tuio, 0, afs_osi_credp);
852 VOP_RWUNLOCK(tfile->vnode, 0);
855 #elif defined(AFS_SGI_ENV)
857 AFS_VOP_RWLOCK(tfile->vnode, VRWLOCK_READ);
858 AFS_VOP_READ(tfile->vnode, &tuio, IO_ISLOCKED, afs_osi_credp,
860 AFS_VOP_RWUNLOCK(tfile->vnode, VRWLOCK_READ);
862 #elif defined(AFS_HPUX100_ENV)
864 code = VOP_RDWR(tfile->vnode, &tuio, UIO_READ, 0, afs_osi_credp);
866 #elif defined(AFS_LINUX20_ENV)
868 code = osi_rdwr(tfile, &tuio, UIO_READ);
870 #elif defined(AFS_DARWIN80_ENV)
872 code = VNOP_READ(tfile->vnode, tuiop, 0, afs_osi_ctxtp);
874 #elif defined(AFS_DARWIN_ENV)
876 VOP_LOCK(tfile->vnode, LK_EXCLUSIVE, current_proc());
877 code = VOP_READ(tfile->vnode, &tuio, 0, afs_osi_credp);
878 VOP_UNLOCK(tfile->vnode, 0, current_proc());
880 #elif defined(AFS_FBSD80_ENV)
882 VOP_LOCK(tfile->vnode, LK_EXCLUSIVE);
883 code = VOP_READ(tfile->vnode, &tuio, 0, afs_osi_credp);
884 VOP_UNLOCK(tfile->vnode, 0);
886 #elif defined(AFS_FBSD50_ENV)
888 VOP_LOCK(tfile->vnode, LK_EXCLUSIVE, curthread);
889 code = VOP_READ(tfile->vnode, &tuio, 0, afs_osi_credp);
890 VOP_UNLOCK(tfile->vnode, 0, curthread);
892 #elif defined(AFS_NBSD_ENV)
894 VOP_LOCK(tfile->vnode, LK_EXCLUSIVE);
895 code = VOP_READ(tfile->vnode, &tuio, 0, afs_osi_credp);
896 VOP_UNLOCK(tfile->vnode, 0);
899 #elif defined(AFS_XBSD_ENV)
901 VOP_LOCK(tfile->vnode, LK_EXCLUSIVE, curproc);
902 code = VOP_READ(tfile->vnode, &tuio, 0, afs_osi_credp);
903 VOP_UNLOCK(tfile->vnode, 0, curproc);
906 code = VOP_RDWR(tfile->vnode, &tuio, UIO_READ, 0, afs_osi_credp);
915 /* otherwise we've read some, fixup length, etc and continue with next seg */
916 len = len - AFS_UIO_RESID(tuiop); /* compute amount really transferred */
918 afsio_skip(auio, trimlen); /* update input uio structure */
920 transferLength += len;
923 break; /* surprise eof */
924 #ifdef AFS_DARWIN80_ENV
932 /* if we make it here with tdc non-zero, then it is the last chunk we
933 * dealt with, and we have to release it when we're done. We hold on
934 * to it in case we need to do a prefetch, obviously.
937 ReleaseReadLock(&tdc->lock);
938 #if !defined(AFS_VM_RDWR_ENV)
939 /* try to queue prefetch, if needed */
941 if (!(tdc->mflags & DFNextStarted))
942 afs_PrefetchChunk(avc, tdc, acred, &treq);
948 ReleaseReadLock(&avc->lock);
950 #ifdef AFS_DARWIN80_ENV
954 osi_FreeSmallSpace(tvec);
957 error = afs_CheckCode(error, &treq, 13);