Arrange for under-writeback pages to be marked thus in their pagecache radix tree. --- 25-akpm/fs/buffer.c | 4 +-- 25-akpm/fs/mpage.c | 2 - 25-akpm/fs/nfs/write.c | 2 - 25-akpm/fs/ntfs/aops.c | 4 +-- 25-akpm/fs/reiserfs/inode.c | 4 +-- 25-akpm/fs/xfs/linux/xfs_aops.c | 2 - 25-akpm/include/linux/page-flags.h | 8 ++++++- 25-akpm/mm/filemap.c | 3 -- 25-akpm/mm/page-writeback.c | 42 +++++++++++++++++++++++++++++++++++++ 25-akpm/mm/page_io.c | 2 - 25-akpm/mm/swap.c | 2 - include/linux/fs.h | 0 include/linux/mm.h | 0 mm/shmem.c | 0 mm/swap_state.c | 0 mm/swapfile.c | 0 mm/truncate.c | 0 mm/vmscan.c | 0 18 files changed, 61 insertions(+), 14 deletions(-) diff -puN fs/buffer.c~tag-writeback-pages fs/buffer.c --- 25/fs/buffer.c~tag-writeback-pages 2004-04-03 03:00:11.754444608 -0800 +++ 25-akpm/fs/buffer.c 2004-04-03 03:00:11.781440504 -0800 @@ -1829,7 +1829,7 @@ static int __block_write_full_page(struc } while ((bh = bh->b_this_page) != head); BUG_ON(PageWriteback(page)); - SetPageWriteback(page); /* Keeps try_to_free_buffers() away */ + set_page_writeback(page); /* Keeps try_to_free_buffers() away */ unlock_page(page); /* @@ -1892,7 +1892,7 @@ recover: } while ((bh = bh->b_this_page) != head); SetPageError(page); BUG_ON(PageWriteback(page)); - SetPageWriteback(page); + set_page_writeback(page); unlock_page(page); do { struct buffer_head *next = bh->b_this_page; diff -puN fs/mpage.c~tag-writeback-pages fs/mpage.c --- 25/fs/mpage.c~tag-writeback-pages 2004-04-03 03:00:11.755444456 -0800 +++ 25-akpm/fs/mpage.c 2004-04-03 03:00:11.782440352 -0800 @@ -546,7 +546,7 @@ alloc_new: } BUG_ON(PageWriteback(page)); - SetPageWriteback(page); + set_page_writeback(page); unlock_page(page); if (boundary || (first_unmapped != blocks_per_page)) { bio = mpage_bio_submit(WRITE, bio); diff -puN mm/filemap.c~tag-writeback-pages mm/filemap.c --- 25/mm/filemap.c~tag-writeback-pages 2004-04-03 03:00:11.756444304 -0800 +++ 25-akpm/mm/filemap.c 2004-04-03 03:00:11.783440200 -0800 @@ -363,8 +363,7 @@ void end_page_writeback(struct page *pag wait_queue_head_t *waitqueue = page_waitqueue(page); if (!TestClearPageReclaim(page) || rotate_reclaimable_page(page)) { - smp_mb__before_clear_bit(); - if (!TestClearPageWriteback(page)) + if (!test_clear_page_writeback(page)) BUG(); smp_mb__after_clear_bit(); } diff -puN mm/page_io.c~tag-writeback-pages mm/page_io.c --- 25/mm/page_io.c~tag-writeback-pages 2004-04-03 03:00:11.757444152 -0800 +++ 25-akpm/mm/page_io.c 2004-04-03 03:00:11.784440048 -0800 @@ -104,7 +104,7 @@ int swap_writepage(struct page *page, st goto out; } inc_page_state(pswpout); - SetPageWriteback(page); + set_page_writeback(page); unlock_page(page); submit_bio(WRITE, bio); out: diff -puN mm/shmem.c~tag-writeback-pages mm/shmem.c diff -puN mm/swap.c~tag-writeback-pages mm/swap.c --- 25/mm/swap.c~tag-writeback-pages 2004-04-03 03:00:11.760443696 -0800 +++ 25-akpm/mm/swap.c 2004-04-03 03:00:11.784440048 -0800 @@ -70,7 +70,7 @@ int rotate_reclaimable_page(struct page list_add_tail(&page->lru, &zone->inactive_list); inc_page_state(pgrotated); } - if (!TestClearPageWriteback(page)) + if (!test_clear_page_writeback(page)) BUG(); spin_unlock_irqrestore(&zone->lru_lock, flags); return 0; diff -puN mm/swapfile.c~tag-writeback-pages mm/swapfile.c diff -puN mm/swap_state.c~tag-writeback-pages mm/swap_state.c diff -puN mm/truncate.c~tag-writeback-pages mm/truncate.c diff -puN mm/vmscan.c~tag-writeback-pages mm/vmscan.c diff -puN include/linux/fs.h~tag-writeback-pages include/linux/fs.h diff -puN include/linux/mm.h~tag-writeback-pages include/linux/mm.h diff -puN include/linux/page-flags.h~tag-writeback-pages include/linux/page-flags.h --- 25/include/linux/page-flags.h~tag-writeback-pages 2004-04-03 03:00:11.769442328 -0800 +++ 25-akpm/include/linux/page-flags.h 2004-04-03 03:00:11.785439896 -0800 @@ -312,12 +312,18 @@ extern struct address_space swapper_spac struct page; /* forward declaration */ int test_clear_page_dirty(struct page *page); +int __clear_page_dirty(struct page *page); +int test_clear_page_writeback(struct page *page); +int test_set_page_writeback(struct page *page); static inline void clear_page_dirty(struct page *page) { test_clear_page_dirty(page); } -int __clear_page_dirty(struct page *page); +static inline void set_page_writeback(struct page *page) +{ + test_set_page_writeback(page); +} #endif /* PAGE_FLAGS_H */ diff -puN mm/page-writeback.c~tag-writeback-pages mm/page-writeback.c --- 25/mm/page-writeback.c~tag-writeback-pages 2004-04-03 03:00:11.771442024 -0800 +++ 25-akpm/mm/page-writeback.c 2004-04-03 03:00:11.786439744 -0800 @@ -604,3 +604,45 @@ int __clear_page_dirty(struct page *page } return TestClearPageDirty(page); } + +int test_clear_page_writeback(struct page *page) +{ + struct address_space *mapping = page->mapping; + int ret; + + if (mapping) { + unsigned long flags; + + spin_lock_irqsave(&mapping->tree_lock, flags); + ret = TestClearPageWriteback(page); + if (ret) + radix_tree_tag_clear(&mapping->page_tree, page->index, + PAGECACHE_TAG_WRITEBACK); + spin_unlock_irqrestore(&mapping->tree_lock, flags); + } else { + ret = TestClearPageWriteback(page); + } + return ret; +} + +int test_set_page_writeback(struct page *page) +{ + struct address_space *mapping = page->mapping; + int ret; + + if (mapping) { + unsigned long flags; + + spin_lock_irqsave(&mapping->tree_lock, flags); + ret = TestSetPageWriteback(page); + if (!ret) + radix_tree_tag_set(&mapping->page_tree, page->index, + PAGECACHE_TAG_WRITEBACK); + spin_unlock_irqrestore(&mapping->tree_lock, flags); + } else { + ret = TestSetPageWriteback(page); + } + return ret; + +} +EXPORT_SYMBOL(test_set_page_writeback); diff -puN fs/nfs/write.c~tag-writeback-pages fs/nfs/write.c --- 25/fs/nfs/write.c~tag-writeback-pages 2004-04-03 03:00:11.772441872 -0800 +++ 25-akpm/fs/nfs/write.c 2004-04-03 03:00:11.787439592 -0800 @@ -768,7 +768,7 @@ nfs_write_rpcsetup(struct list_head *hea req = nfs_list_entry(head->next); nfs_list_remove_request(req); nfs_list_add_request(req, &data->pages); - SetPageWriteback(req->wb_page); + set_page_writeback(req->wb_page); *pages++ = req->wb_page; count += req->wb_bytes; } diff -puN fs/ntfs/aops.c~tag-writeback-pages fs/ntfs/aops.c --- 25/fs/ntfs/aops.c~tag-writeback-pages 2004-04-03 03:00:11.773441720 -0800 +++ 25-akpm/fs/ntfs/aops.c 2004-04-03 03:00:11.788439440 -0800 @@ -743,7 +743,7 @@ lock_retry_remap: } BUG_ON(PageWriteback(page)); - SetPageWriteback(page); /* Keeps try_to_free_buffers() away. */ + set_page_writeback(page); /* Keeps try_to_free_buffers() away. */ unlock_page(page); /* @@ -885,7 +885,7 @@ static int ntfs_writepage(struct page *p // FIXME: Make sure it is ok to SetPageError() on unlocked page under // writeback before doing the change! #if 0 - SetPageWriteback(page); + set_page_writeback(page); unlock_page(page); #endif diff -puN fs/reiserfs/inode.c~tag-writeback-pages fs/reiserfs/inode.c --- 25/fs/reiserfs/inode.c~tag-writeback-pages 2004-04-03 03:00:11.775441416 -0800 +++ 25-akpm/fs/reiserfs/inode.c 2004-04-03 03:00:11.790439136 -0800 @@ -2134,7 +2134,7 @@ static int reiserfs_write_full_page(stru } while(bh != head) ; BUG_ON(PageWriteback(page)); - SetPageWriteback(page); + set_page_writeback(page); unlock_page(page); /* @@ -2198,7 +2198,7 @@ fail: } while(bh != head); SetPageError(page); BUG_ON(PageWriteback(page)); - SetPageWriteback(page); + set_page_writeback(page); unlock_page(page); do { struct buffer_head *next = bh->b_this_page; diff -puN fs/xfs/linux/xfs_aops.c~tag-writeback-pages fs/xfs/linux/xfs_aops.c --- 25/fs/xfs/linux/xfs_aops.c~tag-writeback-pages 2004-04-03 03:00:11.776441264 -0800 +++ 25-akpm/fs/xfs/linux/xfs_aops.c 2004-04-03 03:00:11.791438984 -0800 @@ -566,7 +566,7 @@ xfs_submit_page( int i; BUG_ON(PageWriteback(page)); - SetPageWriteback(page); + set_page_writeback(page); clear_page_dirty(page); unlock_page(page); _