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.
Reviewed-on: http://gerrit.openafs.org/3283
Reviewed-by: Matt Benjamin <matt@linuxbox.com>
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Tested-by: Derrick Brashear <shadow@dementia.org>
(cherry picked from commit
e4250dc64eb26b5da1480e9f5bd58d016f81847f)
Change-Id: I54dc4ef040b816596cf48edf866976943220d988
Reviewed-on: http://gerrit.openafs.org/3644
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Derrick Brashear <shadow@dementia.org>
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
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,