[PATCH] io-accounting: write-cancel accounting
[pandora-kernel.git] / fs / buffer.c
index 517860f..d1f1b54 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/hash.h>
 #include <linux/suspend.h>
 #include <linux/buffer_head.h>
+#include <linux/task_io_accounting_ops.h>
 #include <linux/bio.h>
 #include <linux/notifier.h>
 #include <linux/cpu.h>
@@ -724,20 +725,21 @@ int __set_page_dirty_buffers(struct page *page)
        }
        spin_unlock(&mapping->private_lock);
 
-       if (!TestSetPageDirty(page)) {
-               write_lock_irq(&mapping->tree_lock);
-               if (page->mapping) {    /* Race with truncate? */
-                       if (mapping_cap_account_dirty(mapping))
-                               __inc_zone_page_state(page, NR_FILE_DIRTY);
-                       radix_tree_tag_set(&mapping->page_tree,
-                                               page_index(page),
-                                               PAGECACHE_TAG_DIRTY);
+       if (TestSetPageDirty(page))
+               return 0;
+
+       write_lock_irq(&mapping->tree_lock);
+       if (page->mapping) {    /* Race with truncate? */
+               if (mapping_cap_account_dirty(mapping)) {
+                       __inc_zone_page_state(page, NR_FILE_DIRTY);
+                       task_io_account_write(PAGE_CACHE_SIZE);
                }
-               write_unlock_irq(&mapping->tree_lock);
-               __mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
-               return 1;
+               radix_tree_tag_set(&mapping->page_tree,
+                               page_index(page), PAGECACHE_TAG_DIRTY);
        }
-       return 0;
+       write_unlock_irq(&mapping->tree_lock);
+       __mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
+       return 1;
 }
 EXPORT_SYMBOL(__set_page_dirty_buffers);
 
@@ -2851,8 +2853,13 @@ int try_to_free_buffers(struct page *page)
                 * could encounter a non-uptodate page, which is unresolvable.
                 * This only applies in the rare case where try_to_free_buffers
                 * succeeds but the page is not freed.
+                *
+                * Also, during truncate, discard_buffer will have marked all
+                * the page's buffers clean.  We discover that here and clean
+                * the page also.
                 */
-               clear_page_dirty(page);
+               if (test_clear_page_dirty(page))
+                       task_io_account_cancelled_write(PAGE_CACHE_SIZE);
        }
 out:
        if (buffers_to_free) {