Commit 62a8067a authored by Al Viro's avatar Al Viro

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: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 81055e58
...@@ -1288,7 +1288,7 @@ static int fuse_get_user_pages(struct fuse_req *req, struct iov_iter *ii, ...@@ -1288,7 +1288,7 @@ static int fuse_get_user_pages(struct fuse_req *req, struct iov_iter *ii,
size_t nbytes = 0; /* # bytes already packed in req */ size_t nbytes = 0; /* # bytes already packed in req */
/* Special case for kernel I/O: can copy directly into the buffer */ /* Special case for kernel I/O: can copy directly into the buffer */
if (ii->type & REQ_KERNEL) { if (ii->type & ITER_KVEC) {
unsigned long user_addr = fuse_get_user_addr(ii); unsigned long user_addr = fuse_get_user_addr(ii);
size_t frag_size = fuse_get_frag_size(ii, *nbytesp); size_t frag_size = fuse_get_frag_size(ii, *nbytesp);
......
...@@ -5,8 +5,6 @@ ...@@ -5,8 +5,6 @@
#ifndef __LINUX_BLK_TYPES_H #ifndef __LINUX_BLK_TYPES_H
#define __LINUX_BLK_TYPES_H #define __LINUX_BLK_TYPES_H
#ifdef CONFIG_BLOCK
#include <linux/types.h> #include <linux/types.h>
struct bio_set; struct bio_set;
...@@ -28,6 +26,8 @@ struct bio_vec { ...@@ -28,6 +26,8 @@ struct bio_vec {
unsigned int bv_offset; unsigned int bv_offset;
}; };
#ifdef CONFIG_BLOCK
struct bvec_iter { struct bvec_iter {
sector_t bi_sector; /* device address in 512 byte sector_t bi_sector; /* device address in 512 byte
sectors */ sectors */
......
...@@ -19,12 +19,21 @@ struct kvec { ...@@ -19,12 +19,21 @@ struct kvec {
size_t iov_len; size_t iov_len;
}; };
enum {
ITER_IOVEC = 0,
ITER_KVEC = 2,
ITER_BVEC = 4,
};
struct iov_iter { struct iov_iter {
int type; int type;
const struct iovec *iov;
unsigned long nr_segs;
size_t iov_offset; size_t iov_offset;
size_t count; size_t count;
union {
const struct iovec *iov;
const struct bio_vec *bvec;
};
unsigned long nr_segs;
}; };
/* /*
...@@ -54,6 +63,7 @@ static inline struct iovec iov_iter_iovec(const struct iov_iter *iter) ...@@ -54,6 +63,7 @@ static inline struct iovec iov_iter_iovec(const struct iov_iter *iter)
} }
#define iov_for_each(iov, iter, start) \ #define iov_for_each(iov, iter, start) \
if (!((start).type & ITER_BVEC)) \
for (iter = (start); \ for (iter = (start); \
(iter).count && \ (iter).count && \
((iov = iov_iter_iovec(&(iter))), 1); \ ((iov = iov_iter_iovec(&(iter))), 1); \
......
This diff is collapsed.
...@@ -259,23 +259,28 @@ int __swap_writepage(struct page *page, struct writeback_control *wbc, ...@@ -259,23 +259,28 @@ int __swap_writepage(struct page *page, struct writeback_control *wbc,
struct kiocb kiocb; struct kiocb kiocb;
struct file *swap_file = sis->swap_file; struct file *swap_file = sis->swap_file;
struct address_space *mapping = swap_file->f_mapping; struct address_space *mapping = swap_file->f_mapping;
struct iovec iov = { struct bio_vec bv = {
.iov_base = kmap(page), .bv_page = page,
.iov_len = PAGE_SIZE, .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); init_sync_kiocb(&kiocb, swap_file);
kiocb.ki_pos = page_file_offset(page); kiocb.ki_pos = page_file_offset(page);
kiocb.ki_nbytes = PAGE_SIZE; kiocb.ki_nbytes = PAGE_SIZE;
iov_iter_init(&from, KERNEL_WRITE, &iov, 1, PAGE_SIZE);
set_page_writeback(page); set_page_writeback(page);
unlock_page(page); unlock_page(page);
ret = mapping->a_ops->direct_IO(KERNEL_WRITE, ret = mapping->a_ops->direct_IO(ITER_BVEC | WRITE,
&kiocb, &from, &kiocb, &from,
kiocb.ki_pos); kiocb.ki_pos);
kunmap(page);
if (ret == PAGE_SIZE) { if (ret == PAGE_SIZE) {
count_vm_event(PSWPOUT); count_vm_event(PSWPOUT);
ret = 0; ret = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment