diff options
Diffstat (limited to 'mm/page_io.c')
| -rw-r--r-- | mm/page_io.c | 56 | 
1 files changed, 41 insertions, 15 deletions
diff --git a/mm/page_io.c b/mm/page_io.c index 8c79a4764be..955db8b0d49 100644 --- a/mm/page_io.c +++ b/mm/page_io.c @@ -31,13 +31,13 @@ static struct bio *get_swap_bio(gfp_t gfp_flags,  	bio = bio_alloc(gfp_flags, 1);  	if (bio) { -		bio->bi_sector = map_swap_page(page, &bio->bi_bdev); -		bio->bi_sector <<= PAGE_SHIFT - 9; +		bio->bi_iter.bi_sector = map_swap_page(page, &bio->bi_bdev); +		bio->bi_iter.bi_sector <<= PAGE_SHIFT - 9;  		bio->bi_io_vec[0].bv_page = page;  		bio->bi_io_vec[0].bv_len = PAGE_SIZE;  		bio->bi_io_vec[0].bv_offset = 0;  		bio->bi_vcnt = 1; -		bio->bi_size = PAGE_SIZE; +		bio->bi_iter.bi_size = PAGE_SIZE;  		bio->bi_end_io = end_io;  	}  	return bio; @@ -62,7 +62,7 @@ void end_swap_bio_write(struct bio *bio, int err)  		printk(KERN_ALERT "Write-error on swap-device (%u:%u:%Lu)\n",  				imajor(bio->bi_bdev->bd_inode),  				iminor(bio->bi_bdev->bd_inode), -				(unsigned long long)bio->bi_sector); +				(unsigned long long)bio->bi_iter.bi_sector);  		ClearPageReclaim(page);  	}  	end_page_writeback(page); @@ -80,7 +80,7 @@ void end_swap_bio_read(struct bio *bio, int err)  		printk(KERN_ALERT "Read-error on swap-device (%u:%u:%Lu)\n",  				imajor(bio->bi_bdev->bd_inode),  				iminor(bio->bi_bdev->bd_inode), -				(unsigned long long)bio->bi_sector); +				(unsigned long long)bio->bi_iter.bi_sector);  		goto out;  	} @@ -248,21 +248,34 @@ 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,  		}; +		from.bvec = &bv;	/* older gcc versions are broken */  		init_sync_kiocb(&kiocb, swap_file);  		kiocb.ki_pos = page_file_offset(page); @@ -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); @@ -320,8 +339,8 @@ int swap_readpage(struct page *page)  	int ret = 0;  	struct swap_info_struct *sis = page_swap_info(page); -	VM_BUG_ON(!PageLocked(page)); -	VM_BUG_ON(PageUptodate(page)); +	VM_BUG_ON_PAGE(!PageLocked(page), page); +	VM_BUG_ON_PAGE(PageUptodate(page), page);  	if (frontswap_load(page) == 0) {  		SetPageUptodate(page);  		unlock_page(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);  | 
