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>
Mon, 8 Nov 2010 01:21:00 +0000 (17:21 -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.

Change-Id: Ic9e496c8c64d5e94f2cf9976d160ef5873f27249
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>

src/afs/afs_bypasscache.c

index 2e92b41..a6e1c18 100644 (file)
@@ -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,