summaryrefslogtreecommitdiff
path: root/mm/page_io.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2014-04-04 23:12:29 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2014-05-06 17:39:45 -0400
commit62a8067a7f35dba2de501c9cb00e4cf36da90bc0 (patch)
treebb008456891c13b9d8a25825a10074efb861cd88 /mm/page_io.c
parent81055e584f9d743cb13dc7944923d817c20f089d (diff)
bio_vec-backed iov_iter
New variant of iov_iter - ITER_BVEC in iter->type, backed with bio_vec array instead of iovec one. Primitives taught to deal with such beasts, __swap_write() switched to using that kind of iov_iter. Note that bio_vec is just a <page, offset, length> triple - there's nothing block-specific about it. I've left the definition where it was, but took it from under ifdef CONFIG_BLOCK. Next target: ->splice_write()... Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'mm/page_io.c')
-rw-r--r--mm/page_io.c19
1 files changed, 12 insertions, 7 deletions
diff --git a/mm/page_io.c b/mm/page_io.c
index 313bfedb75d1..33bb38c4aad7 100644
--- a/mm/page_io.c
+++ b/mm/page_io.c
@@ -259,23 +259,28 @@ int __swap_writepage(struct page *page, struct writeback_control *wbc,
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
};
- struct iov_iter from;
init_sync_kiocb(&kiocb, swap_file);
kiocb.ki_pos = page_file_offset(page);
kiocb.ki_nbytes = PAGE_SIZE;
- iov_iter_init(&from, KERNEL_WRITE, &iov, 1, PAGE_SIZE);
set_page_writeback(page);
unlock_page(page);
- ret = mapping->a_ops->direct_IO(KERNEL_WRITE,
+ ret = mapping->a_ops->direct_IO(ITER_BVEC | WRITE,
&kiocb, &from,
kiocb.ki_pos);
- kunmap(page);
if (ret == PAGE_SIZE) {
count_vm_event(PSWPOUT);
ret = 0;