]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - mm/page_io.c
Merge tag 'upstream-4.13-rc1' of git://git.infradead.org/linux-ubifs
[karo-tx-linux.git] / mm / page_io.c
index 2da71e627812ea5cee576be0bca85cce32974708..b6c4ac388209c945d744f2541326411314a1cceb 100644 (file)
@@ -117,6 +117,7 @@ static void swap_slot_free_notify(struct page *page)
 static void end_swap_bio_read(struct bio *bio)
 {
        struct page *page = bio->bi_io_vec[0].bv_page;
+       struct task_struct *waiter = bio->bi_private;
 
        if (bio->bi_status) {
                SetPageError(page);
@@ -132,7 +133,9 @@ static void end_swap_bio_read(struct bio *bio)
        swap_slot_free_notify(page);
 out:
        unlock_page(page);
+       WRITE_ONCE(bio->bi_private, NULL);
        bio_put(bio);
+       wake_up_process(waiter);
 }
 
 int generic_swapfile_activate(struct swap_info_struct *sis,
@@ -329,11 +332,13 @@ out:
        return ret;
 }
 
-int swap_readpage(struct page *page)
+int swap_readpage(struct page *page, bool do_poll)
 {
        struct bio *bio;
        int ret = 0;
        struct swap_info_struct *sis = page_swap_info(page);
+       blk_qc_t qc;
+       struct block_device *bdev;
 
        VM_BUG_ON_PAGE(!PageSwapCache(page), page);
        VM_BUG_ON_PAGE(!PageLocked(page), page);
@@ -372,9 +377,23 @@ int swap_readpage(struct page *page)
                ret = -ENOMEM;
                goto out;
        }
+       bdev = bio->bi_bdev;
+       bio->bi_private = current;
        bio_set_op_attrs(bio, REQ_OP_READ, 0);
        count_vm_event(PSWPIN);
-       submit_bio(bio);
+       bio_get(bio);
+       qc = submit_bio(bio);
+       while (do_poll) {
+               set_current_state(TASK_UNINTERRUPTIBLE);
+               if (!READ_ONCE(bio->bi_private))
+                       break;
+
+               if (!blk_mq_poll(bdev_get_queue(bdev), qc))
+                       break;
+       }
+       __set_current_state(TASK_RUNNING);
+       bio_put(bio);
+
 out:
        return ret;
 }