[PATCH] handle BIO allocation failures in swap_writepage()
[linux-flexiantxendom0-3.2.10.git] / mm / page_io.c
1 /*
2  *  linux/mm/page_io.c
3  *
4  *  Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
5  *
6  *  Swap reorganised 29.12.95, 
7  *  Asynchronous swapping added 30.12.95. Stephen Tweedie
8  *  Removed race in async swapping. 14.4.1996. Bruno Haible
9  *  Add swap of shared pages through the page cache. 20.2.1998. Stephen Tweedie
10  *  Always use brw_page, life becomes simpler. 12 May 1998 Eric Biederman
11  */
12
13 #include <linux/mm.h>
14 #include <linux/kernel_stat.h>
15 #include <linux/pagemap.h>
16 #include <linux/swap.h>
17 #include <linux/bio.h>
18 #include <linux/buffer_head.h>
19 #include <asm/pgtable.h>
20 #include <linux/swapops.h>
21
22 static int
23 swap_get_block(struct inode *inode, sector_t iblock,
24                 struct buffer_head *bh_result, int create)
25 {
26         struct swap_info_struct *sis;
27         swp_entry_t entry;
28
29         entry.val = iblock;
30         sis = get_swap_info_struct(swp_type(entry));
31         bh_result->b_bdev = sis->bdev;
32         bh_result->b_blocknr = map_swap_page(sis, swp_offset(entry));
33         bh_result->b_size = PAGE_SIZE;
34         set_buffer_mapped(bh_result);
35         return 0;
36 }
37
38 static struct bio *
39 get_swap_bio(int gfp_flags, struct page *page, bio_end_io_t end_io)
40 {
41         struct bio *bio;
42         struct buffer_head bh;
43
44         bio = bio_alloc(gfp_flags, 1);
45         if (bio) {
46                 swap_get_block(NULL, page->index, &bh, 1);
47                 bio->bi_sector = bh.b_blocknr * (PAGE_SIZE >> 9);
48                 bio->bi_bdev = bh.b_bdev;
49                 bio->bi_io_vec[0].bv_page = page;
50                 bio->bi_io_vec[0].bv_len = PAGE_SIZE;
51                 bio->bi_io_vec[0].bv_offset = 0;
52                 bio->bi_vcnt = 1;
53                 bio->bi_idx = 0;
54                 bio->bi_size = PAGE_SIZE;
55                 bio->bi_end_io = end_io;
56         }
57         return bio;
58 }
59
60 static void end_swap_bio_write(struct bio *bio)
61 {
62         const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
63         struct page *page = bio->bi_io_vec[0].bv_page;
64
65         if (!uptodate)
66                 SetPageError(page);
67         end_page_writeback(page);
68         bio_put(bio);
69 }
70
71 static void end_swap_bio_read(struct bio *bio)
72 {
73         const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
74         struct page *page = bio->bi_io_vec[0].bv_page;
75
76         if (!uptodate) {
77                 SetPageError(page);
78                 ClearPageUptodate(page);
79         } else {
80                 SetPageUptodate(page);
81         }
82         unlock_page(page);
83         bio_put(bio);
84 }
85
86 /*
87  * We may have stale swap cache pages in memory: notice
88  * them here and get rid of the unnecessary final write.
89  */
90 int swap_writepage(struct page *page)
91 {
92         struct bio *bio;
93         int ret = 0;
94
95         if (remove_exclusive_swap_page(page)) {
96                 unlock_page(page);
97                 goto out;
98         }
99         bio = get_swap_bio(GFP_NOIO, page, end_swap_bio_write);
100         if (bio == NULL) {
101                 set_page_dirty(page);
102                 ret = -ENOMEM;
103                 goto out;
104         }
105         kstat.pswpout++;
106         SetPageWriteback(page);
107         unlock_page(page);
108         submit_bio(WRITE, bio);
109 out:
110         return ret;
111 }
112
113 int swap_readpage(struct file *file, struct page *page)
114 {
115         struct bio *bio;
116         int ret = 0;
117
118         ClearPageUptodate(page);
119         bio = get_swap_bio(GFP_KERNEL, page, end_swap_bio_read);
120         if (bio == NULL) {
121                 ret = -ENOMEM;
122                 goto out;
123         }
124         kstat.pswpin++;
125         submit_bio(READ, bio);
126 out:
127         return ret;
128 }
129 /*
130  * swapper_space doesn't have a real inode, so it gets a special vm_writeback()
131  * so we don't need swap special cases in generic_vm_writeback().
132  *
133  * Swap pages are PageLocked and PageWriteback while under writeout so that
134  * memory allocators will throttle against them.
135  */
136 static int swap_vm_writeback(struct page *page, int *nr_to_write)
137 {
138         struct address_space *mapping = page->mapping;
139
140         unlock_page(page);
141         return generic_writepages(mapping, nr_to_write);
142 }
143
144 struct address_space_operations swap_aops = {
145         vm_writeback:   swap_vm_writeback,
146         writepage:      swap_writepage,
147         readpage:       swap_readpage,
148         sync_page:      block_sync_page,
149         set_page_dirty: __set_page_dirty_nobuffers,
150 };
151
152 /*
153  * A scruffy utility function to read or write an arbitrary swap page
154  * and wait on the I/O.
155  */
156 int rw_swap_page_sync(int rw, swp_entry_t entry, struct page *page)
157 {
158         int ret;
159
160         lock_page(page);
161
162         BUG_ON(page->mapping);
163         page->mapping = &swapper_space;
164         page->index = entry.val;
165
166         if (rw == READ) {
167                 ret = swap_readpage(NULL, page);
168                 wait_on_page_locked(page);
169         } else {
170                 ret = swap_writepage(page);
171                 wait_on_page_writeback(page);
172         }
173         page->mapping = NULL;
174         if (ret == 0 && (!PageUptodate(page) || PageError(page)))
175                 ret = -EIO;
176         return ret;
177 }