Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
block_io.c
Go to the documentation of this file.
1 /*
2  * This file provides functions for block I/O operations on swap/file.
3  *
4  * Copyright (C) 1998,2001-2005 Pavel Machek <[email protected]>
5  * Copyright (C) 2006 Rafael J. Wysocki <[email protected]>
6  *
7  * This file is released under the GPLv2.
8  */
9 
10 #include <linux/bio.h>
11 #include <linux/kernel.h>
12 #include <linux/pagemap.h>
13 #include <linux/swap.h>
14 
15 #include "power.h"
16 
28 static int submit(int rw, struct block_device *bdev, sector_t sector,
29  struct page *page, struct bio **bio_chain)
30 {
31  const int bio_rw = rw | REQ_SYNC;
32  struct bio *bio;
33 
34  bio = bio_alloc(__GFP_WAIT | __GFP_HIGH, 1);
35  bio->bi_sector = sector;
36  bio->bi_bdev = bdev;
37  bio->bi_end_io = end_swap_bio_read;
38 
39  if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) {
40  printk(KERN_ERR "PM: Adding page to bio failed at %llu\n",
41  (unsigned long long)sector);
42  bio_put(bio);
43  return -EFAULT;
44  }
45 
46  lock_page(page);
47  bio_get(bio);
48 
49  if (bio_chain == NULL) {
50  submit_bio(bio_rw, bio);
51  wait_on_page_locked(page);
52  if (rw == READ)
54  bio_put(bio);
55  } else {
56  if (rw == READ)
57  get_page(page); /* These pages are freed later */
58  bio->bi_private = *bio_chain;
59  *bio_chain = bio;
60  submit_bio(bio_rw, bio);
61  }
62  return 0;
63 }
64 
65 int hib_bio_read_page(pgoff_t page_off, void *addr, struct bio **bio_chain)
66 {
67  return submit(READ, hib_resume_bdev, page_off * (PAGE_SIZE >> 9),
68  virt_to_page(addr), bio_chain);
69 }
70 
71 int hib_bio_write_page(pgoff_t page_off, void *addr, struct bio **bio_chain)
72 {
73  return submit(WRITE, hib_resume_bdev, page_off * (PAGE_SIZE >> 9),
74  virt_to_page(addr), bio_chain);
75 }
76 
77 int hib_wait_on_bio_chain(struct bio **bio_chain)
78 {
79  struct bio *bio;
80  struct bio *next_bio;
81  int ret = 0;
82 
83  if (bio_chain == NULL)
84  return 0;
85 
86  bio = *bio_chain;
87  if (bio == NULL)
88  return 0;
89  while (bio) {
90  struct page *page;
91 
92  next_bio = bio->bi_private;
93  page = bio->bi_io_vec[0].bv_page;
94  wait_on_page_locked(page);
95  if (!PageUptodate(page) || PageError(page))
96  ret = -EIO;
97  put_page(page);
98  bio_put(bio);
99  bio = next_bio;
100  }
101  *bio_chain = NULL;
102  return ret;
103 }