diff options
author | Matthew Wilcox <matthew.r.wilcox@intel.com> | 2014-06-04 19:07:48 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-04 19:54:02 -0400 |
commit | dd6bd0d9c7dbb3951005db4e424abbd37c4ff801 (patch) | |
tree | cddb3dcb163db01dd9af6e39ca4aee6f1a5470c5 /mm/page_io.c | |
parent | 47a191fd38ebddb1bd1510ec2bc1085c578c8868 (diff) |
swap: use bdev_read_page() / bdev_write_page()
By calling the device driver to write the page directly, we avoid
allocating a BIO, which allows us to free memory without allocating
memory.
[akpm@linux-foundation.org: fix used-uninitialized bug]
Signed-off-by: Matthew Wilcox <matthew.r.wilcox@intel.com>
Cc: Dave Chinner <david@fromorbit.com>
Cc: Dheeraj Reddy <dheeraj.reddy@intel.com>
Cc: Hugh Dickins <hughd@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/page_io.c')
-rw-r--r-- | mm/page_io.c | 21 |
1 files changed, 20 insertions, 1 deletions
diff --git a/mm/page_io.c b/mm/page_io.c index 7c59ef681381..58b50d2901fe 100644 --- a/mm/page_io.c +++ b/mm/page_io.c | |||
@@ -248,11 +248,16 @@ out: | |||
248 | return ret; | 248 | return ret; |
249 | } | 249 | } |
250 | 250 | ||
251 | static sector_t swap_page_sector(struct page *page) | ||
252 | { | ||
253 | return (sector_t)__page_file_index(page) << (PAGE_CACHE_SHIFT - 9); | ||
254 | } | ||
255 | |||
251 | int __swap_writepage(struct page *page, struct writeback_control *wbc, | 256 | int __swap_writepage(struct page *page, struct writeback_control *wbc, |
252 | void (*end_write_func)(struct bio *, int)) | 257 | void (*end_write_func)(struct bio *, int)) |
253 | { | 258 | { |
254 | struct bio *bio; | 259 | struct bio *bio; |
255 | int ret = 0, rw = WRITE; | 260 | int ret, rw = WRITE; |
256 | struct swap_info_struct *sis = page_swap_info(page); | 261 | struct swap_info_struct *sis = page_swap_info(page); |
257 | 262 | ||
258 | if (sis->flags & SWP_FILE) { | 263 | if (sis->flags & SWP_FILE) { |
@@ -297,6 +302,13 @@ int __swap_writepage(struct page *page, struct writeback_control *wbc, | |||
297 | return ret; | 302 | return ret; |
298 | } | 303 | } |
299 | 304 | ||
305 | ret = bdev_write_page(sis->bdev, swap_page_sector(page), page, wbc); | ||
306 | if (!ret) { | ||
307 | count_vm_event(PSWPOUT); | ||
308 | return 0; | ||
309 | } | ||
310 | |||
311 | ret = 0; | ||
300 | bio = get_swap_bio(GFP_NOIO, page, end_write_func); | 312 | bio = get_swap_bio(GFP_NOIO, page, end_write_func); |
301 | if (bio == NULL) { | 313 | if (bio == NULL) { |
302 | set_page_dirty(page); | 314 | set_page_dirty(page); |
@@ -338,6 +350,13 @@ int swap_readpage(struct page *page) | |||
338 | return ret; | 350 | return ret; |
339 | } | 351 | } |
340 | 352 | ||
353 | ret = bdev_read_page(sis->bdev, swap_page_sector(page), page); | ||
354 | if (!ret) { | ||
355 | count_vm_event(PSWPIN); | ||
356 | return 0; | ||
357 | } | ||
358 | |||
359 | ret = 0; | ||
341 | bio = get_swap_bio(GFP_KERNEL, page, end_swap_bio_read); | 360 | bio = get_swap_bio(GFP_KERNEL, page, end_swap_bio_read); |
342 | if (bio == NULL) { | 361 | if (bio == NULL) { |
343 | unlock_page(page); | 362 | unlock_page(page); |