summaryrefslogtreecommitdiff
path: root/drivers/staging
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-06-12 10:30:18 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2014-06-12 10:30:18 -0700
commit16b9057804c02e2d351e9c8f606e909b43cbd9e7 (patch)
treea3ac6e1d9d57a8abf4267e5ead3f2de1309335eb /drivers/staging
parent5c02c392cd2320e8d612376d6b72b6548a680923 (diff)
parentc2338f2dc7c1e9f6202f370c64ffd7f44f3d4b51 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs updates from Al Viro: "This the bunch that sat in -next + lock_parent() fix. This is the minimal set; there's more pending stuff. In particular, I really hope to get acct.c fixes merged this cycle - we need that to deal sanely with delayed-mntput stuff. In the next pile, hopefully - that series is fairly short and localized (kernel/acct.c, fs/super.c and fs/namespace.c). In this pile: more iov_iter work. Most of prereqs for ->splice_write with sane locking order are there and Kent's dio rewrite would also fit nicely on top of this pile" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (70 commits) lock_parent: don't step on stale ->d_parent of all-but-freed one kill generic_file_splice_write() ceph: switch to iter_file_splice_write() shmem: switch to iter_file_splice_write() nfs: switch to iter_splice_write_file() fs/splice.c: remove unneeded exports ocfs2: switch to iter_file_splice_write() ->splice_write() via ->write_iter() bio_vec-backed iov_iter optimize copy_page_{to,from}_iter() bury generic_file_aio_{read,write} lustre: get rid of messing with iovecs ceph: switch to ->write_iter() ceph_sync_direct_write: stop poking into iov_iter guts ceph_sync_read: stop poking into iov_iter guts new helper: copy_page_from_iter() fuse: switch to ->write_iter() btrfs: switch to ->write_iter() ocfs2: switch to ->write_iter() xfs: switch to ->write_iter() ...
Diffstat (limited to 'drivers/staging')
-rw-r--r--drivers/staging/lustre/lustre/include/lclient.h11
-rw-r--r--drivers/staging/lustre/lustre/lclient/lcommon_cl.c48
-rw-r--r--drivers/staging/lustre/lustre/llite/file.c112
-rw-r--r--drivers/staging/lustre/lustre/llite/llite_internal.h3
-rw-r--r--drivers/staging/lustre/lustre/llite/rw.c3
-rw-r--r--drivers/staging/lustre/lustre/llite/rw26.c102
-rw-r--r--drivers/staging/lustre/lustre/llite/vvp_io.c29
7 files changed, 77 insertions, 231 deletions
diff --git a/drivers/staging/lustre/lustre/include/lclient.h b/drivers/staging/lustre/lustre/include/lclient.h
index 827209ea6bd0..386a36c00f57 100644
--- a/drivers/staging/lustre/lustre/include/lclient.h
+++ b/drivers/staging/lustre/lustre/include/lclient.h
@@ -82,16 +82,7 @@ struct ccc_io {
/**
* I/O vector information to or from which read/write is going.
*/
- struct iovec *cui_iov;
- unsigned long cui_nrsegs;
- /**
- * Total iov count for left IO.
- */
- unsigned long cui_tot_nrsegs;
- /**
- * Old length for iov that was truncated partially.
- */
- size_t cui_iov_olen;
+ struct iov_iter *cui_iter;
/**
* Total size for the left IO.
*/
diff --git a/drivers/staging/lustre/lustre/lclient/lcommon_cl.c b/drivers/staging/lustre/lustre/lclient/lcommon_cl.c
index dc24cfa58037..1b0c216bc568 100644
--- a/drivers/staging/lustre/lustre/lclient/lcommon_cl.c
+++ b/drivers/staging/lustre/lustre/lclient/lcommon_cl.c
@@ -720,31 +720,12 @@ int ccc_io_one_lock_index(const struct lu_env *env, struct cl_io *io,
void ccc_io_update_iov(const struct lu_env *env,
struct ccc_io *cio, struct cl_io *io)
{
- int i;
size_t size = io->u.ci_rw.crw_count;
- cio->cui_iov_olen = 0;
- if (!cl_is_normalio(env, io) || cio->cui_tot_nrsegs == 0)
+ if (!cl_is_normalio(env, io) || cio->cui_iter == NULL)
return;
- for (i = 0; i < cio->cui_tot_nrsegs; i++) {
- struct iovec *iv = &cio->cui_iov[i];
-
- if (iv->iov_len < size)
- size -= iv->iov_len;
- else {
- if (iv->iov_len > size) {
- cio->cui_iov_olen = iv->iov_len;
- iv->iov_len = size;
- }
- break;
- }
- }
-
- cio->cui_nrsegs = i + 1;
- LASSERTF(cio->cui_tot_nrsegs >= cio->cui_nrsegs,
- "tot_nrsegs: %lu, nrsegs: %lu\n",
- cio->cui_tot_nrsegs, cio->cui_nrsegs);
+ iov_iter_truncate(cio->cui_iter, size);
}
int ccc_io_one_lock(const struct lu_env *env, struct cl_io *io,
@@ -775,30 +756,7 @@ void ccc_io_advance(const struct lu_env *env,
if (!cl_is_normalio(env, io))
return;
- LASSERT(cio->cui_tot_nrsegs >= cio->cui_nrsegs);
- LASSERT(cio->cui_tot_count >= nob);
-
- cio->cui_iov += cio->cui_nrsegs;
- cio->cui_tot_nrsegs -= cio->cui_nrsegs;
- cio->cui_tot_count -= nob;
-
- /* update the iov */
- if (cio->cui_iov_olen > 0) {
- struct iovec *iv;
-
- cio->cui_iov--;
- cio->cui_tot_nrsegs++;
- iv = &cio->cui_iov[0];
- if (io->ci_continue) {
- iv->iov_base += iv->iov_len;
- LASSERT(cio->cui_iov_olen > iv->iov_len);
- iv->iov_len = cio->cui_iov_olen - iv->iov_len;
- } else {
- /* restore the iov_len, in case of restart io. */
- iv->iov_len = cio->cui_iov_olen;
- }
- cio->cui_iov_olen = 0;
- }
+ iov_iter_reexpand(cio->cui_iter, cio->cui_tot_count -= nob);
}
/**
diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c
index c4ddec2b3589..716e1ee0104f 100644
--- a/drivers/staging/lustre/lustre/llite/file.c
+++ b/drivers/staging/lustre/lustre/llite/file.c
@@ -1114,9 +1114,7 @@ restart:
switch (vio->cui_io_subtype) {
case IO_NORMAL:
- cio->cui_iov = args->u.normal.via_iov;
- cio->cui_nrsegs = args->u.normal.via_nrsegs;
- cio->cui_tot_nrsegs = cio->cui_nrsegs;
+ cio->cui_iter = args->u.normal.via_iter;
cio->cui_iocb = args->u.normal.via_iocb;
if ((iot == CIT_WRITE) &&
!(cio->cui_fd->fd_flags & LL_FILE_GROUP_LOCKED)) {
@@ -1180,58 +1178,23 @@ out:
return result;
}
-static ssize_t ll_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
- unsigned long nr_segs, loff_t pos)
+static ssize_t ll_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
{
struct lu_env *env;
struct vvp_io_args *args;
- size_t count = 0;
ssize_t result;
int refcheck;
- result = generic_segment_checks(iov, &nr_segs, &count, VERIFY_WRITE);
- if (result)
- return result;
-
env = cl_env_get(&refcheck);
if (IS_ERR(env))
return PTR_ERR(env);
args = vvp_env_args(env, IO_NORMAL);
- args->u.normal.via_iov = (struct iovec *)iov;
- args->u.normal.via_nrsegs = nr_segs;
+ args->u.normal.via_iter = to;
args->u.normal.via_iocb = iocb;
result = ll_file_io_generic(env, args, iocb->ki_filp, CIT_READ,
- &iocb->ki_pos, count);
- cl_env_put(env, &refcheck);
- return result;
-}
-
-static ssize_t ll_file_read(struct file *file, char *buf, size_t count,
- loff_t *ppos)
-{
- struct lu_env *env;
- struct iovec *local_iov;
- struct kiocb *kiocb;
- ssize_t result;
- int refcheck;
-
- env = cl_env_get(&refcheck);
- if (IS_ERR(env))
- return PTR_ERR(env);
-
- local_iov = &vvp_env_info(env)->vti_local_iov;
- kiocb = &vvp_env_info(env)->vti_kiocb;
- local_iov->iov_base = (void __user *)buf;
- local_iov->iov_len = count;
- init_sync_kiocb(kiocb, file);
- kiocb->ki_pos = *ppos;
- kiocb->ki_nbytes = count;
-
- result = ll_file_aio_read(kiocb, local_iov, 1, kiocb->ki_pos);
- *ppos = kiocb->ki_pos;
-
+ &iocb->ki_pos, iov_iter_count(to));
cl_env_put(env, &refcheck);
return result;
}
@@ -1239,64 +1202,27 @@ static ssize_t ll_file_read(struct file *file, char *buf, size_t count,
/*
* Write to a file (through the page cache).
*/
-static ssize_t ll_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
- unsigned long nr_segs, loff_t pos)
+static ssize_t ll_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
{
struct lu_env *env;
struct vvp_io_args *args;
- size_t count = 0;
ssize_t result;
int refcheck;
- result = generic_segment_checks(iov, &nr_segs, &count, VERIFY_READ);
- if (result)
- return result;
-
env = cl_env_get(&refcheck);
if (IS_ERR(env))
return PTR_ERR(env);
args = vvp_env_args(env, IO_NORMAL);
- args->u.normal.via_iov = (struct iovec *)iov;
- args->u.normal.via_nrsegs = nr_segs;
+ args->u.normal.via_iter = from;
args->u.normal.via_iocb = iocb;
result = ll_file_io_generic(env, args, iocb->ki_filp, CIT_WRITE,
- &iocb->ki_pos, count);
+ &iocb->ki_pos, iov_iter_count(from));
cl_env_put(env, &refcheck);
return result;
}
-static ssize_t ll_file_write(struct file *file, const char *buf, size_t count,
- loff_t *ppos)
-{
- struct lu_env *env;
- struct iovec *local_iov;
- struct kiocb *kiocb;
- ssize_t result;
- int refcheck;
-
- env = cl_env_get(&refcheck);
- if (IS_ERR(env))
- return PTR_ERR(env);
-
- local_iov = &vvp_env_info(env)->vti_local_iov;
- kiocb = &vvp_env_info(env)->vti_kiocb;
- local_iov->iov_base = (void __user *)buf;
- local_iov->iov_len = count;
- init_sync_kiocb(kiocb, file);
- kiocb->ki_pos = *ppos;
- kiocb->ki_nbytes = count;
-
- result = ll_file_aio_write(kiocb, local_iov, 1, kiocb->ki_pos);
- *ppos = kiocb->ki_pos;
-
- cl_env_put(env, &refcheck);
- return result;
-}
-
-
-
/*
* Send file content (through pagecache) somewhere with helper
*/
@@ -3143,10 +3069,10 @@ int ll_inode_permission(struct inode *inode, int mask)
/* -o localflock - only provides locally consistent flock locks */
struct file_operations ll_file_operations = {
- .read = ll_file_read,
- .aio_read = ll_file_aio_read,
- .write = ll_file_write,
- .aio_write = ll_file_aio_write,
+ .read = new_sync_read,
+ .read_iter = ll_file_read_iter,
+ .write = new_sync_write,
+ .write_iter = ll_file_write_iter,
.unlocked_ioctl = ll_file_ioctl,
.open = ll_file_open,
.release = ll_file_release,
@@ -3158,10 +3084,10 @@ struct file_operations ll_file_operations = {
};
struct file_operations ll_file_operations_flock = {
- .read = ll_file_read,
- .aio_read = ll_file_aio_read,
- .write = ll_file_write,
- .aio_write = ll_file_aio_write,
+ .read = new_sync_read,
+ .read_iter = ll_file_read_iter,
+ .write = new_sync_write,
+ .write_iter = ll_file_write_iter,
.unlocked_ioctl = ll_file_ioctl,
.open = ll_file_open,
.release = ll_file_release,
@@ -3176,10 +3102,10 @@ struct file_operations ll_file_operations_flock = {
/* These are for -o noflock - to return ENOSYS on flock calls */
struct file_operations ll_file_operations_noflock = {
- .read = ll_file_read,
- .aio_read = ll_file_aio_read,
- .write = ll_file_write,
- .aio_write = ll_file_aio_write,
+ .read = new_sync_read,
+ .read_iter = ll_file_read_iter,
+ .write = new_sync_write,
+ .write_iter = ll_file_write_iter,
.unlocked_ioctl = ll_file_ioctl,
.open = ll_file_open,
.release = ll_file_release,
diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h
index dde7632ba01f..140ee947ba49 100644
--- a/drivers/staging/lustre/lustre/llite/llite_internal.h
+++ b/drivers/staging/lustre/lustre/llite/llite_internal.h
@@ -917,8 +917,7 @@ struct vvp_io_args {
union {
struct {
struct kiocb *via_iocb;
- struct iovec *via_iov;
- unsigned long via_nrsegs;
+ struct iov_iter *via_iter;
} normal;
struct {
struct pipe_inode_info *via_pipe;
diff --git a/drivers/staging/lustre/lustre/llite/rw.c b/drivers/staging/lustre/lustre/llite/rw.c
index f0122c568a09..56162103cc79 100644
--- a/drivers/staging/lustre/lustre/llite/rw.c
+++ b/drivers/staging/lustre/lustre/llite/rw.c
@@ -151,8 +151,7 @@ static struct ll_cl_context *ll_cl_init(struct file *file,
result = cl_io_rw_init(env, io, CIT_WRITE, pos, PAGE_CACHE_SIZE);
if (result == 0) {
cio->cui_fd = LUSTRE_FPRIVATE(file);
- cio->cui_iov = NULL;
- cio->cui_nrsegs = 0;
+ cio->cui_iter = NULL;
result = cl_io_iter_init(env, io);
if (result == 0) {
result = cl_io_lock(env, io);
diff --git a/drivers/staging/lustre/lustre/llite/rw26.c b/drivers/staging/lustre/lustre/llite/rw26.c
index 55ca8d3c3e46..af84c1aaa5f8 100644
--- a/drivers/staging/lustre/lustre/llite/rw26.c
+++ b/drivers/staging/lustre/lustre/llite/rw26.c
@@ -218,14 +218,11 @@ static void ll_free_user_pages(struct page **pages, int npages, int do_dirty)
int i;
for (i = 0; i < npages; i++) {
- if (pages[i] == NULL)
- break;
if (do_dirty)
set_page_dirty_lock(pages[i]);
page_cache_release(pages[i]);
}
-
- OBD_FREE_LARGE(pages, npages * sizeof(*pages));
+ kvfree(pages);
}
ssize_t ll_direct_rw_pages(const struct lu_env *env, struct cl_io *io,
@@ -363,18 +360,16 @@ static ssize_t ll_direct_IO_26_seg(const struct lu_env *env, struct cl_io *io,
#define MAX_DIO_SIZE ((MAX_MALLOC / sizeof(struct brw_page) * PAGE_CACHE_SIZE) & \
~(DT_MAX_BRW_SIZE - 1))
static ssize_t ll_direct_IO_26(int rw, struct kiocb *iocb,
- const struct iovec *iov, loff_t file_offset,
- unsigned long nr_segs)
+ struct iov_iter *iter, loff_t file_offset)
{
struct lu_env *env;
struct cl_io *io;
struct file *file = iocb->ki_filp;
struct inode *inode = file->f_mapping->host;
struct ccc_object *obj = cl_inode2ccc(inode);
- long count = iov_length(iov, nr_segs);
- long tot_bytes = 0, result = 0;
+ ssize_t count = iov_iter_count(iter);
+ ssize_t tot_bytes = 0, result = 0;
struct ll_inode_info *lli = ll_i2info(inode);
- unsigned long seg = 0;
long size = MAX_DIO_SIZE;
int refcheck;
@@ -392,11 +387,8 @@ static ssize_t ll_direct_IO_26(int rw, struct kiocb *iocb,
MAX_DIO_SIZE >> PAGE_CACHE_SHIFT);
/* Check that all user buffers are aligned as well */
- for (seg = 0; seg < nr_segs; seg++) {
- if (((unsigned long)iov[seg].iov_base & ~CFS_PAGE_MASK) ||
- (iov[seg].iov_len & ~CFS_PAGE_MASK))
- return -EINVAL;
- }
+ if (iov_iter_alignment(iter) & ~CFS_PAGE_MASK)
+ return -EINVAL;
env = cl_env_get(&refcheck);
LASSERT(!IS_ERR(env));
@@ -411,63 +403,49 @@ static ssize_t ll_direct_IO_26(int rw, struct kiocb *iocb,
mutex_lock(&inode->i_mutex);
LASSERT(obj->cob_transient_pages == 0);
- for (seg = 0; seg < nr_segs; seg++) {
- long iov_left = iov[seg].iov_len;
- unsigned long user_addr = (unsigned long)iov[seg].iov_base;
+ while (iov_iter_count(iter)) {
+ struct page **pages;
+ size_t offs;
+ count = min_t(size_t, iov_iter_count(iter), size);
if (rw == READ) {
if (file_offset >= i_size_read(inode))
break;
- if (file_offset + iov_left > i_size_read(inode))
- iov_left = i_size_read(inode) - file_offset;
+ if (file_offset + count > i_size_read(inode))
+ count = i_size_read(inode) - file_offset;
}
- while (iov_left > 0) {
- struct page **pages;
- int page_count, max_pages = 0;
- long bytes;
-
- bytes = min(size, iov_left);
- page_count = ll_get_user_pages(rw, user_addr, bytes,
- &pages, &max_pages);
- if (likely(page_count > 0)) {
- if (unlikely(page_count < max_pages))
- bytes = page_count << PAGE_CACHE_SHIFT;
- result = ll_direct_IO_26_seg(env, io, rw, inode,
- file->f_mapping,
- bytes, file_offset,
- pages, page_count);
- ll_free_user_pages(pages, max_pages, rw==READ);
- } else if (page_count == 0) {
- GOTO(out, result = -EFAULT);
- } else {
- result = page_count;
- }
- if (unlikely(result <= 0)) {
- /* If we can't allocate a large enough buffer
- * for the request, shrink it to a smaller
- * PAGE_SIZE multiple and try again.
- * We should always be able to kmalloc for a
- * page worth of page pointers = 4MB on i386. */
- if (result == -ENOMEM &&
- size > (PAGE_CACHE_SIZE / sizeof(*pages)) *
- PAGE_CACHE_SIZE) {
- size = ((((size / 2) - 1) |
- ~CFS_PAGE_MASK) + 1) &
- CFS_PAGE_MASK;
- CDEBUG(D_VFSTRACE,"DIO size now %lu\n",
- size);
- continue;
- }
-
- GOTO(out, result);
+ result = iov_iter_get_pages_alloc(iter, &pages, count, &offs);
+ if (likely(result > 0)) {
+ int n = (result + offs + PAGE_SIZE - 1) / PAGE_SIZE;
+ result = ll_direct_IO_26_seg(env, io, rw, inode,
+ file->f_mapping,
+ result, file_offset,
+ pages, n);
+ ll_free_user_pages(pages, n, rw==READ);
+ }
+ if (unlikely(result <= 0)) {
+ /* If we can't allocate a large enough buffer
+ * for the request, shrink it to a smaller
+ * PAGE_SIZE multiple and try again.
+ * We should always be able to kmalloc for a
+ * page worth of page pointers = 4MB on i386. */
+ if (result == -ENOMEM &&
+ size > (PAGE_CACHE_SIZE / sizeof(*pages)) *
+ PAGE_CACHE_SIZE) {
+ size = ((((size / 2) - 1) |
+ ~CFS_PAGE_MASK) + 1) &
+ CFS_PAGE_MASK;
+ CDEBUG(D_VFSTRACE,"DIO size now %lu\n",
+ size);
+ continue;
}
- tot_bytes += result;
- file_offset += result;
- iov_left -= result;
- user_addr += result;
+ GOTO(out, result);
}
+ iov_iter_advance(iter, result);
+ tot_bytes += result;
+ file_offset += result;
}
out:
LASSERT(obj->cob_transient_pages == 0);
diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c
index 7dd2b4723c5f..0e0b404cb5e6 100644
--- a/drivers/staging/lustre/lustre/llite/vvp_io.c
+++ b/drivers/staging/lustre/lustre/llite/vvp_io.c
@@ -211,27 +211,26 @@ static int vvp_mmap_locks(const struct lu_env *env,
struct cl_lock_descr *descr = &cti->cti_descr;
ldlm_policy_data_t policy;
unsigned long addr;
- unsigned long seg;
ssize_t count;
int result;
+ struct iov_iter i;
+ struct iovec iov;
LASSERT(io->ci_type == CIT_READ || io->ci_type == CIT_WRITE);
if (!cl_is_normalio(env, io))
return 0;
- if (vio->cui_iov == NULL) /* nfs or loop back device write */
+ if (vio->cui_iter == NULL) /* nfs or loop back device write */
return 0;
/* No MM (e.g. NFS)? No vmas too. */
if (mm == NULL)
return 0;
- for (seg = 0; seg < vio->cui_nrsegs; seg++) {
- const struct iovec *iv = &vio->cui_iov[seg];
-
- addr = (unsigned long)iv->iov_base;
- count = iv->iov_len;
+ iov_for_each(iov, i, *(vio->cui_iter)) {
+ addr = (unsigned long)iov.iov_base;
+ count = iov.iov_len;
if (count == 0)
continue;
@@ -527,9 +526,7 @@ static int vvp_io_read_start(const struct lu_env *env,
switch (vio->cui_io_subtype) {
case IO_NORMAL:
LASSERT(cio->cui_iocb->ki_pos == pos);
- result = generic_file_aio_read(cio->cui_iocb,
- cio->cui_iov, cio->cui_nrsegs,
- cio->cui_iocb->ki_pos);
+ result = generic_file_read_iter(cio->cui_iocb, cio->cui_iter);
break;
case IO_SPLICE:
result = generic_file_splice_read(file, &pos,
@@ -595,12 +592,11 @@ static int vvp_io_write_start(const struct lu_env *env,
CDEBUG(D_VFSTRACE, "write: [%lli, %lli)\n", pos, pos + (long long)cnt);
- if (cio->cui_iov == NULL) /* from a temp io in ll_cl_init(). */
+ if (cio->cui_iter == NULL) /* from a temp io in ll_cl_init(). */
result = 0;
else
- result = generic_file_aio_write(cio->cui_iocb,
- cio->cui_iov, cio->cui_nrsegs,
- cio->cui_iocb->ki_pos);
+ result = generic_file_write_iter(cio->cui_iocb, cio->cui_iter);
+
if (result > 0) {
if (result < cnt)
io->ci_continue = 0;
@@ -1162,10 +1158,9 @@ int vvp_io_init(const struct lu_env *env, struct cl_object *obj,
* results." -- Single Unix Spec */
if (count == 0)
result = 1;
- else {
+ else
cio->cui_tot_count = count;
- cio->cui_tot_nrsegs = 0;
- }
+
/* for read/write, we store the jobid in the inode, and
* it'll be fetched by osc when building RPC.
*