1
0
Fork 0

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: Al Viro <viro@zeniv.linux.org.uk>
hifive-unleashed-5.1
Al Viro 2014-04-04 12:15:19 -04:00
parent 4908b822b3
commit b42b15fdad
7 changed files with 46 additions and 163 deletions

View File

@ -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.
*/

View File

@ -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,
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,
@ -776,30 +757,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);
}
/**

View File

@ -1105,9 +1105,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)) {
@ -1171,56 +1169,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;
count = iov_length(iov, nr_segs);
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;
}
@ -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).
*/
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 = iov_length(iov, nr_segs);
ssize_t result;
int refcheck;
@ -1242,46 +1205,15 @@ static ssize_t ll_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
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
*/
@ -3133,10 +3065,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,
@ -3148,10 +3080,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,
@ -3166,10 +3098,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,

View File

@ -974,8 +974,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;

View 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);
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);

View File

@ -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.
*

View File

@ -90,6 +90,15 @@ static inline void iov_iter_truncate(struct iov_iter *i, size_t 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_toiovec(struct iovec *iov, unsigned char *kdata, int len);