OSDN Git Service

MIPS: VDSO: Prevent use of smp_processor_id()
[android-x86/kernel.git] / mm / page-writeback.c
index 439cc63..281a46a 100644 (file)
@@ -2148,6 +2148,7 @@ int write_cache_pages(struct address_space *mapping,
 {
        int ret = 0;
        int done = 0;
+       int error;
        struct pagevec pvec;
        int nr_pages;
        pgoff_t uninitialized_var(writeback_index);
@@ -2244,25 +2245,31 @@ continue_unlock:
                                goto continue_unlock;
 
                        trace_wbc_writepage(wbc, inode_to_bdi(mapping->host));
-                       ret = (*writepage)(page, wbc, data);
-                       if (unlikely(ret)) {
-                               if (ret == AOP_WRITEPAGE_ACTIVATE) {
+                       error = (*writepage)(page, wbc, data);
+                       if (unlikely(error)) {
+                               /*
+                                * Handle errors according to the type of
+                                * writeback. There's no need to continue for
+                                * background writeback. Just push done_index
+                                * past this page so media errors won't choke
+                                * writeout for the entire file. For integrity
+                                * writeback, we must process the entire dirty
+                                * set regardless of errors because the fs may
+                                * still have state to clear for each page. In
+                                * that case we continue processing and return
+                                * the first error.
+                                */
+                               if (error == AOP_WRITEPAGE_ACTIVATE) {
                                        unlock_page(page);
-                                       ret = 0;
-                               } else {
-                                       /*
-                                        * done_index is set past this page,
-                                        * so media errors will not choke
-                                        * background writeout for the entire
-                                        * file. This has consequences for
-                                        * range_cyclic semantics (ie. it may
-                                        * not be suitable for data integrity
-                                        * writeout).
-                                        */
+                                       error = 0;
+                               } else if (wbc->sync_mode != WB_SYNC_ALL) {
+                                       ret = error;
                                        done_index = page->index + 1;
                                        done = 1;
                                        break;
                                }
+                               if (!ret)
+                                       ret = error;
                        }
 
                        /*
@@ -2506,13 +2513,13 @@ void account_page_redirty(struct page *page)
        if (mapping && mapping_cap_account_dirty(mapping)) {
                struct inode *inode = mapping->host;
                struct bdi_writeback *wb;
-               bool locked;
+               struct wb_lock_cookie cookie = {};
 
-               wb = unlocked_inode_to_wb_begin(inode, &locked);
+               wb = unlocked_inode_to_wb_begin(inode, &cookie);
                current->nr_dirtied--;
                dec_node_page_state(page, NR_DIRTIED);
                dec_wb_stat(wb, WB_DIRTIED);
-               unlocked_inode_to_wb_end(inode, locked);
+               unlocked_inode_to_wb_end(inode, &cookie);
        }
 }
 EXPORT_SYMBOL(account_page_redirty);
@@ -2618,15 +2625,15 @@ void cancel_dirty_page(struct page *page)
        if (mapping_cap_account_dirty(mapping)) {
                struct inode *inode = mapping->host;
                struct bdi_writeback *wb;
-               bool locked;
+               struct wb_lock_cookie cookie = {};
 
                lock_page_memcg(page);
-               wb = unlocked_inode_to_wb_begin(inode, &locked);
+               wb = unlocked_inode_to_wb_begin(inode, &cookie);
 
                if (TestClearPageDirty(page))
                        account_page_cleaned(page, mapping, wb);
 
-               unlocked_inode_to_wb_end(inode, locked);
+               unlocked_inode_to_wb_end(inode, &cookie);
                unlock_page_memcg(page);
        } else {
                ClearPageDirty(page);
@@ -2658,7 +2665,7 @@ int clear_page_dirty_for_io(struct page *page)
        if (mapping && mapping_cap_account_dirty(mapping)) {
                struct inode *inode = mapping->host;
                struct bdi_writeback *wb;
-               bool locked;
+               struct wb_lock_cookie cookie = {};
 
                /*
                 * Yes, Virginia, this is indeed insane.
@@ -2695,7 +2702,7 @@ int clear_page_dirty_for_io(struct page *page)
                 * always locked coming in here, so we get the desired
                 * exclusion.
                 */
-               wb = unlocked_inode_to_wb_begin(inode, &locked);
+               wb = unlocked_inode_to_wb_begin(inode, &cookie);
                if (TestClearPageDirty(page)) {
                        mem_cgroup_dec_page_stat(page, MEM_CGROUP_STAT_DIRTY);
                        dec_node_page_state(page, NR_FILE_DIRTY);
@@ -2703,7 +2710,7 @@ int clear_page_dirty_for_io(struct page *page)
                        dec_wb_stat(wb, WB_RECLAIMABLE);
                        ret = 1;
                }
-               unlocked_inode_to_wb_end(inode, locked);
+               unlocked_inode_to_wb_end(inode, &cookie);
                return ret;
        }
        return TestClearPageDirty(page);