* to be unlocked.
*/
#if defined(AFS_LINUX24_ENV)
-#define unlock_pages(auio) \
+#define unlock_and_release_pages(auio) \
do { \
struct iovec *ciov; \
struct page *pp; \
while(1) { \
if(pp != NULL && PageLocked(pp)) \
UnlockPage(pp); \
+ put_page(pp); /* decrement refcount */ \
iovno++; \
if(iovno > iovmax) \
break; \
} while(0)
#else
#ifdef UKERNEL
-#define unlock_pages(auio) \
+#define unlock_and_release_pages(auio) \
do { } while(0)
#else
#error AFS_CACHE_BYPASS not implemented on this platform
afs_NoCacheFetchProc(register struct rx_call *acall,
register struct vcache *avc,
register uio_t *auio,
- afs_int32 release_pages)
+ afs_int32 release_pages,
+ afs_int32 size)
{
afs_int32 length;
afs_int32 code;
result = 0;
afs_warn("Preread error. code: %d instead of %d\n",
code, sizeof(afs_int32));
- unlock_pages(auio);
+ unlock_and_release_pages(auio);
goto done;
} else
length = ntohl(length);
+
+ if (length > size) {
+ result = EIO;
+ afs_warn("Preread error. Got length %d, which is greater than size %d\n",
+ length, size);
+ unlock_and_release_pages(auio);
+ goto done;
+ }
/*
* The fetch protocol is extended for the AFS/DFS translator
if (code < 0) {
afs_warn("afs_NoCacheFetchProc: rx_Read error. Return code was %d\n", code);
result = 0;
- unlock_pages(auio);
+ unlock_and_release_pages(auio);
goto done;
} else if (code == 0) {
result = 0;
afs_warn("afs_NoCacheFetchProc: rx_Read returned zero. Aborting.\n");
- unlock_pages(auio);
+ unlock_and_release_pages(auio);
goto done;
}
length -= code;
/* this is appropriate when no caller intends to unlock
* and release the page */
#ifdef AFS_LINUX24_ENV
- SetPageUptodate(pp);
- if(PageLocked(pp))
- UnlockPage(pp);
- else
- afs_warn("afs_NoCacheFetchProc: page not locked at iovno %d!\n", iovno);
+ SetPageUptodate(pp);
+ if(PageLocked(pp))
+ UnlockPage(pp);
+ else
+ afs_warn("afs_NoCacheFetchProc: page not locked at iovno %d!\n", iovno);
+ put_page(pp); /* decrement refcount */
#ifndef AFS_KMAP_ATOMIC
- kunmap(pp);
+ kunmap(pp);
#endif
#else
#ifndef UKERNEL
AFS_GLOCK();
while(bcnt < 20) {
breq = afs_BQueue(BOP_FETCH_NOCACHE, avc, B_DONTWAIT, 0, acred, 1, 1,
- bparms);
+ bparms, (void *)0, (void *)0);
if(breq != 0) {
code = 0;
break;
* processed, like unlocking the pages and freeing memory.
*/
#ifdef AFS_LINUX24_ENV
- unlock_pages(bparms->auio);
+ unlock_and_release_pages(bparms->auio);
#else
#ifndef UKERNEL
#error AFS_CACHE_BYPASS not implemented on this platform
uio_t *auio;
struct iovec *iovecp;
struct vrequest *areq;
- afs_int32 code, length_hi, bytes, locked;
+ afs_int32 code = 0;
+#ifdef AFS_64BIT_CLIENT
+ afs_int32 length_hi, bytes, locked;
+#endif
register struct afs_conn *tc;
afs_int32 i;
tcall = NULL;
}
}
- if (code == RXGEN_OPCODE || afs_serverHasNo64Bit(tc)) {
- if (auio->uio_offset > 0x7FFFFFFF) {
- code = EFBIG;
- } else {
- afs_int32 pos;
- pos = auio->uio_offset;
- COND_GUNLOCK(locked);
- if (!tcall)
- tcall = rx_NewCall(tc->id);
- code = StartRXAFS_FetchData(tcall,
- (struct AFSFid *) &avc->f.fid.Fid,
- pos, bparms->length);
- COND_RE_GLOCK(locked);
- }
- afs_serverSetNo64Bit(tc);
- }
} /* afs_serverHasNo64Bit */
+ if (code == RXGEN_OPCODE || afs_serverHasNo64Bit(tc)) {
+ if (auio->uio_offset > 0x7FFFFFFF) {
+ code = EFBIG;
+ } else {
+ afs_int32 pos;
+ pos = auio->uio_offset;
+ COND_GUNLOCK(locked);
+ if (!tcall)
+ tcall = rx_NewCall(tc->id);
+ code = StartRXAFS_FetchData(tcall,
+ (struct AFSFid *) &avc->f.fid.Fid,
+ pos, bparms->length);
+ COND_RE_GLOCK(locked);
+ }
+ afs_serverSetNo64Bit(tc);
+ }
#else
code = StartRXAFS_FetchData(tcall,
(struct AFSFid *) &avc->f.fid.Fid,
#endif
if (code == 0) {
code = afs_NoCacheFetchProc(tcall, avc, auio,
- 1 /* release_pages */);
+ 1 /* release_pages */,
+ bparms->length);
} else {
afs_warn("BYPASS: StartRXAFS_FetchData failed: %d\n", code);
- unlock_pages(auio);
+ unlock_and_release_pages(auio);
goto done;
}
if (code == 0) {
afs_warn("BYPASS: No connection.\n");
code = -1;
#ifdef AFS_LINUX24_ENV
- unlock_pages(auio);
+ unlock_and_release_pages(auio);
#else
#ifndef UKERNEL
#error AFS_CACHE_BYPASS not implemented on this platform