]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
Cache bypass: release and unlock pages when we get 0-length reply
authorMarc Dionne <marc.c.dionne@gmail.com>
Sun, 7 Nov 2010 20:06:16 +0000 (15:06 -0500)
committerDerrick Brashear <shadow@dementia.org>
Wed, 12 Jan 2011 14:15:23 +0000 (06:15 -0800)
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>
src/afs/afs_bypasscache.c

index ed12e0ed03e26a3c52a3099783cb6bcbf60e0964..a636915f85262e591a1ded1fb233dd0a11a585a9 100644 (file)
@@ -284,18 +284,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
@@ -350,6 +350,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,