From e4250dc64eb26b5da1480e9f5bd58d016f81847f Mon Sep 17 00:00:00 2001 From: Marc Dionne Date: Sun, 7 Nov 2010 15:06:16 -0500 Subject: [PATCH] Cache bypass: release and unlock pages when we get 0-length reply In some cases, such as reading past the end of file as known to the server, fetchdata will get a 0 length reply. Deal gracefully by unlocking and releasing any pages reserved by readpages. Failure to do so here leads to deadlocks later as we can exit with some pages still locked. Change-Id: Ic9e496c8c64d5e94f2cf9976d160ef5873f27249 Reviewed-on: http://gerrit.openafs.org/3283 Reviewed-by: Matt Benjamin Reviewed-by: Derrick Brashear Tested-by: Derrick Brashear --- src/afs/afs_bypasscache.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/afs/afs_bypasscache.c b/src/afs/afs_bypasscache.c index 2e92b413d1..a6e1c18b51 100644 --- a/src/afs/afs_bypasscache.c +++ b/src/afs/afs_bypasscache.c @@ -285,18 +285,18 @@ done: ciov = auio->uio_iov; \ iovmax = auio->uio_iovcnt - 1; \ pp = (struct page*) ciov->iov_base; \ - afs_warn("BYPASS: Unlocking pages..."); \ while(1) { \ - if(pp != NULL && PageLocked(pp)) \ - UnlockPage(pp); \ - put_page(pp); /* decrement refcount */ \ + if (pp) { \ + if (PageLocked(pp)) \ + UnlockPage(pp); \ + put_page(pp); /* decrement refcount */ \ + } \ iovno++; \ if(iovno > iovmax) \ break; \ ciov = (auio->uio_iov + iovno); \ pp = (struct page*) ciov->iov_base; \ } \ - afs_warn("Pages Unlocked.\n"); \ } while(0) #else #ifdef UKERNEL @@ -355,6 +355,13 @@ afs_NoCacheFetchProc(struct rx_call *acall, goto done; } + /* If we get a 0 length reply, time to cleanup and return */ + if (length == 0) { + unlock_and_release_pages(auio); + result = 0; + goto done; + } + /* * The fetch protocol is extended for the AFS/DFS translator * to allow multiple blocks of data, each with its own length,