Use set_page_writeback and end_page_writeback
[openafs.git] / src / afs / LINUX / osi_vnodeops.c
index 3d65d89..1c5cd0a 100644 (file)
@@ -1073,7 +1073,7 @@ afs_linux_lookup(struct inode *dip, struct dentry *dp)
                dput(alias);
            } else {
                iput(ip);
-               unlock_kernel();
+               afs_maybe_unlock_kernel();
                crfree(credp);
                return alias;
            }
@@ -2127,17 +2127,23 @@ afs_linux_writepage(struct page *pp)
     isize = i_size_read(inode);
 
     /* Don't defeat an earlier truncate */
-    if (page_offset(pp) > isize)
+    if (page_offset(pp) > isize) {
+       set_page_writeback(pp);
+       unlock_page(pp);
        goto done;
+    }
 
     AFS_GLOCK();
     ObtainWriteLock(&vcp->lock, 537);
     code = afs_linux_prepare_writeback(vcp);
-    if (code) {
+    if (code == AOP_WRITEPAGE_ACTIVATE) {
+       /* WRITEPAGE_ACTIVATE is the only return value that permits us
+        * to return with the page still locked */
        ReleaseWriteLock(&vcp->lock);
        AFS_GUNLOCK();
        return code;
     }
+
     /* Grab the creds structure currently held in the vnode, and
      * get a reference to it, in case it goes away ... */
     credp = vcp->cred;
@@ -2145,6 +2151,16 @@ afs_linux_writepage(struct page *pp)
     ReleaseWriteLock(&vcp->lock);
     AFS_GUNLOCK();
 
+    set_page_writeback(pp);
+
+    SetPageUptodate(pp);
+
+    /* We can unlock the page here, because it's protected by the
+     * page_writeback flag. This should make us less vulnerable to
+     * deadlocking in afs_write and afs_DoPartialWrite
+     */
+    unlock_page(pp);
+
     /* If this is the final page, then just write the number of bytes that
      * are actually in it */
     if ((isize - page_offset(pp)) < to )
@@ -2171,12 +2187,7 @@ afs_linux_writepage(struct page *pp)
     afs_maybe_unlock_kernel();
 
 done:
-    SetPageUptodate(pp);
-    if ( code != AOP_WRITEPAGE_ACTIVATE ) {
-       /* XXX - do we need to redirty the page here? */
-       unlock_page(pp);
-    }
-
+    end_page_writeback(pp);
     page_cache_release(pp);
 
     if (code1)