Force page->private removal in btrfs_invalidatepage
authorChris Mason <chris.mason@oracle.com>
Fri, 18 Apr 2008 20:11:30 +0000 (16:11 -0400)
committerChris Mason <chris.mason@oracle.com>
Thu, 25 Sep 2008 15:04:02 +0000 (11:04 -0400)
btrfs_invalidatepage is not allowed to leave pages around on the lru.
Any such pages will trigger an oops later on because the VM will see
page->private and assume it is a buffer head.

This also forces extra flushes of the async work queues before
dropping all the pages on the btree inode during unmount.  Left over
items on the work queues are one possible cause of busy state ranges
during truncate_inode_pages.

Signed-off-by: Chris Mason <chris.mason@oracle.com>
fs/btrfs/disk-io.c
fs/btrfs/inode.c

index 9d648f2f41a5a95445c0cc549f9865d11d3fd0c8..b479cdfe3ee89746d05c7b59871330ce9ccc81eb 100644 (file)
@@ -533,6 +533,12 @@ static void btree_invalidatepage(struct page *page, unsigned long offset)
        tree = &BTRFS_I(page->mapping->host)->io_tree;
        extent_invalidatepage(tree, page, offset);
        btree_releasepage(page, GFP_NOFS);
+       if (PagePrivate(page)) {
+               printk("2invalidate page cleaning up after releasepage\n");
+               ClearPagePrivate(page);
+               set_page_private(page, 0);
+               page_cache_release(page);
+       }
 }
 
 #if 0
@@ -1484,6 +1490,8 @@ int close_ctree(struct btrfs_root *root)
        write_ctree_super(NULL, root);
        mutex_unlock(&fs_info->fs_mutex);
 
+       btrfs_transaction_flush_work(root);
+
        if (fs_info->delalloc_bytes) {
                printk("btrfs: at unmount delalloc count %Lu\n",
                       fs_info->delalloc_bytes);
@@ -1514,7 +1522,11 @@ int close_ctree(struct btrfs_root *root)
        extent_io_tree_empty_lru(&fs_info->extent_ins);
        extent_io_tree_empty_lru(&BTRFS_I(fs_info->btree_inode)->io_tree);
 
+       flush_workqueue(end_io_workqueue);
+       flush_workqueue(async_submit_workqueue);
+
        truncate_inode_pages(fs_info->btree_inode->i_mapping, 0);
+
        flush_workqueue(end_io_workqueue);
        destroy_workqueue(end_io_workqueue);
 
index 40f8da884090b65c4c3af6358cdda9d029013c20..347cd85db128bd0a79d811c0bb318cfd7c8d536c 100644 (file)
@@ -2524,6 +2524,12 @@ static void btrfs_invalidatepage(struct page *page, unsigned long offset)
        tree = &BTRFS_I(page->mapping->host)->io_tree;
        extent_invalidatepage(tree, page, offset);
        btrfs_releasepage(page, GFP_NOFS);
+       if (PagePrivate(page)) {
+               printk("invalidate page cleaning up after releasepage\n");
+               ClearPagePrivate(page);
+               set_page_private(page, 0);
+               page_cache_release(page);
+       }
 }
 
 /*