Commit b42b15fd authored by Al Viro's avatar Al Viro

lustre: get rid of messing with iovecs

* switch to ->read_iter/->write_iter
* keep a pointer to iov_iter instead of iov/nr_segs
* do not modify iovecs; use iov_iter_truncate()/iov_iter_advance() and
a new primitive - iov_iter_reexpand() (expand previously truncated
iterator) istead.
* (racy) check for lustre VMAs intersecting with iovecs kept for now as
for_each_iov() loop.
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 4908b822
...@@ -82,16 +82,7 @@ struct ccc_io { ...@@ -82,16 +82,7 @@ struct ccc_io {
/** /**
* I/O vector information to or from which read/write is going. * I/O vector information to or from which read/write is going.
*/ */
struct iovec *cui_iov; struct iov_iter *cui_iter;
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;
/** /**
* Total size for the left IO. * Total size for the left IO.
*/ */
......
...@@ -721,31 +721,12 @@ int ccc_io_one_lock_index(const struct lu_env *env, struct cl_io *io, ...@@ -721,31 +721,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, void ccc_io_update_iov(const struct lu_env *env,
struct ccc_io *cio, struct cl_io *io) struct ccc_io *cio, struct cl_io *io)
{ {
int i;
size_t size = io->u.ci_rw.crw_count; size_t size = io->u.ci_rw.crw_count;
cio->cui_iov_olen = 0; if (!cl_is_normalio(env, io) || cio->cui_iter == NULL)
if (!cl_is_normalio(env, io) || cio->cui_tot_nrsegs == 0)
return; return;
for (i = 0; i < cio->cui_tot_nrsegs; i++) { iov_iter_truncate(cio->cui_iter, size);
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);
} }
int ccc_io_one_lock(const struct lu_env *env, struct cl_io *io, int ccc_io_one_lock(const struct lu_env *env, struct cl_io *io,
...@@ -776,30 +757,7 @@ void ccc_io_advance(const struct lu_env *env, ...@@ -776,30 +757,7 @@ void ccc_io_advance(const struct lu_env *env,
if (!cl_is_normalio(env, io)) if (!cl_is_normalio(env, io))
return; return;
LASSERT(cio->cui_tot_nrsegs >= cio->cui_nrsegs); iov_iter_reexpand(cio->cui_iter, cio->cui_tot_count -= nob);
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;
}
} }
/** /**
......
...@@ -1105,9 +1105,7 @@ ll_file_io_generic(const struct lu_env *env, struct vvp_io_args *args, ...@@ -1105,9 +1105,7 @@ ll_file_io_generic(const struct lu_env *env, struct vvp_io_args *args,
switch (vio->cui_io_subtype) { switch (vio->cui_io_subtype) {
case IO_NORMAL: case IO_NORMAL:
cio->cui_iov = args->u.normal.via_iov; cio->cui_iter = args->u.normal.via_iter;
cio->cui_nrsegs = args->u.normal.via_nrsegs;
cio->cui_tot_nrsegs = cio->cui_nrsegs;
cio->cui_iocb = args->u.normal.via_iocb; cio->cui_iocb = args->u.normal.via_iocb;
if ((iot == CIT_WRITE) && if ((iot == CIT_WRITE) &&
!(cio->cui_fd->fd_flags & LL_FILE_GROUP_LOCKED)) { !(cio->cui_fd->fd_flags & LL_FILE_GROUP_LOCKED)) {
...@@ -1171,56 +1169,23 @@ ll_file_io_generic(const struct lu_env *env, struct vvp_io_args *args, ...@@ -1171,56 +1169,23 @@ ll_file_io_generic(const struct lu_env *env, struct vvp_io_args *args,
return result; return result;
} }
static ssize_t ll_file_aio_read(struct kiocb *iocb, const struct iovec *iov, static ssize_t ll_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
unsigned long nr_segs, loff_t pos)
{ {
struct lu_env *env; struct lu_env *env;
struct vvp_io_args *args; struct vvp_io_args *args;
size_t count = 0;
ssize_t result; ssize_t result;
int refcheck; int refcheck;
count = iov_length(iov, nr_segs);
env = cl_env_get(&refcheck); env = cl_env_get(&refcheck);
if (IS_ERR(env)) if (IS_ERR(env))
return PTR_ERR(env); return PTR_ERR(env);
args = vvp_env_args(env, IO_NORMAL); args = vvp_env_args(env, IO_NORMAL);
args->u.normal.via_iov = (struct iovec *)iov; args->u.normal.via_iter = to;
args->u.normal.via_nrsegs = nr_segs;
args->u.normal.via_iocb = iocb; args->u.normal.via_iocb = iocb;
result = ll_file_io_generic(env, args, iocb->ki_filp, CIT_READ, result = ll_file_io_generic(env, args, iocb->ki_filp, CIT_READ,
&iocb->ki_pos, count); &iocb->ki_pos, iov_iter_count(to));
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;
cl_env_put(env, &refcheck); cl_env_put(env, &refcheck);
return result; return result;
} }
...@@ -1228,12 +1193,10 @@ static ssize_t ll_file_read(struct file *file, char *buf, size_t count, ...@@ -1228,12 +1193,10 @@ static ssize_t ll_file_read(struct file *file, char *buf, size_t count,
/* /*
* Write to a file (through the page cache). * Write to a file (through the page cache).
*/ */
static ssize_t ll_file_aio_write(struct kiocb *iocb, const struct iovec *iov, static ssize_t ll_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
unsigned long nr_segs, loff_t pos)
{ {
struct lu_env *env; struct lu_env *env;
struct vvp_io_args *args; struct vvp_io_args *args;
size_t count = iov_length(iov, nr_segs);
ssize_t result; ssize_t result;
int refcheck; int refcheck;
...@@ -1242,46 +1205,15 @@ static ssize_t ll_file_aio_write(struct kiocb *iocb, const struct iovec *iov, ...@@ -1242,46 +1205,15 @@ static ssize_t ll_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
return PTR_ERR(env); return PTR_ERR(env);
args = vvp_env_args(env, IO_NORMAL); args = vvp_env_args(env, IO_NORMAL);
args->u.normal.via_iov = (struct iovec *)iov; args->u.normal.via_iter = from;
args->u.normal.via_nrsegs = nr_segs;
args->u.normal.via_iocb = iocb; args->u.normal.via_iocb = iocb;
result = ll_file_io_generic(env, args, iocb->ki_filp, CIT_WRITE, 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); cl_env_put(env, &refcheck);
return result; 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 * Send file content (through pagecache) somewhere with helper
*/ */
...@@ -3133,10 +3065,10 @@ int ll_inode_permission(struct inode *inode, int mask) ...@@ -3133,10 +3065,10 @@ int ll_inode_permission(struct inode *inode, int mask)
/* -o localflock - only provides locally consistent flock locks */ /* -o localflock - only provides locally consistent flock locks */
struct file_operations ll_file_operations = { struct file_operations ll_file_operations = {
.read = ll_file_read, .read = new_sync_read,
.aio_read = ll_file_aio_read, .read_iter = ll_file_read_iter,
.write = ll_file_write, .write = new_sync_write,
.aio_write = ll_file_aio_write, .write_iter = ll_file_write_iter,
.unlocked_ioctl = ll_file_ioctl, .unlocked_ioctl = ll_file_ioctl,
.open = ll_file_open, .open = ll_file_open,
.release = ll_file_release, .release = ll_file_release,
...@@ -3148,10 +3080,10 @@ struct file_operations ll_file_operations = { ...@@ -3148,10 +3080,10 @@ struct file_operations ll_file_operations = {
}; };
struct file_operations ll_file_operations_flock = { struct file_operations ll_file_operations_flock = {
.read = ll_file_read, .read = new_sync_read,
.aio_read = ll_file_aio_read, .read_iter = ll_file_read_iter,
.write = ll_file_write, .write = new_sync_write,
.aio_write = ll_file_aio_write, .write_iter = ll_file_write_iter,
.unlocked_ioctl = ll_file_ioctl, .unlocked_ioctl = ll_file_ioctl,
.open = ll_file_open, .open = ll_file_open,
.release = ll_file_release, .release = ll_file_release,
...@@ -3166,10 +3098,10 @@ struct file_operations ll_file_operations_flock = { ...@@ -3166,10 +3098,10 @@ struct file_operations ll_file_operations_flock = {
/* These are for -o noflock - to return ENOSYS on flock calls */ /* These are for -o noflock - to return ENOSYS on flock calls */
struct file_operations ll_file_operations_noflock = { struct file_operations ll_file_operations_noflock = {
.read = ll_file_read, .read = new_sync_read,
.aio_read = ll_file_aio_read, .read_iter = ll_file_read_iter,
.write = ll_file_write, .write = new_sync_write,
.aio_write = ll_file_aio_write, .write_iter = ll_file_write_iter,
.unlocked_ioctl = ll_file_ioctl, .unlocked_ioctl = ll_file_ioctl,
.open = ll_file_open, .open = ll_file_open,
.release = ll_file_release, .release = ll_file_release,
......
...@@ -974,8 +974,7 @@ struct vvp_io_args { ...@@ -974,8 +974,7 @@ struct vvp_io_args {
union { union {
struct { struct {
struct kiocb *via_iocb; struct kiocb *via_iocb;
struct iovec *via_iov; struct iov_iter *via_iter;
unsigned long via_nrsegs;
} normal; } normal;
struct { struct {
struct pipe_inode_info *via_pipe; struct pipe_inode_info *via_pipe;
......
...@@ -157,8 +157,7 @@ static struct ll_cl_context *ll_cl_init(struct file *file, ...@@ -157,8 +157,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); result = cl_io_rw_init(env, io, CIT_WRITE, pos, PAGE_CACHE_SIZE);
if (result == 0) { if (result == 0) {
cio->cui_fd = LUSTRE_FPRIVATE(file); cio->cui_fd = LUSTRE_FPRIVATE(file);
cio->cui_iov = NULL; cio->cui_iter = NULL;
cio->cui_nrsegs = 0;
result = cl_io_iter_init(env, io); result = cl_io_iter_init(env, io);
if (result == 0) { if (result == 0) {
result = cl_io_lock(env, io); result = cl_io_lock(env, io);
......
...@@ -211,27 +211,26 @@ static int vvp_mmap_locks(const struct lu_env *env, ...@@ -211,27 +211,26 @@ static int vvp_mmap_locks(const struct lu_env *env,
struct cl_lock_descr *descr = &cti->cti_descr; struct cl_lock_descr *descr = &cti->cti_descr;
ldlm_policy_data_t policy; ldlm_policy_data_t policy;
unsigned long addr; unsigned long addr;
unsigned long seg;
ssize_t count; ssize_t count;
int result; int result;
struct iov_iter i;
struct iovec iov;
LASSERT(io->ci_type == CIT_READ || io->ci_type == CIT_WRITE); LASSERT(io->ci_type == CIT_READ || io->ci_type == CIT_WRITE);
if (!cl_is_normalio(env, io)) if (!cl_is_normalio(env, io))
return 0; 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; return 0;
/* No MM (e.g. NFS)? No vmas too. */ /* No MM (e.g. NFS)? No vmas too. */
if (mm == NULL) if (mm == NULL)
return 0; return 0;
for (seg = 0; seg < vio->cui_nrsegs; seg++) { iov_for_each(iov, i, *(vio->cui_iter)) {
const struct iovec *iv = &vio->cui_iov[seg]; addr = (unsigned long)iov.iov_base;
count = iov.iov_len;
addr = (unsigned long)iv->iov_base;
count = iv->iov_len;
if (count == 0) if (count == 0)
continue; continue;
...@@ -527,9 +526,7 @@ static int vvp_io_read_start(const struct lu_env *env, ...@@ -527,9 +526,7 @@ static int vvp_io_read_start(const struct lu_env *env,
switch (vio->cui_io_subtype) { switch (vio->cui_io_subtype) {
case IO_NORMAL: case IO_NORMAL:
LASSERT(cio->cui_iocb->ki_pos == pos); LASSERT(cio->cui_iocb->ki_pos == pos);
result = generic_file_aio_read(cio->cui_iocb, result = generic_file_read_iter(cio->cui_iocb, cio->cui_iter);
cio->cui_iov, cio->cui_nrsegs,
cio->cui_iocb->ki_pos);
break; break;
case IO_SPLICE: case IO_SPLICE:
result = generic_file_splice_read(file, &pos, result = generic_file_splice_read(file, &pos,
...@@ -595,12 +592,11 @@ static int vvp_io_write_start(const struct lu_env *env, ...@@ -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); 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; result = 0;
else else
result = generic_file_aio_write(cio->cui_iocb, result = generic_file_write_iter(cio->cui_iocb, cio->cui_iter);
cio->cui_iov, cio->cui_nrsegs,
cio->cui_iocb->ki_pos);
if (result > 0) { if (result > 0) {
if (result < cnt) if (result < cnt)
io->ci_continue = 0; io->ci_continue = 0;
...@@ -1162,10 +1158,9 @@ int vvp_io_init(const struct lu_env *env, struct cl_object *obj, ...@@ -1162,10 +1158,9 @@ int vvp_io_init(const struct lu_env *env, struct cl_object *obj,
* results." -- Single Unix Spec */ * results." -- Single Unix Spec */
if (count == 0) if (count == 0)
result = 1; result = 1;
else { else
cio->cui_tot_count = count; cio->cui_tot_count = count;
cio->cui_tot_nrsegs = 0;
}
/* for read/write, we store the jobid in the inode, and /* for read/write, we store the jobid in the inode, and
* it'll be fetched by osc when building RPC. * it'll be fetched by osc when building RPC.
* *
......
...@@ -90,6 +90,15 @@ static inline void iov_iter_truncate(struct iov_iter *i, size_t count) ...@@ -90,6 +90,15 @@ static inline void iov_iter_truncate(struct iov_iter *i, size_t count)
i->count = count; i->count = count;
} }
/*
* reexpand a previously truncated iterator; count must be no more than how much
* we had shrunk it.
*/
static inline void iov_iter_reexpand(struct iov_iter *i, size_t count)
{
i->count = count;
}
int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len); int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len);
int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len); int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len);
......
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