From 9ad6b7bc2e00ba02f915cffd5b6bcd6564bb2c75 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Fri, 18 Apr 2008 16:11:30 -0400 Subject: [PATCH] Force page->private removal in btrfs_invalidatepage 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 --- fs/btrfs/disk-io.c | 12 ++++++++++++ fs/btrfs/inode.c | 6 ++++++ 2 files changed, 18 insertions(+) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 9d648f2f41a5..b479cdfe3ee8 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -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); diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 40f8da884090..347cd85db128 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -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); + } } /*