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/include/linux/page-flags.h | 8 ++++++- 25-akpm/mm/filemap.c | 3 -- 25-akpm/mm/page-writeback.c | 41 +++++++++++++++++++++++++++++++++++++ 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 14 files changed, 54 insertions(+), 8 deletions(-) diff -puN fs/buffer.c~tag-writeback-pages fs/buffer.c --- 25/fs/buffer.c~tag-writeback-pages 2004-03-14 03:00:49.116118568 -0800 +++ 25-akpm/fs/buffer.c 2004-03-14 03:00:49.149113552 -0800 @@ -1833,7 +1833,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); /* @@ -1896,7 +1896,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-03-14 03:00:49.117118416 -0800 +++ 25-akpm/fs/mpage.c 2004-03-14 03:00:49.150113400 -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-03-14 03:00:49.119118112 -0800 +++ 25-akpm/mm/filemap.c 2004-03-14 03:00:49.151113248 -0800 @@ -365,8 +365,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-03-14 03:00:49.120117960 -0800 +++ 25-akpm/mm/page_io.c 2004-03-14 03:00:49.152113096 -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-03-14 03:00:49.135115680 -0800 +++ 25-akpm/mm/swap.c 2004-03-14 03:00:49.152113096 -0800 @@ -67,7 +67,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-03-14 03:00:49.144114312 -0800 +++ 25-akpm/include/linux/page-flags.h 2004-03-14 03:00:49.153112944 -0800 @@ -315,12 +315,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-03-14 03:00:49.146114008 -0800 +++ 25-akpm/mm/page-writeback.c 2004-03-14 03:00:49.154112792 -0800 @@ -650,3 +650,44 @@ 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; + +} _