aboutsummaryrefslogtreecommitdiffstats
path: root/mm/page_io.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/page_io.c')
-rw-r--r--mm/page_io.c52
1 files changed, 52 insertions, 0 deletions
diff --git a/mm/page_io.c b/mm/page_io.c
index 34f02923744c..307a3e795290 100644
--- a/mm/page_io.c
+++ b/mm/page_io.c
@@ -17,6 +17,7 @@
17#include <linux/swap.h> 17#include <linux/swap.h>
18#include <linux/bio.h> 18#include <linux/bio.h>
19#include <linux/swapops.h> 19#include <linux/swapops.h>
20#include <linux/buffer_head.h>
20#include <linux/writeback.h> 21#include <linux/writeback.h>
21#include <linux/frontswap.h> 22#include <linux/frontswap.h>
22#include <asm/pgtable.h> 23#include <asm/pgtable.h>
@@ -94,6 +95,7 @@ int swap_writepage(struct page *page, struct writeback_control *wbc)
94{ 95{
95 struct bio *bio; 96 struct bio *bio;
96 int ret = 0, rw = WRITE; 97 int ret = 0, rw = WRITE;
98 struct swap_info_struct *sis = page_swap_info(page);
97 99
98 if (try_to_free_swap(page)) { 100 if (try_to_free_swap(page)) {
99 unlock_page(page); 101 unlock_page(page);
@@ -105,6 +107,32 @@ int swap_writepage(struct page *page, struct writeback_control *wbc)
105 end_page_writeback(page); 107 end_page_writeback(page);
106 goto out; 108 goto out;
107 } 109 }
110
111 if (sis->flags & SWP_FILE) {
112 struct kiocb kiocb;
113 struct file *swap_file = sis->swap_file;
114 struct address_space *mapping = swap_file->f_mapping;
115 struct iovec iov = {
116 .iov_base = page_address(page),
117 .iov_len = PAGE_SIZE,
118 };
119
120 init_sync_kiocb(&kiocb, swap_file);
121 kiocb.ki_pos = page_file_offset(page);
122 kiocb.ki_left = PAGE_SIZE;
123 kiocb.ki_nbytes = PAGE_SIZE;
124
125 unlock_page(page);
126 ret = mapping->a_ops->direct_IO(KERNEL_WRITE,
127 &kiocb, &iov,
128 kiocb.ki_pos, 1);
129 if (ret == PAGE_SIZE) {
130 count_vm_event(PSWPOUT);
131 ret = 0;
132 }
133 return ret;
134 }
135
108 bio = get_swap_bio(GFP_NOIO, page, end_swap_bio_write); 136 bio = get_swap_bio(GFP_NOIO, page, end_swap_bio_write);
109 if (bio == NULL) { 137 if (bio == NULL) {
110 set_page_dirty(page); 138 set_page_dirty(page);
@@ -126,6 +154,7 @@ int swap_readpage(struct page *page)
126{ 154{
127 struct bio *bio; 155 struct bio *bio;
128 int ret = 0; 156 int ret = 0;
157 struct swap_info_struct *sis = page_swap_info(page);
129 158
130 VM_BUG_ON(!PageLocked(page)); 159 VM_BUG_ON(!PageLocked(page));
131 VM_BUG_ON(PageUptodate(page)); 160 VM_BUG_ON(PageUptodate(page));
@@ -134,6 +163,17 @@ int swap_readpage(struct page *page)
134 unlock_page(page); 163 unlock_page(page);
135 goto out; 164 goto out;
136 } 165 }
166
167 if (sis->flags & SWP_FILE) {
168 struct file *swap_file = sis->swap_file;
169 struct address_space *mapping = swap_file->f_mapping;
170
171 ret = mapping->a_ops->readpage(swap_file, page);
172 if (!ret)
173 count_vm_event(PSWPIN);
174 return ret;
175 }
176
137 bio = get_swap_bio(GFP_KERNEL, page, end_swap_bio_read); 177 bio = get_swap_bio(GFP_KERNEL, page, end_swap_bio_read);
138 if (bio == NULL) { 178 if (bio == NULL) {
139 unlock_page(page); 179 unlock_page(page);
@@ -145,3 +185,15 @@ int swap_readpage(struct page *page)
145out: 185out:
146 return ret; 186 return ret;
147} 187}
188
189int swap_set_page_dirty(struct page *page)
190{
191 struct swap_info_struct *sis = page_swap_info(page);
192
193 if (sis->flags & SWP_FILE) {
194 struct address_space *mapping = sis->swap_file->f_mapping;
195 return mapping->a_ops->set_page_dirty(page);
196 } else {
197 return __set_page_dirty_no_writeback(page);
198 }
199}