Don't move journal_stop from under page lock.

Fixes: ext4-convert-to-new-aops.patch
Signed-off-by: Nick Piggin <[EMAIL PROTECTED]>

Index: linux-2.6/fs/ext4/inode.c
===================================================================
--- linux-2.6.orig/fs/ext4/inode.c
+++ linux-2.6/fs/ext4/inode.c
@@ -36,6 +36,7 @@
 #include <linux/mpage.h>
 #include <linux/uio.h>
 #include <linux/bio.h>
+#include <linux/swap.h> /* mark_page_accessed */
 #include "xattr.h"
 #include "acl.h"
 
@@ -1215,6 +1216,31 @@ static int write_end_fn(handle_t *handle
 }
 
 /*
+ * Generic write_end handler for ordered and writeback ext4 journal modes.
+ * We can't use generic_write_end, because that unlocks the page and we need to
+ * unlock the page after ext4_journal_stop, but ext4_journal_stop must run
+ * after block_write_end.
+ */
+static int ext4_generic_write_end(struct file *file,
+                               struct address_space *mapping,
+                               loff_t pos, unsigned len, unsigned copied,
+                               struct page *page, void *fsdata)
+{
+       struct inode *inode = file->f_mapping->host;
+
+       copied = block_write_end(file, mapping, pos, len, copied, page, fsdata);
+
+       mark_page_accessed(page);
+
+       if (pos+copied > inode->i_size) {
+               i_size_write(inode, pos+copied);
+               mark_inode_dirty(inode);
+       }
+
+       return copied;
+}
+
+/*
  * We need to pick up the new inode size which generic_commit_write gave us
  * `file' can be NULL - eg, when called from page_symlink().
  *
@@ -1248,17 +1274,17 @@ static int ext4_ordered_write_end(struct
                new_i_size = pos + copied;
                if (new_i_size > EXT4_I(inode)->i_disksize)
                        EXT4_I(inode)->i_disksize = new_i_size;
-               copied = generic_write_end(file, mapping, pos, len, copied,
+               copied = ext4_generic_write_end(file, mapping, pos, len, copied,
                                                        page, fsdata);
                if (copied < 0)
                        ret = copied;
-       } else {
-               unlock_page(page);
-               page_cache_release(page);
        }
        ret2 = ext4_journal_stop(handle);
        if (!ret)
                ret = ret2;
+       unlock_page(page);
+       page_cache_release(page);
+
        return ret ? ret : copied;
 }
 
@@ -1276,7 +1302,7 @@ static int ext4_writeback_write_end(stru
        if (new_i_size > EXT4_I(inode)->i_disksize)
                EXT4_I(inode)->i_disksize = new_i_size;
 
-       copied = generic_write_end(file, mapping, pos, len, copied,
+       copied = ext4_generic_write_end(file, mapping, pos, len, copied,
                                                        page, fsdata);
        if (copied < 0)
                ret = copied;
@@ -1284,6 +1310,9 @@ static int ext4_writeback_write_end(stru
        ret2 = ext4_journal_stop(handle);
        if (!ret)
                ret = ret2;
+       unlock_page(page);
+       page_cache_release(page);
+
        return ret ? ret : copied;
 }
 
@@ -1311,8 +1340,6 @@ static int ext4_journalled_write_end(str
                                to, &partial, write_end_fn);
        if (!partial)
                SetPageUptodate(page);
-       unlock_page(page);
-       page_cache_release(page);
        if (pos+copied > inode->i_size)
                i_size_write(inode, pos+copied);
        EXT4_I(inode)->i_state |= EXT4_STATE_JDATA;
@@ -1326,6 +1353,9 @@ static int ext4_journalled_write_end(str
        ret2 = ext4_journal_stop(handle);
        if (!ret)
                ret = ret2;
+       unlock_page(page);
+       page_cache_release(page);
+
        return ret ? ret : copied;
 }
 
-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to