Commit 8ece6262 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] tag dirty pages as such in the radix tree

Arrange for all dirty pagecache pages to be tagged as dirty within their
radix tree.
parent 89261aab
...@@ -873,6 +873,8 @@ int __set_page_dirty_buffers(struct page *page) ...@@ -873,6 +873,8 @@ int __set_page_dirty_buffers(struct page *page)
inc_page_state(nr_dirty); inc_page_state(nr_dirty);
list_del(&page->list); list_del(&page->list);
list_add(&page->list, &mapping->dirty_pages); list_add(&page->list, &mapping->dirty_pages);
radix_tree_tag_set(&mapping->page_tree, page->index,
PAGECACHE_TAG_DIRTY);
} }
spin_unlock_irq(&mapping->tree_lock); spin_unlock_irq(&mapping->tree_lock);
__mark_inode_dirty(mapping->host, I_DIRTY_PAGES); __mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
......
...@@ -364,6 +364,13 @@ struct block_device { ...@@ -364,6 +364,13 @@ struct block_device {
unsigned long bd_private; unsigned long bd_private;
}; };
/*
* Radix-tre tags, for tagging dirty and writeback pages within the pagecache
* radix trees
*/
#define PAGECACHE_TAG_DIRTY 0
#define PAGECACHE_TAG_WRITEBACK 1
/* /*
* Use sequence counter to get consistent i_size on 32-bit processors. * Use sequence counter to get consistent i_size on 32-bit processors.
*/ */
......
...@@ -318,4 +318,6 @@ static inline void clear_page_dirty(struct page *page) ...@@ -318,4 +318,6 @@ static inline void clear_page_dirty(struct page *page)
test_clear_page_dirty(page); test_clear_page_dirty(page);
} }
int __clear_page_dirty(struct page *page);
#endif /* PAGE_FLAGS_H */ #endif /* PAGE_FLAGS_H */
...@@ -522,6 +522,8 @@ int __set_page_dirty_nobuffers(struct page *page) ...@@ -522,6 +522,8 @@ int __set_page_dirty_nobuffers(struct page *page)
inc_page_state(nr_dirty); inc_page_state(nr_dirty);
list_del(&page->list); list_del(&page->list);
list_add(&page->list, &mapping->dirty_pages); list_add(&page->list, &mapping->dirty_pages);
radix_tree_tag_set(&mapping->page_tree,
page->index, PAGECACHE_TAG_DIRTY);
} }
spin_unlock_irq(&mapping->tree_lock); spin_unlock_irq(&mapping->tree_lock);
if (!PageSwapCache(page)) if (!PageSwapCache(page))
...@@ -560,13 +562,45 @@ EXPORT_SYMBOL(set_page_dirty_lock); ...@@ -560,13 +562,45 @@ EXPORT_SYMBOL(set_page_dirty_lock);
*/ */
int test_clear_page_dirty(struct page *page) int test_clear_page_dirty(struct page *page)
{ {
if (TestClearPageDirty(page)) { struct address_space *mapping = page->mapping;
struct address_space *mapping = page->mapping; unsigned long flags;
if (mapping && !mapping->backing_dev_info->memory_backed) if (mapping) {
dec_page_state(nr_dirty); spin_lock_irqsave(&mapping->tree_lock, flags);
return 1; if (TestClearPageDirty(page)) {
radix_tree_tag_clear(&mapping->page_tree, page->index,
PAGECACHE_TAG_DIRTY);
spin_unlock_irqrestore(&mapping->tree_lock, flags);
if (!mapping->backing_dev_info->memory_backed)
dec_page_state(nr_dirty);
return 1;
}
spin_unlock_irqrestore(&mapping->tree_lock, flags);
return 0;
} }
return 0; return TestClearPageDirty(page);
} }
EXPORT_SYMBOL(test_clear_page_dirty); EXPORT_SYMBOL(test_clear_page_dirty);
/*
* Clear a page's dirty flag while ignoring dirty memory accounting
*/
int __clear_page_dirty(struct page *page)
{
struct address_space *mapping = page->mapping;
if (mapping) {
unsigned long flags;
spin_lock_irqsave(&mapping->tree_lock, flags);
if (TestClearPageDirty(page)) {
radix_tree_tag_clear(&mapping->page_tree, page->index,
PAGECACHE_TAG_DIRTY);
spin_unlock_irqrestore(&mapping->tree_lock, flags);
return 1;
}
spin_unlock_irqrestore(&mapping->tree_lock, flags);
return 0;
}
return TestClearPageDirty(page);
}
...@@ -149,7 +149,7 @@ int add_to_swap(struct page * page) ...@@ -149,7 +149,7 @@ int add_to_swap(struct page * page)
switch (err) { switch (err) {
case 0: /* Success */ case 0: /* Success */
SetPageUptodate(page); SetPageUptodate(page);
ClearPageDirty(page); __clear_page_dirty(page);
set_page_dirty(page); set_page_dirty(page);
INC_CACHE_INFO(add_total); INC_CACHE_INFO(add_total);
return 1; return 1;
...@@ -246,7 +246,7 @@ int move_from_swap_cache(struct page *page, unsigned long index, ...@@ -246,7 +246,7 @@ int move_from_swap_cache(struct page *page, unsigned long index,
if (!err) { if (!err) {
swap_free(entry); swap_free(entry);
/* shift page from clean_pages to dirty_pages list */ /* shift page from clean_pages to dirty_pages list */
ClearPageDirty(page); __clear_page_dirty(page);
set_page_dirty(page); set_page_dirty(page);
} }
return err; return err;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment