Merge branch 'for-3.10' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq
[platform/adaptation/renesas_rcar/renesas_kernel.git] / mm / page_io.c
index 78eee32..bb5d752 100644 (file)
@@ -42,7 +42,7 @@ static struct bio *get_swap_bio(gfp_t gfp_flags,
        return bio;
 }
 
-static void end_swap_bio_write(struct bio *bio, int err)
+void end_swap_bio_write(struct bio *bio, int err)
 {
        const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
        struct page *page = bio->bi_io_vec[0].bv_page;
@@ -185,9 +185,7 @@ bad_bmap:
  */
 int swap_writepage(struct page *page, struct writeback_control *wbc)
 {
-       struct bio *bio;
-       int ret = 0, rw = WRITE;
-       struct swap_info_struct *sis = page_swap_info(page);
+       int ret = 0;
 
        if (try_to_free_swap(page)) {
                unlock_page(page);
@@ -199,6 +197,17 @@ int swap_writepage(struct page *page, struct writeback_control *wbc)
                end_page_writeback(page);
                goto out;
        }
+       ret = __swap_writepage(page, wbc, end_swap_bio_write);
+out:
+       return ret;
+}
+
+int __swap_writepage(struct page *page, struct writeback_control *wbc,
+       void (*end_write_func)(struct bio *, int))
+{
+       struct bio *bio;
+       int ret = 0, rw = WRITE;
+       struct swap_info_struct *sis = page_swap_info(page);
 
        if (sis->flags & SWP_FILE) {
                struct kiocb kiocb;
@@ -214,6 +223,7 @@ int swap_writepage(struct page *page, struct writeback_control *wbc)
                kiocb.ki_left = PAGE_SIZE;
                kiocb.ki_nbytes = PAGE_SIZE;
 
+               set_page_writeback(page);
                unlock_page(page);
                ret = mapping->a_ops->direct_IO(KERNEL_WRITE,
                                                &kiocb, &iov,
@@ -222,11 +232,27 @@ int swap_writepage(struct page *page, struct writeback_control *wbc)
                if (ret == PAGE_SIZE) {
                        count_vm_event(PSWPOUT);
                        ret = 0;
+               } else {
+                       /*
+                        * In the case of swap-over-nfs, this can be a
+                        * temporary failure if the system has limited
+                        * memory for allocating transmit buffers.
+                        * Mark the page dirty and avoid
+                        * rotate_reclaimable_page but rate-limit the
+                        * messages but do not flag PageError like
+                        * the normal direct-to-bio case as it could
+                        * be temporary.
+                        */
+                       set_page_dirty(page);
+                       ClearPageReclaim(page);
+                       pr_err_ratelimited("Write error on dio swapfile (%Lu)\n",
+                               page_file_offset(page));
                }
+               end_page_writeback(page);
                return ret;
        }
 
-       bio = get_swap_bio(GFP_NOIO, page, end_swap_bio_write);
+       bio = get_swap_bio(GFP_NOIO, page, end_write_func);
        if (bio == NULL) {
                set_page_dirty(page);
                unlock_page(page);