[PATCH] C99 designated initializers for arch/sh
[linux-2.6/history.git] / mm / page_io.c
blob50d137ca40fa5363ce1cba09480983f4f0c319ef
1 /*
2 * linux/mm/page_io.c
4 * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
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
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/swapops.h>
19 #include <linux/buffer_head.h> /* for block_sync_page() */
20 #include <linux/mpage.h>
21 #include <asm/pgtable.h>
23 static struct bio *
24 get_swap_bio(int gfp_flags, struct page *page, bio_end_io_t end_io)
26 struct bio *bio;
28 bio = bio_alloc(gfp_flags, 1);
29 if (bio) {
30 struct swap_info_struct *sis;
31 swp_entry_t entry;
33 entry.val = page->index;
34 sis = get_swap_info_struct(swp_type(entry));
36 bio->bi_sector = map_swap_page(sis, swp_offset(entry)) *
37 (PAGE_SIZE >> 9);
38 bio->bi_bdev = sis->bdev;
39 bio->bi_io_vec[0].bv_page = page;
40 bio->bi_io_vec[0].bv_len = PAGE_SIZE;
41 bio->bi_io_vec[0].bv_offset = 0;
42 bio->bi_vcnt = 1;
43 bio->bi_idx = 0;
44 bio->bi_size = PAGE_SIZE;
45 bio->bi_end_io = end_io;
47 return bio;
50 static int end_swap_bio_write(struct bio *bio, unsigned int bytes_done, int err)
52 const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
53 struct page *page = bio->bi_io_vec[0].bv_page;
55 if (bio->bi_size)
56 return 1;
58 if (!uptodate)
59 SetPageError(page);
60 end_page_writeback(page);
61 bio_put(bio);
62 return 0;
65 static int end_swap_bio_read(struct bio *bio, unsigned int bytes_done, int err)
67 const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
68 struct page *page = bio->bi_io_vec[0].bv_page;
70 if (bio->bi_size)
71 return 1;
73 if (!uptodate) {
74 SetPageError(page);
75 ClearPageUptodate(page);
76 } else {
77 SetPageUptodate(page);
79 unlock_page(page);
80 bio_put(bio);
81 return 0;
85 * We may have stale swap cache pages in memory: notice
86 * them here and get rid of the unnecessary final write.
88 int swap_writepage(struct page *page)
90 struct bio *bio;
91 int ret = 0;
93 if (remove_exclusive_swap_page(page)) {
94 unlock_page(page);
95 goto out;
97 bio = get_swap_bio(GFP_NOIO, page, end_swap_bio_write);
98 if (bio == NULL) {
99 set_page_dirty(page);
100 ret = -ENOMEM;
101 goto out;
103 inc_page_state(pswpout);
104 SetPageWriteback(page);
105 unlock_page(page);
106 submit_bio(WRITE, bio);
107 out:
108 return ret;
111 int swap_readpage(struct file *file, struct page *page)
113 struct bio *bio;
114 int ret = 0;
116 ClearPageUptodate(page);
117 bio = get_swap_bio(GFP_KERNEL, page, end_swap_bio_read);
118 if (bio == NULL) {
119 ret = -ENOMEM;
120 goto out;
122 inc_page_state(pswpin);
123 submit_bio(READ, bio);
124 out:
125 return ret;
128 * swapper_space doesn't have a real inode, so it gets a special vm_writeback()
129 * so we don't need swap special cases in generic_vm_writeback().
131 * Swap pages are !PageLocked and PageWriteback while under writeout so that
132 * memory allocators will throttle against them.
134 static int swap_vm_writeback(struct page *page, struct writeback_control *wbc)
136 struct address_space *mapping = page->mapping;
138 unlock_page(page);
139 return generic_writepages(mapping, wbc);
142 struct address_space_operations swap_aops = {
143 .vm_writeback = swap_vm_writeback,
144 .writepage = swap_writepage,
145 .readpage = swap_readpage,
146 .sync_page = block_sync_page,
147 .set_page_dirty = __set_page_dirty_nobuffers,
151 * A scruffy utility function to read or write an arbitrary swap page
152 * and wait on the I/O.
154 int rw_swap_page_sync(int rw, swp_entry_t entry, struct page *page)
156 int ret;
158 lock_page(page);
160 BUG_ON(page->mapping);
161 page->mapping = &swapper_space;
162 page->index = entry.val;
164 if (rw == READ) {
165 ret = swap_readpage(NULL, page);
166 wait_on_page_locked(page);
167 } else {
168 ret = swap_writepage(page);
169 wait_on_page_writeback(page);
171 page->mapping = NULL;
172 if (ret == 0 && (!PageUptodate(page) || PageError(page)))
173 ret = -EIO;
174 return ret;