xfs
[Top] [All Lists]

[PATCH] Re-dirty pages on I/O error

To: xfs-dev <xfs-dev@xxxxxxx>, xfs-oss <xfs@xxxxxxxxxxx>
Subject: [PATCH] Re-dirty pages on I/O error
From: Lachlan McIlroy <lachlan@xxxxxxx>
Date: Thu, 11 Sep 2008 18:37:33 +1000
Reply-to: lachlan@xxxxxxx
User-agent: Thunderbird 2.0.0.16 (X11/20080707)
If we get an error in xfs_page_state_convert() - and it's not EAGAIN - then
we throw away the dirty page without converting the delayed allocation.  This
leaves delayed allocations that can never be removed and confuses code that
expects a flush of the file to clear them.  We need to re-dirty the page on
error so we can try again later or report that the flush failed.

--- a/fs/xfs/linux-2.6/xfs_aops.c       2008-09-11 16:32:11.000000000 +1000
+++ b/fs/xfs/linux-2.6/xfs_aops.c       2008-09-11 15:44:09.000000000 +1000
@@ -1147,16 +1147,6 @@ error:
        if (iohead)
                xfs_cancel_ioend(iohead);

-       /*
-        * If it's delalloc and we have nowhere to put it,
-        * throw it away, unless the lower layers told
-        * us to try again.
-        */
-       if (err != -EAGAIN) {
-               if (!unmapped)
-                       block_invalidatepage(page, 0);
-               ClearPageUptodate(page);
-       }
        return err;
}

@@ -1216,8 +1206,11 @@ xfs_vm_writepage(
         * then mark the page dirty again and leave the page
         * as is.
         */
-       if (current_test_flags(PF_FSTRANS) && need_trans)
-               goto out_fail;
+       if (current_test_flags(PF_FSTRANS) && need_trans) {
+               redirty_page_for_writepage(wbc, page);
+               unlock_page(page);
+               return -EAGAIN;
+       }

        /*
         * Delay hooking up buffer heads until we have
@@ -1231,20 +1224,14 @@ xfs_vm_writepage(
         * to real space and flush out to disk.
         */
        error = xfs_page_state_convert(inode, page, wbc, 1, unmapped);
-       if (error == -EAGAIN)
-               goto out_fail;
-       if (unlikely(error < 0))
-               goto out_unlock;

-       return 0;
+       if (error < 0) {
+               redirty_page_for_writepage(wbc, page);
+               unlock_page(page);
+               return error;
+       }

-out_fail:
-       redirty_page_for_writepage(wbc, page);
-       unlock_page(page);
        return 0;
-out_unlock:
-       unlock_page(page);
-       return error;
}

STATIC int

<Prev in Thread] Current Thread [Next in Thread>