]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - mm/page-writeback.c
UBUNTU: Ubuntu-4.13.0-45.50
[mirror_ubuntu-artful-kernel.git] / mm / page-writeback.c
index 96e93b214d317baf4fb4ffbb5fcbe726e110980d..bf050ab025b76a268cd09a37173eac4f86febcb8 100644 (file)
@@ -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);
@@ -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;
 }