]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - mm/page-writeback.c
Linux 4.13-rc6
[karo-tx-linux.git] / mm / page-writeback.c
index 0b60cc7ddac2b1a63ce71ed17c02a64cb6370e1c..bf050ab025b76a268cd09a37173eac4f86febcb8 100644 (file)
@@ -601,7 +601,7 @@ static inline void __wb_writeout_inc(struct bdi_writeback *wb)
 {
        struct wb_domain *cgdom;
 
-       __inc_wb_stat(wb, WB_WRITTEN);
+       inc_wb_stat(wb, WB_WRITTEN);
        wb_domain_writeout_inc(&global_wb_domain, &wb->completions,
                               wb->bdi->max_prop_frac);
 
@@ -2435,8 +2435,8 @@ void account_page_dirtied(struct page *page, struct address_space *mapping)
                __inc_lruvec_page_state(page, NR_FILE_DIRTY);
                __inc_zone_page_state(page, NR_ZONE_WRITE_PENDING);
                __inc_node_page_state(page, NR_DIRTIED);
-               __inc_wb_stat(wb, WB_RECLAIMABLE);
-               __inc_wb_stat(wb, WB_DIRTIED);
+               inc_wb_stat(wb, WB_RECLAIMABLE);
+               inc_wb_stat(wb, WB_DIRTIED);
                task_io_account_write(PAGE_SIZE);
                current->nr_dirtied++;
                this_cpu_inc(bdp_ratelimits);
@@ -2724,9 +2724,12 @@ EXPORT_SYMBOL(clear_page_dirty_for_io);
 int test_clear_page_writeback(struct page *page)
 {
        struct address_space *mapping = page_mapping(page);
+       struct mem_cgroup *memcg;
+       struct lruvec *lruvec;
        int ret;
 
-       lock_page_memcg(page);
+       memcg = lock_page_memcg(page);
+       lruvec = mem_cgroup_page_lruvec(page, page_pgdat(page));
        if (mapping && mapping_use_writeback_tags(mapping)) {
                struct inode *inode = mapping->host;
                struct backing_dev_info *bdi = inode_to_bdi(inode);
@@ -2741,7 +2744,7 @@ int test_clear_page_writeback(struct page *page)
                        if (bdi_cap_account_writeback(bdi)) {
                                struct bdi_writeback *wb = inode_to_wb(inode);
 
-                               __dec_wb_stat(wb, WB_WRITEBACK);
+                               dec_wb_stat(wb, WB_WRITEBACK);
                                __wb_writeout_inc(wb);
                        }
                }
@@ -2754,12 +2757,18 @@ int test_clear_page_writeback(struct page *page)
        } else {
                ret = TestClearPageWriteback(page);
        }
+       /*
+        * NOTE: Page might be free now! Writeback doesn't hold a page
+        * reference on its own, it relies on truncation to wait for
+        * the clearing of PG_writeback. The below can only access
+        * page state that is static across allocation cycles.
+        */
        if (ret) {
-               dec_lruvec_page_state(page, NR_WRITEBACK);
+               dec_lruvec_state(lruvec, NR_WRITEBACK);
                dec_zone_page_state(page, NR_ZONE_WRITE_PENDING);
                inc_node_page_state(page, NR_WRITTEN);
        }
-       unlock_page_memcg(page);
+       __unlock_page_memcg(memcg);
        return ret;
 }
 
@@ -2786,7 +2795,7 @@ int __test_set_page_writeback(struct page *page, bool keep_write)
                                                page_index(page),
                                                PAGECACHE_TAG_WRITEBACK);
                        if (bdi_cap_account_writeback(bdi))
-                               __inc_wb_stat(inode_to_wb(inode), WB_WRITEBACK);
+                               inc_wb_stat(inode_to_wb(inode), WB_WRITEBACK);
 
                        /*
                         * We can come through here when swapping anonymous