diff options
Diffstat (limited to 'mm/page_io.c')
| -rw-r--r-- | mm/page_io.c | 42 | 
1 files changed, 34 insertions, 8 deletions
diff --git a/mm/page_io.c b/mm/page_io.c index 7c59ef681381..243a9b76e5ce 100644 --- a/mm/page_io.c +++ b/mm/page_io.c @@ -248,20 +248,33 @@ out:  	return ret;  } +static sector_t swap_page_sector(struct page *page) +{ +	return (sector_t)__page_file_index(page) << (PAGE_CACHE_SHIFT - 9); +} +  int __swap_writepage(struct page *page, struct writeback_control *wbc,  	void (*end_write_func)(struct bio *, int))  {  	struct bio *bio; -	int ret = 0, rw = WRITE; +	int ret, rw = WRITE;  	struct swap_info_struct *sis = page_swap_info(page);  	if (sis->flags & SWP_FILE) {  		struct kiocb kiocb;  		struct file *swap_file = sis->swap_file;  		struct address_space *mapping = swap_file->f_mapping; -		struct iovec iov = { -			.iov_base = kmap(page), -			.iov_len  = PAGE_SIZE, +		struct bio_vec bv = { +			.bv_page = page, +			.bv_len  = PAGE_SIZE, +			.bv_offset = 0 +		}; +		struct iov_iter from = { +			.type = ITER_BVEC | WRITE, +			.count = PAGE_SIZE, +			.iov_offset = 0, +			.nr_segs = 1, +			.bvec = &bv  		};  		init_sync_kiocb(&kiocb, swap_file); @@ -270,10 +283,9 @@ int __swap_writepage(struct page *page, struct writeback_control *wbc,  		set_page_writeback(page);  		unlock_page(page); -		ret = mapping->a_ops->direct_IO(KERNEL_WRITE, -						&kiocb, &iov, -						kiocb.ki_pos, 1); -		kunmap(page); +		ret = mapping->a_ops->direct_IO(ITER_BVEC | WRITE, +						&kiocb, &from, +						kiocb.ki_pos);  		if (ret == PAGE_SIZE) {  			count_vm_event(PSWPOUT);  			ret = 0; @@ -297,6 +309,13 @@ int __swap_writepage(struct page *page, struct writeback_control *wbc,  		return ret;  	} +	ret = bdev_write_page(sis->bdev, swap_page_sector(page), page, wbc); +	if (!ret) { +		count_vm_event(PSWPOUT); +		return 0; +	} + +	ret = 0;  	bio = get_swap_bio(GFP_NOIO, page, end_write_func);  	if (bio == NULL) {  		set_page_dirty(page); @@ -338,6 +357,13 @@ int swap_readpage(struct page *page)  		return ret;  	} +	ret = bdev_read_page(sis->bdev, swap_page_sector(page), page); +	if (!ret) { +		count_vm_event(PSWPIN); +		return 0; +	} + +	ret = 0;  	bio = get_swap_bio(GFP_KERNEL, page, end_swap_bio_read);  	if (bio == NULL) {  		unlock_page(page);  |